[med-svn] [openfreezer] 01/05: New upstream version 2013

Andreas Tille tille at debian.org
Fri Dec 30 17:01:26 UTC 2016


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository openfreezer.

commit 6a987389d78075881472e761241d5e35987bb2f0
Author: Andreas Tille <tille at debian.org>
Date:   Fri Dec 30 17:43:40 2016 +0100

    New upstream version 2013
---
 OpenFreezer Database Notes.pdf                     |   Bin 0 -> 64682 bytes
 OpenFreezer/Chemical.php                           |  1354 ++
 OpenFreezer/Classes/Bug_Class.php                  |   140 +
 OpenFreezer/Classes/Bug_Function_Class.php         |    88 +
 OpenFreezer/Classes/Chemical_Class.php             |   338 +
 OpenFreezer/Classes/Chemical_Location_Class.php    |   175 +
 OpenFreezer/Classes/ColFunctOutputer.php           |   829 +
 OpenFreezer/Classes/HT_Class.php                   |   112 +
 OpenFreezer/Classes/MemberLogin_Class.php          |   535 +
 OpenFreezer/Classes/Member_Class.php               |   367 +
 OpenFreezer/Classes/Order_Class.php                |   586 +
 OpenFreezer/Classes/Project_Class.php              |   199 +
 OpenFreezer/Classes/Reagent_Class.php              |   651 +
 OpenFreezer/Classes/SeqFeature.php                 |   600 +
 OpenFreezer/Classes/Sequence.php                   |   439 +
 OpenFreezer/Classes/Session_Var_Class.php          |  1230 ++
 OpenFreezer/Classes/StopWatch.php                  |   105 +
 OpenFreezer/Classes/generalFunc_Class.php          |   430 +
 OpenFreezer/DatabaseConn.php                       |    43 +
 OpenFreezer/Docs/Copyright.doc                     |   Bin 0 -> 73728 bytes
 OpenFreezer/Docs/Copyright.odt                     |   Bin 0 -> 20073 bytes
 OpenFreezer/HeaderFunctions.php                    |   626 +
 OpenFreezer/Location.php                           |   613 +
 OpenFreezer/Location/Location_Admin_Class.php      |   552 +
 OpenFreezer/Location/Location_Creator_Class.php    |   634 +
 OpenFreezer/Location/Location_Funct_Class.php      |  1469 ++
 OpenFreezer/Location/Location_Output_Class.php     |  1753 ++
 OpenFreezer/Location/Location_Well_Class.php       |  2612 +++
 OpenFreezer/Project.php                            |   792 +
 OpenFreezer/Project/ProjectFunctions.php           |   615 +
 OpenFreezer/Reagent.php                            |  1161 +
 OpenFreezer/Reagent/ColFunctOutputer_Class.php     |  1718 ++
 OpenFreezer/Reagent/Reagent_Background_Class.php   |   691 +
 OpenFreezer/Reagent/Reagent_Creator_Class.php      |  8919 ++++++++
 OpenFreezer/Reagent/Reagent_Function_Class.php     |  2920 +++
 OpenFreezer/Reagent/Reagent_Output_Class.php       |  6405 ++++++
 OpenFreezer/Reagent/Reagent_Special_Prop_Class.php |   128 +
 OpenFreezer/Reagent/Sequence_Function_Class.php    |   199 +
 OpenFreezer/Reagent/cell_assoc.png                 |   Bin 0 -> 29457 bytes
 OpenFreezer/Reagent/fasta.php                      |    50 +
 OpenFreezer/Reagent/genBank.php                    |     9 +
 OpenFreezer/Reagent/pr_translation_rules.pdf       |   Bin 0 -> 59662 bytes
 OpenFreezer/Reagent/restriction.php                |    18 +
 OpenFreezer/Reagent/vector_assoc.jpeg              |   Bin 0 -> 37331 bytes
 OpenFreezer/Reagent/vector_assoc.png               |   Bin 0 -> 37331 bytes
 OpenFreezer/Search/searchFunctions.php             |   608 +
 OpenFreezer/Search/searchOutput_reagent.php        |  1562 ++
 OpenFreezer/User.php                               |  1757 ++
 OpenFreezer/User/UserFunctions.php                 |    79 +
 OpenFreezer/bugreport.php                          |   268 +
 OpenFreezer/cgi/add_project_members.py             |    48 +
 OpenFreezer/cgi/add_users.py                       |    47 +
 OpenFreezer/cgi/barcodes.py                        |    27 +
 OpenFreezer/cgi/cell_line_stats.py                 |   193 +
 OpenFreezer/cgi/comment_handler.py                 |   134 +
 OpenFreezer/cgi/container.py                       |   144 +
 OpenFreezer/cgi/create.py                          |  1695 ++
 OpenFreezer/cgi/database_conn.py                   |    42 +
 OpenFreezer/cgi/delete.py                          |    66 +
 OpenFreezer/cgi/exception.py                       |   567 +
 OpenFreezer/cgi/general_handler.py                 |  1882 ++
 OpenFreezer/cgi/general_output.py                  |   737 +
 OpenFreezer/cgi/graphics_handler.py                |    56 +
 OpenFreezer/cgi/lab_handler.py                     |   414 +
 OpenFreezer/cgi/laboratory.py                      |    97 +
 OpenFreezer/cgi/location_database_handler.py       |  1190 ++
 OpenFreezer/cgi/location_request_handler.py        |   495 +
 OpenFreezer/cgi/location_type_database_handler.py  |   391 +
 OpenFreezer/cgi/location_type_request_handler.py   |   213 +
 OpenFreezer/cgi/mapper.py                          |  1038 +
 OpenFreezer/cgi/oligos_vector_map.py               |   922 +
 OpenFreezer/cgi/packet.py                          |   124 +
 OpenFreezer/cgi/preload.py                         |  3879 ++++
 OpenFreezer/cgi/prep.py                            |    67 +
 OpenFreezer/cgi/preview.py                         |    64 +
 OpenFreezer/cgi/project_database_handler.py        |   519 +
 OpenFreezer/cgi/project_output.py                  |   703 +
 OpenFreezer/cgi/project_request_handler.py         |   427 +
 OpenFreezer/cgi/reagent.py                         |   681 +
 OpenFreezer/cgi/reagent_handler.py                 |  3385 +++
 OpenFreezer/cgi/reagent_output.py                  |   946 +
 OpenFreezer/cgi/reagent_type_output.py             |  2627 +++
 OpenFreezer/cgi/reagent_type_request_handler.py    |  2093 ++
 OpenFreezer/cgi/restriction.py                     |   154 +
 OpenFreezer/cgi/restriction_map.py                 |   135 +
 OpenFreezer/cgi/restriction_sites.py               |    18 +
 OpenFreezer/cgi/sequence.py                        |   258 +
 OpenFreezer/cgi/sequence_feature.py                |   101 +
 OpenFreezer/cgi/sequence_handler.py                |  2412 +++
 OpenFreezer/cgi/session.py                         |    50 +
 OpenFreezer/cgi/session_handler.py                 |   131 +
 OpenFreezer/cgi/system_set_handler.py              |   214 +
 OpenFreezer/cgi/update.py                          |  4304 ++++
 OpenFreezer/cgi/user.py                            |   168 +
 OpenFreezer/cgi/user_handler.py                    |   530 +
 OpenFreezer/cgi/user_output.py                     |  1304 ++
 OpenFreezer/cgi/user_request_handler.py            |   990 +
 OpenFreezer/cgi/utils.py                           |   256 +
 OpenFreezer/cgi/vector_frames.py                   |  1138 +
 OpenFreezer/cgi/vector_map.py                      |   917 +
 OpenFreezer/cgi/vector_oligos.py                   |   336 +
 OpenFreezer/cgi/vector_sequence.py                 |   505 +
 OpenFreezer/cgi/well.py                            |    86 +
 OpenFreezer/contacts.php                           |   105 +
 OpenFreezer/copyright.php                          |   125 +
 OpenFreezer/dedication.php                         |    60 +
 OpenFreezer/docs.php                               |   130 +
 OpenFreezer/exportChemical.php                     |    10 +
 OpenFreezer/functions.php                          |   334 +
 OpenFreezer/index.php                              |   102 +
 OpenFreezer/orderExcel.php                         |    10 +
 OpenFreezer/overlib/BabelFish.js                   |    58 +
 OpenFreezer/overlib/Mini/overlib_anchor_mini.js    |    98 +
 .../overlib/Mini/overlib_centerpopup_mini.js       |    28 +
 .../overlib/Mini/overlib_crossframe_mini.js        |    36 +
 OpenFreezer/overlib/Mini/overlib_csstyle_mini.js   |    45 +
 OpenFreezer/overlib/Mini/overlib_debug_mini.js     |    49 +
 OpenFreezer/overlib/Mini/overlib_exclusive_mini.js |     1 +
 .../overlib/Mini/overlib_followscroll_mini.js      |    38 +
 OpenFreezer/overlib/Mini/overlib_hideform_mini.js  |    33 +
 OpenFreezer/overlib/Mini/overlib_mini.js           |   322 +
 OpenFreezer/overlib/Mini/overlib_setonoff_mini.js  |    32 +
 OpenFreezer/overlib/Mini/overlib_shadow_mini.js    |    53 +
 OpenFreezer/overlib/ajaxcontentmws.js              |   185 +
 OpenFreezer/overlib/arrow.gif                      |   Bin 0 -> 88 bytes
 OpenFreezer/overlib/calendarmws.js                 |   624 +
 OpenFreezer/overlib/calendarmws_lang.js            |   705 +
 OpenFreezer/overlib/cornerBL.gif                   |   Bin 0 -> 205 bytes
 OpenFreezer/overlib/cornerBR.gif                   |   Bin 0 -> 208 bytes
 OpenFreezer/overlib/cornerTL.gif                   |   Bin 0 -> 207 bytes
 OpenFreezer/overlib/cornerTR.gif                   |   Bin 0 -> 206 bytes
 OpenFreezer/overlib/edgeB.gif                      |   Bin 0 -> 47 bytes
 OpenFreezer/overlib/edgeL.gif                      |   Bin 0 -> 48 bytes
 OpenFreezer/overlib/edgeR.gif                      |   Bin 0 -> 48 bytes
 OpenFreezer/overlib/edgeT.gif                      |   Bin 0 -> 47 bytes
 OpenFreezer/overlib/exit.gif                       |   Bin 0 -> 866 bytes
 OpenFreezer/overlib/exit_blue.gif                  |   Bin 0 -> 371 bytes
 OpenFreezer/overlib/exit_metallic.gif              |   Bin 0 -> 371 bytes
 OpenFreezer/overlib/flower.gif                     |   Bin 0 -> 4255 bytes
 OpenFreezer/overlib/htmlspecialcharsmws.js         |    68 +
 OpenFreezer/overlib/iframecontentmws.js            |    53 +
 OpenFreezer/overlib/inputText.gif                  |   Bin 0 -> 93 bytes
 OpenFreezer/overlib/license.html                   |   265 +
 OpenFreezer/overlib/loading.gif                    |   Bin 0 -> 674 bytes
 OpenFreezer/overlib/makemini.pl                    |    95 +
 OpenFreezer/overlib/objectcontentmws.js            |    16 +
 OpenFreezer/overlib/oval.gif                       |   Bin 0 -> 3662 bytes
 OpenFreezer/overlib/overlib.js                     |  1491 ++
 OpenFreezer/overlib/overlib421.zip                 |   Bin 0 -> 62403 bytes
 OpenFreezer/overlib/overlibCompat.js               |    30 +
 OpenFreezer/overlib/overlibConfig.txt              |   650 +
 OpenFreezer/overlib/overlib_anchor.js              |   333 +
 OpenFreezer/overlib/overlib_centerpopup.js         |    89 +
 OpenFreezer/overlib/overlib_crossframe.js          |   105 +
 OpenFreezer/overlib/overlib_cssstyle.js            |   182 +
 OpenFreezer/overlib/overlib_debug.js               |   177 +
 OpenFreezer/overlib/overlib_exclusive.js           |   123 +
 OpenFreezer/overlib/overlib_followscroll.js        |   175 +
 OpenFreezer/overlib/overlib_hideform.js            |   135 +
 OpenFreezer/overlib/overlib_setonoff.js            |   101 +
 OpenFreezer/overlib/overlib_shadow.js              |   270 +
 OpenFreezer/overlib/overlibmws.js                  |   622 +
 OpenFreezer/overlib/overlibmws.zip                 |   Bin 0 -> 93422 bytes
 OpenFreezer/overlib/overlibmws_bubble.js           |   134 +
 OpenFreezer/overlib/overlibmws_crossframe.js       |    58 +
 OpenFreezer/overlib/overlibmws_debug.js            |   120 +
 OpenFreezer/overlib/overlibmws_draggable.js        |    85 +
 OpenFreezer/overlib/overlibmws_exclusive.js        |    58 +
 OpenFreezer/overlib/overlibmws_filter.js           |   156 +
 OpenFreezer/overlib/overlibmws_function.js         |    44 +
 OpenFreezer/overlib/overlibmws_hide.js             |    81 +
 OpenFreezer/overlib/overlibmws_iframe.js           |    93 +
 OpenFreezer/overlib/overlibmws_modal.js            |   139 +
 OpenFreezer/overlib/overlibmws_overtwo.js          |   117 +
 OpenFreezer/overlib/overlibmws_print.js            |   143 +
 OpenFreezer/overlib/overlibmws_regCore.js          |    75 +
 OpenFreezer/overlib/overlibmws_scroll.js           |    70 +
 OpenFreezer/overlib/overlibmws_shadow.js           |   113 +
 OpenFreezer/overlib/overlibmwslogo.gif             |   Bin 0 -> 1403 bytes
 OpenFreezer/overlib/print.gif                      |   Bin 0 -> 866 bytes
 OpenFreezer/overlib/pushpin.gif                    |   Bin 0 -> 1854 bytes
 OpenFreezer/overlib/quotation.gif                  |   Bin 0 -> 1080 bytes
 OpenFreezer/overlib/raised_blue.gif                |   Bin 0 -> 881 bytes
 OpenFreezer/overlib/raised_metallic.gif            |   Bin 0 -> 882 bytes
 OpenFreezer/overlib/semitrans.gif                  |   Bin 0 -> 757 bytes
 OpenFreezer/overlib/showCalendar.gif               |   Bin 0 -> 200 bytes
 OpenFreezer/overlib/sprintf.js                     |   133 +
 OpenFreezer/overlib/square.gif                     |   Bin 0 -> 2580 bytes
 OpenFreezer/pictures/1280352360_arrow_collapse.gif |   Bin 0 -> 79 bytes
 OpenFreezer/pictures/1NYK.jpg                      |   Bin 0 -> 5101 bytes
 OpenFreezer/pictures/1px.gif                       |   Bin 0 -> 49 bytes
 OpenFreezer/pictures/LIM.gif                       |   Bin 0 -> 306 bytes
 OpenFreezer/pictures/Mom.jpg                       |   Bin 0 -> 19501 bytes
 OpenFreezer/pictures/SH2_domain.gif                |   Bin 0 -> 57483 bytes
 OpenFreezer/pictures/V117609_map.svg               |    97 +
 OpenFreezer/pictures/WS_FTP.LOG                    |    22 +
 OpenFreezer/pictures/a1.png                        |   Bin 0 -> 28540 bytes
 OpenFreezer/pictures/a2.png                        |   Bin 0 -> 24354 bytes
 OpenFreezer/pictures/about_hover.png               |   Bin 0 -> 1656 bytes
 OpenFreezer/pictures/add_reagent_screenshot.png    |   Bin 0 -> 174955 bytes
 OpenFreezer/pictures/allgold.png                   |   Bin 0 -> 4854 bytes
 OpenFreezer/pictures/arrow-menu.png                |   Bin 0 -> 290 bytes
 OpenFreezer/pictures/arrow-right.png               |   Bin 0 -> 2028 bytes
 OpenFreezer/pictures/arrow.png                     |   Bin 0 -> 326 bytes
 OpenFreezer/pictures/arrow2.png                    |   Bin 0 -> 9566 bytes
 OpenFreezer/pictures/arrow3.png                    |   Bin 0 -> 8707 bytes
 OpenFreezer/pictures/arrow4.png                    |   Bin 0 -> 8546 bytes
 OpenFreezer/pictures/arrow_collapse.gif            |   Bin 0 -> 856 bytes
 OpenFreezer/pictures/arrow_expand.gif              |   Bin 0 -> 901 bytes
 OpenFreezer/pictures/arrow_more.png                |   Bin 0 -> 182 bytes
 OpenFreezer/pictures/back_arrow.png                |   Bin 0 -> 16819 bytes
 OpenFreezer/pictures/background-beige.png          |   Bin 0 -> 5162 bytes
 OpenFreezer/pictures/background-gray.png           |   Bin 0 -> 2645 bytes
 OpenFreezer/pictures/background-texture.png        |   Bin 0 -> 30297 bytes
 OpenFreezer/pictures/background.jpg                |   Bin 0 -> 8713 bytes
 OpenFreezer/pictures/background.png                |   Bin 0 -> 7350 bytes
 OpenFreezer/pictures/bah.png                       |   Bin 0 -> 37488 bytes
 OpenFreezer/pictures/bg.png                        |   Bin 0 -> 636 bytes
 OpenFreezer/pictures/bg2.png                       |   Bin 0 -> 374 bytes
 OpenFreezer/pictures/bg3.png                       |   Bin 0 -> 193 bytes
 OpenFreezer/pictures/bg4.png                       |   Bin 0 -> 907 bytes
 OpenFreezer/pictures/bg5.png                       |   Bin 0 -> 905 bytes
 OpenFreezer/pictures/bg6.png                       |   Bin 0 -> 795 bytes
 OpenFreezer/pictures/bg7.png                       |   Bin 0 -> 691 bytes
 OpenFreezer/pictures/bg8.png                       |   Bin 0 -> 189 bytes
 OpenFreezer/pictures/bg9.png                       |   Bin 0 -> 699 bytes
 OpenFreezer/pictures/bg_active.png                 |   Bin 0 -> 13573 bytes
 OpenFreezer/pictures/bgetst.png                    |   Bin 0 -> 2131 bytes
 OpenFreezer/pictures/bgtemp.png                    |   Bin 0 -> 11933 bytes
 OpenFreezer/pictures/bgtmp.png                     |   Bin 0 -> 5824 bytes
 OpenFreezer/pictures/bigbottomgray.png             |   Bin 0 -> 983 bytes
 OpenFreezer/pictures/bigtopgray.png                |   Bin 0 -> 1065 bytes
 OpenFreezer/pictures/bio_bullet.gif                |   Bin 0 -> 270 bytes
 OpenFreezer/pictures/black.png                     |   Bin 0 -> 180 bytes
 OpenFreezer/pictures/black1px.gif                  |   Bin 0 -> 49 bytes
 OpenFreezer/pictures/bluelines.png                 |   Bin 0 -> 700 bytes
 OpenFreezer/pictures/border.jpg                    |   Bin 0 -> 4774 bytes
 OpenFreezer/pictures/border_down.jpg               |   Bin 0 -> 4638 bytes
 OpenFreezer/pictures/bottomdarkgray.png            |   Bin 0 -> 710 bytes
 OpenFreezer/pictures/bottomshadowframe.png         |   Bin 0 -> 6808 bytes
 OpenFreezer/pictures/bubble.gif                    |   Bin 0 -> 1147 bytes
 OpenFreezer/pictures/bubble_filler.gif             |   Bin 0 -> 71 bytes
 OpenFreezer/pictures/bubble_middle.gif             |   Bin 0 -> 2252 bytes
 OpenFreezer/pictures/bug_hover.png                 |   Bin 0 -> 2325 bytes
 OpenFreezer/pictures/bullet-menu.png               |   Bin 0 -> 553 bytes
 OpenFreezer/pictures/bullet.gif                    |   Bin 0 -> 62 bytes
 OpenFreezer/pictures/bullet.png                    |   Bin 0 -> 2417 bytes
 OpenFreezer/pictures/button.png                    |   Bin 0 -> 457 bytes
 OpenFreezer/pictures/button_bg.png                 |   Bin 0 -> 216 bytes
 OpenFreezer/pictures/button_collapse.png           |   Bin 0 -> 912 bytes
 OpenFreezer/pictures/button_collapse2.png          |   Bin 0 -> 708 bytes
 OpenFreezer/pictures/button_collapse_blue.png      |   Bin 0 -> 949 bytes
 OpenFreezer/pictures/button_expand.png             |   Bin 0 -> 873 bytes
 OpenFreezer/pictures/button_expand2.png            |   Bin 0 -> 836 bytes
 OpenFreezer/pictures/button_select.gif             |   Bin 0 -> 1257 bytes
 OpenFreezer/pictures/buttonbg.png                  |   Bin 0 -> 1373 bytes
 OpenFreezer/pictures/buttonsborder.png             |   Bin 0 -> 1541 bytes
 OpenFreezer/pictures/cell_assoc.gif                |   Bin 0 -> 29457 bytes
 OpenFreezer/pictures/cell_assoc.png                |   Bin 0 -> 29457 bytes
 OpenFreezer/pictures/charcoalframe.png             |   Bin 0 -> 12426 bytes
 OpenFreezer/pictures/clientserverdiagm.png         |   Bin 0 -> 73017 bytes
 OpenFreezer/pictures/clone.gif                     |   Bin 0 -> 903 bytes
 OpenFreezer/pictures/collapse.png                  |   Bin 0 -> 479 bytes
 OpenFreezer/pictures/complogo.bmp                  |   Bin 0 -> 1907182 bytes
 OpenFreezer/pictures/complogo2.bmp                 |   Bin 0 -> 295214 bytes
 OpenFreezer/pictures/computer.jpg                  |   Bin 0 -> 3010 bytes
 OpenFreezer/pictures/contact_hover.png             |   Bin 0 -> 1883 bytes
 OpenFreezer/pictures/contrast.gif                  |   Bin 0 -> 7499 bytes
 OpenFreezer/pictures/copyright_hover.png           |   Bin 0 -> 2012 bytes
 OpenFreezer/pictures/creambg.png                   |   Bin 0 -> 5550 bytes
 OpenFreezer/pictures/creamline.png                 |   Bin 0 -> 215 bytes
 OpenFreezer/pictures/cursor_pointer.gif            |   Bin 0 -> 125 bytes
 OpenFreezer/pictures/darkbottomgray.png            |   Bin 0 -> 738 bytes
 OpenFreezer/pictures/darkgrayline.png              |   Bin 0 -> 145 bytes
 OpenFreezer/pictures/dbdiagm.png                   |   Bin 0 -> 32990 bytes
 OpenFreezer/pictures/dedication.png                |   Bin 0 -> 1977 bytes
 OpenFreezer/pictures/dedication_hover.png          |   Bin 0 -> 1931 bytes
 OpenFreezer/pictures/del.gif                       |   Bin 0 -> 8913 bytes
 OpenFreezer/pictures/delete_icon.jpg               |   Bin 0 -> 988 bytes
 OpenFreezer/pictures/disk_small.gif                |   Bin 0 -> 345 bytes
 OpenFreezer/pictures/divider.gif                   |   Bin 0 -> 148 bytes
 OpenFreezer/pictures/divider.png                   |   Bin 0 -> 2663 bytes
 OpenFreezer/pictures/dna.png                       |   Bin 0 -> 20997 bytes
 OpenFreezer/pictures/docs_focus.png                |   Bin 0 -> 2414 bytes
 OpenFreezer/pictures/docs_hover.png                |   Bin 0 -> 2455 bytes
 OpenFreezer/pictures/double.png                    |   Bin 0 -> 253 bytes
 OpenFreezer/pictures/down_new.png                  |   Bin 0 -> 733 bytes
 OpenFreezer/pictures/download.png                  |   Bin 0 -> 6069 bytes
 OpenFreezer/pictures/download_hover.png            |   Bin 0 -> 1808 bytes
 OpenFreezer/pictures/eighty_percent_map.png        |   Bin 0 -> 22692 bytes
 OpenFreezer/pictures/eighty_percent_search.png     |   Bin 0 -> 97950 bytes
 OpenFreezer/pictures/excel.gif                     |   Bin 0 -> 891 bytes
 OpenFreezer/pictures/expand.png                    |   Bin 0 -> 523 bytes
 OpenFreezer/pictures/faq_hover.png                 |   Bin 0 -> 1235 bytes
 OpenFreezer/pictures/fifty_percent_map.png         |   Bin 0 -> 9174 bytes
 OpenFreezer/pictures/firefox_logo.gif              |   Bin 0 -> 1145 bytes
 OpenFreezer/pictures/firefox_logo.jpg              |   Bin 0 -> 171708 bytes
 OpenFreezer/pictures/five_after_three.pdf          |   Bin 0 -> 29034 bytes
 OpenFreezer/pictures/focus_about.png               |   Bin 0 -> 1669 bytes
 OpenFreezer/pictures/focus_bug.png                 |   Bin 0 -> 2635 bytes
 OpenFreezer/pictures/focus_color.png               |   Bin 0 -> 191 bytes
 OpenFreezer/pictures/focus_contact.png             |   Bin 0 -> 1929 bytes
 OpenFreezer/pictures/focus_dedication.png          |   Bin 0 -> 2062 bytes
 OpenFreezer/pictures/focus_download.png            |   Bin 0 -> 1795 bytes
 OpenFreezer/pictures/focus_faq.png                 |   Bin 0 -> 1212 bytes
 OpenFreezer/pictures/focus_home.png                |   Bin 0 -> 1189 bytes
 OpenFreezer/pictures/focus_news.png                |   Bin 0 -> 1327 bytes
 OpenFreezer/pictures/frame.png                     |   Bin 0 -> 16184 bytes
 OpenFreezer/pictures/framenew.png                  |   Bin 0 -> 10550 bytes
 OpenFreezer/pictures/framewblackcorners.png        |   Bin 0 -> 6847 bytes
 OpenFreezer/pictures/freezer.jpg                   |   Bin 0 -> 22464 bytes
 OpenFreezer/pictures/freezer_w_tubes.jpg           |   Bin 0 -> 21945 bytes
 OpenFreezer/pictures/god.png                       |   Bin 0 -> 26413 bytes
 OpenFreezer/pictures/goldbg.png                    |   Bin 0 -> 9464 bytes
 OpenFreezer/pictures/goldlines.png                 |   Bin 0 -> 287 bytes
 OpenFreezer/pictures/goodqualitymap.png            |   Bin 0 -> 120971 bytes
 OpenFreezer/pictures/granite.png                   |   Bin 0 -> 20312 bytes
 OpenFreezer/pictures/granitegray.png               |   Bin 0 -> 38200 bytes
 OpenFreezer/pictures/gray_line.png                 |   Bin 0 -> 203 bytes
 OpenFreezer/pictures/gray_round_top_left.png       |   Bin 0 -> 645 bytes
 OpenFreezer/pictures/graybevelbottom.png           |   Bin 0 -> 13794 bytes
 OpenFreezer/pictures/graybevelframe.png            |   Bin 0 -> 14015 bytes
 OpenFreezer/pictures/graybevelupsidedown.png       |   Bin 0 -> 14136 bytes
 OpenFreezer/pictures/graybg.png                    |   Bin 0 -> 857 bytes
 OpenFreezer/pictures/graybg2.png                   |   Bin 0 -> 746 bytes
 OpenFreezer/pictures/graybottom.png                |   Bin 0 -> 438 bytes
 OpenFreezer/pictures/graybottomshadowframe.png     |   Bin 0 -> 9117 bytes
 OpenFreezer/pictures/grayline.png                  |   Bin 0 -> 145 bytes
 OpenFreezer/pictures/graylines.png                 |   Bin 0 -> 1055 bytes
 OpenFreezer/pictures/graylinewoutline.png          |   Bin 0 -> 295 bytes
 OpenFreezer/pictures/grayroundcorners.png          |   Bin 0 -> 775 bytes
 OpenFreezer/pictures/graytop.png                   |   Bin 0 -> 500 bytes
 OpenFreezer/pictures/graytopshadowframe.png        |   Bin 0 -> 9353 bytes
 OpenFreezer/pictures/graywborder.png               |   Bin 0 -> 13856 bytes
 OpenFreezer/pictures/grb2.jpg                      |   Bin 0 -> 61379 bytes
 OpenFreezer/pictures/green_bg.jpg                  |   Bin 0 -> 8676 bytes
 OpenFreezer/pictures/hdr.png                       |   Bin 0 -> 27237 bytes
 OpenFreezer/pictures/hdr10.png                     |   Bin 0 -> 36062 bytes
 OpenFreezer/pictures/hdr11.png                     |   Bin 0 -> 40711 bytes
 OpenFreezer/pictures/hdr2.png                      |   Bin 0 -> 27567 bytes
 OpenFreezer/pictures/hdr3.png                      |   Bin 0 -> 38387 bytes
 OpenFreezer/pictures/hdr4.png                      |   Bin 0 -> 27585 bytes
 OpenFreezer/pictures/hdr5.png                      |   Bin 0 -> 27585 bytes
 OpenFreezer/pictures/hdr6.png                      |   Bin 0 -> 27470 bytes
 OpenFreezer/pictures/hdr7.png                      |   Bin 0 -> 34114 bytes
 OpenFreezer/pictures/hdr8.png                      |   Bin 0 -> 30516 bytes
 OpenFreezer/pictures/hdr9.png                      |   Bin 0 -> 35327 bytes
 OpenFreezer/pictures/hdr_larisa.png                |   Bin 0 -> 20298 bytes
 OpenFreezer/pictures/hdr_of.png                    |   Bin 0 -> 13860 bytes
 OpenFreezer/pictures/hdr_short.png                 |   Bin 0 -> 33083 bytes
 OpenFreezer/pictures/hdr_tux.png                   |   Bin 0 -> 7449 bytes
 OpenFreezer/pictures/header.png                    |   Bin 0 -> 40077 bytes
 OpenFreezer/pictures/header5.png                   |   Bin 0 -> 65040 bytes
 OpenFreezer/pictures/header_new.png                |   Bin 0 -> 38208 bytes
 OpenFreezer/pictures/header_trans.jpg              |   Bin 0 -> 23963 bytes
 OpenFreezer/pictures/heading.png                   |   Bin 0 -> 37070 bytes
 OpenFreezer/pictures/heading10.png                 |   Bin 0 -> 40005 bytes
 OpenFreezer/pictures/heading11.png                 |   Bin 0 -> 41407 bytes
 OpenFreezer/pictures/heading12.png                 |   Bin 0 -> 41793 bytes
 OpenFreezer/pictures/heading13.png                 |   Bin 0 -> 42176 bytes
 OpenFreezer/pictures/heading14.png                 |   Bin 0 -> 36408 bytes
 OpenFreezer/pictures/heading15.png                 |   Bin 0 -> 37721 bytes
 OpenFreezer/pictures/heading2.png                  |   Bin 0 -> 41292 bytes
 OpenFreezer/pictures/heading3.png                  |   Bin 0 -> 41595 bytes
 OpenFreezer/pictures/heading4.png                  |   Bin 0 -> 41659 bytes
 OpenFreezer/pictures/heading5.png                  |   Bin 0 -> 44888 bytes
 OpenFreezer/pictures/heading6.png                  |   Bin 0 -> 43691 bytes
 OpenFreezer/pictures/heading7.png                  |   Bin 0 -> 45785 bytes
 OpenFreezer/pictures/heading8.png                  |   Bin 0 -> 41168 bytes
 OpenFreezer/pictures/heading9.png                  |   Bin 0 -> 44188 bytes
 OpenFreezer/pictures/heading_larisa.png            |   Bin 0 -> 41487 bytes
 OpenFreezer/pictures/heading_new.png               |   Bin 0 -> 40679 bytes
 OpenFreezer/pictures/help.gif                      |   Bin 0 -> 894 bytes
 OpenFreezer/pictures/help_hover.png                |   Bin 0 -> 1065 bytes
 OpenFreezer/pictures/help_orange.gif               |   Bin 0 -> 903 bytes
 OpenFreezer/pictures/hm4.png                       |   Bin 0 -> 6086 bytes
 OpenFreezer/pictures/hm6.png                       |   Bin 0 -> 6653 bytes
 OpenFreezer/pictures/home_hover.png                |   Bin 0 -> 1191 bytes
 OpenFreezer/pictures/hr.png                        |   Bin 0 -> 460 bytes
 OpenFreezer/pictures/icebg.jpg                     |   Bin 0 -> 95935 bytes
 OpenFreezer/pictures/images.jpg                    |   Bin 0 -> 1060 bytes
 OpenFreezer/pictures/insert_example.png            |   Bin 0 -> 44350 bytes
 OpenFreezer/pictures/just_larisa.png               |   Bin 0 -> 21373 bytes
 OpenFreezer/pictures/lab.html                      |    97 +
 OpenFreezer/pictures/largemapwborder.png           |   Bin 0 -> 37959 bytes
 OpenFreezer/pictures/larisa.png                    |   Bin 0 -> 42474 bytes
 OpenFreezer/pictures/larisa1.png                   |   Bin 0 -> 47199 bytes
 OpenFreezer/pictures/larisa2.png                   |   Bin 0 -> 40655 bytes
 OpenFreezer/pictures/larisa3.png                   |   Bin 0 -> 10856 bytes
 OpenFreezer/pictures/larisa4.png                   |   Bin 0 -> 10999 bytes
 OpenFreezer/pictures/larisa_all.png                |   Bin 0 -> 11107 bytes
 OpenFreezer/pictures/larisa_alone.png              |   Bin 0 -> 22912 bytes
 OpenFreezer/pictures/larisa_blue.png               |   Bin 0 -> 16504 bytes
 OpenFreezer/pictures/larisa_final.png              |   Bin 0 -> 18107 bytes
 OpenFreezer/pictures/larisa_glow.png               |   Bin 0 -> 47506 bytes
 OpenFreezer/pictures/larisa_glow_caps.png          |   Bin 0 -> 42706 bytes
 OpenFreezer/pictures/larisa_glow_shadow.png        |   Bin 0 -> 70907 bytes
 OpenFreezer/pictures/larisa_hdr.png                |   Bin 0 -> 12470 bytes
 OpenFreezer/pictures/larisa_hdr2.png               |   Bin 0 -> 21558 bytes
 OpenFreezer/pictures/larisa_hdr_&.png              |   Bin 0 -> 8390 bytes
 OpenFreezer/pictures/larisa_new.png                |   Bin 0 -> 24178 bytes
 OpenFreezer/pictures/larisa_plain.png              |   Bin 0 -> 30983 bytes
 OpenFreezer/pictures/left.png                      |   Bin 0 -> 1383 bytes
 OpenFreezer/pictures/leftinnershadowframe.png      |   Bin 0 -> 10303 bytes
 OpenFreezer/pictures/less_vertical.gif             |   Bin 0 -> 229 bytes
 OpenFreezer/pictures/license_hover.png             |   Bin 0 -> 1412 bytes
 OpenFreezer/pictures/lin.png                       |   Bin 0 -> 312 bytes
 OpenFreezer/pictures/lin2.png                      |   Bin 0 -> 333 bytes
 OpenFreezer/pictures/lin_vert.png                  |   Bin 0 -> 215 bytes
 OpenFreezer/pictures/line.png                      |   Bin 0 -> 206 bytes
 OpenFreezer/pictures/line3.png                     |   Bin 0 -> 233 bytes
 OpenFreezer/pictures/line4.png                     |   Bin 0 -> 585 bytes
 OpenFreezer/pictures/lines.png                     |   Bin 0 -> 283 bytes
 OpenFreezer/pictures/lines2.png                    |   Bin 0 -> 200 bytes
 OpenFreezer/pictures/link2.png                     |   Bin 0 -> 2514 bytes
 OpenFreezer/pictures/link3.png                     |   Bin 0 -> 660 bytes
 OpenFreezer/pictures/link4.png                     |   Bin 0 -> 683 bytes
 OpenFreezer/pictures/link5.png                     |   Bin 0 -> 5458 bytes
 OpenFreezer/pictures/link6.png                     |   Bin 0 -> 4083 bytes
 OpenFreezer/pictures/link7.png                     |   Bin 0 -> 3841 bytes
 OpenFreezer/pictures/link_icon.png                 |   Bin 0 -> 1708 bytes
 OpenFreezer/pictures/logo.jpg                      |   Bin 0 -> 21945 bytes
 OpenFreezer/pictures/mainbullet.png                |   Bin 0 -> 445 bytes
 OpenFreezer/pictures/mainbullet2.png               |   Bin 0 -> 444 bytes
 OpenFreezer/pictures/map.png                       |   Bin 0 -> 76478 bytes
 OpenFreezer/pictures/map2.png                      |   Bin 0 -> 33756 bytes
 OpenFreezer/pictures/map3.png                      |   Bin 0 -> 30725 bytes
 OpenFreezer/pictures/map4.png                      |   Bin 0 -> 35014 bytes
 OpenFreezer/pictures/map_small.png                 |   Bin 0 -> 57113 bytes
 OpenFreezer/pictures/mapcontrast.png               |   Bin 0 -> 40091 bytes
 OpenFreezer/pictures/mapframe.png                  |   Bin 0 -> 32165 bytes
 OpenFreezer/pictures/mbio3.jpg                     |   Bin 0 -> 14350 bytes
 OpenFreezer/pictures/menu_bg.png                   |   Bin 0 -> 48433 bytes
 OpenFreezer/pictures/menubg.png                    |   Bin 0 -> 2052 bytes
 OpenFreezer/pictures/minus.gif                     |   Bin 0 -> 828 bytes
 OpenFreezer/pictures/minus.png                     |   Bin 0 -> 140 bytes
 OpenFreezer/pictures/mol_bullet.gif                |   Bin 0 -> 288 bytes
 OpenFreezer/pictures/more-info.gif                 |   Bin 0 -> 1407 bytes
 OpenFreezer/pictures/more_vertical.gif             |   Bin 0 -> 252 bytes
 OpenFreezer/pictures/new01.gif                     |   Bin 0 -> 1016 bytes
 OpenFreezer/pictures/new_hdr.png                   |   Bin 0 -> 25304 bytes
 OpenFreezer/pictures/new_header.png                |   Bin 0 -> 33704 bytes
 OpenFreezer/pictures/newframe.png                  |   Bin 0 -> 9942 bytes
 OpenFreezer/pictures/newmap.jpg                    |   Bin 0 -> 208304 bytes
 OpenFreezer/pictures/newmap.png                    |   Bin 0 -> 122737 bytes
 OpenFreezer/pictures/newof.png                     |   Bin 0 -> 41041 bytes
 OpenFreezer/pictures/news_hover.png                |   Bin 0 -> 1270 bytes
 OpenFreezer/pictures/newsearch.png                 |   Bin 0 -> 58344 bytes
 OpenFreezer/pictures/newtitle.png                  |   Bin 0 -> 4030 bytes
 OpenFreezer/pictures/ninety_percent_map.png        |   Bin 0 -> 27453 bytes
 OpenFreezer/pictures/nonrecomb_vector.pdf          |   Bin 0 -> 29103 bytes
 OpenFreezer/pictures/null.gif                      |   Bin 0 -> 98 bytes
 OpenFreezer/pictures/objectmodel.png               |   Bin 0 -> 57441 bytes
 OpenFreezer/pictures/of_hding.png                  |   Bin 0 -> 40968 bytes
 OpenFreezer/pictures/of_hding2.png                 |   Bin 0 -> 43436 bytes
 OpenFreezer/pictures/of_hding3.png                 |   Bin 0 -> 43465 bytes
 OpenFreezer/pictures/of_hding4.png                 |   Bin 0 -> 43470 bytes
 OpenFreezer/pictures/of_hding5.png                 |   Bin 0 -> 44825 bytes
 OpenFreezer/pictures/of_hding6.png                 |   Bin 0 -> 44982 bytes
 OpenFreezer/pictures/of_larisa.png                 |   Bin 0 -> 36415 bytes
 OpenFreezer/pictures/of_lims.PNG                   |   Bin 0 -> 22830 bytes
 OpenFreezer/pictures/of_logo.png                   |   Bin 0 -> 48011 bytes
 OpenFreezer/pictures/of_trans.jpg                  |   Bin 0 -> 18613 bytes
 OpenFreezer/pictures/offinal.png                   |   Bin 0 -> 36955 bytes
 OpenFreezer/pictures/ofhdr.png                     |   Bin 0 -> 40235 bytes
 OpenFreezer/pictures/ofnew.png                     |   Bin 0 -> 36962 bytes
 OpenFreezer/pictures/ofsingle.png                  |   Bin 0 -> 36305 bytes
 OpenFreezer/pictures/oftitlefinal.png              |   Bin 0 -> 42355 bytes
 OpenFreezer/pictures/ok.png                        |   Bin 0 -> 716 bytes
 OpenFreezer/pictures/ok2.png                       |   Bin 0 -> 755 bytes
 OpenFreezer/pictures/ok3.png                       |   Bin 0 -> 641 bytes
 OpenFreezer/pictures/openfreezer.jpg               |   Bin 0 -> 20333 bytes
 OpenFreezer/pictures/openfreezer.png               |   Bin 0 -> 16175 bytes
 OpenFreezer/pictures/page_bg.gif                   |   Bin 0 -> 1426 bytes
 OpenFreezer/pictures/page_bg_temp.gif              |   Bin 0 -> 1307 bytes
 OpenFreezer/pictures/page_bg_temp.jpg              |   Bin 0 -> 414 bytes
 OpenFreezer/pictures/parchment.png                 |   Bin 0 -> 107976 bytes
 OpenFreezer/pictures/penguin_alone.gif             |   Bin 0 -> 627 bytes
 OpenFreezer/pictures/penguin_transparent.gif       |   Bin 0 -> 4267 bytes
 OpenFreezer/pictures/ph_sci-microscope.jpg         |   Bin 0 -> 75129 bytes
 OpenFreezer/pictures/pinkline.png                  |   Bin 0 -> 200 bytes
 OpenFreezer/pictures/plus.gif                      |   Bin 0 -> 836 bytes
 OpenFreezer/pictures/plus.png                      |   Bin 0 -> 149 bytes
 OpenFreezer/pictures/plus_bullet.gif               |   Bin 0 -> 59 bytes
 OpenFreezer/pictures/project.html                  |   110 +
 OpenFreezer/pictures/proteins_transparent.gif      |   Bin 0 -> 22165 bytes
 OpenFreezer/pictures/q3.png                        |   Bin 0 -> 607 bytes
 OpenFreezer/pictures/ratti.lg.jpg                  |   Bin 0 -> 134276 bytes
 OpenFreezer/pictures/ratti.lg_2.jpg                |   Bin 0 -> 12077 bytes
 OpenFreezer/pictures/read_more.png                 |   Bin 0 -> 482 bytes
 OpenFreezer/pictures/redtop.png                    |   Bin 0 -> 501 bytes
 OpenFreezer/pictures/redtop2.png                   |   Bin 0 -> 764 bytes
 OpenFreezer/pictures/redtop3.png                   |   Bin 0 -> 877 bytes
 OpenFreezer/pictures/researcher.jpg                |   Bin 0 -> 17544 bytes
 OpenFreezer/pictures/right.png                     |   Bin 0 -> 1397 bytes
 OpenFreezer/pictures/roses.gif                     |   Bin 0 -> 3262 bytes
 OpenFreezer/pictures/roses2.gif                    |   Bin 0 -> 3253 bytes
 OpenFreezer/pictures/round.png                     |   Bin 0 -> 193 bytes
 OpenFreezer/pictures/round_bl.png                  |   Bin 0 -> 677 bytes
 OpenFreezer/pictures/round_br.png                  |   Bin 0 -> 629 bytes
 OpenFreezer/pictures/round_tl.png                  |   Bin 0 -> 667 bytes
 OpenFreezer/pictures/round_tr.png                  |   Bin 0 -> 636 bytes
 OpenFreezer/pictures/round_up.png                  |   Bin 0 -> 362 bytes
 OpenFreezer/pictures/rt.png                        |   Bin 0 -> 1639 bytes
 OpenFreezer/pictures/rt2.png                       |   Bin 0 -> 911 bytes
 OpenFreezer/pictures/rt3.png                       |   Bin 0 -> 775 bytes
 OpenFreezer/pictures/rt4.png                       |   Bin 0 -> 803 bytes
 OpenFreezer/pictures/rt5.png                       |   Bin 0 -> 812 bytes
 OpenFreezer/pictures/rt6.png                       |   Bin 0 -> 820 bytes
 OpenFreezer/pictures/rt7.png                       |   Bin 0 -> 555 bytes
 OpenFreezer/pictures/rt8.png                       |   Bin 0 -> 759 bytes
 OpenFreezer/pictures/rt9.png                       |   Bin 0 -> 649 bytes
 OpenFreezer/pictures/rtplain.png                   |   Bin 0 -> 207 bytes
 OpenFreezer/pictures/save.gif                      |   Bin 0 -> 2314 bytes
 OpenFreezer/pictures/save_blue.gif                 |   Bin 0 -> 2325 bytes
 OpenFreezer/pictures/screenshot.jpg                |   Bin 0 -> 120952 bytes
 OpenFreezer/pictures/screenshot_w_border.jpg       |   Bin 0 -> 67796 bytes
 OpenFreezer/pictures/search2.png                   |   Bin 0 -> 61268 bytes
 OpenFreezer/pictures/search3.png                   |   Bin 0 -> 60018 bytes
 OpenFreezer/pictures/search4.png                   |   Bin 0 -> 59933 bytes
 OpenFreezer/pictures/search_95.png                 |   Bin 0 -> 58410 bytes
 OpenFreezer/pictures/search_compressed.png         |   Bin 0 -> 61554 bytes
 OpenFreezer/pictures/search_cropped.png            |   Bin 0 -> 142405 bytes
 OpenFreezer/pictures/search_screen.png             |   Bin 0 -> 164279 bytes
 OpenFreezer/pictures/selcolor.htm                  |   203 +
 OpenFreezer/pictures/sh2_3d.gif                    |   Bin 0 -> 20383 bytes
 OpenFreezer/pictures/sh2_domain.jpg                |   Bin 0 -> 19428 bytes
 OpenFreezer/pictures/sh3_habil.gif                 |   Bin 0 -> 10581 bytes
 OpenFreezer/pictures/shadowframe.png               |   Bin 0 -> 9198 bytes
 OpenFreezer/pictures/sharp_map.png                 |   Bin 0 -> 32603 bytes
 OpenFreezer/pictures/side_about.png                |   Bin 0 -> 3013 bytes
 OpenFreezer/pictures/side_copyright.png            |   Bin 0 -> 3462 bytes
 OpenFreezer/pictures/side_docs.png                 |   Bin 0 -> 4122 bytes
 OpenFreezer/pictures/side_docs_btn_small.png       |   Bin 0 -> 2471 bytes
 OpenFreezer/pictures/side_download.png             |   Bin 0 -> 3220 bytes
 OpenFreezer/pictures/side_help.png                 |   Bin 0 -> 2194 bytes
 OpenFreezer/pictures/side_home.png                 |   Bin 0 -> 2399 bytes
 OpenFreezer/pictures/side_news.png                 |   Bin 0 -> 2517 bytes
 OpenFreezer/pictures/silver_border_all.png         |   Bin 0 -> 8749 bytes
 OpenFreezer/pictures/silver_bullet.png             |   Bin 0 -> 2795 bytes
 OpenFreezer/pictures/silver_bullet2.png            |   Bin 0 -> 3929 bytes
 OpenFreezer/pictures/silverbg.png                  |   Bin 0 -> 5129 bytes
 OpenFreezer/pictures/silverborder.png              |   Bin 0 -> 12598 bytes
 OpenFreezer/pictures/silverframe.png               |   Bin 0 -> 7621 bytes
 OpenFreezer/pictures/silverframe2.png              |   Bin 0 -> 9699 bytes
 OpenFreezer/pictures/silverframe3.png              |   Bin 0 -> 5507 bytes
 OpenFreezer/pictures/silvermenubullet.png          |   Bin 0 -> 917 bytes
 OpenFreezer/pictures/sitebg.jpg                    |   Bin 0 -> 22575 bytes
 OpenFreezer/pictures/sitebg.png                    |   Bin 0 -> 34875 bytes
 OpenFreezer/pictures/small_bg.png                  |   Bin 0 -> 580 bytes
 OpenFreezer/pictures/small_sharp_amp.png           |   Bin 0 -> 30161 bytes
 OpenFreezer/pictures/smaller_map.png               |   Bin 0 -> 27453 bytes
 OpenFreezer/pictures/smallergrayframe.png          |   Bin 0 -> 13837 bytes
 OpenFreezer/pictures/smallmap.png                  |   Bin 0 -> 52370 bytes
 OpenFreezer/pictures/smallmapwborder.png           |   Bin 0 -> 26175 bytes
 OpenFreezer/pictures/smallsearch.png               |   Bin 0 -> 46369 bytes
 OpenFreezer/pictures/smtg.png                      |   Bin 0 -> 27354 bytes
 OpenFreezer/pictures/sort/sort_blue_down.gif       |   Bin 0 -> 839 bytes
 OpenFreezer/pictures/sort/sort_blue_left.gif       |   Bin 0 -> 842 bytes
 OpenFreezer/pictures/sort/sort_blue_right.gif      |   Bin 0 -> 841 bytes
 OpenFreezer/pictures/sort/sort_blue_up.gif         |   Bin 0 -> 837 bytes
 OpenFreezer/pictures/sort/sort_down.gif            |   Bin 0 -> 839 bytes
 OpenFreezer/pictures/sort/sort_left.gif            |   Bin 0 -> 842 bytes
 OpenFreezer/pictures/sort/sort_red_down.gif        |   Bin 0 -> 848 bytes
 OpenFreezer/pictures/sort/sort_red_up.gif          |   Bin 0 -> 845 bytes
 OpenFreezer/pictures/sort/sort_right.gif           |   Bin 0 -> 841 bytes
 OpenFreezer/pictures/sort/sort_up.gif              |   Bin 0 -> 840 bytes
 OpenFreezer/pictures/sort_blue_down.gif            |   Bin 0 -> 98 bytes
 OpenFreezer/pictures/sort_blue_left.gif            |   Bin 0 -> 98 bytes
 OpenFreezer/pictures/sort_blue_right.gif           |   Bin 0 -> 98 bytes
 OpenFreezer/pictures/sort_blue_up.gif              |   Bin 0 -> 98 bytes
 OpenFreezer/pictures/sort_down.gif                 |   Bin 0 -> 98 bytes
 OpenFreezer/pictures/sort_left.gif                 |   Bin 0 -> 98 bytes
 OpenFreezer/pictures/sort_right.gif                |   Bin 0 -> 98 bytes
 OpenFreezer/pictures/sort_up.gif                   |   Bin 0 -> 98 bytes
 OpenFreezer/pictures/sphere_bullet.jpeg            |   Bin 0 -> 466 bytes
 OpenFreezer/pictures/spotfire.gif                  |   Bin 0 -> 1079 bytes
 OpenFreezer/pictures/star_bullet.gif               |   Bin 0 -> 865 bytes
 OpenFreezer/pictures/submenu_bg.png                |   Bin 0 -> 2276 bytes
 OpenFreezer/pictures/tab2.png                      |   Bin 0 -> 1167 bytes
 OpenFreezer/pictures/tabhelp.png                   |   Bin 0 -> 2582 bytes
 OpenFreezer/pictures/table_corner.gif              |   Bin 0 -> 114 bytes
 OpenFreezer/pictures/tblborder.png                 |   Bin 0 -> 1226 bytes
 OpenFreezer/pictures/test.png                      |   Bin 0 -> 39473 bytes
 OpenFreezer/pictures/test2.png                     |   Bin 0 -> 39542 bytes
 OpenFreezer/pictures/test_of.png                   |   Bin 0 -> 36241 bytes
 OpenFreezer/pictures/test_tubes.jpg                |   Bin 0 -> 16100 bytes
 OpenFreezer/pictures/testbg.png                    |   Bin 0 -> 1845 bytes
 OpenFreezer/pictures/testbg2.png                   |   Bin 0 -> 2404 bytes
 OpenFreezer/pictures/testframe.png                 |   Bin 0 -> 8414 bytes
 OpenFreezer/pictures/testgray.png                  |   Bin 0 -> 18200 bytes
 OpenFreezer/pictures/testmenu.png                  |   Bin 0 -> 2387 bytes
 OpenFreezer/pictures/text_final.png                |   Bin 0 -> 39158 bytes
 OpenFreezer/pictures/textoutline.png               |   Bin 0 -> 1334 bytes
 OpenFreezer/pictures/tm_trans.jpg                  |   Bin 0 -> 2850 bytes
 OpenFreezer/pictures/tmpof.png                     |   Bin 0 -> 40518 bytes
 OpenFreezer/pictures/top.png                       |   Bin 0 -> 1277 bytes
 OpenFreezer/pictures/top_about.png                 |   Bin 0 -> 1630 bytes
 OpenFreezer/pictures/top_bug.png                   |   Bin 0 -> 2252 bytes
 OpenFreezer/pictures/top_contact.png               |   Bin 0 -> 1858 bytes
 OpenFreezer/pictures/top_copyright.png             |   Bin 0 -> 1933 bytes
 OpenFreezer/pictures/top_docs.png                  |   Bin 0 -> 2406 bytes
 OpenFreezer/pictures/top_download.png              |   Bin 0 -> 1785 bytes
 OpenFreezer/pictures/top_faq.png                   |   Bin 0 -> 1207 bytes
 OpenFreezer/pictures/top_help.png                  |   Bin 0 -> 1033 bytes
 OpenFreezer/pictures/top_home.png                  |   Bin 0 -> 1171 bytes
 OpenFreezer/pictures/top_license.png               |   Bin 0 -> 1361 bytes
 OpenFreezer/pictures/top_news.png                  |   Bin 0 -> 1244 bytes
 OpenFreezer/pictures/topdarkgray.png               |   Bin 0 -> 753 bytes
 OpenFreezer/pictures/topleftround.png              |   Bin 0 -> 4305 bytes
 OpenFreezer/pictures/topline.png                   |   Bin 0 -> 957 bytes
 OpenFreezer/pictures/topshadowframe.png            |   Bin 0 -> 8437 bytes
 OpenFreezer/pictures/tux.PNG                       |   Bin 0 -> 6588 bytes
 OpenFreezer/pictures/tuxsicle.jpg                  |   Bin 0 -> 18289 bytes
 OpenFreezer/pictures/up_arrow.png                  |   Bin 0 -> 1038 bytes
 OpenFreezer/pictures/up_new.png                    |   Bin 0 -> 724 bytes
 OpenFreezer/pictures/vector_assoc.gif              |   Bin 0 -> 37331 bytes
 OpenFreezer/pictures/vector_assoc.png              |   Bin 0 -> 37331 bytes
 OpenFreezer/pictures/vector_diagm.pdf              |   Bin 0 -> 34333 bytes
 OpenFreezer/pictures/version_trans.jpg             |   Bin 0 -> 16981 bytes
 OpenFreezer/pictures/vert.png                      |   Bin 0 -> 143 bytes
 OpenFreezer/pictures/verysmallmap.png              |   Bin 0 -> 22053 bytes
 OpenFreezer/pictures/white-bullet.png              |   Bin 0 -> 1019 bytes
 OpenFreezer/pictures/whitegetfirefox80x15.gif      |   Bin 0 -> 859 bytes
 OpenFreezer/pictures/whmis/biohazard.jpg           |   Bin 0 -> 3152 bytes
 .../pictures/whmis/classificiation_system.pdf      |   Bin 0 -> 76053 bytes
 OpenFreezer/pictures/whmis/compressed_gas.jpg      |   Bin 0 -> 2485 bytes
 OpenFreezer/pictures/whmis/corrosive.jpg           |   Bin 0 -> 2928 bytes
 OpenFreezer/pictures/whmis/flammable.jpg           |   Bin 0 -> 2856 bytes
 .../pictures/whmis/new_images/biohazard.jpg        |   Bin 0 -> 2021 bytes
 .../pictures/whmis/new_images/compressed_gas.jpg   |   Bin 0 -> 2711 bytes
 .../pictures/whmis/new_images/corrosive.jpg        |   Bin 0 -> 3025 bytes
 .../pictures/whmis/new_images/flammable.jpg        |   Bin 0 -> 1665 bytes
 .../pictures/whmis/new_images/oxidizing.jpg        |   Bin 0 -> 2841 bytes
 .../pictures/whmis/new_images/poisonous.jpg        |   Bin 0 -> 3066 bytes
 OpenFreezer/pictures/whmis/new_images/reactive.jpg |   Bin 0 -> 2969 bytes
 OpenFreezer/pictures/whmis/new_images/toxic.jpg    |   Bin 0 -> 1538 bytes
 OpenFreezer/pictures/whmis/oxidizer.jpg            |   Bin 0 -> 2957 bytes
 OpenFreezer/pictures/whmis/poisonous.jpg           |   Bin 0 -> 3232 bytes
 OpenFreezer/pictures/whmis/reactive.jpg            |   Bin 0 -> 3023 bytes
 OpenFreezer/pictures/whmis/toxic.jpg               |   Bin 0 -> 1937 bytes
 OpenFreezer/pictures/yellow_bg.jpg                 |   Bin 0 -> 3879 bytes
 OpenFreezer/scripts/menu.js                        | 21066 +++++++++++++++++++
 OpenFreezer/search.php                             |   244 +
 OpenFreezer/styles/Header_styles.css               |   785 +
 OpenFreezer/styles/SearchStyle.css                 |   372 +
 OpenFreezer/styles/SearchStyle_old.css             |   102 +
 OpenFreezer/styles/SequenceStyle.css               |     7 +
 OpenFreezer/styles/WebsiteBasic.css                |   135 +
 OpenFreezer/styles/generic.css                     |   238 +
 UNIX_install_instructions.pdf                      |   Bin 0 -> 510933 bytes
 openfreezer.sql                                    |  1481 ++
 652 files changed, 119040 insertions(+)

diff --git a/OpenFreezer Database Notes.pdf b/OpenFreezer Database Notes.pdf
new file mode 100755
index 0000000..2718c4c
Binary files /dev/null and b/OpenFreezer Database Notes.pdf differ
diff --git a/OpenFreezer/Chemical.php b/OpenFreezer/Chemical.php
new file mode 100755
index 0000000..a51c484
--- /dev/null
+++ b/OpenFreezer/Chemical.php
@@ -0,0 +1,1354 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2010 Pawson Laboratory, All Rights Reserved
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Chemical
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Include/require statements
+*/
+	include_once "Classes/MemberLogin_Class.php";
+	include_once "Classes/Chemical_Class.php";
+
+	include_once "Project/ProjectFunctions.php";	// Aug 10/07; it includes Member_Class so don't need to redeclare it here
+
+	include_once "Classes/Session_Var_Class.php";
+	include_once "Classes/generalFunc_Class.php";
+	
+	include "Classes/StopWatch.php";
+
+	// Jan. 23/08: Order reagents
+	include "Location/Location_Funct_Class.php";
+	include "Classes/Order_Class.php";
+	
+	include_once "DatabaseConn.php";
+	include "HeaderFunctions.php";
+
+	/**
+	 * A constant used to define table width on User module views
+	 * @global INT $Const_Table_Width
+	*/
+	global $Const_Table_Width;
+	$colspan_const = 0;
+
+	header("Cache-control: private"); //IE 6 Fix 
+
+	session_start();
+
+	$loginBlock = new MemberLogin_Class( );  
+	$loginBlock->loginCheck( $_POST );
+
+	// print header	
+	outputMainHeader();
+
+	?>
+	<div class="main">
+		<table border="0" width="100%">
+			<?php
+			if (isset($_SESSION["userinfo"]))
+			{
+				if( $loginBlock->verifyPermissions( basename( $_SERVER["PHP_SELF"] ), $_SESSION["userinfo"]->getUserID( ) ) ) 
+				{
+					$sessionChecker = new Session_Var_Class();
+					$sessionChecker->checkSession_all(); 	// july 17/07
+					unset($sessionChecker);
+
+					$currUserID = $_SESSION["userinfo"]->getUserID();
+					$currUserName = $_SESSION["userinfo"]->getDescription();
+					?>
+					<tr>
+						<td>
+							<?php
+							if ($_GET["View"] == "1")
+							{
+								if (isset($_POST["search_chemical"]))
+								{
+									$results = findChemical();
+									printChemicalSearchResults($results);
+								}
+								else
+								{
+									printSearchForm();
+								}
+							}
+							else if ($_GET["View"] == "2")
+							{
+								// print_r($_POST);
+								if (isset($_POST["add_chemical"]))
+								{
+									//if (addChemical())
+										//echo "<SPAN style=\"color:#0000FF; font-weight:bold; font-family:Times; font-size:11pt;\">Chemical added successfully.</SPAN>";
+
+									$chemID = addChemical();
+//echo $chemID;
+								//	print_r($_POST);
+
+									if ($chemID > 0)
+										printChemicalDetails($chemID);
+										//print_r($_POST);
+								}
+								else
+								{
+									printCreationForm();
+								}
+							}
+							else if ($_GET["View"] == "3")
+							{
+								if (isset($_GET["chemicalID"]))
+								{
+									printChemicalDetails($_GET["chemicalID"]);
+								}
+							}
+							?>
+						</td>
+					</tr>
+					<?php
+				}
+				else
+				{
+					echo "<tr><td class=\"warning\">";
+					echo "Please log in to access this page.";
+					echo "</td></tr>";
+				}
+			}
+			else
+			{
+				echo "<tr><td class=\"warning\">";
+				echo "Please log in to access this page.";
+				echo "</td></tr>";
+			}
+		?>
+		</table>
+	</div>
+	<?php
+
+	outputMainFooter();
+	
+	
+
+/*********************************************************************
+	FUNCTIONS
+*********************************************************************/
+
+/**
+* Output the search form
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+*/
+function printSearchForm()
+{
+	global $cgi_path;
+	global $conn;
+
+	// name	
+	if (isset($_POST["name_criteria"]))
+	{
+		$name_display = "table-row";
+		$name_checked = "checked";
+	}
+	else
+	{
+		$name_display = "none";
+		$name_checked = "";
+	}
+	
+	// supplier
+	if (isset($_POST["supplier_criteria"]))
+	{
+		$supplier_display = "table-row";
+		$supplier_checked = "checked";
+		$post_supplier = $_POST["supplier"];
+	}
+	else
+	{
+		$supplier_display = "none";
+		$supplier_checked = "";
+		$post_supplier = "";
+	}
+	
+	
+	// CAS no.
+	if (isset($_POST["cas_criteria"]))
+	{
+		$cas_display = "table-row";
+		$cas_checked = "checked";
+		$post_cas = $_POST["cas_no"];
+	}
+	else
+	{
+		$cas_display = "none";
+		$cas_checked = "";
+		$post_cas = "";
+	}
+
+	?>
+		<FORM NAME="search_chemicals_form" METHOD="POST" ACTION="<?php echo $_SERVER["PHP_SELF"] . "?View=1"; ?>">
+
+			<TABLE width="100%" cellpadding="5" cellspacing="5" border="0">
+			
+				<TH colspan="3" style="color:#0000FF; border-top:1px groove black; border-bottom: 1px groove black; padding-top: 10px; padding-top:5px;">
+					SEARCH CHEMICALS
+				</TH>
+
+				<TR>
+					<TD colspan="3">
+						<P><P>Search chemical by:     
+					
+						<SELECT ID="search_criteria_list" NAME="search_criteria" onChange="showChemicalLocationList(); showSafetySearchForm();">
+							<OPTION NAME="default" VALUE="default">All</OPTION>
+							<OPTION NAME="name_criteria">Chemical Name</OPTION>
+							<OPTION NAME="cas_criteria">CAS Number</OPTION>
+							<OPTION NAME="supplier_criteria">Supplier</OPTION>
+							<OPTION NAME="location_criteria">Location</OPTION>
+							<OPTION NAME="safety_criteria">Safety</OPTION>
+						</SELECT>
+					</TD>
+				</TR>
+
+
+				<TR>
+					<TD ID="chem_search_caption" style="width:120px; white-space:nowrap; vertical-align:top;">
+						Enter search keyword:
+					</TD>
+
+					<TD>					
+						<INPUT TYPE="TEXT" SIZE="40" ID="chem_search_keyword" NAME="chemSearchKeyword" VALUE="<?php echo $_POST["chemSearchKeyword"]; ?>">
+
+						<SELECT ID="chemical_locations" NAME="chemLocType" style="font-size:10pt; display:none">
+							<OPTION VALUE="default"> -- Select Location -- </OPTION>
+						<?php
+							$locations_rs = mysql_query("SELECT chemLocNameID, chemicalLocationName FROM ChemicalLocationNames_tbl ORDER BY chemicalLocationName", $conn) or die("Could not select chemical location: " . mysql_error());
+	
+							while ($locations_ar = mysql_fetch_array($locations_rs, MYSQL_ASSOC))
+							{
+								$chemLocID = $locations_ar["chemLocNameID"];
+								$chemLocName = $locations_ar["chemicalLocationName"];
+							
+								echo "<OPTION VALUE=\"" . $chemLocID . "\">" . $chemLocName . "</OPTION>";
+							}
+						?>
+						</SELECT>
+					
+						<SELECT ID="safety_search" name="safety[]" SIZE="15" style="display:none;" MULTIPLE>
+							<OPTION VALUE="A - Compressed Gas">A - Compressed Gas</OPTION>
+							<OPTION VALUE="B1 - Flammable Gas">B1 - Flammable Gas</OPTION>
+							<OPTION VALUE="B2 - Flammable Liquid">B2 - Flammable Liquid</OPTION>
+							<OPTION VALUE="B3 - Combustible Liquid">B3 - Combustible Liquid</OPTION>
+							<OPTION VALUE="B4 - Flammable Solid">B4 - Flammable Solid</OPTION>
+							<OPTION VALUE="B5 - Flammable Aerosol">B5 - Flammable Aerosol</OPTION>
+							<OPTION VALUE="B6 - Reactive Flammable">B6 - Reactive Flammable</OPTION>
+							<OPTION VALUE="C - Oxidizing">C - Oxidizing</OPTION>
+							<OPTION VALUE="D1A - Immediate Very Toxic">D1A - Immediate, Very Toxic</OPTION>
+							<OPTION VALUE="D1B - Immediate Toxic">D1B - Immediate, Toxic</OPTION>
+							<OPTION VALUE="D2A - Other Very Toxic">D2A - Other, Very Toxic</OPTION>
+							<OPTION VALUE="D2B - Other Toxic">D2B - Other, Toxic</OPTION>
+							<OPTION VALUE="E - Corrosive">E - Corrosive</OPTION>
+							<OPTION VALUE="F - Dangerously Reactive">F - Dangerously Reactive</OPTION>
+							<OPTION VALUE="Non-Controlled">Non-Controlled</OPTION>
+						</SELECT>
+					</TD>
+				</TR>
+
+				<TR>
+					<TD colspan="3">
+						<INPUT TYPE="SUBMIT" NAME="search_chemical" VALUE="Search">
+					</TD>
+				</TR>
+			</TABLE>
+		</FORM>
+	<?php
+}
+
+/**
+* Perform the search function based on the search form input (search criteria selection and keyword/s)
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+*
+* @return resultset
+*/
+function findChemical()
+{
+	global $conn;
+	
+	$chemResults = array();
+	$chemical = null;
+	
+	$keyword = $_POST["chemSearchKeyword"];
+
+	$chemDescription = "";
+	$locationDescr = "";
+
+	// Determine if any search attributes have been set
+	switch ($_POST["search_criteria"])
+	{
+		case 'Safety':
+		break;
+
+		case 'Chemical Name':
+			$keyword = $_POST["chemSearchKeyword"];
+			
+			$query = "SELECT c.chemListID, cn.chemicalName, cn.CAS_No, c.Quantity, g.comment as supplier, g2.comment as Comment, c.Safety as Safety, c.MSDS, g4.comment as locationComments, cln.chemicalLocationName as chemLocName, t.chemLocTypeName FROM ChemicalNames_tbl cn, Chemicals_tbl c, ChemicalLocations_tbl l, ChemicalLocationNames_tbl cln, ChemicalLocationTypes_tbl t, GeneralComments_tbl g, GeneralComments_tbl g2, GeneralComments_tbl g4 WHERE  l.chemLocName=cln.chemLocNameID AND cn.chemical [...]
+		break;
+
+		case 'CAS Number':
+			$keyword = $_POST["chemSearchKeyword"];
+			
+			$query = "SELECT c.chemListID, cn.chemicalName, cn.CAS_No, c.Quantity, g.comment as supplier, g2.comment as Comment, c.Safety as Safety, c.MSDS, g4.comment as locationComments, cln.chemicalLocationName as chemLocName, t.chemLocTypeName FROM ChemicalNames_tbl cn, Chemicals_tbl c, ChemicalLocations_tbl l, ChemicalLocationNames_tbl cln, ChemicalLocationTypes_tbl t, GeneralComments_tbl g, GeneralComments_tbl g2, GeneralComments_tbl g4 WHERE l.chemLocName=cln.chemLocNameID AND cn.CAS_No LI [...]
+
+		break;
+
+		case 'Supplier':
+			$keyword = $_POST["chemSearchKeyword"];
+			
+			$query = "SELECT c.chemListID, cn.chemicalName, cn.CAS_No, c.Quantity, g.comment as supplier, g2.comment as Comment, c.Safety as Safety, c.MSDS, g4.comment as locationComments, cln.chemicalLocationName as chemLocName, t.chemLocTypeName FROM ChemicalNames_tbl cn, Chemicals_tbl c, ChemicalLocations_tbl l, ChemicalLocationTypes_tbl t, ChemicalLocationNames_tbl cln, GeneralComments_tbl g, GeneralComments_tbl g2, GeneralComments_tbl g4 WHERE l.chemLocName=cln.chemLocNameID AND g.comment LI [...]
+
+		break;
+
+		case 'Location':
+
+			$chemLocID = $_POST["chemLocType"];
+			
+			$query = "SELECT c.chemListID, cn.chemicalName, cn.CAS_No, c.Quantity, g.comment as supplier, g2.comment as Comment, c.Safety as Safety, c.MSDS, g4.comment as locationComments, cln.chemicalLocationName as chemLocName, t.chemLocTypeName FROM ChemicalNames_tbl cn, Chemicals_tbl c, ChemicalLocations_tbl l, ChemicalLocationTypes_tbl t, ChemicalLocationNames_tbl cln, GeneralComments_tbl g, GeneralComments_tbl g2, GeneralComments_tbl g4 WHERE l.chemLocName=cln.chemLocNameID AND cln.chemLocN [...]
+
+		break;
+
+		default:
+			$keyword = $_POST["chemSearchKeyword"];
+
+			$query = "(SELECT c.chemListID, cn.chemicalName, cn.CAS_No, c.Quantity, g.comment as supplier, g2.comment as Comment, c.Safety as Safety, c.MSDS, g4.comment as locationComments, cln.chemicalLocationName as chemLocName, t.chemLocTypeName FROM ChemicalNames_tbl cn, Chemicals_tbl c, ChemicalLocations_tbl l, ChemicalLocationNames_tbl cln, ChemicalLocationTypes_tbl t, GeneralComments_tbl g, GeneralComments_tbl g2, GeneralComments_tbl g4 WHERE l.chemLocName=cln.chemLocNameID AND cn.`chemica [...]
+
+		break;
+	}
+
+	if ($_POST["search_criteria"] != "Safety")
+	{
+		$searchResultSet = mysql_query($query, $conn) or die("Could not find chemicals: " . mysql_error());
+
+		while ($results_ar = mysql_fetch_array($searchResultSet, MYSQL_ASSOC))
+		{
+			//print_r($results_ar);
+
+			$chemName = $results_ar["chemicalName"];
+			//print $chemName . " ";
+
+			$chemListID = $results_ar["chemListID"];	// Jan. 19, 2011
+			$casNo = $results_ar["CAS_No"];
+			$quantity = $results_ar["Quantity"];
+			$supplier = $results_ar["supplier"];
+			$safety = $results_ar["Safety"];
+			$msds = $results_ar["MSDS"];
+			//print $safety . "<BR>";
+
+			$comments = $results_ar["Comment"];
+
+			$locationDescr = $results_ar["locationComments"];	// Jan. 20, 2011
+
+			$locationType = $results_ar["chemLocName"];	// flammable, acid, organic, etc.
+			$locationTemp = $results_ar["chemLocTypeName"];	// 4C, -20C, room temp.
+
+			$tmpLocation = new ChemicalLocation($locationType, $locationTemp, $locationDescr);
+
+			$chemical = new Chemical($chemName, $casNo, $tmpLocation, $supplier, $quantity, $safety, $chemDescription, $comments, $msds, $chemListID);
+
+			$chemResults[] = $chemical;
+		}
+	}
+	else
+	{
+		$keyword = $_POST["safety"];		// array, because list is multiple
+		
+		$kwd = "";
+
+		foreach ($keyword as $k => $val)
+		{
+			$kwd = "'" . $val . "'";
+
+			$query = "SELECT c.chemListID, cn.chemicalName, cn.CAS_No, c.Quantity, g.comment as supplier, g2.comment as Comment, c.Safety as Safety, c.MSDS, g4.comment as locationComments, cln.chemicalLocationName as chemLocName, t.chemLocTypeName FROM ChemicalNames_tbl cn, Chemicals_tbl c, ChemicalLocations_tbl l, ChemicalLocationTypes_tbl t, ChemicalLocationNames_tbl cln, GeneralComments_tbl g, GeneralComments_tbl g2, GeneralComments_tbl g4 WHERE l.chemLocName=cln.chemLocNameID AND FIND_IN_SET( [...]
+
+			$searchResultSet = mysql_query($query, $conn) or die("Could not find chemicals: " . mysql_error());
+
+			while ($results_ar = mysql_fetch_array($searchResultSet, MYSQL_ASSOC))
+			{
+				//print_r($results_ar);
+
+				$chemName = $results_ar["chemicalName"];
+				//print $chemName . " ";
+
+				$chemListID = $results_ar["chemListID"];	// Jan. 19, 2011
+				$casNo = $results_ar["CAS_No"];
+				$quantity = $results_ar["Quantity"];
+				$supplier = $results_ar["supplier"];
+				$safety = $results_ar["Safety"];
+				//print $safety . "<BR>";
+				$msds = $results_ar["MSDS"];
+
+				$comments = $results_ar["Comment"];
+
+				$locationDescr = $results_ar["locationComments"];	// Jan. 20, 2011
+
+				$locationType = $results_ar["chemLocName"];	// flammable, acid, organic, etc.
+				$locationTemp = $results_ar["chemLocTypeName"];	// 4C, -20C, room temp.
+
+				$tmpLocation = new ChemicalLocation($locationType, $locationTemp, $locationDescr);
+
+				$chemical = new Chemical($chemName, $casNo, $tmpLocation, $supplier, $quantity, $safety, $chemDescription, $comments, $msds, $chemListID);
+
+				$chemResults[$chemListID] = $chemical;
+			}
+
+			// remove duplicates, so that a chemical that's both Toxic and Biohazard is not printed twice
+			$chemResults = array_unique($chemResults);
+		}
+	}
+
+	mysql_free_result($searchResultSet);
+
+	return $chemResults;
+}
+
+
+/**
+* Output search results
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+*
+* @param $resultset
+*/
+function printChemicalSearchResults($results)
+{
+	echo "Found " . sizeof($results) . " chemicals matching your search query:";
+	
+	if (sizeof($results) > 0)
+		echo "<span class=\"linkShow\" style=\"margin-left:10px; font-size:9pt; font-weight:bold;\" onclick=\"document.exportChemSearchResults.submit();\">Download</span>";
+	
+	$outputContent = "";
+
+	echo "<BR>";
+	
+	if (sizeof($results) > 0)
+	{
+		echo "<P><TABLE width=\"100%\" class=\"preview\">";
+	
+		// print header row
+		echo "<th class=\"searchHeader\">Chemical Name</th>";
+		echo "<th class=\"searchHeader\" style=\"width:80px;\">CAS Number</th>";
+		echo "<th class=\"searchHeader\" style=\"width:80px;\">Location Name/<BR>Room Number</th>";
+		echo "<th class=\"searchHeader\" style=\"width:80px;\">Storage Type/<BR>Temperature</th>";
+//		echo "<th class=\"searchHeader\" style=\"width:80px;\">Location Comments</th>";
+		echo "<th class=\"searchHeader\">Supplier</th>";
+		echo "<th class=\"searchHeader\" style=\"width:40px;\">WHMIS</th>";
+		echo "<th class=\"searchHeader\" style=\"width:40px;\">MSDS</th>";
+		echo "<th class=\"searchHeader\">Comments</th>";
+		echo "<th class=\"searchHeader\" style=\"width:50px;\">Quantity</th>";
+
+		$outputContent = "Chemical Name\tCAS Number\tLocation Name/Room Number\tStorage Type/Temperature\tWHMIS\tMSDS\tComments\tQuantity\r";
+	
+		foreach ($results as $key => $tmpChemical)
+		{
+			$tmpChemName = $tmpChemical->getName();
+			$tmpCAS_No = $tmpChemical->getCAS_No();
+			$tmpSafety = $tmpChemical->getSafety();
+			$tmpQty = $tmpChemical->getQuantity();
+			$tmpDescr = $tmpChemical->getDescription();
+			$tmpSupplier = $tmpChemical->getSupplier();
+			$tmpLocation = $tmpChemical->getLocation();			
+			$tmpComments = $tmpChemical->getComments();
+			$tmpLocComms = $tmpLocation->getDescription();
+			$tmpChemID = $tmpChemical->getChemicalID();
+			$msds = $tmpChemical->getMSDS();
+
+			// June 17, 2011: Final change to safety (for now) :)
+			$tmpSafety_ar = explode(",", $tmpSafety);
+//			print_r($tmpSafety_ar);
+			$safetyClassifier = "";
+			$safetyVal = "";
+
+			foreach ($tmpSafety_ar as $sKey => $sVal)
+			{
+				// get the classification letter
+				$tmp_class_ar = explode(" - ", $sVal);
+				$safetyClassifier = $tmp_class_ar[0];
+//				$safetyVal .= $safetyClassifier . "<BR>";
+				$safetyVal .= $safetyClassifier . ", ";
+			}
+
+			// remove last comma
+			$safetyVal = rtrim($safetyVal, ", ");
+
+			?>
+			<TR>
+				<TD class="preview">
+				<?php
+					 echo $tmpChemName;
+				?>
+				</TD>
+
+
+				<TD class="preview">
+				<?php
+					 echo $tmpCAS_No;
+				?>
+				</TD>
+
+				<TD class="preview">
+				<?php
+					 echo $tmpLocation->printLocation();
+				?>
+				</TD>
+
+				<!-- Storage type (temperature) -->
+				<TD class="preview">
+				<?php
+					 echo $tmpLocation->getTemperature();
+				?>
+				</TD>
+
+				<!-- <TD class="preview">
+				<?php
+					 echo $tmpLocComms;
+				?>
+				</TD> -->
+
+				<TD class="preview">
+				<?php
+					 echo $tmpSupplier;
+				?>
+				</TD>
+
+				<TD class="preview" style="padding-left:2px;">
+				<?php
+					 //echo $tmpSafety;
+					echo $safetyVal;
+				?>
+				</TD>
+
+				<TD class="preview" style="padding-left:5px; padding-right:5px;">
+				<?php
+					if ($msds && ($msds != ""))
+						echo "<a target=\"new\" href=\"" . $msds . "\">MSDS</a>";
+					else
+						echo "";
+				?>
+				</TD>
+
+				<TD class="preview">
+				<?php
+					 echo $tmpComments;
+				?>
+				</TD>
+
+				<TD class="preview">
+				<?php
+					 echo $tmpQty;
+				?>
+				</TD>
+				
+				<td>
+					<a class="search" href="Chemical.php?View=3&chemicalID=<?php echo $tmpChemID; ?>">Details</a></td>
+				</td>
+
+			</TR>
+			<?php
+
+			$tmpLocName = $tmpLocation->getName();
+			$tmpLocType = $tmpLocation->getTemperature();
+
+			$outputContent .= $tmpChemName . "\t" . $tmpCAS_No . "\t" . $tmpLocName ."\t" . $tmpLocType . "\t" . $safetyVal . "\t" . $msds . "\t" . $tmpComments . "\t" . $tmpQty . "\n";
+		}
+
+//	echo $outputContent;
+
+	?>
+	</TABLE>
+	<?php
+
+		echo "<FORM style=\"display:none;\" NAME=\"exportChemSearchResults\" METHOD=\"POST\" ACTION=\"exportChemical.php\">";
+		echo "<INPUT TYPE=\"hidden\" NAME=\"outputContent\" VALUE=\"" . $outputContent . "\">";
+		echo "</FORM>";
+	}
+}
+
+/**
+* Output form to input chemicals
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+*/
+function printCreationForm()
+{
+	global $conn;
+
+	?>
+	<FORM NAME="search_chemicals_form" METHOD="POST" ACTION="<?php echo $_SERVER["PHP_SELF"] . "?View=2"; ?>" onSubmit="return checkChemicalCreation();">
+	
+		<TABLE frame="box" rules="all" style="margin-left:5px" width="99%">
+			<TH colspan="2" style="padding-top:5px; text-align:center;">
+				<span style="color:#0000FF; margin-top:5px;">ADD CHEMICALS</span>
+				<P style="color:#FF0000; font-weight:normal; font-size:8pt; margin-top:5px;">Fields in red marked with an asterisk (<span style="font-size:9pt; color:#FF0000;">*</span>) are mandatory</P>
+			</TH>
+
+			<TR>
+				<TD style="white-space:nowrap; font-weight:bold; padding-left:5px; padding-top:2px; padding-bottom:2px;">
+					Chemical Name: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+				</TD>
+
+				<TD style="padding-left:10px;" colspan="2">
+					<INPUT TYPE="TEXT" SIZE="35" ID="chemical_name" NAME="chemName">  
+				</TD>
+			</TR>
+
+			<TR>
+				<TD style="font-weight:bold; padding-left:5px;">
+					CAS Number:
+				</TD>
+
+				<TD style="padding-left:10px; padding-top:2px; padding-bottom:2px;" colspan="2">
+					<INPUT TYPE="TEXT" SIZE="10" NAME="cas_no">  
+				</TD>
+			</TR>
+			<?php
+				// Jan. 22, 2011: changing database structure, unlinking chemical location names from temperature
+				$locationNames_rs = mysql_query("SELECT chemLocNameID, chemicalLocationName FROM ChemicalLocationNames_tbl ORDER BY chemicalLocationName", $conn) or die("Could not select chemical location: " . mysql_error());
+				
+				// change Jan. 22, 2011
+				//$locations_rs = mysql_query("SELECT chemLocID, chemLocName FROM ChemicalLocations_tbl ORDER BY chemLocName", $conn) or die("Could not select chemical location: " . mysql_error());
+
+				// replaced Jan. 22, 2011:
+				$locations_rs = mysql_query("SELECT cl.chemLocID, cn.chemLocNameID, cn.chemicalLocationName AS chemLocName, ct.chemLocTypeName FROM ChemicalLocations_tbl cl, ChemicalLocationTypes_tbl ct, ChemicalLocationNames_tbl cn WHERE cn.status='ACTIVE' AND ct.status='ACTIVE' AND cl.status='ACTIVE' AND cl.chemLocType=ct.chemLocTypeID AND cl.chemLocName=cn.chemLocNameID ORDER BY chemLocName", $conn) or die("Could not select chemical location: " . mysql_error());
+			
+				$locNames = Array();
+			?>
+			<TR>
+				<TD style="font-weight:bold; padding-left:5px;">
+					Chemical Location: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+				</TD>
+
+				<TD style="padding-left:10px;" colspan="2">
+					<SELECT ID="chemical_locations" NAME="chemLocType" style="font-size:10pt;" onChange="showHideAddLocation();">
+						<OPTION VALUE="default"> -- Select Location Name -- </OPTION><?php
+
+						while ($locations_ar = mysql_fetch_array($locations_rs, MYSQL_ASSOC))
+						{
+							$chemLocID = $locations_ar["chemLocID"];
+//							$chemLocName = $locations_ar["chemLocName"];
+							$chemLocName = $locations_ar["chemLocName"] . " " . $locations_ar["chemLocTypeName"];
+							
+							$chemLocNameID = $locations_ar["chemLocNameID"];
+							$locNames[$chemLocNameID] = $locations_ar["chemLocName"];
+
+							echo "<OPTION VALUE=\"" . $chemLocID . "\">" . $chemLocName . "</OPTION>";
+						}
+
+						?>
+						<OPTION VALUE="addChemLoc">or, ADD NEW LOCATION</OPTION>
+					</SELECT>
+
+					<DIV ID="add_chem_loc" style="display:none; font-size:9pt; font-weight:bold; padding-top:5px; width:100%;">
+						<table border="0" style="padding-top:10px;">
+							<!-- <th style="text-align:left;">Select an existing location name from the list, or add your own:</th> -->
+							<tr>
+								<td style="font-weight:bold; padding-left:3px;">Storage Name/Room Number: <sup style="font-size:10pt; color:#FF0000;">*</sup></td>
+								<td style="padding-left:10px;">
+									<SELECT ID="existingLocationNamesList" NAME="newChemLocNameList" style="font-size:10pt;" onChange="if (this.options[options.selectedIndex].value == 'Other') document.getElementById('new_chem_loc_name').style.display=''; else document.getElementById('new_chem_loc_name').style.display='none';">
+										<OPTION VALUE="default"> -- Select -- </OPTION><?php
+
+										foreach ($locNames as $key => $value)
+										{
+											echo "<OPTION VALUE=\"" . $value . "\">" . $value . "</OPTION>";
+										}
+
+										?>
+										<OPTION VALUE="Other">ADD NEW</OPTION>
+									</SELECT>
+										
+									<!-- , or add new storage name / room number:  -->
+									<BR><INPUT TYPE="TEXT" ID="new_chem_loc_name" NAME="newChemLocName" SIZE="35" style="display:none;">
+									<input type="hidden" id="addLocName">
+								</td>
+							</tr>
+
+							<TR>
+								<TD style="font-weight:bold; padding-left:3px;">
+									Storage Type/Temperature: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+								</TD>
+
+								<TD style="padding-left:10px;">
+									<input type="hidden" id="addLocType">
+										<!-- do a selection again and output list, if available -->
+									<?php
+
+									$locTypes_rs = mysql_query("SELECT chemLocTypeID, chemLocTypeName FROM ChemicalLocationTypes_tbl WHERE status='ACTIVE'", $conn) or die("Could not select chemical location types: " . mysql_error());
+
+									?><SELECT NAME="newChemLocTypeList" ID="chem_loc_type_list" style="font-size:10pt;" onChange="showHideAddLocType();" DISABLED>
+										<OPTION VALUE="default"> -- Select Storage Type/Temperature -- </OPTION><?php
+
+											while ($locTypes_ar = mysql_fetch_array($locTypes_rs, MYSQL_ASSOC))
+											{
+												$chemLocTypeID = $locTypes_ar["chemLocTypeID"];
+												$chemLocTypeName = $locTypes_ar["chemLocTypeName"];
+						
+												echo "<OPTION VALUE=\"" . $chemLocTypeID . "\">" . $chemLocTypeName . "</OPTION>";
+											}
+										?>
+										<OPTION VALUE="addChemLocType">or, ADD NEW STORAGE TYPE/TEMPERATURE</OPTION>
+									</SELECT>
+
+									<DIV ID="add_chem_loc_type" style="display:none; font-size:9pt; font-weight:bold; padding-top:5px;">
+										<BR>Location Type:  
+										<INPUT TYPE="TEXT" ID="new_chem_loc_type" NAME="newChemLocType" SIZE="35">
+										<input type="hidden" id="addLocType">
+									</DIV>
+								</TD>
+							</TR>
+
+							<TR>
+								<TD style="white-space:nowrap; font-weight:bold; padding-left:5px;">
+									Location Comments:
+								</TD>
+
+								<TD style="padding-left:10px;">
+									<INPUT TYPE="TEXT" SIZE="75" NAME="locComms">  
+								</TD>
+							</TR>
+						</table>
+					</DIV>
+				</TD>
+			</TR>
+
+			<TR>
+				<TD style="font-weight:bold; padding-left:5px;">
+					Supplier:
+				</TD>
+
+				<TD style="padding-left:10px; padding-top:2px; padding-bottom:2px;" colspan="2">
+					<INPUT TYPE="TEXT" SIZE="10" NAME="supplier">  
+				</TD>
+			</TR>
+
+			<TR>
+				<TD style="font-weight:bold; padding-left:5px;">
+					Comments:
+				</TD>
+
+				<TD style="padding-left:10px; padding-top:2px; padding-bottom:2px;" colspan="2">
+					<INPUT TYPE="TEXT" SIZE="28" NAME="comments">  
+				</TD>
+			</TR>
+
+			<TR>
+				<TD style="font-weight:bold; padding-left:5px;">
+					MSDS/Supplier Link:
+				</TD>
+
+				<TD style="padding-left:10px; padding-top:2px; padding-bottom:2px;" colspan="2">
+					<INPUT TYPE="TEXT" SIZE="28" NAME="msds">  
+					<IMG SRC="pictures/link5.png" WIDTH="18" HEIGHT="8" onmouseover="return overlib('Please enter a complete URL in the textbox, e.g. http://www.mysite.com', CAPTION, 'MSDS/Supplier Link', STICKY);">
+				</TD>
+			</TR>
+
+			<TR>
+				<TD style="font-weight:bold; padding-left:7px; text-align:left; width:175px;">
+					Safety - WHMIS Classification:<BR><P>
+					<a href="pictures/whmis/classificiation_system.pdf" style="margin-left:2px;" target="new">What's this?</a>
+				</TD>
+
+				<TD style="padding-left:10px; padding-right:10px; border-right:0px; padding-top:5px; padding-bottom:5px;">
+					<!-- <INPUT TYPE="TEXT" SIZE="75" NAME="safety">   -->
+
+					<SELECT name="safety_add[]" SIZE="15" MULTIPLE style="margin-top:10px; margin-bottom:10px;">
+						<OPTION VALUE="A - Compressed Gas">A - Compressed Gas</OPTION>
+						<OPTION VALUE="B1 - Flammable Gas">B1 - Flammable Gas</OPTION>
+						<OPTION VALUE="B2 - Flammable Liquid">B2 - Flammable Liquid</OPTION>
+						<OPTION VALUE="B3 - Combustible Liquid">B3 - Combustible Liquid</OPTION>
+						<OPTION VALUE="B4 - Flammable Solid">B4 - Flammable Solid</OPTION>
+						<OPTION VALUE="B5 - Flammable Aerosol">B5 - Flammable Aerosol</OPTION>
+						<OPTION VALUE="B6 - Reactive Flammable">B6 - Reactive Flammable</OPTION>
+						<OPTION VALUE="C - Oxidizing">C - Oxidizing</OPTION>
+						<OPTION VALUE="D1A - Immediate Very Toxic">D1A - Immediate, Very Toxic</OPTION>
+						<OPTION VALUE="D1B - Immediate Toxic">D1B - Immediate, Toxic</OPTION>
+						<OPTION VALUE="D2A - Other Very Toxic">D2A - Other, Very Toxic</OPTION>
+						<OPTION VALUE="D2B - Other Toxic">D2B - Other, Toxic</OPTION>
+						<OPTION VALUE="E - Corrosive">E - Corrosive</OPTION>
+						<OPTION VALUE="F - Dangerously Reactive">F - Dangerously Reactive</OPTION>
+						<OPTION VALUE="Non-Controlled">Non-Controlled</OPTION>
+					</SELECT>
+				</TD>
+			</TR>
+
+			<TR>
+				<TD style="font-weight:bold; padding-left:5px;">
+					Quantity:
+				</TD>
+
+				<TD style="padding-left:10px; padding-top:2px; padding-bottom:2px;" colspan="2">
+					<INPUT TYPE="TEXT" SIZE="10" NAME="quantity">  
+				</TD>
+			</TR>
+		</TABLE>
+
+		<P><P><INPUT TYPE="SUBMIT" NAME="add_chemical" VALUE="Submit" style="margin-left:3px;">
+	</FORM>
+	<?php
+}
+
+
+/**
+* Process request to add chemicals
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+*
+* @return resultset
+*/
+function addChemical()
+{
+	global $conn;
+
+	// mandatory fields
+	$chemName = "";
+	$chemLocType = "";
+
+	$casNo = "";
+	$locComms = "";
+	$supplier = "";
+	$safety = "";
+	$chemComms = "";
+	$qty = "";
+
+	// 'Chemical' comment link ID
+	$chemCommLink_rs = mysql_query("SELECT commentLinkID FROM CommentLink_tbl WHERE link='Chemical'", $conn) or die ("Error selecting chemical comment link: " . mysql_error());
+	$chemComm_row = mysql_fetch_row($chemCommLink_rs);
+
+	$chemCommLinkID = $chemComm_row[0];
+
+//	echo $chemCommLinkID;
+//	print_r($_POST);
+
+	if (isset($_POST["chemName"]))		// better be set
+		$chemName = $_POST["chemName"];
+
+	// June 16, 2011
+	if (isset($_POST["msds"]))
+		$msds = $_POST["msds"];
+
+	if (isset($_POST["chemLocType"]))
+	{
+		if ($_POST["chemLocType"] == "addChemLoc")
+		{		
+			// Adding new location; check type first
+			if ($_POST["newChemLocTypeList"] == "addChemLocType")
+			{
+				if (isset($_POST["newChemLocType"]))
+				{
+					$chemLocTypeName = $_POST["newChemLocType"];
+			
+					// CHECK EXISTENCE
+					$chemLocTypes = mysql_query("SELECT chemLocTypeID FROM ChemicalLocationTypes_tbl WHERE chemLocTypeName='" . $chemLocTypeName . "' AND status='ACTIVE'", $conn) or die("Cannot select chemical location type: " . mysql_error());
+			
+					if ($chemLocTypeRow = mysql_fetch_row($chemLocTypes))
+					{
+						$chemLocTypeID = $chemLocTypeRow[0];
+					}
+					else
+					{
+						mysql_query("INSERT INTO ChemicalLocationTypes_tbl(chemLocTypeName) VALUES('" . $chemLocTypeName . "')");
+						$chemLocTypeID = mysql_insert_id();
+					}
+				}
+			}
+			else
+			{
+				$chemLocTypeID = $_POST["newChemLocTypeList"];
+			}
+
+			// create new ChemicalLocations_tbl entry
+			$newChemLocName = null;
+
+			if (isset($_POST["newChemLocName"]) && ($_POST["newChemLocName"] != ""))
+			{
+				$newChemLocName = $_POST["newChemLocName"];
+			}
+			else if (isset($_POST["newChemLocNameList"]) && ($_POST["newChemLocNameList"] != ""))
+			{
+				$newChemLocName = $_POST["newChemLocNameList"];
+			}
+
+			if ($newChemLocName != "")
+			{
+				// Jan. 21, 2011: grab location comments
+			//	print_r($_POST);
+				$newLocComms = $_POST["locComms"];
+				
+				// find their ID
+				$comms_rs = mysql_query("SELECT commentID FROM GeneralComments_tbl WHERE commentLinKID='" . $chemCommLinkID . "' AND comment='" . $newLocComms . "' AND status='ACTIVE'", $conn) or die("Cannot select location comments: " . mysql_error());
+
+				$comms_ar = mysql_fetch_row($comms_rs);
+
+				if ($comms_ar)
+					$locCommID = $comms_ar[0];
+				else
+				{
+					// if not found, create an empty comment with 'Chemical' identifier
+					mysql_query("INSERT INTO GeneralComments_tbl(commentLinkID, comment) VALUES('" . $chemCommLinkID . "', '" . $newLocComms . "')");
+					$locCommID = mysql_insert_id();
+				}	
+
+				// check if location exists; user might unknowingly enter 'MS shelf' again
+				// Jan. 22, 2011: changed database structure
+				$chemLocNameSet = mysql_query("SELECT chemLocNameID FROM ChemicalLocationNames_tbl WHERE chemicalLocationName='" . $newChemLocName . "' AND status='ACTIVE'", $conn) or die("Could not select chemical location: " . mysql_error());
+
+				if ($chemLocName_row = mysql_fetch_row($chemLocNameSet))
+				{
+					$chemLocNameID = $chemLocName_row[0];
+
+					$chemLocSet = mysql_query("SELECT chemLocID FROM ChemicalLocations_tbl WHERE chemLocName='" . $chemLocNameID . "' AND chemLocType='" . $chemLocTypeID . "' AND status='ACTIVE'", $conn) or die("Could not select chemical location: " . mysql_error());
+	
+					if ($chemLoc_row = mysql_fetch_row($chemLocSet))
+					{
+						$chemLocID = $chemLoc_row[0];
+					}
+					else
+					{
+						mysql_query("INSERT INTO ChemicalLocations_tbl(chemLocName, chemLocType) VALUES('" . $chemLocNameID . "', '" . $chemLocTypeID . "')", $conn) or die("Cannot insert chemical: " . mysql_error());
+						$chemLocID = mysql_insert_id();
+					}
+				}
+				else
+				{
+					// create new entry
+					mysql_query("INSERT INTO ChemicalLocationNames_tbl(chemicalLocationName) VALUES('" . $newChemLocName . "')");
+					$chemLocNameID = mysql_insert_id();
+
+					mysql_query("INSERT INTO ChemicalLocations_tbl(chemLocName, chemLocType) VALUES('" . $chemLocNameID . "', '" . $chemLocTypeID . "')", $conn) or die("Cannot insert chemical: " . mysql_error());
+					$chemLocID = mysql_insert_id();
+				}
+
+				// Just update its comments, period:
+				mysql_query("UPDATE ChemicalLocations_tbl SET chemLocComments='" . $locCommID . "' WHERE chemLocID='" . $chemLocID . "'");
+			}
+		}
+		else
+		{
+			// existing location - THIS IS WHERE IT FAILS
+			$chemLocID = $_POST["chemLocType"];		// correction Jan. 4, 2011
+
+			// Look in the database to see if the selected location has comments (it better)
+			$locComm_rs = mysql_query("SELECT commentID FROM GeneralComments_tbl WHERE commentLinkID='" . $chemCommLinkID . "' AND comment='" . $locComms . "' AND status='ACTIVE'", $conn) or die("Cannot select location comment: " . mysql_error());
+		
+			if ($row = mysql_fetch_row($locComm_rs))
+			{
+				$locCommID = $row[0];
+			}
+			else
+			{
+				echo "ever here??";
+			}
+		}
+	}
+
+	if (isset($_POST["cas_no"]))
+		$casNo = $_POST["cas_no"];
+
+	if (isset($_POST["locComms"]))
+		$locComms = $_POST["locComms"];
+
+	if (isset($_POST["supplier"]))
+		$supplier = $_POST["supplier"];
+
+	if (isset($_POST["safety_add"]))
+		$safety = $_POST["safety_add"];
+
+//	print_r($safety);
+	
+	if (isset($_POST["comments"]))
+		$chemComms = $_POST["comments"];
+
+	if (isset($_POST["quantity"]))
+		$qty = $_POST["quantity"];
+
+	// Find out whether this chemical exists in ChemicalNames_tbl -- Jan. 21, 2011: BUT do a FULL query!!
+	$chem_rs = mysql_query("SELECT chemicalID FROM ChemicalNames_tbl WHERE chemicalName='" . $chemName . "' AND CAS_No='" . $casNo . "' AND status='ACTIVE'", $conn) or die("Cannot select chemical : " . mysql_error());
+
+	if ($chemRow = mysql_fetch_row($chem_rs))
+	{
+		$chemID = $chemRow[0];
+	}
+	else
+	{
+		// create new entry
+		mysql_query("INSERT INTO ChemicalNames_tbl(chemicalName, CAS_No) VALUES('" . $chemName . "', '" . $casNo . "')", $conn) or die("Cannot insert chemical: " . mysql_error());
+		$chemID = mysql_insert_id();
+	}
+
+	// Create GeneralComments_tbl entries for chemical comments, location comments, supplier and safety IFF non-empty
+	if (sizeof(trim($chemComms)) > 0)
+	{
+		$chemComm_rs = mysql_query("SELECT commentID FROM GeneralComments_tbl WHERE commentLinkID='" . $chemCommLinkID . "' AND comment='" . $chemComms . "'", $conn) or die("Cannot select chemical comment: " . mysql_error());
+	
+		if ($row = mysql_fetch_row($chemComm_rs))
+		{
+			$chemCommID = $row[0];
+		}
+		else
+		{
+			$q1 = "INSERT INTO GeneralComments_tbl(commentLinkID, comment) VALUES('" . $chemCommLinkID . "', '" . $chemComms . "')";
+			mysql_query($q1, $conn) or die("Cannot insert chemical comments: " . mysql_error());
+			$chemCommID = mysql_insert_id();
+		}
+	}
+
+/*	if (sizeof(trim($locComms)) > 0)
+	{
+		$locComm_rs = mysql_query("SELECT commentID FROM GeneralComments_tbl WHERE commentLinkID='" . $chemCommLinkID . "' AND comment='" . $locComms . "'", $conn) or die("Cannot select location comment: " . mysql_error());
+	
+		if ($row = mysql_fetch_row($locComm_rs))
+		{
+			$locCommID = $row[0];
+		}
+		else
+		{
+			$q2 = "INSERT INTO GeneralComments_tbl(commentLinkID, comment) VALUES('" . $chemCommLinkID . "', '" . $locComms . "')";
+			mysql_query($q2, $conn) or die("Cannot insert location comments: " . mysql_error());
+			$locCommID = mysql_insert_id();
+		}
+	}*/
+	
+
+	// Update location comments!
+//	mysql_query("UPDATE ChemicalLocations_tbl SET chemLocComments='" . $locCommID . "' WHERE chemLocID='" . $chemLocID . "'");
+
+	if (sizeof(trim($supplier)) > 0)
+	{
+		$supplierComm_rs = mysql_query("SELECT commentID FROM GeneralComments_tbl WHERE commentLinkID='" . $chemCommLinkID . "' AND comment='" . $supplier . "'", $conn) or die("Cannot select location comment: " . mysql_error());
+	
+		if ($row = mysql_fetch_row($supplierComm_rs))
+		{
+			$supplierCommID = $row[0];
+		}
+		else
+		{
+			$q3 = "INSERT INTO GeneralComments_tbl(commentLinkID, comment) VALUES('" . $chemCommLinkID . "', '" . $supplier . "')";
+			mysql_query($q3, $conn) or die("Cannot insert supplier comments: " . mysql_error());
+			$supplierCommID = mysql_insert_id();
+		}
+	}
+
+
+	if (sizeof($safety) > 0)	// array now
+	{
+		/*
+		$safetyComm_rs = mysql_query("SELECT commentID FROM GeneralComments_tbl WHERE commentLinkID='" . $chemCommLinkID . "' AND comment='" . $safety . "'", $conn) or die("Cannot select location comment: " . mysql_error());
+	
+		if ($row = mysql_fetch_row($safetyComm_rs))
+		{
+			$safetyCommID = $row[0];
+		}
+		else
+		{
+			$q3 = "INSERT INTO GeneralComments_tbl(commentLinkID, comment) VALUES('" . $chemCommLinkID . "', '" . $safety . "')";
+			mysql_query($q3, $conn) or die("Cannot insert safety comments: " . mysql_error());
+			$safetyCommID = mysql_insert_id();
+		}
+		*/
+
+		// June 15, 2011: No, not anymore
+		//$safety = $_POST["safety_add"];		// array, because list is multiple
+		$whmis = $_POST["whmis_class"];
+		
+		$safety = implode(",", $safety);
+		$whmis = implode(",", $whmis);
+//print_r($safety);
+	}
+
+	// Jan. 19, 2011: Still, check for existence of chemical with all these credentials (don't want refreshing and having a chemical inserted 10x)
+	$chemSelect_rs = mysql_query("SELECT chemListID FROM Chemicals_tbl WHERE chemicalID='" . $chemID . "' AND chemicalLocation='" . $chemLocID . "' AND Comments='" . $chemCommID . "' AND Quantity='" . $qty . "' AND Supplier='" . $supplierCommID . "' AND Safety='" . $safety . "' AND MSDS='" . $msds . "' AND status='ACTIVE'", $conn) or die("Cannot select chemical: " . mysql_error());
+
+	//echo "SELECT chemListID FROM Chemicals_tbl WHERE chemicalID='" . $chemID . "' AND chemicalLocation='" . $chemLocID . "' AND Comments='" . $chemCommID . "' AND Quantity='" . $qty . "' AND Supplier='" . $supplierCommID . "' AND Safety='" . $safety . "' AND status='ACTIVE'<BR><BR>";
+
+	if ($chem_set = mysql_fetch_row($chemSelect_rs))
+	{
+		return $chem_set[0];
+	}
+	else
+	{
+		$query = "INSERT INTO Chemicals_tbl(chemicalID, chemicalLocation, Comments, Quantity, Supplier, Safety, MSDS) VALUES('" . $chemID . "', '" . $chemLocID . "', '" . $chemCommID . "', '" . $qty . "', '" . $supplierCommID . "', ('" . $safety . "'), '" . $msds . "')";
+
+	//	echo $query;
+
+		$chemInsertResult = mysql_query($query, $conn) or die("Cannot insert chemical: " . mysql_error());
+		$chemListID = intval(mysql_insert_id());
+
+		return $chemListID;
+	}
+}
+
+/**
+* Print details for a selected chemical (output detailed view)
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+*
+* @param INT Database ID of the sought chemical
+*/
+function printChemicalDetails($chemListID)
+{
+	$chemical = createChemical($chemListID);
+
+//	print_r($chemical);
+
+	$chemSymbols = Array();
+	$chemClasses = Array();
+
+	$chemClasses["A - Compressed Gas"] = "Compressed Gas";
+	$chemClasses["B1 - Flammable Gas"] = "Flammable";
+	$chemClasses["B2 - Flammable Liquid"] = "Flammable";
+	$chemClasses["B3 - Combustible Liquid"] = "Flammable";
+	$chemClasses["B4 - Flammable Solid"] = "Flammable";
+	$chemClasses["B5 - Flammable Aerosol"] = "Flammable";
+	$chemClasses["B6 - Reactive Flammable"] = "Flammable";
+	$chemClasses["C - Oxidizing"] = "Oxidizing";
+	$chemClasses["D1A - Immediate Very Toxic"] = "Highly Toxic";
+	$chemClasses["D1B - Immediate Toxic"] = "Highly Toxic";
+	$chemClasses["D2A - Other Very Toxic"] = "Toxic";
+	$chemClasses["D2B - Other Toxic"] = "Toxic";
+	$chemClasses["E - Corrosive"] = "Corrosive";
+	$chemClasses["F - Dangerously Reactive"] = "Reactive";
+
+//	$chemSymbols["Biohazard"] = "pictures/whmis/new_images/biohazard.jpg";		// not for us
+	$chemSymbols["Corrosive"] = "pictures/whmis/new_images/corrosive.jpg";
+	$chemSymbols["Compressed Gas"] = "pictures/whmis/new_images/compressed_gas.jpg";
+	$chemSymbols["Flammable"] = "pictures/whmis/new_images/flammable.jpg";
+	$chemSymbols["Oxidizing"] = "pictures/whmis/new_images/oxidizing.jpg";
+	$chemSymbols["Highly Toxic"] = "pictures/whmis/new_images/poisonous.jpg";
+	$chemSymbols["Reactive"] = "pictures/whmis/new_images/reactive.jpg";
+	$chemSymbols["Toxic"] = "pictures/whmis/new_images/toxic.jpg";
+
+	?>
+	<TABLE width="760px" cellpadding="5" cellspacing="5" border="1" frame="box" rules="none" style="padding-left:5px; vertical-align:middle" name="chem_props" class="detailedView_tbl">
+		<tr>
+			<td class="detailedView_heading" style="white-space:nowrap; color:blue; color:#0000DF; text-align:center;" colspan="2">
+				<?php echo $chemical->getName(); ?> Details Page  
+				<INPUT TYPE="hidden" name="chemicalName" value="<?php echo $chemical->getName(); ?>">
+			</td>
+		</tr>
+
+		<tr>
+			<td style="text-align:center; vertical-align:bottom; white-space:nowrap;" colspan="100%">
+				<?php 
+					$chems = $chemical->getSafety();
+
+					$chemArray = explode(",", $chems);
+					//print_r($chemArray);
+
+					$symbols_uniq = Array();
+
+					foreach ($chemArray as $cKey => $cVal)
+					{
+						$chemClass = $chemClasses[$cVal];
+						$fName = $chemSymbols[$chemClass];
+
+						$symbols_uniq[] = $fName;
+					}
+	
+					$symbols_uniq = array_unique($symbols_uniq);
+
+					foreach ($symbols_uniq as $key => $fSrc)
+					{
+						?><IMG SRC="<?php echo $fSrc; ?>" height="35px" style="cursor:auto;"> <?php
+					}
+				?>
+			</td>
+		</tr>
+
+		<!-- Chemical Name -->
+		<TR>
+			<TD class="detailedView_colName">Chemical Name</TD>
+			<TD class="detailedView_value"><?php echo $chemical->getName(); ?></TD>
+		</TR>
+
+		<!-- Description - MO: not available -->
+		<!-- <TR>
+			<TD class="detailedView_colName">Description</TD>
+			<TD class="detailedView_value"><?php echo $chemical->getDescription(); ?></TD>
+		</TR>-->
+	
+		<!-- CAS No. -->
+		<TR>
+			<TD class="detailedView_colName">CAS Number</TD>
+			<TD class="detailedView_value"><?php echo $chemical->getCAS_No(); ?></TD>
+		</TR>
+
+		<!-- Supplier -->
+		<TR>
+			<TD class="detailedView_colName">Supplier</TD>
+			<TD class="detailedView_value"><?php echo $chemical->getSupplier(); ?></TD>
+		</TR>
+
+		<!-- Comments -->
+		<TR>
+			<TD class="detailedView_colName">Comments</TD>
+			<TD class="detailedView_value"><?php echo $chemical->getComments(); ?></TD>
+		</TR>
+		
+		<!-- Safety - CHANGING, JUNE 15, 2011 -->
+<!--		<TR>
+			<TD class="detailedView_colName">Safety</TD>
+			<TD class="detailedView_value"><?php echo $chemical->getSafety(); ?></TD>
+		</TR> -->
+
+		<!-- Quantity -->
+		<TR>
+			<TD class="detailedView_colName">Quantity</TD>
+			<TD class="detailedView_value"><?php echo $chemical->getQuantity(); ?></TD>
+		</TR>
+
+		<!-- June 15, 2011 -->
+		<TR>
+			<TD colspan="4" class="detailedView_heading" style="text-align:left; padding-right:6px; padding-top:10px; color:#0000DF; font-size:9pt; font-family:Helvetica; white-space:nowrap;">Safety Information</TD>
+		</TR>
+
+		<TR>
+			<TD class="detailedView_colName" style="padding-left:10px;">MSDS / Supplier Link</TD>
+			<TD style="font-weight:bold;">
+				<?php
+					$msds = $chemical->getMSDS();
+
+					echo "<a target=\"new\" href=\"" . $msds . "\">" . $msds . "</a>";
+				?>
+			</TD>
+		</TR>
+
+		<TR>
+			<TD class="detailedView_colName" style="padding-left:10px;">Safety - WHMIS Classification:</TD>
+			<TD style="color:red;"><?php 
+				echo "<UL style=\"padding-left:10px; font-weight:bold; font-size:9pt;\">";
+
+				$chem_ar = explode(",", $chemical->getSafety());
+				//echo str_replace(",", ", ", $chemical->getSafety());
+		
+				foreach ($chem_ar as $cName => $cVal)
+				{
+					switch ($cVal)
+					{
+						case 'D1A - Immediate Very Toxic':
+							echo "<LI>D1A - Immediate, Very Toxic</LI>";
+						break;
+
+						case 'D1B - Immediate Toxic':
+							echo "<LI>D1B - Immediate, Toxic</LI>";
+						break;
+
+						case 'D2A - Other Very Toxic':
+							echo "<LI>D2A - Other, Very Toxic</LI>";
+						break;
+
+						case 'D2B - Other Toxic':
+							echo "<LI>D2B - Other, Toxic</LI>";
+						break;
+
+						default:
+							echo "<LI>" . $cVal . "</LI>";
+						break;
+					}
+				}
+
+				echo "</UL>";
+			?></TD>
+		</TR> 
+
+		<!-- Location Info -->
+		<TR>
+			<TD colspan="4" class="detailedView_heading" style="text-align:left; padding-right:6px; padding-top:10px; color:#0000DF; font-size:9pt; font-family:Helvetica; white-space:nowrap;">Location Details</TD>
+		</TR>
+		<?php 
+			$chemLoc = $chemical->getLocation();
+		?>
+		<!-- Location Name -->
+		<TR>
+			<TD class="detailedView_colName">Storage Name / Room Number</TD>
+			<TD class="detailedView_value"><?php echo $chemLoc->getName(); ?></TD>
+		</TR>
+
+		
+		<!-- Location Type -->
+		<TR>
+			<TD class="detailedView_colName">Storage Type/Temperature</TD>
+			<TD class="detailedView_value"><?php echo $chemLoc->getTemperature(); ?></TD>
+		</TR>
+
+		
+		<!-- Location comments -->
+		<TR>
+			<TD class="detailedView_colName">Location Comments</TD>
+			<TD class="detailedView_value"><?php echo $chemLoc->getDescription(); ?></TD>
+		</TR>
+	</table>
+	<?php	
+}
+
+
+/**
+* Select all information on the chemical identified by $chemID from the database and create a Chemical object with this information
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+*
+* @param INT Database ID of the sought chemical
+*/
+function createChemical($chemListID)
+{
+	global $conn;
+
+	$newChem = null;
+
+	$chem_rs = mysql_query("SELECT cn.chemicalName, cn.CAS_No, gc1.comment as Comments, gc2.comment as Supplier, gc3.comment as chemLocComments, c.Quantity, c.Safety as Safety, c.MSDS as MSDS, clt.chemLocTypeName, cln.chemicalLocationName FROM ChemicalNames_tbl cn, Chemicals_tbl c, GeneralComments_tbl gc1, GeneralComments_tbl gc2, GeneralComments_tbl gc3, CommentLink_tbl gcl, ChemicalLocationTypes_tbl clt, ChemicalLocations_tbl cl, ChemicalLocationNames_tbl cln WHERE cn.chemicalID=c.chemica [...]
+
+	if ($chem_ar = mysql_fetch_array($chem_rs, MYSQL_ASSOC))
+	{
+		$chemicalName = $chem_ar["chemicalName"];
+		$cas_NO = $chem_ar["CAS_No"];
+		$supplier = $chem_ar["Supplier"];
+		$safety = $chem_ar["Safety"];
+		$quantity = $chem_ar["Quantity"];
+		$msds = $chem_ar["MSDS"];
+		$chemComms = $chem_ar["Comments"];
+		$chemLocName = $chem_ar["chemicalLocationName"];
+		$chemLocTypeName = $chem_ar["chemLocTypeName"];
+		$chemLocComms = $chem_ar["chemLocComments"];
+
+		$tmpChemLoc = new ChemicalLocation($chemLocName, $chemLocTypeName, $chemLocComms);
+		$newChem = new Chemical($chemicalName, $cas_NO, $tmpChemLoc, $supplier, $quantity, $safety, "", $chemComms, $msds);
+	}
+
+	return $newChem;
+}
+
+mysql_close($conn);
+?>
diff --git a/OpenFreezer/Classes/Bug_Class.php b/OpenFreezer/Classes/Bug_Class.php
new file mode 100755
index 0000000..455bdbc
--- /dev/null
+++ b/OpenFreezer/Classes/Bug_Class.php
@@ -0,0 +1,140 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package BugReport
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+ * A class to represent reported bugs and/or feature requests
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @package BugReport
+ *
+ * @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+	class Bug_Class
+	{
+		var $bug_type;
+		var $bug_descr;
+		var $module;
+		var $requested_by;	// INT representing user ID
+		var $isClosed;
+
+		/**
+		 * Constructor
+		 *
+		 * @param STRING one of 'bug report' or 'feature request'
+		 * @param STRING detailed description of the bug/feature request
+		 * @param STRING module in which the bug was discovered (or feature request should be applied)
+		 * @param INT userID of the user submitting the bug/feature report
+		 * @param boolean is the bug/request open or closed
+		 *
+		 * @author Marina Olhovsky
+		 * @version 3.1
+		*/
+		function Bug_Class($bug_type, $bug_descr, $module, $requested_by, $isClosed = false)
+		{
+			$this->bug_type = $bug_type;
+			$this->bug_descr = $bug_descr;
+			$this->module = $module;
+			$this->requested_by = $requested_by;
+			$this->isClosed = $isClosed;
+		}
+
+		/**
+		 * Return the type of this request: bug or feature
+		 *
+		 * @author Marina Olhovsky
+		 * @version 3.1
+		 *
+		 * @return STRING
+		*/
+		function getBugType()
+		{
+			return $this->bug_type;
+		}
+
+
+		/**
+		 * Return the details of this request
+		 *
+		 * @author Marina Olhovsky
+		 * @version 3.1
+		 *
+		 * @return STRING
+		*/
+		function getBugDescription()
+		{
+			return $this->bug_descr;
+		}
+
+
+		/**
+		 * Return the module this request is associated with
+		 *
+		 * @author Marina Olhovsky
+		 * @version 3.1
+		 *
+		 * @return STRING
+		*/
+		function getModule()
+		{
+			return $this->module;
+		}
+
+
+		/**
+		 * Return the userID of the user submitting this request
+		 *
+		 * @author Marina Olhovsky
+		 * @version 3.1
+		 *
+		 * @return INT
+		*/
+		function getRequestedBy()
+		{
+			return $this->requested_by;
+		}
+
+
+		/**
+		 * Return the status of this request, whether it is open or closed
+		 *
+		 * @author Marina Olhovsky
+		 * @version 3.1
+		 *
+		 * @return boolean
+		*/
+		function isClosed()
+		{
+			return $this->isClosed;
+		}
+	}
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Classes/Bug_Function_Class.php b/OpenFreezer/Classes/Bug_Function_Class.php
new file mode 100755
index 0000000..82ce307
--- /dev/null
+++ b/OpenFreezer/Classes/Bug_Function_Class.php
@@ -0,0 +1,88 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package BugReport
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+ * Include/require statements
+ *
+*/
+
+include_once("Bug_Class.php");
+
+/**
+ * Auxiliary class to handle bug reports and feature requests
+ * Written August 2, 2010
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package BugReport
+ *
+ * @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+class Bug_Function_Class
+{
+	/**
+	* Default constructor
+	*/
+	function Bug_Function_Class()
+	{}
+	
+
+	/**
+	 * Retrieve ALL the current bug/feature requests from the database
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @return Array
+	*/
+	function fetchAllBugs()
+	{
+		global $conn;
+
+		$bugs = Array();
+
+		$active_bugs_rs = mysql_query("SELECT bug_type, bug_descr, module, requested_by FROM BugReport_tbl WHERE status='ACTIVE' AND is_closed='NO'");
+
+		while ($active_bugs_ar = mysql_fetch_array($active_bugs_rs, MYSQL_ASSOC))
+		{
+			$bug_type = $active_bugs_ar["bug_type"];
+			$bug_descr = $active_bugs_ar["bug_descr"];
+			$module = $active_bugs_ar["module"];
+			$requested_by = $active_bugs_ar["requested_by"];
+
+			$tmpBug = new Bug_Class($bug_type, $bug_descr, $module, $requested_by);
+			$bugs[] = $tmpBug;
+		}
+
+		return $bugs;
+	}
+}
+?>
diff --git a/OpenFreezer/Classes/Chemical_Class.php b/OpenFreezer/Classes/Chemical_Class.php
new file mode 100755
index 0000000..81aa1e2
--- /dev/null
+++ b/OpenFreezer/Classes/Chemical_Class.php
@@ -0,0 +1,338 @@
+<?php
+/**
+* PHP versions 4 and 5 http://php.net
+*
+* Copyright (c) 2005-2010 Mount Sinai Hospital, Toronto, Canada
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Chemical
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Canada
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Include/require statements
+*/
+include_once "Chemical_Location_Class.php";
+
+/**
+ * This class represents a chemical
+ * Written July 28, 2008
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Chemical
+ *
+ * @copyright	2005-2011 Mount Sinai Hospital, Toronto, Canada
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+class Chemical
+{
+	/**
+	 * @var STRING
+	 * Name of the chemical
+	*/
+	var $chemicalName;
+
+
+	/**
+	 * @var STRING
+	 * CAS no. of the chemical (a mixture of alphanumeric characters)
+	*/
+	var $casNo;
+
+
+	/**
+	 * @var STRING
+	 * Location of the chemical (e.g. '-40C Freezer')
+	*/
+	var $chemicalLocation;
+
+
+	/**
+	 * @var STRING
+	 * Description of the chemical
+	*/
+	var $chemicalDescription;
+
+
+	/**
+	 * @var STRING
+	 * Comments regarding the chemical
+	*/
+	var $comments;
+
+
+	/**
+	 * @var STRING
+	 * Supplier of the chemical (e.g. 'Invitrogen')
+	*/
+	var $supplier;
+
+
+	/**
+	 * @var STRING
+	 * Quantity of the chemical (e.g. '50 ml')
+	*/
+	var $quantity;
+
+
+	/**
+	 * @var STRING
+	 * Safety information on the chemical
+	*/
+	var $safety;
+
+	/**
+	 * @var INT
+	 * Internal database identifier of the chemical
+	*/
+	var $chemicalID;
+
+	/**
+	 * @var STRING
+	 * Hyperlink to MSDS for this chemical
+	*/
+	var $msds;
+
+	// Constructor
+	/**
+	 * Constructor
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING Name of the chemical
+	 * @param STRING CAS no. of the chemical
+	 * @param STRING Location of the chemical
+	 * @param STRING Supplier of the chemical
+	 * @param STRING Quantity of the chemical
+	 * @param STRING Safety information of the chemical
+	 * @param STRING Description of the chemical
+	 * @param STRING Comments on the chemical
+	 * @param INT Internal database ID of the chemical (optional)
+	 *
+	 * @see $chemicalName
+	 * @see $casNo
+	 * @see $chemicalLocation
+	 * @see $supplier
+	 * @see $quantity
+	 * @see $safety
+	 * @see $chemicalDescription
+	 * @see $comments
+	 * @see $chemicalID
+	*/
+	function Chemical($chemName, $casNo, $chemLocation, $supplier, $quantity, $safety, $chemDescription, $chemComments, $msds, $chemID=0)
+	{
+		$this->chemicalName = $chemName;
+		$this->casNo = $casNo;
+		$this->chemicalLocation = $chemLocation;
+		$this->chemicalDescription = $chemDescription;
+		$this->supplier = $supplier;
+		$this->quantity = $quantity;
+		$this->safety = $safety;
+		$this->comments = $chemComments;
+		$this->msds = $msds;
+		$this->chemicalID = $chemID;
+	}
+
+
+	/**
+	 * Return the name of this chemical
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @return STRING
+	*/
+	function getName()
+	{
+		return $this->chemicalName;
+	}
+
+
+	/**
+	 * Return the CAS no. of this chemical
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @return STRING
+	*/
+	function getCAS_No()
+	{
+		return $this->casNo;
+	}
+
+
+	/**
+	 * Return the description of this chemical
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @return STRING
+	*/
+	function getDescription()
+	{
+		return $this->chemicalDescription;
+	}
+
+
+	/**
+	 * Return the location of this chemical
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @return STRING
+	*/
+	function getLocation()
+	{
+		return $this->chemicalLocation;
+	}
+
+
+	/**
+	 * Return the supplier of this chemical
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @return STRING
+	*/
+	function getSupplier()
+	{
+		return $this->supplier;
+	}
+
+
+	/**
+	 * Return the quantity of this chemical
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @return STRING
+	*/
+	function getQuantity()
+	{
+		return $this->quantity;
+	}
+
+
+	/**
+	 * Return the safety information on this chemical
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @return STRING
+	*/
+	function getSafety()
+	{
+		return $this->safety;
+	}
+
+
+	/**
+	 * Return the comments on this chemical
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @return STRING
+	*/
+	function getComments()
+	{
+		return $this->comments;
+	}
+
+	
+	/**
+	 * Return the database ID of this chemical
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @return INT
+	*/
+	function getChemicalID()
+	{
+		return $this->chemicalID;
+	}
+
+	/**
+	 * Return the URL to the MSDS for this chemical
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @return INT
+	*/
+	function getMSDS()
+	{
+		return $this->msds;
+	}
+
+	
+	/**
+	 * Set the database ID of this chemical to the argument value
+	 * 
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param INT chemID The internal database identifier of this chemial (corresponds to chemicalID column in Chemicals_tbl) 
+	*/
+	function setChemicalID($chemID)
+	{
+		$this->chemicalID = $chemID;
+	}
+
+
+	/**
+	 * Set the location of this chemical to the argument value
+	 * 
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param ChemicalLocation Location of this chemical (object)
+	*/
+	function setChemicalLocation($chemicalLocation)
+	{
+		$this->chemicalLocation = $chemicalLocation;
+	}
+
+
+	/**
+	 * Set the MSDS hyperlink of this chemical to the argument value
+	 * 
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING Hyperlink to the MSDS of this chemical
+	*/
+	function setMSDS($msds)
+	{
+		$this->msds = $msds;
+	}
+}
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Classes/Chemical_Location_Class.php b/OpenFreezer/Classes/Chemical_Location_Class.php
new file mode 100755
index 0000000..10c3048
--- /dev/null
+++ b/OpenFreezer/Classes/Chemical_Location_Class.php
@@ -0,0 +1,175 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Chemical
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+ * This class represents the storage location of a chemical
+ * Examples of storage locations include cabinets, fridges, etc.
+ *
+ * Each location has a 'temperature' attribute (4C, -20C, room temperature) and a name ("Cabinet A", "Fridge 1", etc.)
+ * Written July 28, 2008
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Chemical
+ *
+ * @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+class ChemicalLocation
+{
+	/**
+	 * @var STRING
+	 * Name of this location
+	*/
+	var $locationName;
+
+
+	/**
+	 * @var STRING
+	 * Temperature of this location (e.g. 'Room temperature', or '-80')
+	*/
+	var $locationTemp;
+
+
+	/**
+	 * @var STRING
+	 * Description of this location
+	*/
+	var $locationDescription;
+
+	/**
+	 * @var INT
+	 * Internal database ID of this location
+	*/
+	var $locationID;
+
+
+	/**
+	 * Constructor
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING Name of the location
+	 * @param STRING Temperature of the location
+	 * @param STRING Description of the location
+	*/
+	function ChemicalLocation($locName, $locTemp, $locDescr)
+	{
+		$this->locationName = $locName;
+		$this->locationTemp = $locTemp;
+		$this->locationDescription = $locDescr;
+	}
+
+
+	/**
+	 * Return the name of this location
+	 *
+	 * @return STRING
+	*/
+	function getName()
+	{
+		return $this->locationName;
+	}
+
+
+	/**
+	 * Return the description of this location
+	 *
+	 * @return STRING
+	*/
+	function getDescription()
+	{
+		return $this->locationDescription;
+	}
+
+
+	/**
+	 * Return the temperature of this location
+	 *
+	 * @return STRING
+	*/
+	function getTemperature()
+	{
+		return $this->locationTemp;
+	}
+
+	/**
+	 * Return a string to output this location
+	 *
+	 * @return STRING
+	*/
+	function printLocation()
+	{
+		// updated July 31/08
+// 		return $this->getName() . " " . $this->getTemperature() . " " . $this->getDescription();
+		return $this->getName();
+	}
+
+	/**
+	 * Set the temperature (type) of this location to the argument value
+	 * 
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING Type/temperature of this location
+	*/
+	function setTemperature($locTemp)
+	{
+		$this->locationTemp = $locTemp;
+	}
+
+	/**
+	 * Set the name of this location to the argument value
+	 * 
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING Name of this location
+	*/
+	function setName($locName)
+	{
+		$this->locationName = $locName;
+	}
+
+	/**
+	 * Set the internal database ID of this location to the argument value
+	 * 
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param INT Internal database ID of this location
+	*/
+	function setLocationID($locID)
+	{
+		$this->locationID = $locID;
+	}
+}
+?>
diff --git a/OpenFreezer/Classes/ColFunctOutputer.php b/OpenFreezer/Classes/ColFunctOutputer.php
new file mode 100755
index 0000000..02d455c
--- /dev/null
+++ b/OpenFreezer/Classes/ColFunctOutputer.php
@@ -0,0 +1,829 @@
+<?php
+
+// DO NOT DELETE THIS CLASS - USED IN SEARCH TABLE OUTPUT!!!!!!!!!!!!!!!!!!!!!!!
+
+/**
+* PHP versions 4 and 5 http://php.net
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Search
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Canada
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Include/require statements
+*/
+include "../functions.php";
+
+class ColFunctOutputer
+{
+	var $setSeparator;
+	var $seqIncrementor;
+	var $maxLineOutput;
+
+	function ColFunctOutputer()
+	{
+		$this->setSeparator = " ";
+		$this->seqIncrementor = 10;
+		$this->maxLineOutput = 10;
+	}
+	
+	function output( $rid,  $columnType, $outputType )
+	{
+		switch( $columnType )
+		{
+			case "Description":
+			case "Comment":
+			case "Comments":
+				return $this->output_description( $rid, $columnType );
+			case "Sequence":
+				if( $outputType == "Preview" )
+				{
+					return $this->output_sequence2( $rid , 2 );
+				}
+				return $this->output_sequence2( $rid, 4 );
+			case "Length":
+				return $this->output_length( $rid );
+			case "Open/Closed":
+				return $this->output_hint_rev1( $rid );
+			case "Packet":
+				if( $outputType == "Preview" )
+					{
+						return $this->output_packet( $rid, 1 );
+					}
+				return $this->output_packet( $rid, 2 );
+
+			// May 29/06, Marina
+			case "parent vector name":
+			case "parent cell line name":
+				return $this->outputCellLineParents($rid, $columnType);
+
+			// June 1/09
+			case "type":
+				return $this->output_Reagent_Type($rid);
+
+			default:
+				return "No matching column type was found!";
+		}
+	}
+
+
+	// June 1/09
+	function output_Reagent_Type($rid)
+	{
+		global $conn;
+		$rfunc = new Reagent_Function_Class();
+
+		$rType = $rfunc->getType($rid);
+
+		$typePropName = $rType . "type";
+		$propType = "";
+
+		$query = "SELECT propertyValue FROM ReagentPropList_tbl WHERE propertyID= '" . $_SESSION["ReagentProp_Name_ID"][$typePropName]. "' AND reagentID='" . $rid . "' AND status='ACTIVE'";
+
+		$seq_rs = mysql_query($query, $conn);
+
+		while ($seq_ar = mysql_fetch_array($seq_rs, MYSQL_ASSOC))
+		{
+			$propType = $seq_ar["propertyValue"];
+		}
+
+		return $propType;
+	}
+
+
+	function outputCellLineParents($rid, $colType)
+	{
+		global $conn;
+
+		$rfunc_obj = new Reagent_Function_Class();	// Aug. 18, 2010
+
+		switch (strtolower($colType))
+		{
+			case "parent vector name":
+				// Find the parent vector and get its name
+				$pv_name = "N/A";
+
+				// Update Aug. 18, 2010
+				// 1. Get the ID of association called 'vector id' that represents the parent vector for cell lines
+				// Aug. 18, 2010: No, the association is called 'cell line parent vector id'
+				$assoc_id_rs = mysql_query("SELECT * FROM `Assoc_Prop_Type_tbl` WHERE `APropName`='cell line parent vector id'", $conn) or die("Error fetching parent vector association ID");
+
+// echo "SELECT * FROM `Assoc_Prop_Type_tbl` WHERE `APropName`='cell line parent vector id'";
+
+				while ($assoc_id_ar = mysql_fetch_array($assoc_id_rs, MYSQL_ASSOC))
+				{
+					$pv_assoc_id = $assoc_id_ar["APropertyID"];
+// echo $pv_assoc_id;
+				}
+
+				// 2. Fetch the parent's ID from Associations table
+				$pv_rs = mysql_query("SELECT * FROM `Association_tbl` a, `AssocProp_tbl` b WHERE a.`reagentID`='" . $rid . "' AND a.`assID`=b.`assID` AND b.`APropertyID`='" . $pv_assoc_id . "' AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'", $conn) or die("Error fetching parent vector ID");
+
+				while ($pv_ar = mysql_fetch_array($pv_rs, MYSQL_ASSOC))
+				{
+					$pv_prop_value = $pv_ar["propertyValue"];
+				}
+
+				// 3. Find the ID of property 'name'
+				// Aug. 18, 2010: Account for category
+				$name_prop_id = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["name"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+
+// removed Aug. 18, 2010
+// 				$name_prop_rs = mysql_query("SELECT `propertyID` FROM `ReagentPropType_tbl` WHERE `propertyName`='name' AND `status`='ACTIVE'", $conn) or die("Error fetching ID of property 'name'");
+// 
+// 				while ($name_prop_ar = mysql_fetch_array($name_prop_rs, MYSQL_ASSOC))
+// 				{
+// 					$name_prop_id = $name_prop_ar["propertyID"];
+// 				}
+
+				// 4. Find the name of the parent in ReagentPropList_tbl
+				$pv_name_rs = mysql_query("SELECT `propertyValue` FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $pv_prop_value . "' AND `propertyID`='" . $name_prop_id . "' AND `status`='ACTIVE'", $conn) or die("Error finding parent vector name");
+
+				while ($pv_name_ar = mysql_fetch_array($pv_name_rs, MYSQL_ASSOC))
+				{
+					$pv_name = $pv_name_ar["propertyValue"];
+				}		
+
+				return $pv_name;
+
+			case "parent cell line name":
+				// Find the parent cell line and get its name - Update Aug. 18, 2010: the property is now called 'parent cell line id', not 'cellline id'
+				$assoc_id_rs = mysql_query("SELECT  * FROM `Assoc_Prop_Type_tbl` WHERE `APropName`='parent cell line id'", $conn) or die("Error fetching parent vector association ID");
+
+				while ($assoc_id_ar = mysql_fetch_array($assoc_id_rs, MYSQL_ASSOC))
+				{
+					$cl_assoc_id = $assoc_id_ar["APropertyID"];
+				}
+
+				// 2. Fetch the parent's ID from Associations table
+				$cl_rs = mysql_query("SELECT * FROM `Association_tbl` a, `AssocProp_tbl` b WHERE a.`reagentID`='" . $rid . "' AND a.`assID`=b.`assID` AND b.`APropertyID`='" . $cl_assoc_id . "' AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'", $conn) or die("Error fetching parent cell line ID");
+
+				while ($cl_ar = mysql_fetch_array($cl_rs, MYSQL_ASSOC))
+				{
+					$cl_prop_value = $cl_ar["propertyValue"];
+				}
+
+				// 3. Find the ID of property 'name'
+				// Aug. 18, 2010: Account for category
+				$name_prop_id = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["name"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+/*
+				$name_prop_rs = mysql_query("SELECT `propertyID` FROM `ReagentPropType_tbl` WHERE `propertyName`='name' AND `status`='ACTIVE'", $conn) or die("Error fetching ID of property 'name'");
+
+				while ($name_prop_ar = mysql_fetch_array($name_prop_rs, MYSQL_ASSOC))
+				{
+					$name_prop_id = $name_prop_ar["propertyID"];
+				}*/
+
+				// 4. Find the name of the parent in ReagentPropList_tbl
+				$cl_name_rs = mysql_query("SELECT `propertyValue` FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $cl_prop_value . "' AND `propertyID`='" . $name_prop_id . "' AND `status`='ACTIVE'", $conn) or die("Error finding parent vector name");
+
+				while ($cl_name_ar = mysql_fetch_array($cl_name_rs, MYSQL_ASSOC))
+				{
+					$cl_name = $cl_name_ar["propertyValue"];
+				}
+
+				return $cl_name;
+		}
+	}
+	
+	function output_packet( $rid, $type )
+	{
+		global $conn;
+		
+		switch( $type )
+		{
+			case 1:
+				$find_name_rs = mysql_query( "SELECT a.`packetID`, a.`lastName` FROM `PacketOwners_tbl` a INNER JOIN `Packets_tbl` b "
+											. " ON a.`packetID`=b.`packetID` WHERE b.`reagentID`='" . $rid . "'" 
+											. " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'", $conn );
+				
+				if( $find_name_ar = mysql_fetch_array( $find_name_rs, MYSQL_ASSOC ) )
+				{
+					$tempName = $find_name_ar["lastName"] . ":" . $find_name_ar["packetID"] ;
+					return $tempName;
+				}
+//				break;
+			case 2:
+				$find_name_rs = mysql_query( "SELECT b.`packetID`, b.`firstName`, b.`lastName`, b.`packetName` FROM `Packets_tbl` a "
+											. " INNER JOIN `PacketOwners_tbl` b ON a.`packetID`=b.`packetID` "
+											. " WHERE a.`reagentID`='" . $rid . "'"
+											. " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'" , $conn );
+				
+				if( $find_name_ar = mysql_fetch_array( $find_name_rs, MYSQL_ASSOC ) )
+				{
+					$tempName = $find_name_ar["packetID"] . ":" . $find_name_ar["lastName"] . "-" . $find_name_ar["packetName"];
+					return $tempName;
+				}
+//				break;
+			default:
+				return "";
+		}
+	}
+	
+	function output_description( $rid, $columnType )
+	{
+		global $conn;
+		//print_r( $_SESSION["ReagentProp_Name_ID"] );
+		//echo "rid: " . $rid . "<br>";
+		$currentTypeID = 0;
+		
+		if( $columnType == "Description" )
+		{
+			$currentTypeID = $_SESSION["ReagentProp_Name_ID"]["Description"];
+		}
+		elseif( $columnType == "Comment" || $columnType == "Comments" )
+		{
+			$currentTypeID = $_SESSION["ReagentProp_Name_ID"]["Comments"];
+		};
+		
+		$foundCommentID_rs = mysql_query( "SELECT `propertyValue` FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $rid  . "' "
+										. " AND `status`='ACTIVE' AND `propertyID`='" . $currentTypeID . "';" , $conn )
+										or die( "[died on comment search]: " . mysql_error() );
+		
+		if( $foundCommentID_ar = mysql_fetch_array( $foundCommentID_rs, MYSQL_ASSOC ) )
+		{
+			$foundRealDesc_rs = mysql_query( "SELECT `comment` FROM `GeneralComments_tbl` " 
+											. " WHERE `commentID`='" . $foundCommentID_ar["propertyValue"] . "'"
+											. " AND `status`='ACTIVE';", $conn );
+			
+			if(  $foundRealDesc_ar = mysql_fetch_array( $foundRealDesc_rs, MYSQL_ASSOC ) )
+			{
+				return $foundRealDesc_ar["comment"];
+			}
+			
+			return "ERROR: Did not find the comment id!";
+		}
+		
+		//return "ERROR: No Description found!";
+		return "";
+	}
+	
+	function output_hint_rev0( $rid )
+	{
+		global $conn;
+		//$assoc_hint_rs = mysql_query( "SELECT DISTINCT a.`propertyValue` AS hint FROM `AssocProp_tbl` a INNER JOIN `AssocProp_tbl` b ON a.`assID`=b.`assID` " .
+									//	" WHERE b.`propertyID`='" . $_SESSION["ReagentProp_Name_ID"]["Insert ID"] . "' AND " .
+									//	" b.`propertyValue`='" . $rid . "' AND " .
+									//	" a.`propertyID`='" . $_SESSION["ReagentProp_Name_ID"]["Association Hint"] . "'" );
+										
+		$test_rs = mysql_query( "SELECT `assID` FROM `AssocProp_tbl` WHERE `propertyID`='" . $_SESSION["ReagentProp_Name_ID"]["Insert ID"] . 
+								"' AND `propertyValue`='" . $rid . "' AND `status`='ACTIVE'", $conn );
+		if( $test_ar = mysql_fetch_array( $test_rs, MYSQL_ASSOC ) )
+		{
+		$assoc_hint_rs = mysql_query( "SELECT `propertyValue` AS hint FROM `AssocProp_tbl` WHERE `propertyID`='" . 
+									$_SESSION["ReagentProp_Name_ID"]["Association Hint"] . "'"
+									. " AND `assID`='" . $test_ar["assID"] . "'" 
+									. " AND `status`='ACTIVE'", $conn );
+		
+		if( $assoc_hint_ar = mysql_fetch_array( $assoc_hint_rs, MYSQL_ASSOC ) )
+		{
+			return $assoc_hint_ar["hint"];
+		}
+		}
+	}
+	
+	function output_hint_rev1( $rid )
+	{
+		global $conn;
+		$new_hint_rs = mysql_query( "SELECT `propertyValue` AS hint FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $rid . "'"
+									. " AND `propertyID`='" . $_SESSION["ReagentProp_Name_ID"]["Association Hint"] 
+									. "' AND `status`='ACTIVE'", $conn );
+									
+		if( $new_hint_ar = mysql_fetch_array( $new_hint_rs, MYSQL_ASSOC ) )
+		{
+			return $new_hint_ar["hint"];
+		}
+	}
+	
+	function output_length( $rid )
+	{
+		global $conn;
+		//print_r($_SESSION["ReagentProp_Name_ID"]);
+		$foundSeqID_rs = mysql_query( "SELECT `propertyValue` FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $rid . "'"
+									. " AND `propertyID` IN ('" . $_SESSION["ReagentProp_Name_ID"]["Sequence"] . "','"
+									. $_SESSION["ReagentProp_Name_ID"]["Full CDNA Sequence"] . "','"
+									. $_SESSION["ReagentProp_Name_ID"]["Subsequence CDNA"] . "')" 
+									. " AND `status`='ACTIVE'", $conn );
+		
+		if( $foundSeqID_ar = mysql_fetch_array( $foundSeqID_rs, MYSQL_ASSOC ) )
+		{
+			$foundRealSeq_rs = mysql_query( "SELECT length(`sequence`) as finalLength FROM `Sequences_tbl` "
+											. " WHERE `seqID`='" . $foundSeqID_ar["propertyValue"] . "'" 
+											. " AND `seqTypeID`='" . getSeqTypeID( "cDNA" ) . "'" 
+											. " AND `status`='ACTIVE';", $conn );
+			
+			if(  $foundRealSeq_ar = mysql_fetch_array( $foundRealSeq_rs, MYSQL_ASSOC ) )
+			{
+				return $foundRealSeq_ar["finalLength"];
+			}
+			
+			return "";
+		}
+	}
+	
+	function output_sequence2($rid, $typeOfOutput)
+	{
+		global $conn;
+		$cdna_sequence = "";
+		$cdna_subsequence = "";
+		$protein_sequence = "";
+		
+		// Aug. 17/09
+		$seqPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["Sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+
+		$protSeqPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["Protein Sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]);
+
+		// NOTE: If you change the types of sequences that are available, you must add it here!
+		$foundSeqID_rs = mysql_query("SELECT `propertyID`, `propertyValue` FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $rid . "' AND `propertyID` IN ('" . $seqPropID . "') AND `status`='ACTIVE'" , $conn);
+
+		while ($foundSeqID_ar = mysql_fetch_array($foundSeqID_rs, MYSQL_ASSOC))
+		{
+			$foundRealSeq_rs = mysql_query("SELECT `seqTypeID`, `sequence` FROM `Sequences_tbl` WHERE `seqID` IN ('" . $foundSeqID_ar["propertyValue"] . "') AND `status`='ACTIVE' ORDER BY `seqTypeID`;", $conn);
+			
+			while ($foundRealSeq_ar = mysql_fetch_array($foundRealSeq_rs, MYSQL_ASSOC))
+			{
+				if ($foundRealSeq_ar["seqTypeID"] == getSeqTypeID("DNA") && $foundSeqID_ar["propertyID"] == $seqPropID)
+				{
+					$cdna_sequence = $foundRealSeq_ar["sequence"];
+				}
+				elseif( $foundRealSeq_ar["seqTypeID"] == getSeqTypeID("Protein") && $foundSeqID_ar["propertyID"] == $protSeqPropID)
+				{
+					$protein_sequence = $foundRealSeq_ar["sequence"];
+				}
+				else
+				{
+					echo "ERROR! Did not find a matching propertyID for the database ID!";
+					return "";
+				}
+			}
+		}
+			//return "ERROR: Did not find the Seq id!";
+			
+			
+		switch ($typeOfOutput)
+		{
+			case 1:
+				// Basic output, with no frills
+				echo $cdna_sequence;
+			break;
+
+			case 2:
+				// Basic output with breaks inbetween every 10
+				echo chunk_split($cdna_sequence, 10, " ");
+			break;
+
+			case 3:
+			break;
+
+			case 4:
+				// Case where you want to output alignment between cdna and protein and you have:
+				// 1. cdna sequence
+				// 2. protein sequence
+				// 3. 5' and 3' primers for the cdna sequence
+				
+				echo "Attempting detailed<br>";
+				
+				echo "<table border=1>";
+				
+				$outputPlace = 0;
+				
+				$setCount = 0;  // Holds the number of sets currently outputted for this line
+				$lineCount = 0; // Holds the number of lines that have been outputted so far for this sequence
+				
+				
+				$maxLineOutput = 10;
+				
+				$fivePrimer = 0;
+				$threePrimer = 0;
+				
+				// Generic Sequence counters
+				$seqCount = 1;
+				$seqArrayCount = 0;
+				$seqIncrementor = 10;
+				
+				$proteinSeqCount = 0;
+				$proteinSpotCount = 0;
+				
+				$proteinStartSpot_tmp = 0;
+				$setProteinStart_tmp = 0;
+				
+				$output_seq = "";
+				
+				if( strlen( $cdna_subsequence ) > 0)
+				{
+					$output_seq = $cdna_subsequence;
+					
+				}
+				elseif( strlen( $cdna_sequence ) > 0 )
+				{
+					$output_seq = $cdna_sequence;
+					
+					// If this is a full cdna sequence, grab the 5' and 3' cutters!
+					$primers_rs = mysql_query( "SELECT `propertyID`, `propertyValue` FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $rid . 
+												"' AND `propertyID` IN ('" . $_SESSION["ReagentProp_Name_ID"]["5' start"] . "','" 
+												. $_SESSION["ReagentProp_Name_ID"]["3' stop"] . "')" 
+												. " AND `status`='ACTIVE'", $conn );
+												
+					while( $primers_ar = mysql_fetch_array( $primers_rs, MYSQL_ASSOC ) )
+					{
+						if( $primers_ar["propertyID"] == $_SESSION["ReagentProp_Name_ID"]["5' start"] )
+						{
+							$fivePrimer = $primers_ar["propertyValue"];
+						}
+						elseif( $primers_ar["propertyID"] == $_SESSION["ReagentProp_Name_ID"]["3' stop"] )
+						{
+							$threePrimer = $primers_ar["propertyValue"];
+						}
+						
+					}
+				}
+				else
+				{
+					// If no sequence was found for this reagent, just return nothing!!
+					// FIX-IT: There should be something better here
+					return "";
+				}
+				
+				if( $fivePrimer == 0 && $threePrimer == 0 )
+				{
+					$fivePrimer = 1;
+					$threePrimer = strlen( $output_seq );
+				}
+				
+				$cdna_length = strlen( $output_seq );
+				
+				$spacedSeq = chunk_split( $output_seq, 10, " " );
+				//echo "Spaced seq: " . $spacedSeq . "<br>";
+				$subSequence_ar = explode( " ", $spacedSeq );
+				
+				$startTag = "<span class=cdna>";
+				$endTag = "</span>";
+				
+				$setSeparator = " ";
+				
+				echo $startTag;
+				
+				
+				//if( strlen( $protein_sequence ) == 0 )
+				//{
+				//convertToAA( "aaa" );
+				//echo "cdna: " . $output_seq . "<BR>";
+				//echo "5 prime: " . $fivePrimer . ": three: " . $threePrimer . "<BR>";
+				$protein_sequence = $this->translate( $output_seq, $fivePrimer, $threePrimer );
+				//echo "FOUND PROTEIN SEQ: " . $protein_sequence . "<BR>";
+				//}
+				$isDone = false;
+				
+				while( !$isDone )
+				{
+					
+					//$setCount = 0;
+					
+					if( $setCount == 0 )
+					{
+						// Output the new start of the row!
+						echo "";
+						echo "<tr>";
+						echo "<td>";
+						//echo "what th: " . $lineCount . "<br>";
+						echo ( ( $lineCount * ( $seqIncrementor * $maxLineOutput ) ) + 1 );
+						echo "-";
+						echo ( ( $lineCount + 1 ) * ( $seqIncrementor * $maxLineOutput ) );
+						echo "</td>";
+						echo "<td>";
+						echo "<tt>";
+					}
+				
+					if( $outputPlace == 0  )
+					{
+						// If the output is BEFORE the protein sequence
+						$seqCount += $seqIncrementor;
+						
+						if( $seqCount < $fivePrimer )
+						{
+							echo $subSequence_ar[ $seqArrayCount ];
+							$seqArrayCount++;
+							$setCount++;
+						}
+						else
+						{
+							// Finds the exact spot in the subsequence
+							// subtract 1 to INCLUDE the dna seq IN IN the protein sequence
+							$spotInSub = ( $fivePrimer % $seqIncrementor ) - 1 ;
+							$temp1 =  substr( $subSequence_ar[ $seqArrayCount ], 0 , $spotInSub  );
+							$temp2 =  substr( $subSequence_ar[ $seqArrayCount ], $spotInSub , $seqIncrementor );	
+							
+							$setProteinStart_tmp = $setCount;
+							$proteinStartSpot_tmp = $spotInSub;
+							//$setCount = $lineCount;
+							
+							echo $temp1;
+							echo $startTag . $temp2 . $endTag;
+							
+							$seqArrayCount++;
+							$setCount++;
+							
+							// Change the placement of the output is in!
+							$outputPlace = 1;
+						}
+					}
+					elseif( $outputPlace == 1 )
+					{
+						$seqCount += $seqIncrementor;
+						
+						// If the output is IN the protein sequence
+						if( $seqCount < $threePrimer )
+						{
+							echo $startTag . $subSequence_ar[ $seqArrayCount ] . $endTag;
+							
+							$seqArrayCount++;
+							$setCount++;
+						}
+						else
+						{
+							$spotInSub = $threePrimer % $seqIncrementor;
+							
+							echo $startTag . substr( $subSequence_ar[ $seqArrayCount ], 0 , $spotInSub  ) . $endTag;
+							echo substr( $subSequence_ar[ $seqArrayCount ], $spotInSub , ( $seqIncrementor ) );
+							
+							$seqArrayCount++;
+							$setCount++;
+							
+							// Change the placement of the output is in!
+							$outputPlace = 2;
+						}
+					}
+					elseif( $outputPlace == 2 )
+					{
+						// If the output is AFTER the protein sequence
+						
+						$seqCount += $seqIncrementor;
+						echo $subSequence_ar[ $seqArrayCount ];
+							
+						$seqArrayCount++;
+						$setCount++;
+					};
+					
+					//echo "setcount : " . $setCount . "<BR>";
+			
+					if( !($seqCount < $cdna_length) )
+					{
+						$isDone = true;
+					}
+					
+					if( $setCount == $maxLineOutput || $isDone )
+					{
+						// Output the end of the row!
+						echo "<br>";
+						$lineCount++;
+						$setCount = 0;
+					}
+					else
+					{
+						echo $setSeparator;
+					};
+					
+					
+					
+					//echo "outputpalce: " . $outputPlace . "<BR>";
+					if( ( $outputPlace == 1 || $outputPlace == 2 )  && $setCount == 0 )
+					{
+						$proteinSpotCount = $this->outputProteinSeq($protein_sequence, $proteinStartSpot_tmp, $setProteinStart_tmp, $proteinSeqCount, $proteinSpotCount);
+						$setProteinStart_tmp = 0;
+						$proteinStartSpot_tmp = 0;
+						
+					}
+					elseif( $setCount == 0 )
+					{
+						echo "<BR>";
+					}
+					
+				}
+				
+				echo $endTag;
+				
+				echo "</table>";
+			break;
+		};
+	}
+
+
+	function outputProteinSeq( $protein_sequence, $proteinStartSpot_tmp, $setProteinStart_tmp, $proteinSeqCount, $proteinSpotCount )
+	{
+		// Output the PROTEIN SEQUENCE
+		//if( $outputPlace == 1 && $setCount == 0 )
+		//echo "protein seq left: " . $protein_sequence . "<br>";
+		//echo "proteinstartspot: " . $proteinStartSpot_tmp . " -- setproteinstart: " . $setProteinStart_tmp 
+			//. " -- proteinSeqcount: " . $proteinSeqCount . " -- proteinSpotcount: " . $proteinSpotCount . "<BR>";
+		$startTag = "<tt>";
+		$endTag = "</tt>";
+
+		// While IN the protein sequence
+
+		$finishedProteinOutput = false;
+		echo $startTag . str_repeat( " ", $proteinStartSpot_tmp ) . $endTag;
+		echo $startTag . str_repeat( $this->setSeparator, ($setProteinStart_tmp * $this->seqIncrementor) ) . $endTag;
+		
+		while( !$finishedProteinOutput)
+		{
+			
+			switch( $proteinSpotCount )
+			{
+				case 0:
+					//Before the first DNA codon for the Protein
+					$proteinSpotCount++;
+					break;
+				case 1: 
+					// first actual DNA codon for the Protein
+					$proteinStartSpot_tmp++;
+					$proteinSpotCount++;
+					echo " ";
+					break;
+				case 2:
+					// Output DNA codon for protein
+					echo "<span class=protein>" . substr( $protein_sequence, $proteinSeqCount, 1 ) . "</span>";
+					
+					$proteinSpotCount++;
+					$proteinSeqCount++;
+					$proteinStartSpot_tmp++;
+					break;
+				case 3:
+					$proteinStartSpot_tmp++;
+					
+					$proteinSpotCount = 1;
+					echo " ";
+					break;
+			}
+			
+			if( $proteinStartSpot_tmp >= $this->seqIncrementor )
+			{
+				// Will add a space when protein current spot is greater than the max set! ie. new set needed!
+
+				echo $this->setSeparator;
+
+				$proteinStartSpot_tmp = 0;
+				$setProteinStart_tmp++;
+				
+				
+			}
+			
+			if( $setProteinStart_tmp == $this->maxLineOutput )
+			{
+				echo "</tt>";
+				echo "</td>";
+				echo "</tr>";
+				
+				$finishedProteinOutput = true;
+				$proteinStartSpot_tmp = 0;
+				$setProteinStart_tmp = 0;
+			}
+		}
+						
+		
+		return $proteinSpotCount;
+	}
+
+	function translate( $sequence, $start, $stop )
+	{
+		$sequence = strtolower( $sequence );
+		//echo "start: " . $start . " -- stop: " . $stop . "<BR>";
+		//echo "length: " . strlen( $sequence ) . "<BR>";
+		if( $start <= 0 || $stop <= 0 || $stop > strlen( $sequence ) || $stop <= $start )
+		{
+			return "";
+		}
+		//echo "stage 2------------------";
+		$cdna_seq = substr( $sequence, ( $start - 1 ), ( $stop - $start ) );
+		//echo "trying cdna_seq : " . $cdna_seq . "<br>";
+		$newProteinSeq = "";
+		
+		$spaced_cdna = chunk_split( $cdna_seq, 3, "|" );
+		$aminoacid_ar = explode( "|", $spaced_cdna );
+		
+		foreach( $aminoacid_ar as $key => $value )
+		{
+			$newProteinSeq = $newProteinSeq . $this->convertToAA( $value );
+		}
+		
+		//echo "new protein trans: " . $newProteinSeq . "<BR>";
+		return $newProteinSeq;
+	}
+	
+	function convertToAA( $threeCodons )
+	{
+		switch( $threeCodons )
+		{
+			case "ttt":
+			case "ttc": return "F";
+				break;
+			case "tta":
+			case "ttg": 
+			case "ctt":
+			case "ctc":
+			case "cta":
+			case "ctg": return "L";
+				break;
+			case "att":
+			case "atc":
+			case "ata": return "I";
+				break;
+			case "atg": return "M";
+				break;
+			case "gtt":
+			case "gtc":
+			case "gta":
+			case "gtg": return "V";
+				break;
+			case "tct":
+			case "tcc":
+			case "tca":
+			case "tcg":
+			case "agt":
+			case "agc": return "S";
+				break;
+			case "aga":
+			case "agg":
+			case "cgt":
+			case "cgc":
+			case "cga":
+			case "cgg": return "R";
+				break;
+			case "cct":
+			case "ccc":
+			case "cca":
+			case "ccg": return "P";
+				break;
+			case "act":
+			case "acc":
+			case "aca":
+			case "acg": return "T";
+				break;
+			case "gct":
+			case "gcc":
+			case "gca":
+			case "gcg": return "A";
+				break;
+			case "tat":
+			case "tac": return "Y";
+				break;
+			case "taa":
+			case "tag":
+			case "tga": return "*";
+				break;
+			case "tgt":
+			case "tgc": return "C";
+				break;
+			case "tgg": return "W";
+				break;
+			case "ggt":
+			case "ggc":
+			case "gga":
+			case "ggg": return "G";
+				break;
+			case "cat":
+			case "cac": return "H";
+				break;
+			case "caa":
+			case "cag": return "Q";
+				break;
+			case "aat":
+			case "aac": return "N";
+				break;
+			case "aaa":
+			case "aag": return "K";
+				break;
+			case "gat":
+			case "gac": return "D";
+				break;
+			case "gaa":
+			case "gag": return "E";
+				break;
+			
+		}
+	}
+}
+?>
diff --git a/OpenFreezer/Classes/HT_Class.php b/OpenFreezer/Classes/HT_Class.php
new file mode 100755
index 0000000..6c867ea
--- /dev/null
+++ b/OpenFreezer/Classes/HT_Class.php
@@ -0,0 +1,112 @@
+<?php
+/**
+ * @package Location
+ *
+ * PHP versions 4 and 5
+ *
+ * @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+ * This file is part of OpenFreezer (TM)
+ *
+ * OpenFreezer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+
+ * OpenFreezer is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+ *
+*/
+
+/**
+ * Used to create hashtables for fetching and printing container properties in the Location module
+ *
+ * @author John Paul Lee
+ * @version 2005
+ * @package Location
+ *
+ * @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ */
+class HT_Class
+{
+	
+	var $keys;
+	var $values;
+	var $size;
+	
+	function HT_Class()
+	{
+		$this->keys = array();
+		$this->values = array();
+		$this->size = 0;
+	}
+	
+	function add( $key, $value )
+	{
+		if( in_array( $key, $this->keys, true ) )
+		{
+			return false;
+		}
+		
+		$this->keys[ $this->size ] = $key; 
+		
+		$this->values[ $this->size ] = $value;
+		
+		$this->size++;
+		
+		return true;
+		
+	}
+	
+	function update( $key, $value )
+	{
+		if( in_array( $key, $this->keys, true ) )
+		{
+			//$this->keys[ $this->size ] = $key; 
+		
+			$realkey = array_search( $key, $this->keys, false );
+		
+			unset( $this->values[ $realkey ] );
+		
+			$this->values[ $realkey ] = $value;
+		
+			return true;
+		}
+		
+		return false;
+		
+	}
+	
+	function get( $key )
+	{
+		if( in_array( $key, $this->keys, false ) )
+		{
+			$foundkey = array_search( $key, $this->keys, false );
+			
+			return $this->values[ $foundkey ];
+		}
+		
+		return -1;
+	}
+	
+	function printAll()
+	{
+		echo "----------------<BR>";
+		echo "Hashtable print (size=" . $this->size . ":<BR>Keys=";
+		print_r( $this->keys );
+		echo "<BR>-----------------<BR>Values=";
+		print_r( $this->values );
+		echo "<BR>";
+	}
+	
+	
+}
+
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Classes/MemberLogin_Class.php b/OpenFreezer/Classes/MemberLogin_Class.php
new file mode 100755
index 0000000..2e09ae9
--- /dev/null
+++ b/OpenFreezer/Classes/MemberLogin_Class.php
@@ -0,0 +1,535 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2010 Pawson Laboratory, All Rights Reserved
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package User
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+ * This class contains functions to manage user authorization at login.
+ *
+ * @author John Paul Lee @version 2005
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package User
+ *
+ * @copyright	2005-2010 Pawson Laboratory
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+class MemberLogin_Class
+{
+	/**
+	 * @var Member_Class
+	 * Member_Class instance, representing the user logging in
+	*/
+	var $currentUser;
+
+	var $result;
+	var $classerror;
+	
+	/**
+	 * Constructor
+	*/
+	function MemberLogin_Class()
+	{
+		$this->result=1;
+		$this->classerror = "MemberLogin_Class.";
+	}
+	
+	/**
+	 * Authenticate user with the username and password provided
+	 *
+	 * @param STRING
+	 * @param STRING
+	 *
+	 * @return boolean
+	 *
+	 * @author John Paul Lee @version 2005
+	*/
+	function confirmUser($username, $password )
+	{
+		global $conn;
+		
+		$userInfo_rs = mysql_query("SELECT * FROM `Users_tbl` WHERE username='" . $username . "' AND password='" . md5( $password ) . "' AND `status`='ACTIVE'", $conn) or die(mysql_error());
+		
+		if( !$userInfo_rs || ( mysql_numrows($userInfo_rs) < 1 ) )
+		{
+		 	echo mysql_error( );
+			return false;
+		}
+		
+		$userInfo_ar = mysql_fetch_array( $userInfo_rs, MYSQL_ASSOC );
+		
+		$cookieID = md5( $userInfo_ar['username'] . "$$" . $_SERVER['REMOTE_ADDR'] . "##" );
+		
+		// query updated May 24/07 by Marina - Added $userInfo_ar['category'] argument
+		// updated again June 19/07 - add 'labID' argument
+		// and again on June 27/07 - added 'description' argument
+		$this->currentUser = new Member_Class( $userInfo_ar["userID"], $userInfo_ar['username'], $userInfo_ar['description'], $userInfo_ar['email'], $userInfo_ar['category'], $userInfo_ar['labID'], $cookieID, $_SERVER['REMOTE_ADDR'], session_id( ), $userInfo_ar["password"]);
+		
+		return true;
+	
+	}
+	
+
+	/**
+	 * Authenticate user via cookies
+	 *
+	 * @param STRING
+	 * @param INT
+	 * @param Array
+	 *
+	 * @return boolean
+	 * @author John Paul Lee @version 2005
+	*/
+	function confirmUserViaCookies( $username, $cookieID, $postVariables )
+	{
+		global $conn;
+		
+		$resultSet = mysql_query( "SELECT * FROM `LoginRecord_tbl` WHERE `cookieID`='" . $cookieID . "' AND `user_ip`='" . $_SERVER['REMOTE_ADDR'] . "' AND `persistent`='T' AND status='ACTIVE'", $conn ) or die( mysql_error( ) );
+		
+		if ( !$resultSet || (mysql_numrows($resultSet) < 1) )
+		{
+			return false;
+		} 
+		
+		$resultArray = mysql_fetch_array($resultSet);
+		
+		$userInformation = mysql_query("SELECT * FROM `Users_tbl` WHERE `userID`='" . $resultArray['userID'] . "' AND `status`='ACTIVE'") or die(mysql_error());
+		
+		if ( !$userInformation || (mysql_numrows($userInformation) < 1) )
+		{
+			return false;
+		}
+		
+		$dbarray =  mysql_fetch_array($userInformation, MYSQL_ASSOC);
+		
+		$cookieID = md5($dbarray['username'] . "$$" . $_SERVER['REMOTE_ADDR'] . "##");
+		
+		$this->currentUser = new Member_Class( $dbarray['userID'], $dbarray['username'], $dbarray['email'], $cookieID, $_SERVER['REMOTE_ADDR'], session_id( ) );
+		
+		return true;
+	
+	}
+	
+
+	/**
+	 * Check whether any user info is stored from previous logins
+	 *
+	 * @param Array
+	 * @return boolean
+	 *
+	 * @author John Paul Lee @version 2005
+	*/
+	function loginCheck( $postVariables ) 
+	{
+		//print_r($postVariables);
+		$this->logPageHit( $_SERVER["PHP_SELF"] );
+		
+		$this->result = 1;
+	
+		if (isset($postVariables["loginsubmit"]))
+		{
+//			echo "post login set\n";
+			//global $conn;
+			
+			$username = $postVariables["loginusername_field"];
+			$password = $postVariables["loginpassword_field"];
+
+			if( $this->confirmUser( $username, $password ) ) 
+			{
+//				echo "confirm user";
+				$this->updateLoginRecord( $postVariables );
+				
+				$_SESSION["userinfo"] = $this->currentUser;
+				
+				if( isset( $postVariables["persistentlogin_field"] ) )
+				{
+					setcookie("jpluserid", $_SESSION["userinfo"]->getUserID(), time()+(60*60*24*10000));
+					setcookie("jplcookie", $_SESSION["userinfo"]->getCookieID(), time()+(60*60*24*10000));
+				}
+				
+				//$phpBB = new PHPBB_Login();
+				//$phpBB->login( $this->newUserInfo->getUserID( ) );
+				
+				$this->result = 0;
+			}
+			else
+			{
+				//echo "else";
+				$this->result = 1;
+			}
+		}
+		elseif( isset( $postVariables["logoutsubmit"] ) ) 
+		{
+//			echo "post logout set\n";
+			$this->sessionLogout( );
+			$this->result = 2;
+		
+		}
+		else
+		{
+// 			echo "post not set and that's the way it should be\n";
+
+			if( $this->verifySession( ) ) 
+			{
+//				echo "userinfo set\n";
+				//$_SESSION["userinfo"] = $this->currentUser;
+				$this->currentUser = $_SESSION["userinfo"];
+				$this->result = 0;
+			} 
+			else 
+			{
+//				echo "no previous logins\n";
+				$this->result = 1;
+			}
+		
+		}
+		
+		if( $this->result == 1 ) 
+		{
+			if( isset( $_COOKIE["jpluserid"] ) && isset( $_COOKIE["jplcookie"] ) ) 
+			{
+//				echo "user login info stored\n";
+				if ($this->confirmUserViaCookies($_COOKIE["jpluserid"], $_COOKIE["jplcookie"], $postVariables))
+				{
+					$this->updateLoginRecord( $postVariables );
+				
+					$_SESSION["userinfo"] = $this->currentUser;
+					
+					//$phpBB = new PHPBB_Login();
+					//$phpBB->login( $this->newUserInfo->getUserID( ) );
+					
+					$this->result = 0;
+				}			
+			}
+
+//			echo "no user login info stored\n";
+		}
+	}
+
+	/**
+	 * Log the visited page (web tracking)
+	 *
+	 * @param STRING
+	 *
+	 * @author John Paul Lee @version 2005
+	*/
+	function logPageHit($pageVisited)
+	{
+		global $conn;
+
+		return mysql_query("INSERT INTO WebTracker_tbl (timestamp, userIP, userHost, url)" . " VALUES (NOW(), '" . $_SERVER["REMOTE_ADDR"] . "','" . addslashes(gethostbyaddr($_SERVER["REMOTE_ADDR"])) . "','" . $pageVisited . "')", $conn ) or die(mysql_error());	
+	}
+
+	/**
+	 * Fetch the user's email address
+	 *
+	 * @param INT
+	 * @return STRING
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	*/
+	function getUserEmail($userID)
+	{
+		global $conn;
+
+		$email = "";
+		
+		$user_rs = mysql_query("SELECT email FROM Users_tbl WHERE userID='" . $userID . "' AND status='ACTIVE'", $conn) or die("Error fetching user email: " . mysql_error());
+
+		if ($user_ar = mysql_fetch_array($user_rs, MYSQL_ASSOC))
+		{
+			$email = $user_ar["email"];
+		}
+
+		return $email;
+	}
+	
+
+	/**
+	 * Verify that a given user is permitted to access a given page
+	 *
+	 * @param STRING
+	 * @param INT
+	 *
+	 * @author John Paul Lee @version 2005
+	 * @author Marina Olhovsky
+	 * @version 3.1 2007-06-04
+	 *
+	 * @return boolean
+	*/
+	// Last modified: June 4/07, Marina - changed SecuredPages_tbl structure today; renamed 'securedPage' column to 'baseURL', and added a 'section' column to represent the menu section this page belongs to. 
+	// Modified selection query accordingly
+	function verifyPermissions($currentPage, $userID)
+	{
+		global $conn;
+
+		$pageInformation_rs = mysql_query("SELECT * FROM `SecuredPages_tbl` WHERE `baseURL`='" . $currentPage . "' AND `status`='ACTIVE'" , $conn) or die(mysql_error());
+		
+		if( !$pageInformation_rs || ( mysql_numrows( $pageInformation_rs ) < 1 ) ) 
+		{
+			return false;
+		}
+		
+		$pageInformation_ar = mysql_fetch_array( $pageInformation_rs, MYSQL_ASSOC );
+		
+// may 24/07	$permissionInformation_rs = mysql_query( "SELECT * FROM `UserPermission_tbl` WHERE `pageID`='" . $pageInformation_ar["pageID"] . "' AND `userID`='" . $userID . "' AND `status`='ACTIVE'" , $conn ) or die(mysql_error());
+
+
+		// May 24/07
+		// get current user's category
+		$currUserCategory = "";
+		
+		$categoryInfo_rs = mysql_query("SELECT * FROM `Users_tbl` WHERE `userID`='" . $userID . "' AND `status`='ACTIVE'", $conn) or die(mysql_error());
+		
+		if ($categoryInfo_ar = mysql_fetch_array($categoryInfo_rs, MYSQL_ASSOC))
+		{
+			$currUserCategory = $categoryInfo_ar["category"];
+		}
+		else
+		{
+			return false;
+		}
+		
+		$category = "";
+		$permissionInformation_rs = mysql_query("SELECT * FROM `UserPermission_tbl` WHERE `pageID`='" . $pageInformation_ar["pageID"] . "' AND `status`='ACTIVE'" , $conn) or die(mysql_error());
+		
+		/* may 24/07
+		if( !$permissionInformation_rs || ( mysql_numrows( $permissionInformation_rs ) < 1 ) ) 
+		{
+			return false;
+		}*/
+		
+		// may 24/07
+		if($permissionInformation_ar = mysql_fetch_array($permissionInformation_rs, MYSQL_ASSOC))
+		{
+			$category = $permissionInformation_ar["categoryID"];
+			
+			if ($category >= $currUserCategory)
+			{
+				return true;
+			}
+		}
+		
+// may 24/07	return true;
+
+		return false;
+	}
+
+	/**
+	 * Verify that a page is accessible to users with the given access level
+	 *
+	 * @param STRING
+	 * @param INT
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @return boolean
+	*/
+	function verifySections($section, $userCategoryID)
+	{
+		global $conn;
+
+		$pageInformation_rs = mysql_query("SELECT * FROM `SecuredPages_tbl` WHERE `section`='" . $section . "' AND `status`='ACTIVE'" , $conn) or die(mysql_error());
+		
+		if (!($pageInformation_ar = mysql_fetch_array($pageInformation_rs, MYSQL_ASSOC)))
+		{
+			return false;
+		}
+		
+		// June 4/07, Marina
+		$permissionInformation_rs = mysql_query("SELECT * FROM UserPermission_tbl WHERE pageID='" . $pageInformation_ar["pageID"] . "' AND status='ACTIVE'" , $conn) or die(mysql_error());
+
+		if ($permissionInformation_ar = mysql_fetch_array($permissionInformation_rs, MYSQL_ASSOC))
+		{
+			$category = $permissionInformation_ar["categoryID"];
+
+			if ($category >= $userCategoryID)
+			{
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+/* Marina, Aug. 25, 2010 - removed, obsolete
+	function verify_User_Type( $usertype )
+	{
+		global $conn;
+		$functionerror = "verify_User_Type(";
+		
+		$usertype_rs = mysql_query("SELECT * FROM `User_Types_tbl` a INNER JOIN `User_Status_tbl` b ON a.`userTypeID`=b.`userTypeID` "
+									. "WHERE b.`userID`='" . $_SESSION["userinfo"]->getUserID() . "' AND a.`name`='" . strtolower( $usertype ) . "' "
+									. "AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'", $conn )
+									or die( "Failure in " . $classerror . $functionerror . "1):" . mysql_error() );
+									
+		if( $usertype_ar = mysql_fetch_array( $usertype_rs, MYSQL_ASSOC ) )
+		{
+			return true;
+		}
+		
+		return false;
+	}
+*/
+
+	/**
+	 * Make sure that the user's login info has been entered in the session
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @return boolean
+	*/
+	function VerifySession()
+	{
+	
+		if (isset($_SESSION["userinfo"]))
+		{
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+
+
+	/**
+	 * Log out - unset session
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	*/
+	function sessionLogout()
+	{
+		session_unset( );
+		session_destroy( );  
+		
+		setcookie( "jpluserid", "", time( )-(60*60*24*10000) );
+		setcookie( "jplcookie", "", time( )-(60*60*24*10000) );
+	
+	}
+	
+
+	/**
+	 * Update user's login record in the database (web tracking)
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @return boolean
+	*/
+	function updateLoginRecord($postVariables)
+	{
+		global $conn;
+	
+		$persistentLogin = "F";
+	
+		if( isset( $postVariables['persistentlogin_field'] ) ) {
+			$persistentLogin = "T";
+		}
+	
+		// Changed So that every time a user logins in, a new login record is created for that user!
+		// Changed Mar 22/05
+		mysql_query( "INSERT INTO `LoginRecord_tbl` (`crec_id`, `userID`, `timestamp`, `user_ip`, `user_host`, `cookieID`, `sessionID`, `persistent`) " 
+						. "VALUES ( '','" . $this->currentUser->getUserID( ) . "',NOW( ),'" . $_SERVER["REMOTE_ADDR"] . "','" 
+						. addslashes( gethostbyaddr( $_SERVER["REMOTE_ADDR"] ) ) . "','" . $this->currentUser->getCookieID( ) . "','" 
+						. session_id( ) . "','" . $persistentLogin . "')", $conn ) or die(mysql_error());
+	
+		//$resultSet = mysql_query( "SELECT * FROM `LoginRecord_tbl` WHERE `userID`='" . $this->currentUser->getUserID( ) . "' AND `user_ip`='" 
+								//	. $_SERVER["REMOTE_ADDR"] . "' AND `status`='ACTIVE'", $conn ) or die(mysql_error());
+		
+		//if(!$resultSet || (mysql_numrows($resultSet) < 1)){
+		//	mysql_query( "INSERT INTO `LoginRecord_tbl` (`crec_id`, `userID`, `timestamp`, `user_ip`, `user_host`, `cookieID`, `sessionID`, `persistent`) " 
+					//	. "VALUES ( '','" . $this->currentUser->getUserID( ) . "',NOW( ),'" . $_SERVER["REMOTE_ADDR"] . "','" 
+					//	. addslashes( gethostbyaddr( $_SERVER["REMOTE_ADDR"] ) ) . "','" . $this->currentUser->getCookieID( ) . "','" 
+					//	. session_id( ) . "','" . $persistentLogin . "')", $conn ) or die(mysql_error());
+		//} else {
+		//	mysql_query( "UPDATE `LoginRecord_tbl` SET `sessionID`='" . session_id( ) . "' WHERE `userID`='" . $this->currentUser->getUserID() 
+						//. "' AND `user_ip`='" . $_SERVER["REMOTE_ADDR"] . "' AND `status`='ACTIVE'", $conn ) or die(mysql_error());
+		//}
+	}
+	
+	
+	/**
+	 * Output user's login info
+	 * @param STRING
+	*/
+	function printLoginInfo($trailer)
+	{
+		global $conn;
+		global $cgi_path;
+		global $hostname;
+
+		if (isset($_SESSION["userinfo"]))
+		{
+			$userInfo_rs = mysql_query( "SELECT * FROM `Users_tbl` WHERE `userID`='" . $this->currentUser->getUserID() . "'", $conn ) or die(mysql_error());
+
+			if( $userInfo_ar = mysql_fetch_array( $userInfo_rs, MYSQL_ASSOC ) )
+			{
+				echo "<FORM name=\"login_form\" METHOD=\"POST\" ACTION=\"" . "index.php"  .  "\" style=\"float:left; background-color:white; padding-left:11px; padding-right:18px; padding-top:7px; white-space:nowrap;\">";
+
+				echo "Welcome <span style=\"color:#FF0000\">" . $userInfo_ar["description"] . "</span>";
+
+				echo "<P>";
+				echo "<INPUT TYPE=\"SUBMIT\" NAME=\"logoutsubmit\" VALUE=\"Logout\" style=\"font-size:12px; elevation:above\">";
+				echo "</P>";
+				echo "</FORM>";
+			}
+		}
+		else
+		{
+			?>
+			<FORM name="logout_form" METHOD=POST ACTION="<?php echo $_SERVER["PHP_SELF"] . $trailer ?>">
+				<P><SPAN class="login">To view additional sections <BR>of the website, please log in:</SPAN>
+
+				<P>Username:<BR/>
+				<INPUT type="text" value="" name="loginusername_field" size="13"><BR/>
+
+				Password:<BR/>
+				<INPUT type="password" value="" name="loginpassword_field" size="13">
+
+				<P>Automatic Login <INPUT type="checkbox" value="" name="persistentlogin_field"></P>
+
+				<INPUT TYPE="submit" NAME="loginsubmit" VALUE="Login" style="font-size:12px; elevation:above">
+			</FORM>
+
+			<!-- June 1, 2010: Automated Password Reset -->
+			<form name="password_reset" METHOD="POST" ACTION="<?php echo $hostname . "User.php?View=6"; ?>">
+				<INPUT type="hidden" name="reset_pw" value="ok">
+			</form>
+
+			<BR><SPAN class="linkShow" onClick="document.password_reset.submit();">Forgot your password?</span>
+			<?php
+		}
+	}
+}
+?>
diff --git a/OpenFreezer/Classes/Member_Class.php b/OpenFreezer/Classes/Member_Class.php
new file mode 100755
index 0000000..1828547
--- /dev/null
+++ b/OpenFreezer/Classes/Member_Class.php
@@ -0,0 +1,367 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package User
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* This class represents users of OpenFreezer (members of biological research laboratories)
+*
+* @author John Paul Lee @version 2005
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+* @package User
+*
+* @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+class Member_Class
+{
+	/**
+	 * @var INT
+	 * Internal database identifier of the user (corresponds to 'userID' column in Users_tbl)
+	*/
+	var $userID;
+
+	/**
+	 * @var STRING
+	 * Username - a User's login alias (one-word lowercase; corresponds to 'username' column in Users_tbl)
+	*/
+	var $username;
+
+	/**
+	 * @var INT
+	 * A number that represents the user's OpenFreezer access level as follows: 1 - Admin, 2 - Creator, 3 - Writer, 4 - Reader.  Corresponds to 'category' column in Users_tbl.
+	*/
+	var $category;	// May 24/07 - the category of the current user - Admin, Creator, Writer, Reader
+
+	/**
+	 * @var INT
+	 * Laboratory identifier (corresponds to 'labID' column in Users_tbl, foreign key references LabInfo_tbl; e.g. '1' - 'Pawson Lab')
+	*/
+	var $labID;	// June 19/07
+
+	/**
+	 * @var STRING
+	 * MD5-encoded user password
+	*/
+	var $password;
+
+	/**
+	 * @var STRING
+	 * Full name of the current user - 'Firstname Lastname' (e.g. 'John Doe'). Corresponds to 'description' column in Users_tbl
+	*/
+	var $description;	// June 27/07, Marina - Full name of the user: 'Firstname Lastname'
+
+	/**
+	 * @var STRING
+	 * User's email address
+	*/
+	var $email;
+
+	/**
+	 * @var STRING
+	 * User's client IP address
+	*/
+	var $ip;
+
+	/**
+	 * @var INT
+	 * Cookie ID
+	*/
+	var $cookieID;
+
+	/**
+	 * @var INT
+	 * User's session ID
+	*/
+	var $sessionID;
+	
+	// the following 2 attributes were added August 7/07 by Marina
+
+	/**
+	 * @var STRING
+	 * User's first name
+	*/
+	var $firstName;
+
+	/**
+	 * @var STRING
+	 * User's last name
+	*/
+	var $lastName;	
+	
+	/**
+	 * @var STRING
+	 * User's position at the lab (optional)
+	*/
+	var $position;		// Aug 8/07, Marina: actual work title
+	
+	/**
+	 * @var Array
+	 * List of user's clone orders.
+	 * @see setOrders(), getOrders()
+	*/
+	// Jan. 23/08
+	var $orders;
+
+	/**
+	 * Constructor. Generates a User representation with the given parameters (user ID is mandatory, rest can be blank)
+	 *
+	 * @param INT
+	 * @param STRING
+	 * @param STRING
+	 * @param STRING
+	 * @param INT
+	 * @param INT
+	 * @param STRING
+	 * @param INT
+	 * @param INT
+	 * @param STRING
+	 *
+	 * @see userID
+	 * @see username
+	 * @see description
+	 * @see email
+	 * @see category
+	 * @see labID
+	 * @see ip
+	 * @see cookieID
+	 * @see sessionID
+	 * @see password
+	*/
+	// Modified August 10/07 - Set default values
+	function Member_Class($newUserID, $newUsername="", $newDescr="", $newEmail="", $newCategory=0, $newLabID=0, $newIP="", $newCookieID=0, $newSessionID=0, $newPassword="")
+	{
+		$this->userID = $newUserID;
+		$this->username = $newUsername;
+		$this->description = $newDescr;		// June 27/07, Marina
+		$this->password = $newPassword;
+		$this->email = $newEmail;
+		$this->ip = $newIP;
+		$this->cookieID = $newCookieID;
+		$this->sessionID = $newSessionID;
+		$this->category = $newCategory;		// May 24/07, Marina
+		$this->labID = $newLabID;		// June 19/07, Marina
+	}
+	
+	/********************************
+	* Access methods
+	*******************************/
+
+	/**
+	 * Return the user's ID
+	 * @return INT
+	 * @see userID
+	*/
+	function getUserID()
+	{
+		return $this->userID;
+	}
+	
+	/**
+	 * Return the user's username
+	 * @return STRING
+	 * @see username
+	*/
+	function getUsername()
+	{
+		return $this->username;
+	}
+	
+	/**
+	 * Return the user's description
+	 * @return STRING
+	 * @see description
+	*/
+	function getDescription()
+	{
+		return $this->description;
+	}
+	
+	/**
+	 * Return the user's password (MD5-encrypted)
+	 * @return STRING
+	 * @see password
+	*/
+	function getPassword()
+	{
+		return $this->password;
+	}
+	
+	/**
+	 * Return the user's email address
+	 * @return STRING
+	 * @see email
+	*/
+	function getEmail()
+	{
+		return $this->email;
+	}
+	
+	/**
+	 * Return the user's client IP address
+	 * @return STRING
+	 * @see ip
+	*/
+	function getIP()
+	{
+		return $this->ip;
+	}
+	
+	/**
+	 * Return the user's cookie ID
+	 * @return INT
+	 * @see cookieID
+	*/
+	function getCookieID()
+	{
+		return $this->cookieID;
+	}
+	
+	/**
+	 * Return the user's session ID
+	 * @return INT
+	 * @see sessionID
+	*/
+	function getSessionID()
+	{
+		return $this->sessionID;
+	}
+	
+	/**
+	 * Return the user's category ID
+	 * @return INT
+	 * @see category
+	*/
+	// May 24/07, Marina
+	function getCategory()
+	{
+		return $this->category;
+	}
+	
+	/**
+	 * Return the user's laboratory ID
+	 * @return INT
+	 * @see labID
+	*/
+	// June 19/07, Marina
+	function getLabID()
+	{
+		return $this->labID;
+	}
+
+	/**
+	 * Return the user's first name
+	 * @return STRING
+	 * @see firstName
+	*/
+	function getFirstName()
+	{
+		return $this->firstName;
+	}
+	
+	/**
+	 * Return the user's last name
+	 * @return STRING
+	 * @see lastName
+	*/
+	function getLastName()
+	{
+		return $this->lastName;
+	}
+
+	/**
+	 * Return the user's position
+	 * @return STRING
+	 * @see position
+	*/
+	function getPosition()
+	{
+		return $this->position;
+	}
+
+	/**
+	 * Return the user's clone requests
+	 * @return ARRAY
+	 * @see orders
+	*/
+	function getOrders()
+	{
+		return $this->orders;
+	}
+	
+	/************************************************
+	* Assignment methods - Added August 7/07, Marina
+	************************************************/
+
+	/**
+	 * Set the user's first name equal to the parameter value
+	 * @param STRING
+	 * @see firstName
+	*/
+	function setFirstName($fName)
+	{
+		$this->firstName = $fName;
+	}
+	
+	/**
+	 * Set the user's last name equal to the parameter value
+	 * @param STRING
+	 * @see lastName
+	*/
+	function setLastName($lName)
+	{
+		$this->lastName = $lName;
+	}
+	
+	/**
+	 * Set the user's position equal to the parameter value
+	 * @param STRING
+	 * @see position
+	*/
+	// August 8/07: New attribute: position
+	function setPosition($pos)
+	{
+		$this->position = $pos;
+	}
+
+	// Jan. 23/08
+	/**
+	 * Assign user's orders
+	 * @param Array
+	 * @see orders
+	*/
+	function setOrders($orders)
+	{
+		$this->orders = $orders;
+	}
+}
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Classes/Order_Class.php b/OpenFreezer/Classes/Order_Class.php
new file mode 100755
index 0000000..f2b6cb9
--- /dev/null
+++ b/OpenFreezer/Classes/Order_Class.php
@@ -0,0 +1,586 @@
+<?php
+
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2010 Pawson Laboratory, All Rights Reserved
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Order
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Include/require statements
+*/
+
+include "Reagent/Reagent_Function_Class.php";
+
+/**
+* This class represents a clone order
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1, 2008-01-23
+* @package Order
+*
+* @copyright	2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+class Order_Class
+{
+	/**
+	 * @var INT
+	 * Internal database ID of the reagent ordered (corresponds to Reagents_tbl.reagentID)
+	*/
+	var $reagentID;
+
+	/**
+	 * @var INT
+	 * Isolate number of the prep being ordered
+	*/
+	var $isolateNum;
+
+	/**
+	 * @var INT
+	 * Internal database ID of the container where the prep is stored
+	*/
+	var $containerID;
+
+	/**
+	 * @var INT
+	 * Row number of the prep in the container
+	*/
+	var $row;
+
+	/**
+	 * @var INT
+	 * Column number of the prep in the container
+	*/
+	var $column;
+
+	/**
+	 * @var INT
+	 * Internal order ID
+	*/
+	var $orderKey;
+
+	/**
+	 * @var STRING
+	 * Name of the reagent ordered
+	*/
+	var $name;
+
+	/**
+	 * @var Array
+	 * List of selectable markers (resistance) of the reagent
+	*/
+	var $resistance;
+
+	/**
+	 * @var STRING
+	 * Restrictions on use of the reagent (yes/no)
+	*/
+	var $restrictions;
+
+	/**
+	 * @var STRING
+	 * Verification of the reagent
+	*/
+	var $verification;
+
+	/**
+	 * @var INT
+	 * Project number of the reagent
+	*/
+	var $project;
+
+	/**
+	 * @var Array
+	 * List of accession numbers for this reagent
+	*/
+	var $accession;
+
+	/**
+	 * @var STRING
+	 * DNA sequence of this reagent
+	*/
+	var $sequence;		// June 2, 2011
+
+	/**
+	 * Constructor
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT
+	 * @param INT
+	 * @param INT
+	 * @param INT
+	 * @param INT
+	*/
+	function Order_Class($rID, $isoNum, $contID, $row, $col)
+	{
+		global $conn;
+
+		$rfunc_obj = new Reagent_Function_Class();
+		$bfunc_obj = new Reagent_Background_Class();	// Feb. 16, 2011
+
+		$this->reagentID = $rID;
+		$this->isolateNum = $isoNum;
+		$this->containerID = $contID;
+		$this->row = $row;
+		$this->column = $col;
+
+		$this->orderKey = $rID . "_" . $isoNum . "_" . $contID . "_" . $row . "_" . $col;
+
+		// Jan. 24/08: Grab the reagent's name , resistance, verification, project and restrictions
+		$namePropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["name"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+
+		$name = $rfunc_obj->getPropertyValue($rID, $namePropID);
+		$this->name = $name;
+
+		$selMarkerPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["selectable marker"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]);
+
+		$resistance = $rfunc_obj->getPropertyValue($rID, $selMarkerPropID);
+		$this->resistance = $resistance;
+
+		$verificationPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["verification"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+
+		$verification = $rfunc_obj->getPropertyValue($rID, $verificationPropID);
+		$this->verification = $verification;
+
+		$projectPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["packet id"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+
+		$project = $rfunc_obj->getPropertyValue($rID, $projectPropID);
+		$this->project = $project;
+
+		$restrPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["restrictions on use"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+
+		$restrictions = $rfunc_obj->getPropertyValue($rID, $restrPropID);
+		$this->restrictions = $restrictions;
+
+		// Feb. 16, 2011: Anne-Claude's request (through Karen): Output accession(s) - make it a list
+		$accessionPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["accession number"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]);
+
+		// Now: accession is a property of Insert, and we're ordering Vectors.  Get the accession from the Insert.
+		$insertID = $bfunc_obj->get_Insert($rID);
+//		echo $insertID;
+
+		$accession = $rfunc_obj->getPropertyValue($insertID, $accessionPropID);
+//		print_r($accession);
+
+		$this->accession = $accession;
+
+		// June 2, 2011: include sequence
+		$seqPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+
+		$rSeq = $rfunc_obj->getSequenceByID($rfunc_obj->getPropertyValue($rID, $seqPropID));
+		$this->sequence = $rSeq;
+	}
+
+	// Assignment methods
+
+	/**
+	 * Set the reagent ID for this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT
+	*/
+	function setReagentID($rID)
+	{
+		$this->reagentID = $rID;
+	}
+
+	/**
+	 * Set the order key
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT
+	*/
+	function setOrderKey($oKey)
+	{
+		$this->orderKey = $oKey;
+	}
+
+	/**
+	 * Set the isolate number for this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT
+	*/
+	function setisolateNum($isoNum)
+	{
+		$this->isolateNum = $isoNum;
+	}
+
+	/**
+	 * Set the container ID
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT
+	*/
+	function setContainerID($contID)
+	{
+		$this->containerID = $contID;
+	}
+
+	/**
+	 * Set the row number
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT
+	*/
+	function setRow($row)
+	{
+		$this->row = $row;
+	}
+
+	/**
+	 * Set the column number
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT
+	*/
+	function setColumn($col)
+	{
+		$this->column = $col;
+	}
+
+	/**
+	 * Set the name of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param STRING
+	*/
+	function setName($name)
+	{
+		$this->name = $name;
+	}
+
+	/**
+	 * Set the 'restrictions on use' value of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param STRING
+	*/
+	function setRestrictions($restr)
+	{
+		$this->restrictions = $restr;
+	}
+
+	/**
+	 * Set the selectable (resistance) marker of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param Array
+	*/
+	function setResistance($res)
+	{
+		$this->resistance = $res;
+	}
+
+	/**
+	 * Set the project number of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT
+	*/
+	function setProject($project)
+	{
+		$this->project = $project;
+	}
+
+	/**
+	 * Set the verification value of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param STRING
+	*/
+	function setVerification($ver)
+	{
+		$this->verification = $ver;
+	}
+
+	
+	// Feb. 16, 2011
+	/**
+	 * Set the accession number(s) of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.2
+	 *
+	 * @param Array
+	*/
+	function setAccession($accession)
+	{
+		$this->accession = $accession;
+	}
+
+
+	// June 2, 2011
+	/**
+	 * Set the sequence of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.3
+	 *
+	 * @param Array
+	*/
+	function setSequence($seq)
+	{
+		$this->sequence = $seq;
+	}
+
+
+	// Access methods
+
+	/**
+	 * Return the ID of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return INT
+	*/
+	function getReagentID()
+	{
+		return $this->reagentID;
+	}
+
+	/**
+	 * Return the isoalte number of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return INT
+	*/
+	function getIsolateNumber()
+	{
+		return $this->isolateNum;
+	}
+
+	/**
+	 * Return the container ID
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return INT
+	*/
+	function getContainerID()
+	{
+		return $this->containerID;
+	}
+
+	/**
+	 * Return the row number
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return INT
+	*/
+	function getRow()
+	{
+		return $this->row;
+	}
+
+	/**
+	 * Return the column number
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return INT
+	*/
+	function getColumn()
+	{
+		return $this->column;
+	}
+
+	/**
+	 * Return the order key
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return INT
+	*/
+	function getOrderKey()
+	{
+		$this->orderKey = $this->reagentID . "_" . $this->isolateNum . "_" . $this->containerID . "_" . $this->row . "_" . $this->column;
+
+		return $this->orderKey;
+	}
+
+	/**
+	 * Return the name of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return STRING
+	*/
+	function getName()
+	{
+		return $this->name;
+	}
+
+	/**
+	 * Return the restrictions on use of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return STRIGN
+	*/
+	function getRestrictions()
+	{
+		return $this->restrictions;
+	}
+
+	/**
+	 * Return the resistance markers of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return Array
+	*/
+	function getResistance()
+	{
+		return $this->resistance;
+	}
+
+	/**
+	 * Return the project ID of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return INT
+	*/
+	function getProject()
+	{
+		return $this->project;
+	}
+
+	/**
+	 * Return the verification vlaue of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return STRING
+	*/
+	function getVerification()
+	{
+		return $this->verification;
+	}
+
+	/**
+	 * Return the accession number(s) of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.2
+	 *
+	 * @return Array
+	*/
+	function getAccession()
+	{
+		return $this->accession;
+	}
+
+	
+	// June 2, 2011
+	/**
+	 * Return the sequence of the reagent in this order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.3
+	 *
+	 * @return Array
+	*/
+	function getSequence()
+	{
+		return $this->sequence;
+	}
+
+	/**
+	 * Remove certain orders from a list of user's clone requests
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param Array list of order keys (INT) to remove
+	*/
+	function removeFromOrder($orderKeys)
+	{
+		$userOrders = $_SESSION["userinfo"]->getOrders();
+		$remainingOrders = array();
+
+		if (sizeof($orderKeys) > 0)
+		{
+			foreach ($orderKeys as $x => $orderKey)
+			{
+				foreach ($userOrders as $key => $order)
+				{
+					$oKey = $order->getOrderKey();
+		
+					if (strcasecmp($orderKey, $oKey) == 0)
+					{
+						unset($userOrders[$key]);
+						$remainingOrders = $userOrders;
+					}
+				}
+			}
+
+//			print_r($remainingOrders);
+	
+			$_SESSION["userinfo"]->setOrders($remainingOrders);
+		}
+	}
+}
+?>
diff --git a/OpenFreezer/Classes/Project_Class.php b/OpenFreezer/Classes/Project_Class.php
new file mode 100755
index 0000000..7fdbb1a
--- /dev/null
+++ b/OpenFreezer/Classes/Project_Class.php
@@ -0,0 +1,199 @@
+<?php
+/**
+* Classes in this package represent projects (historically called 'packets') in OpenFreezer.  Projects are used to group reagents that fit a common theme (e.g. "SH2 domains", "Kinase Project", or "John Doe's reagents"
+*
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Project
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+ * This class represents a project (historically called 'packet') in OpenFreezer.  Projects are used to group reagents that fit a common theme (e.g. "SH2 domains", "Kinase Project", or "John Doe's reagents"
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Project
+ *
+ * @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ */
+class Project
+{
+	/**
+	 * @var INT
+	 * Numeic identifier of this project
+	*/
+	var $packetID;
+
+	/**
+	 * @var STRING
+	 * Name of this project
+	*/
+	var $packetName;
+
+	/**
+	 * @var Member_Class
+	 * Person who owns this project
+	*/
+	var $packetOwner;	// Member instance
+
+	/**
+	 * @var STRING
+	 * Description of this project
+	*/
+	var $packetDescription;
+
+	/**
+	 * @var boolean
+	 * Is this project public?  A project can be public, namely reagents associated with this project are accessible by all users of OpenFreezer; alternatively, a project can be private, in which case only users who are given viewing privileges may view reagents in this project.
+	*/
+	var $isPublic;
+	
+	/**
+	 * Constructor.  Project ID must be set, the rest of values may be blank.
+	 *
+	 * @param INT
+	 * @param STRING
+	 * @param Member_Class
+	 * @param STRING
+	 * @param boolean
+	 *
+	 * @see packetID
+	 * @see packetName
+	 * @see packetOwner
+	 * @see packetDescription
+	 * @see isPublic
+	*/
+	// Project ID must be set, the rest of values may be blank
+	function Project($pID, $pName="", $pOwner=Null, $pDesc="", $public=true)
+	{
+		$this->packetID = $pID;
+		$this->packetName = $pName;
+		$this->packetOwner = $pOwner;
+		$this->packetDescription = $pDesc;
+		$this->isPublic = $public;
+	}
+	
+
+	/***********************
+	* Assignment methods
+	***********************/
+
+	/**
+	 * Set the name of this project equal to the argument value.
+	 * @param STRING
+	 * @see packetName
+	*/
+	function setName($pName)
+	{
+		$this->packetName = $pName;
+	}
+	
+	/**
+	 * Set the owner of this project equal to the argument value.
+	 * @param Member_Class
+	 * @see packetOwner
+	*/
+	function setOwner($owner)
+	{
+		$this->packetOwner = $owner;
+	}
+	
+	/**
+	 * Set the description of this project equal to the argument value.
+	 * @param STRING
+	 * @see packetDescription
+	*/
+	function setDescription($desc)
+	{
+		$this->$packetDescription = $desc;
+	}
+	
+	/**
+	 * Set the value of $isPublic variable to the argument value ($public=TRUE makes this project public; $public=FALSE makes the project private)
+	 * @param boolean
+	 * @see isPublic
+	*/
+	function setPublic($public)
+	{
+		$this->isPublic = $public;
+	}
+	
+	/***********************
+	* Access methods
+	***********************/
+
+	/**
+	 * Return the ID of this project
+	 * @return INT
+	 * @see packetID
+	*/
+	function getPacketID()
+	{
+		return $this->packetID;
+	}
+	
+	/**
+	 * Return the name of this project
+	 * @return STRING
+	 * @see packetName
+	*/
+	function getName()
+	{
+		return $this->packetName;
+	}
+	
+	/**
+	 * Return the owner of this project
+	 * @return Member_Class
+	 * @see packetOwner
+	*/
+	function getOwner()
+	{
+		return $this->packetOwner;
+	}
+	
+	/**
+	 * Return the description of this project
+	 * @return STRING
+	 * @see packetDescription
+	*/
+	function getDescription()
+	{
+		return $this->packetDescription;
+	}
+	
+	/**
+	 * Return TRUE or FALSE, depending on whether this project is public or private.
+	 * @return boolean
+	 * @see isPublic
+	*/
+	function isPublic()
+	{
+		return $this->isPublic;
+	}
+}
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Classes/Reagent_Class.php b/OpenFreezer/Classes/Reagent_Class.php
new file mode 100755
index 0000000..a052098
--- /dev/null
+++ b/OpenFreezer/Classes/Reagent_Class.php
@@ -0,0 +1,651 @@
+<?php
+/**
+* Classes in this package represent reagent entities in OpenFreezer
+*
+* Written October 20, 2008, by Marina Olhovsky
+*
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Reagent
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* This class represents a reagent entity in OpenFreezer
+*
+* Written October 20, 2008, by Marina Olhovsky
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+* @package Reagent
+*
+* @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+class Reagent_Class
+{
+	/******************************************************
+	* Instance variables - Basic properties of the reagent
+	******************************************************/
+
+	/**
+	* @var MIXED
+	* OpenFreezer ID of the reagent - a one-letter prefix followed by a numeric identifier (e.g. V123)
+	*/
+	var $rID = "";
+
+	/**
+	* @var STRING
+	* Type of the reagent (e.g. 'Vector', 'Protein', 'Antibody', etc.)
+	*/
+	var $rType = "";	// one of Vector, Insert, Oligo, Cell Line (more if added later)
+
+	/**
+	* @var STRING
+	* Name of the reagent, e.g. 'MAP Kinase'
+	*/
+	var $rName = "";
+
+	/**
+	* @var STRING
+	* Status of the reagent, e.g. 'Completed', 'Not Available', etc.
+	*/
+	var $rStatus = "";
+
+	/**
+	* @var INT
+	* Numeric ID of this reagent's project
+	*/
+	var $projectID = 0;
+
+	/**
+	* @var STRING
+	* Experimental verification of the reagent, e.g. 'sequence verified', 'expression verified', etc.
+	*/
+	var $rVerification = "";
+
+	/**
+	* @var STRING
+	* (Functional) description of the reagent
+	*/
+	var $funcDescr = "";
+
+	/**
+	* @var STRING
+	* (Experimental) comments for this reagent
+	*/
+	var $expComments = "";
+
+	/**
+	* @var STRING
+	* Verification comments for this reagent
+	*/
+	var $verComments = "";
+
+	/**
+	* @var STRING
+	* Reagent source, e.g. 'in-house', or 'Invitrogen'
+	*/
+	var $rSource = "";
+
+	/**
+	* @var STRING
+	* Origin species of this reagent (differs from antibody reactivity species)
+	*/
+	var $rSpecies = "";
+
+	/**
+	* @var BOOLEAN
+	* Are there any restrictions on the use of this reagent for future experiments?
+	*/
+	var $hasRestrictions = false;
+
+	/**
+	* @var STRING
+	* DNA, RNA or Protein sequence of this reagent, if applicable.  Represented by a string of allowable characters (ACGTN for DNA, ACGU for RNA, and amino acids for protein)
+	*/
+	var $rSequence = "";
+	
+	/**
+	* @var Array
+	* List of SeqFeature objects
+	*/
+	var $rFeatures = array();	// list of SeqFeature objects
+
+	/**
+	* Default constructor. Generates a Reagent instance based on the OpenFreezer ID of the reagent
+	* @param STRING OpenFreezer ID of this reagent (e.g. 'V123')
+	*/
+	function Reagent_Class($rID)
+	{
+		$this->rID = $rID;
+	}
+
+	/******************************************************************************
+	* Assignment methods
+	* (simply set the value of the given instance variable to the parameter value)
+	******************************************************************************/
+
+	/**
+	 * Set the name of this reagent equal to the parameter value
+	 * @param STRING
+	 * @see rName
+	*/
+	function setReagentName($rName)
+	{
+		$this->rName = $rName;
+	}
+
+
+	/**
+	 * Set the status of this reagent equal to the parameter value
+	 * @param STRING
+	 * @see rStatus
+	*/
+	function setReagentStatus($status)
+	{
+		$this->rStatus = $status;
+	}
+
+
+	/**
+	 * Set the project number of this reagent equal to the parameter value
+	 * @param INT
+	 * @see projectID
+	*/
+	function setProjectID($pID)
+	{
+		$this->projectID = $pID;
+	}
+
+
+	/**
+	 * Set the verification of this reagent equal to the parameter value
+	 * @param STRING
+	 * @see rVerification
+	*/
+	function setReagentVerification($verif)
+	{
+		$this->rVerification = $verif;
+	}
+
+
+	/**
+	 * Set the description of this reagent equal to the parameter value
+	 * @param STRING
+	 * @see funcDescr
+	*/
+	function setFunctionalDescription($fDescr)
+	{
+		$this->funcDescr = $fDescr;
+	}
+
+
+	/**
+	 * Set the experimental comments of this reagent equal to the parameter value
+	 * @param STRING
+	 * @see expComments
+	*/
+	function setExperimentalComments($expComms)
+	{
+		$this->expComments = $expComms;
+	}
+
+
+	/**
+	 * Set the verification comments of this reagent equal to the parameter value
+	 * @param STRING
+	 * @see verComments
+	*/
+	function setVerificationComments($verComms)
+	{
+		$this->verComments = $verComms;
+	}
+
+
+	/**
+	 * Set the reagent source equal to the parameter value
+	 * @param STRING
+	 * @see rSource
+	*/
+	function setReagentSource($rSrc)
+	{
+		$this->rSource = $rSrc;
+	}
+
+
+	/**
+	 * Set the sequence of this reagent equal to the parameter value
+	 * @param STRING
+	 * @see rSequence
+	*/
+	function setReagentSequence($rSeq)
+	{
+		$this->rSequence = $rSeq;
+	}
+
+
+	/**
+	 * Set the species of this reagent equal to the parameter value
+	 * @param STRING
+	 * @see rSpecies
+	*/
+	function setReagentSpecies($species)
+	{
+		$this->rSpecies = $species;
+	}
+
+
+	/**
+	 * Set 'restrictions on use' for this reagent equal to true
+	 * @param boolean false
+	 * @see hasRestrictions
+	*/
+	function setRestrictionsOnUse()
+	{
+		$this->hasRestrictions = true;
+	}
+
+	/**
+	 * Set 'restrictions on use' for this reagent equal to false
+	 * @param boolean false
+	 * @see hasRestrictions
+	*/
+	function removeRestrictionsOnUse()
+	{
+		$this->hasRestrictions = false;
+	}
+
+	/**
+	 * Set the features of this reagent equal to parameter array values
+	 * @param Array
+	 * @see rFeatures
+	*/
+	function setReagentFeatures($features)
+	{
+		$this->rFeatures = $features;
+	}
+
+	/************************************************
+	* Access methods
+	************************************************/
+
+	/**
+	 * Return the value of the 'type' variable assigned to this reagent
+	 * @return STRING
+	 * @see rType
+	*/
+	function getReagentType()
+	{
+		return $this->rType;
+	}
+
+	/**
+	 * Return the name of this reagent
+	 * @return STRING
+	 * @see rName
+	*/
+	function getReagentName()
+	{
+		return $this->rName;
+	}
+
+	/**
+	 * Return the status of this reagent
+	 * @return STRING
+	 * @see rStatus
+	*/
+	function getReagentStatus()
+	{
+		return $this->rStatus;
+	}
+
+	/**
+	 * Return the project number of this reagent
+	 * @return INT
+	 * @see projectID
+	*/
+	function getProjectID()
+	{
+		return $this->projectID;
+	}
+
+	/**
+	 * Return the description of this reagent
+	 * @return STRING
+	 * @see funcDescr
+	*/
+	function getFunctionalDescription()
+	{
+		return $this->funcDescr;
+	}
+
+	/**
+	 * Return the verification value of this reagent
+	 * @return STRING
+	 * @see rVerification
+	*/
+	function getVerification()
+	{
+		return $this->rVerification;
+	}
+
+	/**
+	 * Return the experimental comments of this reagent
+	 * @return STRING
+	*/
+	function getExperimentalComments()
+	{
+		return $this->expComments;
+	}
+
+	/**
+	 * Return the verification comments of this reagent
+	 * @return STRING
+	 * @see verComments
+	*/
+	function getVerificationComments()
+	{
+		return $this->verComments;
+	}
+
+	/**
+	 * Return the value of 'reagent source' variable
+	 * @return STRING
+	 * @see rSource
+	*/
+	function getReagentSource()
+	{
+		return $this->rSource;
+	}
+
+	/**
+	 * Return the sequence of this reagent
+	 * @return STRING
+	 * @see rSequence
+	*/
+	function getReagentSequence()
+	{
+		return $this->rSequence;
+	}
+
+	/**
+	 * Return the restrictions on use value of this reagent (true or false)
+	 * @return BOOLEAN
+	 * @see hasRestrictions
+	*/
+	function hasRestrictionsOnUse()
+	{
+		return $this->hasRestrictions;
+	}
+
+	/**
+	 * Return an array of features of this reagent
+	 * @return Array
+	 * @see rFeatures
+	*/
+	function getReagentFeatures()
+	{
+		return $this->rFeatures;
+	}
+}
+
+/**
+* This class represents reagents of type Vector in OpenFreezer
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+* @package Reagent
+*
+* @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*/
+class Vector_Class extends Reagent_Class
+{
+	/**
+	 * @var STRING
+	 * Vector type (e.g. Gateway Entry Clone, Parent Destination Vector, etc.)
+	*/
+	var $vectorType;
+
+	/**
+	 * @var INT
+	 * Novel, Recombination, Non-Recombination (INT corresponds to ATypeID column in AssocType_tbl)
+	*/
+	var $cloningMethod;	// Novel, Recombination, Non-Recombination (INT corresponds to ATypeID)
+
+
+	/**
+	 * Default constructor. Generates a Vector object (set $rType=Vector and cloingMethod=1, defaulting all Vectors to Novel)
+	*/
+	function Vector_Class()
+	{
+		$this->rType = "Vector";
+		$this->vectorType = "";
+		$this->cloningMethod = 1;	// default all to Novel
+	}
+
+	/*******************************************************************************************
+	* Assignment methods (set the value of the given instance variable to the parameter value)
+	*******************************************************************************************/
+
+	/**
+	 * Set the cloning method of this vector equal to the parameter value
+	 * @param STRING
+	 * @see cloningMethod
+	*/
+	function setCloningMethod($cm)
+	{
+		$this->cloningMethod = $cm;
+	}
+
+	/**
+	 * Set the vector type of this vector equal to the parameter value
+	 * @param STRING
+	 * @see vType
+	*/
+	function setVectorType($vType)
+	{
+		$this->vType = $vType;
+	}
+
+	/**************************************************************
+	* Access methods (retrieve the value of the internal variable)
+	**************************************************************/
+
+	/**
+	 * Returns the cloning (preparation) method of this vector - an INT corresponding to ATypeID column value in AssocType_tbl, indicating whether the vector is Novel (no parents), non-recombination (contains an Insert in its backbone plasmid), or prepared by LoxP recombination
+	 * @return INT
+	 * @see cloningMethod
+	*/
+	function getCloningMethod()
+	{
+		return $this->cloningMethod;
+	}
+
+	/**
+	 * Returns the vector's type as a STRING
+	 * @return STRING
+	 * @see vType
+	*/
+	function getVectorType()
+	{
+		return $this->vType;
+	}
+}
+
+
+/**
+* This class represents reagents of type Insert in OpenFreezer
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+* @package Reagent
+*
+* @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*/
+class Insert_Class extends Reagent_Class
+{
+	/**
+	 * @var STRING
+	 * Translated amino acid sequence - property of Insert
+	*/
+	var $protSequence;		// translated peptide sequence - property of Insert
+
+	/**
+	 * @var STRING
+	 * ORF, cDNA with UTRs, ORF subsequence, Non-coding
+	*/
+	var $typeOfInsert;
+
+	/**
+	 * @var STRING
+	 * Indicates whether the Insert's DNA sequence contains an ATG and a stop codon (e.g. 'Open with ATG' means the sequence contains an ATG, indicating start of translation, but no stop codon; conversely, 'Closed, no ATG' means the sequence contains a stop codon and no ATG).  This value is required for correctly translating the Insert sequence into protein.
+	*/
+	var $openClosed;
+
+	/**
+	 * Default constructor. Generates an Insert object (set $rType=Insert and assigns default blank values to the rest of the variables)
+	*/
+	function Insert_Class()
+	{
+		$this->rType = "Insert";
+		$this->protSequence = "";
+		$this->typeOfInsert = "";
+		$this->openClosed = "";
+	}
+
+
+	/******************************
+	* Assignment methods
+	******************************/
+
+	/**
+	 * Set the protein sequence of this insert equal to the parameter value
+	 * @param STRING
+	 * @see protSequence
+	*/
+	function setProteinSequence($pSeq)
+	{
+		$this->protSequence = $pSeq;
+	}
+
+	/**
+	 * Set the type of insert equal to the input argument
+	 * @param STRING
+	 * @see typeOfInsert
+	*/
+	function setTypeOfInsert($iType)
+	{
+		$this->typeOfInsert = $iType;
+	}
+
+	/**
+	 * Set the open/closed value equal to the input argument
+	 * @param STRING
+	 * @see openClosed
+	*/
+	function setOpenClosed($oc)
+	{
+		$this->openClosed = $oc;
+	}
+
+	/**************************************************************************
+	* Access methods (return the value of the corresponding instance variable)
+	**************************************************************************/
+
+	/**
+	 * Return the protein sequence of this Insert
+	 * @return STRING
+	 * @see protSequence
+	*/
+	function getProteinSequence()
+	{
+		return $this->protSequence;
+	}
+
+	/**
+	 * Return the Type of Insert value
+	 * @return STRING
+	 * @see typeOfInsert
+	*/
+	function getTypeOfInsert()
+	{
+		return $this->typeOfInsert;
+	}
+	
+	/**
+	 * Return the Open/Closed value of this Insert
+	 * @return STRING
+	 * @see openClosed
+	*/
+	function getOpenClosed()
+	{
+		return $this->openClosed;
+	}
+}
+
+
+/**
+* This class represents reagents of type Oligo in OpenFreezer
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+* @package Reagent
+*
+* @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*/
+class Oligo_Class extends Reagent_Class
+{
+	/**
+	* Default constructor. Generates an Oligo object (set $rType=Oligo)
+	*/
+	function Oligo_Class()
+	{
+// 		$this->rType = "Oligo";
+	}
+}
+
+
+/**
+* This class represents reagents of type Cell Line in OpenFreezer
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+* @package Reagent
+*
+* @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*/
+class CellLine_Class extends Reagent_Class
+{
+	/**
+	* Default constructor. Generates a Cell Line object (set $rType=CellLine)
+	*/
+	function CellLine_Class()
+	{
+		$this->rType = "Cell Line";
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Classes/SeqFeature.php b/OpenFreezer/Classes/SeqFeature.php
new file mode 100755
index 0000000..39424ef
--- /dev/null
+++ b/OpenFreezer/Classes/SeqFeature.php
@@ -0,0 +1,600 @@
+<?php
+/**
+* This module represents properties (attributes) of reagents in OpenFreezer.  Properties can either be 'basic' properties that apply to the Reagent as a whole (e.g. name, type), or they can be Sequence Features, which characterize specific segments of the reagent's sequence.
+*
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Sequence
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+ * This class represents basic properties of reagents in OpenFreezer.
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Sequence
+ *
+ * @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+class ReagentProperty
+{
+	/**
+	 * Instance variables - Basic attributes of a Property object
+	*/
+
+	/**
+	 * @var STRING
+	 * Property name (corresponds to 'propertyName' column in ReagentPropType_tbl, always in lowercase, e.g. 'cloning method')
+	 * @see setPropertyName(), getPropertyName()
+	*/
+	var $pName;	// e.g. name, status, etc.
+
+	/**
+	 * @var STRING
+	 * Database alias of the property (corresponds to 'propertyAlias' column in ReagentPropType_tbl, a one-word lowercase alias for propertyName, with whitespaces in multi-word names replaced by underscores, e.g. 'cloning_method')
+	 * @see setPropertyAlias(), getPropertyAlias()
+	*/
+	var $pAlias;
+
+	/**
+	 * @var STRING
+	 * Full-length description of the property (corresponds to 'propertyDesc' column in ReagentPropType_tbl, preserves the original case in which the property's name was entered, e.g. 'Cloning Method')
+	 * @see setPropertyDescription(), getPropertyDescription()
+	*/
+	var $pDescr;
+
+	/**
+	 * @var STRING
+	 * Name of this property's category in the context of a given reagent (e.g. 'Name' is always under 'General Properties' for all reagent types, whereas 'Origin' might be a classifier for Insert and a DNA Sequence Feature for Vector)
+	 * @see setPropertyCategory(), getPropertyCategory()
+	*/
+	var $pCategory;
+
+	/**
+	 * @var mixed
+	 * Actual value of this property; type varies ('status' is a string and project ID is an INT).  Corresponds to 'propertyValue' column in ReagentPropType_tbl.
+	 * @see setPropertyValue(), getPropertyValue()
+	*/
+	var $pValue;	// actual feature value, e.g. SH2, 'In Progress', etc.
+
+	/**
+	 * @var INT
+	 * Internal database identifier of this property, corresponds to 'propertyID' column in ReagentPropType_tbl.
+	 * @see setPropertyID(), getPropertyID()
+	*/
+	var $propID;	// Nov. 3/09
+
+	/**
+	 * @var boolean
+	 * A boolean value to indicate whether this property is a sequence feature.  Set to 'false' in this class and set to 'true' in descendant SequenceFeature class.  Sequence features are used to describe specific DNA/RNA/Protein sequence segments and always have 'startPos', 'endPos' and 'direction' values.
+	*/
+	var $isFeature = false;
+
+
+	/***********************************************
+	* Methods
+	************************************************/
+
+	/**
+	 * Default constructor. Generates a ReagentProperty instance with variable values set to function parameters.
+	 *
+	 * @param STRING Name of the property in lowercase (e.g. 'selectable marker' - corresponds to propertyName column in ReagentPropertyType_tbl)
+	 * @param STRING Internal database alias of the property (one word lowercase, whitespace replaced with underscore, e.g. 'selectable_marker' - corresponds to propertyAlias column in ReagentPropertyType_tbl)
+	 * @param STRING Full property name (e.g. 'Selectable Marker' - corresponds to propertyDesc column in ReagentPropertyType_tbl)
+	 * @param STRING Category of this property in the current context (e.g. 'Classifiers')
+	 * @param MIXED Actual property value (e.g. 'Ampicillin', corresponds to propertyValue column in ReagentPropList_tbl) - default null
+	 *
+	 * @see pName
+	 * @see pAlias
+	 * @see pDescr
+	 * @see pCategory
+	 * @see pValue
+	*/
+	function ReagentProperty($pName, $pAlias, $pDescr, $pCategory, $pValue=null)
+	{
+		$this->pName = $pName;
+		$this->pAlias = $pAlias;
+		$this->pDescr = $pDescr;
+		$this->pCategory = $pCategory;
+		$this->pValue = $pValue;
+	}
+
+
+	/**
+	 * Is the property a sequence feature?  TRUE for objects of type SeqFeature; FALSE for all other ReagentProperty type objects
+	 * @return boolean
+	 * @see SeqFeature
+	*/
+	function isSequenceFeature()
+	{
+		return $this->isFeature;
+	}
+
+
+	/***********************************************
+	* Assignment methods
+	***********************************************/
+
+	/**
+	 * Set the property ID of this property equal to $pID
+	 * @param INT Corresponds to propertyID column in ReagentPropType_tbl
+	 * @see propID
+	*/
+	function setPropertyID($pID)
+	{
+		$this->propID = $pID;
+	}
+
+	/**
+	 * Set the name of this property equal to $pName
+	 * @param STRING Corresponds to propertyName column in ReagentPropType_tbl
+	*/
+	function setPropertyName($pName)
+	{
+		$this->pName = $pName;
+	}
+
+	/**
+	 * Set the value of this property equal to $pValue
+	 * @param MIXED Corresponds to propertyValue column in ReagentPropType_tbl
+	 * @see pValue
+	*/
+	function setPropertyValue($pValue)
+	{
+		$this->pValue = $pValue;
+	}
+
+	/**
+	 * Set the alias of this property equal to $pAlias
+	 * @param STRING Corresponds to propertyAlias column in ReagentPropType_tbl (most often a one-word lowercase string, with whitespaces replaced by underscores "_")
+	 * @see pAlias
+	*/
+	function setPropertyAlias($pAlias)
+	{
+		$this->pAlias = $pAlias;
+	}
+
+	/**
+	 * Set the description of this property equal to $pDescr
+	 * @param STRING Corresponds to propertyDesc column in ReagentPropType_tbl
+	 * @see pDescr
+	*/
+	function setPropertyDescription($pDescr)
+	{
+		$this->pDescr = $pDescr;
+	}
+
+	/**
+	 * Set the category of this property equal to $pCategory
+	 * @param STRING Corresponds to propertyCategory column in ReagentPropType_tbl
+	 * @see pCategory
+	*/
+	function setPropertyCategory($pCategory)
+	{
+		$this->pCategory = $pCategory;
+	}
+
+
+	/********************************
+	* Access Methods
+	********************************/
+
+	/**
+	 * Return the name of this property
+	 * @return STRING
+	 * @see pName
+	 * @throws Exception if this is a sequence feature as opposed to simple property (SequenceFeature type objects do not have a pName attribute; they have a featureType attribute instead)
+	*/
+	function getPropertyName()
+	{
+		if (!$this->pName || strlen($this->pName) == 0)
+			throw new Exception("Wrong reagent property type");
+
+		return $this->pName;
+	}
+
+	/**
+	* Return the alias of this property
+	* @return STRING
+	* @see pAlias
+	*/
+	function getPropertyAlias()
+	{
+		return $this->pAlias;
+	}
+	
+	/**
+	* Return the description of this property
+	* @return STRING
+	* @see pDescr
+	*/
+	function getPropertyDescription()
+	{
+		return $this->pDescr;
+	}
+
+	/**
+	* Return the category of this property
+	* @return STRING
+	* @see pCategory
+	*/
+	function getPropertyCategory()
+	{
+		return $this->pCategory;
+	}
+
+	/**
+	* Return the value of this property
+	* @return MIXED
+	* @see pValue
+	*/
+	function getPropertyValue()
+	{
+		return $this->pValue;
+	}
+
+	/**
+	* Return the ID of this property
+	* @return MIXED
+	* @see propID
+	*/
+	function getPropertyID()
+	{
+		return $this->propID;
+	}
+}
+
+/**
+* This class represents reagent sequence features (e.g. tag type, promoter, selectable marker, origin of replication, etc.)
+*
+* The main characteristic of a feature is the 1-m type/vaue relationship (i.e. a feature can have multiple values; a reagent can have a BAP tag on its sequence at pos. 23-65 on the N-terminus and a reverse oriented His tag at the C-terminus, at positions 345-386)
+*
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1 2008-05-20
+* @package Sequence
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3 
+*/
+class SeqFeature extends ReagentProperty
+{
+	/*************************************
+	* Instance variables
+	*************************************/
+
+	/**
+	 * @var STRING
+	 * Name of the feature, e.g. promoter, tag type, origin, etc. Corresponds to 'propertyName' column in ReagentPropType_tbl.
+	*/
+	var $fType = "";		// e.g. promoter, tag type, origin, etc.
+
+	/**
+	 * @var STRING
+	 * Actual feature value, e.g. BGH, CMV, Blasticidin, etc. Corresponds to 'propertyValue' column in ReagentPropList_tbl.
+	*/
+	var $fValue = "";		// actual feature value, e.g. BGH, CMV, Blasticidin, etc.
+
+	/**
+	 * @var INT
+	 * Start position of the feature on the DNA/RNA/Protein sequence of the reagent. Corresponds to 'startPos' column in ReagentPropList_tbl.
+	*/
+	var $fStart = 0;
+
+	/**
+	 * @var INT
+	 * End position of the feature on the DNA/RNA/Protein sequence of the reagent. Corresponds to 'endPos' column in ReagentPropList_tbl.
+	*/
+	var $fEnd = 0;
+
+	/**
+	 * @var STRING
+	 * Orientation of the feature on the DNA/RNA/Protein sequence - either 'forward' or 'reverse'. Corresponds to 'direction' column in ReagentPropList_tbl.
+	*/
+	var $fDir = "forward";		// orientation: forward or reverse
+
+	/**
+	 * @var STRING
+	 * Actual feature descriptor value. Only applies to selected features - currently only applies to features of type 'tag' and 'promoter' (the descriptor for tag type is 'tag position', and the descriptor for promoter is 'expression system') E.g., if $fType = 'tag', $fDescr may be 'Internal', 'N-terminus', 'C-terminus' or 'None'.  If $fType is 'promoter', $fDescr may assume any of the Expression System values defined in OpenFreezer, such as 'Mammalian', 'Bacteria', and more.  Corresponds  [...]
+	 * @see getFeatureDescriptorType(), hasFeatureDescriptor()
+	*/
+	var $fDescr = null;		// descriptor; only applies to selected features - currently only applies to tag type and promoter (the descriptor for tag type is 'tag position', and the descriptor for promoter is 'expression system')
+
+	/**
+	 * @var STRING
+	 * Actual full-length description of the feature, e.g. "cDNA" or "5' Cloning Site"
+	*/
+	var $description = "";
+
+	/**
+	 * @var boolean
+	 * Always set to TRUE for all objects of this class
+	*/
+	var $isFeature = true;
+
+	/**
+	 * @var INT
+	 * Database ID of the feature (corresponds to propertyID column in ReagentPropType_tbl)
+	*/
+	var $featureID = -1;		// Nov 3/09
+
+
+	/*************************************
+	* Methods
+	*************************************/
+
+	/**
+	 * Default constructor. Generates a SeqFeature object with variable values set to function parameters.
+	 *
+	 * @param STRING Lowercase name of the feature, e.g. 'cleavage site' - corresponds to 'propertyName' column in ReagentPropType_tbl
+	 * @param MIXED Actual value of the feature, e.g. 'enterokinase' - corresponds to 'propertyValue' column in ReagentPropList_tbl
+	 * @param INT Start position of the feature on the sequence (on the 5' strand for DNA sequences) - corresponds to 'endPos' column in ReagentPropList_tbl
+	 * @param INT Start position of the feature on the sequence (on the 5' strand for DNA sequences) - corresponds to 'startPos' column in ReagentPropList_tbl
+	 * @param STRING Direction (orientation) of the feature on the sequence (on the 5' strand for DNA sequences) - either 'forward' or 'reverse' - corresponds to 'direction' column in ReagentPropList_tbl
+	 * @param STRING Descriptor value (only applies to selected features; 'expression system' for Promoter and 'tag position' for Tag) - e.g. 'Mammalian' (expression system) or 'Internal' (tag position) - corresponds to 'descriptor' column in ReagentPropList_tbl
+	 * @param STRING Full name of the feature in the correct lettercase (e.g. 'Cleavage Site' - corresponds to propertyDesc column in ReagentPropType_tbl)
+	 *
+	 * @see fType
+	 * @see fValue
+	 * @see fStart
+	 * @see fEnd
+	 * @see fDir
+	 * @see fDescr
+	 * @see description
+	*/
+	function SeqFeature($fType="", $fValue="", $fStart=0, $fEnd=0, $fDir="", $fDescr="", $description="")
+	{
+		$this->fType = $fType;
+		$this->fValue = $fValue;
+		$this->fStart = $fStart;
+		$this->fEnd = $fEnd;
+		$this->fDir = $fDir;
+		$this->fDescr = $fDescr;
+		$this->description = $description;
+	}
+
+	/**
+	 * Is this property a sequence feature?
+	 * @return boolean Always TRUE for all objects of this class
+	*/
+	function isSequenceFeature()
+	{
+		return $this->isFeature;
+	}
+
+
+	/********************************
+	 * Assignment Methods
+	********************************/
+
+	/**
+	 * Set the type of this feature equal to $ft (e.g. 'Tag', 'Promoter', 'Selectable Marker', etc.)
+	 * @param STRING
+	 * @see fType
+	*/
+	function setFeatureType($ft)
+	{
+		$this->fType = $ft;
+	}
+
+	/**
+	 * Set the ID of this feature equal to $fID
+	 * @param INT
+	 * @see featureID
+	*/
+	function setFeatureID($fID)
+	{
+		$this->featureID = $fID;
+	}
+
+	/**
+	 * Set the value of this feature equal to $fv
+	 * @param MIXED
+	 * @see fValue
+	*/
+	function setFeatureValue($fv)
+	{
+		$this->fValue = $fv;
+	}
+
+	/**
+	 * Set the start position of this feature equal to $fs
+	 * @param INT
+	 * @see fStart
+	*/
+	function setFeatureStart($fs)
+	{
+		$this->fStart = $fs;
+	}
+
+	/**
+	 * Set the end position of this feature equal to $fe
+	 * @param INT
+	 * @see fEnd
+	*/
+	function setFeatureEnd($fe)
+	{
+		$this->fEnd = $fe;
+	}
+
+	/**
+	 * Set the orientation of this feature equal to $fd
+	 * @param STRING 'forward' or 'reverse'
+	 * @see fDir
+	*/
+	function setFeatureDirection($fd)
+	{
+		$this->fDir = $fd;
+	}
+
+	/**
+	 * Set the value of this feature's descriptor equal to $f_desc.  Currently applies only to Tag and Promoter, whose descriptors are Tag Position and Expression System respectively.  This function may set the value of Tag Position to 'Internal' or set Expression System to be 'Mammalian'; for any other features descriptor would be blank.
+	 * @param STRING
+	 * @see fDescr
+	*/
+	function setFeatureDescriptor($f_desc)
+	{
+		$this->fDescr = $f_desc;
+	}
+
+	/**
+	 * Set the full description of this feature (the text that appears on the web interface) equal to $description (e.g. 'Open/Closed', 'cDNA', etc.)
+	 * @param STRING
+	 * @see description
+	*/
+	function setFeatureDecription($description)
+	{
+		$this->description = $description;
+	}
+
+
+	/***************************
+	 * Access Methods
+	****************************/
+
+	/**
+	 * Return the type of this feature (e.g. 'promoter', 'selectable marker', etc.)
+	 * @return STRING
+	 * @see fType
+	*/
+	function getFeatureType()
+	{
+		return $this->fType;
+	}
+
+	/**
+	 * Return the value of this feature (e.g. 'BAP', 'Cerulean', etc.)
+	 * @return MIXED
+	 * @see fValue
+	*/
+	function getFeatureValue()
+	{
+		return $this->fValue;
+	}
+
+	/**
+	 * Return the start position of this feature
+	 * @return INT
+	 * @see fStart
+	*/
+	function getFeatureStart()
+	{
+		return $this->fStart;
+	}
+
+	/**
+	 * Return the end position of this feature
+	 * @return INT
+	 * @see fEnd
+	*/
+	function getFeatureEnd()
+	{
+		return $this->fEnd;
+	}
+
+	/**
+	 * Return the orientation of this feature
+	 * @return STRING 'forward' or 'reverse'
+	 * @see fDir
+	*/
+	function getFeatureDirection()
+	{
+		return $this->fDir;
+	}
+
+
+	/**
+	 * Return the value of this feature's descriptor, if available (would only return actual values for tag and promoter)
+	 * @return STRING
+	 * @see fDescr
+	*/
+	// Returns actual value
+	function getFeatureDescriptor()
+	{
+		return $this->fDescr;
+	}
+
+
+	/**
+	 * Return the name of this feature's descriptor - 'tag position' if the feature is 'tag' and 'expression system' if the feature is 'promoter'; returns the empty string otherwise
+	 * @return STRING
+	*/
+	function getFeatureDescriptorType()
+	{
+		switch ($this->fType)
+		{
+			case 'tag':
+				return "tag position";
+			break;
+			
+			case 'promoter':
+				return "expression system";
+			break;
+			
+			default:
+				return "";
+			break;
+		}
+	}
+
+
+	/**
+	 * Boolean method to determine if this feature has a descriptor.
+	 * @return boolean TRUE if this feature's type is 'tag' or 'promoter'; FALSE otherwise
+	*/
+	// June 11/08: Boolean method to determine if this feature has a descriptor
+	function hasFeatureDescriptor()
+	{
+		if ( ($this->fType == 'tag') || ($this->fType == 'promoter'))
+			return true;
+		
+		return false;
+	}
+
+
+	/**
+	 * Return the full description of this feature as opposed to name or alias (e.g. "cDNA" or "Open/Closed")
+	 * @return STRING
+	 * @see description
+	*/
+	function getFeatureDescription()
+	{
+		return $this->description;
+	}
+
+
+	/**
+	 * Return the database ID of this feature, corresponds to propertyID column value in ReagentPropType_tbl
+	 * @return INT
+	 * @see featureID
+	*/
+	function getFeatureID()
+	{
+		return $this->featureID;
+	}
+}
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Classes/Sequence.php b/OpenFreezer/Classes/Sequence.php
new file mode 100755
index 0000000..affa82f
--- /dev/null
+++ b/OpenFreezer/Classes/Sequence.php
@@ -0,0 +1,439 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Sequence
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Include/require statements
+*/
+//include "generalFunc_Class.php";
+
+/**
+ * Top-level class for Sequence objects
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Sequence
+ *
+ * @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+class Sequence
+{
+	/**
+	 * @var STRING
+	 * String representation of the sequence
+	*/
+	var $sequence = "";
+
+	/**
+	 * @var INT
+	 * Length of the sequence
+	*/
+	var $seqLength = 0;
+
+	// Moved start, end and mw here (to parent class) on Aug. 24, 2010
+
+	/**
+	 * @var INT
+	 * Start position of this sequence
+	*/
+	var $start;
+
+	/**
+	 * @var INT
+	 * End position of this sequence
+	*/
+	var $end;
+
+	/**
+	 * @var FLOAT
+	 * Molecular weight of this sequence
+	*/
+	var $mw;
+
+	/**
+	 * @var generalFunc_Class
+	 * Auxiliary object to invoke functions
+	*/
+	var $gfunc_obj;
+
+	/**
+	 * Default constructor. Generates a Sequence object based on the given sequence, its length is calculated too.
+	 * @param STRING
+	*/
+	function Sequence($sequence="")
+	{
+		$gfunc_obj = new generalFunc_Class();
+
+		$this->sequence = $sequence;
+		$this->seqLength = strlen($gfunc_obj->remove_whitespaces($sequence));
+	}
+
+	/**
+	 * Set the sequence equal to the argument value
+	 * @param STRING Sequence
+	 * @see sequence
+	*/
+	function setSequence($sequence)
+	{
+		$this->sequence = $sequence;
+	}
+
+	// Moved start, end and mw assignment methods up here (to parent class) on Aug. 24, 2010
+
+	/**
+	 * Set the start position of the sequence equal to the input value.
+	 * @param INT
+	 * @see start
+	*/
+	function setStart($start)
+	{
+		$this->start = $start;
+	}
+
+	/**
+	 * Set the end position of the sequence equal to the input value.
+	 * @param INT
+	 * @see end
+	*/
+	function setEnd($end)
+	{
+		$this->end = $end;
+	}
+
+	/**
+	 * Set the molecular weight of the sequence equal to the input value.
+	 * @param FLOAT
+	 * @see mw
+	*/
+	// Jan. 25, 2010
+	function setMW($mw)
+	{
+		$this->mw = $mw;
+	}
+
+	/**
+	 * Return the sequence as a string
+	 * @return STRING Sequence
+	 * @see sequence
+	*/
+	function getSequence()
+	{
+		return $this->sequence;
+	}
+
+	/**
+	 * Return the length of this sequence
+	 * @return INT
+	 * @see sequLength
+	*/
+	function getSequenceLength()
+	{
+		return $this->seqLength;
+	}
+
+	// moved start, end and mw retrieval methods up here (to parent class) on Aug. 24, 2010
+	/**
+	 * Return the start position of the sequence.
+	 * @return INT
+	 * @see start
+	*/
+	function getStart()
+	{
+		return $this->start;
+	}
+
+	/**
+	 * Return the end position of the sequence.
+	 * @return INT
+	 * @see end
+	*/
+	function getEnd()
+	{
+		return $this->end;
+	}
+
+	/**
+	 * Return the molecular weight of the sequence.
+	 * @return FLOAT
+	 * @see mw
+	*/
+	function getMW()
+	{
+		return $this->mw;
+	}
+}
+
+
+/**
+ * This class represents a protein sequence
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1 2009-06-23
+ * @package Sequence
+ *
+ * @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+class ProteinSequence extends Sequence
+{
+	// Instance variables
+
+	/**
+	 * @var INT
+	 * Translation frame of the protein sequence
+	*/
+	var $frame;
+
+	/**
+	 * Default constructor. Generates a Protein Sequence object based on the input parameters.
+	 * @param STRING
+	 * @param INT
+	 * @param INT
+	 * @param INT
+	 * @param FLOAT
+	 * @see sequence
+	 * @see frame
+	 * @see start
+	 * @see end
+	 * @see mw
+	*/
+	function ProteinSequence($seq="", $frame=0, $start=0, $end=0, $mw=0)
+	{
+		$this->sequence = $seq;		// added Aug. 24, 2010
+		$this->frame = $frame;
+		$this->start = $start;
+		$this->end = $end;
+		$this->mw = $mw;	// jan. 22, 2010
+	}
+
+	/*****************************
+	* Assignment methods
+	*****************************/
+	
+	/**
+	 * Set the frame of the sequence equal to the input value.
+	 * @param INT
+	 * @see frame
+	*/
+	function setFrame($frame)
+	{
+		$this->frame = $frame;
+	}
+	
+	/*****************************
+	* Access methods
+	*****************************/
+
+	/**
+	 * Return the frame of the sequence.
+	 * @return INT
+	 * @see frame
+	*/
+	function getFrame()
+	{
+		return $this->frame;
+	}
+}
+
+/**
+ * This class represents a DNA sequence
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Sequence
+ *
+ * @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+class DNASequence extends Sequence
+{
+	// Instance variables
+
+	/**
+	 * @var boolean
+	 * Is there an ATG codon present in this sequence?
+	*/
+	var $hasATG;
+
+	/**
+	 * @var boolean
+	 * Is there a stop codon present in this sequence?
+	*/
+	var $hasStopCodon;
+
+	/**
+	 * @var FLOAT
+	 * Melting temperature of this sequence
+	*/
+	var $tm;	// Jan. 25, 2010
+
+	/**
+	 * @var FLOAT
+	 * GC content (%) of this sequence
+	*/
+	var $gc;	// June 25, 2010
+
+	/**
+	 * Default constructor. Generates a DNA Sequence object based on the input parameters.
+	 * @param STRING
+	 * @param INT
+	 * @param INT
+	 * @param FLOAT
+	 * @param FLOAT
+	 * @param FLOAT
+	 * @see sequence
+	 * @see start
+	 * @see end
+	 * @see mw
+	 * @see tm
+	 * @see gc
+	*/
+	function DNASequence($seq="", $start=0, $end=0, $mw=0, $tm=0, $gc=0)
+	{
+		$this->sequence = $seq;		// Aug. 24, 2010
+		$this->start = $start;
+		$this->end = $end;
+		$this->mw = $mw;	// jan. 25, 2010
+		$this->tm = $tm;	// jan. 25, 2010
+		$this->gc = $gc;	// june 25, 2010
+	}
+
+	/***************************
+	* Assignment methods
+	***************************/
+
+	/**
+	 * Set the melting temperature of the sequence equal to the input value.
+	 * @param FLOAT
+	 * @see tm
+	*/
+	// Jan. 25, 2010
+	function setTM($tm)
+	{
+		$this->tm = $tm;
+	}
+
+	/**
+	 * Set the GC content of the sequence equal to the input value.
+	 * @param FLOAT
+	 * @see gc
+	*/
+	function setGC($gc)
+	{
+		$this->gc = $gc;
+	}
+
+	/***************************
+	* Access methods
+	***************************/
+	
+	/**
+	 * Return the melting temperature of the sequence.
+	 * @return FLOAT
+	 * @see tm
+	*/
+	// Jan. 25, 2010
+	function getTM()
+	{
+		return $this->tm;
+	}
+
+	/**
+	 * Return the GC content of the sequence.
+	 * @return FLOAT
+	 * @see gc
+	*/
+	function getGC()
+	{
+		return $this->gc;
+	}
+}
+
+
+/**
+ * This class represents a RNA sequence
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1 2009-06-23
+ * @package Sequence
+ *
+ * @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+class RNASequence extends Sequence
+{
+	/*****************************
+	* Instance variables
+	*****************************/
+
+	/**
+	 * @var FLOAT
+	 * Melting temperature of this sequence
+	*/
+	var $tm;	// Jan. 25, 2010
+
+	/**
+	 * Default constructor. Generates a RNA Sequence object based on the input parameters.
+	 * @param STRING
+	 * @param INT
+	 * @param INT
+	 * @param FLOAT
+	 * @param FLOAT
+	 * @see sequence
+	 * @see start
+	 * @see end
+	 * @see mw
+	 * @see tm
+	*/
+	function DNASequence($seq="", $start=0, $end=0, $mw=0, $tm=0)
+	{
+		$this->start = $start;
+		$this->end = $end;
+		$this->mw = $mw;	// jan. 25, 2010
+		$this->tm = $tm;	// jan. 25, 2010
+	}
+
+	// Assignment methods - inherited from parent class
+
+	/**
+	 * Return the melting temperature of the sequence.
+	 * @return FLOAT
+	 * @see tm
+	*/
+	// Jan. 25, 2010
+	function getTM()
+	{
+		return $this->tm;
+	}
+}
+?>
diff --git a/OpenFreezer/Classes/Session_Var_Class.php b/OpenFreezer/Classes/Session_Var_Class.php
new file mode 100755
index 0000000..0f799c9
--- /dev/null
+++ b/OpenFreezer/Classes/Session_Var_Class.php
@@ -0,0 +1,1230 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package All
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* This class sets user's session variables by generating maps of constant database column values
+*
+* @author John Paul Lee @version 2005
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+*
+* @package All
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*
+*/
+class Session_Var_Class
+{
+	var $original_view_offset;
+	var $original_High_offset;
+	
+	/**
+	 * Constructor
+	 *
+	*/
+	function Session_Var_Class()
+	{
+		$this->original_view_offset = 0;
+		$this->original_high_offset = 50;
+	}
+
+
+	/**
+	 * Main function that sets session variables by mapping database column values, such as reagent or property names to IDs
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	*/
+	function checkSession_all()
+	{
+		// Marina: Update April 23/09 - Since the database can now be updated at addition of new reagent types and properties, the easiest solution would be to reset session variables every time a view is loaded
+// 		if( !isset( $_SESSION["ReagentProp_Name_ID"] ) )
+// 		{
+			$_SESSION["ReagentProp_Name_ID"] = $this->getReagentPropID_const();
+// 		};
+
+// 		if( !isset( $_SESSION["ReagentProp_ID_Name"] ) )
+// 		{
+			$_SESSION["ReagentProp_ID_Name"] = $this->getReagentPropID_const_rev();
+// 		}
+		
+// 		if( !isset( $_SESSION["ReagentType_Name_ID"] ) )
+// 		{
+			$_SESSION["ReagentType_Name_ID"] = $this->getReagentTypes_const();
+// 		}
+		
+// 		if( !isset( $_SESSION["ReagentType_ID_Name"] ) )
+// 		{
+			$_SESSION["ReagentType_ID_Name"] = $this->getReagentTypes_const_rev();
+// 		}
+
+		// May 1/08, Marina
+// 		if (!isset($_SESSION["ReagentProp_Alias_Name"]))
+// 		{
+			$_SESSION["ReagentProp_Alias_Name"] = $this->getReagentProp_Alias_Names();
+// 		}
+
+		// May 1/08, Marina
+// 		if (!isset($_SESSION["ReagentProp_Name_Alias"]))
+// 		{
+			$_SESSION["ReagentProp_Name_Alias"] = $this->getReagentProp_Name_Aliases();
+// 		}
+
+		// Nov. 2/09
+		$_SESSION["ReagentProp_ID_Alias"] = $this->getReagentProp_ID_Aliases();
+
+		// May 2/08, Marina: Map property names to descriptions
+// 		if (!isset($_SESSION["ReagentProp_Name_Desc"]))
+// 		{
+			$_SESSION["ReagentProp_Name_Desc"] = $this->getReagentProp_Name_Desc();
+			$_SESSION["ReagentProp_Desc_Name"] = $this->getReagentProp_Desc_Name();
+// 		}
+
+		$_SESSION["ReagentProp_Desc_ID"] = $this->getReagentProp_Desc_ID();
+		$_SESSION["ReagentProp_ID_Desc"] = $this->getReagentProp_ID_Desc();
+
+		// April 30/09
+		$_SESSION["ReagentProp_Alias_Desc"] = $this->getReagentProp_Alias_Desc();
+		$_SESSION["ReagentProp_Desc_Alias"] = $this->getReagentProp_Desc_Alias();
+		
+		// May 5/08, Marina: Map association names to aliases
+// 		if (!isset($_SESSION["ReagentAssoc_Name_Alias"]))
+// 		{
+			$_SESSION["ReagentAssoc_Name_Alias"] = $this->getReagentAssoc_Name_Alias();
+// 		}
+
+		// July 6/09
+		$_SESSION["ReagentAssoc_ID_Name"] = $this->getReagentAssoc_ID_Name();
+		$_SESSION["ReagentAssoc_Name_ID"] = array_flip($this->getReagentAssoc_ID_Name());
+
+		// July 6/09
+		$_SESSION["ReagentAssoc_ID_Description"] = $this->getReagentAssoc_ID_Description();
+
+		// Aug 11/09
+		$_SESSION["ReagentAssoc_ID_Alias"] = $this->getReagentAssoc_ID_Alias();
+
+// 		if( !isset( $_SESSION["view_Offset"] ) )
+// 		{
+			$_SESSION["view_Offset"] = $this->original_view_offset;
+// 		}
+		
+		if( !isset( $_SESSION["ToView_High"] ) )
+		{
+			$_SESSION["ToView_High"] = $this->original_high_offset;
+		}
+		
+// 		if( !isset( $_SESSION["ReagentType_Prefix_Name"] ) )
+// 		{
+			$_SESSION["ReagentType_Prefix_Name"] = $this->setReagentPrefix();
+// 		}
+		
+// 		if( !isset( $_SESSION["ReagentType_Name_Prefix"] ) )
+// 		{
+			$_SESSION["ReagentType_Name_Prefix"] = $this->setReagentPrefix_reverse();
+// 		}
+		
+		if( !isset( $_SESSION["userCategoryNames"]) )
+		{
+			$_SESSION["userCategoryNames"] = $this->getUserCategorieByName();
+		}
+
+// 		if (!isset($_SESSION["contGroupNames"]))
+// 		{
+			$_SESSION["contGroupNames"] = $this->getContainerGroupNames();
+// 		}
+
+		// April 23/09
+// 		if (!isset($_SESSION["ReagentPropCategory_Name_ID"]))
+// 		{
+			$_SESSION["ReagentPropCategory_Name_ID"] = $this->getReagentPropertyCategoryName_ID_Map();
+// 		}
+
+		$_SESSION["ReagentPropCategory_ID_Name"] = $this->getReagentPropertyCategory_ID_Name_Map();
+
+		// May 22/09
+		$_SESSION["ReagentPropCategory_Name_Alias"] = $this->getReagentPropertyCategory_Name_Alias_Map();
+		$_SESSION["ReagentPropCategory_Alias_Name"] = $this->getReagentPropertyCategory_Alias_Name_Map();
+
+		$_SESSION["ReagentPropCategory_ID_Alias"] = $this->getReagentPropertyCategory_ID_Alias_Map();
+		$_SESSION["ReagentPropCategory_Alias_ID"] = $this->getReagentPropertyCategory_Alias_ID_Map();
+
+		// April 28/09
+		$_SESSION["ReagentType_ID_Prefix"] = $this->mapReagent_ID_Prefix();
+		$_SESSION["ReagentType_Prefix_ID"] = $this->mapReagent_Prefix_ID();
+
+		// May 21/09
+		$_SESSION["Reagent_Feature_Name_Descriptor"]["tag type"] = "tag position";
+		$_SESSION["Reagent_Feature_Name_Descriptor"]["promoter"] = "expression system";
+
+		// Dec. 21/09: moved here from location
+		$_SESSION["Container_ID_Name"] = $this->mapContainer_ID_Name();
+		$_SESSION["Container_Name_ID"] = $this->mapContainer_Name_ID();
+
+		// June 30, 2010
+		$_SESSION["Lab_Name_ID"] = $this->mapLab_Name_ID();
+		$_SESSION["Lab_ID_Name"] = $this->mapLab_ID_Name();
+
+		$_SESSION["ContainerTypeID_Code"] = $this->mapContainerType_ID_Code();
+	}
+
+	/**
+	 * Create maps specific to reagents in a similar fashion by mapping table column values
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	*/
+	function checkSession_reagent()
+	{
+		if( !isset( $_SESSION["ReagentProp_Name_ID"] ) )
+		{
+			$_SESSION["ReagentProp_Name_ID"] = $this->getReagentPropID_const();
+		};
+		
+		if( !isset( $_SESSION["ReagentProp_ID_Name"] ) )
+		{
+			$_SESSION["ReagentProp_ID_Name"] = $this->getReagentPropID_const_rev();
+		}
+		
+		if( !isset( $_SESSION["ReagentType_Name_ID"] ) )
+		{
+			$_SESSION["ReagentType_Name_ID"] = $this->getReagentTypes_const();
+		}
+		
+		if( !isset( $_SESSION["ReagentType_ID_Name"] ) )
+		{
+			$_SESSION["ReagentType_ID_Name"] = $this->getReagentTypes_const_rev();
+		}
+		
+		if( !isset( $_SESSION["ReagentType_Prefix_Name"] ) )
+		{
+			$_SESSION["ReagentType_Prefix_Name"] = $this->setReagentPrefix();
+		}
+		
+		if( !isset( $_SESSION["ReagentType_Name_Prefix"] ) )
+		{
+			$_SESSION["ReagentType_Name_Prefix"] = $this->setReagentPrefix_reverse();
+		}
+	}
+
+
+	/**
+	 * Make a dictionary out of a mysql_result_set using the values of the second column as array keys and the first column as values
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param resultset
+	 * @return Array associative array (aka 'dictionary' or 'map')
+	*/
+	function setVectorTypeIDs($tomatch)
+	{
+		$vectorTypeID_arr = array();
+	
+// 		print_r( $tomatch );
+		
+		while( $row = mysql_fetch_row($tomatch) )
+		{
+			//foreach ($row as $col_value) {
+			//echo "\t\t$col_value\n";
+			//	}	
+			$vectorTypeID_arr[ $row[1] ] = $row[0];
+		}
+		
+// 		print_r( $vectorTypeID_arr );
+		
+		return $vectorTypeID_arr;
+	}
+	
+
+	/**
+	 * Map reagent type names to their prefixes
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @return Array dictionary of reagentTypeName => reagentTypePrefix tuples, e.g. 'Vector' => 'V'
+	 * @see setVectorTypeIDs()
+	*/
+	function setReagentPrefix( )
+	{
+		global $conn;
+		
+		$prefix_rs = mysql_query("SELECT `reagentTypeName`, `reagent_prefix` FROM `ReagentType_tbl` WHERE `status`='ACTIVE'", $conn ) or die("Failure in prefix sql fetch:" . mysql_error());
+
+		$prefix_final = $this->setVectorTypeIDs($prefix_rs);
+		mysql_free_result($prefix_rs);
+		
+		return $prefix_final;
+	}
+	
+
+	/**
+	 * Map prefixes to reagent type names
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @return Array dictionary of reagentTypePrefix => reagentTypeName tuples, e.g. 'V' => 'Vector'
+	 * @see setVectorTypeIDs()
+	*/
+	function setReagentPrefix_reverse()
+	{
+		global $conn;
+		
+		$prefix_rs = mysql_query("SELECT `reagent_prefix`, `reagentTypeName` FROM `ReagentType_tbl` WHERE `status`='ACTIVE'", $conn) or die("Failure in prefix sql fetch:" . mysql_error());
+		
+		$prefix_final = $this->setVectorTypeIDs($prefix_rs);
+		mysql_free_result($prefix_rs);
+		
+		return $prefix_final;
+	}
+
+
+	/**
+	 * Map reagent type IDs to their prefixes
+	 *
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2009-04-28
+	 *
+	 * @return Array dictionary of reagentTypeID => reagentTypePrefix tuples, e.g. 1 => 'V'
+	 * @see setVectorTypeIDs()
+	*/
+	function mapReagent_ID_Prefix()
+	{
+		global $conn;
+		
+		$prefix_rs = mysql_query("SELECT reagent_prefix, reagentTypeID FROM ReagentType_tbl WHERE status='ACTIVE'", $conn) or die("Failure in prefix sql fetch:" . mysql_error());
+		
+		$prefix_final = $this->setVectorTypeIDs($prefix_rs);
+		mysql_free_result($prefix_rs);
+		
+		return $prefix_final;
+	}
+
+
+	/**
+	 * Map reagent type prefixes to IDs
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1  2009-04-28
+	 *
+	 * @return Array dictionary of reagentTypePrefix => reagentTypeID tuples, e.g. 'V' => 1
+	 * @see setVectorTypeIDs()
+	*/
+	function mapReagent_Prefix_ID()
+	{
+		global $conn;
+		
+		$prefix_rs = mysql_query("SELECT reagentTypeID, reagent_prefix FROM ReagentType_tbl WHERE status='ACTIVE'", $conn) or die("Failure in prefix sql fetch:" . mysql_error());
+		
+		$prefix_final = $this->setVectorTypeIDs($prefix_rs);
+		mysql_free_result($prefix_rs);
+		
+		return $prefix_final;
+	}
+	
+
+	/**
+	 * Map reagent property names to their IDs
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1  2009-04-28
+	 *
+	 * @return Array dictionary of propertyName => propertyID tuples, e.g. 'name' => '1'
+	 * @see setVectorTypeIDs()
+	*/
+	function getReagentPropID_const()
+	{
+		// CONST : Finds all the names of the property and their given property ID's
+		// propName --> propID
+		// [DEBUG] : 1
+		global $conn;
+		
+		$reagentPropID_rs = mysql_query("SELECT propertyID, propertyName FROM `ReagentPropType_tbl` WHERE `status`='ACTIVE'", $conn) or die("Query to find property names failed!: ".mysql_error());
+		
+		
+		$reagentPropID_const = $this->setVectorTypeIDs( $reagentPropID_rs );
+		mysql_free_result( $reagentPropID_rs );
+		
+		return $reagentPropID_const;
+	}
+
+	/**
+	 * Map association property names to aliases
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1  2008-05-05
+	 *
+	 * @return Array dictionary of APropName => alias tuples, e.g. 1 => 'insert_id'
+	*/
+	function getReagentAssoc_Name_Alias()
+	{
+		global $conn;
+		
+		$assoc_Name_Alias_Map = array();
+
+		$assoc_rs = mysql_query("SELECT APropName, alias FROM Assoc_Prop_Type_tbl WHERE status='ACTIVE'", $conn) or die("Cannot map association names to aliases: " . mysql_error());
+
+		while ($assoc_ar = mysql_fetch_array($assoc_rs))
+		{
+			$assocName = $assoc_ar["APropName"];
+			$assocAlias = $assoc_ar["alias"];
+
+			$assoc_Name_Alias_Map[$assocName] = $assocAlias;
+		}
+
+		return $assoc_Name_Alias_Map;
+	}
+
+	/**
+	 * Map association property IDs to names
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return Array dictionary of APropertyID => APropName tuples, e.g. 1 => 'insert id'
+	*/
+	function getReagentAssoc_ID_Name()
+	{
+		global $conn;
+		
+		$assoc_ID_Name_Map = array();
+
+		$assoc_rs = mysql_query("SELECT APropertyID, APropName FROM Assoc_Prop_Type_tbl WHERE status='ACTIVE'", $conn) or die("Cannot map association IDs to names: " . mysql_error());
+
+		while ($assoc_ar = mysql_fetch_array($assoc_rs))
+		{
+			$assocName = $assoc_ar["APropName"];
+			$assocID = $assoc_ar["APropertyID"];
+
+			$assoc_ID_Name_Map[$assocID] = $assocName;
+		}
+
+		return $assoc_ID_Name_Map;
+	}
+
+	/**
+	 * Map association property IDs to aliases
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return Array dictionary of APropertyID => alias tuples, e.g. 1 => 'insert_id'
+	*/
+	function getReagentAssoc_ID_Alias()
+	{
+		global $conn;
+
+		$assoc_ID_Alias_Map = array();
+
+		$assoc_rs = mysql_query("SELECT APropertyID, alias FROM Assoc_Prop_Type_tbl WHERE status='ACTIVE'", $conn) or die("Cannot map association IDs to alias: " . mysql_error());
+
+		while ($assoc_ar = mysql_fetch_array($assoc_rs))
+		{
+			$assocID = $assoc_ar["APropertyID"];
+			$assocAlias = $assoc_ar["alias"];
+			
+			$assoc_ID_Alias_Map[$assocID] = $assocAlias;
+		}
+
+		return $assoc_ID_Alias_Map;
+	}
+
+	/**
+	 * Map association property IDs to descriptions
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1  2008-05-05
+	 *
+	 * @return Array dictionary of APropertyID => description tuples, e.g. 1 => 'Insert ID', or '7' => 'Insert Parent Vector ID'
+	*/
+	function getReagentAssoc_ID_Description()
+	{
+		global $conn;
+		
+		$assoc_ID_Desc_Map = array();
+
+		$assoc_rs = mysql_query("SELECT APropertyID, description FROM Assoc_Prop_Type_tbl WHERE status='ACTIVE'", $conn) or die("Cannot map association IDs to description: " . mysql_error());
+
+		while ($assoc_ar = mysql_fetch_array($assoc_rs))
+		{
+			$assocID = $assoc_ar["APropertyID"];
+			$assocDesc = $assoc_ar["description"];
+			
+			$assoc_ID_Desc_Map[$assocID] = $assocDesc;
+		}
+
+		return $assoc_ID_Desc_Map;
+	}
+
+
+	/**
+	 * Map reagent property names to their descriptions
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1  2008-05-02
+	 *
+	 * @return Array dictionary of propertyName => propertyDesc tuples, e.g. 'tag position' => 'Tag Position'
+	*/
+	function getReagentProp_Name_Desc()
+	{
+		global $conn;
+
+		$prop_Name_Desc_Map = array();
+	
+		$prop_rs = mysql_query("SELECT propertyName, propertyDesc FROM ReagentPropType_tbl WHERE status='ACTIVE'", $conn) or die("Cannot map property names to descriptions: " . mysql_error());
+
+		while ($prop_ar = mysql_fetch_array($prop_rs, MYSQL_ASSOC))
+		{
+			$propName = $prop_ar["propertyName"];
+			$propDesc = $prop_ar["propertyDesc"];
+			
+			$prop_Name_Desc_Map[$propName] = $propDesc;
+		}
+
+		return $prop_Name_Desc_Map;
+	}
+
+	/**
+	 * Equal and opposite - Map reagent property descriptions to their names
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1  2009-04-30
+	 *
+	 * @return Array dictionary of propertyDesc => propertyName tuples, e.g. 'Tag Position' => 'tag position'
+	*/
+	function getReagentProp_Desc_Name()
+	{
+		global $conn;
+
+		$prop_Name_Desc_Map = array();
+	
+		$prop_rs = mysql_query("SELECT propertyName, propertyDesc FROM ReagentPropType_tbl WHERE status='ACTIVE'", $conn) or die("Cannot map property names to descriptions: " . mysql_error());
+
+		while ($prop_ar = mysql_fetch_array($prop_rs, MYSQL_ASSOC))
+		{
+			$propName = $prop_ar["propertyName"];
+			$propDesc = $prop_ar["propertyDesc"];
+			
+			$prop_Desc_Name_Map[$propDesc] = $propName;
+		}
+
+		return $prop_Desc_Name_Map;
+	}
+	
+
+	/**
+	 * Map reagent property aliases to their names
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1  2008-05-01
+	 *
+	 * @return Array dictionary of propertyDesc => propertyName tuples, e.g. 'Tag Position' => 'tag position'
+	*/
+	function getReagentProp_Alias_Names()
+	{
+		global $conn;
+
+		$reagentProp_rs = mysql_query("SELECT propertyAlias, propertyName FROM ReagentPropType_tbl WHERE status='ACTIVE'", $conn) or die("Could not map property aliases to names: " . mysql_error());
+		
+		$propAliasNameMap = array();
+
+		while ($reagentProp_ar = mysql_fetch_array($reagentProp_rs, MYSQL_ASSOC))
+		{
+			$pAlias = $reagentProp_ar["propertyAlias"];
+			$pName = $reagentProp_ar["propertyName"];
+
+			$propAliasNameMap[$pAlias] = $pName;
+		}
+
+		mysql_free_result($reagentProp_rs);
+
+		return $propAliasNameMap;
+	}
+
+
+	/**
+	 * Map reagent property names to their aliases
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1  2008-05-01
+	 *
+	 * @return Array dictionary of propertyName => propertyAlias tuples, e.g. 'tag position' => 'tag_position'
+	*/
+	function getReagentProp_Name_Aliases()
+	{
+		global $conn;
+
+		$reagentProp_rs = mysql_query("SELECT propertyAlias, propertyName FROM ReagentPropType_tbl WHERE status='ACTIVE'", $conn) or die("Could not map property aliases to names: " . mysql_error());
+		
+		$propNameAliasMap = array();
+
+		while ($reagentProp_ar = mysql_fetch_array($reagentProp_rs, MYSQL_ASSOC))
+		{
+			$pAlias = $reagentProp_ar["propertyAlias"];
+			$pName = $reagentProp_ar["propertyName"];
+
+			$propNameAliasMap[$pName] = $pAlias;
+		}
+
+		mysql_free_result($reagentProp_rs);
+
+		return $propNameAliasMap;
+	}
+
+	/**
+	 * Map reagent property IDs to their aliases
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return Array dictionary of propertyID => propertyAlias tuples, e.g. '8' => 'tag_position'
+	*/
+	function getReagentProp_ID_Aliases()
+	{
+		global $conn;
+
+		$reagentProp_rs = mysql_query("SELECT propertyAlias, propertyID FROM ReagentPropType_tbl WHERE status='ACTIVE'", $conn) or die("Could not map property aliases to names: " . mysql_error());
+		
+		$propIDAliasMap = array();
+
+		while ($reagentProp_ar = mysql_fetch_array($reagentProp_rs, MYSQL_ASSOC))
+		{
+			$pAlias = $reagentProp_ar["propertyAlias"];
+			$pID = $reagentProp_ar["propertyID"];
+
+			$propIDAliasMap[$pID] = $pAlias;
+		}
+
+		mysql_free_result($reagentProp_rs);
+
+		return $propIDAliasMap;
+	}
+
+
+	/**
+	 * Map reagent property alias to description
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2009-04-30
+	 *
+	 * @return Array dictionary of propertyAlias => propertyDesc tuples, e.g. 'tag_position' => 'Tag Position'
+	*/
+	function getReagentProp_Alias_Desc()
+	{
+		global $conn;
+		
+		$prop_rs = mysql_query("SELECT propertyAlias, propertyDesc FROM ReagentPropType_tbl WHERE status='ACTIVE'", $conn) or die("Cannot map property names to descriptions: " . mysql_error());
+
+		while ($prop_ar = mysql_fetch_array($prop_rs, MYSQL_ASSOC))
+		{
+			$propAlias = $prop_ar["propertyAlias"];
+			$propDesc = $prop_ar["propertyDesc"];
+			
+			$prop_Alias_Desc_Map[$propAlias] = $propDesc;
+		}
+
+		return $prop_Alias_Desc_Map;
+	}
+
+
+	/**
+	 * Map reagent property description to alias
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2009-04-30
+	 *
+	 * @return Array dictionary of propertyDesc => propertyAlias tuples, e.g. 'Tag Position' => 'tag_position'
+	*/
+	function getReagentProp_Desc_Alias()
+	{
+		global $conn;
+		
+		$prop_rs = mysql_query("SELECT propertyAlias, propertyDesc FROM ReagentPropType_tbl WHERE status='ACTIVE'", $conn) or die("Cannot map property names to descriptions: " . mysql_error());
+
+		while ($prop_ar = mysql_fetch_array($prop_rs, MYSQL_ASSOC))
+		{
+			$propAlias = $prop_ar["propertyAlias"];
+			$propDesc = $prop_ar["propertyDesc"];
+			
+			$prop_Desc_Alias_Map[$propDesc] = $propAlias;
+		}
+
+		return $prop_Desc_Alias_Map;
+	}
+
+	/**
+	 * Map reagent property IDs to their names
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @return Array dictionary of propertyID => propertyName tuples, e.g. '8' => 'tag position'
+	 * @see setVectorTypeIDs()
+	*/
+	function getReagentPropID_const_rev( )
+	{
+		// CONST : Finds all the names of the property and their given property ID's
+		// propName --> propID
+		// [1] : DEBUG
+		global $conn;
+		
+		$reagentPropID_rs = mysql_query( "SELECT propertyName, propertyID FROM `ReagentPropType_tbl` WHERE `status`='ACTIVE'", $conn ) or die("Query to find property names failed!: ".mysql_error() );
+		
+		$reagentPropID_const = $this->setVectorTypeIDs( $reagentPropID_rs );
+		mysql_free_result( $reagentPropID_rs );
+		//echo "<br> ---- reagentPropID_const ---- <br>";
+		//print_r( $reagentPropID_const );
+		return $reagentPropID_const;
+	}
+	
+
+	/**
+	 * Map reagent type names to IDs
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @return Array dictionary of reagentTypeName => reagentTypeID tuples, e.g. 'Vector' => '1'
+	 * @see setVectorTypeIDs()
+	*/
+	function getReagentTypes_const()
+	{
+		// CONST : Finds all vector types available currently in the database
+		// 			reagentType --> reagentTypeID
+		// 			Vector --> 1
+		global $conn;
+		$reagentTypes_rs = mysql_query( "SELECT `reagentTypeID`, `reagentTypeName` FROM `ReagentType_tbl` WHERE `status`='ACTIVE'", $conn ) 
+								or die("Query Failed 1: " .mysql_error() );
+		$reagentTypes_const = $this->setVectorTypeIDs( $reagentTypes_rs );
+		mysql_free_result( $reagentTypes_rs );
+		//echo "<br> ---- reagentTypes_const ---- <br>";
+		//print_r( $reagentTypes_const );
+		return $reagentTypes_const;
+	}
+	
+	/**
+	 * Map reagent type IDs to names
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @return Array dictionary of reagentTypeID => reagentTypeName tuples, e.g. '1' => 'Vector'
+	 * @see setVectorTypeIDs()
+	*/
+	function getReagentTypes_const_rev()
+	{
+		// CONST : Finds all vector types available currently in the database
+		// 			reagentType --> reagentTypeID
+		// 			1 --> Vector
+		global $conn;
+		
+		$reagentTypes_rs = mysql_query( "SELECT `reagentTypeName`, `reagentTypeID` FROM `ReagentType_tbl` WHERE `status`='ACTIVE'", $conn) 
+								or die("Query Failed 1: " .mysql_error() );
+		$reagentTypes_const = $this->setVectorTypeIDs( $reagentTypes_rs );
+		mysql_free_result( $reagentTypes_rs );
+		//echo "<br> ---- reagentTypes_const ---- <br>";
+		//print_r( $reagentTypes_const );
+		return $reagentTypes_const;
+	}
+	
+	// CONST : Finds all the vector properties associated with a given vector type.
+	/**
+	 * Map all properties for preps of a given reagent type to their 'required' values (i.e. array keys are property IDs, array values are 'REQ' or 'OPT' values indicating whether the property is required or optional for preps of the given reagent)
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param INT reagent type ID
+	 * @param Array dictionary of reagent type ID => name tuples (cannot use $_SESSION[...] here, hasn't been set yet!)
+	 *
+	 * @return Array dictionary of propertyID => STRING tuples, e.g. '1' => 'REQ', '2' => 'OPT'
+	*/
+	function getReagentPropReq($reagentToFind, $types)
+	{
+		global $conn;
+		
+		$reagentProp_rs = mysql_query( "SELECT `propertyID`,`requirement` FROM `PropertyReq_tbl` WHERE reagentTypeID='" . 
+						$types[$reagentToFind] . "' AND `status`='ACTIVE' ORDER BY `propertyID` ASC;", $conn ) 
+							or die("Query to find reagent property associated failed!: ".mysql_error() );
+		
+		$tempPropReq_ar = array ();
+		
+		while( $row = mysql_fetch_array( $reagentProp_rs, MYSQL_ASSOC ) )
+		{
+			$tempPropReq_ar[$row["propertyID"]]=$row["requirement"];
+		}
+		
+		mysql_free_result( $reagentProp_rs );
+		return $tempPropReq_ar;
+	}
+
+
+	/**
+	 * Same as getReagentPropReq, only the argument for SQL query is reagentTypeID
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param INT reagent type ID
+	 * @param Array dictionary of reagent type ID => name tuples -- REDUNDANT
+	 *
+	 * @return Array dictionary of propertyID => STRING tuples, e.g. '1' => 'REQ', '2' => 'OPT'
+	 * @see getReagentPropReq()
+	*/
+	function getReagentPropReq_num($reagentTypeID_tofind, $types)
+	{
+		global $conn;
+
+		$reagentProp_rs = mysql_query("SELECT `propertyID`,`requirement` FROM `PropertyReq_tbl` WHERE reagentTypeID='" . $reagentTypeID_tofind . "' AND `status`='ACTIVE' ORDER BY `propertyID` ASC;", $conn) or die("Query to find reagent property associated failed!: ".mysql_error());
+		
+		$tempPropReq_ar = array ();
+		
+		while ($row = mysql_fetch_array($reagentProp_rs, MYSQL_ASSOC))
+		{
+			$tempPropReq_ar[$row["propertyID"]]=$row["requirement"];
+		}
+		
+		mysql_free_result($reagentProp_rs);
+
+		return $tempPropReq_ar;
+	}
+	
+	
+	// July 16/07, Marina
+	/**
+	 * Same as getReagentPropReq, only the argument for SQL query is reagentTypeID
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2007-07-16
+	 *
+	 * @return Array dictionary of user category ID => user category name tuples, e.g. '1' => 'Admin'
+	*/
+	function getUserCategorieByName()
+	{
+		global $conn;
+		
+		$userCategoryNames = array();
+		
+		$categories_rs = mysql_query("SELECT categoryID, category FROM UserCategories_tbl WHERE status='ACTIVE'", $conn) or die("Cannot fetch user categories: " . mysql_error());
+		
+		while ($categories_ar = mysql_fetch_array($categories_rs, MYSQL_ASSOC))
+		{
+			$categoryID = $categories_ar["categoryID"];
+			$categoryName = $categories_ar["category"];
+			
+			$userCategoryNames[$categoryName] = $categoryID;
+		}
+		
+		return $userCategoryNames;
+	}
+
+	// Jan. 30/08, Marina
+	/**
+	 * Map container type (group) names to IDs
+	 *
+	 * Redundant to mapContainer_Name_ID()
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2008-01-30
+	 *
+	 * @return Array dictionary of container type (historically called 'group') names => container type ID name tuples, e.g. '2' => 'Glycerol Stocks'
+	*/
+	function getContainerGroupNames()
+	{
+		global $conn;
+		
+		$contGroupNames = array();
+
+		$groupNames_rs = mysql_query("SELECT contGroupID, contGroupName FROM ContainerGroup_tbl WHERE status='ACTIVE'", $conn) or die("Cannot fetch container types: " . mysql_error());
+		
+		while ($groupNames_ar = mysql_fetch_array($groupNames_rs, MYSQL_ASSOC))
+		{
+			$contGroupID = $groupNames_ar["contGroupID"];
+			$contGroupName = $groupNames_ar["contGroupName"];
+			
+			$contGroupNames[$contGroupName] = $contGroupID;
+		}
+		
+		return $contGroupNames;
+	}
+
+	// April 23/09
+	/**
+	 * Map reagent property category IDs to names
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2009-04-23
+	 *
+	 * @return Array dictionary of reagent property category ID => reagent property category name tuples, e.g. '1' => 'General Properties'
+	*/
+	function getReagentPropertyCategory_ID_Name_Map()
+	{
+		global $conn;
+
+		$propCategoryMap = Array();
+
+		$propCategories_set = mysql_query("SELECT propertyCategoryID, propertyCategoryName FROM ReagentPropTypeCategories_tbl WHERE status='ACTIVE'", $conn) or die("Cannot select reagent property categories: " . mysql_error());
+		
+		while ($propCategories = mysql_fetch_array($propCategories_set, MYSQL_ASSOC))
+		{
+			$propCatID = $propCategories["propertyCategoryID"];
+			$propCatName = $propCategories["propertyCategoryName"];
+
+			$propCategoryMap[$propCatID] = $propCatName;
+		}
+
+		return $propCategoryMap;
+	}
+
+
+	// April 23/09
+	/**
+	 * Equal and opposite: Map reagent property category names to IDs
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2009-04-23
+	 *
+	 * @return Array dictionary of reagent property category name => reagent property category ID tuples, e.g. 'General Properties' => '1'
+	*/
+	function getReagentPropertyCategoryName_ID_Map()
+	{
+		global $conn;
+
+		$propCategoryMap = Array();
+
+		$propCategories_set = mysql_query("SELECT propertyCategoryID, propertyCategoryName FROM ReagentPropTypeCategories_tbl WHERE status='ACTIVE'", $conn) or die("Cannot select reagent property categories: " . mysql_error());
+		
+		while ($propCategories = mysql_fetch_array($propCategories_set, MYSQL_ASSOC))
+		{
+			$propCatID = $propCategories["propertyCategoryID"];
+			$propCatName = $propCategories["propertyCategoryName"];
+
+			$propCategoryMap[$propCatName] = $propCatID;
+		}
+
+		return $propCategoryMap;
+	}
+
+	/**
+	 * Map reagent property descriptions to IDs
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return Array dictionary of reagent property description => reagent property ID tuples, e.g. 'Tag Position' => '8'
+	*/
+	function getReagentProp_Desc_ID()
+	{
+		global $conn;
+
+		$reagentProp_rs = mysql_query("SELECT propertyDesc, propertyID FROM ReagentPropType_tbl WHERE status='ACTIVE'", $conn) or die("Could not map property descriptor to ID: " . mysql_error());
+		
+		$propDescIDMap = array();
+
+		while ($reagentProp_ar = mysql_fetch_array($reagentProp_rs, MYSQL_ASSOC))
+		{
+			$pDescr = $reagentProp_ar["propertyDesc"];
+			$pID = $reagentProp_ar["propertyID"];
+
+			$propDescIDMap[$pDescr] = $pID;
+		}
+
+		mysql_free_result($reagentProp_rs);
+
+		return $propDescIDMap;
+	}
+
+
+	/**
+	 * Map reagent property IDs to descriptions
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return Array dictionary of reagent property ID => reagent property description tuples, e.g. '8' => 'Tag Position'
+	*/
+	function getReagentProp_ID_Desc()
+	{
+		global $conn;
+
+		$reagentProp_rs = mysql_query("SELECT propertyDesc, propertyID FROM ReagentPropType_tbl WHERE status='ACTIVE'", $conn) or die("Could not map property descriptor to ID: " . mysql_error());
+		
+		$propIDDescMap = array();
+
+		while ($reagentProp_ar = mysql_fetch_array($reagentProp_rs, MYSQL_ASSOC))
+		{
+			$pDescr = $reagentProp_ar["propertyDesc"];
+			$pID = $reagentProp_ar["propertyID"];
+
+			$propIDDescMap[$pID] = $pDescr;
+		}
+
+		mysql_free_result($reagentProp_rs);
+
+		return $propIDDescMap;
+	}
+
+
+	/**
+	 * Map reagent property category names to aliases
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return Array dictionary of reagent property category name => reagent property category alias tuples, e.g. 'General Properties' => 'general_properties'
+	*/
+	function getReagentPropertyCategory_Name_Alias_Map()
+	{
+		global $conn;
+
+		$propCategoryMap = Array();
+
+		$propCategories_set = mysql_query("SELECT propertyCategoryName, propertyCategoryAlias FROM ReagentPropTypeCategories_tbl WHERE status='ACTIVE'", $conn) or die("Cannot select reagent property categories: " . mysql_error());
+		
+		while ($propCategories = mysql_fetch_array($propCategories_set, MYSQL_ASSOC))
+		{
+			$propCatAlias = $propCategories["propertyCategoryAlias"];
+			$propCatName = $propCategories["propertyCategoryName"];
+
+			$propCategoryMap[$propCatName] = $propCatAlias;
+		}
+
+		return $propCategoryMap;
+	}
+
+
+	/**
+	 * Equal and opposite: Map reagent property category aliases to names
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return Array dictionary of reagent property category alias => reagent property category name tuples, e.g.  'general_properties' => 'General Properties'
+	*/
+	function getReagentPropertyCategory_Alias_Name_Map()
+	{
+		global $conn;
+
+		$propCategoryMap = Array();
+
+		$propCategories_set = mysql_query("SELECT propertyCategoryName, propertyCategoryAlias FROM ReagentPropTypeCategories_tbl WHERE status='ACTIVE'", $conn) or die("Cannot select reagent property categories: " . mysql_error());
+		
+		while ($propCategories = mysql_fetch_array($propCategories_set, MYSQL_ASSOC))
+		{
+			$propCatAlias = $propCategories["propertyCategoryAlias"];
+			$propCatName = $propCategories["propertyCategoryName"];
+
+			$propCategoryMap[$propCatAlias] = $propCatName;
+		}
+
+		return $propCategoryMap;
+	}
+
+	/**
+	 * Map reagent property category IDs to aliases
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return Array dictionary of reagent property category ID => reagent property category alias tuples, e.g.  '1' => 'general_properties'
+	*/
+	function getReagentPropertyCategory_ID_Alias_Map()
+	{
+		global $conn;
+
+		$propCategoryMap = Array();
+
+		$propCategories_set = mysql_query("SELECT propertyCategoryID, propertyCategoryAlias FROM ReagentPropTypeCategories_tbl WHERE status='ACTIVE'", $conn) or die("Cannot select reagent property categories: " . mysql_error());
+		
+		while ($propCategories = mysql_fetch_array($propCategories_set, MYSQL_ASSOC))
+		{
+			$propCatID = $propCategories["propertyCategoryID"];
+			$propCatAlias = $propCategories["propertyCategoryAlias"];
+
+			$propCategoryMap[$propCatID] = $propCatAlias;
+		}
+
+		return $propCategoryMap;
+	}
+
+
+	/**
+	 * Equal and opposite: Map reagent property category aliases to IDs
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return Array dictionary of reagent property category alias => reagent property category ID tuples, e.g.  'general_properties' => '1'
+	*/
+	function getReagentPropertyCategory_Alias_ID_Map()
+	{
+		global $conn;
+
+		$propCategoryMap = Array();
+
+		$propCategories_set = mysql_query("SELECT propertyCategoryID, propertyCategoryAlias FROM ReagentPropTypeCategories_tbl WHERE status='ACTIVE'", $conn) or die("Cannot select reagent property categories: " . mysql_error());
+		
+		while ($propCategories = mysql_fetch_array($propCategories_set, MYSQL_ASSOC))
+		{
+			$propCatID = $propCategories["propertyCategoryID"];
+			$propCatAlias = $propCategories["propertyCategoryAlias"];
+
+			$propCategoryMap[$propCatAlias] = $propCatID;
+		}
+
+		return $propCategoryMap;
+	}
+
+
+	/**
+	 * Map container type (group) IDs to names
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return Array dictionary of container type (historically called 'group') ID => container type name tuples, e.g. '2' => 'Glycerol Stocks'
+	*/
+	function mapContainer_ID_Name()
+	{
+		global $conn;
+		$cont_ID_Name_ar = Array();
+
+		$container_names_rs = mysql_query( "SELECT * FROM `ContainerGroup_tbl` WHERE `status`='ACTIVE' ORDER BY `contGroupID`" , $conn ) or die("Failure in container name sql" . mysql_error() );
+		
+		while( $container_names_ar = mysql_fetch_array( $container_names_rs, MYSQL_ASSOC ) )
+		{
+			$cont_ID_Name_ar[ $container_names_ar["contGroupID"] ] = $container_names_ar["contGroupName"];
+		}
+		
+		return $cont_ID_Name_ar;
+	}
+
+	/**
+	 * Map container type (group) IDs to names
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return Array dictionary of container type (historically called 'group') ID => container type name tuples, e.g.  'Glycerol Stocks' => '2'
+	*/
+	function mapContainer_Name_ID()
+	{
+		global $conn;
+		$cont_Name_ID_ar = Array();
+
+		$container_names_rs = mysql_query( "SELECT * FROM `ContainerGroup_tbl` WHERE `status`='ACTIVE' ORDER BY `contGroupID`" , $conn ) or die("Failure in container name sql" . mysql_error() );
+		
+		while( $container_names_ar = mysql_fetch_array( $container_names_rs, MYSQL_ASSOC ) )
+		{
+			$cont_Name_ID_ar[ $container_names_ar["contGroupName"] ] = $container_names_ar["contGroupID"];
+		}
+		
+		return $cont_Name_ID_ar;
+	}
+
+
+	/**
+	 * Map container type (group) IDs to codes (e.g. 'GS' for 'Glycerol Stocks'
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @return Array dictionary of container type (historically called 'group') ID => container type code tuples, e.g.  'Glycerol Stocks' => 'GS'
+	*/
+	function mapContainerType_ID_Code()
+	{
+		global $conn;
+		$contType_ID_Code_ar = Array();
+
+		$container_types_rs = mysql_query("SELECT * FROM `ContainerGroup_tbl` WHERE `status`='ACTIVE'", $conn) or die("Error mapping container type name to code: " . mysql_error());
+		
+		while ($container_types_ar = mysql_fetch_array($container_types_rs, MYSQL_ASSOC))
+		{
+			$contType_ID_Code_ar[$container_types_ar["contGroupID"]] = $container_types_ar["contGroupCode"];
+		}
+
+		return $contType_ID_Code_ar;
+	}
+
+	// June 30, 2010
+	/**
+	 * Map laboratory names to IDs
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2010-06-30
+	 *
+	 * @return Array dictionary of lab name => lab ID tuples, e.g.  'Pawson Lab' => '1'
+	*/
+	function mapLab_Name_ID()
+	{
+		global $conn;
+
+		$labName_ID_ar = Array();
+
+		$labNames_rs = mysql_query("SELECT * FROM LabInfo_tbl WHERE status='ACTIVE'", $conn) or die("Cannot select lab info: " . mysql_error());
+
+		while ($labNames_ar = mysql_fetch_array($labNames_rs, MYSQL_ASSOC))
+		{
+			$labName_ID_ar[$labNames_ar["lab_name"]] = $labNames_ar["labID"];
+		}
+
+		return $labName_ID_ar;
+	}
+
+	// June 30, 2010
+	/**
+	 * Equal and opposite: Map laboratory IDs to names
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2010-06-30
+	 *
+	 * @return Array dictionary of lab ID => lab name tuples, e.g. '1' => 'Pawson Lab'
+	*/
+	function mapLab_ID_Name()
+	{
+		global $conn;
+
+		$labID_Name_ar = Array();
+
+		$labNames_rs = mysql_query("SELECT * FROM LabInfo_tbl WHERE status='ACTIVE'", $conn) or die("Cannot select lab info: " . mysql_error());
+
+		while ($labNames_ar = mysql_fetch_array($labNames_rs, MYSQL_ASSOC))
+		{
+			$labID_Name_ar[$labNames_ar["labID"]] = $labNames_ar["lab_name"];
+		}
+
+		return $labID_Name_ar;
+	}
+}
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Classes/StopWatch.php b/OpenFreezer/Classes/StopWatch.php
new file mode 100755
index 0000000..fbd36e5
--- /dev/null
+++ b/OpenFreezer/Classes/StopWatch.php
@@ -0,0 +1,105 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package All
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+// Code for a basic start/stop timer 
+// Will output the time difference in seconds
+// If the time is less than a second, will output the microseconds
+
+/**
+* Code for a basic start/stop timer 
+*
+* Will output the time difference in seconds
+*
+* If the time is less than a second, will output the microseconds
+*
+* @author John Paul Lee @version 2005
+*
+* @package All
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+class StopWatch
+{
+	var $starttime_m;
+	var $starttime_s;
+	var $endtime_m;
+	var $endtime_s;
+	
+	function StopWatch()
+	{
+		$this->starttime_m = 0;
+		$this->starttime_s = 0;
+		$this->endtime_m = 0;
+		$this->endtime_s = 0;
+	}
+	
+	function startStopWatch()
+	{
+		list( $starttime_mt, $starttime_st ) = explode(" ", microtime());
+		$this->starttime_m = $starttime_mt;
+		$this->starttime_s = $starttime_st;
+	}
+	
+	function stopStopWatch()
+	{
+		list( $endtime_mt, $endtime_st ) = explode(" ", microtime());
+		$this->endtime_m = $endtime_mt;
+		$this->endtime_s = $endtime_st;
+	}
+	
+	function printStopWatch_verbose()
+	{
+		//echo "ST: " . $this->starttime_s . " - " . $this->starttime_m . "<br>";
+		//echo "ET: " . $this->endtime_s . " - " .  $this->endtime_m . "<br>";
+		
+		$temp = $this->endtime_s - $this->starttime_s;
+		if( $temp > 0 )
+		{
+			echo "Time (sec): " . ( ( $this->endtime_s + $this->endtime_m ) - ( $this->starttime_s + $this->starttime_m ) );
+		}
+		else
+		{
+			$temp = $this->endtime_m - $this->starttime_m;
+			echo "Time (micro): " . $temp;
+		}
+	}
+	
+	function resetStopWatch()
+	{
+		$this->starttime_m = 0;
+		$this->starttime_s = 0;
+		$this->endtime_m = 0;
+		$this->endtime_s = 0;
+	}
+}
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Classes/generalFunc_Class.php b/OpenFreezer/Classes/generalFunc_Class.php
new file mode 100755
index 0000000..879b05a
--- /dev/null
+++ b/OpenFreezer/Classes/generalFunc_Class.php
@@ -0,0 +1,430 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package All
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Auxiliary functions used to handle general attributes of reagents and locations in OpenFreezer
+* Examples include: format reagent identifier, filter whitespaces, etc.
+* Written July 28, 2008
+*
+* @author John Paul Lee @version 2005
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+*
+* @package All
+* @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+class generalFunc_Class
+{
+
+	/**
+	 * Default constructor (zero-argument)
+	*/
+	function generalFunc_Class()
+	{
+	}
+	
+	
+	/**
+	 * Return the converted OpenFreezer identifier of the given reagent type and groupID
+	 *
+	 * @author John Paul Lee @version 2005
+	 * @author Marina Olhovsky
+	 *
+	 * @version 3.1
+	 *
+	 * Written by John Paul Lee; modified  April 2009 by Marina - now that we're letting users create new reagent types, prefixes are no longer limited to one character
+	 *
+	 * @param INT Integer column value that corresponds to a reagent Type (e.g. 1 => Vector)
+	 * @param INT Numeric identifier of a particular reagent of this type
+	 *
+	 * @return STRING (e.g. V123)
+	*/
+	function getConvertedID($tempType, $tempGroup)
+	{
+// 		$testgroup = substr($_SESSION["ReagentType_ID_Name"][$tempType], 0, 1) . $tempGroup;	// removed April 28/09
+		
+		// Replaced April 28/09
+		$testgroup = $_SESSION["ReagentType_ID_Prefix"][$tempType] . $tempGroup;
+		return $testgroup;
+	}
+	
+
+	// Returns OpenFreezer ID (V123, I456, etc.)
+	/**
+	 * Return the OpenFreezer ID that corresponds to the given database column value
+	 *
+	 * @author John Paul Lee @version 2005
+	 * @author Marina Olhovsky
+	 *
+	 * @version 3.1
+	 *
+	 * @param INT Corresponds to reagentID column value
+	 *
+	 * @return STRING (e.g. V123)
+	 *
+	 * @see getConvertedID()
+	*/
+	function getConvertedID_rid($rid)
+	{
+		global $conn;
+		
+		$reagents_rs = mysql_query( "SELECT * FROM `Reagents_tbl` WHERE `reagentID`='" . $rid . "' AND `status`='ACTIVE'" , $conn ) 
+		or die( "failed search for reagent id found!" . mysql_error() );
+
+		if( $reagents_ar = mysql_fetch_array( $reagents_rs, MYSQL_ASSOC ) )
+		{
+			return $this->getConvertedID($reagents_ar["reagentTypeID"], $reagents_ar["groupID"]);
+		}
+		
+		return "";
+	}
+	
+	// Function: get_rid()
+	// Defn: Will return the rid (internal database id) from a given Aurora ID (the visual outputted ID.
+	// Paramater: $limsid = OpenFreezer ID (ie. V23, I232, C22)
+	// Returns: The appropriate RID (internal database ID)
+	// Error: Returns -1 if no valid rid was found for the given limsID
+	/**
+	 * Opposite of getConvertedID_rid($rid): Return the internal reagentID that corresponds to the given OpenFreezer ID
+	 *
+	 * i.e. V1 => 1 (Reagent_tbl.reagentID = 1)
+	 *
+	 * @author John Paul Lee @version 2005
+	 * @author Marina Olhovsky
+	 *
+	 * @version 3.1
+	 *
+	 * @param STRING Corresponds to reagentID column value (e.g. V123)
+	 *
+	 * @return INT
+	*/
+	function get_rid($limsid)
+	{
+		global $conn;
+
+		// Replaced Jan. 12/09: intval() returns true if the argument is '12orf29'
+// NO!		if (intval($this->get_groupID($limsid)) > 0)
+		if (ctype_digit($this->get_groupID($limsid)))		// Jan. 12/09
+		{
+			$rid_rs = mysql_query("SELECT * FROM `Reagents_tbl` WHERE `reagentTypeID`='" . $this->get_typeID($limsid) . "' " . "AND `groupID`='" . $this->get_groupID($limsid) . "' AND `status`='ACTIVE'", $conn) or die("Failure in grabbing get_rid() sql: " . mysql_error());
+			
+			if ($rid_ar = mysql_fetch_array($rid_rs, MYSQL_ASSOC))
+			{
+				return $rid_ar["reagentID"];
+			}
+		}
+
+		return -1;
+	}
+
+
+	/**
+	 * February 2, 2007, Marina: For VERY long lists of IDs, do one batch convert and return a dictionary
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param Array list of internal db ids
+	 *
+	 * @return Array dictionary of (db_id, LIMS_ID) tuples
+	*/
+	function getLabIDs($id_list)
+	{
+		global $conn;
+		$lab_ids = array();
+
+		foreach ($id_list as $key => $rid)
+		{
+			$reagents_rs = mysql_query("SELECT CONCAT(reagent_prefix, groupID) as lims_id FROM Reagents_tbl r, ReagentType_tbl t WHERE r.reagentID='" . $rid . "' AND r.reagentTypeID=t.reagentTypeID AND r.status='ACTIVE'" , $conn) or die("Failed search for reagent ID " . mysql_error());
+
+
+			if ($reagents_ar = mysql_fetch_array($reagents_rs, MYSQL_ASSOC))
+			{
+				$lab_ids[$rid] = $reagents_ar["lims_id"];
+			}
+		}
+
+		return $lab_ids;
+	}
+
+	
+	/**
+	 * April 16, 2007, Marina: Get the type ID of $rid == an **internal database ID**
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param INT internal db ID
+	 *
+	 * @return INT (1, 2, 3, 4, ...) for Vector, Insert, Oligo, Cell Line, etc.
+	*/
+	function getTypeID($rid)
+	{
+		global $conn;
+		
+		$reagents_rs = mysql_query("SELECT * FROM `Reagents_tbl` WHERE `reagentID`='" . $rid . "' AND `status`='ACTIVE'" , $conn) or die("failed search for reagent id found!" . mysql_error());
+
+		if ($reagents_ar = mysql_fetch_array($reagents_rs, MYSQL_ASSOC))
+		{
+			return $reagents_ar["reagentTypeID"];
+		}
+		
+		return -1;
+	}
+	
+
+	/**
+	 * Return the numeric portion of a reagent's OpenFreezer identifier
+	 *
+	 * Marina, June 8/09: Simple prefix matching is not going to work for all novel reagent types now, since single-letter prefixes can be contained within longer ones (e.g. 'V' for Vector and 'VI' for Virus).  Use regular expressions instead.
+	 *
+	 * @author John Paul Lee @version 2005
+	 * @author Marina Olhovsky
+	 *
+	 * @version 3.1
+	 *
+	 * @param STRING alphanumeric string representing an OpenFreezer ID, e.g. V123, or Ab123
+	 *
+	 * @return INT numeric portion of the identifier
+	*/
+	function get_groupID($limsid)
+	{
+		$groupID_tmp = -1;
+
+		// Marina, June 8/09: Simple prefix matching is not going to work for all novel reagent types now, since single-letter prefixes can be contained within longer ones (e.g. 'V' for Vector and 'VI' for Virus)
+		// Use regular expressions instead:
+/*
+		if (!isset($_SESSION["ReagentType_Name_Prefix"]))
+		{
+			//return -1;
+			$temp_session_var_obj = new Session_Var_Class();
+			
+			$temp_session_var_obj->checkSession();
+			
+			unset( $temp_session_var_obj );
+		}*/
+
+		// added June 8/09
+		$keywords = preg_split("/[A-Z]+/", strtoupper(trim($limsid)));
+		$groupID_tmp = $keywords[1];
+
+		/*
+		foreach( $_SESSION["ReagentType_Name_Prefix"] as $name => $prefix )
+		{
+			if (strpos(strtoupper($limsid), $prefix) === 0)
+			{
+				//$reagentTypeID_tmp = $_SESSION["ReagentType_Name_ID"][ $name ];
+				
+				$groupID_tmp = substr( $limsid, strlen( $prefix ), strlen( $limsid ) );
+				
+				break;
+			}
+		}*/
+		
+		return $groupID_tmp;
+	}
+	
+
+	/**
+	 * Equal and opposite to getGroupID: Return the database ID that corresponds to the type of the given reagent, identified by $limsid
+	 *
+	 * Marina, June 8/09: Simple prefix matching is not going to work for all novel reagent types now, since single-letter prefixes can be contained within longer ones (e.g. 'V' for Vector and 'VI' for Virus).  Use regular expressions instead
+	 *
+	 * @author John Paul Lee @version 2005
+	 * @author Marina Olhovsky
+	 *
+	 * @version 3.1
+	 *
+	 * @param STRING alphanumeric string representing an OpenFreezer ID, e.g. V123, or Ab123
+	 *
+	 * @return INT Database identifier of the type of this reagent (1 => Vector for V123, 6 => Antibody for Ab123, etc.)
+	*/
+	function get_typeID($limsid)
+	{
+		global $conn;
+		
+		$reagentTypeID_tmp = -1;
+
+/* Removed June 8/09
+		if( !isset( $_SESSION["ReagentType_Name_Prefix"] ) )
+		{
+			//return -1;
+			$temp_session_var_obj = new Session_Var_Class();
+			
+			$temp_session_var_obj->checkSession();
+			
+			unset( $temp_session_var_obj );
+		}
+		
+		foreach( $_SESSION["ReagentType_Name_Prefix"] as $name => $prefix )
+		{
+			if( strpos( strtoupper( $limsid ) , $prefix ) === 0 )
+			{
+				$reagentTypeID_tmp = $_SESSION["ReagentType_Name_ID"][ $name ];
+				
+				//$groupID_tmp = substr( $insert_rid, strlen( $prefix ), strlen( $insert_rid ) );
+				
+				break;
+			}
+		}*/
+		
+		// added June 8/09
+		$keywords = preg_split("/[0-9]+/", trim($limsid));
+
+		// Nov. 4/09: CASE-SENSITIVITY!!!  Searching for 'v123' would not match 'v' for Vector through SESSION vars!!!
+// 		$reagentTypeID_tmp = $_SESSION["ReagentType_Prefix_ID"][$keywords[0]];
+
+		$prefix_rs = mysql_query("SELECT reagentTypeID FROM ReagentType_tbl WHERE reagent_prefix='" . $keywords[0] . "' AND status='ACTIVE'", $conn) or die ("Could not select reagent type prefix: " . mysql_error());
+
+		if ($prefix_ar = mysql_fetch_array($prefix_rs, MYSQL_ASSOC))
+			$reagentTypeID_tmp = $prefix_ar["reagentTypeID"];
+
+		return $reagentTypeID_tmp;
+	}
+
+
+	/**
+	 * Return the experiment ID that corresponds to this reagent (to determine if there are locations for this reagent)
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param INT Internal reagent ID (Reagents_tbl.reagentID column value)
+	 *
+	 * @return INT Experiment_tbl.expID column value
+	*/
+	function get_expID( $rid )
+	{
+		global $conn;
+		
+		$exp_rs = mysql_query("SELECT * FROM `Experiment_tbl` WHERE `reagentID`='" . $rid . "' AND `status`='ACTIVE'" , $conn) or die("Failure in get_expID() sql statement: " . mysql_error());
+
+		if ($exp_ar = mysql_fetch_array($exp_rs, MYSQL_ASSOC))
+		{
+			return $exp_ar["expID"];
+		}
+		
+		return -1;
+	}
+
+	/**
+	 * Retrive the highest group ID in Reagents_tbl (to assign the next highest to a newly added reagent)
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param INT reagent type ID (e.g. 1 => Vector)
+	 *
+	 * @return INT Highest numeric identifier of reagents of this type ( = group ID)
+	*/
+	function get_max_groupid( $reagentTypeID )
+	{
+		global $conn;
+		
+		$final_max = -1;
+		
+		$max_rs = mysql_query("SELECT MAX(`groupID`) as maxid FROM `Reagents_tbl` WHERE `ReagentTypeID`='" . $reagentTypeID . "' ". "AND `status`='ACTIVE'", $conn) or die( "FAILURE IN get_max_groupid(): " . mysql_error());
+
+		if( $max_ar = mysql_fetch_array( $max_rs, MYSQL_ASSOC ) )
+		{
+			$final_max = $max_ar["maxid"];
+		}
+		
+		mysql_free_result( $max_rs );
+		unset( $max_rs, $max_ar );
+		
+		return $final_max;
+	}
+
+
+	/**
+	 * Remove whitespace from a string
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param STRING
+	 * @return STRING
+	*/
+	function remove_whitespaces( $sin )
+	{
+		$white = array(" ", "\t", "\r", "\n", "\0", "\x0B");
+		
+		return str_replace( $white, "", $sin );
+	}
+
+	
+	/**
+	 * Auxiliary function to remove elements from a set represented by string
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param INT
+	 * @param STRING
+	 *
+	 * @return STRING
+	*/
+	function reset_set($count, $set)
+	{
+		if ($count > 0)
+		{
+			$set = substr( $set, 0, strlen( $set ) - 2 ) . ")";
+		}
+		else
+		{
+			$set = "('')";
+		}
+
+		return $set;
+	}
+
+
+	/**
+	 * Replace special characters in a string with appropriate HTML tags
+	 *
+	 * Added Feb. 12/08, Marina - Source http://www.hawkee.com/snippet/445/
+	 *
+	 * @param STRING
+	 * @return STRING
+	*/
+	function textarea_encode($html_code)
+	{
+		$from = array('<', '>');
+		$to = array('#&50', '#&52');
+		$html_code = str_replace($from, $to, $html_code);
+
+		return $html_code;
+	}
+}
+?>
diff --git a/OpenFreezer/DatabaseConn.php b/OpenFreezer/DatabaseConn.php
new file mode 100755
index 0000000..56eaa6f
--- /dev/null
+++ b/OpenFreezer/DatabaseConn.php
@@ -0,0 +1,43 @@
+<?php
+// CHANGE THE FOLLOWING VARIABLE VALUES TO YOUR DATABASE CONNECTION PARAMETERS
+$databaseip = "Your MySQL server IP";
+$databasename = "my_openfreezer_db";
+$name = "openfreezer_www";
+$pw = "MySQL password for openfreezer_www";
+
+// September 11, 2007, Marina:
+global $hostname;
+$hostname = "Your OpenFreezer URL, e.g. http://www.my_openfreezer.org/";
+
+// added email addresses on June 3, 2010 - easy to change
+global $mail_programmer;
+$mail_programmer = "olhovsky at lunenfeld.ca";
+
+global $mail_biologist;
+$mail_biologist = "colwill at lunenfeld.ca";
+
+global $conn;
+
+/**
+ * A constant used to define table width on User module views
+ * @global INT $Const_Table_Width
+*/
+global $Const_Table_Width;
+
+// May 5/06, Marina -- The minimum group ID for MGC clones in the system
+// (i.e. Vectors and Inserts from the MGC set have LIMS IDs V5000+ and I50000+)
+global $MGC_Start;
+
+$MGC_Start = 50000;	// 5/5/06, Marina
+
+$Const_Table_Width = "700px";
+
+// August 20, 2007, Marina: CHANGED mysql_pconnect to mysql_connect - DON'T USE PERSISTENT CONNECTIONS, THEY OVERLOAD THE DATABASE AND SLOW DOWN SEARCH!!!!!!!!!
+$conn = mysql_connect($databaseip, $name, $pw) or die("Could not connect: " . mysql_error());
+
+mysql_select_db($databasename, $conn) or die("Could not select database: " . mysql_error());
+
+// Added for CGI script execution
+global $cgi_path;
+$cgi_path = $hostname . "cgi/";		
+?>
diff --git a/OpenFreezer/Docs/Copyright.doc b/OpenFreezer/Docs/Copyright.doc
new file mode 100755
index 0000000..7c1e266
Binary files /dev/null and b/OpenFreezer/Docs/Copyright.doc differ
diff --git a/OpenFreezer/Docs/Copyright.odt b/OpenFreezer/Docs/Copyright.odt
new file mode 100755
index 0000000..76fd062
Binary files /dev/null and b/OpenFreezer/Docs/Copyright.odt differ
diff --git a/OpenFreezer/HeaderFunctions.php b/OpenFreezer/HeaderFunctions.php
new file mode 100755
index 0000000..dffa71d
--- /dev/null
+++ b/OpenFreezer/HeaderFunctions.php
@@ -0,0 +1,626 @@
+<?php
+/**
+ * Output page for main header, footer and side menu
+ *
+ * @author John Paul Lee <ninja_gara at hotmail.com>
+ * @version 2005
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @copyright	Mount Sinai Hospital, Toronto, Canada
+ *
+*/
+// Function: outputMainHeader()
+// Defn: Will output the main header that should go on all pages
+function outputMainHeader()
+{
+	global $Const_Table_Width;
+	global $hostname;
+
+	?>
+	<!--<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">-->
+	<HTML>
+		<HEAD>
+			<link href="styles/SearchStyle.css" rel="stylesheet" type="text/css">
+			<link href="styles/Header_styles.css" rel="stylesheet" type="text/css">
+			
+			<!-- August 14/07, Marina: For MS-Map - copied from Nexus -->
+			<LINK REL="stylesheet" HREF="styles/generic.css" type="text/css"/>
+			<!-- <script src="scripts/generic.js" language="javascript" type="text/javascript"></script>-->
+
+			<script type="text/javascript" src="scripts/menu.js"></script>
+
+			<!-- March 29, 2010: Incorporate overlib for sticky popups and tooltips -->
+			<script type='text/javascript' src='overlib/overlib.js'></script>
+			<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000"></div>
+		</HEAD>
+
+<!-- removed Oct. 3/07 - doesn't work on Mac OS X	<BODY onLoad="initAll()"> -->
+
+		<BODY style="width:98%; padding-right:10px;">
+
+			<!-- this is for infopops -->
+			<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>
+
+			<table id="header_table" cellpadding="0" cellspacing="0" style="background:#000000; width:100%;">
+				<tr><td style="padding:0;"><img src="pictures/hdr.png"></td><td><img src="pictures/tux.PNG" style="margin-left:2%;"></td></tr>
+			</table>
+
+            <div style="margin-top:5px; height:20px; padding-top:3px; background:maroon; color: white; font-weight:bold; font-size:9pt; width:100%; text-align:center;">Best viewed in <a href="http://www.mozilla.com/en-US/firefox/" style="color:yellow;">Mozilla Firefox®</a> prior to version 4</div>
+			<?php
+				// moved here Aug. 6/08
+				outputNavBar();
+			?>
+			<Div class="main">
+				<DIV class="main_content" style="padding:5px;" ID="mainDiv">
+				<?php
+}
+
+function outputMainFooter()
+{
+	global $cgi_path;		// Nov. 12/07
+
+// 			echo "</DIV>";	// moved here July 25/08 - close 'main'
+			?>
+				</DIV>	<!--close 'main_content'-->
+			</DIV>	<!--close 'main'-->
+
+			<DIV class="footer_container">
+				<DIV class="footer">
+					Copyright ©Mount Sinai Hospital, Toronto, Canada.
+<!--  <a class="footer" href="copyright.php">More Details</a> -->
+				</DIV>
+			</DIV>
+
+			<!-- Added Oct. 3/07, replacing onLoad initAll -->
+			<script type="text/javascript">initAll(); getEnzymes('<?php echo $cgi_path; ?>');</script>
+		</BODY>
+	</HTML>
+	<?php
+}
+
+function outputNavBar()
+{
+	global $cgi_path;
+// echo $cgi_path;
+	global $conn;		// Aug. 13, 2010
+// echo "ok";
+	$colspan_tmp = 0;
+	
+	// Array of section names
+	$currentSectionNames = array();
+
+	// Array of links to names
+	$currentSectionLinks = array();
+	
+	// Classify each header as to what OF section it belongs
+	$menuTypes = array();
+
+	// Jan. 12, 2010: change menu layout
+	$submenu_links = array();
+	$submenu_types = array();
+	$menuitems = array();	// to check permissions
+
+	// Differentiate between 'public' and 'private' pages
+	$publicSectionNames = array();
+	$publicSectionLinks = array();
+
+	$quickLinks = array();	// Aug. 13/10
+
+	$quickLinks["Reagent Tracker"][] = "Add reagents";
+	$quickLinks["Reagent Tracker"][] = "Search reagents";
+
+	$quickLinks["Location Tracker"][] = "Add containers";
+	$quickLinks["Location Tracker"][] = "Search containers";
+
+	$quickLinks["Project Management"][] = "Add projects";
+	$quickLinks["Project Management"][] = "Search projects";
+
+	$quickLinks["User Management"][] = "Change your password";
+	$quickLinks["User Management"][] = "View your orders";
+
+	// make a db map for quick links
+	$linksMap = array();
+
+	$links_rs = mysql_query("SELECT section, baseURL FROM SecuredPages_tbl WHERE status='ACTIVE'", $conn) or die("Cannot select menu links " . mysql_error());
+
+	while ($links_ar = mysql_fetch_array($links_rs, MYSQL_ASSOC))
+	{
+		$section = $links_ar["section"];
+		$baseURL = $links_ar["baseURL"];
+
+		$linksMap[$section] = $baseURL;
+	}
+
+	$currentSectionNames[] = "Home";
+	$currentSectionLinks["Home"] = "index.php";
+	$publicSections["Home"] = "index.php";
+	
+	// Reagent Tracker
+	$currentSectionNames[] = "Reagent Tracker";
+	$currentSectionLinks["Reagent Tracker"] = "Reagent.php?View=1";
+	$menuTypes["Reagent Tracker"] = "Reagent";
+
+	$publicSections["Reagent Tracker"] = "Reagent.php?View=1";
+
+	// Jan. 12, 2010
+	$submenu_types["Reagent Tracker"][] = "Reagents";
+	$submenu_types["Reagent Tracker"][] = "Reagent Types";
+
+	$submenu_links["Reagents"]["Add"] = "Reagent.php?View=2";
+	$submenu_links["Reagents"]["Search"] = "search.php?View=1";
+	$submenu_links["Reagents"]["Statistics"] = "Reagent.php?View=4";
+
+	$menuitems["Reagents"]["Add"] = "Add reagents";		// SecuredPages_tbl.section column value
+	$menuitems["Reagents"]["Search"] = "Search reagents";	// SecuredPages_tbl.section column value
+	$menuitems["Reagents"]["Statistics"] = "Statistics";	// SecuredPages_tbl.section column value
+
+	$submenu_links["Reagent Types"]["Add"] = "Reagent.php?View=3";
+	$submenu_links["Reagent Types"]["Search"] = "Reagent.php?View=5";
+
+	$menuitems["Reagent Types"]["Add"] = "Add reagent types";	// May 18, 2010
+	$menuitems["Reagent Types"]["Search"] = "Search reagent types";
+
+	// Location Tracker
+	$currentSectionNames[] = "Location Tracker";
+	$currentSectionLinks["Location Tracker"] = "Location.php?View=1";
+	$menuTypes["Location Tracker"] = "Location";
+
+	$publicSections["Location Tracker"] = "Location.php?View=1";
+
+	// Jan. 12, 2010
+	$submenu_types["Location Tracker"][] = "Containers";
+	$submenu_types["Location Tracker"][] = "Container Sizes";
+	$submenu_types["Location Tracker"][] = "Container Types";
+
+	$submenu_links["Container Types"]["Add"] = "Location.php?View=6&Sub=2";
+	$submenu_links["Container Types"]["Search"] = "Location.php?View=6&Sub=4";
+
+	$menuitems["Container Types"]["Add"] = "Add container types";
+	$menuitems["Container Types"]["Search"] = "Search container types";
+
+	$submenu_links["Container Sizes"]["Add"] = "Location.php?View=6&Sub=1";
+	$submenu_links["Container Sizes"]["Search"] = "Location.php?View=6&Sub=5";
+
+	$menuitems["Container Sizes"]["Add"] = "Add container sizes";
+	//$menuitems["Container Sizes"]["Search"] = "Search container sizes";
+
+	$submenu_links["Containers"]["Add"] = "Location.php?View=6&Sub=3";
+	$submenu_links["Containers"]["Search"] = "Location.php?View=2";
+
+	$menuitems["Containers"]["Add"] = "Add containers";
+	$menuitems["Containers"]["Search"] = "Search containers";
+
+	// Projects
+	$currentSectionNames[] = "Project Management";
+	$currentSectionLinks["Project Management"] = "Project.php?View=1";
+	$menuTypes["Project Management"] = "Project";
+	$submenu_types["Project Management"][] = "Projects";
+
+	$submenu_links["Projects"]["Add"] = "Project.php?View=1";
+	$submenu_links["Projects"]["Search"] = "Project.php?View=2";
+
+	$menuitems["Projects"]["Add"] = "Add Projects";
+	$menuitems["Projects"]["Search"] = "Search Projects";
+
+	// Users and Labs
+	$currentSectionNames[] = "User Management";
+	$currentSectionLinks["User Management"] = "User.php";
+	$menuTypes["User Management"] = "User";
+
+	$submenu_types["User Management"][] = "Users";
+
+	$submenu_links["Users"]["Add"] = "User.php?View=1";
+	$submenu_links["Users"]["Search"] = "User.php?View=2";
+
+	$submenu_links["Users"]["Change your password"] = "User.php?View=6";
+	$submenu_links["Users"]["Personal page"] = "User.php?View=7";
+	$submenu_links["Users"]["View your orders"] = "User.php?View=8";
+
+	$menuitems["Users"]["Add"] = "Add Users";
+	$menuitems["Users"]["Search"] = "Search Users";
+	$menuitems["Users"]["Change your password"] = "Change your password";
+	$menuitems["Users"]["Personal page"] = "Personal page";
+	$menuitems["Users"]["View your orders"] = "View your orders";
+
+	$currentSectionNames[] = "Lab Management";
+	$currentSectionLinks["Lab Management"] = "User.php";
+	$menuTypes["Lab Management"] = "Lab";
+	$submenu_types["Lab Management"][] = "Laboratories";
+
+	$submenu_links["Laboratories"]["Add"] = "User.php?View=3";
+	$submenu_links["Laboratories"]["Search"] = "User.php?View=4";
+
+	$menuitems["Laboratories"]["Add"] = "Add laboratories";
+	$menuitems["Laboratories"]["Search"] = "Search laboratories";
+
+	// July 28/08: Chemical Tracker
+	$currentSectionNames[] = "Chemical Tracker";
+	$currentSectionLinks["Chemical Tracker"] = "Chemical.php?View=1";
+	$menuTypes["Chemical Tracker"] = "Chemical";
+	
+	// Jan. 12, 2010
+	$submenu_types["Chemical Tracker"][] = "Chemicals";
+	
+	$submenu_links["Chemicals"]["Add"] = "Chemical.php?View=2";
+	$submenu_links["Chemicals"]["Search"] = "Chemical.php?View=1";
+
+	$menuitems["Chemicals"]["Add"] = "Add Chemicals";
+	$menuitems["Chemicals"]["Search"] = "Search Chemicals";
+
+	$currentSectionNames[] = "Documentation";
+	$currentSectionLinks["Documentation"] = "docs.php";
+	$publicSections["Documentation"] = "docs.php";
+
+ 	$currentSectionNames[] = "Terms and Conditions";
+ 	$currentSectionLinks["Terms and Conditions"] = "copyright.php";
+	$publicSections["Terms and Conditions"] = "copyright.php";
+
+	$currentSectionNames[] = "Help and Support";
+ 	$currentSectionLinks["Help and Support"] = "bugreport.php";
+	$publicSections["Help and Support"] = "bugreport.php";
+	
+ 	$currentSectionNames[] = "Contact Us";
+ 	$currentSectionLinks["Contact Us"] = "contacts.php";
+	$publicSections["Contact Us"] = "contacts.php";
+
+	$counter = 0;
+
+	?>
+	<div class="sidemenu" ID="mainMenu">
+		<div class="menu-content">
+<!-- 			<ul class="menulist"> -->
+			<ul id="nav" class="menu">
+			<?php
+				// June 4/07, Marina: Hide restricted pages, according to user roles: (sort of 'private' and 'public' pages)
+				$loginBlock = new MemberLogin_Class();  
+				$loginBlock->loginCheck($_POST);
+
+				// Output the menu link IFF the user is authorized to access that page
+				if (isset($_SESSION["userinfo"]))
+				{
+					foreach ($currentSectionNames as $i => $name)
+					{
+						echo "<LI>";
+						
+						if (($loginBlock->verifySections($name, $_SESSION["userinfo"]->getCategory())))
+						{
+							if ($menuTypes[$name])
+							{
+								$counter = 0;
+
+								echo "<DIV style=\"border-top:3px double #FFF8DC; border-right:3px double #FFF8DC; border-bottom:3px double #FFF8DC; border-left:6px double #FFF8DC; margin-top:2px; width:166px; padding-top:5px; padding-bottom:5px;\">";
+
+									echo "<DIV style=\"background-image:url('pictures/small_bg.png'); width:166px; height:30px;\">";
+
+										echo "<select style=\"cursor:pointer; width:150px; background:#FFF8DC; font-weight:bold; color:#555; font-size:9pt; font-family:Helvetica; position:absolute; top:10; left:10; border:0;\" onChange=\"if ((window.location.toString().indexOf('Reagent.php?View=2') >= 0) && (window.location.toString().indexOf('&rID') >= 0)){result = confirm('Are you sure you want to navigate away from this page?  Your input will be lost.'); if (result) cancelReagentCreation(); return result;} else{op [...]
+
+											echo "<option selected style=\"cursor:pointer; font-weight:bold; color:#555; font-size:9pt; position:absolute; top:13; left:16; border:0; font-family:Helvetica;\" value=\"\"> " . $name . "</option>";
+
+
+											foreach ($submenu_types[$name] as $stKey => $stName)
+											{
+												$nAllowed = 0;
+	
+												foreach ($submenu_links[$stName] as $slKey => $sLink)
+												{
+													if (($loginBlock->verifySections($menuitems[$stName][$slKey], $_SESSION["userinfo"]->getCategory())))
+													{
+														$nAllowed++;
+													}
+												}
+			
+												if ($nAllowed > 0)
+												{
+													// $stName is e.g. 'Chemicals'
+													echo "<option style=\"font-family:Helvetica; cursor:pointer; background-color:#FFF8DC; border:0; font-weight:bold; font-family:Helvetica; font-size:8pt; text-decoration:none; color:#555; margin-left:2px;\" value=\"\">  " . strtoupper($stName) . "</option>";
+		
+													foreach ($submenu_links[$stName] as $slKey => $sLink)
+													{
+														if (($loginBlock->verifySections($menuitems[$stName][$slKey], $_SESSION["userinfo"]->getCategory())))
+														{
+															echo "<option style=\"font-weight:bold; color:#555; background:#EFEFEF; font-size:8pt; border:0; outline:none; font-family:Helvetica; cursor:pointer;\" value=\"" . $sLink . "\">    " . $slKey . "</option>";
+														}
+													}
+												}
+											}
+
+										echo "</select>";
+									echo "</div>";
+
+									if (in_array($name, array_keys($quickLinks)))
+									{
+										// Quick links - also by permission
+										echo "<div id=\"quick_links_" . $name . "\" style=\"font-family:Helvetica; width:166px; padding-bottom:0; margin-top:0; padding-top:2px; padding-left:7px;\">";
+	
+											echo "<UL style=\"width:90%; font-family:Helvetica; display:inline;\">";
+	
+												foreach ($quickLinks[$name] as $qlKey => $qlName)
+												{
+													if (($loginBlock->verifySections($qlName, $_SESSION["userinfo"]->getCategory())))
+													{
+														echo "<LI><img  src=\"pictures/silvermenubullet.png\" width=\"7\" height=\"6\" style=\"padding-bottom:2px;\"> <a style=\"font-weight:bold; font-size:8pt; font-family:Helvetica; text-decoration:none; color:#555; margin-left:2px;\" onclick=\"if ((window.location.toString().indexOf('Reagent.php?View=2') >= 0) && (window.location.toString().indexOf('&rID') >= 0)){result = confirm('Are you sure you want to navigate away from this page?  Your input will be lost.'); if (resul [...]
+													}
+												}
+											echo "</UL>";
+										echo "</DIV>";
+									}
+
+								echo "</div>";
+							}
+							else
+							{
+								if (strcasecmp($name, "Home") == 0)
+									echo "<DIV style=\"background:url('pictures/small_bg.png') repeat-y; border-top: 2px solid #FFF8DC; border-left:6px double #FFF8DC; border-right:6px double #FFF8DC; padding-top:7px; margin-top:2px; width:166px; padding-bottom:8px;\">";
+								else
+									echo "<DIV style=\"background:url('pictures/small_bg.png') repeat-y; border-left:6px double #FFF8DC; border-right:6px double #FFF8DC; padding-top:7px; margin-top:2px; width:166px; padding-bottom:8px;\">";
+
+									// OK - bullet image - KEEP
+									echo "<img src=\"pictures/silvermenubullet.png\" style=\"width:11px; height:9px; margin-left:5px;\">";
+
+									// actual inscription (don't have to make it h/l actually)
+									echo "<a onclick=\"if ((window.location.toString().indexOf('Reagent.php?View=2') >= 0) && (window.location.toString().indexOf('&rID') >= 0)){result = confirm('Are you sure you want to navigate away from this page?  Your input will be lost.'); if (result) cancelReagentCreation(); return result;}\" style=\"font-weight:bold; color:#555; font-size:9pt; font-family:Helvetica; padding-left:3px; text-decoration:none;\" href=\"" . $currentSectionLinks[$name] . "\">" . $name . "</a>";
+
+								echo "</DIV>";
+							}
+						}
+					}
+
+					echo "</LI>";
+
+					?><form name="curr_user_form" style="display:none" method="post" action="<?php echo $cgi_path . "user_request_handler.py"; ?>">
+						<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $_SESSION["userinfo"]->getDescription(); ?>">
+						<INPUT type="hidden" id="curr_user_hidden" name="view_user" VALUE="<?php echo $_SESSION["userinfo"]->getUserID(); ?>">
+					</FORM><?php
+
+				}
+				else
+				{
+					printGeneralMenu($publicSections);
+				}
+			?>
+			</UL>
+
+			<div class="login">
+			<?php
+				// print login block on the menu side
+				$loginBlock = new MemberLogin_Class();
+				$loginBlock->loginCheck($_POST);
+				$loginBlock->printLoginInfo("?View=1");
+			?>
+			</div>
+		</div>
+	</div>
+
+	<!-- Marina: March 4/08: Create a resizeable border -->
+<!-- 	<div id="mainBorder" class="resizeableRight" onMouseDown="resize();"></div> -->
+	<?php
+}
+
+function printGeneralMenu($publicSections)
+{
+	// Output general info pages - homepage, docs, copyright, contact us
+	foreach ($publicSections as $name => $url)
+	{
+		if (strcasecmp($name, "Home") == 0)
+			echo "<DIV style=\"background:url('pictures/small_bg.png') repeat-y; border-top: 2px solid #FFF8DC; border-left:6px double #FFF8DC; padding-top:7px; margin-top:2px; width:166px; padding-bottom:8px;\">";
+		else
+			echo "<DIV style=\"background:url('pictures/small_bg.png') repeat-y; border-left:6px double #FFF8DC; padding-top:7px; margin-top:2px; width:160px; padding-bottom:8px;\">";
+
+			// OK - bullet image - KEEP
+			echo "<img src=\"pictures/silvermenubullet.png\" style=\"width:11px; height:9px; margin-left:5px;\">";
+
+			// actual inscription (don't have to make it h/l actually)
+			echo "<a onclick=\"if ((window.location.toString().indexOf('Reagent.php?View=2') >= 0) && (window.location.toString().indexOf('&rID') >= 0)){result = confirm('Are you sure you want to navigate away from this page?  Your input will be lost.'); if (result) cancelReagentCreation(); return result;}\" style=\"font-weight:bold;  color:#555; font-size:9pt; padding-left:3px; text-decoration:none;\" href=\"" . $url . "\">" . $name . "</a>";
+
+		echo "</DIV>";
+	}
+}
+
+
+// Signature modified July 16/07 by Marina - Added $loginBlock parameter
+function outputSubmenu_header($submenu_type, $loginBlock)
+{
+	global $cgi_path;
+
+	$current_selection_names_ar = array();
+	$current_selection_links_ar = array();
+	
+	switch ($submenu_type)
+	{
+		case "Location":
+		
+			$location_submenu_names_ar = array();
+			$location_submenu_links_ar = array();
+
+			$location_submenu_names_ar[] = "Add container types";
+			$location_submenu_links_ar[] = "Location.php?View=6&Sub=2";
+
+			// Jan. 8, 2010
+			$location_submenu_names_ar[] = "Search container types";
+			$location_submenu_links_ar[] = "Location.php?View=6&Sub=4";
+
+			$location_submenu_names_ar[] = "Add container sizes";
+			$location_submenu_links_ar[] = "Location.php?View=6&Sub=1";
+
+			// Jan. 8, 2010
+			//$location_submenu_names_ar[] = "Search container sizes";
+			//$location_submenu_links_ar[] = "Location.php?View=6&Sub=5";
+
+			$location_submenu_names_ar[] = "Add containers";
+			$location_submenu_links_ar[] = "Location.php?View=6&Sub=3";
+
+			$location_submenu_names_ar[] = "Search containers";
+			$location_submenu_links_ar[] = "Location.php?View=2";
+
+			$current_selection_names_ar = $location_submenu_names_ar;
+			$current_selection_links_ar = $location_submenu_links_ar;
+			
+		break;
+
+
+		case "Reagent":
+		
+			$reagent_submenu_names_ar = array();
+			$reagent_submenu_links_ar = array();
+			
+			$reagent_submenu_names_ar[] = "Add reagents";
+			$reagent_submenu_links_ar[] = "Reagent.php?View=2";
+			
+			$reagent_submenu_names_ar[] = "Search reagents";
+			$reagent_submenu_links_ar[] = "search.php?View=1";
+
+			// June 3, 2009
+			$reagent_submenu_names_ar[] = "Search reagent types";
+			$reagent_submenu_links_ar[] = "Reagent.php?View=5";
+
+			$current_selection_names_ar = $reagent_submenu_names_ar;
+			$current_selection_links_ar = $reagent_submenu_links_ar;
+			
+		break;
+
+		
+		// July 28/08
+		case "Chemical":
+		
+			$chemical_submenu_names_ar = array();
+			$chemical_submenu_links_ar = array();
+			
+			$chemical_submenu_names_ar[] = "Add chemicals";
+			$chemical_submenu_links_ar[] = "Chemical.php?View=2";
+
+			$chemical_submenu_names_ar[] = "Search chemicals";
+			$chemical_submenu_links_ar[] = "Chemical.php?View=1";
+
+			$current_selection_names_ar = $chemical_submenu_names_ar;
+			$current_selection_links_ar = $chemical_submenu_links_ar;
+			
+		break;	
+		
+		// May 30/07, Marina: Project Management section
+		case "Project":
+			
+			$project_submenu_names_ar[] = "Add projects";
+			$project_submenu_links_ar[] = "Project.php?View=1";
+			
+			$project_submenu_names_ar[] = "Search projects";
+			$project_submenu_links_ar[] = "Project.php?View=2";
+			
+//			$project_submenu_names_ar[] = "Delete Projects";
+//			$project_submenu_links_ar[] = "Project.php?View=3";
+			
+			$current_selection_names_ar = $project_submenu_names_ar;
+			$current_selection_links_ar = $project_submenu_links_ar;
+		break;
+		
+		
+		// July 11/07, Marina: User Management section
+		case "User":
+		
+//			$user_submenu_names_ar[] = "Delete Users";
+//			$user_submenu_links_ar[] = "User.php?View=2";
+
+			$user_submenu_names_ar[] = "Add users";
+			$user_submenu_links_ar[] = "User.php?View=1";
+			
+			$user_submenu_names_ar[] = "Search users";
+			$user_submenu_links_ar[] = "User.php?View=2";
+			
+			$user_submenu_names_ar[] = "Change your password";
+			$user_submenu_links_ar[] = "User.php?View=6";
+
+			$user_submenu_names_ar[] = "Personal page";
+			$user_submenu_links_ar[] = "User.php?View=7";
+
+			// Jan. 23/08: Order clones
+			$user_submenu_names_ar[] = "View your orders";
+			$user_submenu_links_ar[] = "User.php?View=8";
+		
+			$current_selection_names_ar = $user_submenu_names_ar;
+			$current_selection_links_ar = $user_submenu_links_ar;
+		break;
+		
+		case "Lab":
+			
+			$lab_submenu_names_ar[] = "Add laboratories";
+			$lab_submenu_links_ar[] = "User.php?View=3";
+			
+			$lab_submenu_names_ar[] = "Search laboratories";
+			$lab_submenu_links_ar[] = "User.php?View=4";
+			
+			$current_selection_names_ar = $lab_submenu_names_ar;
+			$current_selection_links_ar = $lab_submenu_links_ar;
+		break;
+	}
+	
+	foreach ($current_selection_names_ar as $i => $name)
+	{
+		// July 16/07, Marina: There can be permission differentiations within a menu section as well (e.g. Projects - only Creators can create, buit Writers can view)
+		if ( ($loginBlock->verifySections($name, $_SESSION["userinfo"]->getCategory())) )
+		{
+			// Sept. 17/07: User page (quasi-hack to pass control to CGI)
+			if (strcasecmp($name, "Personal page") == 0)
+			{
+				echo "<LI>";
+// 				echo "<IMG SRC=\"pictures/star_bullet.gif\" WIDTH=\"10\" HEIGHT=\"10\" BORDER=\"0\" ALT=\"star\" class=\"menu-leaf\">";
+
+				echo "<span class=\"linkShow\" style=\"font-size:9pt\" onClick=\"redirectToCurrentUserDetailedView(" . $_SESSION["userinfo"]->getUserID() .  ");\">" . $name . "</span>";
+
+				echo "</LI>";
+				?>
+				<form name="curr_user_form" style="display:none" method="post" action="<?php echo $cgi_path . "user_request_handler.py"; ?>">
+					<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $_SESSION["userinfo"]->getDescription(); ?>">
+					<INPUT type="hidden" id="curr_user_hidden" name="view_user" VALUE="<?php echo $_SESSION["userinfo"]->getUserID(); ?>">
+				</FORM>
+				<?php
+			}
+			else
+			{
+				echo "<LI>";
+	
+// 				echo "<IMG SRC=\"pictures/star_bullet.gif\" WIDTH=\"10\" HEIGHT=\"10\" BORDER=\"0\" ALT=\"plus\" class=\"menu-leaf\">";
+	
+				echo "<a class=\"top_title\" class=\"submenu\" href=\"" . $current_selection_links_ar[$i] . "\">" . $name . "</a>";
+				echo "</LI>";
+			}
+		}
+	}
+}
+
+function getLocation_submenu_links()
+{
+}
+
+function outputLoginBlock( $trailing, $loginBlock )
+{
+	if( isset( $_SESSION["userinfo"] ) ) 
+		{ 
+			if( $loginBlock->verifyPermissions( basename( $_SERVER["PHP_SELF"] ), $_SESSION["userinfo"]->getUserID()))
+			{
+				echo "basename: " .  basename( $_SERVER['PHP_SELF'] ) . "<BR>";
+				echo "username: " .  $_SESSION['userinfo']->getUserID( ) . "<BR>";
+				$loginBlock->printLoginInfo();
+			}
+			else
+			{
+				echo "basename: " .  basename( $_SERVER['PHP_SELF'] ) . "<BR>";
+				echo "username: " .  $_SESSION['userinfo']->getUserID( ) . "<BR>";
+				echo "FAILED!";
+			}
+		}
+	else
+	{
+
+	?>
+		<FORM METHOD="POST" ACTION="<?php echo $_SERVER['PHP_SELF'] . $trailing; ?>" style="float:right">
+			Username: <INPUT type="text" value="" name="loginusername_field"> 
+			Password: <INPUT type="password" value="" name="loginpassword_field">
+			Automatic Login <INPUT type="checkbox" value="" name="persistentlogin_field"> 
+
+			<INPUT TYPE="SUBMIT" NAME="loginsubmit" VALUE="Loginsubmit">
+		</FORM>
+	<?php
+	}
+}
+?>
diff --git a/OpenFreezer/Location.php b/OpenFreezer/Location.php
new file mode 100755
index 0000000..fb63ac7
--- /dev/null
+++ b/OpenFreezer/Location.php
@@ -0,0 +1,613 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Location
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Include/require statements
+*/
+
+	include "Classes/MemberLogin_Class.php";
+	include "Classes/Member_Class.php";
+	include "Classes/Session_Var_Class.php";
+	include "Classes/Order_Class.php";	// Jan. 23/08
+	include "Classes/generalFunc_Class.php";
+	include "Classes/HT_Class.php";
+	include "Classes/StopWatch.php";
+	include "Classes/ColFunctOutputer.php";
+
+	include "Location/Location_Funct_Class.php";
+	include "Location/Location_Output_Class.php";
+	include "Location/Location_Admin_Class.php";
+	include "Location/Location_Creator_Class.php";
+	include "Location/Location_Well_Class.php";
+
+	include "DatabaseConn.php";
+	include "HeaderFunctions.php";
+
+	include "Reagent/Reagent_Background_Class.php";	// april 16/07, Marina
+
+	include "Project/ProjectFunctions.php";		// August 13/07, Marina
+
+/**
+ * Central Location deploy page
+ *
+ * @author John Paul Lee @version 2005
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Search
+ *
+ * @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+	
+	/**
+	 * A constant used to define table width on User module views
+	 * @global INT $Const_Table_Width
+	*/
+	global $Const_Table_Width;
+
+	session_start();
+
+	$loginBlock = new MemberLogin_Class( );  
+	$loginBlock->loginCheck( $_POST );
+
+	header("Cache-control: private"); //IE 6 Fix 
+
+	$colspan_const = 0;
+
+	// print header	
+	outputMainHeader();
+	
+	?>
+	<title>OpenFreezer Location Page</title>
+
+	<table height="100%">
+		<table border="0" width="100%">
+			<!-- Marina: March 4/08: Create a resizeable border -->
+			<!--<tr>
+				<td rowspan="100%" style="padding-left:0; padding-right:5px;">
+					<div class="resizeable" onMouseDown="resize();"></div>
+				</td>
+			</tr>-->
+		<?php
+
+		if (isset($_SESSION["userinfo"]))
+		{
+			if ($loginBlock->verifyPermissions(basename($_SERVER['PHP_SELF']), $_SESSION['userinfo']->getUserID()))
+			{
+				$sessionChecker = new Session_Var_Class();
+				$sessionChecker->checkSession_all();	// Dec. 21/09
+				unset( $sessionChecker );
+
+				?>
+				<tr>
+					<td>
+					<?php
+						if ($_GET["View"] == "1")
+						{
+							if (isset($_POST["location_view1_changeview_submit"]))
+							{
+								if ($_POST["location_view1_currentgroup_hidden"] == "1")
+								{
+									$currentGrouping = 2;
+								}
+								else
+								{
+									$currentGrouping = 1;
+								}
+							}
+							else
+							{
+								$currentGrouping = 1;
+							}
+
+							// View 1
+							// Basic view for general location information, nothing more
+							$loc_obj = new Location_Output_Class();
+// 							$loc_obj->init_Location_vars();
+							$gfunc_obj = new generalFunc_Class();	// feb. 15/08
+
+							if( isset( $_GET["rid"] ) )
+							{
+								// Jan. 23/08: Order reagents
+								$lfunc_obj = new Location_Funct_Class();
+
+								if (isset($_POST["addToOrder"]) && $_POST["addToOrder"] == "1")
+								{
+									$tmp_rid = $_POST["orderReagentID"];
+									$tmp_iso = $_POST["orderIsolateNum"];
+									$tmp_cont = $_POST["orderContainerID"];
+									$tmp_row = $_POST["orderRow"];
+									$tmp_col = $_POST["orderCol"];
+
+									// Add order IFF does not exist
+									if (!$lfunc_obj->inOrder($tmp_rid, $tmp_iso, $tmp_cont, $tmp_row, $tmp_col))
+									{
+										$tempOrder = new Order_Class($tmp_rid, $tmp_iso, $tmp_cont, $tmp_row, $tmp_col);
+	
+										$tmpUserOrders = $_SESSION["userinfo"]->getOrders();
+	
+										if (sizeof($tmpUserOrders) == 0)
+										{
+											$tmp_orders = Array();
+											$tmp_orders[] = $tempOrder;
+											$_SESSION["userinfo"]->setOrders($tmp_orders);
+										}
+										else
+										{
+											$tmpUserOrders[] = $tempOrder;
+											$_SESSION["userinfo"]->setOrders($tmpUserOrders);
+										}
+									}
+								}
+
+								// Changes made Feb. 15/08
+								if ($currentGrouping == 1)
+								{
+									$currView = "Group by Container";
+									$switchTo = "Group by Isolate";
+
+									$contViewClass = "currentView";
+									$isoViewClass = "switchTo";
+
+									$contSpanClass = "tabLinkActive";
+									$isoSpanClass =  "tabLinkInactive";
+
+									$caption = "Locations of " . $_SESSION["ReagentType_ID_Name"][$gfunc_obj->getTypeID($_GET["rid"])] . " " . $gfunc_obj->getConvertedID_rid($_GET["rid"]) . " grouped by Container:";
+								}
+								else
+								{
+									$currView = "Group by Isolate";
+									$switchTo = "Group by Container";
+						
+									$isoViewClass = "currentView";
+									$contViewClass = "switchTo";
+
+									$contSpanClass = "tabLinkInactive";
+									$isoSpanClass =  "tabLinkActive";
+
+									$caption = "Locations of " . $_SESSION["ReagentType_ID_Name"][$gfunc_obj->getTypeID($_GET["rid"])] . " " . $gfunc_obj->getConvertedID_rid($_GET["rid"]) . " grouped by Isolate:";
+								}
+								?>
+								<TABLE width="100%" cellpadding="2" cellspacing="1">
+									<TR>
+										<TD>
+											<TABLE id="tabsTbl" cellspacing="0">
+												<TR>
+													<TD style="padding-left:1px;" class="<?php echo $contViewClass; ?>">
+														<span id="groupByContainerTab" class="<?php echo $contSpanClass; ?>"  onClick="groupByContainer();">  Group by Container  </span>
+													</TD>
+			
+													<TD class="<?php echo $isoViewClass; ?>">
+														<span id="groupByIsolateTab" class="<?php echo $isoSpanClass?>" style="padding-left:38px; padding-right:38px;" onClick="groupByIsolate();">Group by Isolate</span>
+													</TD>
+												</TR>
+											</TABLE>
+										</TD>
+									</TR>
+
+									<form NAME="viewLocation" action="<?php echo $_SERVER["PHP_SELF"]; ?>?View=1&rid=<?php echo $_GET["rid"]; ?>" method="post">
+
+										<input type="hidden" id="location_output_mode" name="location_view1_currentgroup_hidden" VALUE="<?php echo $_POST["location_view1_currentgroup_hidden"]; ?>">
+	
+										<SPAN style="font-weight:bold; font-size:10pt; text-align:left; text-decoration:none; padding-left:8px; color:#545454;">Locations of <?php echo $_SESSION["ReagentType_ID_Name"][$gfunc_obj->getTypeID($_GET["rid"])] . " " . $gfunc_obj->getConvertedID_rid($_GET["rid"]); ?></SPAN><BR><BR>
+	
+										<!-- Feb. 15/08 -->
+										<input type="hidden" name="location_view1_changeview_submit" value="<?php echo $switchTo; ?>">
+	
+										<!-- Jan. 23/08: Order clones -->
+										<INPUT TYPE="hidden" ID="order_rid" NAME="orderReagentID">
+	
+										<INPUT TYPE="hidden" ID="order_iso_num" NAME="orderIsolateNum">
+	
+										<INPUT TYPE="hidden" ID="order_cont_id" NAME="orderContainerID">
+	
+										<INPUT TYPE="hidden" ID="order_row" NAME="orderRow">
+	
+										<INPUT TYPE="hidden" ID="order_col" NAME="orderCol">
+	
+										<INPUT TYPE="hidden" ID="order_placed" NAME="addToOrder" VALUE="0">
+									</form>
+
+									<TR><TD class="locationContent">
+									<?php
+										echo "<SPAN style=\"font-size:10pt; font-weight:bold; color:#0000CD;\">" . $caption . "</SPAN><BR><BR>";
+
+										$loc_obj->printIsolates_ExpandedView( $_GET["rid"], $currentGrouping );
+									?>
+									</TD></TR>
+								</TABLE>
+								<?php
+							}
+							else
+							{
+								// Feb 9, Marina -- Replace with a short index page
+								$loc_obj->print_Location_info();
+							}
+						}
+						elseif( $_GET["View"] == "2" )
+						{
+							// View 2
+							// View choice menu information options		** (the drop-down container selection -- Marina)
+							$loc_obj = new Location_Output_Class();
+
+							# May 22/07, Marina
+							$lfunc_obj = new Location_Funct_Class();
+
+							if (isset($_POST["cont_name_selection"]) && isset($_POST["cont_plate_selection"]))
+							{
+								$loc_obj->printForm($_POST);
+								$loc_obj->outputPlateView_groupID($_SESSION["Container_Name_ID"][$_POST["cont_name_selection"]], $_POST["cont_plate_selection"]);
+							}
+							else if (isset($_GET["gID"]))
+							{
+								$_POST["cont_name_selection"] = $_GET["gID"];
+								$loc_obj->printForm($_POST);
+							}
+							elseif(isset($_GET["Mod"]))
+							{
+								$loc_obj->outputPlateView_contID($_GET["Mod"]);
+							}
+							elseif(!isset($_POST["cont_name_selection"]))
+							{
+								$loc_obj->printForm($_POST);
+							}
+							elseif (isset($_POST["cont_name_selection"]) && strcasecmp($_POST["cont_name_selection"], "No container selected") == 0)
+							{
+								$loc_obj->printForm($_POST);
+							}
+							else
+							{
+								$loc_obj->printForm($_POST);
+							}
+						}
+						elseif ($_GET["View"] == "3")
+						{
+							if (isset($_GET["Sub"]))
+							{
+								if ($_GET["Sub"] == "1")
+								{
+									$loc_obj = new Location_Admin_Class();
+									$loc_obj->printContainerStorageInfo($_GET["Mod"], true);
+								}
+							}
+							else
+							{
+								if (isset($_GET["Mod"]))
+								{
+									// Jan. 3, 2010: View the container's storage (freezer, fridge, LN tank, etc.)
+									$loc_obj = new Location_Admin_Class();
+
+									// Check user access here!!!!!!!!!!
+									// ...........
+
+									$loc_obj->printContainerStorageInfo($_GET["Mod"]);
+								}
+								else	// feb. 24/10
+								{
+									$loc_obj = new Location_Output_Class();
+									$loc_obj->printErrPage("Invalid selection!");
+								}
+							}
+						}
+						elseif ($_GET["View"] == "4")
+						{
+							// Feb. 24/10: this is going to be container sizes search view but restrict for now
+							$loc_obj = new Location_Output_Class();
+							$loc_obj->printErrPage("Invalid selection!");
+						}
+						// View 5
+						// View for modifying and admining all containers
+						elseif ($_GET["View"] == "5")
+						{
+// Feb. 24/10: again, check access here
+// .............
+
+							$loc_obj = new Location_Admin_Class();
+
+							if( isset( $_POST["cont_name_selection"] ) && !isset( $_GET["Mod"] ) )
+							{
+								$loc_obj->printContainerInfo( $_SESSION["Container_Name_ID"][$_POST["cont_name_selection"]] );
+							}
+							elseif( isset( $_GET["Mod"] ) && !isset( $_POST["cont_modify_button"] ) )
+							{
+								$loc_obj->printModifyContainer_Form( "", $_GET["Mod"] );
+							}
+							elseif (isset($_POST["cont_modify_button"]))
+							{
+								$loc_obj->printModifyContainer_Form($loc_obj->updateContainerInfo($_POST), $_GET["Mod"]);
+							}
+							elseif (isset($_POST["container_submit_button"]))
+							{
+								$loc_obj->printContainerInfo( $_SESSION["Container_Name_ID"][$_POST["cont_name_selection"]] );
+							}
+							else if (isset($_GET["Del"]))
+							{
+								if ($_GET["Del"] == 1)
+								{
+									echo "<span style=\"font-size:10pt; font-weight:bold; color:brown;\">Container deleted successfully.</span>";
+								}
+							}
+							else	// feb. 24/10
+							{
+								$loc_obj = new Location_Output_Class();
+								$loc_obj->printErrPage("Invalid selection!");
+							}
+						}
+						// View 6
+						// View for creating new types of containers
+						elseif ($_GET["View"] == "6")
+						{
+// Feb. 24/10: add access check!!!!!!
+
+							$loc_obj = new Location_Creator_Class();
+		
+							if (isset($_GET["Sub"]))
+							{
+								if ($_GET["Sub"] == "1")
+								{
+									// Submenu Section: New Container **Sizes**
+									if (isset($_POST["cont_type_create_button"]))
+									{
+										$loc_obj->process_submit($_POST);
+									}
+
+									$loc_obj->printForm_newTypes();
+								}
+								elseif ($_GET["Sub"] == "2")
+								{
+									$loc_obj->printForm_addNewContainerTypes();
+								}
+								elseif( $_GET["Sub"] == "3" ) 
+								{
+									// Modified Sept. 18/07 by Marina
+									// Creation processing performed by CGI, redirected to newly created plate
+									if (isset($_GET["Mod"]))
+									{
+										$loc_obj = new Location_Output_Class();
+										$lfunc_obj = new Location_Funct_Class();
+
+										$loc_obj->outputPlateView_contID($_GET["Mod"]);
+									}
+									else
+									{
+										$loc_obj->printForm_newContainers();
+									}
+								}
+								elseif ($_GET["Sub"] == "4")
+								{
+									// Jan. 8, 2010 - View container types
+									$loc_obj = new Location_Output_Class();
+
+									if (isset($_GET["contTypeID"]))
+									{
+										if (isset($_GET["Mod"]))
+										{
+											// Print container type in Modify mode
+											$loc_obj->print_Detailed_Cont_Type($_GET["contTypeID"], true);
+										}
+										else
+										{
+											// Print detailed view of selected container type
+											$loc_obj->print_Detailed_Cont_Type($_GET["contTypeID"], false);
+										}
+									}
+									else if (isset($_POST["contTypeList"]))
+									{
+										// Print detailed view of selected container type
+										$loc_obj->print_Detailed_Cont_Type($_POST["contTypeList"], false);
+									}
+									else if (isset($_GET["Del"]))
+									{
+										echo "<SPAN style=\"font-weight:bold; color:maroon;\">Container type deleted successfully.</SPAN><BR><P>";
+
+										echo "<a href='" . $_SERVER["PHP_SELF"] . "?View=6&Sub=4'>Back to container types list</a>";
+									}
+									else
+									{
+										// Print container types selection list
+										$loc_obj->printContainerTypesList();
+									}
+								}
+							}
+							else	// feb. 24/10
+							{
+								$loc_obj = new Location_Output_Class();
+								$loc_obj->printErrPage("Invalid selection!");
+							}
+						}
+						// View 7
+						// View for inserting new wells
+						elseif( $_GET["View"] == "7" ) 
+						{
+							if (isset($_POST["well_new_button"]))
+							{
+								$loc_well_obj = new Location_Well_Class();
+								$loc_well_obj->create_wells( $_POST, $_GET["Mod"] );
+							}
+
+							elseif (isset($_POST["well_unreserve_button"]))
+							{
+								$loc_well_obj = new Location_Well_Class();
+								$loc_well_obj->unreserve_wells($_POST, $_GET["Mod"]);
+							}
+
+							elseif (isset($_POST["well_delete_button"]))
+							{
+								$loc_well_obj = new Location_Well_Class();
+								$loc_well_obj->delete_wells($_POST, $_GET["Mod"]);
+							}
+
+							elseif( isset( $_POST["well_modify_button"] ) )
+							{
+								$loc_well_obj = new Location_Well_Class();
+								$loc_well_obj->printForm_modify( $_POST["wells_checkbox"], $_GET["Mod"], false );
+							}
+
+							elseif( isset( $_POST["well_mod_submit_button"] ) )
+							{
+								$loc_well_obj = new Location_Well_Class();
+
+								if ($loc_well_obj->process_modify($_GET["Mod"]) === true)
+								{
+									$loc_obj = new Location_Output_Class();
+									$loc_obj->outputPlateView_contID($_GET["Mod"]);
+								}
+								else
+								{
+									$loc_well_obj->printForm_modify( $_SESSION["wells_checkbox_tmp"], $_GET["Mod"], true );
+								}
+							}
+
+							// Added April 24/07 -- Add Cancel button to well creation/modification views
+							elseif (isset($_POST["well_mod_cancel_button"]))
+							{
+								if( isset( $_GET["Mod"] ) )
+								{
+									$loc_obj = new Location_Output_Class();
+									$loc_obj->outputPlateView_contID( $_GET["Mod"] );
+								}
+							}
+
+							// Cancel button for well creation view
+							// The well would still be reserved, but if the user changes his/her mind and decides to not put anything in the well, s/he can cancel his/her action in an elegant way instead of pressing browser's Back button
+							// Update Jan. 7, 2010: I think the well should be unreserved if user decides to cancel.
+							elseif (isset($_POST["well_create_cancel_button"]))
+							{
+								$loc_well_obj = new Location_Well_Class();
+
+								if (isset($_GET["Mod"]))
+								{
+									$loc_obj = new Location_Output_Class();
+									$loc_obj->outputPlateView_contID($_GET["Mod"]);
+								}
+							}
+
+							elseif( isset( $_POST["mod_empty_well_cancel"] ) )
+							{
+								if( isset( $_GET["Mod"] ) )
+								{
+									$loc_obj = new Location_Output_Class();
+									$loc_obj->outputPlateView_contID( $_GET["Mod"] );
+								}
+							}
+
+							elseif( isset( $_POST["well_limsid_submit_button"] ) )
+							{
+								$loc_well_obj = new Location_Well_Class();
+
+								if ($loc_well_obj->process_firstStage( $_POST , $_GET["Mod"] ) === true)
+								{
+									$loc_obj = new Location_Output_Class();
+
+									if( isset( $_GET["Mod"] ) )
+									{
+										$loc_obj->outputPlateView_contID( $_GET["Mod"] );
+									}
+								}
+								else
+								{
+									// Creation failed
+									$loc_well_obj->create_wells( $_SESSION["wells_checkbox_tmp"], $_GET["Mod"], true);
+								}
+							}
+							elseif (isset( $_POST["well_delete_submit_button"] ))
+							{
+								$loc_well_obj = new Location_Well_Class();
+
+								if ($loc_well_obj->process_delete( $_SESSION["wells_checkbox_tmp"], $_GET["Mod"] ))
+								{
+									$loc_obj = new Location_Output_Class();
+
+									if( isset( $_GET["Mod"] ) )
+									{
+										$loc_obj->outputPlateView_contID( $_GET["Mod"] );
+									}
+								}
+								else
+								{
+									// echo "Deletion failed <br>";
+								}
+							}
+							else	// feb. 24/10
+							{
+								$loc_obj = new Location_Output_Class();
+								$loc_obj->printErrPage("Invalid selection!");
+							}
+						}
+
+						?>
+						</td>
+					</tr>
+					<?php
+				}
+				else
+				{
+					// May 30/07, Marina
+					echo "<tr><td class=\"warning\">";
+					echo "You are not authorized to view this page.  Please contact the site administrator.";
+					echo "</td></tr>";
+				}
+
+				?>
+				</table>
+			<?php
+
+			mysql_close();
+			outputMainFooter();
+		}
+		else
+		{
+			// April 9/07, Marina: May output general info page for non-registered users
+			if (isset($_GET["View"]) && ($_GET["View"] == 1))
+			{
+				$loc_obj = new Location_Output_Class();
+				$loc_obj->print_Location_info();
+				
+				outputMainFooter();
+			}
+			else
+			{
+				echo "<tr><td class=\"warning\">";
+				echo "Please log in to access this page.";
+				echo "</td></tr>";
+				?>
+						</TABLE>
+					</table>
+				<?php
+				
+				outputMainFooter();
+			}
+		}
+	mysql_close($conn);
+?>
diff --git a/OpenFreezer/Location/Location_Admin_Class.php b/OpenFreezer/Location/Location_Admin_Class.php
new file mode 100755
index 0000000..aaa36ba
--- /dev/null
+++ b/OpenFreezer/Location/Location_Admin_Class.php
@@ -0,0 +1,552 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Location
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+ * This class handles location administration functions, often by invoking functions in other classes of the module
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Location
+ *
+ * @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+class Location_Admin_Class
+{
+	/**
+	 * Default constructor
+	*/
+	function Location_Admin_Class()
+	{}
+	
+	/**
+	 * Print details of the container type identified by $contGroupID
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-01-16
+	 *
+	 * @param INT $contGroupID Represents a container type, e.g. '2' => 'Glycerol Stock'
+	*/
+	function printContainerInfo($contGroupID)
+	{
+		$loc_obj = new Location_Funct_Class();
+		$loc_obj->printContainerInfo($contGroupID);
+	}
+
+	/**
+	 * Print information on a container's storage type (fridge, freezer, LN tank, etc.)
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-01-03
+	 *
+	 * @param INT $contID
+	 * @param boolean $modify_state
+	*/
+	function printContainerStorageInfo($contID, $modify_state)
+	{
+		global $conn;
+		global $hostname;
+		global $cgi_path;
+
+		$lfunc = new Location_Funct_Class();
+
+		// Jan. 3, 2010 - Let Admin delete plate IFF EMPTY
+		$currUserID = $_SESSION["userinfo"]->getUserID();
+		$currUserCategory = $_SESSION["userinfo"]->getCategory();
+		$currUserLab = $_SESSION["userinfo"]->getLabID();
+
+		$contName = $lfunc->getContainerName($contID);
+		$contLab = $lfunc->getContainerLabID($contID);
+
+		$original_info_rs = mysql_query("SELECT name, location, locationName, address, shelf, rack, row_number, col_number, locationTypeName FROM Container_tbl c, LocationTypes_tbl l WHERE containerID='" . $contID . "' AND c.status='ACTIVE' AND l.locationTypeID=c.location AND l.status='ACTIVE'", $conn) or die("Error reading container original info in SQL statement: " . mysql_error());
+
+		if ($original_info_ar = mysql_fetch_array($original_info_rs, MYSQL_ASSOC))
+		{
+			// Display storage type, name, shelf, rack, column, row
+			$storageType = $original_info_ar["locationTypeName"];
+			$contName = $original_info_ar["name"];
+			$storageName = $original_info_ar["locationName"];
+			$address = $original_info_ar["address"];
+			$shelf = $original_info_ar["shelf"];
+			$rack = $original_info_ar["rack"];
+			$row = $original_info_ar["row_number"];
+			$column = $original_info_ar["col_number"];
+		}
+
+			?><FORM method=post action="<?php echo $cgi_path . "location_request_handler.py"; ?>" onSubmit="return confirmMandatoryLocation() && checkLocationNumeric();">
+			<input type="hidden" name="cont_id_hidden" value="<?php echo $contID; ?>">
+
+			<table width="765px" cellpadding="5" cellspacing="5" border="1" frame="void" rules="all">
+				<TR>
+					<td colspan="2" style="font-weight:bold; font-size:12pt; text-align:center; color:#0000DF;">
+						<HR>                  <?php echo $contName; ?> Storage Information<?php
+
+						// Modification: only allowed for writers or above from the same lab
+						if (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || (($currUserCategory <= $_SESSION["userCategoryNames"]["Writer"]) && ($currUserLab == $contLab)))
+						{
+							if ($modify_state)
+							{
+								?>     <input type="SUBMIT" style="font-size:9pt;" name="save_cont_storage" value="Save">  <input type="BUTTON" style="font-size:9pt;" value="Cancel" onClick="window.location.href='<?php echo $_SERVER["PHP_SELF"] . "?View=3&Mod=" . $contID; ?>'"><?php
+							}
+							else
+							{
+								?>          <input type="SUBMIT" style="font-size:9pt;" name="edit_cont_location" value="Modify"><?php
+							}
+						}
+	
+						?><BR><a href="<?php echo $hostname . "Location.php?View=6&Sub=3&Mod=" . $contID; ?>" style="font-weight:normal; font-size:9pt;">Back to Container</a>
+						<HR>
+					</td>
+				</TR>
+
+				<TR>
+					<TD style="font-weight:bold; width:150px; border-left:1px solid black; border-bottom:1px solid black;">
+						Storage name <font size="3" face="Helvetica" color="FF0000"><b>*</b></font>
+					</TD>
+
+					<TD style="border-left:1px solid black; border-right:1px solid black; border-bottom:1px solid black;"><?php
+
+						if ($modify_state)
+							echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"34\" name=\"storage_name\" ID=\"locationName\" value=\"" . $storageName . "\">";
+						else
+							echo $storageName;
+					?></TD>
+				</TR>
+
+				<TR>
+					<TD style="font-weight:bold; border-left:1px solid black; border-bottom:1px solid black;">
+						Storage type <font size="3" face="Helvetica" color="FF0000"><b>*</b></font>
+					</TD>
+
+					<TD style="border-left:1px solid black; border-right:1px solid black; border-bottom:1px solid black;">
+						<?php
+
+							if ($modify_state)
+								$lfunc->printStorageTypes($storageType);
+							else
+								echo $storageType;
+						?>
+					</TD>
+				</TR>
+
+				<TR>
+					<TD style="font-weight:bold; width:150px; border-left:1px solid black; border-bottom:1px solid black;">
+						Address
+					</TD>
+
+					<TD style="border-left:1px solid black; border-right:1px solid black; border-bottom:1px solid black;">
+						<?php 
+							if ($modify_state)
+								echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"34\" name=\"storage_address\" value=\"" . $address . "\">";
+							else
+								echo $address;
+						?>
+					</TD>
+				</TR>
+
+				<TR>
+					<TD style="font-weight:bold; border-left:1px solid black; border-bottom:1px solid black;">
+						Shelf number
+					</TD>
+
+					<TD style="border-left:1px solid black; border-right:1px solid black; border-bottom:1px solid black;">
+						<?php
+							$mod_shelf = ($shelf != 0) ? $shelf : "";
+
+							if ($modify_state)
+								echo "<INPUT type=\"text\" ID=\"contShelf\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" name=\"cont_shelf\" value=\"" . $mod_shelf . "\">";
+							else
+								echo $mod_shelf;
+						?>
+					</TD>
+				</TR>
+
+				<TR>
+					<TD style="border-left:1px solid black; font-weight:bold;">
+						Rack
+					</TD>
+
+					<TD style="border-left:1px solid black; border-right:1px solid black; border-bottom:1px solid black;">
+						<?php
+							$mod_rack = ($rack != 0) ? $rack : "";
+
+							if ($modify_state)
+								echo "<INPUT type=\"text\" ID=\"contRack\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" name=\"cont_rack\" value=\"" . $mod_rack . "\">";
+							else
+								echo $mod_rack;
+						?>
+					</TD>
+				</TR>
+
+				<TR>
+					<TD style="font-weight:bold; border-left:1px solid black;">
+						Column
+					</TD>
+
+					<TD style="border-left:1px solid black; border-right:1px solid black; border-bottom:1px solid black;">
+						<?php
+							$mod_col = ($column!= 0) ? $column : "";
+
+							if ($modify_state)
+								echo "<INPUT type=\"text\" ID=\"contCol\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" name=\"cont_col\" value=\"" . $mod_col . "\">";
+							else
+								echo $mod_col;
+						?>
+					</TD>
+				</TR>
+
+				<TR>
+					<TD style="font-weight:bold; border-left:1px solid black; border-bottom:1px solid black;">
+						Row
+					</TD>
+
+					<TD style="border-bottom:1px solid black; border-right:1px solid black;  border-left:1px solid black;">
+						<?php
+							$mod_row = ($row != 0) ? $row : "";
+
+							if ($modify_state)
+								echo "<INPUT type=\"text\" ID=\"contRow\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" name=\"cont_row\" value=\"" . $mod_row . "\">";
+							else
+								echo $mod_row;
+						?>
+					</TD>
+				</TR>
+			</table>
+
+			</FORM><?php
+		
+	}
+
+
+	/**
+	 * Print container modification form
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2007-09-19
+	 *
+	 * @param STRING $output_str Seems to be inactive in this function, keep for future updates
+	 * @param INT $contID
+	*/
+	function printModifyContainer_Form($output_str, $contID)
+	{
+		global $conn;
+		global $cgi_path;
+
+		$lfunc = new Location_Funct_Class();
+
+		$original_info_rs = mysql_query("SELECT * FROM `Container_tbl` WHERE `containerID`='" . $contID . "' AND `status`='ACTIVE'", $conn) or die("Error reading container original info in SQL statement: " . mysql_error());
+
+		if ($original_info_ar = mysql_fetch_array($original_info_rs, MYSQL_ASSOC))
+		{
+			?>
+			<FORM NAME="deleteContainerForm" METHOD="POST" ACTION="<?php echo $cgi_path . "location_request_handler.py";?>">
+				<INPUT TYPE="hidden" NAME="delete_container">
+				<INPUT TYPE="hidden" NAME="containerID" VALUE="<?php echo $contID; ?>">
+			</FORM>
+
+			<FORM method=post action="<?php /*echo $_SERVER["PHP_SELF"] . "?View=5&Mod=" . $contID . ""; */ echo $cgi_path . "location_request_handler.py"; ?>">
+
+			<input type=hidden name="cont_id_hidden" value="<?php echo $contID; ?>">
+
+			<table width="796px" cellpadding="5" style="border: 1px solid black;" frame="box" rules="all">
+				<th colspan="3" style="text-align:center;">
+					Update Container Information
+				</th>
+
+				<tr>
+					<td style="font-size:9pt; white-space:nowrap;">
+						Container Name
+					</td>
+	
+					<td style="padding-left:10px; padding-right:10px;">
+						<INPUT style="font-size:9pt;" type="text" onKeyPress="return disableEnterKey(event);" size="25" value="<?php echo $original_info_ar["name"] ?>" name="cont_name_field">
+					</td>
+				</tr>
+
+				<tr>
+					<td>
+						Container Type
+					</td>
+	
+					<td style="padding-left:10px;">
+					<?php 
+						// Feb 9, Marina -- Disallow modification of occupied containers
+						$size_rs  = mysql_query( "SELECT `maxCol`, `maxRow` FROM `ContainerTypeID_tbl` WHERE `contTypeID`='" . $original_info_ar["contTypeID"] . "' AND `status`='ACTIVE'" , $conn ) or die("Error reading container original info in SQL statement: " . mysql_error());
+					
+						if ($size_ar = mysql_fetch_array( $size_rs, MYSQL_ASSOC ) )
+						{
+							$cols = $size_ar["maxCol"];
+							$rows = $size_ar["maxRow"];
+						}
+					
+						$capacity = $cols * $rows;
+
+						$loc_func_obj = new Location_Funct_Class();
+						$empty_cells = $loc_func_obj->getEmptyCellNum($contID, $original_info_ar["contTypeID"]);
+						$occupied_cells = $capacity - $empty_cells;
+	
+						if (($occupied_cells) > 0)
+						{
+							// Don't allow modification of occupied container types or sizes
+							echo "<select disabled name=\"cont_group_selection\">";
+						}
+						else
+						{
+							echo "<select name=\"cont_group_selection\" style=\"font-size:8pt;\">";
+						}
+
+						$group_list_rs = mysql_query("SELECT * FROM `ContainerGroup_tbl` WHERE `status`='ACTIVE'", $conn) or die("ERROR SQL#12: " . mysql_error());
+						
+						while ($group_list_ar = mysql_fetch_array($group_list_rs, MYSQL_ASSOC))
+						{
+							if ($group_list_ar["contGroupID"] == $original_info_ar["contGroupID"])
+							{
+								echo "<option selected>" . $group_list_ar["contGroupName"] . "</option>";
+							}
+							else
+							{
+								echo "<option>" . $group_list_ar["contGroupName"] . "</option>";
+							}
+						}
+					?>
+						</select>
+					</td>
+	
+					<td style="font-size:9pt;">
+						Please select a container type from the list provided.  If  the desired type is not in the list, please <a href="<?php echo $hostname . "contacts.php"; ?>" style="font-size:9pt;">contact the Administrator</a> to create it.
+					</td>
+				</tr>
+			
+				<tr>
+					<td>
+						Container Size
+					</td>
+	
+					<td style="padding-left:7px;">
+					<?php
+	
+					if (($occupied_cells) > 0)
+					{
+						// Don't allow modification of occupied container types or sizes
+						echo "<select disabled name=\"cont_size_selection\" style=\"font-size:8pt;\">";
+					}
+					else
+					{
+						echo "<select name=\"cont_size_selection\" style=\"font-size:8pt;\">";
+					}
+		
+					$type_list_rs = mysql_query("SELECT * FROM `ContainerTypeID_tbl` WHERE `status`='ACTIVE'", $conn) or die("ERROR: " . mysql_error());
+
+					while( $type_list_ar = mysql_fetch_array( $type_list_rs, MYSQL_ASSOC ) )
+					{
+						if( $type_list_ar["contTypeID"] == $original_info_ar["contTypeID"] )
+						{
+							echo "<option selected>" . $type_list_ar["containerName"] . "</option>";
+						}
+						else
+						{
+							echo "<option>" . $type_list_ar["containerName"] . "</option>";
+						}
+					}
+					?>
+					</select>
+					</td>
+	
+					<td style="font-size:9pt;">
+						Please select a container size from the list provided.  If the desired size is not in the list, please add it using the <a href="<?php echo $_SERVER["PHP_SELF"] . "?View=6&Sub=1"; ?>" style="font-size:9pt;">Add container sizes</a> menu item.
+					</td>
+				</tr>
+	
+				<tr>
+					<td>
+						Description:
+					</td>
+		
+					<td style="padding-left:7px;  padding-right:10px;">
+						<INPUT type="text" onKeyPress="return disableEnterKey(event);" style="font-size:9pt;" size="35" value="<?php echo $original_info_ar["container_desc"]; ?>" name="cont_desc_field">
+					</td>
+	
+					<td></td>
+				</tr>
+		
+				<!-- Lab - Added Sept. 19/07 -->
+				<tr>
+					<td>
+						Laboratory:
+					</td>
+		
+					<td style="padding-left:7px;">
+					<?php
+						$lfunc->printLabList($original_info_ar["labID"]);
+					?>
+					</td>
+	
+					<td>
+						Please select from the dropdown list
+					</td>
+				</tr>
+		
+				<tr>
+					<td colspan="3">
+						<input type="submit" name="cont_modify_button" value="Submit" onClick="enableSelect();"> <?php
+	
+						// Jan. 3, 2010 - Let Admin delete plate IFF EMPTY
+						$currUserID = $_SESSION["userinfo"]->getUserID();
+						$currUserCategory = $_SESSION["userinfo"]->getCategory();
+						$userLab = $_SESSION["userinfo"]->getLabID();
+						$contLab = $original_info_ar["labID"];
+			
+						// check for empty is kinda redundant, since Modification page can now be accessed IFF container empty, but keep for consistency.  Check for user lab is required.
+						if (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || (($currUserCategory <= $_SESSION["userCategoryNames"]["Writer"]) && ($contLab == $userLab)))
+						{
+							?><input type="button" style="font-size:9pt;" name="delete_container_button" value="Delete Container" onClick="deleteContainer('<?php echo $contID; ?>')"><?php
+						}
+						else
+						{
+							?><input type="button" style="font-size:9pt;" DISABLED value="Delete Container"><?php
+						}
+
+						?><input type="button" style="font-size:9pt;" value="Cancel" onClick="window.location.href='<?php echo $_SERVER["PHP_SELF"] . "?View=2&Mod=" . $contID; ?>'">
+					</TD>
+				</tr>
+			</table>
+
+			</FORM><?php
+		}
+	}
+	
+	
+	/**
+	 * Update container information
+	 *
+	 * Modified Feb 9, 2006 by Marina, to account for cases where container group and size were unchanged
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING $output_str Seems to be inactive in this function, keep for future updates
+	 * @param INT $contID
+	*/
+	function updateContainerInfo($postvars)
+	{
+		global $conn;
+		$lfunc = new Location_Funct_Class();
+
+		$group_changed = false;
+		$type_changed = false;
+
+		if (isset($postvars["cont_id_hidden"]))
+		{
+			$contID_tmp = $postvars["cont_id_hidden"];
+		
+			// May 31/06, Marina - Get the container's CURRENT information - mostly care about the group for group count update
+			$curr_rs = mysql_query("SELECT * FROM `Container_tbl` WHERE `containerID`='" . $contID_tmp . "' AND `status`='ACTIVE'");
+
+			if ($curr_ar = mysql_fetch_array($curr_rs, MYSQL_ASSOC))
+			{
+				// May not require all those fields now, but good to retrieve them all in case need later
+				$curr_name = $curr_ar["name"];
+				$curr_desc = $curr_ar["container_desc"];
+				$curr_group = $curr_ar["contGroupID"];
+				$curr_group_count = $curr_ar["contGroupCount"];
+			}
+	
+			$name_tmp = /*addslashes( */$postvars["cont_name_field"] /*)*/;
+			$desc_tmp = /*addslashes( */$postvars["cont_desc_field"] /*)*/;
+
+			if (isset($postvars["cont_group_selection"]))
+			{
+				// Updated May 31/06 by Marina
+				$contGroupID_tmp = $_SESSION["Container_Name_ID"][ $postvars["cont_group_selection"] ];
+
+				if ($contGroupID_tmp != $curr_group)	// may 31/06
+				{
+					// only in this case has the group changed!!
+					$group_changed = true;	
+				}
+			}
+
+			// June 5/06, Marina -- Instead of relying on the user to select the isolate active state of the container, determine it based on the container's new group type:
+			$isolate_rs = mysql_query ("SELECT `isolate_active` FROM `Container_tbl` WHERE `contGroupID`='" . $contGroupID_tmp . "' AND `status`='ACTIVE'", $conn) or die("Error selecting container's isolate active state: " . mysql_error());
+
+			if ($isolate_ar = mysql_fetch_array($isolate_rs, MYSQL_ASSOC))
+			{
+				$isolate_tmp = $isolate_ar["isolate_active"];
+			}
+			else
+			{
+				// default to No
+				$isolate_tmp = "NO";
+			}
+
+
+			if (isset($postvars["cont_size_selection"]))
+			{
+				$size_changed = true;
+				$contTypeID_tmp = $lfunc->convertContTypeName_to_ID( $postvars["cont_size_selection"] );
+			}
+			
+			// June 5, Marina - Moved isolate change into group change section; only update name and description here
+			mysql_query("UPDATE `Container_tbl` SET `name`='" . $name_tmp . "', `container_desc`='" . $desc_tmp . "' WHERE `containerID`='" . $contID_tmp . "' AND `status`='ACTIVE'", $conn) or die("Error in updating SQL statement: " . mysql_error());
+			
+			if ($group_changed == true)
+			{
+				// May 30/06, Marina - Update group COUNT, so that, if you change container type from Vector into Cell Line and there are 40 Vector containers and only 3 Cell Lines, you don't end up with a list of Cell Line containers whose numbers go 1, 2, 3, 40
+				// It needs to be done first, before changing the group type - otherwise, if the old group count was high, moving into a group with fewer entries would still result in an incorrect ID
+				// Count the number of containers in the new group and set the new container's groupCount to that number
+				$find_groupnum_rs = mysql_query("SELECT MAX(`contGroupCount`) AS nextnum FROM `Container_tbl` WHERE `contGroupID`='" . $contGroupID_tmp . "'AND `status`='ACTIVE'", $conn ) or die( "Error in updating SQL statement: " . mysql_error() );
+
+				if( $find_groupnum_ar = mysql_fetch_array( $find_groupnum_rs, MYSQL_ASSOC ) )
+				{
+					mysql_query("UPDATE `Container_tbl` SET `contGroupCount`='" . ($find_groupnum_ar["nextnum"] + 1) . "' WHERE `containerID`='" . $contID_tmp . "' AND `status`='ACTIVE'", $conn) or die("Error in updating SQL statement: " . mysql_error());
+				}
+
+				mysql_query("UPDATE `Container_tbl` SET `contGroupID`='" . $contGroupID_tmp . "' WHERE `containerID`='" . $contID_tmp . "' AND `status`='ACTIVE'", $conn) or die( "Error in updating SQL statement: " . mysql_error() );
+
+				// June 5/06:
+				// Update container PROPERTIES, so when a Vector plate is changed into cell line, it displays the right properties
+				$lfunc->updateContainerProperties($contID_tmp, $contGroupID_tmp, $isolate_tmp);
+			}
+
+			if ($size_changed == true)
+			{
+				mysql_query("UPDATE `Container_tbl` SET `contTypeID`='" . $contTypeID_tmp . "' WHERE `containerID`='" . $contID_tmp . "' AND `status`='ACTIVE'", $conn) or die("Error in updating SQL statement: " . mysql_error());
+			}
+
+			return "Container successfully updated!";
+		}
+		
+		return "Error in trying to update the container!";
+		
+		unset( $lfunc );
+	}
+}
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Location/Location_Creator_Class.php b/OpenFreezer/Location/Location_Creator_Class.php
new file mode 100755
index 0000000..09de155
--- /dev/null
+++ b/OpenFreezer/Location/Location_Creator_Class.php
@@ -0,0 +1,634 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2010 Pawson Laboratory
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Location
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+/**
+ * This class handles functions for creation of new containers, container sizes and container types.
+ *
+ * Most of the processing code has been moved to Python, but form output is handled here
+ *
+ * @author John Paul Lee @version 2005
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Location
+ *
+ * @copyright  2005-2010 Pawson Laboratory
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+class Location_Creator_Class
+{
+	/**
+	 * Default constructor
+	*/
+	function Location_Creator_Class()
+	{
+	}
+
+	/**
+	 * Print form to add container TYPES (processing is done by Python, which adds rows to ContainerGroup_tbl and assigns prep attributes)
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2009-12-18
+	 *
+	*/
+	function printForm_addNewContainerTypes()
+	{
+		global $conn;
+		global $cgi_path;
+
+		$lfunc = new Location_Funct_Class();
+
+		?>
+		<FORM METHOD="POST" ACTION="<?php echo $cgi_path . "location_type_request_handler.py"; ?>" onSubmit="return verifyContainerType();">
+
+			<table border="1" bordercolor="black" frame="box" rules="all" style="width:765px;" cellpadding="3">
+
+				<tr>
+					<td colspan="3" style="font-weight:bold; font-size:10pt; color:#00C00D; padding-top:8px; padding-bottom:10px; text-align:center;">
+						ADD CONTAINER TYPE<BR>
+				
+						<span style="font-size:10pt; color:#FF0000">
+							Fields marked with a red asterisk (*) are mandatory
+						</span>
+					</td>
+				</tr>
+
+				<tr>
+					<td style="white-space:nowrap; width:150px; padding-left:9px; font-size:9pt; font-weight:bold; color:#238E23;" colspan="3">
+						Name <font size="3" face="Helvetica" color="FF0000"><b>*</b></font>
+						  <INPUT type="text" size="25" name="cont_group_name_field" ID="containerTypeName" onKeyPress="return disableEnterKey(event);">
+
+						<!-- TOOLTIP -->
+						  <a href="#" style="font-size:9pt; font-weight:normal;" onclick="return overlib('Choose a descriptive name for this container type (e.g. \'MiniPrep Plate\' or \'Liquid Nitrogen Container\')', CAPTION, 'Container Type Name', STICKY);">Details</a>
+					</td>
+				</tr>
+
+			
+				<tr><TD colspan="3"></TD></TR>
+
+				<tr>
+					<td style="padding-top:8px; padding-bottom:7px; padding-left:8px; font-size:9pt; font-weight:bold; color:#238E23;" colspan="3">
+						Reagent types:
+
+						<!-- TOOLTIP -->
+						   <a href="#" style="font-size:9pt; font-weight:normal;" onclick="return overlib('Typically, containers are designed to store samples (preps) of only one reagent type(this setup allows to define a distinct set of properties for a container).  However, preps of different reagent types that share the same characteristics may be stored in the same container type (e.g. preps for both Vector and Insert can be stored in 96-well Glycerol Stock plates)', CAPTION, 'Reagent T [...]
+
+						<BR><BR>
+
+						<select ID="contTypesList" MULTIPLE size="5" name="cont_cont_group_selection" style="margin-left:4px; padding-left:1px;">
+						<?php
+							foreach ($_SESSION["ReagentType_ID_Name"] as $rTypeID => $rType)
+							{
+								echo "<option value=\"" . $rTypeID . "\">" . $rType . "</option>";
+							}
+						?>
+						</select><BR>
+
+						<INPUT TYPE="CHECKBOX" ID="selectAllReagentTypesContainer" style="margin-top:7px;" onClick="selectAllContainerProperties(this.id, 'contTypesList', false)"><span style="color:#000000; font-weight:normal;">Select All</span>
+					</td>
+				</tr>
+
+				<tr><TD colspan="3"></TD></TR>
+
+				<tr>
+					<td style="padding-top:8px; padding-bottom:6px; padding-left:8px; font-size:9pt; font-weight:bold; color:#238E23;" colspan="4">
+						Container Type Code:<SPAN style="margin-left:4px; font-size:11pt; font-face:Helvetica; font-weight:bold; color:#FF0000;">*</SPAN>
+
+						  <INPUT type="text" size="5" value="" ID="containerCode" name="cont_cont_code_field" onKeyPress="return disableEnterKey(event);">
+
+						<!-- TOOLTIP -->
+						    <a href="#" style="font-weight:normal; font-size:9pt;" onclick="return overlib('Please enter a <B>two-letter</B> <U>unique</U> identifier for this container type (e.g. \'MP\' for MiniPrep Plates, or \'GS\' for Glycerol Stock containers).  <u>Codes that are listed as currently in use may not be reused</u>.', CAPTION, 'Container Code', STICKY);">Details</a><BR><P>
+
+						<SPAN style="margin-left:3px; font-size:9pt; font-face:Helvetica; font-weight:normal; color:#000000;">The following container type codes are currently in use in OpenFreezer and <u>may NOT be reused</u>:</span>
+
+						<TABLE style="margin-left:10px; border:0">
+							<TR><UL><?php
+
+							$count = 0;
+
+							$code_rs = mysql_query("SELECT contGroupName, contGroupCode FROM ContainerGroup_tbl WHERE status='ACTIVE'", $conn) or die("Cannot select container codes: " . mysql_error());
+
+							while ($code_ar = mysql_fetch_array($code_rs, MYSQL_ASSOC))
+							{
+								$contGroupName = $code_ar["contGroupName"];
+								$contGroupCode = $code_ar["contGroupCode"];
+
+								if (($count != 0) && ($count % 2 == 0))
+									echo "</TR><TR>";
+
+								echo "<TD style=\"font-size:9pt; font-weight:bold; text-decoration:none;\"><LI>" . $contGroupCode . "</TD>";
+								echo "<TD> - </TD>";
+								echo "<TD style=\"font-size:9pt;\">" . $contGroupName . "</TD>";
+								echo "<TD> </TD>";
+								echo "<TD> </TD>";
+
+								$count++;
+							}
+
+						?></UL></TR></table>
+					</td>
+				</tr>
+
+				<tr><TD colspan="3"></TD></TR>
+
+				<tr>
+					<td  style="white-space:nowrap; width:150px; padding-left:10px; font-size:9pt; font-weight:bold; padding-top:10px; padding-bottom:10px; color:#238E23;" colspan="3">
+						Isolate Active   
+
+						<span style="font-weight:normal; color:#000000;">
+							<input type="radio" checked name="cont_cont_isolateActive_radio" value="Yes"> Yes
+							<input type="radio" name="cont_cont_isolateActive_radio" value="No"> No
+	
+							<!-- TOOLTIP -->
+							    <a href="#" style="font-size:9pt;" onclick="return overlib('A reagent may be associated with an isolate - different colony picks (e.g. when cloning vectors or cell lines)', CAPTION, 'Isolate Active', STICKY);">Details</a>
+						</span>
+					</td>
+				</tr>
+
+				<!-- Feb. 12/09: List of features for this container type: -->
+				<tr><TD colspan="3"></TD></TR>
+
+				<tr>
+					<td  style="white-space:nowrap; width:150px; padding-left:9px; font-size:9pt; font-weight:bold; padding-top:12px; padding-bottom:8px; color:#238E23;" colspan="4">
+						Container Type Attributes:
+
+						<!-- TOOLTIP -->
+						  <a href="#" style="font-weight:normal; font-size:9pt;" onclick="return overlib('Features associated with preps stored in this container (e.g. Bacteria Strain, or Method used to prepare the clone).  If your sought feature is not in the list, add it by typing the feature name in the textbox and pressing \'Add\'', CAPTION, 'Container Type Features', STICKY);">Details</a><BR><P>
+					
+						<table cellpadding="2">
+							<tr>
+								<TD style="font-size:9pt; font-weight:bold; text-align:center;">
+									Attributes that will be assigned<BR>to containers of this type:
+								</td>
+
+								<TD> </TD>
+
+								<TD style="font-size:9pt; font-weight:bold; text-align:left;">
+									Select from additional container type<BR>attributes available in OpenFreezer:
+								</TD>
+							</TR>
+
+							<TR>
+								<td style="white-space:nowrap; text-align:left;">
+									<SELECT SIZE="10" MULTIPLE NAME="container_features" ID="cont_dest_features" style="min-width:140px; margin-left:15px;"></SELECT>
+								
+									<P><INPUT TYPE="checkbox" style="margin-left:15px;" onClick="selectAll(this.id, 'cont_dest_features')" id="add_all_chkbx_dest"> Select All</INPUT>
+								</td>
+							
+								<td style="text-align:left; padding-left:10px; padding-right:20px;">
+									<input style="margin-top:10px;" onclick="moveListElements('cont_src_features', 'cont_dest_features', false)" value="<<" type="button"></INPUT><BR><BR>
+
+									<input onclick="moveListElements('cont_dest_features', 'cont_src_features', false)" value=">>" type="button"></INPUT><BR><BR><BR><BR>
+								</td>
+
+								<td style="white-space:nowrap; padding-left:20px;">
+								<?php
+									$props_rs = mysql_query("SELECT elementTypeID, propertyName FROM PrepElemTypes_tbl WHERE status='ACTIVE' ORDER BY propertyName") or die("Error fetching container attributes");
+		
+									echo "<SELECT SIZE='10' MULTIPLE ID='cont_src_features'>";
+		
+									while ($props_ar = mysql_fetch_array($props_rs, MYSQL_ASSOC))
+									{
+										$propertyName = $props_ar["propertyName"];
+										$elementTypeID = $props_ar["elementTypeID"];
+		
+										// Update Jan. 14, 2010: pass the property NAME to Python, not the value!
+										echo "<OPTION VALUE=\"" . $propertyName . "\" NAME=\"" . $propertyName . "\">" . $propertyName . "</OPTION>";
+									}
+		
+									echo "</SELECT>";
+
+									?>
+									<P><INPUT TYPE="checkbox" onClick="selectAll(this.id, 'cont_src_features')" id="add_all_chkbx_src"> Select All</INPUT>
+								</td>
+							</tr>
+
+							<tr>
+								<td colspan="3" style="white-space:nowrap;"><HR>or, add new feature: <INPUT type="text" size="35" ID="new_cont_feature_txt" value="" name="new_cont_feature" onKeyPress="return disableEnterKey(event);"> <input onclick="addElementToListFromInput('new_cont_feature_txt', 'cont_dest_features')" value="Add" type="button"></INPUT></td>
+							</tr>
+						</table>
+					</td>
+				</tr>
+
+				<tr>
+					<td colspan="3">
+						<input type="submit" name="cont_type_create_button" value="SUBMIT" onClick="selectAllElements('cont_dest_features');">
+					</td>
+				</tr>
+			</table>
+		</FORM>
+		<?php
+	}
+
+
+	/**
+	 * This function outputs a form to create new container 'SIZES', e.g. "96-well plate" or "25-slot box".
+	 *
+	 * Keep the name "newTypes" for consistency, just remember that historically "type" referred to "size".
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	*/
+	function printForm_newTypes()
+	{
+		global $conn;
+		
+		?>
+		<form method=post action="<?php echo $_SERVER["PHP_SELF"] . "?View=6&Sub=1"; ?>">
+		
+			<table border=1 frame="box" rules="all" width="780px" cellpadding="5">
+		
+				<thead>
+					<tr>
+						<td colspan="3" style="font-weight:bold; text-align:left; padding-top:8px; padding-bottom:10px; padding-left:280px;">
+							ADD NEW CONTAINER SIZE
+						</td>
+					</tr>
+				</thead>
+
+				<tbody>
+
+					<tr>
+						<td style="padding-left:10px;">
+							Name
+						</td>
+
+						<td style="padding-left:10px;">
+							<INPUT type="text" name="cont_type_name_field" onKeyPress="return disableEnterKey(event);">
+						</td>
+
+						<td style="padding-left:10px;">
+							Description of the container's form and capacity (e.g. '96-well plate', '25-slot box')
+						</td>
+					</tr>
+
+					<tr>
+						<td style="padding-left:10px;">
+							Max Row Number
+						</td>
+
+						<td style="padding-left:10px;">
+							<INPUT type="text" size="5" name="cont_type_maxrow_field" onKeyPress="return disableEnterKey(event);">
+						</td>
+
+						<td style="padding-left:10px;">
+							The maximum number of rows in this container.
+						</td>
+					</tr>
+
+					<tr>
+						<td style="padding-left:10px;">
+							Max Column Number
+						</td>
+
+						<td style="padding-left:10px;">
+							<INPUT type="text" size="5" name="cont_type_maxcol_field" onKeyPress="return disableEnterKey(event);">
+						</td>
+
+						<td style="padding-left:10px;">
+							The maximum number of columns in this container.
+						</td>
+					</tr>
+
+					<tr>
+						<td style="text-align:left; padding-top:10px;" colspan="3">
+							<input type="submit" name="cont_type_create_button" value="SUBMIT">
+						</td>
+					</tr>
+                		</tbody>
+
+				<tr>
+					<td colspan="3">
+					
+						<BR><SPAN STYLE="margin-left:25px; text-decoration:underline; font-weight:bold;">Currently Available Container Sizes:</SPAN>
+
+						<UL>
+						<?php
+							$type_name_rs = mysql_query("SELECT * FROM `ContainerTypeID_tbl` WHERE `status`='ACTIVE'", $conn) or die("ERROR in group name SQL Statement: " . mysql_error());
+							
+							while ($type_name_ar = mysql_fetch_array($type_name_rs, MYSQL_ASSOC))
+							{
+								echo "<LI>" . $type_name_ar["containerName"] . "<b>: " . $type_name_ar["maxRow"] . "</b> rows x <b>" . $type_name_ar["maxCol"] . "</b> columns";
+							}
+						?>
+				        	</UL>
+					</td>
+				</tr>
+			</table>
+		</form>
+		<?php
+	}
+	
+
+	/**
+	 * This function outputs a form to create new CONTAINERS
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 update Sept. 18/07
+	 *
+	*/
+	function printForm_newContainers()
+	{
+		global $conn;
+		global $cgi_path;
+
+		$lfunc = new Location_Funct_Class();
+
+		?><FORM METHOD="POST" ACTION="<?php echo $cgi_path . "location_request_handler.py"; ?>" onSubmit="return confirmMandatoryLocation() && checkLocationNumeric();">
+			<table border="1" frame="box" rules="all" width="765px" cellpadding="3" cellspacing="3">
+
+				<th colspan="3" style="font-size:10pt; color:#0055FF; text-align:center">
+					CREATE NEW CONTAINERS<BR>
+			
+					<span style="font-size:10pt; color:#FF0000">
+						Fields marked with a red asterisk (*) are mandatory
+					</span>
+				</th>
+			
+				<tr><td colspan="3"> </td></tr>
+
+				<tr>
+					<td style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						Name <SPAN style="font-size:13; font-face:Helvetica; color:#FF0000; font-weight:bold;">*</span>
+					</td>
+
+					<td colspan="2" style="padding-left:10px; padding-right:12px; white-space:nowrap;">
+						<INPUT type="text" value="" name="cont_cont_name_field" ID="containerName" onKeyPress="return disableEnterKey(event);">
+
+						 <a href="#" style="font-weight:normal; font-size:9pt;" onclick="return overlib('Choose a descriptive name that will distinguish this container from other containers (e.g. \'Jane Doe\'s Oligo Plate 1\'', CAPTION, 'Container Name', STICKY);">Details</a>
+					</td>
+				</tr>
+
+				<tr>
+					<td style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						Container Type: <SPAN style="font-size:13; font-face:Helvetica; color:#FF0000; font-weight:bold;">*</span>
+					</td>
+			
+					<td style="padding-left:10px; padding-right:12px; white-space:nowrap;">
+						<select name="cont_cont_group_selection" ID="contGroupBox" style="font-size:8pt;">
+							<OPTION SELECTED VALUE="default">-- Select container type --</OPTION>
+							<?php
+								$group_list_rs = mysql_query("SELECT * FROM `ContainerGroup_tbl` WHERE `status`='ACTIVE'", $conn) or die("ERROR SQL#12: " . mysql_error());
+								
+								while ($group_list_ar = mysql_fetch_array($group_list_rs, MYSQL_ASSOC))
+								{
+									echo "<option VALUE=\"" . $group_list_ar["contGroupID"] . "\">" . $group_list_ar["contGroupName"] . "</option>";
+								}
+							?>
+						</select>
+					</td>
+			
+					<td style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						If  the sought container type is not in the list, please <a href="<?php echo $hostname . "contacts.php"; ?>" target="new">contact the Administrator</a> to add it.
+					</td>
+				</tr>
+
+				<tr>
+					<td style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						Container Size <SPAN style="font-size:13; font-face:Helvetica; color:#FF0000; font-weight:bold;">*</span>
+					</td>
+			
+					<td style="padding-left:10px; padding-right:25px; white-space:nowrap;">
+						<select name="cont_cont_type_selection" ID="contSizeList" style="font-size:8pt;">
+							<OPTION SELECTED VALUE="default">-- Select container size--</OPTION>
+							<?php
+							$type_list_rs = mysql_query("SELECT * FROM `ContainerTypeID_tbl` WHERE `status`='ACTIVE'", $conn) or die("ERROR SQL#13: " . mysql_error());
+	
+							while( $type_list_ar = mysql_fetch_array( $type_list_rs, MYSQL_ASSOC ) )
+							{
+								echo "<option>" . $type_list_ar["containerName"] . "</option>";
+							}
+							?>
+						</select>
+					</td>
+
+					<td style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						If the sought container size is not in the list, please <a href="<?php echo $_SERVER["PHP_SELF"] . "?View=6&Sub=1"; ?>" target="new">add it</a> first.
+					</td>
+				</tr>
+			
+				<tr>
+					<td style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						Description:
+					</td>
+			
+					<td style="padding-left:10px; padding-right:12px;" colspan="2">
+						<INPUT type="text" value="" name="cont_cont_desc_field" onKeyPress="return disableEnterKey(event);">
+					</td>
+				</tr>
+
+				<tr>
+					<td style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						Laboratory:
+					</td>
+			
+					<td style="padding-left:10px; padding-right:12px; white-space:nowrap;">
+						<?php
+							$currLabID = $_SESSION["userinfo"]->getLabID();
+							$lfunc->printLabList();
+						?>
+					</td>
+
+					<td style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						If the laboratory is not in the list, please <a href="<?php echo $hostname . "contacts.php"; ?>" target="new">contact the Administrator</a> to add it.
+
+						 <a href="#" style="font-weight:normal; font-size:9pt;" onclick="return overlib('Laboratory that owns this container', CAPTION, 'Laboratory', STICKY);">Details</a>
+					</td>
+				</tr>
+
+				<tr>
+					<td style="padding-left:10px; white-space:nowrap; width:150px; font-size:9pt; padding-right:10px;">
+						Storage type <font size="3" face="Helvetica" color="FF0000"><b>*</b></font>
+					</td>
+
+					<td style="padding-left:10px; white-space:nowrap;">
+					<?php
+						$lfunc->printStorageTypes();
+					?>
+					</td>
+
+					<td style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						If the sought storage type is not in the list, please <a href="<?php echo $hostname . "contacts.php"; ?>" target="new">contact the Administrator</a> to add it.
+
+						 <a href="#" style="font-weight:normal; font-size:9pt;" onclick="return overlib('Indicate whether this container is stored at room temperature, in a fridge, a freezer, or a Liquid Nitrogen tank', CAPTION, 'Storage Type', STICKY);">Details</a>
+					</td>
+				</tr>
+
+				<tr>
+					<td style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						Storage Name <font size="3" face="Helvetica" color="FF0000"><b>*</b></font>
+					</td>
+
+					<td style="padding-left:10px; white-space:nowrap;" colspan="2">
+						<INPUT type="text" ID="locationName" name="storage_name" onKeyPress="return disableEnterKey(event);">
+
+						  <a href="#" style="font-weight:normal; font-size:9pt;" onclick="return overlib('A descriptive name of the storage (e.g. \'Freezer 1\' or \'Revco -80\')', CAPTION, 'Storage Name', STICKY);">Details</a>
+					</td>
+				</tr>
+
+				<TR>
+					<TD style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						Address
+					</TD>
+
+					<td style="padding-left:10px; white-space:nowrap;" colspan="2">
+						<INPUT type="text" name="storage_address" onKeyPress="return disableEnterKey(event);">
+
+						  <a href="#" style="font-weight:normal; font-size:9pt;" onclick="return overlib('A room number or a complete address of the laboratory where the container is located (e.g. \'MSH rm. 1068\', \'60 Murray Street\', or \'London, England\')', CAPTION, 'Address', STICKY);">Details</a>
+					</td>
+				</TR>
+
+				<tr>
+					<td style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						Shelf number
+					</td>
+
+					<td style="padding-left:10px; white-space:nowrap;" colspan="2">
+						<INPUT type="text" size="5" ID="contShelf" name="cont_shelf" onKeyPress="return disableEnterKey(event);">
+
+						  <a href="#" style="font-weight:normal; font-size:9pt;" onclick="return overlib('Indicate the shelf number in the fridge or freezer where the container is located, if applicable (this field may be left blank)', CAPTION, 'Shelf Number', STICKY);">Details</a>
+					</td>
+				</tr>
+
+				<tr>
+					<td style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						Rack number
+					</td>
+
+					<td style="padding-left:10px;" colspan="2">
+						<INPUT type="text" size="5" ID="contRack" name="cont_rack" onKeyPress="return disableEnterKey(event);">
+
+						  <a href="#" style="font-weight:normal; font-size:9pt;" onclick="return overlib('Indicate the rack number in the tank, fridge or freezer where the container is located, if applicable (this field may be left blank)', CAPTION, 'Rack Number', STICKY);">Details</a>
+					</td>
+				</tr>
+
+				<tr>
+					<td style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						Column number
+					</td>
+
+					<td style="padding-left:10px;" colspan="2">
+						<INPUT type="text" size="5" ID="contCol" name="cont_col" onKeyPress="return disableEnterKey(event);">
+
+						  <a href="#" style="font-weight:normal; font-size:9pt;" onclick="return overlib('Indicate the container\'s column number on the rack, if applicable (this field may be left blank)', CAPTION, 'Column Number', STICKY);">Details</a>
+					</td>
+				</tr>
+
+				<tr>
+					<td style="padding-left:10px; font-size:9pt; padding-right:10px;">
+						Row number
+					</td>
+
+					<td style="padding-left:10px;" colspan="2">
+						<INPUT type="text" size="5" ID="contRow" name="cont_row" onKeyPress="return disableEnterKey(event);">
+
+						  <a href="#" style="font-weight:normal; font-size:9pt;" onclick="return overlib('Indicate the container\'s row number on the rack, if applicable (this field may be left blank)', CAPTION, 'Row Number', STICKY);">Details</a>
+					</td>
+				</tr>
+
+				<tr>
+					<td colspan="3">
+						<input type="submit" name="cont_cont_create_button" onClick="enableSelect();" value="SUBMIT">
+					</td>
+				</tr>
+			</table>
+		</FORM>
+		<?php
+	}
+	
+	/**
+	 * Interpret POST request and invoke the proper processing function
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param Array $postvars $_POST form input
+	*/
+	function process_submit($postvars)
+	{
+		if (isset($postvars["cont_type_create_button"]))
+		{
+			return $this->process_type($postvars);
+		}
+	}
+	
+
+	/**
+	 * Create a new container size (insert POST values into database)
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param Array $postvars $_POST form input
+	*/
+	function process_type($postvars)
+	{
+		global $conn;
+		
+		if( strlen( $postvars["cont_type_name_field"] ) <= 0 )
+		{
+			return "Error Occured inserting new Container Type: Name field was not found!";
+		}
+		elseif( $postvars["cont_type_maxrow_field"] <= 0 )
+		{
+			return "Error Occured inserting new Container Type: Row field does not contain a valid value!";
+		}
+		elseif( $postvars["cont_type_maxcol_field"] <= 0 )
+		{
+			return "Error Occured inserting new Container Type: Column field does not contain a valid value!";
+		}
+		
+		$type_check_rs = mysql_query("SELECT * FROM `ContainerTypeID_tbl` WHERE (`maxCol`='" . $postvars["cont_type_maxrow_field"] . "' AND `maxRow`='" . $postvars["cont_type_maxcol_field"] . "') OR `containerName`='" . $postvars["cont_type_name_field"] . "' AND `status`='ACTIVE'", $conn) or die( "ERROR IN SQL STATEMENT in CONT TYPE: " . mysql_error());
+		
+		if ($type_check_ar = mysql_fetch_array($type_check_rs, MYSQL_ASSOC))
+		{
+			return "Error Occured inserting new Container Type: Duplicate Entry Found!";
+		}
+		else
+		{
+			mysql_query("INSERT `ContainerTypeID_tbl` (`contTypeID`, `containerName`, `maxCol`, `maxRow`, `status`) VALUES ('', '" . $postvars["cont_type_name_field"] . "', '" . $postvars["cont_type_maxcol_field"] . "', '" . $postvars["cont_type_maxrow_field"] . "','ACTIVE')" ) or die ("ERROR IN INSERTING NEW CONT TYPE: " . mysql_error());
+
+			return "Container Type successfully inserted!";
+		}
+	}
+}
+
+?>
diff --git a/OpenFreezer/Location/Location_Funct_Class.php b/OpenFreezer/Location/Location_Funct_Class.php
new file mode 100755
index 0000000..f3f6cd3
--- /dev/null
+++ b/OpenFreezer/Location/Location_Funct_Class.php
@@ -0,0 +1,1469 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2010 Pawson Laboratory, All Rights Reserved
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Location
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+ * This class handles general location functions
+ *
+ * @author John Paul Lee @version 2005
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Location
+ *
+ * @copyright  2005-2010 Pawson Laboratory
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+class Location_Funct_Class
+{
+	/**
+	 * Default constructor
+	*/
+	function Location_Funct_Class()
+	{}
+
+	/**
+	 * Fetch the internal database ID of a container SIZE from its name
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING $name E.g. '81-slot box'
+	 * @return INT Internal database ID of the container size
+	*/
+	function convertContTypeName_to_ID($name)
+	{
+		global $conn;
+		
+		$typeID_rs = mysql_query("SELECT `contTypeID` FROM `ContainerTypeID_tbl` WHERE `containerName`='" . $name . "' AND `status`='ACTIVE'", $conn) or die( "Error in converting NAME to ID in SQL: " . mysql_error());
+	
+		if ($typeID_ar = mysql_fetch_array($typeID_rs, MYSQL_ASSOC))
+		{
+			return $typeID_ar["contTypeID"];
+		}
+		
+		return -1;
+	}
+	
+	/**
+	 * Fetch the internal database ID of a container TYPE from its name
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING $name E.g. 'Glycerol Stocks'
+	 * @return INT Internal database ID of the container type
+	*/
+	function convertContGroupName_to_ID($name)
+	{
+		global $conn;
+		
+		$groupID_rs = mysql_query("SELECT `contGroupID` FROM `ContainerGroup_tbl` WHERE `contGroupName`='" . $name . "' AND `status`='ACTIVE'", $conn) or die("ERROR READING SQL GROUP NAME: " . mysql_error());
+
+		if ($groupID_ar = mysql_fetch_array($groupID_rs, MYSQL_ASSOC))
+		{
+			return $groupID_ar["contGroupID"];
+		}
+		
+		return -1;
+	}
+	
+	/**
+	 * Fetch a container's name given its internal db ID
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2007-04-24
+	 *
+	 * @param INT $contID
+	 * @return STRING
+	*/
+	function getContainerName($contID)
+	{
+		global $conn;
+		
+		$contID_rs = mysql_query("SELECT `name` FROM `Container_tbl` WHERE `containerID`='" . $contID . "'", $conn) or die("Could not select container name: " . mysql_error());
+		
+		if ($contID_ar = mysql_fetch_array($contID_rs, MYSQL_ASSOC))
+		{
+			return $contID_ar["name"];
+		}
+		
+		return "";
+	}
+	
+	/**
+	 * Determine the group name (type) of a given container
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2007-05-22
+	 *
+	 * @param INT $contID
+	 * @return STRING Container type (e.g. Vector, Glycerol Stock, Oligo, Insert, Cell Line)
+	*/
+	function getContainerGroupName($contID)
+	{
+		global $conn;
+		
+		$typeID_rs = mysql_query("SELECT g.`contGroupName` FROM `Container_tbl` c, `ContainerGroup_tbl` g WHERE c.`containerID`='" . $contID . "' AND c.`contGroupID`=g.`contGroupID` AND c.`status`='ACTIVE' AND g.`status`='ACTIVE'", $conn) or die( "Error retrieving container type: " . mysql_error());
+		
+		if ($typeID_ar = mysql_fetch_array($typeID_rs, MYSQL_ASSOC))
+		{
+			return $typeID_ar["contGroupName"];
+		}
+		
+		return "";
+	}
+	
+	/**
+	 * Determine the lab ID of a given container
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param INT $contID
+	 * @return INT
+	*/
+	function getContainerLabID($contID)
+	{
+		global $conn;
+		
+		$typeID_rs = mysql_query("SELECT c.labID FROM Container_tbl c WHERE c.containerID='" . $contID . "' AND c.status='ACTIVE'", $conn) or die( "Error retrieving container type: " . mysql_error());
+		
+		if ($typeID_ar = mysql_fetch_array($typeID_rs, MYSQL_ASSOC))
+		{
+			return $typeID_ar["labID"];
+		}
+		
+		return "";
+	
+	}
+
+	/**
+	 * Update container properties (types of prep attributes)
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-06-05
+	 *
+	 * @param INT $contID
+	 * @param INT $groupID
+	 * @param STRING $isolate_tmp YES or NO - do preps in this container have isolates?
+	*/
+	function updateContainerProperties($contID, $groupID, $isolate_tmp)
+	{
+		global $conn;
+
+		// First, CLEAR CURRENT PROPERTIES OF THE CONTAINER!!!!!!!!
+		mysql_query("UPDATE `Prep_Req_tbl` SET `status`='DEP' WHERE `containerID`='" . $contID . "' AND `status`='ACTIVE'", $conn) or die("Cannot clear container properties: " . mysql_error());
+
+		// Update isolate active state of the container
+		mysql_query("UPDATE `Container_tbl` SET `isolate_active`='" .  $isolate_tmp . "' WHERE `containerID`='" . $contID . "' AND `status`='ACTIVE'", $conn) or die("Error in updating SQL statement: " . mysql_error());
+
+		// Required properties for each container type: HARD-CODED, NEEDS FIXING!!!
+		switch ($groupID)
+		{
+			case '1':	// Vector plates - Method ID, Concentration
+	
+				// Method ID
+				$method_rs = mysql_query("SELECT `elementTypeID` FROM `PrepElemTypes_tbl` WHERE `propertyName`='Method ID'") or die("Error fetching Method ID property");
+	
+				if ($method_ar = mysql_fetch_array($method_rs, MYSQL_ASSOC))
+				{
+					$method_id = $method_ar["elementTypeID"];
+				}
+	
+				mysql_query("INSERT INTO `Prep_Req_tbl` (`prepElementTypeID`, `containerID`, `requirement`) VALUES ('" . $method_id . "', '" . $contID . "','REQ')");
+	
+	
+				// Concentration
+				$conc_rs = mysql_query("SELECT `elementTypeID` FROM `PrepElemTypes_tbl` WHERE `propertyName`='Concentration'") or die("Error fetching Concentration property " . mysql_error());
+	
+				if ($conc_ar = mysql_fetch_array($conc_rs, MYSQL_ASSOC))
+				{
+					$conc_id = $conc_ar["elementTypeID"];
+				}
+	
+				mysql_query("INSERT INTO `Prep_Req_tbl` (`prepElementTypeID`, `containerID`, `requirement`) VALUES ('" . $conc_id . "', '" . $contID . "','REQ')");
+	
+			break;
+	
+			case '2':	// Glycerol Stocks - Bacteria Strain (no concentration!)
+	
+				$bact_rs = mysql_query("SELECT `elementTypeID` FROM `PrepElemTypes_tbl` WHERE `propertyName`='Bacteria Strain'") or die("Error fetching Concentration property " . mysql_error());
+	
+				if ($bact_ar = mysql_fetch_array($bact_rs, MYSQL_ASSOC))
+				{
+					$bact_id = $bact_ar["elementTypeID"];
+				}
+	
+				mysql_query("INSERT INTO `Prep_Req_tbl` (`prepElementTypeID`, `containerID`, `requirement`) VALUES ('" . $bact_id . "', '" . $contID . "','REQ')");
+	
+			break;
+	
+			case '3':	// Oligo boxes/plates - Reagent Source, Concentration
+	
+				// Reagent Source
+				$source_rs = mysql_query("SELECT `elementTypeID` FROM `PrepElemTypes_tbl` WHERE `propertyName`='Reagent Source'") or die("Error fetching Concentration property " . mysql_error());
+	
+				if ($source_ar = mysql_fetch_array($source_rs, MYSQL_ASSOC))
+				{
+					$source_id = $source_ar["elementTypeID"];
+				}
+	
+				mysql_query("INSERT INTO `Prep_Req_tbl` (`prepElementTypeID`, `containerID`, `requirement`) VALUES ('" . $source_id . "', '" . $contID . "','REQ')");
+	
+				// Concentration
+				$conc_rs = mysql_query("SELECT `elementTypeID` FROM `PrepElemTypes_tbl` WHERE `propertyName`='Concentration'") or die("Error fetching Concentration property " . mysql_error());
+	
+				if ($conc_ar = mysql_fetch_array($conc_rs, MYSQL_ASSOC))
+				{
+					$conc_id = $conc_ar["elementTypeID"];
+				}
+	
+				mysql_query("INSERT INTO `Prep_Req_tbl` (`prepElementTypeID`, `containerID`, `requirement`) VALUES ('" . $conc_id . "', '" . $contID . "','REQ')");
+	
+			break;
+	
+			case '4':	//  Insert plates - Alternate ID, 5'/3' digest, Concentration
+	
+				// Alternate ID
+				$alt_id_rs = mysql_query("SELECT `elementTypeID` FROM `PrepElemTypes_tbl` WHERE `propertyName`='Alternate ID'") or die("Error fetching Alternate ID property");
+	
+				if ($alt_id_ar = mysql_fetch_array($alt_id_rs, MYSQL_ASSOC))
+				{
+					$alt_id_id = $alt_id_ar["elementTypeID"];
+				}
+	
+				mysql_query("INSERT INTO `Prep_Req_tbl` (`prepElementTypeID`, `containerID`, `requirement`) VALUES ('" . $alt_id_id . "', '" . $contID . "','REQ')");
+	
+				// 5' digest/3' Digest
+				$digest_rs = mysql_query("SELECT `elementTypeID` FROM `PrepElemTypes_tbl` WHERE `propertyName`='" . addslashes("5' digest/3' Digest") . "'") or die("Error fetching Digest property");
+	
+				if ($digest_ar = mysql_fetch_array($digest_rs, MYSQL_ASSOC))
+				{
+					$digest_id = $digest_ar["elementTypeID"];
+				}
+	
+				mysql_query("INSERT INTO `Prep_Req_tbl` (`prepElementTypeID`, `containerID`, `requirement`) VALUES ('" . $digest_id . "', '" . $contID . "','REQ')");
+	
+				// Concentration
+				$conc_rs = mysql_query("SELECT `elementTypeID` FROM `PrepElemTypes_tbl` WHERE `propertyName`='Concentration'") or die("Error fetching Concentration property");
+	
+				if ($conc_ar = mysql_fetch_array($conc_rs, MYSQL_ASSOC))
+				{
+					$conc_id = $conc_ar["elementTypeID"];
+				}
+	
+				mysql_query("INSERT INTO `Prep_Req_tbl` (`prepElementTypeID`, `containerID`, `requirement`) VALUES ('" . $conc_id . "', '" . $contID . "','REQ')");
+	
+			break;	
+	
+			case '5':	// Cell Lines - Isolate Name, Plates/Vial, Date, Person, Passage
+	
+				// Isolate Name
+				$iso_name_rs = mysql_query("SELECT `elementTypeID` FROM `PrepElemTypes_tbl` WHERE `propertyName`='Isolate Name'") or die("Error fetching Isolate Name property");
+	
+				if ($iso_name_ar = mysql_fetch_array($iso_name_rs, MYSQL_ASSOC))
+				{
+					$iso_name_id = $iso_name_ar["elementTypeID"];
+				}
+	
+				mysql_query("INSERT INTO `Prep_Req_tbl` (`prepElementTypeID`, `containerID`, `requirement`) VALUES ('" . $iso_name_id . "', '" . $contID . "','REQ')");
+	
+				// Plates/Vial
+				$plates_vial_rs = mysql_query("SELECT `elementTypeID` FROM `PrepElemTypes_tbl` WHERE `propertyName`='Plates/Vial'") or die("Error fetching Plates/Vial property");
+	
+				if ($plates_vial_ar = mysql_fetch_array($plates_vial_rs, MYSQL_ASSOC))
+				{
+					$plates_vial_id = $plates_vial_ar["elementTypeID"];
+				}
+	
+				mysql_query("INSERT INTO `Prep_Req_tbl` (`prepElementTypeID`, `containerID`, `requirement`) VALUES ('" . $plates_vial_id . "', '" . $contID . "','REQ')");
+	
+				// Date
+				$date_rs = mysql_query("SELECT `elementTypeID` FROM `PrepElemTypes_tbl` WHERE `propertyName`='Date'") or die("Error fetching Date property");
+	
+				if ($date_ar = mysql_fetch_array($date_rs, MYSQL_ASSOC))
+				{
+					$date_id = $date_ar["elementTypeID"];
+				}
+	
+				mysql_query("INSERT INTO `Prep_Req_tbl` (`prepElementTypeID`, `containerID`, `requirement`) VALUES ('" . $date_id . "', '" . $contID . "','REQ')");
+	
+				// Person
+				$person_rs = mysql_query("SELECT `elementTypeID` FROM `PrepElemTypes_tbl` WHERE `propertyName`='Person'") or die("Error fetching Person property");
+	
+				if ($person_ar = mysql_fetch_array($person_rs, MYSQL_ASSOC))
+				{
+					$person_id = $person_ar["elementTypeID"];
+				}
+	
+				mysql_query("INSERT INTO `Prep_Req_tbl` (`prepElementTypeID`, `containerID`, `requirement`) VALUES ('" . $person_id . "', '" . $contID . "','REQ')");
+	
+				// Passage
+				$passage_rs = mysql_query("SELECT `elementTypeID` FROM `PrepElemTypes_tbl` WHERE `propertyName`='Passage'") or die("Error fetching Person property");
+	
+				if ($passage_ar = mysql_fetch_array($passage_rs, MYSQL_ASSOC))
+				{
+					$passage_id = $passage_ar["elementTypeID"];
+				}
+	
+				mysql_query("INSERT INTO `Prep_Req_tbl` (`prepElementTypeID`, `containerID`, `requirement`) VALUES ('" . $passage_id . "', '" . $contID . "','REQ')");
+	
+			break;
+	
+			default:
+				echo "Reagent type not found in database!<br>";
+			break;
+		}
+	}
+
+	/**
+	 * Get reagent types allowed to be stored in this container type
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-02-09
+	 *
+	 * @param INT $selContType
+	 * @return Array
+	*/
+	function getContainerReagentTypes($selContType)
+	{
+		global $conn;
+	
+		$r_types_rs = mysql_query("SELECT DISTINCT(reagentTypeID) FROM ContainerReagentTypes_tbl WHERE contTypeID='" . $selContType . "' AND status='ACTIVE'", $conn);
+	
+		$allowed_r_types = array();
+	
+		while ($r_types_ar = mysql_fetch_array($r_types_rs, MYSQL_ASSOC))
+		{
+			$rTypeID = $r_types_ar["reagentTypeID"];
+			$allowed_r_types[] = $rTypeID;
+		}
+
+		return $allowed_r_types;
+	}
+
+	/**
+	 * Sort names of plates on plate search page (list returned by selecting a container type)
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-06-02
+	 *
+	 * @param Array $plates_ar
+	*/
+	function sortPlateNames($plates_ar)
+	{
+		// Output the array.  The trick is to sort first the alphabetic and then the numeric portion of the name
+		foreach ($plates_ar as $key => $value)
+		{
+			$plateIndex = strpos($value, "Plate ");
+			$temp_ar[$value] = $key;
+		}
+
+		return $temp_ar;
+	}
+
+	/**
+	 * Usage is different from User.php, modifying
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-01-13
+	 *
+	 * @param INT $selLab
+	*/
+	function printLabList($selLab=0)
+	{
+		global $conn;
+
+		$labList = array();
+
+		$currLabID = $_SESSION["userinfo"]->getLabID();
+		$currUserCategory = $_SESSION["userinfo"]->getCategory();
+
+		// Select list of labs from the database
+		$labList_rs = mysql_query("SELECT labID, lab_name FROM LabInfo_tbl WHERE status='ACTIVE' ORDER BY lab_name", $conn) or die("Error selecting labs: " . mysql_error());
+		
+		while ($labList_ar = mysql_fetch_array($labList_rs, MYSQL_ASSOC))
+		{
+			$labID = $labList_ar["labID"];
+			$labName = $labList_ar["lab_name"];
+			
+			$labList[$labID] = $labName;
+		}
+	
+		if ($currUserCategory == $_SESSION["userCategoryNames"]["Admin"])
+		{
+			echo "<SELECT id=\"labList\" name=\"labs\" style=\"font-size:8pt;\">";
+
+			echo "<OPTION VALUE=\"default\">-- Select Laboratory --</OPTION>";	// Feb. 8/10
+
+			foreach ($labList as $labID => $lab)
+			{
+				if ($selLab != 0)
+				{
+					if ($selLab == $labID)
+						$selected = "SELECTED";
+					else
+						$selected = "";
+				}
+				else
+				{
+					if ($labID == $currLabID)
+						$selected = "SELECTED";
+					else
+						$selected = "";
+				}
+				
+				?><OPTION ID="<?php echo $labID; ?>" NAME="lab_optn" VALUE="<?php echo $labID; ?>" <?php echo $selected; ?>><?php echo $lab; ?></OPTION><?php
+			}
+		
+			echo "</SELECT>";
+		}
+		else
+		{
+			// Select the user's lab and disable the rest
+			echo "<SELECT id=\"labList\" DISABLED name=\"labs\" style=\"font-size:8pt;\">";
+			
+			foreach ($labList as $labID => $lab)
+			{
+				if ($labID == $currLabID)
+				{
+					$selected = "SELECTED";
+				}
+				else
+				{
+					$selected = "";
+				}
+				
+				echo "<OPTION VALUE=\"default\">-- Select Laboratory --</OPTION>";
+
+				?><OPTION ID="<?php echo $labID; ?>" NAME="lab_optn" VALUE="<?php echo $labID; ?>" <?php echo $selected; ?>><?php echo $lab; ?></OPTION><?php
+			}
+		
+			echo "</SELECT>";
+		}
+	}
+
+	/**
+	 * Print a list of storage types (-80 Fridge, room temp, etc. - select the option whose value is $selected)
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-01-13
+	 *
+	 * @param STRING $selected
+	*/
+	function printStorageTypes($selected)
+	{
+		global $conn;
+
+		$props_rs = mysql_query("SELECT locationTypeID, locationTypeName FROM LocationTypes_tbl WHERE status='ACTIVE' ORDER BY locationTypeID") or die("Error fetching storage types: " . mysql_error());
+
+		echo "<SELECT ID='location_types' NAME=\"storage_type\" style=\"font-size:8pt;\">";
+
+		if (!$selected)
+			echo "<OPTION value=\"default\" SELECTED>-- Select storage type -- </OPTION>";
+		else
+			echo "<OPTION value=\"default\" SELECTED>-- Select storage type -- </OPTION>";
+
+		while ($props_ar = mysql_fetch_array($props_rs, MYSQL_ASSOC))
+		{
+			$locationTypeName = $props_ar["locationTypeName"];
+			$locationTypeID = $props_ar["locationTypeID"];
+
+			if ($selected && (strcasecmp($selected, $locationTypeName) == 0))
+				echo "<OPTION SELECTED VALUE='" . $locationTypeID . "' NAME='" . $locationTypeName . "'>" . $locationTypeName . "</OPTION>";
+			else
+				echo "<OPTION VALUE='" . $locationTypeID . "' NAME='" . $locationTypeName . "'>" . $locationTypeName . "</OPTION>";
+		}
+
+		echo "</SELECT>";
+	}
+
+	/**
+	 * Output information summary row for a selected plate (Changing main Location search page)
+	 *
+	 * This is NOT actively used in this version; will apply in redesigning container search view
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2008-08-28
+	 *
+	 * @param STRING $plateName
+	 * @param INT $contTypeID
+	*/
+	function printPlateInfo($plateName, $contTypeID)
+	{
+		global $conn;
+
+		// Aug. 28/08
+		$contCheck_rs = mysql_query("SELECT * FROM Container_tbl WHERE name='" . $plateName . "' AND contGroupID=" . $contTypeID . " AND status='ACTIVE'", $conn) or die("ERROR reading from container table sql error" . mysql_error());
+
+		if ($contCheck_ar = mysql_fetch_array($contCheck_rs, MYSQL_ASSOC))
+		{
+			?>
+			<P><table width="100%" border="1" frame="box" rules="all" bordercolor="#004891" id="preview_container_view">
+			
+			<!-- Updated May 23/07, Marina -->
+			<TR>
+				<TD class="locationHeading" onClick="sortByColumn('barcode')">Barcode</TD>
+	
+				<TD class="locationHeading" onClick="sortByColumn('name')">Name</TD>
+	
+				<TD class="locationHeading" onClick="sortByColumn('containerName')">Type</TD>
+	
+				<TD class="locationHeading" onClick="sortByColumn('container_desc')">Description</TD>
+	
+				<TD class="locationHeading" onClick="sortByColumn('description')">Laboratory</TD>
+	
+				<TD class="locationHeading" onClick="sortByColumn('empty_cells')">Empty Cells</TD>
+				
+				<TD class="locationHeadingNonLink" colspan="3">Links</TD>
+			</TR>
+			<?php
+	
+			// Changed Aug. 28/08
+			$contInfo_rs = mysql_query("SELECT * FROM `Container_tbl` a, `ContainerTypeID_tbl` b, LabInfo_tbl l WHERE a.`name`='" . $plateName . "' AND a.`contTypeID`=b.`contTypeID` AND l.labID=a.labID AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND l.status='ACTIVE'", $conn) or die("ERROR reading from container table sql error" . mysql_error());
+	
+			while ($contInfo_ar = mysql_fetch_array($contInfo_rs, MYSQL_ASSOC))
+			{
+				echo "<tr>";
+				
+					// Sept. 19/07, Marina: New - Barcode
+					echo "<td align=\"center\">" . $contInfo_ar["barcode"] . "</td>";
+		
+					// Name
+					if (isset($contInfo_ar["name"]))
+					{
+						echo "<td class=\"plateNameValue\" style=\"text-align:center\">" . $contInfo_ar["name"] . "</td>";
+					}
+					else
+					{
+						echo "<td>" . "Not Currently Set" . "</td>";
+					}
+		
+					// Size
+					echo "<td class=\"locationOtherValue\">" . $contInfo_ar["containerName"] . "</td>";
+					
+					
+					// Description
+					if( isset( $contInfo_ar["container_desc"] ) )
+					{
+						echo "<td class=\"descriptionValue\"  style=\"text-align:center\">" . $contInfo_ar["container_desc"] . "</td>";
+					}
+					else
+					{
+						echo "<td> </td>";
+					}
+					
+					// Lab - get the complete lab name instead of ID - Marina, May 23/07
+					echo "<td class=\"locationOtherValue\">" . $contInfo_ar["lab_name"] . "</td>";
+		
+					// Empty Cells
+					echo "<td align=\"center\">" . $this->getEmptyCellNum( $contInfo_ar["containerID"], $contInfo_ar["contTypeID"] ) . "</td>";	// may 23/07
+		
+					// "Modify" and "View" links
+					// Mar 28/06, Marina -- Disallow modification of occupied containers
+					$size_rs  = mysql_query( "SELECT `maxCol`, `maxRow` FROM `ContainerTypeID_tbl` WHERE `contTypeID`='" . $contInfo_ar["contTypeID"] . "' AND `status`='ACTIVE'" , $conn ) or die("Error reading container original info in SQL statement: " . mysql_error());
+						
+					if ($size_ar = mysql_fetch_array( $size_rs, MYSQL_ASSOC ) )
+					{
+						$cols = $size_ar["maxCol"];
+						$rows = $size_ar["maxRow"];
+					}
+				
+					$capacity = $cols * $rows;
+					$empty_cells = $this->getEmptyCellNum($contInfo_ar["containerID"], $contInfo_ar["contTypeID"]);
+					$occupied_cells = $capacity - $empty_cells;
+		
+					// Sept. 12/07, Marina: A Reader cannot modify in any case
+					$currUserID = $_SESSION["userinfo"]->getUserID();
+					$currUserCategory = $_SESSION["userinfo"]->getCategory();
+		
+					if (($occupied_cells > 0) || ($currUserCategory == $_SESSION["userCategoryNames"]["Reader"]))
+					{
+						echo "<td class=\"adminDisabled\">Modify</td>";
+					}
+					else
+					{
+						echo "<td class=\"locationOtherValue\">" . "<a href=\"Location.php?View=5&Mod=" . $contInfo_ar["containerID"] . "\">Modify</a></td>";
+						
+					}
+		
+					echo "<td class=\"locationOtherValue\">" . "<a href=\"Location.php?View=2&Mod=" . $contInfo_ar["containerID"] . "\">View</a></td>";	// may 23/07
+
+				echo "</tr>";
+			}
+	
+			echo "</table>";
+		}
+	}
+
+	/**
+	 * Find the experiment ID of a given reagent
+	 *
+	 * @author Marina Olhovsky
+	 * @version April 27, 2011
+	 *
+	 * @param Array or INT User can query for a single reagent ID or a list of reagent IDs to fetch experiment ID(s) for
+	 *
+	 * @return Array
+	*/
+	function findReagentExperimentID($rID)
+	{
+		global $conn;
+
+		$experiments_ar = Array();
+
+		if (is_array($rID))
+		{
+//			$rID_str = implode($rID, ",");
+//			$rID_list = "(" . $rID_str . ")";
+
+			foreach ($rID as $a => $r)
+			{
+				$exp_rs = mysql_query("SELECT expID FROM Experiment_tbl WHERE reagentID = '" . $r . "' AND status='ACTIVE'");	
+				
+				while ($exp_ar = mysql_fetch_array($exp_rs, MYSQL_ASSOC))
+				{
+					$expID = $exp_ar["expID"];
+					$experiments_ar[$r] = $expID;
+				}
+			}
+		}
+		else
+		{
+			$exp_rs = mysql_query("SELECT expID FROM Experiment_tbl WHERE reagentID='" . $rID . "' AND status='ACTIVE'");
+		
+			while ($exp_ar = mysql_fetch_array($exp_rs, MYSQL_ASSOC))
+			{
+				$expID = $exp_ar["expID"];
+				$experiments_ar[] = $expID;
+			}
+		}
+
+		return $experiments_ar;
+	}
+
+
+	/**
+	 * Print search results by container type (main container search view, where a type - 'Glycerol Stocks' or 'Liquid Nitrogen' is selected)
+	 *
+	 * Last modified: May 23/07, Marina: Add option to sort by column
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param INT $contGroupID
+	*/
+	function printContainerInfo($contGroupID)
+	{
+		//print_r($_POST);
+
+		global $conn;
+		?>
+		<table width="100%" border="1" frame="box" rules="all" bordercolor="#004891" id="preview_container_view">
+		
+		<!-- Updated May 23/07, Marina -->
+		<TR>
+			<TD class="locationHeading"  style="padding-left:3px; padding-right:3px;" onClick="sortByColumn('contGroupCount')">Container #</TD>
+
+			<TD class="locationHeading" onClick="sortByColumn('barcode')" style="padding-left:3px; padding-right:3px;">Barcode</TD>
+
+			<TD class="locationHeading"  style="padding-left:3px; padding-right:3px;" onClick="sortByColumn('name')">Name</TD>
+
+			<TD  style="padding-left:3px; padding-right:3px;" class="locationHeading" onClick="sortByColumn('containerName')">Type</TD>
+
+			<TD class="locationHeading"  style="padding-left:3px; padding-right:3px;" onClick="sortByColumn('container_desc')">Description</TD>
+
+			<TD class="locationHeading" onClick="sortByColumn('description')" style="padding-left:3px; padding-right:3px;">Laboratory</TD>
+
+			<TD class="locationHeading" onClick="sortByColumn('empty_cells')" style="padding-left:3px; padding-right:3px;">Empty Cells</TD>
+			
+			<TD class="locationHeadingNonLink" style="padding-left:3px; padding-right:3px;" colspan="3">Links</TD>
+		</TR>
+		<?php
+ 		
+		// May 23/07, Marina: Add column 'sort' option
+		if (isset($_POST["sortOn"]) && (strlen($_POST["sortOn"]) != 0))
+		{
+			$sortBy = $_POST["sortOn"];
+
+			if ($sortBy != "empty_cells")
+			{
+				$q = "SELECT * FROM `Container_tbl` a, `ContainerTypeID_tbl` b, LabInfo_tbl l WHERE a.`contGroupID`='" . $contGroupID . "' AND a.`contTypeID`=b.`contTypeID` AND l.labID=a.labID AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND l.status='ACTIVE' ORDER BY " . $sortBy;
+
+				//echo $q;
+
+				$contInfo_rs = mysql_query("SELECT * FROM `Container_tbl` a, `ContainerTypeID_tbl` b, LabInfo_tbl l WHERE a.`contGroupID`='" . $contGroupID . "' AND a.`contTypeID`=b.`contTypeID` AND l.labID=a.labID AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND l.status='ACTIVE' ORDER BY " . $sortBy, $conn) or die("ERROR reading from container table sql error" . mysql_error());
+
+				while ($contInfo_ar = mysql_fetch_array($contInfo_rs, MYSQL_ASSOC))
+				{
+					$contLab = $contInfo_ar["labID"];
+
+					echo "<tr>";
+
+					// Container #
+					// (represents the container's SERIAL NUMBER IN ITS CATEGORY)
+					// (e.g. Cont.#37 comes 12th in the Glycerol Stocks group, etc.)
+					echo "<td align=\"center\">" . $contInfo_ar["contGroupCount"] . "</td>";
+
+					// Sept. 19/07, Marina: New - Barcode
+					echo "<td align=\"center\">" . $contInfo_ar["barcode"] . "</td>";
+
+					// Name
+					if( isset( $contInfo_ar["name"] ) )
+					{
+						echo "<td class=\"plateNameValue\">" . $contInfo_ar["name"] . "</td>";	// may 23/07
+					}
+					else
+					{
+						echo "<td>" . "Not Currently Set" . "</td>";
+					}
+
+					// Size
+					echo "<td class=\"locationOtherValue\">" . $contInfo_ar["containerName"] . "</td>";	// may 23/07
+					
+					// Description
+					if( isset( $contInfo_ar["container_desc"] ) )
+					{
+						echo "<td class=\"descriptionValue\">" . $contInfo_ar["container_desc"] . "</td>";	// may 23/07
+					}
+					else
+					{
+						echo "<td> </td>";
+					}
+					
+					// Lab - get the complete lab name instead of ID - Marina, May 23/07
+					echo "<td class=\"locationOtherValue\">" . $contInfo_ar["lab_name"] . "</td>";		// may 23/07
+
+					// Empty Cells
+					echo "<td align=\"center\">" . $this->getEmptyCellNum( $contInfo_ar["containerID"], $contInfo_ar["contTypeID"] ) . "</td>";	// may 23/07
+
+					// "Modify" and "View" links
+					// Mar 28/06, Marina -- Disallow modification of occupied containers
+					$size_rs  = mysql_query( "SELECT `maxCol`, `maxRow` FROM `ContainerTypeID_tbl` WHERE `contTypeID`='" . $contInfo_ar["contTypeID"] . "' AND `status`='ACTIVE'" , $conn ) or die("Error reading container original info in SQL statement: " . mysql_error());
+					
+					if ($size_ar = mysql_fetch_array( $size_rs, MYSQL_ASSOC ) )
+					{
+						$cols = $size_ar["maxCol"];
+						$rows = $size_ar["maxRow"];
+					}
+				
+					$capacity = $cols * $rows;
+					$empty_cells = $this->getEmptyCellNum($contInfo_ar["containerID"], $contInfo_ar["contTypeID"]);
+					$occupied_cells = $capacity - $empty_cells;
+
+					// Sept. 12/07, Marina: A Reader cannot modify in any case
+					$currUserID = $_SESSION["userinfo"]->getUserID();
+					$currUserCategory = $_SESSION["userinfo"]->getCategory();
+					$currUserProjects = getAllowedUserProjectIDs($currUserID);
+					$currUserLab = $_SESSION["userinfo"]->getLabID();
+
+					$rfunc_obj = new Reagent_Function_Class();
+
+					$packetPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["packet id"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+
+					// Jan. 7, 2010: find out whether user has project access to ALL preps in container; if s/he does not, disable 'View' link
+					$q = "SELECT DISTINCT(l.propertyValue) FROM Container_tbl c, ReagentPropList_tbl l, Prep_tbl p, Wells_tbl w, Isolate_tbl i, Experiment_tbl e WHERE c.containerID='" . $contInfo_ar["containerID"] . "' AND w.containerID=c.containerID AND p.wellID=w.wellID AND i.isolate_pk=p.isolate_pk AND i.expID=e.expID AND e.reagentID=l.reagentID AND l.propertyID='" . $packetPropID . "' AND c.status='ACTIVE' AND l.status='ACTIVE' AND p.status='ACTIVE' AND w.status='ACTIVE' AND i.status='ACTIVE' AND e [...]
+
+					$prepProject_rs = mysql_query($q, $conn) or die("Error finding prep project IDs: " . mysql_error());
+					$prepProjects = Array();
+
+					while ($prepProject_ar = mysql_fetch_array($prepProject_rs, MYSQL_ASSOC))
+					{
+						$prepProjects[] = $prepProject_ar["propertyValue"];
+					}
+
+					$isAllowed = false;
+
+					foreach ($prepProjects as $pKey => $pID)
+					{
+						if (in_array($pID, $currUserProjects))
+						{
+							$isAllowed = true;
+							break;
+						}
+					}
+
+					if ($occupied_cells == 0)
+					{
+						// may view empty containers
+						$isAllowed = true;
+					}
+
+					if ($isAllowed)
+						echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\">" . "<a href=\"Location.php?View=2&Mod=" . $contInfo_ar["containerID"] . "\">View</a></td>";	// may 23/07
+					else
+						echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\">" . "<SPAN class=\"linkDisabled\" style=\"font-size:9pt;\">View</SPAN></td>";
+
+					if (($occupied_cells == 0) && ($currUserCategory != $_SESSION["userCategoryNames"]["Reader"]) && (($contLab == $currUserLab) || ($currUserCategory == $_SESSION["userCategoryNames"]["Admin"])))
+					{
+						echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\">" . "<a href=\"Location.php?View=5&Mod=" . $contInfo_ar["containerID"] . "\">Modify</a></td>";	// may 23/07
+						
+					}
+					else
+					{
+						echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\"><span class=\"linkDisabled\" style=\"font-size:9pt;\">Modify</span></td>";		// may 23/07
+					}
+
+					// Jan. 4, 2010
+					if (($currUserCategory != $_SESSION["userCategoryNames"]["Reader"]) && (($contLab == $currUserLab) || ($currUserCategory == $_SESSION["userCategoryNames"]["Admin"])))
+					{
+						echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\">" . "<a href=\"Location.php?View=3&Mod=" . $contInfo_ar["containerID"] . "\">Location</a></td>";
+					}
+					else
+					{
+						echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\"><span class=\"linkDisabled\" style=\"font-size:9pt;\">Location</span></td>";
+					}
+
+					echo "</tr>";
+				}
+			}
+			else
+			{
+				// Find empty cells first and sort; then repeat selection (use different variable names)
+				$contInfo_tmp_rs = mysql_query("SELECT * FROM `Container_tbl` a, `ContainerTypeID_tbl` b, LabInfo_tbl l WHERE a.`contGroupID`='" . $contGroupID . "' AND a.`contTypeID`=b.`contTypeID` AND l.labID=a.labID AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND l.status='ACTIVE'", $conn) or die("ERROR reading from container table sql error" . mysql_error());			
+
+				// generate a sorted array by empty cells
+				while ($contInfo_tmp_ar = mysql_fetch_array($contInfo_tmp_rs, MYSQL_ASSOC))
+				{
+					$cEmpty = $this->getEmptyCellNum($contInfo_tmp_ar["containerID"], $contInfo_tmp_ar["contTypeID"]);
+					$cEmpty_sorted[$contInfo_tmp_ar["containerID"]] = $cEmpty;
+				}
+
+				asort($cEmpty_sorted);
+				
+				//print_r($cEmpty_sorted);
+
+				// Repeat search, this time fetching actual containers
+				foreach ($cEmpty_sorted as $contID => $emptyCells)
+				{
+					//echo $contID . ", ";
+
+				//	echo "SELECT * FROM `Container_tbl` a, `ContainerTypeID_tbl` b, LabInfo_tbl l WHERE a.`containerID`='" . $contID . "' AND a.`contTypeID`=b.`contTypeID` AND l.labID=a.labID AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND l.status='ACTIVE'";
+
+					$contInfo_rs = mysql_query("SELECT * FROM `Container_tbl` a, `ContainerTypeID_tbl` b, LabInfo_tbl l WHERE a.`containerID`='" . $contID . "' AND a.`contTypeID`=b.`contTypeID` AND l.labID=a.labID AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND l.status='ACTIVE'", $conn) or die("ERROR reading from container table sql error" . mysql_error());
+
+					while ($contInfo_ar = mysql_fetch_array($contInfo_rs, MYSQL_ASSOC))
+					{
+						$contLab = $contInfo_ar["labID"];
+
+						echo "<tr>";
+
+						// Container #
+						// (represents the container's SERIAL NUMBER IN ITS CATEGORY)
+						// (e.g. Cont.#37 comes 12th in the Glycerol Stocks group, etc.)
+						echo "<td align=\"center\">" . $contInfo_ar["contGroupCount"] . "</td>";
+
+						// Sept. 19/07, Marina: New - Barcode
+						echo "<td align=\"center\">" . $contInfo_ar["barcode"] . "</td>";
+
+						// Name
+						if( isset( $contInfo_ar["name"] ) )
+						{
+							echo "<td class=\"plateNameValue\">" . $contInfo_ar["name"] . "</td>";	// may 23/07
+						}
+						else
+						{
+							echo "<td>" . "Not Currently Set" . "</td>";
+						}
+
+						// Size
+						echo "<td class=\"locationOtherValue\">" . $contInfo_ar["containerName"] . "</td>";	// may 23/07
+						
+						
+						// Description
+						if( isset( $contInfo_ar["container_desc"] ) )
+						{
+							echo "<td class=\"descriptionValue\">" . $contInfo_ar["container_desc"] . "</td>";	// may 23/07
+						}
+						else
+						{
+							echo "<td> </td>";
+						}
+						
+						// Lab - get the complete lab name instead of ID - Marina, May 23/07
+						echo "<td class=\"locationOtherValue\">" . $contInfo_ar["lab_name"] . "</td>";		// may 23/07
+
+						// Empty Cells
+						echo "<td align=\"center\">" . $cEmpty_sorted[$contInfo_ar["containerID"]] . "</td>";
+
+						//echo "<td align=\"center\">" . $this->getEmptyCellNum( $contInfo_ar["containerID"], $contInfo_ar["contTypeID"] ) . "</td>";	// may 23/07
+
+						// "Modify" and "View" links
+						// Mar 28/06, Marina -- Disallow modification of occupied containers
+						$size_rs  = mysql_query( "SELECT `maxCol`, `maxRow` FROM `ContainerTypeID_tbl` WHERE `contTypeID`='" . $contInfo_ar["contTypeID"] . "' AND `status`='ACTIVE'" , $conn ) or die("Error reading container original info in SQL statement: " . mysql_error());
+						
+						if ($size_ar = mysql_fetch_array( $size_rs, MYSQL_ASSOC ) )
+						{
+							$cols = $size_ar["maxCol"];
+							$rows = $size_ar["maxRow"];
+						}
+					
+						$capacity = $cols * $rows;
+						$empty_cells = $this->getEmptyCellNum($contInfo_ar["containerID"], $contInfo_ar["contTypeID"]);
+						$occupied_cells = $capacity - $empty_cells;
+
+						// Sept. 12/07, Marina: A Reader cannot modify in any case
+						$currUserID = $_SESSION["userinfo"]->getUserID();
+						$currUserCategory = $_SESSION["userinfo"]->getCategory();
+						$currUserProjects = getAllowedUserProjectIDs($currUserID);
+						$currUserLab = $_SESSION["userinfo"]->getLabID();
+
+						$rfunc_obj = new Reagent_Function_Class();
+
+						$packetPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["packet id"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+
+						// Jan. 7, 2010: find out whether user has project access to ALL preps in container; if s/he does not, disable 'View' link
+						$q = "SELECT DISTINCT(l.propertyValue) FROM Container_tbl c, ReagentPropList_tbl l, Prep_tbl p, Wells_tbl w, Isolate_tbl i, Experiment_tbl e WHERE c.containerID='" . $contInfo_ar["containerID"] . "' AND w.containerID=c.containerID AND p.wellID=w.wellID AND i.isolate_pk=p.isolate_pk AND i.expID=e.expID AND e.reagentID=l.reagentID AND l.propertyID='" . $packetPropID . "' AND c.status='ACTIVE' AND l.status='ACTIVE' AND p.status='ACTIVE' AND w.status='ACTIVE' AND i.status='ACTIVE' AND  [...]
+
+						$prepProject_rs = mysql_query($q, $conn) or die("Error finding prep project IDs: " . mysql_error());
+						$prepProjects = Array();
+
+						while ($prepProject_ar = mysql_fetch_array($prepProject_rs, MYSQL_ASSOC))
+						{
+							$prepProjects[] = $prepProject_ar["propertyValue"];
+						}
+
+						$isAllowed = false;
+
+						foreach ($prepProjects as $pKey => $pID)
+						{
+							if (in_array($pID, $currUserProjects))
+							{
+								$isAllowed = true;
+								break;
+							}
+						}
+
+						if ($occupied_cells == 0)
+						{
+							// may view empty containers
+							$isAllowed = true;
+						}
+
+						if ($isAllowed)
+							echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\">" . "<a href=\"Location.php?View=2&Mod=" . $contInfo_ar["containerID"] . "\">View</a></td>";	// may 23/07
+						else
+							echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\">" . "<SPAN class=\"linkDisabled\" style=\"font-size:9pt;\">View</SPAN></td>";
+
+						if (($occupied_cells == 0) && ($currUserCategory != $_SESSION["userCategoryNames"]["Reader"]) && (($contLab == $currUserLab) || ($currUserCategory == $_SESSION["userCategoryNames"]["Admin"])))
+						{
+							echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\">" . "<a href=\"Location.php?View=5&Mod=" . $contInfo_ar["containerID"] . "\">Modify</a></td>";	// may 23/07
+							
+						}
+						else
+						{
+							echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\"><span class=\"linkDisabled\" style=\"font-size:9pt;\">Modify</span></td>";		// may 23/07
+						}
+
+						// Jan. 4, 2010
+						if (($currUserCategory != $_SESSION["userCategoryNames"]["Reader"]) && (($contLab == $currUserLab) || ($currUserCategory == $_SESSION["userCategoryNames"]["Admin"])))
+						{
+							echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\">" . "<a href=\"Location.php?View=3&Mod=" . $contInfo_ar["containerID"] . "\">Location</a></td>";
+						}
+						else
+						{
+							echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\"><span class=\"linkDisabled\" style=\"font-size:9pt;\">Location</span></td>";
+						}
+
+						echo "</tr>";
+					}
+				}
+			}
+		}
+		else
+		{
+			//$q = "SELECT * FROM `Container_tbl` a, `ContainerTypeID_tbl` b, LabInfo_tbl l WHERE a.`contGroupID`='" . $contGroupID . "' AND a.`contTypeID`=b.`contTypeID` AND l.labID=a.labID AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND l.status='ACTIVE' ORDER BY contGroupCount";
+
+			$contInfo_rs = mysql_query("SELECT * FROM `Container_tbl` a, `ContainerTypeID_tbl` b, LabInfo_tbl l WHERE a.`contGroupID`='" . $contGroupID . "' AND a.`contTypeID`=b.`contTypeID` AND l.labID=a.labID AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND l.status='ACTIVE' ORDER BY contGroupCount", $conn) or die("ERROR reading from container table sql error" . mysql_error());
+
+			while ($contInfo_ar = mysql_fetch_array($contInfo_rs, MYSQL_ASSOC))
+			{
+				$contLab = $contInfo_ar["labID"];
+
+				echo "<tr>";
+
+				// Container #
+				// (represents the container's SERIAL NUMBER IN ITS CATEGORY)
+				// (e.g. Cont.#37 comes 12th in the Glycerol Stocks group, etc.)
+				echo "<td align=\"center\">" . $contInfo_ar["contGroupCount"] . "</td>";
+
+				// Sept. 19/07, Marina: New - Barcode
+				echo "<td align=\"center\">" . $contInfo_ar["barcode"] . "</td>";
+
+				// Name
+				if( isset( $contInfo_ar["name"] ) )
+				{
+					echo "<td class=\"plateNameValue\">" . $contInfo_ar["name"] . "</td>";	// may 23/07
+				}
+				else
+				{
+					echo "<td>" . "Not Currently Set" . "</td>";
+				}
+
+				// Size
+				echo "<td class=\"locationOtherValue\">" . $contInfo_ar["containerName"] . "</td>";	// may 23/07
+				
+				
+				// Description
+				if( isset( $contInfo_ar["container_desc"] ) )
+				{
+					echo "<td class=\"descriptionValue\">" . $contInfo_ar["container_desc"] . "</td>";	// may 23/07
+				}
+				else
+				{
+					echo "<td> </td>";
+				}
+				
+				// Lab - get the complete lab name instead of ID - Marina, May 23/07
+				echo "<td class=\"locationOtherValue\">" . $contInfo_ar["lab_name"] . "</td>";		// may 23/07
+
+				// Empty Cells
+				echo "<td align=\"center\">" . $this->getEmptyCellNum( $contInfo_ar["containerID"], $contInfo_ar["contTypeID"] ) . "</td>";	// may 23/07
+
+				// "Modify" and "View" links
+				// Mar 28/06, Marina -- Disallow modification of occupied containers
+				$size_rs  = mysql_query( "SELECT `maxCol`, `maxRow` FROM `ContainerTypeID_tbl` WHERE `contTypeID`='" . $contInfo_ar["contTypeID"] . "' AND `status`='ACTIVE'" , $conn ) or die("Error reading container original info in SQL statement: " . mysql_error());
+				
+				if ($size_ar = mysql_fetch_array( $size_rs, MYSQL_ASSOC ) )
+				{
+					$cols = $size_ar["maxCol"];
+					$rows = $size_ar["maxRow"];
+				}
+			
+				$capacity = $cols * $rows;
+				$empty_cells = $this->getEmptyCellNum($contInfo_ar["containerID"], $contInfo_ar["contTypeID"]);
+				$occupied_cells = $capacity - $empty_cells;
+
+				// Sept. 12/07, Marina: A Reader cannot modify in any case
+				$currUserID = $_SESSION["userinfo"]->getUserID();
+				$currUserCategory = $_SESSION["userinfo"]->getCategory();
+				$currUserProjects = getAllowedUserProjectIDs($currUserID);
+				$currUserLab = $_SESSION["userinfo"]->getLabID();
+
+				$rfunc_obj = new Reagent_Function_Class();
+
+				$packetPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["packet id"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+
+				// Jan. 7, 2010: find out whether user has project access to ALL preps in container; if s/he does not, disable 'View' link
+				$q = "SELECT DISTINCT(l.propertyValue) FROM Container_tbl c, ReagentPropList_tbl l, Prep_tbl p, Wells_tbl w, Isolate_tbl i, Experiment_tbl e WHERE c.containerID='" . $contInfo_ar["containerID"] . "' AND w.containerID=c.containerID AND p.wellID=w.wellID AND i.isolate_pk=p.isolate_pk AND i.expID=e.expID AND e.reagentID=l.reagentID AND l.propertyID='" . $packetPropID . "' AND c.status='ACTIVE' AND l.status='ACTIVE' AND p.status='ACTIVE' AND w.status='ACTIVE' AND i.status='ACTIVE' AND e. [...]
+
+				$prepProject_rs = mysql_query($q, $conn) or die("Error finding prep project IDs: " . mysql_error());
+				$prepProjects = Array();
+
+				while ($prepProject_ar = mysql_fetch_array($prepProject_rs, MYSQL_ASSOC))
+				{
+					$prepProjects[] = $prepProject_ar["propertyValue"];
+				}
+
+				$isAllowed = false;
+
+				foreach ($prepProjects as $pKey => $pID)
+				{
+					if (in_array($pID, $currUserProjects))
+					{
+						$isAllowed = true;
+						break;
+					}
+				}
+
+				if ($occupied_cells == 0)
+				{
+					// may view empty containers
+					$isAllowed = true;
+				}
+
+				if ($isAllowed)
+					echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\">" . "<a href=\"Location.php?View=2&Mod=" . $contInfo_ar["containerID"] . "\">View</a></td>";	// may 23/07
+				else
+					echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\">" . "<SPAN class=\"linkDisabled\" style=\"font-size:9pt;\">View</SPAN></td>";
+
+				if (($occupied_cells == 0) && ($currUserCategory != $_SESSION["userCategoryNames"]["Reader"]) && (($contLab == $currUserLab) || ($currUserCategory == $_SESSION["userCategoryNames"]["Admin"])))
+				{
+					echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\">" . "<a href=\"Location.php?View=5&Mod=" . $contInfo_ar["containerID"] . "\">Modify</a></td>";	// may 23/07
+					
+				}
+				else
+				{
+					echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\"><span class=\"linkDisabled\" style=\"font-size:9pt;\">Modify</span></td>";		// may 23/07
+				}
+
+				// Jan. 4, 2010
+				if (($currUserCategory != $_SESSION["userCategoryNames"]["Reader"]) && (($contLab == $currUserLab) || ($currUserCategory == $_SESSION["userCategoryNames"]["Admin"])))
+				{
+					echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\">" . "<a href=\"Location.php?View=3&Mod=" . $contInfo_ar["containerID"] . "\">Location</a></td>";
+				}
+				else
+				{
+					echo "<td class=\"locationOtherValue\" style=\"padding-left:7px; padding-right:7px;\"><span class=\"linkDisabled\" style=\"font-size:9pt;\">Location</span></td>";
+				}
+
+				echo "</tr>";
+			}
+		}
+		
+		echo "</table>";
+	}
+	
+
+	/**
+	 * Retrieve size of container identified by $contID
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-01-03
+	 *
+	 * @param INT $contID
+	 * @return INT
+	*/
+	function getContainerSize($contID)
+	{
+		global $conn;
+		
+		$contSize = 0;
+
+		$maxContSize_rs = mysql_query("SELECT (`maxCol` * `maxRow`) AS maxSize FROM `ContainerTypeID_tbl` WHERE `contTypeID`='" . $contTypeID . "' AND `status`='ACTIVE'") or die("ERROR reading container type id table sql " . mysql_error());
+		
+		if ($maxContSize_ar = mysql_fetch_array($maxContSize_rs, MYSQL_ASSOC))
+		{
+			$contSize = $contSize_ar["maxSize"];
+		}
+
+		return $contSize;
+	}
+
+	/**
+	 * Determine if any containers of type $contTypeID exist in the database
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-01-12
+	 *
+	 * @param INT $contTypeID
+	 * @return boolean
+	*/
+	function isUsedContainerType($contTypeID)
+	{
+		global $conn;
+
+		$numConts = 0;
+
+		$contTypeSet = mysql_query("SELECT COUNT(containerID) AS cont_num FROM Container_tbl WHERE contGroupID='" . $contTypeID . "' AND status='ACTIVE'", $conn);
+
+		if ($contTypes = mysql_fetch_array($contTypeSet, MYSQL_ASSOC))
+		{
+			$numConts = $contTypes["cont_num"];
+		}
+
+		return $numConts > 0;
+	}
+
+
+	/**
+	 * Determine if this container is empty
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-01-03
+	 *
+	 * @param INT $contID
+	 * @return boolean
+	*/
+	function isEmpty($contID)
+	{
+		global $conn;
+	
+		$contTypeID = $this->getContainerSize($contID);
+		return ($this->getEmptyCellNum($contID, $contTypeID) == 0);
+	}
+
+
+	/**
+	 * Get the number of unoccupied slots in this container
+	 *
+	 * Last modified: October 9, 2006
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param INT $contID
+	 * @param INT $contTypeID
+	 *
+	 * @return INT
+	*/
+	function getEmptyCellNum($contID, $contTypeID)
+	{
+		global $conn;
+		
+		// Get the maximum capacity of this container TYPE (i.e. 96, 81, etc)
+		$maxContSize_rs = mysql_query("SELECT (`maxCol` * `maxRow`) AS maxSize FROM `ContainerTypeID_tbl` WHERE `contTypeID`='" . $contTypeID . "' AND `status`='ACTIVE'") or die("ERROR reading container type id table sql " . mysql_error());
+		
+		$maxContSize_ar = mysql_fetch_array($maxContSize_rs, MYSQL_ASSOC);	
+		
+		// Find number of wells occupied in current container:
+		$maxWells_rs = mysql_query("SELECT COUNT(p.`wellID`) AS currentSize FROM `Wells_tbl` w, `Prep_tbl` p WHERE w.`containerID`='" . $contID . "' AND w.`wellID`=p.`wellID` AND w.`status`='ACTIVE' AND p.`status`='ACTIVE'") or die("ERROR reading container table!" . mysql_error());
+	
+		$maxWells_ar = mysql_fetch_array( $maxWells_rs, MYSQL_ASSOC );
+		
+		// empty cells = (capacity - occupied cells)
+		return $maxContSize_ar["maxSize"] - $maxWells_ar["currentSize"];
+	}
+	
+
+	/**
+	 * Is this container isolate active?
+	 *
+	 * Modified Sept. 20/07: Changed table structure - isolate_active is no longer a column in Container_tbl but has been moved into ContainerGroup_tbl - modify selection function accordingly
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param INT $contID
+	 * @return boolean
+	*/
+	function isIsoActive($contID)
+	{
+		global $conn;
+		
+		$contGroupName = $this->getContainerGroupName($contID);
+
+		$isoAct_rs = mysql_query("SELECT `isolate_active` FROM `ContainerGroup_tbl` WHERE `contGroupName`='" . $contGroupName . "' AND `status`='ACTIVE'", $conn) or die( "FAILURE IN: Location_Funct_Class.getIsoAct_State(1): " . mysql_error() );
+		
+		$isoAct_ar = mysql_fetch_array( $isoAct_rs , MYSQL_ASSOC );
+		
+		$iso_act = $isoAct_ar["isolate_active"];
+		
+		mysql_free_result( $isoAct_rs );
+		unset( $isoAct_rs, $isoAct_ar );
+		
+		return $iso_act;
+	}
+
+	/**
+	 * Return the attributes of this container type
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-01-08
+	 *
+	 * @param INT $selContType
+	 * @return Array
+	*/
+	function getContainerTypeAttributes($selContType)
+	{
+		global $conn;
+
+		$attrs_rs = mysql_query("SELECT p.elementTypeID, p.propertyName FROM ContainerTypeAttributes_tbl c, PrepElemTypes_tbl p WHERE c.containerTypeID='" . $selContType . "' AND c.containerTypeAttributeID=p.elementTypeID AND c.status='ACTIVE' AND p.status='ACTIVE' ORDER BY p.elementTypeID");
+
+		$props = Array();
+
+		while ($attrs_ar = mysql_fetch_array($attrs_rs, MYSQL_ASSOC))
+		{
+			$propID = $attrs_ar["elementTypeID"];
+			$propType = $attrs_ar["propertyName"];
+			$props[$propID] = $propType;
+		}
+
+		return $props;
+	}
+
+
+	/**
+	 * Does this reagent type have any preps in this container type? (e.g. are there any Cell Lines stored in Liquid Nitrogen plates)
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-06-22
+	 *
+	 * @param INT $selContType
+	 * @param INT $rType
+	 * @return boolean
+	*/
+	function isUsedContainerReagentType($selContType, $rType)
+	{
+		global $conn;
+
+		$isUsed_rs = mysql_query("select count(*) as num_used from Experiment_tbl e, Isolate_tbl i, Prep_tbl p, Wells_tbl w, Reagents_tbl r, Container_tbl c where r.reagentTypeID='" . $rType . "' and e.reagentID=r.reagentID and e.expID=i.expID and i.isolate_pk=p.isolate_pk and p.wellID=w.wellID and w.containerID=c.containerID and c.contGroupID='" . $selContType . "' and e.status='ACTIVE' and i.status='ACTIVE' and p.status='ACTIVE' and w.status='ACTIVE'", $conn) or die("Error checking used cont [...]
+
+		if ($isUsed_ar = mysql_fetch_array($isUsed_rs, MYSQL_ASSOC))
+		{
+			$numUsed = $isUsed_ar["num_used"];
+
+			if ($numUsed > 0)
+				return true;
+		}
+
+		return false;
+	}
+
+	/**
+	 * Is the given property assigned to any preps in this container type?
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-01-11
+	 *
+	 * @param INT $selContType
+	 * @param INT $elementTypeID
+	 * @return boolean
+	*/
+	function isUsedPrepElement($selContType, $elementTypeID)
+	{
+		global $conn;
+
+		$isUsed_rs = mysql_query("SELECT COUNT(prepPropID) as num_used FROM PrepElementProp_tbl pep, Prep_tbl p, Wells_tbl w, Container_tbl c WHERE pep.elementTypeID='" . $elementTypeID . "' AND pep.prepID=p.prepID and p.wellID=w.wellID and w.containerID=c.containerID and c.contGroupID='" . $selContType . "' AND p.status='ACTIVE' AND c.status='ACTIVE' AND p.status='ACTIVE'", $conn) or die("Error checking used container feature: " . mysql_error());
+
+		if ($isUsed_ar = mysql_fetch_array($isUsed_rs, MYSQL_ASSOC))
+		{
+			$numUsed = $isUsed_ar["num_used"];
+
+			if ($numUsed > 0)
+				return true;
+		}
+
+		return false;
+	}
+
+
+	/**
+	 * Is this container **type**, identified by $contTypeID, isolate active?
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-01-08
+	 *
+	 * @param INT $contTypeID
+	 * @return boolean
+	*/
+	function isolateActive($contTypeID)
+	{
+		global $conn;
+
+		$isoAct_rs = mysql_query("SELECT isolate_active FROM ContainerGroup_tbl WHERE contGroupID='" . $contTypeID . "' AND status='ACTIVE'", $conn) or die("FAILURE IN: Location_Funct_Class.getIsoAct_State(2): " . mysql_error());
+		
+		$isoAct_ar = mysql_fetch_array($isoAct_rs, MYSQL_ASSOC);
+		
+		$iso_act = $isoAct_ar["isolate_active"];
+		
+		mysql_free_result($isoAct_rs);
+		unset($isoAct_rs, $isoAct_ar);
+		
+		return $iso_act;
+	}
+
+	/**
+	 * Converts an integer into the alphabet base (A-Z).
+	 *
+	 * Source: http://php.net/manual/fr/function.base-convert.php
+	 *
+	 * @param int $n This is the number to convert.
+	 * @return string The converted number.
+	 * @author Theriault
+	 *
+	*/
+	function num2alpha($n) 
+	{
+		$r = '';
+
+		for ($i = 1; $n >= 0 && $i < 10; $i++) 
+		{
+			$r = chr(0x41 + ($n % pow(26, $i) / pow(26, $i - 1))) . $r;
+			$n -= pow(26, $i);
+		}
+
+		return $r;
+	}
+	
+	/**
+	* Converts an alphabetic string into an integer.
+	*
+	* @param int $n This is the number to convert.
+	* @return string The converted number.
+	* @author Theriault http://php.net/manual/fr/function.base-convert.php
+	*
+	*/
+	function alpha2num($a)
+	{
+		$r = 0;
+		$l = strlen($a);
+
+		for ($i = 0; $i < $l; $i++)
+		{
+			$r += pow(26, $i) * (ord($a[$l - $i - 1]) - 0x40);
+		}
+
+		return $r - 1;
+	}
+
+	/**
+	 * Get the letter that corresponds to the number representing a row in a container.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-01-08
+	 *
+	 * @param INT $row
+	 * @return STRING
+	*/
+	function getLetterRow($row)
+	{
+		return $this->num2alpha($row - 1);
+	}
+
+	/**
+	 * Determine if the reagent argument is in the current user's order. Return 1 if yes or 0 if no
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2008-01-23
+	 *
+	 * @param INT $row
+	 * @return INT
+	*/
+	function inOrder($rID, $isoNum, $contID, $row, $col)
+	{
+		$userID = $_SESSION["userinfo"]->getUserID();
+		$userOrders = $_SESSION["userinfo"]->getOrders();
+		$tempOrderKey = $rID . "_" . $isoNum . "_" . $contID . "_" . $row . "_" . $col;
+
+		foreach ($userOrders as $key => $order)
+		{
+			$oKey = $order->getOrderKey();
+
+			if (strcasecmp($tempOrderKey, $oKey) == 0)
+				return 1;
+		}
+
+		return 0;
+	}
+}
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Location/Location_Output_Class.php b/OpenFreezer/Location/Location_Output_Class.php
new file mode 100755
index 0000000..4a6e9ff
--- /dev/null
+++ b/OpenFreezer/Location/Location_Output_Class.php
@@ -0,0 +1,1753 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2010 Pawson Laboratory, All Rights Reserved
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Location
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+ * This class handles location output functions
+ *
+ * @author John Paul Lee @version 2005
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Location
+ *
+ * @copyright  2005-2010 Pawson Laboratory
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+class Location_Output_Class
+{
+	/**
+	 * Default constructor
+	*/
+	function Location_Output_Class()
+	{}
+	
+	/**
+	 * Changed the appearance of location view 1
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-02-09
+	*/
+	function print_Location_info()
+	{
+		?>
+		<table width="770px" cellpadding="5">
+			<tr>
+				<td colspan="3" style="font-size:18pt; font-weight:bold; text-align:center;">
+					LOCATION TRACKER
+				</td>
+			</tr>
+			<tr>
+				<td colspan="3" style="text-align:center; font-weight:bold">
+					This module is used to track the locations and properties of all preps of reagents in the laboratory
+				</td>
+			</tr>
+			<tr>
+				<td colspan="3" style="padding-top:8px;">
+					<DL>
+					<DT>
+						<span style="font-weight:bold; text-decoration:underline;">Terminology</span>
+						<p><UL>
+							<LI>
+								Each reagent is associated with an <font color="#004891"><i><b><u>isolate</u></b></i></font> (e.g. when cloning vectors or cell lines – different colony picks) and a <font color="#004891"><i><b><u>prep</u></b></i></font> (a physical preparation of a particular isolate that is stored).  For each reagent, a certain isolate is selected for downstream applications and is marked as the selected isolate.  If a particular reagent does not need isolates (currently oligos), then it  [...]
+							</LI>
+							<p><LI>
+								To make a new container - a user chooses a container size and a container group (e.g. Vector 96 well plate)
+							</LI>
+							<p><LI>
+								It is in the location tracker that we track isolates and preps of various reagents and designate which isolate is active.  We also flag certain preps that should not be used.
+							</LI>
+						</UL>
+				</td>
+			</tr>
+		</table>
+		<?php
+	}
+
+	/**
+	 * Print locations of all preps of the reagent identified by $rid
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-02-09
+	 *
+	 * @param INT $rid
+	 * @param INT $view Either 'group by container' or 'group by isolates'
+	*/
+	function printIsolates_ExpandedView($rid, $view)
+	{
+		global $conn;
+		global $hostname;
+
+		$canOrder = false;	// May 13, 2011
+		
+		$gfunc_obj = new generalFunc_Class();
+		$lfunc_obj = new Location_Funct_Class();
+		$bfunc_obj = new Reagent_Background_Class();	// April 16/07, Marina
+		$rfunc_obj= new Reagent_Function_Class();	// Jan. 30/08, Marina
+
+		$isolates_ht = new HT_Class();
+		$wellID_set = "('";
+		$setcount = 0;
+
+		$expID = $this->getExpID( $rid );
+
+		if ($expID < 1)
+		{
+			// April 16/07, Marina: Mostly applies to Inserts: No location for the Insert itself, but show the locations of its child vectors
+			if ($gfunc_obj->getTypeID($rid) == $_SESSION["ReagentType_Name_ID"]["Insert"])
+			{
+				echo "No location was found for Insert <a href=\"Reagent.php?View=6&rid=" . $rid . "\">" . $gfunc_obj->getConvertedID_rid($rid) . "</a> in OpenFreezer<BR/>";
+				echo "<P>Below are locations of Vectors that contain this Insert:</P>";
+
+				$children = $bfunc_obj->get_Children($rid, "Insert Children");
+
+				foreach ($children as $key=>$val)
+				{
+					$child_expID = $this->getExpID($val);
+
+					if ($child_expID < 1)
+					{
+						echo "No location was found for Vector <a href=\"Reagent.php?View=6&rid=" . $val . "\">" . $gfunc_obj->getConvertedID_rid($val) . "</a> in OpenFreezer<BR>";
+					}
+					else
+					{
+						$this->printIsolates_ExpandedView($val, $view);
+					}
+				}
+			}
+			else
+			{
+				echo "No location was found for <a href=\"Reagent.php?View=6&rid=" . $rid . "\">" . $gfunc_obj->getConvertedID_rid($rid) . "</a> in OpenFreezer";
+				return false;
+			}
+		}
+		
+		// April 24/07, Marina: At Karen's request, show Vector locations for ALL Inserts, not just those that don't have their own location
+		else if ($gfunc_obj->getTypeID($rid) == $_SESSION["ReagentType_Name_ID"]["Insert"])
+		{
+			echo "<P style=\"font-weight:bold; color:#0000CD\">Locations of Vectors that contain Insert <a href=\"Reagent.php?View=6&rid=" . $rid . "\">" . $gfunc_obj->getConvertedID_rid($rid) . "</a>:</P>";
+
+			$children = $bfunc_obj->get_Children($rid, "Insert Children");
+
+			foreach ($children as $key=>$val)
+			{
+				$child_expID = $this->getExpID($val);
+
+				if ($child_expID < 1)
+				{
+					echo "No location was found for Vector <a href=\"Reagent.php?View=6&rid=" . $val . "\">" . $gfunc_obj->getConvertedID_rid($val) . "</a> in OpenFreezer";
+				}
+				else
+				{
+					$this->printIsolates_ExpandedView($val, $view);
+				}
+			}
+	
+			// separator
+			echo "<P style=\"font-weight:bold; color:#0000CD\">Locations of Insert <a href=\"Reagent.php?View=6&rid=" . $rid . "\">" . $gfunc_obj->getConvertedID_rid($rid) . "</a>:</P>";
+		}
+		
+		// DO NOT ADD 'ELSE' - WON'T OUTPUT INSERT LOCATION IF IT EXISTS, IN ADDITION TO VECTORS
+		// Updated March 26/08 - added 'flag' field to query - Karen asked to disallow ordering clones that are flagged
+		// May 18, 2010: added b.refAvailID to query to be printed at Anna's request
+		$isolates_rs = mysql_query( "SELECT a.`isolate_pk`, a.`isolateNumber`, a.`beingUsed`, b.`wellID`, b.`flag`, b.`comments`, b.refAvailID FROM `Isolate_tbl` a, `Prep_tbl` b WHERE a.`isolate_pk`=b.`isolate_pk` AND a.`expID`='" . $expID. "' AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'", $conn) or die("FAILURE IN Location_Output_Class.printIsolates_ContainerView(1):" . mysql_error());
+
+		while ($isolates_ar = mysql_fetch_array($isolates_rs, MYSQL_ASSOC))
+		{
+			// Updated March 26/08 - added 'flag' and 'comments' to the query
+			$isolates_ht->add($isolates_ar["wellID"], array("isolateNumber" => $isolates_ar["isolateNumber"], "beingUsed" => $isolates_ar["beingUsed"], "flag"=>$isolates_ar["flag"], "comments" => $isolates_ar["comments"], "refAvailID" => $isolates_ar["refAvailID"]));
+			$wellID_set = $wellID_set . $isolates_ar["wellID"] . "','";
+			$setcount++;
+		}
+		
+		$wellID_set = $gfunc_obj->reset_set( $setcount, $wellID_set );
+		
+		$well_rs = mysql_query("SELECT * FROM `Wells_tbl` WHERE `status`='ACTIVE' AND `wellID` IN " . $wellID_set . "", $conn) or die("FAILURE IN Location_Output_Class.printIsolates_ContainerView(2):" . mysql_error() );
+
+		$contID_set = "('";
+		$setcount = 0;
+
+		while ($well_ar = mysql_fetch_array($well_rs, MYSQL_ASSOC))
+		{
+			$isolate_tmp = $isolates_ht->get($well_ar["wellID"]);
+			
+			$isolate_tmp["wellRow"] = $well_ar["wellRow"];
+			$isolate_tmp["wellCol"] = $well_ar["wellCol"];
+			$isolate_tmp["containerID"] = $well_ar["containerID"];
+			$isolates_ht->update($well_ar["wellID"], $isolate_tmp);
+
+			$contID_set = $contID_set . $well_ar["containerID"] . "','";
+			$setcount++;
+		}
+			
+		$contID_set = $gfunc_obj->reset_set( $setcount, $contID_set );
+		$contInfo_ht = new HT_Class();
+			
+		$cont_rs = mysql_query("SELECT a.`containerID`, b.`contGroupName`, a.`contGroupCount`, a.`name`, a.isolate_active FROM `Container_tbl` a, `ContainerGroup_tbl` b WHERE a.`contGroupID`=b.`contGroupID` AND a.`containerID` IN " . $contID_set . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'" , $conn) or die("FAILURE IN Location_Output_Class.printIsolates_ContainerView(3): " . mysql_error());
+
+		while( $cont_ar = mysql_fetch_array( $cont_rs, MYSQL_ASSOC ) )
+		{
+			$contInfo_ht->add( $cont_ar["containerID"], array("contGroupName" => $cont_ar["contGroupName"], "contGroupCount" => $cont_ar["contGroupCount"], "isoActive" => $cont_ar["isolate_active"], "name" => $cont_ar["name"]));
+		}
+		
+		if ($view == 1)
+		{
+echo "<TABLE cellpadding=\"2\" cellspacing=\"2\" style=\"width:100%;\">";
+			$finished_rs = mysql_query("SELECT DISTINCT a.`wellID`, b.`containerID`, b.`contGroupID`, b.`contGroupCount`, b.`name` FROM `Wells_tbl` a, `Container_tbl` b WHERE a.`containerID`=b.`containerID` AND a.`wellID` IN " . $wellID_set . " ORDER BY b.`containerID`, a.`wellID`", $conn) or die("FAILURE IN Location_Output_Class.printIsolates_ContainerView(4): " . mysql_error());
+
+			$currentContGroupID = 0;
+
+			$contInfo_tmp = array();
+			$toPrint_ar = array();
+
+// 			// Feb. 16/10: discovered this today: there's an expID but no isolate (prob. result of incomplete db deletion but still, this could happen, keep error msg)
+// 			if (!mysql_fetch_array($finished_rs, MYSQL_ASSOC))
+// 			{
+// 				echo "<TR><TD>";
+// 					echo "No location was found for <a href=\"Reagent.php?View=6&rid=" . $rid . "\">" . $gfunc_obj->getConvertedID_rid($rid) . "</a> in OpenFreezer<sup>TM</sup>";
+// 				echo "</TD></TR>";
+// 			}
+
+			while ($finished_ar = mysql_fetch_array($finished_rs, MYSQL_ASSOC))
+			{
+				echo "<TR><TD>";
+
+				$toPrint_ar = $isolates_ht->get( $finished_ar["wellID"] );
+				$contInfo_tmp = $contInfo_ht->get($finished_ar["containerID"]);
+				
+				if ($currentContGroupID != $finished_ar["contGroupID"])
+				{
+// 					echo "<P><HR></P>";
+				}	// FIX: this brace was initially after the "$currentContGroupID = $finished_ar["contGroupID"];" assignment => was not printing name and number correctly
+					// Marina Olhovsky, July 28, 2005
+
+				// Updated Jan 30/06, Marina
+				if ($contInfo_tmp["name"] != "NONE")
+				{
+					echo "Name of container: <strong>" . $contInfo_tmp["name"] . "</strong><BR>";
+				}
+				else	
+				{
+					echo "Name of container: <strong>" . $contInfo_tmp["contGroupName"] . "</strong><BR>";
+					echo "Container number: <strong>" . $contInfo_tmp["contGroupCount"] . "</strong><BR>";
+				}
+				
+				$currentContGroupID = $finished_ar["contGroupID"];
+		
+				// Added by Marina on August 1, 2005
+				echo "\n<a href=\"Location.php?View=2&Mod=" . $finished_ar["containerID"] . "&Row=" . $toPrint_ar["wellRow"] . "&Col=" . $toPrint_ar["wellCol"] . "#focus_" . $toPrint_ar["wellRow"] . "_" . $toPrint_ar["wellCol"] . "\">" . $gfunc_obj->getConvertedID_rid( $rid );
+				
+				if( $contInfo_tmp["isoActive"] == "YES" )
+				{
+					echo "-" . $toPrint_ar["isolateNumber"] . "</a> ";
+				}
+				else
+				{
+					echo "</a> ";
+				}
+				
+				if ($toPrint_ar["beingUsed"] == "YES")
+				{
+					echo "(Currently set Isolate Being Used)";
+				}
+				
+				// Jan. 22/08: Order clones
+				echo $lfunc_obj->getLetterRow($toPrint_ar["wellRow"]) . " : " . $toPrint_ar["wellCol"];
+
+				$inOrder = $lfunc_obj->inOrder($rid, $toPrint_ar["isolateNumber"], $toPrint_ar["containerID"], $toPrint_ar["wellRow"], $toPrint_ar["wellCol"]);
+
+				// Updated Jan. 30/08: ONLY show "order" option for GS Vector locations
+				if (($currentContGroupID == $_SESSION["contGroupNames"]["Glycerol Stocks"]) && ($rfunc_obj->getType($rid) == $_SESSION["ReagentType_Name_ID"]["Vector"]))
+				{
+					// March 26/08: Show if sample is contaminated (flagged) - disallow order
+					if ($toPrint_ar["flag"] != "YES")
+					{/*
+						echo "<BR><span style=\"color:#FF0000; font-size:9pt; font-weight:bold\">Flagged – do not use as contaminated</span><BR>";
+					}
+					else
+					{*/
+						$displayOrderLink = ($inOrder == 0) ? "inline" : "none";
+						$displayInOrder = ($inOrder == 1) ? "inline" : "none";
+					
+						echo "<span class=\"linkShow\" NAME=\"addToOrder\" ID=\"orderClone_" . $rid . "_" . $toPrint_ar["isolateNumber"] . "_" . $toPrint_ar["containerID"] . "_" . $toPrint_ar["wellRow"] . "_" . $toPrint_ar["wellCol"] . "\" NAME=\"orderClone\" style=\"padding-left:25px; display:" . $displayOrderLink . "\" onClick=\"addToOrder('" . $rid . "', '" . $toPrint_ar["isolateNumber"] . "', '" . $toPrint_ar["containerID"] . "', '" . $toPrint_ar["wellRow"] . "', '" . $toPrint_ar["wellCol"] . "')\">Ad [...]
+		
+						echo "<span class=\"linkOrdered\" ID=\"inOrder_" . $rid . "_" . $toPrint_ar["isolateNumber"] . "_" . $toPrint_ar["containerID"] . "_" . $toPrint_ar["wellRow"] . "_" . $toPrint_ar["wellCol"] . "\" style=\"padding-left:25px; display:" . $displayInOrder . "\">In Order</span>";
+						
+						echo "<BR/>";
+
+						$canOrder = true;	// May 13, 2011
+					}
+				}
+
+				if ($toPrint_ar["flag"] == "YES")
+				{
+					// May 18, 2010: Printing Reference at Anna's request
+					echo "<BR><span style=\"color:#FF0000; font-size:9pt; font-weight:bold\">" . trim($toPrint_ar["comments"]);
+
+					if (trim($toPrint_ar["refAvailID"]) != trim($toPrint_ar["comments"]))
+					{
+						echo " " . trim($toPrint_ar["refAvailID"]);
+					}
+
+ 					echo "</span><BR>";
+				}
+
+				echo "</td></tr>";
+				unset($contInfo_tmp, $toPrint_ar);
+			}
+
+			if ($canOrder)
+			{		
+				// May 13, 2011
+				echo "<TR><TD colspan=\"100%\" style=\"color:#FF0000; font-weight:bold; padding-left:0;\"><P><u>NOTE</u>:<BR>You can search for more clones and add them to your order.<BR>Once all the clones of interest have been added, press <a href=\"" . $hostname . "User.php?View=8\">View your orders</a> on the side menu and follow the instructions to submit your request.</TD></TR>";
+			}
+
+			echo "</table>";
+		}
+		else
+		{
+			echo "<table cellpadding=\"2\" cellspacing=\"2\" width=\"100%\">";
+
+			$finished_rs = mysql_query("SELECT a.`isolate_pk`, a.`isolateNumber`, a.`beingUsed`, b.`wellID` FROM `Isolate_tbl` a, `Prep_tbl` b WHERE a.`isolate_pk`=b.`isolate_pk` AND a.`expID`='" . $expID. "' AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY a.`isolateNumber`", $conn) or die("FAILURE IN Location_Output_Class.printIsolates_ContainerView(1):" . mysql_error());
+
+			$currentIsolateID = 0;
+			
+			while ($finished_ar = mysql_fetch_array($finished_rs, MYSQL_ASSOC))
+			{
+				echo "<tr><td>";
+
+				$toPrint_ar = array();
+				$toPrint_ar = $isolates_ht->get($finished_ar["wellID"]);
+				$contInfo_tmp = $contInfo_ht->get($toPrint_ar["containerID"]);
+
+				// March 26/08: Get container type (in order to show "Order" link on this view)
+				$currentContGroupName = $contInfo_tmp["contGroupName"];
+				$currentContGroupID =  $lfunc_obj->convertContGroupName_to_ID($currentContGroupName);
+
+				if ($currentIsolateID != $finished_ar["isolateNumber"])
+				{
+					# Modified May 22/07 by Marina
+					# Link the Vector back to its Detailed View, and link to location off the plate name below
+					echo "\n<a href=\"Reagent.php?View=6&rid=" . $rid . "\">" . $gfunc_obj->getConvertedID_rid($rid);	# May 22/07
+						
+					if( $contInfo_tmp["isoActive"] == "YES" )
+					{
+						echo "-" . $toPrint_ar["isolateNumber"] . "</a>";
+					}
+					else
+					{
+						echo "</a>";
+					}
+					
+					if( $toPrint_ar["beingUsed"] == "YES" )
+					{
+						echo "  (Currently set Isolate Being Used)";
+					}
+					
+					echo "<br>";
+					$currentIsolateID = $finished_ar["isolateNumber"];
+					echo "<BR>";
+				}
+				
+				# Changed May 22/07, Marina - Output full container name instead of a meaningless number
+				echo $contInfo_tmp["name"] . ", well ";
+				echo "<A HREF=\"Location.php?View=2&Mod=" . $toPrint_ar["containerID"] . "&Row=" . $toPrint_ar["wellRow"] . "&Col=" . $toPrint_ar["wellCol"] . "#focus_" . $toPrint_ar["wellRow"] . "_" . $toPrint_ar["wellCol"] . "\">";
+				echo $lfunc_obj->getLetterRow($toPrint_ar["wellRow"]) . ":" . $toPrint_ar["wellCol"];
+				echo "</A>";
+				
+				// March 26/08: Add "Order clones" btn
+				$inOrder = $lfunc_obj->inOrder($rid, $toPrint_ar["isolateNumber"], $toPrint_ar["containerID"], $toPrint_ar["wellRow"], $toPrint_ar["wellCol"]);
+
+				// Jan. 30/08: ONLY show "order" option for GS Vector locations
+				if (($currentContGroupID == $_SESSION["contGroupNames"]["Glycerol Stocks"]) && ($rfunc_obj->getType($rid) == $_SESSION["ReagentType_Name_ID"]["Vector"]))
+				{
+					// March 26/08: Show if sample is contaminated (flagged) - disallow order
+					if ($toPrint_ar["flag"] != "YES")
+					{
+						$displayOrderLink = ($inOrder == 0) ? "inline" : "none";
+						$displayInOrder = ($inOrder == 1) ? "inline" : "none";
+					
+						echo "<span class=\"linkShow\" NAME=\"addToOrder\" ID=\"orderClone_" . $rid . "_" . $toPrint_ar["isolateNumber"] . "_" . $toPrint_ar["containerID"] . "_" . $toPrint_ar["wellRow"] . "_" . $toPrint_ar["wellCol"] . "\" NAME=\"orderClone\" style=\"padding-left:25px; display:" . $displayOrderLink . "\" onClick=\"addToOrder('" . $rid . "', '" . $toPrint_ar["isolateNumber"] . "', '" . $toPrint_ar["containerID"] . "', '" . $toPrint_ar["wellRow"] . "', '" . $toPrint_ar["wellCol"] . "')\">Ad [...]
+		
+						echo "<span class=\"linkOrdered\" ID=\"inOrder_" . $rid . "_" . $toPrint_ar["isolateNumber"] . "_" . $toPrint_ar["containerID"] . "_" . $toPrint_ar["wellRow"] . "_" . $toPrint_ar["wellCol"] . "\" style=\"padding-left:25px; display:" . $displayInOrder . "\">In Order</span>";
+						
+						echo "<BR/>";
+
+						$canOrder = true;	// May 13, 2011
+					}
+				}
+
+				// Show "flagged" notification for all reagent types
+				if ($toPrint_ar["flag"] == "YES")
+				{
+					echo "<BR><span style=\"color:#FF0000; font-size:9pt; font-weight:bold\">" . $toPrint_ar["comments"] . "</span><BR>";
+
+					if (strcasecmp(trim($toPrint_ar["refAvailID"]), trim($toPrint_ar["comments"])) != 0)
+					{
+						echo " " . trim($toPrint_ar["refAvailID"]);
+					}
+
+					echo "</span><BR>";
+				}
+
+				echo "<BR>";
+				echo "</td></tr>";
+				unset( $contInfo_tmp, $toPrint_ar );
+			}
+
+
+			// May 13, 2011
+			if ($canOrder)
+			{		
+				// May 13, 2011
+				echo "<TR><TD colspan=\"100%\" style=\"color:#FF0000; font-weight:bold; padding-left:0;\"><P><u>NOTE</u>:<BR>You can search for more clones and add them to your order.<BR>Once all the clones of interest have been added, press 'View your orders' on the side menu and follow the instructions to submit your request.</TD></TR>";
+			}
+
+			echo "</table>";
+		}
+		
+		unset( $gfunc_obj, $lfunc_obj, $contInfo_ht, $isolates_ht );
+	}
+	
+	/**
+	 * Print container type selection list with the appropriate container type selected according to POST variables.  Print list of containers in the selected type.  Used on CONTAINER SEARCH VIEW (Location.php?View=2)
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param Array $postvars
+	*/
+	function printForm($postvars)
+	{
+		?>
+		<!-- Updated Aug. 28/08: Show list of plates for selected container type -->
+		<FORM name="printContainersOfOneTypeForm" method=post action="<?php echo $_SERVER["PHP_SELF"] . "?View=2"; ?>">
+			<FIELDSET>
+				<LEGEND>Please select a container for viewing, modification, and insertion from one of the following container types:</LEGEND>
+
+				<select name="cont_name_selection" id="cont_name_selection" size=1 onChange="this.form.submit()">
+					<option>No container selected</option>
+					
+					<?php
+					foreach ($_SESSION["Container_ID_Name"] as $key => $value)
+					{
+						if ($postvars["cont_name_selection"] == $value)
+						{
+							echo "<option selected>" . $value . "</option>\n";
+						}
+						else
+						{
+							echo "<option>" . $value . "</option>\n";
+						}
+					}
+					?>
+				</select>
+			</FIELDSET>
+			
+			<!-- May 23/07, Marina: Add a hidden field to store name of column to sort by -->
+			<INPUT TYPE="hidden" id="sortByCol_hidden" name="sortOn">
+		</FORM>
+		<?php
+
+		if (isset($_POST["cont_name_selection"]) && $_POST["cont_name_selection"] != "No container selected")
+		{
+			$loc_funct_obj = new Location_Funct_Class();
+			$loc_funct_obj->printContainerInfo($_SESSION["Container_Name_ID"][$_POST["cont_name_selection"]]);
+			unset( $loc_funct_obj );
+		}
+	}
+
+	/**
+	 * Print container type selection list with the appropriate container type selected according to POST variables.  Print list of containers in the selected type.
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param Array $postvars
+	*/
+	function printPlateList($contType, $selPlate=false)
+	{
+		global $conn;
+
+		$contGroupID = $_SESSION["Container_Name_ID"][$contType];
+
+		$contInfo_rs = mysql_query("SELECT * FROM `Container_tbl` a, `ContainerTypeID_tbl` b, LabInfo_tbl l WHERE a.`contGroupID`='" . $contGroupID . "' AND a.`contTypeID`=b.`contTypeID` AND l.labID=a.labID AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND l.status='ACTIVE' ORDER BY `name`", $conn) or die("ERROR reading from container table sql error" . mysql_error());
+
+		echo "<P><SELECT ID=\"plates_list\" NAME=\"platesList\" onChange=\"this.form.submit();\">";
+		echo "<OPTION>-- Select Plate --</OPTION>"; 
+
+		while ($contInfo_ar = mysql_fetch_array($contInfo_rs, MYSQL_ASSOC))
+		{
+			echo "<OPTION  " . ((strcasecmp($selPlate, $contInfo_ar["name"]) == 0) ? "selected" : "") . ">" . $contInfo_ar["name"] . "</OPTION>";
+		}
+
+		echo "</SELECT>";
+
+		echo "</FIELDSET>";
+	}
+
+	/**
+	 * Get expID that corresponds to $rid
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param INT $rid
+	*/
+	function getExpID($rid)
+	{
+		global $conn;
+		
+		$exp_rs = mysql_query("SELECT `expID` FROM `Experiment_tbl` WHERE `reagentID`='" . $rid . "' AND status='ACTIVE'" , $conn) or die("Error in grabbing expid" . mysql_error());
+
+		if ($exp_ar = mysql_fetch_array($exp_rs, MYSQL_ASSOC))
+		{
+			return $exp_ar["expID"];
+		}
+		
+		return -1;
+	}
+	
+	/**
+	 * Print detailed view of the container identified by $contID
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param INT $contID
+	 * @uses outputPlateView_restricted()
+	*/
+	function outputPlateView_contID($contID)
+	{
+		$this->outputPlateView_restricted("WHERE a.`containerID`='" . $contID . "' ");
+	}
+
+	/**
+	 * Print detailed view of the container identified by $groupID and $plateNum (passes different query to outputPlateView_restricted())
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param INT $groupID
+	 * @param INT $plateNum
+	 *
+	 * @uses outputPlateView_restricted()
+	*/
+	function outputPlateView_groupID($groupID, $plateNum)
+	{
+		$this->outputPlateView_restricted("WHERE a.`contGroupID`='" . $groupID . "' " . "AND a.`contGroupCount`='" . $plateNum . "' ");
+	}
+
+	/**
+	 * Print a list of container types ('Glycerol Stock', 'Liquid Nitrogen', etc.) on the CONTAINER TYPE SEARCH VIEW (as opposed to container search view) - Location.php?View=6&Sub=4
+	 *
+	 * Note: Variable name 'Container_ID_Name' is kept for historical reasons; a better name would be Container**Type**_ID_Name to show that we are selecting container types.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	*/
+	function printContainerTypesList()
+	{
+		global $conn;
+		
+		?>
+		<FORM NAME="searchContainerTypes" METHOD="POST" ACTION="<?php echo $_SERVER["PHP_SELF"] . "?View=6&Sub=4"; ?>">
+			<FIELDSET style="width:745px;">
+				<LEGEND>Please select a container type from the list:</LEGEND>
+	
+				<SELECT NAME="contTypeList" style="font-size:8pt;">
+					<OPTION>-- Container Type --</OPTION>
+					<?php
+						foreach ($_SESSION["Container_ID_Name"] as $cTypeID => $cTypeName)
+						{
+							echo "<OPTION VALUE=\"" . $cTypeID . "\">" . $cTypeName . "</OPTION>";
+						}
+					?>
+				</SELECT>
+
+			<INPUT TYPE="SUBMIT" NAME="viewContainerType" VALUE="Go">
+		</FORM>
+		<?php
+	}
+
+	/**
+	 * Print the detailed view of the container type that corresponds to $selContType in either 'view' or 'modify' mode depending on the value of $modify_state.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	*/
+	function print_Detailed_Cont_Type($selContType, $modify_state=false)
+	{
+		global $conn;
+		global $cgi_path;
+
+		$lfunc_obj = new Location_Funct_Class();
+		$modify_disabled = "";
+
+		if ($lfunc_obj->isUsedContainerType($selContType))
+		{
+			$modify_disabled = "DISABLED";
+		}
+
+		?><FORM METHOD="POST" ACTION="<?php echo $cgi_path . "location_type_request_handler.py"; ?>">
+		<table width="765px" cellpadding="3" cellspacing="0" style="background-color:#FEFEEE; border:1px solid gold; padding:10px;">
+			<TR>
+				<TD style="text-align:center; padding-bottom:5px; font-weight:bold; font-size:12pt; white-space:nowrap; border-bottom:2px solid gold; color:maroon;" colspan="2">
+					<INPUT type="hidden" NAME="containerType" VALUE="<?php echo $selContType; ?>">
+					<?php echo $_SESSION["Container_ID_Name"][$selContType]; ?> Container Type Details
+				</TD>
+
+				<TD style="text-align:right; font-weight:bold; padding-bottom:5px; font-size:12pt; white-space:nowrap; border-bottom:2px solid gold;" colspan="2"><?php
+
+				if ($modify_state)
+				{
+					?><input type="submit" name="cont_type_save" value="Save" onClick="enableSelect(); enableText(); selectAllElements('cont_dest_features'); selectAllElements('reagentTypesList'); return verifyContainerType();">
+
+					<input type="submit" name="cont_type_delete" <?php echo $modify_disabled;?> value="Delete" onClick="return confirm('Are you sure you want to delete this container type?  Deletion cannot be undone.');">
+
+					<input type="submit" name="cancel_cont_type_modify" value="Cancel"><?php
+				}
+				else
+				{
+					?><INPUT TYPE="submit" VALUE="Modify" style="text-align:right; padding-right:10px;" NAME="cont_type_modify"><?php
+				}
+
+				?></TD>
+			</TR>
+			<?php
+			if ($modify_state)
+			{
+				?><tr>
+					<td style="white-space:nowrap; width:150px; padding-top:10px; padding-bottom:8px; border-bottom:2px solid gold; font-weight:bold; padding-top:10px; padding-bottom:8px; border-bottom:2px solid gold;" colspan="3">
+						Name: <font size="3" face="Helvetica" color="FF0000"><b>*</b></font>   
+
+						<INPUT style="padding-left:2px;" type="text" size="25" name="cont_group_name_field" ID="containerTypeName" onKeyPress="return disableEnterKey(event);" <?php echo $modify_disabled; ?> VALUE="<?php echo $_SESSION["Container_ID_Name"][$selContType]; ?>">
+					</td>
+				</tr><?php
+			}
+
+			if ($modify_state)
+			{
+				?>
+				<tr>
+					<td style="white-space:nowrap; padding-top:10px; padding-bottom:10px; font-weight:bold;" colspan="3">
+						Reagent types:<BR>
+						<SPAN style="font-weight:normal; color:black; font-size:9pt; padding-top:2px;">Specify the reagent types that may be stored in this container.  Other reagent types will be disallowed.</SPAN>
+					</td>
+				</tr>
+
+				<tr>
+					<td colspan="3">
+						<table>
+							<TR>
+								<td style="padding-left:6px; padding-bottom:10px; border-bottom:2px solid gold;" colspan="3">
+									<select ID="reagentTypesList" MULTIPLE size="5" name="reagent_types" style="margin-left:4px; padding-left:1px;">
+									<?php
+					
+										$allowed_r_types = $lfunc_obj->getContainerReagentTypes($selContType);
+			
+										foreach ($allowed_r_types as $key => $rTypeID)
+										{
+											$rType = $_SESSION["ReagentType_ID_Name"][$rTypeID];
+		
+											// June. 22, 2010
+											if ($lfunc_obj->isUsedContainerReagentType($selContType, $rTypeID))
+												echo "<option DISABLED value=\"" . $rTypeID . "\">" . $rType . "</option>";
+											else
+												echo "<option value=\"" . $rTypeID . "\">" . $rType . "</option>";
+										}
+									?>
+									</select><BR>
+			
+									<INPUT TYPE="CHECKBOX" ID="selectAllReagentTypesContainer" style="margin-top:10px;" onClick="selectAllContainerProperties(this.id, 'reagentTypesList', false)"><span style="font-size:9pt;">Select All</span></INPUT>
+								</TD>
+
+								<!-- March 5/10: make 2 lists -->
+								<TD style="padding-left:5px">
+									<!-- buttons -->
+									<INPUT TYPE="BUTTON" VALUE="<<" NAME="addBtn[]" style="font-size:7pt;" onclick="moveListElements('reagentTypesPool', 'reagentTypesList', false, true);"><BR>
+			
+									<P><INPUT TYPE="BUTTON" NAME="rmvBtn[]" STYLE="font-size:7pt;" style="font-size:8pt;" VALUE=">>" onclick="moveListElements('reagentTypesList', 'reagentTypesPool', false, false);"><BR><BR><BR>
+								</TD>
+
+								<td style="padding-left:6px; padding-bottom:10px; border-bottom:2px solid gold;" colspan="3">
+									<select ID="reagentTypesPool" MULTIPLE size="5" style="margin-left:4px; padding-left:1px;">
+									<?php
+										// Feb. 9-16, 2010
+										$allowed_r_types = $lfunc_obj->getContainerReagentTypes($selContType);
+
+										foreach ($_SESSION["ReagentType_ID_Name"] as $rTypeID => $rType)
+										{
+											if (!in_array($rTypeID, array_values($allowed_r_types)))
+												echo "<option value=\"" . $rTypeID . "\">" . $rType . "</option>";
+										}
+									?>
+									</select><BR>
+			
+									<INPUT TYPE="CHECKBOX" ID="selectAllReagentTypesContainer" style="margin-top:10px;" onClick="selectAllContainerProperties(this.id, 'reagentTypesList', false)"><span style="font-size:9pt;">Select All</span></INPUT>
+								</td>
+							</tr>
+						</table>
+					</TD>
+				</tr>
+			
+				<tr>
+					<td style="padding-top:10px; padding-right:15px; padding-bottom:8px; border-bottom:2px solid gold; font-weight:bold;" colspan="3">
+						Container Code:<SPAN style="margin-left:4px; font-size:11pt; font-face:Helvetica; font-weight:bold; color:#FF0000;">*</SPAN>   
+
+						<INPUT style="padding-left:2px;" type="text" size="5" value="<?php echo $_SESSION["ContainerTypeID_Code"][$selContType]; ?>" <?php echo $modify_disabled; ?> ID="containerCode" name="cont_cont_code_field" onKeyPress="return disableEnterKey(event);"><BR>
+
+						<SPAN style="font-weight:normal; font-size:9pt;">A unique two-letter identifier for this container type (e.g. 'MP' for MiniPrep Plates, or 'GS' for Glycerol Stock containers)</SPAN><BR><P><HR><P>
+
+						<SPAN style="font-weight:normal; font-size:9pt;">The following container codes, currently used in OpenFreezer, <u>may NOT be reused</u>:</SPAN><BR>
+
+						<TABLE border="0">
+							<TR><UL><?php
+
+							$count = 0;
+
+							$code_rs = mysql_query("SELECT contGroupName, contGroupCode FROM ContainerGroup_tbl WHERE status='ACTIVE'", $conn) or die("Cannot select container codes: " . mysql_error());
+
+							while ($code_ar = mysql_fetch_array($code_rs, MYSQL_ASSOC))
+							{
+								$contGroupName = $code_ar["contGroupName"];
+								$contGroupCode = $code_ar["contGroupCode"];
+
+								if (($count != 0) && ($count % 2 == 0))
+									echo "</TR><TR>";
+
+								echo "<TD style=\"font-size:9pt; font-weight:bold; text-decoration:none;\"><LI>" . $contGroupCode . "</TD>";
+								echo "<TD> - </TD>";
+								echo "<TD style=\"font-size:9pt;\">" . $contGroupName . "</TD>";
+								echo "<TD> </TD>";
+								echo "<TD> </TD>";
+
+								$count++;
+							}
+
+						?></UL></TR></TABLE>
+					</td>
+				</tr>
+				<?php
+			}
+			else
+			{
+
+				?>
+				<tr>
+					<td style="white-space:nowrap; font-weight:bold; padding-top:10px; padding-bottom:8px; border-bottom:2px solid gold;" colspan="4">
+						Container Code:  
+						<?php echo $_SESSION["ContainerTypeID_Code"][$selContType]; ?>
+					</td>
+				</tr>
+				<?php
+			}
+				?>
+				<tr>
+					<td style="padding-top:10px; padding-bottom:10px; padding-left:5px; border-bottom:2px solid gold;" colspan="3">
+						<B>Isolate Active:</b>  <?php
+
+						if ($modify_state)
+						{
+							$isoActive = $lfunc_obj->isolateActive($selContType);
+
+							if ($lfunc_obj->isUsedContainerType($selContType))
+								$isoDisabled = "DISABLED";
+							else
+								$isoDisabled = "";
+
+							?>
+							<input type="radio" <?php if (strcasecmp($isoActive, "YES") == 0) echo "checked"; ?> <?php echo $isoDisabled; ?> name="cont_cont_isolateActive_radio" value="Yes"> Yes
+							<input type="radio" <?php if (strcasecmp($isoActive, "NO") == 0) echo "checked"; ?> <?php echo $isoDisabled; ?> name="cont_cont_isolateActive_radio" value="No"> No
+							<BR><SPAN style="font-size:9pt;">Specify whether preps in containers of this type originate from different colony picks (isolates)</SPAN><?php
+						}
+						else
+						{
+							echo $lfunc_obj->isolateActive($selContType);
+						}
+					?>
+					</td>
+				</tr>
+				<?php
+					$allowed_r_types = $lfunc_obj->getContainerReagentTypes($selContType);
+		
+					if (count($allowed_r_types) > 0)
+					{
+		
+						?>
+						<tr>
+							<td colspan="100%" style="white-space:nowrap; font-weight:bold; padding-top:12px;">
+								Reagent types:
+							</td>
+						</tr>
+		
+						<TR>
+							<td style="padding-left:10px; padding-top:10px; border-bottom:2px solid gold;" colspan="100%">
+							<?php
+		
+							echo "<UL>";
+			
+							foreach ($allowed_r_types as $rKey => $rTypeID)
+								echo "<LI>" . $_SESSION["ReagentType_ID_Name"][$rTypeID] . "</LI>";
+		
+							echo "</UL>";
+		
+							?>
+							</td>
+						</tr>
+						<?php
+					}
+				?>
+				<!-- Feb. 12/09: List of features for this container type: -->
+				<tr>
+					<td style="font-weight:bold; padding-left:5px; padding-top:15px;" colspan="3">
+						Container Type Attributes:
+					</td>
+				</tr>
+
+				<tr>
+					<?php
+						if ($modify_state)
+						{
+							?>
+							<td style="padding-left:2px; padding-top:10px; white-space:nowrap;">
+								<table cellpadding="2" style="border: 1px groove gray; padding-top:5px; padding-bottom:5px; padding-left:5px; padding-right:5px; width:80%;" frame="box" rules="none">
+									<tr>
+										<TD style="font-size:9pt; font-weight:bold; text-align:left; padding-left:15px;">
+											Attributes assigned to containers of this type:
+										</td>
+		
+										<TD width="78px;"> </TD>
+		
+										<TD style="text-align:center; font-size:9pt; font-weight:bold;">
+											Additional container attributes<BR> available in OpenFreezer:
+										</TD>
+									</TR>
+		
+									<TR>
+										<td style="white-space:nowrap; width:180px; padding-left:10px;">
+
+											<SELECT SIZE="10" MULTIPLE NAME="container_features" ID="cont_dest_features" style="min-width:150px;">
+											<?php
+
+											$props_rs = mysql_query("SELECT p.elementTypeID, p.propertyName FROM PrepElemTypes_tbl p, ContainerTypeAttributes_tbl c WHERE c.containerTypeID='" . $selContType . "' AND c.containerTypeAttributeID=p.elementTypeID AND c.status='ACTIVE' AND p.status='ACTIVE'") or die("Error fetching container attributes");
+				
+											$usedContTypeProps = Array();
+
+											while ($props_ar = mysql_fetch_array($props_rs, MYSQL_ASSOC))
+											{
+												$propertyName = $props_ar["propertyName"];
+												$elementTypeID = $props_ar["elementTypeID"];
+
+												$usedContTypeProps[] = $propertyName;
+
+												$disabled = "";
+
+												if ($lfunc_obj->isUsedPrepElement($selContType, $elementTypeID))
+													$disabled = "DISABLED";
+												
+												// Update Jan. 14, 2010: pass the property NAME to Python, not the value!
+												echo "<OPTION " . $disabled . " VALUE=\"" . $propertyName . "\" NAME=\"" . $propertyName . "\">" . $propertyName . "</OPTION>";
+											}
+				
+											?>
+											</SELECT>
+										
+											<P><INPUT TYPE="checkbox" onClick="selectAll(this.id, 'cont_dest_features')" id="add_all_chkbx_dest"> Select All</INPUT>
+										</td>
+									
+										<td style="text-align:center; padding-left:10px; padding-right:10px;">
+											<input style="margin-top:10px;" onclick="moveListElements('cont_src_features', 'cont_dest_features', false)" value="<<" type="button"></INPUT><BR><BR>
+		
+											<input onclick="moveListElements('cont_dest_features', 'cont_src_features', false)" value=">>" type="button"></INPUT><BR><BR><BR><BR>
+										</td>
+		
+										<td style="white-space:nowrap; padding-left:20px;">
+										<?php
+											$props_rs = mysql_query("SELECT elementTypeID, propertyName FROM PrepElemTypes_tbl WHERE status='ACTIVE' ORDER BY propertyName") or die("Error fetching container attributes");
+				
+											echo "<SELECT SIZE='10' MULTIPLE ID='cont_src_features' style='min-width:180px;'>";
+				
+											while ($props_ar = mysql_fetch_array($props_rs, MYSQL_ASSOC))
+											{
+												$propertyName = $props_ar["propertyName"];
+												$elementTypeID = $props_ar["elementTypeID"];
+				
+												if (!in_array($propertyName, $usedContTypeProps))
+													echo "<OPTION VALUE=\"" . $propertyName . "\" NAME=\"" . $propertyName . "\">" . $propertyName . "</OPTION>";
+											}
+				
+											echo "</SELECT>";
+		
+											?>
+											<P><INPUT TYPE="checkbox" onClick="selectAll(this.id, 'cont_src_features')" id="add_all_chkbx_src"> Select All</INPUT>
+										</td>
+									</tr>
+		
+									<tr>
+										<td colspan="3" style="white-space:nowrap;"><HR>or, add new feature: <INPUT type="text" size="35" ID="new_cont_feature_txt" value="" name="new_cont_feature" onKeyPress="return disableEnterKey(event);"> <input onclick="addElementToListFromInput('new_cont_feature_txt', 'cont_dest_features')" value="Add" type="button"></INPUT></td>
+									</tr>
+								</table>
+							</td>
+							<?php
+						}
+						else
+						{
+							?><TD><?php
+
+							$contTypeAttrs = $lfunc_obj->getContainerTypeAttributes($selContType);
+
+							if (count($contTypeAttrs) > 0)
+							{
+								echo "<UL>";
+
+								foreach ($contTypeAttrs as $key => $value)
+								{
+									echo "<LI>" . $value . "</LI>";
+								}
+
+								echo "</UL>";
+							}
+
+							?></td><?php
+						}
+					?>
+				</tr>
+			</table>
+		</FORM>
+		<?php
+	}
+
+
+	/**
+	 * Print an error message.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-02-24
+	 *
+	 * @param STRING $err_msg
+	*/
+	function printErrPage($err_msg)
+	{
+		echo "<TABLE style=\"width:98%;\">";
+		echo "<TR><TD style=\"font-weight:bold; font-size:24pt;\">";
+		echo $err_msg;
+		echo "</TD></TR>";
+		echo "</TABLE>";
+	}
+
+	/**
+	 * Print the detailed view of a conatiner
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-02-24
+	 *
+	 * @param STRING $selected_SQL_statement
+	*/
+	function outputPlateView_restricted($selected_SQL_statement)
+	{
+		global $conn;
+		global $cgi_path;	// jan. 3, 2010
+		global $hostname;	// sept. 11/07
+
+		$gfunc_obj = new generalFunc_Class();
+		$lfunc_obj = new Location_Funct_Class();
+		$locWells_obj = new Location_Well_Class();
+
+		$maxRow_const = 0;
+		$maxCol_const = 0;
+		$contID_const = 0;
+		$groupCount_const = 0;
+		$groupID_const = 0;
+		
+		$groupName_const = "";
+		
+		$isIsolate_container = "NO";
+		
+		$general_property_ar = array();
+		
+		$currentRow = 1;
+		$currentCol = 1;
+		
+		$isIsolate_container = false;
+		
+		$containerName = "";		// May 23/06, Marina
+
+		// Sept 27, Marina
+		if (isset($_SESSION["userinfo"]))
+		{
+			$currentUserID = $_SESSION["userinfo"]->getUserID();
+		}
+
+		// Grab the container basic information
+		$containerID_rs = mysql_query("SELECT a.`containerID`, a.`contGroupCount`, a.`contGroupID`, a.`contTypeID`, a.`name`, c.`isolate_active`, b.`maxCol`, b.`maxRow`, a.location, a.labID FROM `Container_tbl` a, `ContainerTypeID_tbl` b, ContainerGroup_tbl c " . $selected_SQL_statement . " AND a.`contTypeID`=b.`contTypeID` AND c.contGroupID=a.contGroupID AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`status`='ACTIVE'", $conn) or die("Error on container groups sql statement: " . mysql_ [...]
+		
+		if ($containerID_ar = mysql_fetch_array($containerID_rs, MYSQL_ASSOC))
+		{
+			$maxRow_const = $containerID_ar["maxRow"];
+			$maxCol_const = $containerID_ar["maxCol"];
+			$contID_const = $containerID_ar["containerID"];
+			$groupCount_const = $containerID_ar["contGroupCount"];
+			$groupID_const = $containerID_ar["contGroupID"];
+			$containerName = $containerID_ar["name"];
+			$contLabID = $containerID_ar["labID"];
+			$contTypeID = $containerID_ar["contTypeID"];
+			
+			if ($containerID_ar["isolate_active"] == "YES")
+			{
+				$isIsolate_container = true;
+			}
+			else
+			{
+				$isIsolate_container = false;
+			}
+		}
+		else
+		{
+			return false;
+		}
+		
+		// Added June 5/06 by Marina
+		$maxGroupCount_rs = mysql_query("SELECT MAX(`contGroupCount`) AS maxCount FROM `Container_tbl` WHERE `contGroupID`='" . $groupID_const . "' AND `status`='ACTIVE'", $conn) or die("Error selecting max group count: " . mysql_error());
+
+		if ($maxGroupCount_ar = mysql_fetch_array($maxGroupCount_rs, MYSQL_ASSOC))
+		{
+			$maxGroupCount = $maxGroupCount_ar["maxCount"];
+		}
+
+		mysql_free_result($containerID_rs);
+		unset($containerID_rs, $containerID_ar);
+		
+		$find_group_name_rs = mysql_query("SELECT `contGroupName` FROM `ContainerGroup_tbl` WHERE `contGroupID`='" . $groupID_const . "' AND `status`='ACTIVE'", $conn) or die("Error in grabbing SQL group name: " . mysql_error());
+	
+		if( $find_group_name_ar = mysql_fetch_array( $find_group_name_rs, MYSQL_ASSOC ) )
+		{
+			$groupName_const = $find_group_name_ar["contGroupName"];
+		}
+		else
+		{
+			return false;
+		}
+		
+		mysql_free_result( $find_group_name_rs );
+		unset( $find_group_name_rs, $find_group_name_ar );
+		
+		$general_property_set = "('";
+		$setcount = 0;
+	
+		$sql = "SELECT p.elementTypeID, p.propertyName FROM PrepElemTypes_tbl p, ContainerTypeAttributes_tbl c WHERE c.containerTypeID='" . $groupID_const . "' AND c.containerTypeAttributeID=p.elementTypeID AND c.status='ACTIVE' AND p.status='ACTIVE' UNION (SELECT DISTINCT c.prepElementTypeID, b.propertyName FROM ContainerTypeAttributes_tbl a, PrepElemTypes_tbl b, Prep_Req_tbl c WHERE a.containerTypeAttributeID=b.elementTypeID AND a.containerTypeID='" . $groupID_const . "' AND c.prepElementTyp [...]
+
+		// Section that finds the cell property requirements for the container
+		$find_cell_info_rs = mysql_query($sql, $conn) or die("Failure in grabbing container cell info sql statement:" . mysql_error());
+		
+		while ($find_cell_info_ar = mysql_fetch_array($find_cell_info_rs, MYSQL_ASSOC))
+		{
+			$general_property_ar[$find_cell_info_ar["propertyName"]] = $find_cell_info_ar["elementTypeID"];
+			$setcount++;
+			$general_property_set = $general_property_set . $find_cell_info_ar["elementTypeID"] . "','";
+		}
+		
+		$general_property_set = $this->reset_set( $setcount, $general_property_set );
+		$setcount = 0;
+		
+		mysql_free_result( $find_cell_info_rs );
+		unset( $find_cell_info_rs, $find_cell_info_ar );
+		
+		$isolate_set = "('";
+		$prepID_set = "('";
+		
+		$prep_info_ht = new HT_Class();
+		
+		// $plate_id_ar will hold all wellID's for every well spot in the container
+		$plate_id_ar = array();
+		
+		// Temporary wellID array for the given row
+		$plate_row_tmp_ar = array();
+		
+		// Temporary row counter
+		$row_count = 1;
+		
+		// SQL Select statement that grabs all the Prep default information
+		$find_prep_rs = mysql_query( "SELECT a.`prepID`, a.`wellID`, a.`isolate_pk`, a.`refAvailID`, a.`flag`, a.`comments`, b.`wellCol`, b.`wellRow`"
+			. "FROM `Prep_tbl` a INNER JOIN `Wells_tbl` b "
+			. "ON a.`wellID`=b.`wellID` "
+			. "WHERE b.`containerID`='" . $contID_const . "' "
+			. "AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' "
+			. "ORDER BY b.`wellRow`, b.`wellCol` ", $conn ) 
+			or die( "Failure in prep sql statement:" . mysql_error() );;
+
+		while ($find_prep_ar = mysql_fetch_array($find_prep_rs, MYSQL_ASSOC))
+		{
+			// Temporary array container for all prep info
+			$prep_tmp_ar = array();
+			
+			if ($find_prep_ar["wellRow"] > $row_count || ($find_prep_ar["wellRow"] == $maxRow_const && $find_prep_ar["wellCol"] == $maxCol_const))
+			{
+				// next row!
+
+				if( !( $find_prep_ar["wellRow"] == $maxRow_const && $find_prep_ar["wellCol"] == $maxCol_const ) )
+				{
+					$plate_id_ar[$row_count] = $plate_row_tmp_ar;
+				
+					$plate_row_tmp_ar = array();
+					$row_count = $find_prep_ar["wellRow"];
+				}
+			}
+
+			// Should alway be adding the next element into the array
+			$plate_row_tmp_ar[ $find_prep_ar["wellCol"] ] = $find_prep_ar["wellID"];
+			
+			$setcount++;
+			$isolate_set = $isolate_set . $find_prep_ar["isolate_pk"] . "','";
+			$prepID_set = $prepID_set . $find_prep_ar["prepID"] . "','";
+			
+			$prep_tmp_ar["prepID"] = $find_prep_ar["prepID"];
+			$prep_tmp_ar["isolate_pk"] = $find_prep_ar["isolate_pk"];
+			$prep_tmp_ar["refAvailID"] = $find_prep_ar["refAvailID"];
+			$prep_tmp_ar["flag"] = $find_prep_ar["flag"];
+			$prep_tmp_ar["comments"] = $find_prep_ar["comments"];
+			$prep_tmp_ar["wellCol"] = $find_prep_ar["wellCol"];
+			$prep_tmp_ar["wellRow"] = $find_prep_ar["wellRow"];
+
+			$prep_info_ht->add( $find_prep_ar["wellID"], $prep_tmp_ar );
+		}
+
+		// HACK: Need to grab the last element in this container element this way. Cleanest way so far.
+		$plate_id_ar[$row_count] = $plate_row_tmp_ar;
+		
+		$isolate_set = $this->reset_set( $setcount, $isolate_set );
+		$prepID_set = $this->reset_set( $setcount, $prepID_set );
+		$setcount = 0;
+		
+		mysql_free_result( $find_prep_rs );
+		unset( $find_prep_rs, $find_prep_ar );
+		
+		$generalProp_ht = new HT_class();
+
+		// SQL Select that finds all the general properties associated with the found prepID's
+		$find_gen_rs = mysql_query("SELECT `prepPropID`, `prepID`, `elementTypeID`, `value` FROM `PrepElementProp_tbl` "
+		. "WHERE `prepID` IN " . $prepID_set . " AND `elementTypeID` IN " . $general_property_set . " "
+		. "AND `status`='ACTIVE' ORDER BY `prepID`, `elementTypeID`", $conn)
+		or die( "Failure in trying to get real general properties of container: " . mysql_error());
+		
+		$temp_ar = array();
+		$current_id = 0;
+		$new_id = 0;
+		
+		while( $find_gen_ar = mysql_fetch_array( $find_gen_rs, MYSQL_ASSOC ) )
+		{
+			if( $current_id == 0 )
+			{
+				$current_id == $find_gen_ar["prepID"];
+			}
+			
+			$new_id = $find_gen_ar["prepID"];
+			
+			if( $new_id != $current_id )
+			{
+				$generalProp_ht->add( $current_id, $temp_ar );
+				
+				$current_id = $new_id;
+				$temp_ar = array();
+			}
+
+			$temp_ar[ $find_gen_ar["elementTypeID"] ] = $find_gen_ar["value"];
+		}
+		
+		// Must add the last element hashtable
+		$generalProp_ht->add( $current_id, $temp_ar );
+		
+		$isolate_ht = new HT_Class();
+		$reagent_set = "('";
+		$find_reagents_rs;
+		
+		// Finds all the Reagent ID and Isolate information for the given set of Cells
+		$find_reagents_rs = mysql_query("SELECT  DISTINCT a.`expID`, a.`reagentID`, b.`isolate_pk`, b.`isolateNumber`, b.`beingUsed` FROM `Experiment_tbl` a INNER JOIN `Isolate_tbl` b ON a.`expID`=b.`expID` WHERE b.`isolate_pk` IN ". $isolate_set . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY b.`isolate_pk`" , $conn) or die( "Failure in grabbing reagent ID SQL statement: " . mysql_error());
+		
+		while( $find_reagents_ar = mysql_fetch_array( $find_reagents_rs , MYSQL_ASSOC ) )
+		{
+			$setcount++;
+			$reagent_set = $reagent_set . $find_reagents_ar["reagentID"] . "','";
+			
+			$temp_ar = array();
+			$temp_ar["reagentID"] = $find_reagents_ar["reagentID"];
+			$temp_ar["isolateNum"] = $find_reagents_ar["isolateNumber"];
+			$temp_ar["beingUsed"] = $find_reagents_ar["beingUsed"];
+			
+			$isolate_ht->add( $find_reagents_ar["isolate_pk"], $temp_ar );
+		}
+		
+		$reagent_set = $this->reset_set($setcount, $reagent_set);
+		$setcount = 0;
+		
+		// Finds the LIMS system Reagent ID information
+		$reagentGroup_rs = mysql_query("SELECT DISTINCT `reagentID`, `reagentTypeID`, `groupID` FROM `Reagents_tbl` WHERE `reagentID` IN " . $reagent_set . " AND `status`='ACTIVE' ORDER BY `reagentID`", $conn );
+		
+		$rGroups_ar = array();
+		$rTypes_ar = array();
+		
+		while( $reagentGroup_ar = mysql_fetch_array( $reagentGroup_rs, MYSQL_ASSOC ) )
+		{
+			$rTypes_ar[ $reagentGroup_ar["reagentID"] ] = $reagentGroup_ar["reagentTypeID"];
+			$rGroups_ar[ $reagentGroup_ar["reagentID"] ] = $reagentGroup_ar["groupID"];
+		}
+
+		// August 13/07, Marina: Restrict prep modification by project
+		
+		// Get the projects this user may modify
+		$currUserID = $_SESSION["userinfo"]->getUserID();
+		$currUserCategory = $_SESSION["userinfo"]->getCategory();
+		$userLabID = $_SESSION["userinfo"]->getLabID();
+
+		$write_disabled = "";
+
+		// admin has unlimited access
+		if ($currUserCategory == $_SESSION["userCategoryNames"]["Admin"])
+		{
+			$userProjects = findAllProjects();
+		}
+		elseif ($currUserCategory == $_SESSION["userCategoryNames"]["Reader"])
+		{
+			$write_disabled = "DISABLED";
+		}
+		else
+		{
+			$userProjects = getUserProjectsByRole($currUserID, 'Writer');
+		}
+
+		// FREEEEEEE MEMORRYYYYYYYYYYY
+		
+		// -------------- Start of Main output area for plate
+
+
+		// Moved here June 2, 2011
+		$contTypeAttribs = $lfunc_obj->getContainerTypeAttributes($groupID_const);
+		?>
+		<form name="wells_form" method=post action="<?php echo $_SERVER["PHP_SELF"] . "?View=7&Mod=" . $contID_const . ""; ?>">
+
+		<table width="765px" cellpadding="5" border="0">
+			<TR>
+				<TD colspan="2">
+					  <a href="<?php echo $_SERVER["PHP_SELF"] . "?View=2&gID=" . $_SESSION["Container_ID_Name"][$groupID_const]; ?>" style="font-size:9pt; font-weight:normal;">View all <?php echo $_SESSION["Container_ID_Name"][$groupID_const]; ?> containers</a><?php
+				?></TD>
+
+				<TD style="text-align:right; padding-right:20px; white-space:nowrap;">
+				<?php
+					$size_rs  = mysql_query( "SELECT `maxCol`, `maxRow` FROM `ContainerTypeID_tbl` WHERE `contTypeID`='" . $contTypeID . "' AND `status`='ACTIVE'" , $conn ) or die("Error reading container original info in SQL statement: " . mysql_error());
+				
+					if ($size_ar = mysql_fetch_array( $size_rs, MYSQL_ASSOC ) )
+					{
+						$cols = $size_ar["maxCol"];
+						$rows = $size_ar["maxRow"];
+					}
+				
+					$capacity = $cols * $rows;
+					$empty_cells = $lfunc_obj->getEmptyCellNum($contID_const, $contTypeID);
+					$occupied_cells = $capacity - $empty_cells;
+
+					if (($occupied_cells == 0) && (($contLabID == $userLabID) || ($currUserCategory == $_SESSION["userCategoryNames"]["Admin"])) && ($currUserCategory != $_SESSION["userCategoryNames"]["Reader"]))
+					{
+						?>    <a href="<?php echo $_SERVER["PHP_SELF"] . "?View=5&Mod=" . $contID_const; ?>" style="font-size:9pt; font-weight:normal;">Edit Container Information</a><?php
+					}
+
+					if ((($currUserCategory != $_SESSION["userCategoryNames"]["Reader"])) && (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || ($contLabID == $userLabID)))
+					{
+						?>     <a style="font-size:9pt; font-weight:normal;" href="<?php echo $_SERVER["PHP_SELF"] . "?View=3&Mod=" . $contID_const; ?>">Location Details</a><?php
+					}
+
+				?></TD>
+			</TR>
+
+			<tr><td colspan="3"><HR></td></tr>
+
+			<tR>
+				<td style="width:150px; padding-left:15px;">
+				<?php 
+					if ($groupCount_const > 1)
+					{
+						?><a style="font-size:9pt;" href="<?php echo $_SERVER["PHP_SELF"] . "?View=2&Mod=" . $this->get_Previous_ContainerID( $groupCount_const, $groupID_const, $contID_const ) . ""; ?>">Previous</a><?php
+					}
+					else
+					{
+						?><span class="linkDisabled" style="font-size:9pt;">Previous</span><?php
+					}
+				?>
+				</td>
+
+				<td style="text-align:center; padding-right:25px; white-space:nowrap; font-size:14px; font-weight:bold; color:#EF4A11;"><?php
+					echo strtoupper($containerName);
+					?>
+				</td>
+
+				<td style="width:120px; text-align:right; padding-right:20px;">
+				<?php 
+					if ($groupCount_const < $maxGroupCount)
+					{
+						?><a style="font-size:9pt;" href="<?php echo $_SERVER["PHP_SELF"] . "?View=2&Mod=" . $this->get_Next_ContainerID($groupCount_const, $groupID_const, $contID_const) . ""; ?>">Next</a><?php
+					}
+					else
+					{
+						?><span class="linkDisabled" style="font-size:9pt;">Next</span><?php
+					}
+				?>
+				</td>
+
+				</TR>
+
+				<TR><TD colspan="3"><HR></TD></TR>
+			</tr>
+
+			<tr>
+				<td style="white-space:nowrap;" colspan="3">
+					<center>
+						<TABLE>
+							<TR>
+								<TD><input type="submit" style="font-size:9pt;" name="well_new_button" value="Create New Wells" <?php echo $write_disabled; ?> onClick="return verifyWellsSelected();"></TD>
+								<TD><input type="submit" style="font-size:9pt;" name="well_modify_button" value="Modify Wells"  <?php echo $write_disabled; ?> onClick="return verifyWellsSelected();"></TD>
+								<TD><input type="submit" style="font-size:9pt;" name="well_delete_button" value="Delete Wells"  <?php echo $write_disabled; ?> onClick="return verifyWellsSelected();"></TD>
+								
+								<!-- May 30, 2011: Removed, done now at the click of the top left corner (implement Excel-like behaviour)
+								<TD><input type="button" style="font-size:9pt;" name="well_select_all_button" value="Select All"  <?php echo $write_disabled; ?> onClick="return selectAllWells()"></TD>
+
+								<TD><input type="button" style="font-size:9pt;" name="well_select_all_button" value="Deselect All"  <?php echo $write_disabled; ?> onClick="return clearAllWells()"></TD> -->
+								
+								<!-- May 30, 2011 -->
+								<TD>
+									<!-- <input type="submit" style="font-size:9pt; padding-bottom:2px; font-weight:bold;" name="update_selected_attributes" value="Update Selected Attributes"<?php echo $write_disabled; ?>> -->
+									<?php
+										$contID = $_GET["Mod"];
+
+										$prep_gen_check_rs = mysql_query("SELECT p.elementTypeID, p.propertyName FROM PrepElemTypes_tbl p, ContainerTypeAttributes_tbl c WHERE c.containerTypeID='" . $selContType . "' AND c.containerTypeAttributeID=p.elementTypeID AND c.status='ACTIVE' AND p.status='ACTIVE' UNION (SELECT a.`prepElementTypeID`, b.`propertyName` FROM `Prep_Req_tbl` a INNER JOIN `PrepElemTypes_tbl` b ON a.`prepElementTypeID`=b.`elementTypeID` WHERE a.`containerID`='" . $contID . "' AND a.`requirement`='RE [...]
+										
+										$req_set = "('";
+										$req_setcount = 0;
+										$general_req_ar = array();
+
+										while ($prep_gen_check_ar = mysql_fetch_array($prep_gen_check_rs, MYSQL_ASSOC))
+										{
+											$req_setcount++;
+
+											$req_set = $req_set . $prep_gen_check_ar["elementTypeID"] . "','";
+											$general_req_ar[$prep_gen_check_ar["propertyName"]] = $prep_gen_check_ar["elementTypeID"];
+										}
+
+//										print_r($general_req_ar);
+									?>
+									<SELECT ID="changeAttributeSelect" onChange="if (verifyWellsSelected()) updateWellAttribute(this[this.selectedIndex].value, '<?php echo $contID; ?>');" style="background-color:lightgray; color:navy; font-weight:bold;">
+										<OPTION selected value="default">Change attribute value</OPTION>
+										<OPTION value="Reference">Reference</OPTION>
+										<?php
+											foreach ($contTypeAttribs as $a => $attrName)
+											{
+												echo "<OPTION value=\"" . $attrName . "\">" . $attrName . "</OPTION>";
+											}
+										?>
+										</OPTION>
+										<OPTION value="Comments">Comments</OPTION>									
+									</SELECT>
+									<IMG src="<?php echo $hostname . "pictures/images.jpg"; ?>" HEIGHT="18" width="18" ALT="Help" style="vertical-align:middle; cursor:pointer; padding-bottom:6px;" onClick="return overlib('Select an attribute name from the list to update its value for all selected wells at once.  Empty wells will not be affected.</B>', CAPTION, 'Change Attribute Value', STICKY);"> 
+									<IMG SRC="pictures/new01.gif" ALT="new" WIDTH="35" HEIGHT="20" style="cursor:auto;">
+								</TD>
+
+								<TD>
+									<IMG SRC="pictures/excel.gif" width="13" height="13" style="vertical-align:middle; padding-bottom:2px;"> <span class="linkShow" style="font-weight:bold; font-size:10pt;" onClick="document.plate_to_excel.submit()">Download</SPAN>
+									<IMG SRC="pictures/new01.gif" ALT="new" WIDTH="35" HEIGHT="20" style="cursor:auto;">
+								</TD>
+							</TR>
+						</TABLE>
+					</center>
+				</td>
+			</tr>
+
+			<!-- May 31, 2011 -->
+			<TR><TD colspan="100%" style="font-weight:bold;"><span style="color:red; font-weight:bold;">**NEW**</span> Click on a column or row heading to select it.</TD></TR>
+
+			<TR><TD colspan="100%" style="font-weight:bold;"><span style="color:red; font-weight:bold;">**NEW**</span> Click on the top left corner to select the entire plate.</TD></TR>
+
+			<TR><TD colspan="100%" style="font-weight:bold; color:#EF4A11"><span style="color:red; font-weight:bold;">**</span> Only wells that you are authorized to modify will be highlighted.</TD></TR>
+
+			<TR><TD colspan="3"></TD></TR>
+
+		</table>
+
+		<table style="width:760px" border="1" frame="box" rules="all" cellpadding="2" cellspacing="2">
+			<tr>
+				<td style="background-color:grey; cursor:pointer; border-top:1px solid gray; border-left:1px solid lightgray; border-bottom:2px outset lightgray; border-right:3px outset lightgray;" onclick="selectOrDeselectAllWells('<?php echo $_GET["Mod"]; ?>', '<?php echo $maxRow_const*$maxCol_const; ?>');" border="0"></td> <!-- For row identifier column --><?php
+
+				for( $i = 1; $i <= $maxCol_const; $i++ )
+				{
+					echo "<td class=\"plateColumn_hdr\" onClick=\"selectPlateColumn('" . $_GET["Mod"] . "', '" . $i . "')\">" . $i . "</td>";
+				}
+
+				?><td class="plateRow_hdr" style="font-size:9pt; cursor:auto; white-space:nowrap; padding-left:8px; padding-right:8px;">Prep Attributes
+
+				</td> <!-- For row identifier cell -->
+			</tr><?php
+
+		for ($row = 1; $row <= $maxRow_const; $row++)
+		{
+			echo "<tr>";
+
+			$wellID_ar_tmp = $plate_id_ar[$row];
+
+			echo "<td class=\"plateRow_hdr\" onClick=\"selectPlateRow('" . $_GET["Mod"] . "', '" . $row . "')\">" . $lfunc_obj->getLetterRow($row) . "</td>";
+			
+			for ($col = 1; $col <= $maxCol_const; $col++)
+			{
+				if (strlen($wellID_ar_tmp[$col]) > 0)
+				{
+					$prep_info_tmp = $prep_info_ht->get($wellID_ar_tmp[$col]);
+					$isolate_info_tmp = $isolate_ht->get($prep_info_tmp["isolate_pk"]);
+			
+					// August 13/07, Marina: If current user does not have write access to the project this reagent belongs to, disallow prep modification - checkbox would be disabled
+					$reagentProject = getReagentProjectID($isolate_info_tmp["reagentID"]);
+					$disabled = $write_disabled;
+
+					if (($isolate_info_tmp["reagentID"] > 0) && ($reagentProject != 0) && !in_array($reagentProject, $userProjects))
+						$disabled = "DISABLED";
+
+					// Feb. 24/10: but not for Admin
+					else if (($reagentProject == 0) && ($currUserCategory != $_SESSION["userCategoryNames"]["Admin"]))
+						$disabled = "DISABLED";
+
+					// Modified April 20/06 by Marina
+					$prep_id_tmp = $gfunc_obj->getConvertedID( $rTypes_ar[ $isolate_info_tmp["reagentID"] ], $rGroups_ar[ $isolate_info_tmp["reagentID"] ] );
+	
+					// Sept. 11-14, 2007: Make the prep ID a hyperlink back to Reagent view, but disable it if the user does not have Read access to the reagent's project
+					
+					if ($currUserCategory == $_SESSION["userCategoryNames"]["Admin"])
+						$readProjects = findAllProjects();
+					else
+						$readProjects = getAllowedUserProjectIDs($currUserID);
+
+					// Jan. 7, 2010: Restrict access completely if user not project member
+					if (in_array($reagentProject, $readProjects))
+					{
+						# May 22/07, Marina - If navigating from Reagent Group by Isolate view to a specific well, mark it with bright orange colour
+						if (isset($_GET["Row"]) && isset($_GET["Col"]) && ($_GET["Row"] == $row) && ($_GET["Col"] == $col))
+						{
+							?><td ID="well_plate_<?php echo $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col; ?>" style="color:#BA55D3; font-size: x-small; font: Geneva, Arial, Helvetica, sans-serif; border-width:3px; border-style: solid"><?php
+						}
+						elseif ($prep_info_tmp["flag"] == "YES")
+						{
+							// Red output - Modified May 19/09: made border thicker
+							?><td ID="well_plate_<?php echo $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col; ?>" style="color:#FF0000; font-size: x-small; font:Geneva, Arial, Helvetica, sans-serif; padding-top:2px; padding-bottom:2px; padding-left:5px; padding-right:5px;">
+								<DIV style="border: 2px solid #FF0000; padding:3px;"><?php
+						}
+						elseif ($isolate_info_tmp["beingUsed"] == "YES" && $isIsolate_container)
+						{
+							// Blue output - Modified May 19/09: made border thicker
+							?><td ID="well_plate_<?php echo $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col; ?>" style="color:#0099FF; font-size: x-small; font: Geneva, Arial, Helvetica, sans-serif; padding-top:2px; padding-bottom:2px; padding-left:5px; padding-right:5px;">
+								<DIV STYLE="border: 2px solid #0099FF; padding:3px;"><?php
+						}
+						else
+						{
+							// Normal black output
+							?><td ID="well_plate_<?php echo $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col; ?>" style="font-size: x-small; font: Geneva, Arial, Helvetica, sans-serif; padding-top:2px; padding-bottom:2px; padding-left:5px; padding-right:5px;">
+								<DIV style="border:1px solid black; padding:3px;"><?php
+						}
+
+						echo "<a href=\"" . $hostname . "Reagent.php?View=6&rid=" . $isolate_info_tmp["reagentID"] . "\">" . $prep_id_tmp;
+
+						if( $isIsolate_container && strlen($prep_id_tmp) > 0)	// apr 20
+						{
+							echo "-";
+							echo $isolate_info_tmp["isolateNum"];
+						}
+						echo  "</a>";
+
+						// Placing here May 18, 2010, AND using ID instead of Name to recognize the anchor buried inside a table.  THIS WORKS.
+						echo "<a ID=\"focus_" . $row . "_" . $col . "\"></a>";	# may 22/07
+
+						echo "<br>";
+
+						echo $prep_info_tmp["refAvailID"] . "<BR>\n";
+						
+						echo "<BR>";
+						$this->printGeneral_property( $generalProp_ht, $prep_info_tmp["prepID"] , "<BR>" );
+						echo "<BR>";
+						echo $prep_info_tmp["comments"] . "<BR>\n";
+						
+						# Added May 22/07, Marina: If arriving at this view from the Reagent Group By Isolate view to view the location of a specific prep, mark the location of that prep by selecting its checkbox
+						if (isset($_GET["Row"]) && isset($_GET["Col"]) && ($_GET["Row"] == $row) && ($_GET["Col"] == $col))
+						{
+							echo "\n<input type=checkbox ID=\"plate_" . $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col . "\" name=wells_checkbox[] checked value=\"" . $row . "|" . $col . "\" " . $disabled . " onClick=\"highlightWell(this.id, 'well_plate_" . $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col . "');\">\n";
+						}
+						else
+						{
+							echo "\n<input type=checkbox ID=\"plate_" . $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col . "\" name=wells_checkbox[] value=\"" . $row . "|" . $col . "\" " . $disabled . " onClick=\"highlightWell(this.id, 'well_plate_" . $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col . "');\">\n";
+						}
+
+						echo "</DIV></TD>\n";		// May 19/09, Marina: added closing </DIV>
+					}
+					else	// Jan. 7, 2010: hide well contents
+					{
+						?><td style="padding-left:2px; text-align:center; background-color:#E1E1E1;">
+							<DIV STYLE="padding-top:35%; width:92%; height:50%; text-align:center; font-weight:bold; font-family:Helvetica; font-size:11pt; color:#8E8E8E;" name="plate_<?php echo $_GET["Mod"]; ?>_wells_restricted[]">RESTRICTED</DIV>
+						</TD><?php
+					}
+				}
+				else
+				{
+					// Added Sept 27, 2005 by Marina, to mark wells that are reserved
+					$query = "SELECT * FROM `Wells_tbl` WHERE `containerID`='" . $contID_const . "' AND `wellRow`='" . $row . "' AND `wellCol`='" . $col . "' AND `reserved`='TRUE' AND `status`='ACTIVE'";
+					$reserved_wells_rs = mysql_query($query, $conn) or die ("Failure in well info selection " . mysql_error());
+
+					// If the well is reserved, output it in colour, differentiating between wells reserved by the current user and wells reserved by others
+					if ($reserved_wells_ar = mysql_fetch_array($reserved_wells_rs))
+					{
+						if( $reserved_wells_ar["do_not_use"] == "TRUE" )
+						{
+							// Do not use is set for the current well
+							// Should have the highest priority of any well type
+							echo "<td ID=\"well_plate_" . $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col . "\" style=\"color:#FF0000; font-size: x-small; font: Geneva, Arial, Helvetica, sans-serif; border-width:thick; border-style: groove\">";
+							echo "This well has been set to <strong>Do Not Use</strong>";
+							echo "</td>";
+						}
+						elseif ($reserved_wells_ar["creatorID"] == $currentUserID)
+						{
+							// If the well is currently reserved by a user
+							// colour cell green
+							echo "<td ID=\"well_plate_" . $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col . "\" style=\"color:#009900; font-size: x-small; font: Geneva, Arial, Helvetica, sans-serif; border-width:thick; border-style: groove\">";
+							echo "\n<input type=checkbox ID=\"plate_" . $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col . "\" name=wells_checkbox[] value=\"" . $row . "|" . $col . "\" " . $write_disabled . " onClick=\"highlightWell(this.id, 'well_plate_" . $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col . "');\">\n";
+							echo "</td>";
+						}
+						else
+						{
+							// Default type
+							// colour cell brown
+							// June 10, 2011: Now that we're allowing modification by attribute, disable the well if not reserved by you!
+							echo "<td ID=\"well_plate_" . $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col . "\" style=\"color:#990000; font-size: x-small; font: Geneva, Arial, Helvetica, sans-serif; border-width:thick; border-style: groove\">";
+							echo "\n<input type=checkbox ID=\"plate_" . $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col . "\" name=wells_checkbox[] value=\"" . $row . "|" . $col . "\" " . "DISABLED" /*$write_disabled*/ . " onClick=\"highlightWell(this.id, 'well_plate_" . $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col . "');\">\n";
+							echo "</td>";
+						}
+					}
+					else
+					{
+						// Default type for all normal wells
+						echo "<td ID=\"well_plate_" . $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col . "\">";
+
+						echo "\n<input type=checkbox ID=\"plate_" . $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col . "\" name=wells_checkbox[] value=\"" . $row . "|" . $col . "\"" . $write_disabled . " onClick=\"highlightWell(this.id, 'well_plate_" . $_GET["Mod"] . "_Row_" . $row . "_Col_" . $col . "');\">\n";
+						echo "</td>";	
+					}
+				}
+			}
+
+			echo "<td style=\"white-space:nowrap;\">";
+
+			// Jan. 15, 2010: If container type is modified after plate was created, $general_property_ar would not return newly added properties
+			$this->printAll_headers(array_flip($contTypeAttribs), "<BR>");
+			echo "</td>";
+			echo "</tr>";
+		}
+		
+		echo "</table>";
+		echo "</form>";
+		echo "</td>";
+		echo "</tr>";
+		echo "</table>";
+
+		?><form name="plate_to_excel" action="<?php echo $cgi_path . "location_request_handler.py"; ?>" method="POST">
+			<input type="hidden" name="contID" value="<?php echo $_GET["Mod"]; ?>">
+			<input type="hidden" name="export_plate">
+		</form><?php
+	}
+
+	/**
+	 * Auxiliary function
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param INT $count
+	 * @param STRING $set
+	*/
+	function reset_set($count, $set)
+	{
+		if( $count > 0 )
+		{
+			$set = substr( $set, 0, strlen( $set ) - 2 ) . ")";
+		}
+		else
+		{
+			$set = "('')";
+		}
+		return $set;
+	}
+	
+
+	/**
+	 * Escape quotation mark in property name
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param STRING $propName
+	*/
+	function getSafeSelect($propName)
+	{
+		if (!(strpos($propName, "''" === false)))
+		{
+			return (str_replace("''", "'", $propName));
+		}
+	}
+
+	/**
+	 * Function printGeneral_property()
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param HT_Class $ht
+	 * @param MIXED $key
+	 * @param STRING $separator
+	*/
+	function printGeneral_property($ht, $key , $separator)
+	{
+		$result_ar = $ht->get( $key );
+		
+		if( $result_ar == -1 )
+		{
+			echo "";
+			echo $separator;
+		}
+		else
+		{
+			foreach( $result_ar as $arrayKey => $arrayValue )
+			{
+//				echo $arrayValue;
+				echo $this->getSafeSelect($arrayValue);		// Feb 22, 2006, Marina
+				echo $separator;
+			}
+		}
+	}
+
+
+	/**
+	 * Print ALL prep property names on container view (general plus specific to container type)
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param Array $name_ar
+	 * @param STRING $separator
+	*/
+	function printAll_headers($name_ar, $separator)
+	{
+		echo "<TABLE style=\"white-space:nowrap; font-weight:bold; font-size:9pt;\" width=\"98%\">";
+			echo "<TR><TD style=\"font-weight:bold; font-size:9pt;\">OpenFreezer ID</td></tr>";
+			echo "<TR><TD style=\"font-weight:bold; font-size:9pt;\">Reference</td></tr>";
+			$this->printGeneral_headers($name_ar, $separator);
+			echo "<TR><TD style=\"font-weight:bold; font-size:9pt;\">Comments</td></tr>";
+
+			// May 31, 2011: redesigning, so it's not needed, only confusing
+// rmvd May 31, 2011		echo "<TR><TD>Tool Checkbox</td></tr>";
+		echo "</TABLE>";
+	}
+	
+	/**
+	 * Print ONLY the prep property names that are specific to this container type
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param Array $name_ar
+	 * @param STRING $separator
+	*/
+	function printGeneral_headers($name_ar , $separator)
+	{
+		foreach($name_ar as $name => $id)
+		{
+			echo "<TR><TD style=\"font-weight:bold; font-size:9pt;\">";
+			echo $name;
+			echo "</td></tr>";
+		}
+	}
+	
+	/**
+	 * Return the ID of the previous container in this container type group
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT $groupCount_const Numeric position of this container in the sequence of other containers of this type
+	 * @param INT $groupID_const ID of this container type (e.g. '2' => 'Glycerol Stock'
+	 * @param INT $contID ID of this container
+	*/
+	function get_Previous_ContainerID($groupCount_const, $groupID_const, $contID)
+	{
+		global $conn;
+		
+		$find_preview_rs = mysql_query("SELECT `containerID`,`contGroupCount` FROM `Container_tbl` WHERE `contGroupID`='" . $groupID_const . "' AND `contGroupCount`<'" . $groupCount_const . "' AND `status`='ACTIVE' ORDER BY `contGroupCount` DESC", $conn);
+
+		if( $find_preview_ar = mysql_fetch_array( $find_preview_rs, MYSQL_ASSOC ) )
+		{
+			return $find_preview_ar["containerID"];
+		}
+		
+		return $contID;
+	}
+	
+
+	/**
+	 * Return the ID of the next container in this container type group
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT $groupCount_const Numeric position of this container among other containers of this type
+	 * @param INT $groupID_const ID of this container type (e.g. '2' => 'Glycerol Stock'
+	 * @param INT $contID ID of this container
+	*/
+	function get_Next_ContainerID( $groupCount_const, $groupID_const, $contID  )
+	{
+		global $conn;
+		
+		$find_preview_rs = mysql_query( "SELECT `containerID`,`contGroupCount` AS next FROM `Container_tbl` WHERE `contGroupID`='" . $groupID_const . "' AND `contGroupCount`>'" . $groupCount_const . "' AND `status`='ACTIVE' ORDER BY `contGroupCount` ASC", $conn );
+
+		if( $find_preview_ar = mysql_fetch_array( $find_preview_rs, MYSQL_ASSOC ) )
+		{
+			return $find_preview_ar["containerID"];
+		}
+		
+		return $contID;
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Location/Location_Well_Class.php b/OpenFreezer/Location/Location_Well_Class.php
new file mode 100755
index 0000000..6615eee
--- /dev/null
+++ b/OpenFreezer/Location/Location_Well_Class.php
@@ -0,0 +1,2612 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2010 Pawson Laboratory, All Rights Reserved
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Location
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+ * This class handles functions related to wells (1-prep slots) in container
+ *
+ * @author John Paul Lee @version 2005
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Location
+ *
+ * @copyright  2005-2010 Pawson Laboratory
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+class Location_Well_Class
+{
+	/**
+	 * Default constructor
+	*/
+	function Location_Well_Class()
+	{}
+	
+	/**
+	 * Fetch the internal database ID of a container SIZE from its name
+	 *
+	 * Last modified by Marina on Sept 10, 2007
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param Array $postvars
+	 * @param INT $contID
+	 * @param boolean $err
+	 *
+	 * @return boolean TRUE on successful creation, FALSE on error
+	*/
+	function create_wells($postvars, $contID, $err=false)
+	{
+		global $conn;
+
+		$lfunc_obj = new Location_Funct_Class();
+		$gfunc_obj = new generalFunc_Class();
+		
+		$well_occupied = false;
+		$wellUnavailable = false;
+		$submit_btn = false;
+		$isoActiveCont = false;
+
+		// Feb. 9, 2010
+		$selContTypeName = $lfunc_obj->getContainerGroupName($contID);
+		$selContType = $_SESSION["Container_Name_ID"][$selContTypeName];
+
+		if (isset( $_SESSION["userinfo"] ) )
+		{
+			$currentUserID = $_SESSION["userinfo"]->getUserID();
+			$currUserCategory = $_SESSION["userinfo"]->getCategory();
+			$userProjects = getUserProjectsByRole($currentUserID, 'Writer');
+		}
+
+		if ($err)
+		{
+			// Return the form with error output
+			?>
+			<form METHOD="POST" ACTION="<?php echo $_SERVER["PHP_SELF"] . "?View=7&Mod=" . $contID . ""; ?>">
+				<table border="1" frame="box" rules="all" valign="middle" cellpadding="3">
+					<th colspan="100%" class="detailedView_heading"><?php echo $lfunc_obj->getContainerName($contID); ?>
+						<BR><span style="font-size:8pt; font-weight:bold; color:red;"><IMG SRC="pictures/new01.gif" ALT="new" WIDTH="35" HEIGHT="20" style="cursor:auto;">You may update multiple wells at once by clicking on the property's column heading and typing its value in the pop-up box.</span>
+					</th>
+				
+					<tr>
+						<td style="width:5%; font-weight:bold; text-align:center; font-size:7pt; color:navy; text-align:center;">Well</td>
+
+						<td style="font-weight:bold; padding-left:4px; padding-right:4px; text-align:center; font-size:7pt; font-weight:bold; color:navy; white-space:nowrap; cursor:pointer;" onClick="popupWellAttrUpdateForm('OpenFreezer ID');">OpenFreezer ID</td>
+						<?php
+							// Correction June 8, 2011							
+							/*
+							$isoAct_state = $lfunc_obj->isIsoActive($contID);
+
+							if ($isoAct_state)*/
+
+							$isoAct_state = $lfunc_obj->isIsoActive( $contID );
+							$_SESSION["isoAct_state"] = $isoAct_state;
+			
+							// Added by Marina on July 25, 2005; MOVED UP HERE ON AUG 31, 2006
+							if ($isoAct_state == "YES")
+							{
+								$isoAct_state = true;
+								$isIsolate_container = true;
+							}
+							else
+							{
+								$isoAct_state = false;
+								$isIsolate_container = false;
+							}
+
+							if ($isIsolate_container) 
+							{
+								?>
+								<input type="hidden" name="well_limsid_isoAct_hidden" value="YES">
+								<td style="font-weight:bold; padding-left:4px; padding-right:4px; text-align:center; font-size:7pt; color:navy; cursor:pointer;" onClick="popupWellAttrUpdateForm('Isolate Number');">Isolate Number</td>
+							
+								<td style="font-weight:bold; text-align:center; font-size:7pt; color:navy; padding-left:7px; padding-right:7px; cursor:pointer;" onClick="checkUncheckAllIsolates();">Current Set Isolate</td>
+								<?php
+							}
+
+						?><td style="font-weight:bold; text-align:center; font-size:7pt; color:navy; cursor:pointer;" onClick="popupWellAttrUpdateForm('Reference');">Reference</td>
+						<td style="font-weight:bold; text-align:center; font-size:7pt; color:navy; width:50px; padding-left:5px; padding-right:5px; cursor:pointer;" onClick="checkUncheckAllFlags();">Flag</td>
+						<td style="font-weight:bold; text-align:center; font-size:7pt; color:navy; cursor:pointer;" onClick="popupWellAttrUpdateForm('Comments');">Comments</td>
+						<?php
+							// General Container Properties
+							$genContProps = array();
+
+							$prep_gen_check_rs = mysql_query("SELECT p.elementTypeID, p.propertyName FROM PrepElemTypes_tbl p, ContainerTypeAttributes_tbl c WHERE c.containerTypeID='" . $selContType . "' AND c.containerTypeAttributeID=p.elementTypeID AND c.status='ACTIVE' AND p.status='ACTIVE' UNION (SELECT a.`prepElementTypeID`, b.`propertyName` FROM `Prep_Req_tbl` a INNER JOIN `PrepElemTypes_tbl` b ON a.`prepElementTypeID`=b.`elementTypeID` WHERE a.`containerID`='" . $contID . "' AND a.`requirement`='REQ'  [...]
+
+							while ($prep_gen_check_ar = mysql_fetch_array($prep_gen_check_rs, MYSQL_ASSOC))
+							{
+								// change Feb. 24/10: different column name returned!
+								$genContProps[$prep_gen_check_ar["elementTypeID"]] = $prep_gen_check_ar["propertyName"];
+							}
+
+							foreach ($genContProps as $propID => $propName)
+								echo "<td  style=\"font-weight:bold; text-align:center; cursor:pointer; font-size:7pt; color:navy;\" onClick=\"popupWellAttrUpdateForm('" . $propName . "');\">" . $propName . "</td>";
+						?>	
+					</tr>
+					<?php
+
+					// print POST values
+					foreach ($postvars as $key => $value)
+					{
+						$pieces = explode( "|", $value );
+						$wellRow = $pieces[0];		// get the row number of each well
+						$wellCol = $pieces[1];		// get the column number of each well
+						$general_info_ht = new HT_Class();
+			
+						?>
+						<tr>
+							<td style="font-weight:bold; color:#104E8B; width:5%; font-size:8pt; text-align:center;">
+							<?php 
+								// Coordinates
+								echo strtoupper($lfunc_obj->getLetterRow($wellRow)) . ":" . $wellCol; 
+							?>
+							</td>
+
+							<td name="limsID_td[]">
+							<?php 
+								// LIMS ID
+								?><input type="text" size="8" class="locationText" name="well_LIMSID_field[]" value="<?php echo strtoupper($_POST["well_LIMSID_field"][$key]); ?>" onKeyPress="return disableEnterKey(event);">
+							</td>
+
+							<?php 
+								// Isolate # if exists
+								if ($isoAct_state)
+								{
+									// Isolate number
+									?>
+									<td style="text-align:center" name="isoNum_td[]">
+										<input type="text" class="locationText" size="5" style="padding-left:5px; padding-right:5px;" name="well_isoNum<?php echo $key; ?>_textfield" value="<?php echo $_POST["well_isoNum" . $key . "_textfield"]; ?>" onKeyPress="return disableEnterKey(event);">
+									</td>
+
+									<td style="text-align:center">
+										<?php
+											// Current set isolate?
+											if (isset($_POST["well_mod_beingUsed" . $key . "_checkbox"])) 
+											{
+												?>
+												<input type="checkbox" name="well_beingUsed<?php echo $key; ?>_checkbox" checked value="YES"></input>
+												<?php
+											}
+											else 
+											{
+												?>
+												<input type="checkbox" name="well_beingUsed<?php echo $key; ?>_checkbox" value="NO"></input>
+												<?php
+											}
+										?>
+									</td>
+									<?php
+								}
+							?>
+							<td name="Reference_td[]">
+								<input type="text" class="locationText" size="12" style="padding-left:5px; padding-right:5px;" name="well_refAvail_text[]" value="<?php echo $_POST["well_refAvail_text"][$key]; ?>" onKeyPress="return disableEnterKey(event);">
+							</td>
+
+							<td style="text-align:center">
+							<?php
+								// Flag
+								if (isset($_POST["well_flag" . $key . "_checkbox"]))
+								{
+									?>
+										<input type="checkbox" name="well_flag<?php echo $key; ?>_checkbox" CHECKED value="YES">
+									<?php
+								}
+								else
+								{
+									?>
+										<input type="checkbox" name="well_flag<?php echo $key; ?>_checkbox" value="NO">
+									<?php
+								}
+							?>
+							</td>
+
+							<td name="Comments_td[]">
+								<input type="text" class="locationText" size="20" style="padding-left:5px; padding-right:5px;" name="well_comments_text[]" value="<?php echo $_POST["well_comments_text"][$key]; ?>" onKeyPress="return disableEnterKey(event);">
+							</td>
+							<?php
+								// finish off general properties
+								foreach ($genContProps as $propID => $propName)
+								{
+									//echo $propID . ", ";
+
+									echo "<td style=\"text-align:center\" name=\"" . $propName . "_td[]\">";
+									echo "<INPUT TYPE=\"TEXT\" class=\"locationText\" style=\"padding-left:5px; padding-right:5px;\" onKeyPress=\"return disableEnterKey(event);\" name=\"well_mod_general" . $propID . "_text[]\" value=\"";
+									echo $_POST["well_mod_general" . $propID . "_text"][$key];
+									echo "\">";
+									echo "</td>";
+								}
+							?>
+							</tr>
+							<?php
+						// Now pull up the project ID again and issue an error if user can't write to it - only way
+						$tmp_lims_id = $gfunc_obj->get_rid($_POST["well_LIMSID_field"][$key]);
+						$projectID = getReagentProjectID($tmp_lims_id);
+
+						if (($tmp_lims_id > 0) && ($currUserCategory != $_SESSION["userCategoryNames"]["Admin"]) && !in_array($projectID, $userProjects))
+						{
+							// print error message
+							echo "<tr>";
+							echo "<td style=\"font-weight:bold; color:#104E8B; width:100px; font-size:8pt; padding-left:10px; padding-right:10px;\"></td>";
+							echo "<td colspan=\"100%\" style=\"color:#FF0000; font-weight:bold; font-size:7pt; padding-left:5px;\">";
+							echo "You may not insert <span style=\"color:#0000FF\">" .  strtoupper($_POST["well_LIMSID_field"][$key]) . "</span> into this well, since you do not have Write access to its project.  Please contact the project owner to obtain permission.";
+							echo "</td>";
+							echo "</tr>";
+						}
+					}
+
+					?><TR><TD colspan="100%" style="padding-top:15px; padding-left:10px; color:#0101DE; font-size:9pt;"><HR><P><B><U>Note</U>: Only preps of the following reagent types may be stored in this container; other prep types are not allowed:</B><BR><BR>
+		
+					<TABLE style="width:200px;" cellpadding="2">
+						<TR>
+							<TD style="text-decoration:underline; padding-left:5px; font-size:9pt; color:green; font-weight:bold;">Name</TD>
+							<TD style="text-decoration:underline; color:green; font-size:9pt; font-weight:bold;">Prefix</TD>
+						</TR>
+					<?php
+		
+					$allowed_r_types = $lfunc_obj->getContainerReagentTypes($selContType);
+		
+					foreach ($allowed_r_types as $key => $value)
+					{
+						echo "<TR>";
+							echo "<TD style=\"padding-left:5px; color:#0202DD;\">" . $_SESSION["ReagentType_ID_Name"][$value] . "</TD>";
+							echo "<TD style=\"padding-left:5px; color:#0202DD;\">" . $_SESSION["ReagentType_ID_Prefix"][$value] . "</TD>";
+		
+							echo "<INPUT TYPE=\"hidden\" ID=\"rTypes_allowed[]\" NAME=\"allowed_prep_prefixes[]\" VALUE=\"" . $_SESSION["ReagentType_ID_Prefix"][$value] . "\">";
+						echo "</TR>";
+					}
+		
+					// list of ALL prefixes
+					foreach ($_SESSION["ReagentType_ID_Prefix"] as $rTypeID => $rTypePrefix)
+					{
+						// Feb. 9, 2010
+						echo "<INPUT TYPE=\"hidden\" NAME=\"all_prefixes[]\" value=\"" . $rTypePrefix . "\">";
+					}
+
+					?></table></td></tr>
+
+					<tr>
+						<td> </td>
+						<td style="text-align:center"><input type="submit" name="well_limsid_submit_button" onClick="return checkPrepType() && checkExistingPrepID();" value="SUBMIT"></td>
+						<td colspan="11"><input type="submit" name="well_create_cancel_button" value="CANCEL"></td>
+					</tr>
+				</table>
+			</form>
+			<?php
+		}
+		elseif (isset($postvars["wells_checkbox"]))	// added by Marina on August 1, 2005
+		{
+			// Arrays to store coordinates of wells (if multiple selected)
+			$wellRow_ar = array();
+			$wellCol_ar = array();
+			
+			$interWellRow_ar = array();
+			$interWellCol_ar = array();
+			
+			$finalWellRow_ar = array();
+			$finalWellCol_ar = array();
+			
+			$goodRow_ar = array();
+			$goodCol_ar = array();
+
+			$badRow_ar = array();
+			$badCol_ar = array();
+			
+			$reservedRow_ar = array();
+			$reservedCol_ar = array();
+
+			$well_occupied = false;
+
+			foreach( $postvars["wells_checkbox"] as $key => $value )
+			{
+				$pieces = explode( "|", $value );
+				$wellRow_ar[ $key ] = $pieces[ 0 ];	// get the row number of each well
+				$wellCol_ar[ $key ] = $pieces[ 1 ];	// get the column number of each well
+			}
+			
+			$_SESSION["wells_checkbox_tmp"] = $postvars["wells_checkbox"];			
+
+			$bad_tmp_count = 0;
+			$good_tmp_count = 0;
+			$temp_count = 0;
+
+			// -----------------------------------------------
+			// General Property Section of the Modify Function
+			// Updated Oct 12/05 Added by John Paul Lee
+			$general_info_ht = new HT_Class();
+
+			// Feb. 24/10, Marina: CHANGE
+			$prep_gen_check_rs = mysql_query("SELECT p.elementTypeID, p.propertyName FROM PrepElemTypes_tbl p, ContainerTypeAttributes_tbl c WHERE c.containerTypeID='" . $selContType . "' AND c.containerTypeAttributeID=p.elementTypeID AND c.status='ACTIVE' AND p.status='ACTIVE' UNION (SELECT a.`prepElementTypeID`, b.`propertyName` FROM `Prep_Req_tbl` a INNER JOIN `PrepElemTypes_tbl` b ON a.`prepElementTypeID`=b.`elementTypeID` WHERE a.`containerID`='" . $contID . "' AND a.`requirement`='REQ' AND  [...]
+	
+			$req_set = "('";
+			$req_setcount = 0;
+			$general_req_ar = array();
+		
+			while ($prep_gen_check_ar = mysql_fetch_array($prep_gen_check_rs, MYSQL_ASSOC))
+			{
+				$req_setcount++;
+
+				$req_set = $req_set . $prep_gen_check_ar["elementTypeID"] . "','";
+				$general_req_ar[ $prep_gen_check_ar["propertyName"] ] = $prep_gen_check_ar["elementTypeID"];
+			}
+				
+			$req_set = $this->reset_set( $req_setcount, $req_set );
+
+			// Finding actual general properties for container
+			foreach( $goodRow_ar as $wellID_tmp => $wellSpot_tmp )
+			{
+				$general_tmp_ar = array();
+
+				$prep_tmp_ar = $well_info_ht->get($wellID_tmp);
+				$prepID_tmp = $prep_tmp_ar["prepID"];
+				
+				$find_gen_prop_rs = mysql_query("SELECT a.`prepID`, a.`elementTypeID`, a.`value`, b.`propertyName` FROM `PrepElementProp_tbl` a INNER JOIN `PrepElemTypes_tbl` b ON a.`elementTypeID`=b.`elementTypeID` WHERE a.`prepID`='" . $prepID_tmp . "' AND b.`elementTypeID` IN " . $req_set . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'", $conn) or die("FAILURE IN GENERAL PROPERTY SEARCH SQL: " . mysql_error());
+				
+				while( $find_gen_prop_ar = mysql_fetch_array( $find_gen_prop_rs, MYSQL_ASSOC ) )
+				{
+					//$general_tmp_ar["propertyName"] = $find_gen_prop_ar["propertyName"];
+					//$general_tmp_ar["value"] = $find_gen_prop_ar["value"];
+					
+					$general_tmp_ar[ $find_gen_prop_ar["propertyName"] ] = $find_gen_prop_ar["value"];
+					
+				}
+				
+				$general_info_ht->add( $prepID_tmp, $general_tmp_ar );
+			}
+
+			// End section for general property 
+			// -----------------------------------------------
+
+			?><form method=post action="<?php echo $_SERVER["PHP_SELF"] . "?View=7&Mod=" . $contID . ""; ?>">
+			<table style="min-width:100%" border="1" frame="box" rules="all" valign="middle" cellpadding="3">
+				<th colspan="100%" class="detailedView_heading"><?php echo $lfunc_obj->getContainerName($contID); ?>				
+					<BR><span style="font-size:8pt; font-weight:bold; color:red;"><IMG SRC="pictures/new01.gif" ALT="new" WIDTH="35" HEIGHT="20" style="cursor:auto;">You may update multiple wells at once by clicking on the property's column heading and typing its value in the pop-up box.</span>
+				</th>
+				
+				<tr>
+					<td style="font-weight:bold; text-align:center; font-size:7pt; font-weight:bold; color:navy; padding-left:7px; padding-right:7px;">Well</td>
+
+					<td style="font-weight:bold; padding-left:4px; padding-right:4px; text-align:center; font-size:7pt; font-weight:bold; color:navy; white-space:nowrap; cursor:pointer;" onclick="popupWellAttrUpdateForm('OpenFreezer ID');">OpenFreezer ID</td>
+					<?php
+						// 1. Check if this is an isolate active container
+						$lfunc_obj = new Location_Funct_Class();
+						$isoAct_state = $lfunc_obj->isIsoActive( $contID );
+						$_SESSION["isoAct_state"] = $isoAct_state;
+		
+						// Added by Marina on July 25, 2005; MOVED UP HERE ON AUG 31, 2006
+						if ($isoAct_state == "YES")
+						{
+							$isoAct_state = true;
+							$isIsolate_container = true;
+						}
+						else
+						{
+							$isoAct_state = false;
+							$isIsolate_container = false;
+						}
+
+						if ($isIsolate_container) 
+						{
+							?><td style="font-weight:bold; padding-left:4px; padding-right:4px; text-align:center; font-size:7pt; color:navy; cursor:pointer;" onclick="popupWellAttrUpdateForm('Isolate Number');">Isolate Number</td>
+
+							<td width="10%" style="font-weight:bold; text-align:center; font-size:7pt; color:navy; padding-left:7px; padding-right:7px; cursor:pointer;" onclick="checkUncheckAllIsolates();">Current Set Isolate</td><?php
+						}
+					?>
+					<td style="font-weight:bold; text-align:center; font-size:7pt; color:navy; cursor:pointer;" onclick="popupWellAttrUpdateForm('Reference');">Reference</td>
+
+					<td style="font-weight:bold; text-align:center; font-size:7pt; color:navy; width:50px; padding-left:5px; padding-right:5px;cursor:pointer;" onClick="checkUncheckAllFlags();">Flag</td>
+
+					<td style="font-weight:bold; text-align:center; font-size:7pt; color:navy; cursor:pointer;" onclick="popupWellAttrUpdateForm('Comments');">Comments</td>
+					<?php
+						// FIX IT: Updated Oct 12/05
+						// For the general properties of each container
+						foreach( $general_req_ar as $pname => $pid )
+						{
+							echo "<td style=\"font-weight:bold; text-align:center; cursor:pointer; font-size:7pt; color:navy;\" onClick=\"popupWellAttrUpdateForm('" . str_replace("'", "\'", $pname) . "');\">";
+							echo $pname;
+							echo "</td>";
+						}
+					?>
+				</tr>
+			<?php
+
+			foreach ($wellRow_ar as $key => $rowvalue)	// ==> for each <key, value> pair in $wellRow_ar (associative array)
+			{
+				// Check if the well is reserved
+				$check_well_reserved_rs = mysql_query( "SELECT * FROM `Wells_tbl` WHERE `containerID`='" . $contID . "' AND `wellRow`='" . $rowvalue . "' AND `wellCol`='" . $wellCol_ar[$key] . "' AND `status`='ACTIVE' AND `reserved`='TRUE'", $conn) or die("ERROR IN CHECKING WELL SQL STATEMENT: " . mysql_error());
+
+				if ($check_well_reserved_ar = mysql_fetch_array($check_well_reserved_rs, MYSQL_ASSOC))
+				{
+					// Well is reserved
+
+					// if a well is reserved, it cannot be occupied
+					$well_occupied = false;
+
+					// Check to see who reserved it
+					$tmp_creator = $check_well_reserved_ar["creatorID"];
+					
+					// Cannot modify a well reserved by someone else
+					if ($tmp_creator != $currentUserID)
+					{
+						$wellUnavailable = true;
+						$query = "SELECT `description` FROM `Users_tbl` WHERE `userID`='" . $tmp_creator . "' AND `status`='ACTIVE'";
+						$resultset = mysql_query($query, $conn);
+
+						if ($result_ar = mysql_fetch_array($resultset))
+						{
+							// Feb 7, Marina - Use full names instead of aliases
+							$username = $result_ar["description"];
+						}
+						else	// default
+						{
+							// June 17, 2010: Well might be reserved by a DEPd user too!
+							$dep_rs = mysql_query("SELECT `description` FROM `Users_tbl` WHERE `userID`='" . $tmp_creator . "'");
+
+							if ($dep_ar = mysql_fetch_array($dep_rs))
+							{
+								$username = $dep_ar["description"];
+							}
+						}
+
+						$badRow_ar[ $bad_tmp_count ] = $wellRow_ar[ $key ];
+						$badCol_ar[ $bad_tmp_count ] = $wellCol_ar[ $key ];
+						$bad_tmp_count++;
+					}
+					else
+					{
+						$wellUnavailable = false;
+
+						// it's a good row
+						$goodRow_ar[ $good_tmp_count ] = $wellRow_ar[ $key ];
+						$goodCol_ar[ $good_tmp_count ] = $wellCol_ar[ $key ];
+						$good_tmp_count++;
+					}
+				}
+				else	// well not reserved
+				{
+					// Check if the well is in the table but is not reserved
+					$check_well_reserved_rs = mysql_query("SELECT * FROM `Wells_tbl` WHERE `containerID`='" . $contID . "' AND `wellRow`='" . $rowvalue . "' AND `wellCol`='" . $wellCol_ar[ $key ] . "' AND `status`='ACTIVE' AND `reserved`='FALSE'", $conn) or die("ERROR IN CHECKING WELL SQL STATEMENT: " . mysql_error());
+
+					// If found, check if the well is occupied
+					if ($check_well_reserved_ar = mysql_fetch_array($check_well_reserved_rs, MYSQL_ASSOC))
+					{
+						$check_well_occupied_rs = mysql_query( "SELECT b.`prepID`, b.`isolate_pk`, b.`refAvailID`, b.`flag`, b.`comments`, a.`wellID` FROM `Wells_tbl` a INNER JOIN `Prep_tbl` b ON a.`wellID`=b.`wellID` WHERE a.`wellRow`='" . $rowvalue . "' AND a.`wellCol`='" . $wellCol_ar[ $key ] . "' AND a.`containerID`='" . $contID . "' AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'", $conn ) 
+						or die( "ERROR IN CHECKING WELL SQL STATEMENT: " . mysql_error() );
+
+						// If not occupied, may reserve and update it
+						$check_well_occupied_ar = mysql_fetch_array( $check_well_occupied_rs, MYSQL_ASSOC );
+
+						if($check_well_occupied_ar)
+						{
+							$well_occupied = true;
+							$wellUnavailable = false;
+
+							$badRow_ar[ $bad_tmp_count ] = $wellRow_ar[ $key ];
+							$badCol_ar[ $bad_tmp_count ] = $wellCol_ar[ $key ];
+							$bad_tmp_count++;
+						}
+						else
+						{
+							// Update the well's reservation status and creator ID
+							$well_occupied = false;
+							$wellUnavailable = false;
+
+							$result1 = mysql_query("UPDATE `Wells_tbl` SET `reserved`='TRUE' WHERE `containerID`='" . $contID . "' AND `wellRow`='" . $rowvalue . "' AND `wellCol`='" . $wellCol_ar[ $key ] . "' AND `status`='ACTIVE'", $conn);
+
+							$result2 = mysql_query("UPDATE `Wells_tbl` SET `creatorID`='" . $currentUserID . "' WHERE `containerID`='" . $contID . "' AND `wellRow`='" . $rowvalue . "' AND `wellCol`='" . $wellCol_ar[ $key ] . "' AND `status`='ACTIVE'", $conn);	
+
+							$goodRow_ar[ $good_tmp_count ] = $wellRow_ar[ $key ];
+							$goodCol_ar[ $good_tmp_count ] = $wellCol_ar[ $key ];
+							$good_tmp_count++;
+						}
+					}
+					else
+					{
+						// Create a new entry in the Wells table for this well
+						$well_occupied = false;
+						$wellUnavailable = false;
+
+						$well_rs = mysql_query("INSERT INTO `Wells_tbl` (`wellID`, `containerID`, `wellCol`, `wellRow`, `reserved`, `creatorID`) VALUES ('', '" . $contID . "', '" . $wellCol_ar[ $key ] . "', '" . $rowvalue . "', 'TRUE', '" . $currentUserID . "')", $conn) or die( "FAILED TO CREATE WELL LOCATION!" . mysql_error() );	
+						
+						$wellID_ar[ $key ] = mysql_insert_id( $conn );
+
+						$goodRow_ar[ $good_tmp_count ] = $wellRow_ar[ $key ];
+						$goodCol_ar[ $good_tmp_count ] = $wellCol_ar[ $key ];
+						$good_tmp_count++;
+					}
+				}
+				
+				// Store well row and column information for next processing stage
+				$interWellRow_ar[ $key ] = $wellRow_ar[ $key ];
+				$interWellCol_ar[ $key ] = $wellCol_ar[ $key ];
+				
+				$_SESSION["interWellRow_ar"] = $interWellRow_ar;
+				$_SESSION["interWellCol_ar"] = $interWellCol_ar;
+				$_SESSION["badRow_ar"] = $badRow_ar;
+				$_SESSION["badCol_ar"] = $badCol_ar;
+	
+				$_SESSION["goodRow_ar"] = $goodRow_ar;
+				$_SESSION["goodCol_ar"] = $goodCol_ar;
+
+				if ((!$well_occupied) && (!$wellUnavailable))
+				{
+					?>
+					<tr>
+						<td style="display:none"><input type="checkbox" name="wells_release_checkbox[]" id="well_release_checkbox[]" value="NO"></td>
+						<td style="font-weight:bold; color:#104E8B; width:50px; font-size:8pt; text-align:center;"><?php echo $lfunc_obj->getLetterRow($rowvalue) . ":" . $wellCol_ar[$key]?></td>
+
+						<td name="limsID_td[]" style="padding-left:7px;"><input type="text" size="7" class="locationText" name="well_LIMSID_field[]" value="" onKeyPress="return disableEnterKey(event);"></td><?php
+
+						if ($isIsolate_container)
+						{
+							echo "<input type=\"hidden\" name=\"well_limsid_isoAct_hidden\" value=\"YES\">\n";	
+							
+							?><td name="isoNum_td[]"><input type="text" class="locationText" size="5" style="padding-left:5px; padding-right:5px;" onKeyPress="return disableEnterKey(event);" name="well_isoNum<?php echo $temp_count; ?>_textfield" id="well_isoNum<?php echo $temp_count; ?>_textfield" value=""></td>
+
+							<td style="text-align:center;"><input type="checkbox" name="well_beingUsed<?php echo $temp_count; ?>_checkbox" id="well_beingUsed<?php echo $temp_count; ?>_checkbox" value="YES"></td>
+							<?php
+						}
+
+					?><td name="Reference_td[]"><input type="text" class="locationText" size="12" style="padding-left:5px; padding-right:5px;" onKeyPress="return disableEnterKey(event);" name="well_refAvail_text[]" value=" "></td>
+
+					<td style="text-align:center;"><input type="checkbox" name="well_flag<?php echo $temp_count; ?>_checkbox" value="YES"></td>
+
+					<td  name="Comments_td[]"><input type="text" class="locationText" size="20" style="padding-left:5px; padding-right:5px;" onKeyPress="return disableEnterKey(event);" name="well_comments_text[]" value=""></td><?php
+
+					// UPDATED: Oct 12/05
+					// Added by: John Paul Lee
+					// Re-integration of general properties that was removed.
+					foreach( $general_req_ar as $pname => $pid )
+					{
+						echo "<td name=\"" . $pname . "_td[]\">";
+						$general_tmp_ar = $general_info_ht->get( $prepID_tmp );
+						echo "<input type=\"text\" class=\"locationText\" style=\"padding-left:5px; padding-right:5px;\" onKeyPress=\"return disableEnterKey(event);\" name=\"well_mod_general" . $pid . "_text[]\" value=\"";
+						echo $general_tmp_ar[ $pname ];
+						echo "\">";
+						echo "</td>";
+					}
+					?>
+					</tr>
+					<?php
+
+					$temp_count++;
+					$submit_btn = true;
+				}
+				else
+				{
+					if ($well_occupied)
+					{
+						echo "<tr>";
+
+						echo "<TD style=\"width:15%; font-weight:bold; font-size:8pt; color:red; text-align:center;\">" . $lfunc_obj->getLetterRow($wellRow_ar[$key]) . ":" . $wellCol_ar[$key] . "</TD>";
+
+						echo "<td colspan=\"100%\" style=\"color:red; font-weight:bold; font-size:7pt; padding-left:5px;\">Well " . $lfunc_obj->getLetterRow($wellRow_ar[$key]) . ":" . $wellCol_ar[$key] . " is occupied. Please select a different well to populate.</td></tr>";
+					}
+					if ($wellUnavailable)
+					{
+						echo "<tr>";
+						
+						echo "<TD style=\"width:100px; font-weight:bold; font-size:8pt; color:red; padding-left:10px; padding-right:10px;\">" . $lfunc_obj->getLetterRow($wellRow_ar[$key]) . ":" . $wellCol_ar[$key] . "</TD>";
+
+						echo "<td colspan=\"100%\" style=\"color:red; font-weight:bold; font-size:7pt; padding-left:5px;\">Well " . $lfunc_obj->getLetterRow($wellRow_ar[$key]) . ":" . $wellCol_ar[$key] . " has been reserved by " . $username . ".  Please select a different well to populate.</td></tr>";
+					}
+				}
+			}	// end foreach
+
+			?><TR><TD colspan="100%" style="padding-top:18px; padding-left:10px; color:#0101DE; font-size:9pt;"><B><U>Note</U>: Only preps of the following reagent types may be stored in this container; other prep types are not allowed:</B><BR>
+
+			<TABLE style="width:200px;" cellpadding="2">
+				<TR>
+					<TD style="text-decoration:underline; padding-top:10px; padding-left:5px; font-size:9pt; color:green; font-weight:bold;">Name</TD>
+					<TD style="text-decoration:underline; color:green; padding-top:10px; font-size:9pt; font-weight:bold;">Prefix</TD>
+				</TR>
+				<?php
+	
+				$allowed_r_types = $lfunc_obj->getContainerReagentTypes($selContType);
+	
+				foreach ($allowed_r_types as $key => $value)
+				{
+					echo "<TR>";
+						echo "<TD style=\"padding-left:5px; color:#0202DD;\">" . $_SESSION["ReagentType_ID_Name"][$value] . "</TD>";
+						echo "<TD style=\"padding-left:5px; color:#0202DD;\">" . $_SESSION["ReagentType_ID_Prefix"][$value] . "</TD>";
+	
+						echo "<INPUT TYPE=\"hidden\" ID=\"rTypes_allowed[]\" NAME=\"allowed_prep_prefixes[]\" VALUE=\"" . $_SESSION["ReagentType_ID_Prefix"][$value] . "\">";
+					echo "</TR>";
+				}
+	
+				// list of ALL prefixes
+				foreach ($_SESSION["ReagentType_ID_Prefix"] as $rTypeID => $rTypePrefix)
+				{
+					// Feb. 9, 2010
+					echo "<INPUT TYPE=\"hidden\" NAME=\"all_prefixes[]\" value=\"" . $rTypePrefix . "\">";
+				}
+
+			?></TABLE></TD></TR><?php
+
+			if ($submit_btn == true)
+			{
+				// Output the submit button at the bottom of the table
+				?>
+				<tr>
+					<td colspan="100%" style="padding-left:25px; text-align:left;"><input type="submit" name="well_limsid_submit_button" value="SUBMIT" onClick="return checkPrepType() && checkExistingPrepID();">  <input type="submit" name="well_create_cancel_button" value="CANCEL"></td>
+				</tr>
+				</table>
+				</form>
+				<?php
+			}
+			else
+			{
+				// Output an OK button
+				// (or Javascript - think about it)
+				?>
+				<tr>
+					<td colspan="100%"><FONT SIZE="4"><B><CENTER><input type="submit" name="mod_empty_well_cancel" value="OK"></CENTER></B></FONT></td>
+				</tr>
+				</table>
+				</form>
+				<?php
+			}
+		}	// end if isset wells_checkbox
+		else
+		{
+			if (!$error_state)
+			{
+				?><CENTER><FORM METHOD=POST ACTION="<?php echo $_SERVER["PHP_SELF"] . "?View=7&Mod=" . $contID . ""; ?>">
+				    <P><B>No well has been selected.  Please select a well to populate.</B><BR><BR>		
+				    <INPUT TYPE="submit" name="mod_empty_well_cancel" value="OK">
+				</FORM></CENTER>
+				<?php
+				
+
+				return false;
+			}
+		}
+
+		unset( $postvars["wells_checkbox"], $count_tmp, $_SESSION["well_create_error_msg"]);
+		return true;
+	}
+
+
+	/**
+	 * Process first stage of well creation (adding a prep to an empty well)
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param Array $postvars
+	 * @param INT $contID
+	 *
+	 * @return boolean TRUE on successful creation, FALSE on error
+	*/
+	function process_firstStage($postvars, $contID)
+	{
+		global $conn;
+
+		$gfunc_obj = new generalFunc_Class();
+		$lfunc_obj = new Location_Funct_Class();
+
+		$selContTypeName = $lfunc_obj->getContainerGroupName($contID);
+		$selContType = $_SESSION["Container_Name_ID"][$selContTypeName];
+
+		// Get user info
+		if( isset( $_SESSION["userinfo"] ) )
+		{
+			$currentUserID = $_SESSION["userinfo"]->getUserID();
+			$currUserCategory = $_SESSION["userinfo"]->getCategory();
+			$userProjects = getUserProjectsByRole($currentUserID, 'Writer');
+		}
+
+		$wellID_ar = array();
+		$isoAct_state = false;		
+		$temp_count = 0;
+		$tmp_count = 0;
+
+		$prep_gen_check_rs = mysql_query("SELECT p.elementTypeID, p.propertyName FROM PrepElemTypes_tbl p, ContainerTypeAttributes_tbl c WHERE c.containerTypeID='" . $selContType . "' AND c.containerTypeAttributeID=p.elementTypeID AND c.status='ACTIVE' AND p.status='ACTIVE' UNION (SELECT a.`prepElementTypeID`, b.`propertyName` FROM `Prep_Req_tbl` a INNER JOIN `PrepElemTypes_tbl` b ON a.`prepElementTypeID`=b.`elementTypeID` WHERE a.`containerID`='" . $contID . "' AND a.`requirement`='REQ' AND a [...]
+
+		$general_req_ar = array();
+			
+		while( $prep_gen_check_ar = mysql_fetch_array( $prep_gen_check_rs, MYSQL_ASSOC ) )
+		{
+			$general_req_ar[ $prep_gen_check_ar["propertyName"] ] = $prep_gen_check_ar["elementTypeID"];		
+		}
+
+		if( $postvars["well_limsid_isoAct_hidden"] == "YES" )
+		{
+			$isoAct_state = true;
+		}
+
+		// Sept. 10/07: Check project ID of input reagents.  Do not proceed until ALL input values are valid - else get 'well occupied' errors if one well gets saved and other(s) don't
+		foreach ($postvars["well_LIMSID_field"] as $key => $value)
+		{
+			$tmp_lims_id = $gfunc_obj->get_rid($value);
+			$projectID = getReagentProjectID($tmp_lims_id);
+
+			if (($tmp_lims_id > 0) && ($currUserCategory != $_SESSION["userCategoryNames"]["Admin"]) && !in_array($projectID, $userProjects))
+			{
+				return false;
+			}
+		}
+
+		// Find the `wellID` of each well submitted
+		foreach ($postvars["well_LIMSID_field"] as $key => $value)
+		{
+			if (strlen(trim($value)) > 0)
+			{
+				$query = "SELECT * FROM `Wells_tbl` WHERE `containerID`='" . $contID . "' "
+				. "AND `wellCol`='" . $_SESSION["goodCol_ar"][ $key ] . "' "
+				. "AND `wellRow`='" . $_SESSION["goodRow_ar"][ $key ] . "' "
+				. "AND `status`='ACTIVE'";
+				
+				$well_tmp_rs = mysql_query( $query, $conn ) or die( "FAILURE IN process_firstStage(): " . mysql_error() );
+
+				if ($well_tmp_ar = mysql_fetch_array($well_tmp_rs, MYSQL_ASSOC))
+				{
+					$wellID_ar[$key] = $well_tmp_ar["wellID"];
+				}
+				else
+				{
+					// Added by Marina on Sept 29/05 to account for occupied or reserved wells
+
+					// Look for it in the "bad" row and col arrays
+					$q2 = "SELECT * FROM `Wells_tbl` WHERE `containerID`='" . $contID . "' AND `wellCol`='" . $_SESSION["badCol_ar"][ $key ] . "' AND `wellRow`='" . $_SESSION["badRow_ar"][ $key ] . "' AND `status`='ACTIVE'";
+
+					$bad_wells_tmp_rs = mysql_query($q2, $conn) or die("FAILURE IN process_firstStage(): " . mysql_error());
+					
+					if ($bad_wells_tmp_ar = mysql_fetch_array($bad_wells_tmp_rs, MYSQL_ASSOC))
+					{
+						continue;
+					}
+					else
+					{
+						echo "Cannot locate a valid ID of one or all of the wells submitted <br>";
+						return false;
+					}
+				}
+			}
+			else
+			{}
+
+			$reagentTypeID_tmp = 0;
+			$groupID_tmp = 0;
+			$isolate_tmp = 0;
+
+			// Finds isolate number if this is an isolate active container
+			if( $isoAct_state )
+			{
+				$isolate_tmp = $_POST["well_isoNum" . $tmp_count . "_textfield"];
+
+				if (isset($_POST["well_beingUsed" . $tmp_count . "_checkbox"]))
+				{
+					$beingUsed = "YES";
+				}
+				else
+				{
+					$beingUsed = "NO";
+				}
+			}
+
+			// Finds the given reagent Type and group ID
+			// Modified June 8/09
+			$reagentTypeID_tmp = $gfunc_obj->get_typeID($value);
+			$groupID_tmp = $gfunc_obj->get_groupID($value);
+
+			// Finds the reagent ID associated with the inputted LIMS ID
+			$reagentID_rs = mysql_query("SELECT * FROM Reagents_tbl WHERE reagentTypeID='" . $reagentTypeID_tmp . "' " . "AND `groupID`='" . $groupID_tmp . "' AND `status`='ACTIVE'", $conn) or die("FAILURE IN SQL: " . mysql_error());
+
+			while ($reagentID_ar = mysql_fetch_array($reagentID_rs, MYSQL_ASSOC))
+			{
+				$expID_tmp = $this->backChecking_LIMSID_Existance($reagentID_ar["reagentID"]);
+
+				if ($expID_tmp <= 0)
+				{
+					// reagentID does not exist in experiment side of database
+					$expInsert_rs = mysql_query("INSERT INTO `Experiment_tbl` (`expID`, `reagentID`, `status`) VALUES ('', '" . $reagentID_ar["reagentID"] . "','ACTIVE')", $conn) or die( "FAILURE IN SQL EXP INSERT SQL: " . mysql_error());
+
+					$expID_tmp = mysql_insert_id($conn);
+				}
+				
+				// Check isolate
+				$isoCheck_rs = mysql_query("SELECT * FROM `Isolate_tbl` WHERE `expID`='" . $expID_tmp . "' AND `isolateNumber`='" . $isolate_tmp . "' AND `status`='ACTIVE'", $conn) or die("FAILURE IN: Location_well_Class.process_firststage(1): " . mysql_error());
+
+				if ($isoCheck_ar = mysql_fetch_array($isoCheck_rs, MYSQL_ASSOC))
+				{
+					$isoID_tmp = $isoCheck_ar["isolate_pk"];
+					
+					// if you're creating an isolate that exists in the db, but want to make it beingUsed
+					// e.g. there is a V24-1 in the db, but it's not beingUsed, and you want to create another V24-1 and make it beingUsed
+					if (!($this->backChecking_beingUsed_duplicate($expID_tmp, $isoID_tmp, $beingUsed)) && ($beingUsed == "YES"))
+					{
+						mysql_query("UPDATE `Isolate_tbl` SET `beingUsed`='YES' WHERE `isolate_pk`='" . $isoID_tmp . "'", $conn);
+					}
+				}
+				else
+				{
+					if ($isoAct_state)
+					{
+						$isoInsert_rs = mysql_query("INSERT INTO `Isolate_tbl` (`isolate_pk`, `expID`, `isolateNumber`, `beingUsed`) " . "VALUES ('', '" . $expID_tmp . "','" . $isolate_tmp . "','NO')", $conn);
+
+						$isoID_tmp = mysql_insert_id( $conn );
+
+						if (!($this->backChecking_beingUsed_duplicate($expID_tmp, $isoID_tmp, $beingUsed)) && ($beingUsed == "YES"))
+						{
+							mysql_query("UPDATE `Isolate_tbl` SET `beingUsed`='YES' WHERE `isolate_pk`='" . $isoID_tmp . "'", $conn);
+						}
+					}
+					else
+					{
+						$isoInsert_rs = mysql_query( "INSERT INTO `Isolate_tbl` (`isolate_pk`, `expID`, `isolateNumber`, `beingUsed`) " . "VALUES ('', '" . $expID_tmp . "','0','NO')", $conn ) 
+						or die( "FAILURE IN Location_well_Class.process_firststage(2):: " . mysql_error() );
+
+						$isoID_tmp = mysql_insert_id( $conn );
+					}
+				}
+
+				$query =  "SELECT * FROM `Prep_tbl` WHERE `wellID`='" . $wellID_ar[ $key ] . "' AND `status`='ACTIVE'";
+
+				$prep_location_check_rs = mysql_query($query, $conn) or die("FAILURE IN Location_well_Class.process_firststage(3):: " . mysql_error());
+
+				if ($prep_location_check_ar = mysql_fetch_array($prep_location_check_rs, MYSQL_ASSOC))
+				{
+					// removed June 7, 2011 - can't remember if this is a debug statement or part of the code
+					//echo "<B>This location is already occupied by prep #" . $prep_location_check_ar[$prepID] . "</B><br>";
+
+					return false;
+				}
+				else
+				{
+					$query = "INSERT INTO `Prep_tbl` (`prepID`, `isolate_pk`, `refAvailID`, `wellID`, `flag`, `comments`, `status`) VALUES ('', '" . $isoID_tmp . "', '" . $_POST["well_refAvail_text"][$tmp_count] . "', '" . $wellID_ar[$key] . "', '" . $_POST["well_flag" . $tmp_count . "_checkbox"] . "', '" . $_POST["well_comments_text"][$tmp_count] . "', 'ACTIVE')";
+					
+					$prepInsert_rs = mysql_query($query, $conn) or die("FAILURE IN Location_well_Class.process_firststage(4):: " . mysql_error());
+				
+					$prepID_tmp = mysql_insert_id( $conn ); // Added: Oct 13/05 - Holds the new prepID of the newly inserted information, used to link the general properties
+					
+					// Unreserve the well
+					$query = "UPDATE `Wells_tbl` SET `reserved`='FALSE' WHERE `wellID`='" . $wellID_ar[ $key ] . "' AND `status`='ACTIVE'";
+					
+					$unreserve_result = mysql_query($query, $conn) or die("FAILURE IN Location_well_Class.process_firststage(4):: " . mysql_error());
+					
+					foreach($general_req_ar as $pname => $pid)
+					{
+						$current_general_value_tmp = $_POST["well_mod_general" . $pid . "_text"][$tmp_count];
+				
+						if ($current_general_value_tmp != $general_tmp_ar[$pname])
+						{
+							// check to see if it already exists
+							$check_general_rs = mysql_query("SELECT * FROM `PrepElementProp_tbl` WHERE `elementTypeID`='" . $pid . "' AND `prepID`='" . $prepID_tmp . "' AND `status`='ACTIVE'", $conn) or die( "FAILURE IN Location_Well_Class.process_modify(7): " . mysql_error());
+							
+							if ($check_general_ar = mysql_fetch_array($check_general_rs, MYSQL_ASSOC))
+							{
+								//echo "Entered update of general property section<BR>";
+								//echo "prepID: " . $prepID_tmp . " -- elementtypeID: " . $pid . " -- value : " . $_POST["well_mod_general" . $pid . "_text"][ $input_count ] . "<BR>";
+								// If the property type already exists in the database, modify the existing value
+								mysql_query( "UPDATE `PrepElementProp_tbl` "
+										. "SET `value`='" . /*addslashes(*/ $current_general_value_tmp /*)*/ . "' "
+										. "WHERE `prepID`='" . $prepID_tmp . "' "
+										. "AND `elementTypeID`='" . $pid . "' "
+										. "AND `status`='ACTIVE' ", $conn )
+										or die( "FAILIURE IN Location_Well_Class.process_modify(8): " . mysql_error() );
+							}
+							else
+							{
+								// If no property type exists, add as new!
+								//echo "Entered INSERT of general property section<BR>";
+								//echo "prepID: " . $prepID_tmp . " -- elementtypeID: " . $pid . " -- value : " . $_POST["well_mod_general" . $pid . "_text"][ $input_count ] . "<BR>";
+								
+								mysql_query( "INSERT INTO `PrepElementProp_tbl` (`prepPropID`, `prepID`, `elementTypeID`,`value`, `status`) VALUES ('', '" . $prepID_tmp . "', '" . $pid . "', '" . $current_general_value_tmp /*)*/ . "', 'ACTIVE')", $conn) or die( "FAILIURE IN Location_Well_Class.process_modify(9): " . mysql_error());
+							}
+						}
+					}
+
+					// End of General Property Insert
+					
+					if ($unreserve_result == false)
+					{
+						echo "Failed to unreserve well " . $wellID_ar[ $key ] . "<br>";
+						return false;
+					}
+				}
+			}
+
+			$tmp_count++;
+		}
+		
+		return true;	
+	}
+	
+	/**
+	 * First step in unreserving wells, takes user input and passes on to processing function (not actively called anymore, removed 'unreserve' button, but don't delete this function, may be of use)
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param Array $postvars
+	 * @param INT $contID
+	 *
+	 * @return boolean TRUE on success, FALSE on error
+	*/
+	function unreserve_wells ($postvars, $contID)
+	{
+		global $conn;
+
+		$lfunc_obj = new Location_Funct_Class();
+		$submit_btn = false;
+
+		if( isset( $_SESSION["userinfo"] ) )
+		{
+			$currentUserID = $_SESSION["userinfo"]->getUserID();
+		}
+
+		if (!isset($postvars["wells_checkbox"] ))
+		{
+			?><CENTER><FORM METHOD=POST ACTION="<?php echo $_SERVER["PHP_SELF"] . "?View=7&Mod=" . $contID . ""; ?>">
+			    <P><B><FONT SIZE="" COLOR="#FF0000">No well has been selected!  Please select a well to unreserve.</FONT></B><BR><BR>
+			    <INPUT TYPE="submit" name="mod_empty_well_cancel" value="OK">
+			</FORM></CENTER><?php
+
+			return false;
+		}
+		else
+		{
+			foreach ($postvars["wells_checkbox"] as $key => $value)
+			{
+				$pieces = explode( "|", $value );
+				$wellRow_ar[ $key ] = $pieces[ 0 ];	// get the row numbers of all the wells selected
+				$wellCol_ar[ $key ] = $pieces[ 1 ];	// get the column numbers of all the wells selected
+
+				// set for next stage
+				$_SESSION["wells_checkbox_tmp"] = $postvars["wells_checkbox"];
+			}
+
+			?><CENTER><FORM METHOD=POST ACTION="<?php echo $_SERVER["PHP_SELF"] . "?View=7&Mod=" . $contID . ""; ?>"><P><B><FONT SIZE="3">Are you sure you want to cancel your reservation for the well(s) selected?</FONT></B><BR><BR><?php
+
+			foreach ($wellRow_ar as $key => $rowvalue)
+			{
+				// Check if the well is occupied; in that case cannot unreserve
+				$q1 = "SELECT b.`prepID`, b.`isolate_pk`, b.`refAvailID`, b.`flag`, b.`comments`, a.`wellID` FROM `Wells_tbl` a INNER JOIN `Prep_tbl` b ON a.`wellID`=b.`wellID` WHERE a.`wellRow`='" . $rowvalue . "' AND a.`wellCol`='" . $wellCol_ar[$key] . "' AND a.`containerID`='" . $contID . "' AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'";
+
+				$check_well_occupied_rs = mysql_query($q1, $conn) or die("ERROR IN CHECKING WELL SQL STATEMENT: " . mysql_error());
+
+				if ($check_well_occupied_ar = mysql_fetch_array($check_well_occupied_rs, MYSQL_ASSOC))
+				{
+					// change this (commented sept 3/10)
+					echo "<B><CENTER><FONT COLOR=\"#FF0000\">Well " . $lfunc_obj->getLetterRow($rowvalue) . "" . $wellCol_ar[$key] . " is occupied! It cannot be unreserved.</FONT></CENTER></B><BR>";
+				}
+				else
+				{
+					// Check that the well has indeed been reserved
+					$check_well_reserved_rs = mysql_query("SELECT * FROM `Wells_tbl` WHERE `containerID`='" . $contID . "' AND `wellRow` = '" . $rowvalue . "' AND `wellCol` = '" . $wellCol_ar[$key] . "' AND `reserved`='TRUE' AND `status`='ACTIVE'", $conn) or die ("Failure checking well reserved status: " . mysql_error);
+
+					if ($check_well_reserved_ar = mysql_fetch_array($check_well_reserved_rs, MYSQL_ASSOC))
+					{
+						// Check that it has been reserved by the current user, i.e. creatorID = current user ID
+						$creatorID_tmp = $check_well_reserved_ar["creatorID"];
+
+						if ($creatorID_tmp == $currentUserID)
+						{
+							// Confirm unreserve:
+
+							$submit_btn = true;
+						}
+						else
+						{
+							// Cannot unreserve a well that has been reserved by someone other than yourself
+							if ($creatorID_tmp == 0)
+							{
+								$username = "Administrator";
+							}
+							else
+							{
+								$query = "SELECT `description` FROM Users_tbl WHERE `userID`='" . $creatorID_tmp . "' AND `status`='ACTIVE'";	// use full names
+								$resultset = mysql_query($query, $conn);
+
+								if ($result_ar = mysql_fetch_array($resultset))
+								{
+									$username = $result_ar["description"];
+								}
+							}
+
+							// comment sept 3/10: change this
+							echo "<FONT COLOR=\"#FF0000\"><CENTER><B>Well " . $lfunc_obj->getLetterRow($rowvalue) . "" . $wellCol_ar[$key] . " has been reserved by " . $username . ".  Please contact him/her to unreserve this well.</B></CENTER></FONT><BR>";
+						}
+					}
+					else	// well is not reserved
+					{
+						echo "<FONT COLOR=\"#FF0000\"><B><CENTER>Well " . $lfunc_obj->getLetterRow($rowvalue) . "" . $wellCol_ar[$key] . " is not reserved!</CENTER></B></FONT><BR>";
+					}
+				}
+			}
+
+			if ($submit_btn)
+			{
+				?><INPUT TYPE="submit" name="well_unreserve_submit_button" value="Unreserve">
+				    <INPUT TYPE="submit" name="mod_empty_well_cancel" value="Cancel"><BR><?php
+			}
+			else
+			{
+				?><INPUT TYPE="submit" name="mod_empty_well_cancel" value="OK"><?php
+			}
+
+			?></FORM></CENTER>
+			<?php	
+		}
+
+		return true;
+	}
+
+	/**
+	 * Process well unreserve.  Looks like it's been deleted in Location.php, but keep it, may need later.
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param Array $session_vars
+	 * @param INT $contID
+	 *
+	 * @return boolean TRUE on success, FALSE on error
+	*/
+	function process_unreserve($session_vars, $contID)
+	{
+		global $conn;
+		$lfunc_obj = new Location_Funct_Class();
+
+		if (isset($session_vars))
+		{
+			foreach ($_SESSION["wells_checkbox_tmp"] as $key => $value)
+			{
+				$pieces = explode( "|", $value );
+				$wellRow_ar[ $key ] = $pieces[ 0 ];		// get the row numbers of all the wells selected
+				$wellCol_ar[ $key ] = $pieces[ 1 ];		// get the column numbers of all the wells selected
+			}
+		}
+
+		foreach( $wellRow_ar as $key => $rowvalue )	
+		{	
+			$query1 = "UPDATE `Wells_tbl` SET `reserved`='FALSE' WHERE `containerID`='" . $contID . "' AND `wellRow` = '" . $rowvalue . "' AND `wellCol` = '" . $wellCol_ar[$key] . "' AND `reserved`='TRUE' AND `status`='ACTIVE'";
+
+			$result1 = mysql_query($query1, $conn) or die ("Failure unreserving well: ". mysql_error);
+				
+			if ($result1 == false)
+			{
+				echo "Failed to unreserve well " . $rowvalue . ":" . $wellCol_ar[$key] . "<br>";
+				return false;
+			}
+
+			$query2 = "UPDATE `Wells_tbl` SET `creatorID`='0' WHERE `containerID`='" . $contID . "' AND `wellRow` = '" . $rowvalue . "' AND `wellCol` = '" . $wellCol_ar[$key] . "'  AND `status`='ACTIVE'";
+
+			$result2 = mysql_query($query2, $conn) or die ("Failure unsetting creator ID: ". mysql_error);
+			
+			if ($result2 == false)
+			{
+				echo "Failed to reset creator ID for well " . $rowvalue . ":" . $wellCol_ar[$key] . "<br>";
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	/**
+	 * Step 1 in well deletion - redirect to confirmation page and pass to processing function.
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param Array $session_vars
+	 * @param INT $contID
+	 *
+	 * @return boolean TRUE on success, FALSE on error
+	*/
+	function delete_wells($postvars, $contID)
+	{
+		global $conn;
+
+		$lfunc_obj = new Location_Funct_Class();
+		$submit_btn = false;
+
+		if (isset($_SESSION["userinfo"]))
+		{
+			$currentUserID = $_SESSION["userinfo"]->getUserID();
+		}
+
+		if (!isset($postvars["wells_checkbox"]))
+		{
+			?><CENTER><FORM METHOD=POST ACTION="<?php echo $_SERVER["PHP_SELF"] . "?View=7&Mod=" . $contID . ""; ?>">
+			    <P><B><FONT size="3" COLOR="#FF0000">No well has been selected!  Please select a well for deletion.</FONT></B><BR><BR><BR>    <INPUT TYPE="submit" name="mod_empty_well_cancel" value="OK"></FORM></CENTER><?php
+
+			return false;
+		}
+		else
+		{
+			?><CENTER><FORM METHOD=POST ACTION="<?php echo $_SERVER["PHP_SELF"] . "?View=7&Mod=" . $contID . ""; ?>"><BR><SPAN style="font-size:13pt; font-weight:bold;">Are you sure you want to delete the well(s) selected?</span></CENTER><BR><?php
+
+echo "<SPAN class=\"linkShow\" style=\"font-size:8pt; margin-left:30px;\" onClick=\"checkAll('wells_checkbox_tmp', [])\">Check All</SPAN>";
+echo "<SPAN class=\"linkShow\" style=\"font-size:8pt; margin-left:10px;\" onClick=\"uncheckAll('wells_checkbox_tmp', [])\">Uncheck All</SPAN>";
+
+echo "<BR><BR><table style=\"margin-left:20px;\" cellpadding=\"4\" cellspacing=\"4\" border=\"1\" frame=\"box\" rules=\"all\">";
+
+echo "<TR>";
+echo "<TD></TD>";
+echo "<TD style=\"text-align:center; white-space:nowrap; font-size:9pt; font-weight:bold; color:navy; padding-left:7px; padding-right:7px;\">Well</TD>";
+echo "<TD style=\"text-align:center; white-space:nowrap; font-size:9pt; font-weight:bold; color:navy; padding-left:7px; padding-right:7px;\">Reagent ID</TD>";
+echo "<TD style=\"text-align:center; white-space:nowrap; font-size:9pt; font-weight:bold; color:navy; padding-left:7px; padding-right:7px;\">Reference</TD>";
+echo "<TD style=\"text-align:center; white-space:nowrap; font-size:9pt; font-weight:bold; color:navy; padding-left:7px; padding-right:7px;\">Comments</TD>";
+echo "</TR>";
+
+			foreach ($postvars["wells_checkbox"] as $key => $value)
+			{
+				$pieces = explode( "|", $value );
+				$wellRow_ar[ $key ] = $pieces[ 0 ];		// get the row numbers of all the wells selected
+				$wellCol_ar[ $key ] = $pieces[ 1 ];		// get the column numbers of all the wells selected
+
+				// set for next stage
+				$_SESSION["wells_checkbox_tmp"] = $postvars["wells_checkbox"];
+			}
+
+			foreach ($wellRow_ar as $key => $rowvalue)
+			{
+				// Check if the well is occupied
+//				$q1 = "SELECT b.`prepID`, b.`isolate_pk`, b.`refAvailID`, b.`flag`, b.`comments`, a.`wellID` FROM `Wells_tbl` a, `Prep_tbl` b WHERE a.`wellID`=b.`wellID` AND a.`wellRow`='" . $rowvalue . "' AND a.`wellCol`='" . $wellCol_ar[$key] . "' AND a.`containerID`='" . $contID . "' AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'";
+				
+				// Update May 10, 2011: show the numbers/reagent IDs of the selected wells and let user cancel creation of some if needed
+				$q1 = "SELECT b.prepID, b.isolate_pk, b.refAvailID, b.flag, b.comments, a.wellID, i.isolateNumber, e.reagentID, r.reagentTypeID, r.groupID FROM Wells_tbl a, Prep_tbl b, Isolate_tbl i, Experiment_tbl e, Reagents_tbl r WHERE a.`wellID`=b.`wellID` AND a.`wellRow`='" . $rowvalue . "' AND a.`wellCol`='" . $wellCol_ar[$key] . "' AND a.`containerID`='" . $contID . "' AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND i.isolate_pk=b.isolate_pk AND e.expID=i.expID AND i.status='ACTIVE' AND e [...]
+
+				//	echo $q1;
+
+				$check_well_occupied_rs = mysql_query($q1, $conn) or die("ERROR IN CHECKING WELL SQL STATEMENT: " . mysql_error());
+
+				if ($check_well_occupied_ar = mysql_fetch_array($check_well_occupied_rs, MYSQL_ASSOC))
+				{
+					$submit_btn = true;
+
+//					print_r($check_well_occupied_ar);
+
+					if ($check_well_occupied_ar["flag"] == "YES")
+						$color = "#FF0000";
+					else
+						$color = "";
+
+					echo "<TR>";
+						echo "<TD style=\"color:" . $color . "; width:35px; text-align:center;\">";
+							echo "<INPUT TYPE=\"checkbox\" CHECKED NAME=\"wells_checkbox_tmp[]\" VALUE=\"" . $lfunc_obj->getLetterRow($rowvalue) . "|" . $wellCol_ar[$key] . "\">  ";
+						echo "</TD>";
+
+						echo "<TD style=\"color:" . $color . "; width:50px; text-align:center;\">";
+							echo $lfunc_obj->getLetterRow($rowvalue) . ":" . $wellCol_ar[$key];
+						echo "</TD>";
+
+						echo "<TD style=\"color:" . $color . "; width:50px;\">";
+							echo $_SESSION["ReagentType_ID_Prefix"][$check_well_occupied_ar["reagentTypeID"]] . $check_well_occupied_ar["groupID"];
+
+							if ($check_well_occupied_ar["isolateNumber"] && $check_well_occupied_ar["isolateNumber"] != "0")
+							{
+								echo "-";
+								echo $check_well_occupied_ar["isolateNumber"];
+							}
+						echo "</TD>";
+
+						echo "<TD style=\"color:" . $color . "; width:auto;\">";
+							echo $check_well_occupied_ar["refAvailID"];
+						echo "</TD>";
+
+						echo "<TD style=\"color:" . $color . "; width:auto;\">";
+							echo $check_well_occupied_ar["comments"];
+						echo "</TD>";
+
+					echo "</TR>";
+				}
+				else
+				{
+					// check if the well is reserved
+					$check_well_reserved_rs = mysql_query("SELECT * FROM `Wells_tbl` WHERE `containerID`='" . $contID . "' AND `wellRow` = '" . $rowvalue . "' AND `wellCol` = '" . $wellCol_ar[$key] . "' AND `reserved`='TRUE' AND `status`='ACTIVE'", $conn) or die ("Failure checking well reserved status: " . mysql_error);
+
+					// if yes, check who reserved it
+					if ($check_well_reserved_ar = mysql_fetch_array($check_well_reserved_rs, MYSQL_ASSOC))
+					{
+						$creatorID_tmp = $check_well_reserved_ar["creatorID"];
+
+						// if you, then delete the well
+						if ($creatorID_tmp == $currentUserID)
+						{
+							echo "<TR>";
+								echo "<TD style=\"color:navy; width:35px; text-align:center;\">";
+									echo "<INPUT TYPE=\"checkbox\" CHECKED NAME=\"wells_checkbox_tmp[]\" VALUE=\"" . $lfunc_obj->getLetterRow($rowvalue) . "|" . $wellCol_ar[$key] . "\">  ";
+								echo "</TD>";
+
+								echo "<TD style=\"color:navy;\" colspan=\"100%;\">";
+									echo "You have reserved well " . $lfunc_obj->getLetterRow($wellRow_ar[$key]) . ":" . $wellCol_ar[$key] . ".  Deletion will release the reservation. Uncheck if you wish to keep the well reserved.";
+								echo "</TD>";
+							echo "</TR>";
+
+							$submit_btn = true;
+						}
+						else
+						{
+							// otherwise, find out who reserved this well and notify the user
+							if ($creatorID_tmp == 0)
+							{
+								$username = "Administrator";
+							}
+							else
+							{
+								$query = "SELECT `description` FROM Users_tbl WHERE `userID`='" . $creatorID_tmp . "' AND `status`='ACTIVE'";
+								$resultset = mysql_query($query, $conn);
+
+								if ($result_ar = mysql_fetch_array($resultset))
+								{
+									$username = $result_ar["description"];
+								}
+							}
+
+							echo "<TR>";
+								echo "<TD colspan=\"100%;\" style=\"color:#FF0000;\">";
+									echo "Well " . $lfunc_obj->getLetterRow($wellRow_ar[$key]) . "" . $wellCol_ar[$key] . " has been reserved by " . $username . ".  Please contact him/her to delete this well.";
+								echo "</TD>";
+							echo "</TR>";
+						}
+					}
+					else
+					{
+						// empty, unreserved well
+						echo "<TR>";
+							echo "<TD colspan=\"100%;\" style=\"color:#FF0000;\">";
+								echo "Well " . $lfunc_obj->getLetterRow($wellRow_ar[$key]) . "" . $wellCol_ar[$key] . " is empty.";
+							echo "</TD>";
+						echo "</TR>";
+					}
+				}
+			}
+
+echo "</table>";
+
+			if ($submit_btn)
+			{
+				?><INPUT TYPE="submit" name="well_delete_submit_button" value="Delete" style="margin-left:25px; margin-top:10px;">
+				 <INPUT TYPE="submit" name="mod_empty_well_cancel" value="Cancel"><?php
+			}
+			else
+			{
+				?><INPUT TYPE="submit" name="mod_empty_well_cancel" value="OK"><?php
+			}
+		}
+
+		return true;
+	}
+	
+	/**
+	 * Process well deletion - delete preps, make the well(s) empty (reserve????)
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param Array $session_vars
+	 * @param INT $contID
+	 *
+	 * @return boolean TRUE on success, FALSE on error
+	*/
+	function process_delete($session_vars, $contID)
+	{
+	//	print_r($session_vars);
+
+		global $conn;
+		$lfunc_obj = new Location_Funct_Class();
+
+		if( isset( $_SESSION["userinfo"] ) )
+		{
+			$currentUserID = $_SESSION["userinfo"]->getUserID();
+		}
+
+		if (isset($session_vars))
+		{
+			foreach ($session_vars as $key => $value)
+			{
+				$pieces = explode("|", $value);
+				$wellRow_ar[$key] = $pieces[0];		// get the row numbers of all the wells selected
+				$wellCol_ar[$key] = $pieces[1];		// get the column numbers of all the wells selected
+			}
+		}
+
+		foreach($wellRow_ar as $key => $rowvalue)
+		{
+			$rowvalue = $lfunc_obj->alpha2num($rowvalue) + 1;
+
+			// Get the wellID, the prepID and the isolate
+			$q1 = "SELECT b.`prepID`, b.`isolate_pk`, b.`refAvailID`, b.`flag`, b.`comments`, a.`wellID` FROM `Wells_tbl` a INNER JOIN `Prep_tbl` b ON a.`wellID`=b.`wellID` WHERE a.`wellRow`='" . $rowvalue . "' AND a.`wellCol`='" . $wellCol_ar[$key] . "' AND a.`containerID`='" . $contID . "' AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'";
+
+			$check_well_occupied_rs = mysql_query($q1, $conn ) or die( "ERROR IN CHECKING WELL SQL STATEMENT: " . mysql_error());
+
+			if ($check_well_occupied_ar = mysql_fetch_array($check_well_occupied_rs, MYSQL_ASSOC))
+			{
+				$wellID_tmp = $check_well_occupied_ar["wellID"];
+				$prepID_tmp = $check_well_occupied_ar["prepID"];
+				$isoID_tmp = $check_well_occupied_ar["isolate_pk"];
+
+				// delete well
+				$q5 = "UPDATE `Wells_tbl` SET `status`='DEP' WHERE `wellID`='" . $wellID_tmp . "' AND `status`='ACTIVE'";
+				$result3 = mysql_query($q5, $conn) or die( "ERROR IN WELL DELETION: " . mysql_error() );
+
+				if ($result3 == false)
+				{
+					echo "Could not delete well " . $wellID_tmp . "<br>";
+					return false;
+				}
+
+				// delete prep
+				$q4 = "UPDATE `Prep_tbl` SET `status`='DEP' WHERE `prepID`='" . $prepID_tmp . "' AND `status`='ACTIVE'";
+				$result2 = mysql_query($q4, $conn) or die( "ERROR IN PREP DELETION: " . mysql_error() );
+
+				if ($result2 == false)
+				{
+					echo "Could not delete prep " . $prepID_tmp . "<br>";
+					return false;
+				}
+
+				// Added Oct. 1/07, Marina: Delete prep properties if existed!!!!!!!!!
+				mysql_query("UPDATE PrepElementProp_tbl SET status='DEP' WHERE prepID='" . $prepID_tmp . "' AND `status`='ACTIVE'", $conn) or die("Could not delete prep properties: " . mysql_error());
+
+				// Check if the prep was the only prep for that isolate #
+				$q2 = "SELECT * FROM `Prep_tbl` WHERE `isolate_pk`='" . $isoID_tmp . "' AND `status`='ACTIVE'";
+				$check_preps_rs = mysql_query($q2, $conn ) or die( "ERROR IN CHECKING ISOLATES: " . mysql_error() );
+
+				// if yes, delete the isolate too
+				if (!($check_preps_ar = mysql_fetch_array($check_preps_rs, MYSQL_ASSOC)))
+				{
+					$q3 = "UPDATE `Isolate_tbl` SET `status`='DEP' WHERE `isolate_pk`='" . $isoID_tmp . "' AND `status`='ACTIVE'";
+					$result1 = mysql_query($q3, $conn) or die( "ERROR IN ISOLATE DELETION: " . mysql_error() );
+
+					if ($result1 == false)
+					{
+						echo "Could not delete isolate " . $isoID_tmp . "<br>";
+						return false;
+					}
+				}
+			}
+			else
+			{
+				// check if the well is reserved
+				$check_well_reserved_rs = mysql_query("SELECT * FROM `Wells_tbl` WHERE `containerID`='" . $contID . "' AND `wellRow` = '" . $rowvalue . "' AND `wellCol` = '" . $wellCol_ar[$key] . "' AND `reserved`='TRUE' AND `status`='ACTIVE'", $conn) or die ("Failure checking well reserved status: " . mysql_error);
+
+				// if yes, check who reserved it
+				if ($check_well_reserved_ar = mysql_fetch_array($check_well_reserved_rs, MYSQL_ASSOC))
+				{
+					$wellID_tmp = $check_well_reserved_ar["wellID"];
+					$creatorID_tmp = $check_well_reserved_ar["creatorID"];						
+
+					// if you, then delete the well
+					if ($creatorID_tmp == $currentUserID)
+					{
+						$q6 = "UPDATE `Wells_tbl` SET `status`='DEP' WHERE `wellID`='" . $wellID_tmp . "' AND `status`='ACTIVE'";
+						$result4 = mysql_query($q6, $conn) or die( "ERROR IN WELL DELETION: " . mysql_error() );
+
+						if ($result4 == false)
+						{
+							echo "Could not delete well " . $wellID_tmp . "<br>";
+							return false;
+						}
+					}
+				}
+			}
+		}
+		
+		return true;
+	}
+	
+	/**
+	 * Print well in 'modify' mode (after user has selected a well for modification)
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param Array $wells_checkbox_ar Selected well coordinates, passed as array [row | column]
+	 * @param INT $contID
+	 * @param boolean $error_state
+	 *
+	 * @return boolean TRUE on success, FALSE on error
+	*/
+	function printForm_modify($wells_checkbox_ar, $contID, $error_state)
+	{
+		global $conn;
+	
+		$wellRow_ar = array();
+		$wellCol_ar = array();
+		
+		$gfunc_obj = new generalFunc_Class();
+		$lfunc_obj = new Location_Funct_Class();
+
+		$selContTypeName = $lfunc_obj->getContainerGroupName($contID);
+		$selContType = $_SESSION["Container_Name_ID"][$selContTypeName];
+
+		// Added by Marina on August 1, 2005
+		if (isset($wells_checkbox_ar))
+		{
+			if ($lfunc_obj->isIsoActive( $contID ) == "YES")
+			{
+				$isIsolate_container = true;
+			}
+			else
+			{
+				$isIsolate_container = false;
+			}
+			
+			foreach( $wells_checkbox_ar as $key => $value )
+			{
+				$pieces = explode( "|", $value );
+				$wellRow_ar[ $key ] = $pieces[ 0 ];
+				$wellCol_ar[ $key ] = $pieces[ 1 ];
+			}
+				
+			// In case errors occur in the submit, allows retrevial of information
+			$_SESSION["wells_checkbox_tmp"] = $wells_checkbox_ar;
+			
+			$goodRow_ar = array();
+			$goodCol_ar = array();
+			
+			$badRow_ar = array();
+			$badCol_ar = array();
+
+			$goodWells_ar = array();
+
+			$count = 0;
+			
+			$well_info_ht = new HT_Class();
+
+			// Comments added by Marina on July 28, 2005
+			// Check if this well is occupied - i.e. if this well id has been assigned to a prep.  If yes, the well contains a prep and is occupied.
+			foreach( $wellRow_ar as $key => $rowvalue )
+			{
+				// But this check performs a JOIN with the Preps table - therefore, it checks to see if this well is occupied by a prep.  If it is, pull the prep info out and modify.
+				
+				$check_well_exist_rs = mysql_query("SELECT b.`prepID`, b.`isolate_pk`, b.`refAvailID`, b.`flag`, b.`comments`, a.`wellID`" . "FROM `Wells_tbl` a INNER JOIN `Prep_tbl` b ON a.`wellID`=b.`wellID` "
+							. "WHERE a.`wellRow`='" . $rowvalue . "' AND a.`wellCol`='" . $wellCol_ar[ $key ] . "' "
+							. "AND a.`containerID`='" . $contID . "' "
+							. "AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'", $conn)
+							or die( "ERROR IN CHECKING WELL SQL STATEMENT: " . mysql_error());
+				
+				if( $check_well_exist_ar = mysql_fetch_array( $check_well_exist_rs, MYSQL_ASSOC ) )
+				{
+					$temp_well_ar = array();
+					
+					$temp_well_ar["isolate_pk"] = $check_well_exist_ar["isolate_pk"];
+					$temp_well_ar["refAvailID"] = $check_well_exist_ar["refAvailID"];
+					$temp_well_ar["flag"] = $check_well_exist_ar["flag"];
+					$temp_well_ar["comments"] = $check_well_exist_ar["comments"];
+					$temp_well_ar["prepID"] = $check_well_exist_ar["prepID"];
+					
+					$well_info_ht->add( $check_well_exist_ar["wellID"], $temp_well_ar );
+					unset( $temp_well_ar );
+					
+					$goodRow_ar[ $check_well_exist_ar["wellID"] ] = $wellRow_ar[ $key ];
+					$goodCol_ar[ $check_well_exist_ar["wellID"] ] = $wellCol_ar[ $key ];
+					$goodWells_ar[$count] = $check_well_exist_ar["wellID"];
+				}
+				else		
+				{
+					// Added by Marina on July 28, 2005	-- Modified on Sept 29
+					// No prep has been assigned to this well.  Nothing to modify.  NEED TO TELL THAT TO THE USER!!!
+					
+					$well_exists = false;
+	
+					$well_tmp_info_rs = mysql_query( "SELECT * FROM `Wells_tbl` WHERE `containerID`='" . $contID . "' "
+											. "AND `wellRow`='" . $rowvalue . "' AND `wellCol`='" . $wellCol_ar[ $key ] . "' "
+											. "AND `status`='ACTIVE'", $conn )
+											or die( "ERROR IN CHECKING WELL SQL STATEMENT: " . mysql_error() );
+				
+					if ($well_tmp_info_ar = mysql_fetch_array($well_tmp_info_rs, MYSQL_ASSOC))
+					{	
+						$badRow_ar[ $well_tmp_info_ar["wellID"] ] = $wellRow_ar[$key];
+						$badCol_ar[ $well_tmp_info_ar["wellID"] ] = $wellCol_ar[ $key ];
+						$badWells_ar[$count] = $check_well_exist_ar["wellID"];
+					}
+				}
+	
+				$count++;
+			}
+			
+			// To track which variables are where
+			$_SESSION["identifier_ar"] = $goodRow_ar;
+			
+			// Well/Prep information Hash Table
+			$_SESSION["well_info_ht"] = $well_info_ht;
+			
+			// -----------------------------------------------
+			// General Property Section of the Modify Function
+			$general_info_ht = new HT_Class();
+			
+			$prep_gen_check_rs = mysql_query("SELECT p.elementTypeID, p.propertyName FROM PrepElemTypes_tbl p, ContainerTypeAttributes_tbl c WHERE c.containerTypeID='" . $selContType . "' AND c.containerTypeAttributeID=p.elementTypeID AND c.status='ACTIVE' AND p.status='ACTIVE' UNION (SELECT a.`prepElementTypeID`, b.`propertyName` FROM `Prep_Req_tbl` a INNER JOIN `PrepElemTypes_tbl` b ON a.`prepElementTypeID`=b.`elementTypeID` WHERE a.`containerID`='" . $contID . "' AND a.`requirement`='REQ' AND  [...]
+	
+			$req_set = "('";
+			$req_setcount = 0;
+			$general_req_ar = array();
+		
+			while ($prep_gen_check_ar = mysql_fetch_array($prep_gen_check_rs, MYSQL_ASSOC))
+			{
+				$req_setcount++;
+				$req_set = $req_set . $prep_gen_check_ar["elementTypeID"] . "','";
+				$general_req_ar[ $prep_gen_check_ar["propertyName"] ] = $prep_gen_check_ar["elementTypeID"];
+			}
+		
+			$req_set = $this->reset_set($req_setcount, $req_set);
+	
+			// Session saved variable for the general properties for processing later
+			$_SESSION["stage2_general_req_ar"] = $general_req_ar;
+				
+			// Finding actual general properties for container
+			foreach( $goodRow_ar as $wellID_tmp => $wellSpot_tmp )
+			{
+				$general_tmp_ar = array();
+				
+				$prep_tmp_ar = $well_info_ht->get( $wellID_tmp );
+				$prepID_tmp = $prep_tmp_ar["prepID"];
+	
+				$find_gen_prop_rs = mysql_query("SELECT a.`prepID`, a.`elementTypeID`, a.`value`, b.`propertyName` FROM `PrepElementProp_tbl` a, `PrepElemTypes_tbl` b WHERE a.`elementTypeID`=b.`elementTypeID` AND a.`prepID`='" . $prepID_tmp . "' AND b.`elementTypeID` IN " . $req_set . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'", $conn) or die( "FAILURE IN GENERAL PROPERTY SEARCH SQL: " . mysql_error());
+				
+				while ($find_gen_prop_ar = mysql_fetch_array($find_gen_prop_rs, MYSQL_ASSOC))
+				{
+					$general_tmp_ar[$find_gen_prop_ar["propertyName"]] = $find_gen_prop_ar["value"];
+				}
+	
+				$general_info_ht->add( $prepID_tmp, $general_tmp_ar );
+			}
+			
+			// General property Hast table saved
+			$_SESSION["general_info_ht"] = $general_info_ht;
+			
+			// ------------------------------------------------------------
+			// Experiment and Isolate Information section of the function
+			$exp_info_ht = new HT_Class();
+			
+			foreach( $goodRow_ar as $wellID_tmp => $wellSpot_tmp )
+			{
+				$prep_tmp_ar = array();
+				
+				$prep_tmp_ar = $well_info_ht->get( $wellID_tmp );
+				$isoID_tmp = $prep_tmp_ar["isolate_pk"];
+				
+				$exp_check_rs = mysql_query( "SELECT b.`expID`, b.`reagentID`, a.`isolateNumber`, a.`isolate_active`, a.`beingUsed` "
+				. "FROM `Isolate_tbl` a INNER JOIN `Experiment_tbl` b ON a.`expID`=b.`expID` "
+				. "WHERE a.`isolate_pk`='" . $isoID_tmp . "' AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'", $conn )
+				or die( "FAILURE IN PREP SQL STATEMENT: " . mysql_error() );
+				
+				$temp_exp_ar = array();
+				
+				if( $exp_check_ar = mysql_fetch_array( $exp_check_rs , MYSQL_ASSOC ) )
+				{
+					$temp_exp_ar["expID"] = $exp_check_ar["expID"];
+					$temp_exp_ar["reagentID"] = $exp_check_ar["reagentID"];
+					$temp_exp_ar["isolateNumber"] = $exp_check_ar["isolateNumber"];
+					$temp_exp_ar["isolate_active"] = $exp_check_ar["isolate_active"];
+					$temp_exp_ar["beingUsed"] = $exp_check_ar["beingUsed"];
+					
+					$exp_info_ht->add( $isoID_tmp, $temp_exp_ar );
+					unset( $temp_exp_ar );
+				}			
+			}
+		
+			// Experiment property information saved Hash Table
+			$_SESSION["exp_info_ht"] = $exp_info_ht;
+			$temp_count = 0;
+			
+			?><form name="well_modify_form" method=post action="<?php echo $_SERVER["PHP_SELF"] . "?View=7&Mod=" . $contID . ""; ?>">
+				<table border="1" frame="box" rules="all" style="min-width:986px" cellpadding="3">
+					<th colspan="100%" class="detailedView_heading"><?php echo $lfunc_obj->getContainerName($contID); ?>
+						<BR><span style="font-size:8pt; font-weight:bold; color:red;"><IMG SRC="pictures/new01.gif" ALT="new" WIDTH="35" HEIGHT="20" style="cursor:auto;">You may update multiple wells at once by clicking on the property's column heading and typing its value in the pop-up box.</span>
+					</th>
+				
+					<tr><?php
+
+				if (!$isIsolate_container)
+				{
+					?>
+						<td style="text-align:center; font-size:7pt; color:navy; font-weight:bold; width:5%;">Well</td>
+						<td style="text-align:center; font-size:7pt; color:navy; font-weight:bold; cursor:pointer;" onclick="popupWellAttrUpdateForm('OpenFreezer ID');">OpenFreezer ID</td>
+						<td style="text-align:center; font-size:7pt; color:navy; font-weight:bold; cursor:pointer;" onclick="popupWellAttrUpdateForm('Reference');">Reference</td>
+						<td style="text-align:center; font-size:7pt; color:navy; font-weight:bold; cursor:pointer;" onClick="checkUncheckAllFlags();">Flag</td>
+						<td style="text-align:center; font-size:7pt; color:navy; font-weight:bold; cursor:pointer;" onclick="popupWellAttrUpdateForm('Comments');">Comments</td>
+					<?php
+				}
+				else
+				{
+					?><td style="text-align:center; font-size:7pt; color:navy; font-weight:bold; width:5%;">Well</td>
+					<td style="text-align:center; font-size:7pt; color:navy; font-weight:bold; cursor:pointer;" onclick="popupWellAttrUpdateForm('OpenFreezer ID');">OpenFreezer ID</td>
+					<td style="text-align:center; font-size:7pt; color:navy; font-weight:bold; cursor:pointer;" onclick="popupWellAttrUpdateForm('Isolate Number');">Isolate Number</td>
+					<td style="text-align:center; font-size:7pt; color:navy; font-weight:bold; padding-left:5px; padding-right:5px; cursor:pointer;" onclick="checkUncheckAllIsolates();">Current Set Isolate</td>
+					<td style="text-align:center; font-size:7pt; color:navy; font-weight:bold; cursor:pointer;" onclick="popupWellAttrUpdateForm('Reference');">Reference</td>
+					<td style="text-align:center; font-size:7pt; color:navy; font-weight:bold; padding-left:5px; padding-right:5px; cursor:pointer;" onClick="checkUncheckAllFlags();">Flag</td>
+					<td style="text-align:center; font-size:7pt; color:navy; font-weight:bold; cursor:pointer;" onclick="popupWellAttrUpdateForm('Comments');">Comments</td>
+					<?php
+				}
+
+			// Output general property headers
+			foreach($general_req_ar as $pname => $pid)
+			{
+				// June 2, 2011: Enable column selection and setting same values
+				echo "<td style=\"text-align:center; font-weight:bold; font-size:7pt; color:navy; cursor:pointer;\" id=\"hdr_" . $pname . "\" onClick=\"popupWellAttrUpdateForm('" . str_replace("'", "\'", $pname) . "');\">";
+				echo $pname;
+				echo "</td>";
+			}
+
+			?></tr><?php
+
+			foreach ($wellRow_ar as $key => $value)
+			{
+				$wellID_tmp = $goodWells_ar[$key];
+				
+				if ($wellID_tmp)
+				{
+					$prep_tmp_ar =  $well_info_ht->get($wellID_tmp);
+					
+					$isoID_tmp = $prep_tmp_ar["isolate_pk"];
+					$prepID_tmp = $prep_tmp_ar["prepID"];
+					
+					$exp_tmp_ar = $exp_info_ht->get($isoID_tmp);
+
+					?>
+					<tr>
+						<td style="width:5%; font-size:8pt; font-weight:bold; color:#104E8B; text-align:center;"><?php echo $lfunc_obj->getLetterRow($wellRow_ar[$key]) . ":" . $wellCol_ar[$key]?></td>
+
+						<td name="limsID_td[]" style="padding-left:7px;">
+							<?php
+								$rid_val = "";	// added June 3, 2011
+
+								// update June 3, 2011
+								if (($error_state == true) && (strlen($_SESSION["well_mod_rid_text"][$temp_count]) > 0) )
+								{
+									$rid_val = $_SESSION["well_mod_rid_text"][$temp_count];
+								}
+								else
+								{
+									$rid_val = $gfunc_obj->getConvertedID_rid($exp_tmp_ar["reagentID"]);
+								}
+							?>
+							
+						<!-- update June 3, 2011 -->
+						<input type="text" size="5" class="locationText" onKeyPress="return disableEnterKey(event);" NAME="well_mod_rid_text[]" value="<?php echo $rid_val; ?>">
+					</td>
+	
+					<?php
+						if ($isIsolate_container)	// Added by Marina on July 27, 2005
+						{
+							?>
+							<td style="text-align:center; padding-left:5px; padding-right:5px;" name="isoNum_td[]">
+								<input type="text" size="5" class="locationText" onKeyPress="return disableEnterKey(event);" name="well_mod_isoNum<?php echo $temp_count; ?>_textfield" id="well_mod_isoNum<?php echo $temp_count; ?>_textfield" value="<?php 
+								//if( $_SESSION["well_mod_error_state"] == "ERROR" )
+								if ($error_state)
+								{
+									echo $_SESSION["well_mod_isoNum_ar"][$temp_count];
+								} 
+								else
+								{ 
+									if (strlen($exp_tmp_ar["isolateNumber"]) > 0)
+									{
+										echo $exp_tmp_ar["isolateNumber"];
+									}
+								}?>">
+							</td>
+	
+							<td align="center">
+								<input type="checkbox" name="well_mod_beingUsed<?php echo $temp_count; ?>_checkbox" value="YES" <?php 
+								//if( $_SESSION["well_mod_error_state"] == "ERROR" )
+								if( $error_state )
+								{
+									if( $_SESSION["well_mod_beingUsed_ar"][ $temp_count ] == "YES" )
+									{
+										echo " checked ";
+									}
+									else
+									{
+										echo " ";
+									}
+								}
+								else
+								{
+									if( $exp_tmp_ar["beingUsed"] == "YES" )
+									{
+										echo " checked ";
+									}
+									else
+									{
+										echo " ";
+									}
+									
+								}
+								?>>
+							</td>
+							<?php
+						}
+					?>
+					<td name="Reference_td[]">
+						<input type="text" class="locationText" size="18" onKeyPress="return disableEnterKey(event);" name="well_mod_refAvail_text[]" value="<?php 
+							//if( $_SESSION["well_mod_error_state"] == "ERROR" )
+							if( $error_state )
+							{
+								echo $_SESSION["well_mod_refAvail_text"][ $temp_count ];
+							}
+							else
+							{
+								if( strlen( $prep_tmp_ar["refAvailID"] ) > 0 )
+								{
+									echo $prep_tmp_ar["refAvailID"];
+								}
+							}
+						?>">
+					</td>
+
+					<td style="text-align:center; padding-left:5px; padding-right:5px;">
+						<!-- name="well_mod_flag_checkbox[]"	=> MODIFIED AUG 10--> 
+					<input type="checkbox" 
+						name="well_mod_flag<?php echo $temp_count; ?>_checkbox"
+						value="YES"<?php
+						//if( $_SESSION["well_mod_error_state"] == "ERROR" )
+
+// echo "what is this: ";
+// print_r($_SESSION["well_mod_flag_checkbox"]);
+
+						if ($error_state)
+						{
+							if( $_SESSION["well_mod_flag_checkbox"][$temp_count] == "YES" )
+							{
+								echo " checked ";
+							}
+							else		// Aug 10
+							{
+								echo " ";
+							}
+						}
+						else
+						{
+							if( $prep_tmp_ar["flag"] == "YES" )
+							{
+								echo " checked ";
+							}
+							else		// Aug 10
+							{
+								echo " ";
+							}
+						}
+					?>>
+					</td>
+
+					<td name="Comments_td[]">
+					<input type="text" class="locationText" onKeyPress="return disableEnterKey(event);" name="well_mod_comments_text[]" value="<?php
+						//if( $_SESSION["well_mod_error_state"] == "ERROR" )
+						if( $error_state )
+						{
+							echo $_SESSION["well_mod_comments_text"][ $temp_count ];
+						}
+						else
+						{
+							if( strlen( $prep_tmp_ar["comments"] ) > 0 )
+							{
+								echo $prep_tmp_ar["comments"];
+							}
+						}
+						?>">
+					</td>
+					<?php
+
+					foreach($general_req_ar as $pname => $pid )
+					{
+						echo "<td name=\"" . $pname . "_td[]\">";
+						$general_tmp_ar = $general_info_ht->get( $prepID_tmp );
+						echo "<input type=\"text\" class=\"locationText\" onKeyPress=\"return disableEnterKey(event);\" name=\"well_mod_general" . $pid . "_text[]\" value=\"";
+						echo $general_tmp_ar[ $pname ];
+						echo "\">";
+						echo "</td>";
+					}
+
+					?>
+					</tr>
+				
+					<?php
+					if( $error_state && strlen( $_SESSION["well_mod_error_msg"][$temp_count] ) > 0 )
+					{
+						?>
+						<tr>
+							<td></td>
+
+							<td colspan="100%" style="color:#FF0000; font-weight:bold; font-size:7pt">Error Occurred: <?php echo $_SESSION["well_mod_error_msg"][$temp_count]; ?></td>
+						</tr>
+						<?php
+					}
+				
+					$temp_count++;
+					$submit_btn = true;
+				}
+				else	// empty well
+				{
+					$badWellID = $wellRow_ar[$key];
+					$tmpRowID = $wellRow_ar[$key];
+					$tmpColID = $wellCol_ar[$key];
+	
+					echo "<tr>";
+					echo "<TD style=\"width:5%; font-weight:bold; font-size:8pt; color:#104E8B; text-align:center;\">" . $lfunc_obj->getLetterRow($tmpRowID) . ":" . $tmpColID . "</TD>";
+					
+					echo "<td colspan=\"100%\" style=\"font-size:7pt; font-weight:bold; color:#104E8B; padding-left:5px;\">No prep information has been stored in well " . $lfunc_obj->getLetterRow($tmpRowID) . ":" . $tmpColID . ".  Please select another well to modify.</td></tr>";
+				}
+			}	// end foreach
+
+			if ($submit_btn)
+			{
+				?>
+					<tr>
+						<td></td>
+
+						<td  colspan="100%">
+							<input type="submit" name="well_mod_submit_button" value="Submit">   
+							<input type="submit" name="well_mod_cancel_button" value="Cancel">
+						</td>
+					</tr>
+				</table>
+				<?php
+			}
+			else
+			{
+				?>
+				<tr>
+				<td>
+				<input type="submit" name="mod_empty_well_cancel" value="OK">
+				</td>
+				</tr>
+				</table>
+				<?php
+			}
+
+			unset( $_SESSION["well_mod_error_msg"] );
+			unset( $gfunc_obj );
+		}
+		else
+		{
+			?><FORM METHOD=POST ACTION="<?php echo $_SERVER["PHP_SELF"] . "?View=7&Mod=" . $contID . ""; ?>"><FONT COLOR="#FF0000"><CENTER><B>No well has been selected for modification!  Please select a well to modify.</B></CENTER></FONT><BR>		
+			<CENTER><INPUT TYPE="submit" name="mod_empty_well_cancel" value="OK"></CENTER>
+			</FORM>
+			<?php
+		}
+	}
+
+	/**
+	 * Save modified well information upon exit from 'modify' mode
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param INT $contID_tmp
+	 * @return boolean TRUE on success, FALSE on error
+	*/
+	function process_modify($contID_tmp)
+	{
+		global $conn;
+		
+		$gfunc_obj = new generalFunc_Class();
+		$isIsolate_container = false;
+		$input_count = 0;
+		$error_msg = "";
+		
+		$isolateDuplicate_ar = array();
+		
+		$inputRow_check_ar = array();
+		
+		unset( $_SESSION["well_mod_error_msg"] );
+		
+		if( !isset( $_SESSION["well_mod_error_msg"] ) )
+		{
+			$_SESSION["well_mod_error_msg"] = array();
+			//$_SESSION["well_mod_error_row"] = array();
+		}
+		
+		// Grab the isolate active state of the container
+		$isoAct_rs = mysql_query( "SELECT `isolate_active` FROM `Container_tbl` WHERE `containerID`='" . $contID_tmp . "' " . "AND `status`='ACTIVE'", $conn ) or die( "FAILURE IN process_modify() : isoAct_rs: " . mysql_error() );
+	
+		if( $isoAct_ar = mysql_fetch_array( $isoAct_rs, MYSQL_ASSOC ) )
+		{
+			if( $isoAct_ar["isolate_active"] == "YES" )
+			{
+				$isIsolate_container = true;
+			}
+			else		// added July 28
+			{
+				$isIsolate_container = false;
+			}
+		}
+		
+		mysql_free_result( $isoAct_rs );
+		unset( $isoAct_rs, $isoAct_ar );
+		
+		foreach( $_SESSION["identifier_ar"] as $wellID_tmp => $wellRow_spot )
+		{
+			$prep_tmp_ar =  $_SESSION["well_info_ht"]->get( $wellID_tmp );
+			$isoID_tmp = $prep_tmp_ar["isolate_pk"];
+			$prepID_tmp = $prep_tmp_ar["prepID"];
+
+			$rid_tmp = 0;
+
+			$stage_rid_check = "FAIL";
+			$stage_isoNum_check = "FAIL";
+			
+			$stage_beingUsed_check = "FAIL";
+			
+			$exp_tmp_ar = $_SESSION["exp_info_ht"]->get( $isoID_tmp );
+			
+			// VERIFY THE VALIDITY OF THE INFORMATION ENTERED BEFORE INSERTING IT INTO THE DATABASE
+
+			//	1. LIMS ID
+			if( isset( $_POST["well_mod_rid_text"] ) && strlen( $_POST["well_mod_rid_text"][ $input_count ] ) > 0 
+				&& $gfunc_obj->getConvertedID_rid( $exp_tmp_ar["reagentID"] ) != $_POST["well_mod_rid_text"][ $input_count ] )
+			{
+				// Must do back checking for LIMS ID integrity check
+				$rid_tmp = $gfunc_obj->get_rid( $_POST["well_mod_rid_text"][ $input_count ] );
+			}
+			else
+			{
+				$rid_tmp = $exp_tmp_ar["reagentID"];
+			}
+
+			$expID_tmp = -1;
+			
+			if( $rid_tmp > 0 )
+			{
+				// September 9, 2007: Add project ID check:
+				$currUserID = $_SESSION["userinfo"]->getUserID();
+				$currUserCategory = $_SESSION["userinfo"]->getCategory();
+				$userProjects = getUserProjectsByRole($currUserID, 'Writer');
+				$projectID = getReagentProjectID($rid_tmp);
+				
+				if (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || in_array($projectID, $userProjects))
+				{
+					$stage_rid_check = "PASS";
+					$expID_tmp = $this->backChecking_LIMSID_Existance( $rid_tmp );
+					
+					if( $expID_tmp <= 0 )
+						$expID_tmp = $this->insert_new_expID( $rid_tmp );
+				}
+				else
+					$error_msg = "You may not insert " .  $_POST["well_mod_rid_text"][ $input_count ] . " into this well, since you do not have Write access to its project.  Please contact the project owner to obtain permission.";
+			}
+			else
+			{
+				$error_msg = $error_msg . " | The LIMS ID was not parsed correctly. Please Check the format of the LIMS ID. ";
+				$stage_rid_check = "FAIL";
+			}
+			
+			
+			// 2. Isolate Active
+			if( $isIsolate_container && $stage_rid_check == "PASS")
+			{
+				// Only executed if this is container is Isolate Active
+				if( $isIsolate_container )
+				{
+					// 3. Isolate Number
+					if( isset( $_POST["well_mod_isoNum" . $input_count . "_textfield"] ) 
+						&& $_POST["well_mod_isoNum" . $input_count . "_textfield"] != $exp_tmp_ar["isolateNumber"] )	// if the inputted isolate is different
+					{
+						// Check if the inputted isolate is already taken
+						$iso_checkdup_tmp = $this->backChecking_isoNum_duplicate( $expID_tmp, $isoID_tmp, $_POST["well_mod_isoNum" . $input_count . "_textfield"] );
+						
+						// Modified Aug 5
+						if( $iso_checkdup_tmp != -1)
+						{
+							$isolateDuplicate_ar[ $input_count ] = true;
+						}
+						else
+						{
+							$isolateDuplicate_ar[ $input_count ] = false;
+						}
+					}
+					else
+					{
+
+					}
+					
+
+					// 4. Being Used -- Checks if this is the Current Set Isolate!
+					if( isset( $_POST["well_mod_beingUsed" . $input_count . "_checkbox"] ) 
+						&& $_POST["well_mod_beingUsed" . $input_count . "_checkbox"] != $exp_tmp_ar["beingUsed"] )
+					{
+						if( $this->backChecking_beingUsed_duplicate( $expID_tmp, $isoID_tmp, $_POST["well_mod_beingUsed" . $input_count . "_checkbox"] ) )
+						{
+							$stage_beingUsed_check = "FAIL";
+							$error_msg = $error_msg . " There is already a isolate set as being used! ";
+//							echo "Error msg in isolate used fail: " . $error_msg . "<BR>";
+						}
+						else
+						{
+							$stage_beingUsed_check = "PASS";
+						}
+					}
+					else
+					{
+						// If this isn't set, default to not default or hasn't been set!, it's ok!
+						$stage_beingUsed_check = "PASS";
+					}
+				}
+				else	// Not isolate active container
+				{
+						
+				}
+			}
+			elseif( !$isIsolate_container && $stage_rid_check == "PASS" )
+			{
+				// NOT AN ISOLATE ACTIVE CONTAINER!!!
+				$stage_isoNum_check = "FAIL";
+				$stage_beingUsed_check = "PASS";
+			}
+			
+			if ($stage_rid_check == "PASS" && $stage_beingUsed_check == "PASS")
+			{
+				$inputRow_check_ar[ $input_count ] = "PASS";
+			}
+			else
+			{
+				$_SESSION["well_mod_error_msg"][ $input_count ] = $error_msg;
+				$inputRow_check_ar[ $input_count ] = "FAIL";
+			}
+			
+			$error_msg = "";
+			$value_checker_bool = false;
+
+			if( !in_array( "FAIL", $inputRow_check_ar ) )
+			{
+				$value_checker_bool = true;
+			}
+			else
+			{
+				$value_checker_bool = false;
+			}
+
+			if ($value_checker_bool)
+			{
+				// Update the information that was changed
+				$prep_tmp_ar =  $_SESSION["well_info_ht"]->get( $wellID_tmp );
+				$isoID_tmp = $prep_tmp_ar["isolate_pk"];
+				$prepID_tmp = $prep_tmp_ar["prepID"];
+
+				$rid_tmp = 0;
+				$expID_tmp = 0;
+				$beingUsed_tmp = "NO";
+				$flag_tmp = "NO";
+				
+				$changed_count = 0;
+				
+				$exp_tmp_ar = $_SESSION["exp_info_ht"]->get( $isoID_tmp );
+				
+				$general_tmp_ar = $_SESSION["general_info_ht"]->get( $prepID_tmp );
+				
+				
+				// 1. LIMS ID
+
+				if( strlen( $_POST["well_mod_rid_text"][ $input_count ] ) > 0 && $gfunc_obj->getConvertedID_rid( $exp_tmp_ar["reagentID"] ) != $_POST["well_mod_rid_text"][$input_count])
+				{
+					$rid_tmp = $gfunc_obj->get_rid( $_POST["well_mod_rid_text"][ $input_count ] );
+					$changed_count++;
+				}
+				else
+				{
+					$rid_tmp = $exp_tmp_ar["reagentID"];
+					
+				}
+				
+				$expID_tmp = $gfunc_obj->get_ExpID( $rid_tmp );
+				$isoActive_sql_string = "";
+				
+				// 2. Isolate number
+				// Modified by Marina on August 8, 2005
+				
+				// Only executed if container is isolate active - NOT executed for Oligos and Inserts
+				if ($isIsolate_container)
+				{
+					// Execute only if the inputted isolate is different (added by Marina on Aug 8, 2005)
+					if (isset($_POST["well_mod_isoNum" . $input_count . "_textfield"]) && $_POST["well_mod_isoNum" . $input_count . "_textfield"] != $exp_tmp_ar["isolateNumber"])
+					{
+						// Insertion/update of isolate information is done here
+						if ($isolateDuplicate_ar[$input_count])
+						{
+							// Need to find the previous isolate number isolate_pk and associate with this isolate entry!
+							
+							// Find this prep's old isolate
+							$isoCheck_rs = mysql_query("SELECT * FROM `Isolate_tbl` WHERE `expID`='" . $expID_tmp . "' " . "AND `isolateNumber`='" . $isolate_tmp . "' " . "AND `status`='ACTIVE'", $conn) or die( "FAILURE IN: process_modify " . mysql_error());
+
+							if ($isoCheck_ar = mysql_fetch_array($isoCheck_rs, MYSQL_ASSOC))
+							{
+								$isoID_old = $isoCheck_ar["isolate_pk"];
+							}
+							else
+							{
+								$isoID_old = $isoID_tmp;
+							}
+							
+							// Find the new isolate
+							$isolate_tmp = $_POST["well_mod_isoNum" . $input_count . "_textfield"];
+
+							$isoCheck_rs = mysql_query("SELECT * FROM `Isolate_tbl` WHERE `expID`='" . $expID_tmp . "' " . "AND `isolateNumber`='" . $isolate_tmp . "' " . "AND `status`='ACTIVE'", $conn) or die("FAILURE IN: process_modify " . mysql_error());
+							
+							if( $isoCheck_ar = mysql_fetch_array( $isoCheck_rs, MYSQL_ASSOC ) )
+							{
+								$isoID_new = $isoCheck_ar["isolate_pk"];
+							}
+							else
+							{
+								$isoID_new = $iso_checkdup_tmp;
+							}
+							
+							// Link the prep to the new isolate (change the prep's isolate ID)
+							mysql_query( "UPDATE `Prep_tbl` SET `isolate_pk`='" . $isoID_new . "' " . "WHERE `prepID`='" . $prepID_tmp . "' AND `status`='ACTIVE'", $conn ) or die( "Failure in Prep Update: " . mysql_error() );
+						
+							// Check if there are other preps associated with this isolate
+							$prep_rs = mysql_query("SELECT * FROM `Prep_tbl` WHERE `isolate_pk` = '" . $isoID_old . "'", $conn) or die( "FAILURE IN prep deletion:: " . mysql_error());
+
+							if (($preps = mysql_num_rows($prep_rs)) > 0)
+							{
+								$preps_exist = true;	
+							}
+							else
+							{
+								$preps_exist = false;
+							}
+
+							// If no other preps are associated with this isolate_pk, deprecate it
+							if ($preps_exist == false)
+							{
+								$isoNum_rs = mysql_query("SELECT * FROM Isolate_tbl WHERE `isolate_pk`='" . $isoID_old . "' AND `expID` = '" . $expID_tmp . "'", $conn) or die ("Failure in isolate number extraction " . mysql_error());
+								
+								$isoNum_ar = mysql_fetch_array($isoNum_rs);
+								$isoNum_tmp = $isoNum_ar["isolateNumber"];
+
+								mysql_query("UPDATE `Isolate_tbl` SET `status`='DEP' WHERE `isolate_pk` = '" . $isoID_old . "' AND `expID` = '" . $expID_tmp . "' AND isolateNumber = '" . $isoNum_tmp . "'", $conn) or die( "FAILURE IN isolate deletion:: " . mysql_error() );
+							}
+						}
+						else
+						{
+							// Written by Marina on August 9, 2005
+							
+							// Create a new isolate with the new isolate number
+							$isoNum_tmp = $_POST["well_mod_isoNum" . $input_count . "_textfield"];		
+
+							mysql_query( "INSERT INTO `Isolate_tbl` (`isolate_pk`, `expID`, `isolateNumber`, `beingUsed`) "	. "VALUES ('', '" . $expID_tmp . "','" . $isoNum_tmp . "','NO')", $conn )
+							or die( "FAILURE IN new isolate insertion:: " . mysql_error() );
+
+							// Setting new iso ID
+							$isoID_new = mysql_insert_id($conn);
+
+							// Insert the new prep in that location
+							mysql_query("UPDATE `Prep_tbl` SET `isolate_pk`='" . $isoID_new . "' " . "WHERE `prepID`='" . $prepID_tmp . "' AND `status`='ACTIVE'", $conn) or die("Failure in Prep Update: " . mysql_error());
+
+							// Check if there are any remaining preps associated with the old isolate; if none, deprecate it
+							$prep_rs = mysql_query("SELECT * FROM `Prep_tbl` WHERE `isolate_pk` = '" . $isoID_tmp . "' AND `status`='ACTIVE'", $conn) or die("FAILURE IN prep deletion:: " . mysql_error());
+
+							if (($preps = mysql_num_rows($prep_rs)) > 0)
+							{
+								$preps_exist = true;
+							}
+							else
+							{
+								$preps_exist = false;
+							}
+
+							// If no other preps are associated with this isolate_pk, deprecate it
+							if ($preps_exist == false)
+							{
+								$isoNum_rs = mysql_query("SELECT * FROM Isolate_tbl WHERE `isolate_pk`='" . $isoID_tmp . "' AND `expID` = '" . $expID_tmp . "'", $conn) or die ("Failure in isolate number extraction " . mysql_error());
+								
+								$isoNum_ar = mysql_fetch_array($isoNum_rs);
+								$isoNum_tmp = $isoNum_ar["isolateNumber"];
+
+								mysql_query("UPDATE `Isolate_tbl` SET `status`='DEP' WHERE `isolate_pk` = '" . $isoID_tmp . "' AND `expID` = '" . $expID_tmp . "' AND isolateNumber = '" . $isoNum_tmp . "' AND `status`='ACTIVE'", $conn) or die( "FAILURE IN isolate deletion:: " . mysql_error() );
+							}
+						}
+					}
+
+					//  3. Being Used
+					//	Updated by Marina on August 10, 2005
+					if (isset( $_POST["well_mod_beingUsed" . $input_count . "_checkbox"]))
+					{
+						if ($_POST["well_mod_beingUsed" . $input_count . "_checkbox"] != $exp_tmp_ar["beingUsed"])
+						{
+							// Modify current used status
+							$beingUsed_tmp = "YES";
+							$changed_count++;
+						}
+						else
+						{
+							$beingUsed_tmp = $exp_tmp_ar["beingUsed"];
+						}
+					}
+					else
+					{
+						if ($_POST["well_mod_beingUsed" . $input_count . "_checkbox"] != $exp_tmp_ar["beingUsed"])
+						{
+							$beingUsed_tmp = "NO";
+							$changed_count++;
+						}
+						else
+						{
+							$beingUsed_tmp = $exp_tmp_ar["beingUsed"];
+						}
+					}
+					
+					if ($changed_count > 0)
+					{
+						mysql_query( "UPDATE `Isolate_tbl` SET `beingUsed`='" . $beingUsed_tmp . "' WHERE `expID`='" . $expID_tmp . "' AND `isolate_pk`='" . $isoID_tmp . "' AND `status`='ACTIVE'", $conn ) or die( "Failure in Process Modify (Updating Iso Info) SQL statement: " . mysql_error() );
+					}
+				}	// end if isolateActive_container
+
+				
+				// 4. Flag
+				// Updated by Marina on August 11, 2005
+
+				if (isset( $_POST["well_mod_flag" . $input_count . "_checkbox"]))
+				{
+					if ($_POST["well_mod_flag" . $input_count . "_checkbox"] != $prep_tmp_ar["flag"])
+					{
+						$flag_tmp = "YES";
+						$changed_count++;
+					}
+					else
+					{
+						$flag_tmp = $prep_tmp_ar["flag"];
+					}
+				}
+				else
+				{
+					// Added Aug 11
+ 					if ($_POST["well_mod_flag" . $input_count . "_checkbox"] != $prep_tmp_ar["flag"])
+					{
+						$flag_tmp = "NO";
+						$changed_count++;
+					}
+					else
+					{
+						$flag_tmp = $prep_tmp_ar["flag"];
+					}
+				}
+
+				if ($changed_count > 0)
+				{	
+					mysql_query( "UPDATE `Prep_tbl` SET `flag`='" . $flag_tmp . "' WHERE `prepID`='" . $prepID_tmp . "' AND `status`='ACTIVE'", $conn ) or die( "FAILURE in process_modify (Updating Prep Info) SQL error: " . mysql_error() );
+				}
+
+
+				// 5. Reference
+				if (isset($_POST["well_mod_refAvail_text"]) && $_POST["well_mod_refAvail_text"][$input_count] != $exp_tmp_ar["refAvail"])
+				{
+					$refAvail_tmp = $_POST["well_mod_refAvail_text"][ $input_count ];
+					$changed_count++;
+				}
+				else			// Added by Marina on July 22, 2005
+				{
+					$refAvail_tmp = "";
+					$changed_count++;
+				}
+
+
+				// 6. Comments
+
+				if( isset( $_POST["well_mod_comments_text"] ) 
+					&& $_POST["well_mod_comments_text"][ $input_count ] != $exp_tmp_ar["comments"] )
+				{
+					// Must do updating for isolate number as well as check that inputted isolate is not taken!
+					$comments_tmp =  $_POST["well_mod_comments_text"][ $input_count ];
+					$changed_count++;
+				}
+				else				// Added by Marina on July 22, 2005
+				{
+					$comments_tmp = "";
+					$changed_count++;
+				}
+								
+				if( $changed_count > 0 )
+				{
+					mysql_query( "UPDATE `Prep_tbl` SET `refAvailID`='" . $refAvail_tmp . "', "
+	//						. "`flag`='" . $flag_tmp . "', "
+							. "`comments`='" . $comments_tmp . "' "
+							. "WHERE `prepID`='" . $prepID_tmp . "' AND `status`='ACTIVE'", $conn )
+							or die( "FAILURE in process_modify (Updating Prep Info) SQL error: " . mysql_error() );
+				}
+				
+				
+				// 7. General Properties
+				foreach($_SESSION["stage2_general_req_ar"] as $pname => $pid)
+				{
+					$current_general_value_tmp = $_POST["well_mod_general" . $pid . "_text"][ $input_count ];
+					
+					if ($current_general_value_tmp != $general_tmp_ar[$pname])
+					{
+						$check_general_rs = mysql_query("SELECT * FROM `PrepElementProp_tbl` WHERE `elementTypeID`='" . $pid . "' AND `prepID`='" . $prepID_tmp . "' AND `status`='ACTIVE'", $conn) or die( "FAILURE IN Location_Well_Class.process_modify(7): " . mysql_error());
+
+						if( $check_general_ar = mysql_fetch_array( $check_general_rs, MYSQL_ASSOC ) )
+						{
+							// If the property type already exists in the database, modify the existing value
+							mysql_query("UPDATE `PrepElementProp_tbl` SET `value`='" . /*addslashes(*/ $current_general_value_tmp /*)*/ . "' WHERE `prepID`='" . $prepID_tmp . "' AND `elementTypeID`='" . $pid . "' AND `status`='ACTIVE' ", $conn) or die("FAILIURE IN Location_Well_Class.process_modify(8): " . mysql_error());
+						}
+						else
+						{
+							// If no property type exists, add as new!
+							mysql_query( "INSERT INTO `PrepElementProp_tbl` (`prepPropID`, `prepID`, `elementTypeID`,`value`, `status`) VALUES ('', '" . $prepID_tmp . "', '" . $pid . "', '" . $current_general_value_tmp  . "', 'ACTIVE')", $conn) or die("FAILIURE IN Location_Well_Class.process_modify(9): " . mysql_error());
+						}
+					}
+				}
+				
+				$input_count++;		
+			}	// end if(value_check_bool)
+			else
+			{
+				// Return to form page with error output
+				
+				// NEED: storage of all inputted values so user doesn't have to reinput them
+				$_SESSION["well_mod_rid_text"] = $_POST["well_mod_rid_text"];
+				$_SESSION["well_mod_comments_text"] = $_POST["well_mod_comments_text"];
+				$_SESSION["well_mod_flag_checkbox"] = $_POST["well_mod_flag_checkbox"];
+				$_SESSION["well_mod_refAvail_text"] = $_POST["well_mod_refAvail_text"];
+				
+				$_SESSION["well_mod_isoact_ar"] = array();
+				$_SESSION["well_mod_isoNum_ar"] = array();
+				$_SESSION["well_mod_beingUsed_ar"] = array();
+				
+				//foreach( $_SESSION["identifier_ar"] as $key => $value )
+				for( $key = 0; $key < sizeof( $_SESSION["identifier_ar"] ) ; $key++ )
+				{
+					$_SESSION["well_mod_isoNum_ar"][ $key ] = $_POST["well_mod_isoNum" . $key . "_textfield"];
+					$_SESSION["well_mod_beingUsed_ar"][ $key ] = $_POST["well_mod_beingUsed" . $key . "_checkbox"];
+				}
+				return false;
+			}
+			
+		}		// ADDED AUG 12/05 -- CLOSE WHILE LOOP
+
+		return true;
+	}
+	
+	/**
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param INT $count
+	 * @param STRING $set
+	 *
+	 * @return STRING
+	*/
+	function reset_set($count, $set)
+	{
+		if ($count > 0)
+		{
+			$set = substr($set, 0, strlen($set) - 2) . ")";
+		}
+		else
+		{
+			$set = "('')";
+		}
+
+		return $set;
+	}
+
+	
+	/**
+	 * Check to see if an experiment has been created for the given reagentID; if yes, return the expID; return 0 otherwise
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param INT $rid_tmp
+	 *
+	 * @return INT Experiment ID (value of expID column in Experiment_tbl)
+	*/
+	function backChecking_LIMSID_existance($rid_tmp)
+	{
+		global $conn;
+		
+		$expID_rs = mysql_query("SELECT * FROM `Experiment_tbl` WHERE `reagentID`='" . $rid_tmp . "' AND `status`='ACTIVE'", $conn) or die( "FAILURE IN backChecking_LIMSID_Existance(): " . mysql_error());
+		
+		if ($expID_ar = mysql_fetch_array($expID_rs, MYSQL_ASSOC))
+		{
+			return $expID_ar["expID"];
+		}
+		
+		return -1;
+	}
+	
+
+	/**
+	 * Check to see if a given reagentID exists as an experiment yet. If it does, return the expID; otherwise, create an existance of that reagentID in the experiment_tbl, and returns the new expID (differs from backChecking_LIMSID_existance() in that this function creates a new expID for this reagent; backChecking_LIMSID_existance() simply returns -1 if no expID found, without inserting)
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @param INT $rid_tmp
+	 *
+	 * @return INT Experiment ID (value of expID column in Experiment_tbl)
+	*/
+	function insert_new_expID($rid_tmp)
+	{
+		global $conn;
+		
+		$exp_check_rs = mysql_query("SELECT * FROM `Experiment_tbl` WHERE `reagentID`='" . $rid_tmp . "' AND `status`='ACTIVE'", $conn) or die("FAILURE IN insert_new_expID(): " . mysql_error());
+		
+		if ($exp_check_ar = mysql_fetch_array($exp_check_rs, MYSQL_ASSOC))
+		{
+			$lastid_tmp = $exp_check_ar["expID"];
+		}
+		else
+		{
+			mysql_query("INSERT INTO `Experiment_tbl` (`expID`, `reagentID`, `status`) VALUES ('', '" . $rid_tmp . "', 'ACTIVE')", $conn) or die( "FAILURE IN backChecking_LIMSID_EXistance() : " . mysql_error());
+	
+			$lastid_tmp = mysql_insert_id( $conn );
+		}
+
+		return $lastid_tmp;
+	}
+
+
+	/**
+	 * Check if a database record exists for the given experiment and isolate number
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param INT $expID_tmp
+	 * @param INT $isoID_tmp Not used in this function; relying on $value in query
+	 * @param INT $value
+	 *
+	 * @return INT Isolate number if found; -1 otherwise
+	*/
+	function backChecking_isoNum_duplicate($expID_tmp, $isoID_tmp, $value)
+	{
+		global $conn;
+		
+		$isoNum_rs = mysql_query("SELECT * FROM `Isolate_tbl` WHERE `expID`='" . $expID_tmp . "' AND `isolateNumber`='" . $value . "' AND `status`='ACTIVE'" , $conn) or die("FAILURE IN backChecking_isoNum() : " . mysql_error());
+
+		if( $isoNum_ar = mysql_fetch_array( $isoNum_rs, MYSQL_ASSOC ) )
+		{
+			return $isoNum_ar["isolate_pk"];
+		}
+		else
+		{
+			return -1;
+		}
+	}
+
+	/**
+	 * Check if the given isolate number is the selected isolate
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param INT $expID_tmp
+	 * @param INT $isoID_tmp
+	 * @param INT $value Not used in this function; relying on $isoID_tmp in query
+	 *
+	 * @return boolean
+	*/
+	function backChecking_beingUsed_duplicate($expID_tmp, $isoID_tmp, $value)
+	{
+		global $conn;
+		
+		$beingUsed_rs = mysql_query( "SELECT * FROM `Isolate_tbl` WHERE `expID`='" . $expID_tmp . "' "
+								. "AND `beingUsed`='YES' AND `status`='ACTIVE'", $conn )
+								or die("FAILURE IN backChecking_beingUsed() : " . mysql_error() );
+								
+		if( $beingUsed_ar = mysql_fetch_array( $beingUsed_rs, MYSQL_ASSOC ) )
+		{
+			if( $beingUsed_ar["isolate_pk"] == $isoID_tmp )
+			{
+				return false;
+			}
+			
+			return true;
+		}
+		
+		return false;
+	}
+	
+	/**
+	 * Extract isolate number from prep ID (e.g. V123-1 -- return isolate number 1) -- Think it's deprecated
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2005-08-12 Modified to handle the case where isolate number is not entered
+	 *
+	 * @param STRING $limsid
+	 *
+	 * @return STRING
+	*/
+	function getIsolateNumber($limsid)
+	{
+		if (strpos($limsid, "-"))
+		{
+			return substr($limsid, strpos($limsid, "-") + 1, strlen($limsid));
+		}
+		else
+		{
+			return $limsid;
+		}
+	}
+	
+	/**
+	 * Print radio buttons for selecting isolate -- Think it's deprecated
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	*/
+	function isoActiveEnabled_radio_buttons_here()
+	{
+		?>
+		<td>
+			<input type="radio" name="well_mod_isoact<?php echo $temp_count; ?>_radio" id="well_mod_isoact<?php echo $temp_count; ?>_radio"
+			<?php
+				
+				
+				if( $isIsolate_container )
+				{
+					echo " disabled checked ";
+				}
+				else
+				{
+					echo " disabled ";
+				}
+				
+			?>
+			value="YES" onClick="enable_isoActive(<?php echo $temp_count; ?>)"> Yes
+			<input type="radio" name="well_mod_isoact<?php echo $temp_count; ?>_radio"  id="well_mod_isoact<?php echo $temp_count; ?>_radio"
+			<?php
+				//if( $exp_tmp_ar["isolate_active"] == "NO" )
+				//{
+				//	echo " checked ";
+				//}
+				if( $isIsolate_container )
+				{
+					echo " disabled ";
+				}
+				else
+				{	
+					echo " disabled checked ";
+				}
+				
+			?>
+			value="NO" onClick="disable_isoActive(<?php echo $temp_count; ?>)"> No
+		</td>
+		<?php	
+	}
+}
+?>
diff --git a/OpenFreezer/Project.php b/OpenFreezer/Project.php
new file mode 100755
index 0000000..93d6423
--- /dev/null
+++ b/OpenFreezer/Project.php
@@ -0,0 +1,792 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2010 Pawson Laboratory, All Rights Reserved
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Project
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Include/require statements
+*/
+	include_once "Classes/MemberLogin_Class.php";
+	include_once "Classes/Member_Class.php";	
+	include_once "Classes/Session_Var_Class.php";
+	include_once "Classes/generalFunc_Class.php";	
+	include_once "Project/ProjectFunctions.php";
+	include_once "DatabaseConn.php";
+	include "Classes/StopWatch.php";
+	include "HeaderFunctions.php";
+
+/**
+ * Root file for Project module
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Project
+ *
+ * @copyright	2005-2010 Pawson Laboratory
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+	header("Cache-control: private"); //IE 6 Fix 
+
+	session_start();
+
+	$loginBlock = new MemberLogin_Class();
+	$loginBlock->loginCheck($_POST);
+
+	// print header	
+	outputMainHeader();
+
+	?>
+	<title>Project Page</title>
+
+	<table height="100%">
+		<table border="0" width="98%">
+			<!-- Marina: March 4/08: Create a resizeable border -->
+			<!--<tr>
+				<td rowspan="100%" style="padding-left:0; padding-right:5px;">
+					<div class="resizeable" onMouseOver="resize();"></div>
+				</td>
+			</tr>-->
+		<?php
+			if (isset($_SESSION["userinfo"]))
+			{
+				if( $loginBlock->verifyPermissions( basename( $_SERVER["PHP_SELF"] ), $_SESSION["userinfo"]->getUserID() ) ) 
+				{
+					$sessionChecker = new Session_Var_Class();
+// 					$sessionChecker->checkSession_reagent();
+					$sessionChecker->checkSession_all(); 	// july 17/07
+					unset($sessionChecker);
+
+					$currUserName = $_SESSION["userinfo"]->getDescription();
+
+					?>
+					<tr>
+						<td>
+						<?php	
+							if ($_GET["View"] == "1")
+							{
+								// Create project
+								printProjectCreationForm();
+							}
+							elseif ($_GET["View"] == "2")
+							{
+								// View Project
+								if (!isset($_GET["pid"]))
+								{
+									printViewProjectForm();
+								}
+							}
+							elseif ($_GET["View"] == "3")
+							{
+								// Delete project
+								if (isset($_GET["Success"]))
+								{
+									if ($_GET["Success"] == 1)
+									{
+										// success
+										echo "<span style=\"color:#FF0000; font-weight:bold\">Project deleted successfully.</span><BR/><BR/>";
+										echo "<a href=\"" . $_SERVER["PHP_SELF"]. "?View=2\">Back to Project list</a>";
+									}
+									else
+									{
+										// Project could not be deleted
+										echo "<span style=\"color:#FF0000; font-weight:bold\">Project " . $_GET["pID"] . " could not be deleted, since there are reagents associated with it.</span><BR/><BR/>";
+										
+										if (isset($_GET["pID"]))
+										{
+											//echo "<a href=\"" . $_SERVER["PHP_SELF"]. "?View=2&pid=" . $_GET["pID"] . "\">Back to Project Details</a>";
+											?>
+											<span class="linkShow" onClick="redirectToProjectDetailedView(<?php echo $_GET["pID"]; ?>)">Back to Project Details</span>
+											
+											<FORM id="viewProjectForm" method="POST" action="<?php echo $cgi_path . "project_request_handler.py"; ?>">
+												<INPUT type="hidden" id="view_packet_hidden" name="view_packet">
+												<INPUT type="hidden" ID="username_hidden" NAME="username" VALUE="<?php echo $currUserName; ?>">
+
+											</FORM>
+											<?php
+										}
+									}
+								}
+								else
+								{
+									printProjectDeletionForm($_GET["Result"]);
+								}
+							}
+							elseif ($_GET["View"] == "4")
+							{
+								// Detailed Project View, incl. Modification
+								
+								// Page content was generated by Python and stored in a file
+								/*
+								if (isset($_GET["fd"]) && $_GET["fd"] != "")
+								{
+									$project_file = "/tmp/tmp" . $_GET["fd"] . ".html";
+									//$project_file = "pictures/project.html";
+									$project_fh = fopen($project_file, 'r');
+									$project_page = fread($project_fh, filesize($project_file));
+									echo $project_page;
+									
+									// delete temp file
+									unlink($project_file);
+								}*/
+							}
+						?>
+						</td>
+					</tr>
+					<?php
+				}
+				else
+				{					
+					echo "<tr><td class=\"warning\">";
+					echo "You are not authorized to view this page.  Please contact the site administrator.";
+					echo "</td></tr>";
+				}
+			}
+			else
+			{
+				echo "<tr><td class=\"warning\">";
+				echo "You need to log in to access this page.";
+				echo "</td></tr>";
+			}
+		?>	
+		</table>
+	</table>
+	<?php
+
+	outputMainFooter();
+	
+/*********************************************************************
+	FUNCTIONS
+*********************************************************************/
+/**
+ * Output project creation page
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+*/
+function printProjectCreationForm()
+{
+	global $cgi_path;
+	
+	$currUserName = $_SESSION["userinfo"]->getDescription();
+
+	?>
+	<FORM NAME="create_project_form" METHOD="POST" ACTION="<?php echo $cgi_path . "project_request_handler.py"; ?>" onSubmit="return verifyProjectOwner('projectOwnersList') && verifyProjectName('packet_name') && verifyProjectDescr('packet_descr') && verifyMembers('readers_target_list') && verifyMembers('writers_target_list');">
+		
+		<!-- Pass user info as a hidden form value to Python -->
+		<INPUT type="hidden" ID="username_hidden" NAME="username" VALUE="<?php echo $currUserName; ?>">
+		
+		<DIV style="width:775px; font-weight:bold; color:#0000FF; text-align:center; padding-bottom: 5px;">CREATE A NEW PROJECT</DIV>
+
+		<TABLE width="775px" cellpadding="4" cellspacing="2">
+		
+			<TH colspan="3" style="text-align:left; color:#0000FF; border-top: 1px groove black; padding-top: 10px;">
+				Project Details:
+			</TH>
+
+
+			<TR>
+				<TD class="createViewColName">
+					Project ID
+				</TD>
+
+				<TD colspan="2" class="createViewColValue">
+					<?php echo getMaxProjectID(); ?>
+					<INPUT TYPE="HIDDEN" NAME="packetID" VALUE="<?php echo getMaxProjectID(); ?>">
+				</TD>
+			</TR>
+			
+			<TR>
+				<TD class="createViewColName">
+					Project Owner
+					<span style="font-size:10pt; color:#FF0000; font-weight:bold">*</span>
+				</TD>
+
+				<TD colspan="2" class="createViewColValue">
+				
+					<SELECT ID="projectOwnersList" NAME="packetOwner">
+
+						<OPTION selected value="default">Select project owner</OPTION>
+					
+						<?php 
+							// Modified June 19/07, Marina: Show CREATORS in owners list - writers will be shown in members list further down
+							$creators = getCreatorsList();
+							
+							foreach ($creators as $key => $value)
+							{
+								// Pre-select current user's name by default
+								if ($key == $_SESSION["userinfo"]->getUserID())
+								{
+									echo "<OPTION SELECTED value=\"" . $key . "\">" . $value . "</OPTION>";
+								}
+								else
+								{
+									echo "<OPTION value=\"" . $key . "\">" . $value . "</OPTION>";
+								}
+							}
+						?>
+					</SELECT>
+
+					<DIV ID="projectOwnerWarning" STYLE="display:none; color:#FF0000; font-weight:normal;">
+						<BR>Please select a name from the list above.
+					</DIV>
+				</TD>
+			</TR>
+
+			<TR>
+				<TD class="createViewColName">
+					<a name="select_members"></a>
+					Project Name
+					<span style="font-size:10pt; color:#FF0000; font-weight:bold">*</span>
+				</TD>
+
+				<TD colspan="2" class="createViewColValue">
+					<INPUT TYPE="TEXT" SIZE="35px" id="packet_name" NAME="packetName">
+
+					<DIV ID="projectNameWarning" STYLE="display:none; color:#FF0000; font-weight:normal;">
+						<BR>Please provide a project name.
+					</DIV>
+				</TD>
+			</TR>
+
+			<TR>
+				<TD class="createViewColName" nowrap>
+					Project Description
+
+					<!-- June 3, 2010: make description mandatory too -->
+					<span style="font-size:10pt; color:#FF0000; font-weight:bold">*</span>
+				</TD>
+
+				<TD colspan="2" class="createViewColValue" style="padding-bottom: 10px;">
+					<INPUT TYPE="TEXT" SIZE="75px" NAME="packetDescription" id="packet_descr">
+
+					<DIV ID="projectDescrWarning" STYLE="display:none; color:#FF0000; font-weight:normal;">
+						<BR>Please provide a project description.
+					</DIV>
+				</TD>
+			</TR>
+			
+			
+			<TR>
+				<TD class="createViewColName">
+					Access type:
+				</TD>
+
+				<TD colspan="2" style="padding-bottom: 10px;">
+					  <INPUT TYPE="RADIO" NAME="private_or_public" VALUE="public">Public         
+					<INPUT TYPE="RADIO" NAME="private_or_public" VALUE="private" checked>Private
+				</TD>
+			</TR>
+			
+			<TR>
+				<TD colspan="2" style="font-size:8pt; font-weight:bold;">
+					A Public project means that reagents in this project may be viewed by ALL OpenFreezer users.  Declaring a project Private hides its content from users who are not explicit members in this project.  Modification of both Public and Private project content is restricted to project members with write access.
+				</TD>
+			</TR>
+			
+			
+			<TR>
+				<TD colspan="3" style="font-weight:bold; text-align:left; color:#0000FF; padding-top: 10px; border-top: 1px groove black;">
+						Project Members:
+				</TD>
+			</TR>
+
+			<tr>
+				<td colspan="3" style="padding-top:8px; font-weight:bold;">
+					Assign members from one or more of the following laboratories to this project:
+				</td>
+			</tr>
+
+			<TR>
+				<td style="vertical-align:top; padding-top:10px" nowrap colspan="3">
+					Laboratory:   
+					
+					<?php 
+						// Modified July 3/07: Show only labs with WRITE access --> Aug 17/07: No, show all labs
+						//$writerCategoryID = findCategoryID("Writer");
+						printLabList();
+					?>
+					<BR/>
+					<P style="margin-top:15px">Members:</span>
+				</td>
+			</tr>
+
+			<tr>
+				<td style="vertical-align:top; padding-top:10px; width:200px; padding-left:10px; white-space:nowrap">
+					<P>
+					<?php
+						$labList = getLabList();
+						$currLabID = $_SESSION["userinfo"]->getLabID();
+
+						foreach ($labList as $labID => $labName)
+						{
+							$display = ($labID == $currLabID) ? "inline" : "none";
+
+							$users = getAllUsers($labID);
+							
+							echo "<SELECT id=\"lab_source_list_" . $labID . "\" name=\"labSourceMembers_" . $labID . "\" multiple size=\"10\"  style=\"display: " . $display . "\">";
+
+							foreach ($users as $key => $value)
+							{
+								echo "<OPTION id=\"user_" . $key . "_lab_" . $labID . "\" value=\"" . $key . "\">" . $value . "</OPTION>";
+							}
+
+							echo "</SELECT>";
+						}
+					?>
+					</P>
+					<!-- April 3/09: Changed function name from selectAllUsers() to selectAll() (renamed function in menu.js for generalization, it can be used to select all elements in any list, not just Users) -->
+					<INPUT TYPE="checkbox" onClick="selectAll(this.id, 'lab_source_list_' + getSelectedLab())" id="add_all_chkbx"> Select All Members</INPUT>
+				</td>
+			
+				<TD style="vertical-align:top; padding-top:15px; padding-left:15px; ">
+
+					For selected members, define their access level to this project:<BR/>
+
+					<P style="font-size:9pt; margin-top:5px;">
+						<input type="radio" id="access_level_radio_read" name="access_levels" value="read" checked>Read-Only    
+						<input type="radio" id="access_level_radio_write" name="access_levels" value="write">Write    
+						<input style="margin-top:4px" onclick="addMembers('lab_source_list_' + getSelectedLab(), getSelectedRole('1'))" value="Go" type="button"></INPUT>
+						<BR/>
+					</P>
+					
+					<P style="font-size: 8pt; border-top: 1px groove black; padding-top: 5px; padding-bottom: 5px">
+						Access levels: <BR/><BR/>
+
+						<span style="font-size: 8pt; margin-left: 9px; font-weight:bold; ">- Read-Only:</span>  May view reagents in this project but may NOT modify them or add new reagents<BR/>
+
+						<span style="font-size: 8pt; margin-left: 9px; font-weight:bold;">- Write:</span>  May create and modify reagents in this project but may NOT change project details or add/remove members to/from this project<BR/>
+
+						<P><span style="font-size: 8pt; font-weight:bold; color:#FF0000; text-align:center"><u>Please note</u>: Only users who have at least Write access to OpenFreezer may be added to the writers list
+					</P>
+				</TD>
+			</tr>
+
+			<tr>
+				<TD colspan="3" style="padding-top:10px; border-top: 1px groove black">
+				
+					<table width="750px">
+					
+						<th colspan="3" style="text-align:left; padding-bottom:5px; border-bottom: 1px solid black">
+							Members currently assigned to this project:<BR/>
+							<span style="font-weight:normal">(You may edit the lists by selecting member names and choosing an action below)</span>
+						</th>
+						
+						<tr>
+							<td style="padding-left:5px; padding-top:5px; padding-bottom:5px; border-right: 1px solid black" width="240px">
+								<span style="font-size:8pt; font-weight:bold;">Readers:</span><BR/>
+								<SELECT style="margin-top:5px;" id="readers_target_list" name="readersTargetList" multiple size="12"></SELECT><BR/>
+								
+								<!-- April 3/09: Changed function name from selectAllUsers() to selectAll() (renamed function in menu.js for generalization, it can be used to select all elements in any list, not just Users) -->
+								<INPUT TYPE="checkbox" style="margin-top:10px" onClick="selectAll(this.id, 'readers_target_list')" id="select_all_reader_chkbx"> Select All</INPUT>
+							</td>
+							
+							<!-- June 20/2007 -->
+							<td width="180px" style="text-align:center; border-right: 1px solid black">
+								<input onclick="addMembers('readers_target_list', 'write')" value="   Make Writer >>" type="button"></INPUT><BR/>
+								<input style="margin-top:30px;" onclick="addMembers('writers_target_list', 'read')" value="<< Make Reader" type="button"></INPUT><BR/>
+								<input style="margin-top:30px;" onclick="removeProjectMembers()" value="Remove Selected" type="button"></INPUT>
+							</td>
+							
+							<td style="padding-left:30px; padding-top:5px; padding-bottom:5px;">
+								
+								<span style="font-size:8pt; font-weight:bold;">Writers:</span><BR/>
+								
+								<SELECT style="margin-top:5px;" id="writers_target_list" name="writersTargetList" multiple size="12"></SELECT><BR/>
+								
+								<!-- April 3/09: Changed function name from selectAll() to selectAll() (renamed function in menu.js for generalization, it can be used to select all elements in any list, not just Users) -->
+								<INPUT style="margin-top:10px;" TYPE="checkbox" onClick="selectAll(this.id, 'writers_target_list')" id="select_all_writer_chkbx"> Select All</INPUT>
+							</td>
+						
+						</tr>
+					</table>
+				</td>
+			</tr>
+						
+			<TR>
+				<TD colspan="3" style="padding-top:10px; border-top: 1px groove black;">
+					<INPUT TYPE="SUBMIT" NAME="create_project" VALUE="Create Project" onClick="addProjectOwnerToWritersList(); selectAllElements('readers_target_list'); selectAllElements('writers_target_list'); alert('Please note: If your project writers list contains names of users who have read-only access to OpenFreezer, their names will be removed from the list during saving.'); ">
+				</TD>
+			</TR>
+		</TABLE>
+	</FORM>
+	<?php
+}
+
+/**
+ * Fetch the NEXT highest project ID from the database (i.e. highest project ID + 1)
+ *
+ * Do NOT check status; e.g. if there are 16 packets in total, and packet 9 is DEP, the new project ID would be 17 and not 9 (i.e. DEP PACKETS ARE **NOT** REPLACED!!!)
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @return INT
+*/
+function getMaxProjectID()
+{
+	global $conn;
+	
+	$newProjectID = 0;
+	
+	// Fetch the next highest project ID, WITHOUT checking status; e.g. if there are 16 packets in total, and packet 9 is DEP, the new project ID would be 17 and not 9 (i.e. DEP PACKETS ARE **NOT** REPLACED!!!)
+	$project_set = mysql_query("SELECT MAX(packetID) AS projectID FROM Packets_tbl", $conn) or die("Cannot fetch maximum project ID: " . mysql_error());
+	
+	if ($project_ar = mysql_fetch_array($project_set, MYSQL_ASSOC))
+	{
+		$newProjectID = $project_ar["projectID"] + 1;
+	}
+	
+	return $newProjectID;
+}
+
+
+/**
+ * Fetch the list of all users who belong to category 'Creators'
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @return Array Dictionary of (userID => username) tuples
+*/
+function getCreatorsList()
+{
+	global $conn;
+
+	$writers = array();
+	
+	$writers_rs = mysql_query("SELECT userID, CONCAT(u.firstname, \" \", u.lastname) AS username FROM Users_tbl u, UserCategories_tbl c WHERE c.category = 'Creator' AND u.category <= c.categoryID AND c.status='ACTIVE' AND u.description <>'' AND u.firstname <>'' AND u.lastname <>'' AND u.status='ACTIVE' ORDER BY username", $conn) or die("Cannot fetch creators: " . mysql_error());
+	
+	while ($writers_ar = mysql_fetch_array($writers_rs, MYSQL_ASSOC))
+	{
+		$uid = $writers_ar["userID"];
+		$username = $writers_ar["username"];
+		$writers[$uid] = $username;
+	}
+
+	return $writers;
+}
+
+
+/**
+ * Select all users from the lab identified by $labID
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @return Array Dictionary of (userID => full person name) tuples (i.e. '1' => 'John Doe')
+*/
+function getAllUsers($labID)
+{
+	global $conn;
+
+	$users = array();
+	
+	// August 17/07, Marina: Select ALL users in a lab, not only >= 'writers'
+	$users_rs = mysql_query("SELECT userID, username, CONCAT(firstname, \" \", lastname) AS uname FROM Users_tbl WHERE labID='" . $labID . "' AND status='ACTIVE' ORDER BY uname", $conn) or die("Cannot fetch users: " . mysql_error());
+	
+	while ($users_ar = mysql_fetch_array($users_rs, MYSQL_ASSOC))
+	{
+		$uid = $users_ar["userID"];
+		$username = $users_ar["username"];
+		$uname = $users_ar["uname"];
+		
+		if ( strlen(trim($uname)) > 0 && $username != 'guest' )
+		{
+			$users[$uid] = $uname;
+		}
+	}
+	
+	return $users;
+}
+
+/**
+ * Print project deletion form -- NOT actively used in this version
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param STRING $success
+*/
+function printProjectDeletionForm($success="")
+{
+	global $cgi_path;
+	
+	$currUserID = $_SESSION["userinfo"]->getUserID();
+	$currUserName = $_SESSION["userinfo"]->getDescription();
+	$currUserCategory = $_SESSION["userinfo"]->getCategory();
+
+	// Show ALL projects for Admins; and only projects owner by current user for users with lower access privileges
+	// Therefore, if user is not admin, check if they own any projects.  If they don't, don't output a deletion form for them at all
+	$currUserProjects = getAllUserProjects($currUserID);
+	
+	// Now, an owner can delete all of his/her projects and be left with 0 - but we don't want to show a warning in this case!  So check if we're here after deletion has taken place. If 'success' argument is an empty string, deletion has not yet been attempted, in which case can issue a zero-projects warning
+	if ($success == "")
+	{
+		// hard-coding categirt value '1' for 'Admin' - selection easy but change at first opportunity
+		if ( ($currUserCategory == '1') || (count($currUserProjects) > 0) )
+		{
+			?>
+			<FORM METHOD="POST" ACTION="<?php echo $cgi_path . "project_request_handler.py"; ?>" onSubmit="return verifyProjectDeletion('packetList', 'delete_project');">
+
+				<!-- HACK: Pass user info as a hidden form value - can't think of a better way to pass it through session from PHP to Python -->
+				<INPUT type="hidden" ID="username_hidden" NAME="username" VALUE="<?php echo $currUserName; ?>">
+
+				<TABLE width="773px" border="1px" frame="box" rules="none" cellpadding="5">
+
+					<TH class="title">
+						DELETE A PROJECT
+					</TH>
+
+					<TR>
+						<TD>
+							<FIELDSET>			
+								<LEGEND> Please select one or more projects that you wish to delete: </LEGEND>
+
+									<P><div class="warning" id="project_warning"> Please select one ore more Project IDs from the dropdown list</div></P>
+									<?php
+										printPacketList(1, "", 1);
+									?>
+								</LEGEND>			
+							</FIELDSET>
+						</TD>
+					</TR>
+
+					<TR>
+						<TD>
+							<P>		
+								<INPUT TYPE="SUBMIT" NAME="delete_project" VALUE="Delete Selected Projects">
+							</P>
+						</TD>
+					</TR>
+				</TABLE>
+			</FORM>
+			<?php
+		}
+		else
+		{
+			echo "<span style=\"font-weight:bold\">Only project owners or administrators are authorized to delete projects.</span><BR/><BR/><BR/><BR/><BR/><BR/><BR/><BR/><BR/><BR/>";
+		}
+	}
+}
+
+/**
+ * Retrive all projects owned by the user identified by $userID
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @return Array List of project IDs
+*/
+function getAllUserProjects($userID)
+{
+	global $conn;
+	
+	$userProjects = array();
+	$currUserID = $_SESSION["userinfo"]->getUserID();
+	
+	$query = "SELECT p.packetID as packetID, p.packetName as packetName, u.lastname as owner FROM Packets_tbl p, Users_tbl u WHERE p.ownerID='" . $currUserID . "' AND p.ownerID=u.userID AND p.status='ACTIVE'";	
+	$find_name_rs = mysql_query($query, $conn) or die("Error fetching packet ID:" . mysql_error());
+
+	while ($find_name_ar = mysql_fetch_array($find_name_rs, MYSQL_ASSOC))
+	{
+		$userProjects[] = $find_name_ar["packetID"];
+	}
+	
+	return $userProjects;
+}
+
+/**
+ * Output project selection page (print dropdown list of projects accessible by the user; redirect to details page for selected project)
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+*/
+function printViewProjectForm()
+{
+	global $cgi_path;
+	global $conn;
+	
+	$currUserName = $_SESSION["userinfo"]->getDescription();
+	$currUserID = $_SESSION["userinfo"]->getUserID();
+	?>
+	<FORM METHOD="POST" ACTION="<?php echo $cgi_path . "project_request_handler.py"; ?>" onSubmit="return verifyProject();">
+		
+		<!-- Pass user info as a hidden form value to Python -->
+		<INPUT type="hidden" ID="username_hidden" NAME="username" VALUE="<?php echo $currUserName; ?>">
+		
+		<TABLE width="775px" border="1px" frame="box" rules="none" cellpadding="5">
+		
+			<TH colspan="2" class="title">
+				SELECT A PROJECT TO VIEW AND MODIFY
+			</TH>
+
+			<TR>
+				<TD colspan="2">
+					<FIELDSET>
+						<LEGEND> Please select a project for viewing and/or modification: </LEGEND>
+						
+						<TABLE>
+							<TR>
+								<TD>
+									<?php
+									$currUserCategory = $_SESSION["userinfo"]->getCategory();
+
+									// Show ALL projects for Admins; for users with lower access privileges only show projects accessible by current user
+									if ($currUserCategory == $_SESSION["userCategoryNames"]['Admin'])
+									{
+										printPacketList(0);
+									}
+									else
+									{
+										// Select projects current user is member of, plus all public projects
+										$uProject_set = mysql_query("SELECT DISTINCT p.packetID as packetID, p.packetName as packetName, u.lastname as owner FROM ProjectMembers_tbl m, Packets_tbl p, Users_tbl u WHERE m.memberID='" . $currUserID . "' AND p.ownerID=u.userID AND m.packetID=p.packetID AND p.status='ACTIVE' UNION SELECT DISTINCT p.packetID as packetID, p.packetName as packetName, u.lastname as owner FROM Packets_tbl p, Users_tbl u WHERE p.is_private='FALSE' AND p.ownerID=u.userID AND p.status='ACTIVE' ORD [...]
+
+										while ($uProjects = mysql_fetch_array($uProject_set, MYSQL_ASSOC))
+										{
+											$pID = $uProjects["packetID"];
+											$temp_packet = $pID . ": " . $uProjects["owner"] . ": " . $uProjects["packetName"];
+											$userProjects[$pID] = $temp_packet;
+										}
+
+										// Alternatively, the user may be a project owner, in which case there would be no explicit entry in ProjectMembers_tbl
+										$owner_set = mysql_query("SELECT DISTINCT p.packetID as packetID, p.packetName as packetName, u.lastname as owner FROM Packets_tbl p, Users_tbl u  WHERE p.ownerID='" . $currUserID . "' AND p.ownerID=u.userID AND p.status='ACTIVE' ORDER BY p.packetID") or die("Cannot fetch user projects: " . mysql_error());
+
+										while ($owners = mysql_fetch_array($owner_set, MYSQL_ASSOC))
+										{
+											$pID = $owners["packetID"];
+											$temp_packet = $pID . ": " . $owners["owner"] . ": " . $owners["packetName"];
+											$userProjects[$pID] = $temp_packet;
+										}
+										
+										$userProjects = array_unique($userProjects);
+										
+										echo "<SELECT id=\"packetList\" name=\"packets\">";
+										echo "<OPTION value=\"0\">Select Project</OPTION>";
+
+										foreach ($userProjects as $pID => $project)
+										{
+											echo "<OPTION value=\"" . $pID . "\">" . $project . "</OPTION>";
+										}
+										
+										echo "</SELECT>";
+									}
+									?>
+								</TD>
+							</TR>
+						</TABLE>
+
+						<div class="warning" id="project_warning"> Please select a Project ID from the dropdown list to view</div>
+
+					</FIELDSET>
+				</TD>
+			</TR>
+						
+			<TR>
+				<TD style="padding-left:25px;">
+					<P>		
+						<INPUT TYPE="SUBMIT" id="viewProject" NAME="view_project" VALUE="Go">
+					</P>
+				</TD>
+			</TR>
+		</TABLE>
+	</FORM>
+	<?php
+}
+
+/**
+ * Output list of laboratories
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param STRING $oper List action (not actively used in this version)
+*/
+function printLabList($oper="")
+{
+	global $conn;
+	
+	$labList = array();
+
+	$labList_rs = mysql_query("SELECT labID, lab_name FROM LabInfo_tbl WHERE status='ACTIVE' ORDER BY lab_name", $conn) or die("Error selecting labs: " . mysql_error());
+	
+	while ($labList_ar = mysql_fetch_array($labList_rs, MYSQL_ASSOC))
+	{
+		$labID = $labList_ar["labID"];
+		$labName = $labList_ar["lab_name"];
+		
+		$labList[$labID] = $labName;
+	}
+	
+	$currLabID = $_SESSION["userinfo"]->getLabID();
+	
+	echo "<SELECT id=\"labList\" name=\"labs\" onChange=\"showLabMembersList()\">";
+
+	foreach ($labList as $key => $value)
+	{
+		$selected = ($key == $currLabID) ? "selected" : "";
+
+		?>
+		<OPTION ID="<?php echo $key; ?>" NAME="lab_optn" VALUE="<?php echo $key; ?>" <?php echo $selected; ?>>
+		<?php 
+			echo $value; 
+		?>		
+		</OPTION>
+		<?php
+	}
+
+	echo "</SELECT>";
+}
+
+/**
+ * Retrieve all laboratories from the database
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @return Array Dictionary of (labID => labName) tuples
+*/
+function getLabList()
+{
+	global $conn;
+
+	$lab_rs = mysql_query("SELECT labID, lab_name FROM LabInfo_tbl WHERE status='ACTIVE' ORDER BY lab_name", $conn) or die("Cannot select labs: " . mysql_error());
+
+	$labs = array();
+
+	while ($lab_ar = mysql_fetch_array($lab_rs, MYSQL_ASSOC))
+	{
+		$labID = $lab_ar["labID"];
+		$labName = $lab_ar["lab_name"];
+
+		$labs[$labID] = $labName;
+	}
+
+	return $labs;
+}
+mysql_close($conn);
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Project/ProjectFunctions.php b/OpenFreezer/Project/ProjectFunctions.php
new file mode 100755
index 0000000..725916e
--- /dev/null
+++ b/OpenFreezer/Project/ProjectFunctions.php
@@ -0,0 +1,615 @@
+<?php
+/**
+*
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Project
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3*/
+
+/**
+* Include/require statements
+*/
+include_once "Classes/Member_Class.php";
+include_once "Classes/Project_Class.php";
+include_once "User/UserFunctions.php";
+
+/**
+ * Various project-related functions
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Project
+ *
+ * @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+// Jan. 7, 2010: Still, queries do not include public projects.  See where should add UNION and where not
+
+/**
+ * Get all projects the user is a member of
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param INT $userID Database ID of the user currently logged in
+ * @return Array List of project IDs
+*/
+function getUserProjectIDs($userID)
+{
+	global $conn;
+	$userProjectIDs = array();
+	
+	$uProject_set = mysql_query("SELECT packetID FROM ProjectMembers_tbl WHERE memberID='" . $userID . "' AND status='ACTIVE' UNION (SELECT packetID FROM Packets_tbl WHERE is_private='FALSE' AND status='ACTIVE')", $conn) or die("Cannot fetch user projects: " . mysql_error());
+	
+	while ($uProjects = mysql_fetch_array($uProject_set, MYSQL_ASSOC))
+	{
+		$userProjectIDs[] = $uProjects["packetID"];
+	}
+	
+	mysql_free_result($uProject_set);
+	unset($uProjects);
+
+	// Alternatively, the user may be a project owner, in which case there would be no explicit entry in ProjectMembers_tbl
+	$owner_set = mysql_query("SELECT packetID FROM Packets_tbl WHERE ownerID='" . $userID . "' AND status='ACTIVE' UNION (SELECT packetID FROM Packets_tbl WHERE is_private='FALSE' AND status='ACTIVE')");
+	
+	while ($owners = mysql_fetch_array($owner_set, MYSQL_ASSOC))
+	{
+		$userProjectIDs[] = $owners["packetID"];
+	}
+	
+	mysql_free_result($owner_set);
+	unset($owners);
+
+	return $userProjectIDs;
+}
+
+
+/**
+ * Same as getUserProjectIDs, but return a list of Project OBJECTS
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1 2007-08-15
+ *
+ * @param INT $userID Database ID of the user currently logged in
+ * @return Array List of project OBJECTS
+*/
+function getUserProjects($userID)
+{
+	global $conn;
+	$userProjects = array();
+	
+	$uProject_set = mysql_query("SELECT m.packetID, p.packetName, p.ownerID, p.packetDescription, p.is_private, u.lastname FROM Packets_tbl p, ProjectMembers_tbl m, Users_tbl u WHERE m.memberID='" . $userID . "' AND p.packetID=m.packetID AND p.ownerID=u.userID AND p.status='ACTIVE' AND m.status='ACTIVE'", $conn) or die("Cannot fetch user projects: " . mysql_error());
+	
+	while ($uProjects = mysql_fetch_array($uProject_set, MYSQL_ASSOC))
+	{
+		$packetID = $uProjects["packetID"];
+		$packetName = $uProjects["packetName"];
+		$packetOwnerID = $uProjects["ownerID"];
+		$packetOwnerName = $uProjects["lastname"];
+		$pDescr = $owners["packetDescription"];
+		$is_private = $owners["is_private"];
+
+		$tmpOwner = new Member_Class($packetOwnerID);
+		$tmpOwner->setLastName($packetOwnerName);
+		
+		$isPrivate = (strcasecmp($is_private, "TRUE") == 0) ? true : false;
+
+		$tmpProject = new Project($packetID, $packetName, $tmpOwner, $pDescr, $isPrivate);
+		$userProjects[$packetID] = $tmpProject;
+	}
+
+	mysql_free_result($uProject_set);
+	unset($uProjects);
+	
+	// Alternatively, the user may be a project owner, in which case there would be no explicit entry in ProjectMembers_tbl
+	$owner_set = mysql_query("SELECT packetID, packetName, lastname, packetDescription, is_private FROM Packets_tbl p, Users_tbl u WHERE p.ownerID='" . $userID . "' AND p.ownerID=u.userID AND p.status='ACTIVE'", $conn) or die("Could not select project owners: " . mysql_error());
+	
+	while ($owners = mysql_fetch_array($owner_set, MYSQL_ASSOC))
+	{
+		$packetID = $owners["packetID"];
+		$packetName = $owners["packetName"];
+		$lastname = $owners["lastname"];
+		$pDescr = $owners["packetDescription"];
+		$is_private = $owners["is_private"];
+
+		$tmpOwner = new Member_Class($userID);
+		$tmpOwner->setLastName($lastname);
+		
+		$isPrivate = (strcasecmp($is_private, "TRUE") == 0) ? true : false;
+
+		$tmpProject = new Project($packetID, $packetName, $tmpOwner, $pDescr, $isPrivate);
+		$userProjects[$packetID] = $tmpProject;
+	}
+	
+	mysql_free_result($owner_set);
+	unset($owners);
+
+	return $userProjects;
+}
+
+/**
+ * Retrieve all projects for users with the given role (one of 'Reader' or 'Writer')
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param INT $userID Database ID of the user currently logged in
+ * @param $role One of 'Reader' or 'Writer'
+ * @return Array List of project IDs
+*/
+function getUserProjectsByRole($userID, $role)
+{
+	global $conn;
+	$userProjects = array();
+
+	// Jan. 7, 2010: include public projects
+	if ($role == 'Reader')
+		$uProject_set = mysql_query("SELECT packetID FROM ProjectMembers_tbl WHERE memberID='" . $userID . "' AND role='" . $role . "' AND status='ACTIVE' UNION (SELECT packetID FROM Packets_tbl WHERE is_private='FALSE' AND status='ACTIVE')", $conn) or die("Cannot fetch user projects: " . mysql_error());
+	else
+		$uProject_set = mysql_query("SELECT packetID FROM ProjectMembers_tbl WHERE memberID='" . $userID . "' AND role='" . $role . "' AND status='ACTIVE'", $conn) or die("Cannot fetch user projects: " . mysql_error());
+	
+	while ($uProjects = mysql_fetch_array($uProject_set, MYSQL_ASSOC))
+	{
+		$userProjects[] = $uProjects["packetID"];
+	}
+	
+	// Alternatively, the user may be a project owner, in which case there would be no explicit entry in ProjectMembers_tbl
+	if ($role == 'Reader')
+		$owner_set = mysql_query("SELECT packetID FROM Packets_tbl WHERE ownerID='" . $userID . "' AND status='ACTIVE' UNION (SELECT packetID FROM Packets_tbl WHERE is_private='FALSE' AND status='ACTIVE')", $conn) or die("Cannot fetch project owner: " . mysql_error());
+	else
+		$owner_set = mysql_query("SELECT packetID FROM Packets_tbl WHERE ownerID='" . $userID . "' AND status='ACTIVE'", $conn) or die("Cannot fetch project owner: " . mysql_error());
+	
+	while ($owners = mysql_fetch_array($owner_set, MYSQL_ASSOC))
+	{
+		$userProjects[] = $owners["packetID"];
+	}
+	
+	return array_unique($userProjects);
+}
+
+/**
+ * Retrieve all the projects in OpenFreezer
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @return Array List of project IDs
+*/
+function findAllProjects()
+{
+	global $conn;
+	
+	$allProjects = array();
+	
+	$project_set = mysql_query("SELECT packetID FROM Packets_tbl WHERE status='ACTIVE'", $conn) or die("Cannot fetch all projects: " . mysql_error());
+	
+	while ($projects = mysql_fetch_array($project_set, MYSQL_ASSOC))
+	{
+		$allProjects[] = $projects["packetID"];
+	}
+
+	$allProjects[] = 0;		// feb. 24/10
+
+	return $allProjects;
+}
+
+
+/**
+ * Retrieve all the **public** projects in OpenFreezer
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1 2010-08-07
+ *
+ * @return Array List of project OBJECTS (mimics Python implementation)
+*/
+function getPublicProjects()
+{
+	global $conn;
+	
+	$publicProjects = array();
+	
+	$public_rs = mysql_query("SELECT packetID, packetName, ownerID, lastname, packetDescription FROM Packets_tbl p, Users_tbl u WHERE is_private='FALSE' AND p.ownerID=u.userID AND p.status='ACTIVE'", $conn) or die("Cannot select public projects: " . mysql_error());
+	
+	while ($public_ar = mysql_fetch_array($public_rs, MYSQL_ASSOC))
+	{
+		$pID = $public_ar["packetID"];
+		$pName = $public_ar["packetName"];
+		$pDesc = $public_ar["packetDescription"];
+		
+		// owner
+		$pOwnerID = $public_ar["ownerID"];
+		$ownerName = $public_ar["lastname"];
+		$pOwner = new Member_Class($pOwnerID);
+		$pOwner->setLastName($ownerName);
+		$newProject = new Project($pID, $pName, $pOwner, $pDesc, true);
+		
+		$publicProjects[] = $newProject;
+	}
+	
+	return $publicProjects;
+}
+
+
+/**
+ * Return a list of IDs of all projects user can view - i.e. all projects s/he is at least a reader on, plus all public projects
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param INT $userID ID
+ * @return Array List of project IDs
+*/
+function getAllowedUserProjectIDs($userID)
+{
+	global $conn;
+
+	$uCat = getUserCategory($userID);
+
+	// Show all projects for Admin
+	if (strcasecmp($uCat, $_SESSION["userCategoryNames"]["Admin"]) == 0)
+	{
+		return findAllProjects();
+	}
+	else
+	{
+		// For non-Admin users, allow access to projects owned by them, public projects, and/or projects they're members of
+		$userProjects = array();
+
+		$uProject_set = mysql_query("SELECT DISTINCT packetID FROM ProjectMembers_tbl WHERE memberID='" . $userID . "' AND status='ACTIVE' UNION SELECT DISTINCT packetID FROM Packets_tbl WHERE is_private='FALSE' AND status='ACTIVE'", $conn) or die("Cannot fetch user projects: " . mysql_error());
+	
+		while ($uProjects = mysql_fetch_array($uProject_set, MYSQL_ASSOC))
+		{
+			$pID = $uProjects["packetID"];
+			$userProjects[] = $pID;
+		}
+	
+		// Alternatively, the user may be a project owner, in which case there would be no explicit entry in ProjectMembers_tbl
+		$owner_set = mysql_query("SELECT DISTINCT packetID FROM Packets_tbl WHERE ownerID='" . $userID . "' AND status='ACTIVE'") or die("Cannot fetch user projects: " . mysql_error());
+	
+		while ($owners = mysql_fetch_array($owner_set, MYSQL_ASSOC))
+		{
+			$pID = $owners["packetID"];
+			$userProjects[] = $pID;
+		}
+		
+		$userProjects = array_unique($userProjects);
+	
+		return $userProjects;
+	}
+}
+
+/**
+ * Retrieve from the database the project number of the given reagent, identified by $rid
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param INT $rid
+ * @return INT
+*/
+function getReagentProjectID($rid)
+{
+	global $conn;
+	$currReagentPacketID = 0;
+
+	$rfunc_obj = new Reagent_Function_Class();
+
+	// update March 1, 2010
+	$packetPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["packet id"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+
+	$project_rs = mysql_query("SELECT p.propertyValue as packetID FROM ReagentPropList_tbl p WHERE p.propertyID='" . $packetPropID . "' AND p.reagentID='" . $rid . "' AND p.status='ACTIVE'", $conn) or die("Could not select reagent packet id: " . mysql_error());
+	
+	
+	if ($project_ar = mysql_fetch_array($project_rs, MYSQL_ASSOC))
+	{
+		$currReagentPacketID = $project_ar["packetID"];
+	}
+	
+	return $currReagentPacketID;		// will default to 0 if project not found
+}
+
+
+/**
+ * Retrieve from the database the numeric ID that corresponds to the given category name
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param STRING
+ * @return INT
+*/
+function findCategoryID($categoryName)
+{
+	global $conn;
+	
+	$categoryID = 0;
+	
+	$category_rs = mysql_query("SELECT categoryID FROM UserCategories_tbl WHERE category='" . $categoryName . "'", $conn) or die("Cannot select category ID: " . mysql_error());
+	
+	while ($category_ar = mysql_fetch_array($category_rs, MYSQL_ASSOC))
+	{
+		$categoryID = $category_ar["categoryID"];
+	}
+	
+	return $categoryID;
+}
+
+
+/**
+ * Print ALL available projects or projects owned by the user
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param INT $mult 1 or 0 - make the SELECT list MULTIPLE or not
+ * @param STRING $actn
+ * @param INT $restr Restrictions on viewing; if $restr == 0 output all projects; otherwise print only projects owned by the user
+ * @param INT $sel Selected option number (project ID)
+*/
+function printPacketList($mult, $actn="", $restr=0, $sel=0)
+{
+	global $conn;
+
+	?>
+	<SELECT id="packetList" name="packets" <?php echo $actn;
+		
+		if ($mult > 0) 
+		{
+			echo " multiple>";
+		}
+		else
+		{
+			echo ">";
+			echo "<OPTION value=\"0\"";
+			
+			if ($sel == 0) 
+				echo " selected>Select Project</OPTION>";
+			else
+				echo ">Select Project</OPTION>";
+		}
+
+		if ($restr == 0)
+		{
+			$query = "SELECT p.packetID as packetID, p.packetName as packetName, u.lastname as owner FROM Packets_tbl p, Users_tbl u WHERE p.ownerID=u.userID AND p.status='ACTIVE' ORDER BY packetID";
+
+			$find_name_rs = mysql_query($query, $conn) or die("Error fetching packet ID:" . mysql_error());
+
+			while ($find_name_ar = mysql_fetch_array($find_name_rs, MYSQL_ASSOC))
+			{
+				$temp_packet = $find_name_ar["packetID"] . ": " . $find_name_ar["owner"] . ": " . $find_name_ar["packetName"];
+				echo "<OPTION value=\"" . $find_name_ar["packetID"] . "\"";
+			
+				if ($sel == $find_name_ar["packetID"])
+					echo " selected>" . $temp_packet . "</option>";
+				else
+					echo ">" . $temp_packet . "</option>";
+			}
+		}
+		else
+		{
+			$currUserID = $_SESSION["userinfo"]->getUserID();
+			$currUserCategory = $_SESSION["userinfo"]->getCategory();
+			
+			// Show ALL projects for Admins; and only projects owned by current user for users with lower access privileges
+			if ($currUserCategory == $_SESSION["userCategoryNames"]['Admin'])
+				$query = "SELECT p.packetID as packetID, p.packetName as packetName, u.lastname as owner FROM Packets_tbl p, Users_tbl u WHERE p.ownerID=u.userID AND p.status='ACTIVE'";
+			else
+				$query = "SELECT p.packetID as packetID, p.packetName as packetName, u.lastname as owner FROM Packets_tbl p, Users_tbl u WHERE p.ownerID='" . $currUserID . "' AND p.ownerID=u.userID AND p.status='ACTIVE'";
+			
+			$find_name_rs = mysql_query($query, $conn) or die("Error fetching packet ID:" . mysql_error());
+
+			while ($find_name_ar = mysql_fetch_array($find_name_rs, MYSQL_ASSOC))
+			{
+				$temp_packet = $find_name_ar["packetID"] . ": " . $find_name_ar["owner"] . ": " . $find_name_ar["packetName"];
+
+				echo "<OPTION value=\"" . $find_name_ar["packetID"] . "\">" . $temp_packet . "</option>";
+			}
+		}
+		?>
+	</SELECT>
+	<?php
+}
+
+/**
+ * Modified version of printPacketList, with a name that includes [] to indicate a list
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1 2007-08-12
+ *
+ * @param INT $mult 1 or 0 - make the SELECT list MULTIPLE or not
+ * @param STRING $actn
+ * @param INT $restr Restrictions on viewing; if $restr == 0 output all projects; otherwise print only projects owned by the user
+*/
+function printSearchPackets($mult, $actn="", $restr=0)
+{
+	global $conn;
+	
+	?>
+	<SELECT id="packetList" name="packets[]" <?php echo $actn;
+		
+		if ($mult > 0) 
+		{
+			echo " multiple>";
+		}
+		else
+		{
+			echo ">";
+		}
+
+		// Default option 'All' - select if necessary
+		echo "<OPTION value=\"0\"";
+
+		if (isset($_POST["packets"]) && in_array(0, array_values($_POST["packets"])))
+			echo "selected";
+
+		echo ">All</OPTION>";
+
+		if ($restr == 0)
+		{
+			$query = "SELECT p.packetID as packetID, p.packetName as packetName, u.lastname as owner FROM Packets_tbl p, Users_tbl u WHERE p.ownerID=u.userID AND p.status='ACTIVE' ORDER BY packetID";
+			$find_name_rs = mysql_query($query, $conn) or die("Error fetching packet ID:" . mysql_error());
+
+			while ($find_name_ar = mysql_fetch_array($find_name_rs, MYSQL_ASSOC))
+			{
+				$temp_packet = $find_name_ar["packetID"] . ": " . $find_name_ar["owner"] . ": " . $find_name_ar["packetName"];
+
+				echo "<OPTION value=\"" . $find_name_ar["packetID"] . "\"";
+				
+				if (isset($_POST["packets"]) && in_array($find_name_ar["packetID"], array_values($_POST["packets"])))
+						echo " selected>" . $temp_packet . "</option>";
+				else
+					echo ">" . $temp_packet . "</option>";
+			}
+		}
+		else
+		{
+			$currUserID = $_SESSION["userinfo"]->getUserID();
+			$currUserCategory = $_SESSION["userinfo"]->getCategory();
+
+			$allProjects = array();
+
+			// Show ALL projects for Admins; and only projects owner by current user for users with lower access privileges
+			if ($currUserCategory == $_SESSION["userCategoryNames"]['Admin'])
+			{
+				$query = "SELECT p.packetID as packetID, p.packetName as packetName, u.lastname as owner FROM Packets_tbl p, Users_tbl u WHERE p.ownerID=u.userID AND p.status='ACTIVE' ORDER BY packetID";
+
+				$find_name_rs = mysql_query($query, $conn) or die("Error fetching packet ID:" . mysql_error());
+
+				while ($find_name_ar = mysql_fetch_array($find_name_rs, MYSQL_ASSOC))
+				{
+					$temp_packet = $find_name_ar["packetID"] . ": " . $find_name_ar["owner"] . ": " . $find_name_ar["packetName"];
+
+					echo "<OPTION value=\"" . $find_name_ar["packetID"] . "\">" . $temp_packet . "</option>";
+				}
+			}
+			else
+			{
+				// allow everyone to search for their own projects and public projects
+				$userProjects = getUserProjects($currUserID);
+				$publicProjects = getPublicProjects();
+
+				foreach ($userProjects as $key => $project)
+				{
+					$pID = $project->getPacketID();
+					$pName = $project->getName();
+					$pOwner = $project->getOwner();
+					$ownerName = $pOwner->getLastName();
+					
+					$tmpName = $pID . " : " . $ownerName . " : " . $pName;
+					$allProjects[$pID] = $tmpName;
+				}
+				
+				foreach ($publicProjects as $key => $project)
+				{
+					$pID = $project->getPacketID();
+					$pName = $project->getName();
+					$pOwner = $project->getOwner();
+					$ownerName = $pOwner->getLastName();
+					
+					$tmpName = $pID . " : " . $ownerName . " : " . $pName;
+					$allProjects[$pID] = $tmpName;
+				}
+
+				$allProjects = array_unique($allProjects);
+			}
+			
+			ksort($allProjects);
+
+			foreach ($allProjects as $pID => $tmpName)
+			{
+				echo "<OPTION VALUE=\"" . $pID . "\"";
+				
+				if (isset($_POST["packets"]) && in_array($pID, array_values($_POST["packets"])))
+					echo "selected>" . $tmpName . "</option>";
+				else
+					echo ">" . $tmpName . "</option>";
+			}
+		}
+		?>
+	</SELECT>
+	<?php
+}
+
+/**
+ * Retrieve project information based on its ID
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1 (restored Aug. 18, 2010)
+ *
+ * @param INT $packetID
+*/
+function getPacketByID($packetID)
+{
+	global $conn;
+
+	$packet_rs = mysql_query("SELECT * FROM Packets_tbl WHERE packetID='" . $packetID . "' AND status='ACTIVE'", $conn) or die("Cannot fetch packet by ID: " . mysql_error());
+	
+	while ($packet_ar = mysql_fetch_array($packet_rs, MYSQL_ASSOC))
+	{
+		$pName = $packet_ar["packetName"];
+		$ownerID = $packet_ar["ownerID"];
+		$tmpOwner = new Member_Class($ownerID);
+		$pDescr = $packet_ar["packetDescription"];
+
+		if ($packet_ar["is_private"] == 'TRUE')
+			$public = false;
+		else
+			$public = true;
+
+			$tmpPacket = new Project_Class($packetID, $pName, $tmpOwner, $pDescr, $public);
+	}
+
+	mysql_free_result($packet_rs);
+	unset($packet_ar);
+
+	return $tmpPacket;
+}
+
+
+/**
+ * Determine if project identified by packetID is public
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param INT $packetID
+*/
+function isPublic($packetID)
+{
+	global $conn;
+
+	// Octl 6, 2010: ignore status='ACTIVE' here, see if it poses a problem
+	$public_rs = mysql_query("SELECT is_private FROM Packets_tbl WHERE packetID='" . $packetID . "'", $conn) or die("Error in project->isPublic: " . mysql_error());
+
+	if ($public_ar = mysql_fetch_array($public_rs, MYSQL_ASSOC))
+	{
+		if ($public_ar["is_private"] == "TRUE")
+			return false;
+		else
+			return true;
+	}
+}
+?>
diff --git a/OpenFreezer/Reagent.php b/OpenFreezer/Reagent.php
new file mode 100755
index 0000000..fb97d76
--- /dev/null
+++ b/OpenFreezer/Reagent.php
@@ -0,0 +1,1161 @@
+<?php
+/**
+* Root file for Reagent module
+*
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2010 Pawson Laboratory, All Rights Reserved
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Reagent
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Include/require statements
+*/
+	include_once "Classes/MemberLogin_Class.php";
+	include_once "Classes/Member_Class.php";
+	include_once "Classes/Session_Var_Class.php";
+	include_once "Classes/generalFunc_Class.php";
+	include_once "Classes/HT_Class.php";
+	include "Classes/StopWatch.php";
+
+	include_once "Classes/Reagent_Class.php";
+
+	include_once "Reagent/Reagent_Special_Prop_Class.php";
+	include_once "Reagent/Reagent_Creator_Class.php";
+
+	include "Location/Location_Output_Class.php";
+	include_once "Reagent/Reagent_Output_Class.php";
+	include_once "Reagent/Reagent_Background_Class.php";
+	include_once "Reagent/ColFunctOutputer_Class.php";
+	include_once "Reagent/Reagent_Function_Class.php";
+	include_once "Reagent/Sequence_Function_Class.php";
+
+	include_once "Project/ProjectFunctions.php";
+
+	include_once "Classes/SeqFeature.php";
+	include_once "Classes/Sequence.php";
+
+	include_once "DatabaseConn.php";
+	include "HeaderFunctions.php";
+
+	/**
+	 * A constant used to define table width on User module views
+	 * @global INT $Const_Table_Width
+	*/
+	global $Const_Table_Width;
+	$colspan_const = 0;
+
+	header("Cache-control: private"); //IE 6 Fix
+
+	session_start();
+
+
+	$loginBlock = new MemberLogin_Class();
+	$loginBlock->loginCheck($_POST);
+
+	// print header	
+	outputMainHeader();
+
+	?>
+	<title>Reagent Page</title>
+
+	<table height="100%">
+		<table style="width:98%;">
+		<?php
+		if (isset($_SESSION["userinfo"]))
+		{
+			// Moved the following 3 statements up here on May 11/09
+			$currUserID = $_SESSION["userinfo"]->getUserID();
+			$currUserCategory = $_SESSION["userinfo"]->getCategory();
+			$allowedUP = getAllowedUserProjectIDs($currUserID);
+
+			if ($loginBlock->verifyPermissions(basename($_SERVER["PHP_SELF"]), $_SESSION["userinfo"]->getUserID()))
+			{
+				$sessionChecker = new Session_Var_Class();
+				$sessionChecker->checkSession_all(); 	// july 17/07
+
+				unset($sessionChecker);
+
+				?>
+				<tr>
+					<td>
+						<?php	
+
+						// View 1
+						// Basic view for general reagent information, nothing more
+
+						if ($_GET["View"] == "1")
+						{
+							$reagent_obj = new Reagent_Output_CLass();
+							$reagent_obj->print_reagent_intro();
+						}
+						elseif($_GET["View"] == "2")
+						{
+							$reagent_obj = new Reagent_Creator_Class();
+
+							// April 17/07: Add exception handling code, if Python found an error, redirect to a proper error page
+							if (isset($_GET["Err"]))
+							{
+								$reagent_obj->process_Error();
+							}
+							else if (isset($_GET["Type"]))
+							{
+								$rType = $_GET["Type"];
+
+								switch ($_GET["Type"])
+								{
+									case 'Vector':
+										// Added April 28/08: Multi-step creation
+										if (isset($_GET["Step"]))
+										{
+											if (isset($_GET["rID"]))
+												$rID = $_GET["rID"];
+
+											if (isset($_GET["Sub"]))
+												$subtype = $_GET["Sub"];
+									
+											if (isset($_GET["Seq"]))
+												$seqID = $_GET["Seq"];
+
+											switch ($_GET["Step"])
+											{
+												case '1':
+													// Preview sequence constructed from parents
+													// Output:
+													// 	1. Heading: "Step 2 of 4: Preview Sequence"
+													// 	2. Parents w/ option to change
+													// 	3. Constructed sequence
+													// 	4. 'Next' and 'Back' buttons
+													$reagent_obj->previewReagentSequence($rType, $subtype, $rID, $seqID);
+												break;
+			
+												case '2':
+													// May 1/08 - Preview Features Loaded from Parents during sequence reconstitution
+													$reagent_obj->previewReagentFeatures($rType, $subtype, $rID, $seqID);
+												break;
+			
+												case '3':
+													// May 2/08 - Final step in the creation process - fill in general info, s.a. name, status, project, etc.
+													$reagent_obj->previewReagentIntro("Vector", $subtype, $rID, $seqID);
+												break;
+											}
+										}
+										else
+										{
+											$parents = array();
+											
+											$parents["PV"] = $_GET["PV"];
+											
+											if (isset($_GET["I"]))
+												$parents["I"] = $_GET["I"];
+											
+											else if (isset($_GET["IPV"]))
+												$parents["IPV"] = $_GET["IPV"];
+
+											$reagent_obj->printCreationForm($_GET["Type"], $_GET["Sub"], $parents);
+										}
+
+									break;
+
+									case 'CellLine':
+										$reagent_obj->process_CellLine_TypeChoice();
+									break;
+
+									case 'Insert':
+
+										if (isset($_GET["ErrCode"]))
+											$reagent_obj->printForm_Insert_Insert(0, false, true);
+
+										if (isset($_GET["Step"]))
+										{
+											if (isset($_GET["rID"]))
+												$rID = $_GET["rID"];
+
+											if (isset($_GET["Seq"]))
+												$seqID = $_GET["Seq"];
+
+											switch ($_GET["Step"])
+											{
+												case '1':
+													// Preview sequence constructed from parents
+													// Output:
+													// 	1. Heading: "Step 2 of 4: Preview Sequence"
+													// 	2. Parents w/ option to change
+													// 	3. Constructed sequence
+													// 	4. 'Next' and 'Back' buttons
+													$reagent_obj->previewReagentSequence($rType, $subtype, $rID, $seqID);
+												break;
+			
+												case '2':
+													// May 1/08 - Preview Features Loaded from Parents during sequence reconstitution
+													$reagent_obj->previewReagentFeatures($rType, $subtype, $rID, $seqID);
+												break;
+			
+												case '3':
+													// May 2/08 - Final step in the creation process - fill in general info, s.a. name, status, project, etc.
+													$reagent_obj->previewReagentIntro("Insert", "", $rID, $seqID);
+												break;
+
+												// Added May 14/08: New procedure for saving Insert from Primer Design
+												case '4':
+													$reagent_obj->previewInsertFeaturesPrimer($rID, $seqID, $_GET["PIV"], $_GET["SO"], $_GET["AS"]);
+												break;
+
+												case '5':
+													$reagent_obj->previewInsertIntroPrimer($rID, $seqID, $_GET["PIV"], $_GET["SO"], $_GET["AS"]);
+												break;
+											}
+										}
+										else
+										{
+											$parents = array();
+											
+											$parents["PV"] = $_GET["PV"];
+											
+											if (isset($_GET["I"]))
+												$parents["I"] = $_GET["I"];
+											
+											else if (isset($_GET["IPV"]))
+												$parents["IPV"] = $_GET["IPV"];
+
+											$reagent_obj->printCreationForm($_GET["Type"], "", $parents);
+										}
+									break;
+
+									default:
+										$reagent_obj->printCreationForm();
+									break;
+								}
+							}
+							else
+							{
+								$reagent_obj->printCreationForm();
+							}
+						}
+						// Add reagent types
+						elseif( $_GET["View"] == "3" )
+						{
+							$reagent_obj = new Reagent_Creator_CLass();
+
+							if (isset($_GET["Step"]))
+							{
+								$reagent_obj->printFormAddReagentType($_GET["Step"]);
+							}
+							else
+							{
+								if (isset($_GET["goback"]))
+								{
+									$reagent_obj->printFormAddReagentType(1, true);
+								}
+								else
+								{
+									$reagent_obj->printFormAddReagentType();
+								}
+							}
+						}
+						elseif( $_GET["View"] == "4" )
+						{
+							$rout_obj = new Reagent_Output_Class();
+							$rout_obj->printReagentStats();
+
+							// June 10, 2011: "Canned" :) query for Cell Lines (NM review)
+							$rout_obj->printCellLineBiosafety();
+						}
+						elseif( $_GET["View"] == "5" )
+						{
+							// Modified June 3/09, Marina: This is obsolete, I've implemented a new method of creating new reagent types; using this view as a search page for Admin to browse through and/or delete reagent types
+
+							if (isset($_GET["Del"]) && ($_GET["Del"] == 1))
+							{
+								echo "<span style=\"color:#FF0000; font-weight:bold\">Reagent type deleted successfully.</span><BR/><BR/>";
+								echo "<a href=\"" . $_SERVER["PHP_SELF"]. "?View=5\">Back to Reagent Types list</a>";
+							}
+							else
+								printViewReagentTypesForm();
+						}
+						elseif ($_GET["View"] == "6")
+						{
+							$gfunc = new generalFunc_Class();		// May 11/06
+							$rfunc = new Reagent_Function_Class();		// May 12/06
+
+							// Detailed view of reagents
+							if ($_GET["rid"] > 0 )
+							{
+// print_r($_POST);
+								$rout_obj = new Reagent_Output_Class();
+								$bfunc_obj = new Reagent_Background_Class();	// May 26/06
+
+								// Feb. 24/10: try to prevent user from viewing unauthorized reagents by checking project access
+								$userProjects = getAllowedUserProjectIDs($currUserID);
+								$reagentProject = getReagentProjectID($_GET["rid"]);
+								
+								if (!in_array($reagentProject, $userProjects))
+								{
+									$rout_obj->printErrPage("Restricted access!");
+								}
+								else if (isset($_GET["ErrCode"]))
+								{
+// echo "Error??";
+									if ($_GET["ErrCode"] == 3)
+									{
+										// Incorrect Parent Vector ID (check could not be caught by JS) - in ALL reagent types
+										$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 3);
+									}
+									elseif ($_GET["ErrCode"] == 1)
+									{
+										switch ($rfunc->getType($_GET["rid"]))
+										{
+											case '1':
+												// vector - PV not loaded
+											break;
+
+											case '2':
+												// Insert - Sites not found at specified position
+												$rout_obj->print_Detailed_Insert(true, $_GET["View"], $_GET["rid"], "Insert");
+											break;
+											
+											case '4':
+												// CL - PV not loaded
+												$rout_obj->print_Detailed_CellLine("Modify", $_GET["View"], $_GET["rid"], 0, "Vector");
+											break;
+											
+											default:
+											break;
+										}
+									}
+									elseif ($_GET["ErrCode"] == 2)
+									{
+										// At the moment, this scenario could only occur for Cell Lines - where their Parent CL details were not preloaded.  But keep the 'switch' just in case, easy to remove afterwards if not needed
+										switch ($rfunc->getType($_GET["rid"]))
+										{
+											case '4':
+												// Parent CL details not preloaded
+												$rout_obj->print_Detailed_CellLine("Modify", $_GET["View"], $_GET["rid"], 0, "Cell Line");
+											break;
+											
+											default:
+											break;
+										}
+									}
+									elseif ($_GET["ErrCode"] == 4)
+									{
+										// Cell Line modification - cannot use the parent cell line entered, don't have read access
+										$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 4);
+									}
+									elseif ($_GET["ErrCode"] == 5)
+									{
+										// Insert modification - cannot use IPV or one of the oligos
+										$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 5);
+									}
+
+									elseif ($_GET["ErrCode"] == 6)
+									{
+										$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"]);
+									}
+
+									elseif ($_GET["ErrCode"] == 7)
+									{
+										$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"]);
+									}
+
+									elseif ($_GET["ErrCode"] == 8)
+									{
+										$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"]);
+									}
+									elseif ($_GET["ErrCode"] == 9)
+									{
+										$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"]);
+									}
+									elseif ($_GET["ErrCode"] == 10)
+									{
+										$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"]);
+									}
+									elseif ($_GET["ErrCode"] == 11)
+									{
+										$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"]);
+									}
+									elseif ($_GET["ErrCode"] == 12)
+									{
+										$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"]);
+									}
+									elseif ($_GET["ErrCode"] == 13)
+									{
+										// August 31/07: Vector modification - Not allowed to use the Insert or IPV due to lack of project access
+										// Using the same ErrCode value, since both Insert and IPV cannot occur simultaneously on one view
+										if (isset($_GET["I"]) || isset($_GET["IPV"]))
+										{
+											$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 2);
+										}
+									}
+								}
+								else if (isset($_GET["mode"]) && ($_GET["mode"] == 'Create'))
+								{
+									$rout_obj->print_Detailed_Reagent("Create", $_GET["View"], $_GET["rid"], 1);
+								}
+								// Modify associations
+								// August 31/07, Marina: Although both Vectors and Cell Lines have a Parent Vector, its form field names are different: For Vectors the field is called parent_vector_name_txt, for Cell Lines it's called pv_name_txt (for historical reasons and naming consistency)
+								elseif (isset($_POST["change_vp_id"]))
+								{
+// echo "Changing parent vector";
+									// August 29/07, Marina: Verify that the user can access parent by project
+								
+									// Parent vector is used everywhere; the other parent type needs to be differentiated based on reagent type
+
+									// Editing a Vector - Check parent vector, and either Insert or IPV ID, depending on the vector type
+									if (isset($_POST["parent_vector_name_txt"]))
+									{
+										$pvID = $gfunc->get_rid($_POST["parent_vector_name_txt"]);
+										$parentVectorProjectID = getReagentProjectID($pvID);
+										
+										if (($currUserCategory != $_SESSION["userCategoryNames"]["Admin"]) && ($pvID > 0) && !in_array($parentVectorProjectID, $allowedUP))
+										{
+											$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 3);
+										}
+										
+										// PV is OK; now determine if the other parent is an insert or IPV
+										elseif (isset($_POST["ipv_name_txt"]))
+										{
+											if ($_POST["ipv_name_txt"] != "")
+											{
+												$ipvID = $gfunc->get_rid($_POST["ipv_name_txt"]);
+												$ipvProjectID = getReagentProjectID($ipvID);
+												
+												// take into account that one of the parent values may be empty
+												if (($currUserCategory != $_SESSION["userCategoryNames"]["Admin"]) && !in_array($ipvProjectID, $allowedUP))
+													$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 2);
+												
+												else
+													$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 1);
+											}
+											else
+												$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 2);
+										}
+										elseif (isset($_POST["insert_name_txt"]))
+										{
+											if ($_POST["insert_name_txt"] != "")
+											{
+												$insertID = $gfunc->get_rid($_POST["insert_name_txt"]);	
+												$insertProjectID = getReagentProjectID($insertID);
+												
+												if (($currUserCategory != $_SESSION["userCategoryNames"]["Admin"]) && !in_array($insertProjectID, $allowedUP))
+													$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 2);
+												else
+													$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 1);
+											}
+											else
+												$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 1);
+										}
+										else
+										{
+											$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 1);
+										}
+									}
+									elseif (isset($_POST["pv_name_txt"]))
+									{
+										// Editing Cell Line; verify parent vector and parent cell line IDs
+
+										$pvID = $gfunc->get_rid($_POST["pv_name_txt"]);
+										$parentVectorProjectID = getReagentProjectID($pvID);
+										
+										if (($pvID > 0) && !in_array($parentVectorProjectID, $allowedUP))
+										{
+											$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 3);
+										}
+										elseif (isset($_POST["cl_name_txt"]))
+										{
+											if ($_POST["cl_name_txt"] != "")
+											{
+												$clID = $gfunc->get_rid($_POST["cl_name_txt"]);
+												$clProjectID = getReagentProjectID($clID);
+
+												if (($currUserCategory != $_SESSION["userCategoryNames"]["Admin"]) && !in_array($clProjectID, $allowedUP))
+													$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 4);
+												else
+													$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 1);
+											}
+											else
+												$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 1);
+										}
+									}
+								}
+								elseif (isset($_GET["ErrCode"]))
+								{
+									if ($_GET["ErrCode"] == 5)
+									{
+										// Insert modification - entered inaccessible IPV ID
+										$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 5);
+									}
+									elseif ($_GET["ErrCode"] == 6)
+									{
+										// Insert modification - entered inaccessible Sense Oligo ID
+										$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 6);
+									}
+									elseif ($_GET["ErrCode"] == 7)
+									{
+										// Insert modification - entered inaccessible Antisense Oligo ID
+										$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 7);
+									}
+								}
+								// Jan. 31/08: Process Insert creation from Primer Design view
+								elseif (isset($_GET["mode"]) && ($_GET["mode"] == 'Create'))
+								{
+									$rout_obj->print_Detailed_Reagent("Modify", $_GET["View"], $_GET["rid"], 1);
+								}
+								else
+								{
+									$rout_obj->print_Detailed_Reagent($_GET["mode"], $_GET["View"], $_GET["rid"], 1);
+								}
+							}
+
+							echo "</td></tr></table>";	// feb. 8/08 - close table here to have footer display properly (over entire page, incl. side menu)
+						}
+						elseif( $_GET["View"] == "7" )
+						{
+							# Sept 8, 2006 -- New Primer Design View
+							$gfunc_obj = new generalFunc_Class();
+							$rfunc_obj = new Reagent_Function_Class();
+
+							# Display general header
+							# ....
+
+							# Specific reagent info
+							if (isset($_GET["rid"]))
+							{
+								$rID = $_GET["rid"];
+
+								if (isset($_POST["get_primers"]))
+								{
+									// Update Jan. 15, 2011: added strtolower() to avoid case-sensitivity issues
+									$fwd_linker = strtolower($rfunc_obj->filterSpaces($_POST["fwd_linker"]));
+									$rev_linker = strtolower($rfunc_obj->filterSpaces($_POST["rev_linker"]));
+
+									$fwdLen = $_POST["fwd_length"];
+									$revLen = $_POST["rev_length"];
+
+									$fwdTm = $_POST["fwd_tm"];
+									$revTm = $_POST["rev_tm"];
+
+									# Create primers and show them on the same page below
+									echo "<table width=\"700px\" border=\"0\" style=\"font-face:Helvetica; font-size:10px\" cellpadding=\"5\">";
+
+										echo "<th colspan=\"5\" style=\"font-size:12px; text-decoration:underline; text-align:left; color:#DA000D; font-weight:bold\">PRIMER DESIGN</th>";
+
+										$constSeq = $_POST["const_dna_seq_" . $rID];
+										$cDNASeq = $rfunc_obj->spaces($constSeq);
+										$protSeq = $_POST["const_prot_seq_" . $rID];
+										$primStart = $_POST["aa_start_" . $rID];
+										$primEnd = $_POST["aa_end_" . $rID];
+										$tar_seq = $rfunc_obj->getSeqToClone($constSeq, $primStart, $primEnd);
+
+										$primers_ar = $rfunc_obj->getPrimers($constSeq, $primStart, $primEnd, $fwd_linker, $rev_linker, $fwdLen, $revLen, $fwdTm, $revTm);	// 12/09/06
+
+										// Retrieving primers and their Tm from an associative array
+										$fwd_ar = $primers_ar[0];
+
+										foreach ($fwd_ar as $pr=>$tm)
+										{
+											$fwd_primer = $pr;
+											$fwd_tm = $tm;
+										}
+
+										$rev_ar = $primers_ar[1];
+
+										foreach ($rev_ar as $pr=>$tm)
+										{
+											$rev_primer = $pr;
+											$rev_tm = $tm;
+										}
+
+											/* Removed Sept 13/06 -- Karen asked to preserve original linker spacing
+											# filter spaces from primers - it is formatted on return, perhaps change that and format only before display
+											$tmp_fwd = $rfunc_obj->filterSpaces($fwd_primer);
+											$tmp_rev = $rfunc_obj->filterSpaces($rev_primer);
+
+											# primer concatenated with linker (w/o spaces)
+											$tmp_fp = $fwd_linker . $tmp_fwd;
+											$tmp_rp = $rev_linker . $tmp_rev;
+											*/
+
+										// Instead:
+										$tmp_fp = $_POST["fwd_linker"] . $fwd_primer;
+										$tmp_rp = $_POST["rev_linker"] . $rev_primer;
+
+										// added jan 31/08
+										echo "<tr>";
+
+										echo "<td style=\"font-size:11px; white-space:nowrap; font-weight:bold\">cDNA sequence:    ";
+
+										// May 11/09: Show 'Create' link IFF the user is authorized to create reagents (i.e. access level >= 'Writer').  Primer Design is NOT restricted for readers, BUT they CANNOT save any reagents into the system!!!!
+										if ($currUserCategory != $_SESSION["userCategoryNames"]["Reader"])
+										{
+											echo "<SPAN class=\"linkShow\" style=\"font-size:11px; font-weight:normal;\" onClick=\"document.createInsert.submit();\">Create Insert</SPAN></td></tr>";
+										}
+
+										echo "<tr><td colspan=\"5\">";
+											echo "<pre font-size:10px>";
+
+											$seqOut = $rfunc_obj->dnaSpace($tar_seq, $_POST["fwd_linker"], $rfunc_obj->reverse_complement($_POST["rev_linker"]));
+
+											echo "<div id=\"sel_dna_div_" . $rID . "\" name=\"sel_dna_div_" . $rID . "\" style=\"white-space:normal; height:auto\">" . $seqOut  . "</div>";
+
+											echo "</pre>";
+										echo "</td></tr>";
+
+										echo "<tr>";
+											echo "<td colspan=\"5\" style=\"font-weight:bold; font-size:11px\">Forward Primer:</td>";
+										echo "</tr>";
+
+										echo "<tr>";
+											echo "<td style=\"font-size:11px; white-space:nowrap\" width=\"25%\">" . $tmp_fp . "</td>";
+
+											echo "<td style=\"font-size:11px; white-space:nowrap\" width=\"8%\"><B>Length:</B>  " . strlen($rfunc_obj->filterSpaces($tmp_fp)) . "</td>";
+
+											// Jan. 31/08: Store TM in a variable
+											$fp_tm = $rfunc_obj->calcTemp($rfunc_obj->filterSpaces($tmp_fp));
+
+											echo "<td style=\"font-size:11px; white-space:nowrap\" width=\"20%\"><B>Tm (w/o linker):</B> " . $fwd_tm  . "<B> °C</B></td>";
+
+											echo "<td style=\"font-size:11px; white-space:nowrap\" width=\"20%\"><B>Tm (with linker):</B>  " . $fp_tm  . "<B> °C</B></td>";
+
+											// Jan. 31/08: Store MW in a variable
+											$fp_mw = $rfunc_obj->get_mw($rfunc_obj->filterSpaces($tmp_fp));
+
+											echo "<td style=\"font-size:11px; white-space:nowrap\"><B>MW: </B>" . $fp_mw . "<B> g/mole</B></td>";
+
+											// June 18/10: Output GC content
+											$fp_gc = $rfunc_obj->get_gc_content($rfunc_obj->filterSpaces($tmp_fp));
+
+											echo "<td style=\"font-size:11px; white-space:nowrap\"><B>GC %: </B>" . $fp_gc . "</td>";
+
+											// JAN. 31/08: Proceed to Oligo creation
+											echo "<FORM name=\"createSenseOligo\" method=\"POST\" action=\"" . $cgi_path . "create.py\">";
+
+											// Store all attributes as hidden form values
+											echo "<INPUT TYPE=\"hidden\" NAME=\"primer_sequence\" VALUE=\"" . $tmp_fp . "\">";
+
+											echo "<INPUT TYPE=\"hidden\" NAME=\"create_oligo\">";
+
+											echo "<INPUT TYPE=\"hidden\" NAME=\"primer_mw\" VALUE=\"" . $fp_mw . "\">";
+
+											echo "<INPUT TYPE=\"hidden\" NAME=\"primer_tm\" VALUE=\"" . $fp_tm . "\">";
+
+											echo "<INPUT TYPE=\"hidden\" NAME=\"oligo_type\" VALUE=\"Sense\">";
+
+											echo "<INPUT TYPE=\"hidden\" NAME=\"primer_insert\" VALUE=\"" . $rID . "\">";
+
+											// Feb. 4/08: Pass linkers to Insert creation form
+											echo "<INPUT TYPE=\"hidden\" NAME=\"fwd_linker\" VALUE=\"" . $fwd_linker . "\">";
+
+											echo "<INPUT TYPE=\"hidden\" NAME=\"rev_linker\" VALUE=\"" . $rev_linker . "\">";
+
+											// removed April 3/08 at Karen's request
+											// echo "<td style=\"font-size:11px; white-space:nowrap\"><SPAN class=\"linkShow\" onClick=\"document.createSenseOligo.submit();\">Create Oligo</SPAN></td>";
+
+											echo "</FORM>";
+										echo "</tr>";
+
+										echo "<tr>";
+											echo "<td colspan=\"5\" style=\"font-weight:bold; font-size:11px\">Reverse Primer:</td>";
+										echo "</tr>";
+
+										echo "<tr>";
+											echo "<td style=\"font-size:11px; white-space:nowrap\">" . $tmp_rp . "</td>";
+
+											echo "<td style=\"font-size:11px; white-space:nowrap\"><B>Length:</B>  " . strlen($rfunc_obj->filterSpaces($tmp_rp)) . "</td>";
+											echo "<td style=\"font-size:11px; white-space:nowrap\"><B>Tm (w/o linker):</B> " . $rev_tm . "<B> °C</B></td>";
+
+											// Changed jan. 30/08: Stored TM in a variable
+											$rp_tm = $rfunc_obj->calcTemp($rfunc_obj->filterSpaces($tmp_rp));
+
+											echo "<td style=\"font-size:11px; white-space:nowrap\"><B>Tm (with linker):</B>  " . $rp_tm . "<B> °C</B></td>";
+
+											// Changed jan. 30/08: Stored MW in a variable
+											$rp_mw = $rfunc_obj->get_mw($rfunc_obj->filterSpaces($tmp_rp));
+
+											echo "<td style=\"font-size:11px; white-space:nowrap\"><B>MW: </B>" . $rp_mw . "<B> g/mole</B></td>";
+
+											// June 18/10: Output GC content
+											$rp_gc = $rfunc_obj->get_gc_content($rfunc_obj->filterSpaces($tmp_rp));
+
+											echo "<td style=\"font-size:11px; white-space:nowrap\"><B>GC %: </B>" . $rp_gc . "</td>";
+
+											// NEW JAN. 30/08: Proceed to Oligo creation
+											echo "<FORM name=\"createAntisenseOligo\" method=\"POST\" action=\"" . $cgi_path . "create.py\">";
+
+											// Store all attributes as hidden form values
+											echo "<INPUT TYPE=\"hidden\" NAME=\"primer_sequence\" VALUE=\"" . $tmp_rp . "\">";
+
+											echo "<INPUT TYPE=\"hidden\" NAME=\"create_oligo\">";
+
+											echo "<INPUT TYPE=\"hidden\" NAME=\"primer_mw\" VALUE=\"" . $rp_mw . "\">";
+
+											echo "<INPUT TYPE=\"hidden\" NAME=\"primer_tm\" VALUE=\"" . $rp_tm . "\">";
+
+											echo "<INPUT TYPE=\"hidden\" NAME=\"primer_insert\" VALUE=\"" . $rID . "\">";
+
+											echo "<INPUT TYPE=\"hidden\" NAME=\"oligo_type\" VALUE=\"Antisense\">";
+
+											// removed April 3/08 at Karen's request
+											// echo "<td style=\"font-size:11px; white-space:nowrap\"><SPAN class=\"linkShow\" onClick=\"document.createAntisenseOligo.submit();\">Create Oligo</SPAN></td>";
+
+											echo "</FORM>";
+
+										// Jan. 31/08: Placing Insert form here, to include Oligo information
+										echo "<FORM style=\"display:none\" name=\"createInsert\" method=\"POST\" action=\"" . $cgi_path . "create.py\">";
+
+										// Insert Info
+										echo "<INPUT TYPE=\"hidden\" name=\"create_insert\">";
+
+										// Correction Jan. 17, 2011:
+										// echo "<INPUT TYPE=\"hidden\" name=\"insert_seq\" value=\"" . $_POST["fwd_linker"] . $tar_seq . $rfunc_obj->reverse_complement($_POST["rev_linker"]) . "\">";
+
+										// replaced Jan. 17, 2011
+										echo "<INPUT TYPE=\"hidden\" name=\"insert_seq\" value=\"" . $fwd_linker . $tar_seq . $rfunc_obj->reverse_complement($rev_linker) . "\">";
+
+										// Sense Oligo Info
+										echo "<INPUT TYPE=\"hidden\" NAME=\"sense_sequence\" VALUE=\"" . $tmp_fp . "\">";
+
+										echo "<INPUT TYPE=\"hidden\" NAME=\"sense_mw\" VALUE=\"" . $fp_mw . "\">";
+
+										echo "<INPUT TYPE=\"hidden\" NAME=\"sense_tm\" VALUE=\"" . $fp_tm . "\">";
+
+										echo "<INPUT TYPE=\"hidden\" NAME=\"sense_gc\" VALUE=\"" . $fp_gc . "\">";
+
+										// Antisense Oligo Info
+										echo "<INPUT TYPE=\"hidden\" NAME=\"antisense_sequence\" VALUE=\"" . $tmp_rp . "\">";
+
+										echo "<INPUT TYPE=\"hidden\" NAME=\"antisense_mw\" VALUE=\"" . $rp_mw . "\">";
+
+										echo "<INPUT TYPE=\"hidden\" NAME=\"antisense_tm\" VALUE=\"" . $rp_tm . "\">";
+
+
+										echo "<INPUT TYPE=\"hidden\" NAME=\"antisense_gc\" VALUE=\"" . $rp_gc . "\">";
+
+										# Original (template) Insert (for naming oligos)
+										echo "<INPUT TYPE=\"hidden\" NAME=\"template_insert\" VALUE=\"" . $rID . "\">";
+
+										# Feb. 12/08: Pass linkers
+										echo "<INPUT TYPE=\"hidden\" NAME=\"fwd_linker\" VALUE=\"" . $fwd_linker . "\">";
+
+										echo "<INPUT TYPE=\"hidden\" NAME=\"rev_linker\" VALUE=\"" . $rev_linker . "\">";
+
+										echo "</FORM>";
+										echo "</tr>";
+									echo "</table>";
+								}	// end if isset get primers
+								else
+								{
+									echo "<form name=\"primers_form\" method=\"post\" onSubmit=\"return verifyTmAndLength()\" action=\"" . $_SERVER["PHP_SELF"] . "?View=7&rid=" . $rID . "\">";
+
+										echo "<table border=\"0\" cellpadding=\"5\">";
+											echo "<th style=\"text-align:left\">PRIMER DESIGN</th>";
+											echo "<input type=\"hidden\" name=\"reagents[]\" value=\"" . $rID . "\">";
+											echo "<tr><td><a style=\"font-size:11px; text-decoration:underline\" href=\"" . $_SERVER["PHP_SELF"] . "?View=6&rid=" . $rID . "\">" . $gfunc_obj->getConvertedID_rid($rID) . "</a> \t";
+	
+											# retrieve PROTEIN sequence (hardcoded property ID but selection trivial)
+											echo "<font style=\"font-size:10px; font-weight:bold\">Translated Protein Sequence:";
+		
+											// Modified Nov. 5/08 - removed 'length' from query - no longer stored as column, calculate on the spot
+											$protSeqPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["protein translation"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+		
+											$protSeqRS = mysql_query("SELECT s.`sequence`, s.`frame`, s.`start`, s.`end` FROM `Sequences_tbl` s, `ReagentPropList_tbl` r WHERE r.`reagentID`='" . $rID . "' AND r.`propertyID`='" . $protSeqPropID . "' AND s.`seqID`=r.`propertyValue` AND r.`status`='ACTIVE' AND s.`status`='ACTIVE'", $conn) or die("Could not select sequence: " . mysql_error());
+	
+											if ($seqResult = mysql_fetch_array($protSeqRS, MYSQL_ASSOC))
+											{
+												$constProtSeq = $seqResult["sequence"];
+												$protSeq = $rfunc_obj->spaces($constProtSeq);
+												$frame = $seqResult["frame"];
+												$startpos = $seqResult["start"];
+												$endpos = $seqResult["end"];
+		
+												$length = strlen($constProtSeq);
+		
+												echo " length " . $length . "</font><BR>";
+		
+												echo "<input type=\"hidden\" name=\"const_prot_seq_" . $rID . "\" id=\"const_protSeq_" . $rID . "\" value=\"" . $constProtSeq . "\">";
+		
+												echo "</td></tr>";	// for the header row
+		
+												echo "<tr><td>";
+													# Aug 16/06
+													echo "<table width=\"100\" cellpadding=\"2\" border=\"0\" style=\"font-size:8px\">";
+		
+		
+													echo "<th>";
+														for ($x = 1; $x <= 10; $x++)
+														{
+															if ($length >= $x*10)
+															{
+																echo "<TD style=\"font-size:10px;text-align:right;  font-weight:bold\">" . $x*10 . "</TD>";
+															}
+														}
+													echo "</th>";
+		
+		
+													$tmp_prot = split("\n", $protSeq);
+		
+													foreach ($tmp_prot as $i=>$tok)
+													{
+														echo "<TR>";
+															// Updated Sept 13/06, Karen asked for row index on the side
+															$rowIndex = $i+1;
+		
+															if ($i == 0)	// first row
+															{
+																$rowStart = 1;
+															}
+															else
+															{
+																$rowStart = $i*100 + 1;
+															}
+		
+															if ($length >= ($rowIndex*100))
+															{
+																$rowEnd = $rowIndex*100;
+															}
+															else
+															{
+																$rowEnd = $length;
+															}
+		
+															echo "<TD  style=\"white-space:nowrap; font-size:10px; font-weight:bold; text-align:right; vertical-align:top\">" . $rowStart . " - " . $rowEnd . "</TD>";
+		
+															$tmp_chunks = split(" ", $tok);
+		
+															foreach ($tmp_chunks as $j=>$chunk)
+															{
+																$chunk = trim($chunk);
+		
+																if (strlen($chunk) > 0)
+																{
+																	echo "<TD>";
+																		echo "<pre font-size:11px;  text-align:justify>" . $chunk . "</pre>";
+																	echo "</TD>";
+																}
+															}
+														echo "</TR>";
+													}
+		
+													echo "</table>";
+												echo "</td></tr>";
+		
+												echo "<input type=\"hidden\" name=\"prot_seq\" value=\"" . $protSeq . "\">";
+											}
+	
+											// August 14, 2006: cDNA -- Moved here; Karen requested removing cDNA from webpage
+											$constSeq = $rfunc_obj->reverseTranslate($protSeq, $rID, $frame, $startpos, $endpos, $length);
+		
+											echo "<input type=\"hidden\" name=\"const_dna_seq_" . $rID . "\" id=\"const_dnaSeq_" . $rID . "\" value=\"" . $constSeq . "\">";
+		
+											// Sept. 11/08: Protein start and end translation indices 
+											echo "<input type=\"hidden\" id=\"prot_start\" value=\"" . $startpos . "\">";
+											echo "<input type=\"hidden\" id=\"prot_stop\" value=\"" . $endpos . "\">";
+		
+											// Sept. 11/08: cDNA start and end indices
+											$cdnaStart = $rfunc_obj->getStartPos($rID, "cdna insert", $_SESSION["ReagentProp_Name_ID"]["cdna insert"]);
+											$cdnaEnd = $rfunc_obj->getEndPos($rID, "cdna insert", $_SESSION["ReagentProp_Name_ID"]["cdna insert"]);
+		
+											echo "<input type=\"hidden\" id=\"cdna_start\" value=\"" . $cdnaStart . "\">";
+											echo "<input type=\"hidden\" id=\"cdna_stop\" value=\"" . $cdnaEnd . "\">";
+		
+											// Primer selection section
+											echo "<tr><td>";
+												echo "<table width=\"100%\" id=\"primers_tbl_" . $rID . "\" cellpadding=\"5\" cellspacing=\"5\" style=\"display:inline\" border=\"0\">";
+													echo "<th colspan=\"3\" style=\"font-size:11px;  text-align:left; white-space:nowrap\">PRIMER BOUNDARIES DEFINITION</th>";
+		
+													echo "<tr><td colspan=\"3\" style=\"font-size:11px; white-space:nowrap\">Please enter the <b>Amino Acid start and stop</b> positions into the boxes below and press &#34GO&#34:</td></tr>";
+				
+													echo "<tr>";
+														echo "<td colspan=\"3\" style=\"font-size:11px\" width=\"10%\">Start:   <input type=\"text\" style=\"color:#000000; font-weight:regular\" size=\"4px\" id=\"aa_start_txt_" . $rID . "\" name=\"aa_start_" . $rID . "\" value=\"";
+				
+														if (isset($_POST["aa_start"]))
+														{
+															echo $_POST["aa_start"] . "\"></td>";
+														}
+														else
+														{
+															echo "\">";
+														}
+				
+														echo "     End:   <input type=\"text\" style=\"color:#000000; font-weight:regular\" size=\"4px\" id=\"aa_end_txt_" . $rID . "\" name=\"aa_end_" . $rID . "\" value=\"";
+				
+														if (isset($_POST["aa_end"]))
+														{
+															echo $_POST["aa_end"] . "\"></td>";
+														}
+														else
+														{
+															echo "\">";
+														}
+				
+														echo "     <input type=\"button\" id=\"aa_bounds_" . $rID . "\" value=\"Go\" onClick=\"return getBounds('protein', " . $rID . ")\"></td>";
+													echo "</tr>";
+		
+													echo "<tr><td colspan=\"3\">";
+														echo "<pre>";
+															echo "<div id=\"sel_prot_div_" . $rID . "\" name=\"sel_prot_div_" . $rID . "\" style=\"width:900px; height:auto\"></div>";
+														echo "</pre>";
+													echo "</td></tr>";
+		
+													echo "<tr><td colspan=\"3\">";
+														echo "<pre font-size:10px>";
+															echo "<div id=\"sel_dna_div_" . $rID . "\" name=\"sel_dna_div_" . $rID . "\" style=\"width:900px; height:auto\"></div>";
+														echo "</pre>";
+													echo "</td></tr>";
+		
+													# Linkers
+													echo "<tr><td colspan=\"3\">";
+														echo "<table border=\"0\" id=\"linkers_tbl\" width=\"100%\" style=\"display:none\" cellspacing=\"5\" cellpadding=\"5\">";
+															echo "<tr>";
+																echo "<td width=\"250px\" colspan=\"2\" style=\"font-size:11px; font-weight:bold; white-space:nowrap\">Would you like to add primer extensions?  ";
+			
+																	echo "<select id=\"linker_selector\"onChange=\"showHideLinkers()\">";
+																		echo "<option selected value=\"No\">No";
+																		echo "<option value=\"Yes\">Yes";
+																		echo "</select>";
+																echo "</td>";
+															echo "</tr>";
+			
+															echo "<tr id=\"linkers_row\" style=\"display:none\">";
+																echo "<td colspan=\"2\">";
+																	echo "<table width=\"100%\" cellspacing=\"5\" cellpadding=\"3\" border=\"0\"";
+																		echo "<tr>";
+																			echo "<td colspan=\"2\" style=\"font-size:11px; white-space:nowrap\">Please select primer extensions for subcloning into selected vectors:</td>";
+																		echo "</tr>";
+			
+																		echo "<tr>";
+																			echo "<td width=\"100px\" style=\"font-size:11px; font-weight:bold; white-space:nowrap\">Forward Primer extension:</td>";
+			
+																			echo "<td>";
+																				echo "<select id=\"fwd_linker_types_selector\" name=\"fwd_linker_types\" onChange=\"selectLinkers()\" style=\"font-size:11px\">";
+																					echo "<option selected value=\"default\">None";
+																					echo "<option value=\"gw_atg\">Gateway (donor vector V1986) 5' linker with ATG";
+																					echo "<option value=\"gw_no_atg\">Gateway (donor vector V1986) 5' linker without ATG";
+																					echo "<option value=\"creator_v7_fusion_atg\">Creator (V7-based in fusion) 5' linker with ATG";
+																					echo "<option value=\"creator_v7_fusion_no_atg\">Creator (V7-based in fusion) 5' linker without ATG";
+																					echo "<option value=\"creator_v37_fusion_atg\">Creator (V37-based in fusion) 5' linker with ATG";
+																					echo "<option value=\"creator_v37_fusion_no_atg\">Creator (V37-based in fusion) 5' linker without ATG";
+																					echo "<option value=\"his_vector_atg\">His-vector (pET28 SacB AP V2082 In Fusion) 5' linker with ATG";
+																					echo "<option value=\"his_vector_no_atg\">His-vector (pET28 SacB AP V2082 In Fusion) 5' linker without ATG";
+				
+																					// April 22, 2009: T7/SP6 Promoters w/ Kozak for Nick and Jerry
+																					echo "<option value=\"t7_promoter\">T7 (T7 PCR Reticulocyte kit)";
+																					echo "<option value=\"sp6_promoter\">SP6 (SP6 Wheat Germ kit)";
+																					echo "<option value=\"other\">Other";
+																				echo "</select>";
+																			echo "</td>";
+																		echo "</tr>";
+			
+																		echo "<tr><td> </td><td colspan=\"2\"><input type=\"text\" id=\"fp_linker\" style=\"font-size:12px\" size=\"65px\" name=\"fwd_linker\"></td></tr>";
+			
+																		echo "<tr>";
+																			echo "<td style=\"font-size:11px; font-weight:bold; white-space:nowrap\">Reverse Primer Extension:</td>";
+																			echo "<td>";
+																				echo "<select id=\"rev_linker_types_selector\" name=\"rev_linker_types\" style=\"font-size:11px\" onChange=\"selectLinkers()\">";
+																					echo "<option selected value=\"default\">None";
+																					echo "<option value=\"gw_stop\">Gateway (donor vector V1986) 3' linker with stop codon";
+																					echo "<option value=\"gw_no_stop\">Gateway (donor vector V1986) 3' linker without stop codon";
+																					echo "<option value=\"creator_fusion_stop\">Creator (V7 or V37-based in fusion) 3' linker with stop codon";
+																					echo "<option value=\"creator_fusion_no_stop\">Creator (V7 or V37-based in fusion) 3' linker without stop codon";
+																					echo "<option value=\"his_vector_stop\">His-vector (pET28 SacB AP V2082 In Fusion) 3' linker with stop codon";
+																					echo "<option value=\"his_vector_no_stop\">His-vector (pET28 SacB AP V2082 In Fusion) 3' linker without stop codon";
+			
+																					// April 22, 2009: Flag-Tag for Nick and Jerry
+																					echo "<option value=\"flag_tag\">C-Terminal FLAG";
+			
+																					echo "<option value=\"other\">Other";
+																				echo "</select>";
+																			echo "</td>";
+																		echo "</tr>";
+			
+																		echo "<tr><td> </td><td colspan=\"2\"><input type=\"text\" style=\"font-size:12px\" size=\"65px\" id=\"tp_linker\" name=\"rev_linker\"></td></tr>";
+																	echo "</table>"; // 5' & 3' linkers
+																echo "</td>";
+															echo "</tr>";
+		
+															# Limit primer size
+															echo "<tr>";
+																echo "<td style=\"font-size:11px\" colspan=\"2\">";
+																	echo "<b>How would you like to limit primer size?</b>";																
+																echo "</td>";
+															echo "</tr>";
+			
+															echo "<tr>";
+																echo "<td style=\"font-size:11px\" colspan=\"2\">";
+																	echo "<HR><u><B>Note:</B></u><BR><P>Primers are generated adding one nucleotide at a time until either Tm or size limit is reached.";
+																	echo "<BR><P>The <b><i>length</i></b> parameter is <u>optional</u>.  If no length is provided, primer assembly stops when 'Tm' is reached.  If 'length' is entered, primer generation stops when its size becomes equal to the 'length' value, even if 'Tm' is not reached at that point.";
+																	echo "<BR><P>The <b><i>Tm</i></b> parameter is <u>mandatory</u>.  You may overwrite the default value of 55 by entering a Tm of your choice in the appropriate textbox.<HR><BR>";
+																echo "</td>";
+															echo "</tr>";
+			
+															echo "<tr>";
+																echo "<td colspan=\"3\"><table width=\"100\" cellpadding=\"5px\" border=\"0\">";
+																echo "<tr>";
+																	echo "<td style=\"font-size:11px; font-weight:bold; white-space:nowrap\">5' primer:</td>";
+																	echo "<td style=\"font-size:11px; white-space:nowrap\">First by length (including linkers):</td>";
+																	echo "<td><input type=\"text\" id=\"fwd_length_id\" name=\"fwd_length\" size=\"5px\"></td>";
+																	echo "<td style=\"font-size:11px; white-space:nowrap\">Then by Tm (not including linkers):</td>";
+																	echo "<td><input type=\"text\" id=\"fwd_tm_id\" name=\"fwd_tm\" size=\"5px\" value=\"55\"></td>";
+																echo "</tr>";
+			
+																echo "<tr>";
+																	echo "<td style=\"font-size:11px; font-weight:bold; white-space:nowrap\">3' primer:</td>";
+																	echo "<td style=\"font-size:11px; white-space:nowrap\">First by length (including linkers):</td>";
+																	echo "<td><input type=\"text\" id=\"rev_length_id\" name=\"rev_length\" size=\"5px\"></td>";
+																	echo "<td style=\"font-size:11px; white-space:nowrap\">Then by Tm (not including linkers):</td>";
+																	echo "<td><input type=\"text\" id=\"rev_tm_id\" name=\"rev_tm\" size=\"5px\" value=\"55\"></td>";
+																echo "</tr>";
+															echo "</tr>";
+														echo "</table>";	// linkers and primer size limits
+													echo "</td></tr>";
+												echo "</table>";	// inner primer table
+											echo "</td></tr>";
+		
+											echo "<tr>";
+												// Updated June 9/09: Do not submit form if user hits 'Enter'
+												echo "<td colspan=\"3\"><input type=\"submit\" style=\"display:none\" id=\"get_primers_btn\" name=\"get_primers\" value=\"Get Primers\"></td>";
+											echo "</tr>";
+										echo "</table>";
+									echo "</form>";
+
+									// Sept. 1, 2010: this is the closing tag for the main DIV table; w/o it the footer doesn't go to bottom of page.  KEEP IT!!
+									echo "</table>";	// outer table
+								}	// end else
+							}	// end if isset rid
+						}	// end view 7
+						?>
+					</td>
+				</tr>
+			</table>
+		<?php
+				mysql_close();
+				outputMainFooter();
+			}
+			else
+			{
+						echo "<tr><td class=\"warning\">";
+						echo "You are not authorized to view this page.  Please contact the site administrator.";
+						echo "</td></tr>";
+						?>
+					</table>
+				<?php
+
+				outputMainFooter();
+			}
+		}
+		else
+		{
+			// April 9/07, Marina: May output general info page for non-registered users
+			if (isset($_GET["View"]) && ($_GET["View"] == 1))
+			{
+				$reagent_obj = new Reagent_Output_CLass();
+				$reagent_obj->print_reagent_intro();
+
+				?>
+				</table>
+				<?php
+
+				outputMainFooter();
+			}
+			else
+			{
+				echo "<tr><td class=\"warning\">";
+				echo "Please log in to access this page.";
+				echo "</td></tr>";
+				
+				?>
+				</table>
+				<?php
+			
+				outputMainFooter();
+			}
+			?>
+			</table>
+			<?php
+		}
+		
+		mysql_close($conn);
+		?>
+	</TABLE>
+	<?php
+
+
+	/**
+	* Output reagent type selection list
+	*
+	* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	* @version 3.1 2009-06-03
+	*/
+	function printViewReagentTypesForm()
+	{
+		global $cgi_path;
+		global $conn;
+		
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+		$currUserID = $_SESSION["userinfo"]->getUserID();
+
+		$r_out = new Reagent_Output_Class();
+
+		?>
+			<FORM METHOD="POST" ACTION="<?php echo $cgi_path . "reagent_type_request_handler.py"; ?>">
+
+				<!-- Pass user info as a hidden form value to Python -->
+				<INPUT type="hidden" ID="username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+				
+				<TABLE width="775px" border="1px" frame="box" rules="none" cellpadding="5">
+				
+					<TH colspan="2" class="title">
+						SEARCH REAGENT TYPES
+					</TH>
+		
+
+					<TR>
+						<TD style="font-weight:bold; padding-left:10px;">
+							Select reagent type from the list below and click 'Go' to view/modify its attributes
+						</TD>
+					</TR>
+
+					<TR>
+						<TD style="padding-left:10px;">
+							<?php
+								$r_out->printReagentTypesList();
+							?>
+						</TD>
+					</TR>
+
+					<TR>
+						<TD style="padding-left:10px;">
+							<P><INPUT TYPE="SUBMIT" id="viewReagentType" NAME="view_reagent_type" VALUE="Go" onClick="return checkSelected('reagentTypes');">
+						</TD>
+					</TR>
+
+					<TR><TD> </TD></TR>
+				</TABLE>
+			</FORM>
+		<?php
+	}
+?>
diff --git a/OpenFreezer/Reagent/ColFunctOutputer_Class.php b/OpenFreezer/Reagent/ColFunctOutputer_Class.php
new file mode 100755
index 0000000..802e712
--- /dev/null
+++ b/OpenFreezer/Reagent/ColFunctOutputer_Class.php
@@ -0,0 +1,1718 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee <ninja_gara at hotmail.com>
+* @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Reagent
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+/**
+ * Contains functions to output specific reagent properties on forms for reagent creation, modification and viewing details
+ *
+ * @author John Paul Lee <ninja_gara at hotmail.com>
+ * @version 2005
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Reagent
+ *
+ * @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+class ColFunctOutputer_Class
+{
+	// Auxiliary internal variables used to print sequences in a specific format; their values may be changed in the code.
+
+	/**
+	* @var STRING
+	* Print a sequence in chunks of 10 on reagent detail views, separated by  
+	*/
+	var $setSeparator;
+
+	/**
+	* @var INT
+	* Output sequence in chunks of 10
+	*/
+	var $seqIncrementor;
+
+	/**
+	* @var INT
+	* Print 10 columns in each row for sequence output
+	*/
+	var $maxLineOutput;
+
+	/**
+	* @var STRING
+	* Assumes the value of an error message returned during execution of mysql queries
+	*/
+	var $classerror = "";
+
+	/**
+	 * Zero-argument constructor: Initialize instance variables
+	 *
+	 * @author John Paul Lee <ninja_gara at hotmail.com>
+	 * @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	*/
+	function ColFunctOutputer_Class()
+	{
+		$this->setSeparator = " ";
+		$this->seqIncrementor = 10;
+		$this->maxLineOutput = 10;
+		$this->classerror = "ColFunctOutputer_Class";
+	}
+	
+	
+	/**
+	* Central function that invokes specific functions for printing the value of a particular property, given by the $columnType argument
+	* @param INT $rid Internal database ID of the reagent whose properties are being printed
+	* @param STRING $columnType Name of the property to print
+	* @param STRING $outputType Differentiates between views (e.g. reagent details or modification)
+	* @param STRING $category Recent addition, indicates the property's category for proper database retrieval and output
+	* @param STRING $default_val Obsolete
+	*/
+	function output_final($rid, $columnType, $outputType, $category="", $default_val = "")
+	{
+		$outputType = strtolower($outputType);
+
+		$rfunc_obj = new Reagent_Function_Class();
+
+		switch (strtolower($columnType))
+		{
+			case "description":
+			case "comment":
+			case "comments":
+			case "verification comments":
+				return $this->get_General_Reagent_Comments($columnType, $rid);
+
+			case "sequence":
+
+				if ($outputType == "preview")	// in Reagent_Creator_Class, but most likely not needed, can replace later
+				{
+					return $this->output_sequence2($rid, 2);
+				}
+				elseif ($outputType == "raw")		// modify view
+				{
+					return $this->output_sequence2($rid, 5);
+				}
+				// Feb. 14/08: In Modify mode, show numbered sequence
+				elseif ($outputType == "modify")
+				{
+// Temporarily removed July 15/08
+// July 15/08, to be fixed		return $this->output_sequence2($rid, 3);
+					return $this->output_sequence2($rid, 2);
+				}
+
+				return $this->output_sequence($rid);
+				
+			case "protein sequence":	
+			case "protein translation":
+				return $this->outputProteinSequence($rid);
+			
+			// Oct. 23/09
+			case "rna sequence":
+				return $this->outputRNASequence($rid, $outputType);
+
+			case "length":
+				if ($outputType == 'dna')
+				{
+					return $this->output_length($rid);
+				}
+				else	// added sept 27/06
+				{
+					return $this->outputProteinLength($rid);
+				}
+			case "open/closed":
+				return $this->output_hint_rev1( $rid );
+			
+			case "packet":
+
+				// Updated May 25/07, Marina
+				if ($outputType == "modify")
+				{
+					return $this->output_packet($rid, 2);
+				}
+
+				return $this->output_packet($rid, 1);
+				
+			case "resistance marker":	// put back March 3/09 - still used for Cell Lines
+				return $this->output_Resistance_Marker($rid, $category, $outputType);
+
+			case "alternate id":		// May 23/06, Marina
+				return $this->output_Alternate_ID($rid, $outputType);
+			// March 19/09: Show multiple accessions
+			case "accession number":
+				return $this->outputAccession($rid);	// aug. 30, 2010: removed $outputType argument
+			case "promoter":
+			case "tag":		// March 13/08
+			case "selectable marker":	// March 17/08
+			case "polya tail":			// March 17/08
+			case "origin of replication":			// March 18/08
+			case "miscellaneous":		// March 18/08
+			case "cleavage site":		// Sept. 18/08
+			case "restriction site":	// Sept. 18/08
+			case "transcription terminator":	// Sept. 18/08
+			case 'intron':			// Dec. 10/08
+				return $this->output_Sequence_Features($rid, $columnType, $category);
+
+			case "frame":		// sept 27/06
+				return $this->getFrame($rid);
+
+			default:
+				if ($rfunc_obj->isSequenceFeature($columnType))
+					return $this->output_Sequence_Features($rid, $columnType, $category);
+
+				return "No matching column type was found!";
+		}
+	}
+	
+
+	/**
+	 * Retrieve from the database and print project information (number+/owner+/name) for the reagent identified by $rid
+	 *
+	 * @author John Paul Lee <ninja_gara at hotmail.com>
+	 * @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2006-01-05
+	 *
+	 * @param INT $rid Internal database ID of the reagent in question
+	 * @param INT $type Output type (differentiates between create/modify/search views and determines the return value of the function - which projects ought to be printed, whether the project's number and/or owner and/or name should be returned by the function or printed as options in dropdown selection list)
+	*/
+	// Modified by Marina on March 30/07; since Packet has been made into a simple property, change retrieval query
+	// Updated May 25/07: Changing table structure of Packets_tbl - modified query accordingly
+	function output_packet($rid, $type)
+	{
+		global $conn;
+		$rfunc_obj = new Reagent_Function_Class();
+
+		$packetPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["packet id"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+
+		// May 25/07
+		if ($type == 1)
+		{
+			$query = "SELECT r.propertyValue as packetID, u.lastname as lastname FROM ReagentPropList_tbl r, Packets_tbl p, Users_tbl u WHERE r.reagentID='" . $rid . "' AND r.propertyID='" . $packetPropID . "' AND r.propertyValue=p.packetID AND p.ownerID=u.userID AND p.status='ACTIVE' AND r.status='ACTIVE'";
+			
+			$find_name_rs = mysql_query($query, $conn) or die("Error fetching packet ID:" . mysql_error());
+
+			if ($find_name_ar = mysql_fetch_array($find_name_rs, MYSQL_ASSOC))
+			{
+				$tempName = $find_name_ar["lastname"] . ":" . $find_name_ar["packetID"];
+				return $tempName;
+			}
+
+			return "None";
+		}
+		else
+		{
+			// Differentiate between Create and Modify Reagent views
+			$userProjects = array();
+
+			// Modify: known reagent ID
+			if ( ($rid <= 0) || (isset($_GET["mode"]) && ($_GET["mode"] == 'Create')) )
+			{
+				// Create: Reagent ID does not exist.  In this case ONLY display a list of projects that the user has WRITE access to
+				// July 17/07: Restrict user access by project
+				// get list of projects that the current user is allowed to view
+				$currUserID = $_SESSION["userinfo"]->getUserID();
+				
+				// admin has unlimited access
+				$currUserCategory = $_SESSION["userinfo"]->getCategory();
+
+				if ($currUserCategory == $_SESSION["userCategoryNames"]["Admin"])
+				{
+					$userProjects = findAllProjects();
+				}
+				else
+				{
+					$userProjects = getUserProjectsByRole($currUserID, 'Writer');
+				}
+				
+				if (sizeof($userProjects) > 0)
+				{
+					$userProjectList = "(" . implode(",", $userProjects) . ")";
+
+					// Output a dropdown list, containing Packet ID : Owner : Packet Name
+					$query = "SELECT p.packetID as packetID, p.packetName as packetName, u.lastname as owner FROM Packets_tbl p, Users_tbl u WHERE p.ownerID=u.userID AND p.packetID IN " . $userProjectList . " AND p.status='ACTIVE'";
+					$find_name_rs = mysql_query($query, $conn) or die("Error fetching packet ID:" . mysql_error());
+	
+					echo "<OPTION name=\"default\" value=\"0\" selected>-- Select Project --</OPTION>";
+	
+					while ($find_name_ar = mysql_fetch_array($find_name_rs, MYSQL_ASSOC))
+					{
+						$temp_packet = $find_name_ar["packetID"] . ": " . $find_name_ar["owner"] . ": " . $find_name_ar["packetName"];
+						echo "<OPTION name=\"pkt_" . $find_name_ar["packetID"] . "\" value=\"" . $find_name_ar["packetID"] . "\">" . $temp_packet . "</option>";
+					}
+				}
+			}
+			else
+			{
+				// current reagent project ID
+				$rIDpID = getReagentProjectID($rid);
+
+				// Output a dropdown list, containing Packet ID : Owner : Packet Name
+				
+				// July 13/07, Marina: Output only projects the user has WRITE access to, plus public projects if user is a Writer (which he should be, otherwise he wouldn't arrive at modification view)
+				$currUserID = $_SESSION["userinfo"]->getUserID();
+				
+				// admin has unlimited access
+				$currUserCategory = $_SESSION["userinfo"]->getCategory();
+
+				if ($currUserCategory == $_SESSION["userCategoryNames"]["Admin"])
+				{
+					$userProjects = findAllProjects();
+				}
+				else
+				{
+					$userProjects = getUserProjectsByRole($currUserID, 'Writer');
+
+/* May 11/09: NO!!!!!!!!!!!!  Do NOT let user save to a project s/he doesn't have Write access to, even if it's public!!!!!!!!!!!!!!!!
+					// add public projects
+					$publicProjects = getPublicProjects();
+
+					foreach ($publicProjects as $key => $project)
+					{
+						$pID = $project->getPacketID();
+						$userProjects[] = $pID;
+					}
+					
+					$userProjects = array_unique($userProjects);
+*/
+				}
+				
+				// Important fix May 27/09: check user projects list is not empty - if it is, query produces error!!!!!!
+				if (count($userProjects) > 0)
+				{
+					$userProjectList = "(" . implode(",", $userProjects) . ")";
+	
+					$query = "SELECT p.packetID as packetID, p.packetName as packetName, u.lastname as owner FROM Packets_tbl p, Users_tbl u WHERE p.ownerID=u.userID AND p.packetID IN " . $userProjectList . " AND p.status='ACTIVE'";
+					$find_name_rs = mysql_query($query, $conn) or die("Error fetching packet ID:" . mysql_error());
+
+					// restored May 14/08
+					echo "<OPTION name=\"default\" value=\"0\" selected>-- Select Project -- </OPTION>";
+	
+					while ($find_name_ar = mysql_fetch_array($find_name_rs, MYSQL_ASSOC))
+					{
+						$temp_packet = $find_name_ar["packetID"] . ": " . $find_name_ar["owner"] . ": " . $find_name_ar["packetName"];
+	
+						if ($find_name_ar["packetID"] == $rIDpID)
+							echo "<OPTION selected name=\"pkt_" . $find_name_ar["packetID"] . "\" value=\"" . $find_name_ar["packetID"] . "\">" . $temp_packet . "</option>";
+						else
+							echo "<OPTION name=\"pkt_" . $find_name_ar["packetID"] . "\" value=\"" . $find_name_ar["packetID"] . "\">" . $temp_packet . "</option>";
+					}
+				}
+			}
+		}
+	}
+	
+
+	/**
+	* Retrieve from the database and output comments or description value for the reagent identified by $rid (since there is a separate table for storing comments, need special SELECT query and output procedure)
+	*
+	* @author John Paul Lee <ninja_gara at hotmail.com>
+	* @version 2005
+	*
+	* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	* @version 3.1 2006-01-05
+	*
+	* @param STRING $columnType Name of the required property - comments or description (different internal propertyID)
+	* @param INT $rid Internal database ID of the reagent in question
+	*
+	* @return STRING
+	*/
+	function get_General_Reagent_Comments($columnType, $rid)
+	{
+		global $conn;
+		$rfunc_obj = new Reagent_Function_Class();
+
+		$currentTypeID = 0;
+		
+		switch( $columnType )
+		{
+			case "description":
+				$currentTypeID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["description"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+				break;
+			case "comments":
+				$currentTypeID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["comments"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+				break;
+			case "verification comments":
+				$currentTypeID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["verification comments"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+				break;
+		}
+		
+		$foundCommentID_rs = mysql_query("SELECT `propertyValue` FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $rid  . "' AND `status`='ACTIVE' AND `propertyID`='" . $currentTypeID . "'" , $conn ) or die( "[died on comment search]: " . mysql_error() );
+
+		if( $foundCommentID_ar = mysql_fetch_array( $foundCommentID_rs, MYSQL_ASSOC ) )
+		{
+			$foundRealDesc_rs = mysql_query("SELECT `comment` FROM `GeneralComments_tbl` WHERE `commentID`='" . $foundCommentID_ar["propertyValue"] . "' AND `status`='ACTIVE'", $conn);
+			
+			if(  $foundRealDesc_ar = mysql_fetch_array( $foundRealDesc_rs, MYSQL_ASSOC ) )
+			{
+				return stripslashes($foundRealDesc_ar["comment"]);
+			}
+			else	# Added Oct 17/06 by Marina
+			{
+				return "";
+			}
+		}
+		
+		return "";
+	}
+	
+	
+	/**
+	* Calculate and output the length of the DNA sequence of the reagent identified by $rid
+	*
+	* @author John Paul Lee <ninja_gara at hotmail.com>
+	* @version 2005
+	*
+	* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	* @version 3.1 2006-09-27
+	*
+	* @param INT $rID Internal database ID of the reagent in question
+	*
+	* @return INT
+	*
+	* @deprecated (this function is no longer actively used but may be of use for future adaptations)
+	*/
+	# Modified Sept 26/06 by Marina
+	function output_length($rid)
+	{
+		global $conn;
+
+		// Update Aug. 17, 2010
+		$seqPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+
+		$foundSeqID_rs = mysql_query("SELECT s.`sequence` FROM `ReagentPropList_tbl` p, `Sequences_tbl` s WHERE p.`reagentID`='" . $rid . "' AND p.`propertyID` = '" . $seqPropID . "' AND s.`seqID`=p.`propertyValue` AND p.`status`='ACTIVE' AND s.`status`='ACTIVE'", $conn);
+
+		if ($foundSeqID_ar = mysql_fetch_array($foundSeqID_rs, MYSQL_ASSOC))
+		{
+			# The following code segment was written by Marina on Sept 26, 2006
+			$sequence = $foundSeqID_ar["sequence"];
+
+			if (strlen($sequence) > 0)
+			{
+				return strlen($sequence);
+			}
+			else
+			{
+				return null;
+			}
+		}
+	
+		return null;
+	}
+
+	/**
+	* Calculate and output the length of the protein sequence of the reagent identified by $rid
+	*
+	* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	* @version 3.1 2006-09-27
+	*
+	* @param INT $rID Internal database ID of the reagent in question
+	*
+	* @return INT
+	*
+	* @deprecated (this function is no longer actively used but may be of use for future adaptations)
+	*/
+	// Written Sept 27/06 by Marina
+	function outputProteinLength($rID)
+	{
+		global $conn;
+		
+		$protSeqRS = mysql_query("SELECT s.`sequence`, s.`length` FROM `Sequences_tbl` s, `ReagentPropList_tbl` r WHERE r.`reagentID`='" . $rID . "' AND r.`propertyID`='46' AND s.`seqID`=r.`propertyValue` AND r.`status`='ACTIVE' AND s.`status`='ACTIVE'", $conn) or die("Could not select protein sequence, frame and length: " . mysql_error());
+
+		if ($protSeq_ar = mysql_fetch_array($protSeqRS, MYSQL_ASSOC))
+		{
+			$sequence = $protSeq_ar["sequence"];
+			$length = $protSeq_ar["length"];
+
+			# First check if length has been stored explicitly
+			if ($length != "")
+			{
+				return $length;
+			}
+			else
+			{
+				# if length has not been stored, take the sequence and compute length on the fly
+				if (strlen($sequence) > 0)
+				{
+					return strlen($sequence);
+				}
+				else
+				{
+					# don't bother with frame, start and end; if there's no sequence forget about length
+					return null;
+				}
+			}
+		}
+
+		# don't bother with the rest, just return nothing
+		return null;
+	}
+
+
+	/**
+	* Filter out whitespace from $sequence ($sequence can be of any type - DNA, RNA or Protein)
+	*
+	* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	* @version 3.1 2006-08-25
+	*
+	* @param STRING $sequence
+	* @return STRING Sequence without leading, trailing and internal whitespace
+	*/
+	// Aug 25/06, Marina
+	function filter_spaces($sequence)
+	{
+		$outSeq = "";
+		$toks = array();
+
+		// Aug. 18, 2010: Strip off leading and trailing whitespace too
+		$sequence = trim($sequence);
+
+		$toks = explode(" ", $sequence);
+
+		foreach ($toks as $key=>$tok)
+		{
+			$outSeq .= $tok;
+		}
+
+		return $outSeq;
+	}
+ 
+
+	/**
+	* Output plain cDNA sequence in chunks of 10 nt
+	*
+	* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	* @version 3.1 2006-08-27
+	*
+	* @param STRING $sequence
+	*/
+	// Written Sept 27, 2006 by Marina
+	// Outputs plain cDNA sequence in chunks of 10 nt
+	function output_sequence($rID)
+	{
+		global $conn;
+		$rfunc_obj = new Reagent_Function_CLass();
+
+		$seqPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+
+		# Get nt sequence
+		$foundSeqID_rs = mysql_query("SELECT s.`sequence` FROM `ReagentPropList_tbl` p, `Sequences_tbl` s WHERE p.`reagentID`='" . $rID . "' AND p.`propertyID` = '" . $seqPropID . "' AND s.`seqID`=p.`propertyValue` AND p.`status`='ACTIVE' AND s.`status`='ACTIVE'", $conn);
+
+		if ($foundSeqID_ar = mysql_fetch_array($foundSeqID_rs, MYSQL_ASSOC))
+		{
+			$sequence = $foundSeqID_ar["sequence"];
+
+			if (strlen($sequence) > 0)
+			{
+				$dnaSeq = $rfunc_obj->spaces($sequence);
+
+				echo "<table cellpadding=\"2\" border=\"0\">";
+
+				if (strlen($dnaSeq) > 0)
+				{
+
+					$tmp_dna = split("\n", $dnaSeq);
+					
+					foreach ($tmp_dna as $i=>$tok)
+					{
+						echo "<TR>";
+	
+						$rowIndex = $i+1;
+	
+						if ($i == 0)	// first row
+						{
+							$rowStart = 1;
+						}
+						else
+						{
+							$rowStart = $i*100 + 1;
+						}
+						
+						// Nov. 3/06 - Output nt count on last line
+						if (strlen($sequence) >= ($rowIndex*100))
+						{
+							$rowEnd = $rowIndex*100;
+						}
+						else
+						{
+							$rowEnd = strlen($sequence);
+						}
+	
+						echo "<TD style=\"font-size:8pt; text-align:right; vertical-align:top; white-space:nowrap;\">" . $rowStart . " </TD>";
+						
+						$tmp_chunks = split(" ", $tok);
+	
+						foreach ($tmp_chunks as $j=>$chunk)
+						{
+							$chunk = trim($chunk);
+	
+							if (strlen($chunk) > 0)
+							{
+								echo "<TD>";
+									echo "<pre font-size:8pt; text-align:justify>" . $chunk . "</pre>";
+								echo "</TD>";
+							}
+						}
+	
+						echo "</TR>";
+					}
+				}
+				echo "</table>";
+			}
+			else
+			{
+				echo "";
+			}
+		}
+		else
+		{
+			echo "";
+		}
+	}
+
+
+	/**
+	* Retrieve from the database and return the longest translated frame of the current reagent's DNA sequence
+	*
+	* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	* @version 3.1 2006-08-27
+	*
+	* @param INT $rID
+	* @return INT
+	*/
+	// Written Sept 27, 2006 by Marina
+	// Output translation frame of a sequence
+	function getFrame($rID)
+	{
+		global $conn;
+		
+		$rfunc_obj = new Reagent_Function_CLass();
+		$gfunc_obj = new generalFunc_Class();
+
+		$reagentType = $gfunc_obj->getTypeID($rID);
+
+		// Modified Aug. 17/09: changed db structure
+		# Hardcoding protein sequence property ID but selection trivial
+		if ($rfunc_obj->hasAttribute($reagentType, $_SESSION["ReagentPropCategory_Name_ID"]["protein sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["Pprotein Sequence"]))
+		{
+			$propID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentPropCategory_Name_ID"]["protein sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]);
+		}
+		else if ($rfunc_obj->hasAttribute($reagentType, $_SESSION["ReagentPropCategory_Name_ID"]["protein translation"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]))
+		{
+			$propID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentPropCategory_Name_ID"]["protein translation"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+		}
+
+		$protSeqRS = mysql_query("SELECT s.`frame` FROM `Sequences_tbl` s, `ReagentPropList_tbl` r WHERE r.`reagentID`='" . $rID . "' AND r.`propertyID`='" . $propID . "' AND s.`seqID`=r.`propertyValue` AND r.`status`='ACTIVE' AND s.`status`='ACTIVE'", $conn) or die("Could not select frame: " . mysql_error());
+
+		if ($seqResult = mysql_fetch_array($protSeqRS, MYSQL_ASSOC))
+		{
+			return $seqResult["frame"];
+		}
+
+		return null;
+	}
+
+
+	/**
+	* Retrieve from the database and output the protein sequence of the reagent identified by $rID (print sequence in chunks of 10 aa)
+	*
+	* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	* @version 3.1 2006-08-27
+	*
+	* @param INT $rID
+	* @param STRING $outputType Differentiates between views (e.g. reagent details or modification)
+	*/
+	function outputProteinSequence($rID, $outputType)
+	{
+		global $conn;
+
+		$rfunc_obj = new Reagent_Function_CLass();
+		$gfunc_obj = new generalFunc_Class();
+
+		// Modified Aug. 17/09: Differentiate between protein translation as a feature of DNA and standalone protein sequence
+		$reagentType = $gfunc_obj->getTypeID($rID);
+
+		if ($rfunc_obj->hasAttribute($reagentType, "protein sequence", $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]))
+		{
+			$propID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["protein sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]);
+		}
+		else if ($rfunc_obj->hasAttribute($reagentType, "protein translation", $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]))
+		{
+			$propID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["protein translation"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+		}
+
+		$protSeqRS = mysql_query("SELECT s.`sequence`, s.`frame`, s.`start`, s.`end`, s.`length` FROM `Sequences_tbl` s, `ReagentPropList_tbl` r WHERE r.`reagentID`='" . $rID . "' AND r.`propertyID`='" . $propID . "' AND s.`seqID`=r.`propertyValue` AND r.`status`='ACTIVE' AND s.`status`='ACTIVE'", $conn) or die("Could not select sequence: " . mysql_error());
+
+		if ($seqResult = mysql_fetch_array($protSeqRS, MYSQL_ASSOC))
+		{
+			$constProtSeq = $seqResult["sequence"];
+			$protSeq = $rfunc_obj->spaces($constProtSeq);
+			$frame = $seqResult["frame"];
+			$startpos = $seqResult["start"];
+			$endpos = $seqResult["end"];
+			$length = $seqResult["length"];
+		}
+
+		if ($outputType != "modify")
+		{
+			echo "<table cellpadding=\"4\" border=\"0\">";
+			
+				$tmp_prot = split("\n", $protSeq);
+
+				foreach ($tmp_prot as $i=>$tok)
+				{
+					echo "<TR>";
+						$rowIndex = $i+1;
+						
+						if ($i == 0)	// first row
+						{
+							$rowStart = 1;
+						}
+						else
+						{
+							$rowStart = $i*100 + 1;
+						}
+						
+						// Nov. 3/06 - Output nt count on last line
+						if ($length >= ($rowIndex*100))
+						{
+							$rowEnd = $rowIndex*100;
+						}
+						else
+						{
+							$rowEnd = $length;
+						}
+						
+						//$rowEnd = $rowIndex*100;
+
+						// Updated July 15/08
+// july 15/08					echo "<TD nowrap style=\"font-size:10px; font-weight:bold; text-align:right; vertical-align:top\">" . $rowStart . " - " . $rowEnd . "</TD>";
+
+						// July 15/08: Show start position only
+						echo "<TD nowrap style=\"font-size:10px; font-weight:bold; text-align:right; vertical-align:top\">" . $rowStart . "</TD>";
+	
+						$tmp_chunks = split(" ", $tok);
+		
+						foreach ($tmp_chunks as $j=>$chunk)
+						{
+							$chunk = trim($chunk);
+	
+							if (strlen($chunk) > 0)
+							{
+								echo "<TD>";
+									echo "<pre font-size:11px;  text-align:justify>" . $chunk . "</pre>";
+								echo "</TD>";
+							}
+						}
+
+					echo "</TR>";
+				}
+				
+			echo "</table>";
+		}
+		else
+		{
+			echo "";
+		}
+	}
+
+
+	/**
+	* Retrieve from the database and output the RNA sequence of the reagent identified by $rID
+	*
+	* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	* @version 3.1 2010
+	*
+	* @param INT $rID
+	* @param STRING $outputType Obsolete, kept to be consistent with output_sequence and outputProteinSequence, but not used in this function
+	*
+	* @return STRING
+	*/
+	function outputRNASequence($rID, $outputType)
+	{
+		global $conn;
+
+		$rfunc_obj = new Reagent_Function_CLass();
+		$gfunc_obj = new generalFunc_Class();
+
+		// Modified Aug. 17/09: Differentiate between protein translation as a feature of DNA and standalone protein sequence
+		$reagentType = $gfunc_obj->getTypeID($rID);
+
+		$propID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["rna sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence"]);
+
+		$rnaSeqRS = mysql_query("SELECT s.`sequence`, s.`start`, s.`end`, s.`length` FROM `Sequences_tbl` s, `ReagentPropList_tbl` r WHERE r.`reagentID`='" . $rID . "' AND r.`propertyID`='" . $propID . "' AND s.`seqID`=r.`propertyValue` AND r.`status`='ACTIVE' AND s.`status`='ACTIVE'", $conn) or die("Could not select sequence: " . mysql_error());
+
+		if ($seqResult = mysql_fetch_array($rnaSeqRS, MYSQL_ASSOC))
+		{
+			$constRNASeq = $seqResult["sequence"];
+			$rnaSeq = $rfunc_obj->spaces($constRNASeq);
+			$startpos = $seqResult["start"];
+			$endpos = $seqResult["end"];
+			$length = $seqResult["length"];
+
+			echo $rnaSeq;
+		}
+	}
+
+
+	/**
+	 * Retrieve from the database and output the DNA sequence of the reagent identified by $rID
+	 *
+	 * Modified by Marina on April 20, 2006 - Assuming that all sequences are cDNA and translation should begin at the first nucleotide (previously was incorrectly relying on 5' start and 3' stop values).  This fixes the problem of sequences not being translated.
+	 *
+	 * Last modified: Feb. 14/08
+	 *
+	 * @author John Paul Lee <ninja_gara at hotmail.com>
+	 * @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2010
+	 *
+	 * @param INT $rID
+	 * @param STRING $typeOfOutput Dictates output format according to view
+	 *
+	*/
+	function output_sequence2($rid, $typeOfOutput)
+	{
+		global $conn;
+
+		$cdna_sequence = "";
+		$cdna_subsequence = "";
+		$protein_sequence = "";
+
+		$rfunc_obj = new Reagent_Function_Class();
+
+		// Aug. 17/09
+		$dnaSeqPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+
+		// 'protein sequence' or 'protein translation'??
+		$protSeqPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["protein sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]);
+
+		// NOTE: If you change the types of sequences that are available, you must add it here!
+		$foundSeqID_rs = mysql_query("SELECT `propertyID`, `propertyValue` FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $rid . "' AND `propertyID`='" . $dnaSeqPropID . "' AND `status`='ACTIVE'", $conn) or die("Could not select sequence: " . mysql_error());
+
+		while ($foundSeqID_ar = mysql_fetch_array($foundSeqID_rs, MYSQL_ASSOC))
+		{
+			$foundRealSeq_rs = mysql_query("SELECT `seqTypeID`, `sequence` FROM `Sequences_tbl` WHERE `seqID` IN ('" . $foundSeqID_ar["propertyValue"] . "') AND `status`='ACTIVE' ORDER BY `seqTypeID`", $conn);
+			
+			while(  $foundRealSeq_ar = mysql_fetch_array( $foundRealSeq_rs, MYSQL_ASSOC ) )
+			{
+				if( $foundRealSeq_ar["seqTypeID"] == $this->getSeqTypeID("DNA") && $foundSeqID_ar["propertyID"] == $dnaSeqPropID)
+				{
+					$cdna_sequence = $foundRealSeq_ar["sequence"];
+				}
+				elseif( $foundRealSeq_ar["seqTypeID"] == $this->getSeqTypeID("Protein") && $foundSeqID_ar["propertyID"] == $protSeqPropID)
+				{
+					$protein_sequence = $foundRealSeq_ar["sequence"];
+				}
+				else
+				{
+					// Aug. 17/09: add 'elseif RNA'
+
+					echo "ERROR! Did not find a matching propertyID for the database ID!";
+					return "";
+				}
+			}
+		}
+
+		switch ($typeOfOutput)
+		{
+			case 1:
+				// Basic output, with no frills
+				echo $cdna_sequence;
+			break;
+
+			case 2:
+				// Basic output with breaks in between every 10
+				echo chunk_split($cdna_sequence, 10, " ");
+			break;
+
+			case 3:
+				$cdna_sequence = trim($cdna_sequence);	// just a precaution
+				$tmp_dna = explode(" ", chunk_split($cdna_sequence, 10, " "));
+
+				$cols = 0;		// number of 10-nt chunks displayed in current row
+				$MAX_COL_CONST = 10;	// constant maximum number of 10-nt chunks per row
+
+				$rowCount = 0;
+				$colCount = 0;
+
+				$tok = trim($tmp_dna[$colCount]);
+
+				while ($tok)
+				{
+					if (strlen($tok) > 0)
+					{
+						$rowIndex = $rowCount+1;
+	
+						if ($rowCount == 0)	// first row
+						{
+							$rowStart = 1;
+						}
+						else
+						{
+							$rowStart = $rowCount*100 + 1;
+						}
+						
+						// Nov. 3/06 - Output nt count on last line
+						if (strlen($cdna_sequence) >= ($rowIndex*100))
+						{
+							$rowEnd = $rowIndex*100;
+						}
+						else
+						{
+							$rowEnd = strlen($cdna_sequence);
+						}
+	
+						// The following formatting produces an ULTIMATE alignment. DO NOT CHANGE!!!!!!!!!!! 
+						// Do not change the padding or size of the textarea either (in Reagent_Output_Class-> print_property_final->sequence->Modify - keep 120 cols)
+						if ($rowStart == 1)
+							echo "    ";
+// may 2/08					else if ($rowStart < 900)
+						else if ($rowStart <= 901)	// may 2/08
+							echo "  ";
+// may 2/08					else if ($rowStart > 901)
+						else		// may 2/08
+							echo " ";
+
+// Changed May 2/08, Marina - Karen asked to only show the start index like NCBI
+// may 2/08					echo $rowStart . "-" . $rowEnd . " ";
+
+	echo $rowStart . " ";
+						while ($cols < $MAX_COL_CONST)
+						{
+							echo trim($tok);
+							echo " ";
+							$cols++;
+							$colCount++;
+							$tok = trim($tmp_dna[$colCount]);
+						}
+					
+						$cols = 0;
+						echo "\n";
+					}
+
+					$rowCount++;
+				}
+			break;
+
+			// Aug. 30, 2010: This is not used, property names are obsolete, but don't remove yet - will need later when redesigning detailed view and showing DNA-protein alignment!
+			case 4:
+				// Case where you want to output alignment between cdna and protein and you have:
+				// 1. cdna sequence
+				// 2. protein sequence
+				// 3. 5' and 3' primers for the cdna sequence
+				
+				echo "<table border=1 width=100%>";
+				
+				$outputPlace = 0;
+				
+				$setCount = 0;  // Holds the number of sets currently outputted for this line
+				$lineCount = 0; // Holds the number of lines that have been outputted so far for this sequence
+				
+				
+				$maxLineOutput = 10;
+				
+				$fivePrimer = 0;
+				$threePrimer = 0;
+				
+				// Generic Sequence counters
+				$seqCount = 1;
+				$seqArrayCount = 0;
+				$seqIncrementor = 10;
+				
+				$proteinSeqCount = 0;
+				$proteinSpotCount = 0;
+				
+				$proteinStartSpot_tmp = 0;
+				$setProteinStart_tmp = 0;
+				
+				$output_seq = "";
+				
+				if( strlen( trim( $cdna_subsequence ) ) > 0)
+				{
+					$output_seq = trim( $cdna_subsequence );
+					
+				}
+				elseif( strlen( trim( $cdna_sequence ) ) > 0 )
+				{
+					$output_seq = trim( $this->filter_spaces($cdna_sequence) );
+
+					// If this is a full cdna sequence, grab the 5' and 3' cutters!
+					$primers_rs = mysql_query( "SELECT `propertyID`, `propertyValue` FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $rid . "' AND `propertyID` IN ('" . $_SESSION["ReagentProp_Name_ID"]["5' start"] . "','" . $_SESSION["ReagentProp_Name_ID"]["3' stop"] . "') AND `status`='ACTIVE'", $conn );
+
+					while( $primers_ar = mysql_fetch_array( $primers_rs, MYSQL_ASSOC ) )
+					{
+						if( $primers_ar["propertyID"] == $_SESSION["ReagentProp_Name_ID"]["5' start"] )
+						{
+							$fivePrimer = $primers_ar["propertyValue"];
+						}
+						elseif( $primers_ar["propertyID"] == $_SESSION["ReagentProp_Name_ID"]["3' stop"] )
+						{
+							$threePrimer = $primers_ar["propertyValue"];
+						}
+					}
+				}
+				else
+				{
+					// If no sequence was found for this reagent, just return nothing!!
+					// FIX-IT: There should be something better here
+					echo "<tr>";
+					echo "<td>";
+					echo "";
+					echo "</td>";
+					echo "</tr>";
+					echo "</table>";
+					return "";
+				}
+				
+				if( $fivePrimer == 0 && $threePrimer == 0 )
+				{
+					$fivePrimer = 1;
+					$threePrimer = strlen( $output_seq );
+				}
+
+				$cdna_length = strlen( $output_seq );
+				
+				$spacedSeq = chunk_split($output_seq, 10, " ");
+				$subSequence_ar = explode(" ", $spacedSeq);
+				
+				$startTag = "<span class=cdna>";
+				$endTag = "</span>";
+				
+				$setSeparator = " ";
+				
+				echo $startTag;
+
+// aug. 30, 2010: if using this code, uncomment translate() function
+				$protein_sequence = $this->translate( $output_seq, $fivePrimer, $threePrimer );
+
+				$isDone = false;
+				
+				while (!$isDone)
+				{
+					if( $setCount == 0 )
+					{
+						// Output the new start of the row!
+						echo "";
+						echo "<tr>";
+						echo "<td>";
+
+						echo ( ( $lineCount * ( $seqIncrementor * $maxLineOutput ) ) + 1 );
+						echo "-";
+						echo ( ( $lineCount + 1 ) * ( $seqIncrementor * $maxLineOutput ) );
+						echo "</td>";
+						echo "<td>";
+						echo "<tt>";
+					}
+				
+					if( $outputPlace == 0  )
+					{
+						// If the output is BEFORE the protein sequence
+						$seqCount += $seqIncrementor;
+
+						$spotInSub = 0;
+						$temp1 =  substr( $subSequence_ar[ $seqArrayCount ], 0 , $spotInSub  );
+						$temp2 =  substr( $subSequence_ar[ $seqArrayCount ], $spotInSub , $seqIncrementor );	
+						$setProteinStart_tmp = $setCount;
+						$proteinStartSpot_tmp = $spotInSub;
+						
+						echo $temp1;
+						echo $startTag . $temp2 . $endTag;
+						
+						$seqArrayCount++;
+						$setCount++;
+						
+						// Change the placement of the output is in!
+						$outputPlace = 1;
+					}
+					elseif( $outputPlace == 1 )
+					{
+						$seqCount += $seqIncrementor;
+						
+						// If the output is IN the protein sequence
+						if( $seqCount < $threePrimer )
+						{
+							echo $startTag . $subSequence_ar[ $seqArrayCount ] . $endTag;
+							
+							$seqArrayCount++;
+							$setCount++;
+						}
+						else
+						{
+							$spotInSub = $threePrimer % $seqIncrementor;
+							
+							echo $startTag . substr( $subSequence_ar[ $seqArrayCount ], 0 , $spotInSub  ) . $endTag;
+							echo substr( $subSequence_ar[ $seqArrayCount ], $spotInSub , ( $seqIncrementor ) );
+							
+							$seqArrayCount++;
+							$setCount++;
+							
+							// Change the placement of the output is in!
+							$outputPlace = 2;
+						}
+					}
+					elseif( $outputPlace == 2 )
+					{
+						// If the output is AFTER the protein sequence
+						
+						$seqCount += $seqIncrementor;
+						echo $subSequence_ar[ $seqArrayCount ];
+							
+						$seqArrayCount++;
+						$setCount++;
+					}
+			
+					if( !($seqCount <= $cdna_length) )	// '=' sign added Apr 19/06 by Marina and Adrian
+					{
+						$isDone = true;
+					}
+					
+					if( $setCount == $maxLineOutput || $isDone )
+					{
+						// Output the end of the row!
+						echo "<br>";
+						$lineCount++;
+						$setCount = 0;
+					}
+					else
+					{
+						echo $setSeparator;
+					}
+					
+					if( ( $outputPlace == 1 || $outputPlace == 2 )  && $setCount == 0 )
+					{
+						// Sept 7/06, Marina -- Passing arguments by reference is deprecated, get warnings - but removing the '&' breaks the code, get incorrect sequence translation.  Keep it for now and investigate, perhaps change later
+
+// aug. 30, 2010: if using this code, uncomment outputProteinSeq() function
+						$proteinSpotCount = $this->outputProteinSeq($protein_sequence, $proteinStartSpot_tmp, $setProteinStart_tmp, &$proteinSeqCount, $proteinSpotCount);
+
+						$setProteinStart_tmp = 0;
+						$proteinStartSpot_tmp = 0;
+					}
+					elseif( $setCount == 0 )
+					{
+						echo "<BR>";
+					}
+				}
+				
+				echo $endTag;
+				
+				echo "</table>";
+			break;
+
+			case 5:
+				echo chunk_split($cdna_sequence, 10, " ");
+			break;
+		}
+	}
+
+/* Aug. 30, 2010: Not used in this version but don't delete yet, will need for outputting DNA-protein alignment view
+	function outputProteinSeq($protein_sequence, $proteinStartSpot_tmp, $setProteinStart_tmp, $proteinSeqCount, $proteinSpotCount)
+	{
+		// Output the PROTEIN SEQUENCE
+		//if( $outputPlace == 1 && $setCount == 0 )
+		//echo "protein seq left: " . $protein_sequence . "<br>";
+		//echo "proteinstartspot: " . $proteinStartSpot_tmp . " -- setproteinstart: " . $setProteinStart_tmp 
+			//. " -- proteinSeqcount: " . $proteinSeqCount . " -- proteinSpotcount: " . $proteinSpotCount . "<BR>";
+		$startTag = "<tt>";
+		$endTag = "</tt>";
+
+		// While IN the protein sequence
+
+		$finishedProteinOutput = false;
+		//echo "What is this?:" . $proteinStartSpot_tmp . "<BR>";
+		echo $startTag . str_repeat( " ", $proteinStartSpot_tmp ) . $endTag;
+		echo $startTag . str_repeat( $this->setSeparator, ($setProteinStart_tmp * $this->seqIncrementor) ) . $endTag;
+		
+		while(!$finishedProteinOutput)
+		{
+			switch($proteinSpotCount)
+			{
+				case 0:
+					//Before the first DNA codon for the Protein
+					$proteinSpotCount++;
+					break;
+				case 1: 
+					// first actual DNA codon for the Protein
+					$proteinStartSpot_tmp++;
+					$proteinSpotCount++;
+					echo " ";
+					break;
+				case 2:
+					// Output DNA codon for protein
+					echo "<span class=protein>" . substr( $protein_sequence, $proteinSeqCount, 1 ) . "</span>";
+					
+					$proteinSpotCount++;
+					$proteinSeqCount++;
+					$proteinStartSpot_tmp++;
+					break;
+				case 3:
+					$proteinStartSpot_tmp++;
+					
+					$proteinSpotCount = 1;
+					echo " ";
+					break;
+			}
+			
+			if( $proteinStartSpot_tmp >= $this->seqIncrementor )
+			{
+				// Will add a space when protein current spot is greater than the max set! ie. new set needed!
+
+				echo $this->setSeparator;
+
+				$proteinStartSpot_tmp = 0;
+				$setProteinStart_tmp++;
+				
+				
+			}
+			
+			if( $setProteinStart_tmp == $this->maxLineOutput )
+			{
+				echo "</tt>";
+				echo "</td>";
+				echo "</tr>";
+				
+				$finishedProteinOutput = true;
+				$proteinStartSpot_tmp = 0;
+				$setProteinStart_tmp = 0;
+			}
+		}
+		
+		return $proteinSpotCount;
+	}
+*/
+
+	/**
+	* Output Insert accession number as a hyperlink to NCBI
+	*
+	* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	* @version 3.1
+	*
+	* @param INT $rid
+	*
+	*/
+	// aug. 30, 2010: removed $output_type argument
+	function outputAccession($rid)
+	{
+		global $conn;
+		$functionerror =  ".outputAccession(";
+		$rfunc_obj = new Reagent_Function_Class();
+
+		$to_return = "<TABLE>";
+
+		$to_return = "<ul style=\"padding-left:1.5em; padding-top:0.5em;\">";
+
+		$accPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["accession number"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]);
+
+		$ar_rs = mysql_query("SELECT `propertyID`, `propertyValue` FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $rid . "' AND `propertyID`='" . $accPropID . "'" . " AND `status`='ACTIVE'", $conn) or die($this->classerror . $functionerror . "1)" . mysql_error());
+	
+		while ($ar_ar = mysql_fetch_array($ar_rs, MYSQL_ASSOC))
+		{
+			if (strcasecmp($ar_ar["propertyValue"], "in house" ) != 0)
+			{
+				$to_return = $to_return . "<li style=\"font-size:8pt\"><a href=\"http://www.ncbi.nlm.nih.gov/entrez/viewer.fcgi?cmd=Search&db=nuccore&val=" . $ar_ar["propertyValue"] . "&doptcmdl=GenBank&cmd=retrieve\" target=\"_blank\">" . strtoupper($ar_ar["propertyValue"]) . "</a></li>";
+			}
+			else
+			{
+				$to_return = $to_return . "<li style=\"font-size:8pt\">" . $ar_ar["propertyValue"] . "</li>";;
+			}
+		}
+
+		$to_return = $to_return .  "</ul>";
+
+		return $to_return;
+	}
+
+	/**
+	 * Output Alternate ID for Insert and Cell Line.
+	 *
+	 * Special output format: During modification, user selects a checkbox that contains the name of the external identifier (e.g. Kasuza, IMAGE, RIKEN, etc.) and types in the numerical portion; the two are then joined together by processing code.  On the detailed view, all external ID values are printed as a bulleted list.
+	 *
+	 * @author John Paul Lee <ninja_gara at hotmail.com>
+	 * @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT $rid
+	 * @param STRING $output_type Differentiate between 'View' and 'Modify' modes
+	 * @param STRING $category See explanation of reagent type attribute categories.  In the case of Alternate ID, the category will almost certainly always be 'External Identifiers' - however, for consistent function calls and added flexibility, keep category as a function argument.
+	 * @param INT $rTypeID Reagent type ID - new in v.3.1, needed for retrieving external db names specific to this reagent type
+	*/
+	function output_Alternate_ID($rid, $output_type, $category, $rTypeID)
+	{
+		global $conn;
+		$functionerror =  ".output_Alternate_ID(";
+		$rfunc_obj = new Reagent_Function_Class();
+
+		$to_return = "<TABLE>";
+
+		$altIDPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["alternate id"], $_SESSION["ReagentPropCategory_Name_ID"][$category]);
+
+		if ($output_type == "Modify")
+		{
+			// existing for this reagent
+			$ar_rs = mysql_query("SELECT propertyValue FROM ReagentPropList_tbl WHERE reagentID='" . $rid . "' AND propertyID='" . $altIDPropID . "' AND `status`='ACTIVE'", $conn) or die($this->classerror . $functionerror . "1)" . mysql_error());
+
+			while ($r_exist_ar = mysql_fetch_array($ar_rs, MYSQL_ASSOC))
+			{
+				$value = $r_exist_ar["propertyValue"];
+				$ar_ar[] = $value;
+
+				// get the actual ID portion
+				$tmp_ids[substr($value, 0, strpos($value, ":"))] = substr($value, strpos($value, ":")+1, strlen($value));
+			}
+
+			// All alt. IDs
+			$propID = $rfunc_obj->getRTypeAttributeID($rTypeID, "alternate id", $_SESSION["ReagentPropCategory_Name_ID"][$category]);
+
+			$set_rs = mysql_query("SELECT b.entityName FROM System_Set_Groups_tbl a, System_Set_tbl b WHERE a.ssetGroupID=b.ssetGroupID AND a.reagentTypeAttributeID='" . $propID . "' AND a.status='ACTIVE' AND b.status ='ACTIVE' ORDER BY b.entityName", $conn) or die("FAILURE IN Reagent_Creator_Class.print_set(1): " . mysql_error());
+
+			while($set_ar = mysql_fetch_array($set_rs, MYSQL_ASSOC))
+			{
+				$ids_ar[] = $set_ar["entityName"];
+			}
+
+			//print_r(array_values($ids_ar));
+
+			foreach ($ids_ar as $num => $key)
+			{
+				if (in_array($key, array_keys($tmp_ids)))
+				{
+					$value = $tmp_ids[$key];
+
+					$to_return .= "<TR ID=\"alt_id_row_" . $key . "\" style=\"display:table-row\">";
+
+					$to_return .= "<TD>" . $key . ":</TD>";
+
+					$to_return .= "<TD>";
+
+					// Python form input
+					$to_return .= "<INPUT type=\"hidden\" name=\"reagent_detailedview_alternate_id_prop\" value=\"" . $key . "\">";
+
+					$to_return .= "<INPUT ID=\"" . $key . "_alternate_id_textbox\" name=\"alternate_id_" . $key . "_textbox_name\" size=\"15\" VALUE=\"" . $value . "\"></INPUT>";
+				}
+				else
+				{
+					$to_return .= "<TR ID=\"alt_id_row_" . $key . "\" style=\"display:none\">";
+
+					$to_return .= "<TD>" . $key . ":</TD>";
+
+					$to_return .= "<TD>";
+				
+					$to_return .= "<INPUT ID=\"" . $key . "_alternate_id_textbox\" name=\"alternate_id_" . $key . "_textbox_name\" size=\"15\" VALUE=\"\"></INPUT>";
+				}
+
+				$to_return .= "</TD>";
+				$to_return .= "</TR>";
+			}
+
+				// Add 'Other' row
+				$to_return .= "<TR ID=\"alt_id_row_Other\" style=\"display:none\">";
+				
+					$to_return .= "<TD>Other:</TD>";
+
+					$to_return .= "<TD>";
+
+					$to_return .= "<INPUT ID=\"Other_alternate_id_textbox\" name=\"alternate_id_name_txt\" size=\"15\" VALUE=\"\"></INPUT>";
+					
+					$to_return .= "</TD>";
+					
+				$to_return .= "</TR>";
+
+			$to_return .= "</TABLE>";
+		}
+		else
+		{
+			$to_return = "<ul style=\"padding-left:1.5em; padding-top:0.5em;\">";
+
+			$ar_rs = mysql_query("SELECT `propertyID`, `propertyValue` FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $rid . "' AND `propertyID`='" . $altIDPropID . "'" . " AND `status`='ACTIVE'", $conn) or die($this->classerror . $functionerror . "1)" . mysql_error());
+		
+			while ($ar_ar = mysql_fetch_array($ar_rs, MYSQL_ASSOC))
+			{
+				$to_return = $to_return . "<li style=\"font-size:8pt\">" . strtoupper($ar_ar["propertyValue"]) . "</li>";
+			}
+	
+			$to_return = $to_return .  "</ul>";
+		}
+
+		return $to_return;
+	}
+
+
+	/**
+	 * Output Selectable Marker (Jan. 28/08, Marina: "Selectable Marker" replaces both Antibiotic Resistance and Resistance Marker for Vector, for Cell Line resistance marker is still used - see output_Resistance_Marker() function)
+	 *
+	 * @author John Paul Lee <ninja_gara at hotmail.com>
+	 * @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT $rid
+	 * @param STRING $output_type Differentiate between 'View' and 'Modify' modes
+	*/
+	function output_Selectable_Marker($rid, $output_type)
+	{
+		global $conn;
+
+		$functionerror =  ".output_Selectable_Marker(";
+
+		$rfunc_obj = new Reagent_Function_CLass();
+
+		$to_return = "<ul style=\"padding-left:1.5em; padding-top:0.5em;\">";
+
+		$ar_rs = mysql_query("SELECT DISTINCT(`propertyValue`) FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $rid . 
+			"' AND `propertyID` IN ('" . $_SESSION["ReagentProp_Name_ID"]["selectable marker"] . "')"
+			. " AND `status`='ACTIVE'", $conn) or die( $this->classerror . $functionerror . "1)" . mysql_error() );
+
+		while( $ar_ar = mysql_fetch_array( $ar_rs, MYSQL_ASSOC ) )
+		{
+			$to_return .= "<li>" . $ar_ar["propertyValue"];
+
+			$pStart = $rfunc_obj->getStartPos($rid, "selectable marker", $_SESSION["ReagentProp_Name_ID"]["selectable marker"], $ar_ar["propertyValue"]);
+
+			$pEnd = $rfunc_obj->getEndPos($rid, "selectable marker", $_SESSION["ReagentProp_Name_ID"]["selectable marker"], $ar_ar["propertyValue"]);
+
+			// pStart can be 0 (right at the beginning of sequence), but if pEnd is 0, that means the value does not exist
+			if ($pEnd != 0)
+			{
+				$to_return .= "  <span style=\"color:#FF7F24\">(nt " . $pStart . " -";
+				$to_return .= " " . $pEnd . ")</span>";
+			}
+
+			$to_return .= "</li>";
+		}
+
+		$to_return = $to_return .  "</ul>";
+		
+		return $to_return;
+
+	}
+
+	/**
+	 * Output Resistance Marker for Cell Lines (restored March 3/09)
+	 *
+	 * @author John Paul Lee <ninja_gara at hotmail.com>
+	 * @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT $rid
+	 * @param STRING $output_type Differentiate between 'View' and 'Modify' modes
+	*/
+	function output_Resistance_Marker($rid, $output_type)
+	{
+		global $conn;
+		$functionerror =  ".output_Resistance_Marker(";
+		$to_return = "<ul>";
+
+		$rm_prop_id =  $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["resistance marker"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]);
+
+		$ar_rs = mysql_query( "SELECT `propertyID`, `propertyValue` FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $rid . "' AND `propertyID`='" . $rm_prop_id . "' AND `status`='ACTIVE'" , $conn  ) or die( $this->classerror . $functionerror . "1)" . mysql_error() );
+		
+		if (count($ar_ar) > 0)
+		{
+			while ($ar_ar = mysql_fetch_array($ar_rs, MYSQL_ASSOC))
+			{
+				$to_return = $to_return . "<li>" . $ar_ar["propertyValue"] . "</li>";
+			}
+		}
+		else
+		{
+// 			echo "here??";
+		}
+
+		$to_return = $to_return .  "</ul>";
+		return $to_return;
+	}
+
+
+	/**
+	 * Output sequence features with multiple values
+	 *
+	 * Dec. 9/09: Differentiate between *units* - output 'aa' for Protein and 'nt' for DNA
+	 *
+	 * @author John Paul Lee <ninja_gara at hotmail.com>
+	 * @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2008-03-06
+	 *
+	 * @param INT $rid
+	 * @param STRING $feature_type
+	 * @param STRING $category (either 'DNA Sequence Features', 'Protein Sequence Features', or 'RNA Sequence Features')
+	*/
+	function output_Sequence_Features($rid, $feature_type, $category)
+	{
+		global $conn;
+
+		$functionerror =  ".output_Sequence_Features(";
+
+		$rfunc_obj = new Reagent_Function_CLass();
+
+		$fAlias = $rfunc_obj->getReagentPropertyAlias($feature_type);
+
+		$propID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][strtolower($feature_type)], $_SESSION["ReagentPropCategory_Name_ID"][$category]);	
+
+		$to_return = "<ul style=\"padding-left:1.5em; padding-top:0.5em;\">";
+
+ 		// April 1/08, Marina: Sort output values by position
+		$ar_rs = mysql_query("SELECT DISTINCT(propertyValue), startPos, endPos, direction FROM ReagentPropList_tbl WHERE reagentID='" . $rid . "' AND propertyID='" . $propID . "' AND propertyValue <> '' AND status='ACTIVE' ORDER BY startPos", $conn) or die("Could not select sequence feature: " . mysql_error());
+
+		while ($ar_ar = mysql_fetch_array($ar_rs, MYSQL_ASSOC))
+		{
+			$to_return .= "<li>" . stripslashes($ar_ar["propertyValue"]);
+
+			// April 1, 2009: For Cell Line just output the name of the selectable marker, w/o positions or direction
+			if (((strcasecmp(strtolower($feature_type), "selectable marker") == 0) && ($rfunc_obj->getType($rid) != $_SESSION["ReagentType_Name_ID"]["CellLine"])) || (strcasecmp(strtolower($feature_type), "selectable marker") != 0))
+			{
+				// Positions
+				$pStart = $ar_ar["startPos"];
+				$pEnd = $ar_ar["endPos"];
+	
+				// pStart can be 0 (right at the beginning of sequence), but if pEnd is 0, that means the value does not exist
+				if ($pEnd != 0)
+				{
+					$to_return .= " <span style=\"color:#006400\">(nt " . $pStart . " -";
+					$to_return .= " " . $pEnd . ")</span>";
+				}
+	
+				$fDirection = $ar_ar["direction"];
+	
+				$to_return .= ", " . $fDirection . " orientation";
+		
+				// March 17/08: Add a descriptor for selected features (tag position for tag type and expression system for promoter)
+				$fDescr = $rfunc_obj->getFeatureDescriptor($rid, $_SESSION["ReagentProp_Name_ID"][$feature_type], $ar_ar["propertyValue"]);
+	
+				if (strlen($fDescr) > 0)
+				{
+					$caption = "";
+	
+					// April 1/08: Need to add caption for the descriptor - actual descriptor property name (tag position, expression system)
+					switch (strtolower($feature_type))
+					{
+						case 'tag':
+							$caption = ", position";
+						break;
+						
+						case 'promoter':
+							$caption = ", expression system";
+						break;
+	
+						default:
+						break;
+					}
+	
+					$to_return .= $caption . " " . $fDescr;
+				}
+			}
+			$to_return .= "</li>";
+		}
+
+		$to_return = $to_return .  "</ul>";
+
+		return $to_return;
+	}
+
+/* Aug. 30, 2010: seems to only be used in output_sequence2() => 'switch' => case 4 ==> don't delete it yet
+	// Modified April 20, 2006 by Marina
+	// Making the assumption that every sequence is a cDNA sequence and its translation should begin at the first nucleotide
+	function translate($sequence, $start, $stop)
+	{
+		$sequence = strtolower( $sequence );
+// 		echo "start: " . $start . " -- stop: " . $stop . "<BR>";
+// 		echo "length: " . strlen( $sequence ) . "<BR>";
+
+// Removed April 20/06 by Marina
+// 		if( $start <= 0 || $stop <= 0 || $stop > strlen( $sequence ) || $stop <= $start )
+// 		{
+// 			return "";
+// 		}
+
+		//echo "stage 2------------------";
+
+// apr 20	$cdna_seq = substr( $sequence, ( $start - 1 ), ( $stop - $start ) );
+
+		$cdna_seq = $sequence;	// April 20/06, Marina
+
+// 		echo "trying cdna_seq : " . $cdna_seq . "<br>";
+		$newProteinSeq = "";
+		
+		$spaced_cdna = chunk_split( $cdna_seq, 3, "|" );
+		$aminoacid_ar = explode( "|", $spaced_cdna );
+		
+		foreach( $aminoacid_ar as $key => $value )
+		{
+			$newProteinSeq = $newProteinSeq . $this->convertToAA( $value );
+		}
+		
+// 		echo "new protein trans: " . $newProteinSeq . "<BR>";
+		return $newProteinSeq;
+	}
+*/
+	
+	/**
+	 * Determine seqTypeID from seqTypeName
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param STRING $toFind Sequence type name (one of 'DNA', 'RNA' or 'Protein') - corresponds to seqTypeName column in SequenceTypes_tbl
+	 * @return INT SequenceTypes_tbl.seqTypeID column value
+	*/
+	function getSeqTypeID($toFind)
+	{
+		global $conn;
+		
+		$type_rs = mysql_query("SELECT `seqTypeID` FROM `SequenceType_tbl` WHERE `status`='ACTIVE' AND `seqTypeName`='" . $toFind . "'", $conn);
+		
+		if ($type_ar = mysql_fetch_array($type_rs, MYSQL_ASSOC))
+		{
+			return $type_ar["seqTypeID"];
+		}
+		
+		return -1;
+	}
+	
+
+	/**
+	 * Return the amino acid that corresponds to the given codon (one-character representation)
+	 *
+	 * @author John Paul Lee <ninja_gara at hotmail.com>
+	 * @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param STRING Nucleotide codon triplet
+	 * @return CHAR
+	*/
+	function convertToAA($threeCodons)
+	{
+		switch(strtolower($threeCodons))	// Aug. 30, 2010, Marina: just in case, add strtolower() call here to be sure
+		{
+			case "ttt":
+			case "ttc": return "F";
+				break;
+			case "tta":
+			case "ttg": 
+			case "ctt":
+			case "ctc":
+			case "cta":
+			case "ctg": return "L";
+				break;
+			case "att":
+			case "atc":
+			case "ata": return "I";
+				break;
+			case "atg": return "M";
+				break;
+			case "gtt":
+			case "gtc":
+			case "gta":
+			case "gtg": return "V";
+				break;
+			case "tct":
+			case "tcc":
+			case "tca":
+			case "tcg":
+			case "agt":
+			case "agc": return "S";
+				break;
+			case "aga":
+			case "agg":
+			case "cgt":
+			case "cgc":
+			case "cga":
+			case "cgg": return "R";
+				break;
+			case "cct":
+			case "ccc":
+			case "cca":
+			case "ccg": return "P";
+				break;
+			case "act":
+			case "acc":
+			case "aca":
+			case "acg": return "T";
+				break;
+			case "gct":
+			case "gcc":
+			case "gca":
+			case "gcg": return "A";
+				break;
+			case "tat":
+			case "tac": return "Y";
+				break;
+			case "taa":
+			case "tag":
+			case "tga": return "*";
+				break;
+			case "tgt":
+			case "tgc": return "C";
+				break;
+			case "tgg": return "W";
+				break;
+			case "ggt":
+			case "ggc":
+			case "gga":
+			case "ggg": return "G";
+				break;
+			case "cat":
+			case "cac": return "H";
+				break;
+			case "caa":
+			case "cag": return "Q";
+				break;
+			case "aat":
+			case "aac": return "N";
+				break;
+			case "aaa":
+			case "aag": return "K";
+				break;
+			case "gat":
+			case "gac": return "D";
+				break;
+			case "gaa":
+			case "gag": return "E";
+				break;
+			
+		}
+	}
+}
+
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Reagent/Reagent_Background_Class.php b/OpenFreezer/Reagent/Reagent_Background_Class.php
new file mode 100755
index 0000000..f56d9df
--- /dev/null
+++ b/OpenFreezer/Reagent/Reagent_Background_Class.php
@@ -0,0 +1,691 @@
+<?php
+/**
+*
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Reagent
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+ * Contains functions for handling reagent associations (parent-child)
+ *
+ * @author John Paul Lee @version 2005
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Reagent
+ *
+ * @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+
+class Reagent_Background_Class
+{
+	/**
+	 * @var Array
+	 * Map of association property ID => name (reflects Assoc_Prop_Type_tbl columns)
+	*/
+	var $AProp_ID_Name;
+
+	/**
+	 * @var Array
+	 * Map of association property name => ID (reflects Assoc_Prop_Type_tbl columns) - inverse of $AProp_ID_Name
+	*/
+	var $AProp_Name_ID;
+
+	/**
+	 * @var STRING
+	 * Error message returned by this class in various cases (contains the name of this class to help pinpoint the source of the error)
+	*/
+	var $classerror;
+	
+	/**
+	 * Zero-argument constructor
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	*/
+	function Reagent_Background_Class()
+	{
+		global $conn;
+		
+		$this->AProp_ID_Name = array();
+		$this->AProp_Name_ID = array();
+		$this->classerror = "Reagent_Background_Class->";
+
+		$aprop_rs = mysql_query("SELECT * FROM `Assoc_Prop_Type_tbl` WHERE `status`='ACTIVE'", $conn ) or die( "FAILURE IN Reagent_BackGround_Class.Reagent_Background_Class(1): " . mysql_error() );
+
+		while( $aprop_ar = mysql_fetch_array( $aprop_rs, MYSQL_ASSOC ) )
+		{
+			$this->AProp_ID_Name[ $aprop_ar["APropertyID"] ] = $aprop_ar["APropName"];
+			$this->AProp_Name_ID[ $aprop_ar["APropName"] ] = $aprop_ar["APropertyID"];
+		}
+	}
+	
+	/**
+	 * Fetches from the database and returns an integer that corresponds to a particular association type identified by $name.
+	 * E.g. if $name is 'CellLine Stable', the return value is '5'.
+	 * Result corresponds to ATypeID column in AssocType_tbl (input argument corresponds to 'association' column).
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param STRING
+	 * @return INT
+	*/
+	function get_Association_Type($name)
+	{
+		global $conn;
+		$functionerror = "get_Association_Type(";
+		
+		$type_rs = mysql_query("SELECT * FROM `AssocType_tbl` WHERE `status`='ACTIVE' AND `association`='" . trim($name) . "'", $conn) or die( $this->classerror . $functionerror . "13)" . mysql_error());
+
+		if( $type_ar = mysql_fetch_array( $type_rs, MYSQL_ASSOC ) )
+		{
+			return $type_ar["ATypeID"];
+		}
+		
+		return -1;
+	}
+	
+
+	/**
+	 * Retrieves the value of APropertyID column in Assoc_Prop_Type_tbl that corresponds to APropName identified by $name
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param STRING
+	 * @return INT
+	*/
+	function get_Association_Property_Type($name)
+	{
+		global $conn;
+
+		$functionerror = "get_Association_Property_Type(";
+		
+		$name = strtolower( $name );
+		
+		// Jan 20/06, Marina
+		$query = "SELECT * FROM `Assoc_Prop_Type_tbl` WHERE `APropName`='" . trim( $name ) . "' AND `status`='ACTIVE'";
+
+		// Jan 20, Marina
+		$type_rs = mysql_query($query, $conn) or die($this->classerror . $functionerror . "13)" . mysql_error());
+
+		if ($type_ar = mysql_fetch_array($type_rs, MYSQL_ASSOC))
+		{
+			return $type_ar["APropertyID"];
+		}
+
+		return -1;
+	}
+	
+
+	/**
+	 * Retrieves the association ID for a given reagent identified by $rid.  Returns value of assID column in Association_tbl that corresponds to $rid.
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT
+	 * @param STRING
+	 * @return INT
+	*/
+	function get_Assocation_ID($rid, $type)
+	{
+		global $conn;
+		$functionerror = "get_Assocation_ID(";
+		
+		$check_rs = mysql_query("SELECT * FROM `Association_tbl` WHERE `reagentID`='" . $rid . "' " . "AND `status`='ACTIVE' AND `ATypeID`='" . $this->get_Association_Type( $type ) . "'", $conn )or die( $this->classerror . $functionerror . "8): " . mysql_error() );
+		
+		if ($check_ar = mysql_fetch_array($check_rs, MYSQL_ASSOC))
+		{
+			return $check_ar["assID"];
+		}
+		
+		return -1;
+	}
+	
+
+	/**
+	 * Return the ID of the parent of reagent identified by $rid.  Parent specification is given by $type - to determine which of the parents should be returned if there is more than one, e.g. parent vector or parent insert for non-recombination vector.  Return -1 if parent is not found.
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT
+	 * @param STRING
+	 * @return INT
+	*/
+	function get_Background_rid($rid, $type)
+	{
+		global $conn;
+
+		$type = strtolower($type);
+
+		if (in_array($type, $this->AProp_ID_Name))
+		{
+			$vpID_rs = mysql_query("SELECT * FROM `AssocProp_tbl` a, `Association_tbl` b WHERE a.`assID`=b.`assID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND b.`reagentID`='" . $rid . "' AND a.`APropertyID`='" . $this->AProp_Name_ID[$type] . "' ", $conn) or die( "FAILURE IN Reagent_BackGround_Class.get_Background_rid(1): " . mysql_error());
+
+			if( $vpID_ar = mysql_fetch_array( $vpID_rs, MYSQL_ASSOC ) )
+			{
+				return $vpID_ar["propertyValue"];
+			}
+		}
+		
+		return -1;
+	}
+	
+
+	/**
+	 * Return the potential parent types for a given reagent type (e.g. Vector and Insert can be used to generate a Vector, but a Cell Line can never be the parent of a Vector).
+	 *
+	 * (This is not 100% perfect, because reagent subtypes are not taken into account. I.e. an Insert is only a potential parent of Vector, but not of any Vector - only of non-recombination vectors, not recombination!  This function is used in Reagent_Output_Class->print_Detailed_Reagent_Other(), to display parents on detailed view, but there's still hard-coding to differentiate between Vector subtypes.  Needs to be refined in the future.)
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT
+	 * @return Array
+	*/
+	function getAssociationTypes($rTypeID)
+	{
+		global $conn;
+		$gfunc_obj = new generalFunc_Class();
+
+		$assocTypes = Array();
+
+		$resultSet = mysql_query("SELECT APropertyID, reagentTypeID, APropName FROM Assoc_Prop_Type_tbl WHERE reagentTypeID='" . $rTypeID . "' AND status='ACTIVE'", $conn) or die(mysql_error());
+
+		while ($results = mysql_fetch_array($resultSet, MYSQL_ASSOC))
+		{
+			$assocTypes[] = $results["APropertyID"];
+		}
+
+		return $assocTypes;
+	}
+
+	/**
+	 * Retrieve parent IDs of a given reagent.
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT
+	 * @return Array
+	*/
+	function getReagentParents($reagentIDToView)
+	{
+		global $conn;
+		$gfunc_obj = new generalFunc_Class();
+
+		$parents = Array();
+
+		$resultSet = mysql_query("SELECT APropertyID, propertyValue FROM Association_tbl a, AssocProp_tbl p WHERE a.reagentID='" . $reagentIDToView . "' AND a.assID=p.assID AND a.status='ACTIVE' AND p.status='ACTIVE'", $conn) or die("Error in getReagentParents() function: " . mysql_error());
+
+		while ($results = mysql_fetch_array($resultSet, MYSQL_ASSOC))
+		{
+			$parentID = $results["propertyValue"];
+			$assocPropID = $results["APropertyID"];
+
+			if (!in_array($assocPropID, array_keys($parents)))
+				$tmp_ar = Array();
+			else
+				$tmp_ar = $parents[$assocPropID];
+
+			$tmp_ar[] = $parentID;
+
+			$parents[$assocPropID] = $tmp_ar;
+		}
+
+		return $parents;
+	}
+
+	/**
+	 * Retrieve all the children of a given reagent (their internal database IDs).
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT
+	 * @return Array
+	*/
+	function getReagentChildren($reagentIDToView)
+	{
+		global $conn;
+		$gfunc_obj = new generalFunc_Class();
+
+		$children = Array();
+		
+		$resultSet = mysql_query("SELECT p.APropertyID, a.reagentID FROM AssocProp_tbl p, Association_tbl a WHERE p.propertyValue='" . $reagentIDToView . "' AND p.status='ACTIVE' AND a.assID=p.assID AND p.status='ACTIVE'", $conn) or die("Error in getReagentParents() function: " . mysql_error());
+
+		while ($results = mysql_fetch_array($resultSet, MYSQL_ASSOC))
+		{
+			$aPropID = $results["APropertyID"];
+			$propVal = $results["reagentID"];
+
+			$children[$aPropID][] = $propVal;
+		}
+
+		return $children;
+	}
+
+
+	/**
+	 * Retrieve a specific type of a reagent's children, e.g. get only the reagents for which the current reagent is a parent cell line.  Used in different reagent views (differentiate between types of reagents and their children).
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT
+	 * @param STRING
+	 * @return Array
+	*/
+	function get_Children($rid, $type)
+	{
+		global $conn;
+		$children_ar = array();
+		$children_set = "('";
+		$setcount = 0;
+
+		if( $type == "Vector Children" )
+		{
+			// Updated Feb. 5/07, Marina -- Get PV and IPV in one query
+			$vcID_rs = mysql_query("SELECT * FROM `AssocProp_tbl` a1 WHERE a1.`status`='ACTIVE' AND a1.`APropertyID`='" . $this->AProp_Name_ID["vector parent id"] . "' AND a1.`propertyValue`='" . $rid . "' UNION SELECT * FROM `AssocProp_tbl` a2 WHERE a2.`status`='ACTIVE' AND a2.`APropertyID`='" . $this->AProp_Name_ID["parent insert vector"] . "' AND a2.`propertyValue`='" . $rid . "'", $conn) or die( "FAILURE IN Reagent_BackGround_Class.get_children(0): " . mysql_error());
+	
+			while( $vcID_ar = mysql_fetch_array( $vcID_rs, MYSQL_ASSOC ) )
+			{
+				$children_set = $children_set . $vcID_ar["assID"] . "','";
+				$setcount++;
+			}
+			
+			if( $setcount > 0 )
+			{
+				$children_set = substr( $children_set, 0, strlen( $children_set ) - 2 ) . ")";
+			}
+			else
+			{
+				$children_set = "('')";
+			}
+		}
+		// Added April 21/06 by Marina
+		elseif( $type == "Vector Insert Children")
+		{
+			$vcID_rs = mysql_query( "SELECT * FROM `AssocProp_tbl` "
+							. "WHERE `status`='ACTIVE' "
+							. "AND `APropertyID`='" . $this->AProp_Name_ID["insert parent vector id"]
+							. "' AND `propertyValue`='" . $rid . "' ", $conn )
+							or die( "FAILURE IN Reagent_BackGround_Class.get_children(0): " . mysql_error() );
+	
+			while( $vcID_ar = mysql_fetch_array( $vcID_rs, MYSQL_ASSOC ) )
+			{
+				$children_set = $children_set . $vcID_ar["assID"] . "','";
+				$setcount++;
+			}
+			
+			if( $setcount > 0 )
+			{
+				$children_set = substr( $children_set, 0, strlen( $children_set ) - 2 ) . ")";
+			}
+			else
+			{
+				$children_set = "('')";
+			}
+		}
+		elseif( $type == "Insert Children" )
+		{
+			// Kept separate in case I need to extend this later on
+			$vcID_rs = mysql_query( "SELECT * FROM `AssocProp_tbl` "
+							. "WHERE `status`='ACTIVE' "
+							. "AND `APropertyID`='" . $this->AProp_Name_ID["insert id"] . "' "
+							. "AND `propertyValue`='" . $rid . "' ", $conn )
+							or die( "FAILURE IN Reagent_BackGround_Class.get_children(1): " . mysql_error() );
+
+			while( $vcID_ar = mysql_fetch_array( $vcID_rs, MYSQL_ASSOC ) )
+			{
+				$children_set = $children_set . $vcID_ar["assID"] . "','";
+				$setcount++;
+			}
+			
+			if( $setcount > 0 )
+			{
+				$children_set = substr( $children_set, 0, strlen( $children_set ) - 2 ) . ")";
+			}
+			else
+			{
+				$children_set = "('')";
+			}
+		}
+		elseif( $type == "Cellline Children" )
+		{
+			// Kept separate in case I need to extend this later on
+			$vcID_rs = mysql_query( "SELECT * FROM `AssocProp_tbl` "
+							. "WHERE `status`='ACTIVE' "
+							. "AND `APropertyID`='" . $this->AProp_Name_ID["parent cell line id"] . "' "
+							. "AND `propertyValue`='" . $rid . "' ", $conn )
+							or die( "FAILURE IN Reagent_BackGround_Class.get_children(2): " . mysql_error() );
+		
+			while( $vcID_ar = mysql_fetch_array( $vcID_rs, MYSQL_ASSOC ) )
+			{
+				$children_set = $children_set . $vcID_ar["assID"] . "','";
+				$setcount++;
+			}
+			
+			if( $setcount > 0 )
+			{
+				$children_set = substr( $children_set, 0, strlen( $children_set ) - 2 ) . ")";
+			}
+			else
+			{
+				$children_set = "('')";
+			}
+		}
+		// Added May 2/06 by Marina
+		elseif ($type == "Vector CellLine Children")
+		{
+			$vcID_rs = mysql_query("SELECT * FROM `AssocProp_tbl` WHERE `status`='ACTIVE' AND `APropertyID`='" . 
+				   $this->AProp_Name_ID["cell line parent vector id"] . "' " . "AND `propertyValue`='" . $rid . "' ", $conn)
+				   or die("FAILURE IN Reagent_BackGround_Class.get_children(\"Vector CellLine Children\"): " . mysql_error());
+		
+			while( $vcID_ar = mysql_fetch_array( $vcID_rs, MYSQL_ASSOC ) )
+			{
+				$children_set = $children_set . $vcID_ar["assID"] . "','";
+				$setcount++;
+			}
+			
+			if( $setcount > 0 )
+			{
+				$children_set = substr( $children_set, 0, strlen( $children_set ) - 2 ) . ")";
+			}
+			else
+			{
+				$children_set = "('')";
+			}
+		}
+		elseif( $type == "Sense Oligo Children" )
+		{
+			// Kept separate incase I need to extend this later on
+			$vcID_rs = mysql_query( "SELECT * FROM `AssocProp_tbl` "
+						. "WHERE `status`='ACTIVE' "
+						. "AND `APropertyID`='" . $this->AProp_Name_ID["sense oligo"] . "' "
+						. "AND `propertyValue`='" . $rid . "' ", $conn )
+						or die( "FAILURE IN Reagent_BackGround_Class.get_children(3): " . mysql_error() );
+				
+			while( $vcID_ar = mysql_fetch_array( $vcID_rs, MYSQL_ASSOC ) )
+			{
+				$children_set = $children_set . $vcID_ar["assID"] . "','";
+				$setcount++;
+			}
+			
+			if( $setcount > 0 )
+			{
+				$children_set = substr( $children_set, 0, strlen( $children_set ) - 2 ) . ")";
+			}
+			else
+			{
+				$children_set = "('')";
+			}
+		}
+		elseif( $type == "AntiSense Oligo Children" )
+		{
+			// Kept separate incase I need to extend this later on	
+			$vcID_rs = mysql_query( "SELECT * FROM `AssocProp_tbl` "
+							. "WHERE `status`='ACTIVE' "
+							. "AND `APropertyID`='" . $this->AProp_Name_ID["antisense oligo"] . "' "
+							. "AND `propertyValue`='" . $rid . "' ", $conn )
+							or die( "FAILURE IN Reagent_BackGround_Class.get_children(4): " . mysql_error() );
+		
+			while( $vcID_ar = mysql_fetch_array( $vcID_rs, MYSQL_ASSOC ) )
+			{
+				$children_set = $children_set . $vcID_ar["assID"] . "','";
+				$setcount++;
+			}
+			
+			if( $setcount > 0 )
+			{
+				$children_set = substr( $children_set, 0, strlen( $children_set ) - 2 ) . ")";
+			}
+			else
+			{
+				$children_set = "('')";
+			}
+		}
+		elseif( $type == "Oligo Children" )
+		{
+			// Kept separate incase I need to extend this later on
+			$vcID_rs = mysql_query( "SELECT * FROM `AssocProp_tbl` "
+							. "WHERE `status`='ACTIVE' "
+							. "AND (`APropertyID`='" . $this->AProp_Name_ID["sense oligo"] 
+							. "' OR `APropertyID`='" . $this->AProp_Name_ID["antisense oligo"]
+							. "') AND `propertyValue`='" . $rid . "' ", $conn )
+							or die( "FAILURE IN Reagent_BackGround_Class.get_children(4): " . mysql_error() );
+		
+			while( $vcID_ar = mysql_fetch_array( $vcID_rs, MYSQL_ASSOC ) )
+			{
+				$children_set = $children_set . $vcID_ar["assID"] . "','";
+				$setcount++;
+			}
+			
+			if( $setcount > 0 )
+			{
+				$children_set = substr( $children_set, 0, strlen( $children_set ) - 2 ) . ")";
+			}
+			else
+			{
+				$children_set = "('')";
+			}
+		}
+		else
+		{
+			echo "Abnormal Failure in: Reagent_Background_Class.get_children(6): Failure to find a matching type!";
+			$children_set = "('')";
+		}
+
+		$setcount = 0;
+
+		$query = "SELECT * FROM `Association_tbl` WHERE `status`='ACTIVE' AND `assID` IN " . $children_set;
+
+		$rid_rs = mysql_query($query, $conn) or die("FAILURE IN Reagent_BackGround_Class.get_children(5): " . mysql_error());
+
+		while( $rid_ar = mysql_fetch_array( $rid_rs , MYSQL_ASSOC ) )
+		{
+			$children_ar[] = $rid_ar["reagentID"];
+		}
+		
+		return $children_ar;
+	}
+
+	/**
+	 * Added Feb. 5/07 by Marina (originally taken from http://us3.php.net/manual/en/function.usort.php - Comparison function to sort array values in ascending order
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>, source http://us3.php.net/manual/en/function.usort.php
+	 * @version 3.1
+	 *
+	 * @param Array
+	 * @param Array
+	 * @return INT
+	*/
+	function cmp($a, $b)
+	{
+		if ($a == $b) 
+		{
+			return 0;
+		}
+
+		return ($a < $b) ? -1 : 1;
+	}
+
+
+	/**
+	 * Print a list of children of the current reagent - prints the results returned by get_Children().
+	 *
+	 * Modified by Marina Feb 2/07: Add show/hide option to display Vector children and Cell Line children lists (as they are getting too long)
+	 *
+	 * Last update: Feb. 5/07
+	 *
+	 * @param INT $rid internal db ID of reagent being viewed
+	 * @param STRING $type association type - 'Vector children' or 'Cell Line Children'
+	 * @param STRING $subtype one-word identifier to pass to Javascript function, to indicate which list is to be shown/hidden
+	 * @see get_Children()
+	*/
+	function print_Children($rid, $type, $subtype)
+	{
+		$gfunc_obj = new generalFunc_Class();
+
+		$children = $this->get_Children( $rid, $type );
+		$children_lab_ids = $gfunc_obj->getLabIDs($children);		// added Feb. 2/07, Marina
+
+		// Sept. 6/07
+		$currUserCategory = $_SESSION["userinfo"]->getCategory();
+
+		if (sizeof($children_lab_ids) > 0)				// feb 2/07, marina
+		{
+			// Feb 2/07, Marina - For now just have show/hide link for vector children, use old way for Inserts
+			if (($type == "Vector Children") || ($type == "Vector CellLine Children") || ($type == "Vector Insert Children"))
+			{
+				$cols = 0;
+				$MAX_COLS = 17;
+	
+				?>
+				<SPAN id="show_<?php echo $subtype; ?>" class="linkShow" onclick="showHideChildren(this.id, 'children_<?php echo $subtype; ?>')">Show Children</SPAN>
+				<SPAN id="hide_<?php echo $subtype; ?>" class="linkHide" onclick="showHideChildren(this.id, 'children_<?php echo $subtype; ?>')">Hide Children</SPAN>
+				  <B>(<?php echo sizeof($children_lab_ids); ?>  total)</B>
+				<tr>
+					<td id="children_<?php echo $subtype; ?>" class="children">
+						<div class="children">
+							<TABLE class="children">
+								<TR>
+								<?php
+									foreach ($children_lab_ids as $key => $rid_tmp)
+									{
+										if ($cols == $MAX_COLS)
+										{
+											echo "</tr><tr>";
+											$cols = 0;
+										}
+						
+										echo "<td>";
+
+										// August 20/07: Restrict viewing by project - if parent belongs to a project you don't have access to, don't allow linking
+										$tmpProject = $rfunc_obj->getReagentProjectID($key);
+										$userProjects = getAllowedUserProjectIDs($_SESSION["userinfo"]->getUserID());
+
+										if (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || in_array($tmpProject, $userProjects))
+										{
+											echo "<a href=\"Reagent.php?View=6&rid=" . $key . "\">" . $rid_tmp . "</a> ";
+											echo "</td>";
+										}
+										else
+										{
+											echo "<span class=\"linkDisabled\">";
+											echo $rid_tmp;
+											echo "</span>  ";
+										}
+
+										$cols++;
+									}
+								?>
+								</TR>
+							</TABLE>
+						</div>	
+					</td>
+				</tr>
+				<?php
+			}
+			else
+			{
+				foreach ($children_lab_ids as $key => $rid_tmp)
+				{
+					// August 20/07: Restrict viewing by project - if parent belongs to a project you don't have access to, don't allow linking
+					$tmpProject = getReagentProjectID($key);
+					$userProjects = getAllowedUserProjectIDs($_SESSION["userinfo"]->getUserID());
+
+					if (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || in_array($tmpProject, $userProjects))
+					{
+						echo "<a href=\"Reagent.php?View=6&rid=" . $key . "\">";
+						echo $rid_tmp;
+						echo "</a>  ";
+					}
+					else
+					{
+						echo "<span class=\"linkDisabled\">";
+						echo $rid_tmp;
+						echo "</span>  ";
+					}
+				}	
+			}
+		}
+		else
+ 		{
+ 			echo " ";
+ 		}
+	}	
+
+	/**
+	 * Return the Insert that belongs to the reagent (Vector) identified by $rid
+	 *
+	 * @param INT $rid internal db ID of the Vector whose Insert needs to be retrieved
+	 * @return INT Internal database ID of the requested Insert
+	*/
+	function get_Insert($rid)
+	{
+		global $conn;
+		$functionerror = "get_Insert(";
+
+		// find out the assocTypeID of property "parent insert vector"
+		$insert_aid =  $this->get_Association_Property_Type("insert id");
+
+		$query = "SELECT * FROM `Association_tbl` A1 INNER JOIN `AssocProp_tbl` A2 ON A1.`assID` = A2.`assID` WHERE A1.`reagentID` = '" . $rid . " ' AND A2.`APropertyID`='" . $insert_aid . "' AND A1.`status`='ACTIVE' AND A2.`status`='ACTIVE'";
+
+		$insert_rs = mysql_query($query, $conn) or die( $classerror . $functionerror . "2):" . mysql_error() );
+		
+		if ($insert_ar = mysql_fetch_array($insert_rs, MYSQL_ASSOC))
+		{
+			return $insert_ar["propertyValue"];
+		}
+
+		return -1;
+	}
+}
+?>
diff --git a/OpenFreezer/Reagent/Reagent_Creator_Class.php b/OpenFreezer/Reagent/Reagent_Creator_Class.php
new file mode 100755
index 0000000..2a6d287
--- /dev/null
+++ b/OpenFreezer/Reagent/Reagent_Creator_Class.php
@@ -0,0 +1,8919 @@
+<?php
+/**
+*
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @package Reagent
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+/**
+ * Contains functions for creation of reagents
+ *
+ * @author John Paul Lee @version 2005
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Reagent
+ *
+ * @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+class Reagent_Creator_Class
+{
+	/**
+	 * @var Array
+	 * A map of cell line association type ID => name relationships, i.e. (1 => "Parent", 2 => "Stable").  Does NOT mirror AssocType_tbl column values, just for internal reference.
+	*/
+	var $CellLine_SubCategory_ID_Name;
+
+	/**
+	 * @var Array
+	 * A map of cell line association type name => ID relationships, i.e. ("Parent" => 1, "Stable" => 2), the inverse of $CellLine_SubCategory_ID_Name.  Does NOT mirror AssocType_tbl column values, just for internal reference.
+	*/
+	var $CellLine_SubCategory_Name_ID;	// this is the one used in creation form (aug. 27, 2010)!!!
+
+	/**
+	 * @var STRING
+	 * Error message returned by this class in various cases (contains the name of this class to help pinpoint the source of the error)
+	*/
+	var $classerror;
+
+	// Helper objects
+
+	/**
+	 * @var Reagent_Background_Class
+	 * Helper object (instance of Reagent_Background_Class) to handle reagent parent-child associations
+	*/
+	var $bfunc_obj;
+
+	/**
+	 * @var generalFunc_Class
+	 * Helper object (instance of generalFunc_Class) to execute general functions
+	*/
+	var $gfunc_obj;
+
+	/**
+	 * @var Reagent_Function_Class
+	 * Helper object (instance of Reagent_Function_Class) to execute general functions with respect to reagents
+	*/
+	var $rfunc_obj;
+
+	/**
+	 * Default constructor
+	*/
+	function Reagent_Creator_Class()
+	{
+		$this->CellLine_SubCategory_ID_Name = array(1 => "Parent", 2 => "Stable");
+		$this->CellLine_SubCategory_Name_ID = array_flip( $this->CellLine_SubCategory_ID_Name);
+
+		$this->classerror = "Reagent_Creator_Class.";
+		$this->bfunc_obj = new Reagent_Background_Class();
+		$this->gfunc_obj = new generalFunc_Class();
+		$this->rfunc_obj = new Reagent_Function_Class();
+	}
+	
+	/**
+	 * Print a selection form for reagent types (user selects the type of reagent to create from a dropdown list)
+	*/
+	function printReagentTypeSelection()
+	{
+		global $cgi_path;
+		
+		$r_out = new Reagent_Output_Class();
+		$gfunc_obj = new generalFunc_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+
+		?>
+		<FIELDSET style="width:745px;">
+			<LEGEND>What type of reagent would you like to create?</LEGEND>
+			
+			<SELECT id="reagentTypes" name="reagentType" onChange="showReagentSubtype()">
+				<OPTION SELECTED value="default">Select reagent type</OPTION>
+				<OPTION DISABLED>- - - - - - - - - - - - - - - - - - -</OPTION>
+
+				<?php
+					$rTypeNames = array_keys($_SESSION["ReagentType_Name_ID"]);
+					sort($rTypeNames, SORT_STRING);
+
+					foreach ($rTypeNames as $key => $r_type)
+					{
+						$rTypePrefix = $_SESSION["ReagentType_Name_Prefix"][$r_type];
+
+						echo "<OPTION VALUE=\"" . $r_type . "\">";
+				
+						if ($r_type == "CellLine")
+							echo "Cell Line (" . $rTypePrefix . ")";
+						else
+							echo $r_type . " (" . $rTypePrefix . ")";
+				
+						echo "</OPTION>";
+					}
+				?>
+			</SELECT>
+		</FIELDSET>
+
+		<TABLE ID="rTypeSelect" width="745px" border="0">
+			<TR>
+				<TD style="padding-left:10px; padding-top:10px;">
+					<?php
+						$vDisplay = "none";
+						$cDisplay = "none";
+					?>
+						<SPAN ID="vector_heading" style="display:none; font-size:10pt; font-weight:bold;">Please indicate Vector subtype:<BR><BR></SPAN>
+
+						<SPAN ID="cell_line_heading" style="display:none; font-size:10pt; font-weight:bold;">Please indicate Cell Line subtype:<BR><BR></SPAN>
+					<?php
+						// Vector and Cell Line subtype selection lists - both hidden initially
+						$r_out->printReagentSubtype($_SESSION["ReagentType_Name_ID"]["Vector"], $subtype, "vectorSubtypes", "vectorSubtype", 0, $vDisplay, $cDisplay);
+						
+						// Cell Line subtype selection
+						$r_out->printReagentSubtype($_SESSION["ReagentType_Name_ID"]["CellLine"], $subtype, "cellLineSubtypes", "cellLineSubtype", 0, $vDisplay, $cDisplay);
+					?>
+				</TD>
+			</TR>
+		
+			<!-- April 11/07: Illustration of different vector and cell line subtypes -->
+			<TR>
+				<TD style="padding-left:10px; padding-top:10px;">
+					<A href="Reagent/vector_assoc.png" id="vector_types_diagram" style="display:<?php echo /*($rType == "Vector") ? "inline" :*/ "none"; ?>" onClick="return popup(this, 'diagram', '650', '725', 'yes')">Click here to view an illustration of vector types and associations</A>
+
+					<A href="Reagent/cell_assoc.png" id="cell_line_types_diagram" style="display:<?php echo /*($rType == "CellLine") ? "inline" : */"none"; ?>" onClick="return popup(this, 'diagram', '650', '725', 'yes')">Click here to view an illustration of cell line types and associations</A>
+				</TD>
+			</TR>
+
+		</TABLE>
+		<?php
+	}
+
+
+	/**
+	 * Print the form to add a new reagent type
+	 * @param INT
+	 * @param boolean
+	 * @author Marina Olhovsky
+	 * @version 2009-04-23
+	*/
+	function printFormAddReagentType($step=1, $goback=false)
+	{
+		global $conn;
+		global $cgi_path;
+
+		$genPrefix = "reagent_detailedview_";
+		$genPostfix = "_prop";
+
+		$r_out = new Reagent_Output_Class();
+		$gfunc_obj = new generalFunc_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+
+		?>
+		<FORM METHOD="POST" ACTION="<?php echo $cgi_path . "reagent_type_request_handler.py"; ?>" NAME="addReagentTypeForm" ID="add_reagent_type_form" onSubmit="enableCheckboxes(); return verifyNewReagentTypeName() && verifyNewReagentTypePrefix();">
+			<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+		
+			<TABLE width="768px" style="margin-left:10px; display:<?php echo $display; ?>; padding:5px;" cellpadding="4" cellspacing="2" ID="addReagentTypeTable">
+				<TH style="font-size:13pt; text-align:left; padding-left:10%; font-weight:bold; color:#0000FF; white-space:nowrap; padding-top: 10px; padding-top:5px;">
+					CREATE A NEW REAGENT TYPE
+				</TH>
+		
+				<TR>
+					<TD style="font-size:10pt; text-align:left; padding-left:16%; font-weight:bold; color:#00C0DD; white-space:nowrap; padding-top:5px;">
+						Step 1 - Define Attributes
+					</TD>
+				</TR>
+		
+				<TR>
+					<TD colspan="2" style="font-weight:bold;">
+						1. Please indicate the <u>name</u> of the new reagent type (e.g. Antibody, Virus, etc.):<BR><BR>
+
+						<SPAN style="font-weight:normal; color:brown; margin-left:16px;">'Sequence', 'DNA Sequence', 'RNA Sequence', 'Protein Sequence', 'DNA' or 'RNA' may <u>NOT</u> be used as reagent<BR><SPAN style="font-weight:normal; color:brown; margin-left:16px;">type names.  'RNAi' or 'siRNA', however, are allowed.</SPAN>
+
+						<P>
+						<INPUT TYPE="TEXT" size="65px" style="margin-left:16px;" ID="reagent_type_name" NAME="reagentTypeName" VALUE="<?php if (isset($_GET["rType"])) echo $_GET["rType"]; ?>" onKeyPress="return disableEnterKey(event);">
+				
+						<BR><div id="reagent_type_name_warning" style="display:none; font-weight:bold;"><span style="margin-left:16px; color:#FF0000;"><IMG SRC="../pictures/up_arrow.png" style="vertical-align:bottom; padding-bottom:4px;">  Please provide a unique name at least 4 characters long for the new reagent type.</span><BR><P><span style="margin-left:16px;">'Sequence', 'DNA Sequence', 'RNA Sequence', 'Protein Sequence', 'DNA' or 'RNA' are <U>NOT</U> valid</SPAN><BR><span style="margin-lef [...]
+					</TD>
+				</TR>
+		
+				<TR ID="rTypePrefixRow">
+					<TD colspan="2" style="text-align:justify;">
+
+						<!-- Keep formatting -->
+						<b><BR>2. Please specify a unique <u>prefix</u>, between one and three characters in length, that will be used <BR><span style="margin-left:16px;">to identify reagents of this type (e.g. 'V' for Vector):</span><BR></b>
+
+						<BR><span style="margin-left:16px; white-space:nowrap;">Normally prefixes are a single character, usually the first letter of the reagent type name specified above.</span><BR><span style="margin-left:16px; white-space:nowrap;">However, other prefixes are acceptable.</span><BR>
+					
+						<P><INPUT TYPE="TEXT" size="5px" style="margin-left:16px;" ID="reagent_type_prefix" NAME="reagentTypePrefix" VALUE="<?php if (isset($_GET["prefix"])) echo $_GET["prefix"]; ?>" onKeyPress="return disableEnterKey(event);">
+		
+						<DIV id="reagent_type_prefix_warning" style="margin-left:16px; display:none; font-weight:bold; color:#FF0000"><IMG SRC="../pictures/up_arrow.png" style="vertical-align:bottom; padding-bottom:4px;">  Please specify a unique prefix (3 characters or less, not containing digits) for the new reagent type</DIV>
+					</TD>
+				</TR>
+		
+				<TR ID="rTypeAssocRow">
+					<TD>
+						<TABLE>
+							<TR>
+								<TD style="white-space:nowrap; font-weight:normal;">
+									<b><BR>3. Please define parent/child relations for the new reagent type<!--<SPAN NAME="newReagentType" style="font-weight:bold;"></SPAN>-->:<BR></b>
+								</TD>
+							</TR>
+			
+							<TR>
+								<TD colspan="2" style="padding-left:12px; font-weight:nowrap; padding-top:10px; font-size:10pt;">
+									Select <b>parent</b> types <!--for <SPAN NAME="newReagentType" style="font-weight:bold;"></SPAN> -->from the list below.<BR><SPAN style="color:red">If the sought type is not in the list, you need to create that type first.</SPAN><BR>
+
+									<P><SELECT MULTIPLE id="add_reagent_type_parents" name="addReagentTypeParents"><?php
+
+									foreach ($_SESSION["ReagentType_ID_Name"] as $key => $value)
+									{
+										echo "<OPTION " . $selected . " value=\"" . $value . "\">" . $value . "</OPTION>";
+									}
+
+									?>
+									</SELECT><BR>
+
+									<SPAN class="linkShow" id="select_all_rtype_parents_chkbx" onClick="selectAllElements('add_reagent_type_parents', false);" style="padding-top:12px; font-size:8pt;"> Select All</SPAN>
+
+									<SPAN class="linkShow" id="clear_all_rtype_parents_chkbx" onClick="clearAllElements('add_reagent_type_parents');" style="padding-top:12px; padding-left:5px; font-size:8pt;"> Clear All</SPAN>
+								</TD>
+							</TR>
+
+							<TR><TD style="padding-left:8px;"><INPUT TYPE="checkbox" ID="includeParent"> Parent of itself</TD></TR>
+						</TABLE>
+					</TD>
+				</TR>
+		
+				<TR ID="rTypePropsRow">
+					<TD>
+						<TABLE ID="addReagentPropsTbl" width="768px">
+							<TR>
+								
+								<TD style="padding-top:10px; font-weight:bold;">
+									<BR>4. Please select properties for the new reagent type in the following categories:<BR>
+									<P><span style="font-size:10pt; padding-left:17px; padding-top: 7px; font-weight:normal; color:#FF0000;">If you do not wish to include a property, uncheck the checkbox next to it.</span>
+								</TD>
+							</TR>
+
+							<TR>
+								<td colspan="4" style="font-size:9pt; font-weight:normal; padding-left:18px; padding-top:5px; color:#000000;">Checkboxes whose selection is disabled are mandatory for all reagent types (e.g. 'Name', 'Status', 'Project ID', 'Description')</td>
+							</TR>
+
+							<!-- Aug. 24/09: Explain how to correct input errors -->
+							<TR>
+								<td colspan="4" style="padding-top:10px; padding-left:18px; color:green;">
+									<DIV style="border:2px double gold; font-size:10pt; padding-right:28px;">
+										<UL>
+											<LI style="color:green">If a novel property name is mistyped, uncheck the checkbox next to the incorrect entry and re-enter it using the 'Add New Property' feature. Unchecked checkboxes are not saved; neither are categories that do not contain any properties, or whose properties have all been unchecked.<BR>
+
+											<LI style="color:brown"><P>The term <b>'Sequence Features'</b> refers to <u>regions at specific positions</u> on a sequence in forward or reverse orientation (e.g. PolyA Tail, Tag, Selectable Marker).  Their values <b>are always selected from a pre-defined list.</b>  Properties that describe the entire sequence rather than portions of it should be stored under a different category (e.g. 'Annotations' or 'Classifiers').
+
+											<LI style="color:green"><P>A property name may only be added to a category once (i.e. 'Name' cannot appear twice under "General Properties").  You will be given an opportunity to assign multiple values to a single property at the next step.
+
+											<LI style="color:brown"><P>Multiple property names across categories entered in different LeTtErCaSe will be converted to the same lettercase at saving  (e.g. 'Alternate ID' and 'alternate id' are considered the same property, even if they appear in different categories).<BR><P><SPAN STYLE="color:red; font-weight:bold;">Existing property names cannot be changed.</SPAN>
+										</UL>
+									</DIV>
+								</td>
+							</TR><?php
+
+							// July 31/09: List of properties to exclude from option list
+							$ignoreList = Array();
+							
+							foreach ($_SESSION["ReagentType_ID_Name"] as $id => $name)
+							{
+								if ($name == "CellLine")
+									$name = "Cell Line";
+							
+								$ignoreList[] = $name . " Type";
+							}
+							
+							$ignoreList[] = "Type of Insert";
+							$ignoreList[] = "Open/Closed";
+
+							?><TR>
+								<TD><?php
+
+								foreach ($_SESSION["ReagentPropCategory_ID_Name"] as $categoryID => $category)
+								{
+									$catAlias = $_SESSION["ReagentPropCategory_ID_Alias"][$categoryID];
+	
+									if ((strcasecmp($category, "DNA Sequence") != 0) && (strcasecmp($category, "Protein Sequence") != 0) && (strcasecmp($category, "RNA Sequence") != 0) && (strcasecmp($category, "DNA Sequence Features") != 0) && (strcasecmp($category, "RNA Sequence Features") != 0) && (strcasecmp($category, "Protein Sequence Features") != 0))
+									{
+										?><P><TABLE ID="addReagentTypePropsTbl_<?php echo $catAlias; ?>" style="white-space:nowrap; width:auto;">
+											<TR ID="<?php echo $catAlias; ?>_row">
+												<TD style="font-weight:bold; padding-top:12px; color:#0000D2; white-space:nowrap;" colspan="4">
+												<?php
+
+													// Expand only the first category, General Properties; collapse the rest
+													?><IMG id="<?php echo $categoryID . "_expand_img"; ?>" SRC="pictures/arrow_collapse.gif" WIDTH="20" HEIGHT="15" BORDER="0" ALT="plus" class="menu-expanded" style="display:inline;" onClick="showHideCategory('<?php echo $categoryID; ?>');">
+
+													<IMG id="<?php echo $categoryID . "_collapse_img"; ?>" SRC="pictures/arrow_expand.gif" WIDTH="40" HEIGHT="34" BORDER="0" ALT="plus" class="menu-collapsed" style="display:none;" onClick="showHideCategory('<?php echo $categoryID; ?>');"><?php
+
+													echo $category;
+													
+													?>
+												</TD>
+											</TR>
+											
+											<TR>
+												<TD>
+													<TABLE ID="category_<?php echo $categoryID; ?>_section" cellpadding="4">
+														<TR>
+															<TD colspan="4" style="padding-left:15px; white-space:nowrap">
+																<input type="hidden" name="category[]" value="<?php echo $catAlias; ?>">
+
+																<input type="hidden" name="category_descriptor_<?php echo $catAlias; ?>" value="<?php echo $category;?>">
+											
+																<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="checkAll" onClick="checkAll('<?php echo "createReagentType_" . $catAlias; ?>');">Check All</span>
+							
+																<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="uncheckAll" onClick="uncheckAll('<?php echo "createReagentType_" . $catAlias; ?>', Array('name', 'status', '<?php echo $_SESSION["ReagentProp_Name_Alias"]['packet id']; ?>', 'comments', 'type', 'description'));">Uncheck All</span>
+															</TD>
+														</TR>
+
+														<TR><?php
+															$props = $rfunc_obj->getPropertiesByCategory($categoryID);
+
+															$mandatoryGeneral = array('name', 'status', 'packet id', 'type', 'comments', 'description');
+
+$mandatoryGeneralPropIDs = array();
+
+foreach ($mandatoryGeneral as $p_k => $p_nm)
+{
+	$mandatoryPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][$p_nm], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+
+	$mandatoryGeneralPropIDs[] = $mandatoryPropID;
+}
+
+
+															$pCount = 0;
+
+															foreach ($props as $key => $prop)	// $prop is an Object
+															{
+																$propName = "";
+																$propDescr = "";
+
+																try
+																{
+																	$propName = $prop->getPropertyName();
+																	$propDescr = $prop->getPropertyDescription();
+																}
+																catch (Exception $e)
+																{
+																	// this is a feature
+																	$propName = $prop->getFeatureType();
+																	$propDescr = $prop->getFeatureDescription();
+																	$featureValue = $prop->getFeatureValue();
+																}
+
+																// July 31/09: Some properties only apply to selected types, don't output them as options
+																$toIgnore = 0;
+																
+																// do a full loop comparison here because of case sensitivity
+																foreach ($ignoreList as $x => $val)
+																{
+																	if (strcasecmp($propName, $val) == 0)
+																	{
+																		$toIgnore = 1;
+																		break;
+																	}
+																}
+																
+																if ($toIgnore == 1)
+																	continue;
+
+																if ($pCount%4 == 0)
+																	echo "</TR><TR>";
+
+																// Feb. 8/10
+																$pc_id = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][$propName], $categoryID);
+// echo $propName . ": " . $pc_id;
+
+// rmvd Feb 8/10															if (in_array($propName, $mandatoryGeneral))
+																if (in_array($pc_id, array_values($mandatoryGeneralPropIDs)))
+																{
+																	$action = "onClick=\"this.checked = true;\"";
+																	$readOnly = "DISABLED";
+																}
+																else
+																{
+																	$readOnly = "";
+																	$action = "";
+																}
+
+																?><TD style="padding-left:20px; white-space:nowrap;"><INPUT TYPE="checkbox" NAME="createReagentType_<?php echo $catAlias . "[]"; ?>" VALUE="<?php echo $_SESSION["ReagentProp_Name_Alias"][$propName];?>" <?php echo $action; ?> <?php echo $readOnly; ?> checked>
+
+<INPUT TYPE="hidden" ID="<?php echo $catAlias . "_:_" . $_SESSION["ReagentProp_Name_Alias"][$propName]; ?>_checkbox_desc_hidden" NAME="propCheckboxes[]" VALUE="<?php echo $propDescr; ?>">
+
+<?php echo $propDescr; ?></TD>
+<?php
+
+																$pCount++;
+															}
+
+															if ($categoryID == 1)
+															{
+																if ($pCount%4 == 0)
+																	echo "</TR><TR>";
+
+																?><TD style="padding-left:20px; white-space:nowrap;"><INPUT TYPE="checkbox" onClick="this.checked = true;" NAME="createReagentType_general_properties[]" VALUE="type" CHECKED DISABLED>Type</TD><?php
+															}
+
+														?></TR>
+
+														<tr>
+															<td colspan="4" style="padding-left:20px; padding-top:10px; white-space:nowrap;">
+																<b>Add new <?php echo $category; ?> property:<b>  
+																<INPUT type="text" size="35" ID="<?php echo $catAlias; ?>_other" value="" name="<?php echo $catAlias; ?>Other" onKeyPress="return disableEnterKey(event);">  
+							
+																<input onclick="updateCheckboxListFromInput('<?php echo $catAlias; ?>_other', '<?php echo $catAlias; ?>', 'category_<?php echo $categoryID; ?>_section', 'add_reagent_type_form'); document.getElementById('<?php echo $catAlias; ?>_other').focus();" value="Add" type="button" style="font-size:10pt;"></INPUT>
+															</td>
+														</tr>
+													</TABLE>
+												</TD>
+											</TR>
+										</TABLE><?php
+									}
+								}
+
+								?></TD>
+							</TR>
+
+							<TR>
+								<TD>
+									<TABLE>
+										<!-- Now print sequence and Features sections -->
+		
+										<!-- June 10/09: Allow selecting only one sequence type -->
+										<TR>
+											<TD colspan="4" style="white-space:nowrap; padding-top:10px;">
+
+												<IMG id="sequence_expand_img" SRC="pictures/arrow_collapse.gif" WIDTH="20" HEIGHT="15" BORDER="0" ALT="plus" class="menu-expanded" style="display:inline" onClick="showHideCategory('sequence');">
+
+												<IMG id="sequence_collapse_img" SRC="pictures/arrow_expand.gif" WIDTH="40" HEIGHT="34" BORDER="0" ALT="plus" class="menu-collapsed" style="display:none" onClick="showHideCategory('sequence');">
+
+												<span style="font-weight:bold; color:#0000D2;">Sequence</span>
+			
+													<DIV ID="category_sequence_section">
+														<P><SPAN style="margin-left:25px;">Select one of the following sequence types:</SPAN><BR>
+				
+														<P>
+														<INPUT style="margin-left:25px; font-size:11pt;" TYPE="radio" ID="sequenceRadioNone" NAME="sequenceType" VALUE="None" checked onClick="hideSequenceSections();">None
+														<INPUT style="margin-left:25px; font-size:11pt;" TYPE="radio" ID="sequenceRadioDNA" NAME="sequenceType" VALUE="DNA Sequence" onClick="showDNASequenceSection();">DNA Sequence
+														<INPUT style="margin-left:25px; font-size:11pt;" TYPE="radio" ID="sequenceRadioProtein" NAME="sequenceType" VALUE="Protein Sequence" onClick="showProteinSequenceSection();">Protein Sequence
+														<INPUT style="margin-left:25px; font-size:11pt;" TYPE="radio" ID="sequenceRadioRNA" NAME="sequenceType" VALUE="RNA Sequence" onClick="showRNASequenceSection();">RNA Sequence
+													</DIV>
+											</td>
+										</tr>
+									
+										<TR ID="dna_sequence_heading_row" style="display:none;">
+											<TD colspan="4" style="padding-top:10px; white-space:nowrap; padding-left:20px;">
+												<BR><IMG SRC="pictures/star_bullet.gif" WIDTH="10" HEIGHT="10" BORDER="0" ALT="bullet" style="padding-right:8px; vertical-align:middle; padding-bottom:2px;"><b>DNA Sequence</b>
+						
+												<input type="hidden" ID="dnaSequenceCategoryInput" name="category[]" value="sequence_properties">
+			
+												<input type="hidden" ID="dnaSequenceCategoryDescriptionInput" name="category_descriptor_sequence_properties" value="DNA Sequence">
+						
+												<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="checkAll" onClick="checkAll('createReagentType_sequence_properties');">Check All</span>
+
+												<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="uncheckAll" onClick="uncheckAll('createReagentType_sequence_properties', Array('<?php echo $_SESSION["ReagentProp_Name_Alias"]["sequence"]; ?>'));">Uncheck All</span>
+											</TD>
+										</TR>
+				
+										<tr ID="dna_sequence_props_row" style="display:none;">
+											<TD colspan="4" style="padding-left:25px;">
+												<TABLE cellspacing="4" ID="addReagentTypeSequenceProperties"><?php
+													$pCount = 0;
+													echo "<TR>";
+
+													$seqPropSet =  $rfunc_obj->getPropertiesByCategory($_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+													
+													foreach ($seqPropSet as $key => $prop)
+													{
+														if ($pCount%4 == 0)
+															echo "</TR><TR>";
+			
+														if (strcasecmp($value, "sequence") == 0)
+														{
+															$action = "onClick=\"this.checked = true;\"";
+															$readOnly = "DISABLED";
+														}
+														else
+														{
+															$readOnly = "";
+															$action = "";
+														}
+		
+														$value = $prop->getPropertyName();
+													
+														// June 11/09: Include category alias in property input name to handle multiple properties in different categories
+														?><TD style="white-space:nowrap; padding-right:10px;">
+															<INPUT TYPE="checkbox" NAME="createReagentType_sequence_properties[]" VALUE="<?php echo $_SESSION["ReagentProp_Name_Alias"][$value]; ?>" <?php echo $action; ?> <?php echo $readOnly; ?> checked>
+
+<INPUT TYPE="hidden" ID="<?php echo $_SESSION["ReagentPropCategory_Name_Alias"]["DNA Sequence"] . "_:_" . $_SESSION["ReagentProp_Name_Alias"][$value]; ?>_checkbox_desc_hidden" NAME="propCheckboxes[]" VALUE="<?php echo $_SESSION["ReagentProp_Name_Desc"][$value]; ?>">
+
+<?php echo $_SESSION["ReagentProp_Name_Desc"][$value]; ?></TD><?php
+														$pCount++;
+													}
+						
+													echo "</TR>";
+												?>
+												</TABLE>
+											</TD>
+										</TR>
+				
+										<tr ID="dna_sequence_add_new_props_row" style="display:none;">
+											<td colspan="4" style="padding-left:25px; padding-top:10px; white-space:nowrap;">
+												<b>Add new DNA sequence property:<b>  
+												<INPUT type="text" size="35" ID="sequence_properties_other" value="" name="sequence_propertiesOther" onKeyPress="return disableEnterKey(event);">  
+
+												<input onclick="updateCheckboxListFromInput('sequence_properties_other', 'sequence_properties', 'addReagentTypeSequenceProperties', 'add_reagent_type_form'); document.getElementById('sequence_properties_other').focus();" value="Add" type="button" style="font-size:10pt;"></INPUT>
+											</td>
+										</tr>
+
+										<!-- Moved here June 10/09 - do separate property set for each sequence type -->
+										<TR ID="dna_sequence_features_heading_row" style="display:none;">
+											<TD colspan="4" style="padding-left:20px; padding-top:10px;">
+												<BR><IMG SRC="pictures/star_bullet.gif" WIDTH="10" HEIGHT="10" BORDER="0" ALT="bullet" style="padding-right:8px; vertical-align:middle; padding-bottom:2px;"><b>DNA Sequence Features</b>
+						
+												<input type="hidden" ID="dnaFeaturesCategoryInput" name="category[]" value="dna_sequence_features">
+			
+												<input type="hidden" ID="dnaFeaturesCategoryDescriptorInput" name="category_descriptor_dna_sequence_features" value="DNA Sequence Features">
+						
+												<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="checkAll" onClick="checkAll('createReagentType_dna_sequence_features');">Check All</span>
+												<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="uncheckAll" onClick="uncheckAll('createReagentType_dna_sequence_features', []);">Uncheck All</span>
+						
+												<BR><span style="font-size:9pt; padding-left:18px; font-weight:normal;">Properties that are linked to a sequence at specific positions and do not exist independently of it</span>
+											</TD>
+										</TR>
+
+										<TR ID="dna_sequence_features_row" style="display:none;">
+											<TD colspan="4" style="padding-left:25px;">
+												<P><TABLE cellspacing="4" ID="addReagentTypeFeatures"><?php
+													$pCount = 0;
+						
+													echo "<TR>";
+						
+													foreach ($featureSet as $key => $value)
+													{
+														if ($pCount%4 == 0)
+															echo "</TR><TR>";
+
+														if ((strcasecmp($value, "tag position") != 0) && (strcasecmp($value, "expression system") != 0))
+														{
+															?><TD style="white-space:nowrap; padding-right:10px;">
+																<INPUT TYPE="checkbox" NAME="createReagentType_dna_sequence_features[]" VALUE="<?php echo $_SESSION["ReagentProp_Name_Alias"][$value];?>" checked><?php echo $_SESSION["ReagentProp_Name_Desc"][$value]; ?></TD>
+
+<INPUT TYPE="hidden" ID="<?php echo "dna_sequence_features_:_" . $_SESSION["ReagentProp_Name_Alias"][$value]; ?>_checkbox_desc_hidden" NAME="propCheckboxes[]" VALUE="<?php echo $_SESSION["ReagentProp_Name_Desc"][$value]; ?>">
+<?php
+														}
+						
+														$pCount++;
+													}
+
+													// Oct. 29/09: show custom sequence features
+													$otherFeatures = $rfunc_obj->getPropertiesByCategory($_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]);
+
+													$pCount = 0;
+
+													foreach ($otherFeatures as $key => $prop)	// $prop is an Object
+													{
+														$propName = "";
+														$propDescr = "";
+
+														try
+														{
+															$propName = $prop->getPropertyName();
+															$propDescr = $prop->getPropertyDescription();
+														}
+														catch (Exception $e)
+														{
+															// this is a feature
+															$propName = $prop->getFeatureType();
+															$propDescr = $prop->getFeatureDescription();
+															$featureValue = $prop->getFeatureValue();
+														}
+
+														if (!in_array($propName, $featureSet) && (strcasecmp($propName, "tag position") != 0) && (strcasecmp($propName, "expression system") != 0))
+														{
+															if ($pCount%4 == 0)
+																echo "</TR><TR>";
+
+															?><TD style="white-space:nowrap;"><INPUT TYPE="checkbox" NAME="createReagentType_dna_sequence_features[]" VALUE="<?php echo $_SESSION["ReagentProp_Name_Alias"][$propName];?>" checked>
+
+<INPUT TYPE="hidden" ID="<?php echo "dna_sequence_features_:_" . $_SESSION["ReagentProp_Name_Alias"][$propName]; ?>_checkbox_desc_hidden" NAME="propCheckboxes[]" VALUE="<?php echo $_SESSION["ReagentProp_Name_Desc"][$propName]; ?>">
+
+<?php echo $propDescr; ?>
+</TD>
+<?php
+
+															$pCount++;
+														}
+													}
+						
+													echo "</TR>";
+												?>
+												</TABLE>
+											</TD>
+										</TR>
+						
+										<tr ID="dna_sequence_add_new_features_row" style="display:none;">
+											<td colspan="4" style="padding-left:25px; padding-top:10px; white-space:nowrap;">
+												<b>Add new DNA sequence feature:<b>  
+												<INPUT type="text" size="35" ID="dna_sequence_features_other" value="" name="featuresOther" onKeyPress="return disableEnterKey(event);">  
+			
+												<input onclick="updateCheckboxListFromInput('dna_sequence_features_other', 'dna_sequence_features', 'addReagentTypeFeatures', 'add_reagent_type_form'); document.getElementById('dna_sequence_features_other').focus();" value="Add" type="button" style="font-size:10pt;"></INPUT>
+											</td>
+										</tr>
+	
+										<!-- June 2/09: Different sequence types - Protein Sequence -->
+										<TR ID="protein_sequence_heading_row" style="display:none;">
+											<TD colspan="4" style="padding-left:20px; padding-top:10px; white-space:nowrap">
+												<BR><IMG SRC="pictures/star_bullet.gif" WIDTH="10" HEIGHT="10" BORDER="0" ALT="bullet" style="padding-right:8px; vertical-align:middle; padding-bottom:2px;"><b>Protein Sequence</b>
+						
+												<input type="hidden" ID="proteinSequenceCategoryInput" name="category[]" value="protein_sequence_properties">
+			
+												<input type="hidden" ID="proteinSequenceCategoryDescriptorInput" name="category_descriptor_protein_sequence_properties" value="Protein Sequence">
+						
+												<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="checkAll" onClick="checkAll('createReagentType_protein_sequence_properties');">Check All</span>
+			
+												<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="uncheckAll" onClick="uncheckAll('createReagentType_protein_sequence_properties',  Array('<?php echo $_SESSION["ReagentProp_Name_Alias"]["protein sequence"]; ?>'));">Uncheck All</span>
+											</TD>
+										</TR>
+				
+										<tr ID="protein_sequence_props_row" style="display:none;">
+											<TD colspan="4" style="padding-left:25px;">
+												<P><TABLE cellspacing="4" ID="addReagentTypeProteinSequenceProperties"><?php
+													$pCount = 0;
+						
+													echo "<TR>";
+						
+													$protSeqPropSet =  $rfunc_obj->getPropertiesByCategory($_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]);
+													
+													foreach ($protSeqPropSet as $key => $prop)
+													{
+														if ($pCount%4 == 0)
+															echo "</TR><TR>";
+
+														$value = $prop->getPropertyName();
+
+			
+														$seqPropDescr = $_SESSION["ReagentProp_Name_Desc"][$value];
+
+														echo "<TD style=\"white-space:nowrap; padding-right:10px;\">";
+
+														if ((strcasecmp($value, "protein sequence") == 0))
+														{
+															echo "<INPUT TYPE=\"checkbox\" NAME=\"createReagentType_protein_sequence_properties[]\" VALUE=\"" . $_SESSION["ReagentProp_Name_Alias"][$value] . "\" onClick=\"this.checked = true;\" CHECKED DISABLED>";
+														}
+														else
+														{
+															echo "<INPUT TYPE=\"checkbox\" NAME=\"createReagentType_protein_sequence_properties[]\" CHECKED VALUE=\"" . $_SESSION["ReagentProp_Name_Alias"][$value] . "\">";
+														}
+
+														?><INPUT TYPE="hidden" ID="<?php echo "protein_sequence_properties_:_" . $_SESSION["ReagentProp_Name_Alias"][$value]; ?>_checkbox_desc_hidden" NAME="propCheckboxes[]" VALUE="<?php echo $seqPropDescr; ?>"><?php
+												
+														echo $seqPropDescr;
+														echo "</TD>";
+														$pCount++;
+													}
+						
+													echo "</TR>";
+												?></TABLE>
+											</TD>
+										</TR>
+						
+										<tr ID="protein_sequence_add_new_props_row" style="display:none;">
+											<td colspan="4" style="padding-left:25px; padding-top:10px; white-space:nowrap;">
+												<b>Add new protein sequence property:<b>  
+												<INPUT type="text" size="35" ID="protein_sequence_properties_other" onKeyPress="return disableEnterKey(event);">  
+			
+												<input onclick="updateCheckboxListFromInput('protein_sequence_properties_other', 'protein_sequence_properties', 'addReagentTypeProteinSequenceProperties', 'add_reagent_type_form'); document.getElementById('protein_sequence_properties_other').focus();" value="Add" type="button" style="font-size:10pt;"></INPUT>
+											</td>
+										</tr>
+			
+										<TR ID="protein_sequence_features_heading_row" style="display:none;">
+											<TD colspan="4" style="padding-left:20px; padding-top:10px;">
+												<BR><IMG SRC="pictures/star_bullet.gif" WIDTH="10" HEIGHT="10" BORDER="0" ALT="bullet" style="padding-right:8px; vertical-align:middle; padding-bottom:2px;"><b>Protein Sequence Features</b>
+						
+												<input type="hidden" name="category[]" ID="proteinFeaturesCategoryInput" value="protein_sequence_features">
+			
+												<input type="hidden" ID="proteinFeaturesCategoryDescriptorInput" name="category_descriptor_protein_sequence_features" value="Protein Sequence Features">
+						
+												<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="checkAll" onClick="checkAll('createReagentType_protein_sequence_features');">Check All</span>
+												<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="uncheckAll" onClick="uncheckAll('createReagentType_protein_sequence_features', []);">Uncheck All</span>
+						
+												<BR><span style="font-size:9pt; padding-left:18px; font-weight:normal;">Properties that are linked to a sequence at specific positions and do not exist independently of it</span>
+											</TD>
+										</TR>
+				
+										<TR ID="protein_sequence_features_row" style="display:none;">
+											<TD colspan="4" style="padding-left:25px;">
+												<P><TABLE cellspacing="4" ID="addReagentTypeProteinFeatures"><?php
+													$pCount = 0;
+						
+													echo "<TR>";
+						
+													foreach ($protFeatureSet as $key => $value)
+													{
+														if ($pCount%4 == 0)
+															echo "</TR><TR>";
+
+														// Nov. 2/09: don't print tag position and expression system; they are dependent on tag type and promoter
+														if ((strcasecmp($value, "tag position") != 0) && (strcasecmp($value, "expression system") != 0))
+														{
+															?><TD style="white-space:nowrap; padding-right:10px;"><INPUT TYPE="checkbox" NAME="createReagentType_protein_sequence_features[]" VALUE="<?php echo $_SESSION["ReagentProp_Name_Alias"][$value];?>" checked><?php echo $_SESSION["ReagentProp_Name_Desc"][$value]; ?>
+
+<INPUT TYPE="hidden" ID="<?php echo "protein_sequence_features_:_" . $_SESSION["ReagentProp_Name_Alias"][$value]; ?>_checkbox_desc_hidden" NAME="propCheckboxes[]" VALUE="<?php echo $_SESSION["ReagentProp_Name_Desc"][$value];; ?>"></TD><?php
+														}
+						
+														$pCount++;
+													}
+
+													// Oct. 29/09: show custom sequence features
+													$otherProtFeatures = $rfunc_obj->getPropertiesByCategory($_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence Features"]);
+
+													$pCount = 0;
+
+													foreach ($otherProtFeatures as $key => $prop)	// $prop is an Object
+													{
+														$propName = "";
+														$propDescr = "";
+
+														try
+														{
+															$propName = $prop->getPropertyName();
+															$propDescr = $prop->getPropertyDescription();
+														}
+														catch (Exception $e)
+														{
+															// this is a feature
+															$propName = $prop->getFeatureType();
+															$propDescr = $prop->getFeatureDescription();
+															$featureValue = $prop->getFeatureValue();
+														}
+
+														if (!in_array($propName, $protFeatureSet) && (strcasecmp($propName, "tag position") != 0) && (strcasecmp($propName, "expression system") != 0))
+														{
+															if ($pCount%4 == 0)
+																echo "</TR><TR>";
+
+															?><TD style="white-space:nowrap;"><INPUT TYPE="checkbox" NAME="createReagentType_protein_sequence_features[]" VALUE="<?php echo $_SESSION["ReagentProp_Name_Alias"][$propName];?>" checked>
+
+<INPUT TYPE="hidden" ID="<?php echo "protein_sequence_features_:_" . $_SESSION["ReagentProp_Name_Alias"][$propName]; ?>_checkbox_desc_hidden" NAME="propCheckboxes[]" VALUE="<?php echo $propDescr; ?>">
+<?php echo $propDescr; ?>
+</TD><?php
+														
+	
+															$pCount++;
+														}
+													}
+
+													echo "</TR>";
+												?>
+												</TABLE>
+											</TD>
+										</TR>
+								
+										<tr ID="protein_sequence_add_new_features_row" style="display:none;">
+											<td colspan="4" style="padding-left:25px; padding-top:10px; white-space:nowrap;">
+												<b>Add new Protein sequence feature:<b>  
+												<INPUT type="text" size="35" ID="protein_sequence_features_other" value="" name="proteinFeaturesOther" onKeyPress="return disableEnterKey(event);">  
+			
+												<input onclick="updateCheckboxListFromInput('protein_sequence_features_other', 'protein_sequence_features', 'addReagentTypeProteinFeatures', 'add_reagent_type_form'); document.getElementById('protein_sequence_features_other').focus();" value="Add" type="button" style="font-size:10pt;"></INPUT>
+											</td>
+										</tr>
+			
+			
+										<!-- June 2/09: Different sequence types - RNA sequence -->
+										<TR ID="rna_sequence_heading_row" style="display:none;">
+											<TD colspan="4" style="padding-left:20px; padding-top:10px; white-space:nowrap">
+												<BR><IMG SRC="pictures/star_bullet.gif" WIDTH="10" HEIGHT="10" BORDER="0" ALT="bullet" style="padding-right:8px; vertical-align:middle; padding-bottom:2px;"><b>RNA Sequence</b>
+						
+												<input type="hidden" name="category[]" ID="rnaSequenceCategoryInput" value="rna_sequence_properties">
+			
+												<input type="hidden" ID="rnaSequenceCategoryDescriptorInput" name="category_descriptor_rna_sequence_properties" value="RNA Sequence">
+						
+												<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="checkAll" onClick="checkAll('createReagentType_rna_sequence_properties');">Check All</span>
+			
+												<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="uncheckAll" onClick="uncheckAll('createReagentType_rna_sequence_properties',  Array('<?php echo $_SESSION["ReagentProp_Name_Alias"]["rna sequence"]; ?>'));">Uncheck All</span>
+											</TD>
+										</TR>
+						
+										<tr ID="rna_sequence_props_row" style="display:none;">
+											<TD colspan="4" style="padding-left:25px;">
+												<P><TABLE cellspacing="4" ID="addReagentTypeRNASequenceProperties"><?php
+													$pCount = 0;
+						
+													echo "<TR>";
+
+													$rnaSeqPropSet = $rfunc_obj->getPropertiesByCategory($_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence"]);													
+						
+													foreach ($rnaSeqPropSet as $key => $prop)
+													{
+														if ($pCount%4 == 0)
+															echo "</TR><TR>";
+
+														$value = $prop->getPropertyName();
+			
+														$seqPropDescr = $_SESSION["ReagentProp_Name_Desc"][$value];
+
+														echo "<TD style=\"white-space:nowrap; padding-right:10px;\">";
+
+														if ((strcasecmp($value, "rna sequence") == 0))
+														{
+															echo "<INPUT TYPE=\"checkbox\" NAME=\"createReagentType_rna_sequence_properties[]\" VALUE=\"" . $_SESSION["ReagentProp_Name_Alias"][$value] . "\" onClick=\"this.checked = true;\" CHECKED DISABLED>";
+														}
+														else
+														{
+															echo "<INPUT TYPE=\"checkbox\" NAME=\"createReagentType_rna_sequence_properties[]\" CHECKED VALUE=\"" . $_SESSION["ReagentProp_Name_Alias"][$value] . "\">";
+														}
+
+														?><INPUT TYPE="hidden" ID="<?php echo "rna_sequence_properties_:_" . $_SESSION["ReagentProp_Name_Alias"][$value]; ?>_checkbox_desc_hidden" NAME="propCheckboxes[]" VALUE="<?php echo $seqPropDescr; ?>"><?php
+														echo $seqPropDescr; 
+														echo "</TD>";
+														$pCount++;
+													}
+						
+													echo "</TR>";
+												?>
+												</TABLE>
+											</TD>
+										</TR>
+
+										<tr ID="rna_sequence_add_new_props_row" style="display:none;">
+											<td colspan="4" style="padding-left:25px; padding-top:10px; white-space:nowrap;">
+												<b>Add new RNA sequence property:<b>  
+												<INPUT type="text" size="35" ID="rna_sequence_properties_other" value="" name="rnaSeqPropOther" onKeyPress="return disableEnterKey(event);">  
+			
+												<input onclick="updateCheckboxListFromInput('rna_sequence_properties_other', 'rna_sequence_properties', 'addReagentTypeRNASequenceProperties', 'add_reagent_type_form'); document.getElementById('rna_sequence_properties_other').focus();" value="Add" type="button" style="font-size:10pt;"></INPUT>
+											</td>
+										</tr>
+		
+										<TR ID="rna_sequence_features_heading_row" style="display:none;">
+											<TD colspan="4" style="padding-left:20px; padding-top:10px;">
+												<BR><IMG SRC="pictures/star_bullet.gif" WIDTH="10" HEIGHT="10" BORDER="0" ALT="bullet" style="padding-right:8px; vertical-align:middle; padding-bottom:2px;"><b>RNA Sequence Features</b>
+						
+												<input type="hidden" name="category[]" ID="rnaFeaturesCategoryInput" value="rna_sequence_features">
+			
+												<input type="hidden" ID="rnaFeaturesCategoryDescriptorInput" name="category_descriptor_rna_sequence_features" value="RNA Sequence Features">
+						
+												<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="checkAll" onClick="checkAll('createReagentType_rna_sequence_features');">Check All</span>
+												<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="uncheckAll" onClick="uncheckAll('createReagentType_rna_sequence_features', []);">Uncheck All</span>
+						
+												<BR><span style="font-size:9pt; padding-left:18px; font-weight:normal;">Properties that are linked to a sequence at specific positions and do not exist independently of it</span>
+											</TD>
+										</TR>
+								
+										<TR ID="rna_sequence_features_row" style="display:none;">
+											<TD colspan="4" style="padding-left:25px;">
+												<P><TABLE cellspacing="4" ID="addReagentTypeRNAFeatures"><?php
+													$pCount = 0;
+						
+													echo "<TR>";
+						
+													$rnaFeatureSet = $rfunc_obj->getPropertiesByCategory($_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence Features"]);
+
+													foreach ($rnaFeatureSet as $key => $prop)
+													{
+														if ($pCount%4 == 0)
+															echo "</TR><TR>";
+
+														$value = $prop->getPropertyName();
+		
+														if ((strcasecmp($value, "tag position") != 0) && (strcasecmp($value, "expression system") != 0))
+														{
+															?><TD style="white-space:nowrap; padding-right:10px;"><INPUT TYPE="checkbox" NAME="createReagentType_rna_sequence_features[]" VALUE="<?php echo $_SESSION["ReagentProp_Name_Alias"][$value];?>" checked><?php echo $_SESSION["ReagentProp_Name_Desc"][$value]; ?>
+
+
+<INPUT TYPE="hidden" ID="<?php echo "rna_sequence_features_:_" . $_SESSION["ReagentProp_Name_Alias"][$value]; ?>_checkbox_desc_hidden" NAME="propCheckboxes[]" VALUE="<?php echo $_SESSION["ReagentProp_Name_Desc"][$value]; ?>"></TD><?php
+														}
+						
+														$pCount++;
+													}
+
+// Oct. 29/09: show custom sequence features
+													$otherRNAFeatures = $rfunc_obj->getPropertiesByCategory($_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence Features"]);
+
+													foreach ($otherRNAFeatures as $key => $prop)	// $prop is an Object
+													{
+														$propName = "";
+														$propDescr = "";
+
+														try
+														{
+															$propName = $prop->getPropertyName();
+															$propDescr = $prop->getPropertyDescription();
+														}
+														catch (Exception $e)
+														{
+															// this is a feature
+															$propName = $prop->getFeatureType();
+															$propDescr = $prop->getFeatureDescription();
+															$featureValue = $prop->getFeatureValue();
+														}
+
+														if (!in_array($propName, $rnaFeatureSet) && (strcasecmp($propName, "tag position") != 0) && (strcasecmp($propName, "expression system") != 0))
+														{
+															if ($pCount%4 == 0)
+																echo "</TR><TR>";
+															?><TD style="white-space:nowrap;"><INPUT TYPE="checkbox" NAME="createReagentType_rna_sequence_features[]" VALUE="<?php echo $_SESSION["ReagentProp_Name_Alias"][$propName];?>" checked>
+
+<INPUT TYPE="hidden" ID="<?php echo "rna_sequence_features_:_" . $_SESSION["ReagentProp_Name_Alias"][$propName]; ?>_checkbox_desc_hidden" NAME="propCheckboxes[]" VALUE="<?php echo $propDescr; ?>">
+<?php echo $propDescr; ?></TD>
+<?php
+														}
+
+														$pCount++;
+													}
+						
+													echo "</TR>";
+												?>
+												</TABLE>
+											</TD>
+										</TR>
+		
+										<tr ID="rna_sequence_add_new_features_row" style="display:none;">
+											<td colspan="4" style="padding-left:25px; padding-top:10px; white-space:nowrap;">
+												<b>Add new RNA sequence feature:<b>  
+												<INPUT type="text" size="35" ID="rna_sequence_features_other" value="" name="rnaFeaturesOther" onKeyPress="return disableEnterKey(event);">  
+			
+												<input onclick="updateCheckboxListFromInput('rna_sequence_features_other', 'rna_sequence_features', 'addReagentTypeRNAFeatures', 'add_reagent_type_form'); document.getElementById('rna_sequence_features_other').focus();" value="Add" type="button" style="font-size:10pt;"></INPUT>
+											</td>
+										</tr>
+									</TABLE>
+								</TD>
+							</TR>
+
+							<TR ID="addCategoryRow">
+								<TD style="padding-top:10px; white-space:nowrap; padding-left:18px; font-weight:bold;">
+									<P><HR><BR>If the property you wish to add does not fit any of the above categories, please add your own category:<BR>
+									<P><INPUT type="text" size="35" ID="new_category" value="" name="newCategory" onKeyPress="return disableEnterKey(event);">  
+		
+									<input onclick="addPropertiesCategory('new_category', 'addReagentPropsTbl', 'addCategoryRow', 'add_reagent_type_form');" value="Add" type="button" style="font-size:10pt;"></INPUT>
+		
+									<BR><BR><HR>
+								</TD>
+							</TR>
+		
+							<TR ID="rTypeSubmitRow">
+								<td style="padding-left:16px; font-size:9pt;">
+									<BR><INPUT TYPE="submit" name="create_rtype" value="Continue" onclick = "collectReagentTypeProperties('add_reagent_type_form'); addReagentTypeNameToParentsList(); return verifyNewReagentTypeName() && verifyNewReagentTypePrefix() && verifyUniqueReagentTypeName() && verifyReagentTypePrefix(); document.getElementById('navigate_away').value=0;" style="font-size:10pt;">
+									<INPUT TYPE="hidden" name="step" value="1">
+								</td>
+							</TR>
+						</TABLE>	<!-- close addReagentPropsTbl -->
+					</TD>
+				</TR>
+
+				<TR><TD style="padding-left:36px;"> </td></tr>
+			</TABLE>
+		</FORM>
+		<?php
+
+		foreach ($_SESSION["ReagentType_ID_Name"] as $key => $value)
+		{
+			echo "<INPUT TYPE=\"hidden\" NAME=\"reagent_type_names[]\" value=\"" . $value . "\">";
+		}
+
+		foreach ($_SESSION["ReagentType_ID_Prefix"] as $key => $value)
+		{
+			echo "<INPUT TYPE=\"hidden\" NAME=\"reagent_type_prefixes[]\" value=\"" . $value . "\">";
+		}
+	}
+
+	
+	/**
+	 * This function prints forms to add new reagents for all reagent types in OpenFreezer.  The forms are hidden initially, displayed if that reagent type is selected from the dropdown menu
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2007-03-27
+	 *
+	 * @param STRING
+	 * @param STRING
+	 * @param Array
+	*/
+	function printCreationForm($rType="", $subtype="", $parents=array())
+	{
+		global $cgi_path;
+		
+		$r_out = new Reagent_Output_Class();
+		$gfunc_obj = new generalFunc_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+
+		// May 5/08: Use a different prefix - make uniform for all reagent types and for dynamic features
+		$genPrefix = "reagent_detailedview_";
+		$genPostfix = "_prop";
+		
+		// Property names
+		$v_name = $rfunc_obj->get_Post_Names("Vector", "");
+
+		// August 21/07, Marina: Pass current user info to CGI script
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+
+		?>
+		<!-- Vector - 3 subtypes -->
+		<FORM method="POST" NAME="createReagentForm" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $rType; ?>', '<?php echo $subtype; ?>');">
+
+			<!-- Pass user info to Python as hidden form value - Aug 21/07 -->
+			<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+			<INPUT type="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+
+			<!-- MAY 2/08: IF RETURNING TO THIS VIEW FROM A LATER PAGE TO CHANGE PARENTS - PASS THE REAGENT ID TO PYTHON!!!!!! -->
+			<?php
+				if (isset($_GET["rID"]))
+				{
+					?>
+						<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $_GET["rID"]; ?>">
+					<?php
+				}
+
+				// May 26/08: Only show reagent type selection box initially; if type/subtype have already been selected disallow changing it in the middle of creation
+				if ($rType == "")
+				{
+					$this->printReagentTypeSelection();
+				}
+				else
+				{
+					// However, Python expects reagent type and subtype as form input. If not showing lists, pass hidden values
+					?>
+						<INPUT TYPE="hidden" NAME="reagentType" VALUE="<?php echo $rType; ?>">
+						<?php
+
+						if (strcasecmp($rType, "Vector") == 0)
+							echo "<INPUT TYPE=\"hidden\" NAME=\"vectorSubtype\" VALUE=\"" . $subtype . "\">";
+						
+						else if (strcasecmp($rType, "CellLine") == 0)
+							echo "<INPUT TYPE=\"hidden\" NAME=\"cellLineSubtype\" VALUE=\"" . $subtype . "\">";
+				}
+			?>
+			<!-- PARENTS -->
+			<table id="nonrec_parents" cellpadding="2" cellspacing="2" style="text-align:center; display:<?php echo (($subtype == "nonrecomb") || ($subtype == "gateway_entry")) ? "inline" : "none"; ?>;">
+				<TR><TD> </TD></TR>
+
+				<tr>
+					<td colspan="4">
+						<span id="nonrecomb_hdr" style="font-weight:bold; color:#00C00D; font-size:13pt; white-space:nowrap; padding-bottom:18px; display:<?php echo ($subtype == "nonrecomb") ? "inline" : "none"; ?>">
+							CREATE A NON-RECOMBINATION VECTOR<BR>
+						</span>
+
+						<span id="gw_entry_hdr" style="color:#00C00D; font-size:13pt; font-weight:bold; white-space:nowrap; display:<?php echo ($subtype == "gateway_entry") ? "inline" : "none"; ?>">
+							CREATE A GATEWAY ENTRY VECTOR<BR>
+						</span>
+
+						<span style="color:#00C00D; font-weight:bold; font-size:10pt; text-align:center; white-space:nowrap;">
+							Step 1 of 4: Define Parents
+						</span>
+						<BR><BR>
+
+						<span id="nonrec_title" style="padding-left:15px; font-weight:bold; white-space:nowrap; display:<?php echo ($subtype == "nonrecomb") ? "inline" : "none"; ?>">Please enter  OpenFreezer IDs of the <u>Parent Vector</u> and <u>Insert</u> used to generate this Vector:<BR></span>
+
+						<span id="gw_entry_title" style="padding-left:15px; font-weight:bold; white-space:nowrap; display:<?php echo ($subtype == "gateway_entry") ? "inline" : "none"; ?>">Please enter OpenFreezer IDs of the <u>Gateway Parent Donor Vector</u> and <u>Insert</u> in the fields below:<BR></span>
+
+						<BR><TABLE width="700px" style="text-align:left;">
+							<TR>
+								<TD width="125px" style="white-space:nowrap; padding-left:20px;">
+									<SPAN id="nonrec_pv" style="display:<?php echo ($subtype == "nonrecomb") ? "inline" : "none"; ?>">Parent Vector OpenFreezer ID:<BR></SPAN>
+
+									<span id="gw_pv" style="display:<?php echo ($subtype == "gateway_entry") ? "inline" : "none"; ?>">Gateway Parent Donor Vector OpenFreezer ID:<BR></span>
+								</TD>
+
+								<TD>
+									<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="nr_pv_id" name="nr_parent_vector" size="8" value="<?php echo $parents["PV"]; ?>">
+								</TD>
+							</TR>
+			
+							<TR>
+								<TD width="125px" style="white-space:nowrap; padding-left:20px;">
+									Insert OpenFreezer ID:
+								</TD>
+								
+								<TD style="white-space:nowrap">
+									<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="insert" name="insert_id" size="8" value="<?php echo $parents["I"]; ?>">
+
+									<!-- Jan. 21/09 -->
+									<?php
+									if ($subtype != 'gateway_entry')
+									{
+										?>  <INPUT TYPE="checkbox" ID="reverseComplementCheckbox" onClick="document.getElementById('customSitesCheckbox').checked=true; showHideCustomSites()" NAME="reverse_complement" style="font-size:10pt"><span id="rc_text">Reverse Complement    </span><?php
+									}
+								?></TD>
+							</TR>
+						</TABLE>
+					</td>
+				</tr>
+
+				<TR>
+					<TD colspan="4" style="text-align:left; padding-left:20px; padding-top:10px;">
+					<?php
+						if ($subtype != 'gateway_entry')
+						{
+							?><div id="rc_caption">
+								<HR>
+								By default, the new Vector's cloning sites are identical to those of the specified parent Insert.  You may change the default values using the 'Customize Sites' function below.
+
+								<A href="pictures/nonrecomb_vector.pdf" onClick="return popup(this, 'diagram', '665', '635', 'yes')">Click here to view an illustration</A><BR><BR>
+
+								<span style="color:#FF0000;">If 'Reverse Complement' is selected, you must also reverse the order of the Insert's cloning sites for non-directional cloning.</span>  E.g. if the 5' and 3' cloning sites of the Insert are BamHI and BglII respectively, indicate "Insert 5' site" => "BglII" and "Insert 3' site" => "BamHI" below.<BR><HR><BR>
+							</div>
+
+							<!-- Nov. 17/08: Add option to make custom sites -->
+							<INPUT TYPE="checkbox" ID="customSitesCheckbox" NAME="custom_sites" style="font-size:10pt" onClick="showHideCustomSites()"> <span id="customize_sites_text">Customize cloning sites<BR>
+							<span style="margin-left:20px; font-size:9pt;">(Click here if Insert and Parent Vector sites are not identical)</span>
+							<BR><BR></span><?php
+						}
+
+						?><TABLE cellpadding="4px" border="1" frame="none" rules="all" ID="customCloningSites" style="display:none">
+							<TH colspan="2">
+								<b>Please specify cloning sites on the Parent Vector and insert:</b><BR>
+							</TH>
+
+							<tr>
+								<td colspan="2" style="font-size:9pt; font-weight:bold">
+									Parent Vector Cloning Sites:
+								</td>
+							</tr>
+					
+							<TR>
+								<TD style="padding-left:10px">
+									5' Cloning Site:
+								</TD>
+					
+								<TD>
+									<?php
+										echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list_1\" name=\"pv_custom_five_prime\"></select>";
+									?>
+								</TD>
+							</TR>
+					
+							<TR>
+								<TD style="padding-left:10px">
+									3' Cloning Site:
+								</TD>
+					
+								<TD>
+									<?php
+										echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list_1\" name=\"pv_custom_three_prime\"></select>";
+									?>
+								</TD>
+							</TR>
+
+
+							<tr>
+								<td colspan="2" style="font-size:9pt; font-weight:bold;">
+									Insert Cloning Sites:
+								</td>
+							</tr>
+					
+							<TR>
+								<TD style="padding-left:10px">
+									5' Cloning Site:
+								</TD>
+					
+								<TD>
+									<?php
+										echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list\" name=\"insert_custom_five_prime\"></select>";
+									?>
+									<BR><div id="fp_warning" style="display:none; color:#FF0000">Please select a value for the 5' restriction site from the dropdown list</div>
+								</TD>
+							</TR>
+					
+							<TR>
+								<TD style="padding-left:10px">
+									3' Cloning Site:
+								</TD>
+					
+								<TD>
+									<?php
+										echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list\" name=\"insert_custom_three_prime\"></select>";
+									?>
+									<BR><div id="tp_warning" style="display:none; color:#FF0000">Please select a value for the 3' restriction site from the dropdown list</div>
+								</TD>
+							</TR>
+
+						</table>
+
+						<BR><INPUT TYPE="submit" name="preload" value="Continue" onClick="if (document.getElementById('cancel_set')) {document.getElementById('cancel_set').value=0}; return verifyCustomSites(); document.getElementById('navigate_away').value=0;">
+						<?php
+							// Nov. 5/08: Add 'Cancel' btn
+							if (isset($_GET["rID"]))
+							{
+								?>
+									 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+
+									<INPUT type="hidden" ID="cancel_set" value="0">
+								<?php
+							}
+						?>
+					</TD>
+				</TR>
+			</table>
+
+			<TABLE id="recomb_parents" width="700px" style="display:<?php echo (($subtype == "recomb") || ($subtype == "gateway_expression")) ? "inline" : "none"; ?>" cellpadding="2px">
+				<tr><td> </td></tr>
+
+				<tr>
+					<td colspan="2">
+						<center>
+						<span id="recomb_hdr" style="font-weight:bold; color:#00C00D; font-size:13pt; white-space:nowrap; padding-bottom:18px; text-align:center; display:<?php echo ($subtype == "recomb") ? "inline" : "none"; ?>">
+							CREATE AN EXPRESSION VECTOR<BR>
+						</span>
+
+						<span id="gw_expr_hdr" style="color:#00C00D; font-size:13pt; font-weight:bold; white-space:nowrap; padding-bottom:18px; text-align:center; display:<?php echo ($subtype == "gateway_expression") ? "inline" : "none"; ?>">
+							CREATE A GATEWAY EXPRESSION VECTOR<BR>
+						</span>
+						
+						<span style="color:#00C00D; font-weight:bold; font-size:10pt; text-align:center; white-space:nowrap; padding-bottom:18px;">
+							Step 1 of 4: Define Parents
+						</span>
+						<BR><BR>
+
+						<span id="creator_title" style="padding-left:15px; font-weight:bold; display:<?php echo ($subtype == "recomb") ? "inline" : "none"; ?>">Please enter  OpenFreezer IDs of the <u>Acceptor</u> and <u>Donor</u> Vectors used to generate this Vector:<BR></span>
+						</center>
+
+						<span id="gw_expression_title" style="padding-left:15px; font-weight:bold; display:<?php echo ($subtype == "gateway_expression") ? "inline" : "none"; ?>">Please enter OpenFreezer IDs of the <u>Gateway Parent Destination Vector</u> and <u>Gateway Entry Clone</u> in the fields below:<BR></span>
+						
+						<BR><table width="400px" cellpadding="2" cellspacing="2" style="border:0; margin-left:10px;">
+							<TR>
+								<TD width="85px" style="white-space:nowrap; padding-left:10px;">
+									<span id="creator_acceptor_pv" style="display:<?php echo ($subtype == "recomb") ? "inline" : "none"; ?>">Creator Acceptor Vector OpenFreezer ID:</span>
+
+									<span id="destination_pv" style="display:<?php echo ($subtype == "gateway_expression") ? "inline" : "none"; ?>">Gateway Parent Destination Vector OpenFreezer ID:</span>
+								</TD>
+			
+								<TD colspan="2">
+									<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="rec_pv_id" name="rec_parent_vector" size="8" value="<?php echo $parents["PV"]; ?>">
+								</TD>
+							</TR>
+			
+							<TR>
+								<TD width="125px" style="padding-left:10px; white-space:nowrap">
+									<span id="creator_donor_ipv" style="display:<?php echo ($subtype == "recomb") ? "inline" : "none"; ?>">Creator Donor Vector OpenFreezer ID:</span>
+
+									<span id="gateway_donor_ipv" style="display:<?php echo ($subtype == "gateway_expression") ? "inline" : "none"; ?>">Gateway Entry Clone OpenFreezer ID:</span>
+								</TD>
+
+								<TD>
+									<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="insert_parent_vector_id" name="insert_parent_vector" size="8" value="<?php echo $parents["IPV"]; ?>">
+								</TD>
+							</TR>
+						</TABLE>
+					</td>
+				</tr>
+
+				<TR>
+					<TD colspan="2" style="padding-top:10px; padding-left:20px;">
+						<INPUT TYPE="submit" name="preload" value="Next">
+					</TD>
+				</TR>
+			</TABLE>
+
+			<!-- Novel Vectors -->
+			<TABLE id="vector_general_props" style="display:none">
+				<TR>
+					<TD colspan="3">
+						<table width="100%" cellpadding="4">
+							<tr>
+								<td style="text-align:center">
+									<span style="color:#00C00D; font-size:13pt; font-weight:bold">
+										CREATE A NEW PARENT (NOVEL) VECTOR
+									</span>
+
+									<!-- For Novel vectors need to redirect to features page from here, so to invoke a different CGI code segment must pass other arguments -->
+									<input type="hidden" name="reagent_type_hidden" value="Vector">
+									<input type="hidden" name="subtype_hidden" value="novel">
+								</td>
+							</tr>
+						</table>
+				
+						<table border="1" width="100%" cellpadding="4" frame="box" rules="none">
+							<tr>
+								<td style="font-size:9pt; padding-left:10px;">
+									<b>Step 1 of 3:</b><BR><P><span style="padding-left:5px;">Please paste your Vector sequence in the box below<!--, <b>including <u>intact cloning sites</u> and any <u>linking sequences</u> between the cloning sites and the start of the cDNA sequence:</b>-->:</span>
+								</td>
+							</tr>
+						
+							<tr>
+								<td>
+									<?php
+										$r_out->print_property_final($genPrefix . $v_name["sequence"] . $genPostfix, "sequence", "", "Preview", true, "DNA Sequence", "");
+									?>
+									<BR><div id="vector_sequence_warning" style="display:none; color:#FF0000">Please paste a sequence in the textbox above.</div>
+								</td>
+							</tr>
+						</table>
+						<BR>
+						
+						<table style="padding-top:10px;">
+							<TR>
+								<td style="padding-left:0px;">
+									<input type="submit" name="confirm_features" value="Continue" onClick="if (document.getElementById('cancel_set')) {document.getElementById('cancel_set').value=0}; return verifyNovelVectorSequence(); document.getElementById('navigate_away').value=0;">
+								</td>
+							</tr>
+							
+						</table>
+					</TD>
+				</TR>
+			</TABLE>
+ 		</FORM>		<!-- moved here May 12/08 -->
+
+		<!-- April 19, 2010: Upload Excel sheets - will be finalized a little later, don't delete this section -->
+		<!--<TABLE>
+			<TR>
+				<TD style="padding-left:10px; padding-top:10px;">
+					Or, use the 'Batch Upload' feature to load more than 10 reagents: 
+					<a href="batch_templates/downloads/vector_reagents_v3.xls" class="linkShow">Download Template</a>
+
+					<BR>
+					<P><B>Please note: Batch input files must contain a minimum of 10 reagents.  For fewer than 10 entries, please use the standard reagent input mechanism.</B>
+				</TD>
+			</TR>
+
+			<TR>
+				<TD style="padding-left:10px; padding-top:10px;">
+					<form enctype="multipart/form-data" action="Reagent/upload.php" method="POST">
+						<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
+						Choose a file to upload: <input name="uploadedfile" type="file" /><br />
+						<input type="submit" value="Upload File" />
+					</form>
+				</TD>
+			</TR>
+		<TABLE>-->
+		<?php
+
+		// Insert
+		$iShow = ($rType == "Insert") ? true : false;
+
+		if (isset($_GET["rID"]))
+		{
+			$rID = $_GET["rID"];
+		}
+		else
+		{
+			$rID = "";
+		}
+
+		$this->printForm_Insert_Insert($rID, $iShow);
+		
+		// Other
+		foreach ($_SESSION["ReagentType_Name_ID"] as $r_type => $rTypeID)
+		{
+			switch ($r_type)
+			{
+				case 'Vector':
+				break;
+
+				case 'Insert':
+				break;
+
+				case 'CellLine':	// update Jan. 19, 2010
+					?>
+					<!-- CELL LINE -->
+					<FORM method="POST" NAME="createReagentForm" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $rType; ?>', '<?php echo $subtype; ?>');">
+						<!-- Pass user info to Python as hidden form value - Aug 21/07 -->
+						<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+						<INPUT type="hidden" NAME="cellLineSubtype" VALUE="stable_cell_line">
+						<INPUT TYPE="hidden" NAME="reagentType" VALUE="CellLine">
+				
+						<TABLE id="stable_cell_line_parents" style="display:none" cellpadding="2px">
+						
+							<TR>
+								<TD nowrap>
+									Parent Vector OpenFreezer ID:
+								</TD>
+			
+								<TD>
+									<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="cl_pv_id" name="cell_line_parent_vector" size="8"/>
+								</TD>
+			
+							</TR>
+							
+							<TR>
+								<TD nowrap>
+									Parent Cell Line OpenFreezer ID:
+								</TD>
+			
+								<TD>
+									<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="parent_cell_line_id" name="parent_cell_line" size="8"/>
+								</TD>
+							</TR>
+			
+							<!-- July 17/08	-->
+							<TR>
+								<TD colspan="2" style="padding-top:8px; padding-left:10px;">
+									<INPUT TYPE="submit" name="preload" value="Next">
+								</TD>
+							</TR>
+						</TABLE>
+					</FORM>
+					<?php
+
+					// General Cell Line properties form
+					$this->printCellLineGeneralPropsForm();
+				break;
+
+				default:
+					if ($rfunc_obj->hasAttribute($_SESSION["ReagentType_Name_ID"][$r_type], "protein sequence", $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]))
+						$seq_type = "protein";
+					else if ($rfunc_obj->hasAttribute($_SESSION["ReagentType_Name_ID"][$r_type], "rna sequence", $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence"]))
+						$seq_type = "rna";
+					else
+						$seq_type = "dna";
+
+					?><FORM method="POST" ENCTYPE="multipart/form-data" NAME="createReagentForm<?php echo $r_type; ?>" action="<?php echo $cgi_path . "create.py"; ?>">
+		
+					<!-- Pass user info to Python as hidden form value - Aug 21/07 -->
+					<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+					<INPUT type="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+
+					<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $r_type; ?>">
+					<?php
+						
+						// moved up here on April 11, 2011
+						$ignoreList = Array();
+
+						$isProtein = $rfunc_obj->hasAttribute($_SESSION["ReagentType_Name_ID"][$r_type], "protein sequence", $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]);
+
+						$isRNA = $rfunc_obj->hasAttribute($_SESSION["ReagentType_Name_ID"][$r_type], "rna sequence", $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence"]);
+
+						if ($isProtein)
+						{
+							$featureType = $_SESSION["ReagentPropCategory_Name_Alias"]["Protein Sequence Features"];
+
+							// For Protein, Tm is entered manually, MW computed automatically
+							$ignoreList[] = "molecular weight";
+						}
+						else if ($isRNA)
+						{
+							$featureType = $_SESSION["ReagentPropCategory_Name_Alias"]["RNA Sequence Features"];
+						}
+						else
+						{
+							$featureType = $_SESSION["ReagentPropCategory_Name_Alias"]["DNA Sequence Features"];
+
+							// For DNA, Tm, MW, GC% and translation are computed automatically
+							$ignoreList[] = "protein translation";
+							$ignoreList[] = "melting temperature";
+							$ignoreList[] = "molecular weight";
+							$ignoreList[] = "gc content";	// june 25, 2010
+						}
+					?>
+					<INPUT TYPE="hidden" NAME="feature_type_<?php echo $r_type; ?>" VALUE="<?php echo $featureType; ?>">
+
+					<TABLE width="700px" ID="createReagentTbl_<?php echo $r_type; ?>" NAME="reagentTypeCreateOther" style="display:none; margin-left:15px; font-size:10pt; width:705px;" cellpadding="4" cellspacing="4">
+						<TR>
+							<TD>
+								<!-- making title a standalone table so it is not resized when sections are collapsed -->
+								<table style="text-align:center; white-space:nowrap;" width="705px"><tr><td style="font-size:12pt; color:#00C00D; font-weight:bold;"><?php echo "ADD NEW " . $r_type; ?></td></tr></table>
+							</TD>
+						</TR>
+						<?php
+
+						// find the attributes of this reagent type
+						$categories = $rfunc_obj->findAllReagentTypeAttributeCategories($rTypeID);
+
+						$seqFeaturesOther = Array();
+
+						foreach ($categories as $categoryID => $category)
+						{
+							if (($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]) && ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence Features"]) && ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence Features"]))
+							{
+								$rTypeAttributes = $rfunc_obj->getReagentTypeAttributesByCategory($_SESSION["ReagentType_Name_ID"][$r_type], $categoryID);
+								
+								if (count($rTypeAttributes) == 0)
+									continue;
+
+								$catAlias = $_SESSION["ReagentPropCategory_ID_Alias"][$categoryID];
+
+								echo "<tr><td><HR></td></tr>";
+	
+								echo "<TR>";
+									echo "<TD>";
+										echo "<table style=\"background-color:#FFFFFF;\">";
+
+											// Aug. 19/09: Changed categoryID to catAlias, since that is also the name of the table in addNewReagentType() and JS was confusing between the two
+											echo "<tr>";
+												echo "<td style=\"font-weight:bold; color:blue; padding-top:2px;\">";
+													echo "<IMG id=\"" . $catAlias . "_expand_img_" . $r_type . "\" SRC=\"pictures/arrow_collapse.gif\" WIDTH=\"20\" HEIGHT=\"15\" BORDER=\"0\" ALT=\"plus\" class=\"menu-expanded\" style=\"display: inline\" onClick=\"showHideCategory('" . $catAlias . "', '" . $r_type . "');\">";
+	
+													echo "<IMG id=\"" . $catAlias . "_collapse_img_" . $r_type . "\" SRC=\"pictures/arrow_expand.gif\" WIDTH=\"40\" HEIGHT=\"34\" BORDER=\"0\" ALT=\"plus\" class=\"menu-collapsed\" style=\"display: none\" onClick=\"showHideCategory('" . $catAlias . "', '" . $r_type . "');\">";
+	
+													echo "<span id=\"section_title_" . $catAlias . "\">" . $category . "</span>";
+												echo "</TD>";
+											echo "</TR>";
+	
+											echo "<tr>";
+												echo "<td style=\"padding-left:2px;\">";
+													echo "<table ID=\"category_" . $catAlias . "_section_" . $r_type . "\" cellpadding=\"4\" cellspacing=\"2\" style=\"background-color:#FFFFFF; margin-top:4px;\">";
+//	print_r($ignoreList);
+													// May 5, 2010
+													foreach ($rTypeAttributes as $attrID => $cProp)
+													{
+														$propDescr = $cProp->getPropertyDescription();
+														$propAlias = $cProp->getPropertyAlias();
+														$propName = $cProp->getPropertyName();
+														$propCategory = $cProp->getPropertyCategory();
+
+														// May 5, 2010
+														$p_id = $_SESSION["ReagentProp_Name_ID"][$propName];
+														$c_id = $_SESSION["ReagentPropCategory_Name_ID"][$propCategory];
+														$pID = $rfunc_obj->getPropertyIDInCategory($p_id, $c_id);
+	
+														if (!in_array($propName, $ignoreList))
+														{
+															echo "<TR style=\"background-color:#F5F5DC;\">";
+
+																echo "<TD style=\"padding-left:15px; padding-right:15px; font-size:8pt; width:100px; font-weight:bold; white-space:nowrap;\">" . $propDescr;
+
+																	// Changes Feb. 8/10
+																	$tmp_pc_id = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][$propName], $_SESSION["ReagentPropCategory_Name_ID"][$propCategory]);
+
+																	//if ( ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["name"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"])) || ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["project id"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"])) || (strcasecmp($propName, "packet id") == 0) || (strcasecmp($propName, "owner") == 0) || ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_S [...]
+
+																	if ($rfunc_obj->isMandatory($r_type, strtolower($propName)))
+																	{
+																		echo "<span style=\"font-size:9pt; color:#FF0000; font-weight:bold; margin-left:5px;\">*</span></TD>";
+																		echo "<INPUT TYPE=\"hidden\" NAME=\"" . $r_type . "_mandatoryProps[]\" VALUE=\"" . $attrID . "\">";
+																	}
+
+																	// June 18, 2010: add explanation for Alt. ID Other
+																	else if ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["alternate id"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]))
+																	{
+																		echo "<BR><BR><span style=\"font-size:8pt;\">For 'Other', please enter<BR> the database name and<BR> numeric identifier, separated<BR> by semicolon, in the textbox<BR> (e.g. 'IMAGE:123456')</span></TD>";
+																	}
+																	else
+																		echo "</TD>";
+																	
+																	echo "<TD style=\"font-size:8pt; padding-left:10px; width:600px;\">";
+
+																	$r_out->print_property_final($genPrefix . $r_type . "_" . $catAlias . "_:_" . $propAlias . $genPostfix, $propName, "", "", true, $propCategory, "Preview", "", $r_type, false, "", 0, 0);
+
+																	if ($rfunc_obj->isCustomizeable($attrID))
+																	{
+																		echo "<BR><INPUT TYPE=\"text\" style=\"display:none;\" ID=\"otherText_" . $propCatID . "\">";
+																	
+																		echo "<INPUT TYPE=\"button\" style=\"font-size:7pt; display:none;\" VALUE=\"Add\" ID=\"addOtherBtn_" . $propCatID . "\" onClick=\"addElementToListFromInput('otherText_" . $propCatID . "', '" . $genPrefix . $r_type . "_" . $catAlias . "_:_" . $propAlias . $genPostfix . "')\" NAME=\"addBtn[]\">";
+																	}
+
+																echo "</TD>";
+															echo "</TR>";
+														}
+													}
+	
+													echo "</TABLE>";
+												echo "</TD>";
+											echo "</TR>";
+										echo "</TABLE>";
+									echo "</TD>";
+								echo "</TR>";
+							}
+							else
+							{
+								$catAlias = $_SESSION["ReagentPropCategory_ID_Alias"][$categoryID];
+
+								echo "<tr><td><HR></td></tr>";
+	
+								echo "<TR>";
+									echo "<TD>";
+										echo "<table style=\"background-color:#FFFFFF;\">";
+
+											// Aug. 19/09: Changed categoryID to catAlias, since that is also the name of the table in addNewReagentType() and JS was confusing between the two
+											echo "<tr>";
+												echo "<td style=\"font-weight:bold; color:blue; padding-top:2px;\">";
+													echo "<IMG id=\"" . $catAlias . "_expand_img_" . $r_type . "\" SRC=\"pictures/arrow_collapse.gif\" WIDTH=\"20\" HEIGHT=\"15\" BORDER=\"0\" ALT=\"plus\" class=\"menu-expanded\" style=\"display: inline\" onClick=\"showHideCategory('" . $catAlias . "', '" . $r_type . "');\">";
+	
+													echo "<IMG id=\"" . $catAlias . "_collapse_img_" . $r_type . "\" SRC=\"pictures/arrow_expand.gif\" WIDTH=\"40\" HEIGHT=\"34\" BORDER=\"0\" ALT=\"plus\" class=\"menu-collapsed\" style=\"display: none\" onClick=\"showHideCategory('" . $catAlias . "', '" . $r_type . "');\">";
+	
+													echo "<span id=\"section_title_" . $catAlias . "\">" . $category . "</span>";
+												echo "</TD>";
+											echo "</TR>";
+	
+											echo "<tr ID=\"category_" . $catAlias . "_section_" . $r_type . "\" style=\"background-color:#FFFFFF; padding-top:4px;\">";
+												echo "<td style=\"padding-left:2px;\">";
+													$this->printFeatures($r_type, "", "", "", "createReagentForm" . $r_type, false, true, "category_" . $catAlias . "_features_section_" . $r_type . "_tbl");
+												echo "</td>";
+											echo "</TR>";
+										echo "</TABLE>";
+									echo "</TD>";
+								echo "</TR>";
+							}
+						}
+
+						// Aug. 11/09: Parents
+						$assoc = $rfunc_obj->findReagentTypeAssociations($rTypeID);
+
+						if (count($assoc) > 0)
+						{
+							echo "<tr><td><HR></td></tr>";
+
+							echo "<tr>";
+								echo "<td style=\"font-weight:bold; color:blue; padding-top:2px;\">";
+									echo "<IMG id=\"assoc_expand_img\" SRC=\"pictures/arrow_collapse.gif\" WIDTH=\"20\" HEIGHT=\"15\" BORDER=\"0\" ALT=\"plus\" class=\"menu-expanded\" style=\"display: inline\" onClick=\"showHideCategory('assoc');\">";
+
+									echo "<IMG id=\"assoc_collapse_img\" SRC=\"pictures/arrow_expand.gif\" WIDTH=\"40\" HEIGHT=\"34\" BORDER=\"0\" ALT=\"plus\" class=\"menu-collapsed\" style=\"display: none\" onClick=\"showHideCategory('assoc');\">";
+
+									echo "<span id=\"section_title_associations\">Associations</span>";
+								echo "</TD>";
+							echo "</TR>";
+
+							echo "<tr>";
+								echo "<td style=\"padding-left:8px; padding-top:10px; padding-bottom:10px;\">";
+									echo "<table ID=\"category_assoc_section_" . $rTypeID . "\" cellpadding=\"4\" cellspacing=\"2\" style=\"background-color:#FFFFFF; margin-top:4px;\">";
+						
+									$r_count = 0;
+
+									foreach ($assoc as $assocID => $assocValue)
+									{
+										// echo "assoc id " . $assocID . "<BR>";
+										// echo "assoc value " . $assocValue . "<BR>";
+
+										// Dec. 10/09: show parent prefix
+										$parentTypeID = $rfunc_obj->findAssocParentType($assocID);
+										$parentPrefix = $_SESSION["ReagentType_ID_Prefix"][$parentTypeID];
+
+										$assocAlias = $_SESSION["ReagentAssoc_ID_Alias"][$assocID];
+
+										// echo "assoc alias " . $assocAlias . "<BR>";
+
+										?><TR ID="<?php echo $rTypeID . "_" . $assocAlias; ?>_assoc_row_<?php echo $assocID . "_" . $r_count; ?>" style="background-color:#F5F5DC;">
+											<TD style="padding-left:15px; padding-right:15px; font-size:8pt; width:120px; font-weight:bold; white-space:nowrap;"><?php
+												echo $assocValue . " (" . $parentPrefix . ")";
+											?></TD>
+			
+											<TD style="font-size:8pt; padding-left:10px; width:600px;">
+
+												<!-- Nov. 24/09: DO ***NOT*** use assocAlias here, because they are ***NOT UNIQUE*** across reagent types!!!!!!!!!!!!!!!!!!!!
+												A Parent Vector can belong to an Antibody as well as a Cell Line!!!!! -->
+
+												<INPUT TYPE="TEXT" ID="<?php echo $r_type; ?>_assoc_<?php echo $assocAlias; ?>_input" onKeyPress="return disableEnterKey(event);" NAME="<?php echo $r_type; ?>_assoc_<?php echo $assocID; ?>_prop">
+
+												<INPUT TYPE="hidden" ID="<?php echo $r_type; ?>_assoc_type" NAME="reagent_association_types" VALUE="<?php echo $assocID; ?>">
+											
+												<SPAN class="linkExportSequence" style="margin-left:15px; font-weight:normal;" onClick="addParent('<?php echo $rTypeID; ?>', '<?php echo $r_type; ?>', '<?php echo $assocAlias; ?>', '<?php echo $assocValue;?>', '<?php echo $assocID; ?>', '<?php echo $r_count; ?>');">Add New</SPAN>
+
+												<SPAN class="linkExportSequence" style="margin-left:15px; font-weight:normal;" onClick="deleteTableRow('category_assoc_section_<?php echo $rTypeID?>', '<?php echo $rTypeID . "_" . $assocAlias; ?>_assoc_row_<?php echo $assocID . "_" . $r_count; ?>');">Remove</SPAN>
+											</TD>
+										</TR><?php
+
+										$r_count++;
+									}
+
+									echo "</TABLE>";
+								}
+
+							echo "</TD>";
+						echo "</TR>";
+
+						// submit button and close form
+						?><TR>
+							<TD colspan="2"><BR>
+								<INPUT TYPE="submit" name="create_reagent" value="Create" onClick="document.pressed = this.value; if (document.getElementById('cancel_set')) {document.getElementById('cancel_set').value=0}; enableSites(); selectAllPropertyValues(true); changeFieldNames('createReagentForm<?php echo str_replace("'", "\'", $r_type); ?>', 'createReagentTbl_<?php echo str_replace("'", "\'", $r_type); ?>', '<?php echo str_replace("'", "\'", $r_type); ?>'); setFeaturePositions('<?php echo str_replace("' [...]
+								<?php
+									if (isset($_GET["rID"]))
+									{
+										?> <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost')">
+
+										<INPUT type="hidden" ID="cancel_set" value="0"><?php
+									}
+								?>
+							</TD>
+						</TR>
+					</TABLE>
+				</FORM>
+				<?php
+
+				break;
+			}
+		}
+	}
+	
+	
+	/**
+	 * Exception handling function - prints a form notifying the user of an error in reagent creation and giving options to correct the input or start anew.
+	 *
+	 * Possible error codes:
+	 *
+	 * VECTOR:
+	 *
+	 * 1. Wrong sites on Insert, not matching type of Vector being created. Only generated at non_recomb vector creation, i.e. target vector subtype is either non-recombination or gateway entry.
+	 * 2. Multiple occurrences of Insert site sequence on Parent Vector sequence: Theoretically occurs for any vector subtype.
+	 * 3. Insert site sequence not found on Parent Vector sequence: Can occur at any vector subtype creation.	
+	 *
+	 * ... more error codes are defined in Python ...
+	 *
+	 * COMMON TO ALL:
+	 *
+	 * 1. Non-existent parent ID provided
+	 * 2. Creator does not have read access to parent project
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2007-04-17
+	 *
+	*/
+	function process_Error()
+	{
+		$rprint_obj = new Reagent_Output_Class();
+		$gfunc_obj = new generalFunc_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+		$gfunc_obj = new generalFunc_Class();
+
+		// August 23/07: Added error checking for other reagent types, so do need to analyze the Type argument
+		$type = $_GET["Type"];
+
+		$err_code = $_GET["Err"];
+		$subtype = $_GET["Sub"];
+
+		$cs_names = $this->rfunc_obj->get_Post_Names("Insert", "Cloning Sites");
+		
+		$vector_prefix = "INPUT_VECTOR_backinfo_";
+		$vector_postfix = "_prop";
+
+		// August 21/07, Marina: Pass current user info to CGI script
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+
+		global $cgi_path;
+		global $hostname;
+
+		// April 30/08
+		$rID = -1;
+
+		if (isset($_GET["rID"]))	// it better be set!!
+			$rID = $_GET["rID"];
+		
+		// Hidden list of restriction enzymes - one for all reagent types and subtypes
+		echo "<SELECT ID=\"enzymeList\" STYLE=\"display:none\"></SELECT>";
+
+		// Updated June 3/08
+		switch ($type)
+		{
+			case 'Vector':
+				switch ($subtype)
+				{
+					case 'nonrecomb':
+
+						// Insert and Parent Vector: Get their database IDs
+						$insert_id_tmp = $gfunc_obj->get_rid($_GET["I"]);
+						$pv_id_tmp = $gfunc_obj->get_rid($_GET["PV"]);
+
+						if (isset($_GET["R1"]) && isset($_GET["R2"]) && !isset($_GET["Err"]))
+						{
+							$fpcs = $_GET["R1"];
+							$tpcs = $_GET["R2"];
+
+							if (strpos($fpcs, "-"))
+							{
+								$fp_h1_end = strpos($fpcs, "-");
+							
+								$fp_h1 = substr($fpcs, 0, $fp_h1_end);
+								$fp_h2 = substr($fpcs, $fp_h1_end);
+							
+								$pv_fpcs = $fp_h1;
+								$insert_fpcs = $fp_h2;
+							
+								$tp_h1_end = strpos($tpcs, "-");
+							
+								$tp_h1 = substr($tpcs, 0, $tp_h1_end);
+								$tp_h2 = substr($tpcs, $tp_h1_end);
+							
+								$pv_tpcs = $tp_h1;
+								$insert_tpcs = $tp_h2;
+							}
+							else
+							{
+								$pv_fpcs = $_GET["R1"];
+								$insert_fpcs = $_GET["R1"];
+								
+								$pv_tpcs = $_GET["R2"];
+								$insert_tpcs = $_GET["R2"];
+							}
+						}
+						// Nov. 18/08: Allow cloning site values from GET if the exception is a hybridization exception - probably won't work all the time, see what happens
+						else if (isset($_GET["R1"]) && isset($_GET["R2"]) && isset($_GET["Err"]) && ($_GET["Err"] == 4))
+						{
+							$fpcs = $_GET["R1"];
+							$tpcs = $_GET["R2"];
+
+							if (strpos($fpcs, "-"))
+							{
+								$fp_h1_end = strpos($fpcs, "-");
+							
+								$fp_h1 = substr($fpcs, 0, $fp_h1_end);
+								$fp_h2 = substr($fpcs, $fp_h1_end);
+							
+								$pv_fpcs = $fp_h1;
+								$insert_fpcs = $fp_h2;
+							
+								$tp_h1_end = strpos($tpcs, "-");
+							
+								$tp_h1 = substr($tpcs, 0, $tp_h1_end);
+								$tp_h2 = substr($tpcs, $tp_h1_end);
+							
+								$pv_tpcs = $tp_h1;
+								$insert_tpcs = $tp_h2;
+							}
+							else
+							{
+								$pv_fpcs = $_GET["R1"];
+								$insert_fpcs = $_GET["R1"];
+								
+								$pv_tpcs = $_GET["R2"];
+								$insert_tpcs = $_GET["R2"];
+							}
+						}
+						else
+						{
+							// CORRECTION NOVEMBER 24, 2010
+
+// 							$property_tmp = $this->backFill($insert_id_tmp, $cs_names);
+// 						
+// 							$fpcs = $property_tmp[$_SESSION["ReagentProp_Name_ID"]["5' cloning site"]];
+// 							$tpcs = $property_tmp[$_SESSION["ReagentProp_Name_ID"]["3' cloning site"]];
+
+							$fpcs_prop_id = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["5' cloning site"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]);
+
+							$fpcs = $rfunc_obj->getPropertyValue($insert_id_tmp, $fpcs_prop_id);
+
+							$tpcs_prop_id = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["3' cloning site"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]);
+							$tpcs = $rfunc_obj->getPropertyValue($insert_id_tmp, $tpcs_prop_id);
+
+							$tmp_fpcs = $_GET["R1"];
+							$tmp_tpcs = $_GET["R2"];
+
+							if (strpos($tmp_fpcs, "-"))
+							{
+								$fp_h1_end = strpos($tmp_fpcs, "-");
+
+								$fp_h1 = substr($tmp_fpcs, 0, $fp_h1_end);
+								$fp_h2 = substr($tmp_fpcs, $fp_h1_end+1);
+							
+								$pv_fpcs = $fp_h1;
+								$insert_fpcs = $fp_h2;
+							}
+							else
+							{
+								$pv_fpcs = $_GET["R1"];
+								$insert_fpcs = $_GET["R1"];
+							}
+
+							if (strpos($tmp_tpcs, "-") > 0)
+							{
+								$tp_h1_end = strpos($tmp_tpcs, "-");
+							
+								$tp_h1 = substr($tmp_tpcs, 0, $tp_h1_end);
+								$tp_h2 = substr($tmp_tpcs, $tp_h1_end+1);
+							
+								$pv_tpcs = $tp_h1;
+								$insert_tpcs = $tp_h2;
+							}
+							else
+							{
+								$pv_tpcs = $_GET["R2"];
+								$insert_tpcs = $_GET["R2"];
+							}
+						}
+				
+						switch ($err_code)
+						{
+							case '1':
+								// Occurs when an attempt is made to generate a NR vector using an Insert with attB sites
+								// In this case, only give the options of either choosing a different Insert or starting over - Not to create hybrid sites (and the default option of proceeding - technically incorrect, but verify with Karen)
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>A sequence for the new vector could not be generated from the sequences of its parents.  The parent vector cannot be digested at one or both of the following restriction sites to generate a non-recombination vector:
+
+										<P>What would you like to do?
+
+										<P>
+										<input type="radio" id = "change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Change parent values<BR>
+										<input type="radio" ID="process_error_restart" name="warning_change_input" value="restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');" checked>Go back and choose a different type of reagent to create<BR>
+
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<TABLE cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD style="white-space:nowrap; padding-right:60px;">
+													5' Cloning Site on Insert:
+												</TD>
+
+												<TD nowrap>
+													<?php
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"10\" style=\"color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $fpcs  . "\" name=\"" . $cs_names["5' cloning site"] . "\">";
+													?>
+												</TD>
+											</TR>
+
+											<TR>
+												<TD style="white-space:nowrap; padding-right:60px;">
+													3' Cloning Site on Insert:
+												</TD>
+
+												<TD nowrap>
+													<?php
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"10\" style=\"color:brown;  background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $tpcs  . "\" name=\"" . $cs_names["3' cloning site"] . "\">";
+													?>
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							case '2':
+								// Insert sites not found on PV sequence.  Here, give the option of making a hybrid:
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+	
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>A sequence for the new vector could not be generated from the sequences of its parents.  One or both cloning sites could not be found on the sequence of the Parent Vector you provided:
+
+										<P>What would you like to do?
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values only (restriction sites will be uploaded from Insert)<BR>
+										<input type="radio" id="make_hybrid_option" name="warning_change_input" value="make_hybrid" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Keep existing parent values and change restriction sites to hybrid (or modify existing hybrid values)<BR>
+										<input type="radio" name="warning_change_input"  ID="process_error_restart" value="restart" checked onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Go back and choose different parent values or vector type<BR>
+
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="15" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="15" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<!-- Updated Nov. 19/08: Replaced text fields with dropdown lists -->
+										<TABLE cellpadding="4px" border="1" frame="none" rules="all">
+											<TH colspan="2">
+												<b>Please specify cloning sites on the Parent Vector and insert:</b><BR>
+											</TH>
+				
+											<tr>
+												<td colspan="2" style="font-size:9pt; font-weight:bold">
+													Parent Vector Cloning Sites:
+												</td>
+											</tr>
+									
+											<TR>
+												<TD style="padding-left:10px">
+													5' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<input type=\"hidden\" id=\"fpcs_val\" value=\"" . $pv_fpcs . "\"></input>";
+
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list_1\" name=\"pv_custom_five_prime\" value=\"" . $pv_fpcs . "\" disabled></select>";
+													?>
+												</TD>
+											</TR>
+									
+											<TR>
+												<TD style="padding-left:10px">
+													3' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<input type=\"hidden\" id=\"tpcs_val\" value=\"" . $pv_tpcs . "\"></input>";
+
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list_1\" name=\"pv_custom_three_prime\" value=\"" . $pv_tpcs . "\" disabled></select>";
+													?>
+												</TD>
+											</TR>
+				
+				
+											<tr>
+												<td colspan="2" style="font-size:9pt; font-weight:bold;">
+													Insert Cloning Sites:
+												</td>
+											</tr>
+									
+											<TR>
+												<TD style="padding-left:10px">
+													5' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<input type=\"hidden\" id=\"fpcs_val_insert\" value=\"" . $insert_fpcs . "\"></input>";
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list\" name=\"insert_custom_five_prime\" value=\"" . $insert_fpcs . "\" disabled=\"true\"></select>";
+													?>
+													<BR><div id="fp_warning" style="display:none; color:#FF0000">Please select a value for the 5' restriction site from the dropdown list</div>
+												</TD>
+											</TR>
+									
+											<TR>
+												<TD style="padding-left:10px">
+													3' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<input type=\"hidden\" id=\"tpcs_val_insert\" value=\"" . $insert_tpcs . "\"></input>";
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list\" value=\"" . $insert_fpcs . "\" name=\"insert_custom_three_prime\" disabled></select>";
+													?>
+													<BR><div id="tp_warning" style="display:none; color:#FF0000">Please select a value for the 3' restriction site from the dropdown list</div>
+												</TD>
+											</TR>
+				
+										</table>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+							
+							case '3':
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents(); ">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>Found multiple occurrences of one or both of the following restriction sites on the parent vector sequence:
+
+										<P>What would you like to do?
+
+										<P>
+										<input type="radio" id="make_hybrid_option" name="warning_change_input" value="change_sites" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Create hybrid restriction sites for the new vector, or change existing hybrid site values<BR>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values only (restriction sites will be uploaded from Insert)<BR>
+										<input type="radio" name="warning_change_input"  ID="process_error_restart" value="restart" onClick="enableOrDisableSites()" checked>Go back and start over<BR>
+
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<TABLE cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													<span style="padding-right:60px;" id="main_5_site_caption">5' Cloning Site on Insert:</span>
+
+													<span id="alt_5_site_caption" style="display:none">5' Cloning Site on resulting Vector:</span>
+												</TD>
+
+												<TD>
+													<?php
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"10\" id=\"fpcs\" style=\"color:brown\" readonly=\"true\" value=\"" . $fpcs  . "\" name=\"" . $cs_names["5' cloning site"] . "\"><BR>";
+
+														echo "<P id=\"fpcs_comment\" style=\"font-size:7pt; display:none\">Please enter a hyphen-delimited name of the hybrid restriction site (e.g. SalI-XhoI, order: vector_site-insert_site)</P>";
+													?>
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													<span style="padding-right:60px;" id="main_3_site_caption">3' Cloning Site on Insert:</span>
+
+													<span id="alt_3_site_caption" style="display:none">3' Cloning Site on resulting Vector:</span>
+												</TD>
+
+												<TD>
+													<?php
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" id=\"tpcs\" size=\"10\" style=\"color:brown\" readonly=\"true\" value=\"" . $tpcs  . "\" name=\"" . $cs_names["3' cloning site"] . "\"><BR>";
+
+														echo "<P id=\"tpcs_comment\" style=\"font-size:7pt; display:none\">Please enter a hyphen-delimited name of the hybrid restriction site (e.g. SalI-XhoI, order: insert_site-vector_site)</P>";
+													?>
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+							
+							case '4':
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>One or both of the following restriction sites cannot be hybridized:
+
+										<P>What would you like to do?<BR>
+
+										<P>
+										<input type="radio" id="make_hybrid_option" name="warning_change_input" value="change_sites" onClick="showHideCustomSites();">Change restriction sites<BR>
+										<input type="radio" name="warning_change_input"  ID="process_error_restart" value="restart" onClick="enableOrDisableSites()" checked>Go back and start over<BR>
+
+										<P>
+										<TABLE width="400px" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD width="150px">
+													5' Cloning Site:
+												</TD>
+
+												<TD>
+													<?php
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"10\" id=\"fpcs\" style=\"color:brown\" readonly=\"true\" value=\"" . $fpcs  . "\" name=\"" . $cs_names["5' cloning site"] . "\"><BR>";
+
+														echo "<P id=\"fpcs_comment\" style=\"font-size:7pt; display:none\">Please enter a hyphen-delimited name of the hybrid restriction site (e.g. SalI-XhoI, order: vector_site-insert_site)</P>";
+													?>
+												</TD>
+											</TR>
+
+											<TR>
+												<TD>
+													3' Cloning Site:
+												</TD>
+
+												<TD>
+													<?php
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" id=\"tpcs\" size=\"10\" style=\"color:brown\" readonly=\"true\" value=\"" . $tpcs  . "\" name=\"" . $cs_names["3' cloning site"] . "\"><BR>";
+
+														echo "<P id=\"tpcs_comment\" style=\"font-size:7pt; display:none\">Please enter a hyphen-delimited name of the hybrid restriction site (e.g. SalI-XhoI, order: insert_site-vector_site)</P>";
+													?>
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<TABLE id="nonrec_parents" width="400px" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<!-- Updated Nov. 19/08: Replaced text fields with dropdown lists -->
+										<TABLE cellpadding="4px" border="1" frame="none" rules="all" ID="customCloningSites" style="display:none;">
+											<TH colspan="2">
+												<b>Please specify cloning sites on the Parent Vector and insert:</b><BR>
+											</TH>
+				
+											<tr>
+												<td colspan="2" style="font-size:9pt; font-weight:bold">
+													Parent Vector Cloning Sites:
+												</td>
+											</tr>
+									
+											<TR>
+												<TD style="padding-left:10px">
+													5' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list_1\" name=\"pv_custom_five_prime\"></select>";
+													?>
+												</TD>
+											</TR>
+									
+											<TR>
+												<TD style="padding-left:10px">
+													3' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list_1\" name=\"pv_custom_three_prime\"></select>";
+													?>
+												</TD>
+											</TR>
+				
+				
+											<tr>
+												<td colspan="2" style="font-size:9pt; font-weight:bold;">
+													Insert Cloning Sites:
+												</td>
+											</tr>
+									
+											<TR>
+												<TD style="padding-left:10px">
+													5' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list\" name=\"insert_custom_five_prime\"></select>";
+													?>
+													<BR><div id="fp_warning" style="display:none; color:#FF0000">Please select a value for the 5' restriction site from the dropdown list</div>
+												</TD>
+											</TR>
+									
+											<TR>
+												<TD style="padding-left:10px">
+													3' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list\" name=\"insert_custom_three_prime\"></select>";
+													?>
+													<BR><div id="tp_warning" style="display:none; color:#FF0000">Please select a value for the 3' restriction site from the dropdown list</div>
+												</TD>
+											</TR>
+										</table>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							case '5':
+								// 5' site occurs after 3' on parent sequence
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents(); setCustomSites();">
+
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+									<select size="1" style="display:none" id="tpcs_list_<?php echo $subtype; ?>"></select>
+
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>The 5' Insert cloning site (<b><?php echo $_GET["R1"]; ?></b>) occurs after the 3' Insert cloning site (<b><?php echo $_GET["R2"]; ?></b>) on the parent vector sequence.
+
+										<P>What would you like to do?<BR>
+
+										<A href="pictures/five_after_three.pdf" onClick="return popup(this, 'diagram', '665', '635', 'yes')">Click here to view an illustration of the options below</A><BR>
+
+										<P><input type="radio" id="reverse_insert_option" name="warning_change_input" onClick="document.getElementById('fpcs_list_1').disabled=false; document.getElementById('tpcs_list_1').disabled=false; document.getElementById('fpcs_list').disabled=false; document.getElementById('tpcs_list').disabled=false;" value="reverse_insert">Reverse Complement the Insert sequence 
+										<P><span style="font-weight:bold; color:red; font-size:8pt; width:150px;"><u>Note</u>: When selecting this option, you must select the cloning sites of the parent vector and Insert from the lists below.  OpenFreezer will reverse complement the Insert sequence for ligation into the Vector after the user selects the sites (i.e. the 3' site on the Insert now has to be designated as the 5' Insert cloning site that will be ligated to the 5' site of the Vector.  The 3' sites must be  [...]
+
+										<P>
+										<input type="radio" id="make_hybrid_option" name="warning_change_input" value="change_sites" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Customize cloning sites by selecting different restriction enzymes or creating hybrid sites<BR>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values only (restriction sites will be uploaded from Insert)<BR>
+										<input type="radio" name="warning_change_input" ID="process_error_restart" value="restart" onClick="enableOrDisableSites()" checked>Go back and start over<BR/>
+
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+										
+										<!-- Updated Nov. 19/08: Replaced text fields with dropdown lists -->
+										<P><HR><TABLE cellpadding="4px" ID="cloning_sites"  style="display:inline; margin-top:20px; color:green;">
+											<TH colspan="2" style="padding-top:10px;">
+												Please specify cloning sites on the Parent Vector and insert:
+											</TH>
+				
+											<tr>
+												<td colspan="2" style="font-size:9pt; font-weight:bold; padding-left:10px; padding-top:15px; color:#0A0AAA;">
+													Parent Vector Cloning Sites:
+												</td>
+											</tr>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													5' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list_1\" name=\"pv_custom_five_prime\" disabled></select>";
+
+														?>
+														<BR><SPAN ID="pv_fpcs_warning" style="display:none; color:red; font-size:9pt; font-weight:bold">Please provide a specific value for the 5' cloning site.</SPAN>
+												</TD>
+											</TR>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													3' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list_1\" name=\"pv_custom_three_prime\" disabled></select>";
+													?>
+													<BR><SPAN ID="pv_tpcs_warning" style="display:none; font-size:9pt; color:red; font-weight:bold">Please provide a specific value for the 3' cloning site.</SPAN>
+												</TD>
+											</TR>
+				
+				
+											<tr>
+												<td colspan="2" style="font-size:9pt; font-weight:bold; padding-top:8px; padding-left:10px; color:#0A0AAA;">
+													Insert Cloning Sites:
+												</td>
+											</tr>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													5' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list\" name=\"insert_custom_five_prime\" value=\"\" disabled=\"true\"></select>";
+													?>
+													<BR><SPAN id="insert_fpcs_warning" style="display:none; color:#FF0000">Please select a value for the 5' restriction site from the dropdown list</SPAN>
+												</TD>
+											</TR>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													3' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list\" name=\"insert_custom_three_prime\" disabled></select>";
+													?>
+													<BR><SPAN id="insert_tpcs_warning" style="display:none; color:#FF0000">Please select a value for the 3' restriction site from the dropdown list</SPAN>
+												</TD>
+											</TR>
+				
+										</table>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go"  onClick="return verifySites({'fpcs_list_1':'pv_fpcs_warning', 'tpcs_list_1':'pv_tpcs_warning', 'fpcs_list':'insert_fpcs_warning', 'tpcs_list':'insert_tpcs_warning'});">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+							
+							case '6':
+								// One or both of the Parent IDs entered do not exist
+								// Check which one
+								$assocType = $_GET["AP"];	// this is an integer, corresponding to APropertyID in Assoc_Prop_Type_tbl
+								
+								switch ($assocType)
+								{
+									case '1':	// insert
+										?>
+										<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+
+											<!-- Pass current user ID as hidden form field -->
+											<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+											<!-- Pass type and subtype as hidden value to Python code -->
+											<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+											<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+											<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+											<FIELDSET style="width:700px; border:0; padding-left:15px;">
+												<P><SPAN style="color:red">There was a problem:</SPAN>
+												<P>The Insert ID you provided does not match an existing reagent in the system.
+
+												<P>What would you like to do?
+
+												<P>
+												<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); document.getElementById('insert').focus();">Enter a new Insert ID<BR>
+												<input type="radio" ID="process_error_restart" name="warning_change_input" value="restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>')" checked>Go back and start over<BR>
+
+												<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+													<TR>
+														<TD nowrap>
+															Parent Vector OpenFreezer ID:
+														</TD>
+
+														<TD>
+															<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+														</TD>
+
+													</TR>
+													
+													<TR>
+														<TD nowrap>
+															Insert OpenFreezer ID:
+														</TD>
+
+														<TD>
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+														</TD>
+													</TR>
+												</TABLE>
+
+												<P>
+												<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+											</FIELDSET>
+										</FORM>
+										<?php
+									break;
+									
+									case '2':	// parent vector
+										?>
+										<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+
+											<!-- Pass type and subtype as hidden value to Python code -->
+											<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+											<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+											<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+											<!-- Pass current user ID as hidden form field -->
+											<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+											<FIELDSET style="width:700px; border:0; padding-left:15px;">
+												<P><SPAN style="color:red">There was a problem:</SPAN>
+												<P>The Parent Vector ID you provided does not match an existing reagent in the system.
+
+												<P>What would you like to do?
+
+												<P>
+												<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Enter a new Parent Vector ID<BR>
+												<input type="radio" ID="process_error_restart" name="warning_change_input" value="restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>')" checked>Go back and start over<BR>
+
+												<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+													
+													<TR>
+														<TD nowrap>
+															Parent Vector OpenFreezer ID:
+														</TD>
+
+														<TD>
+															<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+														</TD>
+
+													</TR>
+													
+													<TR>
+														<TD nowrap>
+															Insert OpenFreezer ID:
+														</TD>
+
+														<TD>
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+														</TD>
+													</TR>
+												</TABLE>
+
+												<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+											</FIELDSET>
+										</FORM>
+										<?php
+									break;
+									
+									case '7':	// parent insert vector
+									
+									break;
+									
+									case '8':	// parent cell line vector
+									
+									break;
+									
+									case '9':	// parent cell line
+									
+									break;
+									
+									default:
+									break;	
+								}
+							break;
+							
+							case '10':
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+									<!-- Pass user info to Python as hidden form value too - Aug 21/07 -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+						
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P style="color:brown;">You are not authorized to use <B><?php echo strtoupper($_GET["PV"]); ?></B> as the parent vector, since <U>you do not have read access to its project</U>.<BR>
+
+										Please contact the project owner to obtain permission or select a different parent vector for your reagent.<BR>
+
+										<input type="radio" name="warning_change_input"  ID="process_error_restart" value="restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');" checked>Start over<BR>
+										<input type="radio" id = "change_parents_warning_option" name="warning_change_input" value="change_parents"; onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Change parent values<BR>
+
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+
+							break;
+
+							case '11':
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+									<!-- Pass user info to Python as hidden form value too - Aug 21/07 -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+						
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P style="color:brown;">You are not authorized to use <B><?php echo strtoupper($_GET["I"]); ?></B> as the parent Insert, since <U>you do not have read access to its project</U>.<BR>
+
+										Please contact the project owner to obtain permission or select a different parent Insert for your reagent.<BR>
+
+										<input type="radio" name="warning_change_input" ID="process_error_restart" value="restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');" checked>Start over<BR>
+										<input type="radio" id = "change_parents_warning_option" name="warning_change_input" value="change_parents"; onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Change parent values<BR>
+
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">   
+									</FIELDSET>
+								</FORM>
+								<?php
+
+							break;
+
+							// May 15/08
+							case '13':
+								// Insert does not contain cloning sites
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>A sequence for the new vector could not be generated from the sequences of its parents.  Either the Insert sequence does not contain one or both of the following cloning sites, or, if 5' and 3' site values are identical, only contains the enzyme at one end:
+
+										<P><?php
+											$tmp_r1 = $_GET["R1"];
+											
+											if (strlen($tmp_r1) > 0)
+											{
+												if (strpos($tmp_r1, "-") > 0)
+												{
+													// hybrid 5', Insert site is after the dash
+													$tmp_insert_r1 = substr($tmp_r1, strpos($tmp_r1, "-")+1);
+												}
+												else
+												{
+													$tmp_insert_r1 = $tmp_r1;
+												}
+
+												echo "<u>5' site</u>: <b>" . $tmp_insert_r1 . "</b><BR>";
+											}
+										?>
+										<P><?php
+											$tmp_r2 = $_GET["R2"];
+											
+											if (strlen($tmp_r2) > 0)
+											{
+												if (strpos($tmp_r2, "-") > 0)
+												{
+													// hybrid 3', Insert site is BEFORE the dash
+													$tmp_insert_r2 = substr($tmp_r2, 0, strpos($tmp_r2, "-"));
+												}
+												else
+												{
+													$tmp_insert_r2 = $tmp_r2;
+												}
+
+												echo "<u>3' site</u>: <b>" . $tmp_insert_r2 . "</b><BR>";
+											}
+										?>
+										<P>What would you like to do?
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values (cloning sites will be loaded from the Insert)<BR>
+
+										<input type="radio" id="make_hybrid_option" name="warning_change_input" value="make_hybrid" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Keep existing parent values and change restriction sites to hybrid (or modify existing hybrid values)<BR/>
+
+										<input type="radio" name="warning_change_input" ID="process_error_restart" value="restart" checked onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Go back and choose different parent values or vector type<BR/>
+										
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<!-- Updated Nov. 19/08: Replaced text fields with dropdown lists -->
+										<TABLE cellpadding="4px" border="1" frame="none" rules="all">
+											<TH colspan="2">
+												<b>Please specify cloning sites on the Parent Vector and insert:</b><BR>
+											</TH>
+				
+											<tr>
+												<td colspan="2" style="font-size:9pt; font-weight:bold">
+													Parent Vector Cloning Sites:
+												</td>
+											</tr>
+									
+											<TR>
+												<TD style="padding-left:10px">
+													5' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list_1\" name=\"pv_custom_five_prime\" disabled></select>";
+													?>
+												</TD>
+											</TR>
+									
+											<TR>
+												<TD style="padding-left:10px">
+													3' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list_1\" name=\"pv_custom_three_prime\" disabled></select>";
+													?>
+												</TD>
+											</TR>
+				
+				
+											<tr>
+												<td colspan="2" style="font-size:9pt; font-weight:bold;">
+													Insert Cloning Sites:
+												</td>
+											</tr>
+									
+											<TR>
+												<TD style="padding-left:10px">
+													5' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list\" name=\"insert_custom_five_prime\" disabled=\"true\"></select>";
+													?>
+													<BR><div id="fp_warning" style="display:none; color:#FF0000">Please select a value for the 5' restriction site from the dropdown list</div>
+												</TD>
+											</TR>
+									
+											<TR>
+												<TD style="padding-left:10px">
+													3' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list\" disabled name=\"insert_custom_three_prime\"></select>";
+													?>
+													<BR><div id="tp_warning" style="display:none; color:#FF0000">Please select a value for the 3' restriction site from the dropdown list</div>
+												</TD>
+											</TR>
+				
+										</table>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							// May 30/08
+							case '14':
+								// Insert cloning site values don't match sequence at site positions
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+						
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>A sequence for the new vector could not be generated from the sequences of its parents.<BR>
+
+										<P>One or both cloning sites does not match an actual enzyme sequence at the following positions on <a href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["I"]); ?>" target="blank"><?php echo $_GET["I"]; ?></a>:
+
+										<P>What would you like to do?
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values<BR>
+										<input type="radio" name="warning_change_input" ID="process_error_restart" value="restart" checked onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Go back and choose different parent values or vector type<BR>
+
+										<TABLE width="100%" id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD style="width:250px;">
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD style="width:180px;">
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+										<BR>
+
+										<TABLE width="100%" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD style="width:250px;">
+													<span id="main_5_site_caption">5' Cloning Site on Insert:</span>
+
+													<span id="alt_5_site_caption" style="display:none">5' Cloning Site on resulting Vector:</span>
+												</TD>
+
+												<TD style="padding-left:10px; white-space:nowrap;">
+													<?php
+														// May 30/08: DO **NOT** give these inputs a name!!!  Don't call them "sites" - Python  will treat them as form input and take the wrong action!!!!!!  Sites here are just for reference; the only input CGI needs here are parents!!!
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"15\" id=\"fpcs\" style=\"color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $_GET["R1"]  . "\">";
+
+														$pStart = $rfunc_obj->getStartPos($gfunc_obj->get_rid($_GET["I"]), "5' cloning site", $_SESSION["ReagentProp_Name_ID"]["5' cloning site"]);
+
+														echo "Start: <INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" style=\"margin-left:5px; color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $pStart  . "\">";
+
+														$pEnd = $rfunc_obj->getEndPos($gfunc_obj->get_rid($_GET["I"]), "5' cloning site", $_SESSION["ReagentProp_Name_ID"]["5' cloning site"]);
+
+														echo "End:<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" style=\"margin-left:5px; color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $pEnd . "\">";
+
+														echo "<BR>";
+
+														echo "<P id=\"fpcs_comment\" style=\"font-size:7pt; display:none\">Please enter a hyphen-delimited name of the hybrid restriction site (e.g. SalI-XhoI, order: vector_site-insert_site)</P>";
+													?>
+												</TD>
+											</TR>
+
+											<TR>
+												<TD  style="width:250px;">
+													<span id="main_3_site_caption">3' Cloning Site on Insert:</span>
+
+													<span id="alt_3_site_caption" style="display:none">3' Cloning Site on resulting Vector:</span>
+												</TD>
+
+												<TD style="padding-left:10px;">
+												<?php
+													// May 30/08: DO **NOT** give these inputs a name!!!  Don't call them "sites" - Python  will treat them as form input and take the wrong action!!!!!!  Sites are just for reference here; the only input CGI needs here are parents!!!
+													echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" id=\"tpcs\" size=\"15\" style=\"color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $_GET["R2"]  . "\">";
+
+													$pStart = $rfunc_obj->getStartPos($gfunc_obj->get_rid($_GET["I"]), "3' cloning site", $_SESSION["ReagentProp_Name_ID"]["3' cloning site"]);
+
+													echo "Start: <INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" style=\"margin-left:5px; color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $pStart  . "\">";
+
+													$pEnd = $rfunc_obj->getEndPos($gfunc_obj->get_rid($_GET["I"]), "3' cloning site", $_SESSION["ReagentProp_Name_ID"]["3' cloning site"]);
+
+													echo "End:<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" style=\"margin-left:5px; color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $pEnd . "\">";
+
+													echo "<BR>";
+
+													echo "<P id=\"tpcs_comment\" style=\"font-size:7pt; display:none\">Please enter a hyphen-delimited name of the hybrid restriction site (e.g. SalI-XhoI, order: insert_site-vector_site)</P>";
+												?>
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							// Added November 24, 2010: Empty Insert cloning sites (e.g. I789 - DNA fragment, no sequence, no sites, mutagenesis)
+							case '23':
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+						
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>Cloning sites are not defined on the parent Insert.<BR>
+
+										<P>Please verify the information on cloning sites recorded for <a href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["I"]); ?>" target="blank"><?php echo $_GET["I"]; ?></a>:
+
+										<P>What would you like to do?
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values<BR>
+										<input type="radio" name="warning_change_input" ID="process_error_restart" value="restart" checked onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Go back and choose different parent values or vector type<BR><BR>
+
+										<TABLE width="350px" id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD style="white-space:nowrap;">
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD style="white-space:nowrap;">
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+										<BR>
+
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							// Dec. 14/09
+							case '24':
+								// Empty parent Vector sequence
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+						
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>A sequence for the new vector could not be generated from the sequences of its parents.<BR>
+
+										<P>The sequence of the parent Vector <a href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["PV"]); ?>" target="blank"><?php echo $_GET["PV"]; ?></a> is empty.
+
+										<P>What would you like to do?
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values<BR>
+										<input type="radio" name="warning_change_input" ID="process_error_restart" value="restart" checked onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Cancel creation and start over<BR>
+										
+										<TABLE width="100%" id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD style="width:250px;">
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD style="width:180px;">
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+										<BR>
+										
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">   
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							// Dec. 14/09
+							case '25':
+								// Empty parent Insert sequence
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+						
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>A sequence for the new vector could not be generated from the sequences of its parents.<BR>
+
+										<P>The sequence of the parent Insert <a href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["I"]); ?>" target="blank"><?php echo $_GET["I"]; ?></a> is empty.
+
+										<P>What would you like to do?
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values<BR>
+										<input type="radio" name="warning_change_input" ID="process_error_restart" value="restart" checked onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Cancel creation and start over<BR>
+
+										<TABLE width="100%" id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD style="width:250px;">
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD style="width:180px;">
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+										<BR>
+										
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">   
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+
+							case '27':	// March 5, 2010
+								// Incompatible overhangs
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents(); setCustomSites();">
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+									<select size="1" style="display:none" id="tpcs_list_<?php echo $subtype; ?>"></select>
+
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>The 5' overhangs of Parent Vector and Insert cloning sites are incompatible with each other.
+
+										<P>What would you like to do?<BR>
+
+										<input type="radio" id="make_hybrid_option" name="warning_change_input" value="change_sites" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Customize cloning sites by selecting different restriction enzymes or creating hybrid sites<BR>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values only (restriction sites will be uploaded from Insert)<BR>
+										<input type="radio" name="warning_change_input" ID="process_error_restart" value="restart" onClick="enableOrDisableSites()" checked>Go back and start over<BR>
+										
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+										
+										<!-- Updated Nov. 19/08: Replaced text fields with dropdown lists -->
+										<P><HR><TABLE cellpadding="4px" ID="cloning_sites"  style="display:inline; margin-top:20px; color:green;">
+											<TH colspan="2" style="padding-top:10px;">
+												Please specify cloning sites on the Parent Vector and insert:
+											</TH>
+				
+											<tr>
+												<td colspan="2" style="font-size:9pt; font-weight:bold; padding-left:10px; padding-top:15px; color:#0A0AAA;">
+													Parent Vector Cloning Sites:
+												</td>
+											</tr>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													5' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list_1\" name=\"pv_custom_five_prime\" disabled></select>";
+													?>
+													<BR><SPAN ID="pv_fpcs_warning" style="display:none; color:red; font-size:9pt; font-weight:bold">Please provide a specific value for the 5' cloning site.</SPAN>
+												</TD>
+											</TR>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													3' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list_1\" name=\"pv_custom_three_prime\" disabled></select>";
+													?>
+													<BR><SPAN ID="pv_tpcs_warning" style="display:none; font-size:9pt; color:red; font-weight:bold">Please provide a specific value for the 3' cloning site.</SPAN>
+												</TD>
+											</TR>
+				
+											<tr>
+												<td colspan="2" style="font-size:9pt; font-weight:bold; padding-top:8px; padding-left:10px; color:#0A0AAA;">
+													Insert Cloning Sites:
+												</td>
+											</tr>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													5' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list\" name=\"insert_custom_five_prime\" value=\"\" disabled=\"true\"></select>";
+													?>
+													<BR><SPAN id="insert_fpcs_warning" style="display:none; color:#FF0000">Please select a value for the 5' restriction site from the dropdown list</SPAN>
+												</TD>
+											</TR>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													3' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list\" name=\"insert_custom_three_prime\" disabled></select>";
+													?>
+													<BR><SPAN id="insert_tpcs_warning" style="display:none; color:#FF0000">Please select a value for the 3' restriction site from the dropdown list</SPAN>
+												</TD>
+											</TR>
+										</table>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go"  onClick="return verifySites({'fpcs_list_1':'pv_fpcs_warning', 'tpcs_list_1':'pv_tpcs_warning', 'fpcs_list':'insert_fpcs_warning', 'tpcs_list':'insert_tpcs_warning'});">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							case '28':	// March 5, 2010
+								// Incompatible overhangs
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents(); setCustomSites();">
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+									<select size="1" style="display:none" id="tpcs_list_<?php echo $subtype; ?>"></select>
+
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>The 3' overhangs of Parent Vector and Insert cloning sites are incompatible with each other.
+
+										<P>What would you like to do?<BR>
+
+										<input type="radio" id="make_hybrid_option" name="warning_change_input" value="change_sites" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Customize cloning sites by selecting different restriction enzymes or creating hybrid sites<BR>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values only (restriction sites will be uploaded from Insert)<BR>
+										<input type="radio" name="warning_change_input" ID="process_error_restart" value="restart" onClick="enableOrDisableSites()" checked>Go back and start over<BR/>
+
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+										
+										<!-- Updated Nov. 19/08: Replaced text fields with dropdown lists -->
+										<P><HR><TABLE cellpadding="4px" ID="cloning_sites"  style="display:inline; margin-top:20px; color:green;">
+											<TH colspan="2" style="padding-top:10px;">
+												Please specify cloning sites on the Parent Vector and insert:
+											</TH>
+				
+											<tr>
+												<td colspan="2" style="font-size:9pt; font-weight:bold; padding-left:10px; padding-top:15px; color:#0A0AAA;">
+													Parent Vector Cloning Sites:
+												</td>
+											</tr>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													5' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list_1\" name=\"pv_custom_five_prime\" disabled></select>";
+													?>
+													<BR><SPAN ID="pv_fpcs_warning" style="display:none; color:red; font-size:9pt; font-weight:bold">Please provide a specific value for the 5' cloning site.</SPAN>
+												</TD>
+											</TR>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													3' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list_1\" name=\"pv_custom_three_prime\" disabled></select>";
+													?>
+													<BR><SPAN ID="pv_tpcs_warning" style="display:none; font-size:9pt; color:red; font-weight:bold">Please provide a specific value for the 3' cloning site.</SPAN>
+												</TD>
+											</TR>
+				
+											<tr>
+												<td colspan="2" style="font-size:9pt; font-weight:bold; padding-top:8px; padding-left:10px; color:#0A0AAA;">
+													Insert Cloning Sites:
+												</td>
+											</tr>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													5' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list\" name=\"insert_custom_five_prime\" value=\"\" disabled=\"true\"></select>";
+													?>
+													<BR><SPAN id="insert_fpcs_warning" style="display:none; color:#FF0000">Please select a value for the 5' restriction site from the dropdown list</SPAN>
+												</TD>
+											</TR>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													3' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list\" name=\"insert_custom_three_prime\" disabled></select>";
+													?>
+													<BR><SPAN id="insert_tpcs_warning" style="display:none; color:#FF0000">Please select a value for the 3' restriction site from the dropdown list</SPAN>
+												</TD>
+											</TR>
+				
+										</table>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go"  onClick="return verifySites({'fpcs_list_1':'pv_fpcs_warning', 'tpcs_list_1':'pv_tpcs_warning', 'fpcs_list':'insert_fpcs_warning', 'tpcs_list':'insert_tpcs_warning'});">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							case '29':
+
+								if (strpos($_GET["R1"], "-") > 0)
+								{
+									$fp_sites_tok = split("-", $_GET["R1"]);
+									$tp_sites_tok = split("-", $_GET["R2"]);
+
+									$insert_fpcs = $fp_sites_tok[1];
+									$insert_tpcs = $tp_sites_tok[0];
+								}
+								else
+								{
+									$insert_fpcs = $_GET["R1"];
+									$insert_tpcs = $_GET["R2"];
+								}
+
+								// 5' site occurs after 3' on parent INSERT sequence
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents(); setCustomSites();">
+
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+									<select size="1" style="display:none" id="tpcs_list_<?php echo $subtype; ?>"></select>
+
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>The 5' Insert cloning site provided (<b><?php echo $insert_fpcs; ?></b>) occurs after the 3' Insert cloning site provided (<b><?php echo $insert_tpcs; ?></b>) on the Insert sequence.
+
+										<P>What would you like to do?
+
+										<A href="pictures/five_after_three.pdf" onClick="return popup(this, 'diagram', '665', '635', 'yes')">Click here to view an illustration of the options below</A><BR>
+
+										<P><input type="radio" id="reverse_insert_option" name="warning_change_input" onClick="document.getElementById('fpcs_list_1').disabled=false; document.getElementById('tpcs_list_1').disabled=false; document.getElementById('fpcs_list').disabled=false; document.getElementById('tpcs_list').disabled=false;" value="reverse_insert">Reverse Complement the Insert sequence 
+										<P><span style="font-weight:bold; color:red; font-size:8pt; width:180px;"><u>Note</u>: When selecting this option, you must select the cloning sites of the parent vector and Insert from the lists below.  OpenFreezer will reverse complement the Insert sequence for ligation into the Vector after the user selects the sites (i.e. the 3' site on the Insert now has to be designated as the 5' Insert cloning site that will be ligated to the 5' site of the Vector.  The 3' sites must be  [...]
+
+										<P>
+										<input type="radio" id="make_hybrid_option" name="warning_change_input" value="change_sites" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Customize cloning sites by selecting different restriction enzymes or creating hybrid sites<BR>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values only (restriction sites will be uploaded from Insert)<BR>
+										<input type="radio" name="warning_change_input" ID="process_error_restart" value="restart" onClick="enableOrDisableSites()" checked>Go back and start over<BR>
+
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+										
+										<!-- Updated Nov. 19/08: Replaced text fields with dropdown lists -->
+										<P><HR><TABLE cellpadding="4px" ID="cloning_sites"  style="display:inline; margin-top:20px; color:green;">
+											<TH colspan="2" style="padding-top:10px;">
+												Please specify cloning sites on the Parent Vector and insert:
+											</TH>
+				
+											<tr>
+												<td colspan="2" style="font-size:9pt; font-weight:bold; padding-left:10px; padding-top:15px; color:#0A0AAA;">
+													Parent Vector Cloning Sites:
+												</td>
+											</tr>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													5' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list_1\" name=\"pv_custom_five_prime\" disabled></select>";
+													?>
+													<BR><SPAN ID="pv_fpcs_warning" style="display:none; color:red; font-size:9pt; font-weight:bold">Please provide a specific value for the 5' cloning site.</SPAN>
+												</TD>
+											</TR>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													3' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list_1\" name=\"pv_custom_three_prime\" disabled></select>";
+													?>
+													<BR><SPAN ID="pv_tpcs_warning" style="display:none; font-size:9pt; color:red; font-weight:bold">Please provide a specific value for the 3' cloning site.</SPAN>
+												</TD>
+											</TR>
+				
+											<tr>
+												<td colspan="2" style="font-size:9pt; font-weight:bold; padding-top:8px; padding-left:10px; color:#0A0AAA;">
+													Insert Cloning Sites:
+												</td>
+											</tr>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													5' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list\" name=\"insert_custom_five_prime\" value=\"\" disabled=\"true\"></select>";
+													?>
+													<BR><SPAN id="insert_fpcs_warning" style="display:none; color:#FF0000">Please select a value for the 5' restriction site from the dropdown list</SPAN>
+												</TD>
+											</TR>
+									
+											<TR>
+												<TD style="padding-left:15px">
+													3' Cloning Site:
+												</TD>
+									
+												<TD>
+													<?php
+														echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list\" name=\"insert_custom_three_prime\" disabled></select>";
+													?>
+													<BR><SPAN id="insert_tpcs_warning" style="display:none; color:#FF0000">Please select a value for the 3' restriction site from the dropdown list</SPAN>
+												</TD>
+											</TR>
+										</table>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go"  onClick="return verifySites({'fpcs_list_1':'pv_fpcs_warning', 'tpcs_list_1':'pv_tpcs_warning', 'fpcs_list':'insert_fpcs_warning', 'tpcs_list':'insert_tpcs_warning'});">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+							
+
+							default:
+								return false;
+							break;
+						}
+					break;
+
+					case 'recomb':
+						$pv_id_tmp = $gfunc_obj->get_rid($_GET["PV"]);
+						$ipv_id_tmp = $gfunc_obj->get_rid($_GET["IPV"]);
+
+						switch ($err_code)
+						{
+							// July 4/08
+							case '2':
+								// LoxP sites not found on PV sequence.
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+									
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P style="color:#FF0000; font-weight:bold;">Error: Cannot construct sequence<BR>
+
+										<P style="color:#FF0000">The <b>LoxP</b> restriction site could not be found on the sequence of the Creator Acceptor Vector you provided:<BR>
+
+										<P>What would you like to do?<BR>
+
+										<P><input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Change parent values<BR>
+
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" checked>Go back and select another vector type<BR>
+										
+										<TABLE id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Creator Acceptor Vector ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+											
+											<TR>
+												<TD nowrap>
+													Creator Donor Vector ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["IPV"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+
+							case '3':
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents(); ">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>Found multiple occurrences of LoxP site on the sequence of the Creator Acceptor Vector:
+
+										<P>What would you like to do?
+
+										<P><input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Change parent values<BR>
+										<input type="radio" name="warning_change_input"  ID="process_error_restart" value="restart" checked>Go back and start over<BR>
+
+										<TABLE id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Creator Acceptor Vector ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+
+											</TR>
+											
+											<TR>
+												<TD nowrap>
+													Creator Donor Vector ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["IPV"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							// May 30/08: Capture error where a non-existent parent ID is passed
+							case '6':
+								// One or both of the Parent IDs entered do not exist
+								// Check which one
+								$assocType = $_GET["AP"];	// this is an integer, corresponding to APropertyID in Assoc_Prop_Type_tbl
+								
+								switch ($assocType)
+								{
+									case '2':	// parent vector
+										?>
+										<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+
+											<!-- Pass type and subtype as hidden value to Python code -->
+											<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+											<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+											<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+											<!-- Pass current user ID as hidden form field -->
+											<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+											<FIELDSET style="width:100%; border:0; padding-left:15px;">
+												<P><SPAN style="color:red">There was a problem:</SPAN>
+												<P>The ID of the Creator Acceptor Vector provided does not match an existing reagent in the system.
+
+												<P>What would you like to do?
+
+												<P>
+												<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Enter a new Creator Acceptor Vector ID<BR>
+												<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>')" checked>Go back and start over<BR>
+
+												<TABLE id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+													
+													<TR>
+														<TD nowrap>
+															Creator Acceptor Vector ID:
+														</TD>
+
+														<TD>
+															<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+														</TD>
+
+													</TR>
+													
+													<TR>
+														<TD nowrap>
+															Creator Donor  Vector ID:
+														</TD>
+
+														<TD>
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["IPV"]; ?>">
+														</TD>
+													</TR>
+												</TABLE>
+
+												<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+											</FIELDSET>
+										</FORM>
+										<?php
+									break;
+									
+									case '7':	// parent insert vector
+										?>
+										<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+
+											<!-- Pass type and subtype as hidden value to Python code -->
+											<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+											<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+											<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+											<!-- Pass current user ID as hidden form field -->
+											<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+											<FIELDSET style="width:100%; border:0; padding-left:15px;">
+												<P><SPAN style="color:red;">An error occurred during sequence construction:</SPAN>
+
+												<P style="color:red; font-weight:bold">Invalid Creator Donor Vector:
+
+												<P>Either <SPAN style="color:#FF0000;"><?php echo strtoupper($_GET["IPV"]); ?></span> does not match an existing reagent in the system or a valid Insert for it could not be found.</P>
+
+												<P>What would you like to do?</P>
+
+												<P>
+												<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Enter a new Vector ID<BR/>
+
+												<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>')" checked>Go back and start over<BR/>
+												</P>
+
+												<TABLE id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+													
+													<TR>
+														<TD nowrap>
+															Creator Acceptor Vector ID:
+														</TD>
+
+														<TD>
+															<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+														</TD>
+
+													</TR>
+													
+													<TR>
+														<TD nowrap>
+															Creator Donor Vector ID:
+														</TD>
+
+														<TD>
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["IPV"]; ?>">
+														</TD>
+													</TR>
+												</TABLE>
+
+												<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+											</FIELDSET>
+										</FORM>
+										<?php
+									break;
+									
+									default:
+									break;
+								}
+							break;
+
+							case '10':
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+									<!-- Pass user info to Python as hidden form value too - Aug 21/07 -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+						
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+
+										<P style="color:brown;">You are not authorized to use <B><?php echo strtoupper($_GET["PV"]); ?></B> as the Creator Acceptor Vector, since <U>you do not have read access to its project</U>.<BR>
+										Please contact the project owner to obtain permission or select a different parent vector for your reagent.<BR>
+
+										<input type="radio" name="warning_change_input"  ID="process_error_restart" value="restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');" checked>Start over<BR>
+										<input type="radio" id = "change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableRecombParents();">Change parent values<BR>
+
+										<TABLE id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Creator Acceptor Vector ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Creator Donor Vector ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo strtoupper($_GET["IPV"]); ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							case '12':
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+			
+									<!-- Pass user info to Python as hidden form value too - Aug 21/07 -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+						
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:#FF0000;">There was a problem:</SPAN>
+
+										<SPAN style="color:brown;">You are not authorized to use <B><?php echo strtoupper($_GET["IPV"]); ?></B> as the Creator Donor Vector, since <U>you do not have read access to its project</U>.<BR>
+
+										Please contact the project owner to obtain permission or select a different Parent Insert Vector for your reagent.<BR>
+
+										<input type="radio" name="warning_change_input"  ID="process_error_restart" value="restart" onClick="enableOrDisableRecombParents();" checked>Start over<BR>
+										<input type="radio" id = "change_parents_warning_option" name="warning_change_input" value="change_parents"; onClick="enableOrDisableRecombParents();">Change parent values<BR>
+
+										</SPAN>
+
+										<TABLE id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Creator Acceptor Vector ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Creator Donor Vector ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["IPV"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							// June 1/08
+							case '14':
+								// June 4, 2010: Insert for recombination cloning?  will produce an error with our latest change! investigate where this is thrown
+
+								// Insert cloning site values don't match sequence at site positions
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+						
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>A sequence for the new vector could not be generated from the sequences of its parents.<BR>
+
+										<P>One or both cloning sites does not match an actual enzyme sequence at the following positions on <a href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["I"]); ?>" target="blank"><?php echo $_GET["I"]; ?></a>:<BR>
+
+										<P>What would you like to do?<BR>
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values<BR>
+										<input type="radio" name="warning_change_input"  ID="process_error_restart" value="restart" checked onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Go back and choose different parent values or vector type<BR>
+
+										<TABLE width="100%" id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD style="width:250px;">
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD style="width:250px;">
+													Insert Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["IPV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD style="width:180px;">
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+										<BR>
+
+										<TABLE width="650px" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD style="width:250px;">
+													<span id="main_5_site_caption">5' Cloning Site on Insert:</span>
+
+													<span id="alt_5_site_caption" style="display:none">5' Cloning Site on resulting Vector:</span>
+												</TD>
+
+												<TD style="padding-left:10px; white-space:nowrap;">
+													<?php
+														// May 30/08: DO **NOT** give these inputs a name!!!  Don't call them "sites" - Python  will treat them as form input and take the wrong action!!!!!!  Sites here are just for reference; the only input CGI needs here are parents!!!
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"15\" id=\"fpcs\" style=\"color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $_GET["R1"]  . "\">";
+
+														$pStart = $rfunc_obj->getStartPos($gfunc_obj->get_rid($_GET["I"]), "5' cloning site", $_SESSION["ReagentProp_Name_ID"]["5' cloning site"]);
+
+														echo "Start: <INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" style=\"margin-left:5px; color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $pStart  . "\">";
+
+														$pEnd = $rfunc_obj->getEndPos($gfunc_obj->get_rid($_GET["I"]), "5' cloning site", $_SESSION["ReagentProp_Name_ID"]["5' cloning site"]);
+
+														echo "End:<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" style=\"margin-left:5px; color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $pEnd . "\">";
+
+														echo "<BR>";
+
+														echo "<P id=\"fpcs_comment\" style=\"font-size:7pt; display:none\">Please enter a hyphen-delimited name of the hybrid restriction site (e.g. SalI-XhoI, order: vector_site-insert_site)</P>";
+													?>
+												</TD>
+											</TR>
+
+											<TR>
+												<TD  style="width:250px;">
+													<span id="main_3_site_caption">3' Cloning Site on Insert:</span>
+
+													<span id="alt_3_site_caption" style="display:none">3' Cloning Site on resulting Vector:</span>
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<?php
+														// May 30/08: DO **NOT** give these inputs a name!!!  Don't call them "sites" - Python  will treat them as form input and take the wrong action!!!!!!  Sites are just for reference here; the only input CGI needs here are parents!!!
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" id=\"tpcs\" size=\"15\" style=\"color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $_GET["R2"]  . "\">";
+
+														$pStart = $rfunc_obj->getStartPos($gfunc_obj->get_rid($_GET["I"]), "3' cloning site", $_SESSION["ReagentProp_Name_ID"]["3' cloning site"]);
+
+														echo "Start: <INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" style=\"margin-left:5px; color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $pStart  . "\">";
+
+														$pEnd = $rfunc_obj->getEndPos($gfunc_obj->get_rid($_GET["I"]), "3' cloning site", $_SESSION["ReagentProp_Name_ID"]["3' cloning site"]);
+
+														echo "End:<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" style=\"margin-left:5px; color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $pEnd . "\">";
+
+														echo "<BR>";
+
+														echo "<P id=\"tpcs_comment\" style=\"font-size:7pt; display:none\">Please enter a hyphen-delimited name of the hybrid restriction site (e.g. SalI-XhoI, order: insert_site-vector_site)</P>";
+													?>
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							// June 2/08
+							case '15':
+								// LoxP not found on DONOR (IPV) sequence
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+									
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+
+										<P><SPAN style="color:#FF0000;"><b>LoxP</b> cloning site could not be found on the sequence of  <a href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["IPV"]); ?>"><?php echo strtoupper($_GET["IPV"]); ?></a></SPAN>
+
+										<P>What would you like to do?<BR>
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Change parent values<BR>
+										<input type="radio" ID="process_error_restart" name="warning_change_input" value="restart" checked>Go back and select another vector type<BR>
+
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Creator Acceptor Vector ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Creator Donor Vector ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo strtoupper($_GET["IPV"]); ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							// June 3/08
+							case '16':
+								// LoxP site only found once on donor sequence
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:red;">An error occurred during sequence construction:</SPAN>
+
+										<P><SPAN style="color:red; font-weight:bold;">Found only one occurrence of LoxP cloning site on the sequence of donor vector <a style="font-weight:normal;" href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["IPV"]); ?>"><?php echo strtoupper($_GET["IPV"]); ?></a></SPAN>
+
+										<P>What would you like to do?</P>
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Enter a new Donor Vector ID<BR/>
+
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>')" checked>Go back and start over<BR/>
+										</P>
+
+										<TABLE id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											
+											<TR>
+												<TD nowrap>
+													Creator Acceptor Vector ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+
+											</TR>
+											
+											<TR>
+												<TD nowrap>
+													Creator Donor Vector ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["IPV"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							// June 3/08
+							case '18':
+								// One or both LoxP sites in resulting recomb. vector sequence got destroyed as a result of user modification (between steps 2 and 3 - previewSequence and previewFeatures)
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:red; font-weight:bold;">Error: Cannot find LoxP site on resulting sequence!</SPAN>
+
+										<P>Please go back and correct the sequence before proceeding
+
+										<P><INPUT TYPE="BUTTON" style="margin-left:10px;" onClick="document.getElementById('navigate_away').value=0; redirect('<?php echo $hostname . "Reagent.php?View=2&Step=1&Type=Vector&Sub=" . $subtype . "&PV=" . $gfunc_obj->get_rid($_GET["PV"]) . "&IPV=" . $gfunc_obj->get_rid($_GET["IPV"]) . "&rID=" . $rID . "&Seq=" . $_GET["Seq"]; ?>');" VALUE="Go back and edit sequence"></INPUT>
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							// June 2/08
+							case '19':
+								// Raised when one of the vector parents provided is not of suitable type 
+								// Introduced mainly to prevent errors where recomb. vectors are used as donors - i.e. IPV in recomb. vector creation must have ATypeID 1
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:red;">An error occurred during sequence construction:</SPAN>
+
+										<P><a href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["IPV"]); ?>"><?php echo strtoupper($_GET["IPV"]); ?></a>  cannot be properly recombined to produce a Creator Expression Vector.  Please verify your Donor Vector input.</SPAN>
+
+										<P>What would you like to do?</P>
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Enter a new Donor Vector ID<BR/>
+
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>')" checked>Go back and start over<BR/>
+										</P>
+
+										<TABLE id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											
+											<TR>
+												<TD nowrap>
+													Creator Acceptor Vector ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+
+											</TR>
+											
+											<TR>
+												<TD nowrap>
+													Creator Donor Vector ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["IPV"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+						}
+					break;
+
+					case 'gateway_entry':
+						// Insert and Parent Vector: Get their database IDs
+						$insert_id_tmp = $gfunc_obj->get_rid($_GET["I"]);
+						$pv_id_tmp = $gfunc_obj->get_rid($_GET["PV"]);
+
+						switch ($err_code)
+						{
+							// April 10/08
+							case '2':
+								// Insert sites not found on PV sequence.  Here, give the option of making a hybrid:
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+						
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>A sequence for the new vector could not be generated from the sequences of its parents.  One or both of the following restriction sites could not be found on the sequence of the Parent Vector you provided:<BR>
+
+										<P>What would you like to do?<BR>
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values only (restriction sites will be uploaded from Insert)<BR>
+										<input type="radio" id="make_hybrid_option" name="warning_change_input" value="make_hybrid" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Keep existing parent values and change restriction sites to hybrid (or modify existing hybrid values)<BR>
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" checked onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Go back and choose different parent values or vector type<BR>
+
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<TABLE cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													<span style="padding-right:60px;" id="main_5_site_caption">5' Cloning Site on Insert:</span>
+
+													<span id="alt_5_site_caption" style="display:none">5' Cloning Site on resulting Vector:</span>
+												</TD>
+
+												<TD>
+													<?php
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"10\" id=\"fpcs\" style=\"color:brown\" readonly=\"true\" value=\"" . $_GET["R1"]  . "\" name=\"" . $_SESSION["ReagentProp_Name_Alias"]["5' cloning site"] . "\"><BR>";
+
+														echo "<P id=\"fpcs_comment\" style=\"font-size:7pt; display:none\">Please enter a hyphen-delimited name of the hybrid restriction site (e.g. SalI-XhoI, order: vector_site-insert_site)</P>";
+													?>
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													<span style="padding-right:60px;" id="main_3_site_caption">3' Cloning Site on Insert:</span>
+
+													<span id="alt_3_site_caption" style="display:none">3' Cloning Site on resulting Vector:</span>
+												</TD>
+
+												<TD>
+													<?php
+														// Modified May 14/08
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" id=\"tpcs\" size=\"10\" style=\"color:brown\" readonly=\"true\" value=\"" . $_GET["R2"]  . "\" name=\"" . $_SESSION["ReagentProp_Name_Alias"]["3' cloning site"] . "\"><BR>";
+
+														echo "<P id=\"tpcs_comment\" style=\"font-size:7pt; display:none\">Please enter a hyphen-delimited name of the hybrid restriction site (e.g. SalI-XhoI, order: insert_site-vector_site)</P>";
+													?>
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">   
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							case '6':
+								// One or both of the Parent IDs entered do not exist
+								// Check which one
+								$assocType = $_GET["AP"];	// this is an integer, corresponding to APropertyID in Assoc_Prop_Type_tbl
+								
+								switch ($assocType)
+								{
+									case '1':	// insert
+										?>
+										<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+
+											<!-- Pass current user ID as hidden form field -->
+											<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+											<!-- Pass type and subtype as hidden value to Python code -->
+											<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+											<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+											<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+											<FIELDSET style="width:100%; border:0; padding-left:15px;">
+												<P><SPAN style="color:red">There was a problem:</SPAN>
+
+												<P>The Insert ID you provided does not match an existing reagent in the system.
+
+												<P>What would you like to do?
+
+												<P>
+												<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); document.getElementById('insert').focus();">Enter a new Insert ID<BR>
+												<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>')" checked>Go back and start over<BR>
+												
+												<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+													<TR>
+														<TD nowrap>
+															Parent Vector OpenFreezer ID:
+														</TD>
+
+														<TD>
+															<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+														</TD>
+
+													</TR>
+													
+													<TR>
+														<TD nowrap>
+															Insert OpenFreezer ID:
+														</TD>
+
+														<TD>
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+														</TD>
+													</TR>
+												</TABLE>
+
+												<P>
+												<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+											</FIELDSET>
+										</FORM>
+										<?php
+									break;
+									
+									case '2':	// parent vector
+										?>
+										<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+
+											<!-- Pass type and subtype as hidden value to Python code -->
+											<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+											<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+											<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+											<!-- Pass current user ID as hidden form field -->
+											<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+											<FIELDSET style="width:100%; border:0; padding-left:15px;">
+												<P><SPAN style="color:red">There was a problem:</SPAN>
+												<P>The Parent Vector ID you provided does not match an existing reagent in the system.
+
+												<P>What would you like to do?
+
+												<P>
+												<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Enter a new Parent Vector ID<BR>
+												<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>')" checked>Go back and start over<BR>
+												
+												<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+													<TR>
+														<TD nowrap>
+															Parent Vector OpenFreezer ID:
+														</TD>
+
+														<TD>
+															<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+														</TD>
+
+													</TR>
+													
+													<TR>
+														<TD nowrap>
+															Insert OpenFreezer ID:
+														</TD>
+
+														<TD>
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+														</TD>
+													</TR>
+												</TABLE>
+
+												<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+											</FIELDSET>
+										</FORM>
+										<?php
+									break;
+								}
+							break;
+
+							case '10':
+								// don't have access to parent vector project
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+						
+									<!-- Pass user info to Python as hidden form value too - Aug 21/07 -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+						
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+			
+										<P style="color:brown;">You are not authorized to use <B><?php echo strtoupper($_GET["PV"]); ?></B> as the parent vector, since <U>you do not have read access to its project</U>.<BR>
+			
+										Please contact the project owner to obtain permission or select a different parent vector for your reagent.</P>
+			
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');" checked>Start over<BR>
+										<input type="radio" id = "change_parents_warning_option" name="warning_change_input" value="change_parents"; onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Change parent values<BR>
+			
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+			
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+			
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+			
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+			
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+			
+							case '11':
+								// don't have read access to Insert project
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+						
+									<!-- Pass user info to Python as hidden form value too - Aug 21/07 -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+						
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+
+										<P><SPAN style="color:brown;">You are not authorized to use <B><?php echo strtoupper($_GET["I"]); ?></B> as the parent Insert, since <U>you do not have read access to its project</U>.</SPAN><BR>
+			
+										Please contact the project owner to obtain permission or select a different parent Insert for your reagent.</P>
+			
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');" checked>Start over<BR/>
+			
+										<input type="radio" id = "change_parents_warning_option" name="warning_change_input" value="change_parents"; onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Change parent values<BR/>
+			
+										</P>
+			
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+			
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+			
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+			
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+			
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+			
+							// May 14/08
+							case '13':
+								// Insert does not contain cloning sites
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+						
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+
+										<P>A sequence for the new vector could not be generated from the sequences of its parents.  The Insert sequence does not contain one or both of the following restriction sites:<BR>
+
+										<P>What would you like to do?
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values<BR>
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" checked onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Go back and choose different parent values or vector type<BR>
+										
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<TABLE cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													<span style="padding-right:60px;" id="main_5_site_caption">5' Cloning Site on Insert:</span>
+
+													<span id="alt_5_site_caption" style="display:none">5' Cloning Site on resulting Vector:</span>
+												</TD>
+
+												<TD>
+													<?php
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"10\" id=\"fpcs\" style=\"color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $_GET["R1"]  . "\" name=\"" . $_SESSION["ReagentProp_Name_Alias"]["5' cloning site"] . "\"><BR>";
+													?>
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													<span style="padding-right:60px;" id="main_3_site_caption">3' Cloning Site on Insert:</span>
+
+													<span id="alt_3_site_caption" style="display:none">3' Cloning Site on resulting Vector:</span>
+												</TD>
+
+												<TD>
+													<?php
+														// Modified May 14/08
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" id=\"tpcs\" size=\"10\" style=\"color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $_GET["R2"]  . "\" name=\"" . $_SESSION["ReagentProp_Name_Alias"]["3' cloning site"] . "\"><BR>";
+													?>
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							// May 29/08
+							case '14':
+								// Insert cloning site values don't match sequence at site positions
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+						
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>A sequence for the new vector could not be generated from the sequences of its parents.<BR>
+
+										<P>One or both cloning sites does not match an actual enzyme sequence at the following positions on <a href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["I"]); ?>" target="blank"><?php echo $_GET["I"]; ?></a>:<BR>
+
+										<P>What would you like to do?<BR>
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values<BR>
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" checked onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Go back and choose different parent values or vector type<BR>
+
+										<TABLE width="100%" id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD style="width:250px;">
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD style="width:180px;">
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+										<BR>
+
+										<TABLE width="650px" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD style="width:250px;">
+													<span id="main_5_site_caption">5' Cloning Site on Insert:</span>
+
+													<span id="alt_5_site_caption" style="display:none">5' Cloning Site on resulting Vector:</span>
+												</TD>
+
+												<TD style="padding-left:10px; white-space:nowrap;">
+													<?php
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"15\" id=\"fpcs\" style=\"color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $_GET["R1"]  . "\" name=\"" . $_SESSION["ReagentProp_Name_Alias"]["5' cloning site"] . "\">";
+
+														$pStart = $rfunc_obj->getStartPos($gfunc_obj->get_rid($_GET["I"]), "5' cloning site", $_SESSION["ReagentProp_Name_ID"]["5' cloning site"]);
+
+														echo "Start: <INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" style=\"margin-left:5px; color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $pStart  . "\">";
+
+														$pEnd = $rfunc_obj->getEndPos($gfunc_obj->get_rid($_GET["I"]), "5' cloning site", $_SESSION["ReagentProp_Name_ID"]["5' cloning site"]);
+
+														echo "End:<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" style=\"margin-left:5px; color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $pEnd . "\">";
+
+														echo "<BR>";
+
+														echo "<P id=\"fpcs_comment\" style=\"font-size:7pt; display:none\">Please enter a hyphen-delimited name of the hybrid restriction site (e.g. SalI-XhoI, order: vector_site-insert_site)</P>";
+													?>
+												</TD>
+											</TR>
+
+											<TR>
+												<TD  style="width:250px;">
+													<span id="main_3_site_caption">3' Cloning Site on Insert:</span>
+
+													<span id="alt_3_site_caption" style="display:none">3' Cloning Site on resulting Vector:</span>
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<?php
+														// Modified May 14/08
+														echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" id=\"tpcs\" size=\"15\" style=\"color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $_GET["R2"]  . "\" name=\"" . $_SESSION["ReagentProp_Name_Alias"]["3' cloning site"] . "\">";
+
+														$pStart = $rfunc_obj->getStartPos($gfunc_obj->get_rid($_GET["I"]), "3' cloning site", $_SESSION["ReagentProp_Name_ID"]["3' cloning site"]);
+
+														echo "Start: <INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" style=\"margin-left:5px; color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $pStart  . "\">";
+
+														$pEnd = $rfunc_obj->getEndPos($gfunc_obj->get_rid($_GET["I"]), "3' cloning site", $_SESSION["ReagentProp_Name_ID"]["3' cloning site"]);
+
+														echo "End:<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"5\" style=\"margin-left:5px; color:brown; background-color:#E8E8E8;\" readonly=\"true\" value=\"" . $pEnd . "\">";
+
+														echo "<BR>";
+
+														echo "<P id=\"tpcs_comment\" style=\"font-size:7pt; display:none\">Please enter a hyphen-delimited name of the hybrid restriction site (e.g. SalI-XhoI, order: insert_site-vector_site)</P>";
+													?>
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">   
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							case '24':
+								// Empty parent Vector sequence
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+						
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>A sequence for the new vector could not be generated from the sequences of its parents.<BR>
+
+										<P>The sequence of the parent Vector <a href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["PV"]); ?>" target="blank"><?php echo $_GET["PV"]; ?></a> is empty.
+
+										<P>What would you like to do?
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values<BR>
+										<input type="radio" name="warning_change_input" ID="process_error_restart" value="restart" checked onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Cancel creation and start over<BR>
+
+										<TABLE width="100%" id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD style="width:250px;">
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD style="width:180px;">
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+										<BR>
+										
+										<P><INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							// Dec. 14/09
+							case '25':
+								// Empty parent Insert sequence
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+						
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+									<FIELDSET style="width:700px; border:0; padding-left:15px;">
+										<P><SPAN style="color:red">There was a problem:</SPAN>
+										<P>A sequence for the new vector could not be generated from the sequences of its parents.<BR>
+
+										<P>The sequence of the parent Insert <a href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["I"]); ?>" target="blank"><?php echo $_GET["I"]; ?></a> is empty.
+
+										<P>What would you like to do?
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Change parent values<BR>
+										<input type="radio" name="warning_change_input" ID="process_error_restart" value="restart" checked onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>'); enableOrDisableSites()">Cancel creation and start over<BR>
+
+										<TABLE width="100%" id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD style="width:250px;">
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="nr_pv_id" name="new_nr_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD style="width:180px;">
+													Insert OpenFreezer ID:
+												</TD>
+
+												<TD style="padding-left:10px;">
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="insert" name="new_insert_id" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["I"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+										<BR>
+										
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							default:
+								return false;
+							break;
+						}
+					break;
+
+// continue code cleanup from here; paste <P><SPAN style="color:red">There was a problem:</SPAN>
+
+					case 'gateway_expression':
+						$pv_id_tmp = $gfunc_obj->get_rid($_GET["PV"]);
+						$ipv_id_tmp = $gfunc_obj->get_rid($_GET["IPV"]);
+
+						switch ($err_code)
+						{
+							// April 10/08
+							case '2':
+								// Insert sites not found on PV sequence.  Here, give the option of making a hybrid:
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+									
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P style="color:red">There was a problem:</P>
+										<P>A sequence for the new vector could not be generated. The  <span style="color:#FF0000">att</span> cloning sites could not be found on either the donor or entry vector sequence.<BR>
+<!-- 										<P>The <span color="#FF0000">attR</span> restriction site could not be found on the sequence of the Parent Vector you provided:</P> -->
+
+										<P>What would you like to do?</P>
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Change parent values<BR/>
+
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" checked>Go back and select another vector type<BR/>
+										</P>
+
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo strtoupper($_GET["IPV"]); ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">   
+										</P>
+
+										<!-- footer padding -->
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							case '6':
+								// One or both of the Parent IDs entered do not exist
+								// Check which one
+								$assocType = $_GET["AP"];	// this is an integer, corresponding to APropertyID in Assoc_Prop_Type_tbl
+								
+								switch ($assocType)
+								{
+									case '2':	// parent vector
+										?>
+										<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+
+											<!-- Pass type and subtype as hidden value to Python code -->
+											<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+											<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+											<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+											<!-- Pass current user ID as hidden form field -->
+											<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+											<FIELDSET style="width:100%; border:0; padding-left:15px;">
+												<P style="color:red">There was a problem:</P>
+												<P>The Parent Vector ID you provided does not match an existing reagent in the system.</P>
+
+												<P>What would you like to do?</P>
+
+												<P>
+												<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Enter a new Parent Vector ID<BR/>
+
+												<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>')" checked>Go back and start over<BR/>
+												</P>
+
+												<TABLE id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+													
+													<TR>
+														<TD nowrap>
+															Parent Vector OpenFreezer ID:
+														</TD>
+
+														<TD>
+															<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+														</TD>
+
+													</TR>
+													
+													<TR>
+														<TD nowrap>
+															Insert Parent Vector OpenFreezer ID:
+														</TD>
+
+														<TD>
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["IPV"]; ?>">
+														</TD>
+													</TR>
+												</TABLE>
+
+												<P>
+												<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+												</P>
+											</FIELDSET>
+										</FORM>
+										<?php
+									break;
+									
+									case '7':	// parent insert vector
+										?>
+										<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+
+											<!-- Pass type and subtype as hidden value to Python code -->
+											<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+											<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+											<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+											<!-- Pass current user ID as hidden form field -->
+											<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+											<FIELDSET style="width:100%; border:0; padding-left:15px;">
+												<P style="color:red;">An error occurred during sequence construction:</P>
+
+												<P style="color:red; font-weight:bold">Invalid Insert Parent Vector ID</P>
+
+												<P>Either <SPAN style="color:#FF0000;"><?php echo strtoupper($_GET["IPV"]); ?></span> does not match an existing reagent in the system or a valid Insert for it could not be found.</P>
+
+												<P>What would you like to do?</P>
+
+												<P>
+												<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Enter a new Insert Parent Vector ID<BR/>
+
+												<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>')" checked>Go back and start over<BR/>
+												</P>
+
+												<TABLE id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+													
+													<TR>
+														<TD nowrap>
+															Parent Vector OpenFreezer ID:
+														</TD>
+
+														<TD>
+															<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+														</TD>
+
+													</TR>
+													
+													<TR>
+														<TD nowrap>
+															Insert Parent Vector OpenFreezer ID:
+														</TD>
+
+														<TD>
+															<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["IPV"]; ?>">
+														</TD>
+													</TR>
+												</TABLE>
+
+												<P>
+												<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+												</P>
+											</FIELDSET>
+										</FORM>
+										<?php
+									break;
+									
+									default:
+									break;	
+								}
+							break;
+
+							case '10':
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+						
+									<!-- Pass user info to Python as hidden form value too - Aug 21/07 -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+						
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P style="color:#FF0000;">There was a problem:</P>
+
+										<P style="color:brown;">You are not authorized to use <B><?php echo strtoupper($_GET["PV"]); ?></B> as the parent vector, since <U>you do not have read access to its project</U>.<BR>
+
+										Please contact the project owner to obtain permission or select a different parent vector for your reagent.</P>
+
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');" checked>Start over<BR>
+
+										<input type="radio" id = "change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableRecombParents();">Change parent values<BR/>
+
+										</P>
+
+										<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo strtoupper($_GET["IPV"]); ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">   
+										</P>
+
+										<!-- footer padding -->
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+									</FIELDSET>
+								</FORM>
+								<?php
+
+							break;
+
+							case '12':
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+						
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+						
+									<!-- Pass user info to Python as hidden form value too - Aug 21/07 -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+						
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P style="color:#FF0000;">There was a problem:</P>
+
+										<P style="color:brown;">You are not authorized to use <B><?php echo strtoupper($_GET["IPV"]); ?></B> as the Insert Parent Vector, since <U>you do not have read access to its project</U>.<BR>
+
+										Please contact the project owner to obtain permission or select a different Parent Insert Vector for your reagent.</P>
+
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableRecombParents();" checked>Start over<BR/>
+
+										<input type="radio" id = "change_parents_warning_option" name="warning_change_input" value="change_parents"; onClick="enableOrDisableRecombParents();">Change parent values<BR/>
+
+										</P>
+
+										<TABLE id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+											</TR>
+
+											<TR>
+												<TD nowrap>
+													Insert Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["IPV"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">   
+										</P>
+
+										<!-- footer padding -->
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+										<blockquote> </blockquote>
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							// Oct. 31/08
+							case '19':
+								// Raised when one of the vector parents provided is not of suitable type 
+								// Introduced mainly to prevent errors where recomb. vectors are used as donors - i.e. IPV in recomb. vector creation must have ATypeID 1
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:red;">An error occurred during sequence construction:</SPAN>
+
+										<P><a href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["IPV"]); ?>"><?php echo strtoupper($_GET["IPV"]); ?></a>  cannot be properly recombined to produce a Gateway Expression Vector.  Please verify your Insert Parent Vector input.</SPAN>
+
+										<P>What would you like to do?</P>
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Enter a new Insert Parent Vector ID<BR/>
+
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>')" checked>Go back and start over<BR/>
+										</P>
+
+										<TABLE id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											
+											<TR>
+												<TD nowrap>
+													Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+
+											</TR>
+											
+											<TR>
+												<TD nowrap>
+													Insert Parent Vector OpenFreezer ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["IPV"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+										</P>
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							case '30':
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:red;">An error occurred during sequence construction:</SPAN>
+
+										<P>The Gateway Parent Destination Vector provided (<a href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["PV"]); ?>"><?php echo strtoupper($_GET["PV"]); ?></a>) does not contain a <span style="color:red;">ccdB</span> gene, which is necessary for successful Gateway cloning.</SPAN>
+
+										<P>What would you like to do?</P>
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Change parent values<BR/>
+
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>')" checked>Go back and start over<BR/>
+										</P>
+
+										<TABLE id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											
+											<TR>
+												<TD nowrap>
+													Gateway Parent Destination Vector ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+
+											</TR>
+											
+											<TR>
+												<TD nowrap>
+													Gateway Entry Vector ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["IPV"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+										</P>
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							case '31':
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:red;">An error occurred during sequence construction:</SPAN>
+
+										<P>The <span style="color:red;">ccdB</span> gene was not found in the sequence of the Gateway Parent Destination Vector (<a href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["PV"]); ?>"><?php echo strtoupper($_GET["PV"]); ?></a>) but found in the sequence of the Gateway Entry Clone (<a href="<?php echo $hostname . "Reagent.php?View=6&rid=" . $gfunc_obj->get_rid($_GET["IPV"]); ?>"><?php echo strtoupper($_GET["IPV"]); ?></a>), suggesting the input [...]
+
+										<P>What would you like to do?</P>
+
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">Change parent values<BR/>
+
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>', '<?php echo $subtype; ?>')" checked>Go back and start over<BR/>
+										</P>
+
+										<TABLE id="recomb_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											
+											<TR>
+												<TD nowrap>
+													Gateway Parent Destination Vector ID:
+												</TD>
+
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="rec_pv_id" name="rec_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+
+											</TR>
+											
+											<TR>
+												<TD nowrap>
+													Gateway Entry Vector ID:
+												</TD>
+
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="ipv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["IPV"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+										</P>
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+
+							default:
+							break;
+						}
+					break;
+
+					default:
+						return false;
+					break;
+				}
+			break;
+
+			case 'Insert':
+				switch ($_GET["Err"])
+				{
+					case '6':
+						// One or all of the Parent IDs entered do not exist
+						?>
+						<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+
+							<!-- Pass type and subtype as hidden value to Python code -->
+							<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+							<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+							<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+
+							<!-- Pass current user ID as hidden form field -->
+							<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+							<FIELDSET style="width:100%; border:0; padding-left:15px;">
+								<P><SPAN style="color:#FF0000; font-weight:bold;">Error: Invalid parent ID</SPAN>
+								
+								<P><SPAN>One or more of the parent IDs provided does not match an existing reagent in the system.  Please verify your parent input.</P>
+
+								<P>What would you like to do?</P>
+
+								<P>
+								<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>');">Edit parent values<BR/>
+
+								<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>')" checked>Go back and start over<BR/>
+								</P>
+
+								<TABLE id="insert_parents" cellpadding="4px" border="1" frame="box" rules="all">
+									
+									<TR>
+										<TD nowrap>
+											Insert Parent Vector OpenFreezer ID:
+										</TD>
+
+										<TD>
+											<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+											<INPUT TYPE="text" id="piv_id" onKeyPress="return disableEnterKey(event);"  name="insert_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PIV"]; ?>">
+										</TD>
+
+									</TR>
+									
+									<TR>
+										<TD nowrap>
+											Sense Oligo OpenFreezer ID:
+										</TD>
+
+										<TD>
+											<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="sense_id" name="sense_oligo" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["SO"]; ?>">
+										</TD>
+									</TR>
+
+										<TR>
+										<TD nowrap>
+											Antisense Oligo OpenFreezer ID:
+										</TD>
+
+										<TD>
+											<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="antisense_id" name="antisense_oligo" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["AS"]; ?>">
+										</TD>
+									</TR>
+								</TABLE>
+
+								<P>
+								<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+								</P>
+							</FIELDSET>
+						</FORM>
+						<?php
+					break;
+
+					case '12':
+						// No access to IPV's project, can't use for creation
+						?>
+						<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+				
+							<!-- Pass type and subtype as hidden value to Python code -->
+							<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+							<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+							<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+				
+							<!-- Pass user info to Python as hidden form value too - Aug 21/07 -->
+							<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+				
+							<FIELDSET style="width:100%; border:0; padding-left:15px;">
+								<P style="color:#FF0000;">There was a problem:</P>
+
+								<P style="color:brown;">You are not authorized to use <B><?php echo strtoupper($_GET["PIV"]); ?></B> as the Insert Parent Vector, since <U>you do not have read access to its project</U>.<BR>
+
+								Please contact the project owner to obtain permission, or select one of the following options:</P>
+
+								<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('Insert');" checked>Start over<BR/>
+
+								<input type="radio" id = "change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('Insert');">Change parent values<BR/>
+
+								</P>
+
+								<TABLE cellpadding="4px" border="1" frame="box" rules="all">
+									<TR>
+										<TD nowrap>
+											Insert Parent Vector OpenFreezer ID:
+										</TD>
+
+										<TD>
+											<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="piv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["PIV"]; ?>">
+										</TD>
+									</TR>
+									
+									<TR>
+										<TD nowrap>
+											Sense Oligo OpenFreezer ID:
+										</TD>
+
+										<TD>
+											<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="sense_id" name="sense_oligo" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["SO"]; ?>">
+										</TD>
+									</TR>
+
+										<TR>
+										<TD nowrap>
+											Antisense Oligo OpenFreezer ID:
+										</TD>
+
+										<TD>
+											<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="antisense_id" name="antisense_oligo" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["AS"]; ?>">
+										</TD>
+									</TR>
+								</TABLE>
+
+								<P>
+								<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">   
+								</P>
+							</FIELDSET>
+						</FORM>
+						<?php
+					break;
+
+					case '20':
+						// No access to Sense Oligo's project, can't use for creation
+						?>
+						<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+				
+							<!-- Pass type and subtype as hidden value to Python code -->
+							<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+							<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+							<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+				
+							<!-- Pass user info to Python as hidden form value too - Aug 21/07 -->
+							<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+				
+							<FIELDSET style="width:100%; border:0; padding-left:15px;">
+								<P style="color:#FF0000; font-weight:bold;">There was a problem:</P>
+
+								<P style="color:brown">You are not authorized to use <B><?php echo strtoupper($_GET["SO"]); ?></B> as the Sense Oligo, since <U>you do not have read access to its project</U>.</P>
+
+								<P style="color:brown">Please contact the project owner to obtain permission, or select one of the following options:</P>
+
+								<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('Insert');" checked>Start over<BR/>
+
+								<input type="radio" id = "change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('Insert');">Change parent values<BR/>
+
+								</P>
+
+								<TABLE cellpadding="4px" border="1" frame="box" rules="all">
+									<TR>
+										<TD nowrap>
+											Insert Parent Vector OpenFreezer ID:
+										</TD>
+
+										<TD>
+											<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="piv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["PIV"]; ?>">
+										</TD>
+									</TR>
+									
+									<TR>
+										<TD nowrap>
+											Sense Oligo OpenFreezer ID:
+										</TD>
+
+										<TD>
+											<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="sense_id" name="sense_oligo" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["SO"]; ?>">
+										</TD>
+									</TR>
+
+										<TR>
+										<TD nowrap>
+											Antisense Oligo OpenFreezer ID:
+										</TD>
+
+										<TD>
+											<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="antisense_id" name="antisense_oligo" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["AS"]; ?>">
+										</TD>
+									</TR>
+								</TABLE>
+
+								<P>
+								<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">   
+								</P>
+							</FIELDSET>
+						</FORM>
+						<?php
+					break;
+
+					case '21':
+						// No access to Sense Oligo's project, can't use for creation
+						?>
+						<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+				
+							<!-- Pass type and subtype as hidden value to Python code -->
+							<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+							<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+							<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+				
+							<!-- Pass user info to Python as hidden form value too - Aug 21/07 -->
+							<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+				
+							<FIELDSET style="width:100%; border:0; padding-left:15px;">
+								<P style="color:#FF0000; font-weight:bold;">There was a problem:</P>
+
+								<P style="color:brown">You are not authorized to use <B><?php echo strtoupper($_GET["AS"]); ?></B> as the Antisense Oligo, since <U>you do not have read access to its project</U>.</P>
+
+								<P style="color:brown">Please contact the project owner to obtain permission, or select one of the following options:</P>
+
+								<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('Insert');" checked>Start over<BR/>
+
+								<input type="radio" id = "change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('Insert');">Change parent values<BR/>
+
+								</P>
+
+								<TABLE cellpadding="4px" border="1" frame="box" rules="all">
+									<TR>
+										<TD nowrap>
+											Insert Parent Vector OpenFreezer ID:
+										</TD>
+
+										<TD>
+											<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="piv_id" name="insert_parent_vector" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["PIV"]; ?>">
+										</TD>
+									</TR>
+									
+									<TR>
+										<TD nowrap>
+											Sense Oligo OpenFreezer ID:
+										</TD>
+
+										<TD>
+											<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="sense_id" name="sense_oligo" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["SO"]; ?>">
+										</TD>
+									</TR>
+
+										<TR>
+										<TD nowrap>
+											Antisense Oligo OpenFreezer ID:
+										</TD>
+
+										<TD>
+											<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="antisense_id" name="antisense_oligo" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["AS"]; ?>">
+										</TD>
+									</TR>
+								</TABLE>
+
+								<P>
+								<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">   
+								</P>
+							</FIELDSET>
+						</FORM>
+						<?php
+					break;
+				}
+			break;
+
+			// New Aug. 27/08
+			case 'CellLine':
+
+				$pv_id_tmp = $gfunc_obj->get_rid($_GET["PV"]);
+				$cl_id_tmp = $gfunc_obj->get_rid($_GET["CL"]);
+
+				switch ($err_code)
+				{
+					case '6':
+						$assocType = $_GET["AP"];	// this is an integer, corresponding to APropertyID in Assoc_Prop_Type_tbl
+								
+						switch ($assocType)
+						{
+							case '7':
+								# non-existent parent Cell Line
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+		
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+		
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:#FF0000; font-weight:bold;">Error: Invalid parent Cell Line ID</SPAN>
+										
+										<P><SPAN>The ID of the Parent Cell Line provided does not match an existing reagent in the system.  Please verify your parent input.</P>
+		
+										<P>What would you like to do?</P>
+		
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>');">Edit parent values<BR/>
+		
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>')" checked>Go back and start over<BR/>
+										</P>
+		
+										<TABLE id="cellLine_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											
+											<TR>
+												<TD nowrap>
+													Cell Line Parent Vector OpenFreezer ID:
+												</TD>
+		
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="clpv_id" name="cell_line_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+		
+											</TR>
+											
+											<TR>
+												<TD nowrap>
+													Parent Cell Line OpenFreezer ID:
+												</TD>
+		
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="pcl_id" name="parent_cell_line" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["CL"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+		
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+										</P>
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+							
+							case '8':	// parent cell line vector
+								# non-existent parent Cell Line
+								?>
+								<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents('<?php echo $type; ?>', '<?php echo $subtype; ?>');">
+		
+									<!-- Pass type and subtype as hidden value to Python code -->
+									<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+									<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+									<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+		
+									<!-- Pass current user ID as hidden form field -->
+									<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+									<FIELDSET style="width:100%; border:0; padding-left:15px;">
+										<P><SPAN style="color:#FF0000; font-weight:bold;">Error: Invalid parent Vector ID</SPAN>
+										
+										<P><SPAN>The ID of the Parent Vector provided does not match an existing reagent in the system.  Please verify your parent input.</P>
+		
+										<P>What would you like to do?</P>
+		
+										<P>
+										<input type="radio" id="change_parents_warning_option" name="warning_change_input" value="change_parents" onClick="enableOrDisableParents('<?php echo $type; ?>');">Edit parent values<BR/>
+		
+										<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableParents('<?php echo $type; ?>')" checked>Go back and start over<BR/>
+										</P>
+		
+										<TABLE id="cellLine_parents" cellpadding="4px" border="1" frame="box" rules="all">
+											
+											<TR>
+												<TD nowrap>
+													Cell Line Parent Vector OpenFreezer ID:
+												</TD>
+		
+												<TD>
+													<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="clpv_id" name="cell_line_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+												</TD>
+		
+											</TR>
+											
+											<TR>
+												<TD nowrap>
+													Parent Cell Line OpenFreezer ID:
+												</TD>
+		
+												<TD>
+													<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);"  id="pcl_id" name="parent_cell_line" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["CL"]; ?>">
+												</TD>
+											</TR>
+										</TABLE>
+		
+										<P>
+										<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">
+										</P>
+									</FIELDSET>
+								</FORM>
+								<?php
+							break;
+							
+							default:
+							break;	
+						}
+					break;
+
+					case '10':
+						?>
+						<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+				
+							<!-- Pass type and subtype as hidden value to Python code -->
+							<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+							<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+							<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+				
+							<!-- Pass user info to Python as hidden form value too - Aug 21/07 -->
+							<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+				
+							<FIELDSET style="width:100%; border:0; padding-left:15px;">
+								<P style="color:#FF0000;">There was a problem:</P>
+	
+								<P style="color:brown;">You are not authorized to use <B><?php echo strtoupper($_GET["PV"]); ?></B> as the parent vector, since <U>you do not have read access to its project</U>.<BR>
+	
+								Please contact the project owner to obtain permission or select a different parent vector for your reagent.</P>
+	
+								<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableCellLineParents();" checked>Start over<BR/>
+	
+								<input type="radio" id = "change_parents_warning_option" name="warning_change_input" value="change_parents"; onClick="enableOrDisableCellLineParents();">Change parent values<BR/>
+	
+								</P>
+	
+								<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+									<TR>
+										<TD nowrap>
+											Parent Vector OpenFreezer ID:
+										</TD>
+	
+										<TD>
+											<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+											<INPUT TYPE="text" id="cl_pv_id" onKeyPress="return disableEnterKey(event);"  name="cell_line_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+										</TD>
+									</TR>
+	
+									<TR>
+										<TD nowrap>
+											Cell Line OpenFreezer ID:
+										</TD>
+	
+										<TD>
+											<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="parent_cell_line_id" name="parent_cell_line" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["CL"]; ?>">
+										</TD>
+									</TR>
+								</TABLE>
+	
+								<P>
+								<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">   
+								</P>
+	
+								<!-- footer padding -->
+								<blockquote> </blockquote>
+								<blockquote> </blockquote>
+								<blockquote> </blockquote>
+								<blockquote> </blockquote>
+								<blockquote> </blockquote>
+								<blockquote> </blockquote>
+								<blockquote> </blockquote>
+								<blockquote> </blockquote>
+	
+							</FIELDSET>
+						</FORM>
+						<?php
+					break;
+
+					case '13':
+						?>
+						<FORM method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+				
+							<!-- Pass type and subtype as hidden value to Python code -->
+							<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $type; ?>">
+							<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+							<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+				
+							<!-- Pass user info to Python as hidden form value too - Aug 21/07 -->
+							<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+				
+							<FIELDSET style="width:100%; border:0; padding-left:15px;">
+								<P style="color:#FF0000;">There was a problem:</P>
+	
+								<P style="color:brown;">You are not authorized to use <B><?php echo strtoupper($_GET["CL"]); ?></B> as the parent cell line, since <U>you do not have read access to its project</U>.<BR>
+	
+								Please contact the project owner to obtain permission or select a different parent vector for your reagent.</P>
+	
+								<input type="radio" name="warning_change_input" value="restart" ID="process_error_restart" onClick="enableOrDisableCellLineParents();" checked>Start over<BR/>
+	
+								<input type="radio" id = "change_parents_warning_option" name="warning_change_input" value="change_parents"; onClick="enableOrDisableCellLineParents();">Change parent values<BR/>
+	
+								</P>
+	
+								<TABLE id="nonrec_parents" cellpadding="4px" border="1" frame="box" rules="all">
+									<TR>
+										<TD nowrap>
+											Parent Vector OpenFreezer ID:
+										</TD>
+	
+										<TD>
+											<!-- DO NOT USE 'disabled'!!! field won't be recognized by CGI -->
+											<INPUT TYPE="text" id="cl_pv_id" onKeyPress="return disableEnterKey(event);"  name="cell_line_parent_vector" size="10" style="color:brown" readonly="true" value="<?php echo $_GET["PV"]; ?>">
+										</TD>
+									</TR>
+	
+									<TR>
+										<TD nowrap>
+											Cell Line OpenFreezer ID:
+										</TD>
+	
+										<TD>
+											<INPUT TYPE="text" onKeyPress="return disableEnterKey(event);" id="parent_cell_line_id" name="parent_cell_line" size="10" readonly="true" style="color:brown"  value="<?php echo $_GET["CL"]; ?>">
+										</TD>
+									</TR>
+								</TABLE>
+	
+								<P>
+								<INPUT TYPE="SUBMIT" NAME="process_warning" VALUE="Go">   
+								</P>
+	
+								<!-- footer padding -->
+								<blockquote> </blockquote>
+								<blockquote> </blockquote>
+								<blockquote> </blockquote>
+								<blockquote> </blockquote>
+								<blockquote> </blockquote>
+								<blockquote> </blockquote>
+								<blockquote> </blockquote>
+								<blockquote> </blockquote>
+	
+							</FIELDSET>
+						</FORM>
+						<?php
+					break;
+				}
+			break;
+		}
+	}
+	
+
+	/**
+	 * Print features table upon saving Insert from Primer Design
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param INT rID
+	 * @param INT seqID
+	 * @param INT insertParentVector
+	 * @param INT sense oligo ID
+	 * @param INT antisense oligo ID
+	*/
+	// May 14/08: Changed the procedure of saving Insert from Primer Design slightly
+	function previewInsertFeaturesPrimer($rID, $seqID, $insertParentVector, $sense, $antisense)
+	{
+		global $hostname;
+		global $cgi_path;
+
+		$gfunc_obj = new generalFunc_Class();
+		$rprint_obj = new Reagent_Output_Class();
+
+		$outputer_obj = new ColFunctOutputer_Class();		// Nov. 10/08
+
+		// May 5/08: Use a different prefix - make uniform for all reagent types and for dynamic features
+		$genPrefix = "reagent_detailedview_";
+		$genPostfix = "_prop";
+
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+
+		?>
+		<FORM NAME="reagentDetailForm" method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onSubmit="setFeaturePositions(); return verifyPositions(true);">
+
+			<!-- Pass user info to Python as hidden form value - Aug 21/07 -->
+			<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+			<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="Insert">
+			<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+			<INPUT TYPE="hidden" NAME="seq_id_hidden" VALUE="<?php echo $seqID; ?>">
+
+			<INPUT TYPE="hidden" NAME="from_primer" VALUE="True">
+
+			<table width="780px" cellpadding="4">
+				<tr>
+					<td style="text-align:center; font-weight:bold; padding-left:150px;">
+						<span style="color:#00C00D; font-size:13pt; padding-bottom:18px;">
+							INSERT CREATION
+							<BR>
+						</span>
+	
+						<span style="color:#00B38D; font-size:10pt;">
+							Step 3 of 4: Confirm Features
+						</span>
+					</td>
+					<td style="text-align:right; padding-right:10px;">
+						<input type="submit" name="confirm_intro" value="Continue" onClick="document.getElementById('cancel_set').value=0; document.getElementById('navigate_away').value=0;">
+						 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+
+						<INPUT type="hidden" ID="cancel_set" value="0">
+					</td>
+				</tr>
+
+<!-- NO, don't do this - will get no added benefit and Oligos just created would be left orphaned (project has not been assigned yet)
+				<tr>
+					<td colspan="2">
+						<a style="font-size:10pt; margin-left:8px;" href="<?php /*echo $hostname . "Reagent.php?View=7&rid=" . $rID;*/ ?>">Back to Primer Design page</a>
+					</td>
+				</tr>
+-->
+			</table>
+
+			<?php
+				// Updated Nov. 5/08 - 'Back' buttons will have different action on Primer Design
+				$this->printParents("Insert", "", true, $insertParentVector, $sense, $antisense, true);
+			?>
+			<BR>
+			<TABLE width="576px" cellpadding="2" style="margin-left:10px;">
+				<TR>
+					<TD style="font-weight:bold;" colspan="2">
+						Sequence:
+					</TD>
+				</TR>
+
+				<TR>
+					<TD colspan="2">
+						<div style="width:970px; height:175px; background-color:#D1D1D1; border:1px solid gray; padding:8px; overflow:auto">
+							<?php
+								// Here can pass $rID as parameter b/c a PropList_tbl entry has already been created
+								// The sequence will be printed WITH NUMBERS (Sept. 2/08)
+								$outputer_obj->output_sequence($rID);
+							?>
+						</div>
+					</TD>
+				</TR>
+			</TABLE>
+			<?php
+			
+			$this->printFeatures("Insert", "", $rID, $seqID, "", true);
+			?>
+		</FORM>
+		<?php
+	}
+
+
+	/**
+	 * Step 3 of creation, preview features a Vector inherited from parents during sequence construction
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-05-01
+	 *
+	 * @param STRING
+	 * @param STRING
+	 * @param INT
+	 * @param INT
+	*/
+	function previewReagentFeatures($rType, $subtype, $rID, $seqID)
+	{
+		global $hostname;
+		global $cgi_path;
+
+		$gfunc_obj = new generalFunc_Class();
+		$rprint_obj = new Reagent_Output_Class();
+
+		$outputer_obj = new ColFunctOutputer_Class();		// Sept. 4/08
+
+		// May 5/08: Use a different prefix - make uniform for all reagent types and for dynamic features
+		$genPrefix = "reagent_detailedview_";
+		$genPostfix = "_prop";
+
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+
+		// Numerical db IDs of parents (parent1 is PV while parent2 can be either Insert or IPV; for Inserts there are 3 parents: 2 Oligos and PIV)
+		$parent1 = -1;
+		$parent2 = -1;
+		$parent3 = -1;
+
+		if ($rType == 'Vector')
+			$linear = false;
+		else
+			$linear = true;
+		?>
+		<FORM NAME="reagentDetailForm" method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onSubmit="setFeaturePositions(); return verifyPositions(<?php echo $linear; ?>);">
+
+			<!-- Pass user info to Python as hidden form value - Aug 21/07 -->
+			<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+			<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $rType; ?>">
+			<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+			<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+			<INPUT TYPE="hidden" NAME="seq_id_hidden" VALUE="<?php echo $seqID; ?>">
+			<?php
+				switch ($rType)
+				{
+					case 'Vector':
+						switch($subtype)
+						{
+							case 'nonrecomb':
+							case 'gateway_entry':
+								$pvID = $_GET["PV"];
+								$insertID = $_GET["I"];
+		
+								$parent1 = $pvID;
+								$parent2 = $insertID;
+
+								# Jan. 21/09: if Insert was reverse complemented, cDNA (and other features??), in order to be mapped correctly, need to be RCd too (only applies to NR vectors)
+
+								if (isset($_GET["Rev"]) && ($_GET["Rev"] == 'True'))
+								{
+									$rev = true;
+									echo "<INPUT TYPE=\"hidden\" NAME=\"reverse_complement\" VALUE=\"" . $rev . "\">";
+								}
+								?>
+									<table width="750px" cellpadding="4">
+										<tr>
+											<td style="text-align:center; font-weight:bold;">
+												<span style="color:#00C00D; font-size:13pt; padding-bottom:18px; margin-left:105px;">
+													<?php
+														if ($subtype == 'nonrecomb')
+															echo "CREATE A NON-RECOMBINATION VECTOR";
+														else if ($subtype == 'gateway_entry')
+															echo "CREATE A GATEWAY ENTRY VECTOR";
+													?>
+													<BR>
+												</span>
+							
+												<span style="color:#00B38D; font-size:10pt; margin-left:105px;">
+													Step 3 of 4: Confirm Features
+												</span>
+											</td>
+
+											<!-- nov. 5/08 -->
+											<TD style="text-align:right; padding-right:15px;">
+												<input type="submit" name="confirm_intro" value="Continue" onClick="document.getElementById('cancel_set').value=0; enableSites(); changeFieldNames('reagentDetailForm', null, '<?php echo $rType; ?>'); setFeaturePositions(); verifyPositions(); document.getElementById('navigate_away').value=0;">
+						
+												 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+						
+												<INPUT type="hidden" ID="cancel_set" value="0">
+											</TD>
+										</tr>
+									</table>
+
+									<!-- May 5/08: Add parents to form -->
+									<INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentAssoc_Name_Alias"]["vector parent id"] . $genPostfix; ?>" VALUE="<?php echo strtoupper($gfunc_obj->getConvertedID_rid($parent1)); ?>">
+						
+									<INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentAssoc_Name_Alias"]["insert id"] . $genPostfix; ?>" VALUE="<?php echo strtoupper($gfunc_obj->getConvertedID_rid($parent2)); ?>">
+								<?php
+		
+								$this->printParents($rType, $subtype, true, $parent1, $parent2);
+							break;
+		
+							case 'recomb':
+							case 'gateway_expression':
+								$pvID = $_GET["PV"];
+								$ipvID = $_GET["IPV"];
+		
+								$parent1 = $pvID;
+								$parent2 = $ipvID;
+		
+								?>
+									<table width="100%" cellpadding="4">
+										<tr>
+											<td colspan="2" style="text-align:center; font-weight:bold;">
+												<span style="color:#00C00D; font-size:13pt; white-space:nowrap; padding-bottom:18px;">
+													<?php
+														if ($subtype == 'recomb')
+															echo "CREATE AN EXPRESSION VECTOR";
+														else if ($subtype == 'gateway_expression')
+															echo "CREATE A GATEWAY EXPRESSION VECTOR";
+													?>
+													<BR>
+												</span>
+							
+												<span style="color:#00B38D; font-size:10pt; white-space:nowrap;">
+													Step 3 of 4: Confirm Features
+												</span>
+											</td>
+
+											<!-- nov. 5/08 -->
+											<TD style="text-align:right; padding-right:15px;">
+												<input type="submit" name="confirm_intro" value="Continue" onClick="document.getElementById('cancel_set').value=0; enableSites(); changeFieldNames('reagentDetailForm', null, '<?php echo $rType; ?>'); setFeaturePositions(); verifyPositions(); document.getElementById('navigate_away').value=0;">
+						
+												 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+						
+												<INPUT type="hidden" ID="cancel_set" value="0">
+											</TD>
+										</tr>
+									</table>
+		
+									<!-- May 5/08: Add parents to form -->
+									<INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentAssoc_Name_Alias"]["vector parent id"] . $genPostfix; ?>" VALUE="<?php echo strtoupper($gfunc_obj->getConvertedID_rid($parent1)); ?>">
+						
+									<INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentAssoc_Name_Alias"]["parent insert vector"] . $genPostfix; ?>" VALUE="<?php echo strtoupper($gfunc_obj->getConvertedID_rid($parent2)); ?>">
+
+									<P>
+								<?php
+		
+								$this->printParents($rType, $subtype, true, $parent1, $parent2);
+							break;
+		
+							case 'novel':
+								?>
+									<table width="100%" cellpadding="4">
+										<tr>
+											<td colspan="2" style="text-align:center; font-weight:bold;">
+												<span style="color:#00C00D; font-size:13pt; margin-left:150px; padding-bottom:18px;">
+													CREATE A NOVEL (PARENT) VECTOR
+													<BR>
+												</span>
+							
+												<span style="color:#00B38D; font-size:10pt; margin-left:150px;">
+													Step 2 of 3: Confirm Features
+												</span>
+											</td>
+
+											<!-- nov. 5/08 -->
+											<TD style="text-align:right; padding-right:15px;">
+												<input type="submit" name="confirm_intro" value="Continue" onClick="document.getElementById('cancel_set').value=0; enableSites(); changeFieldNames('reagentDetailForm', null, '<?php echo $rType; ?>'); setFeaturePositions(); verifyPositions(); document.getElementById('navigate_away').value=0;">
+						
+												 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+						
+												<INPUT type="hidden" ID="cancel_set" value="0">
+											</TD>
+										</tr>
+									</table>
+								<?php
+							break;
+						}
+					break;
+
+					case 'Insert':
+						$pivID = $_GET["PIV"];
+						$parent1 = $pivID;
+						
+						$senseID = $_GET["SO"];
+						$parent2 = $senseID;
+						
+						$antisenseID = $_GET["AS"];
+						$parent3 = $antisenseID;
+						?>
+							<table width="750px" cellpadding="2">
+								<tr>
+									<td colspan="2" style="text-align:center; font-weight:bold; padding-left:225px;">
+										<span style="color:#00C00D; font-size:13pt; padding-bottom:18px;">
+											CREATE AN INSERT
+											<BR>
+										</span>
+					
+										<span style="color:#00B38D; font-size:10pt;">
+											Step 3 of 4: Confirm Features
+										</span>
+									</td>
+
+									<!-- nov. 5/08 -->
+									<TD style="text-align:right; padding-right:15px;">
+										<input type="submit" name="confirm_intro" value="Continue" onClick="document.getElementById('cancel_set').value=0; enableSites(); changeFieldNames('reagentDetailForm', 'modifyReagentPropsTbl',  'Insert'); setFeaturePositions(); verifyPositions(); document.getElementById('navigate_away').value=0;">
+				
+										 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+				
+										<INPUT type="hidden" ID="cancel_set" value="0">
+									</TD>
+								</tr>
+							</table>
+						<?php
+
+						$this->printParents($rType, $subtype, true, $parent1, $parent2, $parent3);
+						?>
+							<!-- May 5/08: Add parents to form -->
+							<INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentAssoc_Name_Alias"]["insert parent vector id"] . $genPostfix; ?>" VALUE="<?php echo strtoupper($parent1); ?>">
+				
+							<INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentAssoc_Name_Alias"]["sense oligo"] . $genPostfix; ?>" VALUE="<?php echo strtoupper($parent2); ?>">
+	
+							<INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentAssoc_Name_Alias"]["antisense oligo"] . $genPostfix; ?>" VALUE="<?php echo strtoupper($parent3); ?>">
+						<?php
+					break;
+				}
+			?>
+			<BR>
+			<TABLE width="750px" cellpadding="2" style="margin-left:10px;">
+				<TR>
+					<TD style="font-weight:bold; font-size:10pt; padding-top:10px;" colspan="2">
+						Sequence:
+						<?php
+							switch ($rType)
+							{
+								case 'Vector':
+									switch($subtype)
+									{
+										case 'nonrecomb':
+// May 20, 2010: why is this commented out???
+// 										case 'gateway_entry':
+
+// adding back May 20, 2010, see if causes problems:
+										case 'gateway_entry':
+											if (isset($_GET["R1"]))
+											{
+												if (isset($_GET["R2"]))
+												{
+													?><a style="margin-left:5px; font-size:9pt; font-weight:normal;" href="<?php echo $hostname . "Reagent.php?View=2&Step=1&Type=" . $rType . "&Sub=" . $subtype . "&rID=" . $rID . "&PV=" . $pvID . "&I=" . $insertID . "&Seq=" . $seqID . "&R1=" . $_GET["R1"] . "&R2=" . $_GET["R2"] . "&Rev=" . $_GET["Rev"]; ?>">Go back and edit sequence</a><P><?php
+												}
+												else
+												{
+													?><a style="margin-left:10px; font-size:9pt; font-weight:normal;" href="<?php echo $hostname . "Reagent.php?View=2&Step=1&Type=" . $rType . "&Sub=" . $subtype . "&rID=" . $rID . "&PV=" . $pvID . "&I=" . $insertID . "&Seq=" . $seqID . "&R1=" . $_GET["R1"] . "&Rev=" . $_GET["Rev"]; ?>">Go back and edit sequence</a><P><?php
+												}
+											}
+											else if (isset($_GET["R2"]))
+											{
+												// not checking for R1, clearly not set
+												?><a style="margin-left:10px; font-size:9pt; font-weight:normal;" onclick="document.getElementById('navigate_away').value=0;" href="<?php echo $hostname . "Reagent.php?View=2&Step=1&Type=" . $rType . "&Sub=" . $subtype . "&rID=" . $rID . "&PV=" . $pvID . "&I=" . $insertID . "&Seq=" . $seqID . "&R2=" . $_GET["R2"] . "&Rev=" . $_GET["Rev"]; ?>">Go back and edit sequence</a><P><?php
+											}
+											else
+											{
+												?><a style="margin-left:10px; font-size:9pt; font-weight:normal;" onclick="document.getElementById('navigate_away').value=0;" href="<?php echo $hostname . "Reagent.php?View=2&Step=1&Type=" . $rType . "&Sub=" . $subtype . "&rID=" . $rID . "&PV=" . $pvID . "&I=" . $insertID . "&Seq=" . $seqID . "&Rev=" . $_GET["Rev"]; ?>">Go back and edit sequence</a><P><?php
+											}
+										break;
+
+										// Moved here Nov. 20/08 - sites are passed through GET variable for NON-RECOMBINATION vectors ONLY
+										case 'gateway_entry':
+											?><a style="margin-left:10px; font-size:9pt; font-weight:normal;" onclick="document.getElementById('navigate_away').value=0;" href="<?php echo $hostname . "Reagent.php?View=2&Step=1&Type=" . $rType . "&Sub=" . $subtype . "&rID=" . $rID . "&PV=" . $pvID . "&I=" . $insertID . "&Seq=" . $seqID; ?>">Go back and edit sequence</a><P><?php
+										break;
+
+										case 'recomb':
+										case 'gateway_expression':
+										?>
+											<a style="margin-left:10px; font-size:9pt; font-weight:normal;" onclick="document.getElementById('navigate_away').value=0;" href="<?php echo $hostname . "Reagent.php?View=2&Step=1&Type=" . $rType . "&Sub=" . $subtype . "&rID=" . $rID . "&PV=" . $pvID . "&IPV=" . $ipvID . "&Seq=" . $seqID; ?>">Go back and edit sequence</a><P>
+										<?php
+										break;
+
+										// oct 28/08
+										case 'novel':
+										?>
+											<a style="margin-left:10px; font-size:9pt; font-weight:normal;" onclick="document.getElementById('navigate_away').value=0;" href="<?php echo $hostname . "Reagent.php?View=2&Step=1&Type=" . $rType . "&Sub=" . $subtype . "&rID=" . $rID . "&Seq=" . $seqID; ?>">Go back and edit sequence</a><P>
+										<?php
+										break;
+									}
+								break;
+
+								case 'Insert':
+								?>
+									<a style="margin-left:10px; font-size:9pt; font-weight:normal;" onclick="document.getElementById('navigate_away').value=0;" href="<?php echo $hostname . "Reagent.php?View=2&Step=1&Type=Insert&rID=" . $rID . "&Seq=" . $seqID; ?>">Go back and edit sequence</a><P>
+								<?php
+								break;
+							}
+					?>
+					</TD>
+				</TR>
+
+				<TR>
+					<TD colspan="2">
+						<div style="width:700px; height:165px; background-color:#F9F9F9; border:1px solid gray; padding:8px; overflow:auto">
+							<?php
+								// Sept. 2/08: Print sequence WITH NUMBERS
+								$outputer_obj->output_sequence($rID);
+							?>
+						</div>
+					</TD>
+				</TR>
+			</TABLE>
+			<BR>
+			<TABLE width="750px" cellpadding="2" style="margin-left:10px;">
+				<TH style="text-align:left">Features:</TH>
+
+				<TR>
+					<TD colspan="2">
+						<?php
+							$this->printFeatures($rType, $subtype, $rID, $seqID);
+						?>
+					</TD>
+				</TR>
+			</TABLE>
+		</FORM>
+		<?php
+	}
+
+
+	/**
+	 * Separate function for common HTML output - print sequence features as a table.
+	 * Modified May 15/09: Make actual props table ID a parameter too, since this function is used in many different places and tables have different names.
+	 *
+	 * @param STRING
+	 * @param STRING
+	 * @param INT
+	 * @param INT
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-05-23
+	*/
+	function outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, $featureName, $feature, $readonly=false, $from_primer=false, $modify=false, $propsTbl_id="modifyReagentPropsTbl", $isProtein=false, $isRNA=false)
+	{
+		$rprint_obj = new Reagent_Output_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+
+		if ($feature)
+		{
+			$featureValue = $feature->getFeatureValue();
+			$fStart = $feature->getFeatureStart();
+			$fEnd = $feature->getFeatureEnd();
+			$fDir = $feature->getFeatureDirection();
+			$fDescr = $feature->getFeatureDescriptor();
+		}
+		else
+		{
+			// show empty fields
+			$featureValue = "";
+			$fStart = 0;
+			$fEnd = 0;
+			$fDir = "forward";
+			$fDescr = "";
+		}
+
+		if (!$isProtein && !$isRNA)
+			$featureID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][$featureName], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]);
+		else if ($isRNA)
+			$featureID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][$featureName], $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence Features"]);
+		else
+			$featureID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][$featureName], $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence Features"]);
+
+		$fAlias = $_SESSION["ReagentProp_Name_Alias"][$featureName];
+
+		// Oct. 26/09: Differentiate between creation and modification views
+		if ($rID <= 0)
+			$tblID = $rType . "_" . $fAlias;
+		else
+			$tblID = $fAlias;
+
+		?>
+		<!-- Updated Oct. 22/08: give unique row IDs for identical features -->
+		<TR ID="<?php echo $tblID; ?>_:_row_<?php echo $featureValue; ?>_start_<?php echo $fStart; ?>_end_<?php echo $fEnd; ?>" style="background-color:#F5F5DC;">
+			<TD style="padding-left:7px; white-space:nowrap; font-size:7pt; padding-right:10px;">
+				<?php
+					echo $_SESSION["ReagentProp_Name_Desc"][$featureName];
+					
+					if ((strcasecmp($subtype, "novel") == 0) && (strcasecmp($featureName, "5' cloning site") == 0))
+					{
+						echo "<INPUT TYPE=\"checkbox\" ID=\"five_prime_site_uknown\" NAME=\"no_five_prime_site\" style=\"margin-left:10px; font-weight:bold\">N/A";
+					}
+					else if ((strcasecmp($subtype, "novel") == 0) && (strcasecmp($featureName, "3' cloning site") == 0))
+					{
+						echo "<INPUT TYPE=\"checkbox\" ID=\"three_prime_site_uknown\" NAME=\"no_three_prime_site\" style=\"margin-left:10px; font-weight:bold\">N/A";
+					}
+				?>
+			</TD>
+
+			<TD style="padding-left:7px; white-space:nowrap; font-size:7pt; padding-bottom:1px; padding-top:1px;">
+				<?php
+					if (strcasecmp($featureName, 'cdna insert') == 0)
+					{
+						echo "If cDNA positions are unknown, select <INPUT TYPE=\"checkbox\" ID=\"cdna_unknown\" NAME=\"no_cdna\" style=\"margin-left:10px; font-weight:bold\">N/A";
+					}
+					else
+					{
+						if ((strcasecmp($featureName, "5' cloning site") != 0) && (strcasecmp($featureName, "3' cloning site") != 0) && (strcasecmp($featureName, "5' linker") != 0) && (strcasecmp($featureName, "3' linker") != 0))
+						{
+							if ($isProtein)
+								echo $rprint_obj->print_property_final($genPrefix . $fAlias . "_:_" . $featureValue . "_start_" . $fStart . "_end_" . $fEnd . $genPostfix, $featureName, $featureValue, $rID, true, "Protein Sequence Features", "", "", $rType, $readonly, $fDescr, $fStart, $fEnd);
+							else if ($isRNA)
+								echo $rprint_obj->print_property_final($genPrefix . $fAlias . "_:_" . $featureValue . "_start_" . $fStart . "_end_" . $fEnd . $genPostfix, $featureName, $featureValue, $rID, true, "RNA Sequence Features", "", "", $rType, $readonly, $fDescr, $fStart, $fEnd);
+							else
+								echo $rprint_obj->print_property_final($genPrefix . $fAlias . "_:_" . $featureValue . "_start_" . $fStart . "_end_" . $fEnd . $genPostfix, $featureName, $featureValue, $rID, true, "DNA Sequence Features", "", "", $rType, $readonly, $fDescr, $fStart, $fEnd);
+						}
+						else
+						{
+							if ($from_primer || $modify)
+								$readonly = false;
+
+							// DNA OK here, only DNA sequences have cloning sites
+							if ($rType && $rID <= 0)
+								echo $rprint_obj->print_property_final($genPrefix . $rType . "_" . $fAlias . $genPostfix, $featureName, $featureValue, $rID, true, "DNA Sequence Features", "", "", $rType, $readonly);
+							else
+								echo $rprint_obj->print_property_final($genPrefix . $fAlias . $genPostfix, $featureName, $featureValue, $rID, true, "DNA Sequence Features", "", "", $rType, $readonly);
+
+							if (isset($_GET["ErrCode"]) && ($_GET["ErrCode"] == 1))
+							{
+								if (isset($_GET["R1"]) && (strcasecmp($featureName, "5' cloning site") == 0) && (strcasecmp($featureValue, $_GET["R1"]) == 0))
+									echo "<BR><SPAN style=\"color:#FF0000; font-size:7pt;\">Site not found on " . $rType . " sequence at the specified positions.  Please verify your input.</span>";
+							
+								if (isset($_GET["R2"]) && (strcasecmp($featureName, "3' cloning site") == 0) && (strcasecmp($featureValue, $_GET["R2"]) == 0))
+									echo "<BR><SPAN style=\"color:#FF0000; font-size:7pt;\">Site not found on " . $rType . " sequence at the specified positions.  Please verify your input.</span>";
+							}
+						}
+
+/* put back when fix alignment, looks terrible otherwise
+						if (strcasecmp($featureName, "5' cloning site") == 0)
+						{
+							?><BR><div id="fp_warning" style="display:none; color:#FF0000">Please select a value for the 5' restriction site from the dropdown list</div><?php
+						}
+						else if (strcasecmp($featureName, "3' cloning site") == 0)
+						{
+							?><div id="tp_warning" style="display:none; color:#FF0000">Please select a value for the 3' restriction site from the dropdown list</div><?php
+						}*/
+					}
+				?>
+			</TD>
+
+			<TD style="padding-left:7px; font-size:7pt; white-space:nowrap;">
+				<?php
+					echo $rprint_obj->print_feature_descriptor($genPrefix, $genPostfix, $featureName, $fDescr, $featureValue, $fStart, $fEnd, $rID, true, "", $subtype, $rType, false);
+				?>
+			</TD>
+
+			<TD style="text-align:left; font-size:7pt; padding-right:2px; padding-left:7px; white-space:nowrap;">
+				<?php
+					// Start position - posType 1 means start
+					if ((strcasecmp($featureName, "5' cloning site") != 0) && (strcasecmp($featureName, "3' cloning site") != 0) && (strcasecmp($featureName, 'cdna insert') != 0) && (strcasecmp($featureName, "5' linker") != 0) && (strcasecmp($featureName, "3' linker") != 0))
+					{
+						// Oct. 26/09
+						if ($rID <= 0)
+							$startFieldName = $genPrefix . $rType . "_" . $fAlias . "_:_" . $featureValue . "_start_" . $fStart . "_end_" . $fEnd . "_startpos" . $genPostfix;
+						else
+							$startFieldName = $genPrefix . $fAlias . "_:_" . $featureValue . "_start_" . $fStart . "_end_" . $fEnd . "_startpos" . $genPostfix;
+
+						$readonly = false;
+					}
+					else
+					{
+						// Jan. 9, 2012, Marina: Enable site positions on Novel Vector
+						if (strcasecmp($subtype, "novel") == 0)
+						{
+							$readonly = false;
+						}
+						else
+						{		
+							if ((strcasecmp($featureName, 'cdna insert') != 0) && (strcasecmp($featureName, "5' linker") != 0) && (strcasecmp($featureName, "3' linker") != 0))
+							{
+								// Nov. 6/08
+								if ($from_primer || $modify)
+									$readonly = false;
+								else
+									$readonly = true;
+							}
+							else
+								$readonly = false;
+						}
+						
+						// Oct. 26/09
+						if ($rID <= 0)
+							$startFieldName = $genPrefix . $rType . "_" . $fAlias . "_startpos" . $genPostfix;
+						else
+							$startFieldName = $genPrefix . $fAlias . "_startpos" . $genPostfix;
+
+					}
+				
+					$rprint_obj->print_feature_position($startFieldName, $fAlias, 1, $featureValue, $fStart, $readonly);
+				?>
+			</TD>
+
+			<TD style="text-align:left; padding-right:2px; font-size:7pt; padding-left:7px; white-space:nowrap;">
+				<?php
+					// End position - posType 0 means end
+					if ((strcasecmp($featureName, "5' cloning site") != 0) && (strcasecmp($featureName, "3' cloning site") != 0) && (strcasecmp($featureName, 'cdna insert') != 0) && (strcasecmp($featureName, "5' linker") != 0) && (strcasecmp($featureName, "3' linker") != 0))
+					{
+						// Oct. 26/09
+						if ($rID <= 0)
+							$endFieldName = $genPrefix . $rType . "_" . $fAlias . "_:_" . $featureValue . "_start_" . $fStart . "_end_" . $fEnd . "_endpos" . $genPostfix;
+						else
+							$endFieldName = $genPrefix . $fAlias . "_:_" . $featureValue . "_start_" . $fStart . "_end_" . $fEnd . "_endpos" . $genPostfix;
+
+						$readonly = false;
+					}
+					else
+					{
+						// Jan. 9, 2012, Marina: Enable site positions on Novel Vector
+						if (strcasecmp($subtype, "novel") == 0)
+						{
+							$readonly = false;
+						}
+						else
+						{
+							if (strcasecmp($featureName, 'cdna insert') != 0 && (strcasecmp($featureName, "5' linker") != 0) && (strcasecmp($featureName, "3' linker") != 0))
+							{
+								// Nov. 6/08
+								if ($from_primer || $modify)
+									$readonly = false;
+								else
+									$readonly = true;
+							}
+							else
+								$readonly = false;
+						}
+
+						// Oct. 26/09
+						if ($rID <= 0)
+							$endFieldName = $genPrefix . $rType . "_" . $fAlias . "_endpos" . $genPostfix;
+						else
+							$endFieldName = $genPrefix . $fAlias . "_endpos" . $genPostfix;
+
+					}
+
+					$rprint_obj->print_feature_position($endFieldName, $fAlias, 0, $featureValue, $fEnd, $readonly);
+				?>
+			</TD>
+
+			<TD style="text-align:left; padding-left:5px; padding-right:5px; font-size:7pt; white-space:nowrap;">
+				<?php
+					// June 6/08: Direction not needed for cDNA feature
+					// Nov. 3/08: NEEDED IF INSERT IS REVERSE COMPLEMENTED!!!!!!!!!!!!!
+					if ((strcasecmp($featureName, "5' cloning site") != 0) && (strcasecmp($featureName, "3' cloning site") != 0) && (strcasecmp($featureName, "5' linker") != 0) && (strcasecmp($featureName, "3' linker") != 0) && (strcasecmp($featureName, "cdna insert") != 0))
+					{
+						// Oct. 26/09
+						if ($rID <= 0)
+							$dirFieldName = $genPrefix . $rType . "_" . $fAlias . "_:_" . $featureValue . "_start_" . $fStart . "_end_" . $fEnd . "_orientation" . $genPostfix;
+						else
+							$dirFieldName = $genPrefix . $fAlias . "_:_" . $featureValue . "_start_" . $fStart . "_end_" . $fEnd . "_orientation" . $genPostfix;
+					}
+					else
+					{
+						// Oct. 26/09
+						if ($rID <= 0)
+							$dirFieldName = $genPrefix . $rType . "_" . $fAlias . "_orientation" . $genPostfix;
+						else
+							$dirFieldName = $genPrefix . $fAlias . "_orientation" . $genPostfix;
+
+					}
+					
+					$rprint_obj->print_feature_direction($dirFieldName, $fAlias, $featureValue, $fDir);
+				?>
+			</TD>
+			
+			<TD style="background-color:#FFFFFF;">
+			<?php
+				// Oct. 26/09
+				if ($rID <= 0)
+					$row_name = $rType . "_" . $fAlias;
+				else
+					$row_name = $fAlias;
+
+				if ((strcasecmp($featureName, "cdna insert") != 0) && (strcasecmp($featureName, "5' cloning site") != 0) && (strcasecmp($featureName, "3' cloning site") != 0))
+				{
+					?><SPAN class="linkShow" style="font-size:7pt; margin-left:5px; font-weight:normal;" onClick="deleteTableRow('<?php echo $propsTbl_id; ?>', '<?php echo $row_name; ?>_:_row_<?php echo addslashes($featureValue); ?>_start_<?php echo $fStart; ?>_end_<?php echo $fEnd; ?>');">Remove</SPAN><?php
+				}
+
+				else
+				{
+					// cDNA and cloning sites - non-mandatory for reagents other than Vector and Insert
+					if (($rType == "Vector") || ($rType == "Insert"))
+					{
+						?><SPAN class="linkDisabled" style="font-size:7pt; margin-left:5px; font-weight:normal;">Remove</SPAN><?php
+					}
+					else
+					{
+						?><SPAN class="linkShow" style="font-size:7pt; margin-left:5px; font-weight:normal;" onClick="deleteTableRow('<?php echo $propsTbl_id; ?>', '<?php echo $row_name; ?>_:_row_<?php echo addslashes($featureValue); ?>_start_<?php echo $fStart; ?>_end_<?php echo $fEnd; ?>');">Remove</SPAN><?php
+					}
+				}
+			?>
+			</td>
+		</TR>
+		<?php
+	}
+
+
+	// May 1/08: Select features from database and print them out
+	// Nov. 6/08: Added $modify parameter to differentiate between creation and modification views.  On modification sites should not be disabled
+	/**
+	 * Select features from database and print them out.
+	 *
+	 * This is a special output function for sequence features that relies heavily on Javascript.  User selects feature names from a dropdown list, and they are appended dynamically to the output table (new table rows are generated using Javascript and assigned separate identifiers, so that features of the same type having different values and positions can be saved correctly).
+	 *
+	 * Nov. 6/08: Added $modify parameter to differentiate between creation and modification views.  On modification sites should not be disabled.
+	 *
+	 * @param STRING
+	 * @param STRING
+	 * @param INT
+	 * @param INT
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-05-23
+	 *
+	*/
+	function printFeatures($rType, $subtype, $rID=-1, $seqID, $form_name="", $from_primer=false, $modify=false, $propsTbl_id="modifyReagentPropsTbl")
+	{
+		global $hostname;
+		global $cgi_path;
+		global $conn;
+
+		$gfunc_obj = new generalFunc_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+		$rprint_obj = new Reagent_Output_Class();
+
+		$genPrefix = "reagent_detailedview_";
+		$genPostfix = "_prop";
+
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+
+		// Numerical db IDs of parents (parent1 is PV while parent2 can be either Insert or IPV)
+		$parent1 = -1;
+		$parent2 = "";
+
+		$isProtein = $rfunc_obj->hasAttribute($_SESSION["ReagentType_Name_ID"][$rType], "protein sequence", $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]);
+
+		$isRNA = $rfunc_obj->hasAttribute($_SESSION["ReagentType_Name_ID"][$rType], "rna sequence", $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence"]);
+
+		// First output existing features and then give option list to select more
+		?>
+			<span style="font-size:10pt; color:#FF0000; font-weight:bold;">
+				Fields marked with a red asterisk (*) are mandatory
+			</span>
+		
+			<!-- Crucial: set the ID of the table - otherwise JS won't add features -->
+			<!-- July 22/09: Replaced modifyReagentPropsTbl with $table_id -->
+			<TABLE ID="<?php echo $propsTbl_id; ?>" style="width:700px; margin-top:4px; border:1px groove black; background-color:#FFFFFF;" cellpadding="2px" cellspacing="4px">
+				<TR style="background-color:#C1FFC1;">
+					<TD style="text-align:center; font-weight:bold; text-decoration:underline;">Name</TD>
+					<TD style="text-align:center; font-weight:bold; text-decoration:underline;">Value</TD>
+					<TD style="text-align:center; font-weight:bold; text-decoration:underline;">Descriptor</TD>
+					<TD style="text-align:center; font-weight:bold; text-decoration:underline; padding-right:10px;">Start</TD>
+					<TD style="text-align:center; font-weight:bold; text-decoration:underline; padding-right:10px;">End</TD>
+					<TD style="text-align:center; font-weight:bold; text-decoration:underline;">Orientation</TD>
+					<TD style="background-color:#FFFFFF; width:25px;"></TD>
+				<TR/>
+				<?php
+
+				$v_features = $rfunc_obj->getReagentFeatures($rType, $subtype);
+				$vfSet = "";
+			
+				foreach ($v_features as $fID => $fName)
+				{
+					if (strlen($vfSet) == 0)
+						$vfSet .= $fID;
+					else
+						$vfSet .= "," . $fID;
+				}
+
+				// May 23/08: Display features in specific order (sites together, linkers together, cDNA separately, rest sorted AB-ly)
+				$cloning_sites = array();
+				$linkers = array();
+				$cdnaInsert = new SeqFeature();
+		
+				if ($rID && $rID > 0)
+				{
+					$query = "SELECT propertyID, propertyValue, descriptor, startPos, endPos, direction FROM ReagentPropList_tbl WHERE reagentID=" . $rID . " AND status='ACTIVE' AND propertyID IN (" . $vfSet . ")";
+	
+					$feature_rs = mysql_query($query, $conn) or die("Could not select reagent features: " . mysql_error());
+				}
+				else
+				{
+					$feature_rs = $v_features;
+				}
+	
+				while ($features = mysql_fetch_array($feature_rs, MYSQL_ASSOC))
+				{
+					$featureID = $features["propertyID"];
+					$featureValue = $features["propertyValue"];
+					$fDescr = $features["descriptor"];
+					$fStart = $features["startPos"];
+					$fEnd = $features["endPos"];
+					$fDir = $features["direction"];
+	
+					$featureName = $_SESSION["ReagentProp_ID_Name"][$rfunc_obj->findPropertyInCategoryID($featureID)];
+	
+					// May 23/08: Use Feature object for sorting
+					$fTemp = new SeqFeature($featureName, $featureValue, $fStart, $fEnd, $fDir, $fDescr);
+	
+					// Group features to display in a certain order
+					if (strcasecmp($featureName, "5' cloning site") == 0)
+					{
+						// Cloning sites - Updated Nov. 18/08: Assign $_GET values if set FOR NON-RECOMBINATION VECTORS ONLY!!!!!!!!!!!!!!!!!
+						if (strcasecmp($subtype, 'nonrecomb') == 0)
+						{
+							if (isset($_GET["R1"]))
+							{
+								$fpcs = $_GET["R1"];
+								$fpStart = $_GET["FPS"];
+								$fpEnd = $_GET["FPE"];
+								$fTemp = new SeqFeature("5' cloning site", $fpcs, $fpStart, $fpEnd);
+								$cloning_sites["5' cloning site"] = $fTemp;
+							}
+		
+							else
+								$cloning_sites["5' cloning site"] = $fTemp;
+						}
+						else
+							$cloning_sites["5' cloning site"] = $fTemp;
+					}
+					else if (strcasecmp($featureName, "3' cloning site") == 0)
+					{
+						if (strcasecmp($subtype, 'nonrecomb') == 0)
+						{
+							if (isset($_GET["R2"]))
+							{
+								$tpcs = $_GET["R2"];
+								$tpStart = $_GET["TPS"];
+								$tpEnd = $_GET["TPE"];
+								$fTemp = new SeqFeature("3' cloning site", $tpcs, $tpStart, $tpEnd);
+								$cloning_sites["3' cloning site"] = $fTemp;
+							}
+							else
+								$cloning_sites["3' cloning site"] = $fTemp;
+						}
+						else
+							$cloning_sites["3' cloning site"] = $fTemp;
+					}
+					else if (strcasecmp($featureName, "5' linker") == 0)
+						$linkers["5' linker"] = $fTemp;
+	
+					else if (strcasecmp($featureName, "3' linker") == 0)
+						$linkers["3' linker"] = $fTemp;
+					
+					else if (strcasecmp($featureName, "cdna insert") == 0)
+						$cdnaInsert = $fTemp;
+					
+					else
+						$tmp_features[$featureName][] = $fTemp;		// Here, use an array, b/c the printFeatures function from ColFuncOutputer_Class that takes care of multiple values is not called, so we're responsible for selecting and printing multiple feature values
+				}
+			
+				// Change April 22, 2010: Don't sort features by name, sort by order in which they are assigned to this reagent type - same code as in OutputClass (see below)
+	
+				// April 21, 2010: SORT properties in order assigned to this reagent type
+				$tmp_order_list = Array();
+				$reagentType = $_SESSION["ReagentType_Name_ID"][$rType];
+			
+				foreach ($tmp_features as $fName => $feature)
+				{
+					$fID = $_SESSION["ReagentProp_Name_ID"][$fName];
+	
+					if ($isProtein)
+						$fCatID = $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence Features"];
+					else if($isRNA)
+						$fCatID = $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence Features"];
+					else
+						$fCatID = $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"];
+	
+					$fPropCatID = $rfunc_obj->getPropertyIDInCategory($fID, $fCatID);
+	
+					$fOrd = $rfunc_obj->getReagentTypePropertyOrdering($reagentType, $fPropCatID);
+					$tmp_order_list[$fPropCatID] = $fOrd;
+				}
+	
+				// April 22, 2010: Print properties in their assigned order
+				$psorted = Array();
+				
+				sort(array_values($tmp_order_list));
+	
+				foreach ($tmp_order_list as $pcID => $pOrd)
+				{
+						$tmp_sorted = Array();
+						$tmp_sorted = $psorted[$pOrd];
+						$tmp_sorted[] = $pcID;
+						$psorted[$pOrd] = $tmp_sorted;
+				}
+	
+				// First print cDNA positions, followed by sites, linkers, and the rest	
+				if ($rType == 'Vector')
+				{
+					if ($subtype != 'novel')
+					{
+						$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, "5' cloning site", $cloning_sites["5' cloning site"], true, $from_primer, $modify, $propsTbl_id);
+						$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, "3' cloning site", $cloning_sites["3' cloning site"], true, $from_primer, $modify, $propsTbl_id);
+		
+						$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, "cdna insert", $cdnaInsert, false, $from_primer, $modify, $propsTbl_id);
+		
+						$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, "5' linker", $linkers["5' linker"], false, $from_primer, $modify, $propsTbl_id);
+						$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, "3' linker", $linkers["3' linker"], false, $from_primer, $modify, $propsTbl_id);
+		
+						foreach ($tmp_features as $f => $features)
+						{
+							//sort($features, SORT_STRING);
+		
+							foreach ($features as $fKey => $feature)
+							{
+								$featureName = $feature->getFeatureType();
+	
+								// actual output value (takes care of case issues)
+								$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, $featureName, $feature, false, $from_primer, $modify, $propsTbl_id);
+							}
+						}
+					}
+					else
+					{
+						// May 22/08: Give option to select cloning sites for Novel Vectors
+						// output an empty enzyme selection list for 5' site
+						$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, "5' cloning site", $cloning_sites["5' cloning site"], false, $from_primer, $modify, $propsTbl_id);
+		
+						$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, "3' cloning site", $cloning_sites["3' cloning site"], false, $from_primer, $modify, $propsTbl_id);
+		
+						// row separator
+						echo "<TR><TD colspan=\"6\"><TD></TR>";
+		
+						// rest of the features - modified April 22, 2010 to print features in assigned order
+						for ($i = 1; $i <= max(array_keys($psorted)); $i++)
+						{
+							$pList = $psorted[$i];
+			
+							foreach ($pList as $ind => $propCatID)
+							{
+								$fID = $rfunc_obj->findPropertyInCategoryID($propCatID);
+								$fName =  $_SESSION["ReagentProp_ID_Name"][$fID];
+								$features = $tmp_features[$fName];
+		
+								foreach ($features as $fInd => $feature)
+								{
+									$featureName = $feature->getFeatureType();
+		
+									// actual output value (takes care of case issues)
+									$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, $featureName, $feature, false, $from_primer, $modify, $propsTbl_id);
+								}
+							}
+						}
+					}
+				}
+				else
+				{
+					if (!$isProtein && !$isRNA)
+					{
+						// updated Nov. 6/08 - added $from_primer and $modify arguments to function call
+						if ($rfunc_obj->hasAttribute($_SESSION["ReagentType_Name_ID"][$rType], "5' cloning site", $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]))
+							$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, "5' cloning site", $cloning_sites["5' cloning site"], true, $from_primer, $modify, $propsTbl_id);
+	
+						if ($rfunc_obj->hasAttribute($_SESSION["ReagentType_Name_ID"][$rType], "3' cloning site", $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]))
+							$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, "3' cloning site", $cloning_sites["3' cloning site"], true, $from_primer, $modify, $propsTbl_id);
+			
+						if ($rfunc_obj->hasAttribute($_SESSION["ReagentType_Name_ID"][$rType], "cdna insert", $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]))
+							$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, "cdna insert", $cdnaInsert, false, $from_primer, $modify, false, true, $propsTbl_id);
+			
+						if ($rfunc_obj->hasAttribute($_SESSION["ReagentType_Name_ID"][$rType], "5' linker", $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]))
+							$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, "5' linker", $linkers["5' linker"], false, $from_primer, $modify, $propsTbl_id);
+	
+						if ($rfunc_obj->hasAttribute($_SESSION["ReagentType_Name_ID"][$rType], "3' linker", $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]))
+							$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, "3' linker", $linkers["3' linker"], false, $from_primer, $modify, $propsTbl_id);
+					}
+	
+	
+					for ($i = 1; $i <= max(array_keys($psorted)); $i++)
+					{
+						$pList = $psorted[$i];
+		
+						foreach ($pList as $ind => $propCatID)
+						{
+							$fID = $rfunc_obj->findPropertyInCategoryID($propCatID);
+							$fName =  $_SESSION["ReagentProp_ID_Name"][$fID];
+							$features = $tmp_features[$fName];
+	
+							foreach ($features as $fKey => $feature)
+							{
+								$featureName = $feature->getFeatureType();
+		
+								// actual output value (takes care of case issues)
+								$this->outputFeaturesTable($rType, $subtype, $rID, $genPrefix, $genPostfix, $featureName, $feature, false, $from_primer, $modify, $propsTbl_id, $isProtein, $isRNA);
+							}
+						}
+					}
+				}
+	
+				// Oct. 26/09
+				if ($rID <= 0)
+				{
+					$createNew = "true";
+					$prop_prefix = $rType . "_";
+				}
+				else
+				{
+					$createNew = "false";
+					$prop_prefix = "";
+				}
+
+				?>
+				<TR><TD colspan="7"><HR></TD></TR>
+				<TR><TD colspan="7"></TD></TR>
+
+				<!-- Row to add features -->
+				<TR ID="addlPropsListRow_<?php echo $rType; ?>">
+					<TD colspan="5" style="font-weight:bold; white-space:nowrap">
+						Select Additional Features:
+
+						<SELECT ID="sequence_property_names_<?php echo $rType; ?>" NAME="sequencePropertyNames" onChange="showPropertyValues2(this.id, '<?php echo str_replace("'", "\'", $form_name); ?>', '<?php echo str_replace("'", "\'", $propsTbl_id); ?>', '<?php echo str_replace("'", "\'", $rType); ?>', '<?php echo $createNew; ?>');" style="font-size:7pt">
+							<OPTION VALUE="default">-- Select More Features --</OPTION>
+							<?php
+								$fText = "";
+
+								foreach ($v_features as $key => $fName)
+								{
+									$f_id = $rfunc_obj->findPropertyInCategoryID($key);
+									$fDescr = $_SESSION["ReagentProp_ID_Desc"][$f_id];
+									$fAlias = $_SESSION["ReagentProp_ID_Alias"][$f_id];
+
+									// Sites and cDNA can only occur once; rest of features can occur > 1s
+									// June 13/08: Remove linkers too
+									if ( (strcasecmp($fName, "5' cloning site") != 0) && (strcasecmp($fName, "3' cloning site") != 0) && (strcasecmp($fName, "cdna insert") != 0) && (strcasecmp($fName, "5' linker") != 0) && (strcasecmp($fName, "3' linker") != 0) && (strcasecmp($fName, "tag position") != 0) && (strcasecmp($fName, "expression system") != 0))
+
+										echo "<OPTION VALUE=\"" . $fAlias . "\">" . $fDescr . "</OPTION>";
+								}
+							?>
+						</SELECT>
+					</TD>
+				</TR>
+
+				<TR><TD colspan="7"></TD></TR>
+
+				<!-- TEMPLATE FEATURE VALUES LISTS - DO NOT REMOVE!!!! -->
+				<?php
+					foreach ($v_features as $key => $fName)
+					{
+						// Update Nov. 3/09
+						$f_id = $rfunc_obj->findPropertyInCategoryID($key);
+						$fDescr = $_SESSION["ReagentProp_ID_Desc"][$f_id];
+						$fAlias = $_SESSION["ReagentProp_ID_Alias"][$f_id];
+
+						?><tr id="<?php echo $prop_prefix . $fAlias; ?>_attribute" style="display:none">
+							<td class="detailedView_colName"><?php echo $fDescr; ?></td>
+					
+							<INPUT TYPE="hidden" ID="<?php echo $rType . "_" . $fAlias . "_descr"; ?>" VALUE="<?php echo $fDescr; ?>">
+
+							<td class="detailedView_value" style="white-space:nowrap;"><?php
+
+								echo "<SELECT ID=\"" . $prop_prefix . $fAlias . "_:_list\" SIZE=\"1\">";
+
+							if ($isProtein)
+								echo $rprint_obj->print_Set_Final_Dropdown($fName, "", "Protein Sequence Features", $_SESSION["ReagentType_Name_ID"][$rType]);
+
+							else if ($isRNA)
+								echo $rprint_obj->print_Set_Final_Dropdown($fName, "", "RNA Sequence Features", $_SESSION["ReagentType_Name_ID"][$rType]);
+							else
+								echo $rprint_obj->print_Set_Final_Dropdown($fName, "", "DNA Sequence Features", $_SESSION["ReagentType_Name_ID"][$rType]);
+						echo "</select>";
+							?></td>
+						</tr><?php
+					}
+
+					// also feature descriptors
+					$f_descriptors = $rfunc_obj->getFeatureDescriptors();
+
+					// $fd in this case is the name of the main property; $fName is the name of the descriptor
+					// E.g. $fd == 'tag type', $fName == 'tag position'
+					foreach ($f_descriptors as $fd => $fName)
+					{
+						$fd_id = $_SESSION["ReagentProp_Name_ID"][$fName];
+						$fdDescr = $_SESSION["ReagentProp_ID_Desc"][$fd_id];
+						$fdAlias = $_SESSION["ReagentProp_ID_Alias"][$fd_id];
+
+						?><tr id="<?php echo $prop_prefix . $fdAlias; ?>_attribute" style="display:none">
+							<td class="detailedView_value" style="white-space:nowrap;"><?php
+								echo "<SELECT ID=\"" . $prop_prefix . $fdAlias . "_:_list\" SIZE=\"1\">";
+									if ($isProtein)
+										echo $rprint_obj->print_Set_Final_Dropdown($fName, "", "Protein Sequence Features", $_SESSION["ReagentType_Name_ID"][$rType]);
+									if ($isRNA)
+										echo $rprint_obj->print_Set_Final_Dropdown($fName, "", "RNA Sequence Features", $_SESSION["ReagentType_Name_ID"][$rType]);
+									else
+										echo $rprint_obj->print_Set_Final_Dropdown($fName, "", "DNA Sequence Features", $_SESSION["ReagentType_Name_ID"][$rType]);
+								echo "</select>";
+							?></td>
+						</tr><?php
+					}
+
+				?>
+			</TABLE>
+		<?php
+	}
+
+
+	/**
+	 * Step 2 of creation, show parents w/ option to change and sequence.
+	 * May 12/08: Renamed to previewReagentSequence - use for all reagent types
+	 *
+	 * @param STRING
+	 * @param STRING
+	 * @param INT
+	 * @param INT
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-04-28
+	 *
+	*/
+	function previewReagentSequence($rType, $subtype, $rID, $seqID)
+	{
+		global $hostname;
+		global $cgi_path;
+
+		$gfunc_obj = new generalFunc_Class();
+		$rprint_obj = new Reagent_Output_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+
+		$genPrefix = "reagent_detailedview_";
+		$genPostfix = "_prop";
+
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+
+		// Numerical db IDs of parents (parent1 is PV while parent2 can be either Insert or IPV)
+		$parent1 = -1;
+		$parent2 = "";
+
+		?>
+		<!-- updated Nov. 5/08 - added 'subtype' parameter -->
+		<FORM NAME="reagentSeqPreview" method="POST" action="<?php echo $cgi_path . "preload.py"; ?>" onSubmit="return verifyReagentSequenceCreation('<?php echo $rType; ?>', '<?php echo $subtype; ?>');">
+
+			<!-- Pass user info to Python as hidden form value - Aug 21/07 -->
+			<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+			
+			<!-- Pass reagent info -->
+			<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $rType; ?>">
+			<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+			<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+			<INPUT TYPE="hidden" NAME="seq_id_hidden" VALUE="<?php echo $seqID; ?>">
+			<?php
+				switch ($rType)
+				{
+					case 'Vector':
+						switch($subtype)
+						{
+							case 'nonrecomb':
+							case 'gateway_entry':
+								$pvID = $_GET["PV"];
+								$insertID = $_GET["I"];
+		
+								$parent1 = $pvID;
+								$parent2 = $insertID;
+		
+								# Jan. 21/09: if Insert was reverse complemented, cDNA (and other features??), in order to be mapped correctly, need to be RCd too (only applies to NR vectors)
+								if (isset($_GET["Rev"]) && ($_GET["Rev"] == 'True'))
+								{
+									$rev = true;
+									echo "<INPUT TYPE=\"hidden\" NAME=\"reverse_complement\" VALUE=\"" . $rev . "\">";
+								}
+
+								?>
+									<table width="770px" cellpadding="4">
+										<tr>
+											<td style="text-align:center; padding-left:70px; font-weight:bold;">
+												<span style="color:#00C00D; font-size:13pt; padding-bottom:18px;">
+												<?php
+													if ($subtype == 'nonrecomb')
+														echo "CREATE A NON-RECOMBINATION VECTOR";
+													else if ($subtype == 'gateway_entry')
+														echo "CREATE A GATEWAY ENTRY VECTOR";
+												?>
+												<BR>
+												</span>
+							
+												<span style="color:#00B38D; font-size:10pt;">
+													Step 2 of 4: Confirm Sequence
+												</span>	
+											</td>
+
+											<!-- nov. 5/08 -->
+											<TD style="text-align:right; padding-right:15px;">
+												<input type="submit" name="confirm_features" value="Continue" onClick="document.getElementById('cancel_set').value=0; document.getElementById('navigate_away').value=0;">
+						
+												 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+						
+												<INPUT type="hidden" ID="cancel_set" value="0">
+											</TD>
+										</tr>
+									</table>
+		
+									<!-- Pass parent info as hidden form input to CGI -->
+									<INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentAssoc_Name_Alias"]["vector parent id"] . $genPostfix; ?>" VALUE="<?php echo $pvID; ?>">
+									<INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentAssoc_Name_Alias"]["insert id"] . $genPostfix; ?>" VALUE="<?php echo $insertID; ?>">
+
+									<!-- Nov. 18/08: Pass sites to CGI too, as hidden input -->
+									<?php
+										if (isset($_GET["R1"]))
+										{
+											?><INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentProp_Name_Alias"]["5' cloning site"] . $genPostfix; ?>" VALUE="<?php echo $_GET["R1"]; ?>"><?php
+										}
+
+										if (isset($_GET["R2"]))
+										{
+											?><INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentProp_Name_Alias"]["3' cloning site"] . $genPostfix; ?>" VALUE="<?php echo $_GET["R2"]; ?>"><?php
+										}	
+							break;
+		
+							case 'recomb':
+							case 'gateway_expression':
+								$pvID = $_GET["PV"];
+								$ipvID = $_GET["IPV"];
+		
+								$parent1 = $pvID;
+								$parent2 = $ipvID;
+
+								?>
+									<table width="750px" cellpadding="4">
+										<tr>
+											<td colspan="2" style="text-align:center; font-weight:bold;">
+												<span style="color:#00C00D; font-size:13pt; padding-bottom:18px;">
+												<?php
+													if ($subtype == 'recomb')
+														echo "CREATE AN EXPRESSION VECTOR";
+													else if ($subtype == 'gateway_expression')
+														echo "CREATE A GATEWAY EXPRESSION VECTOR";
+												?>
+												<BR>
+												</span>
+							
+												<span style="color:#00B38D; font-size:10pt;">
+													Step 2 of 4: Confirm Sequence
+												</span>	
+											</td>
+
+											<!-- nov. 5/08 -->
+											<TD style="text-align:right; padding-right:15px;">
+												<input type="submit" name="confirm_features" value="Continue" onClick="document.getElementById('cancel_set').value=0; document.getElementById('navigate_away').value=0;">
+						
+												 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+						
+												<INPUT type="hidden" ID="cancel_set" value="0">
+											</TD>
+										</tr>
+									</table>
+									<P>
+
+									<!-- Pass parent info as hidden form input to CGI -->
+									<INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentAssoc_Name_Alias"]["vector parent id"] . $genPostfix; ?>" VALUE="<?php echo $pvID; ?>">
+		
+									<INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentAssoc_Name_Alias"]["parent insert vector"] . $genPostfix; ?>" VALUE="<?php echo $ipvID; ?>">
+								<?php
+							break;
+		
+							case 'novel':
+								?>
+								<table width="750px" cellpadding="4">
+									<tr>
+										<td colspan="2" style="text-align:center; font-weight:bold;">
+											<span style="color:#00C00D; font-size:13pt; margin-left:150px; padding-bottom:18px;">
+												CREATE A NOVEL (PARENT) VECTOR
+												<BR>
+											</span>
+						
+											<span style="color:#00B38D; font-size:10pt; margin-left:150px;">
+												Step 1 of 3: Confirm Sequence:
+											</span>
+										</td>
+
+										<!-- nov. 5/08 -->
+										<TD style="text-align:right; padding-right:15px;">
+
+											<input type="submit" name="confirm_features" value="Continue" onClick="document.getElementById('cancel_set').value=0; document.getElementById('navigate_away').value=0;">
+											
+											 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+					
+											<INPUT type="hidden" ID="cancel_set" value="0">
+										</TD>
+									</tr>
+								</table>
+								<?php
+							break;
+						}
+					break;
+
+					case 'Insert':
+						$pivID = $_GET["PIV"];
+						$senseID = $_GET["SO"];
+						$antisenseID = $_GET["AS"];
+		
+						$parent1 = $pivID;
+						$parent2 = $senseID;
+						$parent3 = $antisenseID;
+
+						?>
+						<!-- Pass parent info as hidden form input to CGI -->
+						<INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentAssoc_Name_Alias"]["insert parent vector id"] . $genPostfix; ?>" VALUE="<?php echo $pivID; ?>">
+
+						<INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentAssoc_Name_Alias"]["sense oligo"] . $genPostfix; ?>" VALUE="<?php echo $senseID; ?>">
+
+						<INPUT TYPE="hidden" NAME="<?php echo $genPrefix . $_SESSION["ReagentAssoc_Name_Alias"]["antisense oligo"] . $genPostfix; ?>" VALUE="<?php echo $antisenseID; ?>">
+
+						<table width="750px" cellpadding="4">
+							<tr>
+								<td colspan="2" style="text-align:center; font-weight:bold; padding-left:220px">
+									<span style="color:#00C00D; font-size:13pt; padding-bottom:18px;">
+										CREATE A NEW INSERT
+										<BR>
+									</span>
+				
+									<span style="color:#00B38D; font-size:10pt;">
+										Step 2 of 4: Confirm Sequence
+									</span>
+								</td>
+
+								<!-- nov. 5/08 -->
+								<TD style="text-align:right; padding-right:15px;">
+									<input type="submit" name="confirm_features" value="Continue" onClick="document.getElementById('cancel_set').value=0; document.getElementById('navigate_away').value=0;">
+
+									 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+			
+									<INPUT type="hidden" ID="cancel_set" value="0">
+								</TD>
+							</tr>
+						</table>
+						<?php
+					break;
+				}
+
+				$this->printParents($rType, $subtype, $readonly, $parent1, $parent2, $parent3);
+			?>
+			<BR>
+
+			<TABLE style="width:750px; margin-top:4px; margin-left:10px;">
+				<TH colspan="2" style="padding-left:2px; text-align:left; font-size:10pt;">Sequence:</TH>
+
+				<TR>
+					<td colspan="2">
+					<?php
+						switch ($rType)
+						{
+							case 'Insert':
+								?>
+								<table width="760px" cellpadding="4">
+									<tr>
+										<td style="font-size:9pt;">
+											Please paste your insert sequence in the box below, <b>including <u>intact cloning sites</u> and any <u>linking sequences</u> between the cloning sites and the start of the cDNA sequence:</b>
+
+<!-- 											<span class="linkShow" style="padding-left:10px;font-size:8pt; font-weight:normal;">View Example</span> -->
+
+											  <A href="pictures/insert_example.png" onClick="return popup(this, 'diagram', '665', '635', 'yes')">View example</A>
+										</td>
+									</tr>
+								
+									<tr>
+										<td colspan="4">
+											<?php
+												$rprint_obj->print_property_final($genPrefix . "sequence" . $genPostfix, "sequence", $seqID, "", true, "DNA Sequence", "Preview", "", $rType, false);
+											?>
+											<BR><div id="sequence_warning" style="display:none; color:#FF0000">Please paste a sequence in the textbox above.</div>
+										</td>
+									</tr>
+								</table>
+								<BR>
+									
+								<table width="760px" cellpadding="4">
+									<tr>
+										<td colspan="4" style="font-size:9pt;">
+											<b>Please specify cloning sites on the insert:</b><BR>
+										</td>
+									</tr>
+							
+									<TR>
+										<TD width="150px" style="padding-left:10px">
+											5' Cloning Site:
+										</TD>
+							
+										<TD style="padding-top:10px;">
+											<?php
+												$five_site = $rfunc_obj->getPropertyValue($rid, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["5' cloning site"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]));
+
+												$rprint_obj->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"]["5' cloning site"] . $genPostfix, "5' cloning site", $five_site, "", true, "DNA Sequence Features", "", "insert");
+											?>
+											<BR><div id="fp_warning" style="display:none; color:#FF0000">Please select a value for the 5' restriction site from the dropdown list</div>
+										</TD>
+									</TR>
+							
+									<TR>
+										<TD style="padding-left:10px">
+											3' Cloning Site:
+										</TD>
+							
+										<TD>
+											<?php
+												$three_site = $rfunc_obj->getPropertyValue($rid, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["3' cloning site"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]));
+
+												$rprint_obj->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"]["3' cloning site"] . $genPostfix, "3' cloning site",$three_site, "", true, "DNA Sequence Features", "", "insert");
+											?>
+											<BR><div id="tp_warning" style="display:none; color:#FF0000">Please select a value for the 3' restriction site from the dropdown list</div>
+										</TD>
+									</TR>
+
+									<TR><TD></td></tr>
+
+									<TR>
+										<TD colspan="2" style="border:1px solid purple; padding-left:7px; vertical-align:full; padding-right:10px; padding-left:10px; padding-bottom:10px; text-align:justify; padding-top:10px; font-weight:bold; color:green; font-size:9pt;">Cloning sites will be mapped onto their positions on the sequence at the next step.  If the sites cannot be found on the sequence, their positions will be set to 0.</TD>
+									</TR>
+								</table>
+								<?php
+							break;
+
+							default:
+								// don't pass $rID as a parameter here b/c there's no PropList_tbl entry at this point - output function will do a select query and return nothing
+								$rprint_obj->print_property_final($genPrefix . "sequence" . $genPostfix, "sequence", $seqID, "", "Preview", true, "DNA Sequence", "");
+								?>
+								<BR><div id="vector_sequence_warning" style="display:none; color:#FF0000">Please paste a sequence in the textbox above.</div>
+								<?php
+							break;
+						}
+						?>
+					</td>
+				</TR>
+			</TABLE>
+		</FORM>
+		<?php
+	}
+	
+
+	/**
+	 * Just OUTPUT parents table.
+	 *
+	 * @param STRING
+	 * @param STRING
+	 * @param boolean
+	 * @param INT
+	 * @param INT
+	 * @param INT
+	 * @param boolean
+	 *
+	 * @author Marina Olhovsky
+	*/
+	function printParents($rType, $subtype, $readonly=false, $parent1=-1, $parent2=-1, $parent3=-1, $from_primer=false)
+	{
+		$gfunc_obj = new generalFunc_Class();
+		$rprint_obj = new Reagent_Output_Class();
+
+		$genPrefix = "reagent_detailedview_";
+		$genPostfix = "_prop";
+
+		$classname = $readonly ? "creation_readonly" : "creation_normal";
+
+		$rID = $_GET["rID"];	// Nov. 5/08
+
+		if (!$readonly)
+			echo "<table style=\"margin-top:5px; margin-left:10px;\" cellpadding=\"4\">";
+		else
+			echo "<table style=\"width:725px; margin-top:5px; margin-left:10px; background-color:#F9F9F9; border:1px solid black; padding:5px;\" cellpadding=\"4\">";
+
+			switch ($rType)
+			{
+				case 'Vector':
+					switch($subtype)
+					{
+						case 'nonrecomb':
+						case 'gateway_entry':
+							$pvID = $parent1;
+							$insertID = $parent2;
+	
+							?>
+								<tr>
+									<td style="padding-left:10px; padding-right:10px; font-size:9pt; width:125px; white-space:nowrap;">
+									<?php
+										// correction May 20, 2010
+										if ($subtype == "gateway_entry")
+											echo "Gateway Parent Donor Vector ID:";
+										else
+											echo "Parent Vector ID:";
+									?>
+									<!-- Parent Vector ID -->
+									</td>
+				
+									<td style="white-space:nowrap">
+									<?php
+										if (!$readonly)
+											echo "<input type=\"text\" onKeyPress=\"return disableEnterKey(event);\" readonly=\"true\"  style=\"background-color:#E8E8E8;\" value=\"" . strtoupper($gfunc_obj->getConvertedID_rid($pvID)) . "\">";
+										else
+										{
+											echo "<A target=\"blank\" HREF=\"Reagent.php?View=6&rid=" . $pvID . "\">" . strtoupper($gfunc_obj->getConvertedID_rid($pvID)) . "</A>";
+										}
+	
+										?>
+									</td>
+								</tr>
+							
+								<tr>
+									<td style="padding-left:10px; font-size:9t;">
+										Insert ID:
+									</td>
+			
+									<td style="white-space:nowrap">
+									<?php
+										if (!$readonly)
+											echo "<input type=\"text\" onKeyPress=\"return disableEnterKey(event);\" readonly=\"true\"  style=\"background-color:#E8E8E8;\" value=\"" . strtoupper($gfunc_obj->getConvertedID_rid($insertID)) . "\">";
+										else
+										{
+											echo "<A target=\"blank\" HREF=\"Reagent.php?View=6&rid=" . $insertID . "\">" . strtoupper($gfunc_obj->getConvertedID_rid($insertID)) . "</A>";
+										}
+									?>
+									</td>
+								</tr>
+	
+								<TR>
+									<td colspan="2">
+										<a style="font-size:9pt; padding-left:5px; font-weight:normal;" href="<?php echo $hostname . "Reagent.php?View=2&Type=Vector&Sub=" . $subtype . "&PV=" . strtoupper($gfunc_obj->getConvertedID_rid($pvID)) . "&I=" . strtoupper($gfunc_obj->getConvertedID_rid($insertID)) . "&rID=" . $rID; ?>">Go back and edit parent values</a>
+									</td>
+								</tr>
+								<?php
+							break;
+		
+							case 'recomb':
+							case 'gateway_expression':
+								$pvID = $parent1;
+								$ipvID = $parent2;
+		
+								?>
+								<tr>
+									<td colspan="2" style="font-size:11pt; font-weight:bold;">
+										Parents:
+
+										<a style="font-size:10pt; font-weight:normal; margin-left:25px;" href="<?php echo $hostname . "Reagent.php?View=2&Type=Vector&Sub=" . $subtype . "&PV=" . strtoupper($gfunc_obj->getConvertedID_rid($pvID)) . "&IPV=" . strtoupper($gfunc_obj->getConvertedID_rid($ipvID)) . "&rID=" . $rID; ?>">Go back and edit parent values</a>
+									<td>
+								</tr>
+								
+								<tr>
+									<td>
+										<table width="500px" style="background-color:#D1D1D1; margin-top:5px;" cellpadding="4" border="1" frame="box" rules="all">
+											<tr>
+												<td style="white-space:nowrap">
+												<?php
+													// correction May 20, 2010
+													if ($subtype == "gateway_expression")
+														echo "Gateway Parent Destination Vector ID:";
+													else
+														echo "Creator Acceptor ID:";
+												?>
+									
+<!-- 													Parent Vector ID -->
+												</td>
+							
+												<td style="white-space:nowrap">
+													<input type="text" onKeyPress="return disableEnterKey(event);"  readonly="<?php echo $readonly; ?>"  style="background-color:#E8E8E8;" value="<?php echo strtoupper($gfunc_obj->getConvertedID_rid($pvID)); ?>">
+												</td>
+											</tr>
+						
+											<tr>
+												<td style="white-space:nowrap">
+												<?php
+													// correction May 20, 2010
+													if ($subtype == "gateway_expression")
+														echo "Gateway Entry Vector ID:";
+													else
+														echo "Creator Donor Vector ID:";
+													?>
+<!-- 													Insert Parent Vector ID -->
+												</td>
+						
+												<td style="white-space:nowrap">
+													<input type="text" onKeyPress="return disableEnterKey(event);"  readonly="<?php echo $readonly; ?>" value="<?php echo strtoupper($gfunc_obj->getConvertedID_rid($ipvID)); ?>" style="background-color:#E8E8E8;">
+												</td>
+											</tr>
+										</table>
+									</td>
+								</tr>
+								<?php
+							break;
+						}
+					break;
+
+					case 'Insert':
+						$pivID = $parent1;
+						$senseID = $parent2;
+						$antisenseID = $parent3;
+
+						// Nov. 5/08
+						if ($from_primer)
+						{
+							?>
+							<tr>
+								<TD>
+								</td>
+							</tr>
+							<?php
+						}
+						?>
+						<tr>
+							<td colspan="2" style="font-size:11pt; font-weight:bold;">
+								Parents:
+								<?php
+									// Nov. 5/08
+									if (!$from_primer)
+									{
+										?>
+										<a style="font-size:10pt; font-weight:normal; margin-left:10px;" href="<?php echo $hostname . "Reagent.php?View=2&Type=Insert&PIV=" . $pivID . "&SO=" . $senseID . "&AS=" . $antisenseID . "&rID=" . $rID; ?>">Go back and edit parent values</a>
+										<?php
+									}
+									?>
+							</td>
+						</tr>
+						
+						<tr>
+							<td>
+								<table width="500px" style="background-color:#D1D1D1; margin-top:5px;" cellpadding="4" border="1" frame="box" rules="all">
+									<tr>
+										<td style="white-space:nowrap">
+											Sense Oligo ID
+										</td>
+				
+										<td style="white-space:nowrap">
+											<input type="text" onKeyPress="return disableEnterKey(event);" readonly="<?php echo $readonly; ?>" value="<?php echo strtoupper($senseID); ?>" style="background-color:#E8E8E8;">
+										</td>
+									</tr>
+
+									<tr>
+										<td style="white-space:nowrap">
+											Antisense Oligo ID
+										</td>
+				
+										<td style="white-space:nowrap">
+											<input type="text" onKeyPress="return disableEnterKey(event);" readonly="<?php echo $readonly; ?>" value="<?php echo strtoupper($antisenseID); ?>" style="background-color:#E8E8E8;">
+										</td>
+									</tr>
+
+									<tr>
+										<td style="white-space:nowrap">
+											Insert Parent Vector ID
+										</td>
+
+										<td style="white-space:nowrap">
+										<?php
+											// Nov. 5/08
+											if (!$from_primer)
+											{
+												?>
+												<input type="text" onKeyPress="return disableEnterKey(event);" readonly="<?php echo $readonly; ?>" style="background-color:#E8E8E8;" value="<?php echo strtoupper($pivID); ?>">
+												<?php
+											}
+											else
+											{
+												?>
+												<!-- hard-code name, selection trivial -->
+												<input type="text" onKeyPress="return disableEnterKey(event);" name="<?php echo $genPrefix . "insert_parent_vector" . $genPostfix; ?>" value="<?php echo strtoupper($pivID); ?>">
+												<?php
+											}
+										?>
+										</td>
+									</tr>
+									<?php
+										if ($from_primer)
+										{
+											echo "(Please input Insert Parent Vector ID if known)";
+										}
+									?>
+				
+								</table>
+							</td>
+						</tr>
+						<?php
+					break;
+				}
+			?>
+		</table>
+		<?php
+	}
+
+
+	/**
+	 * Print Vector creation form (don't dare delete!!!!!!!!!!!!!!!!)
+	 *
+	 * @param STRING
+	 * @param STRING
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-04-14
+	*/
+	function printForm_Vector_Create($rType, $subtype)
+	{
+		global $cgi_path;
+
+		// Form input
+		$genPrefix = "reagent_detailedview_";
+		$genPostfix = "_prop";
+
+		$assoc_prefix = "assoc_";
+		$assocPostfix = "_hidden";
+
+		// Property names
+		$v_name = $this->rfunc_obj->get_Post_Names("Vector", "");
+
+		// Object Instatiations
+		$gfunc_obj = new generalFunc_Class();
+		$rprint_obj = new Reagent_Output_Class();
+		
+		// User info
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+
+		switch ($subtype)
+		{
+			case 'novel':
+				?>
+				<!-- Pass user info to Python as hidden form value - Aug 21/07 -->
+				<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>"> 
+				<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $rType; ?>">
+				<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+				<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+				<input type="hidden" id="vector_cloning_method" name="cloning_method_hidden" value="<?php echo $cloningMethod; ?>">
+
+				<!-- MAY 2/08: IF RETURNING TO THIS VIEW FROM A LATER PAGE TO CHANGE PARENTS - PASS THE REAGENT ID TO PYTHON!!!!!! -->
+				<?php
+					if (isset($_GET["rID"]))
+					{
+						?>
+							<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $_GET["rID"]; ?>">
+						<?php
+					}
+				?>
+				<table width="680px" cellpadding="4">
+					<tr>
+						<td style="text-align:center">
+							<span style="color:#00C00D; font-size:13pt; font-weight:bold">
+								CREATE A NEW PARENT (NOVEL) VECTOR
+							</span>
+						</td>
+					</tr>
+				</table>
+		
+				<table border="1" width="600px" cellpadding="4" frame="box" rules="none">
+					<tr>
+						<td style="font-size:9pt; padding-left:10px;">
+							<b>Step 1 of 3:</b><BR><P><span style="padding-left:5px;">Please paste your Vector sequence in the box below<!--, <b>including <u>intact cloning sites</u> and any <u>linking sequences</u> between the cloning sites and the start of the cDNA sequence:</b>-->:</span>
+						</td>
+					</tr>
+				
+					<tr>
+						<td>
+							<?php
+								$rprint_obj->print_property_final($genPrefix . $v_name["sequence"] . $genPostfix, "sequence", "", "Preview", true, "DNA Sequence", "");
+							?>
+							<BR><div id="vector_sequence_warning" style="display:none; color:#FF0000">Please paste a sequence in the textbox above.</div>
+						</td>
+					</tr>
+				</table>
+				<BR>
+				
+				<table style="padding-top:10px;">
+					<TR>
+						<td style="padding-left:0px;">
+							<input type="submit" name="confirm_features" value="Continue" onClick="document.getElementById('cancel_set').value=0; return verifyNovelVectorSequence(); document.getElementById('navigate_away').value=0;">
+						</td>
+					</tr>
+					
+				</table>
+				<?php
+			break;
+		}
+	}
+
+
+	/**
+	 * Final Insert creation step from Primer Designer
+	 *
+	 * @param INT
+	 * @param INT
+	 * @param STRING sense oligo ID, e.g. O123
+	 * @param STRING antisense oligo ID, e.g. O123
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-05-14
+	*/
+	function previewInsertIntroPrimer($rID, $seqID, $sense, $antisense)
+	{
+		global $hostname;
+		global $cgi_path;
+
+		$gfunc_obj = new generalFunc_Class();
+		$rprint_obj = new Reagent_Output_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+
+		// May 5/08: Use a different prefix - make uniform for all reagent types and for dynamic features
+		$genPrefix = "reagent_detailedview_";
+		$genPostfix = "_prop";
+
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+
+		$reagent_name = $rfunc_obj->get_Post_Names("Insert", "Primer General");
+
+		// When creating Insert from Primer, most of its general properties, annotations and classifiers have already been preloaded from parents and saved.  Only need to provide a name for the Insert, a project ID, description, verification, comments; optionally a Parent Vector
+
+		?>
+		<FORM NAME="reagentDetailForm" method="POST" action="<?php echo $cgi_path . "create.py"; ?>">
+
+			<input type="hidden" ID="changeStateIntro" name="change_state" value="Save">
+			<input type="hidden" name="save_intro">
+
+			<INPUT TYPE="hidden" NAME="from_primer" VALUE="True">
+
+			<!-- Pass user info to Python as hidden form value - Aug 21/07 -->
+			<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+			<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="Insert">
+			<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+			<INPUT TYPE="hidden" NAME="seq_id_hidden" VALUE="<?php echo $seqID; ?>">
+			<?php
+
+			$senseID = $_GET["SO"];
+			$antisenseID = $_GET["AS"];
+			$pivID = $_GET["PIV"];
+
+			?>
+			<table width="780px" cellpadding="4">
+				<tr>
+					<td colspan="2" style="text-align:center; font-weight:bold;">
+						<span style="color:#00C00D; font-size:13pt; padding-bottom:18px;">
+							INSERT CREATION
+							<BR>
+						</span>
+	
+						<span style="color:#00B38D; font-size:10pt;">
+							Step 4 of 4: Confirm General Properties
+						</span>
+
+						<BR>
+			
+						<a onclick="document.getElementById('navigate_away').value=0;" href="<?php echo $hostname . "Reagent.php?View=2&Step=4&Type=Insert&SO=" . $senseID . "&AS=" . $antisenseID . "&PIV=" . $pivID . "&rID=" . $rID . "&Seq=" . $seqID; ?>">Go back and edit features</a>
+
+					</td>
+
+					<!-- nov. 5/08 -->
+					<TD style="text-align:right; padding-right:15px;">
+						<input type="submit" name="confirm_intro" value="Continue" onClick="document.pressed='Create'; document.getElementById('cancel_set').value=0; selectAllPropertyValues(true); return checkMandatoryProps('Insert'); document.getElementById('navigate_away').value=0;">
+
+						 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+
+						<INPUT type="hidden" ID="cancel_set" value="0">
+					</TD>
+				</tr>
+
+				<TR>
+					<TD colspan="2" style="text-align:center; font-weight:bold;">
+						<span style="font-size:9pt; color:#FF0000; font-weight:bold;">
+							Fields marked with a red asterisk (*) are mandatory
+						</span>
+					</TD>
+				</TR>
+			</table>
+
+			<P>
+			<?php
+
+			$rType = "Insert";
+			$rTypeID = $_SESSION["ReagentType_Name_ID"]["Insert"];
+
+			// find the attributes of this reagent type
+			$categories = $rfunc_obj->findAllReagentTypeAttributeCategories($rTypeID);
+
+			echo "<P><HR><TABLE>";
+
+			foreach ($categories as $categoryID => $category)
+			{
+				if (($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]) && ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence Features"]) && ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence Features"]) && ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]) && ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]) && ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["RNA Se [...]
+				{
+					$rTypeAttributes = $rfunc_obj->getReagentTypeAttributesByCategory($rTypeID, $categoryID);
+
+					if (count($rTypeAttributes) == 0)
+						continue;
+
+					$catAlias = $_SESSION["ReagentPropCategory_ID_Alias"][$categoryID];
+
+					echo "<TR>";
+						echo "<TD style=\"padding-left:5px;\">";
+							echo "<table style=\"background-color:#FFFFFF;\">";
+								// Aug. 19/09: Changed categoryID to catAlias, since that is also the name of the table in addNewReagentType() and JS was confusing between the two
+								echo "<tr>";
+									echo "<td style=\"font-weight:bold; color:blue; padding-top:2px;\">";
+										echo "<IMG id=\"" . $catAlias . "_expand_img_" . $rType . "\" SRC=\"pictures/arrow_collapse.gif\" WIDTH=\"20\" HEIGHT=\"15\" BORDER=\"0\" ALT=\"plus\" class=\"menu-expanded\" style=\"display: inline\" onClick=\"showHideCategory('" . $catAlias . "', '" . $rType . "');\">";
+
+										echo "<IMG id=\"" . $catAlias . "_collapse_img_" . $rType . "\" SRC=\"pictures/arrow_expand.gif\" WIDTH=\"40\" HEIGHT=\"34\" BORDER=\"0\" ALT=\"plus\" class=\"menu-collapsed\" style=\"display: none\" onClick=\"showHideCategory('" . $catAlias . "', '" . $rType . "');\">";
+
+										echo "<span id=\"section_title_" . $catAlias . "\">" . $category . "</span>";
+									echo "</TD>";
+								echo "</TR>";
+
+								echo "<tr>";
+									echo "<td style=\"padding-left:20px;\">";
+										echo "<table ID=\"category_" . $catAlias . "_section_" . $rType . "\" cellpadding=\"4\" cellspacing=\"2\" style=\"background-color:#FFFFFF; margin-top:4px;\">";
+
+										foreach ($rTypeAttributes as $attrID => $cProp)
+										{
+											$propDescr = $cProp->getPropertyDescription();
+											$propAlias = $cProp->getPropertyAlias();
+											$propName = $cProp->getPropertyName();
+											$propCategory = $cProp->getPropertyCategory();
+
+											// May 5, 2010
+											$p_id = $_SESSION["ReagentProp_Name_ID"][$propName];
+											$c_id = $_SESSION["ReagentPropCategory_Name_ID"][$propCategory];
+											$pID = $rfunc_obj->getPropertyIDInCategory($p_id, $c_id);
+
+											if (!in_array($propName, $ignoreList))
+											{
+												echo "<TR style=\"background-color:#F5F5DC;\">";
+
+													echo "<TD style=\"padding-left:15px; padding-right:15px; font-size:8pt; width:100px; font-weight:bold; white-space:nowrap;\">" . $propDescr;
+
+													$tmp_pc_id = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][$propName], $_SESSION["ReagentPropCategory_Name_ID"][$propCategory]);
+
+													if ( ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["name"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"])) || ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["project id"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"])) || (strcasecmp($propName, "packet id") == 0) || (strcasecmp($propName, "owner") == 0) || ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SESSION [...]
+													{
+														// March 3, 2011
+														if (strcasecmp($propName, "open/closed") == 0)
+															echo " <span style=\"font-size:9pt; color:#FF0000; font-weight:bold\">*</span>  <IMG src=\"" . $hostname . "pictures/hm4.png\" HEIGHT=\"13\" width=\"16\" ALT=\"link_icon\" style=\"vertical-align:middle; cursor:auto\" onmouseover=\"return overlib('Select the correct open/closed value to ensure correct translation of the DNA sequence to protein.  Refer to the \'Translation Guidelines\' for more information.', CAPTION, 'Open/Closed', STICKY);\">";
+
+														else if (strcasecmp($propName, "type of insert") == 0)
+															echo " <span style=\"font-size:9pt; color:#FF0000; font-weight:bold\">*</span>  <IMG src=\"" . $hostname . "pictures/hm4.png\" HEIGHT=\"13\" width=\"16\" ALT=\"link_icon\" style=\"vertical-align:middle; cursor:auto\" onmouseover=\"return overlib('Select the correct type of insert value to ensure correct translation of the DNA sequence to protein.  Refer to the \'Translation Guidelines\' for more information.', CAPTION, 'Type of Insert', STICKY);\">";
+														
+														else
+															echo " <span style=\"font-size:9pt; color:#FF0000; font-weight:bold\">*</span></TD>";
+// echo $rType . "_mandatoryProps[]";
+
+														echo "<INPUT TYPE=\"hidden\" NAME=\"" . $rType . "_mandatoryProps[]\" VALUE=\"" . $attrID . "\">";
+
+
+														// When checking open/closed, need to pass type of insert to Javascript so it can be checked too
+														if (strcasecmp($propName, "type of insert") == 0)
+														{
+															$openClosedAttrID = $rfunc_obj->getRTypeAttributeID($rTypeID, "open/closed", $categoryID);
+
+															// echo $openClosedAttrID;
+															echo "<INPUT TYPE=\"hidden\" ID=\"Insert_open_closed_prop\" VALUE=\"" . $openClosedAttrID . "\">";
+														}
+
+														else if (strcasecmp($propName, "open/closed") == 0)
+														{
+															$iTypeAttrID = $rfunc_obj->getRTypeAttributeID($rTypeID, "type of insert", $categoryID);
+
+															// echo $openClosedAttrID;
+															echo "<INPUT TYPE=\"hidden\" ID=\"Insert_type_of_insert_prop\" VALUE=\"" . $iTypeAttrID . "\">";
+														}
+													}
+													else if ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["alternate id"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]))
+													{
+														echo "<BR><BR><span style=\"font-size:8pt;\">For 'Other', please enter<BR> the database name and<BR> numeric identifier, separated<BR> by semicolon, in the textbox<BR> (e.g. 'IMAGE:123456')</span></TD>";
+													}
+													else
+													{
+														echo "</TD>";
+													}
+
+													echo "<TD style=\"font-size:8pt; padding-left:10px; width:600px;\">";
+
+													// March 10/10: preload properties from parent
+													$pVal = $rfunc_obj->getPropertyValue($rID, $tmp_pc_id);
+													$rprint_obj->print_property_final($genPrefix . $rType . "_" . $catAlias . "_:_" . $propAlias . $genPostfix, $propName, $pVal, "", true, $propCategory, "Preview", "", $rType, false, "", 0, 0);
+
+													echo "</TD>";
+												echo "</TR>";
+											}
+										}
+
+										echo "</TABLE>";
+									echo "</TD>";
+								echo "</TR>";
+							echo "</TABLE>";
+
+							echo "<BR>";
+
+						echo "</TD>";
+					echo "</TR>";
+
+					echo "<TR><TD colspan=\"2\" style=\"padding-left:5px; border-top:1px solid black;\"><BR></TD></TR>";
+				}
+			}
+
+			echo "</TABLE>";
+		?>
+		</FORM>
+		<?php
+	}
+
+
+	/**
+	 * Final step in creation - ONLY show form to enter general info, DON'T show sequence/features (too much, too messy)
+	 *
+	 * @param STRING
+	 * @param STRING
+	 * @param INT
+	 * @param INT
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-05-05
+	*/
+	function previewReagentIntro($rType, $subtype, $rID, $seqID)
+	{
+		global $hostname;
+		global $cgi_path;
+		global $conn;
+
+		$gfunc_obj = new generalFunc_Class();
+		$rprint_obj = new Reagent_Output_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+
+		// May 5/08: Use a different prefix - make uniform for all reagent types and for dynamic features
+		$genPrefix = "reagent_detailedview_";
+		$genPostfix = "_prop";
+
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+
+		// Numerical db IDs of parents (parent1 is PV while parent2 can be either Insert or IPV)
+		$parent1 = -1;
+		$parent2 = "";
+
+		$allAttrs = $rfunc_obj->getAllReagentTypeAttributes($_SESSION["ReagentType_Name_ID"][$rType]);
+
+		// get cloning method (ATypeID)
+		$query = "SELECT * FROM Association_tbl WHERE reagentID='" . $rID . "' AND status='ACTIVE'";
+
+		$cloning_method_rs = mysql_query($query, $conn) or die("Could not determine cloning method: " . mysql_error());
+
+		if ($cloning_method_ar = mysql_fetch_array($cloning_method_rs, MYSQL_ASSOC))
+		{
+			$cloningMethod = $cloning_method_ar["ATypeID"];
+		}
+		else
+		{
+			$cloningMethod = 3;	// hard-code BASIC cloning method - parent vector
+		}
+
+		mysql_free_result($cloning_method_rs);
+		unset($cloning_method_ar);
+
+		?>
+		<!-- Pass user info to Python as hidden form value - Aug 21/07 -->
+		<FORM NAME="reagentDetailForm" method="POST" action="<?php echo $cgi_path . "create.py"; ?>">
+
+			<input type="hidden" ID="changeStateVectorIntro" name="change_state" value="Save">
+			<input type="hidden" name="save_intro">
+
+			<!-- Pass user info to Python as hidden form value - Aug 21/07 -->
+			<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+			<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $_GET["Type"]; ?>">
+			<INPUT TYPE="hidden" NAME="subtype_hidden" VALUE="<?php echo $subtype; ?>">
+			<INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $rID; ?>">
+			<input type="hidden" id="vector_cloning_method" name="cloning_method_hidden" value="<?php echo $cloningMethod; ?>">
+			<INPUT TYPE="hidden" NAME="seq_id_hidden" VALUE="<?php echo $seqID; ?>">
+			<?php
+				switch ($rType)
+				{
+					case 'Vector':
+						switch($subtype)
+						{
+							case 'nonrecomb':
+							case 'gateway_entry':
+								$pvID = $_GET["PV"];
+								$insertID = $_GET["I"];
+		
+								$parent1 = $pvID;
+								$parent2 = $insertID;
+
+								?>
+								<table width="780px" cellpadding="4">
+									<tr>
+										<td colspan="2" style="text-align:center; padding-left:200px; font-weight:bold;">
+											<span style="color:#00C00D; font-size:13pt; padding-bottom:18px;">
+												<?php
+													if ($subtype == 'nonrecomb')
+														echo "CREATE A NON-RECOMBINATION VECTOR";
+													else if ($subtype == 'gateway_entry')
+														echo "CREATE A GATEWAY ENTRY VECTOR";
+												?>
+												<BR>
+											</span>
+						
+											<span style="color:#00B38D; font-size:10pt;">
+												Step 4 of 4: Confirm General Properties
+											</span>
+										</td>
+ 										<!-- nov. 5/08 -->
+										<TD style="text-align:right; padding-right:15px;">
+											<input type="submit" name="confirm_intro" value="Continue" onClick="document.pressed='Create'; document.getElementById('cancel_set').value=0; enableSites(); changeFieldNames('reagentDetailForm', null, '<?php echo $rType; ?>'); setFeaturePositions(); verifyPositions(); selectAllPropertyValues(true); return checkMandatoryProps('<?php echo $_GET["Type"]; ?>', '<?php echo $subtype; ?>'); document.getElementById('navigate_away').value=0;">
+					
+											 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+					
+											<INPUT type="hidden" ID="cancel_set" value="0">
+										</TD>
+									</tr>
+								</table>
+								<?php
+							break;
+		
+							case 'recomb':
+							case 'gateway_expression':
+								$pvID = $_GET["PV"];
+								$ipvID = $_GET["IPV"];
+		
+								$parent1 = $pvID;
+								$parent2 = $ipvID;
+		
+								?>
+								<table width="780px" cellpadding="4">
+									<tr>
+										<td colspan="2" style="text-align:center; padding-left:200px; font-weight:bold;">
+											<span style="color:#00C00D; font-size:13pt; padding-bottom:18px; margin-left:150px;">
+												<?php
+													if ($subtype == 'recomb')
+														echo "CREATE AN EXPRESSION VECTOR";
+													else if ($subtype == 'gateway_expression')
+														echo "CREATE A GATEWAY EXPRESSION VECTOR";
+												?>
+												<BR>
+											</span>
+						
+											<span style="color:#00B38D; font-size:10pt;">
+												Step 4 of 4: Confirm General Properties
+											</span>
+										</td>
+
+										<!-- nov. 5/08 -->
+										<TD style="text-align:right; padding-right:15px;">
+											<input type="submit" name="confirm_intro" value="Continue" onClick="document.pressed='Create'; document.getElementById('cancel_set').value=0; enableSites(); changeFieldNames('reagentDetailForm', null, '<?php echo $rType; ?>'); setFeaturePositions(); verifyPositions(); selectAllPropertyValues(true); return checkMandatoryProps('<?php echo $_GET["Type"]; ?>', '<?php echo $subtype; ?>'); document.getElementById('navigate_away').value=0;">
+					
+											 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+					
+											<INPUT type="hidden" ID="cancel_set" value="0">
+										</TD>
+									</tr>
+								</table>
+								<?php
+							break;
+
+							default:
+								?>
+								<table width="780px" cellpadding="4">
+									<tr>
+										<td style="text-align:center; font-weight:bold;">
+											<span style="color:#00C00D; font-size:13pt; padding-bottom:18px; margin-left:150px;">CREATE NOVEL VECTOR<BR></span>
+						
+											<span style="color:#00B38D; font-size:10pt; margin-left:150px;">
+												Step 3 of 3: Confirm General Properties
+											</span>
+										</td>
+
+										<!-- nov. 5/08 -->
+										<TD style="text-align:right; padding-right:15px;">
+											<input type="submit" name="confirm_intro" value="Continue" onClick="document.pressed='Create'; document.getElementById('cancel_set').value=0; enableSites(); changeFieldNames('reagentDetailForm', null, '<?php echo $rType; ?>'); setFeaturePositions(); verifyPositions(); selectAllPropertyValues(true); return checkMandatoryProps('<?php echo $_GET["Type"]; ?>', '<?php echo $subtype; ?>'); document.getElementById('navigate_away').value=0;">
+
+											 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+					
+											<INPUT type="hidden" ID="cancel_set" value="0">
+										</TD>
+									</tr>
+								</table>
+								<?php
+							break;
+						}
+					break;
+
+					case 'Insert':
+						$pivID = $_GET["PIV"];
+						$senseID = $_GET["SO"];
+						$antisenseID = $_GET["AS"];
+
+						$parent1 = $pivID;
+						$parent2 = $senseID;
+						$parent3 = $antisenseID;
+
+						?>
+						<table style="width:780px" cellpadding="4">
+							<tr>
+								<td style="text-align:center; padding-left:200px; font-weight:bold;">
+									<span style="color:#00C00D; font-size:13pt;  padding-bottom:18px;">
+										CREATE AN INSERT
+										<BR>
+									</span>
+				
+									<span style="color:#00B38D; font-size:10pt;">
+										Step 4 of 4: Confirm General Properties
+									</span>
+								</td>
+
+								<!-- nov. 5/08 -->
+								<TD style="text-align:right; padding-right:15px;">
+									<input type="submit" name="confirm_intro" value="Continue" onClick="document.pressed='Create'; document.getElementById('cancel_set').value=0; document.pressed='Create'; enableSites(); changeFieldNames('reagentDetailForm', null, '<?php echo $rType; ?>'); setFeaturePositions(); verifyPositions(); selectAllPropertyValues(true); return checkMandatoryProps('<?php echo $_GET["Type"]; ?>', '<?php echo $subtype; ?>'); document.getElementById('navigate_away').value=0;">
+			
+									 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+			
+									<INPUT type="hidden" ID="cancel_set" value="0">
+								</TD>
+							</tr>
+						</table>
+						<?php
+					break;
+				}
+
+				?><TABLE cellpadding="2" width="700px">
+				<TR>
+					<TD style="padding-left:10px;">
+					<?php
+						switch ($rType)
+						{
+							case 'Vector':
+								switch($subtype)
+								{
+									case 'nonrecomb':
+									case 'gateway_entry':
+									?>
+										<a onclick="document.getElementById('navigate_away').value=0;" href="<?php echo $hostname . "Reagent.php?View=2&Step=2&Type=Vector&Sub=" . $subtype . "&PV=" . $pvID . "&I=" . $insertID . "&rID=" . $rID . "&Seq=" . $seqID . "&Rev=" . $_GET["Rev"]; ?>">Go back and edit features</a>
+									<?php
+									break;
+	
+									case 'recomb':
+									case 'gateway_expression':
+									?>
+										<a onclick="document.getElementById('navigate_away').value=0;" href="<?php echo $hostname . "Reagent.php?View=2&Step=2&Type=Vector&Sub=" . $subtype . "&PV=" . $pvID . "&IPV=" . $ipvID . "&rID=" . $rID . "&Seq=" . $seqID; ?>">Go back and edit features</a>
+									<?php
+									break;
+
+									case 'novel':
+									?>
+										<a onclick="document.getElementById('navigate_away').value=0;" href="<?php echo $hostname . "Reagent.php?View=2&Step=2&Type=Vector&Sub=" . $subtype . "&rID=" . $rID . "&Seq=" . $seqID; ?>">Go back and edit features</a>
+									<?php
+									break;
+								}
+							break;
+
+							case 'Insert':
+							?>
+								<a onclick="document.getElementById('navigate_away').value=0;" href="<?php echo $hostname . "Reagent.php?View=2&Step=2&Type=Insert&PIV=" . $pivID . "&SO=" . $senseID . "&AS=" . $antisenseID . "&rID=" . $rID . "&Seq=" . $seqID; ?>">Go back and edit features</a>
+							<?php
+							break;
+						}
+						?>
+					</TD>
+				</TR>
+			</TABLE>
+			<?php
+					$rTypeID = $_SESSION["ReagentType_Name_ID"][$rType];
+
+					// find the attributes of this reagent type
+					$categories = $rfunc_obj->findAllReagentTypeAttributeCategories($rTypeID);
+
+					echo "<P><HR><TABLE>";
+
+					foreach ($categories as $categoryID => $category)
+					{
+						if (($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]) && ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence Features"]) && ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence Features"]) && ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]) && ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]) && ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["RNA  [...]
+						{
+							$rTypeAttributes = $rfunc_obj->getReagentTypeAttributesByCategory($rTypeID, $categoryID);
+							
+							if (count($rTypeAttributes) == 0)
+								continue;
+
+							$catAlias = $_SESSION["ReagentPropCategory_ID_Alias"][$categoryID];
+
+							// print_r($rTypeAttributes);
+		
+							echo "<TR>";
+								echo "<TD style=\"padding-left:5px;\">";
+									echo "<table style=\"background-color:#FFFFFF;\">";
+										// Aug. 19/09: Changed categoryID to catAlias, since that is also the name of the table in addNewReagentType() and JS was confusing between the two
+										echo "<tr>";
+											echo "<td style=\"font-weight:bold; color:blue; padding-top:2px;\">";
+												echo "<IMG id=\"" . $catAlias . "_expand_img_" . $rType . "\" SRC=\"pictures/arrow_collapse.gif\" WIDTH=\"20\" HEIGHT=\"15\" BORDER=\"0\" ALT=\"plus\" class=\"menu-expanded\" style=\"display: inline\" onClick=\"showHideCategory('" . $catAlias . "', '" . $rType . "');\">";
+
+												echo "<IMG id=\"" . $catAlias . "_collapse_img_" . $rType . "\" SRC=\"pictures/arrow_expand.gif\" WIDTH=\"40\" HEIGHT=\"34\" BORDER=\"0\" ALT=\"plus\" class=\"menu-collapsed\" style=\"display: none\" onClick=\"showHideCategory('" . $catAlias . "', '" . $rType . "');\">";
+
+												echo "<span id=\"section_title_" . $catAlias . "\">" . $category . "</span>";
+											echo "</TD>";
+										echo "</TR>";
+
+										echo "<tr>";
+											echo "<td style=\"padding-left:20px;\">";
+												echo "<table ID=\"category_" . $catAlias . "_section_" . $rType . "\" cellpadding=\"4\" cellspacing=\"2\" style=\"background-color:#FFFFFF; margin-top:4px;\">";
+
+												// Update May 5, 2010: keys are now attrIDs
+												foreach ($rTypeAttributes as $attrID => $cProp)
+												{
+													$propDescr = $cProp->getPropertyDescription();
+													$propAlias = $cProp->getPropertyAlias();
+													$propName = $cProp->getPropertyName();
+													$propCategory = $cProp->getPropertyCategory();
+
+													// added May 5, 2010 just in case
+													$p_id = $_SESSION["ReagentProp_Name_ID"][$propName];
+													$c_id = $_SESSION["ReagentPropCategory_Name_ID"][$propCategory];
+													$pID = $rfunc_obj->getPropertyIDInCategory($p_id, $c_id);
+
+													if (!in_array($propName, $ignoreList))
+													{
+														echo "<TR style=\"background-color:#F5F5DC;\">";
+
+															echo "<TD style=\"padding-left:15px; padding-right:15px; font-size:8pt; width:100px; font-weight:bold; white-space:nowrap;\">" . $propDescr;
+
+															// Feb. 8/10
+															$tmp_pc_id = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][$propName], $_SESSION["ReagentPropCategory_Name_ID"][$propCategory]);
+
+															//if ( ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["name"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"])) || ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["project id"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"])) || (strcasecmp($propName, "packet id") == 0) || (strcasecmp($propName, "owner") == 0) || ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SES [...]
+															if ($rfunc_obj->isMandatory($rType, $propName))
+															{
+																// March 3, 2011
+																if (strcasecmp($propName, "open/closed") == 0)
+																	echo " <span style=\"font-size:9pt; color:#FF0000; font-weight:bold\">*</span>  <IMG src=\"" . $hostname . "pictures/hm4.png\" HEIGHT=\"13\" width=\"16\" ALT=\"link_icon\" style=\"vertical-align:middle; cursor:auto\" onmouseover=\"return overlib('Select the correct open/closed value to ensure correct translation of the DNA sequence to protein.  Refer to the \'Translation Guidelines\' for more information.', CAPTION, 'Open/Closed', STICKY);\">";
+
+																else if (strcasecmp($propName, "type of insert") == 0)
+																	echo " <span style=\"font-size:9pt; color:#FF0000; font-weight:bold\">*</span>  <IMG src=\"" . $hostname . "pictures/hm4.png\" HEIGHT=\"13\" width=\"16\" ALT=\"link_icon\" style=\"vertical-align:middle; cursor:auto\" onmouseover=\"return overlib('Select the correct type of insert value to ensure correct translation of the DNA sequence to protein.  Refer to the \'Translation Guidelines\' for more information.', CAPTION, 'Type of Insert', STICKY);\">";
+																
+																else
+																	echo " <span style=\"font-size:9pt; color:#FF0000; font-weight:bold\">*</span></TD>";
+
+																echo "<INPUT TYPE=\"hidden\" NAME=\"" . $rType . "_mandatoryProps[]\" VALUE=\"" . $attrID . "\">";
+
+																// When checking open/closed, need to pass type of insert to Javascript so it can be checked too
+																if (strcasecmp($propName, "type of insert") == 0)
+																{
+																	$openClosedAttrID = $rfunc_obj->getRTypeAttributeID($rTypeID, "open/closed", $categoryID);
+
+																	echo "<INPUT TYPE=\"hidden\" ID=\"Insert_open_closed_prop\" VALUE=\"" . $openClosedAttrID . "\">";
+																}
+
+																else if (strcasecmp($propName, "open/closed") == 0)
+																{
+																	$iTypeAttrID = $rfunc_obj->getRTypeAttributeID($rTypeID, "type of insert", $categoryID);
+
+																	echo "<INPUT TYPE=\"hidden\" ID=\"Insert_type_of_insert_prop\" VALUE=\"" . $iTypeAttrID . "\">";
+																}
+
+															}
+															else if ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["alternate id"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]))
+															{
+																echo "<BR><BR><span style=\"font-size:8pt;\">For 'Other', please enter<BR> the database name and<BR> numeric identifier, separated<BR> by semicolon, in the textbox<BR> (e.g. 'IMAGE:123456')</span></TD>";
+															}
+															else
+																echo "</TD>";
+
+															echo "<TD style=\"font-size:8pt; padding-left:10px; width:600px;\">";
+
+															$rprint_obj->print_property_final($genPrefix . $rType . "_" . $catAlias . "_:_" . $propAlias . $genPostfix, $propName, "", "", true, $propCategory, "Preview", "", $rType, false, "", 0, 0);
+
+															echo "</TD>";
+														echo "</TR>";
+													}
+												}
+
+												echo "</TABLE>";
+											echo "</TD>";
+										echo "</TR>";
+									echo "</TABLE>";
+
+									echo "<BR>";
+
+								echo "</TD>";
+							echo "</TR>";
+
+							echo "<TR><TD colspan=\"2\" style=\"padding-left:5px; border-top:1px solid black;\"><BR></TD></TR>";
+						}
+					}
+
+					echo "</TABLE>";
+			?></FORM>
+		</FORM>
+		<?php
+	}
+
+
+	/**
+	 * In this step, allow user to input Insert parents (May 12/08: Split Insert creation into steps, like Vector)
+	 *
+	 * @param INT
+	 * @param boolean
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-05-05
+	*/
+	function printForm_Insert_Insert($rID, $show)
+	{
+		if (isset($_GET["rID"]))
+		{
+			$rID = $_GET["rID"];
+		}
+
+		global $cgi_path;	// march 31/07, marina
+
+		$tablestyle = "";
+		$vectorcloningsites_style = "";
+		
+		// Object Instatiations
+		$gfunc_obj = new generalFunc_Class();
+		$rprint_obj = new Reagent_Output_Class();
+		
+		$rfunc_obj = new Reagent_Function_Class();
+		$rfunc_obj->reset_Reagent_Session();
+		
+		$insert_prefix = "INPUT_INSERT_info_";
+		$insert_postfix = "_prop";
+		$reagentTypeID = $_SESSION["ReagentType_Name_ID"]["Insert"];
+		
+		$il_names = $this->rfunc_obj->get_Post_Names("Insert", "");
+		$property_tmp = array();
+		$error_tmp = "";
+		$rid_tmp = 0;
+		
+		$vectorcloningsites_style = "style=\"visibility:hidden; display:none;\"";
+		
+		if( $show == false )
+		{
+			$tablestyle = "display:none";
+		}
+	
+		$assoc_prefix = "assoc_";
+
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+
+		$pivID = $_GET["PIV"];
+		$senseID = $_GET["SO"];
+		$antisenseID = $_GET["AS"];
+		
+		$parent1 = $pivID;
+		$parent2 = $senseID;
+		$parent3 = $antisenseID;
+		?>
+		<FORM method="POST" NAME="createReagentForm" action="<?php echo $cgi_path . "preload.py"; ?>" onsubmit="return verifyParents();">
+			<input type="hidden" name="reagentType" value="Insert">
+			<input type="hidden" name="reagent_id_hidden" value="<?php echo $rID; ?>">
+ 			<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+			<TABLE width="100%" id="insert_general_props" style="<?php echo $tablestyle; ?>">
+				<tr>
+					<td style="font-size:13pt;color:#00C00D; text-align:center; font-weight:bold">
+						CREATE A NEW INSERT
+					</td>
+				</tr>
+
+				<tr>
+					<td style="color:#00B38D; font-size:10pt; text-align:center; font-weight:bold">
+						Step 1 of 4: Define Parents
+						<BR>
+
+						<BR>
+						<SPAN style="font-size:9pt; font-weight:bold; color:#0000BD;">** This step is <u>optional</u> - if parent values are not known, you may leave this page blank and press 'Continue' to proceed to the next step **</SPAN>
+					</td>
+				</tr>
+			
+				<tr>
+					<td>
+						<TABLE width="100%" style="border: 1px outset black;" cellpadding="3">
+							<TR>
+								<TD colspan="2">
+									<span style="font-size:9pt; padding-left:5px; font-weight:bold; white-space:nowrap;">Please enter  OpenFreezer IDs of the reagents (Insert Parent Vector, Sense and Antisense Oligos) used to generate this Insert, if known:</span>
+								</td>
+							</tr>
+				
+							<TR>
+								<TD style="white-space:nowrap; padding-left:20px;">
+									Sense Oligo ID
+								</TD>
+				
+								<TD>
+									<input type="text" onKeyPress="return disableEnterKey(event);" size="5" id="insertSenseOligo" name="sense_oligo" style="margin-left:10px;" VALUE="<?php echo $senseID; ?>">
+								</TD>
+							</TR>
+				
+							<TR>
+								<TD style="white-space:nowrap; padding-left:20px;">
+									AntiSense Oligo ID
+								</TD>
+				
+								<TD>
+									<input type="text" onKeyPress="return disableEnterKey(event);" size="5" style="margin-left:10px;" id="insertAntisenseOligo" name="antisense_oligo" VALUE="<?php echo $antisenseID; ?>">
+								</TD>
+							</TR>
+				
+							<TR>
+								<TD style="white-space:nowrap; padding-left:20px;">
+									Insert Parent Vector ID
+								</TD>
+				
+								<TD>
+									<input type="text" onKeyPress="return disableEnterKey(event);" size="5" style="margin-left:10px;" id="insertParentVector" name="insert_parent_vector" VALUE="<?php echo $pivID; ?>">
+								</TD>
+							</TR>
+						</TABLE>
+					</TD>
+				</TR>
+
+				<TR>
+					<td colspan="2">
+						<input type="submit" name="preload" value="Continue" style="margin-top:5px; margin-left:2px;" onClick="document.getElementById('cancel_set').value=0; document.getElementById('navigate_away').value=0;">
+						<?php
+							// if returning to view from a later stage, add 'Cancel' button
+							if (isset($_GET["rID"]))
+							{
+								?>
+									 <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost'); document.getElementById('navigate_away').value=0;">
+
+									<INPUT type="hidden" ID="cancel_set" value="0">
+								<?php
+							}
+						?>
+					</td>
+				</tr>
+			</TABLE>
+		</FORM>
+		<?php
+	}
+
+/* Aug. 27, 2010: obsolete??
+	 // Print Cell Line creation page that looks and behaves like Vector.  Offer a choice between parent and stable cell line, and display different forms depending on the selection. (2006-04-06)
+	function printForm_CellLine_TypeChoice($view, $type)
+	{
+		global $conn;
+
+		echo "<script type=\"text/javascript\">\n";
+		echo "function dummysubmit( formname )\n";
+		echo "{\n";
+			echo "var getformid = document.getElementById( formname );\n";
+			
+			echo "getformid.submit();\n";
+		echo "}\n";
+		echo "</script>\n";
+		
+		$cell_line_types = array();
+		?>
+			<form method="get" id="cellline_type_form_id" action="<?php echo $_SERVER["PHP_SELF"]; ?>">
+			<input type="hidden" name="View" value="<?php echo $view; ?>">
+			<input type="hidden" name="Type" value="<?php echo $type; ?>">
+				<table cellpadding="3" width="770px">
+					<tr>
+						<td>
+							What type of Cell Line are you creating?
+						</td>
+					</tr>
+
+					<tr> 
+						<td>
+							    <input type="radio" name="Mod" value="<?php echo $this->CellLine_SubCategory_Name_ID["Parent"]; ?>" checked>Parent Cell Line<br>
+
+							    <input type="radio" name="Mod" value="<?php echo $this->CellLine_SubCategory_Name_ID["Stable"]; ?>">Stable Cell Line<br>
+						</td>
+					</tr>
+
+					<!-- May 11/06, Marina -->
+					<tr>
+						<td>
+						         <A href="Reagent/cell_assoc.png" onClick="return popup(this, 'diagram', '650', '725', 'yes')">Click here to view an illustration of cell line types and associations</A>
+						<!-- <IMG width="500" height="500" src="vector_assoc.png" alt="Illustration"> -->
+						</td>
+					</tr>
+
+					<tr>
+						<td>
+							         <input type="button" name="Doestmatter" value="Next" onClick="dummysubmit('cellline_type_form_id')">
+						</td>
+					</tr>
+				</table>
+			</form>
+		<?php
+	}
+*/
+
+	/**
+	 * Print form to input cell line general properties preloaded from parents at stable cell line creation.
+	 *
+	 * @param INT parent cell line ID
+	 * @param INT parent vector ID
+	 * @param boolean
+	 * @param boolean
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	*/
+	function printCellLineGeneralPropsForm($backfill_CellLine_ID=null, $backfill_Vector_ID=null, $attemptBackfill=false, $show=false)
+	{
+		global $cgi_path;
+
+		$r_out = new Reagent_Output_Class();
+		$gfunc_obj = new generalFunc_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+
+		// May 5/08: Use a different prefix - make uniform for all reagent types and for dynamic features
+		$genPrefix = "reagent_detailedview_";
+		$genPostfix = "_prop";
+
+		$r_type = "CellLine";
+		$rTypeID = 4;
+
+		$new_name = "";
+		$rid_vector_tmp = -1;
+		$rid_cellline_tmp = -1;
+		$default_class = "Parent";
+
+		$parent_CL_props = Array();
+		$preload = false;
+
+		$display = "none";
+		$header = "<TR><TD><table style=\"text-align:center; white-space:nowrap;\" width=\"705px\"><tr><td style=\"font-size:12pt; color:#00C00D; font-weight:bold;\">ADD NEW CELL LINE</td></tr></table></TD></TR>";
+
+		// differentiate between parent and stable
+		if ($attemptBackfill)
+		{
+			// Parent information
+			if ($backfill_CellLine_ID)
+				$rid_cellline_tmp = $gfunc_obj->get_rid($backfill_CellLine_ID);
+			else
+				$rid_cellline_tmp = -1;
+	
+			if ($backfill_Vector_ID)
+				$rid_vector_tmp = $gfunc_obj->get_rid($backfill_Vector_ID);
+			else
+				$rid_vector_tmp = -1;
+	
+			$default_class = "cDNA Stable";
+
+			$namePropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["name"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+
+			$vector_name = $rfunc_obj->getPropertyValue($rid_vector_tmp, $namePropID);
+			$cellline_name = $rfunc_obj->getPropertyValue($rid_cellline_tmp, $namePropID);
+
+			if (strlen($vector_name) > 0 && strlen($cellline_name) > 0)
+			{
+				$new_name = $vector_name . " in " . $cellline_name;
+			}
+
+			$parent_CL_props[$namePropID] = $new_name;
+
+			// Upload properties from parent cell line: species, developmental stage, selectable marker, tissue type, morphology
+			$clSpeciesPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["species"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]);
+			
+			$parent_CL_Species = $rfunc_obj->getPropertyValue($rid_cellline_tmp, $clSpeciesPropID);
+
+			$parent_CL_props[$clSpeciesPropID] = $parent_CL_Species;
+
+			$clDevStagePropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["developmental stage"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]);
+
+			$parent_CL_DevStage = $rfunc_obj->getPropertyValue($rid_cellline_tmp, $clDevStagePropID);
+
+			$parent_CL_props[$clDevStagePropID] = $parent_CL_DevStage;
+
+			// REMEMBER TO SWITCH THIS TO 'GROWTH PROPERTIES' CATEGORY WHEN GOING LIVE!!!!!!!!!!!!
+			$clSelMarkerPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["selectable marker"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]);
+
+			$parent_CL_SelMarker = $rfunc_obj->getPropertyValue($rid_cellline_tmp, $clSelMarkerPropID);
+			$parent_CL_props[$clSelMarkerPropID] = $parent_CL_SelMarker;
+
+			$clMorphologyPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["morphology"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]);
+
+			$parent_CL_Morphology = $rfunc_obj->getPropertyValue($rid_cellline_tmp, $clMorphologyPropID);
+
+			$parent_CL_props[$clMorphologyPropID] = $parent_CL_Morphology;
+
+			$clTissueTypePropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["tissue type"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]);
+
+			$parent_CL_TissueType = $rfunc_obj->getPropertyValue($rid_cellline_tmp, $clTissueTypePropID);
+
+			$parent_CL_props[$clTissueTypePropID] = $parent_CL_TissueType;
+
+			$display = "inline";
+			
+			$header = "";
+		}
+
+		// pass parent IDs as hidden form values
+		echo "<input type=\"hidden\" name=\"assoc_parent_cell_line_prop\" value=\"" . $backfill_CellLine_ID . "\">";
+		echo "<input type=\"hidden\" name=\"assoc_cell_line_parent_vector_prop\" value=\"" . $backfill_Vector_ID . "\">";
+
+// Removing Nov. 24, 2010 - seems obsolete
+// 		// Apr 07/06, Marina
+// 		if ($rid_cellline_tmp > 0)
+// 		{
+// 			// Match background property names to their database ids and retrieve their values
+// 			$back_cellline_prop_ar = $this->backFill($rid_cellline_tmp, $cl_name);
+// 			$back_vector_prop_ar = $this->backFill($rid_vector_tmp, $cl_name);
+// 		}
+
+		?><FORM method="POST" ENCTYPE="multipart/form-data" NAME="createReagentForm<?php echo $r_type; ?>" action="<?php echo $cgi_path . "create.py"; ?>">
+
+			<!-- Pass user info to Python as hidden form value - Aug 21/07 -->
+			<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+		
+			<INPUT TYPE="hidden" NAME="reagent_type_hidden" VALUE="<?php echo $r_type; ?>">
+			<?php
+				if ($attemptBackfill)
+				{
+					?>
+					<INPUT type="hidden" name="INPUT_CELLLINE_info_cellline_id_prop" value="<?php echo $backfill_CellLine_ID; ?>">
+
+					<INPUT type="hidden" name="INPUT_CELLLINE_info_vector_id_prop" value="<?php echo $backfill_Vector_ID; ?>">
+					<?php
+				}
+			?>
+			<TABLE ID="cell_line_general_props" NAME="cellLineCreate" style="display:<?php echo $display; ?>; font-size:10pt; width:750px;" cellpadding="4" cellspacing="4"><?php
+
+				if (isset($_GET["rID"]))
+				{
+					?><INPUT TYPE="hidden" NAME="reagent_id_hidden" VALUE="<?php echo $_GET["rID"]; ?>"><?php
+				}
+
+				echo $header;
+
+				// find the attributes of this reagent type
+				$categories = $rfunc_obj->findAllReagentTypeAttributeCategories($rTypeID);
+	
+				foreach ($categories as $categoryID => $category)
+				{
+					$rTypeAttributes = $rfunc_obj->getReagentTypeAttributesByCategory($_SESSION["ReagentType_Name_ID"][$r_type], $categoryID);
+
+					if (count($rTypeAttributes) == 0)
+						continue;
+
+					$catAlias = $_SESSION["ReagentPropCategory_ID_Alias"][$categoryID];
+
+					echo "<TR>";
+						echo "<TD>";
+							echo "<table style=\"background-color:#FFFFFF;\">";
+								// Aug. 19/09: Changed categoryID to catAlias, since that is also the name of the table in addNewReagentType() and JS was confusing between the two
+								echo "<tr>";
+									echo "<td style=\"font-weight:bold; color:blue; padding-top:2px;\">";
+										echo "<IMG id=\"" . $catAlias . "_expand_img_" . $r_type . "\" SRC=\"pictures/arrow_collapse.gif\" WIDTH=\"20\" HEIGHT=\"15\" BORDER=\"0\" ALT=\"plus\" class=\"menu-expanded\" style=\"display: inline\" onClick=\"showHideCategory('" . $catAlias . "', '" . $r_type . "');\">";
+
+										echo "<IMG id=\"" . $catAlias . "_collapse_img_" . $r_type . "\" SRC=\"pictures/arrow_expand.gif\" WIDTH=\"40\" HEIGHT=\"34\" BORDER=\"0\" ALT=\"plus\" class=\"menu-collapsed\" style=\"display: none\" onClick=\"showHideCategory('" . $catAlias . "', '" . $r_type . "');\">";
+
+										echo "<span id=\"section_title_" . $catAlias . "\">" . $category . "</span>";
+									echo "</TD>";
+								echo "</TR>";
+	
+								echo "<tr>";
+									echo "<td style=\"padding-left:3px;\">";
+										echo "<table ID=\"category_" . $catAlias . "_section_" . $r_type . "\" cellpadding=\"4\" cellspacing=\"2\" style=\"background-color:#FFFFFF; margin-top:4px;\">";
+
+										foreach ($rTypeAttributes as $attrID => $cProp)
+										{
+											$propDescr = $cProp->getPropertyDescription();
+											$propAlias = $cProp->getPropertyAlias();
+											$propName = $cProp->getPropertyName();
+											$propCategory = $cProp->getPropertyCategory();
+
+											// May 5, 2010
+											$p_id = $_SESSION["ReagentProp_Name_ID"][$propName];
+											$c_id = $_SESSION["ReagentPropCategory_Name_ID"][$propCategory];
+											$pID = $rfunc_obj->getPropertyIDInCategory($p_id, $c_id);
+
+											echo "<TR style=\"background-color:#F5F5DC;\">";
+
+												echo "<TD style=\"padding-left:15px; padding-right:15px; font-size:8pt; width:100px; font-weight:bold; white-space:nowrap;\">" . $propDescr;
+
+												$tmp_pc_id = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][$propName], $_SESSION["ReagentPropCategory_Name_ID"][$propCategory]);
+
+												if ( ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["name"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"])) || ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["project id"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"])) || (strcasecmp($propName, "packet id") == 0) || (strcasecmp($propName, "owner") == 0) || ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SESSION[ [...]
+												{
+													echo "<span style=\"font-size:9pt; color:#FF0000; font-weight:bold; margin-left:5px;\">*</span></TD>";
+
+													echo "<INPUT TYPE=\"hidden\" NAME=\"" . $r_type . "_mandatoryProps[]\" VALUE=\"" . $attrID . "\">";
+												}
+												else if ($tmp_pc_id == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["alternate id"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]))
+												{
+													echo "<BR><BR><span style=\"font-size:8pt;\">For 'Other', please enter<BR> the database name and<BR> numeric identifier, separated<BR> by semicolon, in the textbox<BR> (e.g. 'IMAGE:123456')</span></TD>";
+												}
+												else
+													echo "</TD>";
+
+												echo "<TD style=\"font-size:8pt; padding-left:10px; width:630px;\">";
+
+												// Prefill some of the default properties
+												if (strcasecmp($propName, "Cell Line Type") == 0)
+												{
+													$r_out->print_property_final($genPrefix . $r_type . "_" . $catAlias . "_:_" . $propAlias . $genPostfix, $propName, $default_class, "", true, $propCategory, "Preview", "", $r_type, true, "", 0, 0);
+												}
+												else if (strcasecmp($propName, "Status") == 0)
+												{
+													$r_out->print_property_final($genPrefix . $r_type . "_" . $catAlias . "_:_" . $propAlias . $genPostfix, $propName, "In Progress", "", true, $propCategory, "Preview", "", $r_type, false, "", 0, 0);
+												}
+												else
+												{
+													if (in_array($pID, array_keys($parent_CL_props)))
+													{
+														$preload = true;
+														$pVal = $parent_CL_props[$pID];
+													}
+													else
+													{
+														$preload = false;
+														$pVal = "";
+													}
+
+													$r_out->print_property_final($genPrefix . $r_type . "_" . $catAlias . "_:_" . $propAlias . $genPostfix, $propName, $pVal, "", true, $propCategory, "Preview", "", $r_type, false, "", 0, 0, false, false, false, $preload);
+												}
+
+												echo "</TD>";
+											echo "</TR>";
+										}
+
+										echo "</TABLE>";
+									echo "</TD>";
+								echo "</TR>";
+							echo "</TABLE>";
+						echo "</TD>";
+					echo "</TR>";
+				}
+
+				?><TR>
+					<TD colspan="2"><BR>
+						<INPUT TYPE="submit" name="create_reagent" value="Create" onClick="if (document.getElementById('cancel_set')) {document.getElementById('cancel_set').value=0}; document.pressed = this.value; selectAllPropertyValues(true); return checkMandatoryProps('<?php echo str_replace("'", "\'", $r_type); ?>'); selectAllPropertyValues(true);">
+						<?php
+							if (isset($_GET["rID"]))
+							{
+								?> <input type="submit" name="cancel_creation" value="Cancel Creation" onClick="document.getElementById('cancel_set').value=1; return confirm('Cancel reagent creation?\n All input will be lost')">
+	
+								<INPUT type="hidden" ID="cancel_set" value="0"><?php
+							}
+						?>
+					</TD>
+				</TR>
+			</TABLE>
+		</FORM>
+		<?php
+	}
+
+
+	// Now this function only applies to Stable Cell Lines - outputs general and parent properties form
+	/**
+	 * Stable Cell Line creation - save parents and preload their properties.
+	 * Modified April 7/07, Marina
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	*/
+	function process_CellLine_TypeChoice()
+	{
+		global $cgi_path;
+
+		echo "<P><CENTER><SPAN style=\"font-size:12pt; color:#00C00D; font-weight:bold;\">ADD NEW CELL LINE</SPAN></CENTER><BR>";
+
+		// Parents
+		$parent_vector_id = $_GET["PV"];	// e.g. V12
+		$parent_cellline_id = $_GET["CL"];	// e.g. C12
+
+		// Output parents here to avoid nested forms
+		$this->printForm_CellLine_Parents($parent_vector_id, $parent_cellline_id);
+		
+		$backfill_Vector_ID = $this->gfunc_obj->get_rid($parent_vector_id);
+		$backfill_CellLine_ID = $this->gfunc_obj->get_rid($parent_cellline_id);		// db ID, e.g. 4527
+
+		$this->printCellLineGeneralPropsForm($parent_cellline_id, $parent_vector_id, true, true);
+	}
+	
+
+	/**
+	 * Print form to input cell line parents at stable cell line creation.
+	 *
+	 * @param INT parent vector ID
+	 * @param INT parent cell line ID
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	*/
+	function printForm_CellLine_Parents($backfill_Vector_ID, $backfill_CellLine_ID)
+	{
+		global $cgi_path;
+
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+
+		echo "<form action=\"" . $cgi_path . "preload.py\" method=\"post\">";
+		echo "<input type=\"hidden\" name=\"reagent_type_hidden\" value=\"" . $_GET["Type"] . "\">";
+		echo "<input type=\"hidden\" name=\"subtype_hidden\" value=\"" . $_GET["Sub"] . "\">";
+
+		if (isset($_GET["rID"]))
+			$rID_tmp = $_GET["rID"];
+			?>
+			<input type="hidden" name="reagent_id_hidden" value="<?php echo $rID_tmp; ?>">
+
+			<!-- Pass user info to Python as hidden form value - Aug 21/07 -->
+			<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+			<table width="750px" cellpadding="2" border="1" frame="box" rules="none" style="margin-left:10px; margin-right:15px;">
+				<th colspan="3" style="color:#0000CD; font-weight:bold; text-align:left">Parent Information:</th>
+
+				<tr>
+					<td nowrap width="150px">
+						Parent Cell Line ID
+					</td>
+
+					<td>
+						<input type=text name="INPUT_CELLLINE_info_cellline_id_prop" value="<?php echo $backfill_CellLine_ID; ?>">
+					</td>
+				</tr>
+			
+				<tr>
+					<td nowrap>
+						Parent Vector ID
+					</td>
+	
+					<td>
+						<input type=text name="INPUT_CELLLINE_info_vector_id_prop" value="<?php echo $backfill_Vector_ID; ?>">
+					</td>
+				</tr>
+
+				<tr>
+					<td>
+						<input type="submit" name="change_parents" value="Change">
+					</td>
+				</tr>
+			
+			</table>
+		<?php
+
+		// close parents form
+		echo "</form>";
+	}
+
+
+	/**
+	 * Fetch properties that should be preloaded from parents at stable cell line creation (retrieve specific property values of the given parent IDs and pass to print function).
+	 *
+	 * @param INT
+	 * @param Array
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 * @deprecated
+	*/
+// 	function backFill($rid, $expectedValues)
+// 	{
+// // print_r($expectedValues);
+// 		global $conn;
+// 
+// 		$temp_ar = array();
+// 		$property_set = "('";
+// 		$setcount = 0;
+// 		
+// 		// Make a distinction between antibiotic resistance for vectors and resistance marker for cell lines - Marina, April 9/06
+// 
+// 		// November 24, 2010: Antibiotic resistance has long ago been changed to selectable marker!!!
+// /*
+// 		$antibio_ar = array();
+// 		$resmark_ar = array();	// April 9/06*/
+// 		
+// 		foreach( $expectedValues as $name => $post_name )
+// 		{
+// 			$property_set = $property_set . $_SESSION["ReagentProp_Name_ID"][ $name ] . "','";
+// 			$temp_ar[ $_SESSION["ReagentProp_Name_ID"][ $name ] ] = "";
+// 			$setcount++;
+// 		}
+// 
+// 		$property_set = $this->gfunc_obj->reset_set( $setcount , $property_set );
+// 		$expectedValues = $temp_ar;
+// 		
+// 		$backfill_rs = mysql_query("SELECT * FROM `ReagentPropList_tbl` WHERE `status`='ACTIVE' AND `reagentID`='" . $rid . "' AND `propertyID` IN " . $property_set . "", $conn ) or die("FAILURE IN REAGENT_CREATOR_CLASS.backFill(1): " . mysql_error());
+// 
+// 		while( $backfill_ar = mysql_fetch_array( $backfill_rs, MYSQL_ASSOC ) )
+// 		{
+// 			if ($backfill_ar["propertyID"] == $_SESSION["ReagentProp_Name_ID"]["antibiotic resistance"])
+// 			{
+// 				$antibio_ar[] = $backfill_ar[ "propertyValue" ];
+// 			}
+// 			else if ($backfill_ar["propertyID"] == $_SESSION["ReagentProp_Name_ID"]["resistance marker"])
+// 			{
+// 				$resmark_ar[] = $backfill_ar[ "propertyValue" ];
+// 			}
+// 			else
+// 			{
+// 				$expectedValues[ $backfill_ar["propertyID"] ] = $backfill_ar["propertyValue"];
+// 			}
+// 		}
+// 		
+// // 		$expectedValues[ $_SESSION["ReagentProp_Name_ID"]["antibiotic resistance"] ] = $antibio_ar;
+// // 		$expectedValues[ $_SESSION["ReagentProp_Name_ID"]["resistance marker"] ] = $resmark_ar;
+// 
+// 		return $expectedValues;
+// 	}
+}
+
+?>
diff --git a/OpenFreezer/Reagent/Reagent_Function_Class.php b/OpenFreezer/Reagent/Reagent_Function_Class.php
new file mode 100755
index 0000000..065a788
--- /dev/null
+++ b/OpenFreezer/Reagent/Reagent_Function_Class.php
@@ -0,0 +1,2920 @@
+<?php
+/**
+*
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2010 Pawson Laboratory, All Rights Reserved
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Reagent
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+ * Contains auxiliary functions for managing reagents
+ *
+ * @author John Paul Lee @version 2005
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Reagent
+ *
+ * @copyright  2005-2010 Pawson Laboratory
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+class Reagent_Function_Class
+{
+	/**
+	 * @var STRING
+	 * Error message returned by this class in various cases (contains the name of this class to help pinpoint the source of the error)
+	*/
+	var $classerror;
+
+	/**
+	 * @var Array
+	 * Map of nucleotide complements ("a" => "t", "c" => "g", "g" => "c", "t" => "a")
+	*/
+	var $complement_map;
+
+	/**
+	 * @var Array
+	 * Map of codon triplets
+	*/
+	var $codonMap;		// Added June 4/08
+	
+	/**
+	* Constructor
+	*/
+	function Reagent_Function_Class()
+	{
+		$this->classerror = "Reagent_Function_Class.";
+		$this->complement_map = array("a" => "t", "c" => "g", "g" => "c", "t" => "a");
+		// print_r($this->complement_map);
+
+		// Added June 4/08
+		$this->codonMap = Array();
+
+		$codonMap["TTT"] = 'F';
+		$codonMap["TCT"] = 'S';
+		$codonMap["TAT"] = 'Y';
+		$codonMap["TGT"] = 'C';
+		$codonMap["TTC"] = 'F';
+		$codonMap["TCC"] = 'S';
+		$codonMap["TAC"] = 'Y';
+		$codonMap["TGC"] = 'C';
+		$codonMap["TTA"] = 'L';
+		$codonMap["TCA"] = 'S';
+		$codonMap["TAA"] = '*';
+		$codonMap["TGA"] = '*';
+		$codonMap["TTG"] = 'L';
+		$codonMap["TCG"] = 'S';
+		$codonMap["TAG"] = '*';
+		$codonMap["TGG"] = 'W';
+		$codonMap["CTT"] = 'L';
+		$codonMap["CCT"] = 'P';
+		$codonMap["CAT"] = 'H';
+		$codonMap["CGT"] = 'R';
+		$codonMap["CTC"] = 'L';
+		$codonMap["CCC"] = 'P';
+		$codonMap["CAC"] = 'H';
+		$codonMap["CGC"] = 'R';
+		$codonMap["CTA"] = 'L';
+		$codonMap["CCA"] = 'P';
+		$codonMap["CAA"] = 'Q';
+		$codonMap["CGA"] = 'R';
+		$codonMap["CTG"] = 'L';
+		$codonMap["CCG"] = 'P';
+		$codonMap["CAG"] = 'Q';
+		$codonMap["CGG"] = 'R';
+		$codonMap["ATT"] = 'I';
+		$codonMap["ACT"] = 'T';
+		$codonMap["AAT"] = 'N';
+		$codonMap["AGT"] = 'S';
+		$codonMap["ATC"] = 'I';
+		$codonMap["ACC"] = 'T';
+		$codonMap["AAC"] = 'N';
+		$codonMap["AGC"] = 'S';
+		$codonMap["ATA"] = 'I';
+		$codonMap["ACA"] = 'T';
+		$codonMap["AAA"] = 'K';
+		$codonMap["AGA"] = 'R';
+		$codonMap["ATG"] = 'M';
+		$codonMap["ACG"] = 'T';
+		$codonMap["AAG"] = 'K';
+		$codonMap["AGG"] = 'R';
+		$codonMap["GTT"] = 'V';
+		$codonMap["GCT"] = 'A';
+		$codonMap["GAT"] = 'D';
+		$codonMap["GGT"] = 'G';
+		$codonMap["GTC"] = 'V';
+		$codonMap["GCC"] = 'A';
+		$codonMap["GAC"] = 'D';
+		$codonMap["GGC"] = 'G';
+		$codonMap["GTA"] = 'V';
+		$codonMap["GCA"] = 'A';
+		$codonMap["GAA"] = 'E';
+		$codonMap["GGA"] = 'G';
+		$codonMap["GTG"] = 'V';
+		$codonMap["GCG"] = 'A';
+		$codonMap["GAG"] = 'E';
+		$codonMap["GGG"] = 'G';
+	}
+
+
+	// July 16, 2010
+	/**
+	 * Calculate the total number of reagents in OpenFreezer
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2010-07-16
+	 * @return INT
+	*/
+	function computeTotalReagents()
+	{
+		global $conn;
+		$total = 0;
+
+		$rcount_rs = mysql_query("SELECT COUNT(reagentID) as rcount FROM Reagents_tbl WHERE status='ACTIVE'");
+
+		if ($rcount_ar = mysql_fetch_array($rcount_rs, MYSQL_ASSOC))
+		{
+			$total = $rcount_ar["rcount"];
+		}
+
+		return $total;
+	}
+
+	// Function: set_Session_Reagent_Types_Prefix_Name()
+	// Defn: Sets the session variable for reagent types where index = Prefixs and values of index = Reagent Type Names
+	// Paramaters: None
+	// Returns: None
+	// Throws: 
+	// Created: July 26/05
+	// Notes: This function does not check if the session variable is set or not. Users should check that before hand.
+	/**
+	 * Generates a map of reagent type prefixes to their names and stores it in a session variable (prefix=> rTypeName)
+	 * @author John Paul Lee @version 2005-05-26
+	*/
+	function set_Session_Reagent_Types_Prefix_Name()
+	{
+		global $conn;
+		$functionerror = "set_Session_Reagent_Types_Prefix_Name(";
+		
+		$prefix_rs = mysql_query("SELECT `reagentTypeName`, `reagent_prefix` FROM `ReagentType_tbl` WHERE `status`='ACTIVE'", $conn) or die($this->classerror . $functionerror . $count++ . ")" . mysql_error());
+
+		$prefix_final = $this->set_Generic_Array( $prefix_rs );
+		mysql_free_result( $prefix_rs );
+		
+		$_SESSION["ReagentType_Prefix_Name"] = $prefix_final;
+	}
+	
+	// Function: set_Session_Reagent_Types_Name_Prefix()
+	// Defn: Set's the session variable for reagent types where index = Reagent Type Names and values of index = Prefixs 
+	// Paramaters: None
+	// Returns: None
+	// Throws: 
+	// Created: July 26/05
+	// Notes: This function does not check if the session variable is set or not. Users should check that before hand.
+	/**
+	 * Generates a map of reagent type prefixes to their names and stores it in a session variable (rTypeName => prefix)
+	 * @author John Paul Lee @version 2005-05-26
+	*/
+	function set_Session_Reagent_Types_Name_Prefix()
+	{
+		global $conn;
+		$functionerror = "set_Session_Reagent_Types_Name_Prefix(";
+		
+		$prefix_rs = mysql_query("SELECT `reagent_prefix`, `reagentTypeName` FROM `ReagentType_tbl` WHERE `status`='ACTIVE'", $conn) or die( $this->classerror . $functionerror . $count++ . ")" . mysql_error() );
+
+		$prefix_final = $this->set_Generic_Array( $prefix_rs );
+		mysql_free_result( $prefix_rs );
+		
+		$_SESSION["ReagentType_Name_Prefix"] = $prefix_final;
+	}
+	
+	/**
+	 * Generates a map of reagent type names to their IDs and stores it in a session variable (rTypeName => rTypeID)
+	 * @author John Paul Lee @version 2005-05-26
+	*/
+	function set_Session_Reagent_Types_Name_ID()
+	{
+		global $conn;
+		$functionerror = "set_Session_Reagent_Types_Name_ID(";
+		
+		$prefix_rs = mysql_query("SELECT `reagentTypeID`, `reagentTypeName` FROM `ReagentType_tbl` WHERE `status`='ACTIVE'", $conn) or die( $this->classerror . $functionerror . $count++ . ")" . mysql_error() );
+
+		$prefix_final = $this->set_Generic_Array( $prefix_rs );
+		mysql_free_result( $prefix_rs );
+		
+		$_SESSION["ReagentType_Name_ID"] = $prefix_final;
+	}
+	
+	/**
+	 * Generates a map of reagent type IDs to their names and stores it in a session variable (rTypeID => rTypeName)
+	 * @author John Paul Lee @version 2005-05-26
+	*/
+	function set_Session_Reagent_Types_ID_Name()
+	{
+		global $conn;
+		$functionerror = "set_Session_Reagent_Types_ID_Name(";
+		
+		$prefix_rs = mysql_query("SELECT `reagentTypeName`, `reagentTypeID`  FROM `ReagentType_tbl` WHERE `status`='ACTIVE'", $conn ) 
+						or die( $this->classerror . $functionerror . $count++ . ")" . mysql_error() );
+							
+		$prefix_final = $this->set_Generic_Array( $prefix_rs );
+		mysql_free_result( $prefix_rs );
+		
+		$_SESSION["ReagentType_ID_Name"] = $prefix_final;
+	}
+	
+	/**
+	 * Generates a map of reagent SUBtype names to their IDs and stores it in a session variable -- NOT USED ACTIVELY AT THE MOMENT
+	 * @author John Paul Lee @version 2005-05-26
+	*/
+	function set_Session_Reagent_SubTypes_RType_Name_ID()
+	{
+		global $conn;
+		$functionerror = "set_Session_Reagent_SubTypes_RType_Name_ID(";
+		$rtype_count = 0;
+		
+		$subtype_session_arr = array();
+		
+		$subtype_rs = mysql_query("SELECT `reagent_SubTypeID`, `reagent_typeID`, `name`  FROM `Reagent_SubType_tbl` WHERE `status`='ACTIVE' "
+						. "ORDER BY `reagent_typeID` ", $conn ) 
+						or die( $this->classerror . $functionerror . $count++ . ")" . mysql_error() );
+							
+		//$prefix_final = $this->set_Generic_Array( $prefix_rs );
+		while( $subtype_ar = mysql_fetch_array( $subtype_rs , MYSQL_ASSOC ) )
+		{
+			if( $subtype_ar["reagent_typeID"] > $rtype_count )
+			{
+				//$subtype_session_arr[ $_SESSION["ReagentType_ID_Name"][ $subtype_ar["reagent_typeID"] ] ] = array( );
+			}
+			
+			$subtype_session_arr[ $_SESSION["ReagentType_ID_Name"][ $subtype_ar["reagent_typeID"] ] ][ $subtype_ar["name"] ] = $subtype_ar["reagent_SubTypeID"];
+		}
+		
+		mysql_free_result( $subtype_rs );
+		
+		$_SESSION["Reagent_SubType_RType_Name_ID"] = $subtype_session_arr;
+	}
+	
+	/**
+	 * Generates a map of reagent SUBtype IDs to their names and stores it in a session variable -- NOT USED ACTIVELY AT THE MOMENT
+	 * @author John Paul Lee @version 2005-05-26
+	*/
+	function set_Session_Reagent_SubTypes_RType_ID_Name()
+	{
+		global $conn;
+		$functionerror = "set_Session_Reagent_SubTypes_RType_ID_Name(";
+		$rtype_count = 0;
+		
+		$subtype_session_arr = array();
+		
+		$subtype_rs = mysql_query("SELECT `reagent_SubTypeID`, `reagent_typeID`, `name`  FROM `Reagent_SubType_tbl` WHERE `status`='ACTIVE' "
+						. "ORDER BY `reagent_typeID` ", $conn ) 
+						or die( $this->classerror . $functionerror . $count++ . ")" . mysql_error() );
+							
+		//$prefix_final = $this->set_Generic_Array( $prefix_rs );
+		while( $subtype_ar = mysql_fetch_array( $subtype_rs , MYSQL_ASSOC ) )
+		{
+			if( $subtype_ar["reagent_typeID"] > $rtype_count )
+			{
+				//$subtype_session_arr[ $_SESSION["ReagentType_ID_Name"][ $subtype_ar["reagent_typeID"] ] ] = array( );
+			}
+			
+			$subtype_session_arr[ $_SESSION["ReagentType_ID_Name"][ $subtype_ar["reagent_typeID"] ] ][ $subtype_ar["reagent_SubTypeID"] ] = $subtype_ar["name"];
+		}
+		
+		mysql_free_result( $subtype_rs );
+		
+		$_SESSION["Reagent_SubType_RType_ID_Name"] = $subtype_session_arr;
+
+	}
+	
+	/**
+	 * Generates a simple map of reagent proerty names to their IDs and stores it in a session variable (propName => propID, e.g. 'name' -> '1')
+	 * @author John Paul Lee @version 2005-05-26
+	*/
+	function set_Session_Reagent_Prop_ID_Name_ID()
+	{
+		// CONST : Finds all the names of the property and their given property ID's
+		//			propName --> propID
+		//           [DEBUG] : 1
+		global $conn;
+		
+		$reagentPropID_rs = mysql_query( "SELECT propertyID, propertyName FROM `ReagentPropType_tbl` WHERE `status`='ACTIVE'", $conn) or die("Query to find property names failed!: ".mysql_error() );
+		
+		$reagentPropID_const = $this->set_Generic_Array($reagentPropID_rs);
+		mysql_free_result($reagentPropID_rs);
+		
+		$_SESSION["ReagentProp_Name_ID"] = $reagentPropID_const;
+	}
+
+	/**
+	 * Generates a simple map of reagent proerty IDs to their names and stores it in a session variable (propID => propName, e.g. '1' -> 'name')
+	 * @author John Paul Lee @version 2005-05-26
+	*/
+	function set_Session_Reagent_Prop_ID_ID_Name( )
+	{
+		// CONST : Finds all the names of the property and their given property ID's
+		//			propName --> propID
+		//           [1] : DEBUG
+		global $conn;
+		
+		$reagentPropID_rs = mysql_query( "SELECT propertyName, propertyID FROM `ReagentPropType_tbl` WHERE `status`='ACTIVE'", $conn) or die("Query to find property names failed!: ".mysql_error() );
+		
+		$reagentPropID_const = $this->set_Generic_Array($reagentPropID_rs);
+		mysql_free_result($reagentPropID_rs);
+
+		$_SESSION["ReagentProp_ID_Name"] = $reagentPropID_const;
+	}
+	
+	// Function set_Generic_Array()
+	// Defn: A generic set function that converts a result set and converts it into an array
+	// Paramaters: Database result set to convert
+	// Returns: Array of converted result set
+	// Throws:
+	// Created: July 26/05
+	/**
+	 * A generic set function that converts a result set and converts it into an array
+	 * @author John Paul Lee @version 2005-05-26
+	 * @param resource
+	 * @return Array
+	*/
+	function set_Generic_Array($toset_rs)
+	{
+		$general_arr = array();
+
+		while ($row = mysql_fetch_row($toset_rs))
+		{
+			$general_arr[$row[1]] = $row[0];
+		}
+
+		return $general_arr;
+	}
+	
+	// Added March 20/07, Marina
+	// Fetch rid's property value corresponding to propID
+	// Update July 2009: $propID now corresponds to propCatID column in ReagentPropertyCategories_tbl
+	/**
+	 * Fetch a given property value of a given reagent.  $propID represents a property within a specific category (corresponds to propCatID column in ReagentPropertyCategories_tbl).
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2007-03-20 last update July 2009
+	 *
+	 * @param INT
+	 * @param INT
+	 * @return resource
+	*/
+	function getPropertyValue($rid, $propID)
+	{
+		global $conn;
+
+		$result = Array();
+		
+		//echo "SELECT propertyValue FROM ReagentPropList_tbl WHERE reagentID='" . $rid . "' AND propertyID='" . $propID . "' AND status='ACTIVE'";
+
+		$props_rs = mysql_query("SELECT propertyValue FROM ReagentPropList_tbl WHERE reagentID='" . $rid . "' AND propertyID='" . $propID . "' AND status='ACTIVE'", $conn) or die ("Failure in selecting reagent property value: " . $mysql_error());
+
+		while ($props_ar = mysql_fetch_array($props_rs, MYSQL_ASSOC))
+		{
+			$result[] = $props_ar["propertyValue"];
+		}
+
+		if (sizeof($result) == 1)
+			return $result[0];
+
+		if (sizeof($result) == 0)
+			return "";
+//print_r($result);
+		return $result;
+	}
+	
+
+	// May 23/08: Return a map of {features => descriptors}
+	/**
+	 * Return a map of {features => descriptors}.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-05-23
+	 * @return STRING
+	*/
+	function getFeatureDescriptors()
+	{
+		$desrs = array();
+
+		$desrs["tag"] = "tag position";
+		$desrs["promoter"] = "expression system";
+
+		return $desrs;
+	}
+	
+
+	// March 17/08, Marina: For sequence features, fetch the extra descriptor (e.g. position for tag type or expr.syst. for promoter) 
+	/**
+	 * For sequence features, fetch the extra descriptor (e.g. position for tag type or expr.syst. for promoter) 
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-05-17
+	 * @return resource
+	*/
+	function getFeatureDescriptor($rid, $fID, $fVal)
+	{
+		global $conn;
+
+		$result = "";
+		
+		if ($fVal && ($fVal != ""))
+		{
+			// echo "SELECT descriptor FROM ReagentPropList_tbl WHERE reagentID='" . $rid . "' AND propertyID='" . $fID . "' AND propertyValue='" . $fVal . "' AND status='ACTIVE'";
+
+			$props_rs = mysql_query("SELECT descriptor FROM ReagentPropList_tbl WHERE reagentID='" . $rid . "' AND propertyID='" . $fID . "' AND propertyValue='" . addslashes($fVal) . "' AND status='ACTIVE'", $conn) or die ("Could not select feature descriptor: " . $mysql_error());
+			
+			if ($props_ar = mysql_fetch_array($props_rs, MYSQL_ASSOC))
+			{
+				$result = $props_ar["descriptor"];
+			}
+
+// 			echo $result;
+		}
+
+		return $result;
+	}
+
+	/**
+	 * Set session variables for reagent information
+	 * @author John Paul Lee @version 2005
+	*/
+	function check_Reagent_Session()
+	{
+		if( !isset( $_SESSION["Reagent_SubType_RType_Name_ID"] ) )
+		{
+			
+			$this->set_Session_Reagent_SubTypes_RType_Name_ID();
+			
+		}
+		
+		if( !isset( $_SESSION["Reagent_SubType_RType_ID_Name"] ) )
+		{
+			$this->set_Session_Reagent_SubTypes_RType_ID_Name();
+		}
+		
+		if( !isset( $_SESSION["ReagentProp_Name_ID"] ) )
+		{
+			$this->set_Session_Reagent_Prop_ID_Name_ID();
+		};
+		
+		if( !isset( $_SESSION["ReagentProp_ID_Name"] ) )
+		{
+			$this->set_Session_Reagent_Prop_ID_ID_Name( );
+		}
+		
+		if( !isset( $_SESSION["ReagentType_Name_ID"] ) )
+		{
+			$this->set_Session_Reagent_Types_Name_ID();
+		}
+		
+		if( !isset( $_SESSION["ReagentType_ID_Name"] ) )
+		{
+			$this->set_Session_Reagent_Types_ID_Name();
+		}
+		
+		if( !isset( $_SESSION["ReagentType_Prefix_Name"] ) )
+		{
+			$this->set_Session_Reagent_Types_Prefix_Name();
+		}
+		
+		if( !isset( $_SESSION["ReagentType_Name_Prefix"] ) )
+		{
+			$this->set_Session_Reagent_Types_Name_Prefix();
+		}
+	}
+	
+	/**
+	 * Reset reagent session variables
+	 * @author John Paul Lee @version 2005
+	*/
+	function reset_Reagent_Session()
+	{
+		unset( $_SESSION["Reagent_SubType_RType_Name_ID"] ); 
+		$this->set_Session_Reagent_SubTypes_RType_Name_ID();
+
+		
+		unset( $_SESSION["Reagent_SubType_RType_ID_Name"] );
+		$this->set_Session_Reagent_SubTypes_RType_ID_Name();
+		
+		unset( $_SESSION["ReagentProp_Name_ID"] );
+		$this->set_Session_Reagent_Prop_ID_Name_ID();
+		
+		unset( $_SESSION["ReagentProp_ID_Name"] );
+		$this->set_Session_Reagent_Prop_ID_ID_Name( );
+		
+		unset( $_SESSION["ReagentType_Name_ID"] );
+		$this->set_Session_Reagent_Types_Name_ID();
+		
+		unset( $_SESSION["ReagentType_ID_Name"] );
+		$this->set_Session_Reagent_Types_ID_Name();
+		
+		unset( $_SESSION["ReagentType_Prefix_Name"] );
+		$this->set_Session_Reagent_Types_Prefix_Name();
+		
+		unset( $_SESSION["ReagentType_Name_Prefix"] );
+		$this->set_Session_Reagent_Types_Name_Prefix();
+	}
+	
+	// This is where the groupID gets set -- in a transaction (March 8/06, Marina)
+	/**
+	 * This is where the groupID gets set -- in a transaction
+	 * @author John Paul Lee @version 2005
+	 * @author Marina Olhovsky @version 2006-05-05 - set high group IDs (>5000) for MGC clones
+	 * @return INT
+	*/
+	function set_New_Reagent_LockSafe($toinsert)
+	{
+		global $conn;
+		global $MGC_Start;	// 5/5/06, Marina
+
+		$functionerror = ".set_New_Reagent_LockSafe(";
+		$newid = -1;
+		
+		$reagentTypeID = $_SESSION["ReagentType_Name_ID"][$toinsert];
+		
+		// Lock tables to ensure to get a consistent PK for each table insert
+		mysql_query("LOCK TABLES `Reagents_tbl` WRITE", $conn );
+		
+		// May 5, Marina - Assign group IDs <50000 when MGC clones are uploaded
+		if (($reagentTypeID == $_SESSION["ReagentType_Name_ID"]["Vector"]) || ($reagentTypeID == $_SESSION["ReagentType_Name_ID"]["Insert"]))
+		{
+			$reagent_rs = mysql_query("SELECT MAX(`groupID`) as maxID FROM `Reagents_tbl` WHERE `reagentTypeID`='" . $reagentTypeID . "' AND `groupID`<'" . $MGC_Start . "' AND `status`='ACTIVE'", $conn) or die("FAILURE IN creating new reagent: " . mysql_error());
+		}
+		else
+		{
+			$reagent_rs = mysql_query("SELECT max(`groupID`) as maxID FROM `Reagents_tbl` WHERE `reagentTypeID`='" . $reagentTypeID . "'  AND `status`='ACTIVE'", $conn) or die( "FAILURE IN creating new reagent: " . mysql_error());
+		}
+
+		if ($reagent_ar = mysql_fetch_array($reagent_rs , MYSQL_ASSOC))
+		{
+			$newreagent_rs = mysql_query( "INSERT INTO `Reagents_tbl` (`reagentID`, `reagentTypeID`, `groupID`, `status`) "
+			. "VALUES ('', '" . $reagentTypeID . "', '" . ($reagent_ar["maxID"] + 1) . "', 'ACTIVE')", $conn)
+			or die( "FAILURE IN Reagent_Creator_Class.process_Vector_all_input(2): " . mysql_error());
+
+			$newid = mysql_insert_id($conn);
+		}
+		else
+		{
+			// What should happen if failure here?
+
+			// May 5/06, Marina - For vectors and inserts, this is the case when their group ID has reached the base ID of MGC clones
+			if (($reagentTypeID == $_SESSION["ReagentType_Name_ID"]["Vector"]) || ($reagentTypeID == $_SESSION["ReagentType_Name_ID"]["Insert"]))
+			{
+				// Retrieve the highest unique group number, without regard for MGC
+				$reagent_rs = mysql_query("SELECT max(`groupID`) as maxID FROM `Reagents_tbl` WHERE `reagentTypeID`='" . $reagentTypeID . "'  AND `status`='ACTIVE'", $conn) or die( "FAILURE IN Reagent_Creator_Class.process_Vector_all_input(1): " . mysql_error());
+	
+				if ($reagent_ar = mysql_fetch_array($reagent_rs, MYSQL_ASSOC))
+				{
+					$newreagent_rs = mysql_query("INSERT INTO `Reagents_tbl` (`reagentID`, `reagentTypeID`, `groupID`, `status`) VALUES ('', '" . $reagentTypeID . "', '" . ($reagent_ar["maxID"] + 1) . "', 'ACTIVE')", $conn) or die("FAILURE IN Reagent_Creator_Class.process_Vector_all_input(2): " . mysql_error());
+				}
+				else
+				{
+					// assign groupID = '1'
+					$newreagent_rs = mysql_query("INSERT INTO `Reagents_tbl` (`reagentID`, `reagentTypeID`, `groupID`, `status`) VALUES ('', '" . $reagentTypeID . "', '" . "1" . "', 'ACTIVE')", $conn)
+					or die("FAILURE IN Reagent_Creator_Class.process_Vector_all_input(2): " . mysql_error());
+				}
+			}
+			else	// unlikely to happen; mostly for error checking - (code John, comm. Marina)
+			{
+				// Assume that there is NO current groupID's for the given reagentType ID, so assume that groupID = 1
+				$newreagent_rs = mysql_query("INSERT INTO `Reagents_tbl` (`reagentID`, `reagentTypeID`, `groupID`, `status`) VALUES ('', '" . $reagentTypeID . "', '" . "1" . "', 'ACTIVE')", $conn)
+				or die("FAILURE IN Reagent_Creator_Class.process_Vector_all_input(2): " . mysql_error());
+			}
+
+			$newid = mysql_insert_id($conn);
+		}
+
+		mysql_query("UNLOCK TABLES");
+		
+		mysql_free_result($reagent_rs);
+		unset($reagent_rs);
+		
+		return $newid;
+		
+	}
+	
+	/**
+	 * Retrieve reagent's association type (parent-child relation type, e.g. non-recombination vector, recombination vector, stable cell line, etc.)
+	 * @author John Paul Lee @version 2005
+	 * @return INT
+	*/
+	function get_Association_Type($name)
+	{
+		global $conn;
+		$functionerror = "get_Association_Type(";
+		
+		$type_rs = mysql_query("SELECT * FROM `AssocType_tbl` WHERE `status`='ACTIVE' AND `association`='" . trim( $name ) . "'", $conn )
+		or die( $this->classerror . $functionerror . "13)" . mysql_error() );
+
+		if( $type_ar = mysql_fetch_array( $type_rs, MYSQL_ASSOC ) )
+		{
+// 			echo "HERE " . $type_ar["ATypeID"] . "<br>";
+			return $type_ar["ATypeID"];
+		}
+		
+		return -1;
+		
+	}
+	
+
+	// Added May 12/06 by Marina
+	/**
+	 * Retrieve reagent type ID
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2006-05-12
+	 * @return INT
+	*/
+	function getType($reagentIDToView)
+	{
+		global $conn;
+
+		if (!isset($_POST["reagent_typeid_hidden"]))
+		{
+			$type_rs = mysql_query("SELECT `reagentTypeID` FROM `Reagents_tbl` WHERE `status`='ACTIVE' AND `reagentID`='" 
+			. $reagentIDToView . "'", $conn);
+			
+			if ($type_ar = mysql_fetch_array($type_rs, MYSQL_ASSOC))
+			{
+				$type = $type_ar["reagentTypeID"];
+			}
+		}
+		else
+		{
+			$type = $_POST["reagent_typeid_hidden"];
+		}
+
+		return $type;
+	}
+
+
+	// Aug. 11/09
+	/**
+	 * Retrieve association properties for the given reagent type (e.g. 'cell line parent vector', 'sense oligo', etc.)
+	 *
+	 * @author Marina Olhovsky
+	 * @return Array
+	*/
+	function findReagentTypeAssociations($reagenttype_id, $hierarchy="PARENT")
+	{
+		global $conn;
+
+		$assocList = Array();
+
+		$type_rs = mysql_query("SELECT APropertyID, description FROM `Assoc_Prop_Type_tbl` WHERE `reagentTypeID`='" . $reagenttype_id . "' AND `status`='ACTIVE' AND `hierarchy`='" . $hierarchy . "' ", $conn) or die("Error in findReagentTypeAssociations() function: " . mysql_error());
+
+		while ($type_ar = mysql_fetch_array($type_rs, MYSQL_ASSOC))
+		{
+			$aPropID = $type_ar["APropertyID"];
+			$aPropDescr = $type_ar["description"];
+
+			$assocList[$aPropID] = $aPropDescr;
+		}
+		
+		return $assocList;
+	}
+
+
+	/**
+	 * Retrieve association property ID for the given reagent type
+	 *
+	 * @author Marina Olhovsky
+	 * @return INT
+	*/
+	function get_Association_Property_Type( $name , $reagenttype_id, $hierarchy )
+	{
+		global $conn;
+		$functionerror = "get_Association_Property_Type(";
+		
+		$name = strtolower($name);
+
+		$type_rs = mysql_query("SELECT * FROM `Assoc_Prop_Type_tbl` WHERE `reagentTypeID`='" . $reagenttype_id . "' AND `status`='ACTIVE' "
+		. "AND `APropName`='" . trim($name) . "' AND `hierarchy`='" . $hierarchy . "' ", $conn)
+		or die($this->classerror . $functionerror . "13)" . mysql_error());
+
+		if ($type_ar = mysql_fetch_array($type_rs, MYSQL_ASSOC))
+		{
+			return $type_ar["APropertyID"];
+		}
+		
+		return -1;
+	}
+	
+	/**
+	 * Not actively used in the current version
+	 * @author John Paul Lee @version 2005
+	*/
+	function get_Reagent_2nd_Type_ID( $reagentTypeID, $name )
+	{
+		global $conn;
+		$functionerror = "get_Reagent_2nd_Type_ID(";
+		
+		$type_rs = mysql_query("SELECT * FROM `Reagent_SubType_tbl` WHERE `reagent_typeID`='" . $reagentTypeID . "' AND `name`='" . $name . "' AND `status`='ACTIVE'", $conn )
+						or die( $this->classerror . $functionerror . "13)" . mysql_error() );
+						
+		if( $type_ar = mysql_fetch_array( $type_rs, MYSQL_ASSOC ) )
+		{
+			return $type_ar["reagent_SubTypeID"];
+		}
+		
+		return -1;
+	}
+	
+	/**
+	 * Not actively used in the current version
+	 * @author John Paul Lee @version 2005
+	*/
+	function get_Reagent_3rd_Type_ID( $subtype_id, $name )
+	{
+		global $conn;
+		$functionerror = "get_Reagent_3rd_Type_ID(";
+		
+		$type_rs = mysql_query("SELECT * FROM `Reagent_3rd_Typing_tbl` WHERE `subtype_id`='" . $subtype_id . "' AND `name`='" . $name . "' AND `status`='ACTIVE'", $conn )
+						or die( $this->classerror . $functionerror . "13)" . mysql_error() );
+						
+		if( $type_ar = mysql_fetch_array( $type_rs, MYSQL_ASSOC ) )
+		{
+			return $type_ar["3rd_typing_id"];
+		}
+		
+		return -1;
+	}
+	
+	// March 27/08
+	/**
+	 * Retrieve the database alias of a particular property
+	 *
+	 * @author Marina Olhovsky
+	 * @param STRING
+	 * @return STRING
+	*/
+	function getReagentPropertyAlias($propName)
+	{
+		global $conn;
+		
+		$propAlias = "";
+
+		$prop_rs = mysql_query("SELECT propertyAlias FROM ReagentPropType_tbl WHERE propertyName='" . mysql_real_escape_string($propName) . "' AND status='ACTIVE'", $conn) or die("Could not select property alias: " . mysql_error());
+
+		if ($prop_ar = mysql_fetch_array($prop_rs))
+		{
+			$propAlias = $prop_ar["propertyAlias"];
+		}
+
+		return $propAlias;
+	}
+
+	// (Comment added May 2/08 by Marina): In plain terms - maps property names to their database alias (returns ReagentPropType_tbl.propertyName => ReagentPropType_tbl.propertyAlias map)
+	/**
+	 * Map property names to their database aliases
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING
+	 * @param STRING
+	 * @param STRING
+	 *
+	 * @return Array
+	*/
+	function get_Post_Names($reagentType, $subtype="", $extra_type = "")
+	{
+		if( $reagentType == "CellLine" )
+		{
+// 			echo "what is this: " . $subtype;
+			$cl_name[ "cell line type" ] = "cell_line_type";
+			$cl_name[ "name" ] = "name";
+			$cl_name[ "alternate id" ] = "alternate_id";
+			$cl_name[ "description" ] = "description";
+			$cl_name[ "comments" ] = "comments";
+			$cl_name[ "packet id" ] = "packet_id";
+			$cl_name[ "status" ] = "status";
+			$cl_name[ "reagent source" ] = "reagent_source";
+			$cl_name[ "restrictions on use" ] = "restrictions_on_use";
+			$cl_name[ "species" ] = "species";
+			$cl_name[ "developmental stage" ] = "developmental_stage";
+			$cl_name[ "selectable marker" ] = "selectable_marker";
+			$cl_name[ "tissue type" ] = "tissue_type";
+			$cl_name[ "morphology" ] = "morphology";
+
+			// April 7/06, Marina
+			$cl_name[ "vector id" ] = "vector_id";
+			$cl_name[ "cell line id" ] = "cellline_id";
+			
+			return $cl_name;
+		}
+		elseif( $reagentType == "Oligo" ) 
+		{
+			$ol_name[ "oligo type" ] = "oligo_type";
+			$ol_name[ "name" ] = "name";
+			$ol_name[ "sequence" ] = "sequence";
+// 			$ol_name[ "tm" ] = "tm";
+			$ol_name["melting temperature"] = "melting_temperature";
+// 			$ol_name[ "mw" ] = "mw";
+			$ol_name["molecular weight"] = "molecular_weight";
+			$ol_name[ "protocol" ] = "protocol";
+			$ol_name[ "accession number" ] = "accession_number";
+			$ol_name[ "reagent source" ] = "reagent_source";
+			$ol_name[ "description" ] = "description";
+			$ol_name[ "comments" ] = "comments";
+			$ol_name[ "packet id" ] = "packet_id";		// April 2/07, Marina - changed 'owner' into 'packet id'
+			
+			return $ol_name;
+		}
+		else if ($reagentType == "Insert")
+		{
+			// May 14/08: Special for Primer Design - a subset of properties that have not yet been saved for this Insert
+			if ($subtype == "Primer General")
+			{
+				// Sept. 8/09: Modified return array - instead of mapping property names to aliases map them to categories to display step 4 (Insert Intro from Primer) correctly
+				$il_name[ "name" ] = "General Properties";
+				$il_name[ "packet id" ] = "General Properties";
+				$il_name[ "status" ] = "General Properties";
+				
+				$il_name[ "description" ] = "General Properties";
+				$il_name[ "comments" ] = "General Properties";
+				$il_name[ "verification comments" ] = "General Properties";
+				$il_name[ "verification" ] = "General Properties";
+	
+				$il_name[ "alternate id" ] = "External Identifiers";
+
+				$il_name["type of insert"] = "Classifiers";
+				$il_name[ "open/closed" ] = "Classifiers";
+				$il_name["cloning method"] = "Classifiers";
+
+// 				$il_name[ "name" ] = "name";
+// 				$il_name[ "packet id" ] = "packet_id";
+// 				$il_name[ "status" ] = "status";
+// 				
+// 				$il_name[ "description" ] = "description";
+// 				$il_name[ "comments" ] = "comments";
+// 				$il_name[ "verification comments" ] = "verification_comments";
+// 				$il_name[ "verification" ] = "verification";
+// 	
+// 				$il_name[ "alternate id" ] = "alternate_id";
+// 
+// 				$il_name["type of insert"] = "insert_type";
+// 				$il_name[ "open/closed" ] = "open_closed";
+// 				$il_name["insert cloning method"] = "cloning_method";
+			}
+			// Nov. 17/08
+			else if (strcasecmp($subtype, "Cloning Sites") == 0)
+			{
+				$il_name[ "5' cloning site" ] = "5_prime_cloning_site";
+				$il_name[ "3' cloning site" ] = "3_prime_cloning_site";
+			}
+			else
+			{
+// may 13/08			$il_name["insert subtype"] = "insert_subtype";
+				$il_name[ "name" ] = "name";
+				$il_name[ "status" ] = "status";
+				$il_name[ "packet id" ] = "packet_id";
+				
+				$il_name[ "description" ] = "description";
+				$il_name[ "comments" ] = "comments";
+				$il_name[ "verification comments" ] = "verification_comments";
+				$il_name[ "verification" ] = "verification";
+	
+				$il_name["type of insert"] = "insert_type";
+				$il_name[ "open/closed" ] = "open_closed";
+				$il_name["cloning method"] = "cloning_method";
+				$il_name["species"] = "species";
+	
+				$il_name[ "accession number" ] = "accession_number";
+				$il_name[ "entrez gene id" ] = "entrez_gene_id";
+				$il_name[ "ensembl gene id" ] = "ensembl_gene_id";
+				$il_name[ "alternate id" ] = "alternate_id";
+				
+				$il_name[ "official gene symbol" ] = "official_gene_symbol";
+
+/* May 13/08: These have now become features
+				$il_name[ "5' start" ] = "5_prime_start";
+				$il_name[ "3' stop" ] = "3_prime_stop";
+				$il_name[ "5' linker" ] = "5_prime_linker";
+				$il_name[ "3' linker" ] = "3_prime_linker";
+				$il_name["cdna insert"] = "cdna_insert";
+				$il_name[ "sequence" ] = "sequence";
+				$il_name[ "tag type" ] = "tag_type";
+				$il_name[ "tag position" ] = "tag_position";
+	
+				// Feb. 26/08: As part of our property redesign, assigning some of the Vector properties to Insert
+				$il_name["promoter"] = "promoter";
+				$il_name["selectable marker"] = "selectable_marker";
+				$il_name["origin"] = "origin";
+				$il_name["polyA"] = "polyA";
+				$il_name["expression system"] = "expression_system";
+				$il_name["miscellaneous"] = "miscellaneous";	// march 18/08
+*/
+		
+// may 13/08			$il_name[ "protocol" ] = "protocol";
+			
+// may 13/08			$il_name["sense id"] = "sense_id";
+// may 13/08			$il_name["anti id"] = "anti_id";
+// may 13/08			$il_name["ipv id"] = "ipv_id";
+			}
+
+			return $il_name;
+		}
+		elseif( $reagentType == "Vector" )
+		{
+			if( $subtype == "General" )
+			{
+				$vl_name[ "name" ] = "name";
+				$vl_name[ "status" ] = "status";
+				$vl_name[ "verification" ] = "verification";
+				$vl_name[ "verification comments" ] = "verification_comments";
+				$vl_name[ "description" ] = "description";
+				$vl_name[ "comments" ] = "comments";
+				$vl_name[ "reagent source" ] = "reagent_source";
+				$vl_name[ "restrictions on use" ] = "restrictions_on_use";
+				$vl_name[ "packet id" ] = "packet_id";
+
+				$vl_name[ "vector type" ] = "vector_type";	// Apr 5 - check!
+
+// 				$vl_name["cdna insert"] = "cdna_insert";	// feb. 25/08, marina
+
+				return $vl_name;
+			}
+			// Feb 11, Marina
+			elseif( $subtype == "Cloning Sites" )
+			{
+				$vl_name["5' cloning site"] = "5' cloning site";
+				$vl_name["3' cloning site"] = "3' cloning site";
+				return $vl_name;
+			}
+			elseif( $subtype == "Background" )
+			{
+				$vl_name[ "name" ] = "name";		// april 8/07, Marina
+				$vl_name[ "selectable marker" ] = "selectable_marker";
+				$vl_name[ "expression system" ] = "expression_system";
+				$vl_name[ "promoter" ] = "promoter";
+				$vl_name[ "tag" ] = "tag";
+				$vl_name[ "tag position" ] = "tag_position";
+// 				$vl_name[ "sequence" ] = "sequence";
+				
+				return $vl_name;
+			}
+			elseif( $subtype == "Insert" )
+			{
+				$il_name["insert subtype"] = "insert_subtype";
+				$il_name[ "name" ] = "name";
+				$il_name[ "status" ] = "status";
+				$il_name[ "open/closed" ] = "open_closed";
+				
+				// accession number instead?
+				$il_name[ "accession number" ] = "accession_number";
+				$il_name[ "entrez gene id" ] = "entrez_gene_id";
+				$il_name[ "ensemble id" ] = "ensemble_id";
+			
+				$il_name[ "5' start" ] = "5_prime_start";
+				$il_name[ "3' stop" ] = "3_prime_stop";
+				$il_name[ "5' cloning site" ] = "5_prime_cloning_site";
+				$il_name[ "3' cloning site" ] = "3_prime_cloning_site";
+				$il_name[ "5' linker" ] = "5_prime_linker";
+				$il_name[ "3' linker" ] = "3_prime_linker";
+				
+				$il_name[ "protocol" ] = "protocol";
+				$il_name[ "sequence" ] = "sequence";
+				
+				$il_name[ "description" ] = "description";
+				$il_name[ "comments" ] = "comments";
+				
+				$il_name[ "tag" ] = "tag";
+				$il_name[ "tag position" ] = "tag_position";
+				
+				$il_name["sense id"] = "sense_id";
+				$il_name["anti id"] = "anti_id";
+				$il_name["type of insert"] = "insert_type";
+
+				return $il_name;
+			}
+			elseif( $subtype == "All" || $subtype == "" )
+			{
+				$vl_name[ "name" ] = "name";
+				
+				// special prop
+				$vl_name[ "vector type" ] = "vector_type";
+				
+				$vl_name[ "entrez gene id" ] = "entrez_gene_id";
+				$vl_name[ "5' cloning site" ] = "5_prime_cloning_site";
+				$vl_name[ "3' cloning site" ] = "3_prime_cloning_site";
+				$vl_name[ "comments" ] = "comments";
+				$vl_name[ "description" ] = "description";
+				$vl_name[ "tag" ] = "tag";
+				$vl_name[ "tag position" ] = "tag_position";
+				$vl_name[ "antibiotic resistance" ] = "antibiotic_resistance";
+				$vl_name[ "reagent source" ] = "reagent_source";
+				
+				$vl_name[ "verification" ] = "verification";
+				$vl_name[ "verification comments" ] = "verification_comments";
+				
+				$vl_name[ "restrictions on use" ] = "restrictions_on_use";
+				$vl_name[ "expression system" ] = "expression_system";
+				$vl_name[ "promoter" ] = "promoter";
+				
+				$il_name[ "protocol" ] = "protocol";
+				
+				$vl_name[ "status" ] = "status";
+				
+// july 9/07	$vl_name[ "project id" ] = "project_id";
+				$vl_name[ "packet id" ] = "packet_id";
+
+				$vl_name[ "sequence" ] = "sequence";
+				
+				$vl_name["cdna insert"] = "cdna_insert";
+
+				// April 18/08: Insert features mapped onto Vector
+				$vl_name["promoter"] = "promoter";
+				$vl_name["selectable marker"] = "selectable_marker";
+				$vl_name["origin"] = "origin";
+				$vl_name["polya"] = "polyA";
+				$vl_name["expression system"] = "expression_system";
+				$vl_name["miscellaneous"] = "miscellaneous";
+
+				// added Sept. 18/08
+				$vl_name["cleavage site"] = "cleavage_site";
+				$vl_name["restriction site"] = "restriction_site";
+				$vl_name["transcription terminator"] = "transcription_terminator";
+
+				$vl_name["intron"] = "intron";		// Dec. 10/08
+
+				return $vl_name;
+			}
+		}
+	}
+
+	/**
+	 * Determines if the property identified by $pName is a feature descriptor
+	 * Returns TRUE if pName is 'tag position' or 'expression system'; FALSE otherwise.
+	 *
+	 * @author Marina Olhovsky
+	 *
+	 * @param STRING
+	 * @return boolean
+	*/
+	function isDescriptor($pName)
+	{
+		switch ($pName)
+		{
+			case 'expression system':
+			case 'tag position':
+				return true;
+			break;
+
+			default:
+				return false;
+			break;
+		}
+	}
+
+
+	/**
+	 * Find the type of parent in the given parent-child association (identified by assocID).  E.g. in assocID = 1, which represents a parent-child relationship between an Insert and its resulting non-recombination vector, this function would return '2', the ID of reagent type 'Insert'.
+	 *
+	 * @author Marina Olhovsky
+	 *
+	 * @param INT
+	 * @return INT
+	*/
+	function findAssocParentType($assocID)
+	{
+		global $conn;
+
+		$assocParentType = 0;
+
+		$assoc_rs = mysql_query("SELECT assocTypeID FROM Assoc_Prop_Type_tbl WHERE APropertyID='" . $assocID . "' AND status='ACTIVE'", $conn) or die("Cannot select assoc parent: " . mysql_error());
+
+		if ($assoc_ar = mysql_fetch_array($assoc_rs, MYSQL_ASSOC))
+		{
+			$assocParentType = intval($assoc_ar["assocTypeID"]);
+		}
+
+		return $assocParentType;
+	}
+
+
+	/**
+	 * Is a given property mandatory for a particular reagent type? (obsolete, replaced by reagentTypeAttributes_tbl)
+	 *
+	 * @author Marina Olhovsky
+	 *
+	 * @param STRING
+	 * @return STRING
+	*/
+	function isMandatory($rType, $propName)
+	{
+		switch($rType)
+		{
+			case 'Vector':
+				switch($propName)
+				{
+					case 'name':
+					case 'status':
+					case 'packet id':
+					case 'vector type':
+						return true;
+					break;
+
+					default:
+						return false;
+					break;
+				}
+			break;
+
+			case 'Insert':
+				switch($propName)
+				{
+					case 'name':
+					case 'status':
+					case 'packet id':
+					case 'type of insert':
+					case 'open/closed':
+						return true;
+					break;
+
+					default:
+						return false;
+					break;
+				}
+			break;
+
+			case 'CellLine':
+				switch($propName)
+				{
+					case 'name':
+					case 'status':
+					case 'packet id':
+					case 'cell line type':
+						return true;
+					break;
+
+					default:
+						return false;
+					break;
+				}
+			break;
+
+			default:
+				switch($propName)
+				{
+					case 'name':
+					case 'status':
+					case 'packet id':
+					case strtolower($rType) . " type":
+						return true;
+					break;
+
+					default:
+						return false;
+					break;
+				}
+			break;
+		}
+	}
+
+	# May 1/08: Special function to define reagent **features**
+	# Returns: an associative array of (propertyName => propertyDescription) tuples
+	# Update July 8/09
+	/**
+	 * Special function to define reagent **features**.  Returns: an associative array of (propertyName => propertyDescription) tuples
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2009-07-08
+	 *
+	 * @param STRING
+	 * @return STRING
+	*/
+	function getReagentFeatures($reagentType, $subtype)
+	{
+		$vl_name = Array();
+
+		// Sequence types and features are mutually exclusive
+		if ($this->hasAttribute($_SESSION["ReagentType_Name_ID"][$reagentType], "protein sequence", $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]))
+		{
+			// get protein sequence features
+
+			$fCatID = $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence Features"];
+
+			$allFeatures = $this->getReagentTypeAttributesByCategory($_SESSION["ReagentType_Name_ID"][$reagentType], $fCatID);
+		}
+		else if ($this->hasAttribute($_SESSION["ReagentType_Name_ID"][$reagentType], "rna sequence", $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence"]))
+		{
+			$fCatID = $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence Features"];
+
+			// get RNA sequence features
+			$allFeatures = $this->getReagentTypeAttributesByCategory($_SESSION["ReagentType_Name_ID"][$reagentType], $fCatID);
+		}
+		else
+		{
+			$fCatID = $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"];
+
+			$allFeatures = $this->getReagentTypeAttributesByCategory($_SESSION["ReagentType_Name_ID"][$reagentType], $fCatID);
+		}
+
+		foreach ($allFeatures as $key => $feature)
+		{
+			try
+			{
+				$fName = strtolower($feature->getPropertyName());
+				$fID = $this->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][$fName], $fCatID);
+			}
+			catch (Exception $e)
+			{
+				$fName = strtolower($feature->getFeatureType());
+				$fID = $this->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][$fName], $fCatID);
+			}
+				
+			$vl_name[$fID] = $fName;
+		}
+
+		return $vl_name;
+	}
+
+
+	/**
+	 * Is the given property identified by $propCatID a sequence feature?
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2009-07-08
+	 *
+	 * @param INT
+	 * @return boolean
+	*/
+	function isSequenceFeature($propCatID)
+	{
+		global $conn;
+		$categoryID = $this->findPropertyCategoryID($propCatID);
+
+		return ($categoryID == $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]) || ($categoryID == $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence Features"]) || ($categoryID == $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence Features"]);
+	}
+
+	// April 11, 2009
+	// Since we now customize reagent types, sets of attributes for a given reagent type are retrieved from the database instead of being hard-coded
+	/**
+	 * Fetch all the attributes of the reagent type identified by $rTypeID.  Since we now customize reagent types, sets of attributes for a given reagent type are retrieved from the database instead of being hard-coded.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2009-04-11
+	 *
+	 * @param INT
+	 * @return Array
+	*/
+	function getAllReagentTypeAttributes($rTypeID)
+	{
+		global $conn;
+
+		$rTypeAttributes = Array();
+
+		$query = "SELECT propertyID, propertyName, propertyDesc, propertyAlias, propertyCategoryName FROM ReagentPropType_tbl t, ReagentTypeAttributes_tbl a, ReagentPropTypeCategories_tbl c, ReagentPropertyCategories_tbl pc WHERE a.reagentTypeID='" . $rTypeID . "' AND a.propertyTypeID=t.propertyID AND pc.propID=t.propertyID AND pc.categoryID=c.propertyCategoryID AND a.status='ACTIVE' AND t.status='ACTIVE' AND c.status='ACTIVE' AND pc.status='ACTIVE' ORDER BY a.ordering";
+
+// 		echo $query;
+	
+		$attributeSet =  mysql_query($query, $conn) or die("Error in getAllReagentTypeAttributes() function: Could not determine attributes for reagent type " . $rTypeID . ": " . mysql_error());
+
+		while ($attributeList = mysql_fetch_array($attributeSet, MYSQL_ASSOC))
+		{
+			$pID = $attributeList["propertyID"];
+			$pName = $attributeList["propertyName"];
+			$pDescr = $attributeList["propertyDesc"];
+			$pAlias = $attributeList["propertyAlias"];
+			$pCategory = $attributeList["propertyCategoryName"];
+
+			$tmpProp = new ReagentProperty($pName, $pAlias, $pDescr, $pCategory);
+			$rTypeAttributes[$pID] = $tmpProp;
+		}
+
+		return $rTypeAttributes;
+	}
+
+
+	/**
+	 * Retrieve all the properties in the category identified by $categoryID.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2009-04-23
+	 *
+	 * @param INT
+	 * @return Array
+	*/
+	function getPropertiesByCategory($categoryID)
+	{
+		global $conn;
+
+		$propList = Array();
+
+		$query = "SELECT propertyID, pc.propCatID, propertyName, propertyDesc, propertyAlias, propertyCategoryName FROM ReagentPropType_tbl t, ReagentPropTypeCategories_tbl c, ReagentPropertyCategories_tbl pc WHERE c.propertyCategoryID='" . $categoryID . "' AND t.propertyID=pc.propID AND pc.categoryID=c.propertyCategoryID AND t.status='ACTIVE' AND c.status='ACTIVE' AND pc.status='ACTIVE' ORDER by t.ordering";
+
+		$propSet =  mysql_query($query, $conn) or die("Could not select property categories: " . mysql_error());
+
+		while ($props = mysql_fetch_array($propSet, MYSQL_ASSOC))
+		{
+			$pID = $props["propCatID"];
+			$pName = $props["propertyName"];
+			$pDescr = $props["propertyDesc"];
+			$pAlias = $props["propertyAlias"];
+			$pCategory = $props["propertyCategoryName"];
+			$tmpProp = new ReagentProperty($pName, $pAlias, $pDescr, $pCategory);
+			$propList[$pID] = $tmpProp;
+		}
+
+		return $propList;
+	}
+
+
+	/**
+	 * Is this property customizable, i.e. can a user add new values to pre-defined list of property values on the fly for a particular reagent type?
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-05-11
+	 *
+	 * @param INT
+	 * @return boolean
+	*/
+	function isCustomizeable($rTypeAttrID)
+	{
+		global $conn;
+	
+		$results_rs = mysql_query("SELECT is_customizeable FROM ReagentTypeAttributes_tbl WHERE reagentTypePropertyID='" . $rTypeAttrID . "' AND status='ACTIVE'");
+	
+		if ($results_ar = mysql_fetch_array($results_rs, MYSQL_ASSOC))
+		{
+			$is_customizeable = $results_ar["is_customizeable"];
+	
+			if (strcasecmp($is_customizeable, 'YES') == 0)
+				return true;
+			else
+				return false;
+		}
+	
+		return false;
+	}
+
+	/**
+	 * Is this property multiple, i.e. can a user select more than one value for this property from a pre-defined list of values for a particular reagent type?
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-05-05
+	 *
+	 * @param INT
+	 * @return boolean
+	*/
+	function isMultiple($rTypeAttrID)
+	{
+		global $conn;
+	
+		$results_rs = mysql_query("SELECT is_multiple FROM ReagentTypeAttributes_tbl WHERE reagentTypePropertyID='" . $rTypeAttrID . "' AND status='ACTIVE'");
+	
+		if ($results_ar = mysql_fetch_array($results_rs, MYSQL_ASSOC))
+		{
+			$is_multiple = $results_ar["is_multiple"];
+	
+			if (strcasecmp($is_multiple, 'YES') == 0)
+				return true;
+			else
+				return false;
+		}
+	
+		return false;
+	}
+
+
+	/**
+	 * Is this property a hyperlink, i.e. should it be printed as a clickable hyperlink on a reagent detailed view?
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-05-05
+	 *
+	 * @param INT
+	 * @return boolean
+	*/
+	function isHyperlink($rTypeAttrID)
+	{
+		global $conn;
+	
+		$results_rs = mysql_query("SELECT is_hyperlink FROM ReagentTypeAttributes_tbl WHERE reagentTypePropertyID='" . $rTypeAttrID . "' AND status='ACTIVE'");
+	
+		if ($results_ar = mysql_fetch_array($results_rs, MYSQL_ASSOC))
+		{
+	
+			$is_hyperlink = $results_ar["is_hyperlink"];
+		
+			if (strcasecmp($is_hyperlink, 'YES') == 0)
+				return true;
+			else
+				return false;
+		}
+	
+		return false;
+	}
+
+
+	/**
+	 * Find ALL the attributes in the given category assigned to a particular reagent **type**
+	 *
+	 * @author Marina Olhovsky
+	 *
+	 * @param INT
+	 * @param INT
+	 * @return Array
+	*/
+	function getReagentTypeAttributesByCategory($rTypeID, $categoryID)
+	{
+		global $conn;
+
+		$rTypeAttributes = Array();
+
+		$query = "SELECT reagentTypePropertyID, propCatID, propertyName, propertyDesc, propertyAlias, propertyCategoryName, t.ordering FROM ReagentPropType_tbl t, ReagentTypeAttributes_tbl a, ReagentPropTypeCategories_tbl c, ReagentPropertyCategories_tbl pc WHERE a.reagentTypeID='" . $rTypeID . "' AND  c.propertyCategoryID='" . $categoryID . "' AND pc.categoryID=c.propertyCategoryID AND a.propertyTypeID=pc.propCatID AND t.propertyID=pc.propID AND a.status='ACTIVE' AND t.status='ACTIVE' AND c.s [...]
+
+		$attributeSet = mysql_query($query, $conn) or die("Error in getReagentTypeAttributesByCategory() function: Could not determine attributes for reagent type " . $rTypeID . ": " . mysql_error());
+
+		while ($attributeList = mysql_fetch_array($attributeSet, MYSQL_ASSOC))
+		{
+			$attrID = $attributeList["reagentTypePropertyID"];	// update May 5, 2010
+
+			$pID = $attributeList["propCatID"];
+			$pName = $attributeList["propertyName"];
+			$pDescr = $attributeList["propertyDesc"];
+			$pAlias = $attributeList["propertyAlias"];
+			$pCategory = $attributeList["propertyCategoryName"];
+
+			$tmpProp = new ReagentProperty($pName, $pAlias, $pDescr, $pCategory);
+
+			// NO!!  Removed May 5, 2010 - don't do this, decouple database from code objects!!  Can find propCatID later if needed from propName and categoryName!!
+// 			$tmpProp->setPropertyID($pID);		// Nov 3/09, this is propCatID
+
+// rmvd May 5/10	$rTypeAttributes[$pID] = $tmpProp;
+			$rTypeAttributes[$attrID] = $tmpProp;		// replaced May 5, 2010
+		}
+
+		return $rTypeAttributes;
+	}
+
+
+	/**
+	 * Find the property ID of a particular reagent type attribute. ** Returns the value of propertyTypeID column (result of several JOINs) **
+	 *
+	 * @author Marina Olhovsky
+	 *
+	 * @param INT
+	 * @param STRING
+	 * @param INT
+	 * @return INT
+	*/
+	function findReagentTypeAttributeID($reagentType, $attrName, $categoryID)
+	{
+		global $conn;
+
+		$pID = 0;
+
+		if (strpos($attrName, "'") >= 0)
+			$attrName = addslashes($attrName);
+
+		$query = "SELECT pc.propCatID FROM ReagentTypeAttributes_tbl a, ReagentPropType_tbl t, ReagentPropertyCategories_tbl pc WHERE a.reagentTypeID='" . $reagentType . "' AND t.propertyName='" . $attrName . "' AND t.propertyID=pc.propID AND pc.categoryID='" . $categoryID . "' AND a.propertyTypeID=pc.propCatID AND a.status='ACTIVE' AND t.status='ACTIVE' AND pc.status='ACTIVE'";
+
+		$attributeSet = mysql_query($query, $conn) or die("Error in findReagentTypeAttributeID() function: " . mysql_error());
+
+		while ($attributeList = mysql_fetch_array($attributeSet, MYSQL_ASSOC))
+		{
+			$pID = $attributeList["propCatID"];
+		}
+
+		return $pID;
+	}
+
+
+	/**
+	 * Clone of findReagentTypeAttributeID, only returns the value of reagentTypePropertyID column as opposed to propertyTypeID
+	 *
+	 * @author Marina Olhovsky
+	 *
+	 * @param INT
+	 * @param STRING
+	 * @param INT
+	 * @return INT
+	*/
+	function getRTypeAttributeID($reagentType, $attrName, $categoryID)
+	{
+		global $conn;
+
+		$propCatID = $this->findReagentTypeAttributeID($reagentType, $attrName, $categoryID);
+
+		$pID = 0;
+
+		$query = "SELECT reagentTypePropertyID FROM ReagentTypeAttributes_tbl WHERE reagentTypeID='" . $reagentType . "' AND propertyTypeID='" . $propCatID . "' AND status='ACTIVE'";
+
+		$attributeSet = mysql_query($query, $conn) or die("Error in getRTypeAttributeID() function: " . mysql_error());
+
+		while ($attributeList = mysql_fetch_array($attributeSet, MYSQL_ASSOC))
+		{
+			$pID = $attributeList["reagentTypePropertyID"];
+		}
+
+		return $pID;
+	}
+
+
+	/**
+	 * Checks whether a reagent type has a specific attribute within a certain category
+	 *
+	 * @author Marina Olhovsky
+	 *
+	 * @param INT
+	 * @param STRING
+	 * @param INT
+	 * @return boolean
+	*/
+	function hasAttribute($reagentType, $attrName, $catID)
+	{
+		return ($this->findReagentTypeAttributeID($reagentType, $attrName, $catID) > 0);
+	}
+
+
+	/**
+	 * Retrieve the ordering of a property for a given reagent type
+	 *
+	 * @author Marina Olhovsky
+	 *
+	 * @param INT
+	 * @param INT
+	 * @return INT
+	*/
+	function getReagentTypePropertyOrdering($rTypeID, $propCatID)
+	{
+		global $conn;
+
+		$pOrder = 0;	// don't use 2147483647
+
+		$propOrder_rs = mysql_query("SELECT ordering FROM ReagentTypeAttributes_tbl WHERE reagentTypeID='" . $rTypeID . "' AND propertyTypeID='" . $propCatID . "' AND status='ACTIVE'");
+
+		if ($propOrder_ar = mysql_fetch_array($propOrder_rs, MYSQL_ASSOC))
+		{
+			$pOrder = $propOrder_ar["ordering"];
+		}
+
+		return $pOrder;
+	}
+
+
+	/**
+	 * Find a specific reagent's properties and their values in a particular category (only returns non-empty values).
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2009-05-22
+	 *
+	 * @param INT
+	 * @param INT
+	 * @return INT
+	*/
+	function findReagentPropertiesByCategory($rID, $categoryID)
+	{
+		global $conn;
+
+		$rTypeAttributes = Array();
+
+		$pCategory = $_SESSION["ReagentPropCategory_ID_Name"][$categoryID];
+
+		// Update June 23/09: 'propertyID' column in ReagentPropList_tbl no longer refers to propertyID in ReagentPropType_tbl BUT to propCatID column in ReagentPropertyCategories_tbl - from now on, properties are taken in the context of their category!!
+		$query = "SELECT pc.propCatID, p.propertyValue, t.propertyName, t.propertyAlias, t.propertyDesc, pc.categoryID, p.startPos, p.endPos, p.direction, p.descriptor FROM `ReagentPropList_tbl` p, ReagentPropType_tbl t, ReagentPropertyCategories_tbl pc WHERE p.`status`='ACTIVE' AND p.`reagentID`='" . $rID . "' AND t.propertyID=pc.propID AND pc.categoryID='" . $categoryID . "' AND p.propertyID=pc.propCatID AND t.`status`='ACTIVE'";
+
+//  echo $query;
+
+		$attributeSet = mysql_query($query, $conn) or die("Error in findReagentPropertiesByCategory() function: Could not determine attributes for reagent type " . $rTypeID . ": " . mysql_error());
+
+		while ($attributeList = mysql_fetch_array($attributeSet, MYSQL_ASSOC))
+		{
+			$propCatID = $attributeList["propCatID"];
+			$pName = $attributeList["propertyName"];
+			$pVal = $attributeList["propertyValue"];
+			$pDescr = $attributeList["propertyDesc"];
+			$pAlias = $attributeList["propertyAlias"];
+			$pStart = $attributeList["startPos"];
+			$pEnd = $attributeList["endPos"];
+			$pDirection = $attributeList["direction"];
+			$pDescriptor = $attributeList["descriptor"];
+			$categoryID = $attributeList["categoryID"];
+
+// Aug. 21/09: NO!!!!!!!!!!!!!!!!!!
+// 'Origin' can become both classifier and feature for a reagent, and it's not enough to just search by name to find out if it is a feature; need category!!!!!!!
+// 			if (!$this->isSequenceFeature($rID, $pName))
+
+			if ( ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]) && ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence Features"]) && ($categoryID != $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence Features"]))
+			{
+				$tmpProp = new ReagentProperty($pName, $pAlias, $pDescr, $pCategory, $pVal);
+// print_r($tmpProp);
+
+// $tmp_ar = split(",", $pVal);
+// 
+// if (count($tmp_ar) > 1)
+
+			}
+			else
+			{
+				$tmpProp = new SeqFeature($pName, $pVal, $pStart, $pEnd, $pDirection, $pDescriptor, $pDescr);	// category is 'features' - might need to differentiate by sequence type later
+			}
+
+			if (in_array($propCatID, array_keys($rTypeAttributes)))
+				$tmp_attr = $rTypeAttributes[$propCatID];
+			else
+				$tmp_attr = array();
+
+			$tmp_attr[] = $tmpProp;
+			$rTypeAttributes[$propCatID] = $tmp_attr;
+		}
+
+//		print_r($rTypeAttributes);
+
+		return $rTypeAttributes;
+	}
+
+	/**
+	 * Find the pre-defined list values of a particular reagent type attribute (e.g. 'origin' for Insert in category 'classifiers').
+	 *
+	 * @author Marina Olhovsky
+	 *
+	 * @param INT
+	 * @return INT
+	*/
+	function getAllReagentTypeAttributeSetValues($attrID)
+	{
+		global $conn;
+		$attrSet = array();
+	
+		$rs_2 = mysql_query("SELECT s.entityName FROM ReagentTypeAttribute_Set_tbl r, System_Set_tbl s WHERE r.reagentTypeAttributeID='" . $attrID . "' AND s.ssetID=r.ssetID AND s.status='ACTIVE' AND r.status='ACTIVE' ORDER BY s.entityName", $conn) or die("FAILURE IN Reagent_Creator_Class.print_set(1): " . mysql_error());
+	
+		while ($set_ar = mysql_fetch_array($rs_2 , MYSQL_ASSOC))
+		{
+			$attrSet[] = $set_ar["entityName"];
+		}
+	
+		return $attrSet;
+	}
+
+
+	/**
+	 * Given a property and a category, find propCatID
+	 *
+	 * @author Marina Olhovsky
+	 *
+	 * @param INT
+	 * @return INT
+	*/
+	function getPropertyIDInCategory($propID, $categoryID)
+	{
+		global $conn;
+		$propCatID = 0;
+
+		$query = "SELECT propCatID FROM ReagentPropertyCategories_tbl WHERE propID='" . $propID . "' AND categoryID='" . $categoryID . "' AND status='ACTIVE'";
+		$prop_rs = mysql_query($query, $conn) or die("Error in getPropertyIDInCategory() function: " . mysql_error());
+// echo $query;
+
+		if ($prop_ar = mysql_fetch_array($prop_rs, MYSQL_ASSOC))
+		{
+			$propCatID = $prop_ar["propCatID"];
+		}
+
+		return $propCatID;
+	}
+
+
+	/**
+	 * Given the value of propCatID column in ReagentPropertyCategories_tbl find the PROPERTY ID, i.e. the value of **propID** column
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2009-06-30
+	 *
+	 * @param INT
+ 	 * @return INT
+	*/
+	function findPropertyInCategoryID($propCatID)
+	{
+		global $conn;
+		$propID = 0;
+
+		$query = "SELECT propID FROM ReagentPropertyCategories_tbl WHERE propCatID='" . $propCatID . "' AND status='ACTIVE'";
+// echo $query;
+		$prop_rs = mysql_query($query, $conn) or die("Error in findPropertyInCategoryID() function: " . mysql_error());
+
+		if ($prop_ar = mysql_fetch_array($prop_rs, MYSQL_ASSOC))
+		{
+			$propID = $prop_ar["propID"];
+		}
+
+		return $propID;
+	}
+
+
+	/**
+	 * Given the value of propCatID column in ReagentPropertyCategories_tbl, find the CATEGORY ID, i.e. the value of **categoryID** column
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2009-06-30
+	 *
+	 * @param INT
+ 	 * @return INT
+	*/
+	function findPropertyCategoryID($propCatID)
+	{
+		global $conn;
+		$categoryID = 0;
+
+		$query = "SELECT categoryID FROM ReagentPropertyCategories_tbl WHERE propCatID='" . $propCatID . "' AND status='ACTIVE'";
+// echo $query;
+		$prop_rs = mysql_query($query, $conn) or die("Error in findPropertyInCategoryID() function: " . mysql_error());
+
+		if ($prop_ar = mysql_fetch_array($prop_rs, MYSQL_ASSOC))
+		{
+			$categoryID = $prop_ar["categoryID"];
+		}
+
+		return $categoryID;
+
+	}
+
+	/**
+	 * Find all attribute categories for a given reagent type
+	 *
+	 * @author Marina Olhovsky
+	 *
+	 * @param INT
+ 	 * @return Array
+	*/
+	function findAllReagentTypeAttributeCategories($rTypeID)
+	{
+		global $conn;
+		$categories = array();
+
+		$query = "select propertyCategoryID, propertyCategoryName from ReagentPropTypeCategories_tbl where propertyCategoryID in (select distinct(categoryID) from ReagentPropertyCategories_tbl where propCatID in (select distinct(propertyTypeID) from ReagentTypeAttributes_tbl where reagentTypeID='" . $rTypeID . "' AND status='ACTIVE') AND status='ACTIVE') ORDER BY propertyCategoryID";
+
+//echo $query;
+
+		$categories_rs = mysql_query($query, $conn) or die("Error in findAllReagentTypeAttributeCategories() function: Could not determine attributes for reagent type " . $rTypeID . ": " . mysql_error());
+
+		while ($categories_ar = mysql_fetch_array($categories_rs, MYSQL_ASSOC))
+		{
+			$categoryID = $categories_ar["propertyCategoryID"];
+			$categories[$categoryID] = $categories_ar["propertyCategoryName"];
+		}
+
+		return $categories;
+	}
+
+
+	/**
+	 * Find the cloning method, i.e. the association type ID, of a given **reagent** (the value of ATypeID column in Association_tbl)
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2008-05-31
+	 *
+	 * @param INT
+ 	 * @return Array
+	*/
+	function getCloningMethod($reagentIDToView)
+	{
+		global $conn;
+
+		$query = "SELECT * FROM `Association_tbl` WHERE `reagentID`='" . $reagentIDToView . "' AND `status`='ACTIVE'";
+		$cloning_method_rs = mysql_query($query, $conn) or die("Could not determine cloning method: " . mysql_error());
+
+		if ($cloning_method_ar = mysql_fetch_array($cloning_method_rs, MYSQL_ASSOC))
+			$cloningMethod = $cloning_method_ar["ATypeID"];
+		else
+			$cloningMethod = 3;	// hard-code BASIC cloning method - parent vector
+
+		mysql_free_result($cloning_method_rs);
+		unset($cloning_method_ar);
+
+		return $cloningMethod;
+	}
+
+
+	/**
+	 * Return a map of current reagent features in the form of (featureID => Feature[]) tuples, where Feature is a SeqFeature **OBJECT**; there may be multiple values per feature ID
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2008-05-31
+	 *
+	 * @param INT
+ 	 * @return Array
+	*/
+	function getCurrentFeatures($rID)
+	{
+		global $conn;
+
+		return $this->findReagentPropertiesByCategory($rID, $_SESSION["ReagentPropCategory_Name_ID"]["Sequence Features"]);
+	}
+
+	/**
+	 * Escape single quotes by preceding them with another single quote for db insertion.  REPLACES PHP built-in function $this->addQuotes, which was storing values with backslashes
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-09-07
+	 *
+	 * @param STRING
+ 	 * @return STRING
+	*/
+	function addQuotes($myString)
+	{
+		return str_replace("'", "''", $myString);
+	}
+
+	/**
+	 * Add spaces to PROTEIN sequence - every 10 characters
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-09-08
+	 *
+	 * @param STRING
+ 	 * @return STRING
+	*/
+	function spaces($seq)
+	{
+		$chunk = "";
+		$seq_out = "";
+		$start = 0;
+
+// 		while ($start < strlen($seq))
+// 		{
+// 			$seq_out .= substr($seq, $start, 10) . " ";
+// 			$start += 10;
+// 		}
+
+		if (strlen($seq) <= 100)
+		{
+			while ($start < strlen($seq))
+			{
+				$seq_out .= substr($seq, $start, 10) . " ";
+				$start += 10;
+			}
+		}
+		else
+		{
+			while ($start < strlen($seq))
+			{
+				$chunk .= substr($seq, $start, 10) . " ";
+	
+				if (strlen($chunk) == 110)
+				{
+// 					$chunk .= "<BR>";
+					$chunk .= "\n";
+					$seq_out .= $chunk;
+					$chunk = "";
+				}
+	
+				$start += 10;
+			}
+
+			$seq_out .= $chunk;
+		}
+
+		return $seq_out;
+	}
+
+
+	/**
+	 * Space out DNA sequence in chunks of 3.
+	 * Updated Jan. 30/08: If there is a linker, change width accordingly.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-09-08
+	 *
+	 * @param STRING
+	 * @param STRING
+	 * @param STRING
+	 *
+ 	 * @return STRING
+	*/
+	function dnaSpace($dnaSeq, $fwd_linker="", $rev_linker="")
+	{
+		$chunk = "";
+		$seq_out = $fwd_linker;
+		$start = 0;
+
+		$fwd_linkerLen = strlen($fwd_linker);	// jan. 30/08
+		$rev_linkerLen = strlen($rev_linker);	// jan. 31/08
+
+		if (strlen($dnaSeq) <= 100)
+		{
+			while ($start < strlen($dnaSeq))
+			{
+				$seq_out .= substr($dnaSeq, $start, 3) . " ";
+				$start += 3;
+			}
+		}
+		else
+		{
+			while ($start < strlen($dnaSeq))
+			{
+				$chunk .= substr($dnaSeq, $start, 3) . " ";
+
+				if ($seq_out == $fwd_linker)
+				{
+					if ((strlen($chunk)+$fwd_linkerLen) == 108)
+					{
+						$chunk .= "\n";
+						$seq_out .= $chunk;
+						$chunk = "";
+					}
+				}
+				else
+				{
+					if (strlen($chunk) == 108)
+					{
+						$chunk .= "\n";
+						$seq_out .= $chunk;
+						$chunk = "";
+					}
+				}
+				$start += 3;
+			}
+
+			$seq_out .= $chunk;
+		}
+
+		$seq_out .= $rev_linker;
+
+		return $seq_out;
+	}
+
+
+	/**
+	 * Reverse translate protein sequence back to cDNA.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-09-08
+	 *
+	 * @param STRING
+	 * @param INT
+	 * @param INT
+	 * @param INT
+	 * @param INT
+	 * @param INT
+	 *
+ 	 * @return STRING
+	*/
+	function reverseTranslate($protSeq, $rID, $frame, $startpos, $endpos, $protLen)
+	{
+		global $conn;
+
+// 		echo "prot seq: " . $protSeq . "<BR>";
+// 		echo "rid: " . $rID . "<BR>";
+// 		echo "frame: " . $frame . "<BR>";
+//  		echo "start: " . $startpos . "<BR>";
+// 		echo "length: " . $protLen . "<BR>";
+
+// june 5/08	$dnaLen = $protLen * 3;
+		$dnaSeqPropID = $this->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+
+// echo $dnaSeqPropID;
+
+		$seqRS = mysql_query("SELECT s.`sequence`, s.`start`, s.`end` FROM `Sequences_tbl` s, `ReagentPropList_tbl` r WHERE r.`reagentID`='" . $rID . "' AND r.`propertyID`='" . $dnaSeqPropID . "' AND s.`seqID`=r.`propertyValue` AND r.`status`='ACTIVE' AND s.`status`='ACTIVE'", $conn) or die("Could not select sequence: " . mysql_error());
+
+// echo "SELECT s.`sequence`, s.`start`, s.`end` FROM `Sequences_tbl` s, `ReagentPropList_tbl` r WHERE r.`reagentID`='" . $rID . "' AND r.`propertyID`='23' AND s.`seqID`=r.`propertyValue` AND r.`status`='ACTIVE' AND s.`status`='ACTIVE'";
+
+		if ($seqResult = mysql_fetch_array($seqRS, MYSQL_ASSOC))
+		{
+			$dnaSeq = strtoupper($seqResult["sequence"]);
+		
+// june 5/08		$cDNA = substr($dnaSeq, $startpos + $frame - 1, $dnaLen);
+		}
+
+		// June 5/08
+		$cDNA = substr($dnaSeq, $startpos-1, $protLen*3);
+// 		echo "cdna " . $cDNA;
+
+		return $cDNA;
+	}
+
+	/**
+	 * Calculate Tm for primers.
+	 * CAUTION: substr_count IS CASE-SENSITIVE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!  That's why Tm with linkers, where $seq arg contained mixed-case strings was returning only the number of occurrences of G and C in the upper-case PRIMER, IGNORNING THE LINKER.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-09-08
+	 *
+	 * @param STRING
+ 	 * @return FLOAT
+	*/
+	function calcTemp($seq)
+	{
+		if (strlen($seq) == 0)
+		{
+			return null;
+		}
+
+		$seq = strtoupper($seq);		# Sept 22/06 -- CRUCIAL, to make the string uniform case
+
+// 		print "seq " . $seq . "<BR>";
+// 		print "G content: " . floatval(substr_count($seq, 'G')) . "<BR>";
+// 		print "C content: " . floatval(substr_count($seq, 'C')) . "<BR>";
+// 		print "Length " . floatval(strlen($seq)) . "<BR>";
+
+		# Modified Sept 22/06 - Borrowed Karen's code and included the length < 14 restriction
+		# If length(seq) < 14, a different computation rule applies
+		$seqLength = floatval(strlen($seq));
+
+		$g_count = floatval(substr_count($seq, 'G'));
+		$c_count = floatval(substr_count($seq, 'C'));
+		$a_count = floatval(substr_count($seq, 'A'));
+		$t_count = floatval(substr_count($seq, 'T'));
+
+		if ($seqLength < 14.0)
+		{
+			$temp = 2 * ($a_count + $t_count) + 4 * ($g_count + $c_count);
+		}
+		else
+		{
+			$temp = 64.9 + 41.0 * ($g_count + $c_count - 16.4) / $seqLength;
+		}
+
+		return round($temp, 2);
+	}
+
+
+	/**
+	 * Calculate the GC% content of a sequence.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-06-18
+	 *
+	 * @param STRING
+ 	 * @return FLOAT
+	*/
+	function get_gc_content($seq)
+	{
+		if (!$seq || (strlen(trim($seq)) == 0))
+		{
+			return 0;
+		}
+
+		$seq = strtoupper($seq);
+
+		$g_count = substr_count($seq, 'G');
+		$c_count = substr_count($seq, 'C');
+
+		$gc_count = $g_count + $c_count;
+
+		$gc_content = floatval($gc_count) / floatval(strlen($seq)) * 100;
+
+		return round($gc_content, 2);
+	}
+
+
+	/**
+	 * Calculate molecular weight of a DNA sequence (Marina: reused Karen's code).
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-09-22
+	 *
+	 * @param STRING
+ 	 * @return FLOAT
+	*/
+	function get_mw($seq)
+	{
+		if (!$seq || (strlen(trim($seq)) == 0))
+		{
+			return 0;
+		}
+
+		$seq = strtoupper($seq);
+
+		# Constant MWs of individual bases
+		$MW_A = 313.209;
+		$MW_G = 329.208;
+		$MW_C = 289.184;
+		$MW_T = 304.196;
+
+		$a_count = floatval(substr_count($seq, 'A'));
+// 		print "A " . $a_count . ", mw " . $MW_A . "<BR>";
+		$t_count = floatval(substr_count($seq, 'T'));
+// 		print "T " . $t_count . ", mw " . $MW_T . "<BR>";
+		$g_count = floatval(substr_count($seq, 'G'));
+// 		print "G " . $g_count . ", mw " . $MW_G . "<BR>";
+		$c_count = floatval(substr_count($seq, 'C'));
+// 		print "C " . $c_count . ", mw " . $MW_C . "<BR>";
+
+		$a_weight = $a_count * $MW_A;
+// 		print $a_weight . "<BR>";
+		$c_weight = $c_count * $MW_C;
+// 		print $c_weight . "<BR>";
+		$g_weight = $g_count * $MW_G;
+// 		print $g_weight . "<BR>";
+		$t_weight = $t_count * $MW_T;
+// 		print $t_weight . "<BR>";
+
+		$base_weight = floatval($a_weight) + floatval($c_weight) + floatval($g_weight) + floatval($t_weight);
+// 		print $base_weight . "<BR>";
+		$mw = $base_weight - 61.964;
+// 		print "MW " . $mw . "<BR>";
+		return round($mw, 2);
+	}
+
+
+	/**
+	 * Calculate molecular weight of a RNA sequence.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010
+	 *
+	 * @param STRING
+ 	 * @return FLOAT
+	*/
+	function getRNA_MW($seq)
+	{
+		if (!$seq || (strlen(trim($seq)) == 0))
+		{
+			return 0;
+		}
+
+		$seq = strtoupper($seq);
+// echo $seq;
+		# Constant MWs of individual bases
+		$MW_A = 329.21;
+		$MW_G = 345.21;
+		$MW_C = 305.18;
+		$MW_U = 306.17;
+
+		$a_count = floatval(substr_count($seq, 'A'));
+// 		print "A " . $a_count . ", mw " . $MW_A . "<BR>";
+		$u_count = floatval(substr_count($seq, 'U'));
+// 		print "U " . $u_count . ", mw " . $MW_U . "<BR>";
+		$g_count = floatval(substr_count($seq, 'G'));
+// 		print "G " . $g_count . ", mw " . $MW_G . "<BR>";
+		$c_count = floatval(substr_count($seq, 'C'));
+// 		print "C " . $c_count . ", mw " . $MW_C . "<BR>";
+
+		$a_weight = $a_count * $MW_A;
+// 		print $a_weight . "<BR>";
+		$c_weight = $c_count * $MW_C;
+// 		print $c_weight . "<BR>";
+		$g_weight = $g_count * $MW_G;
+// 		print $g_weight . "<BR>";
+		$u_weight = $u_count * $MW_U;
+// 		print $u_weight . "<BR>";
+
+		$base_weight = floatval($a_weight) + floatval($c_weight) + floatval($g_weight) + floatval($u_weight);
+// 		print $base_weight . "<BR>";
+		$mw = $base_weight + 159.0;
+// 		print "MW " . $mw . "<BR>";
+		return round($mw, 2);
+	}
+
+
+	/**
+	 * Calculate molecular weight of a Protein sequence.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2010-01-22
+	 *
+	 * @param STRING
+ 	 * @return FLOAT
+	*/
+	function computeProteinMW($proteinSequence)
+	{
+		$peptideMassDict = Array('A'=>71.08, 'C'=>103.14, 'D'=>115.09, 'E'=>129.12, 'F'=>147.18, 'G'=>57.05, 'H'=>137.14, 'I'=>113.16, 'K'=>128.17, 'L'=>113.16, 'M'=>131.19, 'N'=>114.1, 'P'=>97.12, 'Q'=>128.13, 'R'=>156.19, 'S'=>87.08, 'T'=>101.11, 'V'=>99.13, 'W'=>186.21, 'Y'=>163.18);
+
+		$mw = 0.0;
+		$pm = 0.0;
+
+		if (strlen($proteinSequence) == 0)
+			return 0.0;
+
+		else if (strpos(strtoupper($proteinSequence), 'X') >= 0)
+			return 0.0;
+
+		for ($i=0; $i < strlen($proteinSequence); $i++)
+		{
+			$aa = strtoupper(substr($proteinSequence, $i, 1));
+
+			if ($aa == "*")
+				break;
+
+			else if ($aa == 'B')
+			{
+				$pm = $peptideMassDict['D'];
+				$mw += $pm;
+			}
+
+			else if ($aa == 'Z')
+			{
+				$pm = $peptideMassDict['E'];
+				$mw += $pm;
+			}
+
+			if (in_array($aa, array_keys($peptideMassDict)))
+			{
+				$pm = $peptideMassDict[$aa];
+				$mw += $pm;
+			}
+		}
+
+		// add water weight - ROUGHLY 18
+		$mw += 18.0;
+
+		return round($mw / 1000.0, 2);
+	}
+
+
+	/**
+	 * Extract the desired portion of cDNA to design primers for.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-09-08
+	 *
+	 * @param STRING
+	 * @param INT
+	 * @param INT
+	 *
+ 	 * @return STRING
+	*/
+	function getSeqToClone($nt_seq, $begin, $end)
+	{
+		$nt_seq = strtoupper($nt_seq);
+		$index = 0;				// 10/05/06
+// 10/05/06	$index = strpos($nt_seq, "ATG");
+		$tmp_start = $index + ($begin-1)*3;
+		$tmp_end = $index + $end*3;
+		$tmp_len = $tmp_end - $tmp_start;
+		$tar_nt_seq = substr($nt_seq, $tmp_start, $tmp_len);
+// 		print "Target Nt seq to clone: " . $tar_nt_seq . "<BR>";
+
+		return $tar_nt_seq;
+	}
+
+
+	/**
+	 * Modified Sept 12/06 to restrict primer size first by custom length, then by Tm; begin and end are PROTEIN sequence indices.
+	 * Comment added Dec. 15/08: Limiting primer size:
+	 * If both primer length and Tm are specified, the algorithm stops primer assembly at 'length' AS LONG AS Tm HAS NOT BEEN REACHED.  If Tm is reached BEFORE length, primer assembly STOPS, EVEN IF 'length' is not reached at this point!!! (E.g. I85472: Choose 5' linker "V7-based w/ stop codon", limit length to 27 and leave Tm at default 55.  The final length (incl. linker) ends up being 22 BECAUSE Tm 55 is too low for a primer of length 27.  If want to limit length to 27, increase Tm to e. [...]
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-09-12
+	 *
+	 * @param STRING
+	 * @param INT
+	 * @param INT
+	 * @param STRING
+	 * @param STRING
+	 * @param INT
+	 * @param INT
+	 * @param INT
+	 * @param INT
+	 *
+ 	 * @return Array containing forward and reverse primers
+	*/
+	function getPrimers($nt_seq, $begin, $end, $fwdLinker, $revLinker, $maxFwdLen, $maxRevLen, $fwdTm, $revTm)
+	{
+// 		print "Input Nt seq " . $nt_seq . ", start " . $begin . ", end " . $end . "<BR>";
+		$nt_seq = strtoupper($nt_seq);
+//		$r_table = array();
+// 		print "Linkers: 5' " . $fwdLinker . " 3' " . $revLinker . "<BR>";
+		$r_table["C"] = "G";
+		$r_table["G"] = "C";
+		$r_table["A"] = "T";
+		$r_table["T"] = "A";
+
+		$fwd_primer = "";
+		$rev_primer = "";
+		$opt_primer = "";
+
+		$temp_fwd = array();
+		$temp_rev = array();
+		$primers = array();
+		
+ 		$tar_nt_seq = $this->getSeqToClone($nt_seq, $begin, $end);		// the sequence we want to clone
+ 		//print "tar seq " . $tar_nt_seq . "<BR>";
+ 		//print "fwd tm " . $fwdTm . "<BR>";
+ 		//print "fwd length " . $maxFwdLen . "<BR>";
+// 		print "length of 5' linker " . strlen($fwdLinker) . "<Br>";
+// 		print "length of 3' linker " . strlen($revLinker) . "<Br>";
+
+		# forward primer
+// 		$min_diff = 100;
+
+		$min_len = 10;			// 21/9/06
+		$go_on = true;
+
+// 		for ($i = 10; $i <= 50; $i++)
+		while ($go_on)
+		{
+// 21/09/06		$primer = substr($tar_nt_seq, 0, $i+1);
+			$primer = substr($tar_nt_seq, 0, $min_len+1);			// 21/09/06
+ 			//print "start loop, primer " . $primer . "<BR>";
+			$temp = $this->calcTemp($primer);
+ 			//echo "temp " . $temp . "<BR>";
+
+			# CHECK LENGTH FIRST
+			if (intval(strlen($primer) + strlen($fwdLinker)) <= $maxFwdLen)		// 12/09/06
+			{
+ 				//print "Current length of primer only: " . strlen($primer) . "<BR>";
+ 				//print "Current length of linker only: " . strlen($fwdLinker) . "<BR>";
+ 				//print "Current length of primer with linker: " . intval(strlen($primer) + strlen($fwdLinker)) . "<BR>";
+
+				if ($temp <= $fwdTm)		// 12/09/06
+				{
+ 					//echo "temp < set; primer: " . $primer . ", temp " . $temp . "<BR>";
+// 					$min_diff = abs($temp - 55.0);
+					$opt_primer = $primer;
+					$opt_temp = $temp;
+					$min_len++;
+				}
+				else
+				{
+ 					/*echo "primer: " . $primer . ", temp " . $temp . "<BR>";
+ 					print "Final length of primer only: " . strlen($primer) . "<BR>";
+ 					print "Final length of linker only: " . strlen($fwdLinker) . "<BR>";
+ 					print "Final length of primer with linker: " . strlen($primer) + strlen($fwdLinker) . "<BR>";*/
+
+					# First primer at temp > 55, record it and exit
+					$opt_primer = $primer;
+					$opt_temp = $temp;
+// 					break;
+					$go_on = false;
+				}
+			}
+			else
+			{
+				// Updated Nov. 9/06
+				if (strlen($maxFwdLen) == 0)
+				{
+					//  Max length is not set, go by temp
+					if ($temp <= $fwdTm)
+					{
+						//echo "temp " . $temp . "<BR>";
+						//echo "length not set, going by temp<BR>";
+// 						$min_diff = abs($temp - 55.0);
+						$opt_primer = $primer;
+						$opt_temp = $temp;
+						$min_len++;
+					}
+					else
+					{
+						//echo "Now exceeded max temp; primer: " . $primer . ", temp " . $temp . "<BR>";
+						$opt_primer = $primer;
+						$opt_temp = $temp;
+						$go_on = false;
+					}
+				}
+				else
+				{
+					//echo "Now exceeded max length; primer: " . $primer . ", temp " . $temp . "<BR>";
+					$go_on = false;
+				}
+			}
+		}
+
+ 		//print "Opt primer selected " . $opt_primer . ", temp " . $opt_temp ."<BR>";
+		$fwd_primer = chunk_split($opt_primer, 3, " ");
+		$temp_fwd[$fwd_primer] = $opt_temp;
+		$primers[0] = $temp_fwd;
+
+		# reverse primer
+// 		$min_diff = 100;
+//		echo $revLinker . "<BR>";
+
+		for ($i = 10; $i <= 50; $i++)
+		{
+			$primer = substr($tar_nt_seq, -$i);
+//			print $primer . "<BR>";
+
+			$temp = $this->calcTemp($primer);
+// 			echo "temp " . $temp . "<BR>";
+
+			if (strlen($primer) + strlen($revLinker) <= $maxRevLen)		// 12/09/06
+			{
+				if ($temp <= $revTm)		// 12/09/06
+				{
+//					print "min diff " . $min_diff . ", ";
+					$opt_primer = $primer;
+					$opt_temp = $temp;
+				}
+				else
+				{
+					# First primer at temp > 55, record it and exit
+					$opt_primer = $primer;
+					$opt_temp = $temp;
+					break;
+				}
+			}
+			else
+			{
+				break;
+			}
+		}
+
+		if ($maxRevLen > 0)
+                {
+			for ($i = strlen($opt_primer); $i > 0 ; $i--)
+			{
+				$index = substr($opt_primer, $i-1, 1);
+				$val = $r_table[$index];
+				$rev_primer .= $val;
+			}
+		}
+		else	# added Nov. 21/06
+                {
+			# when max length is not given, take reverse complement of ENTIRE sequence to be cloned until max temp is reached
+                    for ($i = strlen($tar_nt_seq); $i > 0 ; $i--)
+                    {
+
+                    	$index = substr($tar_nt_seq, $i-1, 1);
+                        $val = $r_table[$index];
+                        $rev_primer .= $val;
+                        $opt_temp = $this->calcTemp($rev_primer);
+
+                        if ($opt_temp > $revTm)
+                        {
+                        	break;
+                        }
+                    }
+                }
+		
+		$temp_rev[chunk_split($rev_primer, 3, " ")] = $opt_temp;
+		$primers[1] = $temp_rev;
+
+		return $primers;
+	}
+
+
+	/**
+	 * Squeeze out whitespace from strings (mostly for sequences)
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2006-09-12
+	 *
+	 * @param STRING
+	 * @return STRING
+	*/
+	function filterSpaces($txt)
+	{
+		$pieces = explode(" ", $txt);
+		$result = "";
+
+		foreach ($pieces as $key=>$val)
+		{
+			$result .= $val;
+		}
+
+		return $result;
+	}
+
+
+	/**
+	 * Retrieve the sequence identified by $seqID from the database
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-10-20
+	 *
+	 * @param INT
+	 * @return STRING
+	*/
+	function getSequenceByID($seqID)
+	{
+		global $conn;
+
+		$sequence = "";
+
+		$resultSeq = mysql_query("SELECT sequence FROM Sequences_tbl WHERE seqID='" . $seqID . "' AND status='ACTIVE'", $conn) or die("Could not select sequence " . mysql_error());
+
+		if ($seq_ar = mysql_fetch_array($resultSeq))
+		{
+			$sequence = $seq_ar["sequence"];
+		}
+
+		return $sequence;
+	}
+
+
+	/**
+	 * Retrieve the comment identified by $seqID from the database (GeneralComments_tbl)
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-10-20
+	 *
+	 * @param INT
+	 * @return STRING
+	*/
+	function getCommentByID($commID)
+	{
+		global $conn;
+
+		$comment = "";
+
+		$comm_rs = mysql_query("SELECT comment FROM GeneralComments_tbl WHERE commentID='" . $commID . "' AND status='ACTIVE'", $conn) or die("Could not select sequence " . mysql_error());
+
+		if ($comm_ar = mysql_fetch_array($comm_rs))
+		{
+			$comment = $comm_ar["comment"];
+		}
+
+		return $comment;
+	}
+
+
+	/**
+	 * Get the start position of the given property.
+	 *
+	 * Updated August 13/08: When propName is a feature that has a descriptor (tag type or promoter), there's a problem when there are multiple features with the same feature value AND the same descriptor! (e.g. 2 SV40 promoters, both Mammalian exp.syst. occurring at  different positions on the sequence!!!)  Then the only method of differentiation between them is by position.  Hence, need to fetch ALL database entries and return an array instead of a single position.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-01-29
+	 *
+	 * @param INT
+	 * @param STRING
+	 * @param INT
+	 * @param STRING (optional, used only when there are multiple values for the same property ID, e.g. selectable marker)
+	 *
+	 * @return INT
+	*/
+	function getStartPos($rID, $propName, $propID, $propVal = "")
+	{
+		global $conn;
+
+		$startPos = 0;
+		$startPosList = Array();	// august 13/08
+
+		if (strlen($rID) > 0)
+		{
+			if ($propVal == "")
+			{
+// 				echo "SELECT startPos FROM ReagentPropList_tbl where reagentID=" . $rID . " AND propertyID=" . $propID . " AND status='ACTIVE'";
+
+				$resultSet = mysql_query("SELECT startPos FROM ReagentPropList_tbl where reagentID=" . $rID . " AND propertyID=" . $propID . " AND status='ACTIVE'", $conn) or die("Unable to get " . $propName . " start position 1: " . mysql_error());
+			}
+			else
+			{
+				$query = "SELECT startPos FROM `ReagentPropList_tbl` where `reagentID`=" . $rID . " AND `propertyID`=" . $propID . " AND `propertyValue`='" . addslashes($propVal) . "' AND `status`='ACTIVE'";
+// echo $query;
+				$resultSet = mysql_query($query, $conn) or die("Unable to get " . $propName . " start position 2: " . mysql_error());
+				
+			}
+	
+			while ($startPos_ar = mysql_fetch_array($resultSet, MYSQL_ASSOC))
+			{
+				$startPos = $startPos_ar["startPos"];
+				$startPosList[] = $startPos;		// Aug. 13/08
+			}
+		}
+
+		if ($propVal == "")		// Aug. 15/08
+			return $startPos;
+		else
+			return $startPosList;	// Aug. 13/08
+	}
+
+
+	/**
+	 * Get the end position of the given property.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-01-29
+	 *
+	 * @param INT
+	 * @param STRING
+	 * @param INT
+	 * @param STRING (optional, used only when there are multiple values for the same property ID, e.g. selectable marker)
+	 *
+	 * @return INT
+	*/
+	function getEndPos($rID, $propName, $propID, $propVal = "")
+	{
+		global $conn;
+
+		$endPos = 0;
+		$endPosList = Array();
+
+		if (strlen($rID) > 0)
+		{
+			if ($propVal == "")
+				$resultSet = mysql_query("SELECT endPos FROM ReagentPropList_tbl where reagentID=" . $rID . " AND propertyID=" . $propID . " AND status='ACTIVE'", $conn) or die("Unable to get " . $propName . " end position 1: " . mysql_error());
+			else
+				$resultSet = mysql_query("SELECT endPos FROM ReagentPropList_tbl where reagentID=" . $rID . " AND propertyID=" . $propID . " AND propertyValue='" . addslashes($propVal) . "' AND status='ACTIVE'", $conn) or die("Unable to get " . $propName . " end position 2: " . mysql_error());
+				
+	
+			while ($endPos_ar = mysql_fetch_array($resultSet, MYSQL_ASSOC))
+			{
+				$endPos = $endPos_ar["endPos"];
+				$endPosList[] = $endPos;
+			}
+		}
+
+		if ($propVal == "")		// Aug. 15/08
+			return $endPos;
+		else
+ 			return $endPosList;
+	}
+
+
+	/**
+	 * Get the value of the given property for a specific reagent.
+	 *
+	 * @author Marina Olhovsky
+	 *
+	 * @param INT
+	 * @param INT
+	 * @param STRING
+	 *
+	 * @return MIXED
+	*/
+	function getPropertyValueSpecific($rID, $propID, $propDescr)
+	{
+		global $conn;
+
+		$pVal = 0;
+		
+		if (strlen($rID) > 0)
+		{
+			$query = "SELECT propertyValue FROM `ReagentPropList_tbl` where `reagentID`=" . $rID . " AND `propertyID`=" . $propID . " AND descriptor='" . $propDescr . "' AND `status`='ACTIVE'";
+// echo $query;
+			$resultSet = mysql_query($query, $conn) or die("Unable to get " . $propName . " start position 2: " . mysql_error());
+			
+			while ($prop_ar = mysql_fetch_array($resultSet, MYSQL_ASSOC))
+			{
+				$pVal = $prop_ar["propertyValue"];
+// echo $pVal;
+			}
+		}
+
+		return $pVal;
+	}
+
+
+	/**
+	 * Fetch a feature's start position by descriptor.  Used for printing features in creation forms.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2010-06-08
+	 *
+	 * @param INT
+	 * @param INT
+	 * @param MIXED
+	 * @param STRING
+	 *
+	 * @return INT
+	*/
+	function getStartPosDescr($rID, $propID, $propVal, $propDescr)
+	{
+		global $conn;
+
+		$startPos = 0;
+		
+		if (strlen($rID) > 0)
+		{
+			$query = "SELECT startPos FROM `ReagentPropList_tbl` where `reagentID`=" . $rID . " AND `propertyID`=" . $propID . " AND `propertyValue`='" . addslashes($propVal) . "' AND descriptor='" . $propDescr . "' AND `status`='ACTIVE'";
+// echo $query;
+			$resultSet = mysql_query($query, $conn) or die("Unable to get " . $propName . " start position 2: " . mysql_error());
+			
+			while ($startPos_ar = mysql_fetch_array($resultSet, MYSQL_ASSOC))
+			{
+				$startPos = $startPos_ar["startPos"];
+			}
+		}
+
+		return $startPos;
+	}
+
+
+	/**
+	 * Fetch a feature's end position by descriptor.  Used for printing features in creation forms.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2010-06-08
+	 *
+	 * @param INT
+	 * @param INT
+	 * @param MIXED
+	 * @param STRING
+	 *
+	 * @return INT
+	*/
+	function getEndPosDescr($rID, $propID, $propVal, $propDescr)
+	{
+		global $conn;
+
+		$endPos = 0;
+		
+		if (strlen($rID) > 0)
+		{
+			$query = "SELECT endPos FROM `ReagentPropList_tbl` where `reagentID`=" . $rID . " AND `propertyID`=" . $propID . " AND `propertyValue`='" . addslashes($propVal) . "' AND descriptor='" . $propDescr . "' AND `status`='ACTIVE'";
+// echo $query;
+			$resultSet = mysql_query($query, $conn) or die("Unable to get " . $propName . " start position 2: " . mysql_error());
+			
+			while ($endPos_ar = mysql_fetch_array($resultSet, MYSQL_ASSOC))
+			{
+				$endPos = $endPos_ar["endPos"];
+			}
+		}
+
+		return $endPos;
+	}
+
+
+	/**
+	 * Get the linker portion of an oligo (recursive method, copied from Python).
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-01-30
+	 *
+	 * @param STRING
+	 * @param STRING
+	 * @param STRING
+	 *
+	 * @return STRING
+	*/
+	function linker_from_oligo($insert_seq, $primer_seq, $linker="")
+	{
+		$pos = stripos($insert_seq, $primer_seq);
+
+		if ($pos !== FALSE)
+		{
+			$linker .= substr($primer_seq, 0, 1);
+			$primer_seq = substr($primer_seq, 1);
+			return $this->linker_from_oligo($insert_seq, $primer_seq, $linker);
+		}
+	
+// 		echo "Linker " . $linker . "<BR>";
+	
+		return $linker;
+	}
+
+
+	/**
+	 * Reverse complement a DNA sequence (most likely Oligo - reverse primer).  DO NOT filter spaces - preserve original spacing in linker.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-01-30
+	 *
+	 * @param STRING
+	 * @return STRING
+	*/
+	function reverse_complement($seq)
+	{
+		//echo $seq;
+
+		// Jan. 17, 2011: convert all to lowercase!!
+		$seq = strtolower($seq);
+
+		$complement_map = $this->complement_map;
+		$reverseComplement = "";
+
+		while (strlen($seq) > 0)
+		{
+			$lastChar = substr($seq, -1);
+
+			if ($lastChar == " ")
+			{
+				$reverseComplement .= $lastChar;
+				$seq = substr($seq, 0, strlen($seq)-1);
+			}
+			else
+			{
+				$revChar = $complement_map[$lastChar];
+				$reverseComplement .= $revChar;
+				$seq = substr($seq, 0, strlen($seq)-1);
+			}
+		}
+
+		return $reverseComplement;
+	}
+
+
+	/**
+	 * Get the direction (orientation) of the given property (forward/reverse).  (March 17/08: Added $propVal argument for multiple features).
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-02-22
+	 *
+	 * @param INT
+	 * @param INT
+	 * @param STRING
+	 *
+	 * @return STRING
+	*/
+	function getPropertyDirection($rID, $propID, $propVal="")
+	{
+		global $conn;
+
+		$propName = $_SESSION["ReagentProp_Name_ID"][$propID];		// for error output
+		$direction = "forward";
+
+		if (strlen(trim($propVal)) == 0)
+		{
+			$resultSet = mysql_query("SELECT direction FROM ReagentPropList_tbl where reagentID=" . $rID . " AND propertyID=" . $propID . " AND status='ACTIVE'", $conn) or die("Unable to get " . $propName . " orientation: " . mysql_error());
+		}
+		else
+		{
+			$resultSet = mysql_query("SELECT direction FROM ReagentPropList_tbl where reagentID=" . $rID . " AND propertyID=" . $propID . " AND propertyValue='" . addslashes($propVal) . "' AND status='ACTIVE'", $conn) or die("Unable to get " . $propName . " orientation: " . mysql_error());
+		}
+
+		if ($results = mysql_fetch_array($resultSet, MYSQL_ASSOC))
+			$direction = $results["direction"];
+
+		return $direction;
+	}
+
+
+	/**
+	 * Separate function to select dropdown list values
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2008-03-05
+	 *
+	 * @param STRING
+	 * @return Array
+	*/
+	function getSetValues($setName)
+	{
+		global $conn;
+
+		$propID = $_SESSION["ReagentProp_Name_ID"][strtolower($setName)];
+
+		$setValues = Array();
+
+		$set_rs = mysql_query("SELECT b.entityName FROM System_Set_Groups_tbl a, System_Set_tbl b WHERE a.ssetGroupID=b.ssetGroupID AND a.propertyIDLink='" . $propID . "' AND a.status='ACTIVE' AND b.status ='ACTIVE' ORDER BY b.entityName", $conn) or die("Could not select set values (1): " . mysql_error());
+
+		if( mysql_num_rows( $set_rs ) > 0 )
+		{
+			while ($set_ar = mysql_fetch_array($set_rs , MYSQL_ASSOC))
+			{
+				$setValues[] = $set_ar["entityName"];
+			}
+		}
+		else
+		{
+			mysql_free_result($set_rs);
+
+			$setretry_rs = mysql_query("SELECT b.entityName FROM System_Set_Groups_tbl a, System_Set_tbl b WHERE a.ssetGroupID=b.ssetGroupID AND a.groupName='" . strtolower($name) . "' AND a.status='ACTIVE' AND b.status='ACTIVE' ORDER BY b.entityName", $conn) or die("Could not select set values (2): " . mysql_error());
+
+			if (mysql_num_rows( $setretry_rs ) > 0 )
+			{
+				while( $setretry_ar = mysql_fetch_array( $setretry_rs , MYSQL_ASSOC ) )
+				{
+					$setValues[] = $set_ar["entityName"];
+				}
+			}
+		}
+		
+		return $setValues;
+	}
+
+
+	/**
+	 * Check if this property type exists in ReagentPropType_tbl
+	 *
+	 * @author Marina Olhovsky
+	 * @version 2009-04-06
+	 *
+	 * @param STRING
+	 * @return boolean
+	*/
+	function existsReagentProperty($propType)
+	{
+		global $conn;
+
+		$propID = -1;
+
+		$prop_set_rs = mysql_query("SELECT propertyID FROM ReagentPropType_tbl WHERE propertyAlias='" . $propType . "' AND status='ACTIVE'", $conn) or die("Cannot select reagent properties: " . mysql_error());
+
+		while ($prop_set_ar = mysql_fetch_array($prop_set_rs, MYSQL_ASSOC))
+		{
+			$propID = $prop_set_ar["propertyID"];
+		}
+
+		return $propID;
+	}
+
+}
+?>
diff --git a/OpenFreezer/Reagent/Reagent_Output_Class.php b/OpenFreezer/Reagent/Reagent_Output_Class.php
new file mode 100755
index 0000000..ce64b68
--- /dev/null
+++ b/OpenFreezer/Reagent/Reagent_Output_Class.php
@@ -0,0 +1,6405 @@
+<?php
+/**
+*
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2010 Pawson Laboratory, All Rights Reserved
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Reagent
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+/**
+* Contains output functions for Reagent module
+*
+* @author John Paul Lee @version 2005
+*
+* @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+* @version 3.1
+* @package Reagent
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*
+*/
+class Reagent_Output_Class
+{
+	/**
+	 * @var Reagent_Function_Class
+	 * Helper object (instance of Reagent_Function_Class)
+	*/
+	var $rfunc_obj;
+
+	/**
+	 * Zero-argument constructor
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	*/
+	function Reagent_Output_Class()
+	{
+		$this->rfunc_obj = new Reagent_Function_Class();
+	}
+
+
+	/**
+	 * Output all currently available reagent types in a list (used in 'Search Reagent Types')
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2009-06-03
+	 *
+	*/
+	function printReagentTypesList()
+	{
+		?>
+		<SELECT id="reagentTypes" name="reagentType" onChange="showReagentSubtype()">
+			<OPTION SELECTED value="default">Select reagent type</OPTION>
+			<?php
+				$rTypeNames = array_keys($_SESSION["ReagentType_Name_ID"]);
+				sort($rTypeNames, SORT_STRING);
+
+				foreach ($rTypeNames as $key => $r_type)
+				{
+					echo "<OPTION VALUE=\"" . $r_type . "\">";
+			
+					if ($r_type == "CellLine")
+						echo "Cell Line";
+					else
+						echo $r_type;
+			
+					echo "</OPTION>";
+				}
+			?>
+		</SELECT>
+		<?php
+	}
+
+
+	/**
+	 * Print reagent statistics (number of reagents of each type available in OpenFreezer)
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2010-07-16
+	 *
+	*/
+	function printReagentStats()
+	{
+		global $conn;
+
+		$total = 0;
+		?>
+		<table width="950px">
+			<tr>
+				<td style="font-size:9pt; color:#238E23; font-weight:bold; padding-bottom:10px; padding-left:25px;">
+					Statistics of reagents currently stored in OpenFreezer
+				</td>
+			</tr>
+
+			<TR>
+				<td>
+					<table>
+						<tr>
+							<td style="font-size:9pt; padding-left:25px; padding-bottom:10px;" colspan="3">
+								Number of reagents in the repository:
+							</td>
+						</tr>
+					<?php
+						foreach ($_SESSION["ReagentType_Name_ID"] as $rTypeName => $rTypeID)
+						{
+							echo "<tr>";
+		
+							echo "<TD style=\"font-size:9pt; padding-left:25px; width:100px;\">" . $rTypeName . ": </td>";
+		
+							$rcount_rs = mysql_query("SELECT COUNT(reagentID) as rcount FROM Reagents_tbl WHERE reagentTypeID='" . $rTypeID . "' AND status='ACTIVE'");
+		
+							if ($rcount_ar = mysql_fetch_array($rcount_rs, MYSQL_ASSOC))
+							{
+								$total += $rcount_ar["rcount"];
+								echo "<TD style=\"text-align:right; font-size:9pt;\">" . number_format($rcount_ar["rcount"]) . "</td>";
+							}
+		
+						}
+
+						echo "<TR><TD style=\"padding-top:5px; font-weight:bold; color:#238E23; font-size:9pt; padding-left:25px; width:100px;\">Total:</TD><TD style=\"text-align:right; border-top:1px solid black; padding-top:5px; font-weight:bold; font-size:9pt;\">" . number_format($total) . "</td></tr>";
+					?>
+					</table>
+				</td>
+			</tr>
+		</table>
+		<?php
+	}
+
+
+	// June 10, 2011
+	/**
+	 * Print cell line biosafety statistics
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2011-06-10
+	 *
+	*/
+	function printCellLineBiosafety()
+	{
+		global $conn;
+		global $cgi_path;
+
+		?><P><span class="linkShow" style="margin-left:30px; font-size:10pt;" onClick="document.cellLineBiosafetyForm.submit();">View All Cell Lines according to Biosafety Classification</SPAN>		
+		<FORM name="cellLineBiosafetyForm" METHOD="POST" ACTION="<?php echo $cgi_path . "cell_line_stats.py"; ?>"></FORM><?php
+	}
+
+
+	/**
+	 * Print general information on Reagent Tracker info page
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	*/
+	function print_reagent_intro()
+	{
+		?>
+		<table width="770px">
+			<tr>
+				<td colspan="3" style="color:#333333; font-size:18pt; font-weight:bold; text-align:center">
+					REAGENT TRACKER
+				</td>
+			</tr>
+			<tr>
+				<td border="1" colspan="3" style="font-size:10pt; font-weight:bold; text-align:center; padding-top:10px;">
+					This module is used to track various types of reagents available in the laboratory
+				</td>
+			</tr>
+
+			<tr>
+				<td border="1" colspan="3">
+				<p><p>Currently tracks the following types of reagents:<br>
+					<DL>
+					<DT><font color="#004891"><u><b>Vectors</b></u>:</font><DD>
+					<UL><li>Self-propagating circular DNA that is comprised of a backbone (parent vector) and may contain an insert.<br><br></LI></UL>
+					<DT><font color="#004891"><u><b>Inserts</b></u>:</font>
+					<DD><UL><li>Linear piece of DNA formed either by PCR, oligo hybridization, or restriction digestion of a parent vector.   The purpose of most inserts is to be subcloned into a vector for propagation and downstream applications.  The insert itself is often stored as an intermediate step in the cloning pathway.  Inserts can also be siRNAs.<br><br></LI></UL>
+					<DT><font color="#004891"><u><b>Oligos</b></u>:</font>
+					<DD><UL><li>Single stranded DNA usually less than 100 nucleotides that are used as PCR primers, sequencing primers, or hybridized to form an insert.<br><br></LI></UL>
+					<DT><font color="#004891"><u><b>Cell lines</b></u>:</font>
+					<DD><UL><li>Immortalized cells that are propagated within the laboratory.  The cell lines are classified as either parent cell lines or stable cell lines, where one or more vectors have been stably expressed within the cell line.</LI></UL>
+					</DL>
+				</td>
+				</tr>
+			<tr>
+		</table>
+		<?php
+	}
+
+
+	/**
+	 * Print start or end position for a sequence feature
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param STRING $posFieldName Form input name, e.g. 'reagent_detailedview_selectable_marker_Ampicillin_start_139_prop'
+	 * @param STRING $fAlias Internal feature alias (for form input) - e.g. 'selectable_marker'
+	 * @param INT $fPosType Start or end position (1 = start, 0 = end)
+	 * @param STRING $fValue Actual feature value, e.g. Ampicillin
+	 * @param INT $posVal Actual position, e.g. 139
+	 * @param boolean $readonly Not modifiable in some views, e.g. step 3 of Vector creation, where cloning site positions are loaded from parents and should not be changed
+	*/
+	function print_feature_position($posFieldName, $fAlias, $fPosType, $fValue, $posVal, $readonly)
+	{
+		$rdonly = ($readonly === true) ? "READONLY" : "";
+		$className = ($readonly === true) ? "input_disabled" : "input_normal";
+
+		if ($fPosType == 1)	// start
+		{
+			echo "<input type=\"text\" class=\"" . $className . "\" style=\"font-size:7pt;\"  size=\"5\" id=\"" . $fAlias . "_start\" name=\"" . $posFieldName . "\" value=\"" . (($posVal >= 0) ? $posVal : "") . "\" " . $rdonly . "></input>";
+		}
+		else	// end
+		{
+			echo "<input type=\"text\" class=\"" . $className . "\" size=\"5\" style=\"font-size:7pt;\"  id=\"" . $fAlias . "_end\" name=\"" . $posFieldName . "\" value=\"" . (($posVal >= 0) ? $posVal : "") . "\" " . $rdonly . "></input>";
+		}
+
+		if ($fAlias == $_SESSION["ReagentProp_Name_Alias"]["cdna insert"])
+			echo " <span style=\"font-size:10pt; color:#FF0000; font-weight:bold\">*</span>";
+	}
+
+
+	/**
+	 * Print sequence feature direction (orientation - 'forward' or 'reverse')
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param STRING $dirFieldName Form input name, e.g. 'reagent_detailedview_selectable_marker_Ampicillin_start_139_prop'
+	 * @param STRING $fAlias Internal feature alias (for form input) - e.g. 'selectable_marker'
+	 * @param STRING $fValue Actual feature value, e.g. Ampicillin
+	 * @param STRING $fDir Actual direction - either 'forward' or 'reverse'
+	*/
+	function print_feature_direction($dirFieldName, $fAlias, $fValue, $fDir)
+	{
+		if (!$fDir || ($fDir == "") || (sizeof($fDir) == 0) || (strcasecmp($fDir, "forward") == 0))
+		{
+			$fwd_checked = "checked";
+			$rev_checked = "";
+		}
+		else
+		{
+			$fwd_checked = "";
+			$rev_checked = "checked";
+		}
+
+		echo "<INPUT TYPE=\"radio\" NAME=\"" . $dirFieldName . "\" " . $fwd_checked . " VALUE=\"forward\" style=\"font-size:7pt\">Forward</INPUT>";
+
+		echo "<INPUT TYPE=\"radio\" NAME=\"" . $dirFieldName . "\" " . $rev_checked . " VALUE=\"reverse\" style=\"font-size:7pt\">Reverse</INPUT>";
+	}
+
+
+	/**
+	 * Output a feature descriptor (only two now: Tag Position for Tag or Expression System for Promoter)
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1 2008-05-13
+	 *
+	 * @param STRING $prefix Used in form input name, e.g. 'reagent_detailedview'
+	 * @param STRING $postfix Used in form input name, e.g. '_prop'
+	 * @param STRING $fName Name of the feature associated with this descriptor (either 'tag' or 'promoter' currently)
+	 * @param STRING $fDescr Actual **value** of the **descriptor** (e.g. 'Internal', 'C-Terminus', etc. for Tag Position, or 'Bacterial', 'Mammalian', etc. for Expression System)
+	 * @param STRING $featureValue Value of the feature (tag or promoter, NOT the descriptor!! - e.g. 'His' tag or promoter 'T7') - needed when there are multiple features of the same type in one sequence (three promoters and four tags - need to know which descriptor belongs to which feature at which position)
+	 * @param INT $fStart Start position of the feature
+	 * @param INT $fEnd End position of the feature
+	 * @param INT $rID Internal database reagent ID
+	 * @param boolean $modify Mode ('Modify' or 'View') - passed on to print_property_final() function
+	 * @param STRING $type_of_output Argument for print_property_final()
+	 * @param STRING $subtype Argument for print_property_final()
+	 * @param STRING $rType Reagent type (used to retrieve attribute ID)
+	 * @param boolean $readonly
+	*/
+	function print_feature_descriptor($prefix, $postfix, $fName, $fDescr, $featureValue, $fStart, $fEnd, $rID, $modify= false, $type_of_output = "", $subtype = "", $rType="", $readonly=false)
+	{
+		$rfunc_obj = new Reagent_Function_CLass();
+
+		// Find the descriptor that corresponds to the given feature
+		$f_descriptors = $rfunc_obj->getFeatureDescriptors();
+
+		$aDescr = $f_descriptors[$fName];
+		$fAlias = $_SESSION["ReagentProp_Name_Alias"][$aDescr];
+
+		// Oct. 26/09
+		if ($rID <= 0)
+			$POST_VAR_NAME = $prefix . $rType . "_" . $fAlias . "_:_" . $featureValue . "_start_" . $fStart . "_end_" . $fEnd . $postfix;
+		else
+			$POST_VAR_NAME = $prefix . $fAlias . "_:_" . $featureValue . "_start_" . $fStart . "_end_" . $fEnd . $postfix;
+
+		// Oct. 22/09
+		if ($rfunc_obj->hasAttribute($_SESSION["ReagentType_Name_ID"][$rType], "protein sequence", $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]))
+			$category = "Protein Sequence Features";
+		else if ($rfunc_obj->hasAttribute($_SESSION["ReagentType_Name_ID"][$rType], "rna sequence", $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence"]))
+                        $category = "RNA Sequence Features";
+		else
+			$category = "DNA Sequence Features";
+
+		$fID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][$fName], $_SESSION["ReagentPropCategory_Name_ID"][$category]);
+
+		// make descriptor category also 'features' for simplicity
+		switch ($fName)
+		{
+			case 'tag':
+				$this->print_property_final($POST_VAR_NAME, "tag position",  $fDescr, $rID, $modify, $category, $type_of_output, $subtype, $rType, $readonly);
+			break;
+
+			case 'promoter':
+				$this->print_property_final($POST_VAR_NAME, "expression system",  $fDescr, $rID, $modify, $category, $type_of_output, $subtype, $rType, $readonly);
+			break;
+		}
+	}
+
+
+	/**
+	 * Common gateway for outputting reagents in a uniform fashion
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING $POST_VAR_NAME Name representing the given property on the form (serves as unique HTML identifier)
+	 * @param STRING $type Name of the property to be printed
+	 * @param MIXED $value Property value - alphanumeric data type specific to that property (may be a string, an integer, a float, etc.)
+	 * @param INT $rid Reagent ID
+	 * @param boolean $modify Differentiate between 'view' and 'modify' modes
+	 * @param STRING $category Category in which this property is defined for the current reagent type (added July 9/09)
+	 * @param STRING $type_of_output Passed on to get_Special_Column_Type() as an argument
+	 * @param STRING $subtype Reagent subtype (needed for different Vector subtypes at creation as argument to Javascript, to distinguish when a form contains multiple fields with the same name but some are hidden - added May 28/07)
+	 * @param STRING $rType Reagent type (added Feb. 5/08)
+	 * @param boolean $readonly Indicates whether this property should be printed as a read-only or modifiable field
+	 * @param STRING $descriptor Feature descriptor (if this property is a feature)
+	 * @param INT $start Start position (applies to features only)
+	 * @param INT $end End position (applies to features only)
+	 * @param boolean $isProtein Is this property a Protein sequence property/feature (determines units - nt or aa) - default 'false'
+	 * @param boolean $isRNA Is this property a RNA sequence property/feature - default 'false'
+	 * @param boolean $isDNA Is this property a DNA sequence property/feature - default 'true'
+	 * @param boolean $preload If this property is preloaded from parent reagent (e.g. when changing Cell Line parents), change font colour
+	 *
+	 * @see get_Special_Column_Type()
+	*/
+	function print_property_final($POST_VAR_NAME, $type, $value, $rid, $modify = false, $category="", $type_of_output = "", $subtype = "", $rType="", $readonly=false, $descriptor="", $start=0, $end=0, $isProtein=false, $isRNA=false, $isDNA=true, $preload=false)
+	{
+		global $conn;
+		global $cgi_path;
+
+		if ($isProtein)
+			$units = "aa";
+		else
+			$units = "nt";
+
+//echo $POST_VAR_NAME;
+
+		$functionerror = "print_property_final(";
+
+		$genfunc_obj = new generalFunc_Class();
+		$rfunc_obj = new Reagent_Function_CLass();
+
+		$lims_id = $genfunc_obj->getConvertedID_rid($rid);
+		$rTypeID = $genfunc_obj->get_typeID($lims_id);
+
+		$outputer_obj = new ColFunctOutputer_Class();
+
+		if (!$rTypeID || ($rTypeID < 0) || strlen($rTypeID) == 0)	// creation
+		{
+			$rTypeID = $_SESSION["ReagentType_Name_ID"][$rType];
+		}
+
+		// May 12/06, Marina
+		if (isset($_GET["error_anchor"]))
+		{
+			$font_color = "FF0000";
+		}
+// change jan. 20, 2010
+// 		elseif (isset($_POST["change_vp_id"]) || isset($_POST["change_cl_id"]))
+// 		{
+// 			$font_color = "0000FF";
+// 		}
+		elseif ($preload)
+		{
+			$font_color = "0000FF";
+		}
+// 		else
+// 		{
+// 			$font_color = "000000";
+// 		}
+
+		// Feb. 25/08: Extract prefix and postfix to generate a name for the start and stop input fields
+		if ($rid)
+			$rType = $_SESSION["ReagentType_ID_Name"][$rfunc_obj->getType($rid)];
+
+		$prop_alias = $_SESSION["ReagentProp_Name_Alias"][$type];
+
+		// March 31, 2010
+		$propCatID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][$type], $_SESSION["ReagentPropCategory_Name_ID"][$category]);
+
+		$aliasIndex = strpos($POST_VAR_NAME, $prop_alias) + strlen($prop_alias);
+
+		$prefix = "reagent_detailedview_";
+		$postfix = "_prop";
+
+		$attrID = $rfunc_obj->getRTypeAttributeID($rTypeID, $type, $_SESSION["ReagentPropCategory_Name_ID"][$category]);
+
+		switch ($type)
+		{
+			case "accession number":
+				if ($modify)
+				{
+					if ($this->isDropdownProperty($type, $_SESSION["ReagentPropCategory_Name_ID"][$category], $rTypeID))
+					{
+						if (is_array($value) && (count($value) > 0))
+						{
+							foreach ($value as $key => $val)
+							{
+								echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" value=\"" . $val . "\" name=\"" . $POST_VAR_NAME . "\"><BR>";
+							}
+						}
+						else
+						{
+							echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" value=\"" . $value . "\" name=\"" . $POST_VAR_NAME . "\"><BR>";
+						}
+					}
+					else
+					{
+						echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" value=\"" . $value . "\" name=\"" . $POST_VAR_NAME . "\">";
+					}
+
+					// June 15, 2010
+					echo "  <IMG src=\"" . $hostname . "pictures/link5.png\" WIDTH=\"18\" HEIGHT=\"8\" ALT=\"link_icon\" style=\"cursor:auto\" onmouseover=\"return overlib('You may link out to an external website by entering a complete URL in the textbox, e.g. http://www.mysite.com', CAPTION, 'Hyperlink', STICKY);\">";
+
+					break;
+				}
+
+				// Make the accession value a hyperlink unless the value is "in house"
+// 				if (strcasecmp($value, "in house" ) != 0)
+// 				{
+// 					echo "<a href=\"http://www.ncbi.nlm.nih.gov/entrez/viewer.fcgi?cmd=Search&db=nuccore&val=" . $value . "&doptcmdl=GenBank&cmd=retrieve\" target=\"_blank\">" . $value . "</a>";
+
+					// Modified March 19/09: show multiple accessions
+					echo $this->get_Special_Column_Type("accession number", $category, $rid, "None");
+// 				}
+// 				else
+// 				{
+// 					echo $value;
+// 				}
+			break;
+
+
+			// March 20/07, Marina
+			case "ensembl gene id":
+			
+				if ($modify)
+				{
+					// June 15, 2010: this shouldn't be a dropdown, not for gene id
+// 					if ($this->isDropdownProperty($type, $_SESSION["ReagentPropCategory_Name_ID"][$category], $rTypeID))
+// 					{
+// 						echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" value=\"" . $value . "\" name=\"" . $POST_VAR_NAME . "\">";
+// 					}
+// 					else
+// 					{
+						echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" value=\"" . $value . "\" name=\"" . $POST_VAR_NAME . "\">";
+// 					}
+
+					// June 15, 2010 - should always be a hyperlink but don't think it's implemented for all reagent types
+					echo "  <IMG src=\"" . $hostname . "pictures/link5.png\" WIDTH=\"18\" HEIGHT=\"8\" ALT=\"link_icon\" style=\"cursor:auto\" onmouseover=\"return overlib('You may link out to an external website by entering a complete URL in the textbox, e.g. http://www.mysite.com', CAPTION, 'Hyperlink', STICKY);\">";
+
+					break;
+				}
+				
+				// Link gene ID to appropriate species
+				$species = $rfunc_obj->getPropertyValue($rid, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["species"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]));
+
+				switch (strtolower($species))
+				{
+					case "homo sapiens":
+						echo "<a href=\"http://www.ensembl.org/Homo_sapiens/geneview?gene=" . $value . "\" target=\"_blank\">" . $value . "</a>";
+					break;
+					
+					case "mus musculus":
+						echo "<a href=\"http://www.ensembl.org/Mus_musculus/geneview?gene=" . $value . "\" target=\"_blank\">" . $value . "</a>";
+					break;
+					
+					case "danio rerio":
+						echo "<a href=\"http://www.ensembl.org/Danio_rerio/geneview?gene=" . $value . "\" target=\"_blank\">" . $value . "</a>";
+					break;
+					
+					case "rattus norvegicus":
+						echo "<a href=\"http://www.ensembl.org/Rattus_norvegicus/geneview?gene=" . $value . "\" target=\"_blank\">" . $value . "</a>";
+					break;
+					
+					default:
+						echo $value;
+					break;
+				}
+				
+			break;
+			
+			// March 20/07, Marina
+			case "official gene symbol":
+			
+				if ($modify)
+				{
+					if ($this->isDropdownProperty($type, $_SESSION["ReagentPropCategory_Name_ID"][$category], $rTypeID))
+					{
+						echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" value=\"" . $value . "\" name=\"" . $POST_VAR_NAME . "\">";
+					}
+					else
+					{
+						echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" value=\"" . $value . "\" name=\"" . $POST_VAR_NAME . "\">";
+					}
+
+					if ($rfunc_obj->isHyperlink($attrID))
+						echo "  <IMG src=\"" . $hostname . "pictures/link5.png\" WIDTH=\"18\" HEIGHT=\"8\" ALT=\"link_icon\" style=\"cursor:auto\" onmouseover=\"return overlib('You may link out to an external website by entering a complete URL in the textbox, e.g. http://www.mysite.com', CAPTION, 'Hyperlink', STICKY);\">";
+
+					break;
+				}
+
+				echo $value;
+				
+			break;
+
+			case "alternate id":
+				if ($modify)
+				{
+					$error_tmp = $this->print_Set_Extended_Checkbox("alternate id", $POST_VAR_NAME , $value, $rid, $_SESSION["ReagentType_ID_Prefix"][$rTypeID], $category, $rTypeID);
+
+					break;
+				}
+
+				echo $this->get_Special_Column_Type("alternate id", $category, $rid, "None");
+
+			break;
+			
+			case "entrez gene id":
+			
+				if ($modify)
+				{
+					if ($this->isDropdownProperty($type, $_SESSION["ReagentPropCategory_Name_ID"][$category], $rTypeID))
+					{
+						echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" value=\"" . $value  . "\" name=\"" . $POST_VAR_NAME . "\">";
+					}
+					else
+					{
+						echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" value=\"" . $value . "\" name=\"" . $POST_VAR_NAME . "\">";
+					}
+
+					// June 15, 2010
+					echo "  <IMG src=\"" . $hostname . "pictures/link5.png\" WIDTH=\"18\" HEIGHT=\"8\" ALT=\"link_icon\" style=\"cursor:auto\" onmouseover=\"return overlib('You may link out to an external website by entering a complete URL in the textbox, e.g. http://www.mysite.com', CAPTION, 'Hyperlink', STICKY);\">";
+
+					break;
+				}
+				
+				// hyperlink to Entrez
+				echo "<a href=\"http://www.ncbi.nlm.nih.gov/sites/entrez?Db=gene&Cmd=ShowDetailView&TermToSearch=" . $value . "\" target=\"_blank\">" . $value . "</a>";
+				
+			break;
+
+			case "protein sequence":
+				if ($readonly === true)
+				{
+					$readonly = "READONLY";
+					$fillColor = "#E8E8E8";
+				}
+				else
+				{
+					$readonly = "";
+					$fillColor = "#FFFFFF";
+				}
+
+				if ($modify)
+				{
+					// Added March 28/07, Marina: CREATION VIEW
+					if (strlen($rid) == 0)
+					{
+						echo "<textarea " . $readonly . " rows=\"10\" cols=\"89\" id=\"protein_sequence_" . $rType . "\" name=\"" . $POST_VAR_NAME . "\" style=\"background-color:" . $fillColor . ";\">";
+
+						$sequence = "";
+
+						// Fetch the actual sequence identified by seqID
+						$query = "SELECT `sequence` FROM `Sequences_tbl` WHERE `seqID`='" . $value . "'";
+						$seq_rs = mysql_query($query, $conn) or die("Failure in sequence retrieval: " . $mysql_error());
+
+						if ($seq_ar = mysql_fetch_array($seq_rs, MYSQL_ASSOC))
+						{
+							$sequence = $seq_ar["sequence"];
+						}
+						
+						echo chunk_split($sequence, 10, " ");
+
+							echo "</textarea>";
+					}
+					else
+					{
+						// Jan. 8/09: changed column count to 96
+						echo "<textarea " . $readonly . "\" rows=\"12\" cols=\"96\" id=\"protein_sequence_" . $rType . "\" name=\"" . $POST_VAR_NAME . "\" style=\"padding-left:5px; background-color:" . $fillColor . "\">";
+
+						echo chunk_split($value, 10, " ");
+
+						echo "</textarea>";
+					}
+				}
+				else
+				{
+					echo $this->get_Special_Column_Type($type, $category, $rid, $type_of_output);
+				}
+			break;
+
+			// Aug. 13/09
+			case "rna sequence":
+				if ($readonly === true)
+				{
+					$readonly = "READONLY";
+					$fillColor = "#E8E8E8";
+				}
+				else
+				{
+					$readonly = "";
+					$fillColor = "#FFFFFF";
+				}
+
+				if ($modify)
+				{
+					// Added March 28/07, Marina: CREATION VIEW
+					if (strlen($rid) == 0)
+					{
+						echo "<textarea " . $readonly . " rows=\"10\" cols=\"89\" id=\"rna_sequence_" . $rType . "\" name=\"" . $POST_VAR_NAME . "\" style=\"background-color:" . $fillColor . ";\">";
+					
+						$sequence = "";
+
+						// Fetch the actual sequence identified by seqID
+						$query = "SELECT `sequence` FROM `Sequences_tbl` WHERE `seqID`='" . $value . "'";
+						$seq_rs = mysql_query($query, $conn) or die("Failure in sequence retrieval: " . $mysql_error());
+
+						if ($seq_ar = mysql_fetch_array($seq_rs, MYSQL_ASSOC))
+						{
+							$sequence = $seq_ar["sequence"];
+						}
+						
+						echo chunk_split($sequence, 10, " ");
+
+						echo "</textarea>";
+					}
+					else
+					{
+						// Oct. 26/09: changed column count to 108
+						echo "<textarea " . $readonly . "\" rows=\"12\" cols=\"108\" id=\"rna_sequence_" . $rType . "\" name=\"" . $POST_VAR_NAME . "\" style=\"padding-left:5px; background-color:" . $fillColor . "\">";
+
+						$propID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["rna sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence"]);
+				
+						$rnaSeqRS = mysql_query("SELECT s.`sequence`, s.`start`, s.`end`, s.`length` FROM `Sequences_tbl` s, `ReagentPropList_tbl` r WHERE r.`reagentID`='" . $rid . "' AND r.`propertyID`='" . $propID . "' AND s.`seqID`=r.`propertyValue` AND r.`status`='ACTIVE' AND s.`status`='ACTIVE'", $conn) or die("Could not select sequence: " . mysql_error());
+				
+						if ($seqResult = mysql_fetch_array($rnaSeqRS, MYSQL_ASSOC))
+						{
+							$constRNASeq = $seqResult["sequence"];
+							echo chunk_split($constRNASeq, 10, " ");
+						}
+
+						echo "</textarea>";
+					}
+				}
+				else
+				{
+					echo $this->get_Special_Column_Type($type, $category, $rid, $type_of_output);
+				}
+			break;
+
+			case "sequence":
+
+				// May 2/08, Marina: Sequence can be disabled, depending on function argument
+				if ($readonly === true)
+				{
+					$readonly = "READONLY";
+					$fillColor = "#E8E8E8";
+				}
+				else
+				{
+					$readonly = "";
+					$fillColor = "#FFFFFF";
+				}
+
+				if ($modify)
+				{
+					// Added March 28/07, Marina: CREATION VIEW
+					if (strlen($rid) == 0)
+					{
+						// Nov. 17/08 - assign a different sequence ID for Oligo
+						if ($_SESSION["ReagentType_ID_Name"][$rType] == "Oligo")
+						{
+							echo "<textarea " . $readonly . " rows=\"10\" cols=\"89\" id=\"oligo_dna_sequence\" name=\"" . $POST_VAR_NAME . "\" style=\"background-color:" . $fillColor . ";\">";
+						}
+						else
+						{
+							echo "<textarea " . $readonly . " rows=\"10\" cols=\"89\" id=\"dna_sequence_" . $rType . "\" name=\"" . $POST_VAR_NAME . "\" style=\"background-color:" . $fillColor . ";\">";
+						}
+
+						$sequence = "";
+
+						// Fetch the actual sequence identified by seqID
+						$query = "SELECT `sequence` FROM `Sequences_tbl` WHERE `seqID`='" . $value . "'";
+						$seq_rs = mysql_query($query, $conn) or die("Failure in sequence retrieval: " . $mysql_error());
+
+						if ($seq_ar = mysql_fetch_array($seq_rs, MYSQL_ASSOC))
+						{
+							$sequence = $seq_ar["sequence"];
+						}
+						
+						echo chunk_split($sequence, 10, " ");
+
+						echo "</textarea>";
+					}
+					else
+					{
+						// Jan. 8/09: changed column count to 96
+						echo "<textarea " . $readonly . "\" rows=\"12\" cols=\"96\" id=\"dna_sequence_" . $rType . "\" name=\"" . $POST_VAR_NAME . "\" style=\"padding-left:5px; background-color:" . $fillColor . "\">";
+
+						if (strlen(trim($value)) > 0)
+						{
+							echo $this->get_Special_Column_Type($type, $category, $rid, "modify");
+						}
+
+						echo "</textarea>";
+					}
+				}
+				else
+				{
+					echo $this->get_Special_Column_Type($type, $category, $rid, $type_of_output);
+				}
+			break;
+			
+			case "protein translation":
+				echo $this->get_Special_Column_Type($type, $category, $rid, $type_of_output);
+			break;
+			
+			case "length":	
+				echo $this->get_Special_Column_Type("length", $category, $rid, $type_of_output);
+			break;
+			
+			// Restored March 30/07, Marina; updated April 6/07 - added "if modify" condition
+			// August 13/07: making modifiable
+ 			case "packet id":
+				if ($modify)
+				{
+					echo "<select id=\"values_" . $attrID . "\" size=\"1\" name=\"" . $POST_VAR_NAME . "\" style=\"font-size:7pt;\">";
+						$error_tmp = $this->get_Special_Column_Type("packet", $category, $rid, "modify");
+					echo "</select>";
+					
+					// May 11/08: Put warning here
+					?>
+						<BR><div NAME="warnings[]" id="warn_<?php echo $attrID; ?>" style="display:none; color:#FF0000">Please select a Project ID from the dropdown list</div>
+					<?php
+				}
+				else
+				{
+					echo $this->get_Special_Column_Type("packet", $category, $rid, "preview");
+				}
+ 			break;	
+
+			case "5' cloning site":
+
+				if ($modify)
+				{
+					// Aug. 5/08: 'Select' elements don't have a 'readonly' attribute, but 'disabled' prevents the element from being submitted with the form.  Solution: Keep 'disabled' here, AND EVERYWHERE this element is used, add a Javascript call on form submit that enables the 'select' box.
+					$rdOnly = ($readonly === true) ? "DISABLED" : "";
+
+					// if-else block added Feb. 25/08: Call different JS functions depending on view
+					if (strlen($rid) <= 0)
+					{
+						// Creation - reagent ID unknown.  MUST BE MORE SPECIFIC WITH GATEWAY SITES (e.g. attB1, attL2, etc. instead of just attB, attL, etc.)
+						echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier; color:" . $font_color . "\" id=\"fpcs_list_1\" name=\"" . $POST_VAR_NAME . "\" onChange=\"showHideFivePrimeOther('" . $subtype . "');\" " . $rdOnly . ">";
+					}
+					// March 5/08
+					else if ($rType == $_SESSION["ReagentType_Name_ID"]["Insert"])
+					{
+						echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier; color:" . $font_color . "\" id=\"fpcs_list_1\" name=\"" . $POST_VAR_NAME . "\" onChange=\"showHideFivePrimeOther('" . $subtype . "');\" " . $rdOnly . ">";
+					}
+					// April 18/08
+					else if ($subtype != "")
+					{
+						echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier; color:" . $font_color . "\" id=\"fpcs_list_" . $subtype . "\" name=\"" . $POST_VAR_NAME . "\" onChange=\"showHideFivePrimeOther('" . $subtype . "');\" " . $rdOnly . ">";
+					}
+					else
+					{
+						echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier; color:" . $font_color . "\" id=\"fpcs_list\" name=\"" . $POST_VAR_NAME . "\" onChange=\"showHideFivePrimeOther('" . $subtype . "');\" " . $rdOnly . ">";
+					}
+
+					echo "</select>";
+
+					echo "<input type=\"hidden\" id=\"fpcs_val\" value=\"" . $value . "\"></input>";
+
+					// DO NOT USE 'DISABLED'
+					$disabled = ($readonly === true) ? "READONLY=\"true\"" : "";
+					$inputColor = ($readonly === true) ? "#E9E9E9" : "";
+
+					echo "  <INPUT TYPE=\"TEXT\" onKeyPress=\"return disableEnterKey(event);\" style=\"font-size:8pt; display:none; background-color:" . $inputColor . "\" ID=\"fpcs_txt_" . $subtype . "\" NAME=\"5_prime_cloning_site_name_txt\" SIZE=\"20\" value=\" " . $value . "\"" . $disabled . "> </INPUT>";
+
+					break;
+				}
+
+				echo $value;
+
+				// Jan. 29/08: Show positions
+				$pStart = $rfunc_obj->getStartPos($rid, $type, $_SESSION["ReagentProp_Name_ID"]["5' cloning site"], "");
+				$pEnd = $rfunc_obj->getEndPos($rid, $type, $_SESSION["ReagentProp_Name_ID"]["5' cloning site"], "");
+
+				if (($pStart > 0) && ($pEnd > 0))
+				{
+					echo "  <span style=\"color:#006400\">(" . $units . " " . $pStart . " -";
+					echo " " . $pEnd . ")</span>";
+				}
+			break;
+
+			case "3' cloning site":
+				
+				if ($modify)
+				{
+					// Aug. 5/08: 'Select' elements don't have a 'readonly' attribute, but 'disabled' prevents the element from being submitted with the form.  Solution: Keep 'disabled' here, AND EVERYWHERE this element is used, add a Javascript call on form submit that enables the 'select' box.
+					$rdOnly = ($readonly === true) ? "DISABLED" : "";
+
+					// if-else block added Feb. 25/08: Call different JS functions depending on view
+					if (strlen($rid) <= 0)
+					{
+						echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier; color:" . $font_color . "\" id=\"tpcs_list_1\" name=\"" . $POST_VAR_NAME . "\" onChange=\"showHideThreePrimeOther('" . $subtype . "');\" " . $rdOnly . "></select>";
+					}
+
+					// March 5/08
+					else if ($rType == $_SESSION["ReagentType_Name_ID"]["Insert"])
+					{
+						echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier; color:" . $font_color . "\" id=\"tpcs_list_1\" name=\"" . $POST_VAR_NAME . "\" onChange=\"showHideFivePrimeOther('" . $subtype . "');\" " . $rdOnly . ">";
+					}
+
+					// April 18/08
+					else if ($subtype != "")
+					{
+						echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier; color:" . $font_color . "\" id=\"tpcs_list_" . $subtype . "\" name=\"" . $POST_VAR_NAME . "\" onChange=\"showHideFivePrimeOther('" . $subtype . "');\" " . $rdOnly . ">";
+					}
+					else
+					{
+						echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier; color:" . $font_color . "\" id=\"tpcs_list\" name=\"" . $POST_VAR_NAME . "\" onChange=\"showHideThreePrimeOther('" . $subtype . "');\" " . $rdOnly . "></select>";
+					}
+
+					echo "</select>";
+
+					echo "<input type=\"hidden\" id=\"tpcs_val\" value=\"" . $value . "\"></INPUT>";
+
+					// DO NOT USE 'DISABLED'
+					$disabled = $rdOnly ? "READONLY=\"true\"" : "";
+					$inputColor = $rdOnly ? "#E9E9E9" : "";
+
+					echo "  <INPUT TYPE=\"text\" onKeyPress=\"return disableEnterKey(event);\" NAME=\"3_prime_cloning_site_name_txt\" ID=\"tpcs_txt_" . $subtype . "\" SIZE=\"20\" style=\"display:none; font-size:8pt; background-color:" . $inputColor . ";\" value=\"" . $value . "\" " . $disabled . "></INPUT>";
+
+					break;
+				}
+
+				echo $value;
+
+				// Jan. 29/08: Show positions
+				$pStart = $rfunc_obj->getStartPos($rid, $type, $_SESSION["ReagentProp_Name_ID"]["3' cloning site"], "");
+				$pEnd = $rfunc_obj->getEndPos($rid, $type, $_SESSION["ReagentProp_Name_ID"]["3' cloning site"], "");
+
+				if (($pStart > 0) && ($pEnd > 0))
+				{
+					echo "  <span style=\"color:#006400\">(nt " . $pStart . " -";
+					echo " " . $pEnd . ")</span>";
+				}
+			break;
+				
+			case "5' linker":
+
+				if ($modify)
+				{
+					echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" ID=\"fp_linker_prop\" value=\"" . $value . "\" name=\"" . $POST_VAR_NAME . "\">";
+
+					break;
+				}
+
+				$tmp_linker = $this->get_Special_Column_Type("5' linker", $category, $rid, "None");
+				echo $tmp_linker;
+
+				// Feb. 13/08: Show positions
+				$pStart = $rfunc_obj->getStartPos($rid, $type, $_SESSION["ReagentProp_Name_ID"]["5' linker"], "");
+				$pEnd = $rfunc_obj->getEndPos($rid, $type, $_SESSION["ReagentProp_Name_ID"]["5' linker"], "");
+
+				// Update March 3/09 - show linker IFF not empty
+				if ($tmp_linker && (strlen($tmp_linker) > 0) && ($pStart >= 0) && ($pEnd >= 0))
+				{
+					echo "  <span style=\"color:#006400\">(nt " . $pStart . " -";
+					echo " " . $pEnd . ")</span>";
+				}
+			break;
+				
+			case "3' linker":
+
+				if ($modify)
+				{
+					echo "<INPUT type=\"text\" onKeyPress=\"return disableEnterKey(event);\" ID=\"tp_linker_prop\" value=\"" . $value . "\" name=\"" . $POST_VAR_NAME . "\">";
+
+					break;
+				}
+
+				$tmp_linker = $this->get_Special_Column_Type("3' linker", $category, $rid, "None");
+				echo $tmp_linker;
+
+				// Feb. 13/08: Show positions
+				$pStart = $rfunc_obj->getStartPos($rid, $type, $_SESSION["ReagentProp_Name_ID"]["3' linker"], "");
+				$pEnd = $rfunc_obj->getEndPos($rid, $type, $_SESSION["ReagentProp_Name_ID"]["3' linker"], "");
+
+				// Update March 3/09 - show linker IFF not empty
+				if ($tmp_linker && (strlen($tmp_linker) > 0) && ($pStart >= 0) && ($pEnd >= 0))
+				{
+					echo "  <span style=\"color:#006400\">(nt " . $pStart . " -";
+					echo " " . $pEnd . ")</span>";
+				}
+			break;
+
+			case "restriction site":
+				if ($modify)
+				{
+					if (($rTypeID == $_SESSION["ReagentType_Name_ID"]["Vector"]) || ($rTypeID == $_SESSION["ReagentType_Name_ID"]["Insert"]))
+					{
+						echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier; color:" . $font_color . "\" id=\"restriction_site_:_list\" name=\"" . $POST_VAR_NAME . "\"></select>";
+	
+						echo "<br>";
+						?>
+							<INPUT style="margin-top:2px; display:none" id="restriction_site_:_txt" name="restriction_site_:_name_txt" size="20"></INPUT>
+						<?php
+					}
+					else
+					{
+						echo "<select size=\"1\" id=\"" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$rTypeID]) . "_restriction_site_:_list\" name=\"" . $POST_VAR_NAME . "\" style=\"font-size:7pt;\">";
+
+						$error_tmp = $this->print_Set_Final_Dropdown($type, $value, $category, $rTypeID, "Preview");
+						echo "</select>";
+					}
+		
+					break;
+				}
+			
+				echo $this->get_Special_Column_Type($type, $category, $rid, "None");
+			break;
+
+			default:
+
+				if ($modify)
+				{
+					if ($readonly)
+						$disabled = "DISABLED";
+					else
+						$disabled = "";
+
+					// June 8, 2010: isDropdownProperty checks whether there are dropdown list values assigned to this property; if none have been assigned yet b/c the property is customizeable (only 'Allow Other' was checked during reagent type creation/modification, then isDropdownProperty() would return false but isCustomizeable() would return true.
+					if ($this->isDropdownProperty($type, $_SESSION["ReagentPropCategory_Name_ID"][$category], $rTypeID) || $rfunc_obj->isCustomizeable($attrID))
+					{
+ 				//		echo "THIS IS DROPDOWN " . $type;
+
+						// Jan. 18, 2010
+						if (!$rfunc_obj->isSequenceFeature($propCatID))
+						{
+							if ($rfunc_obj->isMultiple($attrID))
+							{
+								$vals = Array();
+								$cb_id = "mult_cb_" . $attrID;
+
+								// there can still be only one value stored for a multiple list
+								if (is_array($value))
+								{
+									$vals = $value;
+								}
+								else
+								{
+									$vals[] = $value;
+								}
+
+								// Make a small table w/ 2 lists again
+								if ($value != "")
+								{
+									$mult_display = "inline";
+									$one_display = "none";
+								}
+								else
+								{
+									$mult_display = "none";
+									$one_display = "inline";
+								}
+
+								?>
+								<DIV ID="multiples_<?php echo $attrID; ?>">
+									<TABLE>
+										<TR>
+											<TD><?php
+
+												echo "<SELECT MULTIPLE=\"MULTIPLE\" SIZE=\"5\" id=\"targetList_" . $attrID . "\" name=\"" . $POST_VAR_NAME . "\" style=\"font-size:7pt; color:#" . $font_color . "\">";
+
+												foreach ($vals as $key => $value)
+												{
+													// May 14, 2010: important not to print empty options!!
+													if ($value != "")
+													{
+														echo "<OPTION VALUE=\"" . $value . "\">" . $value . "</OPTION>";
+													}
+												}
+	
+												echo "</SELECT>";
+											?></TD>
+	
+											<TD>
+												<!-- buttons -->
+												<INPUT TYPE="BUTTON" VALUE="<< Add" NAME="addBtn[]" style="font-size:7pt;" onclick="moveListElements('srcList_<?php echo $attrID; ?>', 'targetList_<?php echo $attrID; ?>', false, true);"><BR>
+	
+												<INPUT TYPE="BUTTON" NAME="rmvBtn[]" STYLE="font-size:7pt;" style="font-size:8pt;" VALUE="Remove >>" onclick="moveListElements('targetList_<?php echo $attrID; ?>', 'srcList_<?php echo $attrID; ?>', false, false);">
+											</TD>
+	
+											<TD>
+												<SELECT MULTIPLE SIZE="5" ID="srcList_<?php echo $attrID; ?>" style="font-size:7pt"><?php
+	
+												$allAttrVals = $rfunc_obj->getAllReagentTypeAttributeSetValues($attrID);
+	
+												foreach ($allAttrVals as $sKey => $sVal)
+												{
+													if (!in_array($sVal, $vals))
+													{
+														echo "<OPTION VALUE=\"" . $sVal . "\">" . $sVal . "</OPTION>";
+													}
+												}
+												?></SELECT>
+											</TD>
+										</TR>
+	
+										<!-- Other -->
+										<?php
+
+										if ($rfunc_obj->isCustomizeable($attrID))
+										{
+											?>
+											<TR>
+												<TD colspan="3">
+													<INPUT TYPE="text" NAME="" ID="otherText_<?php echo $attrID; ?>">
+		
+													<INPUT TYPE="button" style="font-size:7pt;" VALUE="Add" ID="addOtherBtn_<?php echo $attrID; ?>" onClick="addElementToListFromInput('otherText_<?php echo $attrID; ?>', 'targetList_<?php echo $attrID; ?>')" NAME="addBtn[]">
+												</TD>
+											</TR>
+											<?php
+										}
+									?>
+									</TABLE>
+								</DIV><?php
+								break;
+							}
+							else
+							{
+								if ($value != "")
+								{
+									if ($descr != "")
+									{
+										$descrTypes = $rfunc_obj->getFeatureDescriptors();
+	
+										$descrType = $descrTypes[$type];
+	
+										$rowID = $prefix . $_SESSION["ReagentProp_Name_Alias"][$type] . "_:_" . $value . "_" . $descrType . "_" . $descr . "_start_" . $start . "_end_" . $end . $postfix;
+	
+										$txtID = $rType . "_" . $_SESSION["ReagentProp_Name_Alias"][$type] . "_:_" . $value . "_" . $descrType . "_" . $descr . "_start_" . $start . "_end_" . $end . "_" . "txt";
+									}
+									else
+									{
+										$txtID = $rType . "_" . $_SESSION["ReagentProp_Name_Alias"][$type] . "_:_" . $value . "_start_" . $start . "_end_" . $end . "_" . "txt";
+	
+										$rowID = $prefix . $_SESSION["ReagentProp_Name_Alias"][$type] . "_:_" . $value . "_start_" . $start . "_end_" . $end . $postfix;
+									}
+								}
+								else
+								{
+									$txtID = str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$rTypeID]) . "_" . $_SESSION["ReagentProp_Name_Desc"][$type] . "_txt";
+	
+									$rowID = str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$rTypeID]) . "_" . $_SESSION["ReagentProp_Name_Desc"][$type] . "_prop";
+								}
+							}
+						}
+						else
+						{
+							if ($rfunc_obj->isDescriptor($type))
+							{
+								// extract main prop info from $POST_VAR_NAME
+								$before = $prefix . $type . "_:_";
+								
+								$list_id = substr($POST_VAR_NAME, strlen($before), strlen($POST_VAR_NAME)-strlen($before)-strlen($postfix));
+
+								$txtID = $prefix . $_SESSION["ReagentProp_Name_Alias"][$type] . "_:_" . $list_id . "_txt";
+							}
+							else
+							{
+								$txtID = $prefix . $_SESSION["ReagentProp_Name_Alias"][$type] . "_:_" . $value . "_start_" . $start . "_end_" . $end . "_" . "txt";
+
+								// Now: CANNOT use simply values_attrID for the list ID, because when there is > 1 of the same feature type, the Other textbox is not shown for the second (the 2 lists have the same ID!!!)  Need to supply again a way of differentiating b/w rows - e.g. with value, positions, direction
+								$tmpStart = strlen($prefix . $_SESSION["ReagentProp_Name_Alias"][$type] . "_:_");
+								
+								$list_id = substr($txtID, $tmpStart, strlen($txtID)-$tmpStart-strlen($postfix)+1);
+							}
+
+							// Jan 18/10
+							$rowID = $prefix . $_SESSION["ReagentProp_Name_Alias"][$type] . "_:_" . $value . "_start_" . $start . "_end_" . $end . $postfix;
+						}
+
+						// update June 9/10
+						// Must have different list IDs for features since there can be multiple, BUT in latest implementation of mandatory props check, a list ID "values_" . $attrID is used.
+						// Bottom line: differentiate here b/w features and non-features
+						if (!$rfunc_obj->isSequenceFeature($propCatID))
+						{
+							echo "<select id=\"values_" . $attrID . "\" name=\"" . $POST_VAR_NAME . "\" style=\"font-size:7pt; color:#" . $font_color . "\" " . $disabled . " onChange=\"showSpecificOtherTextbox(this.id, '" . str_replace("'", "\'", $txtID) . "');\">";
+						}
+						else
+						{
+							echo "<select id=\"values_" . $attrID . "_" . $list_id . "\" name=\"" . $POST_VAR_NAME . "\" style=\"font-size:7pt; color:#" . $font_color . "\" " . $disabled . " onChange=\"showSpecificOtherTextbox(this.id, '" . str_replace("'", "\'", $txtID) . "');\">";
+						}
+
+						$error_tmp = $this->print_Set_Final_Dropdown($type, $value, $category, $rTypeID, "Preview");
+
+						echo "</select>";
+
+						// March 3, 2011
+						if (strcasecmp($type, "type of insert") == 0)
+						{
+							echo "<INPUT TYPE=\"hidden\" id=\"type_of_insert_attr_id_hidden\" VALUE=\"" . $attrID . "\">";
+
+							// THIS IS THE GOOD 'HELP TOOLTIP' IMAGE!!!
+//							echo "  <IMG src=\"" . $hostname . "pictures/hm.png\" HEIGHT=\"18\" width=\"18\" ALT=\"link_icon\" style=\"vertical-align:middle; cursor:auto\" onmouseover=\"return overlib('Select the correct type of insert to ensure correct  translation of the DNA sequence to protein.', CAPTION, 'Type of Insert', STICKY);\">";
+
+							echo "<span ID=\"translationRules\" class=\"linkExportSequence\" style=\"vertical-align:bottom; margin-left:5px; font-size:9pt;\" onClick=\"return popup('Reagent/pr_translation_rules.pdf', 'Protein Translation Rules', 1200, 1200, 'yes');\">Translation Guidelines</span><IMG SRC=\"pictures/new01.gif\" ALT=\"new\" WIDTH=\"35\" HEIGHT=\"20\">";
+						}
+
+						// March 3, 2011
+						if (strcasecmp($type, "open/closed") == 0)
+						{
+//							echo "    <IMG src=\"" . $hostname . "pictures/link5.png\" WIDTH=\"18\" HEIGHT=\"8\" ALT=\"link_icon\" style=\"cursor:auto\" onmouseover=\"return overlib('Select the correct open/closed value to ensure correct  translation of the DNA sequence to protein.', CAPTION, 'Open/Closed', STICKY);\">";
+
+							echo "  <span ID=\"translationRules\" class=\"linkExportSequence\" style=\"margin-left:5px; font-size:9pt;\" onClick=\"return popup('Reagent/pr_translation_rules.pdf', 'Protein Translation Rules', 1200, 1200, 'yes');\">Translation Guidelines</span><IMG SRC=\"pictures/new01.gif\" ALT=\"new\" WIDTH=\"35\" HEIGHT=\"20\">";
+						}
+
+						if (!$rfunc_obj->isSequenceFeature($propCatID))
+						{
+							$txtName = $prefix . $rType . "_" . $_SESSION["ReagentPropCategory_Name_Alias"][$category] . "_:_" . $_SESSION["ReagentProp_Name_Alias"][$type] . "_name_txt";
+						}
+						else
+						{
+							$txtName = str_replace("_prop", "_name_txt", $POST_VAR_NAME);
+						}
+
+						echo "<INPUT type=\"text\" style=\"display:none; width:200px; font-size:7pt;\" ID=\"" . $txtID . "\" onKeyPress=\"return disableEnterKey(event);\" value=\"" . $value . "\" name=\"" . $txtName . "\">";
+
+						?><div NAME="warnings[]" id="warn_<?php echo $attrID; ?>" style="display:none; color:#FF0000;"><BR>Please select a value for <?php echo $_SESSION["ReagentProp_Name_Desc"][$type]; ?> from the dropdown list</div><?php
+
+						break;
+					}
+					else if ($this->isComment($type, $_SESSION["ReagentPropCategory_Name_ID"][$category], $rTypeID))
+					{
+						$descrValue = $this->get_Special_Column_Type($type, $category, $rid, "None");
+
+						echo "<INPUT type=\"text\" " . $disabled . " onKeyPress=\"return disableEnterKey(event);\" value=\"" . $descrValue . "\" name=\"" . $POST_VAR_NAME . "\" style=\"color:#" . $font_color . ";\">";
+
+						// June 15, 2010: show hyperlink tooltip
+						if ($rfunc_obj->isHyperlink($attrID))
+							echo "  <IMG src=\"" . $hostname . "pictures/link5.png\" WIDTH=\"18\" HEIGHT=\"8\" ALT=\"link_icon\" style=\"cursor:auto\" onmouseover=\"return overlib('You may link out to an external website by entering a complete URL in the textbox, e.g. http://www.mysite.com', CAPTION, 'Hyperlink', STICKY);\">";
+
+						break;
+					}
+					else
+					{
+						// append units to Tm and MW (April 14, 2011)
+						if ($type == "melting temperature")
+						{
+							if (is_array($value) && count($value) == 0)
+								$value = "";
+
+							echo "<INPUT type=\"text\" " . $disabled . " id=\"values_" . $attrID . "\" onKeyPress=\"return disableEnterKey(event);\" value=\"" . $value . "\" name=\"" . $POST_VAR_NAME . "\" style=\"color:" . $font_color . ";\" SIZE=\"5\">";
+
+							echo " <b>°C</b>";
+						}
+						else if ($type == "molecular weight")
+						{
+							if (is_array($value) && count($value) == 0)
+								$value = "";
+
+							$val = ($value != "") ? round($value, 2) : $value;
+
+							echo "<INPUT type=\"text\" " . $disabled . " id=\"values_" . $attrID . "\" onKeyPress=\"return disableEnterKey(event);\" value=\"" . $val . "\" name=\"" . $POST_VAR_NAME . "\" style=\"color:" . $font_color . ";\" SIZE=\"5\">";
+
+							if ($isProtein)
+								echo " <b>kDa</b>";
+							else
+								echo " <b>g/mol</b>";
+						}
+						else	// added this 'else' on April 14, 2011 to show a smaller box for Tm and MW
+						{
+							if (is_array($value) && count($value) == 0)
+								$value = "";
+
+							echo "<INPUT type=\"text\" " . $disabled . " id=\"values_" . $attrID . "\" onKeyPress=\"return disableEnterKey(event);\" value=\"" . $value . "\" name=\"" . $POST_VAR_NAME . "\" style=\"color:" . $font_color . ";\">";
+						}
+						// June 15, 2010 show hyperlink tooltip
+						if ($rfunc_obj->isHyperlink($attrID))
+							echo "  <IMG src=\"" . $hostname . "pictures/link5.png\" WIDTH=\"18\" HEIGHT=\"8\" ALT=\"link_icon\" style=\"cursor:auto\" onmouseover=\"return overlib('You may link out to an external website by entering a complete URL in the textbox, e.g. http://www.mysite.com', CAPTION, 'Hyperlink', STICKY);\">";
+
+						// May 20, 2010: changed ID
+						?><BR><div NAME="warnings[]" id="warn_<?php echo $attrID; ?>" style="display:none; color:#FF0000">Please provide a <?php echo $_SESSION["ReagentProp_Name_Desc"][$type]; ?> value for the new <?php echo $_SESSION["ReagentType_ID_Name"][$rTypeID]; ?></div><?php
+
+						break;
+					}
+				}
+
+				if ($rfunc_obj->isSequenceFeature($rid, $type))
+				{
+					echo $this->get_Special_Column_Type($type, $category, $rid, "None");
+
+					?><BR><div id="<?php echo str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$rTypeID]) . "_" . $_SESSION["ReagentProp_Name_Desc"][$type]; ?>_warning" style="display:none; color:#FF0000">Please provide <?php echo $_SESSION["ReagentProp_Name_Desc"][$type]; ?> for the new <?php echo $_SESSION["ReagentType_ID_Name"][$rTypeID]; ?></div><?php
+
+					break;
+				}
+
+				// June 15, 2010: Output hyperlinks
+				if ($rfunc_obj->isHyperlink($attrID))
+					echo "<a href=\"" . $value . "\">" . $value . "</a>";
+				else
+				{
+					if (is_array($value))
+					{
+						echo "<UL style=\"padding-left:15px;\">";
+
+						foreach ($value as $a => $val)
+							echo "<LI>" . $val . "</LI>";
+
+						echo "</UL>";
+					}
+					else
+					{
+						// May 9, 2011: round MW
+						if ($type == "molecular weight")
+						{
+							echo round($value, 2);
+						}
+						else
+							echo $value;
+					}
+				}
+
+				// April 14, 2011: Add units
+				if ($type == "melting temperature")
+					echo " <b>°C</b>";
+
+				else if ($type == "molecular weight")
+				{
+					if ($isProtein)
+						echo " <b>kDa</b>";
+					else
+						echo " <b>g/mol</b>";
+				}
+
+			break;
+		}
+	}
+
+	
+	/**
+	 * Print individual properties that require special output format
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING $type Name of the property to be printed
+	 * @param INT $rid Reagent ID
+	 * @param STRING $category Category in which this property is defined for the current reagent type (added Aug. 21/09)
+	 * @param STRING $output_type Passed on to get_Special_Column_Type() as an argument
+	*/
+	function get_Special_Column_Type($type, $category, $rid, $output_type)
+	{
+		$outputer_obj = new ColFunctOutputer_Class();
+		$toreturn = $outputer_obj->output_final($rid, $type, $output_type, $category);
+		unset( $outputer_obj );
+		
+		return $toreturn;
+	}
+
+
+	// -----------------------------------------------------------------------------------------------------------------------------
+	// The next 3 functions were written to preload information about parents during the modification of reagent associations
+	// They may be combined into one function and differentiated on reagent type - I have separated them for now in case they
+	// need to be extended later on
+	// May 4, 2006, Marina
+	// -----------------------------------------------------------------------------------------------------------------------------
+
+	/**
+	 * Preload parent vector properties at Stable cell line modification
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-05-04
+	 *
+	 * @param INT $rID reagent ID (child cell line)
+	 * @deprecated
+	*/
+// removed Nov. 24, 2010
+// 	function preload_StableCL_PV_props($rID)
+// 	{
+// 		$prefix = "reagent_detailedview_";
+// 		$postfix = "_prop";
+// 	
+// 		$v_names = $this->rfunc_obj->get_Post_Names("Vector", "General");
+// 	
+// 		$creator_obj = new Reagent_Creator_Class();
+// 		$property_tmp = array();
+// 	
+// 		if( $rID > 0 )
+// 		{
+// 			$property_tmp = $creator_obj->backFill($rID, $v_names);
+// 		}
+// 	
+// 		return $property_tmp;
+// 	}
+
+	/**
+	 * Preload parent cell line properties at Stable cell line modification
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-05-01
+	 *
+	 * @param INT $rID reagent ID (child cell line)
+	 * @deprecated
+	*/
+// removed Nov. 24, 2010
+// 	function preload_CellLineProps_Modify($rID)
+// 	{
+// 		$prefix = "reagent_detailedview_";
+// 		$postfix = "_prop";
+// 	
+// 		$cl_names = $this->rfunc_obj->get_Post_Names("CellLine", "");
+// 	
+// 		$creator_obj = new Reagent_Creator_Class();
+// 		$property_tmp = array();
+// 	
+// 		if( $rID > 0 )
+// 		{	
+// 			// Match property names to their database ids
+// 			$property_tmp = $creator_obj->backFill($rID, $cl_names);
+// 		}
+// 	
+// 		return $property_tmp;
+// 	}
+
+	/**
+	 * Central function for displaying reagent detailed view, that invokes other output functions to print a detailed view depending on the reagent type
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING $modify
+	 * @param INT $view Page number for redirection
+	 * @param INT $toViewReagentID Current reagent ID
+	 * @param INT $check Error code from parent modification
+	*/
+	function print_Detailed_Reagent($modify, $view, $toViewReagentID, $check)
+	{
+		global $conn;
+
+		$gfunc_obj = new generalFunc_Class();
+		$modify_state = false;
+
+		if ($modify == "Modify")
+		{
+			$modify_state = true;
+		}
+		
+		$typeOf_rs = mysql_query("SELECT `reagentTypeID`, `groupID` FROM `Reagents_tbl` WHERE `status`='ACTIVE' AND `reagentID`='" . $toViewReagentID . "'", $conn);
+		
+		// July 17/07, Marina: Limit modification by project - restrict to Admin, project owner or writers in this project
+		$currUserID = $_SESSION["userinfo"]->getUserID();
+		$currUserCategory = $_SESSION["userinfo"]->getCategory();
+		$userProjects = getUserProjectsByRole($currUserID, 'Writer');
+
+		$rIDpID = getReagentProjectID($toViewReagentID);
+
+		// Admin has unlimited access
+		if ($currUserCategory == $_SESSION["userCategoryNames"]["Admin"])
+		{
+			$modify_restricted = false;
+		}
+		else
+		{
+			// Jan. 31/08: Negative or 0 project ID is encountered only during reagent creation.  Allow
+			if ($rIDpID <= 0)
+			{
+				$modify_restricted = false;
+			}
+			else
+			{
+				if (in_array($rIDpID, $userProjects))
+				{
+					$modify_restricted = false;
+				}
+				else
+				{
+					$modify_restricted = true;
+				}
+			}
+		}
+		
+		if ($typeOf_ar = mysql_fetch_array($typeOf_rs, MYSQL_ASSOC))
+		{
+			// Dec. 22/09: Quick and dirty - keep existing code for Cell Line modify
+			if ($modify && ($typeOf_ar["reagentTypeID"] == 4))
+			{
+				$this->print_Detailed_Cellline($modify, $view, $toViewReagentID, $check, $modify_restricted);
+			}
+			else
+			{
+				// April 28/09 - Adding ability to add new reagent types
+				$this->print_Detailed_Reagent_Other($modify_state, $view, $toViewReagentID, $typeOf_ar["reagentTypeID"], $typeOf_ar["groupID"], $modify_restricted);
+			}
+		}
+	}
+
+	/**
+	 * Is this property a comment? (there is a separate table for comments in the database, so a different query is used for retrieving the comment itself rather than its column ID number)
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING $name Property name (e.g. 'description')
+	 * @param INT $categoryID (e.g. '1' for 'General Properties')
+	 * @param INT $rTypeID (e.g. '1' for 'Vector')
+	*/
+	function isComment($name, $categoryID, $rTypeID)
+	{
+		global $conn;
+		$rfunc_obj = new Reagent_Function_Class();
+
+		$result = false;
+
+		// Nov. 11/09: For now - plain and simple hack: just return true if this is a comment or description value, change later if needed --> Feb.5/10: needed now (can have comments under General and under Growth Properties)!
+		if ($categoryID == 1)
+		{
+			switch ($name)
+			{
+				case 'description':
+				case 'comments':
+				case 'verification comments':
+					$result = true;
+				break;
+	
+				default:
+					$result = false;
+				break;
+			}
+		}
+		else
+			$result = false;
+
+		return $result;
+	}
+
+
+	/**
+	 * Should this property be entered as an arbitrary freetext value, or selected from a dropdown list of pre-defined values?  Sequence features are always selected from a list; input form of other properties is specific for each reagent type and is defined at the introduction of a new reagent type into OpenFreezer.
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2009-04-30
+	 *
+	 * @param STRING $name Property name (e.g. 'promoter')
+	 * @param INT $categoryID (e.g. '1' for 'DNA Sequence Features')
+	 * @param INT $rTypeID (e.g. '1' for 'Insert')
+	*/
+	function isDropdownProperty($name, $categoryID, $rTypeID)
+	{
+		global $conn;
+		$rfunc_obj = new Reagent_Function_Class();
+
+		// updates Nov. 10/09
+		$propCatID = $rfunc_obj->findReagentTypeAttributeID($rTypeID, $name, $categoryID);
+		$attrID = $rfunc_obj->getRTypeAttributeID($rTypeID, $name, $categoryID);
+		$setValsList = Array();
+
+		$set_rs = mysql_query("SELECT reagentTypeAttributeSetID FROM ReagentTypeAttribute_Set_tbl WHERE reagentTypeAttributeID='" . $attrID . "' AND status='ACTIVE'", $conn) or die("FAILURE IN Reagent_Creator_Class.print_set(3): " . mysql_error());
+
+		if ($set_ar = mysql_fetch_array($set_rs, MYSQL_ASSOC))
+			return true;
+		else
+			return false;
+	}
+
+
+	/**
+	 * Output a dropdown (SELECT) list of properties that have pre-defined values
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING $name Property name (e.g. 'intron')
+	 * @param STRING $selected Selected list value
+	 * @param STRING $category (e.g. 'General Properties')
+	 * @param INT $rTypeID (e.g. '1' for 'Vector')
+	 * @param STRING $type_of_output Obsolete, but caution when deleting - need to update everywhere this function is called
+	*/
+	function print_Set_Final_Dropdown($name, $selected, $category, $rTypeID=0, $type_of_output = "")
+	{
+		global $conn;
+
+		$rfunc_obj = new Reagent_Function_Class();
+
+		// Update Nov. 10/09
+		$categoryID = $_SESSION["ReagentPropCategory_Name_ID"][$category];
+		$attrID = $rfunc_obj->getRTypeAttributeID($rTypeID, $name, $categoryID);
+		$errorcount=0;
+
+		$rs_2 = mysql_query("SELECT s.entityName FROM ReagentTypeAttribute_Set_tbl r, System_Set_tbl s WHERE r.reagentTypeAttributeID='" . $attrID . "' AND s.ssetID=r.ssetID AND s.status='ACTIVE' AND r.status='ACTIVE' ORDER BY s.entityName", $conn) or die("FAILURE IN Reagent_Creator_Class.print_set(1): " . mysql_error());
+
+		// Jan. 15, 2010
+		echo "<OPTION value=\"\">-- Select " . ucwords($name) . "--</option>";
+
+		while ($set_ar = mysql_fetch_array($rs_2 , MYSQL_ASSOC))
+		{
+			if (strcasecmp($set_ar["entityName"], trim($selected)) == 0)
+			{
+				echo "<option selected value=\"" . $selected . "\">";
+				$errorcount++;
+			}
+			else
+			{
+				echo "<option value=\"" . $set_ar["entityName"] . "\">";
+			}
+
+			echo stripslashes($set_ar["entityName"]) . "</option>";
+		}
+
+		// added June 7, 2010 (moved from print_property_final() function, better this way for features)
+		if ($rfunc_obj->isCustomizeable($attrID))
+		{
+			echo "<option value=\"Other\">Other</option>";
+		}
+	}
+
+
+	/**
+	 * Output a list of checkboxes (e.g. Alternate ID)
+	 *
+	 * Feb. 26/08: Changed method signature - added $rid parameter - for showing start/stop positions of checkbox values for a particular reagent
+	 *
+	 * July 16/09: changed queries to reflect new table structure
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param STRING $name Property name (e.g. 'alternate id')
+	 * @param STRING $checkboxname Name of the checkbox on the form
+	 * @param Array $selected_ar List of selected checkbox values
+	 * @param INT $rid Reagent ID
+	 * @param STRING $rTypePrefix Prefix of the reagent type (e.g. 'V' for Vector)
+	 * @param STRING $category Name of the category in which the property appears (e.g. 'External Identifiers)
+	 * @param INT $rTypeID Reagent type ID (e.g. '1' for Vector)
+	*/
+	function print_Set_Extended_Checkbox($name, $checkboxname, $selected_ar, $rid=0, $rTypePrefix="", $category, $rTypeID=0)
+	{
+		global $conn;
+
+		$prefix = "reagent_detailedview_";
+		$postfix = "_prop";
+
+		$rfunc_obj = new Reagent_Function_Class();	// Feb. 26/08
+
+		// Feb. 26/08: show positions
+		$pStart = 0;
+		$pEnd = 0;
+
+		// Extract the property alias from the checkbox name
+		$aliasStart = substr($checkboxname, strlen($prefix));
+		$prop_alias = substr($aliasStart, 0, strlen($aliasStart)-strlen($postfix));
+
+		$font_color = "000000";
+
+		if (isset($_POST["change_vp_id"]))
+		{
+			$font_color = "FF0000";	
+		}
+
+		$propID = $rfunc_obj->getRTypeAttributeID($rTypeID, $name, $_SESSION["ReagentPropCategory_Name_ID"][$category]);
+
+		// Feb. 5/10: If there's only one value in $selected_ar, it is NOT an array!  Make it into one:
+		if (isset($selected_ar) && (!is_array($selected_ar)) && $selected_ar != "")
+		{
+			$tmp_ar = Array();
+			$tmp_ar[] = $selected_ar;
+
+			$selected_ar = $tmp_ar;
+		}
+
+		// updates Nov. 10/09
+		$categoryID = $_SESSION["ReagentPropCategory_Name_ID"][$category];
+		$categoryAlias = $_SESSION["ReagentPropCategory_Name_Alias"][$category];	// Feb. 5/10
+
+		$propCatID = $rfunc_obj->findReagentTypeAttributeID($rTypeID, $name, $categoryID);
+		$attrID = $rfunc_obj->getRTypeAttributeID($rTypeID, $name, $categoryID);
+
+		$attrSet_rs = mysql_query("SELECT entityName FROM System_Set_tbl s, ReagentTypeAttribute_Set_tbl r WHERE r.reagentTypeAttributeID='" . $attrID . "' AND s.ssetID=r.ssetID AND r.status='ACTIVE' AND s.status='ACTIVE'", $conn) or die("FAILURE IN Reagent_Creator_Class.print_set(1): " . mysql_error());
+
+		// For Alternate IDs, extract the name portion before the identifier (semicolon-delimited)
+		if (strcasecmp(strtolower($name), "alternate id") == 0)
+		{
+			$tmp_selected = array();
+	
+			if (isset($selected_ar))
+			{
+				foreach ($selected_ar as $key => $value)
+				{
+					$db_name = substr($value, 0, strpos($value, ":"));
+					$db_id = substr($value, strpos($value, ":") + 1);
+					$tmp_selected[$db_name] = $db_id;
+				}
+	
+				$selected_ar = $tmp_selected;
+			}
+		}
+		
+		switch (strtolower($name))
+		{
+			case 'alternate id':
+	
+				while ($set_ar = mysql_fetch_array($attrSet_rs, MYSQL_ASSOC))
+				{
+					if (isset($selected_ar) && in_array($set_ar["entityName"], array_keys($selected_ar)))
+					{
+						echo "<input type=\"checkbox\" checked name=\"" . $checkboxname . "\" value=\"". $set_ar["entityName"] . "\" id=\"" . $rTypePrefix . "_alternate_id_" . $set_ar["entityName"] . "_checkbox\" onClick=\"showAltIDTextBox('" . $rTypePrefix . "_alternate_id_" . $set_ar["entityName"] . "_checkbox', '" . $rTypePrefix . "_alternate_id_" . $set_ar["entityName"] . "_textbox')\">"  . $set_ar["entityName"] . "  ";
+		
+						echo "<INPUT style=\"display:inline\" id=\"" . $rTypePrefix . "_alternate_id_" . $set_ar["entityName"] . "_textbox\" name=\"alternate_id_" . $set_ar["entityName"] . "_textbox_name\" size=\"15\" value=\"" . $selected_ar[$set_ar["entityName"]] . "\"></INPUT><br>";
+		
+// 						$errorcount++;
+					}
+					else
+					{
+						echo "<input type=\"checkbox\" name=\"" . $checkboxname . "\" value=\"". $set_ar["entityName"] . "\" id=\"" . $rTypePrefix . "_alternate_id_" . $set_ar["entityName"] . "_checkbox\" onClick=\"showAltIDTextBox('" . $rTypePrefix . "_alternate_id_" . $set_ar["entityName"] . "_checkbox', '" . $rTypePrefix . "_alternate_id_" . $set_ar["entityName"] . "_textbox')\">"  . $set_ar["entityName"] . "  ";
+		
+						echo "<INPUT style=\"display: none\" id=\"" . $rTypePrefix . "_alternate_id_" . $set_ar["entityName"] . "_textbox\" name=\"alternate_id_" . $set_ar["entityName"] . "_textbox_name\" size=\"15\"></INPUT><br>";
+					}
+				}
+
+				// other
+				echo "<input type=\"checkbox\" id=\"" . $rTypePrefix . "_other_chkbx\" name=\"" . $checkboxname . "\" value=\"Other\" onClick=\"if (this.checked) showSpecificOtherCheckbox('" . $rTypePrefix . "_alternate_id_Other_chkbx_txt')\">Other";
+
+				?>
+					<INPUT style="display:none; margin-left:5px;" id="<?php echo $rTypePrefix; ?>_alternate_id_Other_chkbx_txt" name="alternate_id_Other_textbox_name" size="15"></INPUT>
+				<?php
+
+			break;
+		}
+	}
+	
+	/**
+	 * Use to display Vector and Cell Line subtype - i.e. stable cell line, gateway entry vector, etc. on reagent creation page
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2007-03-28
+	 *
+	 * @param INT $rTypeID Reagent type ID (e.g. '1' for Vector)
+	 * @param STRING $selected Selected reagent subtype alias (e.g. 'non_recomb')
+	 * @param STRING $listID ID of the SELECT element on the form
+	 * @param STRING $listName Name of the SELECT element on the form
+	 * @param boolean $readonly Should the element be displayed as read-only or made editable
+	 * @param STRING $vDisplay Either 'inline' or 'none' - indicates whether the Vector subtypes list should be visible or hidden
+	 * @param STRING $cDisplay Either 'inline' or 'none' - indicates whether the Cell Line subtypes list should be visible or hidden
+	*/
+	function printReagentSubtype($rTypeID, $selected, $listID, $listName, $readonly, $vDisplay="none", $cDisplay="none")
+	{
+		global $conn;
+		$count = 0;
+		
+		$rfunc_obj = new Reagent_Function_Class();
+		$rfunc_obj->check_Reagent_Session();
+		$rfunc_obj->reset_Reagent_Session();
+		unset( $rfunc_obj );
+		
+		$subtype_rs = mysql_query("SELECT `name`, `alias` FROM Reagent_SubType_tbl WHERE `reagent_typeID`='" . $rTypeID . "'", $conn) or die("Could not fetch reagent subtype: " . mysql_error());
+		
+		// default option
+		switch ($rTypeID)
+		{
+			case $_SESSION["ReagentType_Name_ID"]["Vector"]:
+	
+				if ($readonly == 1)
+					echo "<SELECT id=\"" . $listID . "\" name=\"" . $listName . "\" disabled onChange=\"showParents('" . $listID . "')\">";
+				else
+					echo "<SELECT style=\"display:" . $vDisplay . "\" id=\"" . $listID . "\" name=\"" . $listName . "\" onChange=\"showParents('" . $listID . "')\">";
+				
+				echo "<OPTION value=\"default\">Select Vector subtype</OPTION>";
+			break;
+			
+			case $_SESSION["ReagentType_Name_ID"]["CellLine"]:
+				if ($readonly == 1)
+					echo "<SELECT id=\"" . $listID . "\" name=\"" . $listName . "\" disabled onChange=\"showParents(this.id)\">";
+				else
+					echo "<SELECT style=\"display:" . $cDisplay . "\" id=\"" . $listID . "\" name=\"" . $listName . "\" onChange=\"showParents(this.id)\">";
+				
+				echo "<OPTION value=\"default\">Select Cell Line subtype</OPTION>";
+			break;
+			
+			default:
+				echo "<OPTION value=\"default\">Select Reagent subtype</OPTION>";
+			break;
+		}
+		
+		while ($subtype_ar = mysql_fetch_array($subtype_rs, MYSQL_ASSOC))
+		{
+			$subtype = $subtype_ar["name"];
+			$alias = $subtype_ar["alias"];
+
+			if ($alias == $selected)
+				echo "<OPTION selected ";
+			else
+				echo "<OPTION ";
+				
+			echo "value=\"" . $alias . "\">" . $subtype . "</OPTION>";
+		}
+		
+		echo "</SELECT>";
+	}
+
+	/*
+	* Output an error message when the user tries to access a reagent s/he does not have project access permissions for
+	*
+	* @author Marina Olhovsky
+	* @version 3.1
+	*
+	* @param STRING Error message that will be shown on the page
+	*/
+	function printErrPage($err_msg)
+	{
+		echo "<TABLE style=\"width:98%;\">";
+		echo "<TR><TD style=\"font-weight:bold; font-size:24pt;\">";
+		echo $err_msg;
+		echo "</TD></TR>";
+		echo "</TABLE>";
+	}
+
+	/**
+	 * Print Vector parents section on Vector detailed view
+	 *
+	 * Dec. 15/09: Replace printForm_Vector_show_associations() - just print parents
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1
+	 *
+	 * @param INT $reagentIDToView Reagent ID
+	*/
+	function printVectorParents($reagentIDToView)
+	{
+		global $conn;
+	
+		$gfunc_obj = new generalFunc_Class();
+		$bfunc_obj = new Reagent_Background_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+	
+		$colspan = 6;
+	
+		$currUserCategory = $_SESSION["userinfo"]->getCategory();
+	
+		// Determine cloning method from Association_tbl:
+		$query = "SELECT * FROM `Association_tbl` WHERE `reagentID`='" . $reagentIDToView . "' AND `status`='ACTIVE'";
+		$cloning_method_rs = mysql_query($query, $conn) or die("Could not determine cloning method: " . mysql_error());
+		
+		if ($cloning_method_ar = mysql_fetch_array($cloning_method_rs, MYSQL_ASSOC))
+		{
+			$cloningMethod = $cloning_method_ar["ATypeID"];
+		}
+		else
+		{
+			$cloningMethod = 3;	// set default to BASIC
+		}
+	
+		if ($cloningMethod != 3)
+		{
+			// don't display parents for parent vectors
+			?>
+			<table width="100%" border="0" cellspacing="5" cellpadding="5">
+
+			<tr>
+				<td align=left colspan="<?php echo $colspan;?>">
+					<i>    <b>Parents</b></i>
+				</td>
+			</tr>
+	
+			<tr>
+				<td width="275px" nowrap>
+					        Parent Vector <b>OpenFreezer</b> ID
+				</td>
+
+				<td nowrap>
+				<?php
+					$tmp_rid = $bfunc_obj->get_Background_rid( $reagentIDToView, "Vector Parent ID" );
+					
+					if ($tmp_rid > 0)
+					{
+						// August 17/07: Restrict viewing by project - if parent belongs to a project you don't have access to, don't allow linking
+						$tmpProject = getReagentProjectID($tmp_rid);
+						$userProjects = getAllowedUserProjectIDs($_SESSION["userinfo"]->getUserID());
+
+						if (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || in_array($tmpProject, $userProjects))
+						{
+							echo "<a href=\"Reagent.php?View=6&rid=" . $tmp_rid . "\">";
+							echo $gfunc_obj->getConvertedID_rid( $tmp_rid );
+							echo "</a> ";
+						}
+						else
+						{
+							echo "<span class=\"linkDisabled\">";
+							echo $gfunc_obj->getConvertedID_rid( $tmp_rid );
+							echo "</span>";
+						}
+					}
+					else
+					{
+						echo "None";
+					}
+				?></td>
+			</tr>
+			<?php
+				// Decide what to show here - insert or IPV - based on the vector's cloning method:	
+				if ($cloningMethod == 1)
+				{
+					// PCR
+					// Show the insert
+					?>
+					<tr>
+						<td width="180px" nowrap>
+							        Insert ID
+						</td>
+	
+						<td nowrap>
+						<?php
+							$tmp_rid = $bfunc_obj->get_Background_rid($reagentIDToView, "Insert ID");
+	
+							if ($tmp_rid > 0)
+							{
+								// August 17/07: Restrict viewing by project - if parent belongs to a project you don't have access to, don't allow linking
+								$tmpProject = getReagentProjectID($tmp_rid);
+								$userProjects = getAllowedUserProjectIDs($_SESSION["userinfo"]->getUserID());
+	
+								if (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || in_array($tmpProject, $userProjects))
+								{
+									echo "<a href=\"Reagent.php?View=6&rid=" . $tmp_rid . "\">";
+									echo $gfunc_obj->getConvertedID_rid( $tmp_rid );
+									echo "</a> ";
+								}
+								else
+								{
+									echo "<span class=\"linkDisabled\">";
+									echo $gfunc_obj->getConvertedID_rid( $tmp_rid );
+									echo "</span>";
+								}
+							}
+							else
+							{
+								echo "None";
+							}
+						?></td>
+					</tr>
+					<?php
+				}
+				elseif ($cloningMethod == 2)
+				{
+					// LOXP
+					// Show IPV
+					?>
+						<tr>
+							<td width="180px" nowrap>
+								        Insert Parent Vector ID
+							</td>
+	
+							<td nowrap>
+							<?php
+								$tmp_rid = $bfunc_obj->get_Background_rid($reagentIDToView, "parent insert vector");
+	
+								if ($tmp_rid > 0)
+								{
+									// August 17/07: Restrict viewing by project - if parent belongs to a project you don't have access to, don't allow linking
+									$tmpProject = getReagentProjectID($tmp_rid);
+									$userProjects = getAllowedUserProjectIDs($_SESSION["userinfo"]->getUserID());
+	
+									if (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || in_array($tmpProject, $userProjects))
+									{
+										echo "<a href=\"Reagent.php?View=6&rid=" . $tmp_rid . "\">";
+										echo $gfunc_obj->getConvertedID_rid( $tmp_rid );
+										echo "</a> ";
+									}
+									else
+									{
+										echo "<span class=\"linkDisabled\">";
+										echo $gfunc_obj->getConvertedID_rid( $tmp_rid );
+										echo "</span>";
+									}
+								}
+								else
+								{
+									echo "None";
+								}
+							?></td>
+						</tr>
+					<?php
+				}
+			?>
+			</table>	<!-- close table -->
+			<?php
+		}
+	}
+
+
+	/**
+	 * Print Cell Line parents section on Cell Line detailed view
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2009-12-22
+	 *
+	 * @param INT $reagentIDToView Reagent ID
+	*/
+	function printCellLineParents($reagentIDToView)
+	{
+		global $conn;
+	
+		$gfunc_obj = new generalFunc_Class();
+		$bfunc_obj = new Reagent_Background_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+	
+		$colspan = 6;
+	
+		$currUserCategory = $_SESSION["userinfo"]->getCategory();
+	
+		?>
+		<table border="0" width="100%" cellspacing="5" cellpadding="5">
+			
+			<tr>
+				<td colspan="<?php echo $colspan; ?>">
+					<table border="0" width="100%">
+						<TR>
+							<td colspan="6" style="color:#0000BB; text-align:left; font-weight:bold;">
+								Parents
+							</td>
+						</tr>
+						
+						<tr>
+							<td width="150px" style="padding-left:10px; padding-top:10px;">
+								Parent Vector
+							</td>
+
+							<td style="text-align:left; padding-top:10px;">
+								<?php
+									$tmp_rid = $bfunc_obj->get_Background_rid($reagentIDToView, "cell line parent vector id");
+
+									if ($tmp_rid > 0)
+									{
+										// August 17/07: Restrict viewing by project - if parent belongs to a project you don't have access to, don't allow linking
+										$tmpProject = getReagentProjectID($tmp_rid);
+										$userProjects = getAllowedUserProjectIDs($_SESSION["userinfo"]->getUserID());
+		
+										if (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || in_array($tmpProject, $userProjects))
+										{
+											echo "<a href=\"Reagent.php?View=6&rid=" . $tmp_rid . "\">";
+											echo $gfunc_obj->getConvertedID_rid( $tmp_rid );
+											echo "</a> ";
+										}
+										else
+										{
+											echo "<span class=\"linkDisabled\">";
+											echo $gfunc_obj->getConvertedID_rid( $tmp_rid );
+											echo "</span>";
+										}
+									}
+									else
+									{
+										echo "None";
+									}
+								?>
+							</td>
+						</tr>
+			
+						<tr>
+							<td width="150px" style="padding-left:10px; padding-top:8px;">Parent Cell Line</td>
+
+							<td style="text-align:left; padding-top:8px;">
+								<?php
+									$tmp_rid = $bfunc_obj->get_Background_rid($reagentIDToView, "parent cell line id");
+									
+									if( $tmp_rid > 0 )
+									{
+										// August 17/07: Restrict viewing by project - if parent belongs to a project you don't have access to, don't allow linking
+										$tmpProject = getReagentProjectID($tmp_rid);
+										$userProjects = getAllowedUserProjectIDs($_SESSION["userinfo"]->getUserID());
+		
+										if (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || in_array($tmpProject, $userProjects))
+										{
+											echo "<a href=\"Reagent.php?View=6&rid=" . $tmp_rid . "\">";
+											echo $gfunc_obj->getConvertedID_rid( $tmp_rid );
+											echo "</a> ";
+										}
+										else
+										{
+											echo "<span class=\"linkDisabled\">";
+											echo $gfunc_obj->getConvertedID_rid( $tmp_rid );
+											echo "</span>";
+										}
+									}
+									else
+									{
+										echo "None";
+									}
+								?>
+							</td>
+							
+						</tr>
+					</table>
+				</td>
+			</tr>
+		</table>
+		<?php
+	}
+
+	/**
+	 * Prints the parent/child association section of reagent detailed view in Modify mode
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-04-26
+	 *
+	 * @param INT $reagentType Reagent type ID (e.g. '1' for Vector)
+	 * @param INT $reagentIDToView Reagent ID
+	 * @param INT $check Error code from changing parent information (e.g. in Cell Lines)
+	 * @param STRING $error_type Indicates the view/reagent type where the error occurred
+	*/
+	function printForm_Vector_modify_associations($reagentType, $reagentIDToView, $check, $error_type="")
+	{
+		global $conn;
+		global $cgi_path;
+		
+		$gfunc_obj = new generalFunc_Class();
+		$bfunc_obj = new Reagent_Background_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+
+		$colspan = 4;
+
+		$currUserName = $_SESSION["userinfo"]->getDescription();		// Nov. 14/07
+		
+		// Associations vary according to reagent type
+		switch ($reagentType)
+		{
+			case "1":	// vector
+				// Changed June 7/06, Marina:
+				// Determine vector's cloning method.  DO NOT DISPLAY FORM FOR PARENT VECTORS!!!!!!!
+				$query = "SELECT * FROM `Association_tbl` WHERE `reagentID`='" . $reagentIDToView . "' AND `status`='ACTIVE'";
+				$cloning_method_rs = mysql_query($query, $conn) or die("Could not determine cloning method: " . mysql_error());
+
+				if ($cloning_method_ar = mysql_fetch_array($cloning_method_rs, MYSQL_ASSOC))
+					$cloningMethod = $cloning_method_ar["ATypeID"];
+				else
+					$cloningMethod = 3;	// hard-code BASIC cloning method - parent vector
+
+				// Feb. 17/10
+				$clAssoc = $rfunc_obj->findReagentTypeAssociations($reagentType);
+
+				foreach ($clAssoc as $assocID => $assocValue)
+				{
+					$assocAlias = $_SESSION["ReagentAssoc_ID_Alias"][$assocID];
+
+					?><INPUT TYPE="hidden" ID="<?php echo $_SESSION["ReagentType_ID_Name"][$reagentType]; ?>_assoc_<?php echo $assocAlias; ?>_input" VALUE="<?php echo $assocID; ?>"><?php
+				}
+
+				if ($cloningMethod != '3')
+				{
+					?>
+					<table border="1" frame="hsides" rules="groups" width="100%" cellspacing="5" cellpadding="5">
+						<tr>
+							<td nowrap width="200px">
+								Parent Vector <b>OpenFreezer</b> ID
+							</td>
+							<?php
+
+							if ($check != 3)
+							{
+// echo "Check NOT 3 ";
+// echo "GET PV " . $_GET["P"];
+								$font_color = "000000";
+
+								if (!isset($_POST["change_vp_id"]))
+								{
+									if (isset($_GET["P"]))	// there is an error but it's not PV
+									{
+										$tmp_rid = $gfunc_obj->get_rid($_GET["P"]);
+										$font_color = "#000000";
+										$tmpPV = $_GET["P"];
+									}
+									elseif (isset($_GET["PV"]))	// PV is the reason for error
+									{
+										$tmp_rid = $gfunc_obj->get_rid($_GET["PV"]);
+										$font_color = "#FF0000";
+										$tmpPV = $_GET["PV"];
+									}
+									else
+									{
+										$tmp_rid = $bfunc_obj->get_Background_rid($reagentIDToView, "Vector Parent ID");
+										$font_color = "000000";
+									}
+								}
+								else
+								{
+									$tmp_rid = $gfunc_obj->get_rid($_POST["parent_vector_name_txt"]);
+									$font_color = "0000FF";
+								}
+	
+								echo "<td colspan=\"2\">";
+
+								echo "<INPUT TYPE=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"10px\" name=\"parent_vector_name_txt\" id=\"parent_vector_id_txt\" style=\"color:" . $font_color . "\" value=\"";
+
+								echo $gfunc_obj->getConvertedID_rid($tmp_rid) . "\">";
+
+								echo "</td>";
+							}
+							else
+							{
+// echo "Check 3";
+								// print the last value entered for parent
+								if (isset($_POST["parent_vector_name_txt"]))
+								{
+									$tmp_rid = $gfunc_obj->get_rid($_POST["parent_vector_name_txt"]);
+									$tmpPV = strtoupper($_POST["parent_vector_name_txt"]);
+									$font_color = "FF0000";
+								}
+								elseif (isset($_GET["PV"]))	// error
+								{
+									$tmp_rid = $gfunc_obj->get_rid($_GET["PV"]);
+									$font_color = "FF0000";
+									$tmpPV = $_GET["PV"];
+								}
+								elseif (isset($_GET["P"]))
+								{
+									// Nov. 14/07: Pass 'P' as argument from CGI if PV is OK but the other parent is not
+									$tmp_rid = $gfunc_obj->get_rid($_GET["P"]);
+									$font_color = "0000FF";
+								}
+								else
+								{
+									// ???
+									$tmp_rid = "";
+									$font_color = "0000FF";
+								}
+
+								echo "<td>";
+
+								echo "<INPUT TYPE=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"10px\" name=\"parent_vector_name_txt\" id=\"parent_vector_id_txt\" style=\"color:" . $font_color . "\" value=\"";
+								echo $gfunc_obj->getConvertedID_rid($tmp_rid) . "\">";
+// 								echo "\">";
+
+								echo "</td>";
+
+								if (strlen($tmpPV) > 0)
+									echo "<a name=\"rp\"></a><td style=\"color:" . $font_color . "\">You may not use " . $tmpPV . " as your parent Vector, since you do not have Read access to its project.  Please select another reagent, or contact the project owner to obtain permissions.</td>";
+							}
+						?>
+					</tr>
+					<?php
+						// ====================================================================================
+						// Modified May 12/06 by Marina
+						// Now decide what to show here - insert or IPV - based on the vector's cloning method:
+			
+						// if PCR - display only PV and I
+						// if LOXP - display PV
+						// ====================================================================================
+						switch ($cloningMethod)
+						{
+							case '1':	
+								// PCR
+								// Show the insert
+								?>
+								<tr>
+									<td width="100px" nowrap>
+										Insert ID
+									</td>
+			
+									<?php
+										if (!isset($_POST["change_vp_id"]))
+										{
+											$tmp_rid = $bfunc_obj->get_Background_rid($reagentIDToView, "Insert ID");
+											$font_color = "000000";
+										}
+										else
+										{
+											$tmp_rid = $gfunc_obj->get_rid($_POST["insert_name_txt"]);
+											$font_color = "0000FF";	// mark change in blue
+										}
+
+										if ($check == 2)
+											$font_color = "FF0000";
+								
+										echo "<td colspan=\"2\">";
+
+										echo "<a name=\"ri\"></a><INPUT onKeyPress=\"return disableEnterKey(event);\" TYPE=\"text\" style=\"color:" . $font_color . "\" size=\"10px\" name=\"insert_name_txt\" id=\"insert_id_txt\" value=\"";
+						
+										if( $tmp_rid > 0 )
+										{
+											echo $gfunc_obj->getConvertedID_rid($tmp_rid) . "\">";
+										}
+										else
+										{
+											if (isset($_POST["insert_name_txt"]))
+											{
+												echo strtoupper($_POST["insert_name_txt"]) . "\">";
+											}
+											else
+											{
+												echo "\">";
+											}
+										}
+
+										if ($check == 2)
+										{
+											if (isset($_POST["insert_name_txt"]))
+											{
+												$tmpInsert = $_POST["insert_name_txt"];
+											}
+											elseif (isset($_GET["I"]))
+											{
+												$tmpInsert = $_GET["I"];
+											}
+
+											if (strlen($tmpInsert) > 0)
+												echo "<a name=\"ri\"></a><td style=\"color:" . $font_color . "\">You may not use " . $tmpInsert . " as your parent Insert, since you do not have Read access to its project.  Please contact the project owner or administrator.";
+										}
+
+										// Jan. 29/09: Do not give reverse option for gateway clones
+										$vType = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["vector type"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]));
+
+// 	
+// 										echo "vector type " . $vType;
+
+										if (strpos(strtolower($vType), 'gateway') === false)
+										{
+											// Feb. 25/08: Check cDNA orientation; if reverse - show checkbox checked by default
+
+											$cdnaDir = $rfunc_obj->getPropertyDirection($reagentIDToView, $_SESSION["ReagentProp_Name_ID"]["cdna insert"]);
+
+											?>  <INPUT TYPE="checkbox" ID="reverseInsertCheckbox" <?php if ($cdnaDir == 'reverse') echo "checked"; ?> onClick="if (this.checked == true) document.getElementById('customSitesCheckbox').checked=true; showHideCustomSites()" NAME="reverse_insert" style="font-size:10pt">Reverse Complement<?php
+										}
+
+										echo "</td>";
+									?>
+								</tr>
+								<?php
+										// Jan. 29/09: Gateway sites are not customizeable
+										$vType = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["vector type"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]));
+
+										if (strpos(strtolower($vType), 'gateway') === false)
+										{
+											?>
+											<TR>
+												<TD colspan="4" style="text-align:left; padding-left:20px; padding-top:10px;">
+							
+													<!-- Nov. 17/08: Add option to make custom sites -->
+													<INPUT TYPE="checkbox" ID="customSitesCheckbox" NAME="custom_sites" style="font-size:10pt" onClick="showHideCustomSites()"> Customize cloning sites<BR>
+													<span style="margin-left:20px; font-size:9pt;">(Click here if Insert and Parent Vector sites are not identical)</span>
+													<BR><BR>
+							
+													<TABLE cellpadding="4px" ID="customCloningSites" style="display:none; border:1px solid black;">
+														<TH colspan="2">
+															<b>Please specify cloning sites on the Parent Vector and insert:</b><BR>
+														</TH>
+							
+														<tr>
+															<td colspan="2" style="font-size:9pt; font-weight:bold">
+																<HR>Parent Vector Cloning Sites:
+															</td>
+														</tr>
+												
+														<TR>
+															<TD style="padding-left:10px">
+																5' Cloning Site:
+															</TD>
+												
+															<TD>
+																<?php
+																	echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list_1\" name=\"pv_custom_five_prime\"></select>";
+																?>
+															</TD>
+														</TR>
+												
+														<TR>
+															<TD style="padding-left:10px">
+																3' Cloning Site:
+															</TD>
+												
+															<TD>
+																<?php
+																	echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list_1\" name=\"pv_custom_three_prime\"></select>";
+																?>
+															</TD>
+														</TR>
+							
+							
+														<tr>
+															<td colspan="2" style="font-size:9pt; font-weight:bold;">
+																<HR>Insert Cloning Sites:
+															</td>
+														</tr>
+												
+														<TR>
+															<TD style="padding-left:10px">
+																5' Cloning Site:
+															</TD>
+												
+															<TD>
+																<?php
+																	echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"fpcs_list\" name=\"insert_custom_five_prime\"></select>";
+																?>
+																<BR><div id="fp_warning" style="display:none; color:#FF0000">Please select a value for the 5' restriction site from the dropdown list</div>
+															</TD>
+														</TR>
+												
+														<TR>
+															<TD style="padding-left:10px">
+																3' Cloning Site:
+															</TD>
+												
+															<TD>
+																<?php
+																	echo "<select size=\"1\" style=\"font-size:7pt; font-family:Courier;\" id=\"tpcs_list\" name=\"insert_custom_three_prime\"></select>";
+																?>
+																<BR><div id="tp_warning" style="display:none; color:#FF0000">Please select a value for the 3' restriction site from the dropdown list</div>
+															</TD>
+														</TR>
+													</table>
+												</TD>
+											</TR>
+											<?php
+
+										}	// close if ($vType not gateway)
+							break;
+		
+							case '2':
+								// LOXP
+								// Show IPV
+								?>
+								<tr>
+									<td width="100px" nowrap>
+										Insert Parent Vector ID
+									</td>
+			
+									<?php
+										if (!isset($_POST["change_vp_id"]))
+										{
+											$tmp_rid = $bfunc_obj->get_Background_rid($reagentIDToView, "Parent Insert Vector");
+											$font_color = "000000";
+										}
+										else
+										{
+											$tmp_rid = $gfunc_obj->get_rid($_POST["ipv_name_txt"]);
+											$font_color = "0000FF";
+										}
+										
+										if ($check == 2)
+											$font_color = "FF0000";
+										
+										echo "<td width=\"100px\" colspan=\"2\" nowrap>";
+										echo "<INPUT TYPE=\"text\" onKeyPress=\"return disableEnterKey(event);\" size=\"10px\" name=\"ipv_name_txt\" style=\"color:" . $font_color . "\" id=\"ipv_id_txt\" value=\"";
+					
+										if ($tmp_rid > 0)
+										{
+											echo $gfunc_obj->getConvertedID_rid( $tmp_rid ) . "\">";
+										}
+										else
+										{
+											if (isset($_POST["ipv_name_txt"]))
+											{
+												echo strtoupper($_POST["ipv_name_txt"]) . "\">";
+											}
+											else
+											{
+												echo "\">";
+											}
+										}
+					
+										echo "</td>";
+									
+										if ($check == 2)
+										{
+											if (isset($_POST["ipv_name_txt"]))
+											{
+												$tmpIPV = $_POST["ipv_name_txt"];
+											}
+											elseif (isset($_GET["IPV"]))
+											{
+												$tmpIPV = $_GET["IPV"];
+											}
+
+											if (strlen($tmpIPV) > 0)
+												echo "<a name=\"ipvr\"></a><td style=\"color:" . $font_color . "\">You may not use " . $tmpIPV . " as your Insert Parent Vector, since you do not have Read access to its project.  Please contact the project owner or administrator.</td>";
+										}
+									?>
+								</tr>
+							<?php
+							break;
+							
+							default:	// something wrong
+								echo "What's up, doc???";
+							break;
+						}	// end switch
+						?>
+				</table><?php
+				}	// end cloning method != 3
+			break;
+
+			case "2":	// insert
+				// Change Oligos and Insert Parent Vector
+				
+				// Determine if an error was issued:
+				if (isset($_GET["ErrCode"]) && ($_GET["ErrCode"] == 5))
+				{
+					if (isset($_GET["IPV"]))
+					{
+						// Show IPV error
+						$ipv_warning_display = "inline";
+						$sense_warning_display = "none";
+						$antisense_warning_display = "none";
+					}
+					elseif (isset($_GET["S"]))
+					{
+						// Show IPV error
+						$sense_warning_display = "inline";
+						$ipv_warning_display = "none";
+						$antisense_warning_display = "none";
+					}
+					elseif (isset($_GET["A"]))
+					{
+						// Show IPV error
+						$antisense_warning_display = "inline";
+						$ipv_warning_display = "none";
+						$sense_warning_display = "none";
+					}
+				}
+				else
+				{
+					// Don't show any errors
+					$antisense_warning_display = "none";
+					$ipv_warning_display = "none";
+					$sense_warning_display = "none";
+				}
+				?>
+				<SCRIPT language="javascript">
+
+					function previewDetails()
+					{
+						var parent_vector_id = "parent_vector_id_txt";
+						var parentElement = document.getElementById(parent_vector_id);
+						var parentValue = parentElement.value;
+					}
+
+				</SCRIPT>
+
+				<table width="100%" cellspacing="5" cellpadding="5">
+					<tr>
+						<td colspan="3" style="font-weight:bold; padding-left:15px;" class="detailedView_BlankTitle">
+							Parent Child Information
+						</td>
+					</tr>
+
+					<tr>
+						<td width="180px" style="white-space:nowrap; padding-left:15px;">
+							Sense Oligo ID
+						</td>
+	
+						<?php
+							echo "<td style=\"white-space:nowrap\">";
+							echo "<INPUT onKeyPress=\"return disableEnterKey(event);\" TYPE=\"text\" size=\"10px\" name=\"assoc_sense_oligo\" id=\"sense_oligo_id_txt\" style=\"color:" . $font_color . "\" value=\"";	// mar 14/07
+						
+							$tmp_rid = $bfunc_obj->get_Background_rid($reagentIDToView, "sense oligo");
+
+							if ($tmp_rid > 0)
+							{
+								echo $gfunc_obj->getConvertedID_rid($tmp_rid) . "\">";
+							}
+							else
+							{
+								echo "\">";
+							}
+		
+							echo "</td>";
+
+							// Sept. 7/07: Error output
+							echo "<td>";
+
+							if (strlen($tmp_rid) > 0)
+								echo "<span style=\"color:#FF0000; display:" . $sense_warning_display . "\">You may not use <span style=\"color:#0000FF;\">" . $gfunc_obj->getConvertedID_rid($tmp_rid) . "</span> as your Sense Oligo, since you do not have Read access to its project.  Please contact the project owner to obtain permission or select a different Sense Oligo value.";
+							echo "</td>";
+						?>
+					</tr>
+					<tr>
+						<td width="180px" style="padding-left:15px; white-space:nowrap;">
+							Antisense Oligo ID
+						</td>
+
+						<?php
+							$tmp_rid = $bfunc_obj->get_Background_rid($reagentIDToView, "antisense oligo");
+		
+							echo "<td>";
+
+							echo "<INPUT onKeyPress=\"return disableEnterKey(event);\" TYPE=\"text\" size=\"10px\" name=\"assoc_antisense_oligo\" id=\"antisense_id_txt\" value=\"";		// mar 14/07
+							
+							if( $tmp_rid > 0 )
+							{
+								echo $gfunc_obj->getConvertedID_rid($tmp_rid) . "\">";
+							}
+							else
+							{
+								echo "\">";
+							}
+		
+							echo "</td>";
+							
+							// Sept. 7/07: Error output
+							echo "<td>";
+	
+							if (strlen($tmp_rid) > 0)
+								echo "<span style=\"color:#FF0000; display:" . $antisense_warning_display . "\">You may not use <span style=\"color:#0000FF;\">" . $gfunc_obj->getConvertedID_rid($tmp_rid) . "</span> as your Antisense Oligo, since you do not have Read access to its project.  Please contact the project owner to obtain permission or select a different Antisense Oligo value.";
+							
+							echo "</td>";
+						?>
+					</tr>
+
+					<tr>
+						<td style="padding-left:15px; white-space:nowrap;">
+							Insert Parent Vector ID
+						</td>
+
+						<?php
+							$tmp_rid = $bfunc_obj->get_Background_rid($reagentIDToView, "Insert Parent Vector ID");
+			
+							echo "<td>";
+
+							echo "<INPUT onKeyPress=\"return disableEnterKey(event);\" TYPE=\"text\" size=\"10px\" name=\"assoc_insert_parent_vector\" id=\"ipv_id_txt\" value=\"";	// mar 14/07
+		
+							if ($tmp_rid > 0)
+							{
+								echo $gfunc_obj->getConvertedID_rid( $tmp_rid ) . "\">";
+							}
+							else
+							{
+								echo "\">";
+							}
+		
+							echo "</td>";
+							
+							// Sept. 7/07: Error output
+							echo "<td>";
+
+							if (strlen($tmp_rid) > 0)
+								echo "<span style=\"color:#FF0000; display:" . $ipv_warning_display . "\">You may not use <span style=\"color:#0000FF;\">" . $gfunc_obj->getConvertedID_rid($tmp_rid) . "</span> as your Insert Parent Vector, since you do not have Read access to its project.  Please contact the project owner to obtain permission or select a different Insert Parent Vector value.";
+
+							echo "</td>";
+						?>
+					</tr>
+				<?php 	
+//					echo "</FORM>"; 
+				?>
+			</table><?php
+			break;
+
+			case "3":	// oligo
+
+			break;
+
+			case "4":	// cell line
+// 				$currUserName = $_SESSION["userinfo"]->getDescription();
+
+				$clAssoc = $rfunc_obj->findReagentTypeAssociations($reagentType);
+
+				foreach ($clAssoc as $assocID => $assocValue)
+				{
+					$assocAlias = $_SESSION["ReagentAssoc_ID_Alias"][$assocID];
+
+					?><INPUT TYPE="hidden" ID="<?php echo $_SESSION["ReagentType_ID_Name"][$reagentType]; ?>_assoc_<?php echo $assocAlias; ?>_input" VALUE="<?php echo $assocID; ?>"><?php
+				}
+
+				?>
+				<table border="0" width="100%" cellspacing="5" cellpadding="5">
+					<?php
+						echo "<FORM METHOD=POST ACTION=\"" . $_SERVER["PHP_SELF"] . "?View=" . $_GET["View"] . "&rid=" . $reagentIDToView . "\">";
+					?>
+
+					<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+					<tr>
+						<td align=left class="detailedView_BlankTitle" colspan="<?php echo $colspan;?>">
+							<table width="100%" border="1" rules="none" frame="hsides" cellpadding="5">
+								<tr>
+									<td style="white-space:nowrap; font-weight:bold">
+										Cell Line Background Information<BR>
+										<P style="font-size:8pt; color:blue; font-weight:normal">Pressing "Change" uploads the new parent vector and cell line details on the form in blue.Please verify all properties before saving.
+									</td>
+								</tr>
+							</table>
+						</td>
+					</tr>
+	
+					<tr>
+						<td width="100px">
+							Parent Vector
+						</td>
+	
+						<?php
+//							echo "<td>";
+							$font_color = "000000";
+
+//							if ($check == 1)
+							if ($check != 3)
+							{
+								if (!isset($_POST["change_cl_id"]) && !isset($_POST["change_vp_id"]))
+								{
+									$tmp_rid = $bfunc_obj->get_Background_rid($reagentIDToView, "Cell Line Parent Vector ID");
+									$font_color = "000000";
+								}
+								else
+								{
+									$tmp_rid = $gfunc_obj->get_rid($_POST["pv_name_txt"]);
+									$font_color = "0000FF";	
+								}
+
+								echo "<td colspan=\"2\">";
+							}
+							else
+							{
+								// print the last value entered for parent
+								if (isset($_POST["pv_name_txt"]))
+									$tmp_rid = $gfunc_obj->get_rid($_POST["pv_name_txt"]);
+								
+								// Added August 28/07, Marina: Changed variable names due to separation of nested forms
+								else if (isset($_GET["ErrVal"]))
+									$tmp_rid = $gfunc_obj->get_rid($_GET["ErrVal"]);
+								else
+								{
+									// ???
+								}
+
+								$font_color = "FF0000";
+							
+								echo "<TD>";
+							}
+	
+							echo "<INPUT onKeyPress=\"return disableEnterKey(event);\" TYPE=\"text\" size=\"10px\" name=\"pv_name_txt\" id=\"pv_id_txt\" style=\"color:" . $font_color . "\" value=\"";
+	
+							if ($tmp_rid > 0)
+								echo $gfunc_obj->getConvertedID_rid($tmp_rid) . "\">";
+							else
+								echo "\">";
+							
+							echo "</td>";
+
+							if ($check == 3)
+							{
+								if (strlen($_POST["pv_name_txt"]) > 0)
+									echo "<td style=\"color:" . $font_color . "\">You may not use " . $_POST["pv_name_txt"] . " as your parent Vector, since you do not have Read access to its project.  Please contact the project owner or administrator.</td>";
+							}
+						?>
+					</tr>
+	
+					<tr>
+						<td width="100px">
+							Parent Cell Line
+						</td>
+	
+						<?php
+							$font_color = "000000";
+	
+							if ($check != 4)
+							{
+								if (!isset($_POST["change_cl_id"]) && !isset($_POST["change_vp_id"]))
+								{
+									$tmp_cl_id = $bfunc_obj->get_Background_rid($reagentIDToView, "Parent Cell Line ID");
+									$font_color = "000000";
+	
+									// Set flag to remember if Change button was pressed
+									echo "<input type=\"hidden\" id=\"assoc_cl_change\" name=\"assoc_change_cl_flag\" value=\"0\">";
+								}
+								else
+								{
+									$tmp_cl_id = $gfunc_obj->get_rid($_POST["cl_name_txt"]);
+									$font_color = "0000FF";
+	
+									// Set flag to remember if Change button was pressed
+									echo "<input type=\"hidden\" id=\"assoc_cl_change\" name=\"assoc_change_cl_flag\" value=\"1\">";
+								}
+
+								echo "<td colspan=\"2\">";
+							}
+							else
+							{
+								// print the last value entered for parent
+								if (isset($_POST["cl_name_txt"]))
+								{
+									$tmp_cl_id = $gfunc_obj->get_rid($_POST["cl_name_txt"]);
+								}
+								else if (isset($_POST["detailed_view_cl_backfillID_old"]))
+								{
+									$tmp_cl_id = $gfunc_obj->get_rid($_POST["detailed_view_cl_backfillID_old"]);
+								}
+								elseif (isset($_GET["CL"]))
+								{
+									$tmp_cl_id = $gfunc_obj->get_rid($_GET["CL"]);
+								}
+								else
+								{
+									// ???
+	//								print_r($_POST);
+								}
+	
+								if (strcasecmp($error_type, "Cell Line") == 0)
+								{
+									$font_color = "FF0000";
+								}
+
+								echo "<input type=\"hidden\" id=\"assoc_cl_change\" name=\"assoc_change_cl_flag\" value=\"" . (isset($_POST["change_cl_id"]) ? "1" : "0") . "\">";
+
+								echo "<TD>";
+							}
+	
+							if ($check == 4)
+								$font_color = "FF0000";
+
+							echo "<INPUT onKeyPress=\"return disableEnterKey(event);\" TYPE=\"text\" size=\"10px\" name=\"cl_name_txt\" id=\"cl_id_txt\" style=\"color:" . $font_color . "\" value=\"";
+		
+							if ($tmp_cl_id > 0)
+							{
+								echo $gfunc_obj->getConvertedID_rid($tmp_cl_id) . "\">";
+							}
+							else
+							{
+								echo $_POST["cl_name_txt"] .  "\">";	// sept 14/07 - print the value entered
+							}
+		
+							echo "</td>";
+
+							if ($check == 4)
+							{
+								if (isset($_POST["cl_name_txt"]))
+								{
+									$tmpCL = $_POST["cl_name_txt"];
+								}
+								elseif (isset($_GET["CL"]))
+								{
+									$tmpCL = $_GET["CL"];
+								}
+
+								if (strlen($tmpCL))
+									echo "<td style=\"color:" . $font_color . "\">You may not use " . $tmpCL . " as your parent Cell Line, since you do not have Read access to its project.  Please contact the project owner or administrator.</td>";
+							}
+						?>
+					</tr>
+
+					<tr>
+						<td> </td>
+
+						<td colspan="2">
+							<INPUT TYPE="SUBMIT" NAME="change_vp_id" VALUE="Change" onClick="return checkParentFormat('<?php echo str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType]); ?>')">
+						</td>
+					</tr>
+				</table>
+				<?php
+			break;
+
+			default:
+
+			break;
+		}
+	}
+
+	/**
+	 * Print Cell Line details page (using old implementation for cell lines; for other reagent types see print_Detailed_Reagent_Other())
+	 *
+	 * @author John Paul Lee @version 2005
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2006-04-26
+	 *
+	 * @param boolean $modify_state Are we in modify mode?
+	 * @param INT $view Page (view) number for redirection
+	 * @param INT $reagentIDToView Reagent ID
+	 * @param INT $check Error code from changing parent information (e.g. in Cell Lines)
+	 * @param boolean $modify_restricted Is modification restricted for the current user according to his/her project and/or system access? 'Modify' button is disabled if user is not authorized to modify
+	 * @param STRING $error_type Indicates the view/reagent type where the error occurred
+	 *
+	 * @see print_Detailed_Reagent_Other()
+	*/
+	function print_Detailed_Cellline($modify_state, $view, $reagentIDToView, $check, $modify_restricted, $error_type="")
+	{
+		global $conn;
+		global $cgi_path;
+
+		$gfunc_obj = new generalFunc_Class();
+		$bfunc_obj = new Reagent_Background_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+		
+		$first_w = "150px";
+		$second_w = "150px";
+		$third_w = "100px";
+		
+		$cellline_prefix = "reagent_detailedview_";
+		$cellline_postfix = "_prop";
+
+		$normal_rs = mysql_query("SELECT `propertyID`, `propertyValue` FROM `ReagentPropList_tbl` WHERE `status`='ACTIVE' AND `reagentID`='" . $reagentIDToView . "';", $conn);
+	
+		$antibiotic_resistance_ar = array();
+		$alternate_ids_ar = array();
+
+		// Dec. 22/09 - CHANGE CATEGORY TO 'GROWTH PROPERTIES'!!!!!!!!!!!!
+		$selMarkerPropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["selectable marker"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]);
+
+		$altID_PropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["alternate id"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]);
+
+		while( $currentProp_ar = mysql_fetch_array( $normal_rs, MYSQL_ASSOC))
+		{
+			switch ($currentProp_ar["propertyID"])
+			{
+				case $selMarkerPropID:
+					$antibiotic_resistance_ar[] = $currentProp_ar["propertyValue"];
+				break;
+
+				case $altID_PropID:
+					$alternate_ids_ar[] = $currentProp_ar["propertyValue"];
+				break;
+
+				default:
+					$tempPropHolder_ar[$currentProp_ar["propertyID"]] = stripslashes($currentProp_ar["propertyValue"] );
+				break;
+			}
+		}
+
+		mysql_free_result( $normal_rs );
+
+		$tempPropHolder_ar[$selMarkerPropID] = $antibiotic_resistance_ar;
+		$tempPropHolder_ar[$altID_PropID] = $alternate_ids_ar;
+
+		// May 1/06, Marina
+		$new_pv_props_ar = array();
+		$new_cl_props_ar = array();
+
+		if (isset($_POST["change_vp_id"]) || isset($_POST["change_cl_id"]))
+		{
+			$change_parent_vector = true;
+			$change_parent_cellline = true;
+
+			// Preload details of new parent vector
+			$new_VP = $_POST["pv_name_txt"];
+			$new_VP_id = $gfunc_obj->get_rid($new_VP);
+
+			// Preload details of new parent cell line
+			$new_CL = $_POST["cl_name_txt"];
+			$new_CL_id = $gfunc_obj->get_rid($new_CL);
+		}
+		
+		$colspan = 4;
+
+		// August 24/07: Find the cloning method
+		// September 13/07: For Cell Lines there is only one: ATypeID = 5. Hardcode
+		$cloningMethod = 5;
+		
+		$typeOf_rs = mysql_query("SELECT `reagentTypeID`, `groupID` FROM `Reagents_tbl` WHERE `status`='ACTIVE' AND `reagentID`='" . $reagentIDToView . "'", $conn) or die("Error: " . $mysql_error());
+		
+		if ($typeOf_ar = mysql_fetch_array($typeOf_rs, MYSQL_ASSOC))
+		{
+			$reagentType = $typeOf_ar["reagentTypeID"];
+			$reagentGroup = $typeOf_ar["groupID"];
+		}
+		
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+
+		?><FORM onSubmit="if (verifyCellLineParents() && checkMandatoryProps('CellLine') ) return true; else return false;" NAME="process_cell_line_props" METHOD="POST" ACTION="<?php echo $cgi_path . "update.py"; ?>">
+
+		<!-- Hidden form elements for Python -->
+		<input type="hidden" name="reagent_id_hidden" value="<?php echo $reagentIDToView; ?>">
+		<input type="hidden" name="save_section" value="associations" ID="preload_cell_line">
+		<input type="hidden" name="reagent_typeid_hidden" value="<?php echo $reagentType; ?>">
+		<input type="hidden" name="reagent_groupnum_hidden" value="<?php echo $reagentGroup; ?>">
+		<input type="hidden" name="cloning_method_hidden" value="<?php echo $cloningMethod; ?>">
+		<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+		<table width="786px" cellpadding="2px" valign="middle" name="reagent_props" class="detailedView_tbl" border="1" frame="box" rules="none">
+		
+	 	<th colspan="6" class="detailedView_heading" style="font-size:15pt">
+			<?php
+				echo $gfunc_obj->getConvertedID($reagentType, $reagentGroup);
+			?>
+		</th>
+		<tr><td colspan="4"><HR></td></tr>
+
+	  	<tr>
+			<td colspan="6">
+				<!-- insert a small table for the buttons -->
+				<table width="100%" class="detailedView_buttons" border="1" frame="vsides" rules="all">
+					<tr>
+					<?php 
+						if (!$modify_restricted)
+						{
+							if( $modify_state )
+							{
+								// "Save" and "Cancel" buttons
+								echo "<td>";
+								echo "<INPUT TYPE=\"SUBMIT\" NAME=\"change_state\" VALUE=\"Save\" onClick=\"document.pressed=this.value; selectAllPropertyValues(); changeParentValues('" . $cloningMethod . "');\">";
+								echo "</td>";
+
+								echo "<td>";
+								echo "<INPUT TYPE=\"SUBMIT\" NAME=\"change_state\" VALUE=\"Cancel\" onClick=\"document.pressed=this.value\">";
+								echo "</td>";
+							}
+							else
+							{
+								// "Modify" button
+								echo "<td><INPUT TYPE=\"SUBMIT\" NAME=\"change_state\" VALUE=\"Modify\"></td>";
+
+								// Location link
+								echo "<td><a href=\"Location.php?View=1&rid=" . $reagentIDToView . "\">Location</a></td>";
+							}
+						}
+						else
+						{
+							// "Modify" button
+							echo "<td><INPUT TYPE=\"SUBMIT\" NAME=\"change_state\" VALUE=\"Modify\" disabled></td>";
+
+							// Location link
+							echo "<td><a href=\"Location.php?View=1&rid=" . $reagentIDToView . "\">Location</a></td>";
+						}
+
+						// June 9/09 ===>>> NOOOOOOOOOOOO, check for preps and children!!!!!!!!!!!
+						if ($currUserName == 'Administrator')
+						{
+							?><TD><SPAN class="linkExportSequence" style="font-size:10pt; padding-top:0; margin-left:5px;" onClick="deleteReagentFromDetailedView('<?php echo $reagentIDToView; ?>');">Delete</SPAN></TD><?php
+						}
+
+					?>
+					</tr>
+				</table>
+			</td>
+		</tr>
+
+		<TR><TD colspan="6"><HR></TD></TR>
+		<?php
+
+		$rPropCategories = $rfunc_obj->findAllReagentTypeAttributeCategories($_SESSION["ReagentType_Name_ID"]["CellLine"]);
+		$cellLineAttribs = $rfunc_obj->getAllReagentTypeAttributes($_SESSION["ReagentType_Name_ID"]["CellLine"]);
+
+		$r_type = "CellLine";
+		
+		foreach ($rPropCategories as $categoryID => $category)
+		{
+			$rTypeAttributes = $rfunc_obj->getReagentTypeAttributesByCategory($_SESSION["ReagentType_Name_ID"][$r_type], $categoryID);
+
+			if (count($rTypeAttributes) == 0)
+				continue;
+
+			$catAlias = $_SESSION["ReagentPropCategory_ID_Alias"][$categoryID];
+
+			echo "<TR>";
+				echo "<TD style=\"padding-left:10px;\">";
+					echo "<table style=\"width:98%; background-color:#FFF8DC; border:1px groove black; padding:5px;\">";
+						// Aug. 19/09: Changed categoryID to catAlias, since that is also the name of the table in addNewReagentType() and JS was confusing between the two
+						echo "<tr>";
+							echo "<td style=\"font-weight:bold; color:blue; padding-top:2px;\">";
+								echo "<IMG id=\"" . $catAlias . "_expand_img_" . $r_type . "\" SRC=\"pictures/arrow_collapse.gif\" WIDTH=\"20\" HEIGHT=\"15\" BORDER=\"0\" ALT=\"plus\" class=\"menu-expanded\" style=\"display: inline\" onClick=\"showHideCategory('" . $catAlias . "', '" . $r_type . "');\">";
+
+								echo "<IMG id=\"" . $catAlias . "_collapse_img_" . $r_type . "\" SRC=\"pictures/arrow_expand.gif\" WIDTH=\"40\" HEIGHT=\"34\" BORDER=\"0\" ALT=\"plus\" class=\"menu-collapsed\" style=\"display: none\" onClick=\"showHideCategory('" . $catAlias . "', '" . $r_type . "');\">";
+
+								echo "<span id=\"section_title_" . $catAlias . "\">" . $category . "</span>";
+							echo "</TD>";
+						echo "</TR>";
+
+						echo "<tr>";
+							echo "<td style=\"padding-left:3px;\">";
+								echo "<table ID=\"category_" . $catAlias . "_section_" . $r_type . "\" cellpadding=\"4\" cellspacing=\"2\" style=\"margin-top:4px;\">";
+
+								// Update May 5, 2010: $key now corresponds to reagentTypePropertyID column in ReagentTypeAttributes_tbl
+								foreach ($rTypeAttributes as $key => $attribute)
+								{
+									$categoryName = $attribute->getPropertyCategory();
+	
+									$propName = $attribute->getPropertyName();
+
+									// May 11, 2011: verify mandatory props on saving
+									if ($rfunc_obj->isMandatory($r_type, $propName))
+										echo "<INPUT TYPE=\"hidden\" NAME=\"" . $r_type . "_mandatoryProps[]\" VALUE=\"" . $key . "\">";
+									
+									$propID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"][$propName], $categoryID);
+									$propDescr = $attribute->getPropertyDescription();
+
+									$propval = $rfunc_obj->getPropertyValue($reagentIDToView, $propID);
+						
+									echo "<TR ID=\"" . $categoryAlias . "\">";
+										echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold; white-space:nowrap;\">" . $propDescr . "</TD>";
+
+										if ($change_parent_vector || $change_parent_cellline)
+										{
+											$new_pv_prop_val = $rfunc_obj->getPropertyValue($new_VP_id, $propID);
+
+											$new_cl_prop_val = $rfunc_obj->getPropertyValue($new_CL_id, $propID);
+
+											// preload properties from parents
+											switch (strtolower($propName))
+											{
+												case 'name':
+													if ((strlen($new_pv_prop_val) > 0) && (strlen($new_cl_prop_val) > 0))
+													{
+														$new_prop_val = $new_pv_prop_val . " in " . $new_cl_prop_val;
+													}
+													else
+													{
+														$new_prop_val = (strlen($new_pv_prop_val) > 0) ? $new_pv_prop_val : $new_cl_prop_val;
+													}
+						
+													echo "<TD colspan=\"4\" class=\"detailedView_value_load\" style=\"white-space:normal;\">";
+														$this->print_property_final($cellline_prefix . $r_type . "_" . $catAlias . "_:_" . $_SESSION["ReagentProp_Name_Alias"][$propName] . $cellline_postfix, $propName, $new_prop_val, $reagentIDToView, true, $categoryName, "", "", "CellLine");
+
+													echo "</TD>";
+												break;
+						
+												case 'selectable marker':
+												case 'species':
+												case 'tissue type':
+												case 'developmental stage':
+												case 'morphology':
+													echo "<TD colspan=\"4\" class=\"detailedView_value_load\" style=\"white-space:normal;\">";
+												
+														$this->print_property_final($cellline_prefix . $r_type . "_" . $catAlias . "_:_" . $_SESSION["ReagentProp_Name_Alias"][$propName] . $cellline_postfix, $propName, $new_cl_prop_val, $new_CL_id, true, $categoryName, "", "", "CellLine");
+													echo "</TD>";
+												break;
+							
+												default:
+													echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+														$this->print_property_final($cellline_prefix . $r_type . "_" . $catAlias . "_:_" . $_SESSION["ReagentProp_Name_Alias"][$propName] . $cellline_postfix, $propName, $propval, $reagentIDToView, true, $categoryName, "", "", "CellLine");
+													echo "</TD>";
+												break;
+											}
+										}
+										else
+										{
+											echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+												$this->print_property_final($cellline_prefix . $_SESSION["ReagentProp_Name_Alias"][$propName] . $cellline_postfix, $propName, $propval, $reagentIDToView, true, $categoryName, "", "", "CellLine");
+											echo "</TD>";
+										}
+										echo "</TD>";
+									echo "</TR>";
+								}
+
+								echo "</TABLE>";
+							echo "</TD>";
+						echo "</TR>";
+					echo "</TABLE>";
+				echo "</TD>";
+			echo "</TR>";
+
+			// spacer row
+			echo "<TR><TD> </TD></TR>";
+		}
+
+		?>
+			<!-- Python input -->
+			<input type="hidden" id="clpv_id_hidden" name="assoc_cell_line_parent_vector_prop">
+			<input type="hidden" id="cl_id_hidden" name="assoc_parent_cell_line_prop">
+		
+			</form>
+			<?php
+	
+			$old_pv_id = $bfunc_obj->get_Background_rid($reagentIDToView, "cell line parent vector id");
+			$old_cl_id = $bfunc_obj->get_Background_rid($reagentIDToView, "parent cell line id");
+			
+			if (isset($_POST["pv_name_txt"]))
+				$old_pv = $_POST["pv_name_txt"];
+			else
+				$old_pv = $gfunc_obj->getConvertedID_rid($old_pv_id);
+			
+			if (isset($_POST["cl_name_txt"]))
+				$old_cl = $_POST["cl_name_txt"];
+			else
+				$old_cl = $gfunc_obj->getConvertedID_rid($old_cl_id);
+		?>
+		<input type="hidden" id="parent_vector_old_id" name="detailed_view_pv_backfillID_old" value="<?php echo $old_pv; ?>">
+		<input type="hidden" id="parent_cellline_old_id" name="detailed_view_cl_backfillID_old" value="<?php echo $old_cl; ?>">
+		
+		<input type="hidden" id="change_pv" name="change_pv_flag" value="">
+		<input type="hidden" id="change_cl" name="change_cl_flag" value="">
+	
+		<!-- *********************************
+			Parent/Child section 
+			Edited by Marina on May 1/06
+		********************************** -->
+		<table>
+			<tr>
+				<td colspan="<?php echo $colspan; ?>">
+				<?php
+					if ($modify_state)
+					{
+						$this->printForm_Vector_modify_associations($reagentType, $reagentIDToView, $check, $error_type);
+					}
+					else
+					{
+						$this->printForm_Vector_show_associations($reagentType, $reagentIDToView);
+					}
+				?>
+				</td>
+			</tr>
+		</table>
+		<?php
+	}
+
+
+	/**
+	 * Print reagent detailed view
+	 *
+	 * @author Marina Olhovsky
+	 * @version 3.1 2009-04-28
+	 *
+	 * @param boolean $modify_state Are we in modify mode?
+	 * @param INT $view Page (view) number for redirection
+	 * @param INT $reagentIDToView Reagent ID
+	 * @param INT $reagentType Reagent type ID
+	 * @param INT $reagentGroup Numeric portion of the reagent's OpenFreezer identifier, NOT the database ID (e.g. 'V123' => $reagentGroup = 123)
+	 * @param boolean $modify_restricted Is modification restricted for the current user according to his/her project and/or system access? 'Modify' button is disabled if user is not authorized to modify
+	*/
+	function print_Detailed_Reagent_Other($modify_state, $view, $reagentIDToView, $reagentType, $reagentGroup, $modify_restricted)
+	{
+		global $conn;
+		global $cgi_path;
+		global $hostname;
+		
+		$gfunc_obj = new generalFunc_Class();
+		$bfunc_obj = new Reagent_Background_Class();
+		$rfunc_obj = new Reagent_Function_Class();
+		$sfunc_obj = new Sequence_Function_Class();
+		$tempPropHolder_ar = $_SESSION["ReagentProp_ID_Name"];
+	
+		foreach ($tempPropHolder_ar as $key => $value)
+		{
+			$tempPropHolder_ar[$key] = "";
+		}
+
+		$genPrefix = "reagent_detailedview_";
+		$genPostfix = "_prop";
+
+		$rGeneralProps = array();
+		$rSequenceProps = array();
+		$rSequenceFeatures = array();
+		$rClassifiers = array();
+		$rExternalIDs = array();
+
+		// Fetch the properties of this reagent in the basic categories first, then check to see if the reagent has more
+		$rPropCategories = $rfunc_obj->findAllReagentTypeAttributeCategories($reagentType);	// returns a list of category IDs
+
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+
+		?><table name="reagent_props" style="vertical-align:middle; padding-right:2px; padding-left:10px;" border="1" frame="box" rules="none" cellspacing="4" class="detailedView_tbl" width="768px"><?php
+
+		$limsID = $gfunc_obj->getConvertedID($reagentType, $reagentGroup);
+
+		// July 7/09: Get parents here and print Insert ID next to 'cDNA' feature positions for recombination vectors
+		$parents = $bfunc_obj->getReagentParents($reagentIDToView);
+		$children = $bfunc_obj->getReagentChildren($reagentIDToView);
+		$parentTypes = $bfunc_obj->getAssociationTypes($reagentType);
+
+		$childrenTypes = Array();
+		$num_children = Array();
+
+		foreach ($children as $aPropID => $childrenIDs)
+		{
+			foreach ($childrenIDs as $cKey => $childID)
+			{
+				$childTypeID = $gfunc_obj->getTypeID($childID);
+
+				$childrenTypes[] = $childTypeID;
+
+				$num_children[$childTypeID]++;
+			}
+		}
+
+		// July 7/09: print the correct parents for Vectors
+		if ($reagentType == $_SESSION["ReagentType_Name_ID"]["Vector"])
+		{
+			$cloningMethod = $rfunc_obj->getCloningMethod($reagentIDToView);
+			$new_parents = Array();
+			$newParentTypes = Array();
+
+			switch ($cloningMethod)
+			{
+				case '1':
+					$newParentTypes[] = $_SESSION["ReagentAssoc_Name_ID"]["vector parent id"];
+					$newParentTypes[] = $_SESSION["ReagentAssoc_Name_ID"]["insert id"];
+
+					$new_parents[$_SESSION["ReagentAssoc_Name_ID"]["vector parent id"]] = $parents[$_SESSION["ReagentAssoc_Name_ID"]["vector parent id"]];
+
+					$new_parents[$_SESSION["ReagentAssoc_Name_ID"]["insert id"]] = $parents[$_SESSION["ReagentAssoc_Name_ID"]["insert id"]];
+
+					$parents = $new_parents;
+					$parentTypes = $newParentTypes;
+				break;
+
+				case '2':
+					$newParentTypes[] = $_SESSION["ReagentAssoc_Name_ID"]["vector parent id"];
+					$newParentTypes[] = $_SESSION["ReagentAssoc_Name_ID"]["parent insert vector"];
+
+					$new_parents[$_SESSION["ReagentAssoc_Name_ID"]["vector parent id"]] = $parents[$_SESSION["ReagentAssoc_Name_ID"]["vector parent id"]];
+
+					$new_parents[$_SESSION["ReagentAssoc_Name_ID"]["parent insert vector"]] = $parents[$_SESSION["ReagentAssoc_Name_ID"]["parent insert vector"]];
+
+					$parents = $new_parents;
+					$parentTypes = $newParentTypes;
+				break;
+
+				case '3':
+				break;
+			}
+
+			// April 15/10: Export in GenBank format
+			$fList = array();
+
+			$vName = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["name"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]));
+
+			$vStatus = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["status"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]));
+									
+			$vDescr = $this->get_Special_Column_Type("description", "General Properties", $reagentIDToView, "None");
+						
+			$vComms = $this->get_Special_Column_Type("comments", "General Properties", $reagentIDToView, "None");
+
+			$verComms = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["verification comments"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]));
+
+			$verification = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["verification"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]));
+
+			$vType = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["vector type"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]));
+
+			$vSrc = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["reagent source"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]));
+
+			$vRestr = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["restrictions on use"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]));
+
+			$vSeqID = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]));
+			$vSeq = $rfunc_obj->getSequenceByID($vSeqID);
+		
+			$fList = $rfunc_obj->findReagentPropertiesByCategory($reagentIDToView, $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"]);
+
+			# Get Insert features
+			$insertID = $bfunc_obj->get_Background_rid($reagentIDToView, "insert id");
+	
+			// Accession - from Insert// 	
+			$accession = $rfunc_obj->getPropertyValue($insertID, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["accession number"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]));
+	
+			$altID = $rfunc_obj->getPropertyValue($insertID, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["alternate id"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]));
+	
+			$insertName = $rfunc_obj->getPropertyValue($insertID, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["name"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]));
+
+			// Species - from Insert
+			$species = $rfunc_obj->getPropertyValue($insertID, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["species"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]));
+
+			$gbk_content = "";
+
+			$gbk_content .= "LOCUS       " . $vName . "      " . strlen($vSeq) . " bp    DNA   CIRCULAR        " . date('d-m-Y') . "\n";
+
+			$gbk_content .= "DEFINITION  " . $vType . ", " . $vDescr . "\n";
+			$gbk_content .= "ACCESSION   " . $limsID . "\n";
+			$gbk_content .= "KEYWORDS    \n";
+			$gbk_content .= "SOURCE      \n";
+			$gbk_content .= "  ORGANISM  \n";
+			
+			$gbk_content .= "REFERENCE   1 - " . strlen($vSeq) . " (bases 1 to " . strlen($vSeq) . ")\n";
+
+			$gbk_content .= "  AUTHORS   " . $vSrc . "\n";
+			$gbk_content .= "  JOURNAL   " . "\n";
+	
+			$gbk_content .= "COMMENT     " . $vComms . "\n";
+
+			$gbk_content .= "FEATURES             Location/Qualifiers\n";
+			$gbk_content .= "     source          1.." . strlen($vSeq) . "\n";
+			
+			foreach ($fList as $key => $myFeature)
+ 			{
+				foreach ($myFeature as $fKey => $feature)
+				{
+					$fType = $feature->getFeatureType();
+					$fVal =  $feature->getFeatureValue();
+					$fStart = $feature->getFeatureStart();
+					$fEnd = $feature->getFeatureEnd();
+					$fDir = $feature->getFeatureDirection();
+					$fDescr = $feature->getFeatureDescriptor();
+
+					$n_sp = 21 - strlen("CDS") - 5;
+
+					$a_sp = "";
+
+					for ($j=0; $j < $n_sp; $j++)
+					{
+						$a_sp .= " ";
+					}
+					
+					if (strcasecmp($fType, "cdna insert") == 0)
+					{					
+						if ($fEnd > 0)
+						{
+							$cdna_start = $fStart;
+							$cdna_end = $fEnd;
+							$cdna_length = $fEnd - $fStart + 1;
+						}
+						else
+						{
+							$cdna_start = 0;
+							$cdna_end = 0;
+							$cdna_length = 0;
+						}
+			
+						switch ($fDir)
+						{
+							case 'reverse':
+								$gbk_content .= "     CDS" . $a_sp . "complement(" . $cdna_start . ".." . $cdna_end . ")\n";
+							break;
+
+							default:
+								$gbk_content .= "     CDS" . $a_sp . $cdna_start . ".." . $cdna_end . "\n";
+							break;
+						}
+
+						$gbk_content .= "                     /organism=" . ucwords($species) . "\n";
+						$gbk_content .= "                     /gene=" . $insertName . "\n";
+				
+						$gbk_content .= "                     /note=accession: " . $accession .  "\n";
+
+						// Alternate ID
+						if (is_array($altID))
+						{
+							$gbk_content .= "                     /note=";
+
+							foreach ($altID as $a => $aID)
+							{
+								$gbk_content .= $aID . " ";
+							}
+
+							$gbk_content .= "\n";
+						}
+						else
+						{
+							$gbk_content .= "                     /note=" . $altID . "\n";
+						}
+
+						# Get gene ID and translation from Insert	
+						$geneID = $rfunc_obj->getPropertyValue($insertID, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["entrez gene id"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]));
+				
+						if ($geneID)
+							$gbk_content .= "                     /db_xref=GeneID:" . $geneID . "\n";
+				
+						$protSeqObj = $sfunc_obj->findProteinTranslation($insertID);
+
+						if ($protSeqObj)
+							$protSeq = $protSeqObj->getSequence();
+									
+						if ($protSeq)
+						{
+							$gbk_content .= "                     /translation=" . $protSeq . "\n";
+						}
+
+						$gbk_content .= "                     /SECDrawas=Gene\n";
+					}
+					else if ( (strcasecmp($fType, "selectable marker") == 0) || (strcasecmp($fType, "tag") == 0))
+					{
+						switch ($fDir)
+						{
+							case 'reverse':
+								$gbk_content .= "     CDS" . $a_sp . "complement(" . $fStart . ".." . $fEnd . ")\n";
+							break;
+
+							default:
+								$gbk_content .= "     CDS" . $a_sp . $fStart . ".." . $fEnd . "\n";
+							break;
+						}
+
+						$gbk_content .= "                     /note=" . $fType . "\n";
+						$gbk_content .= "                     /gene=" . $fVal . "\n";
+						$gbk_content .= "                     /SECDrawas=Region\n";
+					}
+					else if (strcasecmp($fType, "promoter") == 0)
+					{
+					
+						switch ($fDir)
+						{
+							case 'reverse':
+								$gbk_content .= "     promoter        complement(" . $fStart . ".." . $fEnd . ")\n";
+							
+							break;
+
+							default:
+								$gbk_content .= "     promoter        " . $fStart . ".." . $fEnd . ")\n";
+							break;
+						}
+
+						$gbk_content .= "                     /note=" . $fType . "\n";
+						$gbk_content .= "                     /gene=" . $fVal . "\n";
+						$gbk_content .= "                     /SECDrawas=Region\n";
+					}
+					else if (strcasecmp($fType, "polya tail") == 0)
+					{					
+						switch ($fDir)
+						{
+							case 'reverse':
+								$gbk_content .= "     polyA_signal    complement(" . $fStart . ".." . $fEnd . ")\n";
+							break;
+
+							default:
+								$gbk_content .= "     polyA_signal    " . $fStart . ".." . $fEnd . ")\n";
+							break;
+						}
+
+						$gbk_content .= "                     /note=" . $fType . "\n";
+						$gbk_content .= "                     /gene=" . $fVal . "\n";
+						$gbk_content .= "                     /SECDrawas=Region\n";
+					}
+					else if (strcasecmp($fType, "origin of replication") == 0)
+					{					
+						switch ($fDir)
+						{
+							case 'reverse':
+								$gbk_content .= "     rep_origin      complement(" . $fStart . ".." . $fEnd . ")\n";
+							break;
+
+							default:
+								$gbk_content .= "     rep_origin      " . $fStart . ".." . $fEnd . ")\n";
+							break;
+						}
+
+						$gbk_content .= "                     /note=" . $fType . "\n";
+						$gbk_content .= "                     /gene=" . $fVal . "\n";
+						$gbk_content .= "                     /SECDrawas=Region\n";
+					}
+					else if (strcasecmp($fType, "intron") == 0)
+					{					
+						switch ($fDir)
+						{
+							case 'reverse':
+								$gbk_content .= "     intron          complement(" . $fStart . ".." . $fEnd . ")\n";
+							break;
+
+							default:
+								$gbk_content .= "     intron          " . $fStart . ".." . $fEnd . ")\n";
+							break;
+						}
+
+						$gbk_content .= "                     /note=" . $fType . "\n";
+						$gbk_content .= "                     /gene=" . $fVal . "\n";
+						$gbk_content .= "                     /SECDrawas=Region\n";
+					}
+					else
+					{
+						switch ($fDir)
+						{
+							case 'reverse':
+								$gbk_content .= "     misc_feature    complement(" . $fStart . ".." . $fEnd . ")\n";
+							break;
+
+							default:
+								$gbk_content .= "     misc_feature    " . $fStart . ".." . $fEnd . "\n";
+							break;
+						}
+
+						$gbk_content .= "                     /note=" . $fType . "\n";
+						$gbk_content .= "                     /gene=" . $fVal . "\n";
+						$gbk_content .= "                     /SECDrawas=Region\n";
+					}
+				}
+ 			}
+ 			
+			$gbk_content .= "\nORIGIN\n";
+ 	
+ 			$chunks = explode(" ", chunk_split(strtoupper($vSeq), 10, " "));
+ 	 	
+ 			for ($i = 0; $i < sizeof($chunks); $i++)
+ 			{				
+				// leading spaces
+				if ($i%6 == 0)
+ 				{
+ 					$gbk_content .= "\n";
+
+					$num_spaces = 10 - strlen($i*10+1);
+
+					for ($k = 0; $k < $num_spaces-1; $k++)
+					{
+						$gbk_content .= " ";
+					}
+
+					$gbk_content .= $i*10+1 . " ";
+ 				}
+
+ 				$gbk_content .=  $chunks[$i] . " ";
+ 			}
+ 	
+ 			$gbk_content .=  $chunks[$i] . "\n//\n";
+		}
+
+		if ($rfunc_obj->hasAttribute($reagentType, "protein translation", $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]))
+		{
+			$isDNA = true;
+			$isRNA = false;
+			$isProtein = false;
+			$units = "nt";
+		}
+		else if ($rfunc_obj->hasAttribute($reagentType, "protein sequence", $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]))
+		{
+			$isDNA = false;
+			$isRNA = false;
+			$isProtein = true;
+			$units = "aa";
+		}
+		else
+		{
+			$isDNA = false;
+			$isRNA = true;
+			$isProtein = false;
+			$units = "nt";
+		}
+
+		?><th colspan="4" class="detailedView_heading" style="font-size:15pt; text-align:center"><?php
+			echo $limsID;
+		?></th><?php
+
+		?><tr><td colspan="6"><HR></td></tr>
+
+		<input type="hidden" ID="lims_id" name="limsID" value="<?php echo $limsID; ?>">
+
+		<tr>
+			<td colspan="6">
+				<table width="100%" class="detailedView_buttons" border="0">
+					<tr>
+					<?php
+						if ($reagentType == $_SESSION["ReagentType_Name_ID"]["Vector"])
+						{
+							?>
+							<td style="text-align:center; padding-left:10px;">
+								<span ID="exportGenbank"  class="linkExportSequence" style="font-size:10pt; padding-top:0; margin-left:5px;" onClick="document.genbank_export.submit();">Export GenBank</span><IMG SRC="pictures/new01.gif" ALT="new" WIDTH="35" HEIGHT="20">  
+							</td>
+							<?php
+						}
+					?>		
+						<td><a href="Location.php?View=1&rid=<?php echo $reagentIDToView; ?>">Location</a></td><?php
+
+						if ($reagentType == $_SESSION["ReagentType_Name_ID"]["Vector"])
+						{
+							$url = $hostname . "Reagent/vector_maps/" . $limsID . "_map.pdf";
+							$oligoMap = $hostname . "Reagent/vector_maps/" . $limsID . "_Oligo_map.pdf";
+			
+							?>
+							<td>
+								<span ID="viewVectorMap" class="linkExportSequence" style="font-size:10pt;" onClick="return popup('<?php echo $url; ?>', '<?php echo $limsID; ?>', 1200, 1200, 'yes');">View Map</span>
+							</td>
+
+							<td>
+								<input type="hidden" id="hidden_vector_id" name="reagent_id_hidden" value="<?php echo $reagentIDToView; ?>">
+		
+								<span ID="viewORFs" class="linkExportSequence" style="font-size:10pt;" onClick="document.vector_frames_form.submit()">View ORFs</span>
+							</td>
+
+							<td>
+								<span ID="viewOligoMap" class="linkExportSequence" style="font-size:10pt;" onClick="return popup('<?php echo $oligoMap; ?>', '<?php echo $limsID; ?>', 1200, 1200, 'yes');">Oligo Map</span>
+							</td>
+							<?php
+						}
+	
+						if  ($reagentType == $_SESSION["ReagentType_Name_ID"]["Insert"])
+						{
+							echo "<td><a href=\"" . $_SERVER["PHP_SELF"] . "?View=7&rid=" . $reagentIDToView . "\">Get Primers</a></td>";
+
+							if (($currUserName == 'Administrator') || ($_SESSION["userinfo"]->getLabID() == 1))
+							{
+								$geneSymbol = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["official gene symbol"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]));
+
+							}
+						}
+		
+						?><td><?php
+						
+							// Disallow deletion of reagents that have preps or children, or reagents in projects that the user does not have Write access to (Readers, of course, may not delete anything)
+							$currUserID = $_SESSION["userinfo"]->getUserID();
+							$currUserCategory = $_SESSION["userinfo"]->getCategory();
+
+							if ($currUserCategory == 1)
+								$userProjects = findAllProjects();
+							else
+								$userProjects = getUserProjectsByRole($currUserID, 'Writer');
+
+							$rIDpID = getReagentProjectID($reagentIDToView);
+							$rChildren = $bfunc_obj->getReagentChildren($reagentIDToView);
+							$delete_restricted = true;
+						
+							if (sizeof($rChildren) == 0)
+							{
+								if ($rIDpID > 0)
+								{
+									// Nov. 20/09: NO!  Even Admin cannot delete reagents that have preps!!
+									if ($currUserCategory == 4)
+									{
+										$delete_restricted = true;
+									}
+									else
+									{
+										$loc_obj = new Location_Output_Class();
+										$child_expID = $loc_obj->getExpID($reagentIDToView);
+
+										// Feb. 18/10: This is not sufficient.  When preps (wells) for a particular reagent are deleted, rows are deleted from Isolates_tbl, but Experiment_tbl entry is untouched.  Therefore, in order to check if preps exist, need to count the number of ISOLATES:
+										$num_isolates = 0;
+										
+										if ($child_expID > 0)
+										{
+											$num_isolates_rs = mysql_query("SELECT COUNT(isolate_pk) as num_iso FROM Isolate_tbl WHERE expID='" . $child_expID . "' AND status='ACTIVE'", $conn) or die("Cannot fetch isolates: " . mysql_error());
+										
+											if ($num_isolates_ar = mysql_fetch_array($num_isolates_rs, MYSQL_ASSOC))
+											{
+												$num_isolates = $num_isolates_ar["num_iso"];
+											}
+										}
+
+										if (($child_expID < 1) || $num_isolates == 0)
+										{
+											// No location, BUT - Dec. 16/09: STILL check if user has project Write access!!!
+											if (!in_array($rIDpID, $userProjects))
+											{
+												if ($currUserCategory == 1)
+												{
+													$delete_restricted = false;
+												}
+												else
+												{
+													$delete_restricted = true;
+												}
+											}
+											else
+											{
+												// no location and project writer, can delete
+												$delete_restricted = false;
+											}
+										}
+										else
+										{
+											// NO ONE, NOT EVEN ADMIN, can delete if has location
+											$delete_restricted = true;
+	
+											echo "<INPUT TYPE=\"hidden\" ID=\"write_access_" . $reagentIDToView . "\" VALUE=\"" . $limsID . "\">";
+										}
+									}
+								}
+								else
+								{
+									if ($currUserCategory == 1)
+									{
+										$delete_restricted = false;
+									}
+									
+								}
+							}
+							else
+							{
+								// No one may delete if has children
+								$delete_restricted = true;
+
+								echo "<INPUT TYPE=\"hidden\" ID=\"has_children_" . $reagentIDToView . "\" VALUE=\"" . $limsID . "\">";
+							}
+
+							if (intval($delete_restricted) != 1)
+							{
+								?><INPUT type="button" VALUE="Delete" onClick="deleteReagentFromDetailedView('<?php echo $reagentIDToView; ?>');"><?php
+							}
+							else
+							{
+								?><INPUT type="button" VALUE="Delete" DISABLED><?php
+							}
+						?></td>
+					</tr>
+				</table>
+			</td>
+		</tr>
+
+		<tr><td colspan="<?php echo $colspan; ?>"><HR></td></tr><?php
+
+		foreach ($rPropCategories as $key => $category)
+		{
+			$categoryID = $_SESSION["ReagentPropCategory_Name_ID"][$category];
+			$categoryAlias = $_SESSION["ReagentPropCategory_ID_Alias"][$categoryID];
+
+			?>
+			<FORM METHOD="POST" ID="editReagentForm_<?php echo $categoryAlias; ?>" NAME="reagentDetailForm_<?php echo $category; ?>" ACTION="<?php echo $cgi_path . "update.py"; ?>">
+				<input type="hidden" name="reagent_id_hidden" value="<?php echo $reagentIDToView; ?>">
+				<input type="hidden" name="reagent_typeid_hidden" value="<?php echo $reagentType; ?>">
+				<input type="hidden" name="reagent_groupnum_hidden" value="<?php echo $reagentGroup; ?>">
+				<input type="hidden" name="cloning_method_hidden" value="<?php echo $cloningMethod; ?>">
+				<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+				<?php
+					if ($reagentType == $_SESSION["ReagentType_Name_ID"]["Insert"])
+						$is_linear = True;
+					else
+						$is_linear = False;
+				?>
+				<input type="hidden" ID="is_linear" value="<?php echo $is_linear; ?>">
+
+			<tr><td colspan="<?php echo $colspan; ?>"></td></tr><?php
+			$r_props = $rfunc_obj->findReagentPropertiesByCategory($reagentIDToView, $_SESSION["ReagentPropCategory_Name_ID"][$category]);
+
+			// April 21, 2010: SORT properties in order assigned to this reagent type
+			$tmp_order_list = Array();
+
+			foreach ($r_props as $propCatID => $props)
+			{
+				$pOrd = $rfunc_obj->getReagentTypePropertyOrdering($reagentType, $propCatID);
+				$tmp_order_list[$propCatID] = $pOrd;
+			}
+
+			// Now: Do NOT put an 'if count($r_props) > 0' block here, because what if the reagent has no External IDs at the moment but user wants to fill them in later??  Of course section headings need to be shown, along with 'Edit' buttons, and when user hits 'Edit' output the full property set for this category to modify as desired
+			if ((strcasecmp($category, "DNA Sequence") != 0) && (strcasecmp($category, "Protein Sequence") != 0) && (strcasecmp($category, "RNA Sequence") != 0))
+			{
+				?><tr ID="<?php echo $categoryAlias; ?>_tbl_view">
+					<td style="padding-top:15px;">
+						<TABLE style="background-color:#FFF8DC; width:100%; border:1px outset; padding:6px;">
+							<tr>
+								<td class="detailedView_heading" colspan="2" style="text-align:left; padding-left:5px; font-weight:bold; color:blue;">
+									<?php echo $category; ?>
+								</td>
+					
+								<td class="detailedView_heading" style="text-align:right; padding-right:6px; padding-top:0; color:#000000; font-size:10pt; font-family:Helvetica; white-space:nowrap;">
+									<?php
+										if ($modify_restricted)
+											$modify_disabled = "DISABLED";
+				
+											// "Modify" button
+											echo "<INPUT TYPE=\"BUTTON\" ID=\"update_reagent_" . $categoryAlias . "\" style=\"margin-left:10px; font-weight:bold; font-size:8pt;\" " . $modify_disabled . " VALUE=\"Edit " . $category . "\" onClick=\"toggleReagentEditModify('edit', '" . $categoryAlias . "', '" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType]) . "');\"></INPUT>";
+									?>
+								</td>
+							</tr><?php
+
+						// April 22, 2010: Print properties in their assigned order
+						$psorted = Array();
+						
+						sort(array_values($tmp_order_list));
+
+						foreach ($tmp_order_list as $pcID => $pOrd)
+						{
+							$tmp_sorted = Array();
+							$tmp_sorted = $psorted[$pOrd];
+							$tmp_sorted[] = $pcID;
+							$psorted[$pOrd] = $tmp_sorted;
+						}
+
+						for ($i = 1; $i <= max(array_keys($psorted)); $i++)
+						{
+							$pList = $psorted[$i];
+
+							foreach ($pList as $ind => $propCatID)
+							{
+								$props = $r_props[$propCatID];
+
+								if (count($props) == 1)
+								{
+									foreach ($props as $key => $prop)
+									{
+										$propName = "";
+										$propDescr = "";
+										$propval = "";
+
+										try
+										{
+											$propName = $prop->getPropertyName();
+											$propDescr = $prop->getPropertyDescription();
+											$propval = $prop->getPropertyValue();
+
+											echo "<TR ID=\"" . $categoryAlias . "_view\">";
+
+												echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold; white-space:nowrap;\">" . $propDescr . "</TD>";
+
+												echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+
+												// Jan. 20, 2010: NO!!!!!!!!!!!!!!  What if have 'comments' under additional categories??
+// 												if ((strcasecmp($propName, "description") == 0) || (strcasecmp($propName, "comments") == 0) || (strcasecmp($propName, "verification comments") == 0) || (strcasecmp($propName, "accession number") == 0))
+
+												if (($propCatID == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["description"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"])) || ($propCatID == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["comments"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"])) || ($propCatID == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["verification comments"], $_SESSION["ReagentPropCategory_Na [...]
+												{
+													// June 10, 2010: hyperlink??
+													$attr_ID = $rfunc_obj->getRTypeAttributeID($reagentType, $propName, $_SESSION["ReagentPropCategory_Name_ID"][$category]);
+
+													if ($rfunc_obj->isHyperlink($attr_ID))
+													{
+														echo "<a target=\"new\" href=\"" . $this->get_Special_Column_Type($propName, $category, $reagentIDToView, "None") . "\">" . $this->get_Special_Column_Type($propName, $category, $reagentIDToView, "None") . "</a>";
+													}
+													else
+														echo $this->get_Special_Column_Type($propName, $category, $reagentIDToView, "None");
+												}
+												else if (strcasecmp($propName, "entrez gene id") == 0)
+												{
+													echo "<a href=\"http://www.ncbi.nlm.nih.gov/sites/entrez?Db=gene&Cmd=ShowDetailView&TermToSearch=" . $propval . "\" target=\"_blank\">" . $propval . "</a>";
+												}
+												else if (strcasecmp($propName, "ensembl gene id") == 0)
+												{
+													$species = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["species"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]));
+
+													switch (strtolower($species))
+													{
+														case "homo sapiens":
+															echo "<a href=\"http://www.ensembl.org/Homo_sapiens/geneview?gene=" . $propval . "\" target=\"_blank\">" . $propval . "</a>";
+														break;
+														
+														case "mus musculus":
+															echo "<a href=\"http://www.ensembl.org/Mus_musculus/geneview?gene=" . $propval . "\" target=\"_blank\">" . $propval . "</a>";
+														break;
+														
+														case "danio rerio":
+															echo "<a href=\"http://www.ensembl.org/Danio_rerio/geneview?gene=" . $propval . "\" target=\"_blank\">" . $propval . "</a>";
+														break;
+														
+														case "rattus norvegicus":
+															echo "<a href=\"http://www.ensembl.org/Rattus_norvegicus/geneview?gene=" . $propval . "\" target=\"_blank\">" . $propval . "</a>";
+														break;
+														
+														default:
+															echo $propval;
+														break;
+													}
+												}
+												else if ((strcasecmp($propName, "packet id") == 0) || (strcasecmp($propName, "owner") == 0))
+												{
+													echo $this->get_Special_Column_Type("packet", "General Properties", $reagentIDToView, "preview");
+												}
+												else if (strcasecmp($propName, "oligo type") == 0)
+												{
+													if (strcasecmp($propval, 's') == 0)
+														$propval = 'Sense';
+													else if (strcasecmp($propval, 'a') == 0)
+														$propval = 'Antisense';
+													
+													echo $propval;
+												}
+												else
+												{
+													// June 15, 2010: Print hyperlinks
+													$attr_ID = $rfunc_obj->getRTypeAttributeID($reagentType, $propName, $_SESSION["ReagentPropCategory_Name_ID"][$category]);
+
+													if ($rfunc_obj->isHyperlink($attr_ID))
+													{
+														echo "<a target=\"new\" href=\"" . $propval . "\">" . $propval . "</a>";
+													}
+													else
+														echo $propval;
+												}
+
+												echo "</TD>";
+
+											echo "</TR>";
+										}
+										catch (Exception $e)
+										{
+											// this is a feature
+											$propName = $prop->getFeatureType();
+											$propDescr = $prop->getFeatureDescription();
+											$featureValue = $prop->getFeatureValue();
+											$featureStart = $prop->getFeatureStart();
+											$featureEnd = $prop->getFeatureEnd();
+											$featureDir = $prop->getFeatureDirection();
+
+											if ($featureEnd != 0)
+											{
+												$positionString = "<span style=\"color:#006400\">(" . $units . " " . $featureStart . " - " . $featureEnd . ")</span>";
+												$cdna_length = $featureEnd - $featureStart + 1;
+												$cdna_string = "<span style=\"color:#006400\">" . $cdna_length . "</SPAN> nucleotides " . $positionString . ", " . $featureDir . " orientation";
+											}
+											else
+											{
+												$positionString = "";
+												$cdna_length = 0;
+												$cdna_string = "";
+											}
+
+											echo "<TR ID=\"" . $categoryAlias . "_view\">";
+
+											echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold; white-space:nowrap;\">" . $propDescr . "</TD>";
+	
+											echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+
+											if (strcasecmp($propName, "cdna insert") == 0)
+											{
+												echo $cdna_string;
+
+												// show cDNA insert
+												if ($cloningMethod != 1)
+												{
+													// Get the Insert that belongs to IPV
+													$tmp_rid = $bfunc_obj->get_Background_rid($reagentIDToView, "Parent Insert Vector");
+										
+													if ($tmp_rid > 0)
+													{
+														$tmp_insert = $bfunc_obj->get_Insert($tmp_rid);
+										
+														// August 17/07: Restrict viewing by project - if parent belongs to a project you don't have access to, don't allow linking
+														$tmpProject = getReagentProjectID($tmp_insert);
+														$userProjects = getAllowedUserProjectIDs($_SESSION["userinfo"]->getUserID());
+										
+														if (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || in_array($tmpProject, $userProjects))
+														{
+															echo "<a href=\"Reagent.php?View=6&rid=" . $tmp_insert . "\" style=\"margin-left:8px; font-weight:normal;\">";
+															echo $gfunc_obj->getConvertedID_rid($tmp_insert);
+															echo "</a> ";
+														}
+														else
+														{
+															echo "<span class=\"linkDisabled\" style=\"margin-left:8px; font-weight:normal;\">";
+															echo $gfunc_obj->getConvertedID_rid($tmp_insert);
+															echo "</span>";
+														}
+													}
+												}
+
+												echo "</TD></TR><TR><TD></TD></TR>";
+											}
+											else if ((strcasecmp($propName, "5' cloning site") == 0) || (strcasecmp($propName, "3' cloning site") == 0))
+											{
+												echo $featureValue . " " . $positionString;
+
+												if (strcasecmp($propName, "3' cloning site") == 0)
+													echo "</TD></TR><TR><TD></TD></TR>";
+											}
+											else if ((strcasecmp($propName, "5' linker") == 0) || (strcasecmp($propName, "3' linker") == 0))
+											{
+												if (strlen($featureValue) > 0)		// July 08/09
+												{
+													echo $featureValue . " " . $positionString . ", " . $featureDir . " orientation";
+	
+													if (strcasecmp($propName, "3' linker") == 0)
+														echo "</TD></TR><TR><TD></TD></TR>";
+												}
+											}
+											else
+											{
+												$featureDescriptor = $prop->getFeatureDescriptor();
+
+												echo "<UL style=\"padding-left:1.5em; padding-top:0.5em;\">";
+
+												if ($featureDescriptor && strlen($featureDescriptor) > 0)
+												{
+													switch($propName)
+													{
+														case 'tag':
+															echo "<LI>" . $featureValue . " " . $positionString . ", " . $featureDir . " orientation, position " . $featureDescriptor .  "</LI>";
+														break;
+													
+														case 'promoter':
+															echo "<LI>" . $featureValue . " " . $positionString . ", " . $featureDir . " orientation, expression system " . $featureDescriptor .  "</LI>";
+														break;
+													}
+												}
+												else
+													echo "<LI>" . $featureValue . " " . $positionString . ", " . $featureDir . " orientation</LI>";
+
+												echo "</UL>";
+
+												echo "</TD></TR>";
+											}
+										}
+									}
+								}
+								else
+								{
+									$pID = $rfunc_obj->findPropertyInCategoryID($propCatID);
+
+									// name and description are the same
+									$propName = $_SESSION["ReagentProp_ID_Name"][$pID];
+									$propDescr = $_SESSION["ReagentProp_ID_Desc"][$pID];
+
+									echo "<TR ID=\"" . $categoryAlias . "_view\">";
+										echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold; white-space:nowrap;\">" . $propDescr . "</TD>";
+
+										echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+
+										echo "<UL style=\"padding-left:1.5em; padding-top:0.5em;\">";
+
+										foreach ($props as $key => $prop)
+										{
+											// May 26, 2011: RESET VARIABLES!!!!!!!!! OTHERWISE IT WILL PRINT POSITIONS FOR NON-FEATURES!!!!!!!
+											$fValue = null;
+											$fStart = null;
+											$fEnd = null;
+											$fDir = null;
+											$fDescr = null;
+
+											// June 30/09: Cannot automatically assume features because non-features like Alternate ID ("checkbox" props) have >1 value
+											if (!$rfunc_obj->isSequenceFeature($propCatID))
+											{
+												$fValue = $prop->getPropertyValue();
+											}
+											else
+											{
+												$fValue = $prop->getFeatureValue();
+												$fStart = $prop->getFeatureStart();
+												$fEnd = $prop->getFeatureEnd();
+												$fDir = $prop->getFeatureDirection();
+												$fDescr = $prop->getFeatureDescriptor();
+											}
+
+											if ($fEnd && ($fEnd != 0))
+												$posString = "<span style=\"color:#006400\">(" . $units . " " . $fStart . " - " . $fEnd . ")</span>";
+											else
+												$posString = "";
+
+											if ($fDir && strlen($fDir) > 0)
+												$dirString =  ", " . $fDir . " orientation";
+											else
+												$dirString = "";
+
+											if ($fDescr && strlen($fDescr) > 0)
+												echo "<LI>" . $fValue . " " . $posString . ", " . $fDescr . $dirString . "</LI>";
+
+											else
+												echo "<LI>" . $fValue . " " . $posString . $dirString . "</LI>";
+										}
+
+										echo "</UL>";
+
+										echo "</TD>";
+									echo "</TR>";
+								}
+							}
+						}
+
+						?></table>
+					</td>
+				</tr>
+
+				<tr ID="<?php echo $categoryAlias; ?>_tbl_modify" style="display:none;">
+					<td style="padding-top:15px;">
+							<TABLE style="background-color:#FFF8DC; width:725px; border:1px outset; padding:6px;">
+								<tr>
+									<td class="detailedView_heading" colspan="2" style="text-align:left; padding-left:5px; font-weight:bold; color:blue;">
+										<?php echo $category; ?>
+									</td>
+						
+									<td class="detailedView_heading" style="text-align:right; padding-right:6px; padding-top:0; color:#000000; font-size:10pt; font-family:Helvetica; white-space:nowrap;">
+										<?php
+											if ($modify_restricted)
+												$modify_disabled = "DISABLED";
+					
+												// "Save" and "Cancel" buttons
+												echo "<INPUT TYPE=\"BUTTON\" ID=\"update_reagent_" . $categoryAlias . "\" style=\"margin-left:10px; font-weight:bold; font-size:8pt;\" " . $modify_disabled . " VALUE=\"Save\" onClick=\"document.pressed = this.value; if (checkMandatoryProps('" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType]) . "', '" . $categoryAlias . "')) toggleReagentEditModify('save', '" . $categoryAlias . "', '" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType [...]
+	
+												echo "<INPUT TYPE=\"BUTTON\" ID=\"update_reagent_" . $categoryAlias . "\" style=\"margin-left:10px; font-weight:bold; font-size:8pt;\" " . $modify_disabled . "  VALUE=\"Cancel\" onClick=\"document.pressed = this.value; cancelModify('" . $reagentIDToView . "');\"></INPUT>";
+										?>
+									</td>
+								</tr><?php
+	
+								// Here need more than saved properties though, need ALL properties in this section for this reagent type
+								$all_attributes = $rfunc_obj->getReagentTypeAttributesByCategory($reagentType, $categoryID);
+
+								if ($categoryID == $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence Features"])
+								{
+									?><TR><TD colspan="7">
+										<table>
+											<TR>
+												<TD colspan="7">
+												<?php
+													$rc_obj = new Reagent_Creator_Class();
+													$seqFunc_obj = new Sequence_Function_Class();
+		
+													$dnaSequence = $seqFunc_obj->findDNASequence($reagentIDToView);
+													
+													if ($dnaSequence)
+														$sequence = $dnaSequence->getSequence();
+													else
+														$sequence = "";
+		
+													$seqID = $seqFunc_obj->findSequenceID($sequence);
+		
+													// Do NOT pass 'insertFeaturesForm' name to printFeatures function!!!!!!!!!!!!
+													$tblID = "modifyReagentPropsTbl_" . $categoryAlias;
+
+													$rc_obj->printFeatures($_SESSION["ReagentType_ID_Name"][$reagentType], "", $reagentIDToView, $seqID, "reagentDetailForm_" . $category, false, true, $tblID);
+												?>
+												</td>
+											</tr>
+										</table>	<!-- close insert_features_view table -->
+									</td></tr><?php
+								}
+								else if ($categoryID == $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence Features"])
+								{
+									?><TR><TD colspan="7">
+										<table>
+											<TR>
+												<TD colspan="7">
+												<?php
+													$rc_obj = new Reagent_Creator_Class();
+													$seqFunc_obj = new Sequence_Function_Class();
+		
+													$proteinSequence = $seqFunc_obj->findProteinSequence($reagentIDToView);
+													
+													if ($proteinSequence)
+														$sequence = $proteinSequence->getSequence();
+													else
+														$sequence = "";
+		
+													$seqID = $seqFunc_obj->findSequenceID($sequence);
+		
+													// Do NOT pass 'insertFeaturesForm' name to printFeatures function!!!!!!!!!!!!
+													$tblID = "modifyReagentPropsTbl_" . $categoryAlias;
+													$rc_obj->printFeatures($_SESSION["ReagentType_ID_Name"][$reagentType], "", $reagentIDToView, $seqID, "reagentDetailForm_" . $category, false, true, $tblID);
+												?>
+												</td>
+											</tr>
+										</table>	<!-- close insert_features_view table -->
+									</td></tr><?php
+								}
+								else if ($categoryID == $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence Features"])
+								{
+									?><TR><TD colspan="7">
+										<table>
+											<TR>
+												<TD colspan="7">
+												<?php
+													$rc_obj = new Reagent_Creator_Class();
+													$seqFunc_obj = new Sequence_Function_Class();
+		
+													$rnaSequence = $seqFunc_obj->findRNASequence($reagentIDToView);
+													
+													if ($rnaSequence)
+														$sequence = $rnaSequence->getSequence();
+													else
+														$sequence = "";
+		
+													$seqID = $seqFunc_obj->findSequenceID($sequence);
+		
+													// Do NOT pass 'insertFeaturesForm' name to printFeatures function!!!!!!!!!!!!
+													$tblID = "modifyReagentPropsTbl_" . $categoryAlias;
+
+													$rc_obj->printFeatures($_SESSION["ReagentType_ID_Name"][$reagentType], "", $reagentIDToView, $seqID, "reagentDetailForm_" . $category, false, true, $tblID);
+												?>
+												</td>
+											</tr>
+										</table>	<!-- close insert_features_view table -->
+									</td></tr><?php
+								}
+								else
+								{
+									// May 5, 2010: keys are now attribute IDs
+									foreach ($all_attributes as $attrID => $attribute)
+									{
+										$pName = $attribute->getPropertyName();
+										$pCategory = $attribute->getPropertyCategory();
+
+										$p_id = $_SESSION["ReagentProp_Name_ID"][$pName];
+										$c_id = $_SESSION["ReagentPropCategory_Name_ID"][$pCategory];
+
+										$pcID = $rfunc_obj->getPropertyIDInCategory($p_id, $c_id);
+
+										// May 11, 2011: verify mandatory props on saving
+										if ($rfunc_obj->isMandatory($_SESSION["ReagentType_ID_Name"][$reagentType], $pName))
+										{
+											//echo "MANDATORY: " . $pName;
+
+											echo "<INPUT TYPE=\"hidden\" NAME=\"" . $_SESSION["ReagentType_ID_Name"][$reagentType] . "_mandatoryProps[]\" VALUE=\"" . $attrID . "\">";
+										}
+
+										if (in_array($pcID, array_keys($r_props)))
+										{
+											$props = $r_props[$pcID];
+
+											if (count($props) == 1)
+											{
+												foreach ($props as $key => $prop)
+												{
+													$propName = "";
+													$propDescr = "";
+													$propval = "";
+			
+													try
+													{
+														$propName = $prop->getPropertyName();
+
+														// May 11, 2011: verify mandatory props on saving
+														if ($rfunc_obj->isMandatory($_SESSION["ReagentType_ID_Name"][$reagentType], $propName))
+														{
+															//echo "MANDATORY: " . $propName;
+
+															echo "<INPUT TYPE=\"hidden\" NAME=\"" . $reagentType . "_mandatoryProps[]\" VALUE=\"" . $attrID . "\">";
+														}
+
+														$propDescr = $prop->getPropertyDescription();
+										
+														$propval = $prop->getPropertyValue();
+														echo "<TR ID=\"" . $categoryAlias . "\">";
+
+														if ($pcID == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["alternate id"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]))
+														{
+															echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $propDescr;
+																echo "<BR><BR><span style=\"font-size:8pt;\">For 'Other', please enter<BR> the database name and<BR> numeric identifier, separated<BR> by semicolon, in the textbox<BR> (e.g. 'IMAGE:123456')</span>";
+															echo "</TD>";
+														}
+														else if ($pcID == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["type of insert"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]))
+														{
+															echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $propDescr;
+
+															echo " <span style=\"font-size:9pt; color:#FF0000; font-weight:bold\">*</span>  <IMG src=\"" . $hostname . "pictures/hm4.png\" HEIGHT=\"13\" width=\"16\" ALT=\"link_icon\" style=\"vertical-align:middle; cursor:auto\" onmouseover=\"return overlib('Select the correct type of insert value to ensure correct translation of the DNA sequence to protein.  Refer to the \'Translation Guidelines\' for more information.', CAPTION, 'Type of Insert', STICKY);\">";			
+
+															echo "</TD>";
+														}
+														else if ($pcID == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["open/closed"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]))
+														{
+															echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $propDescr;
+
+															echo " <span style=\"font-size:9pt; color:#FF0000; font-weight:bold\">*</span>  <IMG src=\"" . $hostname . "pictures/hm4.png\" HEIGHT=\"13\" width=\"16\" ALT=\"link_icon\" style=\"vertical-align:middle; cursor:auto\" onmouseover=\"return overlib('Select the correct open/closed value to ensure correct translation of the DNA sequence to protein.  Refer to the \'Translation Guidelines\' for more information.', CAPTION, 'Open/Closed', STICKY);\">";			
+
+															echo "</TD>";
+														}
+														else
+														{
+															echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $propDescr . "</TD>";
+														}
+			
+															echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";		
+																$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"][$propName] . $genPostfix, $propName, $propval, $reagentIDToView, true, $category);
+															echo "</TD>";
+														echo "</TR>";
+													}
+													catch (Exception $e)
+													{
+														// this is a feature
+														$propName = $prop->getFeatureType();
+														$propDescr = $prop->getFeatureDescription();
+														$featureValue = $prop->getFeatureValue();
+														$featureStart = $prop->getFeatureStart();
+														$featureEnd = $prop->getFeatureEnd();
+														$featureDir = $prop->getFeatureDirection();
+
+														// May 11, 2011: verify mandatory props on saving
+														if ($rfunc_obj->isMandatory($_SESSION["ReagentType_ID_Name"][$reagentType], $propName))
+														{
+															//echo "MANDATORY: " . $propName;
+
+															echo "<INPUT TYPE=\"hidden\" NAME=\"" . $reagentType . "_mandatoryProps[]\" VALUE=\"" . $attrID . "\">";
+														}
+			
+														if ($featureEnd != 0)
+														{
+															$positionString = "<span style=\"color:#006400\">(" . $units . " " . $featureStart . " - " . $featureEnd . ")</span>";
+															$cdna_length = $featureEnd - $featureStart + 1;
+															$cdna_string = "<span style=\"color:#006400\">" . $cdna_length . "</SPAN> nucleotides " . $positionString . ", " . $featureDir . " orientation";
+														}
+														else
+														{
+															$positionString = "";
+															$cdna_length = 0;
+															$cdna_string = "";
+														}
+			
+														echo "<TR ID=\"" . $categoryAlias . "\">";
+			
+														echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $propDescr;
+
+															if ($pcID == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["alternate id"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]))
+																echo "<BR><BR><span style=\"font-size:8pt;\">For 'Other', please enter<BR> the database name and<BR> numeric identifier, separated<BR> by semicolon, in the textbox<BR> (e.g. 'IMAGE:123456')</span>";
+
+														echo "</TD>";
+				
+														echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+			
+														// No cDNA, sites or linkers for RNA sequence
+														$featureDescriptor = $prop->getFeatureDescriptor();
+		
+														echo "<UL style=\"padding-left:1.5em; padding-top:0.5em;\">";
+		
+														if ($featureDescriptor && strlen($featureDescriptor) > 0)
+														{
+															switch($propName)
+															{
+																case 'tag':
+																	echo "<LI>" . $featureValue . " " . $positionString . ", " . $featureDir . " orientation, position " . $featureDescriptor .  "</LI>";
+																break;
+															
+																case 'promoter':
+																	echo "<LI>" . $featureValue . " " . $positionString . ", " . $featureDir . " orientation, expression system " . $featureDescriptor .  "</LI>";
+																break;
+															}
+														}
+														else
+															echo "<LI>" . $featureValue . " " . $positionString . ", " . $featureDir . " orientation</LI>";
+		
+														echo "</UL>";
+		
+														echo "</TD></TR>";
+													}
+												}
+											}
+											else
+											{
+												$pVals = Array();
+
+												foreach ($props as $pkey => $a_prop)
+												{
+													$pVals[$pcID][] = $a_prop->getPropertyValue();
+												}
+
+												$pID = $rfunc_obj->findPropertyInCategoryID($pcID);
+			
+												$propName = $_SESSION["ReagentProp_ID_Name"][$pID];
+
+												$propDescr = $_SESSION["ReagentProp_ID_Desc"][$pID];
+
+												// May 11, 2011: verify mandatory props on saving
+												if ($rfunc_obj->isMandatory($_SESSION["ReagentType_ID_Name"][$reagentType], $propName))
+												{
+													//echo "MANDATORY: " . $propName;
+
+													echo "<INPUT TYPE=\"hidden\" NAME=\"" . $reagentType . "_mandatoryProps[]\" VALUE=\"" . $attrID . "\">";
+												}
+
+												if ($propName == "alternate id")
+												{
+													echo "<TR ID=\"" . $categoryAlias . "\">";
+														echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $propDescr;
+
+														if ($pcID == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["alternate id"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]))
+															echo "<BR><BR><span style=\"font-size:8pt;\">For 'Other', please enter<BR> the database name and<BR> numeric identifier, separated<BR> by semicolon, in the textbox<BR> (e.g. 'IMAGE:123456')</span>";
+
+														echo "</TD>";
+
+														echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+															$this->print_Set_Extended_Checkbox($propName, $genPrefix . $_SESSION["ReagentProp_Name_Alias"][$propName] . $genPostfix, $pVals[$pcID], $reagentIDToView, "", $category, $reagentType);
+														echo "</TD>";
+													echo "</TR>";
+												}
+												// May 7, 2010: Allowing other properties to have multiple values
+												else
+												{
+													echo "<TR ID=\"" . $categoryAlias . "\">";
+														echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $propDescr;
+
+														if ($pcID == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["alternate id"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]))
+															echo "<BR><BR><span style=\"font-size:8pt;\">For 'Other', please enter<BR> the database name and<BR> numeric identifier, separated<BR> by semicolon, in the textbox<BR> (e.g. 'IMAGE:123456')</span>";
+														echo "</TD>";
+
+														echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+															$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"][$propName] . $genPostfix, $propName, $pVals[$pcID], $reagentIDToView, true, $category);
+														echo "</TD>";
+													echo "</TR>";
+												}
+											}
+										}
+										else
+										{
+											$tmp_propID = $rfunc_obj->findPropertyInCategoryID($pcID);
+											$tmp_propDescr = $_SESSION["ReagentProp_ID_Desc"][$tmp_propID];
+											$tmp_propName = $_SESSION["ReagentProp_ID_Name"][$tmp_propID];
+	
+											// May 11, 2011: verify mandatory props on saving
+											if ($rfunc_obj->isMandatory($_SESSION["ReagentType_ID_Name"][$reagentType], $tmp_propName))
+											{
+												//echo "MANDATORY: " . $tmp_propName;
+
+												echo "<INPUT TYPE=\"hidden\" NAME=\"" . $reagentType . "_mandatoryProps[]\" VALUE=\"" . $attrID . "\">";
+											}
+
+											if (strcasecmp($tmp_propName, "protein translation") != 0)
+											{
+												$tmp_propAlias = $_SESSION["ReagentProp_Name_Alias"][$tmp_propName];
+		
+												echo "<TR ID=\"" . $categoryAlias . "\">";
+													echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $tmp_propDescr;
+
+														if ($pcID == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["alternate id"], $_SESSION["ReagentPropCategory_Name_ID"]["External Identifiers"]))
+															echo "<BR><BR><span style=\"font-size:8pt;\">For 'Other', please enter<BR> the database name and<BR> numeric identifier, separated<BR> by semicolon, in the textbox<BR> (e.g. 'IMAGE:123456')</span>";
+
+														else if ($pcID == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["type of insert"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]))
+														{															
+															echo " <span style=\"font-size:9pt; color:#FF0000; font-weight:bold\">*</span>  <IMG src=\"" . $hostname . "pictures/hm4.png\" HEIGHT=\"13\" width=\"16\" ALT=\"link_icon\" style=\"vertical-align:middle; cursor:auto\" onmouseover=\"return overlib('Select the correct type of insert value to ensure correct translation of the DNA sequence to protein.  Refer to the \'Translation Guidelines\' for more information.', CAPTION, 'Type of Insert', STICKY);\">";			
+
+															echo "</TD>";
+														}
+														else if ($pcID == $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["open/closed"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]))
+														{														
+															echo " <span style=\"font-size:9pt; color:#FF0000; font-weight:bold\">*</span>  <IMG src=\"" . $hostname . "pictures/hm4.png\" HEIGHT=\"13\" width=\"16\" ALT=\"link_icon\" style=\"vertical-align:middle; cursor:auto\" onmouseover=\"return overlib('Select the correct open/closed value to ensure correct translation of the DNA sequence to protein.  Refer to the \'Translation Guidelines\' for more information.', CAPTION, 'Open/Closed', STICKY);\">";			
+
+															echo "</TD>";
+														}
+	
+													echo "</TD>";
+		
+													echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+														$this->print_property_final($genPrefix . $tmp_propAlias . $genPostfix , $tmp_propName, "", $reagentIDToView, true, $category);
+													echo "</TD>";
+												echo "</TR>";
+											}
+										}
+									}
+								}
+							?></table>
+					</td>
+				</tr><?php		// end 'Modify' section
+			}
+			else if ( (strcasecmp($category, "DNA Sequence") == 0) && $rfunc_obj->hasAttribute($reagentType, "sequence", $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]))
+			{
+				// June 18, 2010
+				$propsList = $rfunc_obj->findReagentPropertiesByCategory($reagentIDToView, $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+
+				// show tabs IFF has protein translation with DNA!!!!!!!!!!!!
+				echo "<TR><TD colspan=\"3\" style=\"padding-right:5px;\"> </TD></TR>";
+			
+				?><tr>
+					<TD colspan="2">
+							<TABLE class="detailedView_tbl" style="width:725px; border:1px outset; padding:6px;" style="border: 1px solid black;">
+								<tr ID="other_reagent_sequence_tbl_view">
+									<td class="detailedView_heading" style="text-align:left; padding-left:5px; font-weight:bold; color:blue;">
+										Sequence Information
+									</TD>
+			
+									<td class="detailedView_heading" style="text-align:right; padding-right:6px; padding-top:0; color:#000000; font-size:10pt; font-family:Helvetica; white-space:nowrap;"><?php
+			
+										if ($modify_restricted)
+											$modify_disabled = "DISABLED";
+			
+										// "Modify" button
+										echo "<INPUT TYPE=\"BUTTON\" ID=\"edit_reagent_" . $categoryAlias . "\" style=\"margin-left:10px; font-weight:bold; font-size:8pt;\" " . $modify_disabled . "  VALUE=\"Edit Sequence\" onClick=\"toggleReagentEditModify('edit', '" . $categoryAlias . "', '" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType]) . "');\"></INPUT>";
+
+										// "Save" and "Cancel" buttons
+										echo "<DIV ID=\"sequenceButtons\" style=\"display:none\">";
+											echo "<INPUT TYPE=\"BUTTON\" ID=\"save_reagent_" . $categoryAlias . "\" style=\"margin-left:10px; font-weight:bold; font-size:8pt;\" " . $modify_disabled . " VALUE=\"Save\" onClick=\"document.pressed = this.value; if (checkMandatoryProps(" . $reagentType . ")) selectAllPropertyValues(); toggleReagentEditModify('save', '" . $categoryAlias . "', '" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType]) . "');\"></INPUT>";
+
+											echo "<INPUT TYPE=\"BUTTON\" ID=\"cancel_save_" . $categoryAlias . "\" style=\"margin-left:10px; font-weight:bold; font-size:8pt;\" " . $modify_disabled . "  VALUE=\"Cancel\" onClick=\"document.pressed = this.value; toggleReagentEditModify('cancel', '" . $categoryAlias . "', '" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType]) . "');\"></INPUT>";
+										echo "</DIV>";
+										?>
+									</td>
+								</tr><?php
+			
+								// June 30/09: The most accurate check is to see whether the reagent has attribute 'protein translation' as a function of 'DNA sequence'.  A protein translation cannot exist without DNA; a protein or RNA sequence, on the other hand, exists as the default sequence for some reagent types instead of DNA
+								if ($rfunc_obj->hasAttribute($reagentType, "protein translation", $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]))
+								{
+									?><tr>
+										<td style="padding-left:0px;" colspan="2">
+											<TABLE id="tabsTbl" cellspacing="0">
+												<TR>
+													<TD style="padding-left:0px;" class="currentView">
+														<span id="viewDnaTab" class="seqTabLinkActive" onClick="showDNASequence();">DNA Sequence</span>
+													</TD>
+							
+													<TD class="switchTo">
+														<span id="viewProteinTab" class="seqTabLinkInactive" onClick="showProteinSequence();">Translated Protein Sequence</span>
+													</TD>
+												</TR>
+											</TABLE>
+										</TD>
+									</TR>
+			
+									<TR>
+										<TD class="sequenceContent" colspan="2">
+											<?php
+												// DNA SEQUENCE INFO
+
+												// Correction June 30/09, keep 'insert' variable name for consistency 
+												$insertName = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["name"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]));
+
+												// get sequence by ID
+												$seqFunc_obj = new Sequence_Function_Class();
+												$dnaSequence = $seqFunc_obj->findDNASequence($reagentIDToView);
+												
+												if ($dnaSequence)
+													$sequence = $dnaSequence->getSequence();
+												else
+													$sequence = "";
+
+												// Replaced July 13/09
+												$insertLength = strlen(str_replace(" ", "", trim($sequence)));
+
+												// June 30/09: added 'nucleotides'
+												$content = ">" . $limsID . ": " . $insertName . "; length " . $insertLength . '\r' . $sequence . '\r';
+							
+												// PROTEIN SEQUENCE INFO
+												// Replaced June 23/09
+												$seqFunc_obj = new Sequence_Function_Class();
+
+												// this is a Protein Sequence OBJECT
+												$proteinSequence = $seqFunc_obj->findProteinTranslation($reagentIDToView);
+
+												if ($proteinSequence)
+												{
+													$frame = $proteinSequence->getFrame();
+													$protStart = $proteinSequence->getStart();
+													$protEnd = $proteinSequence->getEnd();
+													$protSeq = $proteinSequence->getSequence();
+													$protLength = strlen(trim($protSeq));
+													$protMW = $proteinSequence->getMW();
+
+													if (!$protMW || $protMW == 0)
+													{
+														$protMW = $rfunc_obj->computeProteinMW($protSeq);
+													}
+												}
+												else
+												{
+													$protSeq = "";
+													$protStart = 0;
+													$protEnd = 0;
+													$protLength = 0;
+												}
+
+												$proteinFastaContent = ">" . $limsID . ": " . $insertName . "; length " . $protLength . " (translation of the longest ORF at nt " . $protStart . "-" . $protEnd . ")" . '\r' . $protSeq . '\r';
+											?>
+											<!-- Actual TAB, container for sequence information -->
+											<table ID="dnaSequenceTab" width="725px" style="display:inline;" border="0">
+												<tr>
+													<td style="padding-left:5px; padding-right:5px; padding-top:3px;">
+														<TABLE ID="insert_sequence_table" border="0">
+															<tr>
+																<td colspan="2" style="padding-left:10px; padding-right:10px; white-space:nowrap;">
+																	<span ID="exportDNASeqFasta" style="font-weight:normal; padding-top:0" class="linkExportSequence" onClick="exportDNASeqToFasta('<?php echo str_replace("'", "\'", $content); ?>')">Export to FASTA</span>
+										
+																	<span ID="viewRestrMap" class="linkExportSequence" style="padding-left:7px; font-weight:normal;" onClick="document.restriction_map_insert.submit()">Restriction Map</span>
+																</td>
+															</tr>
+					
+															<tr>
+																<td colspan="2" class="detailedView_value">
+																	<?php
+																		echo "<DIV ID=\"sequence_properties_tbl_view\" class=\"tabSequence\" style=\"margin-top:4px;\">";
+																			$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"]["sequence"] . $genPostfix , "sequence", $sequence, $reagentIDToView, false, $category, "", "", $reagentType);
+																		echo "</DIV>";
+
+																		// Feb 28/08 - Sequence in Modify mode - hidden
+																		echo "<DIV ID=\"sequence_properties_tbl_modify\" style=\"display:none\" class=\"tabSequence\" style=\"margin-top:4px;\">";
+																			$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"]["sequence"] . $genPostfix , "sequence", $sequence, $reagentIDToView, true, $category, "", "", $reagentType);
+																		echo "</DIV>";
+																	?>
+																</td>
+															</tr>
+															<?php
+
+															// August 13/09: This is ONLY required for Inserts!!!!!!!
+															// REMOVED MAY 19, 2011: causes issues with JS verification of mandatory properties
+															//if ($reagentType == $_SESSION["ReagentType_Name_ID"]["Insert"])
+															//{
+																?>
+																<!-- <tr><td colspan="6" style="padding-top:4px"></td></tr>
+																
+																<tr ID="itype_modify" style="display:none">
+																	<td class="detailedView_colName">Type of Insert
+																	<?php
+																	echo " <span style=\"font-size:9pt; color:#FF0000; font-weight:bold\">*</span>  <IMG src=\"" . $hostname . "pictures/hm4.png\" HEIGHT=\"13\" width=\"16\" ALT=\"link_icon\" style=\"vertical-align:middle; cursor:auto\" onmouseover=\"return overlib('Select the correct type of insert value to ensure correct translation of the DNA sequence to protein.  Refer to the \'Translation Guidelines\' for more information.', CAPTION, 'Type of Insert', STICKY);\">";
+																	?>
+																	</td>
+													
+																	<td colspan="5" class="detailedView_value"><?php
+	
+																		$iTypeID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["type of insert"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]);
+																		$insertType = $rfunc_obj->getPropertyValue($reagentIDToView, $iTypeID);
+														
+																		$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"]["type of insert"] . $genPostfix , "type of insert", $insertType, $reagentIDToView, true, "Classifiers");
+
+																		?><div id="it_warning" style="display:none; color:#FF0000"><P>Please select a Type of Insert from the dropdown list</div>
+																	</td>
+																</tr>
+											
+																<tr ID="modifyOpenClosed" style="display:none">
+																	<td class="detailedView_colName">
+																		Open/Closed
+																		<?php
+																		echo " <span style=\"font-size:9pt; color:#FF0000; font-weight:bold\">*</span>  <IMG src=\"" . $hostname . "pictures/hm4.png\" HEIGHT=\"13\" width=\"16\" ALT=\"link_icon\" style=\"vertical-align:middle; cursor:auto\" onmouseover=\"return overlib('Select the correct open/closed value to ensure correct translation of the DNA sequence to protein.  Refer to the \'Translation Guidelines\' for more information.', CAPTION, 'Open/Closed', STICKY);\">";
+																		?>
+																	</td>
+										
+																	<td colspan="5" class="detailedView_value"><?php
+	
+																		$ocID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["open/closed"], $_SESSION["ReagentPropCategory_Name_ID"]["Classifiers"]);
+																		$openClosed = $rfunc_obj->getPropertyValue($reagentIDToView, $ocID);
+														
+																		$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"]["open/closed"] . $genPostfix , "open/closed", $openClosed, $reagentIDToView, true, "Classifiers");
+
+																		?><div id="oc_warning" style="display:none; color:#FF0000"><P>Please select an Open/Closed value from the dropdown list</div>
+																	</td>
+																</tr> -->
+																<?php 
+															//}	// close "if Insert"
+															
+															?>
+															<tr id="dnaLengthView">
+																<td class="detailedView_colName" style="padding-left:6px; background-color:#C1FFC1; font-size:9pt; font-weight:bold;">
+																	DNA Length:
+																</td>
+												
+																<td class="detailedView_value">
+																	<SPAN style="color:#006400"><?php
+																		echo $insertLength;
+																	?></SPAN> nucleotides
+																</td>
+															</tr>
+
+															<tr id="dnaLengthModify" style="display:none">
+																<td class="detailedView_colName" style="padding-left:6px; background-color:#C1FFC1; font-size:9pt; font-weight:bold;">
+																	DNA Length:
+																</td>
+													
+																<td class="detailedView_value">
+																	<SPAN style="color:#006400"><?php
+																		echo $insertLength;
+																	?></SPAN> nucleotides
+																</td>
+															</tr>
+														</table>	<!-- close insert_sequence_tbl -->
+													</td>
+												</tr>
+											</table>	<!-- close DNA tab!!! -->
+							
+											<!-- Keep format as is, it looks good -->
+											<table ID="proteinSequenceTab" style="display:none">
+												<tr>
+													<td style="padding-left:5px; padding-right:5px; padding-top:3px">
+														<TABLE ID="protein_sequence_table" border="0">
+															<tr>
+																<td colspan="2" style="font-size:9pt; margin-top:5px;  padding-left:10px; font-weight:bold;">
+																	<!-- Caption text edited Sept. 11/08 -->
+																	Translated Protein Sequence of the longest Open Reading Frame (<span style="color:#0000CD">nt <?php echo $protStart . " - " . $protEnd; ?></span>) from cDNA:
+															
+																	<span class="linkExportSequence" style="font-weight:normal; margin-left:15px" onClick="exportProteinSeqToFasta('<?php echo $proteinFastaContent; ?>')">Export to FASTA</span>
+																</td>
+															</tr>
+										
+															<tr>
+																<td colspan="2">
+																<?php
+																	echo "<DIV style=\"margin-top:2px; padding-left:10px;\" class=\"tabSequence\">";
+
+																	echo "<table cellpadding=\"4\" border=\"0\">";
+		
+																	if (strlen($protSeq) > 0)
+																	{
+																		$tmp_protSeq = $rfunc_obj->spaces($protSeq);
+																		$tmp_prot = split("\n", $tmp_protSeq);
+															
+																		foreach ($tmp_prot as $i=>$tok)
+																		{
+																			echo "<TR>";
+
+																			$rowIndex = $i+1;
+																			
+																			if ($i == 0)	// first row
+																			{
+																				$rowStart = 1;
+																			}
+																			else
+																			{
+																				$rowStart = $i*100 + 1;
+																			}
+																			
+																			
+																			// Nov. 3/06 - Output nt count on last line
+																			if ($protLength >= ($rowIndex*100))
+																			{
+																				$rowEnd = $rowIndex*100;
+																			}
+																			else
+																			{
+																				$rowEnd = $protLength;
+																			}
+																			
+																			// July 15/08: Show start position only
+																			echo "<TD nowrap style=\"font-size:10px; font-weight:bold; text-align:right; vertical-align:top\">" . $rowStart . "</TD>";
+														
+																			$tmp_chunks = split(" ", $tok);
+																			foreach ($tmp_chunks as $j=>$chunk)
+																			{
+																				$chunk = trim($chunk);
+														
+																				if (strlen($chunk) > 0)
+																				{
+																					echo "<TD>";
+																						echo "<pre font-size:11px;  text-align:justify>" . $chunk . "</pre>";
+																					echo "</TD>";
+																				}
+																			}
+
+																			echo "</TR>";
+																		}
+																	}
+
+																	echo "</table>";
+
+																	echo "</DIV>";
+																?>
+																</td>
+															</tr>
+										
+															<tr><td colspan="2"></td></tr>
+												
+															<tr><td colspan="2" style="padding-top:4px; color:#0000CD; padding-left:3px; font-weight:bold; font-size:9pt;">Protein Sequence Features:</td></tr>
+												
+															<tr><td colspan="2"></td></tr>
+												
+															<tr>
+																<td class="detailedView_colName" width="150px">Length</td>
+																
+																<td class="detailedView_value" colspan="5"><?php
+
+																	if ($protLength > 0)
+																		echo "<span style=\"color:green;\">" . $protLength . "</span>  amino acids";
+																?></td>
+															</tr>
+												
+															<tr>
+																<td class="detailedView_colName">Frame</td>
+																
+																<td class="detailedView_value">
+																<?php echo $frame; ?>
+																</td>
+															</tr>
+
+															<!-- Jan. 22, 2010: print MW  -->
+															<tr>
+																<td class="detailedView_colName">Molecular Weight</td>
+																
+																<td class="detailedView_value">
+																<?php
+																	if ($protMW && $protMW > 0) echo round($protMW, 2) . " kDa"; ?>
+																</td>
+															</tr>
+
+												
+															<tr><td colspan="2"></td></tr>
+														</table>
+													<td>
+												</tr>
+											</table>
+										</td>
+									</tr>
+			
+									<TR><TD> </TD></TR><?php
+								}	// end if has protein sequence
+								else
+								{
+									?><TR>
+										<TD class="sequenceContent" colspan="2">
+											<?php
+												// DNA SEQUENCE INFO
+												$insertName = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["name"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]));
+
+												// get sequence by ID
+												$seqFunc_obj = new Sequence_Function_Class();
+												$dnaSequence = $seqFunc_obj->findDNASequence($reagentIDToView);
+												
+												if ($dnaSequence)
+												{
+													$sequence = $dnaSequence->getSequence();
+													// echo $sequence;
+
+													// Jan. 25/10
+													$mw = $dnaSequence->getMW();
+													
+													if (!$mw || ($mw == null) || ($mw < 0))
+													{
+														$mw = $rfunc_obj->get_MW($sequence);
+													}
+
+													$tm = $dnaSequence->getTM();
+
+													if (!$tm || ($tm == null) || ($tm < 0))
+													{
+														$tm = $rfunc_obj->calcTemp($sequence);
+													}
+
+													$gc = $dnaSequence->getGC();
+
+													if (!$gc || ($gc == null) || ($gc == 0))
+													{
+														$gc = $rfunc_obj->get_gc_content($sequence);
+													}
+												}
+
+												// Replaced July 13/09
+												$insertLength = strlen(str_replace(" ", "", $sequence));
+												$content = ">" . $limsID . ": " . $insertName . "; length " . $insertLength . '\r' . $sequence . '\r';
+											?>
+											<TABLE ID="sequence_properties_tbl_view">
+												<tr>
+													<td colspan="2" style="padding-left:10px; padding-right:10px; white-space:nowrap;">
+														<span ID="exportDNASeqFasta" style="font-weight:normal; padding-top:0" class="linkExportSequence" onClick="exportDNASeqToFasta('<?php echo str_replace("'", "\'", $content); ?>')">Export to FASTA</span>
+							
+														<span ID="viewRestrMap" class="linkExportSequence" style="padding-left:7px; font-weight:normal;" onClick="document.restriction_map_insert.submit()">Restriction Map</span>
+
+														<!-- March 19, 2010: Print Oligos for Vector -->
+														<!-- Correction Aug. 18, 2010: DON'T print sequencing primers for other reagent types!!!!!!!!!! -->
+														<?php
+															if ($reagentType == $_SESSION["ReagentType_Name_ID"]["Vector"])
+															{
+																?><span ID="viewOligos" class="linkExportSequence" style="font-weight:normal; padding-left:7px;" onClick="document.vector_oligos_form.submit()">Sequencing Primers</span><?php
+
+																//echo "<IMG SRC=\"pictures/new01.gif\" ALT=\"new\" WIDTH=\"35\" HEIGHT=\"20\" style=\"cursor:auto\">";
+															}
+														?>
+													</td>
+												</tr>
+			
+												<tr>
+													<td colspan="6">
+														<?php
+															echo "<DIV class=\"tabSequence\" style=\"margin-top:4px;\">";
+																$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"]["sequence"] . $genPostfix , "sequence", $sequence, $reagentIDToView, false, "DNA Sequence");
+															echo "</DIV>";
+														?>
+													</td>
+												</tr>
+								
+												<tr><td colspan="6" style="padding-top:4px"></td></tr>
+												
+												<tr>
+													<td class="detailedView_colName" style="padding-left:6px;">
+														DNA Length:
+													</td>
+										
+													<td class="detailedView_value">
+									
+														<SPAN style="color:#006400"><?php
+															echo $insertLength;
+														?></SPAN> nucleotides
+													</td>
+												</tr>
+										
+												<tr id="dnaLengthModify" style="display:none">
+													<td class="detailedView_colName" style="padding-left:6px;">
+														DNA Length:
+													</td>
+										
+													<td class="detailedView_value">
+									
+														<SPAN style="color:#006400"><?php
+															echo $insertLength;
+														?></SPAN> nucleotides
+													</td>
+												</tr>
+
+												<tr><td colspan="6"></td></tr>
+												<?php
+
+//												echo "</FORM>";
+											
+												if ($rfunc_obj->hasAttribute($reagentType, "molecular weight", $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]))
+												{
+													// get MW and Tm for Oligo - Jan. 25/10: no, compute from sequence
+													?><tr>
+														<td class="detailedView_colName" style="padding-left:6px;">Molecular Weight:</td>
+											
+														<td class="detailedView_value"><?php 
+															if ($mw && ($mw > 0))
+																echo round($mw, 2) . " g/mol";
+														?></td>
+													</tr><?php
+												}
+
+												if ($rfunc_obj->hasAttribute($reagentType, "melting temperature", $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]))
+												{
+													?><tr>
+														<td class="detailedView_colName" style="padding-left:6px;">Melting Temperature:</td>
+											
+														<td class="detailedView_value"><?php
+															if ($tm && ($tm > 0))
+																echo $tm . " °C";
+														?></td>
+													</tr><?php
+												}
+
+												if ($rfunc_obj->hasAttribute($reagentType, "gc content", $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]))
+												{
+													$gc_content = $rfunc_obj->get_gc_content($sequence);
+
+													?><tr>
+														<td class="detailedView_colName" style="padding-left:6px;">GC content:</td>
+											
+														<td class="detailedView_value"><?php
+															if ($gc_content && ($gc_content > 0))
+																echo $gc_content . " %";
+														?></td>
+													</tr><?php
+												}
+
+												?><tr><td colspan="6"></td></tr><?php
+
+												// April 19, 2011
+												$all_attributes = $rfunc_obj->getReagentTypeAttributesByCategory($reagentType, $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+
+												// May 5, 2010: keys are now attribute IDs
+												foreach ($all_attributes as $attrID => $attribute)
+												{
+													$pName = $attribute->getPropertyName();
+
+													if (($pName != "sequence") && ($pName != "melting temperature") && ($pName != "molecular weight") && ($pName != "gc content") && ($pName != "length"))
+													{
+														// echo $pName . "<BR>";
+
+														$p_id = $_SESSION["ReagentProp_Name_ID"][$pName];
+
+														$pcID = $rfunc_obj->getPropertyIDInCategory($p_id, $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+
+														// only printing properties whose values are filled in
+														if (in_array($pcID, array_keys($r_props)))
+														{
+															$props = $r_props[$pcID];
+
+															if (count($props) == 1)
+															{
+																$prop = $props[0];
+
+																$propval = "";
+						
+																$propName = $prop->getPropertyName();
+																$propDescr = $prop->getPropertyDescription();
+																$propval = $prop->getPropertyValue();
+
+																echo "<TR ID=\"" . $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"] . "\">";
+
+																echo "<TD class=\"detailedView_colName\" style=\"font-weight:bold;\">" . $propDescr . ":</TD>";
+																	echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";		
+																		$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"][$propName] . $genPostfix, $propName, $propval, $reagentIDToView, false, "DNA Sequence");
+																	echo "</TD>";
+																echo "</TR>";
+															}
+															else
+															{
+																// Property with multiple values, e.g. a multiple dropdown
+																$pVals = Array();
+
+																foreach ($props as $pkey => $a_prop)
+																{
+																	$pVals[$pcID][] = $a_prop->getPropertyValue();
+																}
+
+																$pID = $rfunc_obj->findPropertyInCategoryID($pcID);
+							
+																$propName = $_SESSION["ReagentProp_ID_Name"][$pID];
+																$propDescr = $_SESSION["ReagentProp_ID_Desc"][$pID];
+																
+																echo "<TR ID=\"" . $_SESSION["ReagentPropCategory_Name_Alias"]["DNA Sequence"] . "\">";
+																	echo "<TD class=\"detailedView_colName\" style=\"font-weight:bold;\">" . $propDescr . ":</td>";
+
+																	echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+																		$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"][$propName] . $genPostfix, $propName, $pVals[$pcID], $reagentIDToView, false, "DNA Sequence");
+																	echo "</TD>";
+																echo "</TR>";															
+															}
+														}
+													}
+												}
+										?></table>
+
+										<TABLE ID="sequence_properties_tbl_modify" style="display:none">
+											<tr>
+												<td colspan="6">	<!-- keep colspan!-->
+													<?php
+														// Feb 28/08 - Sequence in Modify mode - hidden
+														echo "<DIV style=\"margin-top:4px;\">";
+
+														$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"]["sequence"] . $genPostfix , "sequence", $sequence, $reagentIDToView, true, "DNA Sequence");
+
+														echo "</DIV>";
+													?>
+												</td>
+											</tr>
+											<?php
+
+										$all_attributes = $rfunc_obj->getReagentTypeAttributesByCategory($reagentType, $categoryID);
+
+										// May 5, 2010: keys are now attribute IDs
+										foreach ($all_attributes as $attrID => $attribute)
+										{
+											$pName = $attribute->getPropertyName();
+
+											if (($pName != "sequence") && ($pName != "melting temperature") && ($pName != "molecular weight") && ($pName != "gc content") && ($pName != "length"))
+											{
+												$p_id = $_SESSION["ReagentProp_Name_ID"][$pName];
+
+												$pcID = $rfunc_obj->getPropertyIDInCategory($p_id, $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+
+												if (in_array($pcID, array_keys($r_props)))
+												{
+													$props = $r_props[$pcID];
+
+													if (count($props) == 1)
+													{
+														$prop = $props[0];
+														
+														$propName = "";
+														$propDescr = "";
+														$propval = "";
+				
+														$propName = $prop->getPropertyName();
+
+														$propDescr = $prop->getPropertyDescription();
+														$propval = $prop->getPropertyValue();
+
+														echo "<TR>";
+
+															echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $propDescr . "</TD>";
+															
+															echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";	
+															
+																$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"][$propName] . $genPostfix, $propName, $propval, $reagentIDToView, true, "DNA Sequence");
+															
+															echo "</TD>";
+
+														echo "</TR>";
+													}
+													else
+													{
+														$pVals = Array();
+
+														foreach ($props as $pkey => $a_prop)
+														{
+															$pVals[] = $a_prop->getPropertyValue();
+														}
+//print_r($pVals);
+														$pID = $rfunc_obj->findPropertyInCategoryID($pcID);
+					
+														$propName = $_SESSION["ReagentProp_ID_Name"][$pID];
+
+														$propDescr = $_SESSION["ReagentProp_ID_Desc"][$pID];
+
+														echo "<TR>";
+															echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $propDescr . ":</TD>";
+
+															echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+																$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"][$propName] . $genPostfix, $propName, $pVals, $reagentIDToView, true, "DNA Sequence");
+															echo "</TD>";
+														echo "</TR>";
+													}
+												}
+												else
+												{
+													$tmp_propID = $rfunc_obj->findPropertyInCategoryID($pcID);
+													$tmp_propDescr = $_SESSION["ReagentProp_ID_Desc"][$tmp_propID];
+													$tmp_propName = $_SESSION["ReagentProp_ID_Name"][$tmp_propID];
+			
+													if (strcasecmp($tmp_propName, "protein translation") != 0)
+													{
+														$tmp_propAlias = $_SESSION["ReagentProp_Name_Alias"][$tmp_propName];
+				
+														echo "<TR>";
+															echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $tmp_propDescr . "</TD>";
+				
+															echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+																$this->print_property_final($genPrefix . $tmp_propAlias . $genPostfix , $tmp_propName, "", $reagentIDToView, true, "DNA Sequence");
+															echo "</TD>";
+														echo "</TR>";
+													}
+												}										
+											}
+										}
+										?></table>
+										</td>
+									</tr><?php
+								}
+		
+								echo "<TR><TD> </TD></TR>";
+							?></table>
+					</td>
+				</tr><?php
+			}
+			// Aug. 13/09: Different sequence types
+			else if ( (strcasecmp($category, "Protein Sequence") == 0) && $rfunc_obj->hasAttribute($reagentType, "protein sequence", $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]))
+			{
+				// June 18, 2010
+				$propsList = $rfunc_obj->findReagentPropertiesByCategory($reagentIDToView, $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]);
+
+				echo "<TR><TD colspan=\"3\" style=\"padding-right:5px;\"> </TD></TR>";
+			
+				?>
+				<TR>
+					<TD>
+						<TABLE class="detailedView_tbl" style="width:725px; border:1px outset; padding:6px;">
+							<tr ID="other_reagent_sequence_tbl_view">
+								<td class="detailedView_heading" style="text-align:left; padding-left:5px; font-weight:bold; color:blue;">			
+									Protein Sequence Information  
+
+									<td class="detailedView_heading" style="text-align:right; padding-right:6px; padding-top:0; color:#000000; font-size:10pt; font-family:Helvetica; white-space:nowrap;"><?php
+
+									if ($modify_restricted)
+										$modify_disabled = "DISABLED";
+
+									// "Modify" button
+									echo "<INPUT TYPE=\"BUTTON\" ID=\"edit_reagent_" . $categoryAlias . "\" style=\"margin-left:10px; font-weight:bold; font-size:8pt;\" " . $modify_disabled . "  VALUE=\"Edit Sequence\" onClick=\"toggleReagentEditModify('edit', 'protein_sequence_properties', '" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType]) . "');\"></INPUT>";
+
+									// "Save" and "Cancel" buttons
+									echo "<DIV ID=\"sequenceButtons\" style=\"display:none\">";
+										echo "<INPUT TYPE=\"BUTTON\" ID=\"save_reagent_" . $categoryAlias . "\" style=\"margin-left:10px; font-weight:bold; font-size:8pt;\" " . $modify_disabled . " VALUE=\"Save\" onClick=\"selectAllPropertyValues(); document.pressed = this.value; toggleReagentEditModify('save', '" . $categoryAlias . "', '" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType]) . "');\"></INPUT>";
+
+										echo "<INPUT TYPE=\"BUTTON\" ID=\"cancel_save_" . $categoryAlias . "\" style=\"margin-left:10px; font-weight:bold; font-size:8pt;\" " . $modify_disabled . "  VALUE=\"Cancel\" onClick=\"document.pressed = this.value; toggleReagentEditModify('cancel', '" . $categoryAlias . "', '" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType]) . "');\"></INPUT>";
+									echo "</DIV>";
+									?>
+								</td>
+							</tr>
+
+							<TR ID="protSequenceContent">
+								<TD>
+								<?php
+
+									// Protein SEQUENCE INFO
+									$insertName = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["name"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]));
+							
+									// get sequence by ID
+									$seqFunc_obj = new Sequence_Function_Class();
+									$protSequence = $seqFunc_obj->findProteinSequence($reagentIDToView);
+
+									if ($protSequence)
+									{
+										$protSeq = $protSequence->getSequence();
+
+										// Jan. 25/10
+										$protMW = $protSequence->getMW();
+
+										if (!$protMW || ($protMW == null) || ($protMW < 0))
+										{
+											$protMW = $rfunc_obj->computeProteinMW($protSeq);
+										}
+									}
+
+									$protLength = strlen(str_replace(" ", "", $protSeq));
+
+									$proteinFastaContent = ">" . $limsID . ": " . $insertName . "; length " . $protLength . '\r' . $protSeq . '\r';
+
+									?><span class="linkExportSequence" style="font-weight:normal;" onClick="exportProteinSeqToFasta('<?php echo $proteinFastaContent; ?>')">Export to FASTA</span>
+								</td>
+							</tr>
+											
+							<tr>
+								<td colspan="2">											
+									<table ID="protein_sequence_properties_tbl_view">
+										<tr>
+											<td colspan="6"><?php
+												echo "<DIV style=\"margin-top:2px; padding-left:10px;\" class=\"tabSequence\">";
+
+												echo "<table cellpadding=\"4\" border=\"0\">";
+
+												if (strlen(str_replace(" ", "", trim($protSeq))) > 0)
+												{
+													$tmp_protSeq = $rfunc_obj->spaces($protSeq);
+													$tmp_prot = split("\n", $tmp_protSeq);
+											
+													foreach ($tmp_prot as $i=>$tok)
+													{
+														echo "<TR>";
+															$rowIndex = $i+1;
+															
+															if ($i == 0)	// first row
+															{
+																$rowStart = 1;
+															}
+															else
+															{
+																$rowStart = $i*100 + 1;
+															}
+															
+															
+															// Nov. 3/06 - Output nt count on last line
+															if ($protLength >= ($rowIndex*100))
+															{
+																$rowEnd = $rowIndex*100;
+															}
+															else
+															{
+																$rowEnd = $protLength;
+															}
+															
+															// July 15/08: Show start position only
+															echo "<TD nowrap style=\"font-size:10px; font-weight:bold; text-align:right; vertical-align:top\">" . $rowStart . "</TD>";
+										
+															$tmp_chunks = split(" ", $tok);
+											
+															foreach ($tmp_chunks as $j=>$chunk)
+															{
+																$chunk = trim($chunk);
+										
+																if (strlen($chunk) > 0)
+																{
+																	echo "<TD>";
+																		echo "<pre font-size:11px;  text-align:justify>" . $chunk . "</pre>";
+																	echo "</TD>";
+																}
+															}
+									
+														echo "</TR>";
+													}
+												}
+
+												echo "</div>";
+												echo "</TABLE>";
+											?></td>
+										</tr>
+
+										<!-- print the rest of Protein sequence properties in 'view' state -->
+
+										<!-- Sequence length first -->
+										<TR>
+											<td class="detailedView_colName" style="padding-left:15px;">Length:</td>
+											
+											<td class="detailedView_value">
+												<?php 
+													echo $protLength . " aa";
+												?>
+											</td>
+										</tr>
+										<?php
+
+										// May 2, 2011: Sort properties in order
+										$psorted = Array();
+		
+										sort(array_values($tmp_order_list));
+
+										foreach ($tmp_order_list as $pcID => $pOrd)
+										{
+											$tmp_sorted = Array();
+											$tmp_sorted = $psorted[$pOrd];
+											$tmp_sorted[] = $pcID;
+											$psorted[$pOrd] = $tmp_sorted;
+										}
+
+									// May 5, 2010: keys are now attribute IDs
+									$categoryID = $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"];
+
+									$all_attributes = $rfunc_obj->getReagentTypeAttributesByCategory($reagentType, $categoryID);
+
+									foreach ($all_attributes as $attrID => $attribute)
+									{
+										$pName = $attribute->getPropertyName();
+
+										if (($pName != "protein sequence") && ($pName != "length"))
+										{
+											$p_id = $_SESSION["ReagentProp_Name_ID"][$pName];
+
+											$pcID = $rfunc_obj->getPropertyIDInCategory($p_id, $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]);
+
+											$r_props = $propsList[$pcID];
+
+											$pVals = Array();
+
+											foreach ($r_props as $pkey => $a_prop)
+											{
+												$pVals[] = $a_prop->getPropertyValue();
+											}
+
+											if (count($pVals) == 1)
+												$pVals = $pVals[0];
+
+											$pID = $rfunc_obj->findPropertyInCategoryID($pcID);
+
+											$propName = $_SESSION["ReagentProp_ID_Name"][$pID];
+
+											$propDescr = $_SESSION["ReagentProp_ID_Desc"][$pID];
+
+											if ($pVals && $pVals != "" && count($pVals) > 0)
+											{
+												echo "<TR>";
+													echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $propDescr . ":</TD>";
+
+													echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+														$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"][$propName] . $genPostfix, $propName, $pVals, $reagentIDToView, false, "Protein Sequence", "", "", $reagentType, false, "", 0, 0, true, false, false, false);
+													echo "</TD>";
+												echo "</TR>";
+											}
+										}
+									}
+
+									?>
+									</table>
+
+									<table style="display:none;" ID="protein_sequence_properties_tbl_modify">
+										<tr>
+											<td colspan="5"><?php
+												echo "<DIV style=\"margin-top:4px;\">";
+													$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"]["protein sequence"] . $genPostfix , "protein sequence", $protSeq, $reagentIDToView, true, "Protein Sequence", "", "", $reagentType, false, "", 0, 0, true, false, false, false);
+												echo "</DIV>";
+											?></td>
+										</tr><?php
+
+										// May 2, 2011: Sort properties in order
+										$psorted = Array();
+		
+										sort(array_values($tmp_order_list));
+
+										foreach ($tmp_order_list as $pcID => $pOrd)
+										{
+											$tmp_sorted = Array();
+											$tmp_sorted = $psorted[$pOrd];
+											$tmp_sorted[] = $pcID;
+											$psorted[$pOrd] = $tmp_sorted;
+										}
+
+										// May 5, 2010: keys are now attribute IDs
+										$categoryID = $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"];
+
+										$all_attributes = $rfunc_obj->getReagentTypeAttributesByCategory($reagentType, $categoryID);
+
+										foreach ($all_attributes as $attrID => $attribute)
+										{
+											$pName = $attribute->getPropertyName();
+
+											if (($pName != "protein sequence") && ($pName != "molecular weight") && ($pName != "length"))
+											{
+												$p_id = $_SESSION["ReagentProp_Name_ID"][$pName];
+
+												$pcID = $rfunc_obj->getPropertyIDInCategory($p_id, $_SESSION["ReagentPropCategory_Name_ID"]["Protein Sequence"]);
+
+												$r_props = $propsList[$pcID];
+
+												$pVals = Array();
+
+												foreach ($r_props as $pkey => $a_prop)
+												{
+													$pVals[] = $a_prop->getPropertyValue();
+												}
+
+												if (count($pVals) == 1)
+													$pVals = $pVals[0];
+
+												$pID = $rfunc_obj->findPropertyInCategoryID($pcID);
+
+												$propName = $_SESSION["ReagentProp_ID_Name"][$pID];
+
+												$propDescr = $_SESSION["ReagentProp_ID_Desc"][$pID];
+											
+												echo "<TR>";
+													echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $propDescr . ":</TD>";
+
+													echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+													
+														$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"][$propName] . $genPostfix, $propName, $pVals, $reagentIDToView, true, "Protein Sequence", "", "", $reagentType, false, "", 0, 0, true, false, false, false);
+													echo "</TD>";
+												echo "</TR>";
+											
+											}
+										}
+
+										?><tr><td colspan="6"></td></tr>
+									</table>
+								</td>
+							</tr>			
+						</TABLE>
+					</TD>
+				</TR>
+				<?php
+			}
+			// Update Dec. 4/09: if there is no sequence at all, the 'else' would output 'RNA'!!
+			else if ( (strcasecmp($category, "RNA Sequence") == 0) && $rfunc_obj->hasAttribute($reagentType, "rna sequence", $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence"]))
+			{
+				// June 18, 2010
+				$propsList = $rfunc_obj->findReagentPropertiesByCategory($reagentIDToView, $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence"]);
+
+				#print_r($propsList);
+
+				echo "<TR><TD colspan=\"3\" style=\"padding-right:5px;\"> </TD></TR>";
+			
+				?><tr>
+					<TD colspan="2">
+						<TABLE class="detailedView_tbl" style="width:100%; border:1px outset; padding:6px; background:#FFF8DC;" style="border: 1px solid black;">
+							<tr ID="other_reagent_sequence_tbl_view">
+								<td class="detailedView_heading" style="text-align:left; padding-left:5px; font-weight:bold; color:blue;">
+									RNA Sequence Information
+
+									<td class="detailedView_heading" style="text-align:right; padding-right:6px; padding-top:0; color:#000000; font-size:10pt; font-family:Helvetica; white-space:nowrap;"><?php
+		
+									if ($modify_restricted)
+										$modify_disabled = "DISABLED";
+		
+									// "Modify" button
+									echo "<INPUT TYPE=\"BUTTON\" ID=\"edit_reagent_" . $categoryAlias . "\" style=\"margin-left:10px; font-weight:bold; font-size:8pt;\" " . $modify_disabled . "  VALUE=\"Edit Sequence\" onClick=\"toggleReagentEditModify('edit', 'rna_sequence_properties', '" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType]) . "');\"></INPUT>";
+
+									// "Save" and "Cancel" buttons
+									echo "<DIV ID=\"sequenceButtons\" style=\"display:none\">";
+										echo "<INPUT TYPE=\"BUTTON\" ID=\"save_reagent_" . $categoryAlias . "\" style=\"margin-left:10px; font-weight:bold; font-size:8pt;\" " . $modify_disabled . " VALUE=\"Save\" onClick=\"selectAllPropertyValues(); document.pressed = this.value; toggleReagentEditModify('save', '" . $categoryAlias . "', '" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType]) . "');\"></INPUT>";
+
+										echo "<INPUT TYPE=\"BUTTON\" ID=\"cancel_save_" . $categoryAlias . "\" style=\"margin-left:10px; font-weight:bold; font-size:8pt;\" " . $modify_disabled . "  VALUE=\"Cancel\" onClick=\"document.pressed = this.value; toggleReagentEditModify('cancel', '" . $categoryAlias . "', '" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType]) . "');\"></INPUT>";
+									echo "</DIV>";
+									?>
+								</td>
+							</tr>
+
+							<TR>
+								<TD class="rnaSequenceContent" colspan="2"><?php
+
+									// RNA SEQUENCE INFO
+									$insertName = $rfunc_obj->getPropertyValue($reagentIDToView, $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["name"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]));
+							
+									// get sequence by ID
+									$seqFunc_obj = new Sequence_Function_Class();
+									$rnaSequence = $seqFunc_obj->findRNASequence($reagentIDToView);
+// 									print_r($rnaSequence);
+									if ($rnaSequence)
+									{
+										$rnaSeq = $rnaSequence->getSequence();
+
+										// Jan. 25/10
+										$rnaMW = $rnaSequence->getMW();
+										
+										/* April 14, 2011: no, don't calculate any of those for RNA
+										if (!$rnaMW || ($rnaMW == null) || ($rnaMW < 0))
+										{
+											$rnaMW = $rfunc_obj->getRNA_MW($rnaSeq);
+										}
+
+										$rna_tm = $rnaSequence->getTM();
+
+										if (!$rna_tm || ($rna_tm == null) || ($rna_tm < 0))
+										{
+											$rna_tm = $rfunc_obj->calcTemp($rnaSeq);
+										}
+										*/
+									}
+
+									// Replaced July 13/09
+									$rnaLength = strlen(str_replace(" ", "", $rnaSeq));
+									$rnaFastaContent = ">" . $limsID . ": " . $insertName . "; length " . $rnaLength . '\r' . trim($rnaSeq) . '\r';
+
+									?><TABLE ID="rna_sequence_table" border="0">
+										<tr>
+											<td colspan="6" style="font-size:9pt; margin-top:5px; padding-left:2px; font-weight:bold;">
+
+												<span class="linkExportSequence" style="font-weight:normal;" onClick="exportRNASeqToFasta('<?php echo $rnaFastaContent; ?>')">Export to FASTA</span>
+											</td>
+										</tr>
+								
+										<tr>
+											<td colspan="2">												
+												<table ID="rna_sequence_properties_tbl_view">
+													<tr>
+														<td colspan="6"><?php
+															echo "<DIV style=\"margin-top:2px; padding-left:10px;\" class=\"tabSequence\">";
+
+															echo "<table cellpadding=\"4\" border=\"0\">";
+
+															if (strlen(str_replace(" ", "", trim($rnaSeq))) > 0)
+															{
+																$tmp_rnaSeq = $rfunc_obj->spaces($rnaSeq);
+																$tmp_rna = split("\n", $tmp_rnaSeq);
+														
+																foreach ($tmp_rna as $i=>$tok)
+																{
+																	echo "<TR>";
+																		$rowIndex = $i+1;
+																		
+																		if ($i == 0)	// first row
+																		{
+																			$rowStart = 1;
+																		}
+																		else
+																		{
+																			$rowStart = $i*100 + 1;
+																		}
+																		
+																		
+																		// Nov. 3/06 - Output nt count on last line
+																		if ($rnaLength >= ($rowIndex*100))
+																		{
+																			$rowEnd = $rowIndex*100;
+																		}
+																		else
+																		{
+																			$rowEnd = $rnaLength;
+																		}
+																		
+																		// July 15/08: Show start position only
+																		echo "<TD nowrap style=\"font-size:10px; font-weight:bold; text-align:right; vertical-align:top\">" . $rowStart . "</TD>";
+													
+																		$tmp_chunks = split(" ", $tok);
+														
+																		foreach ($tmp_chunks as $j=>$chunk)
+																		{
+																			$chunk = trim($chunk);
+													
+																			if (strlen($chunk) > 0)
+																			{
+																				echo "<TD>";
+																					echo "<pre font-size:11px;  text-align:justify>" . $chunk . "</pre>";
+																				echo "</TD>";
+																			}
+																		}
+												
+																	echo "</TR>";
+																}
+															}
+
+															echo "</table>";
+
+															echo "</DIV>";
+														?>
+														</td>
+													</tr>
+
+													<!-- print the rest of RNA sequence properties in 'view' state -->
+
+													<!-- Sequence length first -->
+													<TR>
+														<td class="detailedView_colName" style="padding-left:15px;">Length:</td>
+														
+														<td class="detailedView_value">
+															<?php 
+																echo $rnaLength . " nt";
+															?>
+														</td>
+													</tr>
+													<?php
+														
+														// May 2, 2011: Sort properties in order
+														$psorted = Array();
+						
+														sort(array_values($tmp_order_list));
+
+														foreach ($tmp_order_list as $pcID => $pOrd)
+														{
+															$tmp_sorted = Array();
+															$tmp_sorted = $psorted[$pOrd];
+															$tmp_sorted[] = $pcID;
+															$psorted[$pOrd] = $tmp_sorted;
+														}
+
+													// May 5, 2010: keys are now attribute IDs
+													$categoryID = $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence"];
+
+													$all_attributes = $rfunc_obj->getReagentTypeAttributesByCategory($reagentType, $categoryID);
+
+													foreach ($all_attributes as $attrID => $attribute)
+													{
+														$pName = $attribute->getPropertyName();
+
+														if (($pName != "rna sequence") && ($pName != "gc content") && ($pName != "length"))
+														{
+														//	echo $pName;
+
+															$p_id = $_SESSION["ReagentProp_Name_ID"][$pName];
+
+															$pcID = $rfunc_obj->getPropertyIDInCategory($p_id, $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence"]);
+
+															$r_props = $propsList[$pcID];
+
+															//print_r($r_props);
+
+															$pVals = Array();
+
+															foreach ($r_props as $pkey => $a_prop)
+															{
+																$pVals[] = $a_prop->getPropertyValue();
+															}
+
+															if (count($pVals) == 1)
+																$pVals = $pVals[0];
+
+															$pID = $rfunc_obj->findPropertyInCategoryID($pcID);
+
+															$propName = $_SESSION["ReagentProp_ID_Name"][$pID];
+
+															$propDescr = $_SESSION["ReagentProp_ID_Desc"][$pID];
+
+															if ($pVals && $pVals != "" && count($pVals) > 0)
+															{
+																echo "<TR>";
+																	echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $propDescr . ":</TD>";
+
+																	echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+																	
+																		$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"][$propName] . $genPostfix, $propName, $pVals, $reagentIDToView, false, "RNA Sequence", "", "", $reagentType, false, "", 0, 0, false, true, false, false);
+
+																	echo "</TD>";
+																echo "</TR>";
+															}
+														}
+													}
+
+													?>
+												</table>									
+												
+												<table ID="rna_sequence_properties_tbl_modify" style="display:none;">
+												<?php
+													
+													// sequence first
+													echo "<tr>";
+														echo "<td colspan=\"6\">";
+															echo "<DIV style=\"margin-top:2px; padding-left:10px;\" class=\"tabSequence\">";
+																$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"]["rna sequence"] . $genPostfix, "rna sequence", $rnaSeq, $reagentIDToView, true, "RNA Sequence", "", "", $reagentType, false, "", 0, 0, false, true, false, false);
+															echo "</DIV>";
+														echo "</td>";
+													echo "</tr>";
+													
+													$categoryID = $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence"];
+
+													$all_attributes = $rfunc_obj->getReagentTypeAttributesByCategory($reagentType, $categoryID);
+
+													// May 5, 2010: keys are now attribute IDs
+													foreach ($all_attributes as $attrID => $attribute)
+													{
+														$pName = $attribute->getPropertyName();
+
+														if (($pName != "rna sequence") && ($pName != "gc content") && ($pName != "length"))
+														{
+												
+															$p_id = $_SESSION["ReagentProp_Name_ID"][$pName];
+
+															$pcID = $rfunc_obj->getPropertyIDInCategory($p_id, $_SESSION["ReagentPropCategory_Name_ID"]["RNA Sequence"]);
+
+															$r_props = $propsList[$pcID];
+
+															//print_r($r_props);
+
+															$pVals = Array();
+
+															foreach ($r_props as $pkey => $a_prop)
+															{
+																$pVals[] = $a_prop->getPropertyValue();
+															}
+
+											//	print_r($pVals);
+
+															if (count($pVals) == 1)
+																$pVals = $pVals[0];
+
+															$pID = $rfunc_obj->findPropertyInCategoryID($pcID);
+
+															$propName = $_SESSION["ReagentProp_ID_Name"][$pID];
+
+															$propDescr = $_SESSION["ReagentProp_ID_Desc"][$pID];
+
+															echo "<TR>";
+																echo "<TD class=\"detailedView_colName\" style=\"padding-left:15px; font-weight:bold;\">" . $propDescr . ":</TD>";
+
+																echo "<TD colspan=\"4\" class=\"detailedView_value\" style=\"white-space:normal;\">";
+																
+																	$this->print_property_final($genPrefix . $_SESSION["ReagentProp_Name_Alias"][$propName] . $genPostfix, $propName, $pVals, $reagentIDToView, true, "RNA Sequence", "", "", $reagentType, false, "", 0, 0, false, true, false, false);
+																echo "</TD>";
+															echo "</TR>";
+														}
+													}
+												?></table>
+											</td>
+										</tr>		
+									</table>
+								<td>
+							</tr>
+						</table>
+					<!-- </td>
+				</tr> -->
+				<?php
+			}
+			
+			// 'switch' was here - removed June 23/09, look in SVN if anything
+			?>
+			</FORM>
+			<?php
+		}
+
+		?>
+		<!-- Export sequence to FASTA -->
+		<form id="export_dna_sequence_form" name="dna_sequence_export" action="Reagent/fasta.php" method="POST">
+			<input type="hidden" name="filename" value="<?php echo $limsID . "_DNA"; ?>"/>
+			<input type="hidden" id="dna_fasta_content" name="dnaFastaContent" value="<?php echo $content; ?>" />
+			<input type="hidden" id="currDNAExportSelection" name="curr_export_sel" value="DNA">
+		</form>
+		
+		<form id="export_protein_sequence_form" name="protein_sequence_export" action="Reagent/fasta.php" method="POST">
+			<input type="hidden" name="filename" value="<?php echo $limsID . "_PEP"; ?>"/>
+			<input type="hidden" id="protein_fasta_content" name="protFastaContent" value="<?php echo $proteinFastaContent; ?>" />
+			<input type="hidden" id="currProteinExportSelection" name="curr_export_sel" value="Protein">
+		</form>
+
+		<form id="export_rna_sequence_form" name="rna_sequence_export" action="Reagent/fasta.php" method="POST">
+			<input type="hidden" name="filename" value="<?php echo $limsID . "_RNA"; ?>"/>
+			<input type="hidden" id="rna_fasta_content" name="rnaFastaContent" value="<?php echo $rnaFastaContent; ?>" />
+			<input type="hidden" id="currRNAExportSelection" name="curr_export_sel" value="RNA">
+		</form>
+		
+
+		<form id="restriction_map_vector_form" name="restriction_map_vector" action="<?php echo $cgi_path . "restriction.py"; ?>" method="POST">
+			<input type="hidden" name="limsID" value="<?php echo $limsID; ?>">
+			<input type="hidden" name="vector_sequence" value="<?php echo $sequence; ?>">
+		</form>
+	
+		<!-- Print all Vector frames - Jan. 23/09 -->
+		<form id="vector_frames" name="vector_frames_form" action="<?php echo $cgi_path . "vector_frames.py"; ?>" method="POST">
+			<input type="hidden" name="rID" value="<?php echo $reagentIDToView; ?>">
+			<input type="hidden" name="vector_sequence" value="<?php echo $sequence; ?>">
+			<input type="hidden" name="orf_type">
+		</form>
+
+		<!-- Print all Vector frames - March 19, 2010 -->
+		<form id="vector_oligos" name="vector_oligos_form" action="<?php echo $cgi_path . "vector_oligos.py"; ?>" method="POST">
+			<input type="hidden" name="rID" value="<?php echo $reagentIDToView; ?>">
+			<input type="hidden" name="vector_sequence" value="<?php echo $sequence; ?>">
+		</form>
+
+		<form id="oligos_vector_map" name="oligos_vector_map_form" action="<?php echo $cgi_path . "oligos_vector_map.py"; ?>" method="POST">
+			<input type="hidden" name="rID" value="<?php echo $reagentIDToView; ?>">
+			<input type="hidden" name="user_id_hidden" value="<?php echo $currUserID; ?>">
+			<input type="hidden" name="vector_sequence" value="<?php echo $sequence; ?>">
+		</form>
+
+		<!-- Restriction map -->
+		<form id="restriction_map_insert_form" name="restriction_map_insert" action="<?php echo $cgi_path . "restriction.py"; ?>" method="POST">
+			<input type="hidden" name="limsID" value="<?php echo $limsID; ?>">
+			<input type="hidden" name="insert_sequence" value="<?php echo $sequence; ?>">
+		</form><?php
+
+		// PARENT/CHILD INFO
+		?><tr ID="other_reagent_parents_tbl_view">
+			<td colspan="6" style="padding-top:15px;">
+
+			<input type="hidden" id="vector_cloning_method" name="cloning_method_hidden" value="<?php echo $cloningMethod; ?>">
+			<input type="hidden" id="curr_uname" name="curr_username" value="<?php echo $currUserName; ?>">
+			
+			<!-- Set hidden action identifiers for Python -->
+			<input type="hidden" ID="changeStateVectorIntro" name="change_state">
+			
+				<table style="width:725px; background-color:#FFF8DC; border: 1px outset; margin-top:8px;">
+					<tr>
+						<td colspan="4" class="detailedView_heading" style="text-align:left; padding-left:12px; padding-right:6px; padding-top:10px; font-size:10pt; color:blue; font-weight:bold; white-space:nowrap;">
+							Parent-Child Information
+						</td><?php
+
+							// Dec. 22/09: find cell line type here and don't show Edit button for Parent
+							$clTypePropID = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["cell line type"], $_SESSION["ReagentPropCategory_Name_ID"]["General Properties"]);
+
+							$cellLineType = $rfunc_obj->getPropertyValue($reagentIDToView, $clTypePropID);
+	
+							// July 13/09: don't show Edit Parents section for Parent Vector
+							if (($cloningMethod != 3) && (strtolower($cellLineType) != "parent") && ($_SESSION["ReagentType_ID_Name"][$reagentType] != 'Oligo'))
+							{
+								?><td style="text-align:right; padding-right:12px; color:#000000; font-size:10pt;"><?php
+	
+								if (!$modify_restricted)
+								{
+									// fixed number of parents
+									if (($_SESSION["ReagentType_ID_Name"][$reagentType] == "Vector") || ($_SESSION["ReagentType_ID_Name"][$reagentType] == "CellLine"))
+										echo "<INPUT TYPE=\"BUTTON\" ID=\"editReagentParentsBtn\" style=\"margin-left:8px; font-weight:bold; font-size:8pt;\" VALUE=\"Edit Parents\" onClick=\"document.pressed=this.value; switchReagentParentsModify('" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType]) . "');\"></INPUT>";
+									else
+										echo "<INPUT TYPE=\"BUTTON\" ID=\"editReagentParentsBtn\" style=\"margin-left:8px; font-weight:bold; font-size:8pt;\" VALUE=\"Edit Parents\" onClick=\"document.pressed=this.value; switchReagentParentsModify('" . $reagentType . "');\"></INPUT>";
+
+									// Feb. 5, 2010
+									if ($_SESSION["ReagentType_ID_Name"][$reagentType] != 'CellLine')
+									{
+										// "Save" button - hidden initially
+										$assoc = $rfunc_obj->findReagentTypeAssociations($reagentType);
+
+										echo "<INPUT TYPE=\"BUTTON\" ID=\"saveReagentParentsBtn\" style=\"display:none; margin-left:10px; font-weight:bold; font-size:8pt;\" VALUE=\"Save\" onClick=\"document.pressed=this.value; if (checkParentFormat('" . $_SESSION["ReagentType_ID_Name"][$reagentType] . "')) saveReagentParents('" . str_replace("'", "\'", $_SESSION["ReagentType_ID_Name"][$reagentType]) . "');\"></INPUT>";
+									}
+
+									// Ditto "Cancel" button
+									echo "<INPUT TYPE=\"BUTTON\" ID=\"cancelChangeReagentParents\" style=\"display:none; margin-left:10px; font-weight:bold; font-size:8pt;\" VALUE=\"Cancel\" onClick=\"document.pressed=this.value; cancelReagentParentsModification();\"></INPUT>";
+								}
+								else
+								{
+									// Show disabled "Modify" button
+									echo "<INPUT TYPE=\"BUTTON\" DISABLED style=\"margin-left:10px; font-weight:bold; font-size:8pt;\" VALUE=\"Edit Parents\"></INPUT>";
+								}
+							}
+						?></td>
+					</tr>
+
+					<tr>
+						<td colspan="7"><?php
+							switch ($_SESSION["ReagentType_ID_Name"][$reagentType])
+							{
+								case 'Vector':
+									?><FORM NAME="reagentParentsForm" METHOD="POST" ACTION="<?php echo $cgi_path . "update.py"; ?>">
+						
+									<input type="hidden" ID="changeStateParents" name="change_state">
+									<input type="hidden" name="save_parents">
+									<input type="hidden" ID="rID_hidden" name="reagent_id_hidden" value="<?php echo $reagentIDToView; ?>">
+									<input type="hidden" id="cloning_method" name="cloning_method_hidden" value="<?php echo $cloningMethod; ?>">
+									<input type="hidden" id="curr_uname" name="curr_username" value="<?php echo $currUserName; ?>">
+									<input type="hidden" name="reagent_typeid_hidden" value="<?php echo $reagentType; ?>">
+									<input type="hidden" name="reagent_groupnum_hidden" value="<?php echo $reagentGroup; ?>">
+
+									<table id="showVectorAssoc">
+										<tr>
+											<td colspan="5">
+											<?php
+												$this->printVectorParents($reagentIDToView);
+											?>
+											</TD>
+										</TR>
+										<?php
+											if (count($children) > 0)
+											{
+												?><tr>
+													<td colspan="5" class="detailedView_parents" style="font-style:italic; font-weight:bold; padding-left:25px; padding-top:10px;">
+														<P>Children
+													<td>
+												</tr>
+				
+												<TR>
+													<TD COLSPAN="6" style="padding-top:10px;">
+														<TABLE>
+															<tr><?php
+																$cols = 0;
+																$MAX_COLS = 17;
+
+																foreach (array_unique($childrenTypes) as $key => $value)
+																{
+																	if ($value == 4)
+																		echo "<td style=\"padding-left:40px; width:180px; white-space:nowrap\">Cell Line Children</td>";
+																	else
+																		echo "<td style=\"padding-left:40px; width:180px; white-space:nowrap\">" . $_SESSION["ReagentType_ID_Name"][$value] . " Children</td>";
+																
+																		?><td width="350px">
+																			<SPAN id="show_<?php echo $_SESSION["ReagentType_ID_Name"][$value]; ?>" class="linkShow" onclick="showHideChildren(this.id, '<?php echo $_SESSION["ReagentType_ID_Name"][$value] . "_children"; ?>');">Show Children</SPAN>
+									
+																			<SPAN id="hide_<?php echo $_SESSION["ReagentType_ID_Name"][$value]; ?>" class="linkHide" onclick="showHideChildren(this.id, '<?php echo $_SESSION["ReagentType_ID_Name"][$value] . "_children"; ?>');">Hide Children</SPAN>
+																			  <B>(<?php echo $num_children[$value]; ?>  total)</B>
+																		</td>
+																	</tr>
+								
+																	<tr id="<?php echo $_SESSION["ReagentType_ID_Name"][$value] . "_children"; ?>" style="display:none;">
+																		<td colspan="5">
+																			<div class="children">
+																				<TABLE class="children">
+																					<TR><?php
+
+																					foreach ($children as $aPropID => $childrenIDs)
+																					{
+																						foreach ($childrenIDs as $cKey => $childID)
+																						{
+																							$childTypeID = $gfunc_obj->getTypeID($childID);
+											
+																							if ($childTypeID == $value)
+																							{
+																								if ($cols == $MAX_COLS)
+																								{
+																									echo "</tr><tr>";
+																									$cols = 0;
+																								}
+						
+																								echo "<td>";
+			
+																									$tmpProject = getReagentProjectID($childID);
+																									$userProjects = getAllowedUserProjectIDs($_SESSION["userinfo"]->getUserID());	// redefine here again, b/c before it was defined as *Writeable* projects only
+																							
+																									if (($tmpProject && ($tmpProject > 0)) && (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || in_array($tmpProject, $userProjects)))
+																									{
+																										echo "<a href=\"Reagent.php?View=6&rid=" . $childID . "\">" . $gfunc_obj->getConvertedID_rid($childID) . "</a>  ";
+																									}
+																									else
+																									{
+																										echo "<span class=\"linkDisabled\">" . $gfunc_obj->getConvertedID_rid($childID) . "</span>  ";
+																									}
+
+																								echo "</td>";
+																								$cols++;
+																							}
+																						}
+																					}
+															
+																					?></TR>
+																				</TABLE>
+																			</DIV>
+																		</td>
+																	</tr><?php
+																}
+
+																?>
+																</tr>
+															</TABLE>
+														</TD>
+													</TR><?php
+												}	// end if has children
+												?>
+											</td>
+										</tr>
+									</table>
+					
+									<table id="editVectorAssoc" style="display:none">
+										<tr>
+											<td colspan="5">
+												<?php
+													$this->printForm_Vector_modify_associations($reagentType, $reagentIDToView, $check);
+												?>
+											</td>
+										</tr>
+					
+										<!-- July 8/08 -->
+										<TR><td colspan="5" style="font-weight:bold; padding-top:8px;">Please update the following Vector information:</TD></TR>
+					
+										<tr>
+											<td class="detailedView_colName">
+												Name
+												<span style="font-size:10pt; color:#000000; font-weight:bold">*</span>
+											</td>
+											
+											<td class="detailedView_value">
+											<?php
+												echo "<INPUT type=\"text\" id=\"new_vector_name\" value=\"" . $tempPropHolder_ar[$_SESSION["ReagentProp_Name_ID"]["name"]] . "\"";
+											?>
+											</td>
+										</tr>
+					
+										<tr>
+											<td class="detailedView_colName">Vector Type</td>
+											
+											<td class="detailedView_value">
+											<?php
+												echo "<select id=\"new_vector_type\" size=\"1\">";
+												echo $this->print_Set_Final_Dropdown("vector type", $tempPropHolder_ar[$_SESSION["ReagentProp_Name_ID"]["vector type"]], "General Properties", $reagentType);
+												echo "</select>";
+											?>
+											</td>
+										</tr>
+								
+										<tr>
+											<td class="detailedView_colName">
+												Project ID
+												<span style="font-size:10pt; color:#000000; font-weight:bold">*</span>
+											</td>
+											
+											<td class="detailedView_value">
+											<?php
+												echo "<select id=\"new_packet_id\" size=\"1\">";
+												echo $this->get_Special_Column_Type("packet", "General Properties", $reagentIDToView, "modify");
+												echo "</select>";
+					
+											?>
+											</td>
+										</tr>
+					
+										<tr>
+											<td class="detailedView_colName" nowrap>Functional Description</td>
+								
+											<td class="detailedView_value" colspan="<?php echo $colspan-1; ?>" style="font-weight:bold; font-size:8pt;">
+												<?php
+													echo "<INPUT type=\"text\" id=\"new_description\" value=\"" . $this->get_Special_Column_Type( "description", $reagentIDToView, "None") . "\"";
+												?>
+											</td>
+										</tr>
+							
+										<tr>
+											<td class="detailedView_colName">Verification</td>
+								
+											<td class="detailedView_value" colspan="3">
+											<?php 
+												echo "<select id=\"new_verification\" size=\"1\">";
+												echo $this->print_Set_Final_Dropdown("verification",  $tempPropHolder_ar[$_SESSION["ReagentProp_Name_ID"]["verification"]], "General Properties", $reagentType);
+												echo "</select>";
+											?>
+											</td>
+										</tr>
+									</table>
+
+									<!-- Hidden parent input values -->
+									<input type="hidden" id="pv_id_hidden" name="assoc_parent_vector">
+									<input type="hidden" id="insert_id_hidden" name="assoc_insert_id">
+									<input type="hidden" id="ipv_id_hidden" name="assoc_parent_insert_vector">
+									<?php
+										$old_pv_id = $bfunc_obj->get_Background_rid($reagentIDToView, "vector parent id");
+							
+										// Sept. 12/07: Remember old IPV and Insert values too
+										$old_insert_id = $bfunc_obj->get_Background_rid($reagentIDToView, "insert id");
+										$old_ipv_id = $bfunc_obj->get_Background_rid($reagentIDToView, "parent insert vector");
+										
+										$old_insert = $gfunc_obj->getConvertedID_rid($old_insert_id);
+										$old_ipv = $gfunc_obj->getConvertedID_rid($old_ipv_id);
+							
+										if (isset($_POST["pv_name_txt"]))
+											$old_pv = $_POST["pv_name_txt"];
+										else
+											$old_pv = $gfunc_obj->getConvertedID_rid($old_pv_id);
+							
+										if (isset($_POST["change_vp_id"]) && ($_POST["change_vp_id"] == "Change"))
+											$change = 1;
+										else
+											$change = 0;
+									?>
+									<input type="hidden" id="parent_vector_old_id" name="detailed_view_pv_backfillID_old" value="<?php echo $old_pv; ?>">
+									<input type="hidden" id="change_pv" name="change_vp_flag" value="<?php echo $change; ?>">
+							
+									<!-- Added Sept. 12/07, Marina -->
+									<input type="hidden" id="insert_old_id" name="detailed_view_insert_backfillID_old" value="<?php echo $old_insert; ?>">
+							
+									<!-- Nov. 16/07: Static values -->
+									<input type="hidden" id="pv_original" value="<?php echo $old_pv; ?>">
+									<input type="hidden" id="insert_original" value="<?php echo $old_insert; ?>">
+									<input type="hidden" id="ipv_original" value="<?php echo $old_ipv; ?>">
+							
+									<input type="hidden" id="ipv_old_id" name="detailed_view_ipv_backfillID_old" value="<?php echo $old_ipv; ?>">
+
+									</FORM><?php
+								break;
+					
+								case 'CellLine':
+									$bfunc_obj = new Reagent_Background_Class();
+									$gfunc_obj = new generalFunc_Class();
+									
+									$old_pv_id = $bfunc_obj->get_Background_rid($reagentIDToView, "cell line parent vector id");
+									$old_cl_id = $bfunc_obj->get_Background_rid($reagentIDToView, "parent cell line id");
+									
+									if (isset($_POST["pv_name_txt"]))
+										$old_pv = $_POST["pv_name_txt"];
+									else
+										$old_pv = $gfunc_obj->getConvertedID_rid($old_pv_id);
+									
+									if (isset($_POST["cl_name_txt"]))
+										$old_cl = $_POST["cl_name_txt"];
+									else
+										$old_cl = $gfunc_obj->getConvertedID_rid($old_cl_id);
+					
+									?>
+									<FORM NAME="reagentParentsForm" METHOD="POST" ACTION="<?php echo $cgi_path . "update.py"; ?>">
+						
+									<input type="hidden" ID="changeStateParents" name="change_state">
+									<input type="hidden" name="save_parents">
+									<input type="hidden" ID="rID_hidden" name="reagent_id_hidden" value="<?php echo $reagentIDToView; ?>">
+									<input type="hidden" id="cloning_method" name="cloning_method_hidden" value="<?php echo $cloningMethod; ?>">
+									<input type="hidden" id="curr_uname" name="curr_username" value="<?php echo $currUserName; ?>">
+									<input type="hidden" name="reagent_typeid_hidden" value="<?php echo $reagentType; ?>">
+									<input type="hidden" name="reagent_groupnum_hidden" value="<?php echo $reagentGroup; ?>">
+
+									<table id="showCellLineAssoc">
+										<tr>
+											<td colspan="5"><?php
+
+												if (strtolower($cellLineType) != "parent")
+													$this->printCellLineParents($reagentIDToView);
+
+											?></TD>
+										</TR><?php
+
+										if (count($children) > 0)
+										{
+											?><tr>
+												<td colspan="5" class="detailedView_parents" style="font-style:italic; font-weight:bold; padding-left:25px; padding-top:10px;">
+													<P>Children
+												<td>
+											</tr>
+			
+											<TR>
+												<TD COLSPAN="6" style="padding-top:10px;">
+													<TABLE>
+														<tr><?php
+															$cols = 0;
+															$MAX_COLS = 17;
+					
+															foreach (array_unique($childrenTypes) as $key => $value)
+															{
+																if ($value == 4)
+																	echo "<td style=\"padding-left:40px; width:180px; white-space:nowrap\">Cell Line Children</td>";
+																else
+																	echo "<td style=\"padding-left:40px; width:180px; white-space:nowrap\">" . $_SESSION["ReagentType_ID_Name"][$value] . " Children</td>";
+															
+																	?><td width="350px">
+																		<SPAN id="show_<?php echo $_SESSION["ReagentType_ID_Name"][$value]; ?>" class="linkShow" onclick="showHideChildren(this.id, '<?php echo $_SESSION["ReagentType_ID_Name"][$value] . "_children"; ?>');">Show Children</SPAN>
+								
+																		<SPAN id="hide_<?php echo $_SESSION["ReagentType_ID_Name"][$value]; ?>" class="linkHide" onclick="showHideChildren(this.id, '<?php echo $_SESSION["ReagentType_ID_Name"][$value] . "_children"; ?>');">Hide Children</SPAN>
+																		  <B>(<?php echo $num_children[$value]; ?>  total)</B>
+																	</td>
+																</tr>
+							
+																<tr id="<?php echo $_SESSION["ReagentType_ID_Name"][$value] . "_children"; ?>" style="display:none;">
+																	<td colspan="5">
+																		<div class="children">
+																			<TABLE class="children">
+																				<TR><?php
+																				foreach ($children as $aPropID => $childrenIDs)
+																				{
+																					foreach ($childrenIDs as $cKey => $childID)
+																					{
+																						$childTypeID = $gfunc_obj->getTypeID($childID);
+										
+																						if ($childTypeID == $value)
+																						{
+																							if ($cols == $MAX_COLS)
+																							{
+																								echo "</tr><tr>";
+																								$cols = 0;
+																							}
+					
+																							echo "<td>";
+			
+																							$tmpProject = getReagentProjectID($value);
+																							
+																							if (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || in_array($tmpProject, $userProjects))
+																							{
+																								echo "<a href=\"Reagent.php?View=6&rid=" . $childID . "\">" . $gfunc_obj->getConvertedID_rid($childID) . "</a>  ";
+																							}
+																							else
+																							{
+																								echo "<span class=\"linkDisabled\">" . $gfunc_obj->getConvertedID_rid($childID) . "</span>  ";
+																							}
+																		
+																							echo "</td>";
+																							$cols++;
+																						}
+																					}
+																				}
+																				?></TR>
+																			</TABLE>
+																		</DIV>
+																	</td>
+																</tr>
+																<?php
+															}
+
+														?></tr>
+													</TABLE>
+												</TD>
+											</TR><?php
+										}	// end if has children
+
+									?></table></FORM>
+					
+									<table id="editCellLineAssoc" style="display:none">
+										<tr>
+											<td colspan="5">
+
+												<input type="hidden" id="parent_vector_old_id" name="detailed_view_pv_backfillID_old" value="<?php echo $old_pv; ?>">
+								
+												<input type="hidden" id="parent_cellline_old_id" name="detailed_view_cl_backfillID_old" value="<?php echo $old_cl; ?>">
+												
+												<input type="hidden" id="change_pv" name="change_pv_flag" value="">
+												<input type="hidden" id="change_cl" name="change_cl_flag" value=""><?php
+								
+												$this->printForm_Vector_modify_associations($reagentType, $reagentIDToView, $check, $error_type="");
+											?></TD>
+										</TR>
+									</TABLE><?php
+								break;
+
+								default:
+									?><table class="detailedView_parents" ID="viewReagentParents" cellspacing="2" cellpadding="5"><?php
+									
+									$userProjects = getAllowedUserProjectIDs($_SESSION["userinfo"]->getUserID());
+
+									if (count($parents) > 0)
+									{
+										?><tr>
+											<td colspan="2" class="detailedView_parents" style="font-weight:bold; padding-left:10px;">
+												Parents
+											</td>
+										</tr><?php
+									
+										// Existing reagent types still have specific output requirements
+										foreach ($parentTypes as $key => $value)
+										{
+// 											print "Parent types: " . $key . ", " . $value . "<BR>";
+
+											echo "<tr><td width=\"180px\" style=\"white-space:nowrap; padding-left:20px; font-size:9pt;\">" . $_SESSION["ReagentAssoc_ID_Description"][$value] . "</td>";
+										
+											echo "<td>";
+	
+											foreach ($parents as $aPropID => $parentList)
+											{
+												foreach ($parentList as $pID => $parentID)
+												{
+													if ($aPropID == $value)
+													{
+														$tmpProject = getReagentProjectID($value);
+
+														if (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || in_array($tmpProject, $userProjects))
+														{
+															echo "<a style=\"padding-left:10px; padding-right:3px;\" href=\"Reagent.php?View=6&rid=" . $parentID . "\">" . $gfunc_obj->getConvertedID_rid($parentID) . "</a>";
+														}
+														else
+														{
+															echo "<span style=\"padding-left:10px; padding-right:3px;\" class=\"linkDisabled\">" . $gfunc_obj->getConvertedID_rid($parentID) . "</span>";
+														}
+													}
+												}
+											}
+
+											echo "</td>";
+										}
+	
+										?></tr><?php
+									}
+		
+									?></TABLE><?php
+
+									// feb 12/10
+									$assocDict = Array();
+
+									foreach ($assoc as $tmpAssocID => $tmpAssocValue)
+									{
+										$tmpAssocAlias = $_SESSION["ReagentAssoc_ID_Alias"][$tmpAssocID];
+										$assocDict[$tmpAssocID] = $tmpAssocAlias;
+									}
+
+								?><FORM NAME="reagentParentsForm" METHOD="POST" ACTION="<?php echo $cgi_path . "update.py"; ?>">
+						
+									<input type="hidden" ID="changeStateParents" name="change_state">
+									<input type="hidden" name="save_parents">
+									<input type="hidden" ID="rID_hidden" name="reagent_id_hidden" value="<?php echo $reagentIDToView; ?>">
+									<input type="hidden" id="cloning_method" name="cloning_method_hidden" value="<?php echo $cloningMethod; ?>">
+									<input type="hidden" id="curr_uname" name="curr_username" value="<?php echo $currUserName; ?>">
+									<input type="hidden" name="reagent_typeid_hidden" value="<?php echo $reagentType; ?>">
+									<input type="hidden" name="reagent_groupnum_hidden" value="<?php echo $reagentGroup; ?>">
+				
+									<table ID="category_assoc_section_<?php echo $reagentType; ?>" class="detailedView_parents" style="display:none" cellspacing="2" cellpadding="5"><?php
+									
+									// placing this here again for even table alignment (July 13/09)
+									?><tr>
+										<td colspan="2" class="detailedView_parents" style="font-weight:bold; padding-left:10px;">
+											Parents
+										</td>
+									</tr><?php
+
+									// $key is just array indexing; $value is APropertyID
+									foreach ($parentTypes as $key => $value)
+									{
+										$assocAlias = $_SESSION["ReagentAssoc_ID_Alias"][$value];
+
+										// 'value' is APropertyID, use it to grab parent type and prefix (Dec. 10/09)
+										if ($value > 0)
+										{
+											$parentTypeID = $rfunc_obj->findAssocParentType($value);
+											$parentPrefix = $_SESSION["ReagentType_ID_Prefix"][$parentTypeID];
+
+											if (in_array($value, array_keys($parents)))
+											{
+												$parentIDs = $parents[$value];
+											
+												foreach ($parentIDs as $aKey => $parentID)
+												{
+													echo "<tr ID=\"" . $_SESSION["ReagentType_ID_Name"][$reagentType] . "_" . $assocAlias . "_assoc_row_" . $aKey . "\">";
+
+													echo "<td width=\"180px\" style=\"white-space:nowrap; padding-left:40px; font-weight:normal;\">" . $_SESSION["ReagentAssoc_ID_Description"][$value] . " (" . $parentPrefix . ")</td>";
+	
+													echo "<td>";
+												
+													?><INPUT TYPE="TEXT" ID="<?php echo $_SESSION["ReagentType_ID_Name"][$reagentType]; ?>_assoc_<?php echo $assocAlias; ?>_input" onKeyPress="return disableEnterKey(event);" NAME="<?php echo $_SESSION["ReagentType_ID_Name"][$reagentType]; ?>_assoc_<?php echo $value; ?>_prop" VALUE="<?php echo $gfunc_obj->getConvertedID_rid($parentID); ?>"><?php
+	
+													if (!in_array($_SESSION["ReagentType_ID_Name"][$reagentType], Array('Vector', 'Insert', 'Oligo', 'CellLine')))
+													{
+														?><SPAN class="linkExportSequence" style="margin-left:15px; font-weight:normal;" onClick="addParent('<?php echo $reagentType; ?>', '<?php echo $_SESSION["ReagentType_ID_Name"][$reagentType]; ?>', '<?php echo $assocAlias; ?>', '<?php echo $_SESSION["ReagentAssoc_ID_Description"][$value];?>', '<?php echo $value; ?>', '<?php echo $aKey; ?>');">Add New</SPAN>
+														<SPAN class="linkExportSequence" style="margin-left:15px; font-weight:normal;" onClick="deleteTableRow('category_assoc_section_<?php echo $reagentType; ?>', '<?php echo $_SESSION["ReagentType_ID_Name"][$reagentType] . "_" . $assocAlias; ?>_assoc_row_<?php echo $aKey; ?>');">Remove</SPAN><?php
+													}
+	
+													echo "</td>";
+													echo "</tr>";
+												}
+											}
+											else
+											{
+												echo "<tr ID=\"" . $_SESSION["ReagentType_ID_Name"][$reagentType] . "_" . $assocAlias . "_assoc_row_" . $aKey . "\">";
+	
+												echo "<td width=\"180px\" style=\"white-space:nowrap; padding-left:40px; font-weight:normal;\">" . $_SESSION["ReagentAssoc_ID_Description"][$value] . " (" . $parentPrefix . ")</td>";
+											
+												echo "<td>";
+
+												?><INPUT TYPE="TEXT" ID="<?php echo $_SESSION["ReagentType_ID_Name"][$reagentType]; ?>_assoc_<?php echo $assocAlias; ?>_input" onKeyPress="return disableEnterKey(event);" NAME="<?php echo $_SESSION["ReagentType_ID_Name"][$reagentType]; ?>_assoc_<?php echo $value; ?>_prop" VALUE=""><?php
+
+												if (!in_array($_SESSION["ReagentType_ID_Name"][$reagentType], Array('Vector', 'Insert', 'Oligo', 'CellLine')))
+												{
+													?><SPAN class="linkExportSequence" style="margin-left:15px; font-weight:normal;" onClick="addParent('<?php echo  $reagentType; ?>', '<?php echo $_SESSION["ReagentType_ID_Name"][$reagentType]; ?>', '<?php echo $assocAlias; ?>', '<?php echo $_SESSION["ReagentAssoc_ID_Description"][$value];?>', '<?php echo $key; ?>');">Add New</SPAN>
+		
+													<SPAN class="linkExportSequence" style="margin-left:15px; font-weight:normal;" onClick="deleteTableRow('category_assoc_section_<?php echo $reagentType; ?>', '<?php echo $_SESSION["ReagentType_ID_Name"][$reagentType] . "_" . $assocAlias; ?>_assoc_row_<?php echo $key; ?>');">Remove</SPAN><?php
+
+												}
+
+												echo "</td>";
+
+												echo "</tr>";
+											}
+										}
+									}
+
+									?></tr></TABLE><?php
+
+									if (count($children) > 0)
+									{
+										?><tr>
+											<td colspan="2" class="detailedView_parents">
+												<i>    <b>Children</b></i>
+											</td>
+										</tr>
+		
+										<TR>
+											<TD COLSPAN="6">
+												<TABLE>
+													<tr><?php
+														$cols = 0;
+														$MAX_COLS = 17;
+				
+														foreach (array_unique($childrenTypes) as $key => $value)
+														{
+															if ($value == 4)
+																echo "<td style=\"padding-left:40px; width:180px; white-space:nowrap\">Cell Line Children</td>";
+															else
+																echo "<td style=\"padding-left:40px; width:180px; white-space:nowrap\">" . $_SESSION["ReagentType_ID_Name"][$value] . " Children</td>";
+														
+																?><td width="350px">
+																	<SPAN id="show_<?php echo $_SESSION["ReagentType_ID_Name"][$value]; ?>" class="linkShow" onclick="showHideChildren(this.id, '<?php echo $_SESSION["ReagentType_ID_Name"][$value] . "_children"; ?>');">Show Children</SPAN>
+							
+																	<SPAN id="hide_<?php echo $_SESSION["ReagentType_ID_Name"][$value]; ?>" class="linkHide" onclick="showHideChildren(this.id, '<?php echo $_SESSION["ReagentType_ID_Name"][$value] . "_children"; ?>');">Hide Children</SPAN>
+																	  <B>(<?php echo $num_children[$value]; ?>  total)</B>
+																</td>
+															</tr>
+						
+															<tr id="<?php echo $_SESSION["ReagentType_ID_Name"][$value] . "_children"; ?>" style="display:none;">
+																<td colspan="5">
+																	<div class="children">
+																		<TABLE class="children">
+																			<TR><?php
+
+																			foreach ($children as $aPropID => $childrenIDs)
+																			{
+																				foreach ($childrenIDs as $cKey => $childID)
+																				{
+																					$childTypeID = $gfunc_obj->getTypeID($childID);
+									
+																					if ($childTypeID == $value)
+																					{
+																						if ($cols == $MAX_COLS)
+																						{
+																							echo "</tr><tr>";
+																							$cols = 0;
+																						}
+				
+																						echo "<td>";
+
+																						$tmpProject = getReagentProjectID($value);
+																						
+																						if (($currUserCategory == $_SESSION["userCategoryNames"]["Admin"]) || in_array($tmpProject, $userProjects))
+																						{
+																							echo "<a href=\"Reagent.php?View=6&rid=" . $childID . "\">" . $gfunc_obj->getConvertedID_rid($childID) . "</a>  ";
+																						}
+																						else
+																						{
+																							echo "<span class=\"linkDisabled\">" . $gfunc_obj->getConvertedID_rid($childID) . "</span>  ";
+																						}
+
+																						echo "</td>";
+																						$cols++;
+																					}
+																				}
+																			}
+
+																			?></TR>
+																		</TABLE>
+																	</DIV>
+																</td>
+															</tr><?php
+														}
+					
+													?></tr>
+												</TABLE>
+											</TD>
+										</TR><?php
+									}	// end if has children
+								?></table><?php
+							break;
+						}
+					?></td>
+				</tr>
+
+				<!-- Hidden error messages -->
+				<tr>
+					<td colspan="<?php echo $colspan; ?>">
+		
+						<SPAN style="color:#FF0000; font-weight:bold; display:<?php echo (isset($_GET["ErrCode"]) && (strcasecmp($_GET["ErrCode"], '6') == 0)) ? "table-row" : "none"; ?>">Vector sequence cannot be reconstructed using the restriction sites and parents provided.  Please verify restriction sites and/or parent input values.</SPAN>
+		
+						<SPAN style="color:#FF0000; font-weight:bold; display:<?php echo (isset($_GET["ErrCode"]) && (strcasecmp($_GET["ErrCode"], '8') == 0)) ? "table-row" : "none"; ?>">Unknown sites on Insert.  Please verify your Insert input value.</SPAN>
+		
+						<SPAN style="color:#FF0000; font-weight:bold; display:<?php echo (isset($_GET["ErrCode"]) && (strcasecmp($_GET["ErrCode"], '9') == 0)) ? "table-row" : "none"; ?>">Sequence generation failed: Restriction sites could not be found on Parent Vector sequence.  Please verify your input values.</SPAN>
+		
+						<SPAN style="color:#FF0000; font-weight:bold; display:<?php echo (isset($_GET["ErrCode"]) && (strcasecmp($_GET["ErrCode"], '10') == 0)) ? "table-row" : "none"; ?>">Sequence generation failed: Insert sites found more than once in Parent Vector sequence.  Please verify your parent input values.</SPAN>
+		
+						<SPAN style="color:#FF0000; font-weight:bold; display:<?php echo (isset($_GET["ErrCode"]) && (strcasecmp($_GET["ErrCode"], '11') == 0)) ? "table-row" : "none"; ?>">Sequence generation failed: Restriction sites cannot be hybridized.  Please verify your restriction sites and/or parent input values.</SPAN>
+		
+						<SPAN style="color:#FF0000; font-weight:bold; display:<?php echo (isset($_GET["ErrCode"]) && (strcasecmp($_GET["ErrCode"], '12') == 0)) ? "table-row" : "none"; ?>">Sequence generation failed: 5' site occurs after 3' restriction site on Parent Vector sequence.  Please verify your restriction sites and/or parent input values.</SPAN>
+					</td>
+				</tr>
+			</table><?php
+
+		echo "</FORM>";
+
+		?>
+			<!-- March 23/09: Export reagent info in GenBank format -->
+			<form id="export_genbank_form" name="genbank_export" action="Reagent/genBank.php" method="POST">
+				<input type="hidden" name="filename" value="<?php echo $limsID; ?>"/>
+				<input type="hidden" id="gbk_content" name="gbkContent" value="<?php echo $gbk_content; ?>" />
+			</form>
+		<?php
+	}
+}
+?>
diff --git a/OpenFreezer/Reagent/Reagent_Special_Prop_Class.php b/OpenFreezer/Reagent/Reagent_Special_Prop_Class.php
new file mode 100755
index 0000000..ab086a7
--- /dev/null
+++ b/OpenFreezer/Reagent/Reagent_Special_Prop_Class.php
@@ -0,0 +1,128 @@
+<?php
+
+class Reagent_Special_Prop_Class
+{
+	var $special_propID_ar = array();
+	
+	function Reagent_Special_Prop_Class()
+	{
+		$this->special_propID_ar[] = $_SESSION["ReagentProp_Name_ID"]["Sequence"];
+		$this->special_propID_ar[] = $_SESSION["ReagentProp_Name_ID"]["Comments"];
+		$this->special_propID_ar[] = $_SESSION["ReagentProp_Name_ID"]["Description"];
+		//$special_propID_set[] = $_SESSION["ReagentProp_Name_ID"]["Owners"];
+	}
+	
+	function isSpecialProperty( $propID_tmp )
+	{
+		if( in_array( $propID_tmp, $this->special_propID_ar ) )
+		{
+			return true;
+		}
+		
+		return false;
+	}
+	
+	function input_property( $rid, $pid, $value )
+	{
+		switch( $propertyID )
+		{
+			case $_SESSION["ReagentProp_Name_ID"]["Sequence"]:
+					$new_value = $this->input_sequence( $value );
+					
+					mysql_query( "INSERT INTO `ReagentPropList_tbl` (`propListID`, `reagentID`, `propertyID`, `propertyValue`, `labID`, `status`) "
+						. "VALUES ('', '" . $rid . "','" . $pid . "','" 
+						. addslashes( $value ). "','" . 1 . "','ACTIVE')", $conn )
+						or die( "FAILURE IN: Reagent_Creator_Class.input_property(1): " . mysql_error() );
+						
+					return mysql_insert_id( $conn );
+				break;
+			case $_SESSION["ReagentProp_Name_ID"]["Comments"]:
+			case $_SESSION["ReagentProp_Name_ID"]["Description"]:
+			
+					$new_value = $this->input_com_desc( $value );
+			
+					mysql_query( "INSERT INTO `ReagentPropList_tbl` (`propListID`, `reagentID`, `propertyID`, `propertyValue`, `labID`, `status`) "
+						. "VALUES ('', '" . $rid . "','" . $pid . "','" 
+						. addslashes( $value ). "','" . 1 . "','ACTIVE')", $conn )
+						or die( "FAILURE IN: Reagent_Creator_Class.input_property(2): " . mysql_error() );
+						
+					return mysql_insert_id( $conn );
+				break;
+			default:
+				break;
+		}
+	}
+	
+	function input_sequence( $value )
+	{
+		global $conn;
+		
+		$gfunc_obj = new generalFunc_class();
+		
+		$sequence_type_rs = mysql_query( "SELECT `seqTypeID` FROM `SequenceType_tbl` WHERE `seqTypeName`='" . "cDNA" . "' "
+									."AND `status`='ACTIVE'", $conn )
+									or die( "FAILURE IN: Reagent_special_prop_class.input_sequence(1): " . mysql_error() );
+		
+		$sequence_type_ar = mysql_fetch_array( $sequence_type_rs, MYSQL_ASSOC );
+		
+		$seqtype = $sequence_type_ar["seqTypeID"];
+		
+		mysql_free_result( $sequence_type_rs );
+		unset( $sequence_type_rs, $sequence_type_ar );
+		
+		$new_value = $gfunc_obj->remove_whitespaces( $value );
+		
+		unset( $gfunc_obj );
+		
+		mysql_query( "INSERT INTO `Sequences_tbl` (`seqID`,`seqTypeID`,`sequence`,`length`,`labID`,`status`) "
+				. "VALUES ('','" . $seqtype . "','" . $new_value . "','" . strlen( $new_value ) . "','" . 1 . "', 'ACTIVE)", $conn )
+				or die( "FAILURE IN: Reagent_special_prop_class.input_sequence(2): " . mysql_error() );
+				
+		return mysql_insert_id( $conn );
+									
+	}
+	
+	function input_com_desc( $value )
+	{
+		global $conn;
+		
+		$commentLink_rs = mysql_query( "SELECT `commentLinkID` FROM `CommentLink_tbl` WHERE `link`='" . "Reagent" . "' AND `status`='ACTIVE'", $conn ) or die( "FAILURE IN Reagent_Special_Prop_Class.input_com_desc(1): " . mysql_error() );
+
+		$commentLink_ar = mysql_fetch_array( $commentLink_rs, MYSQL_ASSOC );
+		
+		$link = $commentLink_ar["commentLinkID"];
+		
+		mysql_free_result( $commentLink_rs );
+		unset( $commentLink_rs, $commentLink_ar );
+		
+		mysql_query( "INSERT INTO `GeneralComments_tbl` (`commentID`, `commentLinkID`, `comment`, `labID`, `status`) "
+				. "VALUES ('', '" . $link . "', '" . addslashes( $value ) . "', '" . 1 . "', 'ACTIVE')", $conn )
+				or die( "FAILURE IN Reagent_Special_Prop_Class.input_com_desc(2): " . mysql_error() );
+				
+		return mysql_insert_id( $conn );
+	}
+
+// 	// Feb. 11/08, Marina: Check if the value of the special property identified by $propID is empty
+// 	// In most cases, $propValue is an INT value of an ID column referencing a special property table (e.g. commentID for GeneralComments_tbl)
+// 	// This function returns the text value of the property (e.g. the value of 'comment' column in GeneralComments_tbl)
+// 	function isEmptyValue($propID, $propValue)
+// 	{
+// 		global $conn;
+// 		
+// 		switch ($propID)
+// 		{
+// 			case $_SESSION["ReagentProp_Name_ID"]["description"]:
+// 				$comment_rs = mysql_query("SELECT comment FROM GeneralComments_tbl WHERE commentID='" . $propValue . "' AND `status`='ACTIVE'", $conn) or die("Could not select description value: " . mysql_error());
+// 		
+// 				while ($comment_ar = mysql_fetch_array($comment_rs, MYSQL_ASSOC))
+// 				{
+// 					$comment = $comment_ar["comment"];
+// 
+// 					return strlen($comment) == 0;
+// 				}
+// 				
+// 			break;
+// 		}
+// 	}
+}
+?>
\ No newline at end of file
diff --git a/OpenFreezer/Reagent/Sequence_Function_Class.php b/OpenFreezer/Reagent/Sequence_Function_Class.php
new file mode 100755
index 0000000..53a89a5
--- /dev/null
+++ b/OpenFreezer/Reagent/Sequence_Function_Class.php
@@ -0,0 +1,199 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Sequence
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+/**
+ * Functions for handling DNA, RNA or Protein sequences
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1 2009-06-23
+ * @package Sequence
+ *
+ * @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+class Sequence_Function_Class
+{
+	/**
+	 * Retrieve the *Protein* sequence of the given reagent from the database (reagent's sequence is of type Protein, not DNA or RNA)
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT $reagentID
+	 * @return ProteinSequence
+	*/
+	function findProteinSequence($reagentID)
+	{
+		global $conn;
+
+		$protein = null;
+
+		$result_rs = mysql_query("SELECT start, end, frame, sequence, mw FROM ReagentPropList_tbl p, ReagentPropertyCategories_tbl pc, Sequences_tbl s WHERE p.reagentID='" . $reagentID . "' AND p.propertyID=pc.propCatID AND pc.propID='" . $_SESSION["ReagentProp_Name_ID"]["protein sequence"] . "' AND s.seqID=p.propertyValue AND p.status='ACTIVE' AND s.status='ACTIVE' AND pc.status='ACTIVE'");
+
+		if ($result_ar = mysql_fetch_array($result_rs, MYSQL_ASSOC))
+		{
+			$proteinSeq = $result_ar["sequence"];
+
+			$start = $result_ar["start"];
+			$end = $result_ar["end"];
+			$frame = $result_ar["frame"];
+			$mw = $result_ar["mw"];
+
+			$protein = new ProteinSequence();
+			$protein->setSequence($proteinSeq);
+			$protein->setStart($start);
+			$protein->setEnd($end);
+			$protein->setFrame($frame);
+			$protein->setMW($mw);
+		}
+
+		return $protein;
+	}
+
+
+	/**
+	 * Retrieve the **translated protein sequence** of the given reagent from the database (the reagent's sequence is of type DNA, and has been also translated into protein)
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT $reagentID
+	 * @return ProteinSequence
+	*/
+	function findProteinTranslation($reagentID)
+	{
+		global $conn;
+
+		$protein = null;
+
+		$result_rs = mysql_query("SELECT propertyValue FROM ReagentPropList_tbl p, ReagentPropertyCategories_tbl pc WHERE p.reagentID='" . $reagentID . "' AND p.propertyID=pc.propCatID AND pc.propID='" . $_SESSION["ReagentProp_Name_ID"]["protein translation"] . "' AND p.status='ACTIVE' AND pc.status='ACTIVE'");
+		
+		if ($result_ar = mysql_fetch_array($result_rs, MYSQL_ASSOC))
+		{
+			$protSeqID = $result_ar["propertyValue"];
+			$result_rs_2 = mysql_query("SELECT start, end, frame, sequence, mw FROM Sequences_tbl WHERE seqID='" . $protSeqID . "' AND status='ACTIVE'", $conn) or die("Error in findProteinSequence() function: " . mysql_error());
+
+			if ($result_ar_2 = mysql_fetch_array($result_rs_2, MYSQL_ASSOC))
+			{
+				$start = intval($result_ar_2["start"]);
+				$end = intval($result_ar_2["end"]);
+				$frame = $result_ar_2["frame"];
+				$protSeq = $result_ar_2["sequence"];
+				$mw = $result_ar_2["mw"];		// Jan. 22, 2010
+				$protein = new ProteinSequence();
+
+				$protein->setSequence($protSeq);
+				$protein->setStart($start);
+				$protein->setEnd($end);
+				$protein->setFrame($frame);
+				$protein->setMW($mw);		// Jan. 22, 2010
+			}
+		}
+
+		return $protein;
+	}
+
+	/**
+	 * Retrieve the DNA sequence of the given reagent from the database
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT $reagentID
+	 * @return DNASequence
+	*/
+	function findDNASequence($reagentID)
+	{
+		global $conn;
+
+		$dna = null;
+
+		$result_rs = mysql_query("SELECT sequence FROM ReagentPropList_tbl p, ReagentPropertyCategories_tbl pc, Sequences_tbl s WHERE p.reagentID='" . $reagentID . "' AND p.propertyID=pc.propCatID AND pc.propID='" . $_SESSION["ReagentProp_Name_ID"]["sequence"] . "' AND s.seqID=p.propertyValue AND p.status='ACTIVE' AND s.status='ACTIVE' AND pc.status='ACTIVE'");
+
+		if ($result_ar = mysql_fetch_array($result_rs, MYSQL_ASSOC))
+		{
+			$dnaSeq = $result_ar["sequence"];
+			$dna = new DNASequence();
+			$dna->setSequence($dnaSeq);
+		}
+
+		return $dna;
+	}
+
+	/**
+	 * Retrieve the ID of the given sequence from the database (return Sequences_tbl.seqID column value; $sequence can be of any type)
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param STRING $sequence
+	 * @return INT
+	*/
+	function findSequenceID($sequence)
+	{
+		global $conn;
+
+		$seq_rs = mysql_query("SELECT seqID FROM Sequences_tbl WHERE sequence='" . $sequence . "' AND status='ACTIVE'");
+
+		if ($seq_ar = mysql_fetch_array($seq_rs, MYSQL_ASSOC))
+		{
+			return $seq_ar["seqID"];
+		}
+
+		return -1;
+	}
+
+	/**
+	 * Retrieve the RNA sequence of the given reagent from the database (reagent's sequence is of type RNA, not DNA or Protein)
+	 *
+	 * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+	 * @version 3.1
+	 *
+	 * @param INT $reagentID
+	 * @return RNASequence
+	*/
+	function findRNASequence($reagentID)
+	{
+		global $conn;
+
+		$rna = null;
+
+		$result_rs = mysql_query("SELECT sequence FROM ReagentPropList_tbl p, ReagentPropertyCategories_tbl pc, Sequences_tbl s WHERE p.reagentID='" . $reagentID . "' AND p.propertyID=pc.propCatID AND pc.propID='" . $_SESSION["ReagentProp_Name_ID"]["rna sequence"] . "' AND s.seqID=p.propertyValue AND p.status='ACTIVE' AND s.status='ACTIVE' AND pc.status='ACTIVE'");
+
+		if ($result_ar = mysql_fetch_array($result_rs, MYSQL_ASSOC))
+		{
+			$rnaSeq = $result_ar["sequence"];
+			$rna = new RNASequence();
+			$rna->setSequence($rnaSeq);
+		}
+
+		return $rna;
+	}
+}
+?>
diff --git a/OpenFreezer/Reagent/cell_assoc.png b/OpenFreezer/Reagent/cell_assoc.png
new file mode 100755
index 0000000..5efac54
Binary files /dev/null and b/OpenFreezer/Reagent/cell_assoc.png differ
diff --git a/OpenFreezer/Reagent/fasta.php b/OpenFreezer/Reagent/fasta.php
new file mode 100755
index 0000000..b060396
--- /dev/null
+++ b/OpenFreezer/Reagent/fasta.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Export sequence contents in FASTA format; differentiate between DNA, Protein and RNA sequence types
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package Sequence
+ *
+ * PHP versions 4 and 5
+ *
+ * @copyright  2005-2010 Pawson Laboratory
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+ * This file is part of OpenFreezer LARISA (TM)
+ *
+ * OpenFreezer LARISA is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+
+ * OpenFreezer LARISA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with OpenFreezer LARISA.  If not, see <http://www.gnu.org/licenses/>.
+ *
+*/
+	header("Content-type: application/octet-stream");
+	header("Content-Disposition: attachment; filename=" . $_REQUEST["filename"] . ".fa");
+	header("Pragma: no-cache");
+	header("Expires: 0");
+	
+	// Differentiate between protein or DNA sequence export request
+	if ($_REQUEST["curr_export_sel"] == 'DNA')
+	{
+		$fastaContent=$_REQUEST['dnaFastaContent'];
+	}
+	else if ($_REQUEST["curr_export_sel"] == 'Protein')
+	{
+		$fastaContent=$_REQUEST['protFastaContent'];
+	}
+	else if ($_REQUEST["curr_export_sel"] == 'RNA')
+	{
+		$fastaContent=$_REQUEST['rnaFastaContent'];
+	}
+	
+	print $fastaContent;
+?>
diff --git a/OpenFreezer/Reagent/genBank.php b/OpenFreezer/Reagent/genBank.php
new file mode 100755
index 0000000..a7dccb8
--- /dev/null
+++ b/OpenFreezer/Reagent/genBank.php
@@ -0,0 +1,9 @@
+<?php
+    	header("Content-type: application/octet-stream");
+    	header("Content-Disposition: attachment; filename=" . $_REQUEST["filename"] . ".gb");
+    	header("Pragma: no-cache");
+    	header("Expires: 0");
+
+	$gbkContent = $_REQUEST['gbkContent'];	
+   	print $gbkContent;
+?>
diff --git a/OpenFreezer/Reagent/pr_translation_rules.pdf b/OpenFreezer/Reagent/pr_translation_rules.pdf
new file mode 100644
index 0000000..3521b70
Binary files /dev/null and b/OpenFreezer/Reagent/pr_translation_rules.pdf differ
diff --git a/OpenFreezer/Reagent/restriction.php b/OpenFreezer/Reagent/restriction.php
new file mode 100755
index 0000000..8e56992
--- /dev/null
+++ b/OpenFreezer/Reagent/restriction.php
@@ -0,0 +1,18 @@
+<?php
+    	header("Content-type: application/octet-stream");
+    	header("Content-Disposition: attachment; filename=" . $_REQUEST["filename"] . ".txt");
+    	header("Pragma: no-cache");
+    	header("Expires: 0");
+
+	// Differentiate between protein or DNA sequence export request
+	if ($_REQUEST["insert_restriction_map"])
+	{
+		$content=$_REQUEST['insert_restriction_map'];
+	}
+	elseif ($_REQUEST["vector_restriction_map"])
+	{
+		$content=$_REQUEST['vector_restriction_map'];
+	}
+	
+   	print $content;
+?>
diff --git a/OpenFreezer/Reagent/vector_assoc.jpeg b/OpenFreezer/Reagent/vector_assoc.jpeg
new file mode 100755
index 0000000..779ff11
Binary files /dev/null and b/OpenFreezer/Reagent/vector_assoc.jpeg differ
diff --git a/OpenFreezer/Reagent/vector_assoc.png b/OpenFreezer/Reagent/vector_assoc.png
new file mode 100755
index 0000000..779ff11
Binary files /dev/null and b/OpenFreezer/Reagent/vector_assoc.png differ
diff --git a/OpenFreezer/Search/searchFunctions.php b/OpenFreezer/Search/searchFunctions.php
new file mode 100755
index 0000000..62fcacd
--- /dev/null
+++ b/OpenFreezer/Search/searchFunctions.php
@@ -0,0 +1,608 @@
+<title>Search Page</title>
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2010 Pawson Laboratory, All Rights Reserved
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Search
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* functions
+*/
+// currentSet can be: Generic OR Advanced
+function searchHeader($currentSet)
+{
+?>
+<td>
+		<center>
+		<a href="../index.php">OpenFreezer Home</a>
+		<?php
+		echo "<a href=\"search.php?View=" . $currentSet . "\">" . $currentSet . " Search </a>";
+		echo "</center>\n";
+			
+		echo "<FORM METHOD=POST ACTION=\"search.php?Type=" . $currentSet . "\">";
+		?>
+	</center>
+	</td>
+	<?php
+}
+
+function outputSubMenu($typeOfMenu)
+{
+	if ($typeOfMenu == "1")
+	{
+		searchNavForm( "1", "False" );
+	}
+}
+
+	// Sept 1, 2006, Marina -- Replace search view
+	function searchNavForm($currentSet, $isAdvanced)
+	{
+		global $conn;
+	
+		$searchOptions[0] = "All";
+		$searchOptions[1] = "OpenFreezer ID";
+		$searchOptions[3] = "Entrez Gene ID";
+		$searchOptions[4] = "Ensembl Gene ID";
+		$searchOptions[5] = "Gene Symbol";
+		$searchOptions[6] = "Name";
+		$searchOptions[7] = "Accession Number";
+		$searchOptions[8] = "Protein Sequence";
+		$searchOptions[9] = "DNA Sequence";
+	
+		# internal option values for the categories list
+		$searchOptionValues[0] = "all";
+		$searchOptionValues[1] = "lims id";
+		$searchOptionValues[3] = "entrez gene id";
+		$searchOptionValues[4] = "ensembl gene id";
+		$searchOptionValues[5] = "official gene symbol";
+		$searchOptionValues[6] = "name";
+		$searchOptionValues[7] = "accession number";
+	
+		$propIDs = array();
+	
+		foreach ($searchOptionValues as $key=>$val)
+		{
+			$props_rs = mysql_query("SELECT `propertyID` FROM `ReagentPropType_tbl` WHERE `propertyName`='" . $val . "'", $conn) or die("Could not select properties: " . mysql_error());
+	
+			while ($props_ar = mysql_fetch_array($props_rs, MYSQL_ASSOC))
+			{
+				// Feb. 28/10: temporary hack for now; will change as search gets more sophisticated
+				// determine the category of each of the above properties to output in summary table
+				/*
+				include "Reagent/Reagent_Function_Class";*/
+
+				$rfunc_obj = new Reagent_Function_Class();
+
+				switch ($val)
+				{
+					case 'name':
+						$category = "General Properties";
+					break;
+
+					case 'entrez gene id':
+					case 'ensembl gene id':
+					case 'official gene symbol':
+					case 'accession number':
+						$category = "External Identifiers";
+					break;
+				}
+
+				$propCatID = $rfunc_obj->getPropertyIDInCategory($props_ar["propertyID"], $_SESSION["ReagentPropCategory_Name_ID"][$category]);
+				$propIDs[$val] = $propCatID;
+			}
+		}
+
+		mysql_free_result($props_rs);
+		unset($props_ar);
+
+		$mult_rTypes_checked = "";
+		$mult_packets_checked = "";
+		$rTypesMultiple = "";
+
+		?>
+			<form name="search_reagents" method="POST" action="<?php echo $_SERVER["PHP_SELF"] . "?View=1";?>">
+				<table width="790px">
+					<th colspan="2" style="font-size:13pt; text-align:center; font-weight:bold; color:#0000FF; white-space:nowrap; padding-bottom:10px; padding-top:5px; border-bottom: 1px solid black;">
+						REAGENT SEARCH PAGE
+					</th>
+
+					<tr>
+						<td colspan="2" style="padding-top:10px; padding-bottom:10px; border-bottom: 1px solid black;">
+							<table width="790px" cellpadding="6" cellspacing="4" border="0">
+								<th colspan="6" style="font-size:10pt; text-align:left; font-weight:bold; color:#1A08F2; white-space:nowrap; padding-top: 10px; padding-top:5px;">
+									Optional Search Filters:
+								</th>
+
+								<tr>
+									<td colspan="2" style="vertical-align:middle; white-space:nowrap; padding-top:10px; padding-left:9px;"><IMG SRC="pictures/bullet.gif" style="vertical-align:middle; padding-left:0; padding-top:0; padding-right:0; padding-bottom:2px;">Reagent type:</td>
+								
+									<td colspan="2" style="padding-left:10px;"><?php
+
+										// Modified May 13/09: Since we're now adding new reagent types, show Reagent type selection in a list instead of es
+										if (isset($_POST["multiple_reagent_types"]))
+											$rTypesMultiple = "MULTIPLE";
+
+										echo "<SELECT NAME=\"filter[]\" " . $rTypesMultiple . " ID=\"reagentTypesFilterList\">";
+
+										if (!isset($_POST["filter"]))
+											echo "<OPTION VALUE=\"default\" SELECTED>All</OPTION>";
+										else
+											echo "<OPTION VALUE=\"default\">All</OPTION>";
+
+										foreach ($_SESSION["ReagentType_Name_ID"] as $Rname => $id)
+										{
+											$selected = "";
+
+											if (strcasecmp($Rname, 'CellLine') == 0)
+												$Rname = "Cell Line";
+											
+											if (isset($_POST["filter"]) && in_array($Rname, $_POST["filter"]))
+												$selected = "SELECTED";
+
+											echo "<OPTION VALUE=\"" . $Rname . "\" " . $selected . ">". $Rname . "</OPTION>";
+										}
+
+										echo "</SELECT>";
+
+										if (isset($_POST["multiple_reagent_types"]))
+											$mult_rTypes_checked = "checked";
+
+										?><input type="checkbox" style="margin-left:10px;" id="searchMultipleReagentTypesCheckbox" name="multiple_reagent_types" <?php echo $mult_rTypes_checked; ?> onClick="searchMultipleReagentTypes();"> Select multiple reagent types
+									</td>
+								</tr>
+							
+								<!-- Added July 16/07: Add Project filter - Beginning of a biomart-like search interface -->
+								<tr>
+									<td colspan="2" style="white-space:nowrap; padding-top:20px; padding-left:9px;"><IMG SRC="pictures/bullet.gif" style="vertical-align:middle; padding-left:0; padding-top:0; padding-right:0; padding-bottom:2px;">Project:</td>
+
+									<td colspan="3" style="padding-left:10px; padding-top:10px; vertical-align:middle;">
+										<?php
+											// Need to think about this more, as there can be multiple project filter values
+											if (isset($_POST["multiple_packets"]))
+											{
+												$mult_packets_checked = "checked";
+												printSearchPackets(1, "", 1);
+											}
+											else
+												printSearchPackets(0, "", 1)
+										?>
+										<input type="checkbox" onClick="searchMultipleProjects();" id="searchMultiple" name="multiple_packets" <?php echo $mult_packets_checked; ?>> Select multiple projects
+									</td>
+								</tr>
+							
+								<tr>
+									<td colspan="2" style="white-space:nowrap; padding-top:10px; padding-left:9px;"><IMG SRC="pictures/bullet.gif" style="vertical-align:middle; padding-left:0; padding-top:0; padding-right:0; padding-bottom:2px;">Property type:</td>
+								
+									<td colspan="2" style="padding-left:10px;">
+										<select id="search_by" name="SearchArea" onChange="checkOutputType()"><?php
+											foreach ($searchOptionValues as $key=>$val)
+											{
+												echo "<option value=\"" . $val . "\"";
+											
+												if (isset($_POST["SearchArea"]))
+												{
+													$searchCategory = $_POST["SearchArea"];
+
+													if (strcasecmp($searchCategory, $val) == 0)
+													{
+														echo "selected";
+													}
+												}
+											
+												echo ">";
+												echo $searchOptions[$key] . "</option>";
+											}
+										?></select>
+									</td>
+								</tr>
+
+								<!-- April 27, 2011 -->
+								<TR>
+									<TD colspan="4" style="padding-left:20px; font-size:9pt;">
+										<input type="checkbox" name="gs_only"
+										<?php 
+											if ( ($_POST["gs_only"] == "on") )
+												echo "checked";
+										?>
+										> Search Glycerol Stocks only (find clones available for order)
+										<IMG SRC="pictures/new01.gif" ALT="new" WIDTH="35" HEIGHT="20" style="cursor:auto">
+									</TD>
+								</TR>
+							</table>
+						</td>
+					</tr>
+					
+					<tr>
+						<td>
+							<table width="790px" cellpadding="6" cellspacing="4" border="0" style="display:inline" id="show_search" cellpadding="4">
+								<tr>
+									<th colspan="2" style="font-size:10pt; text-align:left; font-weight:bold; color:#1A08F2; white-space:nowrap; padding-right:15px; padding-top:5px;">
+										Enter search term:
+									</td>
+								
+									<td style="padding-left:0;" colspan="2">
+										<?php
+											echo "<INPUT TYPE=\"text\" id=\"search_term_id\" name=\"Keyword\" value=\"";
+
+											if (isset($_POST["Keyword"]))
+											{
+												echo stripslashes($_POST["Keyword"])  . "\"";		// 26/9/06
+											}
+											else
+											{
+												echo "\"";
+											}
+										?>
+									</td>
+	
+									<td>
+										<INPUT TYPE="submit" name="search_submit" value="Search">
+									</td>
+
+									<!-- Added April 16/07 -->
+									<td>
+										<input type="checkbox" name="exact_match"
+										<?php 
+											if ( ($_POST["exact_match"] == "on") )
+												echo "checked";
+										?>
+										> Exact match</INPUT><BR>
+
+										<input type="checkbox" name="search_completed"
+										<?php 
+											if ( ($_POST["search_completed"] == "on") )
+												echo "checked";
+										?>
+										> Show completed reagents only
+									</td>
+								</tr>
+							</table>
+	
+							<table width="100%" border="0" id="show_protein" style="display:none">
+								<tr>
+									<td colspan="3" style="font-size:12px" nowrap>
+										Please paste your PROTEIN sequence here:
+									</td>
+								</tr>
+				
+								<tr>
+									<td colspan="3">
+										<textarea wrap="virtual" name="prot_sequence" rows="5" cols="45"></textarea>
+									</td>
+	
+									<td>
+										<INPUT TYPE="submit" name="search_submit" value="Search">
+									</td>
+								</tr>
+							</table>
+		
+							<table width="100%" border="0" id="show_dna" style="display:none">
+								<tr>
+									<td colspan="3" style="font-size:12px" nowrap>
+										Please paste your DNA sequence here:
+									</td>
+								</tr>
+				
+								<tr>
+									<td colspan="3">
+										<textarea wrap="virtual" name="dna_sequence" rows="5" cols="45"></textarea>
+									</td>
+	
+									<td>
+										<INPUT TYPE="submit" name="search_submit" value="Search">
+									</td>
+								</tr>
+							</table>
+						</td>
+					</tr>
+				</tbody>
+				</table>
+			</form>
+		<?php
+	}
+	?>
+	<script language="javascript">
+	
+		function checkOutputType()
+		{
+			searchBoxElem = document.getElementById("search_by");
+			showSearchElem = document.getElementById("show_search");
+			showProteinElem = document.getElementById("show_protein");
+			showDNAElem = document.getElementById("show_dna");
+			searchTermElem = document.getElementById("search_term_id");
+
+			var myindex  = searchBoxElem.selectedIndex
+			var selValue = searchBoxElem.options[myindex].value
+	
+			if (selValue == "protein sequence")
+			{
+				showProteinElem.style.display="inline";
+				showSearchElem.style.display="none";
+				showDNAElem.style.display="none";
+			}
+			else if (selValue == "sequence")
+			{
+				showDNAElem.style.display="inline";
+				showSearchElem.style.display="none";
+				showProteinElem.style.display="none";
+			}
+			else
+			{
+				showSearchElem.style.display="inline";
+				showProteinElem.style.display="none";
+				showDNAElem.style.display="none";
+			}
+
+			searchTermElem.focus();
+		}
+	
+	</script>
+	<?php
+
+function submit_changes( $foundValues, $oldValues, $reagentIDToView )
+{
+	global $conn; 
+	$type_rs = mysql_query( "SELECT `reagentTypeID` FROM `Reagents_tbl` WHERE `status`='ACTIVE' AND `reagentID`='" 
+							. $reagentIDToView . "'", $conn ) ;
+	
+	if( $type_ar = mysql_fetch_array( $type_rs, MYSQL_ASSOC ) )
+	{
+		switch( $type_ar["reagentTypeID"] )
+		{
+			case $_SESSION["ReagentType_Name_ID"]["Vector"]:
+				check_New_VectorInfo( $foundValues, $oldValues, $reagentIDToView );
+				break;
+			case $_SESSION["ReagentType_Name_ID"]["Insert"]:
+				check_New_InsertInfo( $foundValues, $oldValues, $reagentIDToView );
+				break;
+			case $_SESSION["ReagentType_Name_ID"]["Oligo"]:
+				check_New_OligoInfo( $foundValues, $oldValues, $reagentIDToView );
+				break;
+			case $_SESSION["ReagentType_Name_ID"]["CellLine"]:
+				check_New_CellLineInfo( $foundValues, $oldValues, $reagentIDToView );
+				break;
+		}
+	}
+}
+
+function check_New_VectorInfo( $foundValues, $oldValues, $rid )
+{
+	global $conn;
+	
+	// founc values should match up with:
+	// 0: Name
+	// 1: Vector type
+	// 2: 5' Cloning Site
+	// 3: 3' Cloning Site
+	// 4: Description
+	// 5: Comments
+	// 6: Tag Type
+	// 7: Tag Position
+	// 8: Antibiotic Resistance
+	// 9: Reagent Source
+	// 10: Status
+	echo "Found values: ";
+	print_r( $foundValues );
+	echo "<br>";
+	$expectedTypes_ar = array();
+	$expectedTypes_ar[] = "Name";
+	$expectedTypes_ar[] = "Vector Type";
+	$expectedTypes_ar[] = "5' cloning site";
+	$expectedTypes_ar[] = "3' cloning site";
+	$expectedTypes_ar[] = "Description";
+	$expectedTypes_ar[] = "Comments";
+	$expectedTypes_ar[] = "Tag";
+	$expectedTypes_ar[] = "Tag Position";
+	$expectedTypes_ar[] = "Antibiotic Resistance";
+	$expectedTypes_ar[] = "Reagent Source";
+	$expectedTypes_ar[] = "Status";
+	
+	foreach( $expectedTypes_ar as $key => $value )
+	{
+		
+		if( strlen( trim( $foundValues[ $key ] ) ) > 0 )
+			{
+				if( strlen( $oldValues[ $_SESSION["ReagentProp_Name_ID"][ $value ] ] ) > 0 )
+				{
+					// Updating found property!
+					
+					if( specialCol( $value, $foundValues[ $key ] ) )
+					{
+						updateViewInfo( $rid,  $value , $foundValues[ $key ], "UPDATEVALUE" );
+					}
+					else
+					{
+						mysql_query( "UPDATE `ReagentPropList_tbl` SET `propertyValue`='" . $foundValues[ $key ] . "' WHERE `reagentID`='" . $rid . "'" .
+									" AND `propertyID`='" . $_SESSION["ReagentProp_Name_ID"][ $value ] . "'"
+									. " AND `status`='ACTIVE'", $conn ) or die("Query failed : " . mysql_error());
+					
+					}
+				}
+				else
+				{
+					// Property didn't exist before!!
+					if( specialCol( $value, $foundValues[ $key ] ) )
+					{
+						updateViewInfo( $rid,  $value , $foundValues[ $key ], "NEWVALUE" );
+					}
+					else
+					{
+						mysql_query( "INSERT INTO `ReagentPropList_tbl` (`propListID`, `reagentID`, `propertyID`, `propertyValue`) VALUES ('', '" . 
+									$rid . "', '" . $_SESSION["ReagentProp_Name_ID"][ $value ] . "', '" . $foundValues[ $key ] 
+									. "')" , $conn ) or die("Query failed : " . mysql_error());
+					}
+				}
+			}
+			else
+			{
+				// Delete old property?
+				
+			}
+		
+	}
+	
+}
+
+function check_New_InsertInfo( $foundValues, $oldValues, $rid )
+{
+	global $conn;
+	// found values should match up with:
+	// 0: Name
+	// 1: 5' Cloning Site
+	// 2: 3' Cloning Site
+	// 3: 5' Linker
+	// 4: 3' Linker
+	// 5: Comments
+	// 6: Status
+	
+	$expectedTypes_ar = array();
+	$expectedTypes_ar[] = "Name";
+	$expectedTypes_ar[] = "5' cloning site";
+	$expectedTypes_ar[] = "3' cloning site";
+	$expectedTypes_ar[] = "5' Linker";
+	$expectedTypes_ar[] = "3' Linker";
+	$expectedTypes_ar[] = "Comments";
+	$expectedTypes_ar[] = "Status";
+	//print_r( $_SESSION["ReagentProp_Name_ID"]);
+	foreach( $expectedTypes_ar as $key => $value )
+	{
+		
+		if( strlen( trim( $foundValues[ $key ] ) ) > 0 )
+			{
+				if( strlen( $oldValues[ $_SESSION["ReagentProp_Name_ID"][ $value ] ] ) > 0 )
+				{
+					// Updating found property!
+					
+					if( specialCol( $value, $foundValues[ $key ] ) )
+					{
+						updateViewInfo( $rid,  $value , $foundValues[ $key ], "UPDATEVALUE" );
+					}
+					else
+					{
+						mysql_query( "UPDATE `ReagentPropList_tbl` SET `propertyValue`='" . $foundValues[ $key ] . "' WHERE `reagentID`='" . $rid . "'" .
+									" AND `propertyID`='" . $_SESSION["ReagentProp_Name_ID"][ $value ] . "'"
+									. " AND `status`='ACTIVE'", $conn ) or die("Query failed : " . mysql_error());
+					
+					}
+				}
+				else
+				{
+					// Property didn't exist before!!
+					if( specialCol( $value, $foundValues[ $key ] ) )
+					{
+						updateViewInfo( $rid, $value , $foundValues[ $key ], "NEWVALUE" );
+					}
+					else
+					{
+						mysql_query( "INSERT INTO `ReagentPropList_tbl` (`propListID`, `reagentID`, `propertyID`, `propertyValue`) VALUES ('', '" . 
+									$rid . "', '" . $_SESSION["ReagentProp_Name_ID"][ $value ] . "', '" . $foundValues[ $key ] 
+									. "')", $conn  ) or die("Query failed : " . mysql_error());
+					}
+				}
+			}
+			else
+			{
+				// Delete old property?
+				
+			}
+		
+	}
+}
+
+function updateViewInfo( $rid, $propName, $value, $update_type )
+{
+	global $conn;
+	
+	echo "IN the func: " . $propName;
+	switch( $propName )
+	{
+		
+		case "Comments":		
+		case "Description":
+			echo "IN HERE: " . $propName . "<br>";
+			switch( $update_type )
+			{
+				case "UPDATEVALUE":
+					$find_old_comment_rs = mysql_query( "SELECT `propertyValue` FROM `ReagentPropList_tbl` WHERE `status`='ACTIVE' "
+														. " AND `reagentID`='" . $rid . "'"
+														. " AND `propertyID`='" . $_SESSION["ReagentProp_Name_ID"][ $propName ] . "'"
+														, $conn );
+														
+					if( $find_old_comment_ar = mysql_fetch_array( $find_old_comment_rs, MYSQL_ASSOC ) )
+					{
+						mysql_query( "UPDATE `GeneralComments_tbl` SET `comment`='" . $value . "'"
+									. " WHERE `status`='ACTIVE'" 
+									. " AND `commentID`='" . $find_old_comment_ar["propertyValue"] . "'", $conn ) 
+									or die("Query failed : " . mysql_error());
+					}
+					break;
+				case "NEWVALUE":
+					$get_comment_type_rs = mysql_query( "SELECT `commentLinkID` FROM `CommentLink_tbl` WHERE `Link`='Reagent' "
+														. " AND `status`='ACTIVE'", $conn ) or die( "Query Failed: " . mysql_error() );
+														
+					$get_comment_type_ar = mysql_fetch_array( $get_comment_type_rs, MYSQL_ASSOC );
+				
+					mysql_query( "INSERT INTO `GeneralComments_tbl` (`commentID`, `commentLinkID`, `comment`) VALUES ('', '"
+								. $get_comment_type_ar["commentLinkID"] . "',"
+								. "'" . $value . "')", $conn ) or die("Query failed: " . mysql_error() );
+								
+					mysql_query( "INSERT INTO `ReagentPropList_tbl` (`propListID`, `reagentID`, `propertyID`, `propertyValue`) VALUES ('', '" 
+								. $rid . "','" . $_SESSION["ReagentProp_Name_ID"][ $propName ] . "','" . mysql_insert_id() 
+								. "')" , $conn );
+								
+					
+					break;
+			}
+			break;
+	}
+	
+}
+
+function specialCol( $tocheck_colName, $colvalue )
+{
+	if( ( $tocheck_colName == "Description" || $tocheck_colName == "Comments" || $tocheck_colName == "Comment" ) )
+	{
+		return true;
+	}
+	elseif( $tocheck_colName == "Sequence" && $colvalue != "" && $colvalue != "KARENFILLTHIS")
+	{
+		return true;
+	}
+	elseif( $tocheck_colName == "Length" )
+	{
+		return true;
+	}
+	elseif( $tocheck_colName == "Open/Closed" )
+	{
+		return true;
+	}
+	
+	return false;
+}
+?>
diff --git a/OpenFreezer/Search/searchOutput_reagent.php b/OpenFreezer/Search/searchOutput_reagent.php
new file mode 100755
index 0000000..d06f4a0
--- /dev/null
+++ b/OpenFreezer/Search/searchOutput_reagent.php
@@ -0,0 +1,1562 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2010 Pawson Laboratory, All Rights Reserved
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Search
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Include/require statements
+*/
+// include "Views/DetailReagent_View.php";
+
+// Modified April 11/07, Marina: Pass SearchArea and Keyword as parameters
+/**
+* Output search results in a table
+*
+* @param STRING searchArea
+* @param STRING keyword
+*
+* @author John Paul Lee @version 2005
+* @author Marina Olhovsky @version 3.1
+*/
+function searchOutputResults($searchArea, $keyword)
+{
+	global $conn;
+
+	$gfunc_obj = new generalFunc_Class();
+	$lfunc_obj = new Location_Funct_Class();	// April 27, 2011
+
+	$reagentSearch_rs = searchReagentProperties($searchArea, $keyword);
+
+	$rfunc_obj = new Reagent_Function_Class();	// March 1, 2010
+	
+	// June 21/07: Restrict viewing reagents by project
+	$userID = $_SESSION["userinfo"]->getUserID();
+	$userCategory = $_SESSION["userinfo"]->getCategory();
+
+	if ($userCategory == 1)
+		$userProjectIDs = findAllProjects();
+	else
+		$userProjectIDs = getUserProjectIDs($userID);
+
+	// allow everyone to view public projects
+	$publicProjects = getPublicProjects();
+
+	foreach ($publicProjects as $key => $project)
+	{
+		$pID = $project->getPacketID();
+		$userProjectIDs[] = $pID;
+	}
+
+	$userProjectIDs = array_unique($userProjectIDs);
+
+	echo "<TABLE>";
+
+	if (isset($_POST["packets"]) && ($_POST["packets"][0] != 0))
+	{
+		$packetFilter = array();
+
+		foreach ($_POST["packets"] as $pID => $packet)
+		{
+			$packetFilter[] = $packet;
+		}
+
+		while($temp_ar = mysql_fetch_array($reagentSearch_rs, MYSQL_ASSOC))
+	//	foreach ($tmp_search_rs_new as $tKey => $temp_ar)
+		{
+		//	print_r($temp_ar);
+
+			// returned reagentID, reagentTypeID and groupID
+			$tmp_rID = $temp_ar["reagentID"];
+
+			$tmp_rType = $temp_ar["reagentTypeID"];
+			$tmp_gID = $temp_ar["groupID"];
+			
+			// Select the project ID for the reagent and check if it's in the project filter
+			$tmp_pID = getReagentProjectID($tmp_rID);
+
+			if (in_array($tmp_pID, array_values($packetFilter)))
+			{
+				$reagentProjectID = getReagentProjectID($temp_ar["reagentID"]);
+
+				if ( (in_array($reagentProjectID, $userProjectIDs) && (sizeof($userProjectIDs) > 0)) || ($userCategory == $_SESSION["userCategoryNames"]["Admin"]) )
+				{
+					if ($temp_ar["reagentTypeID"] != $lastReagentType)
+					{
+						// For each reagent found, find the properties associated with its reagent type
+						$propToOutput_ar = initializeDefaultOutput($temp_ar["reagentTypeID"]);
+						$alias_ar = makeAliases($propToOutput_ar);
+
+						$propToOutput_str = "('";
+						$prop_count = 0;
+
+						// Creates the array that will hold all the data for the given reagent type
+						$propOrderArray_ar = array_flip($propToOutput_ar);
+
+						foreach ($propOrderArray_ar as $key => $value)
+						{
+							$propOrderArray_ar[$key] = "";
+						}
+
+						foreach($propToOutput_ar as $i => $value)
+						{
+							if (in_array($value, $_SESSION["ReagentProp_ID_Name"]))
+							{
+								$propToOutput_str = $propToOutput_str . $_SESSION["ReagentProp_Name_ID"][$value] . "','";
+								$prop_count++;
+							}
+						}
+
+						if( $prop_count > 0 )
+						{
+							$propToOutput_str = substr( $propToOutput_str, 0, strlen( $propToOutput_str ) - 2 ) . ")";
+						}
+						else
+						{
+							$propToOutput_str = "('')";
+						}
+
+						outputHeader($propOrderArray_ar, $firstHeader);
+						$lastReagentType = $temp_ar["reagentTypeID"];
+					}
+
+					$previewInfo_tmp = findoutputReagent_specific($propToOutput_str, $propOrderArray_ar, $temp_ar["reagentID"], $temp_ar["reagentTypeID"], $temp_ar["groupID"]);
+
+					outputReagentPreview( $temp_ar["reagentID"], $gfunc_obj->getConvertedID( $temp_ar["reagentTypeID"], $temp_ar["groupID"]), $previewInfo_tmp, "", "" );
+
+					$numHits++;	// june 21/07
+				}
+			}
+		}
+
+//		mysql_free_result($tmp_search_rs);
+		unset($propOrderArray_ar);
+		unset($userProjectIDs);
+		unset($previewInfo_tmp);
+		unset($temp_ar);
+	}
+	else
+	{
+		// removed June 21/07 - show number of rows user can actually view
+//		echo "Number of hits: " . mysql_num_rows( $reagentSearch_rs ) . "<BR>";
+		$numHits = 0;	// june 21/07
+
+		?>
+		<link href="styles/SearchStyle.css" rel="stylesheet" type="text/css">
+		<center>
+		<?php
+			$lastReagentType = -1;
+			$firstHeader = false;
+
+//				foreach ($tmp_search_rs_new as $rKey => $temp_ar)
+				while( $temp_ar = mysql_fetch_array( $reagentSearch_rs, MYSQL_ASSOC ) ) // returns reagentID, reagentTypeID and groupID
+				{
+					$reagentProjectID = getReagentProjectID($temp_ar["reagentID"]);
+
+					if ((in_array($reagentProjectID, $userProjectIDs) && (sizeof($userProjectIDs) > 0)) || ($userCategory == $_SESSION["userCategoryNames"]["Admin"]))
+					{
+						if( $temp_ar["reagentTypeID"] != $lastReagentType )
+						{
+							// For each reagent found, find the properties associated with its reagent type
+							$propToOutput_ar = initializeDefaultOutput($temp_ar["reagentTypeID"]);
+							$alias_ar = makeAliases($propToOutput_ar);
+
+							$propToOutput_str = "('";
+							$prop_count = 0;
+
+							// Creates the array that will hold all the data for the given reagent type
+							$propOrderArray_ar = array_flip($propToOutput_ar);
+
+							foreach ($propOrderArray_ar as $key => $value)
+							{
+								$propOrderArray_ar[$key] = "";
+							}
+
+							foreach($propToOutput_ar as $i => $value)
+							{
+								// March 1, 2010
+								$propID = $_SESSION["ReagentProp_Name_ID"][$value];
+						
+								switch ($value)
+								{
+									case 'name':
+									case 'packet id':
+							
+									// display type for novel reagent types
+									case strtolower($_SESSION["ReagentType_ID_Name"][$temp_ar["reagentTypeID"]]) . ' type':
+									case 'type':
+										$category = "General Properties";
+									break;
+						
+									case 'entrez gene id':
+									case 'ensembl gene id':
+									case 'official gene symbol':
+									case 'accession number':
+										$category = "External Identifiers";
+									break;
+								}
+						
+								$propCatID_tmp = $rfunc_obj->getPropertyIDInCategory($propID, $_SESSION["ReagentPropCategory_Name_ID"][$category]);
+								
+								if ($propCatID_tmp > 0)
+								{
+									$propToOutput_str = $propToOutput_str . $propCatID_tmp . "','";
+									$prop_count++;
+								}
+							}
+
+							if( $prop_count > 0 )
+							{
+								$propToOutput_str = substr( $propToOutput_str, 0, strlen( $propToOutput_str ) - 2 ) . ")";
+							}
+							else
+							{
+								$propToOutput_str = "('')";
+							}
+
+							outputHeader($propOrderArray_ar, $firstHeader);
+							$lastReagentType = $temp_ar["reagentTypeID"];
+						}
+
+						$previewInfo_tmp = findoutputReagent_specific($propToOutput_str, $propOrderArray_ar, $temp_ar["reagentID"], $temp_ar["reagentTypeID"], $temp_ar["groupID"]);
+
+						outputReagentPreview($temp_ar["reagentID"], $gfunc_obj->getConvertedID($temp_ar["reagentTypeID"], $temp_ar["groupID"]), $previewInfo_tmp, "", "");
+
+						$numHits++;	// june 21/07
+					}
+				}
+			?>
+			</table>
+		</center>
+		<?php
+		mysql_free_result($reagentSearch_rs);
+//		mysql_free_result($tmp_search_rs_new);
+		unset($propToOutput_ar);
+		unset($previewInfo_tmp);
+		unset($temp_ar);
+	}
+
+	// March 19/10: moved this into search.php to print the number of hits at the bottom of the list, not after every reagent type
+// 	echo "Number of hits: " . $numHits . "<BR>";
+	unset($reagentSearch_rs);
+
+	// June 5/09
+	return $numHits;
+}
+
+
+# May 22/07, Marina
+# For every property name in $names_ar, select its alias from ReagentPropType_tbl
+/**
+* Generate a map of property names to their aliases
+*
+* @param Array names_ar
+*
+* @author John Paul Lee @version 2005
+* @author Marina Olhovsky @version 3.1
+*/
+function makeAliases($names_ar)
+{
+	global $conn;
+	
+	$aliases = array();
+	
+	foreach ($names_ar as $key=>$value)
+	{
+		$alias_rs = mysql_query("SELECT `propertyAlias` FROM `ReagentPropType_tbl` WHERE `propertyName`='" . $value . "'");
+		
+		if ($alias_ar = mysql_fetch_array($alias_rs, MYSQL_ASSOC))
+		{
+			$aliases[] = $alias_ar["propertyAlias"];
+		}
+	}
+	
+	mysql_free_result($alias_rs);
+	mysql_close();
+	
+	unset($alias_ar);
+	
+	return $aliases;
+}
+
+# May 22/07, Marina
+/**
+* @deprecated
+*/
+function makeTempTable($tableCols)
+{
+	global $conn;
+	
+	$numFields = sizeof($tableCols);
+	$count = 1;
+	
+	$query = "CREATE TABLE TEMP_SEARCH_PROPS(";
+	
+	
+	foreach ($tableCols as $key=>$value)
+	{
+		if ($count < $numFields)
+		{
+			$query .= $value . " VARCHAR(250), ";
+			$count++;
+		}
+		else
+		{
+			$query .= $value . " VARCHAR(250)";
+		}
+	}
+	
+	$query .= ")";
+
+	mysql_query($query, $conn) or die("Cannot create temp table: " . mysql_error());
+}
+
+
+/**
+* Output table column headers for the search results table
+*
+* @param Array previewHeaderInfo
+* @param boolean testHeader
+*
+* @author John Paul Lee @version 2005
+* @author Marina Olhovsky @version 3.1
+*/
+function outputHeader($previewHeaderInfo, $testHeader)
+{
+	global $Const_Table_Width;
+
+	if( !$testHeader )
+	{
+		echo "</table>";
+	}
+
+	echo "<table width=\"770px\" class=\"preview\">";
+
+	echo "<tr>";
+	
+	// added June 5/09
+	echo "<td class=\"searchCheckbox\">";
+		echo "<input type=\"checkbox\" ID=\"checkAllSearch\" onClick=\"(!this.checked) ? uncheckAll('ReagentCheckBox', []) : checkAll('ReagentCheckBox'); \" value=\"default\">";
+	echo "</td>";
+	
+	# May 22/07, Marina: Add sort option
+	if (isset($_POST["SearchArea"]) && isset($_POST["Keyword"]))
+	{
+		$searchCategory = $_POST["SearchArea"];
+		$keyword = trim($_POST["Keyword"]);
+	}
+	elseif (isset($_GET["SearchArea"]) && isset($_GET["Keyword"]))
+	{
+		$searchCategory = trim($_GET["SearchArea"]);
+		$keyword = trim($_GET["Keyword"]);
+	}
+		
+	// output a header column for the LIMS ID
+	echo "<th name=\"lims_id\" scope=\"col\" class=\"searchHeader\"><a href=\"" . $_SERVER["PHP_SELF"] . "?View=1&SearchArea=" . $searchCategory . "&Keyword=" . $keyword . "&sortBy=lims_id\">OpenFreezer ID</a></th>";
+	
+	// Step 1: Output headers for each main element property names
+	// June 22/07: Property names and header values may vary slightly (e.g. for property 'packet id' output heading 'Project ID')
+	foreach ($previewHeaderInfo as $key => $value)
+	{
+		switch ($key)
+		{
+			case 'packet id':
+				echo "<th scope=\"col\" name=\"" . $key . "\" class=\"searchHeader\"> <a href=\"" . $_SERVER["PHP_SELF"] . "?View=1&SearchArea=" . $searchCategory . "&Keyword=" . $keyword . "&sortBy=" . $key . "\">Project #</a></th>";
+			
+			break;
+			
+			default:
+				echo "<th scope=\"col\" name=\"" . $key . "\" class=\"searchHeader\"> <a href=\"" . $_SERVER["PHP_SELF"] . "?View=1&SearchArea=" . $searchCategory . "&Keyword=" . $keyword . "&sortBy=" . $key . "\">" . $key . "</a></th>";
+	
+			break;
+		}
+	}
+}
+
+
+/**
+* Search the reagent properties (not including description or LIMS IDs) for a given property.
+*
+* Will also take into account the filters set for the current search.
+*
+* NOTE: If no filter has been set, it will search for every reagent!
+*
+* @param STRING searchArea
+* @param STRING keyword
+*
+* @author John Paul Lee @version 2005
+* @author Marina Olhovsky @version 3.1
+*/
+function searchReagentProperties($searchArea, $keyword)
+{
+	global $conn;
+
+	$gfunc_obj = new generalFunc_Class();
+
+	# Sept 26/06 -- Account for escape sequence
+	$rfunc = new Reagent_Function_Class();
+
+	if (!get_magic_quotes_gpc())
+	{
+		$keyword = $rfunc->addQuotes($keyword);
+	}
+
+	// September 6, 2006, Marina, modified April 11/07
+	# Hack: copying internal option values for the categories list here, since cannot get them all from POST - needs to be fixed
+	$searchOptionValues[0] = "all";
+	$searchOptionValues[1] = "entrez gene id";
+	$searchOptionValues[2] = "packet id";
+	$searchOptionValues[3] = "ensembl gene id";
+	$searchOptionValues[4] = "official gene symbol";
+	$searchOptionValues[5] = "name";
+	$searchOptionValues[6] = "accession number";
+	$searchOptionValues[7] = "sequence";
+
+	$searchOptionCategories[1] = "External Identifiers";
+	$searchOptionCategories[2] = "General Properties";
+	$searchOptionCategories[3] = "External Identifiers";
+	$searchOptionCategories[4] = "External Identifiers";
+	$searchOptionCategories[5] = "General Properties";
+	$searchOptionCategories[6] = "General Properties";
+	
+	// added April 16/07 - find ID of 'status' property if asked to search for completed clones only
+	$searchOptionValues[7] = "status";
+
+	$propIDs = array();
+
+	foreach ($searchOptionValues as $key=>$val)
+	{
+		$catName = $searchOptionCategories[$key];
+		$catID = $_SESSION["ReagentPropCategory_Name_ID"][$catName];
+
+		$props_rs = mysql_query("SELECT propCatID FROM ReagentPropType_tbl t, ReagentPropertyCategories_tbl c WHERE t.propertyName='" . $val . "' AND t.propertyID=c.propID AND t.status='ACTIVE' AND c.status='ACTIVE' ", $conn) or die("Could not select properties: " . mysql_error());
+
+		while ($props_ar = mysql_fetch_array($props_rs, MYSQL_ASSOC))
+		{
+			$propIDs[$val] = $props_ar["propCatID"];
+		}
+	}
+
+	mysql_free_result($props_rs);
+	unset($props_ar);
+
+	// Modified May 15/09: no more checkboxes!
+	$filter_tmp = array();
+
+	$filterSet = "";	// filter by reagent type - V, I, O, C {1,2,3,4}
+	
+	if (isset($_POST["filter"]))		// if one of the reagent types is selected
+	{
+		foreach ($_POST["filter"] as $key => $value)
+		{
+			if (strcasecmp($value, "default") != 0)
+			{
+				if (strcasecmp($value, "Cell Line") == 0)
+				{
+					$filter_tmp[] = $_SESSION["ReagentType_Name_ID"]['CellLine'];
+				}
+				else
+				{
+					$filter_tmp[] = $_SESSION["ReagentType_Name_ID"][$value];
+				}
+
+				$filterSet = "('" . implode( "','", $filter_tmp ) . "')";
+			}
+			else	// search all reagent types
+			{
+				$filterSet = "('";
+		
+				foreach( $_SESSION["ReagentType_Name_ID"] as $key => $value )
+				{
+					$filterSet = $filterSet . $value . "','";
+				}
+		
+				$filterSet = substr( $filterSet, 0,  strlen( $filterSet ) - 2  ) . ")";
+			}
+		}
+	}
+	else	// search all reagent types
+	{
+		$filterSet = "('";
+
+		foreach( $_SESSION["ReagentType_Name_ID"] as $key => $value )
+		{
+			$filterSet = $filterSet . $value . "','";
+		}
+
+		$filterSet = substr( $filterSet, 0,  strlen( $filterSet ) - 2  ) . ")";
+	}
+
+	// September 6, 2006, Marina -- Filter search by categories
+	$searchCategory = $searchArea;
+	$results = array();
+
+	# Try searching for multiple keywords
+// 	$keywords_array = explode(" ", $keyword);
+// 	print_r($keywords_array);
+
+	# Find keyword in database, filter by specific category if given
+	if (strcasecmp($searchCategory, 'lims id') == 0)
+	{
+		# 'LIMS ID' property is now obsolete, newly created reagents don't have it.  Special case for searching
+		$tempType = $gfunc_obj->get_typeID($keyword);
+
+		# Now, user could omit reagent type altogether, only enter the group ID in the keyword box and use the reagent type filter.  Need to account for that case:
+		if ($tempType < 0)
+		{
+			# Check filter
+			foreach ($filter_tmp as $key=>$val)
+			{
+				$tempType = $val;
+				$tempGroup = $keyword;
+
+				if (isset($_POST["exact_match"]))
+					$srch = "='" . $tempGroup . "'";
+				else
+					$srch = "LIKE '%" . $tempGroup . "%'";
+				
+				// April 16/07: Search for completed reagents only - Added 'if' and 'else' blocks
+				if (isset($_POST["search_completed"]))
+				{
+					$statusPropID = $propIDs["status"];
+
+					if (isset($_POST["gs_only"]))
+					{
+						$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch . " AND b.`propertyID`= '" . $statusPropID . "' AND b.`propertyValue` LIKE '%completed%' AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND a.reagentID IN (select e.reagentID from Experiment_tbl e, Wells_tbl w, Container_tbl c, Isolate_tbl i, [...]
+					}
+					else
+					{
+						$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch . " AND b.`propertyID`= '" . $statusPropID . "' AND b.`propertyValue` LIKE '%completed%' AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY `reagentTypeID`, `groupID`", $conn) or die("Could not find reagent: " . mysql_error());
+					}
+				}
+				else
+				{
+					if (isset($_POST["gs_only"]))
+					{
+						$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch . " AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND a.reagentID IN (select e.reagentID from Experiment_tbl e, Wells_tbl w, Container_tbl c, Isolate_tbl i, Prep_tbl p where p.wellID=w.wellID and p.isolate_pk=i.isolate_pk and w.containerID=c [...]
+					}
+					else
+					{
+						$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch . " AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY `reagentTypeID`, `groupID`", $conn) or die("Could not find reagent: " . mysql_error());
+					}
+				}
+			}
+		}
+		else
+		{
+			$tempGroup = $gfunc_obj->get_groupID($keyword);
+
+			if (isset($_POST["exact_match"]))
+				$srch = "='" . $tempGroup . "'";
+			else
+				$srch = "LIKE '%" . $tempGroup . "%'";
+
+			// April 16/07: Search for completed reagents only - Added 'if' and 'else' blocks
+			if (isset($_POST["search_completed"]))
+			{
+				$statusPropID = $propIDs["status"];
+
+				if (isset($_POST["gs_only"]))
+				{
+					$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch . " AND b.`propertyID`= '" . $statusPropID . "' AND b.`propertyValue` LIKE '%completed%' AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND a.reagentID IN (select e.reagentID from Experiment_tbl e, Wells_tbl w, Container_tbl c, Isolate_tbl i,  [...]
+				}
+				else
+				{
+					$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch . " AND b.`propertyID`= '" . $statusPropID . "' AND b.`propertyValue` LIKE '%completed%' AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY `reagentTypeID`, `groupID`", $conn) or die("Could not find reagent: " . mysql_error());		
+				}
+			}
+			else
+			{
+				if (isset($_POST["gs_only"]))
+				{
+					$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch . " AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND a.reagentID IN (select e.reagentID from Experiment_tbl e, Wells_tbl w, Container_tbl c, Isolate_tbl i, Prep_tbl p where p.wellID=w.wellID and p.isolate_pk=i.isolate_pk and w.containerID=c. [...]
+				}
+				else
+				{
+					$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch . " AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY `reagentTypeID`, `groupID`", $conn) or die("Could not find reagent: " . mysql_error());
+				}
+			}
+		}
+	}
+	else if (strcasecmp($searchCategory, "all") != 0)
+	{
+		$catPropID = $propIDs[$searchCategory];		// e.g. [selectable marker] => ['58', '635']
+
+		if (isset($_POST["exact_match"]))
+			$srch = "='" . trim($keyword) . "'";
+		else
+			$srch = "LIKE '%" . trim($keyword) . "%'";
+	
+		// April 16/07: Search for completed reagents only - Added 'if' and 'else' blocks
+		if (isset($_POST["search_completed"]))
+		{
+			$statusPropID = $propIDs["status"];
+
+			if (isset($_POST["gs_only"]))
+			{
+				$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyID`='" . $catPropID . "' AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND [...]
+			}
+			else
+			{
+				$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyID`='" . $catPropID . "' AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND [...]
+			}
+		}
+		else
+		{
+			if (isset($_POST["gs_only"]))
+			{
+				$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyID`='" . $catPropID . "' AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND a.reagentID IN (select e.reagentID from Experiment_tbl e, Wells_tbl w, Container_tbl c, Isolate_tbl i, Prep_tbl p where p.wellID=w.wellID an [...]
+			}
+			else
+			{
+				$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyID`='" . $catPropID . "' AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY `reagentTypeID`, `groupID`", $conn) or die("Could not find reagent: " . mysql_error());
+			}
+		}
+	}
+	else	# Search category = 'All'
+	{
+		# the search term could, once again, be an OF ID
+		if ($gfunc_obj->get_rid($keyword) > 0)
+		{
+// echo "Keyword " . $keyword;
+
+// echo "what is this: " . $gfunc_obj->get_rid($keyword);
+
+			if (isset($_POST["exact_match"]))
+				$srch = "='" . trim($keyword) . "'";
+			else
+				$srch = "LIKE '%" . trim($keyword) . "%'";
+
+			# this is an ID; don't need to check filter, since $gfunc_obj->get_rid($keyword) > 0
+			$tempType = $gfunc_obj->get_typeID($keyword);
+			$tempGroup = $gfunc_obj->get_groupID($keyword);
+
+			if (isset($_POST["exact_match"]))
+				$srch_grp = "='" . trim($tempGroup) . "'";
+			else
+				// Feb. 17/10: Careful with this - the % in front of the group ID can result in C2 being matched to C12!
+				$srch_grp = "LIKE '%" . trim($tempGroup) . "%'";
+
+			// Important correction June 8/09 (done on production too!!): If filterSet is set, $tempType must be in it!!!
+			
+			// April 16/07: Search for completed reagents only - Added 'if' and 'else' blocks
+			if (isset($_POST["search_completed"]))
+			{
+				$statusPropID = $propIDs["status"];
+
+				if (isset($_POST["gs_only"]))
+				{
+					$searchResultSet = mysql_query("(SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`reagentTypeID` IN " . $filterSet .  " AND a.`groupID` " . $srch_grp . " AND b.`propertyID`= '" . $statusPropID . "' AND b.`propertyValue` LIKE '%completed%' AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'  AND a.reagentID IN (select e.reagentID from Experiment_t [...]
+				}
+				else
+				{
+					$searchResultSet = mysql_query("(SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`reagentTypeID` IN " . $filterSet .  " AND a.`groupID` " . $srch_grp . " AND b.`propertyID`= '" . $statusPropID . "' AND b.`propertyValue` LIKE '%completed%' AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY `reagentTypeID`, `groupID`) UNION (SELECT DISTIN [...]
+				}
+			}
+			else
+			{
+				if (isset($_POST["gs_only"]))
+				{
+					$searchResultSet = mysql_query("(SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`reagentTypeID` IN " . $filterSet .  " AND a.`groupID` " . $srch_grp . " AND a.`reagentID`=b.`reagentID` AND a.reagentID IN (select e.reagentID from Experiment_tbl e, Wells_tbl w, Container_tbl c, Isolate_tbl i, Prep_tbl p where p.wellID=w.wellID and p.isolate_pk=i.isolate_pk and w.containerID= [...]
+				}
+				else
+				{
+					$searchResultSet = mysql_query("(SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`reagentTypeID` IN " . $filterSet .  " AND a.`groupID` " . $srch_grp . " AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY `reagentTypeID`, `groupID`) UNION (SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropL [...]
+				}
+			}
+		}
+		else	// Search category = 'All', and keyword is not a reagent ID
+		{
+			if (isset($_POST["exact_match"]))
+				$srch = "='" . trim($keyword) . "'";
+			else
+				$srch = "LIKE '%" . trim($keyword) . "%'";
+
+			# Could be searching for:
+			# - a non-existent reagent
+			# - a group ID (with filter or without; if w/o, only search for properties)
+			# - a property (can restrict to a reagent type)
+
+			# And again, the user might be omitting reagent type from the keyword, OR searching for a partial OF ID
+			if (is_numeric($keyword))
+//			if (ctype_digit($keyword))	// Replaced Jan. 12/09, b/c is_numeric returns true if the search term is C12orf29
+			{
+				# this could be a group ID, but it could also be part of a property, so search both
+
+				# Check filter
+				if (isset($_POST["filter"]))
+				{
+					foreach ($filter_tmp as $key=>$val)
+					{	
+						$tempType = $val;
+						$tempGroup = $keyword;
+
+						if (isset($_POST["exact_match"]))
+							$srch_grp = "='" . trim($tempGroup) . "'";
+						else
+							$srch_grp = "LIKE '%" . trim($tempGroup) . "%'";
+
+						
+						if (isset($_POST["search_completed"]))
+						{
+							$statusPropID = $propIDs["status"];
+						
+							if (isset($_POST["gs_only"]))
+							{
+								$searchResultSet = mysql_query("(SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch_grp . " AND a.reagentID IN (select e.reagentID from Experiment_tbl e, Wells_tbl w, Container_tbl c, Isolate_tbl i, Prep_tbl p where p.wellID=w.wellID and p.isolate_pk=i.isolate_pk and w.containerID=c.containerID and i.expID=e.expID and c.contGroup [...]
+							}
+							else
+							{
+								$searchResultSet = mysql_query("(SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch_grp . " AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='ACTIVE') UNION (SELECT DISTIN [...]
+							}
+						}
+						else
+						{
+							if (isset($_POST["gs_only"]))
+							{
+								$searchResultSet = mysql_query("(SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch_grp . " AND a.`reagentID`=b.`reagentID` AND a.reagentID IN (select e.reagentID from Experiment_tbl e, Wells_tbl w, Container_tbl c, Isolate_tbl i, Prep_tbl p where p.wellID=w.wellID and p.isolate_pk=i.isolate_pk and w.containerID=c.containerID and i.expID=e.expID and c.co [...]
+							}
+							else
+							{
+								$searchResultSet = mysql_query("(SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch_grp . " AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE') UNION (SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $fi [...]
+							}
+						}
+					}
+				}
+				else
+				{
+					# only search properties, but check filter first
+					if (isset($_POST["filter"]))
+					{
+						if (isset($_POST["search_completed"]))
+						{
+							$statusPropID = $propIDs["status"];
+						
+							if (isset($_POST["gs_only"]))
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='ACTIVE' AND a.reagentID I [...]
+							}
+							else
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='ACTIVE'", $conn) or die(" [...]
+							}
+						}
+						else
+						{
+							if (isset($_POST["gs_only"]))
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . "  AND a.reagentID IN (select e.reagentID from Experiment_tbl e, Wells_tbl w, Container_tbl c, Isolate_tbl i, Prep_tbl p where p.wellID=w.wellID and p.isolate_pk=i.isolate_pk and w.containerID=c.containerID and i.expID=e.expID and [...]
+							}
+							else
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'", $conn) or die("Could not find reagent: " . mysql_error());
+							}
+						}
+					}
+					else
+					{
+						if (isset($_POST["search_completed"]))
+						{
+							$statusPropID = $propIDs["status"];
+						
+							if (isset($_POST["gs_only"]))
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c WHERE a.`reagentID`=b.`reagentID` AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='ACTIVE' AND a.reagentID IN (select e.reagentID from Experiment_tbl e, W [...]
+							}
+							else
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c WHERE a.`reagentID`=b.`reagentID` AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='ACTIVE' ORDER BY `reagentTypeID`, `groupID`", $conn) or die("Could not  [...]
+							}
+						}
+						else
+						{
+							if (isset($_POST["gs_only"]))
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentID`=b.`reagentID` AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND a.reagentID IN (select e.reagentID from Experiment_tbl e, Wells_tbl w, Container_tbl c, Isolate_tbl i, Prep_tbl p where p.wellID=w.wellID and p.isolate_pk=i.isolate_pk and w.containerID=c.containerID and i.expID=e.expID an [...]
+							}
+							else
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentID`=b.`reagentID` AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY `reagentTypeID`, `groupID`", $conn) or die("Could not find reagent: " . mysql_error());
+							}
+						}
+					}
+				}
+			}
+			else	// keyword is not numeric
+			{
+				# this may still be a partial ID!
+				$tempType = $gfunc_obj->get_typeID($keyword);
+	
+				# In this case we don't need to check the filter, since we already know the keyword is not numeric, so this is not a group ID
+
+				# however, this might not be a reagent ID after all:
+				if ($tempType < 0)
+				{
+					# this is not a reagent ID; just search properties
+					
+					// Jan. 21, 2011
+					$projectList = array_values($_POST["packets"]);
+					$projects = join($projectList, ",");
+					$projectPropID = $propIDs["packet id"];
+
+					# check completed first
+					if (isset($_POST["search_completed"]))
+					{
+						$statusPropID = $propIDs["status"];
+					
+						if ($projects != '0')
+						{
+							if (count($projectList) == 1)
+							{
+								if (isset($_POST["gs_only"]))
+								{
+									$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c, ReagentPropList_tbl d WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='A [...]
+								}
+								else
+								{
+									$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c, ReagentPropList_tbl d WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='A [...]
+								}
+							}
+							else
+							{
+								if (isset($_POST["gs_only"]))
+								{
+									$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c, ReagentPropList_tbl d WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='A [...]
+								}
+								else
+								{
+									$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c, ReagentPropList_tbl d WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='A [...]
+								}
+							}
+						}
+						else
+						{
+							if (isset($_POST["gs_only"]))
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='ACTIVE' AND a.reagentID I [...]
+							}
+							else
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='ACTIVE' ORDER BY `reagent [...]
+							}
+						}
+					}
+					else
+					{
+						// Jan. 21, 2011
+						$projectList = array_values($_POST["packets"]);
+						$projects = join($projectList, ",");
+
+						$projectPropID = $propIDs["packet id"];
+
+						if ($projects != '0')
+						{
+							if (count($projectList) == 1)
+							{
+								if (isset($_POST["gs_only"]))
+								{
+									$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, ReagentPropList_tbl c WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND c.reagentID=b.reagentID AND c.propertyID='" . $projectPropID . "' AND c.propertyValue='" . $projectList[0] . "' AND c.status='ACTIVE' AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND a.reagentID IN [...]
+								}
+								else
+								{
+									$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, ReagentPropList_tbl c WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND c.reagentID=b.reagentID AND c.propertyID='" . $projectPropID . "' AND c.propertyValue='" . $projectList[0] . "' AND c.status='ACTIVE' AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY `reagentT [...]
+								}
+							}
+							else
+							{
+								if (isset($_POST["gs_only"]))
+								{
+									$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, ReagentPropList_tbl c WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND c.reagentID=b.reagentID AND c.propertyID='" . $projectPropID . "' AND c.propertyValue IN (" . $projects . ") AND c.status='ACTIVE' AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND a.reagentID IN (s [...]
+								}
+								else
+								{
+									$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, ReagentPropList_tbl c WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND c.reagentID=b.reagentID AND c.propertyID='" . $projectPropID . "' AND c.propertyValue IN (" . $projects . ") AND c.status='ACTIVE' AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY `reagentType [...]
+								}
+							}
+						}
+						else
+						{
+							if (isset($_POST["gs_only"]))
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND a.reagentID IN (select e.reagentID from Experiment_tbl e, Wells_tbl w, Container_tbl c, Isolate_tbl i, Prep_tbl p where p.wellID=w.wellID and p.isolate_pk=i.isolate_pk and w.co [...]
+							}
+							else
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY `reagentTypeID`, `groupID`", $conn) or die("Could not find reagent: " . mysql_error());
+							}
+						}
+					}
+				}
+				else
+				{
+					# Could be either a reagent ID, OR something like 'V234abc'!!
+					# Therefore, make sure the portion after the leading alpha char is indeed numeric!
+					$tempTrail = substr($keyword, strlen($tempType), strlen($keyword));
+
+					if (ctype_digit($tempTrail))	// Replaced Jan. 12/09, b/c is_numeric returns true if the search term is C12orf29
+					{
+						# check status
+						if (isset($_POST["search_completed"]))
+						{
+							$statusPropID = $propIDs["status"];
+							$tempGroup = $gfunc_obj->get_groupID($keyword);
+
+							if (isset($_POST["exact_match"]))
+								$srch = "='" . $tempGroup . "'";
+							else
+								$srch = "LIKE '%" . $tempGroup . "%'";
+			
+							if (isset($_POST["gs_only"]))
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch . " AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='ACTIVE' AND a.reagentID IN (select [...]
+							}
+							else
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch . " AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='ACTIVE' ORDER BY `reagentTypeID`,  [...]
+							}
+						}
+						else
+						{
+							# May search for reagent ID (still no guarantees it would be found), or a property (yes, properties might be of the form 'C342' as well!)
+							$tempGroup = $gfunc_obj->get_groupID($keyword);
+			
+							if (isset($_POST["exact_match"]))
+								$srch = "='" . $tempGroup . "'";
+							else
+								$srch = "LIKE '%" . $tempGroup . "%'";
+			
+							if (isset($_POST["gs_only"]))
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch . " AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND a.reagentID IN (select e.reagentID from Experiment_tbl e, Wells_tbl w, Container_tbl c, Isolate_tbl i, Prep_tbl p where p.wellID=w.wellID and p.isolate_pk=i.isolate_pk and w.containerID [...]
+							}
+							else
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentTypeID`='" . $tempType . "' AND a.`groupID` " . $srch . " AND a.`reagentID`=b.`reagentID` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY `reagentTypeID`, `groupID`", $conn) or die("Could not find reagent: " . mysql_error());
+							}
+						}
+					}
+					else
+					{
+						# search properties
+						
+						# check status
+						if (isset($_POST["search_completed"]))
+						{
+							$statusPropID = $propIDs["status"];
+						
+							if (isset($_POST["gs_only"]))
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='ACTIVE' AND a.reagentID I [...]
+							}
+							else
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b, `ReagentPropList_tbl` c WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND c.`reagentID`=b.`reagentID` AND c.`propertyID`='" . $statusPropID . "' AND c.`propertyValue` LIKE '%completed%' AND c.status='ACTIVE' ORDER BY `reagent [...]
+							}
+						}
+						else
+						{
+							if (isset($_POST["gs_only"]))
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' AND a.reagentID IN (select e.reagentID from Experiment_tbl e, Wells_tbl w, Container_tbl c, Isolate_tbl i, Prep_tbl p where p.wellID=w.wellID and p.isolate_pk=i.isolate_pk and w.co [...]
+							}
+							else
+							{
+								$searchResultSet = mysql_query("SELECT DISTINCT a.`reagentID`, a.`reagentTypeID`, a.`groupID` FROM `Reagents_tbl` a, `ReagentPropList_tbl` b WHERE a.`reagentID`=b.`reagentID`  AND a.`reagentTypeID` IN " . $filterSet .  " AND b.`propertyValue` ". $srch . " AND a.`status`='ACTIVE' AND b.`status`='ACTIVE' ORDER BY `reagentTypeID`, `groupID`", $conn) or die("Could not find reagent: " . mysql_error());
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	unset($propIDs);
+	unset($conn);		// ????????????
+
+	return $searchResultSet;
+}
+
+
+/**
+* @deprecated
+*/
+function getIDSet($keyword)
+{
+	global $conn;
+	$keyword = trim( $keyword );
+	
+	$reagentID_set = "('";
+	$reagent_type = -1;		// 5/16/06
+	$rid_count = 0;
+
+	if( strncasecmp( $keyword, "Vector", 1 ) == 0 )
+	{
+		$reagent_type = $_SESSION["ReagentType_Name_ID"]["Vector"];
+	}
+	elseif( strncasecmp( $keyword, "Insert", 1 ) == 0 )
+	{
+		$reagent_type = $_SESSION["ReagentType_Name_ID"]["Insert"];
+	}
+	elseif( strncasecmp( $keyword, "Oligo", 1 ) == 0 )
+	{
+		$reagent_type = $_SESSION["ReagentType_Name_ID"]["Oligo"];
+	}
+	elseif( strncasecmp( $keyword, "CellLine", 1 ) == 0 )
+	{
+		$reagent_type = $_SESSION["ReagentType_Name_ID"]["CellLine"];
+	}
+	
+	// May 16/06, Marina
+	if ($reagent_type > 0)
+	{
+//echo "reagent_type : " . $reagent_type . "<BR>";
+//echo "keyword: " . substr( $keyword, 1 ) . "<BR>";
+		$find_reagentID_rs = mysql_query( "SELECT * FROM `Reagents_tbl` WHERE `reagentTypeID`='" . $reagent_type . "'"
+		. " AND `groupID` LIKE '" . substr( $keyword, 1 ) . "' AND `status`='ACTIVE'" , $conn ) or die( "Error trying to find the general reagent ID (2) : " . mysql_error());
+	}
+	else	// 5/16/06
+	{
+//echo "reagent_type : " . $reagent_type . "<BR>";
+//echo "keyword: " . substr( $keyword, 1 ) . "<BR>";
+		$find_reagentID_rs = mysql_query( "SELECT * FROM `Reagents_tbl` WHERE `groupID` LIKE '" . $keyword . "' AND `status`='ACTIVE'" , $conn ) or die( "Error trying to find the general reagent ID (2) : " . mysql_error() );
+	}
+
+	while( $find_reagentID_ar = mysql_fetch_array( $find_reagentID_rs, MYSQL_ASSOC ) )
+	{
+		$rid_count++;
+		$reagentID_set = $reagentID_set . $find_reagentID_ar["reagentID"] . "','";
+	}
+	
+	if( $rid_count > 0 )
+	{
+		$reagentID_set = substr( $reagentID_set, 0,  strlen( $reagentID_set ) - 2  ) . ")";
+	}
+	else
+	{
+		$reagentID_set = "('')";
+	}
+	
+	return $reagentID_set;
+}
+
+
+/**
+* @deprecated
+*/
+function searchMethodProperty()
+{
+}
+
+
+/**
+* Perform a JOIN of Comments and Properties tables to retrieve the full-length value of a comment, which is stored in Comments_tbl and referenced as a foreign key in Properties_tbl
+*
+* @param STRING keyword
+*
+* @author John Paul Lee @version 2005
+* @author Marina Olhovsky @version 3.1
+*/
+function searchCommentProperty($keyword)
+{
+	global $conn;
+	
+	$test_rs = mysql_query( "SELECT  DISTINCT a.`prepID` , a.`comments`  AS value, b.`value`  AS originalID 
+							FROM  `Prep_tbl` a
+							INNER  JOIN  `PrepElementProp_tbl` b ON a.`PrepID`  = b.`prepID` 
+							WHERE a.`comments` 
+							LIKE  '%" . $keyword . "%' 
+							AND a.`status`='ACTIVE'
+							AND b.`status`='ACTIVE'
+							AND b.`elementTypeID`  =  '1'", $conn );
+	return $test_rs;
+}
+
+
+// Modified June 21/07, Marina: Add 'project id' property
+/**
+* Return a list of default properties searched for each reagent type
+*
+* @param INT Reagent type
+*
+* @author John Paul Lee @version 2005
+* @author Marina Olhovsky @version 3.1
+*/
+function initializeDefaultOutput($type)
+{
+	// March 18/09, Marina: Since tag type is now a feature that could potentially have multiple values, and tag position is a descriptor for it, remove from search output
+// 	$vectorDefault_ar = array(0=>"packet id", 1=>"name", 2=>"vector type", 3=>"status", 4=>"tag type", 5=>"tag position", 6=>"description");
+	$vectorDefault_ar = array(0=>"packet id", 1=>"name", 2=>"vector type", 3=>"status", 4=>"tag", 5=>"description");
+
+	$insertDefault_ar[] = "packet id";
+	$insertDefault_ar[] = "name";
+	$insertDefault_ar[] = "status";
+	$insertDefault_ar[] = "type of insert";
+	$insertDefault_ar[] = "open/closed";
+	$insertDefault_ar[] = "length";
+	$insertDefault_ar[] = "comments";
+
+	$oligoDefault_ar[] = "packet id";
+	$oligoDefault_ar[] = "name";
+	$oligoDefault_ar[] = "sequence";
+	$oligoDefault_ar[] = "length";
+	$oligoDefault_ar[] = "oligo type";	# marina, oct 19/06, changed from 'sense'
+	$oligoDefault_ar[] = "protocol";
+	
+	$cellLineDefault_ar[] = "packet id";
+	$cellLineDefault_ar[] = "name";
+	$cellLineDefault_ar[] = "status";
+	$cellLineDefault_ar[] = "cell line type";
+	$cellLineDefault_ar[] = "parent vector name";
+	$cellLineDefault_ar[] = "parent cell line name";
+	$cellLineDefault_ar[] = "description";
+
+	$propToOutput_ar = array();
+	$propToOutput_str = "('";
+	
+	switch ($type)
+	{
+		case $_SESSION["ReagentType_Name_ID"]["Vector"]:
+			$propToOutput_ar = $vectorDefault_ar;
+		break;
+
+		case $_SESSION["ReagentType_Name_ID"]["Insert"]:
+			$propToOutput_ar = $insertDefault_ar;
+		break;
+
+		case $_SESSION["ReagentType_Name_ID"]["Oligo"]:
+			$propToOutput_ar = $oligoDefault_ar;
+		break;
+
+		case $_SESSION["ReagentType_Name_ID"]["CellLine"]:
+			$propToOutput_ar = $cellLineDefault_ar;
+		break;
+
+		default:
+			// Modified June 1/09
+			$propToOutput_ar = array("name", "packet id", "status", "type", "description");
+		break;
+	}
+	
+	return $propToOutput_ar;
+}
+
+
+/**
+* Find the basic information for each reagent that matches the search parameters
+*
+* @param STRING A string representing the list of IDs of the properties to be displayed, separated by commas and enclosed in brackets, e.g.  ('5','3','14','15','21','13'))
+* @param Array An array containing the names of properties to be displayed, e.g. Array ( [name] => [status] => [5' cloning site] => [3' cloning site] => [open/closed] => [comments] => ) )
+* @param INT $tempReagentID ID of the reagent whose properties are currently being displayed
+* @param INT $type Type of this reagent
+* @param INT $groupNum GroupID of this reagent
+*
+* @return resultset
+*/
+function findoutputReagent_specific($preview_str, $storePreview_ar, $tempReagentID, $type, $groupNum)
+{
+	global $conn;
+
+	// Mar 31/06, Marina
+	// Added to change the way some properties are displayed 
+	// e.g. 'description' and 'comments' were showing the ID of the property in the General Comments table
+	// 'sense' was showing as either 'a' or 's', not the full word
+	// perhaps more to be added
+
+	$tmp_sequence  = "";	// Aug 31/06
+
+	foreach ($storePreview_ar as $key => $value)
+	{
+		// Feb. 28/10: add category
+		if ($key == 'type')
+			$propID = $_SESSION["ReagentProp_Name_ID"][$_SESSION["ReagentType_ID_Name"][$type] . " type"];
+		else
+			$propID = $_SESSION["ReagentProp_Name_ID"][$key];
+
+		$rfunc_obj = new Reagent_Function_Class();
+
+		switch ($key)
+		{
+			case 'name':
+			case 'packet id':
+			case 'vector type':
+			case 'oligo type':
+			case 'cell line type':
+			case 'type':
+			case $_SESSION["ReagentType_ID_Name"][$type] . " type":
+			case 'status':
+			case 'description':
+			case 'comments':
+				$category = "General Properties";
+			break;
+
+			case 'length':
+			case 'sequence':
+				$category = "DNA Sequence";
+			break;
+
+			case 'tag':
+				$category = "DNA Sequence Features";
+			break;
+
+			case 'entrez gene id':
+			case 'ensembl gene id':
+			case 'official gene symbol':
+			case 'accession number':
+				$category = "External Identifiers";
+			break;
+
+			case 'type of insert':
+			case 'open/closed':
+			case 'protocol':
+				$category = "Classifiers";
+			break;
+		}
+
+		$propId_tmp = $rfunc_obj->getPropertyIDInCategory($propID, $_SESSION["ReagentPropCategory_Name_ID"][$category]);
+
+		// Specific property formatting
+		if ($key != 'description' && $key != 'comments')
+		{
+			if ($key == 'sequence')	// May 30/06
+			{
+				$normal_rs = mysql_query("SELECT a.`sequence` FROM `Sequences_tbl` a, `ReagentPropList_tbl` b WHERE b.`propertyID` = '". $propId_tmp . "' AND b.`reagentID`='" . $tempReagentID . "' AND a.`seqID` = b.`propertyValue` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'", $conn) or die( "Failure in searchOutput_reagent.findoutputReagent_specific(2): " . mysql_error() );
+
+				while( $normal_ar = mysql_fetch_array( $normal_rs, MYSQL_ASSOC ) )
+				{
+					$storePreview_ar[$key] = $normal_ar["sequence"];
+					$tmp_sequence =  $normal_ar["sequence"];
+				}
+			}
+			else if ($key == 'length')	# sept 26/06
+			{
+				$propId_tmp = $rfunc_obj->getPropertyIDInCategory($_SESSION["ReagentProp_Name_ID"]["sequence"], $_SESSION["ReagentPropCategory_Name_ID"]["DNA Sequence"]);
+
+				# Find sequence and calculate its length on the spot
+				$foundSeqID_rs = mysql_query("SELECT s.`sequence` FROM `ReagentPropList_tbl` p, `Sequences_tbl` s WHERE p.`reagentID`='" . $tempReagentID . "' AND p.`propertyID` = '" . $propId_tmp . "' AND s.`seqID`=p.`propertyValue` AND p.`status`='ACTIVE' AND s.`status`='ACTIVE'", $conn);
+
+				if ($foundSeqID_ar = mysql_fetch_array($foundSeqID_rs, MYSQL_ASSOC))
+				{
+					$sequence = $foundSeqID_ar["sequence"];
+
+					if (strlen($sequence) > 0)
+					{
+						$storePreview_ar["length"] = strlen($sequence);
+					}
+				}
+			}
+			// March 20/09
+			else if ($key == 'tag')
+			{
+				$normal_rs = mysql_query("SELECT propertyID, propertyValue, descriptor FROM ReagentPropList_tbl WHERE reagentID='" . $tempReagentID . "' AND status='ACTIVE' AND propertyID='". $propId_tmp . "'", $conn) or die("Failure in searchOutput_reagent.findoutputReagent_specific(2): " . mysql_error());
+
+				while ($normal_ar = mysql_fetch_array($normal_rs, MYSQL_ASSOC))
+				{
+					if ($normal_ar["descriptor"] && ($normal_ar["descriptor"] != ""))
+					{
+						$storePreview_ar[$key][] = $normal_ar["propertyValue"] . "/" . $normal_ar["descriptor"];
+					}
+					else
+					{
+						$storePreview_ar[$key][] = $normal_ar["propertyValue"];
+					}
+				}
+			}
+			else
+			{
+				$normal_rs = mysql_query("SELECT `propertyID`, `propertyValue` FROM `ReagentPropList_tbl` WHERE `reagentID`='" . $tempReagentID . "' AND `status`='ACTIVE' AND `propertyID` = '". $propId_tmp . "'", $conn) or die( "Failure in searchOutput_reagent.findoutputReagent_specific(2): " . mysql_error() );
+
+				while( $normal_ar = mysql_fetch_array( $normal_rs, MYSQL_ASSOC ) )
+				{
+					if ($key == 'oligo type')
+					{
+						// Display 'sense' or 'antisense' instead of letters 'a' and 's'
+						// Only set in display variable ($storePreview_ar); therefore, the actual property value is not affected
+						if ((strcasecmp($normal_ar["propertyValue"], 'a') == 0) || (strcasecmp($normal_ar["propertyValue"], 'antisense') == 0))
+						{
+							$storePreview_ar[$key] = "Antisense";
+						}
+						elseif ((strcasecmp($normal_ar["propertyValue"], 's') == 0) || (strcasecmp($normal_ar["propertyValue"], 'sense') == 0))
+						{
+							$storePreview_ar[$key] = "Sense";
+						}
+					}
+					else
+					{
+						$storePreview_ar[$key] = $normal_ar["propertyValue"];
+					}
+				}
+			}
+		}
+		else
+		{
+			$normal_rs = mysql_query("SELECT a.`comment` FROM `GeneralComments_tbl` a, `ReagentPropList_tbl` b WHERE b.`propertyID` = '". $propId_tmp . "' AND b.`reagentID`='" . $tempReagentID . "' AND a.`commentID` = b.`propertyValue` AND a.`status`='ACTIVE' AND b.`status`='ACTIVE'", $conn) or die( "Failure in searchOutput_reagent.findoutputReagent_specific(2): " . mysql_error() );
+
+			while( $normal_ar = mysql_fetch_array( $normal_rs, MYSQL_ASSOC ) )
+			{
+				$storePreview_ar[$key] = $normal_ar["comment"];
+			}
+		}
+	}
+
+	return $storePreview_ar;
+}
+
+
+/**
+* Display the specific properties for each reagent returned by the search query.
+*
+* @param INT
+* @param INT
+* @param Array
+* @param INT
+* @param MIXED
+*/
+function outputReagentPreview($rid_tmp, $LIMSID_tmp, $previewInfo_tmpArr, $matchPropertyID_tmp, $matchPropertyValue_tmp)
+{
+	global $conn;
+
+	$gfunc = new generalFunc_Class();
+	$bfunc_obj = new Reagent_Background_Class();	// Aug. 12/09
+	$rfunc = new Reagent_Function_Class();
+
+	// Aug. 12/09: check authorization for deletion
+	$currUserName = $_SESSION["userinfo"]->getDescription();
+	$currUserID = $_SESSION["userinfo"]->getUserID();
+	$currUserCategory = $_SESSION["userinfo"]->getCategory();
+	$userProjects = getUserProjectsByRole($currUserID, 'Writer');
+	$rIDpID = getReagentProjectID($rid_tmp);
+	$rChildren = $bfunc_obj->getReagentChildren($rid_tmp);
+	
+	$rTypeID = $rfunc->getType($rid_tmp);
+
+	$delete_restricted = true;
+
+	echo "<INPUT TYPE=\"hidden\" ID=\"lims_id_" . $LIMSID_tmp . "\" VALUE=\"" . $LIMSID_tmp . "\">";
+
+	// Aug. 12/09: Disallow deletion if this reagent has children!
+/*	if ($currUserName == 'Administrator')
+	{
+		$delete_restricted = false;
+	}
+	else*/
+
+	/*if ($rIDpID <= 0)	// Feb. 16/10
+	{
+		$delete_restricted = false;
+	}
+	else*/ if (sizeof($rChildren) == 0)
+	{
+		// Feb. 16/10: no children, check location
+		$loc_obj = new Location_Output_Class();
+		$child_expID = $loc_obj->getExpID($rid_tmp);
+
+		// Feb. 18/10: This is not sufficient.  When preps (wells) for a particular reagent are deleted, rows are deleted from Isolates_tbl, but Experiment_tbl entry is untouched.  Therefore, in order to check if preps exist, need to count the number of ISOLATES:
+		$num_isolates = 0;
+
+		// echo $child_expID;
+		
+		if ($child_expID > 0)
+		{
+		// echo "SELECT COUNT(isolate_pk) as num_iso FROM Isolate_tbl WHERE expID='" . $child_expID . "' AND status='ACTIVE'";
+		
+			$num_isolates_rs = mysql_query("SELECT COUNT(isolate_pk) as num_iso FROM Isolate_tbl WHERE expID='" . $child_expID . "' AND status='ACTIVE'", $conn) or die("Cannot fetch isolates: " . mysql_error());
+		
+			if ($num_isolates_ar = mysql_fetch_array($num_isolates_rs, MYSQL_ASSOC))
+			{
+				$num_isolates = $num_isolates_ar["num_iso"];
+		// 		echo $num_isolates;
+			}
+		}
+		
+		// echo $num_isolates;
+
+		if (($child_expID < 1) || ($num_isolates == 0))
+// 		if ($child_expID < 1)
+		{
+			// No location, BUT - Dec. 16/09: STILL check if user has project Write access!!!
+			if (!in_array($rIDpID, $userProjects))
+			{
+				if ($currUserName == 'Administrator')
+				{
+					$delete_restricted = false;
+				}
+				else
+				{
+					$delete_restricted = true;
+				}
+			}
+			else
+			{
+				// no location and project writer, can delete
+				$delete_restricted = false;
+			}
+		}
+		else
+		{
+			// NO ONE, NOT EVEN ADMIN, can delete if has location
+			$delete_restricted = true;
+
+			echo "<INPUT TYPE=\"hidden\" ID=\"write_access_" . $rid_tmp . "\" VALUE=\"" . $LIMSID_tmp . "\">";
+		}
+
+// 		if ($rIDpID <= 0)
+// 		{
+// 			$delete_restricted = false;
+// 		}
+// 		else if ($rIDpID > 0)
+// 		{
+// 			if ($currUserName == 'Administrator')
+// 			{
+// 				$delete_restricted = false;
+// 			}
+// 			else if (in_array($rIDpID, $userProjects))
+// 			{
+// 				$delete_restricted = false;
+// 			}
+// 			else
+// 			{
+// 				$delete_restricted = true;
+// 				echo "<INPUT TYPE=\"hidden\" ID=\"write_access_" . $rid_tmp . "\" VALUE=\"" . $LIMSID_tmp . "\">";
+// 			}
+// 		}
+	}
+	else
+	{
+		$delete_restricted = true;
+		echo "<INPUT TYPE=\"hidden\" ID=\"has_children_" . $rid_tmp . "\" VALUE=\"" . $LIMSID_tmp . "\">";
+	}
+
+	if ($delete_restricted)
+		$disabled = "DISABLED";
+	else
+		$disabled = "";
+
+	echo "<INPUT TYPE=\"hidden\" ID=\"del_status_rid_" . $LIMSID_tmp . "\">";
+
+	echo "<tr>";
+
+	// Step 3: Output corressponding values for those headers
+	echo "<td class=\"searchCheckbox\">";
+		echo "<input type=\"checkbox\" " . $disabled . " name=\"ReagentCheckBox[]\" value=" . $rid_tmp . ">";
+	echo "</td>";
+
+	// output the LIMS ID
+	echo "<td class=\"preview\">" . $LIMSID_tmp . "</td>";
+
+	foreach($previewInfo_tmpArr as $key => $value )
+	{
+// echo $key;
+// echo $value;
+		if (strcasecmp($key, "tag") == 0)
+		{
+			echo "<td class=\"preview\">";
+
+			if (sizeof($value) == 1)
+			{
+				echo $value[0];
+			}
+			else
+			{
+				$tagTypeOutput = "";
+
+				foreach ($value as $x => $tagTypeOutput)
+				{
+					// don't place separator after last entry
+					if ($x != sizeof($value)-1)
+						echo $tagTypeOutput . ', ';
+					else
+						echo $tagTypeOutput;
+				}
+			}
+			echo "</td>";
+		}
+		else if ((strcasecmp($key, "type") != 0)&& (!in_array($key, $_SESSION["ReagentProp_ID_Name"]) || specialCol($key, $value)))
+		{
+			outputSpecializedColumns($rid_tmp, $key, "Preview");
+		}
+		else
+		{
+			echo "<td class=\"preview\">" . $value . "</td>";
+		}
+	}
+
+	echo "<td>";
+		echo "<a class=\"search\" href=\"Reagent.php?View=6&rid=" . $rid_tmp . "\">Detailed View</a></td>";
+	echo "</td>";
+
+	echo "<td>";
+		echo "<a class=\"search\" href=\"Location.php?View=1&rid=" . $rid_tmp . "\">Location</a>";
+	echo "</td>";
+
+	// Only show Primer Design button for Inserts
+	if ($gfunc->get_typeID($gfunc->getConvertedID_rid($rid_tmp)) == 2)
+	{
+		echo "<td>";
+			echo "<a class=\"search\" href=\"Reagent.php?View=7&rid=" . $rid_tmp . "\">Primer Design</a>";
+		echo "</td>";
+	}
+
+	echo "</tr>";
+}
+
+
+// function: outputSpecializedColumns()
+// Defn: Will process and output (with td tags) the wanted value found through a special column type
+/**
+* Process and output (with td tags) the wanted value found through a special column type
+*
+* @see ColFunctOutputer
+* @author John Paul Lee @version 2005
+*/
+function outputSpecializedColumns($rid_tmp, $colType, $outputType)
+{
+	echo "<td class=\"preview\">";
+		$outputer = new ColFunctOutputer;
+		echo $outputer->output($rid_tmp, $colType, $outputType);
+	echo "</td>";
+	
+}
+
+// function: getSpecializedColumns()
+// Defn: Will process and return the wanted value found through a special column type
+/**
+* Process and return the wanted value found through a special column type
+*
+* @see ColFunctOutputer
+* @author John Paul Lee @version 2005
+*/
+function getSpecializedColumns( $rid_tmp, $colType, $outputType )
+{
+	$outputer = new ColFunctOutputer;
+	$toreturn = $outputer->output( $rid_tmp, $colType, $outputType );
+	unset( $outputer );
+	
+	return $toreturn;
+}
+?>
diff --git a/OpenFreezer/User.php b/OpenFreezer/User.php
new file mode 100755
index 0000000..1c15e6f
--- /dev/null
+++ b/OpenFreezer/User.php
@@ -0,0 +1,1757 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2010 Pawson Laboratory, All Rights Reserved
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package User
+*
+* @copyright  2005-2010 Pawson Laboratory
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Include/require statements
+*/
+	include_once "Classes/MemberLogin_Class.php";
+
+	include_once "Project/ProjectFunctions.php";		// Aug 10/07; it includes Member_Class so don't need to redeclare it here
+
+	include_once "Classes/Session_Var_Class.php";
+	include_once "Classes/generalFunc_Class.php";
+
+	include "Classes/StopWatch.php";
+
+	// Feb. 16, 2011: Reagent_Background_Class is needed in Order_Class, but cannot place the 'include' statement in Order_Class.php because it becomes a circular reference.  Place it here, before 'include Order_CLass'
+	include "Reagent/Reagent_Background_Class.php";
+
+	// Jan. 23/08: Order reagents
+	include "Location/Location_Funct_Class.php";
+	include "Classes/Order_Class.php";
+	
+	include_once "DatabaseConn.php";
+	include "HeaderFunctions.php";
+
+	include_once "menu.js";
+/**
+ * Root file for User module
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ * @package User
+ *
+ * @copyright	2005-2010 Pawson Laboratory
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+*/
+	/**
+	 * A constant used to define table width on User module views
+	 * @global INT $Const_Table_Width
+	*/
+	global $Const_Table_Width;
+
+	$colspan_const = 0;
+
+	/**
+	 * Hostname (e.g. http://openfreezer.org/)
+	 * @global STRING $hostname
+	*/
+	global $hostname;
+
+	header("Cache-control: private"); //IE 6 Fix
+
+	session_start();
+
+	$loginBlock = new MemberLogin_Class();
+	$loginBlock->loginCheck($_POST);
+
+	// print header
+	outputMainHeader();
+
+	/**
+	 * Email address of Dr Karen Colwill, the biologist leader of OpenFreezer: colwill at lunenfeld.ca
+	 * @global STRING $mail_biologist
+	*/
+	global $mail_biologist;		// June 3, 2010
+
+	/**
+	 * Email address of Marina Olhovsky, the programmer of OpenFreezer: olhovsky at lunenfeld.ca
+	 * @global STRING $mail_programmer
+	*/
+	global $mail_programmer;
+
+	?>
+	<title>Users and Labs</title>
+	
+	<div class="main">
+		<table border="0" valign="middle">
+			<!-- Marina: March 4/08: Create a resizeable border -->
+			<!--<tr>
+				<td rowspan="100%" style="padding-left:0; padding-right:5px;">
+					<div class="resizeable" onMouseOver="resize();"></div>
+				</td>
+			</tr>-->
+			<?php
+			if (isset($_SESSION["userinfo"]))
+			{
+				if ($loginBlock->verifyPermissions(basename($_SERVER["PHP_SELF"]), $_SESSION["userinfo"]->getUserID()))
+				{
+					$sessionChecker = new Session_Var_Class();
+					$sessionChecker->checkSession_all();
+					unset($sessionChecker);
+
+					$currUserID = $_SESSION["userinfo"]->getUserID();
+					$currUserName = $_SESSION["userinfo"]->getDescription();
+
+					?>
+					<tr>
+						<td>
+							<?php
+							if ($_GET["View"] == "1")
+							{
+								if ($_SESSION["userinfo"]->getCategory() == 1)
+								{
+									// Create users
+									if (isset($_GET["ErrCode"]))
+									{
+										// read error page content from file
+										// Page content was generated by Python and stored in a file
+										if (isset($_GET["fd"]) && $_GET["fd"] != "")
+										{
+											$user_file = "/tmp/tmp" . $_GET["fd"] . ".html";
+										
+											$user_fh = fopen($user_file, 'r');
+											$user_page = fread($user_fh, filesize($user_file));
+											echo $user_page;
+											
+											unlink($user_file);
+										}
+										else
+										{
+											echo "Error: this username already exists";
+										}
+									}
+									else
+									{
+										printUserCreationForm();
+									}
+								}
+								else
+								{
+									// redirect
+									// this does NOT work!!
+// 									header("Location:" . $hostname . "index.php");
+									?><SCRIPT LANGUAGE="javascript">window.location.href="<?php echo $_SERVER["PHP_SELF"] . "?View=6"; ?>";</script><?php
+								}
+							}
+							
+							elseif ($_GET["View"] == "2")
+							{
+								// delete user
+								if (isset($_GET["Del"]))
+								{
+									echo "<span style=\"color:#0000FF; font-weight:bold;\">User deleted successfully.</span>";
+								}
+								else
+								{		
+									printSearchUserForm();
+
+									if (isset($_POST["search_user"]))
+									{
+										findUser();
+									}
+								}
+							}
+							elseif ($_GET["View"] == "3")
+							{
+								// add lab
+								if (!isset($_GET["Lab"]))
+								{
+									printLabCreationForm();
+								}
+							}
+							
+							elseif ($_GET["View"] == "4")
+							{
+								// lab detailed view
+								printViewLabForm();
+							}
+							elseif ($_GET["View"] == "5")
+							{
+								// delete lab
+								echo "<span style=\"color:#0000FF; font-weight:bold;\">Laboratory deleted successfully.</span><BR>";
+
+								echo "<P><a href=\"" . $_SERVER["PHP_SELF"]. "?View=4\">Back to Lab list</a>";
+							}
+							elseif ($_GET["View"] == "6")
+							{
+								// Change password
+								if (isset($_POST["change_pw"]))
+								{
+									$old_pw = trim($_POST["old_pw"]);
+									$new_pw = trim($_POST["new_pw"]);
+									$new_pw_conf = trim($_POST["new_pw_2"]);
+												
+									$currPW = $_SESSION["userinfo"]->getPassword();
+									
+									if (strcasecmp(md5($old_pw), $currPW) != 0)
+									{
+										printFormChangePasswd(true, false, false);
+									}
+									else if (strcasecmp($new_pw, $new_pw_conf) != 0)
+									{
+										printFormChangePasswd(false, true, false);
+									}
+									else if (strcasecmp($new_pw, $old_pw) == 0)
+									{
+										printFormChangePasswd(false, false, true);
+									}
+									else
+									{
+										mysql_query("UPDATE Users_tbl SET password=MD5('" . $new_pw . "') WHERE userID='" . $currUserID . "' AND status='ACTIVE'");
+										echo "Your password has been changed successfully.  Please use the new password on your next login.";
+									}
+								}
+								else
+								{
+									printFormChangePasswd();
+								}
+							}
+							// Jan. 23/08: Order clones
+							elseif ($_GET["View"] == "8")
+							{
+								outputOrders();
+							}
+							// Jan. 23/08: Remove reagents from order
+							else if ($_GET["View"] == "9")
+							{
+// 								print_r($_POST);
+								$tmpOrder = new Order_Class();
+								$tmpOrder->removeFromOrder($_POST["removeFromOrder"]);
+								outputOrders();
+							}
+							?>
+						</td>
+					</tr>
+					<?php
+				}
+				else
+				{
+					echo "<tr><td class=\"warning\">";
+					echo "Please log in to access this page.";
+					echo "</td></tr>";
+				}
+			}
+			else
+			{
+				// June 1, 2010: Automated password reset
+				if (isset($_POST["reset_pw"]))
+				{
+					printFormPasswdReset();
+				}
+				else if (isset($_GET["Reset"]))
+				{
+					switch ($_GET["Reset"])
+					{
+						case '1':
+							if (isset($_GET["uid"]))
+							{
+								$email = $loginBlock->getUserEmail($_GET["uid"]);
+	
+								echo "<span style=\"color:blue;\">A temporary password has been emailed to " . $email . ". Please change this password on your next login.</span>";
+							}
+							else
+							{
+								echo "Could not retrieve user ID.  Please contact administrator.";
+							}
+						break;
+						
+						case '0':
+							echo "<span style=\"color:red\">Error setting password: Could not match the username provided to an existing OpenFreezer user account.<BR>";
+
+							echo "<P>If you have not yet obtained an OpenFreezer user account, please <a href='mailto:" . $mail_programmer . "'>contact the administrator</a>.</span>";
+						break;
+						
+						default:
+						break;
+					}
+				}
+				else
+				{
+					echo "<tr><td class=\"warning\">";
+					echo "Please log in to access this page.";
+					echo "</td></tr>";
+				}
+			}
+		?>
+		</table>
+	</div>
+	
+	<?php
+
+	outputMainFooter();
+	
+
+	/*********************************
+	*	FUNCTIONS
+	*********************************/
+
+/**
+ * @name Print form for addition of new users into OpenFreezer
+ *
+*/
+function printUserCreationForm()
+{
+	global $cgi_path;
+	global $conn;
+	
+	// Duplicate username error
+	$showUsernameWarning = (isset($_GET["ErrCode"]) && ($_GET["ErrCode"] == 'Dup_un')) ? "inline" : "none";
+	
+	// get username from session
+	$currUserName = $_SESSION["userinfo"]->getDescription();
+	?>
+		<FORM NAME="create_user_form" METHOD="POST" ACTION="<?php echo $cgi_path . "user_request_handler.py"; ?>" onSubmit="return verifyAddUser();">
+			<!-- Pass user info as a hidden form value - currently the most secure way to pass session info from PHP to Python -->
+			<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+			<TABLE width="760px" cellpadding="5" cellspacing="5">
+			
+				<TH colspan="4" style="color:#0000FF; border-top:1px groove black; border-bottom: 1px groove black; padding-top: 10px; padding-top:5px;">
+					ADD NEW USER
+					<P style="color:#FF0000; font-weight:normal; font-size:8pt; margin-top:5px;">Fields in red marked with an asterisk (<span style="font-size:9pt; color:#FF0000;">*</span>) are mandatory</P>
+				</TH>
+				
+				<TR>
+					<TD style="width:150px; vertical-align:top; padding-top:10px; color:#FF0000;">
+						Laboratory: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+					</TD>
+					
+					<TD style="vertical-align:top; padding-top:10px">
+						<?php printLabList(); ?>
+						<BR/>
+						<P id="lab_warning" style="color:#FF0000; display:none">Please select a laboratory name from the dropdown list above.</P>
+					</TD>
+				</TR>
+				
+				<TR>
+					<TD class="createViewColName" style="color:#FF0000;">
+						Username: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+					</TD>
+
+					<TD class="createViewColValue">
+						<INPUT TYPE="TEXT" SIZE="35px" id="user_name" NAME="username"/>
+						<BR/>
+						<!-- Warning anchor -->
+						<a name="w1" style="text-decoration:none; font-weight:normal; font-size:8pt">
+						<P id="dup_uname_warning" style="color:#FF0000; display:<?php echo $showUsernameWarning; ?>">This username already exists.  Please specify a different username.</P>
+						</a>
+					</TD>
+
+					<TD style="font-size:8pt">
+<!-- 						Alphanumeric string up to 10 characters used to log into the system. -->
+					</TD>
+				</TR>
+				
+				<TR>
+					<TD class="createViewColName" style="color:#FF0000;">
+						First name: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+					</TD>
+
+					<TD class="createViewColValue">
+						<INPUT TYPE="TEXT" SIZE="35px" id="first_name" NAME="firstName"/>
+					</TD>
+				</TR>
+					
+				<TR>
+					<TD class="createViewColName" style="color:#FF0000;">
+						Last name: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+					</TD>
+
+					<TD class="createViewColValue">
+						<INPUT TYPE="TEXT" SIZE="35px" id="last_name" NAME="lastName"/>
+					</TD>
+				</TR>
+				
+				<TR>
+					<TD class="createViewColName">
+						Email:
+					</TD>
+
+					<TD class="createViewColValue">
+						<INPUT TYPE="TEXT" SIZE="35px" id="e_mail" NAME="email"/>
+					</TD>
+				</TR>
+				
+				<TR>
+					<TD>
+						Access Level:
+					</TD>
+
+					<TD colspan="3">
+						<INPUT TYPE="RADIO" name="system_access_level" value="Reader" style="margin-top:8px; font-size:9pt" checked onClick="showHideWriteProjectAccess()">Reader<BR/>
+						<INPUT TYPE="RADIO" name="system_access_level" value="Writer" style="margin-top:8px; font-size:9pt" onClick="showHideWriteProjectAccess()">Writer<BR/>
+						<INPUT TYPE="RADIO" name="system_access_level" value="Creator" style="margin-top:8px; font-size:9pt" onClick="showHideWriteProjectAccess()">Creator<BR/>
+						<INPUT TYPE="RADIO" name="system_access_level" value="Admin" style="margin-top:8px; font-size:9pt" onClick="showHideWriteProjectAccess()">Admin<BR/>
+					</TD>
+				</TR>
+				
+				<!-- Modified Sept. 9/07: Hide Write access section by default, only show if the new user is made non-reader -->
+				<TR>
+					<TD colspan="4">
+						<TABLE id="write_project_access" style="display:none" width="100%">
+							<TR>
+								<TD colspan="4" style="border-top:1px groove black; border-bottom:1px groove black; padding-top:8px; font-size:8pt; font-weight:bold;">
+									Grant project access permissions to this user:<BR>
+									<span id="read_note" style="display:table-row; font-size:8pt; font-weight:normal; margin-top:10px;">Select one or more projects from the list above and press 
+									<input style="margin-top:8px" onclick="addProjects('packetListWrite', getSelectedRole('1'))" value="Go" type="button"></INPUT></span><BR>
+								</TD>
+							</TR>
+
+							<TR>
+								<TD colspan="4" nowrap>
+									<?php 
+										printProjectList('packetListWrite');
+									?>
+									<BR>
+
+									<!-- April 3/09: Changed function name from selectAll() to selectAll() (renamed function in menu.js for generalization, it can be used to select all elements in any list, not just Users) -->
+									<INPUT TYPE="checkbox" style="margin-top:10px; font-size:8pt;" onClick="selectAll(this.id, 'packetListWrite')" id="add_all_chkbx"> Select All</INPUT>
+								</TD>
+							</TR>
+	
+							<TR>
+								<TD style="vertical-align:top" colspan="3">
+									<span style="font-size:8pt; font-weight:bold">User's access level to selected projects:<BR/></span>
+									<input type="radio" id="access_level_radio_read" name="access_levels" value="read" style="margin-top:8px; font-size:9pt" checked>Read-Only    <BR/>
+									<input type="radio" id="access_level_radio_write" name="access_levels" value="write" style="margin-top:5px; font-size:9pt">Write    <BR/>
+									<input style="margin-top:8px" onclick="addProjects('packetListWrite', getSelectedRole('1'))" value="Go" type="button"></INPUT>
+
+									<P style="font-size:8pt; border-top:1px groove black; padding-top:10px; padding-bottom:5px; margin-top:10px">
+									Access levels: <BR/>
+									<span style="font-size: 8pt; margin-left: 9px; font-weight:bold; ">- Read-Only:</span>  May view reagents in a project but may NOT modify them or add new reagents<BR/>
+
+									<span style="font-size: 8pt; margin-left: 9px; font-weight:bold;">- Write:</span>  May create and modify reagents in a project but may NOT change project details or add/remove members to/from the project<BR/>
+									</P>
+								</TD>
+							</TR>
+
+							<TR>
+								<TD colspan="4" style="border-top:1px groove black; border-bottom:1px groove black; font-size:8pt; font-weight:bold">
+									User's current project access privileges:
+								</TD>
+							</TR>
+
+							<TR>
+								<TD style="border-right:1px solid black; font-size:8pt">
+									<B>Read-Only</B><BR/>
+									<SELECT id="user_projects_readonly" name="userProjectsReadonly" style="margin-top:5px" multiple size="12">
+									<?php
+										// August 10/07: Default reader access to all on public projects
+										$publicProjects = getPublicProjects();
+
+										foreach ($publicProjects as $key => $tmpProj)
+										{
+											$pID = $tmpProj->getPacketID();
+											$pName = $tmpProj->getName();
+											
+											// added Oct. 5, 2010
+											$pOwner = $tmpProj->getOwner();
+											
+											// concatenate project ID and name in the form '1:parent'
+// Oct. 5, 2010										$tmpDescr = $pID . ": " . $pName;
+
+											// replaced Oct. 5, 2010
+											$tmpDescr = $pID . ": " . $pOwner->getLastName() . ": " . $pName;
+											
+											echo "<OPTION VALUE=\"" . $pID . "\">" . $tmpDescr . "</OPTION>";
+										}
+									?>
+									</SELECT><BR/>
+
+									<!-- April 3/09: Changed function name from selectAll() to selectAll() (renamed function in menu.js for generalization, it can be used to select all elements in any list, not just Users) -->
+									<INPUT style="margin-top:10px;" TYPE="checkbox" onClick="selectAll(this.id, 'user_projects_readonly')" id="select_all_reader_chkbx"> Select All</INPUT>
+								</TD>
+
+								<TD style="text-align:center; width:100px; border-right: 1px solid black; padding-left:20px; padding-right:20px;">
+									<input onclick="addProjects('user_projects_readonly', 'write')" value="   Make Writeable >>" type="button"></INPUT><BR/>
+									<input style="margin-top:30px;" onclick="addProjects('user_projects_write', 'read')" value="<< Make Read-Only" type="button"></INPUT><BR/>
+									<input style="margin-top:30px;" 	onclick="addProjects('user_projects_write', 'rmv_write'); addProjects('user_projects_readonly', 'rmv_write')" value="Remove Selected" type="button"></INPUT>
+								</TD>
+
+								<TD style="padding-left:50px; font-size:8pt">
+									<B>Write</B><BR/>
+									<SELECT id="user_projects_write" name="userProjectsWrite" style="margin-top:5px" multiple size="12"></SELECT><BR/>
+
+
+									<!-- April 3/09: Changed function name from selectAll() to selectAll() (renamed function in menu.js for generalization, it can be used to select all elements in any list, not just Users) -->
+									<INPUT style="margin-top:10px;" TYPE="checkbox" onClick="selectAll(this.id, 'user_projects_write')" id="select_all_writer_chkbx"> Select All</INPUT>
+								</TD>
+							</TR>
+
+							<TR>
+								<TD colspan="4" style="border-top:1px groove black; border-bottom:1px groove black">
+									<INPUT TYPE="SUBMIT" id="addUser" NAME="add_user" VALUE="Add User" onClick="selectAllElements('user_projects_readonly'); selectAllElements('user_projects_write');">
+								</TD>
+							</TR>
+						</TABLE>
+
+						<!-- Sept. 9/07: Show Read project section by default; if user is made non-reader, replace it with Write section -->
+						<TABLE id="read_project_access" width="100%">
+							
+							<!-- Update Oct. 4, 2010 -->
+							<th colspan="100%" style="color:blue; border-top:1px ridge black; padding-top:8px; font-size:9pt; text-align:left; padding-left:5px;">Grant project access permissions to the user:<BR></th>
+
+							<TR>
+								<TD style="vertical-align:top; font-size:9pt; padding-top:5px; padding-left:5px; width:400px; font-weight:bold;">
+									Select projects:<BR><P>
+								
+									<table border="0">
+										<TR>
+											<td width="75px" colspan="2" style="vertical-align:top;"><input type="radio" name="select_projects" checked onclick="document.getElementById('searchByMembers').style.display='none'; document.getElementById('searchByLab').style.display=''; hideUserProjects(); hideKeywd(); hideAllProjects();">By lab:
+												<SPAN ID='searchByLab' style="vertical-align:top; margin-left:40px;"><?php printLabList("onChange=\"showLabProjects('projectLabID');\"", "", "projectLabID", ""); ?></SPAN>
+											</TD>
+										</TR>
+									
+										<TR>
+											<TD colspan="2" ID="project_read_checkbox" style="white-space:nowrap; display:none;">
+											<?php
+												$labList = getLabList();
+									
+												foreach ($labList as $labID => $labName)
+												{
+													$labProjects = getLabProjects($labID);
+
+													if (sizeof($labProjects) > 0)
+													{
+														echo "<SELECT MULTIPLE id=\"lab_projects_" . $labID . "\" style=\"margin-left:10px; display:" . $display . "\">";
+
+														foreach ($labProjects as $packetID => $tmpProjTxt)
+														{
+															echo "<OPTION ID=\"lab_" . $labID . "_project_" . $packetID . "\" VALUE=\"" . $packetID . "\">" . $tmpProjTxt . "</OPTION>";
+														}
+
+														echo "</SELECT>";
+
+														?><div style="margin-top:10px;" id="selectAllCaption_<?php echo $labID; ?>"><INPUT TYPE="checkbox" id="readonly_add_chkbx_<?php echo $labID; ?>" style="margin-left:5px; font-size:8pt;" onClick="selectAll(this.id, '<?php echo "lab_projects_" . $labID; ?>')"> Select All</INPUT></div><?php
+													}
+													else
+														echo "<span ID=\"no_projects_" . $labID . "\" style=\"color:#EF4A11; padding-left:10px; display:" . $display . "\">No projects available</span>";
+
+												}
+
+												?>
+											</TD>
+
+											<TD style="vertical-align:top;">
+												<DIV ID="projectCaption" style="display:none; padding-left:20px; white-space:nowrap; padding-top:10px; font-size:8pt; font-weight:bold;">
+													<input ID="addReadProjects" onclick="addProjects('packetListRead', 'readonly')" value="Add >>" type="button"></INPUT><BR><P>
+
+													<input ID="readonly_remove_btn" onclick="moveProjectToLabListSpecific('user_projects_read');" value="Remove" type="button"></INPUT>
+												</DIV>
+											</td>
+										</TR>
+
+										<TR>
+											<td colspan="2" style="vertical-align:top; white-space:nowrap;"><input type="radio" name="select_projects" onclick="document.getElementById('searchByLab').style.display='none'; document.getElementById('searchByMembers').style.display=''; hideLabProjects(); hideKeywd(); hideAllProjects();" colspan="3">By owner:
+											<?php
+												echo "<SELECT id=\"searchByMembers\" style=\"margin-left:12px; display:none;\" onChange=\"showUserProjects(this[this.selectedIndex].value);\">";
+
+												echo "<OPTION SELECTED value=\"default\">Select Owner</OPTION>";
+
+												$users = findAllProjectOwners();
+
+												// Need to print users in alphabetical order, but calling sort() on $users gets rid of the userIDs as array keys.  Use two dictionaries to sort by value and preserve keys.
+
+												// userName => userID
+												$uNameIDs = array_flip($users);
+
+												$userIDs = array_keys($users);
+												$userNames = array_values($users);
+
+												sort($userNames);
+
+												foreach ($userNames as $key => $value)
+												{
+													$userName = $value;
+													$userID = $uNameIDs[$userName];
+
+													echo "<OPTION value=\"" . $userID . "\">" . $userName . "</OPTION>";
+												}
+										
+												echo "</SELECT>";
+											?></TD>
+										</TR><?php
+
+												// show projects for each user, hidden initially
+												foreach ($userNames as $key => $value)
+												{
+													$userName = $value;
+													$userID = $uNameIDs[$userName];
+
+													// find projects owned by selected user
+													$uPackets = Array();
+
+													echo "<TR style=\"display:none;\" ID=\"" . $userID . "_projects\"><TD width=\"75px\"> </TD><TD style=\"padding-left:23px;\">";
+
+													echo "<SELECT ID=\"userPackets_" . $userID . "\" multiple size=\"5\">";
+												
+													$find_name_rs = mysql_query("SELECT p.packetID as packetID, p.packetName as packetName, u.lastname as owner FROM Packets_tbl p, Users_tbl u WHERE p.ownerID='" . $userID . "' AND p.ownerID=u.userID AND p.status='ACTIVE' ORDER BY p.packetID", $conn) or die("Error fetching packet ID:" . mysql_error());
+
+													while ($find_name_ar = mysql_fetch_array($find_name_rs, MYSQL_ASSOC))
+													{
+														echo "<OPTION value=\"" . $find_name_ar["packetID"] . "\" ID=\"" . $userID . "_user_projects_" . $find_name_ar["packetID"] . "\">" .  $find_name_ar["packetID"] . ": " . $find_name_ar["owner"] . ": " . $find_name_ar["packetName"] . "</OPTION>";
+													}
+
+													echo "</SELECT></TD>";
+
+													?><TD ID="userProjectCaption_<?php echo $userID; ?>" style="display:none; padding-left:12px; white-space:nowrap; padding-top:10px; font-size:8pt; font-weight:bold;">
+														<input ID="addReadProjectsUser" value="Add >>" type="button" onclick="addProjects('userPackets_<?php echo $userID; ?>', 'readonly')"></INPUT><BR><P>
+	
+														<input style="margin-left:12px;" ID="user_readonly_remove_btn" onclick="moveProjectToUserListSpecific('user_projects_read');" value="Remove" type="button"></INPUT>
+													</TD><?php
+	
+													echo "</TR>";
+												}
+
+										?><TR><td colspan="3" style="white-space:nowrap;"><input type="radio" name="select_projects" onclick="document.getElementById('searchByLab').style.display='none'; document.getElementById('searchByMembers').style.display='none'; hideUserProjects(); hideLabProjects(); showProjectKeywordSearch(); hideAllProjects();">By name (type any keyword in project name or description):</TD></TR>
+
+										<TR ID="projectKeywdSearch" style="display:none;">
+											<TD style="padding-left:15px; font-size:9pt;" colspan="2">
+												LIKE %<INPUT TYPE="text" size="25" ID="project_keywd" NAME="projectKeyword">%
+												<INPUT TYPE="button" style="font-size:9pt;" onclick="searchProjectByKeyword();" value="Find">
+											</TD>
+										</TR>
+										
+										<TR ID="project_search_results" style="display:none;">
+											<TD style="padding-left:12px;">
+												<SELECT MULTIPLE SIZE="5" ID="keywdProjectMatchList"></SELECT>
+											</TD>
+										
+											<TD ID="keywdProjectCaption" style="padding-left:12px; white-space:nowrap; padding-top:10px; font-size:8pt; font-weight:bold;">
+												<input ID="addReadProjectsKeywd" value="Add >>" type="button" onclick="addProjects('keywdProjectMatchList', 'readonly')"></INPUT><BR><P>
+											
+												<input ID="user_readonly_remove_btn" onclick="moveListElements('user_projects_read', 'keywdProjectMatchList', false, false);" value="<< Remove" type="button"></INPUT>
+											</TD>
+										</TR>
+									
+										<TR><td colspan="3" style="white-space:nowrap;"><input type="radio" name="select_projects" onclick="document.getElementById('searchByLab').style.display='none'; document.getElementById('searchByMembers').style.display='none'; hideUserProjects(); hideLabProjects(); hideKeywd(); showAllProjects();">View all projects:</TD></TR>
+
+										<TR ID="viewAllProjects" style="display:none;">
+											<TD>
+												<?php 
+													printProjectList('packetListReadAll');
+												?>
+												<BR>
+			
+												<!-- April 3/09: Changed function name from selectAll() to selectAll() (renamed function in menu.js for generalization, it can be used to select all elements in any list, not just Users) -->
+												<INPUT TYPE="checkbox" style="margin-top:10px; font-size:8pt;" onClick="selectAll(this.id, 'packetListReadAll')" id="add_all_chkbx"> Select All</INPUT>
+											</TD>
+
+											<TD style="vertical-align:top;">
+												<DIV ID="allProjectsCaption" style="padding-left:20px; white-space:nowrap; padding-top:10px; font-size:8pt; font-weight:bold;">
+													<input ID="addReadProjects" onclick="addProjects('packetListReadAll', 'readonly')" value="Add >>" type="button"></INPUT><BR><P>
+
+													<input ID="readonly_remove_btn" onclick="moveListElements('user_projects_read', 'packetListReadAll', true, false);" value="<< Remove" type="button"></INPUT>
+												</DIV>
+											</td>
+										</TR>
+									</table>
+								</TD>
+
+								<TD colspan="4" style="vertical-align:top; font-size:9pt; padding-top:3px; padding-bottom:5px; font-weight:bold; padding-left:5px;">
+									User's current project access privileges:<BR>
+									<span style="color:black; font-weight:normal; font-size:8pt;">(All users have read access to public projects)</span>
+
+									<table>
+										<TR>
+											<TD style="font-size:8pt; padding-left:5px;">
+												<SELECT id="user_projects_read" name="userProjectsReadonlyWrite" style="margin-top:8px" multiple size="12">
+												<?php
+													// August 10/07: Default reader access to all on public projects
+													$publicProjects = getPublicProjects();
+			
+													foreach ($publicProjects as $key => $tmpProj)
+													{
+														$pID = $tmpProj->getPacketID();
+														$pName = $tmpProj->getName();
+			
+														// added Oct. 5, 2010
+														$pOwner = $tmpProj->getOwner();
+
+														// replaced Oct. 5, 2010 - include owner's name
+														$tmpDescr = $pID . ": " . $pOwner->getLastName() . ": " . $pName;
+														
+														echo "<OPTION DISABLED VALUE=\"" . $pID . "\">" . $tmpDescr . "</OPTION>";
+													}
+												?>
+												</SELECT><BR>
+
+												<INPUT style="margin-top:10px;" TYPE="checkbox" onClick="selectAll(this.id, 'user_projects_read')" id="readonly_rmv_chkbx"> Select All</INPUT>
+<!-- 												<BR> -->
+<!-- 												<span style="font-size:8pt; font-weight:normal;">To revoke access, select one or more projects from the list and press</span> -->
+											</TD>
+										</TR>
+									</table>
+								</TD>
+							</TR>
+
+							<TR>
+								<TD colspan="4" style="border-top:1px groove black; border-bottom:1px groove black">
+									<INPUT TYPE="SUBMIT" id="addUser" NAME="add_user" VALUE="Add User" onClick="selectAllElements('user_projects_read');">
+								</TD>
+							</TR>
+						</TABLE>
+					</TD>
+				</TR>
+			</TABLE>
+		</FORM>
+
+<!-- 		<FORM NAME="projectSearchForm" METHOD="POST" ACTION="<?php /*echo $cgi_path . "project_request_handler.py"; */?>"></FORM> -->
+	<?php
+}
+
+// New Oct. 5, 2010, modified Oct. 6, 2010
+// return a list of lab projects; will print them in calling function
+/**
+ * Return a list of lab projects to be printed in the calling function
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1 2010-10-05, modified Oct. 6, 2010
+ *
+ * @param INT $labID
+ *
+*/
+function getLabProjects($labID)
+{
+	global $conn;
+	$projects = Array();
+
+	// Get all projects owned by users in this lab
+	$query = "SELECT p.packetID, p.packetName, u.lastname FROM Packets_tbl p, Users_tbl u WHERE u.labID='" . $labID . "' AND u.userID=p.ownerID AND p.status='ACTIVE' ORDER BY p.packetID";
+
+	$labProjectList = mysql_query($query, $conn) or die("Error fetching lab projects: " . mysql_error());
+
+	while ($labProjects = mysql_fetch_array($labProjectList, MYSQL_ASSOC))
+	{
+		$packetID = $labProjects["packetID"];
+		$packetName = $labProjects["packetName"];
+		$lastname = $labProjects["lastname"];
+		$tmpProjTxt = $packetID . ": " . $lastname . ": " . $packetName;
+
+		$projects[$packetID] = $tmpProjTxt;
+	}
+
+	return $projects;
+}
+
+
+/**
+ * Print form for users to change their password
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param boolean $curr_pw_err
+ * @param boolean $new_pw_err if new password values entered do not match
+ * @param boolean $old_pw_err: if old password is identical to new password
+ *
+*/
+function printFormChangePasswd($curr_pw_err = false, $new_pw_err = false, $old_pw_err = false)
+{
+	global $conn;
+	
+	$curr_err_display = $curr_pw_err ? "table-row" : "none";
+	$new_err_display = $new_pw_err ? "table-row" : "none";
+	$old_err_display = $old_pw_err ? "table-row" : "none";
+	
+	?>
+	<FORM NAME="change_passwd" METHOD="POST" ACTION="<?php $_SERVER["PHP_SELF"] . "?View=7"?>">
+		
+		<TABLE width="700px" cellpadding="8px" style="margin-left:20px;" border="1px outset black" frame="box" rules="all">
+		
+			<TR>
+				<TH colspan="2" style="color:#0000FF; text-align:center; font-weight:bold">CHANGE YOUR PASSWORD</TH>
+			</TR>
+			
+			<TR>
+				<TD style="width:100px">Old Password:</TD>
+				<TD><INPUT TYPE="password" ID="old_passwd" NAME="old_pw"></TD>
+			</TR>
+					
+			<TR style="display:<?php echo $curr_err_display; ?>">
+				<TD colspan="2" style="color:#FF0000; font-size:8pt;">
+					The old password value is incorrect.  Please verify your input.
+				</TD>
+			</TR>
+			
+			<TR>
+				<TD style="width:100px">New Password:</TD>
+				<TD><INPUT TYPE="password" ID="new_passwd" NAME="new_pw"></TD>
+			</TR>
+			
+			<TR style="display:<?php echo $old_err_display; ?>">
+				<TD colspan="2" style="color:#FF0000; font-size:8pt;">
+					The new password must differ from your old password.  Please select a different password value.
+				</TD>
+			</TR>
+			
+			<TR>			
+				<TD style="width:150px; white-space:nowrap">Confirm New Password:</TD>
+				<TD><INPUT TYPE="password" ID="new_passwd_confirm" NAME="new_pw_2"></TD>
+			</TR>
+			
+			<TR style="display:<?php echo $new_err_display; ?>">
+				<TD colspan="2" style="color:#FF0000; font-size:8pt;">
+					The new password values do not match.  Please retype the new password correctly.
+				</TD>
+			</TR>
+			
+			<TR>
+				<TD colspan="2" style="white-space:nowrap;">
+					<INPUT TYPE="SUBMIT" NAME="change_pw" VALUE="Change" onClick="return checkNonEmptyPassword();">
+				</TD>
+			</TR>
+		</TABLE>
+	</FORM>
+	<?php
+}
+
+
+/**
+ * Print form for user deletion -- NOT actively used in this version
+ * 
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+*/
+function printUserDeletionForm()
+{
+	global $conn;
+	global $cgi_path;
+	
+	// Similar to Delete Project - show a list of labs, select lab, show members list, select user, and delete without asking questions (maybe just popup a JS confirm for formality)
+	?>
+		<FORM NAME="delete_user_form" METHOD="POST" ACTION="<?php echo $cgi_path . "user_request_handler.py"; ?>" onSubmit="return verifyDeleteUser();">
+			
+			
+			<TABLE width="775px" cellpadding="5" cellspacing="5">
+			
+				<TH colspan="3" style="color:#0000FF; border-top:1px groove black; border-bottom: 1px groove black;">
+					DELETE USER
+				</TH>
+				
+				<TR>
+					<TD style="width:150px; vertical-align:top; padding-top:10px;">
+						Select laboratory:  
+						<?php 
+							printLabList("onChange=\"showLabMembersList()\""); 
+						?>
+					</TD>
+				</TR>
+				
+				<TR id="deleteMembersRow" style=" display:none">
+					<TD style="width:150px; vertical-align:top; padding-top:10px;">
+						Select member names from the list below and press 'Add selected to Delete list' to add them to the list of candidates for deletion:<BR/><BR/>
+						<?php 
+							printLabMembersList();
+						?>
+						<BR/><BR/>
+						
+						<INPUT TYPE="button" id="addUserDel" VALUE="Add selected to Delete list" onClick="return checkSelectUser('lab_source_list_' + getSelectedLab(), 'deletion_candidates_list', this.id);">
+						<BR/><BR/><HR/>
+						
+						<span style="font-weight:bold; color:#FF0000;">These users are marked for deletion:</span><BR/>
+						<span style="font-size:9pt; padding-top:15px; padding-bottom:15px;">To remove a user from this list, select the user's name and press 'Return selected to Users list'</span><BR/>
+						
+						<SELECT style="margin-top:5px;" id="deletion_candidates_list" name="deletionCandidates" multiple size="12"></SELECT><BR/><BR/>
+						
+						<INPUT TYPE="button" id="rmvUserDel" VALUE="Return selected to Users list" onClick="return checkSelectUser('deletion_candidates_list', 'lab_source_list_' + getSelectedLab(), this.id);"><BR/><BR/>
+					</TD>
+				</TR>
+				
+				<TR>
+					<TD style="width:150px; vertical-align:middle; border-top:1px groove black; border-bottom: 1px groove black; padding-top:6px; padding-bottom:6px;">
+						<INPUT TYPE="SUBMIT" id="deleteUserBtn" NAME="delete_user" VALUE="Delete Users" disabled onClick="selectAllElements('deletion_candidates_list')">
+					</TD>
+				</TR>
+			</TABLE>
+		</FORM>
+	<?php	
+}
+
+
+/**
+ * Print form for searching users; give option to select search criteria
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+*/
+function printSearchUserForm()
+{
+	// Determine if this is our first visit to this page or whether we've arrived here after a search, in which case checkbox values have been set
+	
+	// lab
+	if (isset($_POST["lab_criteria"]))
+	{
+		$lab_display = "table-row";
+		$lab_checked = "checked";
+	}
+	else
+	{
+		$lab_display = "none";
+		$lab_checked = "";
+	}
+
+	
+	// first name
+	if (isset($_POST["first_name_criteria"]))
+	{
+		$fn_display = "table-row";
+		$fn_checked = "checked";
+		$post_fn = $_POST["firstname"];
+	}
+	else
+	{
+		$fn_display = "none";
+		$fn_checked = "";
+		$post_fn = "";
+	}
+	
+	
+	// last name
+	if (isset($_POST["last_name_criteria"]))
+	{
+		$ln_display = "table-row";
+		$ln_checked = "checked";
+		$post_ln = $_POST["lastname"];
+	}
+	else
+	{
+		$ln_display = "none";
+		$ln_checked = "";
+		$post_ln = "";
+	}
+	?>
+	<FORM METHOD="POST" NAME="findUserForm" ACTION="<?php echo $_SERVER["PHP_SELF"] . "?View=2"; ?>">
+		<TABLE width="100%" cellpadding="5" cellspacing="5">
+			<TH colspan="3" style="color:#0000FF; padding-left:25px">
+				SEARCH USERS
+			</TH>
+			
+			<TR>
+				<TD colspan="2">
+					Please select attributes to include in your search:
+				</TD>
+			</TR>
+			
+			<TR>
+				<TD style="vertical-align:top">
+					<INPUT TYPE="checkbox" name="lab_criteria" onClick="showLabList()" <?php echo $lab_checked; ?>> Lab:
+				</TD>
+			</TR>
+
+			<TR id="labList" style="display:<?php echo $lab_display; ?>">
+				<TD style="vertical-align:top">
+					<?php 
+						printLabList("", "multiple");
+					?>
+				</TD>
+			</TR>
+						
+			<TR>
+				<TD>
+					<INPUT TYPE="checkbox" name="first_name_criteria" onClick="showFirstName()" <?php echo $fn_checked; ?>> First name <span style="font-size:7pt">(LIKE quantitation applies to partial entries, no wildcards required):</span>
+					
+					<SPAN id="firstNameField" style="display:<?php echo $fn_display; ?>">
+						LIKE % <INPUT TYPE="TEXT" SIZE="20" ID="fName" NAME="firstname" VALUE="<?php echo $post_fn; ?>"> %
+					</SPAN>
+			</TR>
+			
+			<TR>
+				<TD>
+					<INPUT TYPE="checkbox" name="last_name_criteria" onClick="showLastName()" <?php echo $ln_checked; ?>> Last name <span style="font-size:7pt">(LIKE quantitation applies to partial entries, no wildcards required):</span>
+
+					<SPAN id="lastNameField" style="display:<?php echo $ln_display; ?>">
+						LIKE % <INPUT TYPE="TEXT" SIZE="20" ID="lName" NAME="lastname" VALUE="<?php echo $post_ln; ?>"> %
+					</SPAN>
+			</TR>
+			
+			<TR>
+				<TD>
+					<INPUT TYPE="SUBMIT" NAME="search_user" VALUE="Submit">
+				</TD>
+			</TR>
+		</TABLE>
+	</FORM>
+	<?php
+}
+
+/**
+ * Search the database for a user matching the search parameters (from $_POST variables)
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @see printUserSearchResults()
+*/
+function findUser()
+{
+	global $conn;
+	
+	$results = array();
+	
+	// Determine if any search attributes have been set
+	//print_r($_POST);
+	
+	$query = "SELECT DISTINCT userID, firstName, lastName FROM Users_tbl u, LabInfo_tbl l WHERE ";
+	
+	if (isset($_POST["lab_criteria"]))
+	{
+		if (isset($_POST["labs"]))
+		{
+			$labs = $_POST["labs"];			// array
+			$count = sizeof($labs);
+
+			$query .= "(";
+
+			foreach ($labs as $key => $labID)	// $labID is the numeric database ID of the lab
+			{
+				if ($count > 1)
+				{
+					$query .= "l.labID = '" . $labID . "' OR ";
+					$count--;
+				}
+				else
+				{
+					// last lab in list - no OR in query
+					$query .= "l.labID = '" . $labID . "' ";				
+				}
+			}
+
+			$query .= ") AND u.labID=l.labID ";
+
+			// Check if additional attributes are set; if yes, append 'AND' operand to query
+			if (isset($_POST["firstname"]) || isset($_POST["lastname"]))
+				$query .= "AND ";
+		}
+	}
+	
+
+	if (isset($_POST["first_name_criteria"]))
+	{
+		if (isset($_POST["firstname"]) && $_POST["firstname"] != "")
+		{
+			$firstName = $_POST["firstname"];
+
+			$query .= "firstname LIKE '%" . $firstName . "%' ";
+
+			if (isset($_POST["last_name_criteria"]))
+				$query .= "OR ";
+			else
+				$query .= "AND ";
+		}
+	}
+
+	if (isset($_POST["last_name_criteria"]))
+	{
+		if (isset($_POST["lastname"]) && $_POST["lastname"] != "")
+		{
+			$lastName = $_POST["lastname"];
+
+			// need 'AND' in any case, to link to the final portion of the query
+			$query .= "lastname LIKE '%" . $lastName . "%' AND ";
+		}
+	}
+
+	$query .= "u.status='ACTIVE' AND l.status='ACTIVE' ORDER BY firstname";
+	//print $query;
+	
+	$user_rs = mysql_query($query, $conn) or die("Cannot select user info: " . mysql_error());
+	
+	while ($users = mysql_fetch_array($user_rs, MYSQL_ASSOC))
+	{
+		$userID = $users["userID"];
+		$fName = $users["firstName"];
+		$lName = $users["lastName"];
+		$description = $users["description"]; 
+		
+		$tmpUser = new Member_Class($userID, "", $description, "", "", "", "", "", "", "");
+		$tmpUser->setFirstName($fName);
+		$tmpUser->setLastName($lName);
+		
+		$results[] = $tmpUser;
+	}
+	
+	printUserSearchResults($results);
+}
+
+
+/**
+ * Print user search results (output a list of users matching the search criteria)
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param resource MySQL result set
+ *
+*/
+function printUserSearchResults($results)
+{
+	global $cgi_path;
+
+	$currUserName = $_SESSION["userinfo"]->getDescription();
+	$currUserID = $_SESSION["userinfo"]->getUserID();
+
+	?>
+	<form name="lab_form" method="post" action="<?php echo $cgi_path . "user_request_handler.py"; ?>">
+		<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+		<INPUT type="hidden" id="view_user_hidden" name="view_user">
+
+		<TABLE>
+		<?php
+			echo "Found " . sizeof($results) . " users matching your search query:";
+
+			foreach ($results as $key => $tmpUser)
+			{
+				?>
+				<TR>
+					<TD>
+					<?php
+						$tmpUserID = $tmpUser->getUserID();
+						$tmpFirstName = $tmpUser->getFirstName();
+						$tmpLastName = $tmpUser->getLastName();
+						
+						// the following are equivalent, but putting them both here in case later changes are anticipated
+						$tmpDescr = $tmpUser->getDescription();
+						$tmpFullName = $tmpFirstName . " " . $tmpLastName;
+					?>
+					<span class="linkShow" onClick="redirectToUserDetailedView('<?php echo $tmpUserID; ?>')"><?php echo $tmpFullName; ?></span>
+					</TD>
+				</TR>
+				<?php
+			}
+		?>
+		</TABLE>
+	</form>		
+	<?php
+}
+
+/**
+ * Retrieves all the laboratories from the database
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @return Array Dictionary of (labID => labName) tuples
+*/
+function getLabList()
+{
+	global $conn;
+
+	$lab_rs = mysql_query("SELECT labID, lab_name FROM LabInfo_tbl WHERE status='ACTIVE' ORDER BY lab_name", $conn) or die("Cannot select labs: " . mysql_error());
+
+	$labs = array();
+
+	while ($lab_ar = mysql_fetch_array($lab_rs, MYSQL_ASSOC))
+	{
+		$labID = $lab_ar["labID"];
+		$labName = $lab_ar["lab_name"];
+
+		$labs[$labID] = $labName;
+	}
+
+	return $labs;
+}
+
+
+/**
+ * Select all users from the given lab
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param INT $labID
+ * @return Array Dictionary of (userID => userName) tuples
+*/
+function getAllUsers($labID)
+{
+	global $conn;
+
+	$users = array();
+	
+	// June 29/07, Marina: ALL users - NOT just in or above category 'writers'
+	$users_rs = mysql_query("SELECT userID, username, CONCAT(firstname, \" \", lastname) AS uname FROM Users_tbl WHERE labID='" . $labID . "' AND status='ACTIVE' ORDER BY uname", $conn) or die("Cannot fetch users: " . mysql_error());
+	
+	while ($users_ar = mysql_fetch_array($users_rs, MYSQL_ASSOC))
+	{
+		$uid = $users_ar["userID"];
+		$username = $users_ar["username"];
+		$uname = $users_ar["uname"];
+		
+		if ( strlen(trim($uname)) > 0 && $username != 'guest' )
+		{
+			$users[$uid] = $uname;
+		}
+	}
+	
+	return $users;
+}
+
+
+/**
+ * Print a list of lab members
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param STRING $actn onChange action for the SELECT list
+*/
+function printLabMembersList($actn = "")
+{
+	global $conn;
+	
+	$labList = getLabList();
+	$currLabID = $_SESSION["userinfo"]->getLabID();
+
+	foreach ($labList as $labID => $labName)
+	{
+		//$display = ($labID == $currLabID) ? "inline" : "none";
+		$display = "none";
+
+		echo "<SELECT id=\"lab_source_list_" . $labID . "\" name=\"labSourceMembers_" . $labID . "\" multiple=\"multiple\" size=\"10\"  style=\"display: " . $display . "\"" . $actn . ">";
+		
+		$users = getAllUsers($labID);
+
+		foreach ($users as $key => $value)
+		{
+			echo "<OPTION id=\"user_" . $key . "_lab_" . $labID . "\" value=\"" . $key . "\">" . $value . "</OPTION>";
+		}
+
+		echo "</SELECT>";
+	}
+}
+
+/**
+ * Auxiliary function to list all the laboratories in OpenFreezer in a dropdown list - single or multiple, depending on the parameters.
+ *
+ * Outputs a SELECT box inside a form that requires a lab list to be shown.
+ *
+ * Oct. 5, 2010: Added $listID parameter, in case this function is reused in one view (e.g. adding users) - assign different IDs to form elements to avoid confusion
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param STRING $actn onChange action for the SELECT list
+ * @param STRING $multiple Should the lab list be multiple or single-option SELECT
+ *
+*/
+function printLabList($actn = "", $multiple = "", $listID="labList", $listName="labs")
+{
+	global $conn;
+	
+	$labList = array();
+	
+	// Select list of labs from the database
+	$labList_rs = mysql_query("SELECT labID, lab_name FROM LabInfo_tbl WHERE status='ACTIVE' ORDER BY lab_name", $conn) or die("Error selecting labs: " . mysql_error());
+	
+	while ($labList_ar = mysql_fetch_array($labList_rs, MYSQL_ASSOC))
+	{
+		$labID = $labList_ar["labID"];
+		$labName = $labList_ar["lab_name"];
+		
+		$labList[$labID] = $labName;
+	}
+	
+	$currLabID = $_SESSION["userinfo"]->getLabID();
+	
+	if (strcasecmp($multiple, 'multiple') == 0)
+	{
+		echo "<SELECT MULTIPLE id=\"" . $listID . "\" name=\"" . $listName . "[]\" " . $actn . ">";
+	}
+	else
+	{
+		echo "<SELECT id=\"" . $listID . "\" name=\"" . $listName . "\" " . $actn . ">";
+		echo "<OPTION>Select Laboratory</OPTION>";
+	}
+	
+	// If post search, show selections	
+	if (isset($_POST["lab_criteria"]) && isset($_POST["labs"]))
+	{
+		$postLabs = $_POST["labs"];
+	}
+
+	foreach ($labList as $key => $value)
+	{
+		if (in_array($key, $postLabs))
+			$selected = "SELECTED";
+		else
+			$selected = "";
+		
+		?><OPTION ID="<?php echo $key; ?>" NAME="lab_optn" VALUE="<?php echo $key; ?>" <?php echo $selected; ?>><?php 
+
+		echo $value; 
+
+		?></OPTION><?php
+	}
+
+	echo "</SELECT>";
+}
+
+/**
+ * Output a list of all projects in OpenFreezer as a SELECT list
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @param STRING $listID Form element ID of the SELECT list
+*/
+
+function printProjectList($listID = "packetList")
+{
+	global $conn;
+	?>
+	<SELECT id="<?php echo $listID; ?>" name="packets" multiple size="15">";
+	<?php
+		// Modified Oct. 4, 2010 - code taken from ColFunctOutputer_Class->output_packet()
+		$userProjects = findAllProjects();
+		$userProjectList = '';
+
+		if (sizeof($userProjects) > 0)
+		{
+			$userProjectList = "(" . implode(",", $userProjects) . ")";
+		}
+
+		$query = "SELECT p.packetID as packetID, p.packetName as packetName, u.lastname as owner FROM Packets_tbl p, Users_tbl u WHERE p.ownerID=u.userID AND p.packetID IN " . $userProjectList . " AND p.status='ACTIVE'";
+
+		$find_name_rs = mysql_query($query, $conn) or die("Error fetching packet ID:" . mysql_error());
+	
+// oct 4/10	$query = "SELECT p.packetID as packetID, p.packetName as packetName FROM Packets_tbl p WHERE p.status='ACTIVE'";
+
+		$find_name_rs = mysql_query($query, $conn) or die("Error fetching packet ID:" . mysql_error());
+
+		while ($find_name_ar = mysql_fetch_array($find_name_rs, MYSQL_ASSOC))
+		{
+			// update Oct. 4, 2010
+// Oct. 4, 2010		$temp_packet = $find_name_ar["packetID"] . ": " . $find_name_ar["packetName"];
+ 			$temp_packet = $find_name_ar["packetID"] . ": " . $find_name_ar["owner"] . ": " . $find_name_ar["packetName"];
+
+			echo "<OPTION value=\"" . $find_name_ar["packetID"] . "\">" . $temp_packet . "</option>";
+		}
+	?>
+	</SELECT>
+	<?php
+}
+
+
+/**
+ * Print a form for adding a new laboratory to OpenFreezer
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+*/
+function printLabCreationForm()
+{
+	global $cgi_path;
+	
+ 	$showLabCodeWarning = (isset($_GET["ErrCode"]) && ($_GET["ErrCode"] == '14')) ? "inline" : "none";
+
+	// get username from session
+	$currUserName = $_SESSION["userinfo"]->getDescription();
+	?>
+	<FORM NAME="create_lab_form" METHOD="POST" ACTION="<?php echo $cgi_path . "user_request_handler.py"; ?>">
+		
+		<!-- Pass user info as a hidden form value - currently the most secure way to pass session info from PHP to Python -->
+		<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+
+		<TABLE width="770px" cellpadding="5" cellspacing="5" boirder="1" frame="box" rules="all">
+
+			<TH colspan="3" style="color:#0000FF; border-top:1px groove black; border-bottom: 1px groove black; padding-top: 10px; padding-top:5px;">
+				ADD NEW LABORATORY
+				<P style="color:#FF0000; font-weight:normal; font-size:8pt; margin-top:5px;">Fields in red marked with an asterisk (<span style="font-size:9pt; color:#FF0000;">*</span>) are mandatory</P>
+			</TH>
+
+			<TR>
+				<TD style="width:50px; vertical-align:middle; padding-top:10px; color:#FF0000; white-space:nowrap; font-size:8pt">
+					Laboratory name: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+				</TD>
+
+				<TD style="width:50px;">
+					<INPUT TYPE="text" id="lab_name" name="labName" size="35px" value="<?php echo isset($_GET["labName"]) ? $_GET["labName"] : ""; ?>">
+				</TD>
+				
+				<TD style="font-size:8pt; vertical-align:middle; ">
+					Usually the name of the lab owner or PI followed by 'Lab' (e.g. 'Pawson Lab', 'Wrana Lab', etc.)
+				</TD>
+			</TR>
+			
+			<TR>
+				<TD style="width:50px; vertical-align:middle; padding-top:15px; color:#FF0000; white-space:nowrap; font-size:8pt">
+					Laboratory head: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+				</TD>
+
+				<TD style="width:50px; vertical-align:middle; padding-top:15px;">
+				<?php 
+					if (isset($_GET["title"]))
+						$title = $_GET["title"];
+					else
+						$title = "Dr.";		// default
+				?>
+					<SELECT ID="titlesList" NAME="titles">
+						<OPTION <?php echo (strcasecmp($title, "Dr.") == 0) ? "SELECTED" : ""; ?> value="Dr.">Dr</OPTION>
+						<OPTION  <?php echo (strcasecmp($title, "Mr.") == 0) ? "SELECTED" : ""; ?> value="Mr.">Mr</OPTION>
+						<OPTION  <?php echo (strcasecmp($title, "Mrs.") == 0) ? "SELECTED" : ""; ?> value="Mrs.">Mrs</OPTION>
+						<OPTION  <?php echo (strcasecmp($title, "Ms.") == 0) ? "SELECTED" : ""; ?> value="Ms.">Ms</OPTION>
+					</SELECT>
+					<INPUT TYPE="text" id="lab_head" name="labHead" size="25px" value="<?php echo isset($_GET["labHead"]) ? $_GET["labHead"] : ""; ?>">
+				</TD>
+				
+				<TD style="font-size:8pt">
+					Complete name of the lab owner or PI (e.g. 'Tony Pawson')
+				</TD>
+			</TR>
+
+			<TR>
+				<TD style="width:50px; vertical-align:middle; color:#FF0000; white-space:nowrap; font-size:8pt">
+					Laboratory ID: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+				</TD>
+
+				<TD style="width:50px; vertical-align:bottom;">
+					<INPUT TYPE="text" id="lab_id" name="labCode" size="5px" value="<?php echo isset($_GET["labCode"]) ? $_GET["labCode"] : ""; ?>"><BR><BR>
+
+					<SPAN id="dup_labcode_warning" style="vertical-align:bottom; color:#FF0000; display:<?php echo $showLabCodeWarning; ?>">This identifier already exists.  Please specify a different lab ID.</SPAN>
+				</TD>
+				
+				<TD style="font-size:8pt; vertical-align:bottom;">
+					A unique two-character identifier that will be used in container barcodes and other features.<BR>
+					E.g. 'PW' => 'Pawson', 'GN' => 'Gingras', 'WG' => 'Woodgett', 'DN' => 'Dennis', etc.
+				</TD>
+			</TR>
+
+			<TR>
+				<TD style="width:50px; vertical-align:middle; white-space:nowrap; font-size:8pt;">
+					Laboratory description:
+				</TD>
+
+				<TD style="width:50px; vertical-align:middle;">
+					<INPUT TYPE="text" id="lab_descr" name="labDescription" size="35px" value="<?php echo isset($_GET["labDescr"]) ? $_GET["labDescr"] : ""; ?>">
+				</TD>
+				
+				<TD style="font-size:8pt; vertical-align:bottom;">
+					Optional; a detailed description of the laboratory's activity (e.g. 'Proteomics Research Laboratory')
+				</TD>
+			</TR>
+			
+			<TR>
+				<TD style="width:50px; vertical-align:middle; white-space:nowrap; font-size:8pt">
+					Location
+				</TD>
+
+				<TD style="width:50px; vertical-align:middle;">
+					<INPUT TYPE="text" id="lab_location" name="labAddress" size="35px" value="<?php echo isset($_GET["locn"]) ? $_GET["locn"] : ""; ?>">
+				</TD>
+				
+				<TD style="font-size:8pt; vertical-align:middle;">
+					Optional; either the exact mailing address of the laboratory, the name of the city/country where the laboratory is located, or other location indicator (e.g. "MIT", "Boston, Massachusetts", or "Mount Sinai Hospital, Toronto, Ontario")
+				</TD>
+			</TR>
+
+			<TR>
+				<TD style="width:50px; vertical-align:middle; white-space:nowrap; font-size:8pt">
+					Default access level:
+				</TD>
+
+				<TD style="font-size:8pt; vertical-align:middle; width:50px;">
+					<?php
+						if (isset($_GET["access"]))
+							$accLev = $_GET["access"];
+						else
+							$accLev = "Reader";
+					?>
+					<INPUT TYPE="RADIO" name="system_access_level" value="Reader" style="margin-top:8px; font-size:8pt" <?php echo (strcasecmp($accLev, 'Reader') == 0) ? "checked" : ""; ?>>Reader<BR/>
+					<INPUT TYPE="RADIO" name="system_access_level" value="Writer" style="margin-top:5px; font-size:8pt" <?php echo (strcasecmp($accLev, 'Writer') == 0) ? "checked" : ""; ?>>Writer<BR/>
+					<INPUT TYPE="RADIO" name="system_access_level" value="Creator" style="margin-top:5px; font-size:8pt" <?php echo (strcasecmp($accLev, 'Creator') == 0) ? "checked" : ""; ?>>Creator<BR/>
+					<INPUT TYPE="RADIO" name="system_access_level" value="Admin" style="margin-top:5px; font-size:8pt" <?php echo (strcasecmp($accLev, 'Admin') == 0) ? "checked" : ""; ?>>Admin<BR/>
+				</TD>
+				
+				<TD style="font-size:8pt; vertical-align:bottom;  padding-top:7px">
+					The default OpenFreezer<sup style="font-size:5pt">TM</sup> access level automatically granted to members of this lab.  This level may be overridden for individual lab members.<BR/>
+					<b><u>Reader</u></b>: May browse selected reagents.  May not create or modify any reagents.<BR/>
+					<b><u>Writer</u></b>: May create and modify reagents.  Cannot create new projects.<BR/>
+					<b><u>Creator</u></b>: May create new projects in OpenFreezer<sup style="font-size:5pt">TM</sup>.  May not add members to the system.<BR/>
+					<b><u>Admin</u></b>: May add new users and laboratories to OpenFreezer<sup style="font-size:5pt">TM</sup>.
+				</TD>
+			</TR>
+		</TABLE>
+		<INPUT TYPE="SUBMIT" NAME="add_lab" VALUE="Add Laboratory" onClick="return checkLab();">
+	</FORM>
+	<?php
+}
+
+
+/**
+ * @name Find a list of users who are currently listed as project owners
+ * @return Array list of user IDs
+ *
+ * @author Marina Olhovsky
+ * @version 2010-10-08
+*/
+function findAllProjectOwners()
+{
+	global $conn;
+
+	$users = Array();
+
+	$query = "SELECT userID, description FROM Users_tbl u, Packets_tbl p WHERE u.userID=p.ownerID AND p.status='ACTIVE'";
+
+	$owners_rs = mysql_query($query, $conn);
+
+	while ($owners_ar = mysql_fetch_array($owners_rs, MYSQL_ASSOC))
+	{
+		$userID = $owners_ar["userID"];
+		$userName = $owners_ar["description"];
+		$users[$userID] = $userName;
+	}
+
+	return $users;
+}
+
+/**
+ * Print a list of laboratories inside a form (in response to 'Search labs' menu selection)
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @uses printLabList()
+*/
+function printViewLabForm()
+{
+	global $cgi_path;
+	
+	// get username from session
+	$currUserName = $_SESSION["userinfo"]->getDescription();
+	$currUserID = $_SESSION["userinfo"]->getUserID();
+	?>
+	<FORM NAME="view_lab_form" METHOD="POST" ACTION="<?php echo $cgi_path . "user_request_handler.py"; ?>">
+		<FIELDSET>
+		<LEGEND> Please select a laboratory from the dropdown list below for viewing and/or editing: </LEGEND>
+		<!-- Pass user info as a hidden form value - currently the most secure way to pass session info from PHP to Python -->
+		<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+		<INPUT type="hidden" ID="curr_userid_hidden" NAME="curr_user_id" VALUE="<?php echo $currUserID; ?>">
+			<?php
+				printLabList();
+			?>
+			   <INPUT TYPE="SUBMIT" id="viewLab" NAME="view_lab" VALUE="Go">
+		</FIELDSET>
+	</FORM>
+	<?php
+}
+
+
+/**
+ * Print a form for users to ask to reset their password (fill in username/full name and a temporary password will be emailed if a matching email address is found)
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1 2010-06-01
+ *
+*/
+function printFormPasswdReset()
+{
+	global $cgi_path;
+
+	?><FORM METHOD="POST" ACTION="<?php echo $cgi_path . "user_request_handler.py"; ?>">
+		<TABLE width="960px" cellpadding="8px" style="margin-left:20px;">
+			<TR>
+				<TD style="padding-left:10px;">
+					Please enter your OpenFreezer username:<BR><P>
+					<INPUT TYPE="TEXT" SIZE="25px" NAME="uName" ID="uname_remind">
+					<BR><BR>
+					<span class="linkShow" onClick="document.getElementById('showUserDescrRow').style.display='table-row';">I forgot my username</span>
+				</td>
+			</tr>
+
+			<TR ID="showUserDescrRow" style="display:none;">
+				<TD style="padding-left:10px;">
+					If you do not remember your username, please enter your full name (first and last):
+					<P><INPUT TYPE="TEXT" SIZE="45px" NAME="uDesc" ID="udesc_remind">
+				</td>
+			</TR>
+
+			<TR>
+				<TD style="padding-left:10px; padding-top:10px;">
+					<INPUT TYPE="SUBMIT" NAME="reset_pw" VALUE="Submit" onClick="return checkPasswordReminder();">
+					<BR><?php 
+						echo "<P>If you have not yet obtained an OpenFreezer user account, please <a href='mailto:" . $mail_programmer . "'>contact the administrator</a>.</span>";
+					?>
+				</TD>
+			</TR>
+		</TABLE>
+	</form><?php
+}
+
+/**
+ * Print a list of user's clone orders, which can be emailed to clone_request
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @uses Member_Class::getOrders()
+*/
+function outputOrders()
+{
+	global $cgi_path;
+	global $hostname;
+	
+	$gfunc_obj = new generalFunc_Class();
+	$lfunc_obj = new Location_Funct_Class();
+
+	// get username from session
+	$currUserName = $_SESSION["userinfo"]->getDescription();
+	$currUserID = $_SESSION["userinfo"]->getUserID();
+
+	// June 30, 2010
+	$currUserLabID = $_SESSION["userinfo"]->getLabID();
+	$currUserLabName = $_SESSION["Lab_ID_Name"][$currUserLabID];
+
+	if (!isset($_GET["Sent"]))
+	{
+		?>
+		<FORM NAME="view_lab_form" METHOD="POST" ACTION="<?php echo $cgi_path . "user_request_handler.py"; ?>">
+
+		<!-- Pass user info as a hidden form value - currently the most secure way to pass session info from PHP to Python -->
+		<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username" VALUE="<?php echo $currUserName; ?>">
+		<INPUT type="hidden" ID="curr_userid_hidden" NAME="curr_user_id" VALUE="<?php echo $currUserID; ?>">
+
+		<?php
+			$userOrders = $_SESSION["userinfo"]->getOrders();
+
+			if (sizeof($userOrders) == 0)
+			{
+				?><SPAN style="color:#0000FF;">You have no pending orders.</SPAN><BR><?php
+			}
+			else
+			{
+				?><SPAN style="color:#000000;">Reagents in your pending order:</SPAN><BR><?php
+				
+				$orderDate = date('Y-m-d');
+
+				// June 2, 2011: Dorothy's suggestion: include sequence
+				$outputContent = "Request Date,Requested By,Laboratory,LIMS ID,Gene Name,Accession Number,Plate,Well,Resistance,Verification,Project #,Restrictions on Use,Handout Date,Picked By,Sequence\r";
+
+				foreach ($userOrders as $key => $order)
+				{
+					$reagentID = $order->getReagentID();
+					$isoNum = $order->getIsolateNumber();
+					$contID = $order->getContainerID();
+					$row = $order->getRow();
+					$col = $order->getColumn();
+					$orderKey = $order->getOrderKey();
+					
+					// June 2, 2011: sequence
+					$seq = $order->getSequence();
+
+					// These properties may have multiple values - BUT: Dec. 16/08 - Check first if multiple; if the value is not an array, implode() won't work and will end up with a blank value!!!
+// 					$name = implode("; ", $order->getName());
+
+					// Dec. 16/08: Need to explicitly check whether the value is an array - won't output single values otherwise
+					if (is_array($order->getName()))
+						$name = implode("; ", $order->getName());
+					else
+						$name = $order->getName();
+
+// 					$resistance = implode("; ", $order->getResistance());
+
+					// Dec. 16/08: Need to explicitly check whether the value is an array - won't output single values otherwise
+					if (is_array($order->getResistance()))
+						$resistance = implode("; ", $order->getResistance());
+					else
+						$resistance = $order->getResistance();
+
+					// Feb, 16, 2011: Ditto for accessions from Insert
+					if (is_array($order->getAccession()))
+						$accession = implode("; ", $order->getAccession());
+					else
+						$accession = $order->getAccession();
+
+// 					$verification = implode("; ", $order->getVerification());
+
+					// Dec. 16/08: Need to explicitly check whether the value is an array - won't output single values otherwise
+					if (is_array($order->getVerification()))
+						$verification = implode("; ", $order->getVerification());
+					else
+						$verification = $order->getVerification();
+
+					$project = $order->getProject();	// Dec. 16/08
+
+					// Dec. 16/08: Need to explicitly check whether the value is an array - won't output single values otherwise
+					if (is_array($order->getRestrictions()))
+						$restrictions = implode("; ", $order->getRestrictions());
+					else
+						$restrictions = $order->getRestrictions();
+
+					echo "<P><INPUT TYPE=\"checkbox\" NAME=\"removeFromOrder[]\" VALUE=\"" . $orderKey . "\">";
+	
+					echo "  <a href=\"" . $hostname . "Location.php?View=2&Mod=" . $contID . "&Row=" . $row . "&Col=" . $col . "#focus_" . $row . "_" . $col . "\">" . $gfunc_obj->getConvertedID_rid($reagentID) . "-" . $isoNum . "</a>  " . $lfunc_obj->getContainerName($contID) . " " . $lfunc_obj->getLetterRow($row) . ":" . $col . "<BR>";
+
+					$outputContent .= $orderDate . "," . $currUserName . "," . $currUserLabName . "," . $gfunc_obj->getConvertedID_rid($reagentID) . "-" . $isoNum . "," . $name . "," . $accession . "," . $lfunc_obj->getContainerName($contID) . "," . $lfunc_obj->getLetterRow($row) . ":" . $col . "," . $resistance . "," . $verification . "," . $project . "," . $restrictions . ",,," . $seq . "\r";
+				}
+
+				// Dump content into a file (March 27/08 - Don't use temp, use the user's name as his/her unique order identifier)
+// 				$orderFileName = tempnam("/tmp", "tmp") . ".csv";
+				$tmp_name_ar = explode(" ", $currUserName);
+				$tmp_uname = implode("_", $tmp_name_ar);
+
+				$orderFileName = "/tmp/" . $tmp_uname . "_Clone_Request.csv";		// caution, check it's unique
+				$orderFile = fopen($orderFileName, 'w+');
+				fwrite($orderFile, $outputContent);
+				rewind($orderFile);
+
+				?>
+				<INPUT TYPE="hidden" NAME="outputContent" VALUE="<?php echo $orderFileName /*$outputContent*/; ?>">
+
+				<P>    <INPUT TYPE="BUTTON" id="removeFromOrder" value="Remove Selected" onClick="changeFormAction('view_lab_form', '<?php echo $_SERVER["PHP_SELF"] . "?View=9"?>')">
+
+				<!--PERMANENT -->
+				    <INPUT TYPE="SUBMIT" id="sendOrder" NAME="send_order" VALUE="Send Order">
+
+				<!-- TEMPORARY!!!!!!!!! -->
+<!-- 				    <INPUT TYPE="SUBMIT" id="sendOrder" NAME="send_order" VALUE="Export to Excel" onClick="toExcel('<?php /*echo $outputContent;*/ ?>');"> -->
+
+				<P><SPAN style="font-weight:bold"><u>Please note</u>: The order list is cleared when you exit the system.  Please make sure you export your order before logging out.</SPAN>
+				<?php
+			}
+		?>
+		</FORM>
+		<?php
+	}
+	else
+	{
+		if ($_GET["Sent"] == 1)
+		{
+			// Clear user's order list
+			$_SESSION["userinfo"]->setOrders(null);
+
+			?><SPAN style="color:#0000FF;">Your request has been submitted successfully.  A copy has been sent to your email address.  Please retain this copy for your records.</SPAN><BR><?php
+		}
+	}
+}
+
+mysql_close($conn);
+?>
diff --git a/OpenFreezer/User/UserFunctions.php b/OpenFreezer/User/UserFunctions.php
new file mode 100755
index 0000000..56876c6
--- /dev/null
+++ b/OpenFreezer/User/UserFunctions.php
@@ -0,0 +1,79 @@
+<?php
+/**
+* Auxiliary functions for managing user information in OpenFreezer
+*
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package User
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+	// Get the category of the user identified by $userID
+	// Output: INTEGER {1,2,3,4}, representing the user's access level to OpenFreezer
+	/**
+	  * @name Retrieve from the database and return the given user's category (access level to OpenFreezer)
+	  * @param INT
+	  * @return INT
+	*/
+	function getUserCategory($userID)
+	{
+		global $conn;
+
+		$categoryInfo_rs = mysql_query("SELECT category FROM `Users_tbl` WHERE `userID`='" . $userID . "' AND `status`='ACTIVE'", $conn) or die(mysql_error());
+		
+		if ($categoryInfo_ar = mysql_fetch_array($categoryInfo_rs, MYSQL_ASSOC))
+		{
+			$currUserCategory = $categoryInfo_ar["category"];
+		}
+
+		mysql_free_result($categoryInfo_rs);
+		unset($categoryInfo_rs, $categoryInfo_ar);
+
+		return $currUserCategory;
+	}
+
+	/**
+	  * @name Retrieve from the database and return the given user's laboratory (its internal database ID, e.g. '1' => 'Pawson Lab')
+	  * @param INT
+	  * @return INT
+	*/
+	function getUserLabID($userID)
+	{
+		global $conn;
+		
+		$uLabID = 0;
+
+		$lab_rs = mysql_query("SELECT labID FROM Users_tbl WHERE userID='" . $userID . "'", $conn) or die("Cannot select user lab ID: " . mysql_error());
+
+		if ($lab_ar = mysql_fetch_array($lab_rs, MYSQL_ASSOC))
+		{
+			$uLabID = $lab_ar["labID"];
+		}
+
+		mysql_free_result($lab_rs);
+		unset($lab_ar);
+
+		return $uLabID;
+	}
+?>
\ No newline at end of file
diff --git a/OpenFreezer/bugreport.php b/OpenFreezer/bugreport.php
new file mode 100755
index 0000000..02d21c1
--- /dev/null
+++ b/OpenFreezer/bugreport.php
@@ -0,0 +1,268 @@
+<?php
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package BugReport
+*
+* @copyright  2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+/**
+* Include/require statements
+*/
+	include "Classes/MemberLogin_Class.php";
+	include "Classes/Member_Class.php";
+	include "Classes/Bug_Function_Class.php";	// Aug. 4, 2010
+
+	include "Classes/Session_Var_Class.php";
+	include "DatabaseConn.php";
+
+	session_start();
+
+	$loginBlock = new MemberLogin_Class();
+	$loginBlock->loginCheck($_POST);
+
+	header("Cache-control: private"); //IE 6 Fix 
+
+	include "HeaderFunctions.php";
+
+	// Global Session Variables.
+	// FIX IT: Should probably isolate this better
+	$sessionChecker = new Session_Var_Class();
+	$sessionChecker->checkSession_all();
+	unset( $sessionChecker );
+
+	// print header
+	outputMainHeader();
+
+	// June 3, 2010
+	global $mail_biologist;
+	global $mail_programmer;
+
+	$b_func_obj = new Bug_Function_Class();
+
+	if (isset($_SESSION["userinfo"]))
+	{
+		$currUserName = $_SESSION["userinfo"]->getDescription();
+		$currUserID = $_SESSION["userinfo"]->getUserID();
+
+		if (isset($_GET["Req"]))
+		{
+			?>
+			<table style="text-align:justify;" width="770px" bgcolor="#FFFFFF">
+
+				<TR>
+					<TD style="padding-top:15px; padding-left:10px; font-weight:bold; white-space:nowrap; color:blue;">
+						Thank you!  Your support request has been submitted.
+					</TD>
+				</TR>
+
+				<TR>
+					<TD style="padding-left:10px;">
+						The programmer of OpenFreezer will contact you once the issue is resolved.
+					</TD>
+				</TR>
+			</table>
+			<?php
+		}
+		else
+		{
+			?>
+			<table style="text-align:justify;" width="770px" bgcolor="#FFFFFF">
+				<!-- Marina: March 4/08: Create a resizeable border -->
+	<!--			<tr>
+					<td rowspan="100%" style="padding-left:0; padding-right:5px;">
+						<div class="resizeable" onMouseOver="resize();"></div>
+					</td>
+				</tr>-->
+	
+				<th colspan="3" style="text-align:center; font-weight:bold; color:#635688; font-family: Arial;">Feature Request and Bug Report</th>
+	
+				<TR>
+					<TD style="padding-top:15px; padding-left:5px">
+						Please <a href="docs.php">read the documentation</a> for information on the features of OpenFreezer.<BR>
+	
+						<P>Please submit your support request using the following form:<BR>
+						<span style="font-size:9pt; color:red;">Fields marked with a red asterisk (<span style="color:red;">*</span>) are mandatory</span><BR>
+	
+						<FORM ACTION="<?php echo $cgi_path . "user_request_handler.py"; ?>" onSubmit="return checkModule() && checkIssue();">
+							<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_userid" VALUE="<?php echo $currUserID; ?>">
+	
+							<table width="760px" style="border: 1px solid black;" cellpadding="2" cellspacing="2">
+								<TR>
+									<TD colspan="2" style="font-size:9pt; padding-left:10px;">Is this a bug report or a feature request?</TD>
+								</tr>
+	
+								<TR>
+									<TD style="font-size:9pt; padding-left:10px;"">
+										<input type="radio" name="request_type" value="bug" checked>Bug
+										<input type="radio" name="request_type" value="feature">Feature
+									</TD>
+								</TR>
+	
+								<tr><td colspan="2"></td></tr>
+	
+								<TR>
+									<TD style="padding-left:10px;"><span style="color:red; padding-left:3px;">*</span> Module:</TD>
+								</TR>
+	
+								<TR>
+									<TD style="padding-left:12px;">
+										<!-- no need to show 'Other' textbox here, keep it simple for now -->
+										<select ID="modules_list" name="modules" style="font-size:9pt;">
+											<option value="default" selected>-- Select --</option>
+											<option value="Add Vector">Add Vector</option>
+											<option value="Add Insert">Add Insert</option>
+											<option value="Add Stable Cell Line">Add Stable Cell Line</option>
+											<option value="Add Other Reagent">Add Other Reagent</option>
+											<option value="Add Reagent Type">Add Reagent Type</option>
+											<option value="Edit Reagent Type">Edit Reagent Type</option>
+											<option value="Delete Reagent Type">Delete Reagent Type</option>
+											<option value="Primer Design">Primer Design</option>
+											<option value="Search Reagents">Search Reagents</option>
+											<option value="Edit Reagent Details">Edit Reagent Details</option>
+											<option value="Change Reagent Parents">Change Reagent Parents</option>
+											<option value="Delete Reagents">Delete Reagents</option>
+											<option value="Clone Request">Clone Request</option>
+											<option value="Add Containers">Add Containers</option>
+											<option value="Edit Container Details">Edit Container Details</option>
+											<option value="Add Container Type">Add Container Type</option>
+											<option value="Edit Container Type">Edit Container Type</option>
+											<option value="Add Container Size">Add Container Size</option>
+											<option value="Add Wells">Add Wells</option>
+											<option value="Modify Wells">Modify Wells</option>
+											<option value="Delete Wells">Delete Wells</option>
+											<option value="Add Project">Add Project</option>
+											<option value="Search Project">Search Project</option>
+											<option value="Edit Project">Edit Project</option>
+											<option value="Delete Project">Delete Project</option>
+											<option value="Change Password">Change Password</option>
+											<option value="Automated Password Reset">Automated Password Reset</option>
+											<option value="other">Other</option>
+										</select>
+									</TD>
+								</TR>
+	
+								<tr><td colspan="2"> </td></tr>
+	
+								<TR>
+									<TD style="padding-left:10px;">
+										 <span style="color:red;">*</span> Please describe in detail your issue or feature request:
+									</TD>
+								</TR>
+	
+								<TR>
+									<td style="padding-left:10px;">
+										<TEXTAREA ID="bugDescription" NAME="bug_description" cols="80" rows="10" style="overflow:scroll;"></TEXTAREA>
+									</td>
+								</TR>
+	
+								<tr><td colspan="2"></td></tr>
+	
+								<TR>
+									<TD style="padding-left:8px;">
+										<INPUT TYPE="submit" NAME="bug_report" VALUE="Submit">
+									</TD>
+								</TR>
+	
+								<tr><td colspan="2"></td></tr>
+							</table>
+						</FORM>
+					</TD>
+				</TR>
+	
+				<TR>
+					<TD style="padding-top:15px; padding-left:5px">
+						<span style="font-size:9pt; margin-top:8px; font-weight:bold; color:red;">List of known bugs:</span><BR><BR>
+
+						<TABLE border="1" frame="box" rules="all" width="100%">
+							<TR>
+								<TD style="text-align:center; font-weight:bold; text-decoration:none; width:auto; white-space:nowrap;">Request Type</TD>
+								<TD style="text-align:center; font-weight:bold; text-decoration:none; width:auto; white-space:nowrap;">Requested By</TD>
+								<TD style="text-align:center; font-weight:bold; text-decoration:none; width:auto; white-space:nowrap;">Module</TD>
+								<TD style="text-align:center; font-weight:bold; text-decoration:none; width:auto; white-space:nowrap;">Description</TD>
+							</TR>
+							<?php
+								$bugs = $b_func_obj->fetchAllBugs();
+	
+								foreach ($bugs as $key => $bug)
+								{
+									echo "<TR>";
+										echo "<TD style=\"padding:5px; white-space:nowrap;\">";
+											echo $bug->getBugType();
+										echo "</TD>";
+
+										echo "<TD style=\"padding:5px; white-space:nowrap;\">";
+											echo $bug->getRequestedBy();
+										echo "</TD>";
+
+										echo "<TD style=\"padding:5px; white-space:nowrap;\">";
+											echo $bug->getModule();
+										echo "</TD>";
+
+										echo "<TD style=\"padding:5px; white-space:nowrap;\">";
+											echo $bug->getBugDescription();
+										echo "</TD>";
+									echo "</TR>";
+								}
+							?>
+						</TABLE>
+					</TD>
+				</TR>
+	
+				<tr>
+					<TD style="padding-top:15px; padding-left:5px">
+						<HR>For additional help and support, please contact <a href="mailto:<?php echo $mail_programmer; ?>">Marina Olhovsky</a> or <a href="mailto:<?php echo $mail_biologist; ?>">Karen Colwill</a>.
+					</TD>
+				</tr>
+			</table>
+			<?php
+		}
+	}
+	else
+	{
+		# Disallow documentation download without login
+		$docs_disabled = true; 
+
+		?>
+		<table style="text-align:justify;" width="770px" bgcolor="#FFFFFF">
+			
+			<th colspan="3" style="text-align:center; font-weight:bold; color:#635688; font-family: Arial;">Feature Request and Bug Report</th>
+
+
+			<tr>
+				<TD style="padding-top:15px; padding-left:5px">
+<!-- 					<P>Please report any bugs or feature requests through the <a href="http://pawsonlab.mshri.on.ca/index.php?option=com_flyspray&Itemid=32">Bug/Feature Tracker</a> on the <A href="http://pawsonlab.mshri.on.ca/index.php">Pawson Lab Home Page</a>. -->
+
+					Please submit all bug reports to <a href="mailto:<?php echo $mail_programmer; ?>">Marina Olhovsky</a>.<BR><BR>
+
+					To request additional system features, please contact <a href="mailto:<?php echo $mail_programmer; ?>">Marina Olhovsky</a> or <a href="mailto:<?php echo $mail_biologist; ?>">Karen Colwill</a>.
+				</TD>
+			</tr>
+		</table>
+		<?php
+	}
+
+	// footer
+	outputMainFooter();
+?>
\ No newline at end of file
diff --git a/OpenFreezer/cgi/add_project_members.py b/OpenFreezer/cgi/add_project_members.py
new file mode 100755
index 0000000..cdf2030
--- /dev/null
+++ b/OpenFreezer/cgi/add_project_members.py
@@ -0,0 +1,48 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+	
+import MySQLdb
+import sys
+import string
+
+from database_conn import DatabaseConn
+from packet import Packet
+#from packet_handler import PacketHandler
+from exception import *
+
+import utils
+
+def redirect(url):
+	"Called to redirect to the given url."
+	print 'Location:' + url
+	print
+
+
+# Process Project (Packet) creation request
+def add_members():
+
+	dbConn = DatabaseConn()
+	
+	db = dbConn.databaseConnect()
+	cursor = db.cursor()
+	hostname = dbConn.getHostname()
+		
+	form = cgi.FieldStorage(keep_blank_values="True")
+	
+	pHandler = PacketHandler(db, cursor)
+	
+	#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+	#print					# DITTO
+	#print `form`
+
+	# Get form values
+	projectID = form.getvalue("packets")
+	projectMembers = form.getlist("projectMembers")
+	
+	pHandler.insertProjectMembers(projectID, projectMembers)
+		
+	redirect(hostname)
+	
+add_members()
diff --git a/OpenFreezer/cgi/add_users.py b/OpenFreezer/cgi/add_users.py
new file mode 100755
index 0000000..6568423
--- /dev/null
+++ b/OpenFreezer/cgi/add_users.py
@@ -0,0 +1,47 @@
+import MySQLdb
+import getpass
+
+def add_users():
+    
+    print "Please enter the following information to connect to the database: "
+    
+    hostname = raw_input("Hostname: (press Enter for 'localhost')")
+    db_name = raw_input("Database name: ")
+    username = raw_input("Username: ")
+    password = getpass.getpass("Password: ")
+    
+    if len(hostname) == 0:
+        hostname = "localhost"
+        
+    conn = MySQLdb.connect(host=hostname, user=username, passwd=password, db=db_name)	
+    cursor = conn.cursor()
+
+    secured_pages = []
+
+    cursor.execute("SELECT `pageID` FROM `SecuredPages_tbl`")
+    page_set = cursor.fetchall()
+    
+    for p in page_set:
+        secured_pages.append(int(p[0]))
+
+    go_on = 1
+    
+    while go_on:
+        
+        new_username = raw_input("Enter a username for the user you wish to add: ")
+        new_passwd = getpass.getpass("Enter the password for this user: ")
+        new_email = raw_input("Enter the email address of this user: ")
+        new_descr = raw_input("Enter a description for this user: ")
+        
+        cursor.execute("INSERT INTO `Users_tbl`(`username`, `password`, `email`, `description`) VALUES(" + `new_username` + ", MD5(" + `new_passwd` + "), " + `new_email` + ", " + `new_descr` + ")")
+        new_user_id = int(conn.insert_id())
+        
+        for page in secured_pages:
+            cursor.execute("INSERT INTO `UserPermission_tbl`(`pageID`, `userID`) VALUES(" + `page` + ", " + `new_user_id` + ")")
+        
+        print "User " + new_username + " successfully added to the database."
+        go_on = int(raw_input("Would you like to add more users? (enter 1 or 0): "))
+        
+    print "Thank you - goodbye!"
+    
+add_users()
\ No newline at end of file
diff --git a/OpenFreezer/cgi/barcodes.py b/OpenFreezer/cgi/barcodes.py
new file mode 100755
index 0000000..0824ad3
--- /dev/null
+++ b/OpenFreezer/cgi/barcodes.py
@@ -0,0 +1,27 @@
+#!/usr/local/bin python
+
+from location_database_handler import LocationHandler
+from database_conn import DatabaseConn
+
+import MySQLdb
+
+dbConn = DatabaseConn()
+db = dbConn.databaseConnect()
+cursor = db.cursor()
+
+lHandler = LocationHandler(db, cursor)
+
+cursor.execute("SELECT * FROM Container_tbl WHERE status='ACTIVE'")
+containers = cursor.fetchall()
+
+for cont in containers:
+	contID = int(cont[0])
+	contTypeID = int(cont[1])
+	contSizeID = int(cont[2])
+	cLab = int(cont[6])
+
+	bcNum = lHandler.findNextContainerBarcodeNumber(contTypeID, contSizeID, cLab)
+	barcode = lHandler.generateBarcode(contTypeID, contSizeID, bcNum, cLab)
+	
+	cursor.execute("UPDATE Container_tbl SET barcode=" + `barcode` + " WHERE containerID=" + `contID`)
+
diff --git a/OpenFreezer/cgi/cell_line_stats.py b/OpenFreezer/cgi/cell_line_stats.py
new file mode 100755
index 0000000..f0a0a0f
--- /dev/null
+++ b/OpenFreezer/cgi/cell_line_stats.py
@@ -0,0 +1,193 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+
+import MySQLdb
+import sys
+import string
+
+from database_conn import DatabaseConn
+
+from mapper import ReagentPropertyMapper, ReagentAssociationMapper
+from general_handler import *
+from reagent_handler import ReagentHandler, InsertHandler
+from sequence_handler import DNAHandler, ProteinHandler
+from comment_handler import CommentHandler
+#from system_set_handler import SystemSetHandler
+from sequence_handler import SequenceHandler
+from reagent import *
+
+from location_database_handler import LocationHandler
+
+import utils
+
+from user_handler import UserHandler
+from project_database_handler import ProjectDatabaseHandler
+from session import Session
+from exception import *
+
+dbConn = DatabaseConn()
+db = dbConn.databaseConnect()
+
+cursor = db.cursor()
+hostname = dbConn.getHostname()
+root_path = dbConn.getRootDir()
+
+dnaHandler = DNAHandler(db, cursor)
+protHandler = ProteinHandler(db, cursor)
+rHandler = ReagentHandler(db, cursor)
+pHandler = ReagentPropertyHandler(db, cursor)
+rtPropHandler = ReagentTypePropertyHandler(db, cursor)
+lHandler = LocationHandler(db, cursor)
+
+propMapper = ReagentPropertyMapper(db, cursor)
+rtMapper = ReagentTypeMapper(db, cursor)
+
+reagentType_Name_ID_Map = rtMapper.mapTypeNameID()
+
+prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+prop_ID_Name_Map = propMapper.mapPropIDName()		# (prop id, prop name)
+
+prop_Name_Descr_Map = propMapper.mapPropNameDescription()
+prop_ID_Descr_Map = propMapper.mapPropIDDescription()
+
+prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+
+def main():
+	
+	#print "Content-type:text/html"
+	#print
+
+	clTypeID = reagentType_Name_ID_Map["CellLine"]
+
+	# list of propNames
+	bhPropNames = rtPropHandler.findReagentTypeAttributeNamesByCategory(clTypeID, prop_Category_Name_ID_Map["Biosafety"])
+
+	bhPropNames.sort()
+
+	content = ""
+
+	# Print in this order
+	content += "Cell Line ID\tName\tRisk Group\tContainment Level\tKnown Pathogens\tSafety Notes\tContainer\tWells\tTotal Vials\tStorage Location\tShelf\tRack\tRow\tColumn\n"
+
+	namePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["name"], prop_Category_Name_ID_Map["General Properties"])
+	#print namePropID
+
+	# get all cell lines - remember, table column value is 'CellLine', not 'Cell Line'!!!
+	cursor.execute("SELECT reagentID FROM Reagents_tbl r, ReagentType_tbl t WHERE r.reagentTypeID=" + `clTypeID` + " AND r.reagentTypeID=t.reagentTypeID AND r.status='ACTIVE' AND t.status='ACTIVE'")
+	cell_line_results = cursor.fetchall()
+
+	for cl_res in cell_line_results:
+		cellLineID = int(cl_res[0])
+		#print cellLineID
+
+		cellLine_id = rHandler.convertDatabaseToReagentID(cellLineID)
+		#print cellLine_id
+
+		# name, storage (location + storage type), container, well
+		clName = rHandler.findSimplePropertyValue(cellLineID, namePropID)
+		#print clName
+
+		# Hard-code
+		riskGroupPropCatID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["risk group"], prop_Category_Name_ID_Map["Biosafety"])
+		riskGroup_prop_val = rHandler.findSimplePropertyValue(cellLineID, riskGroupPropCatID)
+
+		if not riskGroup_prop_val:
+			riskGroup_prop_val = ""
+	
+		contLevelPropCatID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["containment level"], prop_Category_Name_ID_Map["Biosafety"])
+		contLevel_prop_val = rHandler.findSimplePropertyValue(cellLineID, contLevelPropCatID)
+
+		if not contLevel_prop_val:
+			contLevel_prop_val = ""
+
+		pathogensPropCatID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["known pathogens"], prop_Category_Name_ID_Map["Biosafety"])
+		pathogens_prop_val = rHandler.findSimplePropertyValue(cellLineID, pathogensPropCatID)
+
+		if not pathogens_prop_val:
+			pathogens_prop_val = ""
+
+		safetyNotesPropCatID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["safety notes"], prop_Category_Name_ID_Map["Biosafety"])
+		safety_prop_val = rHandler.findSimplePropertyValue(cellLineID, safetyNotesPropCatID)
+
+		if not safety_prop_val:
+			safety_prop_val = ""
+
+		# Location
+		expID = lHandler.findExperimentByReagentID(cellLineID)
+		isolates = lHandler.findIsolates(expID)
+
+		total_vials = 0
+		wells = ""
+
+		wellContDict = {}
+
+		for isoID in isolates:
+			preps = lHandler.findPreps(isoID)
+			
+			for prepID in preps:
+				total_vials += 1
+
+				wellID = lHandler.findWellID(prepID)
+				containerID = lHandler.findContainerByWell(wellID)
+
+				if wellContDict.has_key(containerID):
+					cont_wells = wellContDict[containerID]
+				else:
+					cont_wells = []
+
+				cont_wells.append(wellID)
+				wellContDict[containerID] = cont_wells
+
+		for containerID in wellContDict.keys():
+			containerName = lHandler.findContainerName(containerID)
+			contStorageName = lHandler.findContainerStorageTypeName(containerID)
+
+			if not contStorageName:
+				contStorageName = ""
+
+			contShelf = lHandler.findContainerShelf(containerID)
+			contRack = lHandler.findContainerRack(containerID)
+			contRow = lHandler.findContainerRow(containerID)
+			contColumn = lHandler.findContainerColumn(containerID)
+			
+			all_wells = wellContDict[containerID]
+
+			storage_location = contStorageName + '\t' + `contShelf` + '\t' + `contRack` + '\t' + `contRow` + '\t' + `contColumn`
+
+			total_vials = 0
+			wells = ""
+
+			for wellID in all_wells:
+				well_coords = lHandler.findWellCoordinates(wellID)
+				
+				# Output: Plate Name\tWells separated by comma\tTotal vials\tStorage		
+				wells += well_coords + ','
+				total_vials += 1
+
+			location_content = containerName + '\t' + wells + '\t' + `total_vials`
+
+			content += cellLine_id + '\t'
+
+			if clName:
+				content += clName + '\t'
+			else:
+				content += '\t'
+
+			content += riskGroup_prop_val + '\t'
+			content += contLevel_prop_val + '\t'		
+			content += pathogens_prop_val + '\t'		
+			content += safety_prop_val + '\t'
+
+			content += location_content + '\t'
+			content += storage_location + '\n'
+		
+	fname = "Cell_Line_Biosafety_Statistics.tsv"
+
+	print "Content-type: application/octet-stream"
+	print "Content-Disposition: attachment; name=" + fname
+	print
+	print content
+	
+main()
\ No newline at end of file
diff --git a/OpenFreezer/cgi/comment_handler.py b/OpenFreezer/cgi/comment_handler.py
new file mode 100755
index 0000000..021a337
--- /dev/null
+++ b/OpenFreezer/cgi/comment_handler.py
@@ -0,0 +1,134 @@
+import string
+import MySQLdb
+
+from general_handler import *
+from mapper import *
+
+################################################################################
+# Module comment_handler
+# An interface to GeneralComments_tbl in OpenFreezer
+#
+# This module performs SQL queries to deal specifically with selecting/inserting/changing
+# comments for reagents and locations
+#
+# Written October 30, 2006 by Marina Olhovsky
+#
+# Last modified: January 20, 2010
+################################################################################
+
+################################################################################
+# CommentHandler class
+# Subclass of GeneralHandler class
+# Written October 30, 2006, by Marina Olhovsky
+################################################################################
+class CommentHandler(GeneralHandler):
+	"This class handles insertion/selection/update of comments in OpenFreezer"
+	
+	__propHandler = None
+	__propMapper = None
+	__prop_Name_ID_Map = None
+	
+	def __init__(self, db, cursor):
+		self.db = db
+		self.cursor = cursor
+		self.__propHandler = ReagentPropertyHandler(db, cursor)
+		self.__propMapper = ReagentPropertyMapper(db, cursor)
+		self.__prop_Name_ID_Map = self.__propMapper.mapPropNameID()
+		self.__prop_Category_Name_ID_Map = self.__propMapper.mapPropCategoryNameID()
+	
+	# Return true if the property is 'experimental comments', 'verification comments' or 'description'
+	def isComment(self, propID):
+		pHandler = self.__propHandler
+		
+		# Update Jan. 20, 2010: Can no longer rely on property name alone, need its category!!!!!!
+		#return propID == pHandler.findPropID('comments') or propID == pHandler.findPropID('verification comments') or propID == pHandler.findPropID('description')
+		
+		return propID == pHandler.findReagentPropertyInCategoryID(self.__prop_Name_ID_Map['comments'], self.__prop_Category_Name_ID_Map["General Properties"]) or propID == pHandler.findReagentPropertyInCategoryID(self.__prop_Name_ID_Map['verification comments'], self.__prop_Category_Name_ID_Map["General Properties"]) or propID == pHandler.findReagentPropertyInCategoryID(self.__prop_Name_ID_Map['description'], self.__prop_Category_Name_ID_Map["General Properties"])
+
+
+	# Check if a comment exists in OpenFreezer
+	# If yes, return its commentID stored in GeneralComments_tbl
+	def existsComment(self, commLinkID, comment):
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT `commentID` FROM `GeneralComments_tbl` WHERE `commentLinkID`=" + `commLinkID` + " AND `comment`=" + `comment` + " AND `status`='ACTIVE'")
+		
+		result = cursor.fetchone()	# may be multiple, e.g. 'MGC Clone', but just get one for simplicity.
+						# Technically there should only be one table entry per comment; multiple IDs for the same comment are the result of poor design and lack of verification
+		
+		if result:
+			return int(result[0])
+		
+		return -1
+	
+
+	# Find the commentLinkID that corresponds to commLink
+	# E.g. commLink = 'Packet', commentLinkID = '3'
+	# commLink = 'Reagent', commentLinkID = '1'
+	# etc.
+	def findCommentLinkID(self, commLink):
+		db = self.db
+		cursor = self.cursor
+		
+		commLinkID = -1
+
+		cursor.execute("SELECT commentLinkID FROM CommentLink_tbl WHERE link=" + `commLink`)
+		result = cursor.fetchone()
+
+		if result:
+			commLinkID = int(result[0])
+
+		return commLinkID		
+
+	# Find the ID of a comment
+	def findCommentID(self, comment, commLinkID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		commentID = -1
+
+		cursor.execute("SELECT commentID FROM GeneralComments_tbl WHERE commentLinkID=" + `commLinkID` + " AND comment=" + `comment` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		if result:
+			commentID = int(result[0])
+
+		return commentID
+
+
+	# Pull out the actual comment text associated with commentID (reciprocal of commentExists)
+	# Parameters: commentID - int
+	# Returns: text
+	def findCommentByID(self, commentID):
+		db = self.db
+		cursor = self.cursor
+
+		cursor.execute("SELECT `comment` FROM `GeneralComments_tbl` WHERE `commentID`=" + `commentID` + " AND `status`='ACTIVE'")
+		result = cursor.fetchone()	# unique
+			
+		if result:
+			return result[0]
+		
+		return None
+	
+
+	# Insert a new comment into GeneralComments_tbl and return its commentID
+	# Comment may be empty
+	# Parameters: comment - a TEXT field
+	# Return: commentID = int
+	def insertComment(self, commLinkID, comment):
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("INSERT INTO `GeneralComments_tbl`(`commentLinkID`, `comment`) VALUES(" + `commLinkID` + ", " + `comment` + ")")
+		return int(db.insert_id())
+		
+		
+	# Set status='DEP' of GeneralComments_tbl entry, identified by commID
+	def deleteComment(self, commID):
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE GeneralComments_tbl SET status='DEP' WHERE commentID=" + `commID` + " AND status='ACTIVE'")
diff --git a/OpenFreezer/cgi/container.py b/OpenFreezer/cgi/container.py
new file mode 100755
index 0000000..1954969
--- /dev/null
+++ b/OpenFreezer/cgi/container.py
@@ -0,0 +1,144 @@
+#!/usr/local/bin/python
+
+# python modules
+import cgi
+import cgitb; cgitb.enable()
+
+import SocketServer
+from SocketServer import BaseRequestHandler
+
+import MySQLdb
+
+import os
+import tempfile
+import stat
+import sys
+import string
+
+# Custom modules
+import utils
+
+from database_conn import DatabaseConn
+#from session import Session
+
+from general_handler import GeneralHandler
+from laboratory import Laboratory
+
+class Container:
+	
+	__cont_type = ""	# Vector, Glycerol Stock, Oligo, Insert, Cell Line
+	__cont_size = 0		# 96-well plate, 81-slot box, etc.
+	__rows = 0
+	__cols = 0
+	__num_wells = 0		# total number of samples stored in the container
+	__cont_name = ""
+	__cont_desc = ""
+	__cont_lab = None	# Laboratory OBJECT, the lab that owns the container
+	
+	__properties = []	# list of properties specific to this container's type
+	
+	
+	def __init__(self, cType="", cSize=0, nRows=0, nCols=0, cName=0, cLab=0, cDesc="", c_props=[]):
+		
+		self.__cont_type = cType
+		self.__cont_size = cSize
+		self.__rows = nRows
+		self.__cols = nCols
+		self.__num_wells = nRows * nCols
+		self.__cont_name = cName
+		self.__cont_desc = cDesc
+		self.__cont_lab = Laboratory(cLab)
+		
+		# Assign properties based on container type
+		if cType == 'Vector':
+			self.__properties = ['Method ID', 'Concentration']
+			
+		elif cType == 'Glycerol Stocks':
+			self.__properties = ['Bacteria Strain']
+			
+		elif cType == 'Oligo':
+			self.__properties = ['Concentration', 'Reagent Source']
+		
+		elif cType == 'Insert':
+			self.__properties = ['Concentration', 'Alternate ID', "5' digest/3' Digest"]
+			
+		elif cType == 'Cell Line':
+			self.__properties = ['Isolate Name', 'Plates/Vial', 'Date', 'Person', 'Passage']
+		
+		# Jan. 3/10
+		else:
+			self.__properties = c_props
+	
+	#################################################
+	# Assignment methods
+	#################################################
+	def setContainerType(self, cType):
+		self.__cont_type = cType
+		
+		
+	def setContainerSize(self, cSize):
+		self.__cont_size = cSize
+		
+		
+	def setNumRows(self, nRows):
+		self.__rows = nRows
+		
+	
+	def setNumCols(self, nCols):
+		self.__cols = nCols
+		
+	
+	def setContainerName(self, cName):
+		self.__cont_name = cName
+		
+		
+	def setContainerDescription(self, desc):
+		self.__cont_desc = desc
+		
+		
+	def setContainerLab(self, cLab):
+		newLab = Laboratory(cLab)
+		self.__cont_lab = newLab
+		
+		
+	#################################################
+	# Access methods
+	#################################################
+	def getContainerType(self):
+		return self.__cont_type
+	
+	
+	def getContainerSize(self):
+		return self.__cont_size
+	
+	
+	def getNumRows(self):
+		return self.__rows
+	
+	
+	def getNumCols(self):
+		return self.__cols
+	
+	
+	def getNumWells(self):
+		
+		if self.__num_wells == 0:
+			return self.__rows * self.__cols
+		else:
+			return self.__num_wells
+		
+		
+	def getContainerName(self):
+		return self.getContainerName
+	
+	
+	def getContainerDescription(self):
+		return self.__cont_desc
+	
+	
+	def getContainerLab(self):
+		return self.__cont_lab
+	
+	
+	def getContainerProperties(self):
+		return self.__properties
\ No newline at end of file
diff --git a/OpenFreezer/cgi/create.py b/OpenFreezer/cgi/create.py
new file mode 100755
index 0000000..aaa1659
--- /dev/null
+++ b/OpenFreezer/cgi/create.py
@@ -0,0 +1,1695 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+
+import MySQLdb
+import sys, os, tempfile
+import string
+
+from database_conn import DatabaseConn
+
+from mapper import ReagentPropertyMapper, ReagentAssociationMapper, ReagentTypeMapper
+
+from general_handler import *
+from reagent_handler import *
+from sequence_handler import DNAHandler, ProteinHandler
+from comment_handler import CommentHandler
+#from system_set_handler import SystemSetHandler
+from user_handler import UserHandler
+from project_database_handler import ProjectDatabaseHandler
+
+from session import Session
+
+from reagent_output import ReagentOutputClass
+from reagent import Reagent, Vector, Insert
+
+from sequence_feature import SequenceFeature
+
+import utils
+
+dbConn = DatabaseConn()
+db = dbConn.databaseConnect()
+
+#db = MySQLdb.connect(host="localhost", user="www", passwd="sh2domain", db="LIMS_ReagentTracker_TEST")
+cursor = db.cursor()
+hostname = dbConn.getHostname()
+
+root_path = dbConn.getRootDir()
+
+# Handlers and mappers
+rHandler = ReagentHandler(db, cursor)
+iHandler = InsertHandler(db, cursor)
+commHandler = CommentHandler(db, cursor)
+sHandler = SystemSetHandler(db, cursor)
+aHandler = AssociationHandler(db, cursor)
+dnaHandler = DNAHandler(db, cursor)
+protHandler = ProteinHandler(db, cursor)
+rnaHandler = RNAHandler(db, cursor)
+pHandler = ReagentPropertyHandler(db, cursor)
+raHandler = ReagentAssociationHandler(db, cursor)
+rtAssocHandler = ReagentTypeAssociationHandler(db, cursor)
+rtPropHandler = ReagentTypePropertyHandler(db, cursor)	# Aug. 31/09
+packetHandler = ProjectDatabaseHandler(db, cursor)
+rtHandler = ReagentTypeHandler(db, cursor)
+
+propMapper = ReagentPropertyMapper(db, cursor)
+assocMapper = ReagentAssociationMapper(db, cursor)
+rMapper = ReagentTypeMapper(db, cursor)
+
+prop_Alias_ID_Map = propMapper.mapPropAliasID()		# (propAlias, propID) - e.g. ('insert_type', '48') --> represents 'type of insert' property
+prop_Name_Alias_Map = propMapper.mapPropNameAlias()	# (propName, propAlias)
+prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+
+prop_ID_Name_Map = propMapper.mapPropIDName()		# Added March 13/08 - (prop id, prop name)
+prop_Alias_Name_Map = propMapper.mapPropAliasName()	# March 18/08 - (propAlias, propName)
+prop_Alias_Descr_Map = propMapper.mapPropAliasDescription()
+
+# June 1/09
+prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+prop_Category_Alias_ID_Map = propMapper.mapPropCategoryAliasID()
+prop_Category_Alias_Name_Map = propMapper.mapPropCategoryAliasName()
+prop_Category_Name_Alias_Map = propMapper.mapPropCategoryNameAlias()
+
+rOut = ReagentOutputClass()
+
+# Create a type name/id map upfront
+reagentType_Name_ID_Map = rMapper.mapTypeNameID()
+reagentType_ID_Name_Map = rMapper.mapTypeIDName()
+
+
+def redirect(url):
+	"Called to redirect to the given url."
+	print 'Location:' + url
+	print
+
+
+# Process reagent properties upon exit from Modify view
+def create():
+	
+	form = cgi.FieldStorage(keep_blank_values="True")
+
+	#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+	#print					# DITTO
+	#print `form`
+
+	# Sept. 3/07
+	uHandler = UserHandler(db, cursor)
+	
+	if form.has_key("curr_username"):
+		# store the user ID for use throughout the session; add to other views in addition to create in PHP
+		currUname = form.getvalue("curr_username")
+		currUser = uHandler.getUserByDescription(currUname)
+		
+		Session.setUser(currUser)
+	
+	########################################################
+	# Various maps
+	########################################################
+
+	prop_Alias_ID_Map = propMapper.mapPropAliasID()		# (propAlias, propID) - e.g. ('insert_type', '48') --> represents 'type of insert' property
+	prop_Name_Alias_Map = propMapper.mapPropNameAlias()	# (propName, propAlias)
+	prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+	prop_Alias_Name_Map = propMapper.mapPropAliasName()	# (propAlias, propName)
+	
+	# Jan. 31/08
+	assoc_Name_ID_Map = assocMapper.mapAssocNameID()	# (assocName, assocID)
+	assoc_ID_Name_Map = assocMapper.mapAssocIDName()	# (assocID, assocName)
+	assoc_ID_Alias_Map = assocMapper.mapAssocIDAlias()	# (assocID, assocAlias)
+
+	# April 15, 2011
+	assocType_ID_Name_Map = assocMapper.mapAssocTypeIDName()
+	assocType_Name_ID_Map = assocMapper.mapAssocTypeNameID()
+	
+	# April 15, 2011
+	assocType_ID_Name_Map = assocMapper.mapAssocTypeIDName()
+	assocType_Name_ID_Map = assocMapper.mapAssocTypeNameID()
+
+	# Nov. 6/08: 'Cancel' function - top priority, regardless of what other actions the form may have
+	if form.has_key("cancel_creation"):
+		
+		# Delete (deprecate) the reagent itself, its properties, protein/DNA sequence and associations
+		#rType = form.getvalue("reagent_type_hidden")
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `prop_Alias_Name_Map`
+		#print `form`
+		
+		prefix = "reagent_detailedview_"
+		postfix = "_prop"
+		
+		rID = int(form.getvalue("reagent_id_hidden"))
+		
+		# if this is an Insert made from Primer, delete the newly created Oligos too
+		if form.has_key("from_primer") and form.getvalue("from_primer") == 'True':
+			senseOligoID = iHandler.findSenseOligoID(rID)
+			antisenseOligoID = iHandler.findAntisenseOligoID(rID)
+			
+			rHandler.deleteReagent(senseOligoID)
+			rHandler.deleteReagent(antisenseOligoID)
+			rHandler.deleteReagent(rID)
+		else:
+			rHandler.deleteReagent(rID)
+		
+		utils.redirect(hostname + "Reagent.php?View=1")
+
+	# Proceed with creation depending on the reagent type
+	elif form.has_key("create_reagent"):
+		rType = form.getvalue("reagent_type_hidden")
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print "REAGENT TYPE " + rType
+
+		# Different form name prefixes depending on reagent type - original setup
+	
+		if rType == 'CellLine':
+			
+			#print "Content-type:text/html"
+			#print
+			#print `form`
+
+			# changed Jan. 19, 2010
+			#genPrefix = "INPUT_CELLLINE_info_"
+			genPrefix = "reagent_detailedview_CellLine_"
+			postfix = "_prop"
+			
+			#assocPrefix = "assoc_"
+
+			assocPropsDict = {}
+			
+			# Create a new Cell Line instance - Jan. 21, 2010: IFF PARENT!!!!!!! rID already generated for stable
+			if form.has_key("reagent_id_hidden"):
+				rID = int(form.getvalue("reagent_id_hidden"))
+			else:
+				rID = rHandler.createNewReagent(rType)
+			
+			reagent = rHandler.createReagent(rID)
+			
+			rTypeID = reagentType_Name_ID_Map["CellLine"]
+
+			# Associations
+			
+			# Jan. 21, 2010
+			if form.has_key("INPUT_CELLLINE_info_cellline_id_prop"):
+				parentCL = form.getvalue("INPUT_CELLLINE_info_cellline_id_prop").strip()
+				parentVector = form.getvalue("INPUT_CELLLINE_info_vector_id_prop").strip()
+				
+				assocPropsDict["cell_line_parent_vector"] = parentVector
+				assocPropsDict["parent_cell_line"] = parentCL
+			else:
+				aTypeID = "Parent Cell Line"
+			
+			# Find the actual names and database IDs of POST values
+			newPropsDict_name = {}		# e.g. ('status', 'Completed')
+        		newPropsDict_id = {}		# e.g. ('3', 'Completed') - db ID instead of property name
+			
+			# Find actual property values
+			for propName_tmp in form.keys():
+				#print propName_tmp
+				
+				if propName_tmp.find("_:_") > 0:
+					pToks = propName_tmp.split("_:_")
+					#print `pToks`
+					
+					if pToks[0].find(genPrefix) == 0:
+						catAlias = pToks[0][len(genPrefix):]
+						#print catAlias
+						categoryID = prop_Category_Alias_ID_Map[catAlias]
+					else:
+						continue
+						
+					if pToks[1].find(postfix) + len(postfix) == len(pToks[1]):
+						propAlias = pToks[1][0:pToks[1].find(postfix)]
+						propName = prop_Alias_Name_Map[propAlias]
+						propID = prop_Alias_ID_Map[propAlias]
+					else:
+						continue
+					
+					if utils.isList(form[propName_tmp]) or propAlias.lower() == "alternate_id":
+						newPropVal = utils.unique(form.getlist(propName_tmp))
+						#print `newPropVal`
+						
+						tmp_alt_ids = []
+						
+						for altID in newPropVal:
+							#print altID
+							
+							# this is ONLY for Alternate ID!!!!!!
+							if form.has_key(propAlias + "_" + altID + "_textbox_name"):
+								if altID.lower() != "other":
+									tmp_alt_id = altID + ":" + form.getvalue(propAlias + "_" + altID + "_textbox_name")
+								else:
+									#print "HERE!!"
+									tmp_alt_id = form.getvalue(propAlias + "_" + altID + "_textbox_name")
+									
+									#print tmp_alt_id
+									
+									# Feb. 5/10: update list
+									other_alt_id = form.getvalue(propAlias + "_" + altID + "_textbox_name")
+									
+									#print other_alt_id
+									new_set_val = other_alt_id[0:other_alt_id.find(":")]
+									#print new_set_val
+									
+									pcID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[propAlias], categoryID)
+							
+									rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, pcID)
+									
+									setGroupID = sHandler.findPropSetGroupID(pcID)
+									ssetID = sHandler.findSetValueID(setGroupID, new_set_val)
+									
+									if sHandler.findSetValueID(setGroupID, form.getvalue(propAlias + "_" + altID + "_textbox_name")) <= 0:
+										ssetID = sHandler.addSetValue(setGroupID, new_set_val)
+									
+									if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+										sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+								
+								#print tmp_alt_id
+								tmp_alt_ids.append(tmp_alt_id)
+
+							# May 26, 2010: This is for any multiple list properties for Cell Line
+							else:
+								#print "here " + altID
+								
+								# update list and save reagent property values
+								new_set_val = altID
+								
+								pcID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[propAlias], categoryID)
+								
+								#print pcID
+							
+								rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, pcID)
+								
+								#print rTypeAttributeID
+								
+								setGroupID = sHandler.findPropSetGroupID(pcID)
+								#print setGroupID
+								ssetID = sHandler.findSetValueID(setGroupID, new_set_val)
+								#print ssetID
+								
+								if sHandler.findSetValueID(setGroupID, new_set_val) <= 0:
+									ssetID = sHandler.addSetValue(setGroupID, new_set_val)
+								
+								if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+									sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+								
+								tmp_alt_ids.append(altID)
+
+						newPropVal = tmp_alt_ids
+					else:
+						newPropVal = form[propName_tmp].value.strip()
+						
+						# May 27, 2010: Here, add check again to see if this is one value in a multiple list!!!  We are not storing property format in database, only way of differentiating b/w freetext and dropdowns that should be updated is: a) If textbox is found - this is a dropdown, save value  b) If rtPropHandler.isMultiple() returns true, this is a multiple dropdown where only one value was entered - OK.  DO NOT ADD ANY OTHER VALUES TO SET!!!!!!!!!!
+						pcID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[propAlias], categoryID)
+						
+						rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, pcID)
+						
+						# This is a multiple dropdown where only one value was entered.  Update set
+						if rtPropHandler.isMultiple(rTypeAttributeID):
+							
+							setGroupID = sHandler.findPropSetGroupID(pcID)
+							ssetID = sHandler.findSetValueID(setGroupID, newPropVal)
+							
+							if sHandler.findSetValueID(setGroupID, newPropVal) <= 0:
+								ssetID = sHandler.addSetValue(setGroupID, newPropVal)
+							
+							if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+								sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+
+						# In 99.9% of cases this is a single dropdown (would be EXTREMELY unlikely that this is a text value that says 'Other').  If textbox exists, update set
+						elif newPropVal.lower() == 'other':
+							# get the value in the textbox
+							#textBox = propName_tmp.replace(postfix, "_name_txt")
+							
+							# But DO NOT USE 'replace()', as it would replace first occurrence from BEGINNING of name, so if have 'prefix_general_PROPerties_Vector_category_:_propName_prop', the first 'PROP' would get replaced.  DON'T use rstrip() either
+							#textBox = propName_tmp.rstrip(postfix) + "_name_txt"
+							textBox = propName_tmp[0:len(propName_tmp)-len(postfix)] + "_name_txt"
+							
+							if form.has_key(textBox):
+								newPropVal = form[textBox].value.strip()
+								#print newPropVal
+								
+								setGroupID = sHandler.findPropSetGroupID(pcID)
+								ssetID = sHandler.findSetValueID(setGroupID, newPropVal)
+								
+								if sHandler.findSetValueID(setGroupID, newPropVal) <= 0:
+									ssetID = sHandler.addSetValue(setGroupID, newPropVal)
+								
+								if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+									sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+
+					propCatID = pHandler.findReagentPropertyInCategoryID(propID, categoryID)
+					newPropsDict_id[propCatID] = newPropVal
+					newPropsDict_name[propName] = newPropVal
+
+			# Action
+			#print `newPropsDict_id`
+			rHandler.addReagentProperties(rID, newPropsDict_id)
+			rHandler.addReagentAssociations(rID, assocPropsDict)
+			
+			# redirect to detailed view of the new reagent
+			utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+			
+		# April 27/09: New reagent types
+		else:
+			#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+			#print					# DITTO
+			#print `form`
+			#print rType
+			
+			genPrefix = "reagent_detailedview_" + rType + "_"	# update Oct. 26/09 - reagent type included in feature names
+			postfix = "_prop"
+			
+			# Create a new Insert instance
+			rID = rHandler.createNewReagent(rType)
+			reagent = rHandler.createReagent(rID)
+			
+			rTypeID = reagentType_Name_ID_Map[rType]
+			
+			# Find the actual names and database IDs of POST values (no checkbox properties for Oligos)
+			newPropsDict_name = {}		# e.g. ('status', 'Completed')
+        		newPropsDict_id = {}		# e.g. ('3', 'Completed') - db ID instead of property name
+			assocPropsDict = {}
+			
+			enzDict = utils.join(dnaHandler.sitesDict, dnaHandler.gatewayDict)
+			
+			# moved here June 1/09
+			#featureNames = Reagent.getSequenceFeatures()
+			#featureDescriptors = Reagent.getFeatureDescriptors()
+			
+			# Aug 21/09: Features
+			if form.has_key("feature_type_" + rType):
+				featureType = form.getvalue("feature_type_" + rType)	# this is an alias, e.g. 'dna_sequence_features', 'rna_sequence_features', or 'protein_sequence_features'
+			
+			# Dec. 10/09: Removed the restriction if rType is Vector or Insert - may update reagent type and its features
+			featureCategoryID = prop_Category_Name_ID_Map[prop_Category_Alias_Name_Map[featureType]]
+			#print featureCategoryID
+			featureNames = rtPropHandler.findReagentTypeAttributeNamesByCategory(reagentType_Name_ID_Map[rType], featureCategoryID)
+			featureDescriptors = Reagent.getFeatureDescriptors()
+
+			categories = {}
+
+			# Find actual property values
+			for propName_tmp in form.keys():
+				#print propName_tmp
+				
+				# Extract propName portion
+				start = propName_tmp.find(genPrefix)
+
+				#print start
+
+				if start >= 0:
+					#print "why here???"
+					#print propName_tmp
+					spacer_index = propName_tmp.find("_:_")
+					#print spacer_index
+					categoryAlias = propName_tmp[start+len(genPrefix):spacer_index]
+					#print categoryAlias + "!!!"
+					
+					if prop_Category_Alias_ID_Map.has_key(categoryAlias):
+						categoryID = prop_Category_Alias_ID_Map[categoryAlias]
+						
+						# Aug 6/09
+						if categories.has_key(categoryAlias):
+							tmp_cat_props = categories[categoryAlias]
+						else:
+							tmp_cat_props = []
+						
+						#print categoryAlias
+						
+						
+						# update Jan. 20, 2010
+						#end = propName_tmp.rfind(postfix)
+						
+						if propName_tmp.rfind(postfix) == len(propName_tmp)-len(postfix):
+							end = len(propName_tmp) - len(postfix)
+						else:
+							continue
+						
+						#print end
+						propName = propName_tmp[spacer_index+len("_:_"):end]
+						
+						tmp_cat_props.append(propName)
+						categories[categoryAlias] = tmp_cat_props
+
+						#print propName
+						prop_id = prop_Alias_ID_Map[propName]
+						propCatID = pHandler.findReagentPropertyInCategoryID(prop_id, categoryID)
+						
+						rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, propCatID)
+						#print rTypeAttributeID
+		
+						# Dec. 10/09: NO!!!!!!
+						# What if a feature name is shared between categories?  There can be 'origin' sequence feature and 'origin' classifier!!!  Check CATEGORY here!!!!!!
+						#if propName.lower() not in featureNames:	# june 1/09
+						if categoryID != prop_Category_Name_ID_Map["DNA Sequence Features"] and categoryID != prop_Category_Name_ID_Map["Protein Sequence Features"] and categoryID != prop_Category_Name_ID_Map["RNA Sequence Features"]:
+							#print propName
+							
+							# new value that would be added to the set (dropdown/checkbox)
+							newSetEntry = ""
+							
+							#tmpPropList = form.getlist(propName_tmp)
+							newPropVal = form.getvalue(propName_tmp)
+							#print `newPropVal`
+							
+							#if utils.isList(tmpPropList):
+							#for newPropVal in tmpPropList:
+								#print newPropVal
+								#newPropVal = form[propName_tmp].value.strip()
+								
+							#print propName_tmp
+							#print newPropVal
+							
+							if propName.lower() == "alternate_id":
+								newPropVal = form.getlist(propName_tmp)
+								
+								tmp_alt_ids = []
+								
+								for altID in newPropVal:
+									if form.has_key(propName + "_" + altID + "_textbox_name"):
+										if altID.lower() != "other":
+											tmp_alt_id = altID + ":" + form.getvalue(propName + "_" + altID + "_textbox_name")
+										else:
+											tmp_alt_id = form.getvalue(propName + "_" + altID + "_textbox_name")
+											
+											# Feb. 5/10: update list
+											other_alt_id = form.getvalue(propName + "_" + altID + "_textbox_name")
+											new_set_val = other_alt_id[0:other_alt_id.find(":")]
+											
+											#rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, propCatID)
+											
+											setGroupID = sHandler.findPropSetGroupID(propCatID)
+											ssetID = sHandler.findSetValueID(setGroupID, new_set_val)
+											
+											if sHandler.findSetValueID(setGroupID, form.getvalue(propName + "_" + altID + "_textbox_name")) <= 0:
+												ssetID = sHandler.addSetValue(setGroupID, new_set_val)
+											
+											if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+												sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+										
+										#print tmp_alt_id
+										tmp_alt_ids.append(tmp_alt_id)
+	
+								newPropVal = tmp_alt_ids
+								
+							else:
+								#print propName
+
+								# April 11, 2011: Compute MW, Tm, GC% - whichever is applicable for the current sequence type
+								if propName.lower() == prop_Name_Alias_Map["sequence"]:
+									# MW, Tm, GC% (protein translation computed for Inserts separately)
+									
+									tmPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["melting temperature"], prop_Category_Name_ID_Map["DNA Sequence"])
+									
+									mwPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["molecular weight"], prop_Category_Name_ID_Map["DNA Sequence"])
+
+									gcPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["gc content"], prop_Category_Name_ID_Map["DNA Sequence"])
+									
+									molWeight = dnaHandler.calculateMW(dnaHandler.squeeze(newPropVal.lower().strip()))
+									
+									gc_content = dnaHandler.calculateGC(dnaHandler.squeeze(newPropVal.lower().strip()))
+									
+									melTemp = dnaHandler.calculateTm(dnaHandler.squeeze(newPropVal.lower().strip()))
+
+									newPropsDict_id[gcPropID] = gc_content
+									newPropsDict_id[mwPropID] = molWeight
+									newPropsDict_id[tmPropID] = melTemp
+									
+								#elif propName.lower() == prop_Name_Alias_Map["rna sequence"]:
+									# MW, GC%
+									
+									#mwPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["molecular weight"], prop_Category_Name_ID_Map["RNA Sequence"])
+
+									# Actually, remove GC% from RNA, it's not a default property
+									#gcPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["gc content"], prop_Category_Name_ID_Map["RNA Sequence"])
+									
+									#gc_content = dnaHandler.calculateGC(dnaHandler.squeeze(newPropVal.lower().strip()))
+									
+									#newPropsDict_id[gcPropID] = gc_content
+									
+									# April 14, 2011: Karen said to NOT calculate MW for RNA automatically
+									#molWeight = rnaHandler.calculateMW_RNA(rnaHandler.squeeze(newPropVal.lower().strip()))
+
+									#newPropsDict_id[mwPropID] = molWeight									
+								elif propName.lower() == prop_Name_Alias_Map["protein sequence"]:
+									# only MW
+									mwPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["molecular weight"], prop_Category_Name_ID_Map["Protein Sequence"])
+
+									peptideMass = protHandler.calculatePeptideMass(protHandler.squeeze(newPropVal.lower().strip()))
+
+									newPropsDict_id[mwPropID] = peptideMass
+
+								if utils.isList(form[propName_tmp]):
+									newPropVal = utils.unique(form.getlist(propName_tmp))
+								
+								# OK, this is for single dropdowns
+								elif newPropVal.lower() == 'other':
+				
+									# get the value in the textbox
+									#textBox = propName + "_name_txt"
+									textBox = propName_tmp[0:len(propName_tmp)-len(postfix)] + "_name_txt"
+									newPropVal = form[textBox].value.strip()
+									newSetEntry = newPropVal
+				
+									# invoke handler to add textbox value to dropdown list
+									
+									# update Nov. 18/09
+									setGroupID = sHandler.findPropSetGroupID(propCatID)	# it must exist
+									
+									ssetID = sHandler.findSetValueID(setGroupID, newSetEntry)
+									
+									if sHandler.findSetValueID(setGroupID, newSetEntry) <= 0:
+										ssetID = sHandler.addSetValue(setGroupID, newSetEntry)
+									
+									if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+										sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+
+								# May 20, 2010: Check for new list values here, and don't use isList to check; use isMultiple b/c even for multiple dropdowns, when only one value is added, it's not considered a list1!!!
+								#rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, propCatID)
+
+								if rtPropHandler.isMultiple(rTypeAttributeID):
+									tmp_ar = []
+									
+									if not utils.isList(newPropVal):
+										tmp_ar.append(newPropVal)
+									else:
+										tmp_ar = newPropVal
+									
+									for val in tmp_ar:
+										
+										# update set with new values
+										setGroupID = sHandler.findPropSetGroupID(propCatID)
+										ssetID = sHandler.findSetValueID(setGroupID, val)
+										
+										if sHandler.findSetValueID(setGroupID, val) <= 0:
+											ssetID = sHandler.addSetValue(setGroupID, val)
+										
+										if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+											sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+
+							# store new property alias and value in dictionary
+							newPropsDict_id[propCatID] = newPropVal
+
+			#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+			#print					# DITTO
+			#print `newPropsDict_id`
+
+			# Action
+			rHandler.addReagentProperties(rID, newPropsDict_id)
+
+			# (deletion is performed in updateFeatures function, no need to call here)
+			newPropsDict_name = {}			# e.g. ('status', 'Completed')
+			newPropsDict_id = {}			# e.g. ('3', 'Completed') - db ID instead of property name
+			
+			startPosDict = {}			# (propID, startpos)
+			endPosDict = {}				# (propID, endpos)
+			
+			# Store orientation
+			orientationDict = {}			# (propID, orientation)
+			
+			# Nov. 6/08: Delete before update
+			rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["5' cloning site"])
+			rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["3' cloning site"])
+			
+			# Sept. 8/08: Delete linkers too
+			rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["5' linker"])
+			rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["3' linker"])
+			
+			# features too
+			rHandler.deleteReagentFeatures(rID)
+
+			if form.has_key(genPrefix + prop_Name_Alias_Map["5' linker"] + postfix):
+				#print "5' Linker"
+				five_prime_linker = form.getvalue(genPrefix + prop_Name_Alias_Map["5' linker"] + postfix).replace(" ", "").strip()
+				fAlias = prop_Name_Alias_Map["5' linker"]
+
+				#fID = prop_Alias_ID_Map[fAlias]
+				fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map[prop_Category_Alias_Name_Map[featureType]])
+				
+				startFieldName = genPrefix + fAlias + "_startpos" + postfix
+				endFieldName = genPrefix + fAlias + "_endpos" + postfix
+				
+				if form.has_key(startFieldName):
+					fStartPos = form.getvalue(startFieldName)
+				else:
+					fStartPos = 0
+					
+				if form.has_key(endFieldName):
+					fEndPos = form.getvalue(endFieldName)
+				else:
+					fEndPos = 0
+
+				# orientation
+				orientationFieldName = genPrefix + fAlias + "_orientation" + postfix
+			
+				if form.has_key(orientationFieldName):
+					tmpDir = form.getvalue(orientationFieldName)
+					#print tmpDir
+				else:
+					tmpDir = 'forward'
+
+				if len(five_prime_linker) > 0:
+					rHandler.addReagentProperty(rID, fID, five_prime_linker, fStartPos, fEndPos, tmpDir)
+				
+			if form.has_key(genPrefix + prop_Name_Alias_Map["3' linker"] + postfix):
+				three_prime_linker = form.getvalue(genPrefix + prop_Name_Alias_Map["3' linker"] + postfix).replace(" ", "").strip()
+				
+				fAlias = prop_Name_Alias_Map["3' linker"]
+
+				#fID = prop_Alias_ID_Map[fAlias]
+				fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map[prop_Category_Alias_Name_Map[featureType]])
+				
+				startFieldName = genPrefix + fAlias + "_startpos" + postfix
+				endFieldName = genPrefix + fAlias + "_endpos" + postfix
+				
+				if form.has_key(startFieldName):
+					fStartPos = form.getvalue(startFieldName)
+				else:
+					fStartPos = 0
+					
+				if form.has_key(endFieldName):
+					fEndPos = form.getvalue(endFieldName)
+				else:
+					fEndPos = 0
+
+				# orientation
+				orientationFieldName = genPrefix + fAlias + "_orientation" + postfix
+			
+				if form.has_key(orientationFieldName):
+					tmpDir = form.getvalue(orientationFieldName)
+					#print tmpDir
+				else:
+					tmpDir = 'forward'
+					
+				if len(three_prime_linker) > 0:
+					rHandler.addReagentProperty(rID, fID, three_prime_linker, fStartPos, fEndPos, tmpDir)
+			
+			# May 27/09: Features - all on the same form for custom reagent types
+			seqFeatures = []
+			
+			featureAliases = {}
+			features = {}
+		
+			# Update Nov. 3/09
+			#print featureType
+			featureNames = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, prop_Category_Alias_ID_Map[featureType])
+			
+			#print `featureNames`
+			
+			for f in featureNames:
+				fAlias = prop_Name_Alias_Map[f]
+				fPropID = prop_Name_ID_Map[f]
+				
+				featureAliases[fAlias] = f
+				features[fPropID] = f
+			
+			#print `featureAliases`
+			#print `prop_Alias_Name_Map`
+		
+			for fAlias in featureAliases:
+				#print fAlias
+				
+				# Special case: cDNA start and stop positions
+				#print prop_Alias_Name_Map[fAlias].lower()
+				if prop_Alias_Name_Map[fAlias].lower() == 'cdna insert':
+					
+					# No value, positions only
+					# Still need to create a new Feature instance
+					#fTemp = SequenceFeature(SequenceFeature)
+					#fID = prop_Alias_ID_Map[fAlias]
+					fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map[prop_Category_Alias_Name_Map[featureType]])
+				
+					#fType = prop_ID_Name_Map[fID]
+					#fTemp.setFeatureType(fType)
+					
+					startFieldName = genPrefix + fAlias + "_startpos" + postfix
+					endFieldName = genPrefix + fAlias + "_endpos" + postfix
+					
+					if form.has_key(startFieldName):
+						tmpStartPos = form.getvalue(startFieldName)
+						#fTemp.setFeatureStartPos(tmpStartPos)
+					else:
+						tmpStartPos = 0
+
+					if form.has_key(endFieldName):
+						tmpEndPos = form.getvalue(endFieldName)
+						#fTemp.setFeatureEndPos(tmpEndPos)
+					else:
+						tmpEndPos = 0
+
+					#seqFeatures.append(fTemp)
+					
+					# Nov. 6/08: Orientation needed too (for reverse complemented Inserts)
+					orientationFieldName = genPrefix + fAlias + "_orientation" + postfix
+				
+					if form.has_key(orientationFieldName):
+						tmpDir = form.getvalue(orientationFieldName)
+						#print tmpDir
+					else:
+						tmpDir = 'forward'
+						
+					if tmpEndPos > 0:
+						rHandler.addReagentProperty(rID, fID, "", tmpStartPos, tmpEndPos)
+					
+				elif prop_Alias_Name_Map[fAlias].lower() == "5' cloning site":
+					#print genPrefix + prop_Name_Alias_Map["5' cloning site"] + postfix
+					five_prime_site = form.getvalue(genPrefix + prop_Name_Alias_Map["5' cloning site"] + postfix)
+					#print "5' site " + five_prime_site
+					
+					fAlias = prop_Name_Alias_Map["5' cloning site"]
+	
+					# May 28/08: Allow blank sites for Novel vectors
+					if five_prime_site:
+						if five_prime_site == "Other":
+							five_prime_site = form.getvalue("5_prime_cloning_site_name_txt")
+						
+						#fID = prop_Alias_ID_Map[fAlias]
+						fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map[prop_Category_Alias_Name_Map[featureType]])
+				
+						startFieldName = genPrefix + fAlias + "_startpos" + postfix
+						endFieldName = genPrefix + fAlias + "_endpos" + postfix
+						
+						#print startFieldName
+						
+						if form.has_key(startFieldName):
+							fStartPos = form.getvalue(startFieldName)
+						else:
+							fStartPos = 0
+							
+						if form.has_key(endFieldName):
+							fEndPos = form.getvalue(endFieldName)
+						else:
+							fEndPos = 0
+		
+						#print " start " + fStartPos
+						#print " end " + fEndPos
+		
+						# orientation
+						orientationFieldName = genPrefix + fAlias + "_orientation" + postfix
+					
+						if form.has_key(orientationFieldName):
+							tmpDir = form.getvalue(orientationFieldName)
+							#print tmpDir
+						else:
+							tmpDir = 'forward'
+		
+						rHandler.addReagentProperty(rID, fID, five_prime_site, fStartPos, fEndPos, tmpDir)
+					
+				elif prop_Alias_Name_Map[fAlias].lower() == "3' cloning site":
+					three_prime_site = form.getvalue(genPrefix + prop_Name_Alias_Map["3' cloning site"] + postfix)
+					#print "3' site: " + three_prime_site
+					
+					fAlias = prop_Name_Alias_Map["3' cloning site"]
+	
+					# May 28/08: Allow blank sites for Novel vectors
+					if three_prime_site:
+						if three_prime_site == "Other":
+							three_prime_site = form.getvalue("3_prime_cloning_site_name_txt")
+							
+						#fID = prop_Alias_ID_Map[fAlias]
+						fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map[prop_Category_Alias_Name_Map[featureType]])
+				
+						startFieldName = genPrefix + fAlias + "_startpos" + postfix
+						endFieldName = genPrefix + fAlias + "_endpos" + postfix
+						
+						if form.has_key(startFieldName):
+							fStartPos = form.getvalue(startFieldName)
+						else:
+							fStartPos = 0
+							
+						if form.has_key(endFieldName):
+							fEndPos = form.getvalue(endFieldName)
+						else:
+							fEndPos = 0
+						
+						# Sept. 3/08: Store orientation
+						orientationFieldName = genPrefix + fAlias + "_orientation" + postfix
+						
+						if form.has_key(orientationFieldName):
+							tmpDir = form.getvalue(orientationFieldName)
+							#print tmpDir
+						else:
+							tmpDir = 'forward'
+		
+						rHandler.addReagentProperty(rID, fID, three_prime_site, fStartPos, fEndPos, tmpDir)
+				else:
+					# make sure linkers are not added here again!
+					
+					tmpStart = -1
+					tmpEnd = -1
+					
+					for tmpPropName in form.keys():
+						#print tmpPropName
+						#print fAlias
+						
+						# convert to lowercase b/c of PolyA
+						if tmpPropName.find(genPrefix + fAlias + "_:_") >= 0:
+							#print tmpPropName
+	
+							pValStartInd = len(genPrefix + fAlias)+3
+							#print pValStartInd
+							#pValStopInd = tmpPropName.find("_", pValStartInd)	# rmvd nov 1/09
+							pValStopInd = tmpPropName.rfind("_start_", pValStartInd)
+							#print pValStopInd
+							
+							# actual feature value
+							tmpPropValue = tmpPropName[pValStartInd:pValStopInd]
+							#print " feature " + tmpPropName
+							#print ", value " + tmpPropValue
+							
+							if tmpPropValue and len(tmpPropValue) > 0:
+								# get positions - changed oct. 25/08
+								
+								# Update Nov 3/09
+								#start_ind1 = tmpPropName.find(tmpPropValue) + len(tmpPropValue) + len("_start_")
+								
+								start_ind1 = tmpPropName.rfind("_start_") + len("_start_")
+								start_ind2 = tmpPropName.find("_end_")
+								#print start_ind2
+		
+								tmpStart = tmpPropName[start_ind1:start_ind2]
+								#print "start " + tmpStart
+								
+								if tmpStart and len(tmpStart) > 0 and int(tmpStart) > 0:
+									end_ind_1 = start_ind2 + len("_end_")
+									#print end_ind_1
+									end_ind_2 = tmpPropName.find("_", end_ind_1)
+									#print end_ind_2
+			
+									tmpEnd = tmpPropName[end_ind_1:end_ind_2]
+									#print "end " + tmpEnd
+									
+									if tmpEnd and len(tmpEnd) > 0 and int(tmpEnd) > 0:
+										tmpDirName = genPrefix + fAlias + "_:_" + tmpPropValue + "_start_" + `int(tmpStart)` + "_end_" + `int(tmpEnd)` + "_orientation" + postfix
+										#print "ok " + tmpDirName
+										
+										if form.has_key(tmpDirName):
+											tmpDir = form.getvalue(tmpDirName)
+											#print "FOUND DIRECTION " + tmpDirName
+								
+											# Nov. 13/08: If there are duplicates, select one
+											if utils.isList(tmpDir):
+												#print "Descriptor " + tmpDescr
+												tmpDir = tmpDir[0]
+								
+											#fID = prop_Alias_ID_Map[fAlias]
+											fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map[prop_Category_Alias_Name_Map[featureType]])
+										
+											# add value to list if not already in it
+											# April 23, 2010: When we get to this stage, the value is not 'Other' anymore, but it's the actual textbox value, appended and passed to the form by JS.  So don't check if other here, just check if exists in dropdown and update list if not!!!
+											#if tmpPropValue.lower() == 'other':	# rmvd April 23, 2010
+												#sHandler.updateSet(fAlias, tmpPropValue)
+											
+											# update Nov. 18/09
+											setGroupID = sHandler.findPropSetGroupID(fID)
+											
+											ssetID = sHandler.findSetValueID(setGroupID, tmpPropValue)
+											
+											if sHandler.findSetValueID(setGroupID, tmpPropValue) <= 0:
+												ssetID = sHandler.addSetValue(setGroupID, tmpPropValue)
+										
+											rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, fID)
+											
+											if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+												sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+											
+										
+											#print "id is " + fID
+											#print fAlias
+											#print prop_Alias_Name_Map[fAlias]
+								
+											# descriptor
+											if featureDescriptors.has_key(prop_Alias_Name_Map[fAlias]):
+												tmpDescrName = featureDescriptors[prop_Alias_Name_Map[fAlias]]
+												tmpDescrAlias = prop_Name_Alias_Map[tmpDescrName]
+												#print "DESCRIPTOR " + tmpDescrAlias
+										
+												tmpDescrField = genPrefix + tmpDescrAlias + "_:_" + tmpPropValue + "_start_" + tmpStart + "_end_" + tmpEnd + postfix
+
+												#print tmpDescrField
+												
+												if form.has_key(tmpDescrField):
+													
+													tmpDescr = form.getvalue(tmpDescrField)
+										
+													# add value to list if not already in it
+													#if tmpDescr.lower() == 'other':
+													descPropID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[tmpDescrAlias], prop_Category_Name_ID_Map[prop_Category_Alias_Name_Map[featureType]])
+										
+													rTypeDescrAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, descPropID)
+									
+													# update Nov. 18/09
+													setGroupID = sHandler.findPropSetGroupID(descPropID)
+													
+													ssetID = sHandler.findSetValueID(setGroupID, tmpDescr)
+													
+													if sHandler.findSetValueID(setGroupID, tmpDescr) <= 0:
+														ssetID = sHandler.addSetValue(setGroupID, tmpDescr)
+													
+													if not sHandler.existsReagentTypeAttributeSetValue(rTypeDescrAttributeID, ssetID):
+														sHandler.addReagentTypeAttributeSetEntry(rTypeDescrAttributeID, ssetID)
+													
+										
+													# Nov. 13/08: If there are duplicates, select one
+													if utils.isList(tmpDescr):
+														#print "Descriptor " + tmpDescr
+														tmpDescr = tmpDescr[0]
+												else:
+													tmpDescr = ""
+											else:
+												tmpDescr = ""
+										
+											if not rHandler.existsPropertyValue(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDescr, tmpDir):
+												rHandler.addReagentProperty(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDir)
+												
+												rHandler.setReagentFeatureDescriptor(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDescr)
+									else:
+										pass
+								else:
+									pass
+							else:
+								pass
+						else:
+							pass
+			
+			# June 12/09: Verification image
+			try: # Windows needs stdio set for binary mode.
+				import msvcrt
+				msvcrt.setmode (0, os.O_BINARY) # stdin  = 0
+				msvcrt.setmode (1, os.O_BINARY) # stdout = 1
+			except ImportError:
+				pass
+			
+			# Generator to buffer file chunks
+			def fbuffer(f, chunk_size=10000):
+				while True:
+					chunk = f.read(chunk_size)
+					
+					if not chunk:
+						break
+					
+				yield chunk
+
+			if form.has_key("verification_image"):
+				fileitem = form["verification_image"]
+				
+				# Test if the file was uploaded
+				# Oct 22/09: Removed temporarily - apparently fileitem is a list, likely b/c I'm not differentiating verification_image form fields by reagent type.  To be fixed.
+				#if fileitem.filename:
+					##print fileitem.filename
+					## strip leading path from file name to avoid directory traversal attacks
+					#fn = os.path.basename(fileitem.filename)
+					#f = open(root_path + 'image_uploads/' + fn, 'wb', 10000)
+				
+					## Read the file in chunks
+					#for chunk in fbuffer(fileitem.file):
+						#f.write(chunk)
+					
+					#f.close()
+			
+			if form.has_key("reagent_association_types"):
+				# Aug. 11/09: Associations; moved here Dec. 9/09 - don't do anything if reagent has no associations, e.g. Oligo
+				aMapper = ReagentAssociationMapper(db, cursor)
+				assoc_Type_Name_Map = aMapper.mapAssocTypeNameID()
+				
+				# Associations
+				assocPrefix = "assoc_"
+				
+				if rType == 'Vector' or rType == 'Insert' or rType == 'CellLine':
+					assocPostfix = "_hidden"
+				else:
+					assocPostfix = "_prop"
+					
+				aTypeID = rtAssocHandler.findAssociationByReagentType(rTypeID)
+				#print aTypeID
+				
+				assocID = rHandler.createReagentAssociation(rID, aTypeID)
+				reagent.setCloningMethod(assocID)	# sept. 13/07
+	
+				assocPropsDict = {}
+				reagent_association_types = []
+
+				reagent_association_types = form.getlist("reagent_association_types")
+				
+				#print `reagent_association_types`
+				
+				for assocPropID in reagent_association_types:
+					
+					assocPropID = int(assocPropID)
+					
+					if form.has_key("assoc_" + `assocPropID` + "_prop"):
+						#tmpAssocProp = form.getvalue("assoc_" + assocPropAlias + "_prop").strip()
+						
+						assocProps = form.getlist("assoc_" + `assocPropID` + "_prop")
+					
+					elif form.has_key(rType + "_assoc_" + `assocPropID` + "_prop"):
+						assocProps = form.getlist(rType + "_assoc_" + `assocPropID` + "_prop")
+						
+					#print `assocProps`
+					
+					for tmpAssocProp in assocProps:
+						#print tmpAssocProp
+						
+						if assoc_ID_Alias_Map.has_key(assocPropID):
+							#assocPropAlias = assoc_ID_Alias_Map[assocPropID]
+							
+							#if assocPropsDict.has_key(assocPropAlias):
+							if assocPropsDict.has_key(assocPropID):
+								#tmp_assoc = assocPropsDict[assocPropAlias]
+								tmp_assoc = assocPropsDict[assocPropID]
+							else:
+								tmp_assoc = []
+
+							tmp_assoc.append(tmpAssocProp.strip())
+							assocPropsDict[assocPropID] = tmp_assoc
+			
+			rHandler.addReagentAssociations(rID, assocPropsDict)
+			
+			utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+			
+	# Added Jan. 31/08: From Primer Designer, use the generated sequence to create Insert or Oligos directly
+	elif form.has_key("create_oligo"):
+		
+		# Create ONLY Oligos, independently of Insert
+		oligo_type = form.getvalue("oligo_type")
+		oligo_sequence = form.getvalue("primer_sequence")
+		
+		mw = form.getvalue("primer_mw")
+		tm = form.getvalue("primer_tm")
+		
+		# June 25, 2010
+		gc = form.getvalue("primer_gc")
+		
+		# Start processing
+		oTypeID = reagentType_Name_ID_Map['Oligo']
+		#print `oTypeID`
+		
+		oligoID = rHandler.createNewReagent('Oligo')
+		#oligo = rHandler.createReagent(oligoID)
+		
+		# Get the name of the template insert and add 'forward'/'reverse' to it
+		templateID = form.getvalue("primer_insert")
+		
+		# correction Oct. 1, 2010
+		namePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map['name'], prop_Category_Name_ID_Map["General Properties"])
+		
+		templateName = rHandler.findSimplePropertyValue(templateID, namePropID)
+		
+		if templateName:
+			if oligo_type == "Sense":
+				newOligoName = templateName + " forward"
+			else:
+				newOligoName = templateName + " reverse"
+		
+			rHandler.addReagentProperty(oligoID, namePropID, newOligoName)
+			
+		# Fix March 22, 2010
+		oTypePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map['oligo type'], prop_Category_Name_ID_Map["General Properties"])
+		
+		mwPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["molecular weight"], prop_Category_Name_ID_Map["DNA Sequence"])
+	
+		tmPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["melting temperature"], prop_Category_Name_ID_Map["DNA Sequence"])
+		
+		# June 25, 2010
+		gcPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["gc content"], prop_Category_Name_ID_Map["DNA Sequence"])
+						
+		rHandler.addReagentProperty(oligoID, oTypePropID, oligo_type)
+		rHandler.addReagentProperty(oligoID, mwPropID, mw)
+		rHandler.addReagentProperty(oligoID, tmPropID, tm)
+		rHandler.addReagentProperty(oligoID, gcPropID, gc)	# june 25, 2010
+		
+		oligoSeqID = dnaHandler.getSequenceID(oligo_sequence)
+		
+		seqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+		
+		rHandler.addReagentProperty(oligoID, seqPropID, oligoSeqID)
+
+		# Redirect to Oligo **Modify** view - with input fields pre-filled, user can fill in the rest
+		utils.redirect(hostname + "Reagent.php?View=6&mode=Create&rType=" + rType + "&rid=" + `oligoID`)
+
+	elif form.has_key("create_insert"):
+		
+		# Create Insert WITH Oligos (from Primer Design)
+		rType = 'Insert'		# april 23/08
+
+		#print "Content-type:text/html"
+		#print
+		#print `form`
+		
+		# june 6/08
+		cdnaStart = 0
+		cdnaEnd = 0
+
+		# sequence includes linkers
+		insert_seq = utils.squeeze(form.getvalue("insert_seq")).lower()		# remember to change case!!!!!
+		
+		iTypeID = reagentType_Name_ID_Map['Insert']
+		insertID = rHandler.createNewReagent('Insert')
+		
+		iSeqID = dnaHandler.getSequenceID(insert_seq)
+		seqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+		rHandler.addReagentProperty(insertID, seqPropID, iSeqID)
+	
+		iTypeAssocID = assocType_Name_ID_Map["Insert Oligos"]
+	
+		iTypeAssocID = assocType_Name_ID_Map["Insert Oligos"]
+
+		# Create an association for this insert/oligos
+		assocID = rHandler.createReagentAssociation(insertID, iTypeAssocID)
+		
+		# Get the name of the original (template) Insert and construct names for the new oligos
+		templateID = form.getvalue("template_insert")
+		
+		# moved up here Oct. 1, 2010
+		namePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["name"], prop_Category_Name_ID_Map["General Properties"])
+		
+		templateName = rHandler.findSimplePropertyValue(templateID, namePropID)
+		
+		# Feb. 13/08: Cannot set the IPV of the new insert to be its template's child vector, since the template may have multiple vector children
+		
+		# Sense Oligo
+		senseSeq = form.getvalue("sense_sequence")
+		senseMW = form.getvalue("sense_mw")
+		senseTM = form.getvalue("sense_tm")
+		
+		senseGC = form.getvalue("sense_gc")
+		
+		senseID = rHandler.createNewReagent('Oligo')
+		
+		# May 14/08: Human-readable form, to pass to next step
+		senseOligo = rHandler.convertDatabaseToReagentID(senseID)
+		
+		oligoTypePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["oligo type"], prop_Category_Name_ID_Map["General Properties"])
+		
+		mwPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["molecular weight"], prop_Category_Name_ID_Map["DNA Sequence"])
+	
+		tmPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["melting temperature"], prop_Category_Name_ID_Map["DNA Sequence"])
+		
+		# April 1, 2010
+		gcPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["gc content"], prop_Category_Name_ID_Map["DNA Sequence"])
+		
+		# Store Sense properties
+		if templateName:
+			senseOligoName = templateName + " forward"
+			rHandler.addReagentProperty(senseID, namePropID, senseOligoName)
+			
+		rHandler.addReagentProperty(senseID, oligoTypePropID, "Sense")
+		rHandler.addReagentProperty(senseID, mwPropID, senseMW)
+		rHandler.addReagentProperty(senseID, tmPropID, senseTM)
+		
+		rHandler.addReagentProperty(senseID, gcPropID, senseGC)
+		
+		senseSeqID = dnaHandler.getSequenceID(senseSeq)
+		rHandler.addReagentProperty(senseID, seqPropID, senseSeqID)
+		
+		# Store 'sense oligo' association
+		sensePropID = aHandler.findAssocPropID("sense oligo")
+		rHandler.addAssociationValue(insertID, sensePropID, senseID, assocID)
+		
+		# Antisense Oligo
+		antisenseSeq = form.getvalue("antisense_sequence")
+		antisenseMW = form.getvalue("antisense_mw")
+		antisenseTM = form.getvalue("antisense_tm")
+		
+		antisenseGC = form.getvalue("antisense_gc")
+		
+		antisenseID = rHandler.createNewReagent('Oligo')
+		
+		# May 14/08: Human-readable form, to pass to next step
+		antisenseOligo = rHandler.convertDatabaseToReagentID(antisenseID)
+		
+		if templateName:
+			antisenseOligoName = templateName + " reverse"
+			rHandler.addReagentProperty(antisenseID, namePropID, antisenseOligoName)
+		
+		rHandler.addReagentProperty(antisenseID, oligoTypePropID, "Antisense")
+		rHandler.addReagentProperty(antisenseID, mwPropID, antisenseMW)
+		rHandler.addReagentProperty(antisenseID, tmPropID, antisenseTM)
+		
+		rHandler.addReagentProperty(antisenseID, gcPropID, antisenseGC)
+		
+		antisenseSeqID = dnaHandler.getSequenceID(antisenseSeq)
+		rHandler.addReagentProperty(antisenseID, seqPropID, antisenseSeqID)
+
+		# Store Antisense Oligo association
+		antisensePropID = aHandler.findAssocPropID("antisense oligo")
+		rHandler.addAssociationValue(insertID, antisensePropID, antisenseID, assocID)
+		
+		# April 3/08: Get the Insert Parent Vector ID from template
+		#print "Content-type:text/html"
+		#print
+
+		aTypeID = aHandler.findATypeID("Insert Parent Vector")
+		ipvPropID = aHandler.findAssocPropID("insert parent vector id")
+		#print `ipvPropID`
+		ipvAssocID = raHandler.findSpeReagentAssociationPropertyID(templateID, ipvPropID)
+		#print `templateID`
+		ipvID = aHandler.findAssocPropValue(ipvAssocID, ipvPropID)
+		#print `ipvID`
+		rHandler.addAssociationValue(insertID, ipvPropID, ipvID)
+		
+		# june 10/08
+		insertParentVector = rHandler.convertDatabaseToReagentID(ipvID)
+		
+		# Determine Insert sites and their positions from primer linkers
+		# Here, fwd_linker and rev_linker refer to the sequences user may choose to add to primers by selecting them from a dropdown list
+		# e.g. "Gateway 5' linker with stop codon", "HIS linker without stop codon", etc.
+		# They are NOT the same as 5' and 3' linker values stored for the end Insert
+		if form.has_key("fwd_linker"):
+			fwd_linker = form.getvalue("fwd_linker")
+		else:
+			fwd_linker = ""
+	
+		if form.has_key("rev_linker"):
+			rev_linker = form.getvalue("rev_linker")
+		else:
+			rev_linker = ""
+
+		##########################################################################################################################
+		# Feb. 12/08: Wanted to search the linker sequence for **every possible restriction enzyme**.  If found, designate the sequence portion before the enzyme as the "filler" and the sequence portion after the enzyme as the "linker"
+		
+		# BUT dismissed this idea because the linker may contain multiple site sequences (mostly His-vectors but still)
+		
+		# Just keep it simple:
+		enzDict = utils.join(dnaHandler.sitesDict, dnaHandler.gatewayDict)	# still need this
+		
+		fpSitePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+		
+		tpSitePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	
+		fpLinkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+		
+		tpLinkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+		
+		if len(fwd_linker) > 0:
+			if utils.squeeze(fwd_linker.strip().lower()) == "ggggacaactttgtacaaaaaagttggcaccatg" or utils.squeeze(fwd_linker.strip().lower()) == "ggggacaactttgtacaaaaaagttggcacc":
+				fp_site = 'attB1'
+				db_prop_val = fp_site
+				
+			else:
+				fp_site = 'AscI'
+				db_prop_val = fp_site
+			
+			fp_seq = enzDict[fp_site].lower()
+			
+			# Record the site's position relative to the **ENTIRE Insert sequence**
+			if insert_seq.find(fp_seq) >= 0:
+				five_start_pos = insert_seq.index(fp_seq) + 1		# make it human-readable, don't start from 0
+				five_end_pos = five_start_pos + len(fp_seq) - 1
+			
+				# store site WITH POSITIONS
+				rHandler.addReagentProperty(insertID, fpSitePropID, db_prop_val, five_start_pos, five_end_pos)
+			
+			# Find filler and linker on the new Insert sequence
+			# "Filler" is the portion from the start of the sequence to the start of the 5' site
+			# "Linker" is the portion from the end of the 5' site to the start of the cDNA
+			if fwd_linker.find(fp_seq) >= 0:	# better be found - Nov. 20/08: EXCEPT when linker == 'Other'!!
+				fp_site_start = fwd_linker.index(fp_seq)
+				fp_site_end = fp_site_start + len(fp_seq)
+				
+				# filler - portion of the linker sequence up to the enzyme
+				fp_filler = insert_seq[0:five_start_pos]
+				
+				# linker - portion of the linker sequence between the enzyme and cDNA
+				fwd_linker_len = len(fwd_linker)
+				insert_linker_size = fwd_linker_len - fp_site_end
+				fp_linker_end = five_end_pos + insert_linker_size
+				fp_linker = insert_seq[five_end_pos:fp_linker_end]
+				
+				# store fp_linker as property of the Insert
+				if len(fp_linker) > 0:
+					rHandler.addReagentProperty(insertID, fpLinkerPropID, fp_linker, five_end_pos+1, fp_linker_end)
+			else:	# nov 20/08
+				#fp_linker_start = 0
+				fp_linker_end = -1
+
+		# 3' linker
+		if len(rev_linker) > 0:
+			
+			# Reverse complement the linker (APril 25/08)
+			rev_linker_seq = dnaHandler.reverse_complement(rev_linker)
+			
+			if utils.squeeze(rev_linker.strip().lower()) == "ggggacaactttgtacaagaaagttgggtacta" or utils.squeeze(rev_linker.strip().lower()) == "ggggacaactttgtacaagaaagttgggta":
+				tp_site = 'attB2'
+				
+				# Database value needs to be "attB", not "attB1" => APRIL 24/08: NO!!!!!! actually storing indices
+				db_prop_val = tp_site
+			
+				# When searching for the 3' site on the Insert sequence, site sequence needs to be reversed
+				tp_seq = enzDict[tp_site].lower()
+				rev_tp_seq = dnaHandler.reverse_complement(tp_seq)
+			
+			else:
+				tp_site = 'PacI'
+				db_prop_val = tp_site
+				tp_seq = enzDict[tp_site].lower()	# palindrome - reads the same both ways, forward or reverse
+
+				## Change Jan. 17, 2011: for linker 'other' the site is not necessarily PacI
+				#if rev_linker.lower().find(tp_seq.lower()):
+				rev_tp_seq = tp_seq
+				#else:
+					#rev_tp_seq = ""
+		
+			# Changes made April 25/08
+			
+			#print "Content-type:text/html"
+			#print
+			
+			# Search the ***ENTIRE*** Insert sequence for a ***REVERSE***-oriented LINKER
+			rev_linker_start = insert_seq.lower().find(rev_linker_seq.lower())	# Occurs right after cDNA; DON'T add 1 **yet**
+			
+			# And here, search for the **FORWARD**-ORIENTED **site** sequence
+			# add 1 here, subtract later during linker computation
+			if rev_linker_seq.find(tp_seq) >= 0:
+				three_start_pos = rev_linker_start + rev_linker_seq.index(tp_seq) + 1
+				three_end_pos = three_start_pos + len(tp_seq) - 1	# length does not depend on orientation
+				
+				# Now the 'linker' portion of the primer linker sequence is between the end of cDNA and the enzyme
+				tp_linker_start = rev_linker_start
+				tp_linker_end = three_start_pos - 1		# subtract 1 here for string lookup
+				
+				# 'Linker' portion of the entire primer linker - between cDNA and cloning site
+				tp_linker = insert_seq[tp_linker_start:tp_linker_end]
+				
+				# store site with positions
+				rHandler.addReagentProperty(insertID, tpSitePropID, db_prop_val, three_start_pos, three_end_pos)
+				
+				# store 3' linker as property of the Insert, add 1 to startpos for readability (do it here, preserve zero-indexing during sequence lookup above but insert a human-readable value into the database)
+				if len(tp_linker) > 0:
+					rHandler.addReagentProperty(insertID, tpLinkerPropID, tp_linker, tp_linker_start+1, tp_linker_end)
+			else:	# nov 20/08
+				tp_linker_start = 0
+				
+		# May 23/08: While we're at it, why not autofill cDNA positions - from 5' linker end to 3' linker start
+		if len(fwd_linker) > 0 and len(rev_linker) > 0:		# added June 6/08 to cover case w/o linkers
+			cdnaStart = fp_linker_end + 1
+			cdnaEnd = tp_linker_start
+
+		# July 2/09
+		cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+		
+		rHandler.setPropertyPosition(insertID, cdnaPropID, "startPos", cdnaStart)
+		rHandler.setPropertyPosition(insertID, cdnaPropID, "endPos", cdnaEnd)
+		
+		##################################################################
+		# Feb. 5/08: Inherit various properties from template:
+		##################################################################
+		# Accession
+		accessionPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["accession number"], prop_Category_Name_ID_Map["External Identifiers"])
+		
+		entrezGenePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["entrez gene id"], prop_Category_Name_ID_Map["External Identifiers"])
+		
+		geneSymbolPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["official gene symbol"], prop_Category_Name_ID_Map["External Identifiers"])
+		
+		ensemblGenePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["ensembl gene id"], prop_Category_Name_ID_Map["External Identifiers"])
+		
+		template_accession = rHandler.findSimplePropertyValue(templateID, accessionPropID)
+		
+		if template_accession and template_accession != "":
+			rHandler.addReagentProperty(insertID, accessionPropID, template_accession)
+		
+		# Entrez Gene ID
+		template_gene_id = rHandler.findSimplePropertyValue(templateID, entrezGenePropID)
+		
+		if template_gene_id and template_gene_id != "":
+			rHandler.addReagentProperty(insertID, entrezGenePropID, template_gene_id)
+		
+		# Gene Symbol
+		template_gene_symbol = rHandler.findSimplePropertyValue(templateID, geneSymbolPropID)
+		
+		if template_gene_symbol and template_gene_symbol != "":
+			rHandler.addReagentProperty(insertID, geneSymbolPropID, template_gene_symbol)
+		
+		# Ensembl Gene ID
+		ensembl_template_gene_id = rHandler.findSimplePropertyValue(templateID, ensemblGenePropID)
+		
+		if ensembl_template_gene_id and ensembl_template_gene_id != "":
+			rHandler.addReagentProperty(insertID, ensemblGenePropID, ensembl_template_gene_id)
+		
+		# Species
+		speciesPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["species"], prop_Category_Name_ID_Map["Classifiers"])
+		
+		template_species = rHandler.findSimplePropertyValue(templateID, speciesPropID)
+		
+		if template_species and template_species != "":
+			rHandler.addReagentProperty(insertID, speciesPropID, template_species)
+		
+		# Default status to "In Progress"
+		statusPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["status"], prop_Category_Name_ID_Map["General Properties"])
+		
+		rHandler.addReagentProperty(insertID, statusPropID, "In Progress")
+		
+		# Modified May 14/08: At this point the first 2 steps of creation - parents and sequence - have been completed; now keep things simple - fill in the Insert's general info (mainly name and project), and proceed to Detailed View (can add features later through Editing)
+		utils.redirect(hostname + "Reagent.php?View=2&Step=4&Type=" + rType + "&rID=" + `insertID` + "&Seq=" + `iSeqID` + "&SO=" + senseOligo + "&AS=" + antisenseOligo + "&PIV=" + insertParentVector)
+		
+		## Redirect to Modify view in creation mode								# removed May 14/08
+		#utils.redirect(hostname + "Reagent.php?View=6&mode=Create&rType=" + rType + "&rid=" + `insertID`)	# removed May 14/08
+
+	# May 5/08: Final creation step - save general info
+	elif form.has_key("save_intro"):
+		
+		#print "Content-type:text/html"
+		#print
+		#print `form`
+		
+		rID = int(form.getvalue("reagent_id_hidden"))
+		rType = form.getvalue("reagent_type_hidden")
+
+		genPrefix = "reagent_detailedview_" + rType + "_"	# update Oct. 26/09 - reagent type included in feature names
+		postfix = "_prop"
+
+		## Create a new Insert instance
+		#rID = rHandler.createNewReagent(rType)
+		#reagent = rHandler.createReagent(rID)
+		
+		rTypeID = reagentType_Name_ID_Map[rType]
+		
+		# Find the actual names and database IDs of POST values (no checkbox properties for Oligos)
+		newPropsDict_name = {}		# e.g. ('status', 'Completed')
+		newPropsDict_id = {}		# e.g. ('3', 'Completed') - db ID instead of property name
+		assocPropsDict = {}
+		
+		categories = {}
+		
+		#print `prop_Alias_ID_Map`
+
+		# Find actual property values
+		for propName_tmp in form.keys():
+			#print propName_tmp
+			
+			# Extract propName portion
+			start = propName_tmp.find(genPrefix)
+
+			#print start
+
+			if start >= 0:
+				#print propName_tmp
+				spacer_index = propName_tmp.find("_:_")
+				#print spacer_index
+				categoryAlias = propName_tmp[start+len(genPrefix):spacer_index]
+				#print categoryAlias + "!!!"
+				
+				if prop_Category_Alias_ID_Map.has_key(categoryAlias):
+					categoryID = prop_Category_Alias_ID_Map[categoryAlias]
+					
+					# Aug 6/09
+					if categories.has_key(categoryAlias):
+						tmp_cat_props = categories[categoryAlias]
+					else:
+						tmp_cat_props = []
+					
+					#print categoryAlias
+					
+					# update Jan. 20, 2010
+					if propName_tmp.rfind(postfix) == len(propName_tmp)-len(postfix):
+						end = len(propName_tmp) - len(postfix)
+					else:
+						continue
+					
+					#end = propName_tmp.rfind(postfix)
+					
+					#print end
+					propName = propName_tmp[spacer_index+len("_:_"):end]
+					
+					#print "pname:" + propName + "!"
+					
+					tmp_cat_props.append(propName)
+					categories[categoryAlias] = tmp_cat_props
+
+					prop_id = prop_Alias_ID_Map[propName]
+					propCatID = pHandler.findReagentPropertyInCategoryID(prop_id, categoryID)
+					
+					#print propCatID
+	
+					# new value that would be added to the set (dropdown/checkbox)
+					newSetEntry = ""
+					
+					#print propName
+					
+					if propName == "alternate_id":
+						newPropVal = form.getlist(propName_tmp)
+						#print `newPropVal`
+						tmp_alt_ids = []
+						
+						annoAlias = propName
+						
+						for altID in newPropVal:
+							if form.has_key(annoAlias + "_" + altID + "_textbox_name"):
+								if altID.lower() == 'other':
+									tmp_alt_id = form.getvalue(annoAlias + "_" + altID + "_textbox_name")
+									
+									#print annoAlias
+									#print annoPropID
+									
+									# update list
+									pcID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[annoAlias], prop_Category_Name_ID_Map["External Identifiers"])
+									#print pcID
+							
+									rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(int(rTypeID), pcID)
+									#print rTypeAttributeID
+									
+									setGroupID = sHandler.findPropSetGroupID(pcID)
+									#print setGroupID
+									
+									ssetID = sHandler.findSetValueID(setGroupID, tmp_alt_id[0:tmp_alt_id.find(":")])
+									#print ssetID
+									
+									if ssetID <= 0:
+										ssetID = sHandler.addSetValue(setGroupID, tmp_alt_id[0:tmp_alt_id.find(":")])
+									
+									if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+										sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+								else:
+									tmp_alt_id = altID + ":" + form.getvalue(annoAlias + "_" + altID + "_textbox_name")
+									#print tmp_alt_id
+									
+								tmp_alt_ids.append(tmp_alt_id)
+						
+						newPropVal = tmp_alt_ids
+						#print `newPropVal`
+						#newPropsDict_name[annoAlias] = newPropVal
+						
+					elif utils.isList(form[propName_tmp]):
+						newPropVal = utils.unique(form.getlist(propName_tmp))
+						
+					else:
+						newPropVal = form.getvalue(propName_tmp)
+						
+						# OK, this is for single dropdowns
+						if newPropVal.lower() == 'other':
+		
+							# get the value in the textbox
+							#textBox = propName + "_name_txt"
+							textBox = propName_tmp[0:len(propName_tmp)-len(postfix)] + "_name_txt"
+							newPropVal = form[textBox].value.strip()
+							newSetEntry = newPropVal
+		
+							# invoke handler to add textbox value to dropdown list
+							rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, propCatID)
+							
+							# update Nov. 18/09
+							setGroupID = sHandler.findPropSetGroupID(propCatID)	# it must exist
+							
+							ssetID = sHandler.findSetValueID(setGroupID, newSetEntry)
+							
+							if sHandler.findSetValueID(setGroupID, newSetEntry) <= 0:
+								ssetID = sHandler.addSetValue(setGroupID, newSetEntry)
+							
+							if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+								sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+
+						# May 20, 2010: Check for new list values here, and don't use isList to check; use isMultiple b/c even for multiple dropdowns, when only one value is added, it's not considered a list1!!!
+						rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, propCatID)
+
+						if rtPropHandler.isMultiple(rTypeAttributeID):
+							tmp_ar = []
+							
+							if not utils.isList(newPropVal):
+								tmp_ar.append(newPropVal)
+							else:
+								tmp_ar = newPropVal
+							
+							for val in tmp_ar:
+								
+								# update set with new values
+								setGroupID = sHandler.findPropSetGroupID(propCatID)
+								ssetID = sHandler.findSetValueID(setGroupID, val)
+								
+								if sHandler.findSetValueID(setGroupID, val) <= 0:
+									ssetID = sHandler.addSetValue(setGroupID, val)
+								
+								if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+									sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+
+					# store new property alias and value in dictionary
+					newPropsDict_id[propCatID] = newPropVal
+
+		# Match db IDs to property aliases
+		for tmpProp in newPropsDict_name.keys():
+			
+			if prop_Alias_ID_Map.has_key(tmpProp):
+				#propID = prop_Alias_ID_Map[tmpProp]
+				propID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[tmpProp], prop_Category_Name_ID_Map["External Identifiers"])
+				
+				newPropsDict_id[propID] = newPropsDict_name[tmpProp]
+
+		# ACTION
+		# Correction May 20, 2011: No.  This deletes previously saved properties on multi-step creation
+		#rHandler.updateReagentProperties(rID, newPropsDict_id)
+		rHandler.updateReagentPropertiesInCategory(rID, prop_Category_Name_ID_Map["General Properties"], newPropsDict_id)
+		
+		# a few extra actions for Insert
+		if rType == 'Insert':
+			
+			# May 14/08: Once Type of Insert and Open/Closed values have been set, translate this Insert's sequence
+			iHandler.updateInsertProteinSequence(rID)
+			
+			# June 12/08: If Insert was created from Primer Design, assign the same project ID to the resulting Oligos
+			if form.has_key("from_primer") and form.getvalue("from_primer") == 'True':
+				
+				insertAssoc = rHandler.findAllReagentAssociationsByName(rID)
+				
+				senseOligoID = insertAssoc["sense oligo"]
+				#print `senseOligoID`
+				antisenseOligoID = insertAssoc["antisense oligo"]
+				#print `antisenseOligoID`
+				
+				packetPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["packet id"], prop_Category_Name_ID_Map["General Properties"])
+				#print packetPropID
+				
+				#print genPrefix + prop_Category_Name_Alias_Map["General Properties"] + "_:_" + prop_Name_Alias_Map["packet id"] + postfix
+				
+				packetID = form.getvalue(genPrefix + prop_Category_Name_Alias_Map["General Properties"] + "_:_" + prop_Name_Alias_Map["packet id"] + postfix)
+				#print `packetID`
+				
+				rHandler.addReagentProperty(senseOligoID, packetPropID, packetID)
+				rHandler.addReagentProperty(antisenseOligoID, packetPropID, packetID)
+
+			# Also, classifiers are passed here
+			rHandler.updateReagentPropertiesInCategory(rID, prop_Category_Name_ID_Map["Classifiers"], newPropsDict_id)
+
+			# and external identifiers, e.g. Alternate ID
+			rHandler.updateReagentPropertiesInCategory(rID, prop_Category_Name_ID_Map["External Identifiers"], newPropsDict_id)
+
+			# AND translate the sequence!!!!
+			insertTypePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["type of insert"], prop_Category_Name_ID_Map["Classifiers"])
+			#print insertTypePropID
+			
+			openClosedPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["open/closed"], prop_Category_Name_ID_Map["Classifiers"])
+			#print openClosedPropID
+		
+			newInsertType = iHandler.findSimplePropertyValue(rID, insertTypePropID)
+			newOpenClosed = iHandler.findSimplePropertyValue(rID, openClosedPropID)
+
+			# Update July 23/09: account for cases where insert type - open/closed are empty
+			iHandler.updateInsertProteinSequence(rID, newInsertType, newOpenClosed)
+	
+		# Redirect to Modify view in creation mode
+		utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+	
+	cursor.close()
+	db.close()
+	
+create()
diff --git a/OpenFreezer/cgi/database_conn.py b/OpenFreezer/cgi/database_conn.py
new file mode 100755
index 0000000..6786699
--- /dev/null
+++ b/OpenFreezer/cgi/database_conn.py
@@ -0,0 +1,42 @@
+import MySQLdb
+
+class DatabaseConn:
+	
+	__hostname__ = "http://your.OpenFreezer.URL/"				# CHANGE THIS to your hostname; REMEMBER THE http://
+	__root_dir__ = "/your/OpenFreezer/installation/directory/"		# CHANGE THIS
+	
+	__mailto_clone_request__ = "clonerequest at YOU.com"			# CHANGE THIS
+	__mailto_programmer__ = "olhovsky at lunenfeld.ca"				
+	__mailto_biologist__ = "colwill at lunenfeld.ca"			
+	
+	__mail_server__ = "your.smtp.mail.server"				# CHANGE THIS
+	__mail_admin__ = "YOUR LOCAL OPENFREEZER ADMIN EMAIL"			# CHANGE THIS
+
+	def getHostname(self):
+		return self.__hostname__
+
+	def getRootDir(self):
+		return self.__root_dir__
+	
+	def databaseConnect(self):
+		
+		# CHANGE THIS
+		db = MySQLdb.connect(host="my.mysql.server.name", user="openfreezer_www", passwd="openfreezer_www_passwd", db="my_openfreezer_db")
+		return db
+
+
+	def getMailCloneRequest(self):
+		return self.__mailto_clone_request__
+	
+	def getProgrammerEmail(self):
+		return self.__mailto_programmer__
+	
+	
+	def getBiologistEmail(self):
+		return self.__mailto_biologist__
+
+	def getMailServer(self):
+		return self.__mail_server__
+
+	def getAdminEmail(self):
+		return self.__mail_admin__
diff --git a/OpenFreezer/cgi/delete.py b/OpenFreezer/cgi/delete.py
new file mode 100755
index 0000000..16256e1
--- /dev/null
+++ b/OpenFreezer/cgi/delete.py
@@ -0,0 +1,66 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+
+import SocketServer
+from SocketServer import BaseRequestHandler
+
+import stat
+import MySQLdb
+
+import os
+import sys
+import string
+
+# Custom modules
+import utils
+
+from database_conn import DatabaseConn
+from exception import *
+
+from reagent import Reagent
+from user import User
+
+from reagent_handler import ReagentHandler
+from user_handler import UserHandler
+from location_database_handler import LocationHandler
+
+from general_handler import *
+from mapper import *
+
+from session import Session
+
+dbConn = DatabaseConn()
+db = dbConn.databaseConnect()
+
+cursor = db.cursor()
+hostname = dbConn.getHostname()
+
+rHandler = ReagentHandler(db, cursor)
+lHandler = LocationHandler(db, cursor)
+
+###################################################################################################################################
+# This is an AJAX function invoked via Javascript from reagent search page
+# Written June 8, 2009, by Marina Olhovsky
+# Last modified June 8, 2009
+###################################################################################################################################
+def deleteReagent(form):
+	
+	if form.has_key("rID"):
+		rID = int(form.getvalue("rID"))
+		limsID = rHandler.convertDatabaseToReagentID(rID)
+		
+		#print "Content-type:text/html"
+		#print
+		#print `form`
+		lHandler.deleteExperimentID(rID)
+		delStatus = rHandler.deleteReagent(rID)		# if deletion failed (reagent has preps) return 0, else return 1
+		
+		print "Content-type:text/html"
+		print
+		print "rID=" + limsID + "&Status=" + `delStatus`
+
+
+form = cgi.FieldStorage(keep_blank_values="True")
+deleteReagent(form)
\ No newline at end of file
diff --git a/OpenFreezer/cgi/exception.py b/OpenFreezer/cgi/exception.py
new file mode 100755
index 0000000..a94fbd2
--- /dev/null
+++ b/OpenFreezer/cgi/exception.py
@@ -0,0 +1,567 @@
+##################################################################################################################
+# This module contains various Exception classes
+
+# Written by: Marina Olhovsky
+
+# Last modified: February 9, 2009
+##################################################################################################################
+
+
+#######################################################################
+# Exceptions that occur during Vector sequence constitution
+#######################################################################
+
+class InsertSitesException(Exception):
+	"Raised when Insert cloning sites are outside the standard REBASE enzyme list - most likely Gateway or LoxP"
+	"This exception is raised during automated Vector sequence construction, when parents' cloning sites do not match the Vector type (e.g. using an Insert with attB sites to generate a non-gateway vector -- exception thrown by sequence generation function)"
+	
+	__err_code__ = 1
+
+	def __init__(self, value="Unknown sites on Insert"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+	
+
+class InsertSitesNotFoundOnParentSequenceException(Exception):
+	"Raised when the sequence of one or both of the Insert's cloning site is not found in the parent vector sequence"
+	
+	__err_code__ = 2
+
+	def __init__(self, value="Insert sites not found in parent vector sequence"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+	
+
+class MultipleSiteOccurrenceException(Exception):
+	"Raised when the sequence of Insert sites is found more than once in the parent vector sequence"
+
+	__err_code__ = 3
+
+	def __init__(self, value="Insert sites occur more than once in parent vector sequence"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+	
+
+class HybridizationException(Exception):
+	"Raised when the restriction sites provided cannot be hybridized"
+
+	__err_code__ = 4
+
+	def __init__(self, value="Restriction sites cannot be hybridized"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+
+
+class FivePrimeAfterThreePrimeException(Exception):
+	"Raised when the 5' restriction site occurs after the 3' site on parent sequence"
+
+	__err_code__ = 5
+
+	def __init__(self, value="5' site occurs after 3' on parent sequence"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+
+
+class ReagentDoesNotExistException(Exception):
+	"Raised when a reagent ID does not exist in the database"
+	
+	__err_code__ = 6
+	
+	def __init__(self, value="Reagent does not exist"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+	
+
+# Feb. 5, 2010
+class ParentVectorDoesNotExistException(Exception):
+	"Raised at stable Cell Line creation, when the Parent Vector does not exist in the database"
+	
+	__err_code__ = 7
+	
+	def __init__(self, value="Parent Vector does not exist"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+	
+
+# Feb. 5, 2010
+class ParentCellLineDoesNotExistException(Exception):
+	"Raised at stable Cell Line creation, when the Parent Cell Line does not exist in the database"
+	
+	__err_code__ = 8
+	
+	def __init__(self, value="Parent Cell Line does not exist"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+	
+class CloningSitesNotFoundInInsertException(Exception):
+	"Raised when the Insert does not contain a cloning site"
+	
+	__err_code__ = 13
+
+	def __init__(self, value="Insert does not contains a portion of a hybrid site"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+
+
+class InsertSitePositionException(Exception):
+	"Raised when a restriction site is not found on Insert sequence at the indicated positions"
+	
+	__err_code__ = 14
+
+	def __init__(self, value="Restriction site is not found on Insert sequence at the indicated positions"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+
+
+class InvalidDonorVectorSitesNotFoundException(Exception):
+	"Raised when a donor vector (IPV in Recombination Vector creation)'s sequence does not contain LoxP sites"
+	
+	__err_code__ = 15
+
+	def __init__(self, value="Donor vector sequence does not contain LoxP sites"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+	
+
+class InvalidDonorVectorSingleSiteException(Exception):
+	"Raised when LoxP site is encountered only once in the sequence of a donor vector (IPV in Recombination Vector creation)"
+	
+	__err_code__ = 16
+
+	def __init__(self, value="Donor vector sequence contains one occurrence of LoxP site"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+	
+class InvalidDonorVectorMultipleSitesException(Exception):
+	"Raised when a donor vector (IPV in Recombination Vector creation) sequence contains MORE than two occurrences of LoxP sites"
+	
+	__err_code__ = 17
+
+	def __init__(self, value="Donor vector sequence contains more than two occurrences of LoxP sites"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+	
+	
+# Replaced June 3/08
+class RecombinationVectorSequenceMissingLoxPException(Exception):
+	"Raised during Recombination Vector creation, when, as a result of user modification, one or both LoxP sites in a recombination sequence gets destroyed"
+	
+	__err_code__ = 18
+	
+	def __init__(self, value="Missing LoxP sites in Recombination Vector Sequence"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+
+# June 2/08
+class ReagentTypeException(Exception):
+	"Raised when the type of reagent selected as parent in creation is invalid (e.g. a recombination vector selected as donor or a Gateway Vector selected as parent in non-recombination)"
+
+	__err_code__ = 19
+
+	def __init__(self, value="Invalid type of reagent selected as parent"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+
+
+# Jan. 14/09
+class DegenerateHybridException(Exception):
+	"Raised when a hybrid sequence is attempted to be made using two degenerate restriction sites (not very common)"
+	
+	__err_code__ = 22
+
+	def __init__(self, value="Attempting to make a hybrid sequence using two degenerate restriction sites"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+
+# Feb. 12/09
+class EmptyCloningSitesException(Exception):
+	__err_code__ = 23
+
+	def __init__(self, value="Empty cloning sites"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+
+
+# Dec. 14/09
+class EmptyParentVectorSequenceException(Exception):
+	__err_code__ = 24
+
+	def __init__(self, value="The sequence of the parent vector provided is empty."):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+
+class EmptyParentInsertSequenceException(Exception):
+	__err_code__ = 25
+
+	def __init__(self, value="The sequence of the parent insert provided is empty."):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+	
+class EmptyInsertParentVectorSequenceException(Exception):
+	__err_code__ = 26
+
+	def __init__(self, value="The sequence of the insert parent vector provided is empty."):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+	
+	
+class IncompatibleFivePrimeOverhangsException(Exception):
+	"Raised when 5' overhangs on vector and insert are incompatible"
+	
+	__err_code__ = 27
+
+	def __init__(self, value="Invalid type of reagent selected as parent"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+
+
+class IncompatibleThreePrimeOverhangsException(Exception):
+	"Raised when 3' overhangs on vector and insert are incompatible"
+	
+	__err_code__ = 28
+
+	def __init__(self, value="Invalid type of reagent selected as parent"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+
+
+class InsertFivePrimeAfterThreePrimeException(Exception):
+	"Raised when 5' is found after 3' on insert sequence - likely when user inputs custom Insert sites in reverse order"
+	
+	__err_code__ = 29
+
+	def __init__(self, value="5' after 3' on Insert sequence"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+
+
+# June 3, 2010
+class GatewayParentDestinationException(Exception):
+	"Raised when the Gateway Parent Destination vector does not contain a ccdB gene"
+	
+	__err_code__ = 30
+
+	def __init__(self, value="ccdB not found on GW Parent Destination vector"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+
+
+# June 3, 2010
+class SwapGatewayParentsException(Exception):
+	"Raised when the Gateway Parent Destination vector does not contain a ccdB gene BUT the Gateway Entry clone does - as if the user has entered them backwards"
+	
+	__err_code__ = 31
+
+	def __init__(self, value="ccdB not found on GW Parent Destination vector and found in Entry clone"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+	
+
+############################################################
+# User-related and Lab-related Exceptions
+############################################################
+
+class DeletedUserException(Exception):
+	"Raised at User creation, when the username provided belongs to a DEP user in Users_tbl"
+	
+	__err_code__ = 7
+	
+	def __init__(self, value="Username belongs to inactive user"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+		
+	def toString(self):
+		return self.value
+		
+		
+class DuplicateUsernameException(Exception):
+	"Raised at User creation, when the username provided belongs to an ACTIVE user in Users_tbl, resulting in UNIQUE username constraint violation (produces MySQL duplicate entry error 1062)"
+	
+	__err_code__ = 8
+	
+	def __init__(self, value="Duplicate username"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+		
+	def toString(self):
+		return self.value
+
+
+class DuplicateEntryException(Exception):
+	"Raised everywhere a query returns multiple rows when in fact only one result is expected"
+	
+	__err_code__ = 9
+	
+	def __init__(self, value="One result expected but query returned more"):
+		self.value = value
+		
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+	
+
+class DuplicateLabCodeException(Exception):
+	"Raised when a user is trying to supply a lab code that is already taken by another lab"
+	
+	__err_code__ = 14
+	
+	def __init__(self, value="This lab ID already exists."):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+	
+	def toString(self):
+		return self.value
+	
+############################################################
+# Project-related exceptions
+############################################################
+class PVProjectAccessException(Exception):
+	"Raised when a user is trying to create a reagent using a Parent Vector from a project s/he doesn't have Read access to"
+	
+	__err_code__ = 10
+	
+	def __init__(self, value="You do not have Write access to this project"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+	
+	
+class InsertProjectAccessException(Exception):
+	"Raised when a user is trying to create a reagent using an Insert from a project s/he doesn't have Read access to"
+	
+	__err_code__ = 11
+	
+	def __init__(self, value="You do not have Write access to this project"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+	
+	
+class IPVProjectAccessException(Exception):
+	"Raised when a user is trying to create a reagent using an Insert Parent Vector from a project s/he doesn't have Read access to"
+	
+	__err_code__ = 12
+	
+	def __init__(self, value="You do not have Write access to this project"):
+		self.value = value
+		
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+
+
+class SenseProjectAccessException(Exception):
+	"Raised when a user is trying to create an Insert using as parent a Sense Oligo from a project s/he doesn't have Read access to"
+	
+	__err_code__ = 20
+	
+	def __init__(self, value="You do not have Write access to this project"):
+		self.value = value
+		
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+	
+	
+class AntisenseProjectAccessException(Exception):
+	"Raised when a user is trying to create an Insert using as parent an Antisense Oligo from a project s/he doesn't have Read access to"
+	
+	__err_code__ = 21
+	
+	def __init__(self, value="You do not have Write access to this project"):
+		self.value = value
+		
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+	
+class CLProjectAccessException(Exception):
+	"Raised when a user is trying to create a reagent using a Cell Line from a project s/he doesn't have Read access to"
+	
+	__err_code__ = 13
+	
+	def __init__(self, value="You do not have Write access to this project"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+
+# July 14/09
+class InvalidPropertyCategoryException(Exception):
+	"Raised when ................."
+	
+	__err_code__ = 13
+	
+	def __init__(self, value="You do not have Write access to this project"):	# is this the right error msg????
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
+
+
+class UnknownReagentTypeException(Exception):
+	"Raised when the reagent type provided is not found in the database"
+	
+	__err_code = 24
+	
+	def __init__(self, value="Reagent type not found in the database"):
+		self.value = value
+
+	def err_code(self):
+		return self.__err_code__
+
+	def toString(self):
+		return self.value
diff --git a/OpenFreezer/cgi/general_handler.py b/OpenFreezer/cgi/general_handler.py
new file mode 100755
index 0000000..77e2e53
--- /dev/null
+++ b/OpenFreezer/cgi/general_handler.py
@@ -0,0 +1,1882 @@
+import MySQLdb
+import sys
+import string
+import random
+import utils
+
+from mapper import ReagentTypeMapper
+import graphics_handler
+
+#from system_set_handler import SystemSetHandler
+
+##################################################################################################################
+# Top-level abstraction for classes that map objects to corresponding database entities in OpenFreezer
+# All SQL queries are performed by these classes, thereby encapsulating the database layer and separating it from the object model
+
+# Written by: Marina Olhovsky
+# Last modified: June 15, 2009
+##################################################################################################################
+
+##############################################################################
+# GeneralHandler class
+##############################################################################
+
+# Superclass of all other handlers (e.g. ReagentHandler, SequenceHandler, etc)
+# October 12, 2006, Marina Olhovsky
+class GeneralHandler(object):
+	"Superclass of all other handlers"
+	
+	# Constructor
+	def __init__(self, db, cursor):
+	
+		self.db = db
+		self.cursor = cursor
+
+
+##############################################################################
+# ReagentPropertyHandler class
+# Descendant of GeneralHandler; specifically handles reagent properties
+#
+# Written March 14/07 by Marina
+##############################################################################
+class ReagentPropertyHandler(GeneralHandler):
+	"Descendant of GeneralHandler - performs various utility functions to handle reagent properties"
+	
+	# Get the database ID of a given property
+	def findPropID(self, propName, case_sensitive=False):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		if case_sensitive:
+			cursor.execute("SELECT `propertyID` FROM `ReagentPropType_tbl` WHERE `propertyName`=" + `propName` + " COLLATE latin1_general_cs AND status='ACTIVE'")
+		else:
+			cursor.execute("SELECT propertyID FROM ReagentPropType_tbl WHERE propertyName=" + `propName` + " AND status='ACTIVE'")
+		
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+		else:
+			return -1
+		
+		
+	# Get the database ID of a given property by DESCRIPTION
+	def findPropIDByDescription(self, propDescr, case_sensitive=False):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+
+		if case_sensitive:
+			#####################################################################################################################
+			# Oct. 30/09: The COLLATE statement *** MUST *** be adjacent to the search term
+			#
+			# Correct: "WHERE propertyDesc='abc' COLLATE latin1_general_cs AND status='ACTIVE'"
+			# Incorrect: "WHERE propertyDesc='abc' AND status='ACTIVE' COLLATE latin1_general_cs" (returns case-insensitive match)
+			#
+			#####################################################################################################################
+			cursor.execute("SELECT propertyID FROM ReagentPropType_tbl WHERE propertyDesc=" + `propDescr` + " COLLATE latin1_general_cs AND status='ACTIVE'")
+		else:
+			cursor.execute("SELECT propertyID FROM ReagentPropType_tbl WHERE propertyDesc=" + `propDescr` + " AND status='ACTIVE'")
+			#print "SELECT propertyID FROM ReagentPropType_tbl WHERE propertyDesc=" + `propDescr` + " AND status='ACTIVE'"
+			
+		result = cursor.fetchone()
+		
+		if result:
+			#print propDescr
+			#print int(result[0])
+			return int(result[0])
+		else:
+			return -1
+	
+	
+	# June 22/09
+	def findPropertyIDFromAlias(self, pAlias, case_sensitive=False):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		if case_sensitive:
+			cursor.execute("SELECT `propertyID` FROM `ReagentPropType_tbl` WHERE propertyAlias=" + `pAlias` + " COLLATE latin1_general_cs AND status='ACTIVE'")
+		else:
+			cursor.execute("SELECT propertyID FROM ReagentPropType_tbl WHERE propertyAlias=" + `pAlias` + " AND status='ACTIVE'")
+			
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+		else:
+			return -1
+	
+	# Oct. 31/09
+	def findPropertyDescriptionFromAlias(self, pAlias, case_sensitive=False):
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+
+		db = self.db
+		cursor = self.cursor
+		
+		if case_sensitive:
+			cursor.execute("SELECT propertyDesc FROM ReagentPropType_tbl WHERE propertyAlias=" + `pAlias` + " COLLATE latin1_general_cs AND status='ACTIVE'")
+		else:
+			#print "SELECT propertyDesc FROM ReagentPropType_tbl WHERE propertyAlias=" + `pAlias` + " AND status='ACTIVE'"
+			cursor.execute("SELECT propertyDesc FROM ReagentPropType_tbl WHERE propertyAlias=" + `pAlias` + " AND status='ACTIVE'")
+			
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+		else:
+			return None
+		
+		
+	# Nov. 2/09: Equal and opposite: find alias based on description
+	def findPropertyAliasFromDescription(self, pDesc, case_sensitive=False):
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+
+		db = self.db
+		cursor = self.cursor
+		
+		if case_sensitive:
+			cursor.execute("SELECT propertyAlias FROM ReagentPropType_tbl WHERE propertyDesc=" + `pDescr` + " COLLATE latin1_general_cs AND status='ACTIVE'")
+		else:
+			cursor.execute("SELECT propertyAlias FROM ReagentPropType_tbl WHERE propertyDesc=" + `pDesc` + " AND status='ACTIVE'")
+			
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+		else:
+			return None
+	
+	
+	# Aug. 11/09: check if there are properties that belong to a category
+	def isEmpty(self, categoryID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT propID FROM ReagentPropertyCategories_tbl WHERE categoryID=" + `categoryID` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		if not results or len(results) == 0:
+			return True
+		
+		return False
+
+
+	# June 15/09: find IDs of all properties in a given category
+	def findPropertiesByCategory(self, pCategoryID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		propIDs = []		# list of property IDs
+		
+		cursor.execute("SELECT propertyID FROM ReagentPropType_tbl p, ReagentPropertyCategories_tbl c WHERE c.categoryID=" + `pCategoryID` + " AND c.propID=p.propertyID AND p.status='ACTIVE' AND c.status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			propID = int(result[0])
+			propIDs.append(propID)
+			
+		return propIDs
+	
+	
+	# Update July 22/09: Given a property ID within a specific category, find the property name
+	def findPropName(self, propID):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT propertyName FROM ReagentPropType_tbl p, ReagentPropertyCategories_tbl pc WHERE p.propertyID=pc.propID AND pc.propCatID=" + `propID` + " AND p.status='ACTIVE' AND pc.status='ACTIVE'")
+		result = cursor.fetchone()
+	
+		if result:
+			return result[0]
+	
+	# Oct. 31/09
+	def findPropNameByDescription(self, descr, case_sensitive=False):
+		db = self.db
+		cursor = self.cursor
+		
+		if case_sensitive:
+			cursor.execute("SELECT propertyName FROM ReagentPropType_tbl p WHERE p.propertyDesc=" + `descr` + " COLLATE latin1_general_cs AND p.status='ACTIVE'")
+		else:
+			cursor.execute("SELECT propertyName FROM ReagentPropType_tbl p WHERE p.propertyDesc=" + `descr` + " AND p.status='ACTIVE'")
+
+		result = cursor.fetchone()
+	
+		if result:
+			return result[0]
+
+		return None
+
+	# April 15, 2009: Find property description from its database ID
+	# input: propID - Int
+	# return: String - property description (corresponds to propertyDesc column in ReagentPropType_tbl, e.g. 'Type of Insert', 'polyA Tail', etc.)
+	def findPropertyDescription(self, propID):
+		db = self.db
+		cursor = self.cursor
+		
+		pDescr = None
+
+		cursor.execute("SELECT `propertyDesc` FROM `ReagentPropType_tbl` WHERE `propertyID`=" + `propID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+	
+		if result:
+			return result[0]
+
+		return pDescr
+
+
+	# Nov. 3/09: Plain check if this propName is stored in the propertyName column of ReagentPropType_tbl
+	def existsPropertyName(self, propName, case_sensitive=False):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		if not case_sensitive:
+			cursor.execute("SELECT * FROM ReagentPropType_tbl WHERE propertyName=" + `propName` + " AND status='ACTIVE'")
+		else:
+			cursor.execute("SELECT * FROM ReagentPropType_tbl WHERE propertyName=" + `propName` + " COLLATE latin1_general_cs AND status='ACTIVE'")
+		
+		result = cursor.fetchone ()	# should only be one
+		
+		if result:
+			return True
+		else:
+			return False
+		
+
+	# June 17/09
+	def existsPropertyInCategory(self, newPropID, categoryID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		#cursor.execute("SELECT propCatID FROM ReagentPropertyCategories_tbl WHERE propID=" + `newPropID` + " AND categoryID=" + `categoryID` + " AND status='ACTIVE'")
+		#result = cursor.fetchone()
+		
+		#if result:
+			#return True
+		
+		#return False
+		
+		return (self.findReagentPropertyInCategoryID(newPropID, categoryID) > 0)
+		
+	
+	def getAllFeatureColors(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT DISTINCT(propertyColor) FROM ReagentPropType_tbl WHERE status='ACTIVE' AND propertyColor!='NULL'")
+		props = cursor.fetchall()
+		
+		fColors = []
+		
+		for prop in props:
+			fColor = prop[0]
+			fColors.append(fColor)
+		
+		return fColors
+		
+		
+	# April 3, 2009: Add a new property type
+	# Return: new database property ID
+	# Modified Jan. 26, 2010
+	def addReagentPropertyType(self, propertyName, propertyAlias, propertyDescription, isSeqFeature=False):
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		
+		db = self.db
+		cursor = self.cursor
+		
+		# Jan. 26/10: get a list of all feature colours in the system
+		featureColors = self.getAllFeatureColors()
+		#print `featureColors`
+		fColors = utils.diff(graphics_handler.getAllColors(), featureColors)
+		#print `fColors`
+		
+		if '0xdda0dd' in fColors:
+			fColors.remove('0xdda0dd')
+		
+		# Jan. 26/10: Generate a new colour if the property is a features (for the vector map)
+		if isSeqFeature:
+			rand = random.randrange(0, len(fColors))
+			nextColor = fColors[rand]
+			#print nextColor
+			#nextColor = float.hex(rand)
+			
+			#nextColor = graphics_handler.getNextColor(featureColors)
+			
+			#print "INSERT INTO ReagentPropType_tbl(propertyName, propertyAlias, propertyDesc, propertyColor) VALUES(" + `propertyName` + ", " + `propertyAlias` + ", " + `propertyDescription` + ", " + `nextColor` + ")"
+		
+			cursor.execute("INSERT INTO ReagentPropType_tbl(propertyName, propertyAlias, propertyDesc, propertyColor) VALUES(" + `propertyName` + ", " + `propertyAlias` + ", " + `propertyDescription` + ", " + `nextColor` + ")")
+		else:
+			cursor.execute("INSERT INTO ReagentPropType_tbl(propertyName, propertyAlias, propertyDesc) VALUES(" + `propertyName` + ", " + `propertyAlias` + ", " + `propertyDescription` + ")")
+		
+		newPropID = int(db.insert_id())
+		
+		return newPropID
+	
+	
+	def addReagentPropertyToCategory(self, newPropID, categoryID):
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("INSERT INTO ReagentPropertyCategories_tbl(propID, categoryID) VALUES(" + `newPropID` + ", " + `categoryID` + ")")
+		return int(db.insert_id())
+	
+
+	# April 11, 2009: Check if property identified by pType is stored in ReagentPropType_tbl
+	# input: pType - String, representing an actual property type (e.g. "Selectable Marker")
+	def existsReagentPropertyType(self, pType, case_sensitive=False):
+		db = self.db
+		cursor = self.cursor
+		
+		if self.findPropID(pType, case_sensitive) > 0:
+			return True
+		else:
+			return False
+	
+	# June 19/09
+	def existsReagentPropertyName(self, pName):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT propertyID FROM ReagentPropType_tbl WHERE propertyName=" + `pName` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return True
+		
+		return False
+	
+	
+	# June 19/09
+	def existsReagentPropertyAlias(self, pAlias):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT propertyID FROM ReagentPropType_tbl WHERE propertyAlias=" + `pAlias` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return True
+		
+		return False
+	
+	
+	# June 19/09
+	# Since we are now dealing with case-sensitive property names shared across categories and reagent types, cannot always rely on Python dictionaries due to case sensitivity.  Do a direct selection from the database
+	# Correction July 27/09: Return multiple values
+	def findReagentPropertyCategoryByDescription(self, desc):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		categories = []
+		
+		cursor.execute("SELECT propertyID FROM ReagentPropType_tbl WHERE propertyDesc=" + `desc` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			propID = int(result[0])
+			
+			cursor.execute("SELECT categoryID FROM ReagentPropertyCategories_tbl WHERE propID=" + `propID` + " AND status='ACTIVE'")
+			results = cursor.fetchall()
+		
+			for result in results:
+				categories.append(int(result[0]))
+			
+		return categories
+	
+	
+	# June 19/09
+	# Returns the value of "propCatID" column in ReagentPropertyCategories_tbl - the composite identifier of a property within a certain category
+	def findReagentPropertyInCategoryID(self, propID, categoryID):
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print
+		#print "SELECT propCatID FROM ReagentPropertyCategories_tbl WHERE propID=" + `propID` + " AND categoryID=" + `categoryID` + " AND status='ACTIVE'"
+		
+		cursor.execute("SELECT propCatID FROM ReagentPropertyCategories_tbl WHERE propID=" + `propID` + " AND categoryID=" + `categoryID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+		
+		return -1
+	
+	
+	# June 19/09
+	def existsReagentPropertyDescription(self, desc, case_sensitive=False):
+		db = self.db
+		cursor = self.cursor
+		
+		if case_sensitive:
+			cursor.execute("SELECT propertyID FROM ReagentPropType_tbl WHERE propertyDesc=" + `desc` + " COLLATE latin1_general_cs AND status='ACTIVE'")
+		else:
+			cursor.execute("SELECT propertyID FROM ReagentPropType_tbl WHERE propertyDesc=" + `desc` + " AND status='ACTIVE'")
+			
+		result = cursor.fetchone()
+		
+		if result:
+			return True
+		
+		return False
+	
+		
+	# June 3/09
+	# Returns a list of category Names (e.g. 'General Properties', 'Sequence Features', etc.)
+	def findAllReagentPropertyCategories(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		categories = []
+		
+		cursor.execute("SELECT propertyCategoryName FROM ReagentPropTypeCategories_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+
+		for result in results:
+			categories.append(result[0])
+			
+		return categories
+	
+	
+	# June 23/09
+	# Returns categoryID from propCatID
+	def findReagentPropertyCategory(self, propCatID):
+		db = self.db
+		cursor = self.cursor
+		
+		pCategory = 0
+
+		cursor.execute("SELECT categoryID FROM ReagentPropertyCategories_tbl WHERE propCatID=" + `propCatID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			pCategory = int(result[0])
+		
+		return pCategory
+	
+
+	def findReagentPropertyInCategory(self, propCatID):
+		db = self.db
+		cursor = self.cursor
+		
+		propID = 0
+		
+		cursor.execute("SELECT propID FROM ReagentPropertyCategories_tbl WHERE propCatID=" + `propCatID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			propID = int(result[0])
+		
+		return propID
+	
+		
+	# June 19/09
+	def existsReagentPropertyInCategory(self, propID, categoryID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT propCatID FROM ReagentPropertyCategories_tbl WHERE propID=" + `propID` + " AND categoryID=" + `categoryID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return True
+		
+		return False
+		
+	
+	def existsReagentPropertyCategory(self, category):
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT * FROM ReagentPropTypeCategories_tbl WHERE propertyCategoryName=" + `category` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		if result:
+			return True
+		else:
+			return False
+
+
+	def addReagentPropertyCategory(self, categoryName, categoryAlias):
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT MAX(ordering) FROM ReagentPropTypeCategories_tbl WHERE status='ACTIVE' AND ordering < " + `sys.maxint`)
+		result = cursor.fetchone()
+		ordering = int(result[0]) + 1
+		
+		cursor.execute("INSERT INTO ReagentPropTypeCategories_tbl(propertyCategoryName, propertyCategoryAlias, ordering) VALUES(" + `categoryName` + ", " + `categoryAlias` + ", " + `ordering` + ")")
+		newPropID = int(db.insert_id())
+		
+		return newPropID
+	
+	# June 3/09
+	def deleteReagentPropertyCategory(self, pCategory):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE ReagentPropTypeCategories_tbl SET status='DEP' WHERE propertyCategoryID=" + `pCategory` + " AND status='ACTIVE'")
+		
+		
+	# June 3/09: Delete ReagentPropType_tbl entry
+	def deleteReagentProperty(self, pID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE ReagentPropType_tbl SET status='DEP' where propertyID=" + `pID` + " AND status='ACTIVE'")
+		
+		
+	def deleteReagentPropertyInCategory(self, attrID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE ReagentPropertyCategories_tbl SET status='DEP' where propCatID=" + `attrID` + " AND status='ACTIVE'")
+		
+		
+	# July 27/09
+	def setPropertyOrdering(self, propID, ordering):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE ReagentPropType_tbl SET ordering=" + `ordering` + " WHERE propertyID=" + `propID` + " AND status='ACTIVE'")
+	
+#################################################################################################################################
+# General Association Handler class to handle various **general** association queries, not attached to any particular reagent
+# Written March 27, 2007 by Marina
+#################################################################################################################################
+class AssociationHandler(GeneralHandler):
+	"Handles various Association queries not attached to a particular reagent"
+	
+	# Find the internal database ID of human-readable 'assocProp'
+	# e.g. 'assocProp' = 'vector parent id'; the result is '2' - the value of APropertyID column in Assoc_Prop_Type_tbl
+	# Output: INT
+	def findAssocPropID(self, assocProp):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT APropertyID FROM Assoc_Prop_Type_tbl WHERE APropName=" + `assocProp` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+			
+		return -1
+
+		
+	# Get ATypeID of 'ATypeName'
+	# ATypeName can be one of 'INSERT' or 'LOXP', and it represents either 'non-recombination' or 'recombination' vector type
+	# Returns: int ATypeID (1 corresponds to non-recombination INSERT vector type; 2 - LOXP, recombination vector)
+	# Input: aTypeName: string
+	# Output: aTypeID: int
+	def findATypeID(self, aTypeName):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT ATypeID FROM AssocType_tbl WHERE association=" + `aTypeName` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+
+		return -1
+
+
+	# Find the value of association identified by assocPropID
+	# E.g. if assocPropID = '2', which corresponds to 'parent vector id', the result is a parent vector LIMS ID
+	def findAssocPropValue(self, assocID, assocPropID):
+	
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("SELECT propertyValue FROM AssocProp_tbl WHERE assID=" + `assocID` + " AND APropertyID=" + `assocPropID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()	# one-to-one property name to value mapping
+		
+		if result:
+			return int(result[0])
+			
+		return -1
+	
+
+	# Nov. 5/08: Get a list of ALL values identified by assocID
+	# Returns: dictionary of (assocPropID, assocPropValue) tuples, where assocPropID represents an association property type (e.g. 1 => Insert ID) and assocPropValue is an integer corresponding to reagent ID
+	def findAssocPropValues(self, assocID):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		assocDict = {}
+	
+		cursor.execute("SELECT APropertyID, propertyValue FROM AssocProp_tbl WHERE assID=" + `assocID` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			if result:
+				assocPropID = int(result[0])
+				assocPropVal = int(result[1])
+				assocDict[assocPropID] = assocPropVal
+			
+		return assocDict
+	
+	
+	# Aug. 11/09
+	def createAssociation(self, assocName):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("INSERT INTO AssocType_tbl(association) VALUES(" + `assocName` + ")")
+		assocID = int(db.insert_id())
+		
+		return assocID
+	
+	
+	# Aug. 27/09: Delete (deprecate) a row in Assoc_Prop_Type_tbl identified by assocPropID
+	# Input: assocPropID => INT, corresponds to APropertyID column value
+	def deleteAssociationProperty(self, assocPropID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE Assoc_Prop_Type_tbl SET status='DEP' where APropertyID=" + `assocPropID` + " AND status='ACTIVE'")
+		
+		
+	# Aug. 27/09: Delete (deprecate) a row in AssocType_tbl, identified by aTypeID
+	# Input: aTypeID => INT, corresponds to the value of ATypeID column in AssocType_tbl
+	def deleteAssociation(self, aTypeID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE AssocType_tbl SET status='DEP' where ATypeID=" + `aTypeID` + " AND status='ACTIVE'")
+		
+		
+	# Jan. 28, 2010: remove a reagent type as parent of other types (e.g. if Insert is a parent of Vector and Insert reagent type is deleted, delete Insert as Vector parent
+	def deleteReagentTypeAssociations(self, rTypeID):
+		db = self.db
+		cursor = self.cursor
+		
+		# If rTypeID = 3, deletes the following rows: (removes 'Oligo' (rtype 3) as parent of all other reagent types)
+		# reagentTypeID	| APropName | alias | description | parentTypeID |
+		# +-------------+---------------+----------------------------+--------------+
+		#     2 | sense oligo | sense_oligo    | Sense Oligo ID       | 3 |
+		#     2 | antisense oligo | antisense_oligo | Antisense Oligo ID   | 3 |
+		#     1 | vector parent oligo | vector_parent_oligo | Sense Oligo ID   | 3 |
+		
+		cursor.execute("UPDATE Assoc_Prop_Type_tbl SET status='DEP' where assocTypeID=" + `rTypeID`)
+	
+	
+##############################################################################
+# ReagentAssociationHandler class
+# Descendant of GeneralHandler; handles reagent associations
+#
+# Written March 16/07 by Marina
+##############################################################################
+class ReagentAssociationHandler(GeneralHandler):
+	"Contains functions to fetch internal database IDs for Reagent associations"
+
+	# Fetch the assID of rID from Association_tbl
+	# Return: assID: INT
+	def findReagentAssociationID(self, rID):
+
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT assID FROM Association_tbl WHERE reagentID=" + `rID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			assocID = int(result[0])
+			return assocID
+			
+		return -1
+
+
+	# Nov. 27/07: For reagents that have more than one association type specify which association is requested
+	# E.g. Inserts - can have ATypeID 4, corresponding to 'Insert Oligos' in AssocType_tbl, and ATypeID 6, corresponding to 'Insert Parent Vector' in AssocType_tbl
+	#
+	# Extra parameter assocPropID - corresponds to APropertyID column in Assoc_Prop_Type_tbl 
+	# (e.g. '4' => 'insert parent vector id', 5 => 'sense oligo', 6 => 'antisense oligo', etc.)
+	def findSpeReagentAssociationPropertyID(self, rID, assocPropID):
+
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT a.assID FROM Association_tbl a, AssocProp_tbl p WHERE a.reagentID=" + `rID` + " AND p.APropertyID=" + `assocPropID` + "  AND p.assID=a.assID AND a.status='ACTIVE' AND p.status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			assocID = int(result[0])
+			return assocID
+			
+		return -1
+	
+		
+	# Find the Association type of reagent identified by rID 
+	# Return: the value of ATypeID field in Association_tbl
+	def findReagentAssociationType(self, rID):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT ATypeID FROM Association_tbl WHERE reagentID=" + `rID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+			
+		return -1
+
+	# June 8/09 - Delete a specific parent/child value matching assocPropID
+	def deleteReagentAssociationPropertyValue(self, assocID, assocPropID):
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE AssocProp_tbl SET status='DEP' WHERE assID=" + `assocID` + " AND APropertyID=" + `assocPropID` + " AND status='ACTIVE'")
+
+
+	# June 8/09 - Delete ALL associations for a specific reagent (identified by assocID)
+	def deleteAllAssociationPropertyValues(self, assocID):
+		db = self.db
+		cursor = self.cursor
+		
+		# deprecate associaion properties (AssocProp_tbl entries)
+		cursor.execute("UPDATE AssocProp_tbl SET status='DEP' WHERE assID=" + `assocID` + " AND status='ACTIVE'")
+
+
+##############################################################################
+# ReagentTypeAssociationHandler class
+# Descendant of GeneralHandler; handles reagent TYPE associations
+#
+# Written August 11, 2009 by Marina
+##############################################################################
+class ReagentTypeAssociationHandler(GeneralHandler):
+	
+	# Aug. 11/09, update Nov. 20/09 - save parent type
+	def addReagentTypeAssociationPropertyValue(self, rTypeID, assocName, assocAlias, description, pAssocType, hierarchy="PARENT"):
+		db = self.db
+		cursor = self.cursor
+		
+		if not self.existsAssociationProperty(rTypeID, assocName, assocAlias, description, hierarchy):
+			cursor.execute("INSERT INTO Assoc_Prop_Type_tbl(reagentTypeID, APropName, hierarchy, alias, description, assocTypeID) VALUES(" + `rTypeID` + ", " + `assocName` + ", " + `hierarchy` + ", " + `assocAlias` + ", " + `description` + ", " + `pAssocType` + ")")
+		
+		
+	# Aug. 11/09 - Returns a dictionary of {APropertyID, description} tuples
+	def getReagentTypeAssociations(self, rTypeID):
+		db = self.db
+		cursor = self.cursor
+
+		assocDict = {}		# APropertyID, APropName
+
+		cursor.execute("SELECT APropertyID, description FROM Assoc_Prop_Type_tbl WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			aPropID = int(result[0])
+			aPropName = result[1]
+			
+			assocDict[aPropID] = aPropName
+			
+		return assocDict
+
+
+	# Aug. 11/09
+	def existsAssociationProperty(self, rTypeID, assocName, assocAlias, description, hierarchy):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT APropertyID FROM Assoc_Prop_Type_tbl WHERE reagentTypeID=" + `rTypeID` + " AND APropName=" + `assocName` + " AND alias=" + `assocAlias` + " AND description=" + `description` + " AND hierarchy=" + `hierarchy` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		if not results or len(results) == 0:
+			return False
+		
+		return True
+
+
+	# Determine what a reagent's ATypeID should be according to its type
+	# E.g. Inserts can only be of ATypeID 4 == "Insert Oligos"
+	# Only applies to Inserts at the moment, its being the only reagent type using Python code for modification
+	def findAssociationByReagentType(self, rTypeID):
+		db = self.db
+		cursor = self.cursor
+		
+		rMapper = ReagentTypeMapper(db, cursor)
+		aHandler = AssociationHandler(db, cursor)
+		
+		aTypeID = -1
+
+		rType_ID_Name_Map = rMapper.mapTypeIDName()
+		rType_Name_ID_Map = rMapper.mapTypeNameID()
+		
+		if rTypeID == rType_Name_ID_Map["Insert"]:
+			aTypeID = aHandler.findATypeID("Insert Oligos")
+			
+		elif rTypeID == rType_Name_ID_Map["CellLine"]:
+			# Cell Line
+			aTypeID = aHandler.findATypeID("CellLine Stable")
+			
+		elif rTypeID != rType_Name_ID_Map["Oligo"] and rTypeID != rType_Name_ID_Map["Vector"]:
+			aTypeID = aHandler.findATypeID(rType_ID_Name_Map[rTypeID])
+		
+		# No need for Oligos; for Vectors it's more complicated since there are 3 different assoc types, so will determine them at another place, during a form action script
+
+		return aTypeID
+	
+	
+	# Aug. 27/09: Select all associations (currently parents) of the reagent type identified by rTypeID
+	# Differs from getReagentTypeAssociations in that the dictionary values returned by this function are **names**
+	# Return: dictionary of (APropertyID, propertyName) tuples, e.g. '1' -> 'insert id'
+	def findReagentTypeAssocProps(self, rTypeID):
+		db = self.db
+		cursor = self.cursor
+		
+		rMapper = ReagentTypeMapper(db, cursor)
+		aHandler = AssociationHandler(db, cursor)
+		
+		assocProps = {}
+		
+		# don't bother with hierarchy now; everything is 'PARENT' at this point --> in our current context, 'associations' = 'parents'
+		cursor.execute("SELECT APropertyID, APropName FROM Assoc_Prop_Type_tbl WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			aPropID = int(result[0])
+			aPropName = result[1]
+			
+			assocProps[aPropID] = aPropName
+		
+		return assocProps
+		
+		
+	# Nov. 20/09
+	def deleteReagentTypeAssociationProperties(self, rTypeID):
+		db = self.db
+		cursor = self.cursor
+	
+		# Update Assoc_Prop_Type_tbl only
+		cursor.execute("UPDATE Assoc_Prop_Type_tbl SET status='DEP' WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+		
+
+	# Nov. 20/09
+	def updateParents(self, rTypeID, parentList):
+		self.deleteReagentTypeAssociationProperties(rTypeID)
+		self.addReagentTypeAssociationProperties(rTypeID, parentList)
+		
+		
+	# Nov. 20/09
+	def addReagentTypeAssociationProperties(self, rTypeID, parentList):
+		db = self.db
+		cursor = self.cursor
+	
+		aMapper = AssociationMapper(db, cursor)
+		
+		assoc_Name_Alias_Map = aMapper.mapAssocNameAlias()
+		assoc_Name_Desc_Map = aMapper.mapAssocNameDescription()
+		assoc_ID_ParentTypeID_Map = aMapper.mapAssocIDParentType()
+		assoc_Name_ID_Map = aMapper.mapAssocNameID()
+		
+		for pAssocName in parentList:
+			pAssocAlias = assoc_Name_Alias_Map(pAssocName)
+			pAssocDesc = assoc_Name_Desc_Map[pAssocName]
+			pAssocID = assoc_Name_ID_Map[pAssocName]
+			pAssocType = assoc_ID_ParentTypeID_Map[pAssocID]
+			
+			self.addReagentTypeAssociationPropertyValue(rTypeID, pAssocName, pAssocAlias, pAssocDesc, pAssocType)
+	
+	
+	# Nov. 20/09: Find assocTypeID column values in Assoc_Prop_Type_tbl - i.e. return the TYPE of reagent that maps to this assocPropID
+	# e.g. 'vector parent id' => assocTypeID 1 (Vector)
+	def findAssocParentType(self, rTypeID, assocPropID):
+		db = self.db
+		cursor = self.cursor
+	
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print "SELECT assocTypeID FROM Assoc_Prop_Type_tbl WHERE APropertyID=" + `assocPropID` + " AND status='ACTIVE'"
+	
+		cursor.execute("SELECT assocTypeID FROM Assoc_Prop_Type_tbl WHERE APropertyID=" + `assocPropID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+		
+		return -1
+
+
+	def isUsedReagentTypeAssociation(self, rTypeID, pTypeID):
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("SELECT p.propListID FROM Assoc_Prop_Type_tbl a, AssocProp_tbl p WHERE a.reagentTypeID=" + `rTypeID` + " AND a.assocTypeID=" + `pTypeID` + " AND p.APropertyID=a.APropertyID AND a.status='ACTIVE' AND p.status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			if int(result[0]):
+				return True
+		
+		return False
+
+
+	def findParentAssocType(self, rTypeID, pTypeID):
+		db = self.db
+		cursor = self.cursor
+	
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print
+		#print "SELECT APropertyID FROM Assoc_Prop_Type_tbl WHERE assocTypeID=" + `pTypeID` + " AND reagentTypeID= " + `rTypeID` + " AND status='ACTIVE'"
+
+		cursor.execute("SELECT APropertyID FROM Assoc_Prop_Type_tbl WHERE assocTypeID=" + `pTypeID` + " AND reagentTypeID= " + `rTypeID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+
+		return -1
+
+
+	# identical to findReagentTypeAssocProps, only returns a list of (APropertyID, assocTypeID) tuples - i.e. identifies the parent types of this reagent type
+	# (E.g. Vector and Oligo are Insert parent types; Cell Line and Vector are Cell Line parent types)
+	def findReagentAssociationParentTypes(self, rTypeID):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		rMapper = ReagentTypeMapper(db, cursor)
+		aHandler = AssociationHandler(db, cursor)
+		
+		assocProps = {}
+		
+		# don't bother with hierarchy now; everything is 'PARENT' at this point --> in our current context, 'associations' = 'parents'
+		cursor.execute("SELECT APropertyID, assocTypeID FROM Assoc_Prop_Type_tbl WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			aPropID = int(result[0])
+			assocTypeID = int(result[1])
+			
+			assocProps[aPropID] = assocTypeID
+		
+		return assocProps
+		
+	
+##############################################################################
+# ReagentTypeHandler class
+# Descendant of GeneralHandler; handles reagent types
+#
+# Written March 30/07 by Marina
+##############################################################################
+class ReagentTypeHandler(GeneralHandler):
+	"Handles queries related to reagent type"
+
+	# Fetch the type name that corresponds to rTypeID
+	# E.g. rTypeID = 4; type name = "Cell Line"
+	#
+	# Input: rTypeID: INT, corresponds to reagentTypeID in ReagentType_tbl
+	# Returns: rTypeName: STRING, corresponds to reagentTypeName in ReagentType_tbl
+	def findReagentType(self, rTypeID):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("SELECT reagentTypeName FROM ReagentType_tbl WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+		
+		return None
+
+
+	# Reverse action: Fetch the type **ID** that corresponds to rTypeName
+	# E.g. rTypeName = "Cell Line"; rTypeID = 4
+	#
+	# Input: rTypeName: STRING, corresponds to reagentTypeName in ReagentType_tbl
+	# Returns: rTypeID: INT, corresponds to reagentTypeID in ReagentType_tbl
+	def findReagentTypeID(self, rTypeName):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("SELECT reagentTypeID FROM ReagentType_tbl WHERE reagentTypeName=" + `rTypeName` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+		
+		return -1
+	
+	
+	# June 3/09
+	def findReagentTypePrefix(self, rTypeName):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("SELECT reagent_prefix FROM ReagentType_tbl WHERE reagentTypeName=" + `rTypeName` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+		
+		return None
+	
+	
+	# April 3/09: Add a new reagent type
+	def addReagentType(self, rTypeName, rPrefix):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("INSERT INTO ReagentType_tbl(reagentTypeName, reagent_prefix) VALUES(" + `rTypeName` + ", " + `rPrefix` + ")")
+		rTypeID = int(db.insert_id())
+		
+		return rTypeID
+	
+	
+	def setReagentTypeName(self, rTypeID, rTypeName):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		if self.existsReagentTypeID(rTypeID):
+			cursor.execute("UPDATE ReagentType_tbl SET reagentTypeName=" + `rTypeName` + " WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+	
+	
+	def existsReagentTypeID(self, rTypeID):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("SELECT * FROM ReagentType_tbl WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return True
+		
+		return False
+		
+	
+	def setReagentTypePrefix(self, rTypeID, rTypePrefix):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		if self.existsReagentTypeID(rTypeID):
+			cursor.execute("UPDATE ReagentType_tbl SET reagent_prefix=" + `rTypePrefix` + " WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+	
+	# April 8/09: Check if a reagent type exists
+	def existsReagentType(self, rTypeName, rPrefix):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("SELECT reagentTypeID FROM ReagentType_tbl WHERE reagentTypeName=" + `rTypeName` + " AND reagent_prefix=" + `rPrefix` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return True
+		else:
+			return False
+		
+	
+	# June 3/09: Check if there are reagents of this type in the database
+	def isEmpty(self, rTypeID):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("SELECT count(reagentID) FROM Reagents_tbl WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			rCount = int(result[0])
+			
+			if rCount == 0:
+				return True
+			else:
+				return False
+		else:
+			return True
+		
+
+	# June 3/09: delete reagent type IFF no reagents have been created for it!! 
+	def deleteReagentType(self, rTypeID):
+
+		db = self.db
+		cursor = self.cursor
+	
+		rTypeName = self.findReagentType(rTypeID)
+		rTypePrefix = self.findReagentTypePrefix(rTypeName)
+		
+		# Can place a check here, only this function is invoked from one place only - reagent type detailed view (fresh after creation or from searching), by pressing the 'Delete' button - which is disabled if there are reagents of this type in the database.  With this function being a standalone procedure, whose task is simple deletion of a row in ReagentType_tbl, not placing any additional checks here; it is the responsibility of the referring page.
+		
+		cursor.execute("UPDATE ReagentType_tbl SET status='DEP' where reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+
+
+######################################################################################
+# ReagentTypePropertyHandler class
+# Descendant of GeneralHandler; handles queries related specifically to reagent type 
+# properties/attributes
+#
+# Written August 31/09 by Marina
+######################################################################################
+class ReagentTypePropertyHandler(GeneralHandler):
+	"Handles queries related specifically to reagent type properties/attributes"
+	
+	# May 7/09
+	def findReagentTypeAttributeNamesByCategory(self, rTypeID, pCategoryID):
+		db = self.db
+		cursor = self.cursor
+		
+		rTypeAttributeNames = []
+		
+		cursor.execute("SELECT p.propertyName FROM ReagentTypeAttributes_tbl t, ReagentPropType_tbl p, ReagentPropertyCategories_tbl c WHERE t.reagentTypeID=" + `rTypeID` + " AND t.propertyTypeID=c.propCatID AND c.categoryID=" + `pCategoryID` + " AND c.propID=p.propertyID AND t.status='ACTIVE' AND p.status='ACTIVE' AND c.status='ACTIVE'")
+		results = cursor.fetchall()
+
+		for result in results:
+			rTypeAttributeNames.append(result[0])
+			
+		return rTypeAttributeNames
+		
+		
+	# May 13, 2010: if have attribute names, why not have attribute IDs?
+	def findReagentTypeAttributeIDsByCategory(self, rTypeID, pCategoryID):
+		db = self.db
+		cursor = self.cursor
+		
+		rTypeAttributeIDs = []
+		
+		#print "Content-type:text/html"
+		#print
+		#print "SELECT t.propertyTypeID FROM ReagentTypeAttributes_tbl t, ReagentPropType_tbl p, ReagentPropertyCategories_tbl c WHERE t.reagentTypeID=" + `rTypeID` + " AND t.propertyTypeID=c.propCatID AND c.categoryID=" + `pCategoryID` + " AND c.propID=p.propertyID AND t.status='ACTIVE' AND p.status='ACTIVE' AND c.status='ACTIVE'"
+		
+		cursor.execute("SELECT t.reagentTypePropertyID FROM ReagentTypeAttributes_tbl t, ReagentPropType_tbl p, ReagentPropertyCategories_tbl c WHERE t.reagentTypeID=" + `rTypeID` + " AND t.propertyTypeID=c.propCatID AND c.categoryID=" + `pCategoryID` + " AND c.propID=p.propertyID AND t.status='ACTIVE' AND p.status='ACTIVE' AND c.status='ACTIVE'")
+		results = cursor.fetchall()
+
+		for result in results:
+			rTypeAttributeIDs.append(int(result[0]))
+			
+		return rTypeAttributeIDs
+
+
+	# Correction June 22/09: This returns a dictionary of {attributeID => propCatID}
+	def findAllReagentTypeAttributes(self, rTypeID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		rTypeAttributeIDs = {}
+		
+		#print "Content-type:text/html"
+		#print
+		#print "SELECT reagentTypePropertyID, propertyTypeID FROM ReagentTypeAttributes_tbl WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'"
+		
+		cursor.execute("SELECT reagentTypePropertyID, propertyTypeID FROM ReagentTypeAttributes_tbl WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+
+		for result in results:
+			rTypeAttributeIDs[int(result[0])] = int(result[1])
+			
+		return rTypeAttributeIDs
+	
+	
+	# April 11, 2009: Add a property to set of properties for a given reagent type
+	# Correction June 19/09: Use the composite key propCatID of ReagentPropertyCategories_tbl - represents a property in conjunction with a category
+	#def addReagentTypeAttribute(self, rTypeID, propTypeID, categoryID):
+	def addReagentTypeAttribute(self, rTypeID, propCatID):
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("INSERT INTO ReagentTypeAttributes_tbl(reagentTypeID, propertyTypeID) VALUES(" + `rTypeID` + ", " + `propCatID` + ")")
+		newReagentTypePropID = int(db.insert_id())
+		
+		return newReagentTypePropID
+	
+
+	# July 28/09: Given the values of reagentTypeID and propertyTypeID columns in ReagentTypeAttributes_tbl, return the value of reagentTypePropertyID (the primary key)
+	def findReagentTypeAttributeID(self, rTypeID, propID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT reagentTypePropertyID FROM ReagentTypeAttributes_tbl WHERE reagentTypeID=" + `rTypeID` + " AND propertyTypeID=" + `propID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()	# one-to-one mapping of reagent type to a property within a specific category
+		
+		if result:
+			return int(result[0])
+		
+		return -1
+	
+	# April 11, 2009: Check if a property exists in ReagentTypeAttributes_tbl, i.e. if a given property is associated with a given reagent type
+	#
+	# input: rTypeID - datbase identifier for a given reagent type (e.g. '1' -> 'Vector)
+	#	 pTypeID - datbase identifier for a given property type (e.g. '1' -> 'Name')
+	#
+	# Return: True or False
+	# Correction June 19/09: Properties are now used in conjunction with their categories; therefore, use a composite key "propCatID" in query
+	#def existsReagentTypeAttribute(self, rTypeID, pTypeID):
+	def existsReagentTypeAttribute(self, rTypeID, propCatID):
+		db = self.db
+		cursor = self.cursor
+		
+		#cursor.execute("SELECT * FROM ReagentTypeAttributes_tbl WHERE reagentTypeID=" + `rTypeID` + " AND propertyTypeID=" + `pTypeID` + " AND status='ACTIVE'")
+		cursor.execute("SELECT * FROM ReagentTypeAttributes_tbl WHERE reagentTypeID=" + `rTypeID` + " AND propertyTypeID=" + `propCatID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		if result:
+			return True
+		else:
+			return False
+	
+	# June 3/09
+	def deleteReagentTypeAttribute(self, rTypeID, pID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print "UPDATE ReagentTypeAttributes_tbl SET status='DEP' WHERE reagentTypeID=" + `rTypeID` + " AND propertyTypeID=" + `pID` + " AND status='ACTIVE'"
+		
+		cursor.execute("UPDATE ReagentTypeAttributes_tbl SET status='DEP' WHERE reagentTypeID=" + `rTypeID` + " AND propertyTypeID=" + `pID` + " AND status='ACTIVE'")
+	
+	
+	# June 14, 2010
+	def isDropdown(self, rTypeAttrID):
+	
+		if self.getAttributeInputFormat(rTypeAttrID) == "predefined":
+			return True
+		else:
+			return False
+		
+	
+	# Sept. 4/09
+	def getAttributeInputFormat(self, rTypeAttrID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		sHandler = SystemSetHandler(db, cursor)
+		
+		# Change June 14, 2010: Now that we're allowing blank dropdown lists if 'Other' is checked, need to explore all possibilities: a) is_customizeable? b) is_multiple? c) has values?  If the property has been declared a hyperlink, assume freetext (dropdowns cannot be hyperlinked unless in error; similarly, freetext fields cannot be made multiple/customizeable)
+		if self.isHyperlink(rTypeAttrID):
+			return "freetext"
+		else:
+			if self.isCustomizeable(rTypeAttrID) or self.isMultiple(rTypeAttrID):
+				return "predefined"
+			else:
+				# This may still be a dropdown, single and non-customizeable
+				# check if values have been set for it
+				# For completeness and consistency, use findReagentTypeAttributeSetValues() here, not findReagentTypeAttributeSetIDs()
+				# (remember: attributeSetID should be deleted when going from dropdown to freetext!)
+				if len(sHandler.findReagentTypeAttributeSetValues(rTypeAttrID)) > 0:
+					return "predefined"
+				else:
+					return "freetext"
+
+
+	# Sept. 10/09: Check if property propID is used by reagents of type rTypeID (i.e. if values of this property have been assigned to reagents of this type) - needed for reagent type modification
+	def propertyUsedForReagentType(self, rTypeID, propID, isDescriptor=False):
+		db = self.db
+		cursor = self.cursor
+		
+		if isDescriptor:
+			cursor.execute("SELECT COUNT(p.propListID) FROM ReagentPropList_tbl p, Reagents_tbl r WHERE p.reagentID=r.reagentID AND r.reagentTypeID=" + `rTypeID` + " AND p.propertyID=" + `propID` + " AND p.descriptor != '' AND p.descriptor != 'NULL' AND p.status='ACTIVE' AND r.status='ACTIVE'")
+			
+		
+		cursor.execute("SELECT COUNT(p.propListID) FROM ReagentPropList_tbl p, Reagents_tbl r WHERE r.reagentTypeID=" + `rTypeID` + " AND r.reagentID=p.reagentID AND p.propertyID=" + `propID` + " AND r.status='ACTIVE' AND p.status='ACTIVE'")
+		
+		#results = cursor.fetchall()
+		result = cursor.fetchone()
+		
+		if result:
+			if int(result[0]) > 0:
+				return True	# property is used
+		
+		#return len(results) > 0
+		
+		return False	# not used
+	
+	# Oct. 15/09 - propID is propCatID
+	def isUsedProperty(self, rTypeID, propID, isDescriptor=False):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print
+		
+		# removed Jan. 21, 2010: queries should be different but they are identical here!
+		#if isDescriptor:
+			#cursor.execute("SELECT COUNT(p.propListID) FROM ReagentPropList_tbl p, Reagents_tbl r WHERE r.reagentTypeID=" + `rTypeID` + " AND p.reagentID=r.reagentID AND p.propertyID=" + `propID` + " AND p.status='ACTIVE' AND r.status='ACTIVE'")
+			
+		#else:
+		
+		cursor.execute("SELECT COUNT(p.propListID) FROM ReagentPropList_tbl p, Reagents_tbl r WHERE r.reagentTypeID=" + `rTypeID` + " AND p.reagentID=r.reagentID AND p.propertyID=" + `propID` + " AND p.status='ACTIVE' AND r.status='ACTIVE'")
+
+		result = cursor.fetchone()
+		
+		if result:
+			if int(result[0]) > 0:
+				return True
+		
+		return False
+
+
+	# Jan. 29/10 - check if actual property value is used
+	# propID == propCatID (property in category)
+	def existsPropertyValue(self, rTypeID, propID, propVal, isDescriptor=False):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+
+		if isDescriptor:
+			cursor.execute("SELECT COUNT(p.propListID) FROM ReagentPropList_tbl p, Reagents_tbl r WHERE r.reagentTypeID=" + `rTypeID` + " AND p.reagentID=r.reagentID AND p.propertyID=" + `propID` + " AND p.descriptor LIKE '%" + propVal + "%' AND p.status='ACTIVE' AND r.status='ACTIVE'")
+			
+		else:
+			#print "SELECT COUNT(p.propListID) FROM ReagentPropList_tbl p, Reagents_tbl r WHERE r.reagentTypeID=" + `rTypeID` + " AND p.reagentID=r.reagentID AND p.propertyID=" + `propID` + " AND p.propertyValue LIKE '%" + propVal + "%' AND p.status='ACTIVE' AND r.status='ACTIVE'"
+			
+			cursor.execute("SELECT COUNT(p.propListID) FROM ReagentPropList_tbl p, Reagents_tbl r WHERE r.reagentTypeID=" + `rTypeID` + " AND p.reagentID=r.reagentID AND p.propertyID=" + `propID` + " AND p.propertyValue LIKE '%" + propVal + "%' AND p.status='ACTIVE' AND r.status='ACTIVE'")
+
+		result = cursor.fetchone()
+		
+		if result:
+			if int(result[0]) > 0:
+				return True
+		
+		return False
+
+	# Nov. 16/09: Given reagentTypePropertyID column value, return the value of propertyTypeID column
+	def findReagentTypeAttributePropertyID(self, rTypeAttrID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"
+		#print
+		#print "SELECT propertyTypeID FROM ReagentTypeAttributes_tbl WHERE reagentTypePropertyID=" + `rTypeAttrID` + " AND status='ACTIVE'"
+		
+		cursor.execute("SELECT propertyTypeID FROM ReagentTypeAttributes_tbl WHERE reagentTypePropertyID=" + `rTypeAttrID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+		
+		return -1
+	
+	
+	# April 9, 2010
+	def getReagentTypePropertyOrdering(self, rTypeID, propCatID):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		if rTypeID and rTypeID > 0 and propCatID and propCatID > 0:
+			cursor.execute("SELECT ordering FROM ReagentTypeAttributes_tbl WHERE reagentTypeID=" + `rTypeID` + " AND propertyTypeID=" + `propCatID` + " AND status='ACTIVE'")
+			
+			#print "Content-type:text/html"
+			#print
+			#print "SELECT ordering FROM ReagentTypeAttributes_tbl WHERE reagentTypeID=" + `rTypeID` + " AND propertyTypeID=" + `propCatID` + " AND status='ACTIVE'"
+			
+			result = cursor.fetchone()
+			
+			if result:
+				return int(result[0])
+		
+		return -1
+
+	# April 9, 2010
+	def setReagentTypeAttributeOrdering(self, rTypeAttrID, pOrder):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		# status='ACTIVE' check might be redundant but still
+		cursor.execute("UPDATE ReagentTypeAttributes_tbl SET ordering=" + `pOrder` + " WHERE reagentTypePropertyID=" + `rTypeAttrID` + " AND status='ACTIVE'")
+		
+		
+	# April 29, 2010
+	def makeMultiple(self, rTypeAttrID):
+	
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("UPDATE ReagentTypeAttributes_tbl SET is_multiple='YES' WHERE reagentTypePropertyID=" + `rTypeAttrID` + " AND status='ACTIVE'")
+		
+	# April 29, 2010
+	def makeSingle(self, rTypeAttrID):
+	
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("UPDATE ReagentTypeAttributes_tbl SET is_multiple='NO' WHERE reagentTypePropertyID=" + `rTypeAttrID` + " AND status='ACTIVE'")
+		
+		
+	def makeCustomizeable(self, rTypeAttrID):
+	
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("UPDATE ReagentTypeAttributes_tbl SET is_customizeable='YES' WHERE reagentTypePropertyID=" + `rTypeAttrID` + " AND status='ACTIVE'")
+
+
+	def removeCustomizeable(self, rTypeAttrID):
+	
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("UPDATE ReagentTypeAttributes_tbl SET is_customizeable='NO' WHERE reagentTypePropertyID=" + `rTypeAttrID` + " AND status='ACTIVE'")
+		
+		
+	# April 29, 2010
+	def makeHyperlink(self, rTypeAttrID):
+	
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("UPDATE ReagentTypeAttributes_tbl SET is_hyperlink='YES' WHERE reagentTypePropertyID=" + `rTypeAttrID` + " AND status='ACTIVE'")
+
+
+	# April 29, 2010
+	def removeHyperlink(self, rTypeAttrID):
+	
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("UPDATE ReagentTypeAttributes_tbl SET is_hyperlink='NO' WHERE reagentTypePropertyID=" + `rTypeAttrID` + " AND status='ACTIVE'")
+	
+	# April 29, 2010
+	def isMultiple(self, rTypeAttrID):
+
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("SELECT is_multiple FROM ReagentTypeAttributes_tbl WHERE reagentTypePropertyID=" + `rTypeAttrID` + " AND status='ACTIVE'")
+		
+		result = cursor.fetchone()
+		
+		if result[0] == 'YES':
+			return True
+		else:
+			return False
+	
+	
+	# April 29, 2010
+	def isHyperlink(self, rTypeAttrID):
+
+		db = self.db
+		cursor = self.cursor
+	
+		#print "Content-type:text/html"
+		#print
+		#print "SELECT is_hyperlink FROM ReagentTypeAttributes_tbl WHERE reagentTypePropertyID=" + `rTypeAttrID` + " AND status='ACTIVE'"
+		
+		cursor.execute("SELECT is_hyperlink FROM ReagentTypeAttributes_tbl WHERE reagentTypePropertyID=" + `rTypeAttrID` + " AND status='ACTIVE'")
+		
+		result = cursor.fetchone()
+		#print result[0]
+		
+		if result[0] == 'YES':
+			return True
+		else:
+			return False
+	
+	# May 11, 2010
+	def isCustomizeable(self, rTypeAttrID):
+
+		db = self.db
+		cursor = self.cursor
+	
+		#print "Content-type:text/html"
+		#print
+		#print "SELECT is_hyperlink FROM ReagentTypeAttributes_tbl WHERE reagentTypePropertyID=" + `rTypeAttrID` + " AND status='ACTIVE'"
+		
+		cursor.execute("SELECT is_customizeable FROM ReagentTypeAttributes_tbl WHERE reagentTypePropertyID=" + `rTypeAttrID` + " AND status='ACTIVE'")
+		
+		result = cursor.fetchone()
+		#print result[0]
+		
+		if result[0] == 'YES':
+			return True
+		else:
+			return False
+	
+	
+######################################################################################
+# UserCategoryHandler class
+# Descendant of GeneralHandler; handles User and Lab categories and access privileges
+#
+# Written July 3/07 by Marina
+######################################################################################
+class UserCategoryHandler(GeneralHandler):
+	"Handles queries related to User and Lab categories and access privileges"
+	
+	# Fetch all category names - Reader, Writer, Creator, Admin
+	# Return: dictionary of (categoryID, category) tuples (e.g. ('1', 'Admin')
+	def findAllCategories(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		categories = {}		# dictionary of (categoryID, category) tuples
+		
+		cursor.execute("SELECT categoryID, category FROM UserCategories_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			catID = int(result[0])
+			category = result[1]
+			
+			categories[catID] = category
+			
+		return categories
+
+
+###################################################################################################################################
+# SystemSetHandler class
+# Subclass of GeneralHandler class
+# Written November 2, 2006, by Marina Olhovsky; migrated to general_handler.py module October 2009 (previously was a separate module)
+#
+# Note on table structure change Nov. 16/09:
+# - removed groupName column from System_Set_Groups_tbl
+# - replaced groupDesc column values by CONCAT category + property (e.g. 'General Properties Name')
+# - propertyIDLink column is now a foreign key referencing ReagentPropertyCategories_tbl(propCatID)
+#
+# (the purpose is to enable dropdown list value separation across reagent types)
+###################################################################################################################################
+class SystemSetHandler(GeneralHandler):
+
+	"This class handles reagent properties in OpenFreezer that are shown as dropdown lists on various views"
+
+	def __init__(self, db, cursor):
+		self.db = db
+		self.cursor = cursor
+
+
+	# Nov. 10/09
+	def existsReagentTypeAttributeSetValue(self, rTypeAttrID, ssetID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"
+		#print
+		#print "SELECT reagentTypeAttributeSetID FROM ReagentTypeAttribute_Set_tbl WHERE reagentTypeAttributeID=" + `rTypeAttrID` + " AND ssetID=" + `ssetID` + " AND status='ACTIVE'"
+		
+		cursor.execute("SELECT reagentTypeAttributeSetID FROM ReagentTypeAttribute_Set_tbl WHERE reagentTypeAttributeID=" + `rTypeAttrID` + " AND ssetID=" + `ssetID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			if int(result[0]) > 0:
+				return True
+			
+		return False
+
+
+	# Nov. 10/09 - THIS DOES NOT DELETE ACTUAL System_Set_Group_tbl OR System_Set_tbl VALUES -- ONLY DELETES ReagentTypeAttribute_Set_tbl ROWS!!!!!!
+	def deleteReagentTypeAttributeSetValues(self, rTypeAttrID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		# multiple dropdown values for one attribute ID
+		cursor.execute("UPDATE ReagentTypeAttribute_Set_tbl SET status='DEP' WHERE reagentTypeAttributeID=" + `rTypeAttrID` + " AND status='ACTIVE'")
+	
+
+	# Add propVal to the appropriate dropdown list
+	# Input:
+	#   setGroupID = ssetGroupID column value in System_Set_tbl
+	#   entityVal = actual set value
+	# Return: new ssetGroupID
+	def addSetValue(self, setGroupID, entityVal):
+		db = self.db
+		cursor = self.cursor
+		
+		pHandler = ReagentPropertyHandler(db, cursor)		# April 13/09
+		
+		if not self.existsSetEntry(setGroupID, entityVal):
+			cursor.execute("INSERT INTO `System_Set_tbl`(`ssetGroupID`, `entityName`, `entityDesc`) VALUES(" + `setGroupID` + ", " + `entityVal` + ", " + `entityVal` + ")")
+			return int(db.insert_id())
+		else:
+			return self.findSetValueID(setGroupID, entityVal)
+
+
+	# Nov. 10/09
+	def findSetValueID(self, setGroupID, entityVal):
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("SELECT ssetID FROM System_Set_tbl WHERE ssetGroupID=" + `setGroupID` + " AND entityName=" + `entityVal` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+		
+		return -1
+	
+	
+	# Nov. 9/09
+	def existsSetGroup(self, propCatID):
+		db = self.db
+		cursor = self.cursor
+		
+		return self.findPropSetGroupID(propCatID) > 0
+	
+	
+	# Nov. 9/09
+	def findPropSetGroupID(self, propCatID):
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"
+		#print
+		#print "SELECT ssetGroupID FROM System_Set_Groups_tbl WHERE propertyIDLink=" + `propCatID` + " AND status='ACTIVE'"
+		
+		cursor.execute("SELECT ssetGroupID FROM System_Set_Groups_tbl WHERE propertyIDLink=" + `propCatID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+		
+		return -1
+	
+		
+	# Nov. 9/09
+	def addReagentTypeAttributeSetEntry(self, rTypeAttrID, ssetID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("INSERT INTO ReagentTypeAttribute_Set_tbl(reagentTypeAttributeID, ssetID) VALUES(" + `rTypeAttrID` + ", " + `ssetID` + ")")
+		
+		return int(db.insert_id())
+		
+	
+	# Nov. 9/09: Make an enty in System_Set_Groups_tbl for propCatID
+	# Return the new ssetGroupID
+	def addSetGroupID(self, propCatID, groupDesc):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("INSERT INTO System_Set_Groups_tbl(propertyIDLink, groupDesc) VALUES(" + `propCatID` + ", " + `groupDesc` + ")")
+		
+		return int(db.insert_id())
+	
+	
+	# Checks if the given set entry exists in System_Set_Groups_tbl
+	def existsSetEntry(self, ssetGroupID, entityVal):
+		db = self.db
+		cursor = self.cursor
+		
+		#cursor.execute("SELECT * FROM System_Set_Groups_tbl s1, System_Set_tbl s2 WHERE s1.groupDesc=" + `entityName` + " AND s1.ssetGroupID=s2.ssetGroupID AND s2.entityName=" + `entityVal` + " AND s1.status='ACTIVE' AND s2.status='ACTIVE'")
+		
+		cursor.execute("SELECT * FROM System_Set_tbl WHERE ssetGroupID=" + `ssetGroupID` + " AND entityName=" + `entityVal` + " AND status='ACTIVE'")
+		result = cursor.fetchall()
+		
+		if not result:
+			return 0	# the entity does NOT exist
+		else:
+			return 1
+		
+		
+	# Find a set of all values for a particular property (e.g. fetch all available Species, Insert Types, etc.)
+	# ssetGroupName: STRING, name of the property (Type of Insert, Species, etc.) - corresponds to 'groupName' column in System_Set_Groups_tbl
+	# Modified August 4/09
+	def findAllSetValues(self, ssetGroupID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		setValues = []
+		
+		#cursor.execute("SELECT s.entityName FROM System_Set_tbl s, System_Set_Groups_tbl g WHERE g.groupName=" + `ssetGroupName` + " AND g.ssetGroupID=s.ssetGroupID AND g.status='ACTIVE' AND s.status='ACTIVE' ORDER BY s.entityName")
+		
+		cursor.execute("SELECT DISTINCT(s.entityName) FROM System_Set_tbl s, System_Set_Groups_tbl g WHERE g.ssetGroupID=" + `ssetGroupID` + " AND g.ssetGroupID=s.ssetGroupID AND g.status='ACTIVE' AND s.status='ACTIVE' ORDER BY s.entityName")
+		results = cursor.fetchall()
+		
+		for result in results:
+			setVal = result[0]
+			setValues.append(setVal)
+			
+		return setValues
+
+	
+	# Nov. 16/09: This is an auxiliary function; it performs the same query as findAllSetValues, but returns actual ssetID column values
+	def findAllSetIDs(self, ssetGroupID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		setIDs = []
+		
+		#cursor.execute("SELECT s.entityName FROM System_Set_tbl s, System_Set_Groups_tbl g WHERE g.groupName=" + `ssetGroupName` + " AND g.ssetGroupID=s.ssetGroupID AND g.status='ACTIVE' AND s.status='ACTIVE' ORDER BY s.entityName")
+		
+		cursor.execute("SELECT DISTINCT(s.ssetID) FROM System_Set_tbl s, System_Set_Groups_tbl g WHERE g.ssetGroupID=" + `ssetGroupID` + " AND g.ssetGroupID=s.ssetGroupID AND g.status='ACTIVE' AND s.status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			setID = int(result[0])
+			setIDs.append(setID)
+			
+		return setIDs
+		
+	
+	def findAllPropSetValues(self, propCatID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		setValues = []
+		
+		ssetGroupID = self.findPropSetGroupID(propCatID)
+		setValues = self.findAllSetValues(ssetGroupID)
+		
+		return setValues
+
+
+	# Oct. 13/09: Find set values for a particular property in a particular category assigned to a particular reagent
+	# i.e. output a subset of values returned by findAllPropSetValues() function above
+	# Updated Nov. 16/09
+	def findReagentTypeAttributeSetValues(self, attrID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		setValues = []
+		
+		# Nov. 16/09
+		setIDs = self.findReagentTypeAttributeSetIDs(attrID)
+		
+		#cursor.execute("SELECT ssetID FROM ReagentTypeAttribute_Set_tbl WHERE reagentTypeAttributeID=" + `attrID` + " AND status='ACTIVE'")
+		#results = cursor.fetchall()
+		
+		#for result in results:
+		for ssetID in setIDs:
+			#ssetID = int(result[0])
+			setVal = self.findSetValue(ssetID)
+
+			if setVal:
+				setValues.append(setVal)
+	
+		return setValues
+			
+			
+	# Nov. 16/09: Auxiliary function - performs the same query as findReagentTypeAttributeSetValues, but returns ssetID column values for a given attrID
+	def findReagentTypeAttributeSetIDs(self, attrID):
+		
+		#print "SELECT ssetID FROM ReagentTypeAttribute_Set_tbl WHERE reagentTypeAttributeID=" + `attrID` + " AND status='ACTIVE'"
+		
+		db = self.db
+		cursor = self.cursor
+		
+		setIDs = []
+		
+		cursor.execute("SELECT ssetID FROM ReagentTypeAttribute_Set_tbl WHERE reagentTypeAttributeID=" + `attrID` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			ssetID = int(result[0])
+			
+			if ssetID:
+				setIDs.append(ssetID)
+	
+		#print setIDs
+		return setIDs
+
+
+	# Nov. 10/09
+	def findSetValue(self, ssetID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT DISTINCT(entityName) FROM System_Set_tbl WHERE ssetID =" + `ssetID` + " AND status='ACTIVE' ORDER BY entityName")
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+		
+		return None
+	
+	
+	# Nov. 16/09
+	def deleteSetValue(self, ssetID):
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print "UPDATE System_Set_tbl SET status='DEP' WHERE ssetID=" + `ssetID` + " AND status='ACTIVE'"
+		
+		cursor.execute("UPDATE System_Set_tbl SET status='DEP' WHERE ssetID=" + `ssetID` + " AND status='ACTIVE'")
+		
+	
+	# June 3/09
+	def deleteSetValues(self, ssetGroupID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE System_Set_tbl SET status='DEP' WHERE ssetGroupID=" + `ssetGroupID` + " AND status='ACTIVE'")
+	
+	
+	# Aug. 5/09
+	def deleteSetGroup(self, setGroupID):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE System_Set_Groups_tbl SET status='DEP' WHERE ssetGroupID=" + `setGroupID` + " AND status='ACTIVE'")
+
+
+	# Oct. 15/09 - propID is propCatID
+	def isUsedSetValue(self, rTypeID, propID, setValue, isDescriptor=False):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		if isDescriptor:
+			cursor.execute("SELECT COUNT(p.propListID) FROM ReagentPropList_tbl p, Reagents_tbl r WHERE r.reagentTypeID=" + `rTypeID` + " AND p.reagentID=r.reagentID AND p.propertyID=" + `propID` + " AND p.descriptor=" + `setValue` + " AND p.status='ACTIVE' AND r.status='ACTIVE'")
+			
+		else:
+			cursor.execute("SELECT COUNT(p.propListID) FROM ReagentPropList_tbl p, Reagents_tbl r WHERE r.reagentTypeID=" + `rTypeID` + " AND p.reagentID=r.reagentID AND p.propertyID=" + `propID` + " AND p.propertyValue=" + `setValue` + " AND p.status='ACTIVE' AND r.status='ACTIVE'")
+			
+		result = cursor.fetchone()
+		
+		if result:
+			if int(result[0]) > 0:
+				return True
+		
+		return False
\ No newline at end of file
diff --git a/OpenFreezer/cgi/general_output.py b/OpenFreezer/cgi/general_output.py
new file mode 100755
index 0000000..95ed4df
--- /dev/null
+++ b/OpenFreezer/cgi/general_output.py
@@ -0,0 +1,737 @@
+#!/usr/local/bin/python
+
+import os
+import tempfile
+import stat
+import sys
+
+from database_conn import DatabaseConn
+from user_handler import UserHandler
+from lab_handler import LabHandler
+
+from user import User
+from session import Session
+from laboratory import Laboratory
+from mapper import UserCategoryMapper, SystemModuleMapper	# updated Aug. 20, 2010
+
+import utils
+
+class GeneralOutputClass:
+	
+	def printHeader(self):
+		
+		content = '''
+			<HTML>
+				<HEAD>
+					<link href="../styles/SearchStyle.css" rel="stylesheet" type="text/css">
+					<link href="../styles/Header_styles.css" rel="stylesheet" type="text/css">
+
+					<LINK REL="stylesheet" HREF="../styles/generic.css" type="text/css"/>
+
+					<script type="text/javascript" language="JavaScript1.2" src="../scripts/menu.js"></script>
+				</HEAD>
+
+				<BODY style="width:98%%" onLoad="initAll()">
+
+					<table cellpadding="0" cellspacing="0" style="width:100%%; background:black;">
+						<tr>
+							<td colspan="3"><img src="../pictures/oftmp.png"></td>
+                                                        <td style="padding-right:2px; background-color:black; padding-top:3px; padding-bottom:2px;"><img src="../pictures/marina1.png" height="68" ALT="logo"></td>
+					
+						</tr>
+					</table>
+				
+	                                <div class="notice" style="font-size:9pt; width:100%%; text-align:center;">Best viewed in <a href="http://www.mozilla.com/en-US/firefox/">Mozilla Firefox®</a> version 2 or later</div>
+	
+					'''
+		
+		content += self.printMainMenu()
+		
+		content += '''
+					<Div class="main">
+						<DIV class="main_content" style="padding:5px;" ID="mainDiv">
+						'''
+		
+		return content
+
+
+	def printFooter(self):
+		content = '''
+					</DIV>	<!--close 'main'-->
+				</DIV>	<!--close 'mainDiv'-->
+				
+				<DIV class="footer_container">
+					<DIV class="footer">
+						Copyright ©Mount Sinai Hospital, Toronto, Canada.
+					</DIV>
+				</DIV>
+			</BODY>
+		</HTML>
+		'''
+		
+		return content
+		
+		
+	# Returns a string containing HTML content for the side menu
+	def printMainMenu(self):
+
+		dbConn = DatabaseConn()
+		hostname = dbConn.getHostname()		# to define form action URL
+		
+		db = dbConn.databaseConnect()
+		cursor = db.cursor()
+
+		uHandler = UserHandler(db, cursor)
+		
+		# Aug. 20, 2010
+		pageMapper = SystemModuleMapper(db, cursor)
+		
+		pageLinkMap = pageMapper.mapPageNameLink()
+		
+		# Array of section names
+		currentSectionNames = []
+
+		# Dictionary of links to names, with names as dictionary keys and links as values
+		currentSectionLinks = {}
+
+		# Added Nov. 10/06 by Marina - Classify each header as to what OF section it belongs
+    		menuTypes = {}
+
+		# June 04/07 - Differentiate between 'public' and 'private' pages
+		publicSectionNames = []
+    		publicSectionLinks = []
+
+		publicSections = {}
+		
+		# Feb. 2, 2010: change menu layout (reflect HeaderFunctions.php code changes Jan. 12/10)
+		submenu_links = {}
+		submenu_types = {}
+		menuitems = {}
+		
+		# Home
+		currentSectionNames.append("Home")
+		currentSectionLinks["Home"] = "../index.php"
+		publicSections["Home"] = "index.php"
+
+		# Reagent
+		currentSectionNames.append("Reagent Tracker")
+		currentSectionLinks["Reagent Tracker"] = "../Reagent.php?View=1"
+		
+		menuTypes["Reagent Tracker"] = "Reagent"
+		publicSections["Reagent Tracker"] = "../Reagent.php?View=1"
+		
+		# Feb. 2, 2010
+		tmp_list = []
+		tmp_list.append("Reagents")
+		tmp_list.append("Reagent Types")
+		
+		submenu_types["Reagent Tracker"] = tmp_list
+		
+		tmp_order_list = {}
+		tmp_order_list[0] = "Add"
+		tmp_order_list[1] = "Search"
+		tmp_order_list[2] = "Statistics"
+
+		submenu_order = {}
+		submenu_order["Reagents"] = tmp_order_list
+
+		tmp_list = {}
+		tmp_list["Add"] = "../Reagent.php?View=2"
+		tmp_list["Search"] = "../search.php?View=1"
+		tmp_list["Statistics"] = "../Reagent.php?View=4"
+		
+		submenu_links["Reagents"] = tmp_list
+		
+		tmp_list = {}
+		tmp_list["Add"] = "Add reagents"
+		tmp_list["Search"] = "Search reagents"
+		tmp_list["Statistics"] = "Statistics"
+	
+		menuitems["Reagents"] = tmp_list
+	
+		tmp_order_list = {}
+		tmp_order_list[0] = "Add"
+		tmp_order_list[1] = "Search"
+	
+		submenu_order["Reagent Types"] = tmp_order_list
+
+		tmp_list = {}
+		tmp_list["Add"] = "../Reagent.php?View=3"
+		tmp_list["Search"] = "../Reagent.php?View=5"
+		submenu_links["Reagent Types"] = tmp_list
+		
+		tmp_list = {}
+		tmp_list["Add"] = "Add reagent types"
+		tmp_list["Search"] = "Search reagent types"
+		menuitems["Reagent Types"] = tmp_list
+		
+		# Locations
+		currentSectionNames.append("Location Tracker")
+		currentSectionLinks["Location Tracker"] = "../Location.php?View=1"
+		
+		menuTypes["Location Tracker"] = "Location"
+		publicSections["Location Tracker"] = "../Location.php?View=1"
+
+		# Feb. 2/10
+		tmp_list = []
+		tmp_list.append("Containers")
+		tmp_list.append("Container Sizes")
+		tmp_list.append("Container Types")
+		submenu_types["Location Tracker"] = tmp_list
+		
+		tmp_order_list = {}
+		tmp_order_list[0] = "Add"
+		tmp_order_list[1] = "Search"
+	
+		submenu_order["Container Types"] = tmp_order_list
+	
+		tmp_order_list = {}
+		tmp_order_list[0] = "Add"
+		#tmp_order_list[1] = "Search"
+	
+		submenu_order["Container Sizes"] = tmp_order_list
+	
+		tmp_order_list = {}
+		tmp_order_list[0] = "Add"
+		tmp_order_list[1] = "Search"
+	
+		submenu_order["Containers"] = tmp_order_list
+	
+		tmp_list = {}
+		tmp_list["Add"] = "../Location.php?View=6&Sub=2"
+		tmp_list["Search"] = "../Location.php?View=6&Sub=4"
+		submenu_links["Container Types"] = tmp_list
+	
+		tmp_list = {}
+		tmp_list["Add"] = "Add container types"
+		tmp_list["Search"] = "Search container types"
+		menuitems["Container Types"] = tmp_list
+		
+		tmp_list = {}
+		tmp_list["Add"] = "../Location.php?View=6&Sub=1"
+		tmp_list["Search"] = "../Location.php?View=6&Sub=5"
+		submenu_links["Container Sizes"] = tmp_list
+	
+		tmp_list = {}
+		tmp_list["Add"] = "Add container sizes"
+		#tmp_list["Search"] = "Search container sizes"
+		menuitems["Container Sizes"] = tmp_list
+		
+		tmp_list = {}
+		tmp_list["Add"] = "../Location.php?View=6&Sub=3"
+		tmp_list["Search"] = "../Location.php?View=2"
+		submenu_links["Containers"] = tmp_list
+		
+		tmp_list = {}
+		tmp_list["Add"] = "Add containers"
+		tmp_list["Search"] = "Search containers"
+		menuitems["Containers"] = tmp_list
+		
+		# Projects
+		currentSectionNames.append("Project Management")
+		currentSectionLinks["Project Management"] = "../Project.php?View=1"
+		menuTypes["Project Management"] = "Project"
+		
+		# Feb. 2/10
+		tmp_list = []
+		tmp_list.append("Projects")
+		submenu_types["Project Management"] = tmp_list
+
+		tmp_order_list = {}
+		tmp_order_list[0] = "Add"
+		tmp_order_list[1] = "Search"
+	
+		submenu_order["Projects"] = tmp_order_list
+	
+		tmp_list = {}
+		tmp_list["Add"] = "../Project.php?View=1"
+		tmp_list["Search"] = "../Project.php?View=2"
+		submenu_links["Projects"] = tmp_list
+	
+		tmp_list = {}
+		tmp_list["Add"] = "Add projects"
+		tmp_list["Search"] = "Search projects"
+		menuitems["Projects"] = tmp_list
+
+		# Users and Labs
+		currentSectionNames.append("User Management")
+		currentSectionLinks["User Management"] = "../User.php"
+		menuTypes["User Management"] = "User"
+
+		currentSectionNames.append("Lab Management")
+		currentSectionLinks["Lab Management"] = "../User.php"
+		menuTypes["Lab Management"] = "Laboratories"
+
+		tmp_order_list = {}
+		tmp_order_list[0] = "Add"
+		tmp_order_list[1] = "Search"
+	
+		submenu_order["Laboratories"] = tmp_order_list
+	
+		# Jan. 7/09: Chemicals
+		currentSectionNames.append("Chemical Tracker")
+		currentSectionLinks["Chemical Tracker"] = "../Chemical.php?View=1"
+		menuTypes["Chemical Tracker"] = "Chemical"
+		
+		# Feb. 2, 2010
+		tmp_list = []
+		tmp_list.append("Chemicals")
+		submenu_types["Chemical Tracker"] = tmp_list
+		
+		tmp_order_list = {}
+		tmp_order_list[0] = "Add"
+		tmp_order_list[1] = "Search"
+	
+		submenu_order["Chemicals"] = tmp_order_list
+	
+		tmp_list = {}
+		tmp_list["Add"] = "../Chemical.php?View=2"
+		tmp_list["Search"] = "../Chemical.php?View=1"
+		submenu_links["Chemicals"] = tmp_list
+		
+		tmp_list = {}
+		tmp_list["Add"] = "Add Chemicals"
+		tmp_list["Search"] = "Search Chemicals"
+		menuitems["Chemicals"] = tmp_list
+
+		# Feb. 2/10
+		tmp_list = []
+		tmp_list.append("Users")
+		submenu_types["User Management"] = tmp_list
+
+		tmp_list = {}
+		tmp_list["Add"] = "../User.php?View=1"
+		tmp_list["Search"] = "../User.php?View=2"
+		tmp_list["Change your password"] = "../User.php?View=6"
+		tmp_list["Personal page"] = "../User.php?View=7"
+		tmp_list["View your orders"] = "../User.php?View=8"
+		submenu_links["Users"] = tmp_list
+	
+		tmp_order_list = {}
+		tmp_order_list[0] = "Add"
+		tmp_order_list[1] = "Search"
+		tmp_order_list[2] = "Change your password"
+		tmp_order_list[3] = "Personal page"
+		tmp_order_list[4] = "View your orders"
+		
+		submenu_order["Users"] = tmp_order_list
+	
+		tmp_list = {}
+		tmp_list["Add"] = "Add users"
+		tmp_list["Search"] = "Search users"
+		tmp_list["Change your password"] = "Change your password"
+		tmp_list["Personal page"] = "Personal page"
+		tmp_list["View your orders"] = "View your orders"
+		menuitems["Users"] = tmp_list
+		
+		tmp_list = []
+		tmp_list.append("Laboratories")
+		submenu_types["Lab Management"] = tmp_list
+		
+		tmp_list = {}
+		tmp_list["Add"] = "../User.php?View=3"
+		tmp_list["Search"] = "../User.php?View=4"
+		submenu_links["Laboratories"] = tmp_list
+		
+		tmp_order_list = {}
+		tmp_order_list[0] = "Add"
+		tmp_order_list[1] = "Search"
+		submenu_order["Laboratories"] = tmp_order_list
+		
+		tmp_list = {}
+		
+		tmp_list["Add"] = "Add laboratories"
+		tmp_list["Search"] = "Search laboratories"
+		menuitems["Laboratories"] = tmp_list
+
+		currentSectionNames.append("Documentation")
+		currentSectionLinks["Documentation"] = "../docs.php"
+		publicSections["Documentation"] = "docs.php"
+
+ 		currentSectionNames.append("Terms and Conditions")
+ 		currentSectionLinks["Terms and Conditions"] = "../copyright.php"
+		publicSections["Terms and Conditions"] = "copyright.php"
+
+		currentSectionNames.append("Help and Support")
+ 		currentSectionLinks["Help and Support"] = "../bugreport.php"
+		publicSections["Help and Support"] = "bugreport.php"
+
+ 		currentSectionNames.append("Contact Us")
+ 		currentSectionLinks["Contact Us"] = "../contacts.php"
+		publicSections["Contact Us"] = "contacts.php"
+		
+		# Aug. 20/10: Quick links
+		
+		tmp_ql = []
+		quickLinks = {}
+
+		tmp_ql.append("Add reagents")
+		tmp_ql.append("Search reagents")
+
+		quickLinks["Reagent Tracker"] = tmp_ql
+		
+		tmp_ql = []
+		
+		tmp_ql.append("Add containers")
+		tmp_ql.append("Search containers")
+	
+		quickLinks["Location Tracker"] = tmp_ql
+		
+		tmp_ql = []
+		
+		tmp_ql.append("Add projects")
+		tmp_ql.append("Search projects")
+		
+		quickLinks["Project Management"] = tmp_ql
+		
+		tmp_ql = []
+		
+		tmp_ql.append("Change your password")
+		tmp_ql.append("View your orders")
+		
+		quickLinks["User Management"] = tmp_ql
+		
+		content = '''
+			<div class="sidemenu" ID="mainMenu">
+				<div class="menu-content">
+					<ul class="menulist">
+						<!-- menu goes here -->
+						'''
+		
+		# Output the menu link IFF the user is authorized to access that page
+		currUser = Session.getUser()
+
+		if currUser:
+			ucMapper = UserCategoryMapper(db, cursor)
+			category_Name_ID_Map = ucMapper.mapCategoryNameToID()
+			currUserCategory = category_Name_ID_Map[currUser.getCategory()]
+			
+			#print "Content-type:text/html"
+			#print
+			allowedSections = uHandler.getAllowedSections(currUserCategory)
+			#print `allowedSections`
+			
+			for name in currentSectionNames:
+				
+				if name in allowedSections:
+					
+					# added Jan. 7/09
+					if name in menuTypes:
+						#print "Content-type:text/html"
+						#print
+						#print name
+						
+						content += "<DIV style=\"border-top:3px double #FFF8DC; border-right:6px double #FFF8DC; border-bottom:3px double #FFF8DC; border-left:6px double #FFF8DC; margin-top:2px; width:162px; padding-top:5px; padding-bottom:0;\">"
+						
+						content += "<DIV style=\"background-image:url('../pictures/small_bg.png'); width:166px; height:30px;\">"
+						
+						content += "<select style=\"cursor:pointer; width:150px; background:#FFF8DC; font-weight:bold; color:#555; font-size:9pt; margin-top:3px; margin-left:2px;  font-family:Helvetica; border:0;\" onChange=\"openPage(this.options[this.options.selectedIndex]);\">"
+						
+						content += "<option selected style=\"cursor:pointer; font-weight:bold; color:#555; font-size:9pt; border:0; font-family:Helvetica;\" value=\"\"> " + name + "</option>"
+						
+						for st_val in submenu_types[name]:
+							numDisallowed = 0
+							
+							# Jan. 13, 2010: Don't print category heading if user has no access to any of its subitems
+							for s_ord in submenu_order[st_val]:
+								linkName = submenu_order[st_val][s_ord]
+								linkURL = submenu_links[st_val][linkName]
+								
+								if not menuitems[st_val][linkName] in allowedSections:
+									numDisallowed += 1
+							
+							if numDisallowed == len(submenu_links[st_val]):
+								continue
+							
+							#print st_val.upper()
+							content += "<option style=\"cursor:pointer; font-weight:bold; color:#555; background:#EFEFEF; font-size:9pt; border:0; font-family:Helvetica;\" onclick\"\"> " + st_val.upper() + "</option>"
+						
+							# Now: since Python dictionaries are not ordered, arrays with > 2 items (e.g. Users - has more than 'add' and 'search') would appear scrambled.  Use an 'order' array instead
+							for s_ord in submenu_order[st_val]:
+								
+								linkName = submenu_order[st_val][s_ord]
+								linkURL = submenu_links[st_val][linkName]
+								
+								#print st_val
+								#print linkName
+								
+								if menuitems[st_val][linkName] in allowedSections:
+
+									content += "<option style=\"padding-left:15px; font-weight:bold; color:#555; font-size:8pt; border:0; font-family:Helvetica; cursor:pointer;\" value=\"" + linkURL + "\">   " + linkName + "</option>"
+							
+						content += "</SELECT>"
+						
+						content += "</DIV>"
+						
+						# Quick links
+						if quickLinks.has_key(name):
+							content += "<div id=\"quick_links_" + name + "\" style=\"font-family:Helvetica; width:166px; padding-bottom:0; margin-top:0; padding-top:0; padding-left:2px;\">"
+							
+							content += "<UL style=\"padding-bottom:2px; padding-top:2px; padding-left:10px; position:relative;\">"
+							
+							for qlName in quickLinks[name]:
+							
+								if qlName in allowedSections:
+								
+									content += "<LI style=\"list-style:none;\"><img  src=\"../pictures/silvermenubullet.png\" width=\"7\" height=\"6\" style=\"padding-bottom:2px;\"> <a style=\"font-weight:bold; font-size:8pt; font-family:Helvetica; text-decoration:none; color:#555; margin-left:2px;\" href=\"../" + pageLinkMap[qlName] + "\">" + qlName + "</a></LI>"
+							
+							content += "</UL>"
+							
+							content += "</DIV>"
+
+						content += "</DIV>"
+					else:
+						if name == "Home":
+							content += "<DIV style=\"background:url('../pictures/small_bg.png') repeat-y; padding-top:7px; margin-top:0; width:162px; border-top:6px double #FFF8DC; border-left:6px double #FFF8DC; border-right:6px double #FFF8DC; padding-bottom:8px;\">"
+
+						else:
+							content += "<DIV style=\"background:url('../pictures/small_bg.png') repeat-y; padding-top:7px; margin-top:2px; width:162px; border-left:6px double #FFF8DC; border-right:6px double #FFF8DC; padding-bottom:8px;\">"
+
+						content += "<img src=\"../pictures/silvermenubullet.png\" style=\"width:11px; height:9px; margin-left:5px;\">"
+
+						content += "<a style=\"font-weight:bold; color:#555; font-size:9pt; padding-left:3px; text-decoration:none;\" href=\"" + currentSectionLinks[name] + "\">" + name + "</a>"
+						
+						content += "</DIV>"
+		else:
+			# WRITE THIS FUNCTION!!!!!!!!!!
+			#content += self.printGeneralMenu(publicSections)
+			print "Content-type:text/html"
+			print
+			print "Unknown user"
+		
+		content += '''
+					</UL>
+				
+					<!-- moved form down here on Aug. 20, 2010 -->
+					<form name="curr_user_form" style="display:none" method="post" action="user_request_handler.py">"
+					'''
+
+		content += "<INPUT type=\"hidden\" ID=\"curr_username_hidden\" NAME=\"curr_username\" VALUE=\"" + currUser.getFullName() + "\">"
+		
+		content += "<INPUT TYPE=\"hidden\" id=\"curr_user_hidden\" name=\"view_user\" VALUE=\"" + `currUser.getUserID()` + "\">"
+		
+		content += '''
+					</FORM>
+				
+					<div class="login">
+					'''
+
+		content += self.printLoginBlock()
+		content += '''
+					</div>
+				</div>
+			</div>
+			'''
+			
+		return content
+
+
+	def printSubmenuHeader(self, submenu_type):
+		
+		dbConn = DatabaseConn()
+		hostname = dbConn.getHostname()		# to define form action URL
+		
+		db = dbConn.databaseConnect()
+		cursor = db.cursor()
+
+		uHandler = UserHandler(db, cursor)
+		
+		current_selection_names = []		# plain list of section names
+		current_selection_links = {}		# dictionary, where section names are keys and their URLs are values
+		
+		if submenu_type == "Location":
+
+			location_submenu_names = []
+			location_submenu_links = {}
+			
+			location_submenu_names.append("Add container types")
+			location_submenu_links["Add container types"] = "../Location.php?View=6&Sub=3"
+
+			location_submenu_names.append("Add container sizes")
+			location_submenu_links["Add container sizes"] = "../Location.php?View=6&Sub=1"
+
+			location_submenu_names.append("Add containers")
+			location_submenu_links["Add containers"] = "../Location.php?View=6&Sub=3"
+
+			location_submenu_names.append("Search containers")
+			location_submenu_links["Search containers"] = "../Location.php?View=2"
+
+			current_selection_names = location_submenu_names
+			current_selection_links = location_submenu_links
+
+		elif submenu_type == "Reagent":
+
+			reagent_submenu_names = []
+			reagent_submenu_links = {}
+
+			reagent_submenu_names.append("Add reagents")
+			reagent_submenu_links["Add reagents"] = "../Reagent.php?View=2"
+
+			reagent_submenu_names.append("Search reagents")
+			reagent_submenu_links["Search reagents"] = "../search.php?View=1"
+
+			# June 3/09
+			reagent_submenu_names.append("Add reagent types")
+			reagent_submenu_links["Add reagent types"] = "../Reagent.php?View=3"
+			
+			reagent_submenu_names.append("Search reagent types")
+			reagent_submenu_links["Search reagent types"] = "../Reagent.php?View=5"
+			
+			current_selection_names = reagent_submenu_names
+			current_selection_links = reagent_submenu_links
+
+		elif submenu_type == "Chemical":
+			
+			chemical_submenu_names = []
+			chemical_submenu_links = {}
+			
+			chemical_submenu_names.append("Add Chemicals")
+			chemical_submenu_links["Add Chemicals"] = "../Chemical.php?View=2"
+			
+			chemical_submenu_names.append("Search Chemicals")
+			chemical_submenu_links["Search Chemicals"] = "../Chemical.php?View=1"
+			
+			current_selection_names = chemical_submenu_names
+			current_selection_links = chemical_submenu_links
+			
+		elif submenu_type == "Prediction":
+			
+			prediction_submenu_names = []
+			prediction_submenu_links = {}
+			
+			prediction_submenu_names.append("Search predictions")
+			prediction_submenu_links["Search predictions"] = "../Prediction.php?View=1"
+
+			current_selection_names = prediction_submenu_names
+			current_selection_links = prediction_submenu_links
+	
+		elif submenu_type == "Project":	
+
+			project_submenu_names = []
+			project_submenu_links = {}
+			
+			project_submenu_names.append("Add projects")
+			project_submenu_links["Add projects"] = "../Project.php?View=1"
+
+			project_submenu_names.append("Search projects")
+			project_submenu_links["Search projects"] = "../Project.php?View=2"
+
+			current_selection_names = project_submenu_names
+			current_selection_links = project_submenu_links
+
+		elif submenu_type == "User":
+
+			user_submenu_names = []
+			user_submenu_links = {}
+			
+			user_submenu_names.append("Add users")
+			user_submenu_links["Add users"] = "../User.php?View=1"
+
+			user_submenu_names.append("Search users")
+			user_submenu_links["Search users"] = "../User.php?View=2"
+
+			user_submenu_names.append("Change your password")
+			user_submenu_links["Change your password"] = "../User.php?View=6"
+
+			user_submenu_names.append("Personal page")
+			user_submenu_links["Personal page"] = "User.php?View=7"
+			
+			user_submenu_names.append("View your orders")
+			user_submenu_links["View your orders"] = "../User.php?View=8"
+			
+			current_selection_names = user_submenu_names
+			current_selection_links = user_submenu_links
+
+		elif submenu_type == "Lab":
+
+			lab_submenu_names = []
+			lab_submenu_links = {}
+			
+			lab_submenu_names.append("Add laboratories")
+			lab_submenu_links["Add laboratories"] = "../User.php?View=3"
+
+			lab_submenu_names.append("Search laboratories")
+			lab_submenu_links["Search laboratories"] = "../User.php?View=4"
+
+			current_selection_names = lab_submenu_names
+			current_selection_links = lab_submenu_links
+
+
+		# There can be permission differentiations within a menu section as well (e.g. Projects - only Creators can create, buit Writers can view)
+		currUser = Session.getUser()
+
+		ucMapper = UserCategoryMapper(db, cursor)
+		category_Name_ID_Map = ucMapper.mapCategoryNameToID()
+
+		currUserCategory = category_Name_ID_Map[currUser.getCategory()]
+		allowedSections = uHandler.getAllowedSections(currUserCategory)
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `allowedSections`
+
+		content = ""
+
+		for name in current_selection_names:
+		
+			if name in allowedSections:
+				
+				if name == 'Personal page':
+					content += "<LI class=\"submenu\">"
+					
+					content += "<IMG SRC=\"../pictures/star_bullet.gif\" WIDTH=\"10\" HEIGHT=\"10\" BORDER=\"0\" ALT=\"plus\" class=\"menu-leaf\">"
+
+					content += "<span class=\"linkShow\" style=\"font-size:9pt\" onClick=\"redirectToCurrentUserDetailedView(" + `currUser.getUserID()` +  ");\">" + name + "</span>"
+
+					content += "</LI>"
+
+					content += "<form name=\"curr_user_form\" style=\"display:none\" method=\"post\" action=\"user_request_handler.py\">"
+					
+					content += "<INPUT type=\"hidden\" ID=\"curr_username_hidden\" NAME=\"curr_username\" VALUE=\"" + currUser.getFullName() + "\">"
+					
+					content += "<INPUT type=\"hidden\" id=\"curr_user_hidden\" name=\"view_user\">"
+					content += "</FORM>"
+				else:
+					content += "<LI class=\"submenu\">"
+	
+					content += "<IMG SRC=\"../pictures/star_bullet.gif\" WIDTH=\"10\" HEIGHT=\"10\" BORDER=\"0\" ALT=\"plus\" class=\"menu-leaf\">"
+	
+					content += "<a class=\"submenu\" href=\"" + current_selection_links[name] + "\">" + name + "</a>"
+					content += "</LI>"
+				
+		return content		
+
+
+	# Output login prompt or welcome block
+	def printLoginBlock(self):
+		content = ""
+		
+		currUser = Session.getUser()
+		
+		if currUser:
+			uDescr = currUser.getDescription()
+			
+			content += "<FORM name=\"login_form\" METHOD=POST ACTION=\"../index.php\" style=\"float:left; white-space:nowrap;\">"
+			content += "Welcome <span style=\"color:#FF0000\">" + uDescr + "</span>"
+			content += "<P><INPUT TYPE=SUBMIT NAME=\"logoutsubmit\" VALUE=\"Logout\" style=\"font-size:12px; elevation:above\"></P></FORM>"
+
+		else:
+			content += "<FORM name=\"logout_form\" METHOD=POST ACTION="">"
+			
+			content += '''
+					<P class="login">To view additional sections of the website, please log in:</P>
+
+					Username:<BR/> 
+					<INPUT type="text" value="" name="loginusername_field" size="13"><BR/>
+
+					Password:<BR/> 
+					<INPUT type="password" value="" name="loginpassword_field" size="13">
+
+					<P>Automatic Login <INPUT type="checkbox" value="" name="persistentlogin_field"></P>
+
+					<INPUT TYPE="submit" NAME="loginsubmit" VALUE="Login" style="font-size:12px; elevation:above">		
+			</FORM>
+			'''
+			
+		return content
+		
diff --git a/OpenFreezer/cgi/graphics_handler.py b/OpenFreezer/cgi/graphics_handler.py
new file mode 100755
index 0000000..d1af0bd
--- /dev/null
+++ b/OpenFreezer/cgi/graphics_handler.py
@@ -0,0 +1,56 @@
+#!/usr/local/bin/python
+
+import reportlab
+import math
+import random
+
+from reportlab.pdfgen import canvas, pathobject
+from reportlab.pdfgen.canvas import *
+from reportlab.pdfgen.pathobject import *
+
+from reportlab.graphics import renderPDF
+from reportlab.graphics.shapes import *
+
+from reportlab.lib.units import cm
+from reportlab.lib.colors import *
+
+import cgi
+import cgitb; cgitb.enable()
+
+import MySQLdb
+import sys
+import os
+import stat
+import string
+import utils
+
+def getNextColor(colorsList):
+	
+	allColors = colors.getAllNamedColors()
+	#print `allColors`
+	i = 0
+	fColors = allColors.values()
+	
+	for fColor in fColors:
+		color = fColor.hexval()
+		
+		if not color in colorsList:
+			#print color
+			return color	# just return next unused color in sequence
+		
+def getAllColors():
+	#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+	#print					# DITTO
+	
+	allColors = colors.getAllNamedColors()
+	#print `allColors`
+	i = 0
+	fColors = allColors.values()
+	#print `fColors`
+	hexColors = []
+	
+	for fColor in fColors:
+		color = fColor.hexval()
+		hexColors.append(color)
+		
+	return hexColors
\ No newline at end of file
diff --git a/OpenFreezer/cgi/lab_handler.py b/OpenFreezer/cgi/lab_handler.py
new file mode 100755
index 0000000..693003e
--- /dev/null
+++ b/OpenFreezer/cgi/lab_handler.py
@@ -0,0 +1,414 @@
+#################################################################################################
+# This module serves as an intermediate layer between the database and Laboratory module objects
+#
+# Written: May 25, 2007, by Marina Olhovsky
+# Last modified: July 5, 2007
+#################################################################################################
+
+import MySQLdb
+import utils
+
+from general_handler import GeneralHandler
+from comment_handler import CommentHandler
+from user_handler import UserHandler
+
+from laboratory import Laboratory
+from user import User
+
+from exception import *
+from mapper import UserCategoryMapper
+
+class LabHandler(GeneralHandler):
+	
+	def __init__(self, db, cursor):
+		super(LabHandler, self).__init__(db, cursor)
+
+
+	# Insert lab details into the database and return the new lab ID
+	def insertLab(self, labName, labDescr, access, address, labHead, labCode):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		if not self.existsLabCode(0, labCode):
+			
+			cursor.execute("INSERT INTO LabInfo_tbl(lab_name, description, default_access_level, location, lab_head, labCode) VALUES(" + `labName` + ", " + `labDescr` + ", " + `address` + ", " + `access` + ", " + `labHead` + ", " + `labCode` + ")")
+			labID = int(db.insert_id())
+		
+		else:
+			raise DuplicateLabCodeException()
+			
+		return labID
+		
+
+	def existsLab(self, labName, labHead, labCode):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT * FROM LabInfo_tbl WHERE lab_name=" + `labName` + " AND lab_head=" + `labHead` + " AND labCode=" + `labCode` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		if results:
+			return True
+		
+		return False
+		
+	
+	# labID: Either 0 or actual lab ID - differentiate between creation and modification; 0 means we're on creation view and just want to check if the code is taken.  Otherwise compare the labID and labcode together, make sure you're not assigning another lab's code to this lab during modification.
+	def existsLabCode(self, labID, labCode):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		if labID == 0:
+			cursor.execute("SELECT * FROM LabInfo_tbl WHERE labCode=" + `labCode` + " AND status='ACTIVE'")
+		else:
+			cursor.execute("SELECT * FROM LabInfo_tbl WHERE labID <> " + `labID` + " AND labCode=" + `labCode` + " AND status='ACTIVE'")
+			
+		results = cursor.fetchall()
+		
+		if results:
+			return True
+		
+		return False
+
+
+	# Fetch all information about the lab identified by labID, and return a Lab object
+	def findLabByID(self, labID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		ucMapper = UserCategoryMapper(db, cursor)
+		category_ID_Name_Map = ucMapper.mapCategoryIDToName()
+		
+		cursor.execute("SELECT lab_name, description, default_access_level, location, lab_head, labCode FROM LabInfo_tbl WHERE labID=" + `labID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		if result:
+			labName = result[0]
+			labDescr = result[1]
+			accessLevel = int(result[2])
+			address = result[3]
+			labHead = result[4]
+			labCode = result[5].upper()
+
+			newLab = Laboratory(labID, labName, labDescr, category_ID_Name_Map[accessLevel], address, labHead, labCode)
+
+			return newLab
+
+	# Check if a member exists in a given lab
+	def existsMember(self, labID, memberID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT * FROM Users_tbl WHERE labID=" + `labID` + " AND userID=" + `memberID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+				
+		if result:
+			return True
+		else:
+			return False
+		
+	
+	# Fetch the list of all laboratories that use OpenFreezer
+	# Edited July 3/07: Add 'accessLevel' parameter to restrict project access
+	# accessLevel: String (e.g. Reader, Writer)
+	# return a dictionary containing (labID, labName) tuples
+	def findAllLabs(self, accessLevel="", oper="="):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		ucMapper = UserCategoryMapper(db, cursor)
+		category_Name_ID_Map = ucMapper.mapCategoryNameToID()
+		
+		labs = {}	# labID, labName
+		
+		if accessLevel != "":
+			cursor.execute("SELECT labID, lab_name FROM LabInfo_tbl l, UserCategories_tbl c WHERE c.categoryID " + oper + `category_Name_ID_Map[accessLevel]` + " AND l.default_access_level=c.categoryID AND l.status='ACTIVE' ORDER BY lab_name")
+		else:
+			cursor.execute("SELECT labID, lab_name FROM LabInfo_tbl WHERE status='ACTIVE'")
+			
+		results = cursor.fetchall()
+		
+		for result in results:
+			labID = int(result[0])
+			labName = result[1]
+			
+			labs[labID] = labName
+			
+		return labs
+
+
+	# Find the name of the lab identified by labID
+	def findLabName(self, labID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		labName = ""
+		
+		cursor.execute("SELECT lab_name FROM LabInfo_tbl WHERE labID=" + `labID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			labName = result[0]
+		
+		return labName
+
+
+	# Opposite: Find the ID of a lab, given its name
+	def findLabID(self, labName):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		labID = 0
+
+		cursor.execute("SELECT labID FROM LabInfo_tbl WHERE lab_name=" + `labName` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			labID = int(result[0])
+		
+		return labID
+
+
+	# Fetch the 2-letter unique code identifier for the lab (used in plate creation but defined here since it's stored in LabInfo_tbl)
+	def findLabCode(self, labID):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT labCode FROM LabInfo_tbl WHERE labID=" + `labID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0].upper()
+		
+		return ""
+	
+	
+	# Find the members of this laboratory
+	# Returns a list of User instances
+	def findMembers(self, labID):
+	
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+	
+		db = self.db
+		cursor = self.cursor
+		
+		tmpLab = self.findLabByID(labID)
+		members = []
+
+		cursor.execute("SELECT userID, username, firstname, lastname, description, category, email FROM Users_tbl WHERE labID=" + `labID` + " AND status='ACTIVE' AND length(description) > 0 ORDER BY description")
+		results = cursor.fetchall()
+
+		for result in results:
+			memberID = int(result[0])
+			username = result[1]
+			firstName = result[2]
+			lastName = result[3]
+			description = result[4]
+			category = result[5]
+			email = result[6]
+			
+			tmpUser = User(memberID, username, firstName, lastName, description, tmpLab, category, email)
+			members.append(tmpUser)
+
+		return members
+
+
+	# Find what default access level (Reader, Writer, Admin) members of this lab have to OpenFreezer
+	def findDefaultAccessLevel(self, labID):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		defaultAccessLevel = ""
+		
+		cursor.execute("SELECT default_access_level FROM LabInfo_tbl WHERE labID=" + `labID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			defaultAccessLevel = int(result[0])
+		
+		return defaultAccessLevel
+
+
+	# Find the address ('location' column) of labID
+	def findLabAddress(self, labID):
+	
+		db = self.db
+		cursor = self.cursor
+
+		location = ""
+		
+		cursor.execute("SELECT location FROM LabInfo_tbl WHERE labID=" + `labID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			location = result[0]
+			
+		return location
+		
+		
+	def findLabHead(self, labID):
+		
+		db = self.db
+		cursor = self.cursor
+
+		labHead = ""
+		
+		cursor.execute("SELECT lab_head FROM LabInfo_tbl WHERE labID=" + `labID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			labHead = result[0]
+			
+		return labHead
+		
+
+	####################################################
+	# UPDATE FUNCTIONS
+	####################################################
+	
+	# Set the name of the lab identified by labID to newName
+	def setLabName(self, labID, newName):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE LabInfo_tbl SET lab_name=" + `newName` + " WHERE labID=" + `labID` + " AND status='ACTIVE'")
+		
+	
+	# Set the name of the lab head for the lab identified by labID
+	def setLabHead(self, labID, newLabHead):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE LabInfo_tbl SET lab_head=" + `newLabHead` + " WHERE labID=" + `labID` + " AND status='ACTIVE'")
+		
+	
+	def setLabCode(self, labID, newLabCode):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		if not self.existsLabCode(labID, newLabCode):
+			cursor.execute("UPDATE LabInfo_tbl SET labCode=" + `newLabCode` + " WHERE labID=" + `labID` + " AND status='ACTIVE'")
+		else:
+			raise DuplicateLabCodeException()
+		
+		
+	# Change the description of labID
+	def setLabDescription(self, labID, newDescr):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE LabInfo_tbl SET description=" + `newDescr` + " WHERE labID=" + `labID` + " AND status='ACTIVE'")
+		
+	
+	# Change the default access level for labID
+	# newAccLev is an INTEGER categoryID that needs to be mapped to its text value
+	def setLabAccessLevel(self, labID, newAccLev):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE LabInfo_tbl SET default_access_level=" + `newAccLev` + " WHERE labID=" + `labID` + " AND status='ACTIVE'")
+
+
+	def setLocation(self, labID, newLocn):		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE LabInfo_tbl SET location=" + `newLocn` + " WHERE labID=" + `labID` + " AND status='ACTIVE'")
+
+		
+	def deleteLab(self, labID):
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE LabInfo_tbl SET status='DEP' WHERE labID=" + `labID` + " AND status='ACTIVE'")
+
+
+	# Delete a member - Complete deletion, set status to DEP
+	def deleteMember(self, labID, memberID):
+		db = self.db
+		cursor = self.cursor
+		
+		uHandler = UserHandler(db, cursor)
+		uHandler.deleteUser(memberID)
+
+		#cursor.execute("UPDATE Users_tbl SET labID='0' WHERE labID=" + `labID` + " AND userID=" + `memberID` + " AND status='ACTIVE'")
+
+
+	# Delete all members from this lab - see comments for deleteMember
+	def deleteAllMembers(self, labID):		
+		db = self.db
+		cursor = self.cursor
+		
+		uHandler = UserHandler(db, cursor)
+		
+		members = self.findMembers(labID)
+		
+		for mem in members:
+			memID = mem.getUserID()	
+			uHandler.deleteUser(memID)
+			
+		#cursor.execute("UPDATE Users_tbl SET labID='0' WHERE labID=" + `labID` + " AND status='ACTIVE'")
+		
+		
+	# Add a member to a lab
+	# Assume member exists in the system (an ACTIVE entry exists in Users_tbl, its labID needs to be set to 'labID' argument value)
+	# However, verify that the member exists just in case
+	def addLabMember(self, labID, memberID):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		uHandler = UserHandler(db, cursor)
+		
+		if uHandler.existsUser(memberID):
+			cursor.execute("UPDATE Users_tbl SET labID=" + `labID` + " WHERE userID=" + `memberID` + " AND status='ACTIVE'")
+				
+	
+	# This function is called upon exit from Modify view to update the list of existing lab members - mainly to remove members from that list
+	# newMembers: list of user IDs, BUT they arrive as STRINGS!!!!!!!!!!  Must be cast to INT
+	def updateLabMembers(self, labID, newMembers):
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		
+		db = self.db
+		cursor = self.cursor
+		
+		uHandler = UserHandler(db, cursor)
+			
+		# Find out which members in old members list are not in new members list and delete them	
+		oldMembers = self.findMembers(labID)
+				
+		# fetch the IDs of members in oldMembers (a list of User objects)
+		oldMemIDs = []
+		
+		for m in oldMembers:
+			oldMemIDs.append(m.getUserID())
+				
+		# Cast each element in newMembers to INT
+		newMemIDs = []
+		
+		for n in newMembers:
+			newMemIDs.append(int(n))
+		
+		memDel = utils.diff(oldMemIDs, newMemIDs)
+		
+		for memID in memDel:
+			#self.deleteMember(labID, memID)
+			uHandler.deleteUser(memID)
diff --git a/OpenFreezer/cgi/laboratory.py b/OpenFreezer/cgi/laboratory.py
new file mode 100755
index 0000000..1ad30e2
--- /dev/null
+++ b/OpenFreezer/cgi/laboratory.py
@@ -0,0 +1,97 @@
+#################################################################################################
+# This module represents laboratories that utilize OpenFreezer as their LIMS system
+#
+# Written: May 25, 2007, by Marina Olhovsky
+# Last modified: July 5, 2007
+#################################################################################################
+class Laboratory:
+
+	__id = 0
+	__name = ""
+	__description = ""
+	__default_access_level = "Reader"
+	__address = ""
+	__labHead = ""
+	__labCode = ""
+	__members = []		# list of User instances
+	
+	
+	##################################
+	# Constructor
+	##################################
+	
+	# Initialize all instance variables - some may be blank by default
+	def __init__(self, lID=0, name="", descr="", accLev="", addr="", lab_head="", lab_code = "", members=[]):
+		self.__id = lID
+		self.__name = name
+		self.__description = descr
+		self.__default_access_level = accLev
+		self.__address = addr
+		self.__labHead = lab_head
+		self.__labCode = lab_code
+		self.__members = members
+
+
+	############################
+	# Assignment methods
+	############################
+
+	def setName(self, name):
+		self.__name = name
+		
+		
+	def setDescription(self, descr):
+		self.__description = descr
+		
+		
+	def setAddress(self, addr):
+		self.__address = addr
+				
+	
+	def setDefaultAccessLevel(self, accLev):
+		self.__default_access_level = accLev
+	
+	def setLabHead(self, labHead):
+		self.__labHead = labHead
+		
+	def setLabCode(self, labCode):
+		self.__labCode = labCode
+		
+	def setMembers(self, members):
+		self.__members = members
+		
+
+	############################
+	# Access methods
+	############################
+
+	def getName(self):
+		return self.__name
+		
+		
+	def getDescription(self):
+		return self.__description
+
+
+	def getAddress(self):
+		return self.__address
+
+
+	def getID(self):
+		return int(self.__id)
+	
+	
+	def getDefaultAccessLevel(self):
+		return self.__default_access_level
+	
+	
+	def getLabHead(self):
+		return self.__labHead
+	
+	
+	def getLabCode(self):
+		return self.__labCode
+	
+	
+	def getMembers(self):
+		return self.__members
diff --git a/OpenFreezer/cgi/location_database_handler.py b/OpenFreezer/cgi/location_database_handler.py
new file mode 100755
index 0000000..e0186b0
--- /dev/null
+++ b/OpenFreezer/cgi/location_database_handler.py
@@ -0,0 +1,1190 @@
+#!/usr/local/bin/python
+
+# python modules
+import cgi
+import cgitb; cgitb.enable()
+
+import SocketServer
+from SocketServer import BaseRequestHandler
+
+import MySQLdb
+
+import os
+import tempfile
+import stat
+import sys
+import string
+
+# Custom modules
+import utils
+
+from database_conn import DatabaseConn
+#from session import Session
+
+from container import Container
+from well import Well					# June 8, 2011
+from prep import PrepProperty				# June 9, 2011
+from general_handler import GeneralHandler
+from lab_handler import LabHandler
+
+from location_type_database_handler import LocationTypeHandler
+
+#################################################################################
+# Top-level abstraction for LocationHandler hierarchy; extends GeneralHandler
+#
+# Written September 18, 2007 by Marina Olhovsky
+# Last modified: Sept. 18/07
+#################################################################################
+
+class LocationHandler(GeneralHandler):
+	"Database handler functions to update information related to Containers"
+	
+	def __init__(self, db, cursor):
+		super(LocationHandler, self).__init__(db, cursor)
+
+	
+	####################################################################################################################################
+	# Insert a new Container_tbl entry into the database; also generate a barcode for that container
+	#
+	# Input: cLab: INT, represents **internal lab database ID**
+	# Return: new container database ID
+	#
+	# Note: Table and column naming conventions are not always obvious, for historical reasons.  Original names assigned to Container-related tables have been preserved in subsequent releases, but their meaning has since changed.  Current Container-related representations are:
+	#
+	# ContainerGroup_tbl: 
+	# 	Describes the type of reagents stored in the container, e.g. 'Vector', 'Insert', 'Oligo', 'Cell Lines'.  One exception is 'Glycerol Stock', which stores Vectors, but has been made into a separate container type category for easy viewing.
+	#
+	# ContainerTypeID_tbl: 
+	# 	Describes container **sizes** - e.g. '96-well plate', '81-slot box', '100-slot box', etc.
+	#
+	#
+	# At the time this function was written, table structure has been modified as follows:
+	#
+	# 'isolate_active' column has been removed from Container_tbl and added to ContainerGroup_tbl
+	# 'barcode' column was added to Container_tbl, to serve as as unique container identifier for OpenFreezer users
+	# 'storage_type' is an INT, representing locationID column in LocationTypes_tbl
+	#
+	# Written Sept. 18/07, by Marina Olhovsky
+	# Last modified: Jan. 3, 2010 by Marina
+	#
+	####################################################################################################################################
+	def insertContainer(self, contTypeID, cSize, cName, cDesc, cLab, storage_type, storage_name, storage_address, cont_shelf, cont_rack, cont_row, cont_col):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		ltHandler = LocationTypeHandler(db, cursor)
+		
+		# find 'container type' and 'container size' foreign keys
+		#contTypeID = ltHandler.containerTypeToID(cType)
+		cType = ltHandler.findContainerTypeName(contTypeID)
+		contSizeID = ltHandler.containerSizeToID(cSize)
+		
+		# find the next available number in this container group to assign to the new container
+		contNum = self.findNextContainerNumberInGroup(contTypeID)
+		
+		# check if this is an isolate active container
+		isoActive = ltHandler.isIsoActive(contTypeID)
+
+		# generate barcode
+		bcNum = self.findNextContainerBarcodeNumber(contTypeID, contSizeID, cLab)
+		barcode = self.generateBarcode(contTypeID, contSizeID, bcNum, cLab)
+		
+		cursor.execute("INSERT INTO Container_tbl(contGroupID, contTypeID, contGroupCount, name, container_desc, labID, barcode, location, locationName, address, shelf, rack, row_number, col_number) VALUES(" + `contTypeID` + ", " + `contSizeID` + ", " + `contNum` + ", " + `cName` + ", " + `cDesc` + ", " + `cLab` + ", " + `barcode` + ", " + `storage_type` + ", " + `storage_name` + ", " + `storage_address` + ", " + `cont_shelf` + ", " + `cont_rack` + ", " + `cont_row` + ", " + `cont_col` + ")")
+		
+		newContID = int(db.insert_id())
+		
+		# Store container-specific properties
+		nRows = ltHandler.findNumRows(contSizeID)
+		nCols = ltHandler.findNumCols(contSizeID)
+		
+		container = Container(cType, cSize, nRows, nCols, cName, cLab, cDesc)
+		
+		#props = container.getContainerProperties()
+		props = ltHandler.findContainerTypeProperties(contTypeID)
+		
+		#print "Content-type:text/html"
+		#print
+		#print storage_type
+		
+		#print `props`
+		self.insertContainerProperties(newContID, props)
+		
+		return newContID
+		
+	
+	# Find the type of container contID
+	# Returns: STRING, value of column contGroupName in ContainerGroup_tbl, which can be easily matched to groupID with the help of containerTypeToID function if necessary
+	def findContainerType(self, contID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT contGroupName FROM ContainerGroup_tbl g, Container_tbl c WHERE c.containerID=" + `contID` + " AND c.contGroupID=g.contGroupID AND c.status='ACTIVE' AND g.status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+			
+		return ""
+		
+
+	def findLocationTypeID(self, storage_type):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT locationTypeID FROM LocationTypes_tbl WHERE locationTypeName=" + `storage_type` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+		
+		return -1
+		
+	
+	# Dec. 21/09
+	# contFeatures is a list of property IDs
+	def addContainerTypeFeatures(self, contTypeID, contFeatures):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		for elTypeID in contFeatures:
+			cursor.execute("INSERT INTO ContainerTypeAttributes_tbl(containerTypeID, containerTypeAttributeID) VALUES(" + `contTypeID` + ", " + `elTypeID` + ")")
+	
+		
+	# Insert container-specific properties
+	def insertContainerProperties(self, contID, props):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		for pName in props:
+			elTypeID = self.getPrepElementTypeID(pName)
+			cursor.execute("INSERT INTO Prep_Req_tbl(prepElementTypeID, containerID, requirement) VALUES(" + `elTypeID` + ", " + `contID` + ", 'REQ')")
+	
+	
+	# Fetch the internal database IDs of container-specific properties, such as 'Method ID', 'Bacteria Strain', etc.
+	def getPrepElementTypeID(self, pName):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT elementTypeID FROM PrepElemTypes_tbl WHERE propertyName=" + `pName` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+		
+	
+	# Find the name of the given container
+	def findContainerName(self, contID):
+	
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT name FROM Container_tbl WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+		
+		return ""
+		
+		
+	# Find container description
+	def findContainerDescription(self, contID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT container_desc FROM Container_tbl WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+		
+		return ""
+		
+	
+	# Find the container's serial number in its group
+	# Returns: contGroupCount value
+	def findContainerNumber(self, contID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+	
+		cursor.execute("SELECT contGroupCount FROM Container_tbl WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			contNum = int(result[0])
+			
+		return contNum
+		
+	
+	# Find the highest number of containers of the given type
+	def findNextContainerNumberInGroup(self, cTypeID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		# initialize count to 1
+		nextContNum = 1
+		
+		cursor.execute("SELECT MAX(contGroupCount) FROM Container_tbl WHERE contGroupID=" + `cTypeID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			if result[0]:
+				nextContNum = int(result[0]) + 1
+			else:
+				nextContNum = 1
+		else:
+			nextContNum = 1
+			
+		return nextContNum
+		
+	
+	# Find the lab ID of the given container
+	def findContainerLabID(self, contID):
+	
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT labID FROM Container_tbl WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+		
+		return 0
+		
+		
+	############################################################################################################################
+	# Generate a barcode for a plate with the given parameters
+	#
+	# A barcode has the following format:
+	# 	2-letter lab code (e.g. PW, WR, GN, DN, etc.)
+	# 	Container size (number of wells/slots in the container - e.g. 96, 81, 100, etc.)
+	# 	2 letters representing container type (VE, GS, IN, OL, CL)
+	# 	Container number - integer - incremented by 1 every time you have the same reagent type (e.g., Vector), the same lab (eg Pawson), and the same number of samples (e.g., 96)
+	#
+	# Input:
+	# 	cType: INT, internal database identifier representing the container category (Vector, Insert, Glycerol Stock, etc.)
+	# 	cSize: INT, internal database identifier representing the container type (96-well plate, 81-slot box, etc.)
+	# 	contNum: INT, the serial number of the container within that category
+	# 	cLab: INT, the internal database identifier of the lab that owns the container
+	#
+	# Output: STRING
+	############################################################################################################################
+	def generateBarcode(self, cTypeID, cSizeID, contNum, cLab):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		# Get the lab code that corresponds to lab ID
+		lHandler = LabHandler(db, cursor)
+		labCode = lHandler.findLabCode(cLab)
+		
+		ltHandler = LocationTypeHandler(db, cursor)
+		
+		# Find the container size
+		contSize = ltHandler.findNumContainerSamples(cSizeID)
+		
+		# Find the container group code
+		contTypeCode = ltHandler.findContainerTypeCode(cTypeID)
+
+		# Produce a string barcode
+		barcode = labCode + `contSize` + contTypeCode + `contNum`
+		
+		return barcode
+	
+	
+	# Find the highest number of containers of the given type, size and lab
+	def findNextContainerBarcodeNumber(self, cTypeID, cSizeID, cLab):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		nextNum = 0
+		
+		# Select all containers in the given category
+		cursor.execute("SELECT COUNT(containerID) FROM Container_tbl WHERE contGroupID=" + `cTypeID` + " AND contTypeID=" + `cSizeID` + " AND labID=" + `cLab` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		return int(result[0]) + 1
+		
+	
+	# Find the barcode value of a container
+	def findContainerBarcode(self, contID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT barcode FROM Container_tbl WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+		
+		return ""
+	
+	
+	# Update container properties
+	# Input:
+	# contType: STRING
+	# contSize: STRING
+	def updateContainerInfo(self, contID, contType, contSize, contName, contDesc, contLab, storage_type, storage_name, storage_address, cont_shelf, cont_rack, cont_row, cont_col):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		ltHandler = LocationTypeHandler(db, cursor)
+		
+		contTypeID = ltHandler.containerTypeToID(contType)
+		contSizeID = ltHandler.containerSizeToID(contSize)
+		
+		# Compare old container properties to new values and only update those that have actually changed
+		oldContType = self.findContainerType(contID)
+		oldContSize = self.findContainerSize(contID)
+		oldContName = self.findContainerName(contID)
+		oldContDesc = self.findContainerDescription(contID)
+		oldLabID = self.findContainerLabID(contID)
+		oldBarcode = self.findContainerBarcode(contID)
+		
+
+		# Update barcode IFF container type, lab or size were changed!!!!
+		if oldBarcode == '' or oldContType != contType or oldContSize != contSize or oldLabID != contLab:
+
+			# only in this case recompute barcode
+			contNum = self.findNextContainerBarcodeNumber(contTypeID, contSizeID, contLab)
+			
+			newBarcode = self.generateBarcode(contTypeID, contSizeID, contNum, contLab)
+			self.updateContainerBarcode(contID, newBarcode)
+		
+		# Update the rest of the container properties if old and new values differ:
+		if contType != oldContType:
+			self.updateContainerType(contID, contType)
+		
+		if contSize != oldContSize:
+			self.updateContainerSize(contID, contSize)
+		
+		if contName != oldContName:
+			self.updateContainerName(contID, contName)
+	
+		if contDesc != oldContDesc:
+			self.updateContainerDescription(contID, contDesc)
+		
+		if contLab != oldLabID:
+			self.updateContainerLab(contID, contLab)
+	
+		# NO.  Update Container page is different from Update Location.  This function is used to update container details - name, description, lab.  If user wants to move a container to a different fridge, they do so through Modify Location - that's a differnet function
+		#self.updateContainerLocation(contID, storage_type, storage_name, cont_shelf, cont_rack, cont_row, cont_col)
+		
+	
+	
+	# Find the container type and size (96-well plate, etc.)
+	def findContainerSize(self, contID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT t.containerName FROM Container_tbl c, ContainerTypeID_tbl t WHERE c.containerID=" + `contID` + " AND c.contTypeID=t.contTypeID AND c.status='ACTIVE' AND t.status='ACTIVE'")
+		
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+			
+	def updateContainerLocation(self, contID, storage_type, storage_name, storage_address, cont_shelf, cont_rack, cont_row, cont_col):
+		
+		oldStorageType = self.findContainerStorageTypeID(contID)
+		oldStorageName = self.findContainerStorageTypeName(contID)
+		oldStorageAddress = self.findContainerStorageAddress(contID)
+		oldShelf = self.findContainerShelf(contID)
+		oldRack = self.findContainerRack(contID)
+		oldRow = self.findContainerRow(contID)
+		oldColumn = self.findContainerColumn(contID)
+		
+		if oldStorageType != storage_type:
+			self.updateContainerStorageType(contID, storage_type)
+			
+		if oldStorageName != storage_name:
+			self.updateContainerStorageName(contID, storage_name)
+	
+		if oldStorageAddress != storage_address:
+			self.updateContainerStorageLocation(contID, storage_address)
+	
+		if oldShelf!= cont_shelf:
+			self.updateContainerShelf(contID, cont_shelf)
+			
+		if oldRack != cont_rack:
+			self.updateContainerRack(contID, cont_rack)
+	
+		if oldRow != cont_row:
+			self.updateContainerRow(contID, cont_row)
+	
+		if oldColumn != cont_col:
+			self.updateContainerColumn(contID, cont_col)
+			
+		
+	# Jan. 6, 2010: Returns INT corresponding to locationTypeID column value in Container_tbl
+	def findContainerStorageTypeID(self, contID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT location FROM Container_tbl WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+		
+		return 0
+		
+	
+	# Jan. 6, 2010
+	def findContainerStorageTypeName(self, contID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT locationName FROM Container_tbl WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+		
+		return None
+	
+	
+	# Jan. 6, 2010
+	def findContainerStorageAddress(self, contID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT address FROM Container_tbl WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+		
+		return None
+	
+	
+	# Jan. 6, 2010
+	def findContainerShelf(self, contID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT shelf FROM Container_tbl WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			try:
+				return int(result[0])
+			except TypeError:
+				return 0
+		
+		return 0
+	
+	
+	# Jan. 6, 2010
+	def findContainerRack(self, contID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT rack FROM Container_tbl WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			try:
+				return int(result[0])
+			except TypeError:
+				return 0
+		
+		return 0
+	
+	
+	# Jan. 6, 2010
+	def findContainerRow(self, contID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT row_number FROM Container_tbl WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			try:
+				return int(result[0])
+			except TypeError:
+				return 0
+		
+		return 0
+	
+	
+	# Jan. 6, 2010
+	def findContainerColumn(self, contID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT col_number FROM Container_tbl WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			try:
+				return int(result[0])
+			except TypeError:
+				return 0
+		
+		
+		return 0
+	
+	def updateContainerStorageType(self, contID, storageTypeID):	
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Container_tbl SET location=" + `storageTypeID` + " WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		
+	
+	def updateContainerStorageName(self, contID, storageName):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Container_tbl SET locationName=" + `storageName` + " WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+	
+	
+	def updateContainerStorageLocation(self, contID, storage_address):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Container_tbl SET address=" + `storage_address` + " WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+	
+	
+	def updateContainerShelf(self, contID, shelf):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Container_tbl SET shelf=" + `shelf` + " WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+	
+	
+	def updateContainerRack(self, contID, rack):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Container_tbl SET rack=" + `rack` + " WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+	
+	
+	def updateContainerRow(self, contID, row):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Container_tbl SET row_number=" + `row` + " WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+	
+	
+	def updateContainerColumn(self, contID, column):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Container_tbl SET col_number=" + `column` + " WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+	
+	
+	# Delete a particular container property (set corresponding column value to blank)
+	def deleteContainerProperty(self, contID, propColName):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Container_tbl SET " + propColName + " = '' WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+	
+	
+	# When container group is changed (an empty container is moved from Vectors to Inserts), update corresponding properties for this container type
+	def updateContainerProperties(self, contID, cType):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		# Clear current properties first
+		cursor.execute("UPDATE Prep_Req_tbl SET status='DEP' WHERE containerID='" + `contID` + "' AND status='ACTIVE'")
+		
+		container = Container(cType)
+		props = container.getContainerProperties()
+		
+		self.insertContainerProperties(contID, props)
+		
+	
+	# Change the type of a container
+	# Input: contType - STRING, verbal container type representation
+	def updateContainerType(self, contID, contType):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+	
+		ltHandler = LocationTypeHandler(db, cursor)
+		
+		contTypeID = ltHandler.containerTypeToID(contType)
+
+		# container number needs to be updated too, since the container was moved into a new group
+		contNum = self.findNextContainerNumberInGroup(contTypeID)
+		cursor.execute("UPDATE Container_tbl SET contGroupCount=" + `contNum` + " WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+
+		# AND container-type specific properties need to be changed too
+		self.updateContainerProperties(contID, contType)
+		
+		# Finally change container type
+		cursor.execute("UPDATE Container_tbl SET contGroupID=" + `contTypeID` + " WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		
+		
+	## Update the isolate active state of a container
+	#def updateIsoActive(self, contID, newIsoActive):
+		
+		#db = self.db
+		#cursor = self.cursor	# for easy access
+		
+		
+	# Change the size of a container
+	def updateContainerSize(self, contID, contSize):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		ltHandler = LocationTypeHandler(db, cursor)
+		
+		contSizeID = ltHandler.containerSizeToID(contSize)
+		
+		cursor.execute("UPDATE Container_tbl SET contTypeID=" + `contSizeID` + " WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		
+	
+	# Change the name of a container
+	def updateContainerName(self, contID, contName):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Container_tbl SET name=" + `contName` + " WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		
+		
+	# Change container description
+	def updateContainerDescription(self, contID, contDesc):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Container_tbl SET container_desc=" + `contDesc` + " WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+	
+	
+	# Change container's lab ID
+	def updateContainerLab(self, contID, contLab):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Container_tbl SET labID=" + `contLab` + " WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		
+		
+	# Change container's barcode
+	def updateContainerBarcode(self, contID, barcode):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Container_tbl SET barcode=" + `barcode` + " WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		
+	
+	# New Feb. 12/09: Add list of container features
+	def addContainerFeatures(self, contID, features):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		#print "Content-type:text/html"
+		#print
+		#print `newContFeatures`
+		
+		for f in features:
+			#print "SELECT elementTypeID FROM PrepElemTypes_tbl WHERE propertyName=" + `f`
+			cursor.execute("SELECT elementTypeID FROM PrepElemTypes_tbl WHERE propertyName=" + `f`)
+			result = cursor.fetchone()
+			
+			if result:
+				fNamePropID = int(result[0])
+			else:
+				# add this feature
+				cursor.execute("INSERT INTO PrepElemTypes_tbl(propertyName, PrepElementDesc) VALUES(" + `f` + ", " + `f` + ")")
+				fNamePropID = int(db.insert_id())
+				
+			cursor.execute("INSERT INTO Prep_Req_tbl(`prepElementTypeID`, `containerID`, `requirement`) VALUES(" + `fNamePropID` + ", " + `contID` + ", 'REQ')")
+			
+			
+	# June 8/09: Delete location of prep identified by expID
+	# Multi-step process:
+	#
+	# (->rID) delete from Experiment_tbl (->expID)
+	# 	(->expID) delete from Isolate_tbl (->isolate_pk)
+	# 		(->isolate_pk) delete from Prep_tbl (->wellID, ->prepID)
+	# 			(->wellID) delete from Wells_tbl
+	# 			(->prepID) delete from PrepElementProp_tbl
+	def deleteLocation(self, expID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		isolates = self.findIsolates(expID)
+		
+		for isolateID in isolates: 
+			preps = self.findPreps(isolateID)
+			
+			for prepID in preps:
+				wellID = self.findWellID(prepID)
+				
+				self.deleteWell(wellID)
+				self.deletePrepProperties(prepID)
+				self.deletePrep(prepID)
+				self.deleteIsolate(isolateID)
+				self.deleteExperiment(expID)
+			
+	
+	def findIsolates(self, expID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		isolates = []
+		
+		cursor.execute("SELECT isolate_pk FROM Isolate_tbl WHERE expID=" + `expID` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			isolates.append(int(result[0]))
+			
+		return isolates
+		
+	
+	def findPreps(self, isolateID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		preps = []
+		
+		cursor.execute("SELECT prepID FROM Prep_tbl WHERE isolate_pk =" + `isolateID` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			preps.append(int(result[0]))
+			
+		return preps
+		
+		
+	def findWellID(self, prepID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		wellID = 0
+		
+		cursor.execute("SELECT wellID FROM Prep_tbl WHERE prepID=" + `prepID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			wellID = int(result[0])
+			
+		return wellID
+		
+	
+	def deleteWell(self, wellID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Wells_tbl SET status='DEP' WHERE wellID=" + `wellID` + " AND status='ACTIVE'")
+		
+	
+	def deletePrep(self, prepID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Prep_tbl SET status='DEP' WHERE prepID=" + `prepID` + " AND status='ACTIVE'")
+		
+	
+	def deletePrepProperties(self, prepID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE PrepElementProp_tbl SET status='DEP' WHERE prepID=" + `prepID` + " AND status='ACTIVE'")
+		
+	
+	def deleteIsolate(self, isolateID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Isolate_tbl SET status='DEP' WHERE isolate_pk=" + `isolateID` + " AND status='ACTIVE'")
+		
+	
+	def deleteExperiment(self, expID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Experiment_tbl SET status='DEP' WHERE expID=" + `expID` + " AND status='ACTIVE'")
+		
+		
+	# Jan. 3, 2010 - Delete an actual plate
+	def deleteContainer(self, containerID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		# Need to delete:
+		# - a container
+		# - its properties
+		
+		cursor.execute("UPDATE Prep_Req_tbl SET status='DEP' WHERE containerID=" + `containerID` + " AND status='ACTIVE'")
+		cursor.execute("UPDATE Container_tbl SET status='DEP' WHERE containerID=" + `containerID` + " AND status='ACTIVE'")
+	
+	# Feb. 18/10
+	def deleteExperimentID(self, rID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		# plain and simple - when a reagent is deleted, delete the Experiment_tbl entry for it
+		cursor.execute("UPDATE Experiment_tbl SET status='DEP' WHERE reagentID=" + `rID` + " AND status='ACTIVE'")
+
+
+	####################################################################################################################################
+	# Written June 6, 2011
+	#
+	# Return the internal database ID of a well in the given container identified by the given coordinates (row and column numbers)
+	#
+	# wellRow: INT
+	# wellCol: INT
+	# contID: INT (internal database ID of the container that contains this well)
+	####################################################################################################################################
+	def findWellIDByCoordinates(self, contID, wellRow, wellCol):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT wellID FROM Wells_tbl WHERE containerID=" + `contID` + " AND  wellRow=" + `wellRow` + " AND wellCol=" + `wellCol` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+		else:
+			return 0
+
+
+	# June 6, 2011
+	def findPrepIDInWell(self, wellID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+
+		cursor.execute("SELECT prepID FROM Prep_tbl WHERE wellID=" + `wellID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		if result:
+			return int(result[0])
+		else:
+			return 0
+
+
+	# June 6, 2011
+	def updatePrepPropertyValue(self, prepID, elementTypeID, propValue):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		if self.existsPrepProperty(prepID, elementTypeID):
+			cursor.execute("UPDATE PrepElementProp_tbl SET value=" + `propValue` + " WHERE prepID=" + `prepID` + " AND elementTypeID=" + `elementTypeID` + " AND status='ACTIVE'")
+		else:
+			self.addPrepPropertyValue(prepID, elementTypeID, propValue)
+
+
+	# June 6, 2011
+	def existsPrepProperty(self, prepID, elementTypeID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+
+		cursor.execute("SELECT * FROM PrepElementProp_tbl WHERE prepID=" + `prepID` + " AND elementTypeID=" + `elementTypeID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		if result:
+			return True
+		else:
+			return False		
+
+
+	# June 6, 2011
+	def addPrepPropertyValue(self, prepID, elementTypeID, propValue):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("INSERT INTO PrepElementProp_tbl(prepID, elementTypeID, value) VALUES(" + `prepID` + ", " + `elementTypeID` + ", " + `propValue` + ")")
+
+
+	# June 6, 2011
+	def updatePrepComments(self, prepID, commVal):
+		db = self.db
+		cursor = self.cursor	# for easy access
+
+		cursor.execute("UPDATE Prep_tbl SET comments=" + `commVal` + " WHERE prepID=" + `prepID` + " AND status='ACTIVE'")
+		
+
+	# June 6, 2011
+	def updatePrepReference(self, prepID, refVal):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE Prep_tbl SET refAvailID=" + `refVal` + " WHERE prepID=" + `prepID` + " AND status='ACTIVE'")
+
+
+	# June 8, 2011
+	# Return an array of wells in the container identified by contID
+	def findContainerWells(self, contID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+
+		wells = []
+		
+		cursor.execute("SELECT wellID, wellRow, wellCol FROM Wells_tbl WHERE containerID=" + `contID` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+
+		for result in results:
+			wellID = int(result[0])
+			wellRow = int(result[1])
+			wellCol = int(result[2])
+
+			tmpWell = Well(wellID, wellRow, wellCol, contID)
+			wells.append(tmpWell)
+
+		return wells
+
+
+	# June 9, 2011
+	def findPrepReference(self, prepID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+
+		cursor.execute("SELECT refAvailID FROM Prep_tbl WHERE prepID=" + `prepID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		if result:
+			return result[0]
+		else:
+			return ""
+			
+
+	# June 9, 2011
+	def findPrepComments(self, prepID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+
+		cursor.execute("SELECT comments FROM Prep_tbl WHERE prepID=" + `prepID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		if result:
+			return result[0]
+		else:
+			return ""
+
+
+	# June 9, 2011
+	def findPrepIsolateID(self, prepID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+
+		cursor.execute("SELECT isolate_pk FROM Prep_tbl WHERE prepID=" + `prepID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		if result:
+			return int(result[0])
+		else:
+			return -1
+
+	
+	# June 9, 2011
+	def findPrepFlag(self, prepID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+
+		cursor.execute("SELECT flag FROM Prep_tbl WHERE prepID=" + `prepID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		flag = 'NO'
+
+		if result:
+			if result[0].upper() == 'YES':
+				flag = 'YES'
+				
+		return flag
+
+
+	##############################################################################
+	# June 9, 2011
+	#
+	# Input: isolateID - INT, corresponds to Isolate_tbl.isolate_pk column value
+	# Return: Isolate_tbl.isolateNumber column value
+	#
+	##############################################################################
+	def findIsolateNumber(self, isolateID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+
+		cursor.execute("SELECT isolateNumber FROM Isolate_tbl WHERE isolate_pk=" + `isolateID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		if result:
+			return int(result[0])
+		else:
+			return 0
+
+
+	# June 9, 2011
+	def isSelectedIsolate(self, isolateID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+
+		cursor.execute("SELECT beingUsed FROM Isolate_tbl WHERE isolate_pk=" + `isolateID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+
+		return 'NO'
+
+
+	# June 9, 2011
+	# Return an array of PrepProperty OBJECTS
+	def findAllPrepProperties(self, prepID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+
+		prepProps = []
+		
+		#print "Content-type:text/html"
+		#print
+		#print "SELECT t.elementTypeID, t.propertyName, p.value FROM PrepElemTypes_tbl t, PrepElementProp_tbl p WHERE p.prepID=" + `prepID` + " AND p.elementTypeID=t.elementTypeID AND p.status='ACTIVE' AND t.status='ACTIVE'"
+
+		cursor.execute("SELECT t.elementTypeID, t.propertyName, p.value FROM PrepElemTypes_tbl t, PrepElementProp_tbl p WHERE p.prepID=" + `prepID` + " AND p.elementTypeID=t.elementTypeID AND p.status='ACTIVE' AND t.status='ACTIVE'")
+
+		results = cursor.fetchall()
+
+		for result in results:
+			propID = int(result[0])
+			#print propID
+			propName = result[1]
+			#print propName
+			propValue = result[2]
+			#print propValue
+
+			tmpPrepProperty = PrepProperty(propID, propName, propValue)
+
+			prepProps.append(tmpPrepProperty)
+
+		#print `prepProps`
+		return prepProps
+
+
+	# June 9, 2011
+	def findExperimentIDByIsolate(self, isolateID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT expID FROM Isolate_tbl WHERE isolate_pk=" + `isolateID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		if result:
+			return int(result[0])
+		else:
+			return -1
+
+	# June 9, 2011
+	def findReagentIDByExperiment(self, expID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+	
+		cursor.execute("SELECT reagentID FROM Experiment_tbl WHERE expID=" + `expID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		if result:
+			return int(result[0])
+		else:
+			return 0
+
+	# June 9, 2011
+	def getNumRows(self, contID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+	
+		contSize = self.findContainerSize(contID)
+		cursor.execute("SELECT maxRow FROM ContainerTypeID_tbl WHERE containerName=" + `contSize`)
+		result = cursor.fetchone()
+
+		return int(result[0])
+
+
+	# June 9, 2011
+	def getNumCols(self, contID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+	
+		contSize = self.findContainerSize(contID)
+		cursor.execute("SELECT maxCol FROM ContainerTypeID_tbl WHERE containerName=" + `contSize`)
+		result = cursor.fetchone()
+
+		return int(result[0])
+
+		
+	# June 13, 2011: Equal and opposite of findReagentIDByExperiment - given a reagent ID, find its expID
+	# Return: expID
+	def findExperimentByReagentID(self, rID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+	
+		cursor.execute("SELECT expID FROM Experiment_tbl WHERE reagentID=" + `rID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		if result:
+			return int(result[0])
+		else:
+			return 0
+
+
+	# June 13, 2011
+	def findContainerByWell(self, wellID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+
+		cursor.execute("SELECT containerID FROM Wells_tbl WHERE wellID=" + `wellID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		return int(result[0])
+
+
+	# June 13, 2011
+	def findWellRowNumber(self, wellID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+	
+		cursor.execute("SELECT wellRow FROM Wells_tbl WHERE wellID=" + `wellID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		return int(result[0])
+
+
+	# June 13, 2011
+	def findWellColumn(self, wellID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+	
+		cursor.execute("SELECT wellCol FROM Wells_tbl WHERE wellID=" + `wellID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		return int(result[0])
+
+
+	# June 13, 2011: Convert well ID to A:1
+	def findWellCoordinates(self, wellID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+
+		wellRowNum = self.findWellRowNumber(wellID)
+		wellCol = self.findWellColumn(wellID)
+		wellRowLetter = Well.convertRowNumberToChar(wellRowNum)
+		wellCoords = wellRowLetter + ":" + `wellCol`
+
+		return wellCoords
\ No newline at end of file
diff --git a/OpenFreezer/cgi/location_request_handler.py b/OpenFreezer/cgi/location_request_handler.py
new file mode 100755
index 0000000..d87eef9
--- /dev/null
+++ b/OpenFreezer/cgi/location_request_handler.py
@@ -0,0 +1,495 @@
+#!/usr/local/bin/python
+
+# python modules
+import cgi
+import cgitb; cgitb.enable()
+
+import SocketServer
+from SocketServer import BaseRequestHandler
+
+import MySQLdb
+
+import os
+import tempfile
+import stat
+import sys
+import string
+
+# Custom modules
+import utils
+
+from database_conn import DatabaseConn
+#from session import Session
+
+from container import Container
+from well import Well
+
+from location_database_handler import LocationHandler
+from location_type_database_handler import LocationTypeHandler
+from reagent_handler import ReagentHandler
+from exception import ReagentDoesNotExistException
+
+from mapper import PrepPropertyMapper, ContainerTypeMapper
+
+##################################################################################################################
+# Contains functions to handle requests for creation, modification and deletion of containers or container types
+#
+# Written Sept. 18, 2007, by Marina Olhovsky
+# Last modified: Sept. 18, 2007
+##################################################################################################################
+class LocationRequestHandler:
+	__db = None
+	__cursor = None
+	__hostname = ""
+	
+	##########################################################
+	# Constructor
+	##########################################################
+	def __init__(self):
+	
+		dbConn = DatabaseConn()
+		db = dbConn.databaseConnect()
+		cursor = db.cursor()
+		hostname = dbConn.getHostname()
+
+		self.__db = db
+		self.__cursor = cursor
+		self.__hostname = hostname
+		
+		
+	##########################################################
+	# Override parent method
+	##########################################################
+	def handle(self):
+		
+		db = self.__db
+		cursor = self.__cursor
+		
+		#print "Content-type:text/html"
+		#print
+		
+		form = cgi.FieldStorage(keep_blank_values="True")
+		#print `form`
+	
+		if form.has_key("cont_cont_create_button"):
+			self.createContainer(form)
+			
+		elif form.has_key("cont_modify_button"):
+			self.modify_container(form)
+			
+		elif form.has_key("delete_container"):
+			self.deleteContainer(form)
+			
+		elif form.has_key("edit_cont_location"):
+			self.editContainerLocation(form)
+		
+		elif form.has_key("save_cont_storage"):
+			self.updateContainerStorage(form)
+		
+		elif form.has_key("validate_reagent_id"):
+			self.validateReagentID(form)
+
+		# June 6, 2011
+		elif form.has_key("update_attribute"):
+			self.updateAttribute(form)
+
+		# June 8, 2011
+		elif form.has_key("export_plate"):
+			self.exportPlate(form)
+
+		cursor.close()
+		db.close()
+		
+		
+	# Store container name, type, size and description arriving from POST and assign a barcode (new feature)
+	def createContainer(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+	
+		lHandler = LocationHandler(db, cursor)
+		
+		# some form values may be blank, so initialize as empty
+		contName = ""
+		contDesc = ""
+		
+		if form.has_key("cont_cont_name_field"):
+			contName = form.getvalue("cont_cont_name_field")
+		
+		if form.has_key("cont_cont_desc_field"):
+			contDesc = form.getvalue("cont_cont_desc_field")
+			
+		# container type and size are selected from a list, so they can't be empty
+		contTypeID = form.getvalue("cont_cont_group_selection")
+		contSize = form.getvalue("cont_cont_type_selection")
+		
+		# laboratory - always selected by default
+		contLab = form.getvalue("labs")
+		
+		# Location - fridge, freezer, LN tank, etc.
+		storage_type = form.getvalue("storage_type")
+		storage_name = form.getvalue("storage_name")
+		cont_row = form.getvalue("cont_row")
+		cont_col = form.getvalue("cont_col")
+		cont_rack = form.getvalue("cont_rack")
+		cont_shelf = form.getvalue("cont_shelf")
+		storage_address = form.getvalue("storage_address")
+		
+		newContID = lHandler.insertContainer(contTypeID, contSize, contName, contDesc, contLab, storage_type, storage_name, storage_address, cont_shelf, cont_rack, cont_row, cont_col)
+
+		utils.redirect(hostname + "Location.php?View=6&Sub=3&Mod=" + `newContID`)
+	
+	
+	# Jan. 3, 2010: Plain redirect to Storage page in Modify mode
+	def editContainerLocation(self, form):
+		
+		hostname = self.__hostname
+		contID = int(form.getvalue("cont_id_hidden"))
+		
+		utils.redirect(hostname + "Location.php?View=3&Sub=1&Mod=" + `contID`)
+	
+	# Jan. 3, 2010: Update location details
+	def updateContainerStorage(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		lHandler = LocationHandler(db, cursor)
+		
+		#print "Content-type:text/html"
+		#print
+		#print `form`
+		
+		contID = int(form.getvalue("cont_id_hidden"))
+		storage_type = form.getvalue("storage_type")
+		storage_name = form.getvalue("storage_name")
+		cont_row = form.getvalue("cont_row")
+		cont_col = form.getvalue("cont_col")
+		cont_rack = form.getvalue("cont_rack")
+		cont_shelf = form.getvalue("cont_shelf")
+		storage_address = form.getvalue("storage_address")
+		
+		lHandler.updateContainerLocation(contID, storage_type, storage_name, storage_address, cont_shelf, cont_rack, cont_row, cont_col)
+		
+		utils.redirect(hostname + "Location.php?View=3&Mod=" + `contID`)
+	
+	
+	def modify_container(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+	
+		lHandler = LocationHandler(db, cursor)
+		
+		contID = int(form.getvalue("cont_id_hidden"))
+		
+		# some form values may be blank, so initialize as empty
+		contName = ""
+		contDesc = ""
+		
+		if form.has_key("cont_name_field"):
+			contName = form.getvalue("cont_name_field")
+		
+		if form.has_key("cont_desc_field"):
+			contDesc = form.getvalue("cont_desc_field")
+			
+		# container type and size are selected from a list, so they can't be empty
+		contType = form.getvalue("cont_group_selection")
+		contSize = form.getvalue("cont_size_selection")
+		
+		# laboratory - always selected by default
+		contLab = int(form.getvalue("labs"))
+		
+		# Location - fridge, freezer, LN tank, etc.
+		storage_type = form.getvalue("storage_type")
+		storage_name = form.getvalue("storage_name")
+		cont_row = form.getvalue("cont_row")
+		cont_col = form.getvalue("cont_col")
+		cont_rack = form.getvalue("cont_rack")
+		cont_shelf = form.getvalue("cont_shelf")
+		storage_address = form.getvalue("storage_address")
+		
+		lHandler.updateContainerInfo(contID, contType, contSize, contName, contDesc, contLab, storage_type, storage_name, storage_address, cont_shelf, cont_rack, cont_row, cont_col)
+		
+		utils.redirect(hostname + "Location.php?View=6&Sub=3&Mod=" + `contID`)
+	
+	
+	def deleteContainer(self, form):
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+	
+		lHandler = LocationHandler(db, cursor)
+		
+		if form.has_key("containerID"):
+			containerID = int(form.getvalue("containerID"))
+			delStatus = lHandler.deleteContainer(containerID)
+			utils.redirect(hostname + "Location.php?View=5&Del=1")
+	
+	
+	def validateReagentID(self, form):
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+	
+		rHandler = ReagentHandler(db, cursor)
+		
+		print "Content-type:text/html"
+		print
+		
+		tmp_rids = form.getlist("rID")
+		#tmp_rid = form.getvalue("rID").strip()
+		#print `tmp_rids`
+		
+		for tmp_rid in tmp_rids:
+			try:
+				tmpReagentID = rHandler.convertReagentToDatabaseID(tmp_rid.strip())
+			except ReagentDoesNotExistException:
+				i = ReagentDoesNotExistException("Reagent does not exist in database")
+				print "ErrCode=" + `i.err_code()` + "&rID=" + tmp_rid
+				break
+
+
+	def updateAttribute(self, form):
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+
+		lHandler = LocationHandler(db, cursor)
+		prepPropMapper = PrepPropertyMapper(db, cursor)
+		prepProp_Name_ID_Map = prepPropMapper.mapPrepPropNameToID()
+		
+		print "Content-type:text/html"
+		print
+		
+		# Update the given attribute for each well selected
+		wells_str = form.getvalue("wells")	# it's a comma-delimited string, count as one value
+
+		contID = int(form.getvalue("contID"))
+		propName = form.getvalue("propName")
+		propVal = form.getvalue("propVal")
+
+		if prepProp_Name_ID_Map.has_key(propName):
+			prepElemID = prepProp_Name_ID_Map[propName]
+		else:
+			prepElemID = 0
+
+		'''
+		if form.has_key("propID"):
+			try:
+				prepElemID = int(form.getvalue("propID"))
+
+			except ValueError:
+				prepElemID = 0
+		'''
+		
+		# wells are provided as a comma-delimited list of 'row|col' values
+		wells = wells_str.split(",")
+
+		for well in wells:
+			coords = well.split('|')
+
+			wellRow = coords[0]
+			wellCol = coords[1]
+
+			wellID = lHandler.findWellIDByCoordinates(contID, wellRow, wellCol)
+			#print wellID
+
+			# get its prep
+			prepID = lHandler.findPrepIDInWell(wellID)
+
+			# Differentiate between update of prep element or reference/comments
+			if prepElemID > 0:
+				lHandler.updatePrepPropertyValue(prepID, prepElemID, propVal)
+			else:
+				if propName.lower() == 'reference':
+					lHandler.updatePrepReference(prepID, propVal)
+
+				elif propName.lower() == 'comments':
+					lHandler.updatePrepComments(prepID, propVal)
+
+		#utils.redirect(hostname + "Location.php?View=2&Mod=" + `contID`)
+		print hostname + "Location.php?View=2&Mod=" + `contID`
+
+
+	# June 8, 2011
+	def exportPlate(self, form):
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+
+		lHandler = LocationHandler(db, cursor)
+		ltHandler = LocationTypeHandler(db, cursor)
+		rHandler = ReagentHandler(db, cursor)
+
+		prepPropMapper = PrepPropertyMapper(db, cursor)
+		cTypeMapper = ContainerTypeMapper(db, cursor)
+
+		prepProp_Name_ID_Map = prepPropMapper.mapPrepPropNameToID()
+		prepProp_ID_Name_Map = prepPropMapper.mapPrepPropIDToName()
+
+		contType_Name_ID_Map = cTypeMapper.mapContainerTypeNameToID()
+		
+		contID = int(form.getvalue("contID"))
+		contName = lHandler.findContainerName(contID)
+		contArray = contName.split(" ")
+		fname = string.join(contArray, "_") + ".csv"
+
+		wells = lHandler.findContainerWells(contID)
+		content = ""
+
+		# debug
+		#print "Content-type:text/html"
+		#print
+
+		contType = lHandler.findContainerType(contID)
+		contTypeID = contType_Name_ID_Map[contType]
+		contProps = ltHandler.findContainerTypeProperties(contTypeID)	# array of names
+		
+		iso_active = ltHandler.isIsoActive(contTypeID)
+
+		if iso_active == 'YES':
+			isoActive = True
+		else:
+			isoActive = False
+
+		#print `contProps`
+
+		# Header
+		if isoActive:
+			content = "Well,OpenFreezer ID,Selected Isolate,Flag,Reference,Comments,"
+		else:
+			content = "Well,OpenFreezer ID,Flag,Reference,Comments,"
+
+		contPropIDs_sorted = []
+
+		for cPropName in contProps:
+			cPropID = prepProp_Name_ID_Map[cPropName]
+			contPropIDs_sorted.append(cPropID)
+
+		contPropIDs_sorted.sort()
+
+		for cPropID in contPropIDs_sorted:
+			cPropName = prepProp_ID_Name_Map[cPropID]
+			content += cPropName + ','
+
+		content += '\n'
+
+		numRows = lHandler.getNumRows(contID)
+		numCols = lHandler.getNumCols(contID)
+
+		plate = {}
+
+		for well in wells:
+			wellRowNum = well.getWellRowNumber()
+			#print wellRowNum
+
+			if plate.has_key(wellRowNum):
+				plate[wellRowNum].append(well)
+			else:
+				tmp_ar = []
+				tmp_ar.append(well)
+				plate[wellRowNum] = tmp_ar
+
+		plate.keys().sort()
+
+		for rowNum in range(1, numRows+1):
+			if plate.has_key(rowNum):
+				wellRow = plate[rowNum]
+				wellRowNum = rowNum
+				wellRowLetter = Well.convertRowNumberToChar(wellRowNum)
+
+				wellRow.sort()
+
+				#print "ROW " + `rowNum`
+				
+				for colNum in range(1, numCols+1):
+					for well in wellRow:
+						wellID = well.getWellID()
+						#print wellID
+						wellCol = well.getWellColumn()
+
+						if wellCol == colNum:
+
+							#print "COLUMN " + `wellCol`
+
+							wellCoords = wellRowLetter + ":" + `wellCol`
+							
+							# get prep, reference, comments, flag
+							prepID = lHandler.findPrepIDInWell(wellID)
+							#print prepID
+							prepRef = lHandler.findPrepReference(prepID)
+							#print prepRef
+
+							if not prepRef:
+								prepRef = ""
+
+							prepComms = lHandler.findPrepComments(prepID)
+							#print prepComms
+
+							if not prepComms:
+								prepComms = ""
+
+							prepFlag = lHandler.findPrepFlag(prepID)
+							#print prepFlag
+
+							# get isolate number, selected isolate
+							isoID = lHandler.findPrepIsolateID(prepID)
+							isoNum = lHandler.findIsolateNumber(isoID)
+							isoSelected = lHandler.isSelectedIsolate(isoID)
+
+							# get prep property values
+							prepPropValues = lHandler.findAllPrepProperties(prepID)
+
+							# find the LIMS ID of the reagent stored in this well
+							expID = lHandler.findExperimentIDByIsolate(isoID)
+							rID = lHandler.findReagentIDByExperiment(expID)
+							limsID = rHandler.convertDatabaseToReagentID(rID)
+
+							# Output: Well , Reagent-isolate , Selected , Flag , Reference , Comments , Attributes [name1 , name2 , name3....]
+							if isoActive:
+								content += wellCoords + ',' + limsID + "-" + `isoNum` + ',' + isoSelected + ',' + prepFlag + ',' + prepRef + ',' + prepComms + ","
+							else:
+								content += wellCoords + ',' + limsID + ',' + prepFlag + ',' + prepRef + ',' + prepComms + ","
+
+							prepPropIDs_sorted = {}
+
+							prepProps = {}
+
+							for pProp in prepPropValues:
+								pName = pProp.getPropName()
+								pVal = pProp.getPropValue()
+								prepProps[pName] = pVal
+
+							prepProps.keys().sort()		# might not be necessary but still
+								
+							for cPropID in contPropIDs_sorted:
+								cPropName = prepProp_ID_Name_Map[cPropID]
+
+								if prepProps.has_key(cPropName):
+									pVal = prepProps[cPropName]
+									content += pVal + ','
+								else:
+									content += ','									
+
+							content += '\n'
+		
+		print "Content-type: application/octet-stream"
+		print "Content-Disposition: attachment; name=" + fname
+		print
+
+		print content
+				
+	
+##########################################################
+# Central callable function
+##########################################################
+def main():
+
+	lReqHandler = LocationRequestHandler()
+	lReqHandler.handle()
+
+main()
\ No newline at end of file
diff --git a/OpenFreezer/cgi/location_type_database_handler.py b/OpenFreezer/cgi/location_type_database_handler.py
new file mode 100755
index 0000000..173f30b
--- /dev/null
+++ b/OpenFreezer/cgi/location_type_database_handler.py
@@ -0,0 +1,391 @@
+#!/usr/local/bin/python
+
+# python modules
+import cgi
+import cgitb; cgitb.enable()
+
+import SocketServer
+from SocketServer import BaseRequestHandler
+
+import MySQLdb
+
+import os
+import tempfile
+import stat
+import sys
+import string
+
+# Custom modules
+import utils
+
+from database_conn import DatabaseConn
+#from session import Session
+
+from container import Container
+from general_handler import GeneralHandler
+from lab_handler import LabHandler
+
+from mapper import *
+
+#################################################################################
+# Top-level abstraction for LocationHandler hierarchy; extends GeneralHandler
+#
+# Written September 18, 2007 by Marina Olhovsky
+# Last modified: Sept. 18/07
+#################################################################################
+
+class LocationTypeHandler(GeneralHandler):
+	"Database handler functions for Container Types (e.g. MiniPrep Plates, Liquid Nitrogen Containers, etc.)"
+
+	def __init__(self, db, cursor):
+		super(LocationTypeHandler, self).__init__(db, cursor)
+
+
+
+	# Jan. 3/09
+	def findContainerTypeProperties(self, contTypeID):
+	
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		contTypeAttrs = []
+		
+		cursor.execute("SELECT p.propertyName FROM PrepElemTypes_tbl p, ContainerTypeAttributes_tbl c WHERE c.containerTypeID=" + `contTypeID` + " AND c.containerTypeAttributeID=p.elementTypeID AND c.status='ACTIVE' and p.status='ACTIVE'")
+		
+		results = cursor.fetchall()
+		
+		for result in results:
+			contTypeAttrs.append(result[0])
+			
+		return contTypeAttrs
+		
+
+	# Find the internal database ID of container type identified by contType
+	# E.g. contType = 'Vector', contTypeID = '1'
+	# Input: contType: STRING
+	# Returns: INT, corresponds to contGroupID column value in ContainerGroup_tbl
+	def containerTypeToID(self, contType):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT contGroupID FROM ContainerGroup_tbl WHERE contGroupName=" + `contType` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			contTypeID = int(result[0])
+			return contTypeID
+		
+		return 0
+	
+	
+	# Dec. 21/09 - Create container type - simply make an entry in ContainerGroup_tbl
+	def insertContainerType(self, contGroupName, isoActive, contGroupCode):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("INSERT INTO ContainerGroup_tbl(contGroupName, isolate_active, contGroupCode) VALUES(" + `contGroupName` + ", " + `isoActive` + ", " + `contGroupCode` + ")")
+		
+		return int(db.insert_id())
+		
+	
+	# Get the 2-letter code matching cTypeID (e.g. 'VE' for Vectors (cTypeID=1), 'GS' for Glycerol Stock (cTypeID=2), etc.)
+	# Returns the value of contGroupCode column in ContainerGroup_tbl
+	def findContainerTypeCode(self, cTypeID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT contGroupCode FROM ContainerGroup_tbl WHERE contGroupID=" + `cTypeID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+		
+		return ""
+	
+
+	def findContainerTypeName(self, cTypeID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT contGroupName FROM ContainerGroup_tbl WHERE contGroupID=" + `cTypeID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+		
+		return ""
+	
+	
+	# Find the internal database ID of an entry in ContainerTypeID_tbl that corresponds to contSize
+	# E.g. contSize = '96-well plate'; result: '1'
+	# Input: contSize: STRING, verbal description of available container types in OpenFreezer
+	# Returns: INT, value of contTypeID column in ContainerTypeID_tbl
+	def containerSizeToID(self, contSize):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT contTypeID FROM ContainerTypeID_tbl WHERE containerName=" + `contSize` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			contSizeID = int(result[0])
+			return contSizeID
+		
+		return 0
+
+	
+	# Find the actual number of wells/slots in the container; do it by multiplying the number of columns by the number of rows
+	def findNumContainerSamples(self, contSizeID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		numCols = self.findNumCols(contSizeID)
+		numRows = self.findNumRows(contSizeID)
+		
+		numWells = numCols * numRows
+		
+		return numWells
+		
+	
+	# Find the number of columns in a container
+	def findNumCols(self, contSizeID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		numCols = 0
+		
+		cursor.execute("SELECT maxCol FROM ContainerTypeID_tbl WHERE contTypeID=" + `contSizeID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			numCols = int(result[0])
+			
+		return numCols
+		
+		
+	# Find the number of rows in a container
+	def findNumRows(self, contSizeID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		numRows = 0
+		
+		cursor.execute("SELECT maxRow FROM ContainerTypeID_tbl WHERE contTypeID=" + `contSizeID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			numRows = int(result[0])
+			
+		return numRows
+
+
+	# Finds if this container type allows storing different isolates of the same reagent/prep
+	# Input: contTypeID: INT, corresponds to contGroupID column in ContainerGroup_tbl
+	# Returns: YES or NO, depending on whether the container type is isolate active or not
+	def isIsoActive(self, contTypeID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		isoActive = ""
+		
+		cursor.execute("SELECT isolate_active FROM ContainerGroup_tbl WHERE contGroupID=" + `contTypeID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:	# which better be!
+			isoActive = result[0]
+			
+		return isoActive
+		
+		
+	# Jan. 13, 2010
+	def updateContainerType(self, contTypeID, contGroupName, contGroupCode, isoActive, newContTypeFeatures, reagentTypes=[]):
+		
+		#print "Content-type:text/html"
+		#print
+		#print "New features: " + `newContTypeFeatures`
+		#print `reagentTypes`
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		pMapper = PrepPropertyMapper(db, cursor)
+		
+		prepProp_ID_Name_Map = pMapper.mapPrepPropIDToName()
+		prepProp_Name_ID_Map = pMapper.mapPrepPropNameToID()
+		
+		# Get old values and compare.  If different, update container type name, container type code and attributes
+		cursor.execute("UPDATE ContainerGroup_tbl SET contGroupName=" + `contGroupName` + " WHERE contGroupID=" + `contTypeID` + " AND status='ACTIVE'")
+		
+		cursor.execute("UPDATE ContainerGroup_tbl SET contGroupCode=" + `contGroupCode` + " WHERE contGroupID=" + `contTypeID` + " AND status='ACTIVE'")
+		
+		# Feb. 16/10: update isolate active state if available
+		if isoActive.upper() != self.findIsolateActive(contTypeID):
+			cursor.execute("UPDATE ContainerGroup_tbl SET isolate_active=" + `isoActive.upper()` + " WHERE contGroupID=" + `contTypeID` + " AND status='ACTIVE'")
+		
+		# grab features and add if required
+		currContTypeFeatures = self.findContainerTypeProperties(contTypeID)
+	
+		#print "Current features: " + `currContTypeFeatures`
+		
+		# delete old and add new
+		for curr_fName in currContTypeFeatures:
+			cfID = prepProp_Name_ID_Map[curr_fName]
+			
+			if not curr_fName in newContTypeFeatures:
+				self.deleteContainerTypeFeature(contTypeID, cfID)
+
+		for fName in newContTypeFeatures:
+			#if prepProp_Name_ID_Map.has_key(fName):
+				#fID = prepProp_Name_ID_Map[fName]
+				
+			if not fName in currContTypeFeatures:
+				self.addContainerTypeFeature(contTypeID, fName)
+			#else:
+				#newPropID = self.addPrepProperty(fName)
+				#self.addContainerTypeFeature(contTypeID, fName)
+		
+		self.updateContainerReagentTypes(contTypeID, reagentTypes)
+		
+	
+	# Feb. 16/10: find the isolate active state of a container type
+	def findIsolateActive(self, contTypeID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("SELECT isolate_active FROM ContainerGroup_tbl WHERE contGroupID=" + `contTypeID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:	# should be
+			return result[0]
+		
+		return "NO"
+		
+	
+	def updateContainerReagentTypes(self, contTypeID, reagentTypes):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		# June 22, 2010: Delete and re-insert
+		self.deleteContainerReagentTypes(contTypeID)
+		
+		#currReagentTypes = self.getContainerReagentTypes(contTypeID)	# list of rTypeIDs
+		
+		for rType in reagentTypes:
+			#if rType not in currReagentTypes:
+			self.addContainerReagentType(contTypeID, rType)
+		
+	
+	def deleteContainerReagentTypes(self, contTypeID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE ContainerReagentTypes_tbl SET status='DEP' WHERE contTypeID=" + `contTypeID` + " AND status='ACTIVE'")
+		
+	
+	def addContainerReagentType(self, contTypeID, rTypeID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("INSERT INTO ContainerReagentTypes_tbl(contTypeID, reagentTypeID) VALUES(" + `contTypeID` + ", " + `rTypeID` + ")")
+		
+		
+	
+	def getContainerReagentTypes(self, contTypeID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		rTypes = []
+		
+		cursor.execute("SELECT reagentTypeID FROM ContainerReagentTypes_tbl WHERE contTypeID=" + `contTypeID` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			rTypeID = int(result[0])
+			rTypes.append(rTypeID)
+			
+		return rTypes
+
+	
+	# Jan. 14, 2010: Adding a new attribute to the list (like 'Other')
+	def addPrepProperty(self, propName):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("INSERT INTO PrepElemTypes_tbl(propertyName, PrepElementDesc) VALUES(" + `propName` + ", " + `propName` + ")")
+		return int(db.insert_id())
+
+	
+	# Jan. 14, 2009
+	def deleteContainerTypeFeature(self, contTypeID, cfID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		cursor.execute("UPDATE ContainerTypeAttributes_tbl SET status='DEP' WHERE containerTypeID=" + `contTypeID` + " AND containerTypeAttributeID=" + `cfID` + " AND status='ACTIVE'")
+
+
+	# Jan. 13, 2010
+	def addContainerTypeFeature(self, contTypeID, propName):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		pMapper = PrepPropertyMapper(db, cursor)
+		
+		prepProp_Name_ID_Map = pMapper.mapPrepPropNameToID()
+		
+		if prepProp_Name_ID_Map.has_key(propName):
+			propID = prepProp_Name_ID_Map[propName]
+		else:
+			propID = self.addPrepProperty(propName)
+		
+		cursor.execute("INSERT INTO ContainerTypeAttributes_tbl(containerTypeID, containerTypeAttributeID) VALUES(" + `contTypeID` + ", " + `propID` + ")")
+	
+	
+	# Jan. 14, 2010: fList is a list of feature IDs
+	def addContainerTypeFeatures(self, contTypeID, fList):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		for fID in fList:
+			self.addContainerTypeFeature(contTypeID, fID)
+	
+	# Jan. 12, 2010
+	def deleteContainerType(self, contTypeID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		# delete container type and attributes - deprecate entries in ContainerGroup_tbl and ContainerTypeAttributes_tbl
+		cursor.execute("UPDATE ContainerTypeAttributes_tbl SET status='DEP' WHERE containerTypeID=" + `contTypeID`)
+		cursor.execute("UPDATE ContainerGroup_tbl SET status='DEP' WHERE contGroupID=" + `contTypeID`)
+		
+		# Feb. 9/10: delete links to reagent types allowed for this container
+		cursor.execute("UPDATE ContainerReagentTypes_tbl SET status='DEP' WHERE contTypeID=" + `contTypeID`)
+		
+		
+	# Feb. 25/10: delete association between container type and reagent type
+	# delete links to reagent types allowed for this container
+	# Used at reagent type deletion
+	def deleteContainerReagentType(self, rTypeID):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		## Feb. 9/10: delete links to reagent types allowed for this container
+		cursor.execute("UPDATE ContainerReagentTypes_tbl SET status='DEP' WHERE reagentTypeID=" + `rTypeID`)
\ No newline at end of file
diff --git a/OpenFreezer/cgi/location_type_request_handler.py b/OpenFreezer/cgi/location_type_request_handler.py
new file mode 100755
index 0000000..8cb8a42
--- /dev/null
+++ b/OpenFreezer/cgi/location_type_request_handler.py
@@ -0,0 +1,213 @@
+#!/usr/local/bin/python
+
+# python modules
+import cgi
+import cgitb; cgitb.enable()
+
+import SocketServer
+from SocketServer import BaseRequestHandler
+
+import MySQLdb
+
+import os
+import tempfile
+import stat
+import sys
+import string
+
+# Custom modules
+import utils
+
+from database_conn import DatabaseConn
+#from session import Session
+
+from container import Container
+from location_type_database_handler import LocationTypeHandler
+
+##################################################################################################################
+# Contains functions to handle requests for creation, modification and deletion of containers or container types
+#
+# Written Sept. 18, 2007, by Marina Olhovsky
+# Last modified: Sept. 18, 2007
+##################################################################################################################
+class LocationTypeRequestHandler:
+	__db = None
+	__cursor = None
+	__hostname = ""
+	
+	##########################################################
+	# Constructor
+	##########################################################
+	def __init__(self):
+	
+		dbConn = DatabaseConn()
+		db = dbConn.databaseConnect()
+		cursor = db.cursor()
+		hostname = dbConn.getHostname()
+
+		self.__db = db
+		self.__cursor = cursor
+		self.__hostname = hostname
+		
+		
+	##########################################################
+	# Override parent method
+	##########################################################
+	def handle(self):
+		
+		db = self.__db
+		cursor = self.__cursor
+		
+		#print "Content-type:text/html"
+		#print
+		
+		form = cgi.FieldStorage(keep_blank_values="True")
+		#print `form`
+		
+		if form.has_key("cont_type_create_button"):
+			self.addContainerType(form)
+		
+		elif form.has_key("cont_type_modify"):
+			self.modifyContainerType(form)
+		
+		elif form.has_key("cont_type_save"):
+			self.updateContainerType(form)
+			
+		elif form.has_key("cont_type_delete"):
+			self.deleteContainerType(form)
+			
+		elif form.has_key("cancel_cont_type_modify"):
+			self.cancelContainerTypeModification(form)
+		
+		cursor.close()
+		db.close()
+	
+
+	# Add a new container TYPE (i.e. update ContainerGroup_tbl and add prep attributes for it)
+	def addContainerType(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+	
+		ltHandler = LocationTypeHandler(db, cursor)
+		
+		# some form values may be blank, so initialize as empty
+		contName = ""
+		contDesc = ""
+		
+		#print "Content-type:text/html"
+		#print
+		#print `form`
+		
+		contGroupName = form.getvalue("cont_group_name_field")
+		contGroupCode = form.getvalue("cont_cont_code_field")
+		
+		if form.has_key("cont_cont_isolateActive_radio"):
+			if form.getvalue("cont_cont_isolateActive_radio").upper() == 'YES':
+				isoActive = form.getvalue("cont_cont_isolateActive_radio").upper()
+			else:
+				isoActive = "NO"
+		
+		newContTypeFeatures = form.getlist("container_features")
+		#print `newContTypeFeatures`
+		newContTypeID = ltHandler.insertContainerType(contGroupName, isoActive, contGroupCode)
+		
+		ltHandler.addContainerTypeFeatures(newContTypeID, newContTypeFeatures)
+		
+		reagentTypes = form.getlist("cont_cont_group_selection")	# feb. 16/10
+		#print `reagentTypes`
+		ltHandler.updateContainerReagentTypes(newContTypeID, reagentTypes)
+		
+		utils.redirect(hostname + "Location.php?View=6&Sub=4&contTypeID=" + `newContTypeID`)
+
+
+	def modifyContainerType(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+	
+		contTypeID = form.getvalue("containerType")
+		
+		# plain redirect
+		utils.redirect(hostname + "Location.php?View=6&Sub=4&contTypeID=" + contTypeID + "&Mod=1")
+		
+	
+	# Update container type information
+	def updateContainerType(self, form):
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+	
+		ltHandler = LocationTypeHandler(db, cursor)
+		
+		contTypeID = form.getvalue("containerType")
+		
+		contName = ""
+		contDesc = ""
+		
+		#print "Content-type:text/html"
+		#print
+		#print `form`
+		
+		contTypeID = int(form.getvalue("containerType"))
+		
+		contGroupName = form.getvalue("cont_group_name_field")
+		contGroupCode = form.getvalue("cont_cont_code_field")
+		
+		if form.has_key("cont_cont_isolateActive_radio"):
+			if form.getvalue("cont_cont_isolateActive_radio").upper() == 'YES':
+				isoActive = form.getvalue("cont_cont_isolateActive_radio").upper()
+				#print isoActive
+			else:
+				isoActive = "NO"
+		else:
+			isoActive = ltHandler.findIsolateActive(contTypeID)
+			
+		newContTypeFeatures = form.getlist("container_features")
+		
+		reagentTypes = form.getlist("reagent_types")	# feb. 9/10
+		
+		#print `reagentTypes`
+
+		ltHandler.updateContainerType(contTypeID, contGroupName, contGroupCode, isoActive, newContTypeFeatures, reagentTypes)
+		
+		utils.redirect(hostname + "Location.php?View=6&Sub=4&contTypeID=" + `contTypeID`)
+
+
+	def deleteContainerType(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+	
+		ltHandler = LocationTypeHandler(db, cursor)
+		
+		#print "Content-type:text/html"
+		#print
+		#print `form`
+		
+		contTypeID = form.getvalue("containerType")
+		#print contTypeID
+		
+		ltHandler.deleteContainerType(contTypeID)
+		utils.redirect(hostname + "Location.php?View=6&Sub=4&Del=1")
+	
+	
+	def cancelContainerTypeModification(self, form):
+		hostname = self.__hostname
+		
+		contTypeID = form.getvalue("containerType")
+		utils.redirect(hostname + "Location.php?View=6&Sub=4&contTypeID=" + contTypeID)
+	
+	
+##########################################################
+# Central callable function
+##########################################################
+def main():
+
+	ltReqHandler = LocationTypeRequestHandler()
+	ltReqHandler.handle()
+
+main()
\ No newline at end of file
diff --git a/OpenFreezer/cgi/mapper.py b/OpenFreezer/cgi/mapper.py
new file mode 100755
index 0000000..7f8e851
--- /dev/null
+++ b/OpenFreezer/cgi/mapper.py
@@ -0,0 +1,1038 @@
+import MySQLdb
+##################################################################################################################
+# Module Mapper
+# Creates hashtable associations between various table fields
+#
+# Written by: Marina Olhovsky
+# Last modified: June 30, 2008
+##################################################################################################################
+
+
+##################################################################################################################
+# Superclass (abstract)
+##################################################################################################################
+class Mapper(object):
+
+	# Constructor
+	def __init__(self, db, cursor):
+	
+		self.db = db
+		self.cursor = cursor
+		
+		
+##################################################################################################################
+# ReagentPropertyMapper - Maps reagent property types, names and database IDs to each other 
+##################################################################################################################
+class ReagentPropertyMapper(Mapper):
+	"Maps reagent property types, names and database IDs to each other"
+
+	# Map ALL property names to their database IDs
+	# Return: propMap: (propName, propID) tuples dictionary
+	def mapPropNameID(self):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		propMap = {}
+		
+		cursor.execute("SELECT `propertyID`, `propertyName` FROM `ReagentPropType_tbl` WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			pID = int(result[0])
+			pName = result[1]
+			propMap[pName] = pID
+			
+		return propMap
+		
+		
+	# Equal and opposite of mapPropNameID: Map ALL property **IDs** to their names
+	# Return: propMap: (propID, propName) tuples dictionary
+	def mapPropIDName(self):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		propMap = {}
+		
+		cursor.execute("SELECT `propertyID`, `propertyName` FROM `ReagentPropType_tbl` WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			pID = int(result[0])
+			pName = result[1]
+			propMap[pID] = pName
+			
+		return propMap
+				
+	
+	# Map database property aliases to their property IDs
+	# Return: (alias, propID) dictionary
+	def mapPropAliasID(self):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		aliasMap = {}
+		
+		cursor.execute("SELECT `propertyAlias`, `propertyID` FROM `ReagentPropType_tbl` WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			alias = result[0]
+			propID = int(result[1])
+			aliasMap[alias] = propID
+			
+		return aliasMap
+
+
+	# Map database property IDs to their aliases 
+	# Return: (propID, alias) dictionary
+	def mapPropIDAlias(self):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		aliasMap = {}
+		
+		cursor.execute("SELECT `propertyAlias`, `propertyID` FROM `ReagentPropType_tbl` WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			alias = result[0]
+			propID = int(result[1])
+			aliasMap[propID] = alias
+			
+		return aliasMap
+
+
+	# Map property names to their database aliases
+	# Return: (propName, alias) dictionary
+	def mapPropNameAlias(self):
+
+		db = self.db
+		cursor = self.cursor
+		
+		aliasMap = {}
+		
+		cursor.execute("SELECT `propertyAlias`, `propertyName` FROM `ReagentPropType_tbl` WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			alias = result[0]
+			propName = result[1]
+			aliasMap[propName] = alias
+			
+		return aliasMap
+
+
+	# Map aliases to full property names
+	# Return: (alias, propName) dictionary
+	def mapPropAliasName(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		aliasMap = {}
+		
+		cursor.execute("SELECT `propertyAlias`, `propertyName` FROM `ReagentPropType_tbl` WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			alias = result[0]
+			propName = result[1]
+			aliasMap[alias] = propName
+			
+		return aliasMap
+
+
+	def mapPropNameDescription(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		descrMap = {}
+		
+		cursor.execute("SELECT propertyName, propertyDesc FROM ReagentPropType_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			propName = result[0]
+			propDesc = result[1]
+			
+			descrMap[propName] = propDesc
+			
+		return descrMap
+
+
+	def mapPropIDDescription(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		prop_ID_Desc_Map = {}
+		
+		cursor.execute("SELECT propertyID, propertyDesc FROM ReagentPropType_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			propID = int(result[0])
+			propDesc = result[1]
+			
+			prop_ID_Desc_Map[propID] = propDesc
+			
+		return prop_ID_Desc_Map
+
+
+	# April 20, 2009
+	# Map aliases to property descriptions
+	# Return: (alias, propDesc) dictionary
+	def mapPropAliasDescription(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		aliasMap = {}
+		
+		cursor.execute("SELECT propertyAlias, propertyDesc FROM ReagentPropType_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			alias = result[0]
+			propDesc = result[1]
+			aliasMap[alias] = propDesc
+			
+		return aliasMap
+		
+		
+	# April 20, 2009
+	# Map property descriptions to aliases
+	# Return: (propDesc, alias) dictionary
+	def mapPropDescAlias(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		aliasMap = {}
+		
+		cursor.execute("SELECT propertyAlias, propertyDesc FROM ReagentPropType_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			propDesc = result[1]
+			alias = result[0]
+			aliasMap[propDesc] = alias
+			
+		return aliasMap
+	
+	# Oct. 27/09
+	def mapPropDescName(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		nameMap = {}
+		
+		cursor.execute("SELECT propertyDesc, propertyName FROM ReagentPropType_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			propDesc = result[0]
+			propName = result[1]
+			nameMap[propDesc] = propName
+			
+		return nameMap
+		
+		
+	# Oct. 29/09
+	def mapPropDescID(self):
+
+		db = self.db
+		cursor = self.cursor
+		
+		nameMap = {}
+		
+		cursor.execute("SELECT propertyDesc, propertyID FROM ReagentPropType_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			propDesc = result[0]
+			propID = int(result[1])
+			nameMap[propDesc] = propID
+			
+		return nameMap
+		
+		
+	# Added June 30/08: Map feature names to their colors for graphic representation
+	def mapFeatureNameColor(self):
+		db = self.db
+		cursor = self.cursor
+		
+		featureColorMap = {}
+		
+		# Query updated Jan. 27/10 - don't rely on colour, select DNA SEQUENCE FEATURES
+		prop_Category_Name_ID_Map = self.mapPropCategoryNameID()
+		
+		featureCategoryID = prop_Category_Name_ID_Map["DNA Sequence Features"]
+		
+		cursor.execute("SELECT p.propertyName, p.propertyColor FROM ReagentPropType_tbl p, ReagentPropertyCategories_tbl pc WHERE p.status='ACTIVE' AND pc.status='ACTIVE' AND p.propertyColor IS NOT NULL AND pc.categoryID=" + `featureCategoryID` + " AND p.propertyID=pc.propID")
+		
+		results = cursor.fetchall()
+		
+		for result in results:
+			featureName = result[0]
+			featureColor = result[1]
+			
+			featureColorMap[featureName] = featureColor
+		
+		return featureColorMap
+		
+	
+	# April 24/09: Map property category names to their IDs
+	def mapPropCategoryNameID(self):
+		db = self.db
+		cursor = self.cursor
+		
+		categoryMap = {}
+		
+		cursor.execute("SELECT propertyCategoryID, propertyCategoryName FROM ReagentPropTypeCategories_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			categoryID = int(result[0])
+			categoryName = result[1]
+			
+			categoryMap[categoryName] = categoryID
+			
+		return categoryMap
+		
+
+	# April 24/09: Map property category names to their aliases
+	def mapPropCategoryNameAlias(self):
+		db = self.db
+		cursor = self.cursor
+		
+		categoryMap = {}
+		
+		cursor.execute("SELECT propertyCategoryName, propertyCategoryAlias FROM ReagentPropTypeCategories_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			categoryName = result[0]
+			categoryAlias = result[1]
+			
+			categoryMap[categoryName] = categoryAlias
+			
+		return categoryMap
+
+
+	# April 24/09: Map property category IDs to their names
+	def mapPropCategoryIDName(self):
+		db = self.db
+		cursor = self.cursor
+		
+		categoryMap = {}
+		
+		cursor.execute("SELECT propertyCategoryID, propertyCategoryName FROM ReagentPropTypeCategories_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			categoryID = int(result[0])
+			categoryName = result[1]
+			
+			categoryMap[categoryID] = categoryName
+			
+		return categoryMap
+	
+	
+	# April 24/09: Map property category IDs to their aliases
+	def mapPropCategoryIDAlias(self):
+		db = self.db
+		cursor = self.cursor
+		
+		categoryMap = {}
+		
+		cursor.execute("SELECT propertyCategoryID, propertyCategoryAlias FROM ReagentPropTypeCategories_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			categoryID = int(result[0])
+			categoryAlias = result[1]
+			
+			categoryMap[categoryID] = categoryAlias
+			
+		return categoryMap
+		
+	
+	# April 24/09: Map property category aliases to their IDs
+	def mapPropCategoryAliasID(self):
+		db = self.db
+		cursor = self.cursor
+		
+		categoryMap = {}
+		
+		cursor.execute("SELECT propertyCategoryID, propertyCategoryAlias FROM ReagentPropTypeCategories_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			categoryID = int(result[0])
+			categoryAlias = result[1]
+			
+			categoryMap[categoryAlias] = categoryID
+			
+		return categoryMap
+			
+	
+	# April 24/09: Map property category aliases to their names
+	def mapPropCategoryAliasName(self):
+		db = self.db
+		cursor = self.cursor
+		
+		categoryMap = {}
+		
+		cursor.execute("SELECT propertyCategoryName, propertyCategoryAlias FROM ReagentPropTypeCategories_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			categoryName = result[0]
+			categoryAlias = result[1]
+			
+			categoryMap[categoryAlias] = categoryName
+			
+		return categoryMap
+		
+		
+	# July 28/09, update April 14, 2010
+	def mapPropIDOrdering(self):
+		
+		#print "Content-type:text/html"
+		#print
+		
+		db = self.db
+		cursor = self.cursor
+		
+		propOrderingDict = {}
+		
+		prop_ID_Name_Map = self.mapPropIDName()
+		
+		for propID in prop_ID_Name_Map.keys():
+			#print propID
+			cursor.execute("SELECT ordering FROM ReagentPropType_tbl WHERE propertyID=" + `propID` + " AND status='ACTIVE'")
+			result = cursor.fetchone()
+			
+			if result:
+				ordering = int(result[0])
+				propOrderingDict[propID] = ordering
+				
+		return propOrderingDict
+
+
+	# Nov. 19/09: Equal and opposite - return a map of (order, id)
+	# Just flip the dictionary returned by mapPropIDOrdering() function
+	def mapPropOrderingID(self):
+		db = self.db
+		cursor = self.cursor
+		
+		propOrderingDict = {}
+		
+		prop_ID_Order_Map = self.mapPropIDOrdering()
+		
+		for propID in prop_ID_Order_Map.keys():
+			pOrder = prop_ID_Order_Map[propID]
+			propOrderingDict[pOrder] = propID
+
+		return propOrderingDict
+
+
+	# July 28/09
+	def mapPropCategoryIDOrdering(self):
+		db = self.db
+		cursor = self.cursor
+		
+		propCategoryOrderingDict = {}
+		
+		propCategory_ID_Name_Map = self.mapPropCategoryIDName()
+		
+		for categoryID in propCategory_ID_Name_Map.keys():
+			cursor.execute("SELECT ordering FROM ReagentPropTypeCategories_tbl WHERE propertyCategoryID=" + `categoryID` + " AND status='ACTIVE'")
+			result = cursor.fetchone()
+			
+			if result:
+				ordering = int(result[0])
+				propCategoryOrderingDict[categoryID] = ordering
+				
+		return propCategoryOrderingDict
+
+
+##################################################################################################################
+# ReagentAssociationMapper - Creates a map of reagent ASSOCIATION types, names and IDs
+##################################################################################################################
+class ReagentAssociationMapper(Mapper):
+		
+	#################################################################################################################################################################
+	# The functions below are analogous to same-name functions in ReagentPropertyMapper, except they deal with reagent ASSOCIATION types, IDs and properties
+	#################################################################################################################################################################
+	
+	# Map ALL reagent association property names to their database IDs in **Assoc_Prop_tbl**
+	# Return: propMap: (propName, propID) tuples dictionary
+	def mapAssocNameID(self):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		propMap = {}
+		
+		cursor.execute("SELECT `APropertyID`, `APropName` FROM `Assoc_Prop_Type_tbl` WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			pID = int(result[0])
+			pName = result[1]
+			propMap[pName] = pID
+			
+		return propMap
+		
+		
+	# Equal and opposite of mapPropNameID: Map ALL property **IDs** to their names
+	# Return: propMap: (propID, propName) tuples dictionary
+	def mapAssocIDName(self):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		propMap = {}
+		
+		cursor.execute("SELECT `APropertyID`, `APropName` FROM `Assoc_Prop_Type_tbl` WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			pID = int(result[0])
+			pName = result[1]
+			propMap[pID] = pName
+			
+		return propMap
+			
+	
+	# Map database property aliases to their property IDs
+	# Return: (alias, propID) dictionary
+	def mapAssocAliasID(self):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		aliasMap = {}
+		
+		cursor.execute("SELECT `alias`, `APropertyID` FROM `Assoc_Prop_Type_tbl` WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			alias = result[0]
+			propID = int(result[1])
+			aliasMap[alias] = propID
+			
+		return aliasMap
+
+
+	# Map database property IDs to their aliases 
+	# Return: (propID, alias) dictionary
+	def mapAssocIDAlias(self):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		aliasMap = {}
+		
+		cursor.execute("SELECT `alias`, `APropertyID` FROM `Assoc_Prop_Type_tbl` WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			alias = result[0]
+			propID = int(result[1])
+			aliasMap[propID] = alias
+			
+		return aliasMap
+
+
+	# Map property names to their database aliases
+	# Return: (propName, alias) dictionary
+	def mapAssocNameAlias(self):
+
+		db = self.db
+		cursor = self.cursor
+		
+		aliasMap = {}
+		
+		cursor.execute("SELECT `alias`, `APropName` FROM `Assoc_Prop_Type_tbl` WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			alias = result[0]
+			propName = result[1]
+			aliasMap[propName] = alias
+			
+		return aliasMap
+
+
+	# Map aliases to full property names
+	# Return: (alias, propName) dictionary
+	def mapAssocAliasName(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		aliasMap = {}
+		
+		cursor.execute("SELECT `alias`, `APropName` FROM `Assoc_Prop_Type_tbl` WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			alias = result[0]
+			propName = result[1]
+			aliasMap[alias] = propName
+			
+		return aliasMap
+		
+		
+	def mapAssocNameDescription(self):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		propMap = {}
+		
+		cursor.execute("SELECT APropName, description FROM Assoc_Prop_Type_tbl WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			pName = result[0]
+			pDescr = result[1]
+			
+			propMap[pName] = pDescr
+			
+		return propMap
+		
+	
+	# Note Feb. 11/10: remember, this function returns a map of (parent type ID, assocPropID) tuples, not the other way around as the name suggests
+	def mapAssocIDParentType(self):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		propMap = {}
+		
+		cursor.execute("SELECT APropertyID, assocTypeID FROM Assoc_Prop_Type_tbl WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			assocPropID = int(result[0])
+			pTypeID = int(result[1])
+			
+			propMap[pTypeID] = assocPropID
+			
+		return propMap
+	
+	
+	# Feb. 11/10: equal and opposite of mapAssocIDParentType, returns a dictionary of (assocPropID, parent type ID) tuples
+	def mapParentTypeAssocID(self):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		propMap = {}
+		
+		cursor.execute("SELECT APropertyID, assocTypeID FROM Assoc_Prop_Type_tbl WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			assocPropID = int(result[0])
+			pTypeID = int(result[1])
+			
+			propMap[assocPropID] = pTypeID
+			
+		return propMap
+	
+	
+	
+	# Creates a map between reagent association type name and ID, i.e. links 'ATypeID' and 'association' columns of AssocType_tbl
+	# e.g. '6' --> "Insert Parent Vector"
+	def mapAssocTypeIDName(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		assocTypeMap = {}
+		
+		cursor.execute("SELECT ATypeID, association FROM AssocType_tbl WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			assocTypeID = int(result[0])
+			assocTypeName = result[1]
+			
+			assocTypeMap[assocTypeID] = assocTypeName
+			
+		return assocTypeMap
+		
+		
+	# Returns: (assocTypeName, assocTypeID) dictionary
+	def mapAssocTypeNameID(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		assocTypeMap = {}
+		
+		cursor.execute("SELECT ATypeID, association FROM AssocType_tbl WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			assocTypeID = int(result[0])
+			assocTypeName = result[1]
+			
+			assocTypeMap[assocTypeName] = assocTypeID
+			
+		return assocTypeMap
+			
+	
+	# Map APropName to ATypeID	
+	# Returns a dictionary containing (Assoc_Prop_Type_tbl.APropertyID, AssocType_tbl.ATypeID) tuples
+	# This is needed when a new association needs to be created for a reagent, but its ATypeID is not given and needs to be determined based on APropName provided
+	# E.g. if an Insert was created without any associations, and now user wants to assign oligos and IPV to this Insert, s/he passes APropertyID '5' ("sense oligo id") to association creation function
+	# The resulting association will then be assigned an ATypeID of 4 (Insert Oligos)
+	# These associations, however, need to be explicitly hard-coded -- they cannot be determined automatically
+	# This matching is only necessary for Inserts and Cell Lines - not needed for Vectors and Oligos
+	def mapAssocPropType(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		# (association, ATypeID) from AssocType_tbl
+		assocTypeMap = self.mapAssocTypeNameID()
+		
+		# (APropName, APropertyID) from Assoc_Prop_Type_tbl
+		assocPropMap = self.mapAssocNameID()
+		
+		# Resulting (APropertyID, ATypeID) map
+		# The keys are unique and can be traced back to only one reagent type
+		assocPropTypeMap = {}
+		
+		# Inserts
+		assocPropTypeMap[assocPropMap["insert parent vector id"]] = assocTypeMap["Insert Parent Vector"]
+		assocPropTypeMap[assocPropMap["sense oligo"]] = assocTypeMap["Insert Oligos"]
+		assocPropTypeMap[assocPropMap["antisense oligo"]] = assocTypeMap["Insert Oligos"]
+		
+		# Cell Lines
+		assocPropTypeMap[assocPropMap["cell line parent vector id"]] = assocTypeMap["CellLine Stable"]
+		assocPropTypeMap[assocPropMap["parent cell line id"]] = assocTypeMap["CellLine Stable"]
+
+		return assocPropTypeMap
+		
+
+#########################################################################################################
+# Handler mapping between reagent type id, prefix and name
+#########################################################################################################
+class ReagentTypeMapper(Mapper):
+	"Maps associations between reagent types, prefixes and internal database IDs"
+	
+	# Maps reagent type ID to its prefix {1:V, 2:I, 3:O, 4:C}
+	def mapTypeIDPrefix(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		typeMap = {}
+		
+		cursor.execute("SELECT reagentTypeID, reagent_prefix FROM ReagentType_tbl WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			rTypeID = int(result[0])
+			prefix = result[1]
+			typeMap[rTypeID] = prefix
+		
+		return typeMap
+		
+		
+	# Conversely, maps reagent prefix to its ID
+	def mapTypePrefixID(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		typeMap = {}
+		
+		cursor.execute("SELECT reagentTypeID, reagent_prefix FROM ReagentType_tbl WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			rTypeID = int(result[0])
+			prefix = result[1]
+			typeMap[prefix] = rTypeID
+		
+		return typeMap
+			
+	
+	# Maps reagent type ID to its name (1:Vector, 2:Insert, 3:Oligo, 4:Cell Line)
+	def mapTypeIDName(self):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		typeMap = {}
+		
+		cursor.execute("SELECT reagentTypeID, reagentTypeName FROM ReagentType_tbl WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			rTypeID = int(result[0])
+			rTypeName = result[1]
+			typeMap[rTypeID] = rTypeName
+		
+		return typeMap
+		
+	
+	# Maps reagent type name to its ID
+	def mapTypeNameID(self):
+
+		db = self.db
+		cursor = self.cursor
+		
+		typeMap = {}
+		
+		cursor.execute("SELECT reagentTypeID, reagentTypeName FROM ReagentType_tbl WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			rTypeID = int(result[0])
+			rTypeName = result[1]
+			typeMap[rTypeName] = rTypeID
+		
+		return typeMap
+		
+	
+	# Maps reagent type names to prefixes: {Vector:'V', Insert:'I', Oligo:'O', Cell Line:'C'}
+	def mapTypeNamePrefix(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		typeMap = {}
+		
+		cursor.execute("SELECT reagentTypeName, reagent_prefix FROM ReagentType_tbl WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			rTypeName = result[0]
+			prefix = result[1]
+			typeMap[rTypeName] = prefix
+		
+		return typeMap
+		
+		
+	# Maps reagent type prefixes to names
+	def mapTypePrefixName(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		typeMap = {}
+		
+		cursor.execute("SELECT reagent_prefix, reagentTypeName FROM ReagentType_tbl WHERE `status`='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			rTypeName = result[0]
+			prefix = result[1]
+			typeMap[prefix] = rTypeName
+		
+		return typeMap
+
+
+	# March 26/07, Marina: Map the given reagent type to its association property aliases
+	# E.g. if type is Vector, its assoc prop aliases are insert_id, parent_vector_id, insert_parent_vector_id
+	def mapTypeAssocAlias(self, rTypeID):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		typeAssocAliasMap = {}
+		
+		cursor.execute("SELECT alias FROM Assoc_Prop_Type_tbl WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+
+		for result in results:
+			typeAssocAliasMap[rTypeID] = result[0]
+
+		return typeAssocAliasMap
+
+
+#########################################################################################################
+# User Category Mapper
+# Maps associations between user categories (access privileges) - their names and internal IDs
+#########################################################################################################
+class UserCategoryMapper(Mapper):
+
+	# Returns (categoryID, categoryName) dictionary
+	# E.g. (4, 'Guest')
+	def mapCategoryIDToName(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		categoryIDNameMap = {}
+		
+		cursor.execute("SELECT categoryID, category FROM UserCategories_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			catID = int(result[0])
+			catName = result[1]
+		
+			categoryIDNameMap[catID] = catName
+			
+		return categoryIDNameMap
+
+
+	# Returns (category, categoryID) map
+	# E.g. ('Admin', 1)
+	def mapCategoryNameToID(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		categoryNameIDMap = {}
+		
+		cursor.execute("SELECT category, categoryID FROM UserCategories_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			catName = result[0]
+			catID = int(result[1])
+			
+			categoryNameIDMap[catName] = catID
+			
+		return categoryNameIDMap
+
+
+
+#########################################################################################################
+# January 13, 2010
+# Maps associations between Prep properties
+#########################################################################################################
+class PrepPropertyMapper(Mapper):
+	
+	def mapPrepPropIDToName(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		prepPropMap = {}
+		
+		cursor.execute("SELECT elementTypeID, propertyName FROM PrepElemTypes_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			prepPropID = int(result[0])
+			prepPropName = result[1]
+			
+			prepPropMap[prepPropID] = prepPropName
+			
+		return prepPropMap
+		
+		
+	def mapPrepPropNameToID(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		prepPropMap = {}
+		
+		cursor.execute("SELECT elementTypeID, propertyName FROM PrepElemTypes_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			prepPropID = int(result[0])
+			prepPropName = result[1]
+			
+			prepPropMap[prepPropName] = prepPropID
+			
+		return prepPropMap
+
+
+	def mapPrepPropNameToDescr(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		prepPropMap = {}
+		
+		cursor.execute("SELECT propertyName, PrepElementDesc FROM PrepElemTypes_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			prepPropName = result[0]
+			prepPropDescr = result[1]
+			
+			prepPropMap[prepPropName] = prepPropDescr
+			
+		return prepPropMap
+		
+# August 20, 2010
+class SystemModuleMapper(Mapper):
+	
+	def mapPageNameLink(self):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		nameLinkMap = {}
+		
+		cursor.execute("SELECT section, baseURL FROM SecuredPages_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			section = result[0]
+			link = result[1]
+			
+			nameLinkMap[section] = link
+			
+		return nameLinkMap
+
+
+# June 9, 2011
+class ContainerTypeMapper(Mapper):
+
+	def mapContainerTypeNameToID(self):
+		db = self.db
+		cursor = self.cursor
+		
+		contTypeNameIDMap = {}
+
+		cursor.execute("SELECT contGroupID, contGroupName FROM ContainerGroup_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+
+		for result in results:
+			contGroupID = int(result[0])
+			contGroupName = result[1]
+
+			contTypeNameIDMap[contGroupName] = contGroupID
+
+		return contTypeNameIDMap
+
+
+	def mapContainerTypeIDToName(self):
+		db = self.db
+		cursor = self.cursor
+		
+		contTypeIDNameMap = {}
+
+		cursor.execute("SELECT contGroupID, contGroupName FROM ContainerGroup_tbl WHERE status='ACTIVE'")
+		results = cursor.fetchall()
+
+		for result in results:
+			contGroupID = int(result[0])
+			contGroupName = result[1]
+
+			contTypeIDNameMap[contGroupID] = contGroupName
+
+		return contTypeIDNameMap
\ No newline at end of file
diff --git a/OpenFreezer/cgi/oligos_vector_map.py b/OpenFreezer/cgi/oligos_vector_map.py
new file mode 100755
index 0000000..20ff9ac
--- /dev/null
+++ b/OpenFreezer/cgi/oligos_vector_map.py
@@ -0,0 +1,922 @@
+#!/usr/local/bin/python
+
+#import reportlab
+
+#from reportlab.graphics.shapes import *
+#from reportlab.graphics.charts.doughnut import Doughnut
+#from reportlab.graphics import widgetbase
+#from reportlab.graphics import renderPDF
+#from reportlab.lib import *
+
+import reportlab
+import math
+import random
+
+from reportlab.pdfgen import canvas, pathobject
+from reportlab.pdfgen.canvas import *
+from reportlab.pdfgen.pathobject import *
+
+from reportlab.graphics import renderPDF
+from reportlab.graphics.shapes import *
+
+from reportlab.lib.units import cm
+from reportlab.lib.colors import *
+
+import cgi
+import cgitb; cgitb.enable()
+
+import MySQLdb
+import sys
+import os
+import stat
+import string
+
+from database_conn import DatabaseConn		# april 20/07
+from exception import *
+import utils
+
+from mapper import ReagentPropertyMapper, ReagentAssociationMapper, ReagentTypeMapper
+from general_handler import *
+from reagent_handler import *
+from comment_handler import CommentHandler
+#from system_set_handler import SystemSetHandler
+from sequence_handler import DNAHandler, ProteinHandler
+
+from reagent import Reagent, Vector
+from sequence_feature import SequenceFeature
+
+# User and Project info
+from user_handler import UserHandler
+from project_database_handler import ProjectDatabaseHandler
+from session import Session
+
+# make global??
+dbConn = DatabaseConn()
+db = dbConn.databaseConnect()
+hostname = dbConn.getHostname()
+cursor = db.cursor()
+
+# Handlers and Mappers
+aHandler = AssociationHandler(db, cursor)
+rHandler = ReagentHandler(db, cursor)
+iHandler = InsertHandler(db, cursor)
+raHandler = ReagentAssociationHandler(db, cursor)
+sHandler = DNAHandler(db, cursor)
+pHandler = ReagentPropertyHandler(db, cursor)
+packetHandler = ProjectDatabaseHandler(db, cursor)
+uHandler = UserHandler(db, cursor)
+rtPropHandler = ReagentTypePropertyHandler(db, cursor)
+
+oHandler = OligoHandler(db, cursor)
+
+propMapper = ReagentPropertyMapper(db, cursor)
+aMapper = ReagentAssociationMapper(db, cursor)
+rMapper = ReagentTypeMapper(db, cursor)
+
+# Various maps
+reagentType_Name_ID_Map =  rMapper.mapTypeNameID()
+reagentType_ID_Name_Map = rMapper.mapTypeIDName()
+
+assoc_Type_Name_Map = aMapper.mapAssocTypeNameID()
+assoc_Name_Alias_Map = aMapper.mapAssocNameAlias()
+assoc_Name_Type_Map = aMapper.mapAssocTypeNameID()
+
+prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+prop_ID_Name_Map = propMapper.mapPropIDName()		# (prop id, prop name)
+prop_Name_Alias_Map = propMapper.mapPropNameAlias()	# (propName, propAlias)
+prop_Alias_Name_Map = propMapper.mapPropAliasName()	# (propAlias, propName)
+prop_Alias_ID_Map = propMapper.mapPropAliasID()		# (propAlias, propID) - e.g. ('insert_type', '48')
+
+prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+
+featureNameColorMap = propMapper.mapFeatureNameColor()
+
+#print `featureNameColorMap`
+
+# Get enzymes list for mapping sequence features
+enzDict = utils.join(sHandler.sitesDict, sHandler.gatewayDict)
+enzDict = utils.join(enzDict, sHandler.recombDict)	# add LoxP
+enzDict['None'] = ""					# add 'None'
+
+# currUser is an INT user ID
+def getCurrentUserProjects(currUser):
+	
+	#print "Content-type:text/html"
+	#print
+	
+	# get projects user has AT LEAST Read access to (i.e. if he is explicitly declared a Writer on a project but not declared a Reader, that's allowed)
+	currReadProj = packetHandler.findMemberProjects(currUser, 'Reader')
+	currWriteProj = packetHandler.findMemberProjects(currUser, 'Writer')
+	publicProj = packetHandler.findAllProjects(isPrivate="FALSE")
+	
+	# list of Packet OBJECTS
+	currUserWriteProjects = utils.unique(currReadProj + currWriteProj + publicProj)
+	
+	if currUser == 1:
+		privateProjects = packetHandler.findAllProjects("TRUE")
+		currUserWriteProjects = utils.unique(privateProjects + publicProj)
+		
+	uPackets = []
+	
+	for p in currUserWriteProjects:
+		uPackets.append(p.getNumber())
+
+	return uPackets
+
+
+def drawMap():
+	
+	dbConn = DatabaseConn()
+	db = dbConn.databaseConnect()
+	
+	cursor = db.cursor()
+	hostname = dbConn.getHostname()
+	root_path = dbConn.getRootDir()
+	
+	form = cgi.FieldStorage(keep_blank_values="True")
+	
+	#print "Content-type:text/html"
+	#print
+	#print `form`
+	
+	if form.has_key("rID"):
+		rID = form.getvalue("rID")
+	else:	# script executed from command line
+		# Worst-case scenarios
+		#rID = 260	# V260
+		#rID = 230	# V260
+		#rID = 80	# V80 - ok
+		#rID = 69661	# V2412 - not bad at all, just one of the oligos overlaps exactly with promoter (1 nt difference)
+		#rID = 23999 	# V59541
+		rID = 97918
+		#print rID
+
+	if form.has_key("user_id_hidden"):
+		userID = form.getvalue("user_id_hidden")
+	else:	# command-line execution
+		userID = 1	# debug
+
+	reagentID = rHandler.convertDatabaseToReagentID(rID)
+	
+	uPackets = getCurrentUserProjects(userID)
+	
+	#print "Content-type:text/html"
+	#print
+	#print reagentID
+	uPackets.sort()
+	#print `uPackets`
+
+	namePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["name"], prop_Category_Name_ID_Map["General Properties"])
+	statusPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["status"], prop_Category_Name_ID_Map["General Properties"])
+	projectPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["packet id"], prop_Category_Name_ID_Map["General Properties"])
+	
+	rName = rHandler.findSimplePropertyValue(rID, namePropID)
+	rTypeID = rHandler.findReagentTypeID(rID)
+	
+	try:
+		os.remove(root_path + "Reagent/vector_maps/" + reagentID + "_Oligo_map.pdf")
+	except OSError:
+		pass
+	
+	#print root_path
+	
+	c = Canvas(root_path + "Reagent/vector_maps/" + reagentID + "_Oligo_map.pdf")
+	
+	c.setPageSize((1500,1500))
+	c.setStrokeColorRGB(0,0,0)
+	c.saveState()
+	
+	# Draw circle
+	origin = 0
+	origin_x = 750
+	origin_y = 750
+	radius = 200
+	
+	c.circle(origin_x, origin_y, radius)
+	c.restoreState()
+	
+	# Divide circle into 100-unit sectors
+	rSeqID = rHandler.findDNASequenceKey(rID)
+	rSeq = sHandler.findSequenceByID(rSeqID)
+	seqLen = len(rSeq)
+	
+	#print "Content-type:text/html"
+	#print
+	#print `rID`
+	
+	unit_angle_measure = float(360) / float(seqLen)
+	#print unit_angle_measure
+	
+	# Mark 1 on the circle - KEEP, Karen said!
+	c.setLineWidth(1)
+	c.setStrokeColor(black)
+	c.setFillColor(black)
+	c.saveState()
+
+	path = c.beginPath()
+	
+	# Draw a triangle pointing down above the circle
+	#path.moveTo(origin_x, origin_y+radius+7)
+	#path.lineTo(origin_x-5, origin_y+radius+14)
+	#path.lineTo(origin_x+5, origin_y+radius+14)
+	#path.lineTo(origin_x, origin_y+radius+7)
+	
+	# Draw a triangle pointing up inside the circle
+	#path.moveTo(origin_x, origin_y+radius-10)
+	#path.lineTo(origin_x-5, origin_y+radius-14)
+	#path.lineTo(origin_x+5, origin_y+radius-14)
+	#path.lineTo(origin_x, origin_y+radius-10)
+	
+	# Draw a triangle pointing right inside the circle
+	path.moveTo(origin_x, origin_y+radius-14)
+	path.lineTo(origin_x, origin_y+radius-28)
+	path.lineTo(origin_x+8, origin_y+radius-21)
+	path.lineTo(origin_x, origin_y+radius-14)
+	c.drawPath(path, True, True)
+	
+	# label 1
+	t = c.beginText()
+	t.setStrokeColor(black)
+	t.setFillColor(black)
+	t.setFont("Helvetica-Bold", 16)
+	#t.setTextOrigin(origin_x-5, origin_y+radius+19)	# above circle
+	t.setTextOrigin(origin_x-3, origin_y+radius-50)	# above circle
+	t.textOut("1")
+	c.drawText(t)
+	
+	c.restoreState()
+
+	# Calculate feature segment sizes
+	sequenceFeatures = rHandler.findReagentSequenceFeatures(rID)
+	#print `sequenceFeatures`
+
+	# Draw legend
+	ox_legend = 1280
+	oy_legend = 1465
+	
+	prev_legend = oy_legend
+	
+	# draw frame
+	c.setStrokeColor(darkgray)
+	c.setFillColor(white)
+	c.saveState()
+	
+	featureNames = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, prop_Category_Name_ID_Map["DNA Sequence Features"])
+	featureNames.sort()
+
+	if len(featureNames) > 15:
+		origin_spacer = -19
+		coeff = 12
+	else:
+		origin_spacer = 65
+		coeff = 15
+	
+	origin_legend = prev_legend+origin_spacer-len(featureNames)*coeff
+	
+	x = (990 - origin_legend) / len(featureNames)
+	#print x
+	
+	if x < 12:
+		x = 12
+	
+	# WHEN WANT TO ADJUST LEGEND GREY BOX HEIGHT: UPDATE THE VALUE ADDED TO legend_height AND THE VALUE SUBTRACTED FROM origin_legend
+	legend_height = len(featureNames)*x + 55
+	
+	c.rect(ox_legend-25, origin_legend-35, 215, legend_height, 1, 1)	# good for specific rtype attributes
+	
+	c.restoreState()
+	
+	protocolPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protocol"], prop_Category_Name_ID_Map["Classifiers"])
+	seqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+	
+	sequenceFeatures = rHandler.findAllReagentFeatures(Vector(rID), rID)
+	
+	# Print reagent ID and size at the centre of the circle and print name at the top of the page
+	c.setFont("Helvetica-Bold", 32)
+	c.setFillColor(black)
+	c.saveState()
+	
+	c.drawCentredString(origin_x, origin_y+35, reagentID)
+	c.drawCentredString(origin_x, origin_y+10, "nt 1 - " + `seqLen`)
+	
+	if rName:
+		c.setFillColor(blue)	
+		c.drawCentredString(origin_x, 1415, rName)
+	
+	c.restoreState()
+	
+	# find all Oligos whose protocol is 'sequencing'
+	# April 26, 2010: Do not include status in this query, as it might just not be recorded for the oligo at all (early entries)
+	cursor.execute("SELECT r.reagentID, r.groupID, s.sequence FROM Sequences_tbl s, ReagentPropList_tbl p1, ReagentPropList_tbl p2, Reagents_tbl r WHERE p1.propertyID=" + `protocolPropID` + " AND p1.propertyValue='sequencing' AND p1.reagentID=r.reagentID AND r.reagentTypeID='3' AND p1.reagentID=p2.reagentID AND p2.propertyID=" + `seqPropID` + " AND p2.propertyValue=s.seqID AND p1.status='ACTIVE' AND p2.status='ACTIVE' AND r.status='ACTIVE' AND s.status='ACTIVE'")
+	
+	#print "SELECT r.reagentID, r.groupID, s.sequence FROM Sequences_tbl s, ReagentPropList_tbl p1, ReagentPropList_tbl p2, Reagents_tbl r WHERE p1.propertyID=" + `protocolPropID` + " AND p1.propertyValue='sequencing' AND p1.reagentID=r.reagentID AND r.reagentTypeID='3' AND p1.reagentID=p2.reagentID AND p2.propertyID=" + `seqPropID` + " AND p2.propertyValue=s.seqID AND p1.status='ACTIVE' AND p2.status='ACTIVE' AND r.status='ACTIVE' AND s.status='ACTIVE'"
+	
+	results = cursor.fetchall()
+	
+	rSeq = utils.squeeze(rSeq).lower()
+	#print rSeq
+	
+	oligoFeatures = []
+	
+	oligoIDsDict = {}	# O123 => 123
+	oligoNamesDict = {}	# 123 => "O123 Name"
+	oligoProjectDict = {}	# 123 => 7
+	
+	for result in results:
+		
+		if result:
+			oligoID = int(result[0])
+			groupID = int(result[1])
+			
+			oligo_lims_id = "O" + `groupID`
+			oligoIDsDict[oligo_lims_id] = oligoID
+			#print oligo_lims_id
+			
+			oligoName = rHandler.findSimplePropertyValue(oligoID, namePropID)
+			
+			# April 26, 2010, Karen's request: Ignore Oligos whose status is 'Failed' or 'Do Not Use'
+			oligoStatus = rHandler.findSimplePropertyValue(oligoID, statusPropID)
+
+			if oligoStatus:
+				#print oligoStatus
+				if oligoStatus.lower() == 'failed' or oligoStatus.lower() == 'do not use':
+					continue
+			
+			if oligoName:
+				oligoNamesDict[oligoID] = oligoName
+			else:
+				oligoNamesDict[oligoID] = ""
+			
+			#cursor.execute("SELECT propertyValue FROM ReagentPropList_tbl WHERE reagentID=" + `oligoID` + " AND propertyID=" + `namePropID` + " AND status='ACTIVE'")
+			#result2 = cursor.fetchone()
+			
+			#if result2:
+				#oligoName = result2[0]
+				#oligoNamesDict[oligoID] = oligoName
+			#else:
+				#oligoNamesDict[oligoID] = ""
+			
+			# PROJECT - MUST CAST TO INT
+			oligoPacket = int(rHandler.findSimplePropertyValue(oligoID, projectPropID))
+			#print oligoPacket
+			
+			if oligoPacket:
+				if oligoPacket not in uPackets:
+					#print oligoPacket
+					continue
+			
+			#cursor.execute("SELECT propertyValue FROM ReagentPropList_tbl WHERE reagentID=" + `oligoID` + " AND propertyID=" + `projectPropID` + " AND status='ACTIVE'")
+			#result3 = cursor.fetchone()
+			
+			#if result3:
+				#oligoPacket = int(result3[0])
+				##print oligoPacket
+				
+				#if oligoPacket not in uPackets:
+					##print oligoPacket
+					#continue
+				
+				#oligoProjectDict[oligoID] = oligoPacket
+			#else:
+				#oligoProjectDict[oligoID] = 0
+			
+			if len(result) == 3:
+				oligoSeq = result[2].strip().lower()
+				#print oligoSeq
+				
+				tm = sHandler.calculateTm(oligoSeq)
+				
+				# Changes made April 26, 2010: Karen caught that the sense/antisense check does not work for T3 and T7 vectors and said to check oligo sequence both ways
+				#if rSeq.find(oligoSeq) < 0:
+					#continue
+					
+				if rSeq.find(oligoSeq) >= 0:
+					fStart = rSeq.find(oligoSeq) + 1
+					fEnd = fStart + len(oligoSeq) - 1
+					
+					#if oHandler.isSenseOligo(oligoID):
+					oFeature = SequenceFeature("sequencing primer", oligo_lims_id, fStart, fEnd, 'forward', oligoSeq, tm)
+					#else:
+						#oFeature = SequenceFeature("sequencing primer", oligo_lims_id, fStart, fEnd, 'reverse', oligoSeq, tm)
+					
+				else:
+					revSeq = sHandler.reverse_complement(oligoSeq)
+					
+					if rSeq.find(revSeq) < 0:
+						continue
+					
+					fStart = rSeq.find(revSeq) + 1
+					fEnd = fStart + len(revSeq)
+					
+					# Note: start pos > end pos, as we're talking about reverse Oligo sequence
+					revStart = fEnd - 1
+					revEnd = fStart
+				
+					# Still, record sense/antisense for displaying on the map ('forward' and 'reverse' here are just static values in Feature class, it doesn't reflect sequence orientation in our case - just use as a temporary placeholder)
+					#if oHandler.isSenseOligo(oligoID):
+						#oligoFeatures.append(oFeature)
+						#oFeature = SequenceFeature("sequencing primer", oligo_lims_id, revStart, revEnd, 'forward', oligoSeq, tm)
+					#else:
+					oFeature = SequenceFeature("sequencing primer", oligo_lims_id, revStart, revEnd, 'reverse', oligoSeq, tm)
+				
+				oligoFeatures.append(oFeature)
+	
+				sequenceFeatures.append(oFeature)
+
+	# SORT features by size, so that short features are not hidden behind the long ones
+	fSizes = []
+	sortedFeatures = []
+	
+	fSortedPos = {}
+	
+	fStartPos = []
+	fEndPos = []
+	
+	for feature in sequenceFeatures:
+		fSize = int(feature.getFeatureSize())
+		
+		if fSize > 0:
+			fSizes.append(fSize)
+		
+		#if fSize > 150:
+		f_start_tmp = int(feature.getFeatureStartPos())
+		fStartPos.append(f_start_tmp)
+		
+		fSortedPos[f_start_tmp] = feature
+	
+		f_end_tmp = int(feature.getFeatureEndPos())
+		fEndPos.append(f_end_tmp)
+		
+	
+	fEndPos.sort()
+	fStartPos.sort()
+	
+	#print `fStartPos`
+	#print `fEndPos`
+	
+	fSizes.sort(reverse=True)
+	#print `fSizes`
+	
+	for fs in fSizes:
+		for feature in sequenceFeatures:
+			fSize = feature.getFeatureSize()
+
+			# added existence check July 17/08 - different features may have same sizes so end up with duplicate features in list (e.g. cloning sizes appeared twice on the map)
+			if fs == fSize and feature not in sortedFeatures:
+				sortedFeatures.append(feature)
+	
+	# Order: 5' site, 3' site, 5' linker, 3' linker, then the rest
+	sites_color = featureNameColorMap["5' cloning site"]		# same for 3' site
+	
+	# 5' site
+	c.setStrokeColor(sites_color)
+	c.setFillColor(sites_color)
+	c.saveState()
+	c.rect(ox_legend-15, prev_legend-20, 25,8, 1, 1)
+	c.restoreState
+	
+	t = c.beginText()
+	t.setStrokeColor(sites_color)
+	t.setFillColor(sites_color)
+	t.setFont("Helvetica-Bold", 10)
+	t.setTextOrigin(ox_legend+12, prev_legend-20)
+	t.textOut(" - " + "5' CLONING SITE")
+	c.drawText(t)
+	c.restoreState
+	
+	prev_legend = prev_legend-15
+	
+	# 3' site
+	c.setStrokeColor(sites_color)
+	c.setFillColor(sites_color)
+	c.saveState()
+	c.rect(ox_legend-15, prev_legend-20, 25,8, 1, 1)
+	c.restoreState
+	
+	t = c.beginText()
+	t.setStrokeColor(sites_color)
+	t.setFillColor(sites_color)
+	t.setFont("Helvetica-Bold", 10)
+	t.setTextOrigin(ox_legend+12, prev_legend-20)
+	t.textOut(" - " + "3' CLONING SITE")
+	c.drawText(t)
+	c.restoreState
+
+	prev_legend = prev_legend-15
+	
+	# Show legend for linkers
+	linkers_color = featureNameColorMap["5' linker"]
+	
+	# 5' linker
+	c.setStrokeColor(linkers_color)
+	c.setFillColor(linkers_color)
+	c.saveState()
+	c.rect(ox_legend-15, prev_legend-20, 25,8, 1, 1)
+	c.restoreState
+	
+	t = c.beginText()
+	t.setStrokeColor(linkers_color)
+	t.setFillColor(linkers_color)
+	t.setFont("Helvetica-Bold", 10)
+	t.setTextOrigin(ox_legend+12, prev_legend-20)
+	t.textOut(" - " + "5' LINKER")
+	c.drawText(t)
+	c.restoreState
+
+	prev_legend = prev_legend-15
+	
+	# 3' linker
+	c.setStrokeColor(linkers_color)
+	c.setFillColor(linkers_color)
+	c.saveState()
+	c.rect(ox_legend-15, prev_legend-20, 25,8, 1, 1)
+	c.restoreState
+	
+	t = c.beginText()
+	t.setStrokeColor(linkers_color)
+	t.setFillColor(linkers_color)
+	t.setFont("Helvetica-Bold", 10)
+	t.setTextOrigin(ox_legend+12, prev_legend-20)
+	t.textOut(" - " + "3' LINKER")
+	c.drawText(t)
+	c.restoreState
+
+	prev_legend = prev_legend-15
+	
+	# Output the rest of the features in alphabetical order
+	featureNames = featureNameColorMap.keys()
+	featureNames.sort()
+	
+	#print `featureNames`
+	
+	for featureName in featureNames:
+		#print featureName
+		if featureNameColorMap.has_key(featureName):
+			color = featureNameColorMap[featureName]
+			
+			if featureName != "5' cloning site" and featureName != "3' cloning site" and featureName != "5' linker" and featureName != "3' linker" and color != None:
+				#print featureName
+				c.setStrokeColor(color)
+				c.setFillColor(color)
+				c.saveState()
+				c.rect(ox_legend-15, prev_legend-20, 25,8, 1, 1)
+				c.restoreState
+				
+				t = c.beginText()
+				t.setStrokeColor(color)
+				t.setFillColor(color)
+				t.setFont("Helvetica-Bold", 10)
+				t.setTextOrigin(ox_legend+12, prev_legend-20)
+				t.textOut(" - " + featureName.upper())
+				c.drawText(t)
+				
+				c.restoreState
+				
+				prev_legend = prev_legend-15
+
+	# Sequencing Primer
+	oligoColor = "#7cfc00"
+	
+	c.setStrokeColor(oligoColor)
+	c.setFillColor(oligoColor)
+	c.saveState()
+	c.rect(ox_legend-15, prev_legend-20, 25,8, 1, 1)
+	c.restoreState
+	
+	t = c.beginText()
+	t.setStrokeColor(oligoColor)
+	t.setFillColor(oligoColor)
+	t.setFont("Helvetica-Bold", 10)
+	t.setTextOrigin(ox_legend+12, prev_legend-20)
+	t.textOut(" - " + "SEQUENCING PRIMER")
+	c.drawText(t)
+	c.restoreState
+
+	prev_legend = prev_legend-15
+	
+	ox_labels = 40
+	oy_labels = 40
+	#prev_legend = oy_labels
+	
+	for feature in sortedFeatures:
+		
+		fType = feature.getFeatureType()
+		fValue = feature.getFeatureName()
+		fSize = feature.getFeatureSize()
+		
+		#print fType
+		#print fValue
+		#print fSize
+		
+		# color
+		if featureNameColorMap.has_key(fType):
+			fColor = featureNameColorMap[fType]
+			textColor = fColor
+			
+		elif fType == 'sequencing primer':
+			fColor = "#7cfc00"
+			textColor = "black"
+
+			o_id = oligoIDsDict[fValue]
+			oligoName = oligoNamesDict[o_id]
+			
+			if len(oligoName) > 0:
+				fValue += " " + oligoName
+		
+		# property name
+		if fType == 'cdna insert':
+			fValue = "cDNA Insert"
+			
+		elif fType == 'promoter':
+			fValue = fValue + " " + fType
+		
+		fStart = feature.getFeatureStartPos()
+		fEnd = feature.getFeatureEndPos()
+		fDir = feature.getFeatureDirection()
+		
+		# value
+		#if fType == 'sequencing primer':
+		
+			#oligoDir = feature.getFeatureDirection()
+		
+			#if oligoDir == 'forward':
+				#oligoType = 'Sense'
+			#else:
+				#oligoType = 'Antisense'
+			
+			#fTxt = fValue + " (" + `fStart` + "-" + `fEnd` + "), " + oligoDir
+		#else:
+		
+		fTxt = fValue + " (" + `fStart` + "-" + `fEnd` + ")"
+			
+		if fSize > 0:
+			f_start = fStart * unit_angle_measure
+		
+			#print "Start " + `fStart`
+			#print "End " + `fEnd`
+		
+			startAngle = 90 - f_start
+			#print "Start angle " + `startAngle`
+			
+			f_end = fEnd * unit_angle_measure
+			endAngle = 90 - f_end
+			#print "End angle " + `endAngle`
+			
+			extAngle = -1*(f_end - f_start)
+			#print "Ext angle " + `extAngle`
+
+			x1 = origin_x - radius
+			y1 = origin_y - radius
+			
+			x2 = origin_x + radius
+			y2 = origin_y + radius
+			
+			p = c.beginPath()
+			
+			c.setLineWidth(10)
+			c.setLineJoin(1)
+			
+			c.setStrokeColor(fColor)
+			c.saveState()
+			
+			p.arc(x1, y1, x2, y2, startAngle, extAngle)
+			c.drawPath(p)
+			c.restoreState()
+			
+			# common to all
+			startAngle_rad = (startAngle * math.pi) / 180.0
+			endAngle_rad = (endAngle * math.pi) / 180.0
+			
+			c.setStrokeColor(fColor)
+			c.setFillColor(fColor)
+			c.setFont("Helvetica-Bold", 9)
+			c.saveState()
+			
+			arc_x_start = origin_x + (radius+5)*math.cos(startAngle_rad)
+			arc_y_start = origin_y + (radius+5)*math.sin(startAngle_rad)
+			
+			arc_x_end = origin_x+(radius+5)*math.cos(endAngle_rad)
+			arc_y_end = origin_y+(radius+5)*math.sin(endAngle_rad)
+			
+			# draw label
+			#c.setStrokeColorRGB(0,0,1)
+			#c.setFillColorRGB(0,0,1)
+			c.setStrokeColor(fColor)
+			c.setFillColor(fColor)
+			c.setFont("Helvetica-Bold", 12)
+			c.saveState()
+			
+			# draw line
+			delta = 45
+			
+			if fStart < seqLen/2:
+				
+				if arc_y_start > origin_y:
+					
+					# THIS WORKS!!!!
+					c.setStrokeColor(fColor)
+					c.setFillColor(fColor)
+					c.setLineWidth(1)
+					c.saveState()
+					
+					fInd = fStartPos.index(fStart)
+					fY = len(fStartPos) - fInd
+
+					c.line(arc_x_start, arc_y_start, arc_x_start+math.fabs(math.sin(delta))*(fInd*10), arc_y_start+math.fabs(math.cos(delta))*(fY*10))
+
+					#c.setStrokeColorRGB(0,0,1)
+					#c.setFillColorRGB(0,0,1)
+
+					c.setStrokeColor(textColor)
+					c.setFillColor(textColor)
+		
+					c.setFont("Helvetica-Bold", 8)
+					c.saveState()
+
+					#c.drawString(arc_x_start+math.fabs(math.sin(delta))*(fInd*10)+2, arc_y_start+math.fabs(math.cos(delta))*(fY*10)-math.cos(delta)*0.9, fValue + " (" + `fStart` + "-" + `fEnd` + ")")
+					
+					c.drawString(arc_x_start+math.fabs(math.sin(delta))*(fInd*10)+2, arc_y_start+math.fabs(math.cos(delta))*(fY*10)-math.cos(delta)*0.9, fTxt)
+
+					c.restoreState()
+					
+				else:
+					fInd = fStartPos.index(fStart)
+					fY = len(fStartPos) - fInd
+
+					c.setStrokeColor(fColor)
+					c.setFillColor(fColor)
+					c.setLineWidth(1)
+					c.saveState()
+					
+					c.line(arc_x_start, arc_y_start, arc_x_start+math.fabs(math.sin(delta))*(fY*10), arc_y_start-math.fabs(math.cos(delta))*(fInd*10))
+				
+					c.restoreState()
+					
+					#c.setStrokeColorRGB(0,0,1)
+					#c.setFillColorRGB(0,0,1)
+					
+					c.setStrokeColor(textColor)
+					c.setFillColor(textColor)
+		
+					c.setFont("Helvetica-Bold", 8)
+					c.saveState()
+				
+					#c.drawString(arc_x_start+math.fabs(math.sin(delta))*(fY*10)+2, arc_y_start-math.fabs(math.cos(delta))*(fInd*10)-math.cos(delta)*13, fValue + " (" + `fStart` + "-" + `fEnd` + ")")
+					
+					c.drawString(arc_x_start+math.fabs(math.sin(delta))*(fY*10)+2, arc_y_start-math.fabs(math.cos(delta))*(fInd*10)-math.cos(delta)*13, fTxt)
+					
+					c.restoreState()
+			else:
+				if arc_y_start > origin_y:
+					
+					fInd = fStartPos.index(fStart)
+					fY = len(fStartPos) - fInd
+
+					c.setStrokeColor(fColor)
+					c.setFillColor(fColor)
+					c.setLineWidth(1)
+					c.saveState()
+					
+					c.line(arc_x_start, arc_y_start, arc_x_start-math.fabs(math.sin(delta)*(fY*10)), arc_y_start+math.fabs(math.cos(delta)*(fInd*10)))
+					
+					c.restoreState()
+					
+					# draw label
+					#c.setStrokeColorRGB(0,0,1)
+					#c.setFillColorRGB(0,0,1)
+					
+					c.setStrokeColor(textColor)
+					c.setFillColor(textColor)
+		
+					c.setFont("Helvetica-Bold", 8)
+					c.saveState()
+					
+					#c.drawRightString(arc_x_start-math.fabs(math.sin(delta)*(fY*10))+2, arc_y_start+math.fabs(math.cos(delta)*(fInd*10)), fValue + " (" + `fStart` + "-" + `fEnd` + ")")
+					
+					c.drawRightString(arc_x_start-math.fabs(math.sin(delta)*(fY*10))+2, arc_y_start+math.fabs(math.cos(delta)*(fInd*10)), fTxt)
+					
+					c.restoreState()
+				else:
+					
+					fInd = fStartPos.index(fStart)
+					fY = len(fStartPos) - fInd
+
+					c.setStrokeColor(fColor)
+					c.setFillColor(fColor)
+					c.setLineWidth(1)
+					c.saveState()
+					
+					c.line(arc_x_start, arc_y_start, arc_x_start-math.fabs(math.sin(delta)*(fInd*10)), arc_y_start-math.fabs(math.cos(delta)*(fY*10)))
+				
+					c.restoreState()
+					
+					# draw label
+					#c.setStrokeColorRGB(0,0,1)
+					#c.setFillColorRGB(0,0,1)
+					
+					c.setStrokeColor(textColor)
+					c.setFillColor(textColor)
+
+					c.setFont("Helvetica-Bold", 8)
+					c.saveState()
+					
+					#c.drawRightString(arc_x_start-math.fabs(math.sin(delta)*(fInd*10))-2, arc_y_start-math.fabs(math.cos(delta)*(fY*10))-math.cos(delta)*12, fValue + " (" + `fStart` + "-" + `fEnd` + ")")
+					
+					c.drawRightString(arc_x_start-math.fabs(math.sin(delta)*(fInd*10))-2, arc_y_start-math.fabs(math.cos(delta)*(fY*10))-math.cos(delta)*12, fTxt)
+					
+					c.restoreState()
+
+	# print Oligo info
+	#prev_legend = prev_legend-10
+	prev_legend = 1365
+	
+	t = c.beginText()
+	t.setStrokeColor(black)
+	t.setFillColor(black)
+	t.setFont("Helvetica-Bold", 10)
+	t.setTextOrigin(ox_labels, prev_legend-15)
+	t.textOut("Sequencing primers for " + reagentID + ":")
+	c.drawText(t)
+	c.restoreState
+
+	prev_legend = prev_legend-18
+	
+	fColor = "#7cfc00"
+
+	# sort oligos
+	tmp_oligos = {}
+	
+	#print `oligoFeatures`
+	
+	for oFeature in oligoFeatures:
+		oligoID = oFeature.getFeatureName()
+		#print oligoID
+		oligoStart = oFeature.getFeatureStartPos()
+		#print oligoStart
+		
+		if tmp_oligos.has_key(oligoStart):
+			tmp_o_list = tmp_oligos[oligoStart]
+		else:
+			tmp_o_list = []
+			tmp_oligos[oligoStart] = oFeature
+		
+		tmp_o_list.append(oFeature)
+		tmp_oligos[oligoStart] = tmp_o_list
+		
+		oligoSeq = oFeature.getFeatureDescrType()
+		#print oligoSeq
+	
+	#print `tmp_oligos`
+
+	for oligoStart in sorted(tmp_oligos.keys()):
+		oFeatures = tmp_oligos[oligoStart]
+		
+		for oFeature in oFeatures:
+			oligoID = oFeature.getFeatureName()
+			#oligoSeq = oFeature.getFeatureDescrType()
+			oligoTm = oFeature.getFeatureDescrName()
+			oligoEnd = oFeature.getFeatureEndPos()
+			oligoDir = oFeature.getFeatureDirection()
+			
+			o_rID = oligoIDsDict[oligoID]
+			oligoName = oligoNamesDict[o_rID]
+			
+			#if oligoDir == 'forward':
+				#oligoType = 'Sense'
+			#else:
+				#oligoType = 'Antisense'
+			
+			c.setStrokeColor(fColor)
+			c.setFillColor(fColor)
+			c.saveState()
+			c.rect(ox_labels+5, prev_legend-15, 15,6, 1, 1)
+			c.restoreState
+		
+			t = c.beginText()
+			t.setStrokeColor(black)
+			t.setFillColor(black)
+			t.setFont("Helvetica-Bold", 10)
+			t.setTextOrigin(ox_labels+25, prev_legend-15)
+			
+			if len(oligoName) > 0:
+				#t.textOut(oligoID + ": " + oligoName + " (" + `oligoStart` + "-" + `oligoEnd` + ")" ", " + oligoType)
+				t.textOut(oligoID + ": " + oligoName + " (" + `oligoStart` + "-" + `oligoEnd` + ")" ", " + oligoDir)
+			else:
+				#t.textOut(oligoID + ": (" + `oligoStart` + "-" + `oligoEnd` + ")" ", " + oligoType)
+				t.textOut(oligoID + ": (" + `oligoStart` + "-" + `oligoEnd` + ")" ", " + oligoDir)
+			
+			#print oligoID + ": (" + `oligoStart` + "-" + `oligoEnd` + ")" ", " + oligoType
+			
+			c.drawText(t)
+			c.restoreState
+			prev_legend = prev_legend-15
+		
+			c.restoreState()
+	
+	c.showPage()
+	c.save()
+		
+	# Feb. 2/09: Change permissions
+	#os.chmod(root_path + "Reagent/vector_maps/" + reagentID + "_Oligo_map.pdf", stat.S_IMODE(stat.S_IRWXU | stat.S_IRWXO | stat.S_IRWXG))
+	
+drawMap()
\ No newline at end of file
diff --git a/OpenFreezer/cgi/packet.py b/OpenFreezer/cgi/packet.py
new file mode 100755
index 0000000..1b7ec41
--- /dev/null
+++ b/OpenFreezer/cgi/packet.py
@@ -0,0 +1,124 @@
+##############################################################
+# This module represents packets, or projects, in OpenFreezer 
+#
+# Written: May 25, 2007, by Marina Olhovsky
+# Last modified: July 16, 2007
+##############################################################
+class Packet:
+
+	__number = 0
+	__name = ""
+	__description = ""
+	__owner = None			# a User instance
+	__isEmpty = True		# are there reagents in this project?
+	__isPrivate = False		# private or public?
+	
+	# added June 20/07 - lists of User instances
+	__readers = []
+	__writers = []
+	
+	
+	# Constructor
+	def __init__(self, num = 0, name = "", descr = "", owner = "", isPrivate = False, readers=[], writers=[]):
+		self.__number = int(num)
+		self.__name = name
+		self.__description = descr
+		self.__owner = owner
+		self.__isEmpty = True		# make empty by default, can change later
+		self.__isPrivate = isPrivate
+		self.__readers = readers
+		self.__writers = writers
+		
+	
+	############################
+	# Assignment methods
+	############################
+
+	def setNumber(self, num):
+		self.__number = num
+		
+		
+	def setName(self, name):
+		self.__name = name
+		
+		
+	def setDescription(self, descr):
+		self.__description = descr
+		
+		
+	def setOwner(self, owner):
+		self.__owner = owner
+
+
+	def setReaders(self, readers):
+		self.__readers = readers
+		
+		
+	def setWriters(self, writers):
+		self.__writers = writers
+
+
+	# isPriv: Boolean, either True or False
+	def setPrivate(self, isPriv):
+		self.__isPrivate = privateOrPublic
+
+
+	############################
+	# Access methods
+	############################
+
+	def getNumber(self):
+		return self.__number
+		
+		
+	def getName(self):
+		return self.__name
+		
+		
+	def getDescription(self):
+		return self.__description
+		
+		
+	def getOwner(self):
+		return self.__owner
+
+	def getReaders(self):
+		return self.__readers
+		
+	def getWriters(self):
+		return self.__writers
+
+
+	################################
+	# Various functions
+	################################
+	
+	# Add 'member' to the list of readers for this project
+	# 'member': a User instance
+	def addReader(self, member):
+		self.__readers.append(member)
+	
+	
+	# Add 'member' as a writer to this project
+	# member: a User instance
+	def addWriter(self, member):
+		self.__writers.append(member)
+		
+		
+	# Add 'member' to this project in the given category
+	# member: User
+	# category: String, one of 'reader' or 'writer'
+	def addMember(self, member, category):
+		
+		if category == 'reader':
+			self.addReader(member)
+			
+		elif category == 'writer':
+			self.addWriter(member)
+
+	def isEmpty(self):
+		return len(self.__writers) == 0 and len(self.__readers) == 0
+		
+		
+	def isPrivate(self):
+		return self.__isPrivate
diff --git a/OpenFreezer/cgi/preload.py b/OpenFreezer/cgi/preload.py
new file mode 100755
index 0000000..b329fbe
--- /dev/null
+++ b/OpenFreezer/cgi/preload.py
@@ -0,0 +1,3879 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+
+import MySQLdb
+import sys
+import os
+import string
+import re
+
+from database_conn import DatabaseConn	# april 20/07 
+from exception import *
+import utils
+
+from mapper import ReagentPropertyMapper, ReagentAssociationMapper, ReagentTypeMapper
+
+# updated April 3/09 - added ReagentTypeHandler
+from general_handler import *
+from reagent_handler import ReagentHandler, InsertHandler
+from comment_handler import CommentHandler
+#from system_set_handler import SystemSetHandler
+from sequence_handler import DNAHandler, ProteinHandler
+
+from sequence_feature import SequenceFeature
+
+# User and Project info
+from user_handler import UserHandler
+from project_database_handler import ProjectDatabaseHandler
+from session import Session
+
+import Bio
+from Bio.Seq import Seq
+#from Bio import Enzyme
+from Bio.Restriction import *
+
+# make global??
+dbConn = DatabaseConn()
+db = dbConn.databaseConnect()
+hostname = dbConn.getHostname()
+cursor = db.cursor()
+
+# Handlers and Mappers
+aHandler = AssociationHandler(db, cursor)
+rHandler = ReagentHandler(db, cursor)
+iHandler = InsertHandler(db, cursor)
+raHandler = ReagentAssociationHandler(db, cursor)
+rtPropHandler = ReagentTypePropertyHandler(db, cursor)	# Aug. 31/09
+rtHandler = ReagentTypeHandler(db, cursor)		# April 3/09
+sHandler = DNAHandler(db, cursor)
+pHandler = ReagentPropertyHandler(db, cursor)
+packetHandler = ProjectDatabaseHandler(db, cursor)
+uHandler = UserHandler(db, cursor)
+sysHandler = SystemSetHandler(db, cursor)		# Dec. 1/08
+
+propMapper = ReagentPropertyMapper(db, cursor)
+aMapper = ReagentAssociationMapper(db, cursor)
+rMapper = ReagentTypeMapper(db, cursor)
+
+# Various maps
+reagentType_Name_ID_Map =  rMapper.mapTypeNameID()
+reagentType_ID_Name_Map = rMapper.mapTypeIDName()
+
+assoc_Type_Name_Map = aMapper.mapAssocTypeNameID()
+assoc_Name_Alias_Map = aMapper.mapAssocNameAlias()	# april 30/08
+
+# removed March 31, 2011: notice the variable assoc_Type_Name_Map two lines above - assigning the same function value to different variables???
+#assoc_Name_Type_Map = aMapper.mapAssocTypeNameID()	# june 2/08
+
+prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+prop_ID_Name_Map = propMapper.mapPropIDName()		# Added March 13/08 - (prop id, prop name)
+prop_Name_Alias_Map = propMapper.mapPropNameAlias()	# (propName, propAlias)
+prop_Alias_Name_Map = propMapper.mapPropAliasName()	# March 18/08 - (propAlias, propName)
+prop_Alias_ID_Map = propMapper.mapPropAliasID()		# (propAlias, propID) - e.g. ('insert_type', '48')
+
+prop_Alias_Descr_Map = propMapper.mapPropAliasDescription()
+
+prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+prop_Category_ID_Name_Map = propMapper.mapPropCategoryNameID()
+
+prop_Category_Alias_Name_Map = propMapper.mapPropCategoryAliasName()
+
+# Get enzymes list for mapping sequence features
+enzDict = utils.join(sHandler.sitesDict, sHandler.gatewayDict)
+enzDict = utils.join(enzDict, sHandler.recombDict)		# add LoxP
+enzDict['None'] = ""						# add 'None'
+
+###############################################################################################################################################
+
+# May 13/08: Action reused multiple times - make a separate function
+def getCurrentUserProjects(currUser):
+	
+	#print "Content-type:text/html"
+	#print
+	
+	# get projects user has AT LEAST Read access to (i.e. if he is explicitly declared a Writer on a project but not declared a Reader, that's allowed)
+	currReadProj = packetHandler.findMemberProjects(currUser.getUserID(), 'Reader')
+	currWriteProj = packetHandler.findMemberProjects(currUser.getUserID(), 'Writer')
+	publicProj = packetHandler.findAllProjects(isPrivate="FALSE")
+	
+	# list of Packet OBJECTS
+	currUserWriteProjects = utils.unique(currReadProj + currWriteProj + publicProj)
+	
+	uPackets = []
+	
+	for p in currUserWriteProjects:
+		uPackets.append(p.getNumber())
+
+	return uPackets
+	
+	
+def previewCellLineProperties(rID, rType, subtype, parents, currUser, db, cursor):
+	#print "Content-type:text/html"
+	#print
+	
+	if subtype == "stable_cell_line":
+		parentVectorID = parents[0]
+		parentCellLine = parents[1]
+		
+		# Get project IDs of parents
+		#packetPropID = pHandler.findPropID("packet id")
+		packetPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["packet id"], prop_Category_Name_ID_Map["General Properties"])
+		
+		# May 13/08
+		uPackets = getCurrentUserProjects(currUser)
+		
+		# parent vector
+		try:
+			pv_db_id = rHandler.convertReagentToDatabaseID(parentVectorID)
+			pvProjectID = int(rHandler.findSimplePropertyValue(pv_db_id, packetPropID))	# need to cast
+			
+			if currUser.getCategory() != 'Admin' and pvProjectID not in uPackets:
+			
+				i = PVProjectAccessException("You do not have read access to this project")
+		
+				clpvAssocProp = aHandler.findAssocPropID("cell line parent vector id")
+
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clpvAssocProp`)
+				
+			else:
+				# parent vector ok, check cell line
+				try:
+					cl_db_id = rHandler.convertReagentToDatabaseID(parentCellLine)
+					clProjectID = rHandler.findSimplePropertyValue(cl_db_id, packetPropID)
+					
+					if isinstance(clProjectID, (int)) and int(clProjectID) > 0:
+					#if clProjectID > 0:
+						clProjectID = int(clProjectID)
+						
+						if currUser.getCategory() != 'Admin' and clProjectID > 0 and clProjectID not in uPackets:
+							i = CLProjectAccessException("You do not have read access to this project")
+					
+							clAssocProp = aHandler.findAssocPropID("parent cell line id")
+			
+							utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clAssocProp`)
+						
+						else:
+							# user may view project, proceed
+							utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&CL=" + parentCellLine)
+
+					# disable access if project ID not set - will allow us to catch errors
+					#elif not isinstance(clProjectID, (int)) and currUser.getCategory() != 'Admin':
+					elif (clProjectID == None or clProjectID <= 0) and currUser.getCategory() != 'Admin':
+						i = CLProjectAccessException("You do not have read access to this project")
+				
+						clAssocProp = aHandler.findAssocPropID("parent cell line id")
+		
+						utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clAssocProp`)
+						
+					else:
+						# everything ok, proceed
+						utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&CL=" + parentCellLine)
+		
+				except ReagentDoesNotExistException:
+					i = ReagentDoesNotExistException("Parent Cell Line ID not found in database")
+					
+					# get "parent cell line" association type
+					clAssocProp = aHandler.findAssocPropID("parent cell line id")
+					
+					# "AP" stands for "Association Property"
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clAssocProp`)
+
+		except ReagentDoesNotExistException:
+			i = ReagentDoesNotExistException("Parent Vector ID not found in database")
+			
+			# get "parent vector" association type
+			clpvAssocProp = aHandler.findAssocPropID("cell line parent vector id")
+			
+			# "AP" stands for "Association Property"
+			utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clpvAssocProp`)
+
+
+# Specifically for Vectors: since this code is reused many times, make it a distinct function
+# Preload Vector properties based on its parent values, including newly generated sequence 
+# Written April 19, 2007; last modified June 1/08 by Marina Olhovsky
+# Updated Oct. 30/08: Added 'reverse_insert' parameter, default False to reverse complement the Insert sequence if necessary (most often if 5' occurs after 3' on PV)
+#
+# Update Jan. 21/09: Added 'reverse_complement' argument; Note the difference between 'reverse_insert' and 'reverse_complement': 'reverse_insert' is set to 'true' ***in response to an exception being thrown***, likely a "5' after 3'" exception, when returning from an error page.  'reverse_complement', on the other hand, is ***voluntary*** user input, e.g. in case of ** directional cloning ** - ** program does not report an error **, user chooses to put the Insert into vector in reverse o [...]
+def previewVectorSequence(rID, reagent, parents, currUser, db, cursor, sites=[], reverse_insert=False, reverse_complement=False):
+	
+	global aHandler
+	#global pHandler
+
+	#print "Content-type:text/html"
+	#print
+	#print "Reverse insert solution " + `reverse_insert`
+	#print "Reverse complement request " + `reverse_complement`
+	#print `sites`
+	
+	reverse = False		# Jan. 22/09
+	
+	# May 13/08
+	uPackets = getCurrentUserProjects(currUser)
+	#print `uPackets`
+	
+	# April 14/08: Create a new Reagent instance
+	rType = reagent.getType()
+	subtype = reagent.getSubtype()
+
+	# site property IDs - update July 2/09
+	fpcs_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	tpcs_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	
+	#fpcs_prop_id = prop_Name_ID_Map["5' cloning site"]	# removed July 2/09
+	#tpcs_prop_id = prop_Name_ID_Map["3' cloning site"]	# removed July 2/09
+
+	if subtype == 'nonrecomb' or subtype =='gateway_entry':
+		
+		pv_db_id = int(parents["vector parent id"])
+		insert_db_id = int(parents["insert id"])
+		
+		# still need the human-readable values for error handling
+		parentVectorID = rHandler.convertDatabaseToReagentID(pv_db_id)
+		insertID = rHandler.convertDatabaseToReagentID(insert_db_id)
+	
+		# April 14/08: Save association - May 5/08: IFF does not exist yet!!!!!!!!!!!!
+		assocID = raHandler.findReagentAssociationID(rID)
+		
+		if assocID <= 0:
+			aTypeID = assoc_Type_Name_Map["INSERT"]
+			assocID = rHandler.createReagentAssociation(rID, aTypeID)
+		
+		reagent.setCloningMethod(assocID)
+
+		pvAssocProp = aHandler.findAssocPropID("vector parent id")
+		insertAssocProp = aHandler.findAssocPropID("insert id")
+		
+		# August 21/07: Restrict parent selection by project - if a parent belongs to a project the creator does not have read access to, disallow creation
+		#packetPropID = pHandler.findPropID("packet id")
+		packetPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["packet id"], prop_Category_Name_ID_Map["General Properties"])
+		pvProjectID = int(rHandler.findSimplePropertyValue(pv_db_id, packetPropID))	# need to cast
+		
+		if currUser.getCategory() != 'Admin' and pvProjectID not in uPackets:
+			
+			i = PVProjectAccessException("You do not have read access to this project")
+	
+			# "AP" stands for "Association Property"
+			utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&AP=" + `pvAssocProp`)
+		
+		# Insert
+		# August 21/07: Restrict parent selection by project - if a parent belongs to a project the creator does not have read access to, disallow creation
+		#packetPropID = pHandler.findPropID("packet id")
+		
+		try:
+			insertProjectID = int(rHandler.findSimplePropertyValue(insert_db_id, packetPropID))	# need to cast
+		except (TypeError, ValueError, IndexError):
+			insertProjectID = 0
+			
+		if currUser.getCategory() != 'Admin' and insertProjectID not in uPackets:
+			i = InsertProjectAccessException("You do not have read access to this project")
+	
+			# "AP" stands for "Association Property"
+			utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&AP=" + `insertAssocProp`)
+			
+		# if projects OK save parents - DELETE ALL PREVIOUS INFORMATION!!!!!!!!!!!!
+		rHandler.deleteReagentAssociationProp(rID, pvAssocProp)
+		rHandler.addAssociationValue(rID, pvAssocProp, pv_db_id, assocID)
+		
+		rHandler.deleteReagentAssociationProp(rID, insertAssocProp)
+		rHandler.addAssociationValue(rID, insertAssocProp, insert_db_id, assocID)
+		
+		# AND, last but not least, the reason this is all being done - Construct a sequence for the new vector from the sequences of its parents
+		pvSeqKey = rHandler.findDNASequenceKey(pv_db_id)
+		pvSeq = sHandler.findSequenceByID(pvSeqKey)			# May 27/08
+		
+		insertSeqKey = rHandler.findDNASequenceKey(insert_db_id)
+		insertSeq = sHandler.findSequenceByID(insertSeqKey)		# May 14/08
+		
+		# Jan. 21/09
+		if reverse_complement:
+			#print "REVERSING INSERT!!!"
+			insertSeq = sHandler.reverse_complement(insertSeq)
+		
+		#print insertSeq
+		
+	# May 28/08
+	elif subtype == 'recomb' or subtype == 'gateway_expression':
+		
+		# Updated May 8/08
+		pv_db_id = int(parents["vector parent id"])
+		ipv_db_id = int(parents["parent insert vector"])
+		
+		# human-readable values for error handling
+		parentVector = rHandler.convertDatabaseToReagentID(pv_db_id)
+		insertParentVector = rHandler.convertDatabaseToReagentID(ipv_db_id)
+		
+		parentVectorID = parentVector
+		insertParentVectorID = insertParentVector
+		
+		# Associations
+		assocID = raHandler.findReagentAssociationID(rID)
+		
+		if assocID <= 0:
+			aTypeID = assoc_Type_Name_Map["LOXP"]
+			assocID = rHandler.createReagentAssociation(rID, aTypeID)
+		
+		reagent.setCloningMethod(assocID)
+
+		pvAssocProp = aHandler.findAssocPropID("vector parent id")
+		ipvAssocProp = aHandler.findAssocPropID("parent insert vector")
+		
+		# get internal db IDs
+		pv_db_id = rHandler.convertReagentToDatabaseID(parentVector)
+		ipv_db_id = rHandler.convertReagentToDatabaseID(insertParentVector)
+
+		# Restrict by packet
+		#packetPropID = pHandler.findPropID("packet id")
+		packetPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["packet id"], prop_Category_Name_ID_Map["General Properties"])
+		
+		# June 10/08: Add error catching for empty project IDs
+		try:
+			pvProjectID = int(rHandler.findSimplePropertyValue(pv_db_id, packetPropID))	# need to cast
+		except TypeError:
+			i = PVProjectAccessException("Invalid Parent Vector project ID")
+			
+			# get "parent vector" association type
+			aHandler = AssociationHandler(db, cursor)
+			pvAssocProp = aHandler.findAssocPropID("vector parent id")
+			
+			# "AP" stands for "Association Property"
+			utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `pvAssocProp`)
+		
+		try:
+			ipvProjectID = int(rHandler.findSimplePropertyValue(ipv_db_id, packetPropID))	# need to cast
+			
+		except TypeError:
+			i = PVProjectAccessException("Invalid Insert Parent Vector project ID")
+		
+			# get "parent vector" association type
+			aHandler = AssociationHandler(db, cursor)
+			ipvAssocProp = aHandler.findAssocPropID("parent insert vector")
+			
+			# "AP" stands for "Association Property"
+			utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `ipvAssocProp`)
+			
+			
+		if currUser.getCategory() != 'Admin' and pvProjectID not in uPackets:
+			i = PVProjectAccessException("You do not have read access to this project")
+	
+			# get "parent vector" association type
+			aHandler = AssociationHandler(db, cursor)
+			pvAssocProp = aHandler.findAssocPropID("vector parent id")
+			
+			# "AP" stands for "Association Property"
+			utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `pvAssocProp`)
+		
+		if currUser.getCategory() != 'Admin' and ipvProjectID not in uPackets:
+			i = IPVProjectAccessException("You do not have read access to this project")
+	
+			# get "parent vector" association type
+			aHandler = AssociationHandler(db, cursor)
+			ipvAssocProp = aHandler.findAssocPropID("parent insert vector")
+			
+			# "AP" stands for "Association Property"
+			utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `ipvAssocProp`)
+		
+		# if projects OK save parents - DELETE ALL PREVIOUS INFORMATION!!!!!!!!!!!!
+		rHandler.deleteReagentAssociationProp(rID, pvAssocProp)
+		rHandler.addAssociationValue(rID, pvAssocProp, pv_db_id, assocID)
+		
+		rHandler.deleteReagentAssociationProp(rID, ipvAssocProp)
+		rHandler.addAssociationValue(rID, ipvAssocProp, ipv_db_id, assocID)	
+		
+		# Get the Insert that belongs to the donor vector
+		ipvInsertAssocID = raHandler.findReagentAssociationID(ipv_db_id)
+		insertAssocPropID = aHandler.findAssocPropID("insert id")
+		insert_db_id = aHandler.findAssocPropValue(ipvInsertAssocID, insertAssocPropID)
+	
+		######################################################################################################################
+		# Sept. 11/08: This may occur if the IPV is of the wrong type - e.g. if user tries to input a GTW Expression Vector in place of a GTW Entry or a Creator Expression Vector instead of a Creator Donor.  Talked to Karen today and decided to disallow this.
+		
+		# June 3, 2010: Talked to Karen, Sunqu/Oliver, David Lye and Anthony Chiu about this extensively.  Final decision: It is NOT mandatory to have an Insert here.  Sunqu was using 2 recombination vectors to generate a Creator Expression Vector via site-directed mutagenesis; the IPV did not have an Insert directly associated with it.  David and Anthony used 2 Novel vectors to create a Gateway Expression vector.  Karen tested creating GW Expression vector by swapping the GW Entry and Parent  [...]
+		
+		######################################################################################################################
+		
+		# removed the 3 lines below on June 3, 2010 (don't throw exception and don't redirect to error page!)
+		#if insert_db_id < 0:
+			#i = ReagentTypeException("Wrong parent type")
+			#utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `pvAssocProp`)
+			
+			#############################################
+			# VERIFIED WITH KAREN AND REMOVED SEPT. 11/08
+			#############################################
+			
+			## June 1/08: Even though this shouldn't happen, the IPV provided may itself be a recombination vector; thus, an Insert is not explicitly stored for it, in which case need to go back an additional step and present the Insert from the IPV of this reagent (equivalent to cDNA Insert on detailed view)
+			#parent_ipv = aHandler.findAssocPropValue(ipvInsertAssocID, ipvAssocProp)
+			
+			#if parent_ipv > 0:
+				#parent_ipv_assoc_id = raHandler.findReagentAssociationID(parent_ipv)
+
+				#if parent_ipv_assoc_id > 0:
+					#ipv_insert_id = aHandler.findAssocPropValue(parent_ipv_assoc_id, insertAssocPropID)
+
+					#if ipv_insert_id > 0:
+						#insert_db_id = ipv_insert_id
+						#insertID = rHandler.convertDatabaseToReagentID(ipv_insert_id)
+					#else:
+						#utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector + "&Err=14&AP=" + `pvAssocProp`)
+				#else:
+					#utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector + "&Err=14&AP=" + `pvAssocProp`)
+			
+		#else:	# removed June 3, 2010
+			#insertID = rHandler.convertDatabaseToReagentID(insert_db_id)	# removed June 3, 2010
+			
+		# June 3, 2010: Instead:
+		if insert_db_id > 0:
+			insertID = rHandler.convertDatabaseToReagentID(insert_db_id)
+			
+			# moved this up here - see comment below
+			insertSeqKey = rHandler.findDNASequenceKey(insert_db_id)
+			insertSeq = sHandler.findSequenceByID(insertSeqKey)
+			
+		# AND, last but not least, the reason this is all being done - Construct a sequence for the new vector from the sequences of its parents
+		pvSeqKey = rHandler.findDNASequenceKey(pv_db_id)
+		ipvSeqKey = rHandler.findDNASequenceKey(ipv_db_id)
+		
+		# moving up June 3, 2010
+		#insertSeqKey = rHandler.findDNASequenceKey(insert_db_id)	# rmvd June 3, 2010
+		#insertSeq = sHandler.findSequenceByID(insertSeqKey)		# rmvd June 3, 2010
+		
+	# May 28/08: Common to all
+	# Fetch the Insert's cloning sites
+	insertCloningSites = []
+	
+	# Moved up here Feb. 11/09
+	fp_insert_cs = rHandler.findSimplePropertyValue(insert_db_id, fpcs_prop_id)
+	tp_insert_cs = rHandler.findSimplePropertyValue(insert_db_id, tpcs_prop_id)
+
+	if len(sites) > 0 and sites[0] and sites[1]:
+		insertCloningSites = sites
+		#print `insertCloningSites`
+	else:
+		# depends on vector type
+		# May 29/08: Need to add another round of validation to make sure sites match subtype (i.e. using an Insert with gateway sites to create a non-recomb Vector) - BUT it's low-priority; errors will be caught, sequence will not be generated, can worry about extra error output pages later
+		if subtype == 'nonrecomb':
+			
+			# Moved up Feb. 11/09
+			## get from Insert
+			#fp_insert_cs = rHandler.findSimplePropertyValue(insert_db_id, fpcs_prop_id)
+			#tp_insert_cs = rHandler.findSimplePropertyValue(insert_db_id, tpcs_prop_id)
+		
+			if fp_insert_cs:
+				insertCloningSites.append(fp_insert_cs)
+			else:
+				insertCloningSites.append("")
+				
+			if  tp_insert_cs:
+				insertCloningSites.append(tp_insert_cs)
+			else:
+				insertCloningSites.append("")
+				
+		elif subtype == 'recomb':
+			insertCloningSites.append("LoxP")
+			insertCloningSites.append("LoxP")
+			
+		elif subtype == 'gateway_entry':
+			insertCloningSites.append("attB1")
+			insertCloningSites.append("attB2")
+			
+		elif subtype == 'gateway_expression':
+			insertCloningSites.append("attL1")
+			insertCloningSites.append("attL2")
+	
+	#print `insertCloningSites`
+	
+	# get linkers if there are any
+	insertLinkers = []
+
+	# Update July 2/09
+	fpLinkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	tpLinkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	
+	#fpLinkerPropID = prop_Name_ID_Map["5' linker"]		# july 2/09
+	#tpLinkerPropID = prop_Name_ID_Map["3' linker"]		# july 2/09
+	
+	fp_insert_linker = rHandler.findSimplePropertyValue(insert_db_id, fpLinkerPropID)
+	tp_insert_linker = rHandler.findSimplePropertyValue(insert_db_id, tpLinkerPropID)
+	
+	# sept. 3/07 - needed to cast to string
+	fwd_linker = ""
+
+	if fp_insert_linker and len(fp_insert_linker) > 0 and fp_insert_linker != 0 and fp_insert_linker != '0':
+		fp_insert_linker = fwd_linker + fp_insert_linker
+	else:
+		fp_insert_linker = fwd_linker
+		
+	# April 24/08
+	if not tp_insert_linker or len(tp_insert_linker) == 0 or tp_insert_linker == 0 or tp_insert_linker == '0':
+		tp_insert_linker = ""
+		
+	insertLinkers.append(fp_insert_linker)
+	insertLinkers.append(tp_insert_linker)
+	
+	fp_linker_start = rHandler.findReagentFeatureStart(insert_db_id, fpLinkerPropID)
+	fp_linker_end = rHandler.findReagentFeatureEnd(insert_db_id, fpLinkerPropID)
+	
+	tp_linker_start = rHandler.findReagentFeatureStart(insert_db_id, tpLinkerPropID)
+	tp_linker_end = rHandler.findReagentFeatureEnd(insert_db_id, tpLinkerPropID)
+	
+	try:
+		# Call different sequence construction methods depending on vector subtype
+		if subtype == 'nonrecomb':
+			# Updated June 8/08
+			# First lookup by string matching; then compare to stored data and report inconsistencies
+			
+			# Check if sites are empty
+			if len(insertCloningSites[0]) == 0 or len(insertCloningSites[1]) == 0:
+				# Modified Feb. 12/09
+				i = EmptyCloningSitesException("")
+				err = i.err_code()
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `err` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])	
+
+			# Nov. 17/08: Added 'if' statements to catch hybrid sites
+			if enzDict.has_key(insertCloningSites[0]):			# nov. 17/08
+				fpSite = enzDict[insertCloningSites[0]].lower()
+				
+				fp_start = insertSeq.lower().find(fpSite) + 1
+				fp_end = fp_start + len(fpSite)
+				
+				# Dec. 17/08, Marina: Test tomorrow with degenerate sequences
+				orig_fp_start = rHandler.findReagentFeatureStart(insert_db_id, fpcs_prop_id)
+				orig_fp_end = rHandler.findReagentFeatureEnd(insert_db_id, fpcs_prop_id)
+				
+				#print orig_fp_end
+			else:
+				fpSite = insertCloningSites[0]
+				
+				fp_start = None
+				fp_end = None
+				
+				orig_fp_start = None
+				orig_fp_end = None
+				
+			if enzDict.has_key(insertCloningSites[1]):			# nov. 17/08
+				tpSite = enzDict[insertCloningSites[1]].lower()
+				
+				tp_start = insertSeq.lower().find(tpSite) + 1
+				tp_end = tp_start + len(tpSite) - 1
+				
+				orig_tp_start = rHandler.findReagentFeatureStart(insert_db_id, tpcs_prop_id)
+				orig_tp_end = rHandler.findReagentFeatureEnd(insert_db_id, tpcs_prop_id)
+
+			else:
+				tpSite = insertCloningSites[1]
+				
+				tp_start = None
+				tp_end = None
+				
+				orig_tp_start = None
+				orig_tp_end = None
+				
+			# Feb. 11/09 update: this check is valid IFF sites are not customized!
+			# Compare to site positions stored for this Insert
+			# Jan. 23/09: Positions WILL change if you reverse the Insert!
+			if not reverse_complement and not reverse_insert and fp_insert_cs == fpSite and tp_insert_cs == tpSite:
+				if fp_start and fp_end and tp_start and tp_end and orig_fp_start and orig_fp_end and orig_tp_start and orig_tp_end and orig_fp_start != fp_start and orig_fp_end != fp_end and orig_tp_start != tp_start and orig_tp_end != tp_end:
+					i = InsertSitePositionException("Insert site positions don't match")
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+
+			cdnaStart = iHandler.findCDNAStart(insert_db_id)
+			cdnaEnd = iHandler.findCDNAEnd(insert_db_id)
+
+			#if fp_start > 0 and tp_end > 0 and tp_end <= len(insertSeq):		# no, don't use this - will not redirect properly!
+			
+			# nov. 6/08
+			if sHandler.gatewayDict.has_key(insertCloningSites[0]) or sHandler.gatewayDict.has_key(insertCloningSites[1]) or sHandler.recombDict.has_key(insertCloningSites[0]) or sHandler.recombDict.has_key(insertCloningSites[1]):
+				# Non-recombination vector attempted with gateway or LoxP Insert - disallow
+				i = InsertSitesException("Wrong sites on Insert")
+				
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+			
+			try:
+				#print "HERE " + `reverse_insert`
+				#print insertSeq
+				
+				# Oct. 30/08
+				newSeq = sHandler.constructNonRecombSequence(pvSeqKey, insertSeq, insertCloningSites, reverse_insert)
+				newSeqID = int(sHandler.matchSequence(newSeq))
+	
+				if newSeqID <= 0:
+					newSeqID = int(sHandler.insertSequence(newSeq))
+		
+				# Jan. 21/09: Pass 'reverse' parameter to feature mapping function for correct remapping of features, particularly cDNA
+				if reverse_complement or reverse_insert:
+					reverse = True
+				
+				# Updated April 28/08: Implement multi-step creation process
+				# Updated Nov. 18/08: Added sites to URL to keep track of hybrids for feature mapping
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Step=1&Type=" + rType + "&Sub=" + subtype + "&PV=" + `pv_db_id` + "&I=" + `insert_db_id` + "&Seq=" + `newSeqID` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1] + "&Rev=" + `reverse`)
+				
+			except CloningSitesNotFoundInInsertException:
+				i = CloningSitesNotFoundInInsertException("Sites not found on Insert sequence")
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+				
+			except InsertSitesException:
+				i = InsertSitesException("Wrong sites on Insert")
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+			
+			except InsertSitesNotFoundOnParentSequenceException:
+				i = InsertSitesNotFoundOnParentSequenceException("Insert sites not found on parent vector sequence")
+				
+				if subtype == 'nonrecomb' or subtype == 'gateway_entry':
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+				else:				# added June 2/08
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+				
+			except MultipleSiteOccurrenceException:
+				i = MultipleSiteOccurrenceException("Site found more than once on parent vector sequence")
+				
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+				
+			except HybridizationException:
+				i = HybridizationException("Sites cannot be hybridized")
+				
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+			
+			# Dec. 14/09
+			except EmptyParentVectorSequenceException:
+				i = EmptyParentVectorSequenceException("Empty parent Vector sequence exception")
+			
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+				
+			except EmptyParentInsertSequenceException:
+				i = EmptyParentInsertSequenceException("Empty parent Insert sequence exception")
+			
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+				
+			except FivePrimeAfterThreePrimeException:
+				i = FivePrimeAfterThreePrimeException("5' site occurs after 3' site on parent vector sequence")
+				
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1] + "&Rev=" + `reverse_complement`)
+			
+			# March 10/10
+			except InsertFivePrimeAfterThreePrimeException:
+				i = InsertFivePrimeAfterThreePrimeException("5' site occurs after 3' site on Insert sequence")
+				
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1] + "&Rev=" + `reverse_complement`)
+				
+			# June 2/08
+			except InvalidDonorVectorSitesNotFoundException:
+				i = InvalidDonorVectorSitesNotFoundException("LoxP sites not found on donor sequence")
+		
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+				
+			except InvalidDonorVectorMultipleSitesException:
+				i = InvalidDonorVectorMultipleSitesException("LoxP sites occur more than twice on donor sequence")
+			
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+			
+			except InvalidDonorVectorSingleSiteException:
+				i = InvalidDonorVectorSingleSiteException("Donor vector sequence contains a singe LoxP site")
+				
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+			
+			except IncompatibleFivePrimeOverhangsException:
+				i = IncompatibleFivePrimeOverhangsException("")
+				
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+			
+			except IncompatibleThreePrimeOverhangsException:
+				i = IncompatibleThreePrimeOverhangsException("")
+				
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+			
+			#else:
+				## error
+				#utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=13&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+			
+		
+		elif subtype == 'gateway_entry':
+		
+			fpSite = "gtacaaaaaa"
+			
+			# Changed attB2 sequence Sept. 15/08
+			#tpSite = "tttcttgtaca"
+			tpSite = "tttcttgtac"
+
+			fp_start = insertSeq.lower().find(fpSite)
+			fp_end = fp_start + len(fpSite)
+			
+			tp_start = insertSeq.lower().rfind(tpSite)	# edited Sept. 15/08: look for 3' site from END of sequence??
+			#print tpSite
+			#print tp_start
+			
+			# updated Sept. 15/08: Don't subtract 1
+			#tp_end = tp_start + len(tpSite) - 1
+			tp_end = tp_start + len(tpSite)
+			
+			# Compare to site positions stored for this Insert
+			orig_fp_start = rHandler.findReagentFeatureStart(insert_db_id, fpcs_prop_id)
+			orig_fp_end = rHandler.findReagentFeatureEnd(insert_db_id, fpcs_prop_id)
+			
+			orig_tp_start = rHandler.findReagentFeatureStart(insert_db_id, tpcs_prop_id)
+			orig_tp_end = rHandler.findReagentFeatureEnd(insert_db_id, tpcs_prop_id)
+			
+			if orig_fp_start+1 != fp_start and orig_fp_end != fp_end and orig_tp_start != tp_start and orig_tp_end != tp_end:
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=14&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+
+			# Removed June 8/08
+			'''
+			fp_start = rHandler.findReagentFeatureStart(insert_db_id, fpcs_prop_id)
+			fp_end = rHandler.findReagentFeatureEnd(insert_db_id, fpcs_prop_id)
+			
+			tp_start = rHandler.findReagentFeatureStart(insert_db_id, tpcs_prop_id)
+			tp_end = rHandler.findReagentFeatureEnd(insert_db_id, tpcs_prop_id)
+			'''
+
+			# Deleted Sept. 15/08: VECTOR-INSERT RECONSTITUTION IS ***INDEPENDENT*** OF ALL OTHER FEATURES EXCEPT CLONING SITES!!!
+			#cdnaStart = iHandler.findCDNAStart(insert_db_id)
+			#cdnaEnd = iHandler.findCDNAEnd(insert_db_id)
+
+			if fp_start >= 0 and tp_end > 0 and tp_end <= len(insertSeq):
+				newSeq = sHandler.entryVectorSequence(pvSeqKey, insertSeq)	# corrected Oct. 31/08 - pass the ENTIRE Insert sequence
+				newSeqID = int(sHandler.matchSequence(newSeq))
+		
+				if newSeqID <= 0:
+					newSeqID = int(sHandler.insertSequence(newSeq))
+		
+				# Updated April 28/08: Implement multi-step creation process
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Step=1&Type=" + rType + "&Sub=" + subtype + "&PV=" + `pv_db_id` + "&I=" + `insert_db_id` + "&Seq=" + `newSeqID`)
+			
+			else:
+				# error
+				# Modified Feb. 12/09
+				i = EmptyCloningSitesException("")
+				err = i.err_code()
+
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `err` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+		
+		# May 28/08
+		elif subtype == 'recomb':
+			
+			# June 2/08: Check that LoxP occurs exactly twice on IPV sequence
+			loxp_seq = enzDict["LoxP"]
+			ipvSeq = sHandler.findSequenceByID(ipvSeqKey)
+			numLoxp = utils.numOccurs(ipvSeq.lower(), loxp_seq.lower())
+			
+			if numLoxp == 0:
+				raise InvalidDonorVectorSitesNotFoundException("LoxP sites not found on donor sequence")
+			
+			elif numLoxp == 1:
+				raise InvalidDonorVectorSingleSiteException("Donor vector sequence contains one occurrence of LoxP sites")
+			
+			elif numLoxp > 2:
+				raise InvalidDonorVectorMultipleSitesException("LoxP sites occur more than twice on donor sequence")
+			
+			try:
+				# updated Oct. 31/08 - don't pass Insert sequence or linkers to sequence reconstitution function
+				#newSeq = sHandler.constructRecombSequence(pvSeqKey, ipvSeqKey, insertSeqKey, insertLinkers)		# removed Oct. 31/08
+				newSeq = sHandler.constructRecombSequence(pvSeqKey, ipvSeqKey)	# added Oct. 31/08
+				newSeqID = int(sHandler.matchSequence(newSeq))
+				
+				if newSeqID <= 0:
+					newSeqID = int(sHandler.insertSequence(newSeq))
+		
+				# Updated April 28/08: Implement multi-step creation process
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Step=1&Type=" + rType + "&Sub=" + subtype + "&PV=" + `pv_db_id` + "&IPV=" + `ipv_db_id` + "&Seq=" + `newSeqID`)
+				
+			except MultipleSiteOccurrenceException:
+				i = MultipleSiteOccurrenceException("")
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Step=1&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()`)
+				
+			except InsertSitesNotFoundOnParentSequenceException:
+				i = InsertSitesNotFoundOnParentSequenceException("")
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Step=1&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()`)
+
+		elif subtype == 'gateway_expression':
+			
+			ipvSeq = sHandler.findSequenceByID(ipvSeqKey)
+
+			# June 3, 2010: Discussed with Karen and decided on the following validation strategy:
+			
+			# Check whether ccdB is recorded on PV but not on IPV; if that's not the case raise an error
+			# (lack of sites will be discovered in the sequence construction function)
+			
+			# check ccdB (selectable marker)
+			selMarkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["selectable marker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+			
+			ccdb_in_entry_vector = rHandler.existsPropertyValue(ipv_db_id, selMarkerPropID, "ccdB")
+
+			if not rHandler.existsPropertyValue(pv_db_id, selMarkerPropID, "ccdB"):
+				# here, issue an error
+				if not ccdb_in_entry_vector:
+					i = GatewayParentDestinationException("Invalid parent destination vector")
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `pvAssocProp`)
+				else:
+					i = SwapGatewayParentsException("ccdB in Gateway Entry clone and not in Parent Destination")
+					
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `pvAssocProp`)
+				
+			'''
+			# June 3, 2010: Thought of putting this in, but there's no point.  E.g. V1899, a GW Parent Destination, CANNOT and SHOULD NOT have its cloning sites set to attR, they occur on its sequence but that's not how the vector was prepared.
+			pv_fpcs = rHandler.findSimplePropertyValue(pv_db_id, fpcs_prop_id)
+			pv_tpcs = rHandler.findSimplePropertyValue(pv_db_id, tpcs_prop_id)
+			
+			ipv_fpcs = rHandler.findSimplePropertyValue(ipv_db_id, fpcs_prop_id)
+			ipv_tpcs = rHandler.findSimplePropertyValue(ipv_db_id, tpcs_prop_id)
+			
+			#print "Content-type:text/html"
+			#print
+			
+			#print pv_fpcs
+			#print pv_tpcs
+			
+			#print ipv_fpcs
+			#print ipv_tpcs
+			
+			if pv_fpcs != 'attR1' or pv_tpcs != 'attR2' or ipv_fpcs != 'attL1' or ipv_tpcs != 'attL2':
+			'''
+			
+			newSeq = sHandler.expressionVectorSequence(pvSeqKey, ipvSeq)
+			newSeqID = int(sHandler.matchSequence(newSeq))
+			
+			if newSeqID <= 0:
+				newSeqID = int(sHandler.insertSequence(newSeq))
+	
+			utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Step=1&Type=" + rType + "&Sub=" + subtype + "&PV=" + `pv_db_id` + "&IPV=" + `ipv_db_id` + "&Seq=" + `newSeqID`)
+			
+	except InsertSitesException:
+		i = InsertSitesException("Wrong sites on Insert")
+		
+		utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+	
+	except InsertSitesNotFoundOnParentSequenceException:
+		i = InsertSitesNotFoundOnParentSequenceException("Insert sites not found on parent vector sequence")
+		
+		if subtype == 'nonrecomb' or subtype == 'gateway_entry':
+			utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+		else:				# added June 2/08
+			utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+		
+	except MultipleSiteOccurrenceException:
+		i = MultipleSiteOccurrenceException("Site found more than once on parent vector sequence")
+		
+		utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+		
+	except HybridizationException:
+		i = HybridizationException("Sites cannot be hybridized")
+		
+		utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+	
+	except FivePrimeAfterThreePrimeException:
+		i = FivePrimeAfterThreePrimeException("5' site occurs after 3' site on parent vector sequence")
+		
+		utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+		
+	# June 2/08
+	except InvalidDonorVectorSitesNotFoundException:
+		i = InvalidDonorVectorSitesNotFoundException("LoxP sites not found on donor sequence")
+
+		utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+		
+	except InvalidDonorVectorMultipleSitesException:
+		i = InvalidDonorVectorMultipleSitesException("LoxP sites occur more than twice on donor sequence")
+	
+		utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+	
+	except InvalidDonorVectorSingleSiteException:
+		i = InvalidDonorVectorSingleSiteException("Donor vector sequence contains a singe LoxP site")
+		
+		utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+	
+	# Dec. 14/09
+	except EmptyParentVectorSequenceException:
+		i = EmptyParentVectorSequenceException("Empty parent Vector sequence exception")
+	
+		utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+	
+	# Dec. 14/09	
+	except EmptyParentInsertSequenceException:
+		i = EmptyParentInsertSequenceException("Empty parent Insert sequence exception")
+	
+		utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&R1=" + insertCloningSites[0] + "&R2=" + insertCloningSites[1])
+
+
+# Updated Jan. 21/09: Added 'reverse' parameter - if True, reverse complement the Insert sequence before mapping features
+def previewVectorFeatures(rID, reagent, parents, oldSeqID, newSeqID, newSeq, currUser, db, cursor, insertCloningSites={}, reverse=False):
+	
+	#print "Content-type:text/html"
+	#print
+	#print "rev " + `reverse`
+	#print `insertCloningSites`
+	
+	# Get parent values depending on subtype
+	url = ""	# the URL to redirect to, will have varying parent name parameters
+	
+	rType = reagent.getType()
+	subtype = reagent.getSubtype()
+	
+	# June 6/08: Delete features before remapping
+	rHandler.deleteReagentFeatures(rID)
+
+	# Nov. 6/08 - Delete linkers separately, as they're not included in features list
+	# Update July 9/09: different property ID selection mechanism!
+	fpLinkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	tpLinkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	
+	fpcs_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	tpcs_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+
+	seqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+	
+	rHandler.deleteReagentProperty(rID, fpLinkerPropID)
+	rHandler.deleteReagentProperty(rID, tpLinkerPropID)
+	
+	insert_fp_linker = ""
+	insert_tp_linker = ""
+	
+	# june 4, 2010
+	pv_db_id = 0
+	insert_db_id = 0
+	ipv_db_id = 0
+	
+	if subtype == 'nonrecomb' or subtype == 'gateway_entry':
+		pv_db_id = parents["vector parent id"]
+		insert_db_id = parents["insert id"]
+		
+		parentVectorID = rHandler.convertDatabaseToReagentID(pv_db_id)
+		insertID = rHandler.convertDatabaseToReagentID(insert_db_id)
+		
+		insertSeqKey = rHandler.findDNASequenceKey(insert_db_id)
+		pvSeqKey = rHandler.findDNASequenceKey(pv_db_id)	# added May 22/08
+		
+		insertSequence = sHandler.findSequenceByID(insertSeqKey).strip().lower()
+		pvSequence = sHandler.findSequenceByID(pvSeqKey).strip().upper()
+	
+		# Nov. 6/08: Find Insert linkers separately
+		insert_fp_linker = rHandler.findSimplePropertyValue(insert_db_id, fpLinkerPropID)
+		insert_tp_linker = rHandler.findSimplePropertyValue(insert_db_id, tpLinkerPropID)
+		
+		if insertCloningSites.has_key("5' cloning site"):
+			r1 = insertCloningSites["5' cloning site"]
+		else:
+			r1 = ""
+			
+		if insertCloningSites.has_key("3' cloning site"):
+			r2 = insertCloningSites["3' cloning site"]
+		else:
+			r2 = ""
+
+		# Updated Nov. 18/08: Include sites in URL in case of hybrid
+		url = hostname + "Reagent.php?View=2&Step=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + `pv_db_id` + "&I=" + `insert_db_id` + "&Seq=" + `newSeqID` + "&R1=" + r1 + "&R2=" + r2 + "&Rev=" + `reverse`
+		
+		#print url
+
+	elif subtype == 'recomb' or subtype == 'gateway_expression':
+		pv_db_id = parents["vector parent id"]
+		ipv_db_id = parents["parent insert vector"]
+		
+		parentVectorID = rHandler.convertDatabaseToReagentID(pv_db_id)
+		ipvID = rHandler.convertDatabaseToReagentID(ipv_db_id)
+		
+		ipvSeqKey = rHandler.findDNASequenceKey(ipv_db_id)
+		pvSeqKey = rHandler.findDNASequenceKey(pv_db_id)	# added May 22/08
+		
+		ipvSequence = sHandler.findSequenceByID(ipvSeqKey).strip().lower()
+		pvSequence = sHandler.findSequenceByID(pvSeqKey).strip().upper()
+		
+		# Insert from IPV?
+		if parents.has_key("insert id"):
+			insert_db_id = parents["insert id"]
+			insertID = rHandler.convertDatabaseToReagentID(insert_db_id)
+			insertSeqKey = rHandler.findDNASequenceKey(insert_db_id)
+			insertSequence = sHandler.findSequenceByID(insertSeqKey).strip().lower()
+			
+			# Nov. 6/08: Find Insert linkers separately
+			insert_fp_linker = rHandler.findSimplePropertyValue(insert_db_id, fpLinkerPropID)
+			insert_tp_linker = rHandler.findSimplePropertyValue(insert_db_id, tpLinkerPropID)
+			
+		url = hostname + "Reagent.php?View=2&Step=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + `pv_db_id` + "&IPV=" + `ipv_db_id` + "&Seq=" + `newSeqID`
+		
+	else:
+		# Novel vector - no parents, nothing to remap, BUT NEED TO SAVE SEQUENCE
+		
+		# Still delete any previous entries for this reagent (in case got back to this view from a later stage after some feature values have been entered)
+		rHandler.deleteReagentProperty(rID, seqPropID)
+		rHandler.addReagentProperty(rID, seqPropID, newSeqID)
+
+		# June 3/08: delete the rest of the features
+		rHandler.deleteReagentProperty(rID, fpcs_prop_id)
+		rHandler.deleteReagentProperty(rID, tpcs_prop_id)
+		
+		# Nov. 6/08 - Delete linkers separately, as they're not included in features list (if they don't exist no harm done)
+		rHandler.deleteReagentProperty(rID, fpLinkerPropID)
+		rHandler.deleteReagentProperty(rID, tpLinkerPropID)
+		
+		rHandler.deleteReagentFeatures(rID)
+
+		utils.redirect(hostname + "Reagent.php?View=2&Step=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&Seq=" + `newSeqID`)
+
+	# For non-Novel reagents, remap features
+	newSeq = utils.squeeze(newSeq).lower()
+
+	# Avoid duplicate values - may already have ReagentPropList_tbl entries for this reagent, clear them before saving (for consistency)
+	rHandler.deleteReagentProperty(rID, seqPropID)
+	rHandler.addReagentProperty(rID, seqPropID, newSeqID)
+	
+	# April 17/08: FIND OUT WHERE ***cDNA*** starts on the new sequence
+	# Correction May 15/08: need the actual cDNA portion of the Insert, w/o sites or linkers
+	
+	# find cDNA portion on **ORIGINAL** Insert sequence
+	# CHANGE JUNE 4, 2010: Now that we are allowing IPV to be of any type and it may not necessarily include an Insert, GRAB CDNA FROM THE **VECTOR** SEQUENCE.
+	# added if-else June 4, 2010, modified again Dec. 3, 2010: checking if insert exists is not sufficient, add check for vector type again!!
+	if subtype == 'nonrecomb' or subtype == 'gateway_entry':	# Dec. 3, 2010
+		#if insert_db_id > 0:	# removed Dec 3, 2010, replaced with 'try-assert' below
+		try:
+			assert insert_db_id > 0
+		
+			insert_cdnaStart = iHandler.findCDNAStart(insert_db_id)
+			insert_cdnaEnd = iHandler.findCDNAEnd(insert_db_id)
+			
+			# Updated June 1/08: added 'if-else'
+			if insert_cdnaStart > 0 and insert_cdnaEnd > 0:
+				cdnaSeq = insertSequence[insert_cdnaStart-1:insert_cdnaEnd]
+			else:
+				cdnaSeq = insertSequence
+				
+		except AssertionError:
+			raise ReagentDoesNotExistException("Insert does not exist")
+
+	elif subtype == 'recomb' or subtype == 'gateway_expression':	# dec 3/10
+	#elif ipv_db_id > 0:	# removed Dec 3, 2010, replaced with 'try-assert' below
+		try:
+			assert ipv_db_id > 0
+			
+			# keep variable names for code consistency
+			cdnaStart = iHandler.findCDNAStart(ipv_db_id)
+			cdnaEnd = iHandler.findCDNAEnd(ipv_db_id)
+			
+			# Updated June 1/08: added 'if-else'
+			if cdnaStart > 0 and cdnaEnd > 0:
+				cdnaSeq = ipvSequence[cdnaStart-1:cdnaEnd]
+			else:
+				cdnaSeq = ipvSequence
+		except AssertionError:
+			raise ReagentDoesNotExistException("Insert Parent Vector does not exist")
+	else:
+		cdnaSeq = ""
+		
+	# Jan. 21/09
+	if reverse:
+		cdnaSeq = sHandler.reverse_complement(cdnaSeq)
+		#print cdnaSeq
+		
+		# Update July 2/09: pass cdnaPropID to setPropertyDirection() function in combination with its category
+		cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+		rHandler.setPropertyDirection(rID, cdnaPropID, 'reverse')
+
+	# Get sites - removed July 9/09
+	#fpcs_prop_id = prop_Name_ID_Map["5' cloning site"]
+	#tpcs_prop_id = prop_Name_ID_Map["3' cloning site"]
+	
+	# May 28/08: Sites depend on vector subtype - LOWERCASE!!!!
+	if subtype == 'nonrecomb':
+		#print r1
+		
+		# Nov. 18/08: Check if either site on the **NEW VECTOR** is hybrid
+		fp_insert_cs = utils.make_array(r1)
+		tp_insert_cs = utils.make_array(r2)
+		
+		#print `fp_insert_cs`
+		pvSeq = Seq(pvSequence)
+		insertSeq = Seq(insertSequence)
+		
+		if sHandler.isHybrid(fp_insert_cs):
+			
+			try:
+				#print fp_insert_cs
+				fpSite = sHandler.hybridSeq(fp_insert_cs)
+				#print fpSite
+
+			except DegenerateHybridException:
+				fpSite = sHandler.getHybridDegenerate(fp_insert_cs, pvSeq, insertSeq, "5 prime")
+				#print fpSite
+			
+			# Jan. 16/09: DON'T EVER DO THIS!!!!!!!!!!!!!!!!
+			#fp_search_start = rHandler.findReagentFeatureStart(pv_db_id, prop_Name_ID_Map["5' cloning site"]) - 1
+			
+			fp_h1 = sHandler.get_H_1(fp_insert_cs)
+			
+			if sHandler.enzDict.has_key(fp_h1):
+				fp_h1_enz = sHandler.enzDict[fp_h1]
+				#print fp_h1_enz
+				
+				# added Dec. 18/08
+				fp_h1_seq = fp_h1_enz.elucidate().replace("_", "")
+				fp_h1_clvg = fp_h1_seq.find("^")
+				fp_h1_flank = fp_h1_seq[0:fp_h1_clvg]
+				
+				pv_fp_h1_pos = fp_h1_enz.search(pvSeq, False)
+				#print `pv_fp_h1_pos`
+				pv_fp_h1_pos.sort()
+				
+				if len(pv_fp_h1_pos) > 0:
+					fpStartPos = newSeq.lower().find(fpSite.lower()) + 1	# replaced March 15, 2010
+					#print fpStartPos
+					# NO.  Replaced March 15, 2010 - this would return wrong results if the hybrid site is BamHI/BglII, and the sequence contains an additional BamHI non-hybrid site.  Then the result would be the position of BamHI, not the BamHI/BglII hybrid.
+					#fpStartPos = pv_fp_h1_pos[0] - len(fp_h1_flank)
+					fpEndPos = fpStartPos + len(fpSite)
+
+		else:
+			# NO!!!! Removed Feb. 11/09 - what if the site is not hybrid but customized and is not the same as Insert cloning site even though found in Insert sequence!!
+			#fp_insert_cs = rHandler.findSimplePropertyValue(insert_db_id, fpcs_prop_id)
+			fp_insert_cs = r1		# use whatever arrives as input!
+			
+			# 5' site
+			#five_prime_site = utils.make_array(fp_insert_cs)
+			#print `five_prime_site`
+			
+			#if not sHandler.isHybrid(five_prime_site):		# Removed Jan. 13/09: Why check again? we're in else, meaning 5' is not hybrid
+			
+			# Sept. 30/08: SfiI sequences from V1889
+			#if fp_insert_cs == 'SfiI':			# removed March 8/10
+				#fpSite = "GGCCATTACGGCC"
+			#else:
+			if enzDict.has_key(fp_insert_cs):
+				fpSite = enzDict[fp_insert_cs]
+			else:
+				print "Content-type:text/html"
+				print
+				print "Unknown 5' site for reagent " + `rID` + ": " + fp_insert_cs
+				return
+			#else:
+				#fpSite = sHandler.hybridSeq(five_prime_site)
+		
+		# 3' site
+		if sHandler.isHybrid(tp_insert_cs):
+			
+			#print `tp_insert_cs`
+			
+			try:
+				tpSite = sHandler.hybridSeq(tp_insert_cs)
+			except DegenerateHybridException:
+				tpSite = sHandler.getHybridDegenerate(tp_insert_cs, pvSeq, insertSeq, "3 prime")
+			
+			#print tpSite
+			
+			# NO!!!!!!!!!!!!!!!!!!!!!!  DON'T EVER DO THIS!!!!!!!!!!!!!!
+			#tp_search_end = rHandler.findReagentFeatureEnd(pv_db_id, prop_Name_ID_Map["3' cloning site"]) - 1
+			
+			tp_h2 = sHandler.get_H_2(tp_insert_cs)
+			#pvSeq = Seq(pvSequence)
+			
+			if sHandler.enzDict.has_key(tp_h2):
+				tp_h2_enz = sHandler.enzDict[tp_h2]
+				#print tp_h2_enz
+				
+				tp_h2_seq = tp_h2_enz.elucidate().replace("_", "")
+				#print tp_h2_seq
+				tp_h2_clvg = tp_h2_seq.find("^")	# ok
+				tp_h2_flank = tp_h2_seq[0:tp_h2_clvg]	# ok
+				#print tp_h2_flank
+				
+				pv_tp_h2_pos = tp_h2_enz.search(pvSeq, False)
+				#print `tp_h2_enz`
+				
+				#print `pv_tp_h2_pos`
+				pv_tp_h2_pos.sort()
+				
+				if len(pv_tp_h2_pos) > 0:
+					# NO.  Replaced March 15, 2010 - this would return wrong results if the hybrid site is BamHI/BglII, and the sequence contains an additional BamHI non-hybrid site.  Then the result would be the position of BamHI, not the BamHI/BglII hybrid.
+					
+					'''
+					pv_tp_start = pv_tp_h2_pos[len(pv_tp_h2_pos)-1] - len(tp_h2_flank)	# ok
+					#print pv_tp_start
+					
+					pv_tp_end = pv_tp_start + len(tpSite)
+					#print pv_tp_end
+					
+					#if tp_end >= len(pvSequence):
+					pv_post = pvSequence[pv_tp_end:].lower()
+					#print pv_post
+					
+					# Feb. 6/09: Added 'if' to account for an extreme case where the 3' site is at the very end of the PV sequence
+					if len(pv_post) > 0:
+						tpStartPos = newSeq.lower().find(pv_post.lower()) - len(tpSite)
+						#print tpStartPos
+						tpEndPos = tpStartPos + len(tpSite)
+						#print tpEndPos
+					else:
+						# check, really not sure what would come out of this - just set it to be at the end of the new sequence
+						tpStartPos = len(newSeq) - len(tpSite) + 1
+						tpEndPos = tpStartPos + len(tpSite)
+					'''
+					
+					#print tpSite.lower()
+					
+					tpStartPos = newSeq.lower().rfind(tpSite.lower()) + 1
+					tpEndPos = tpStartPos + len(tpSite)
+		else:
+			# NO!!!! Removed Feb. 11/09 - what if the site is not hybrid but customized and is not the same as Insert cloning site even though found in Insert sequence!!
+			#tp_insert_cs = rHandler.findSimplePropertyValue(insert_db_id, tpcs_prop_id)
+			
+			tp_insert_cs = r2		# use actual input value!
+			
+			#three_prime_site = utils.make_array(tp_insert_cs)
+	
+			#if not sHandler.isHybrid(three_prime_site):
+				
+			# Sept. 30/08: Special case: SfiI from V1889
+			#if tp_insert_cs == 'SfiI':
+				#tpSite = "GGCCGCCTCGGCC"
+			#else:
+			if enzDict.has_key(tp_insert_cs):	# March 8/10
+				tpSite = enzDict[tp_insert_cs]
+			else:
+				print "Content-type:text/html"
+				print
+				print "Unknown 3' site for reagent " + `rID` + ": " + tp_insert_cs
+				return
+			
+		#print fpSite
+		#print tpSite
+		
+	elif subtype == 'recomb':
+		fp_insert_cs = 'LoxP'
+		tp_insert_cs = 'LoxP'
+	
+		fpSite = enzDict[fp_insert_cs].lower()
+		tpSite = enzDict[tp_insert_cs].lower()
+	
+	elif subtype == 'gateway_entry':
+		fp_insert_cs = 'attL1'
+		tp_insert_cs = 'attL2'
+		
+		# Special sequences - Changed May 29/08 after discussion with Karen
+		fpSite = 'tttgtacaaaaaa'
+		tpSite = 'tttcttgtacaaagtt'
+		
+	elif subtype == 'gateway_expression':
+		fp_insert_cs = 'attB1'
+		tp_insert_cs = 'attB2'
+		
+		fpSite = 'gtacaaaaaa'
+		tpSite = 'tttcttgtac'
+		
+	# 5' cloning site (sequence in lowercase, search for site in lowercase too)
+	#print fp_search_start
+	#print fpSite
+	
+	if not sHandler.isHybrid(fp_insert_cs):
+		if newSeq.find(fpSite.lower()) >= 0:
+			fpStartPos = newSeq.find(fpSite.lower()) + 1
+			fpEndPos = fpStartPos + len(fpSite)
+		else:
+			# Dec. 17/08: reason could be that the site is a degenerate - try one more time with BioPython
+			# ** Jan. 14/09: Ignoring the case of a hybrid degenerate (e.g. RsrII-Rsr2I) for now **
+			tmpSeq = Bio.Seq.Seq(newSeq)
+			
+			# Jan. 6/09: Gateway sites not in enzDict
+			if sHandler.enzDict.has_key(fp_insert_cs):
+				fp_cs = sHandler.enzDict[fp_insert_cs]
+				
+				# added Dec. 18/08
+				fp_seq = fp_cs.elucidate().replace("_", "")
+				fp_clvg = fp_seq.find("^")
+				fp_flank = fp_seq[0:fp_clvg]
+				
+				tmp_fp_pos = fp_cs.search(tmpSeq)
+				tmp_fp_pos.sort()
+				
+				if len(tmp_fp_pos) > 0:
+					fpStartPos = tmp_fp_pos[0] - len(fp_flank)
+					fpEndPos = fpStartPos + len(fpSite)
+					
+					if fpStartPos == 0:
+						fpStartPos = 0
+						fpEndPos = 0
+				else:
+					fpStartPos = 0
+					fpEndPos = 0
+			# Jan. 6/09
+			else:
+				fpStartPos = 0
+				fpEndPos = 0
+		
+	# 3' cloning site
+	if not sHandler.isHybrid(tp_insert_cs):
+		if newSeq.rfind(tpSite.lower()) >= 0:
+			tpStartPos = newSeq.rfind(tpSite.lower()) + 1		# look from END of sequence?????
+			tpEndPos = tpStartPos + len(tpSite)
+		else:	
+			# Dec. 17/08
+			# reason could be that the site is a degenerate - try one more time with BioPython
+			tmpSeq = Bio.Seq.Seq(newSeq)
+			
+			# Jan. 6/09: Gateway sites are not in enzDict
+			if sHandler.enzDict.has_key(tp_insert_cs):
+				tp_cs = sHandler.enzDict[tp_insert_cs]
+				
+				# dec. 18/08
+				tp_seq = tp_cs.elucidate().replace("_", "")
+				tp_clvg = tp_seq.find("^")
+				tp_flank = tp_seq[0:tp_clvg]
+				
+				tmp_tp_pos = tp_cs.search(tmpSeq)
+				tmp_tp_pos.sort()
+				
+				if len(tmp_tp_pos) > 0:
+					tpStartPos = tmp_tp_pos[len(tmp_tp_pos)-1] - len(tp_flank)
+					tpEndPos = tpStartPos + len(tpSite)	# do NOT subtract 1 here, done below at db insertion!
+					
+					if tpStartPos == 0:
+						tpStartPos = 0
+						tpEndPos = 0
+				else:
+					tpStartPos = 0
+					tpEndPos = 0
+			# Jan. 6/09
+			else:
+				tpStartPos = 0
+				tpEndPos = 0
+				
+	#print "Content-type:text/html"
+	#print
+	#print "5' " + `fpStartPos` + " 3' " + `tpStartPos`
+	
+	# Nov. 18/08: Pass site positions in URL (mostly done for Hybrids)
+	url += "&FPS=" + `fpStartPos`
+	url += "&FPE=" + `fpEndPos-1`
+	url += "&TPS=" + `tpStartPos`
+	url += "&TPE=" + `tpEndPos-1`
+	
+	# Nov. 6/08: Map linkers in the same fashion
+	if insert_fp_linker and len(insert_fp_linker) >= 10:
+		fpLinkerStartPos = newSeq.find(insert_fp_linker.lower()) + 1
+		fpLinkerEndPos = fpLinkerStartPos + len(insert_fp_linker)
+		rHandler.addReagentProperty(rID, fpLinkerPropID, insert_fp_linker, fpLinkerStartPos, fpLinkerEndPos-1)
+	else:
+		fpLinkerStartPos = 0
+		fpLinkerEndPos = 0
+		
+	# 3' linker
+	if insert_tp_linker and len(insert_tp_linker) >= 10:
+		tpLinkerStartPos = newSeq.find(insert_tp_linker.lower()) + 1
+		tpLinkerEndPos = tpLinkerStartPos + len(insert_tp_linker)
+		rHandler.addReagentProperty(rID, tpLinkerPropID, insert_tp_linker, tpLinkerStartPos, tpLinkerEndPos-1)
+	else:
+		tpLinkerStartPos = 0
+		tpLinkerEndPos = 0
+	
+	# Nov. 3/08 - check if 5' site is after 3' - if yes, look for the reverse sequence
+	cdna_dir = 'forward'
+	
+	if fpStartPos > tpStartPos:
+		if not reverse:		# if haven't reversed it already
+			cdnaSeq = sHandler.reverse_complement(cdnaSeq)
+			
+			# Update July 2/09: pass cdnaPropID to setPropertyDirection() function in combination with its category
+			cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+			rHandler.setPropertyDirection(rID, cdnaPropID, 'reverse')
+		
+	# cDNA (in lowercase already)
+	if newSeq.find(cdnaSeq) >= 0:
+		
+		cdnaStart = newSeq.find(cdnaSeq) + 1		# may 22/08
+		cdnaEnd = cdnaStart + len(cdnaSeq) - 1		# may 22/08
+	else:
+		cdnaStart = 0
+		cdnaEnd = 0
+
+	# June 3/08: Karen's request: Issue a warning if user destroys one or both of the LoxP sites in a recomb. sequence
+	if subtype == 'recomb':
+		
+		if (fpStartPos == 0 and fpEndPos == 0) or (tpStartPos == 0 and tpEndPos == 0) or (fpStartPos == tpStartPos and fpEndPos == tpEndPos):
+			i = RecombinationVectorSequenceMissingLoxPException("Missing LoxP sites from recombination vector sequence")
+		
+			utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&IPV=" + ipvID + "&Err=" + `i.err_code()` + "&Seq=" + `oldSeqID`)
+	
+	# July 2/09
+	cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+
+	rHandler.setPropertyPosition(rID, cdnaPropID, "startPos", cdnaStart)
+	rHandler.setPropertyPosition(rID, cdnaPropID, "endPos", cdnaEnd)
+	
+	# Store new values - DELETE BEFORE INSERTING
+	
+	# removed July 9/09
+	#fpcs_prop_id = prop_Name_ID_Map["5' cloning site"]
+	#tpcs_prop_id = prop_Name_ID_Map["3' cloning site"]
+
+	rHandler.addReagentProperty(rID, fpcs_prop_id, fp_insert_cs, fpStartPos, fpEndPos-1)
+	rHandler.addReagentProperty(rID, tpcs_prop_id, tp_insert_cs, tpStartPos, tpEndPos-1)
+	
+	if subtype == 'gateway_entry':
+		
+		iFeatures = rHandler.findReagentSequenceFeatures(insert_db_id)
+		pvFeatures = rHandler.findReagentSequenceFeatures(pv_db_id)
+		
+		# Parent Vector features are found before cDNA start and after cDNA end on the new sequence
+		for f in pvFeatures:
+			fType = f.getFeatureType()
+			
+			if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+			
+				# original feature positions on PV sequence
+				pv_fStart = f.getFeatureStartPos()
+				pv_fEnd = f.getFeatureEndPos()
+			
+				fVal = f.getFeatureName()
+				pv_fDir = f.getFeatureDirection()
+				
+				if pv_fStart > 0 and pv_fEnd > 0:
+					
+					# Features from PV are inherited IFF they are located **entirely** before the 5' cloning site or after 3' cloning site
+					# Hence: May 22/08 - Find 5' start and 3' end on **original** PV sequence
+					pv_fpcs_start = pvSequence.lower().find(fpSite)
+					pv_tpcs_end = pvSequence.lower().find(tpSite) + len(tpSite)
+					
+					fSeq = pvSequence[pv_fStart-1:pv_fEnd].lower()
+	
+					# June 4/08 - Search for the feature IFF > 10 nts
+					if len(fSeq) >= 10:
+	
+						# Look for this feature on the NEWly reconstituted Vector
+						fIndex = newSeq.lower().find(fSeq)
+	
+						if fIndex >= 0:
+							fpStart = fIndex + 1
+							fpEnd = fpStart + len(fSeq) - 1
+							
+							# If found, make sure this feature occurs either before or after the INSERT - i.e. before 5' cloning site start OR after 3' cloning site end
+							if (fpStart < fpStartPos and fpEnd < fpStartPos) or (fpStart >= tpEndPos and fpEnd > tpEndPos):
+								fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+								rHandler.addReagentProperty(rID, fID, fVal, fpStart, fpEnd, pv_fDir)
+					
+								if f.getFeatureDescrType():
+									fDescr = f.getFeatureDescrName()
+									
+									# Updated July 2/09, moved up July 9/09
+									#fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+									rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fpStart, fpEnd, fDescr)
+				
+		# Search for each Insert feature on the new sequence
+		# June 6/08: Added 'if' statement - needs testing
+		for f in iFeatures:
+			fType = f.getFeatureType()
+			#print fType
+			
+			if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+				# feature positions on the Insert sequence - Modified May 21/08: Account for the fact that NOT the entire Insert sequence is used, only a subsequence
+				fiStart = f.getFeatureStartPos()
+				fiEnd = f.getFeatureEndPos()
+				fVal = f.getFeatureName()
+				#print fVal
+				fSeq = insertSequence[fiStart:fiEnd].lower()
+			
+				if len(fSeq) >= 10:
+					fStart = newSeq.lower().find(fSeq)
+					fEnd = fStart + len(fSeq)
+				
+					if fStart >= 1:
+	
+						# May 22/08: NO!!! This is precisely what we decided we're NOT going to do!!!
+						'''
+						## recompute based on cDNA start
+						#fiStart = fiStart - insert_cdnaStart
+						#fiEnd = fiEnd - insert_cdnaStart
+						
+						# feature positions on the new Vector sequence
+						#fStart = cdnaStart + fiStart
+						#fEnd = fStart + len(fSeq)
+						'''
+						
+						# Insert features, on the other hand, must occur entirely WITHIN the Insert - i.e. between the cloning sites (Oct. 30/08)
+						if fStart >= fpStartPos and fEnd <= tpEndPos:
+							# Orientation
+							fiDir = f.getFeatureDirection()
+							
+							fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+							rHandler.addReagentProperty(rID, fID, fVal, fStart, fEnd, fiDir)
+						
+							if f.getFeatureDescrType():
+								fDescr = f.getFeatureDescrType()
+								
+								# Updated July 2/09
+								rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fStart, fEnd, fDescr)
+	elif subtype == 'nonrecomb':
+		iFeatures = rHandler.findReagentSequenceFeatures(insert_db_id)
+		pvFeatures = rHandler.findReagentSequenceFeatures(pv_db_id)
+		
+		#print "Content-type:text/html"
+		#print
+		
+		# changes made Oct. 14/08
+		tmp_dict = {}
+		
+		# Parent Vector features are found before 5' start and after 3' end on the new sequence
+		for f in pvFeatures:
+			fType = f.getFeatureType()
+			#print fType
+			
+			if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+			
+				# original feature positions on PV sequence
+				pv_fStart = f.getFeatureStartPos()
+				#print `pv_fStart`
+				pv_fEnd = f.getFeatureEndPos()
+				
+				fSeq = pvSequence[pv_fStart-1:pv_fEnd].lower()
+				tmp_dict[fSeq] = f
+		
+		for fSeq in tmp_dict.keys():
+			f_tmp = tmp_dict[fSeq]
+			
+			if len(fSeq) >= 10:
+				fList = utils.findall(newSeq.lower(), fSeq, [])
+				
+				for fIndex in fList:
+					fpStart = fIndex + 1
+					fpEnd = fpStart + len(fSeq) - 1
+					
+					if fpStart > 0 and fpEnd > 0:
+						# removed Feb. 23/09 - why same 'if' twice??!!!!
+						## If found, make sure this feature occurs either before or after the CLONING SITES!!!!!
+						#if (fpStart < fpStartPos and fpEnd < fpStartPos) or (fpStart > fpEndPos and fpEnd > fpEndPos):
+						
+						#If found, make sure this feature occurs either before or after the CLONING SITES
+						# Nov. 4/08: fpStart >= tpEndPos, since tpEndPos is one greater than the actual site end value
+						if (fpStart < fpStartPos and fpEnd < fpStartPos) or (fpStart >= tpEndPos and fpEnd > tpEndPos):
+							fType = f_tmp.getFeatureType()
+							fVal =  f_tmp.getFeatureName()
+							pv_fDir = f_tmp.getFeatureDirection()
+				
+							#print fType + ": " + fVal + ": " + `fpStart` + "-" + `fpEnd`
+							
+							fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+							rHandler.addReagentProperty(rID, fID, fVal, fpStart, fpEnd, pv_fDir)
+					
+							if f_tmp.getFeatureDescrType():
+								fDescr = f_tmp.getFeatureDescrName()
+								#print "?? " + fDescr
+								
+								# Updated July 2/09
+								rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fpStart, fpEnd, fDescr)
+
+		# Search for each Insert feature on the new sequence
+		# June 6/08: Added 'if' statement - needs testing
+		
+		tmp_i_dict = {}
+		
+		for f in iFeatures:
+			fType = f.getFeatureType()
+			#print fType
+			
+			if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+				# feature positions on the Insert sequence - Modified May 21/08: Account for the fact that NOT the entire Insert sequence is used, only a subsequence
+				fiStart = f.getFeatureStartPos()
+				fiEnd = f.getFeatureEndPos()
+				#fVal = f.getFeatureName()
+				#print fVal
+				fSeq = insertSequence[fiStart:fiEnd].lower()
+				tmp_i_dict[fSeq] = f
+			
+			
+		for fSeq in tmp_i_dict.keys():
+			f_tmp = tmp_i_dict[fSeq]
+			
+			if len(fSeq) >= 10:
+				
+				# Jan. 21/09: Look for reverse features if sequence reverse complemented???
+				if reverse:
+					fSeq = sHandler.reverse_complement(fSeq)
+
+				fList = utils.findall(newSeq.lower(), fSeq, [])
+				
+				for fIndex in fList:
+					fStart = newSeq.lower().find(fSeq)
+					fEnd = fStart + len(fSeq)
+					
+					f_tmp.getFeatureName()
+					
+					# still, double check to make sure this feature occurs between the CLONING SITES on the resulting Vector sequence!!!!
+					if fStart >= fpStartPos and fEnd <= tpEndPos:
+						fType = f_tmp.getFeatureType()
+						fVal =  f_tmp.getFeatureName()
+						fiDir = f_tmp.getFeatureDirection()
+						
+						# Jan. 22/09
+						if reverse:
+							fiDir = 'reverse'
+						
+						fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+						rHandler.addReagentProperty(rID, fID, fVal, fStart, fEnd, fiDir)
+					
+						if f_tmp.getFeatureDescrType():
+							fDescr = f_tmp.getFeatureDescrType()
+							
+							# Updated July 2/09
+							rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fStart, fEnd, fDescr)
+	
+	elif subtype == 'recomb':
+		
+		# April 17/08: Map the rest of the features
+		ipvFeatures = rHandler.findReagentSequenceFeatures(ipv_db_id)
+		pvFeatures = rHandler.findReagentSequenceFeatures(pv_db_id)
+		
+		# changes made Oct. 14/08
+		tmp_dict = {}
+		
+		# Parent Vector features are found before cDNA start and after cDNA end on the new sequence
+		for f in pvFeatures:
+			fType = f.getFeatureType()
+			
+			if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+			
+				# original feature positions on PV sequence
+				pv_fStart = f.getFeatureStartPos()
+				pv_fEnd = f.getFeatureEndPos()
+				
+				fSeq = pvSequence[pv_fStart-1:pv_fEnd].lower()
+				tmp_dict[fSeq] = f
+			
+		for fSeq in tmp_dict.keys():
+			f_tmp = tmp_dict[fSeq]
+			
+			if len(fSeq) >= 10:
+				#print f_tmp.getFeatureName()
+
+				fList = utils.findall(newSeq.lower(), fSeq, [])
+				#print `fList`
+				
+				for fIndex in fList:
+					fpStart = fIndex + 1
+					fpEnd = fpStart + len(fSeq) - 1
+					
+					if fpStart > 0 and fpEnd > 0:
+						
+						fType = f_tmp.getFeatureType()
+						fVal =  f_tmp.getFeatureName()
+						#print fVal
+						pv_fDir = f_tmp.getFeatureDirection()
+				
+						# Nov. 4/08: In recombination vectors there's only one LoxP occurrence on the parent and it should be transferred onto the child as a restriction site; rest of features are all inherited.  So remove the site position check; don't replace it with check for a single LoxP site occurrence yet, see how it goes.
+						
+						# removed Nov. 6/08
+						##If found, make sure this feature occurs either before or after the CLONING SITES!!!!!!!!
+						#if (fpStart < fpStartPos and fpEnd < fpStartPos) or (fpStart >= tpEndPos and fpEnd > tpEndPos):
+							#print fType + ": " + fVal + ": " + `fpStart` + "-" + `fpEnd`
+						
+						fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+						rHandler.addReagentProperty(rID, fID, fVal, fpStart, fpEnd, pv_fDir)
+				
+						if f_tmp.getFeatureDescrType():
+							fDescr = f_tmp.getFeatureDescrName()
+							#print fDescr
+					
+							# Updated July 2/09
+							rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fpStart, fpEnd, fDescr)
+
+		# Search for each IPV feature on the new sequence
+		# June 6/08: Added 'if' statement - needs testing
+		
+		tmp_ipv_dict = {}
+		
+		for f in ipvFeatures:
+			fType = f.getFeatureType()
+			#print fType
+			
+			if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+				# feature positions on the Insert sequence - Modified May 21/08: Account for the fact that NOT the entire Insert sequence is used, only a subsequence
+				fiStart = f.getFeatureStartPos()
+				fiEnd = f.getFeatureEndPos()
+				#fVal = f.getFeatureName()
+				#print fVal
+				fSeq = ipvSequence[fiStart:fiEnd].lower()
+				tmp_ipv_dict[fSeq] = f
+			
+		for fSeq in tmp_ipv_dict.keys():
+			f_tmp = tmp_ipv_dict[fSeq]
+			#print f_tmp.getFeatureName()
+
+			if len(fSeq) >= 10:
+				fList = utils.findall(newSeq.lower(), fSeq, [])
+				#print `fList`
+
+				for fIndex in fList:
+					fStart = newSeq.lower().find(fSeq)
+					#print "start " + `fStart`
+					fEnd = fStart + len(fSeq)
+					#print "end  " + `fEnd`
+					
+					# still, double check to make sure this feature occurs between Insert cDNA start and end on resulting Vector sequence
+					#print "cdna start " + `cdnaStart`
+					#print "cdna end " + `cdnaEnd`
+
+					# features must be between the cloning sites - this check remains!!!
+					if fStart > fpEndPos and fEnd < tpEndPos:
+						fType = f_tmp.getFeatureType()
+						fVal =  f_tmp.getFeatureName()
+						fiDir = f_tmp.getFeatureDirection()
+						#print fType + ": " + fVal + ": " + `fStart` + "-" + `fEnd`
+					
+						fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+						rHandler.addReagentProperty(rID, fID, fVal, fStart, fEnd, fiDir)
+					
+						if f_tmp.getFeatureDescrType():
+							fDescr = f_tmp.getFeatureDescrType()
+							#print fDescr
+							# Updated Sept. 2/08
+							
+							# Updated July 2/09
+							# why twice?? removed july 2/09
+							#rHandler.setReagentFeatureDescriptor(rID, prop_Name_ID_Map[fType], fVal, fDescr)
+							rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fStart, fEnd, fDescr)
+
+	elif subtype == 'gateway_expression':
+		ipvFeatures = rHandler.findReagentSequenceFeatures(ipv_db_id)
+		pvFeatures = rHandler.findReagentSequenceFeatures(pv_db_id)
+			
+		# Parent Vector features are found before cDNA start and after cDNA end on the new sequence
+		for f in pvFeatures:
+			fType = f.getFeatureType()
+			#print fType
+			
+			if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+			
+				# original feature positions on PV sequence
+				pv_fStart = f.getFeatureStartPos()
+				pv_fEnd = f.getFeatureEndPos()
+			
+				fVal = f.getFeatureName()
+				#print fVal
+				pv_fDir = f.getFeatureDirection()
+				
+				#print pv_fDir
+				
+				if pv_fStart > 0 and pv_fEnd > 0:
+					
+					# Features from PV are inherited IFF they are located **entirely** before the 5' cloning site or after 3' cloning site
+					# Hence: May 22/08 - Find 5' start and 3' end on **original** PV sequence
+					pv_fpcs_start = pvSequence.lower().find(fpSite)
+					pv_tpcs_end = pvSequence.lower().find(tpSite) + len(tpSite)
+					
+					fSeq = pvSequence[pv_fStart-1:pv_fEnd].lower()
+	
+					# June 4/08 - Search for the feature IFF > 10 nts
+					if len(fSeq) >= 10:
+	
+						# Look for this feature on the NEWly reconstituted Vector
+						fIndex = newSeq.lower().find(fSeq)
+	
+						if fIndex >= 0:
+							fpStart = fIndex + 1
+							fpEnd = fpStart + len(fSeq) - 1
+							
+							#print "start " + `fpStart`
+							#print "end " + `fpEnd`
+	
+							# If found, make sure this feature occurs either before or after the cDNA
+							if (fpStart < fpStartPos and fpEnd < fpStartPos) or (fpStart >= tpEndPos and fpEnd > tpEndPos):
+								
+								# June 9/08: Orientation
+								fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+								rHandler.addReagentProperty(rID, fID, fVal, fpStart, fpEnd, pv_fDir)
+					
+								if f.getFeatureDescrType():
+									fDescr = f.getFeatureDescrName()
+									#print fVal
+									#print fDescr
+									
+									# Updated July 2/09
+									rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fpStart, fpEnd, fDescr)
+				
+		# Search for each Insert feature on the new sequence
+		# June 6/08: Added 'if' statement - needs testing
+		for f in ipvFeatures:
+			fType = f.getFeatureType()
+			#print fType
+			
+			if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+				# feature positions on the Insert sequence - Modified May 21/08: Account for the fact that NOT the entire Insert sequence is used, only a subsequence
+				fiStart = f.getFeatureStartPos()
+				fiEnd = f.getFeatureEndPos()
+				fVal = f.getFeatureName()
+				#print fVal
+				
+				#fSeq = cdnaSeq[fiStart:fiEnd].lower()	# NO!!!!
+				
+				fSeq = ipvSequence[fiStart:fiEnd].lower()
+			
+				if len(fSeq) >= 10:
+					fStart = newSeq.lower().find(fSeq)
+					fEnd = fStart + len(fSeq)
+				
+					if fStart >= 1:
+	
+						# May 22/08: NO!!! This is precisely what we decided we're NOT going to do!!!
+						'''
+						## recompute based on cDNA start
+						#fiStart = fiStart - insert_cdnaStart
+						#fiEnd = fiEnd - insert_cdnaStart
+						
+						# feature positions on the new Vector sequence
+						#fStart = cdnaStart + fiStart
+						#fEnd = fStart + len(fSeq)
+						'''
+						
+						# still, double check to make sure this feature occurs between cloning sites on resulting Vector sequence
+						if fStart >= fpEndPos and fEnd <= tpStartPos:
+							
+							# June 9/08: Orientation
+							fiDir = f.getFeatureDirection()
+							
+							fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+							rHandler.addReagentProperty(rID, fID, fVal, fStart, fEnd, fiDir)
+						
+							if f.getFeatureDescrType():
+								fDescr = f.getFeatureDescrType()
+								
+								# Updated July 2/09
+								rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fStart, fEnd, fDescr)
+	
+	utils.redirect(url)
+	
+	
+def previewInsertFeatures(insertID, five_prime_site, three_prime_site, parents, sequence, seqID):
+	
+	#print "Content-type:text/html"
+	#print
+	#print sequence
+
+	# Delete old properties before inserting new values - Updated July 9/09
+	seqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+	rHandler.deleteReagentProperty(insertID, seqPropID)
+	
+	fpcs_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	tpcs_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	
+	rHandler.deleteReagentProperty(insertID, fpcs_prop_id)
+	rHandler.deleteReagentProperty(insertID, tpcs_prop_id)
+	
+	# Sept. 8/08: Delete linkers too
+	fp_linker_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	tp_linker_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	
+	rHandler.deleteReagentProperty(insertID, fp_linker_prop_id)
+	rHandler.deleteReagentProperty(insertID, tp_linker_prop_id)
+	
+	# features too
+	rHandler.deleteReagentFeatures(insertID)
+	
+	# Nov. 6/08 - Delete linkers separately, as they're not included in features list
+	rHandler.deleteReagentProperty(insertID, fp_linker_prop_id)
+	rHandler.deleteReagentProperty(insertID, tp_linker_prop_id)
+	
+	# Save sequence
+	rHandler.addReagentProperty(insertID, seqPropID, seqID)
+	
+	# May 26/08: Check hybrid sites
+	fpcs = utils.make_array(five_prime_site)
+	tpcs = utils.make_array(three_prime_site)
+	
+	if sHandler.isHybrid(fpcs):
+		fp_seq = sHandler.hybridSeq(fpcs)
+	else:
+		if len(five_prime_site) > 0:
+			fp_seq = enzDict[five_prime_site].lower()
+		else:
+			fp_seq = ""
+
+	if sHandler.isHybrid(tpcs):
+		tp_seq = sHandler.hybridSeq(tpcs)
+		
+	else:
+		if len(three_prime_site) > 0:
+			tp_seq = enzDict[three_prime_site].lower()
+		else:
+			tp_seq = ""
+			
+	#print fp_seq
+	
+	# Removed March 8/10
+	# Start positions from 1 to make them human-readable
+	# Nov. 4/08: Use old strategy for SfiI
+	#if five_prime_site == "SfiI" and three_prime_site == "SfiI":
+		#m = re.findall("GGCC.....GGCC", sequence.upper())	# m is a LIST
+		
+		#if len(m) > 0:
+			#fp_seq = m[0].lower()
+			#tp_seq = m[1].lower()
+			
+			#if len(fp_seq) > 0 and sequence.find(fp_seq) >= 0:
+				#five_start_pos = sequence.index(fp_seq) + 1
+				#five_end_pos = five_start_pos + len(fp_seq) - 1
+			#else:
+				#five_start_pos = 0
+				#five_end_pos = 0
+			
+			#if len(tp_seq) > 0 and sequence.rfind(tp_seq) >= 0:
+				#three_start_pos = sequence.rfind(tp_seq) + 1
+				#three_end_pos = three_start_pos + len(tp_seq) - 1
+			#else:
+				#three_start_pos = 0
+				#three_end_pos = 0
+		#else:
+			#five_start_pos = 0
+			#five_end_pos = 0
+			
+			#three_start_pos = 0
+			#three_end_pos = 0
+	#else:
+	if len(fp_seq) > 0 and sequence.find(fp_seq) >= 0:
+		five_start_pos = sequence.index(fp_seq) + 1
+		five_end_pos = five_start_pos + len(fp_seq) - 1
+	else:
+		# Dec. 17/08
+		# reason could be that the site is a degenerate - try one more time with BioPython
+		tmpSeq = Bio.Seq.Seq(sequence)
+		
+		# Jan. 6/09: Gateway sites are not in enzDict
+		if sHandler.enzDict.has_key(five_prime_site):
+			fp_cs = sHandler.enzDict[five_prime_site]
+			
+			# dec. 18/08
+			fp_seq = fp_cs.elucidate().replace("_", "")
+			fp_clvg = fp_seq.find("^")
+			fp_flank = fp_seq[0:fp_clvg]
+			
+			tmp_fp_pos = fp_cs.search(tmpSeq)
+			tmp_fp_pos.sort()
+			
+			if len(tmp_fp_pos) > 0:	# Jan. 7/09: added > 0
+				five_start_pos = tmp_fp_pos[0] - len(fp_flank)
+				five_end_pos = five_start_pos + len(fp_cs.site) - 1	# Jan. 7/09: DO NOT use fp_seq; it contains the extra ^ char!!!
+				
+				if five_start_pos == 0:
+					five_start_pos = 0
+					five_end_pos = 0
+			else:
+				five_start_pos = 0
+				five_end_pos = 0
+		# Jan. 6/09: maybe a gateway site is not found
+		else:
+			five_start_pos = 0
+			five_end_pos = 0
+	
+	# 3' site: Regular search, no need to reverse complement
+	#print tp_seq
+	# Nov. 4/08: BUT search from END of sequence!!!!
+	if len(tp_seq) > 0 and sequence.rfind(tp_seq) >= 0:
+		three_start_pos = sequence.rfind(tp_seq) + 1
+		#print three_start_pos
+		three_end_pos = three_start_pos + len(tp_seq) - 1
+		#print three_end_pos
+	else:
+		# Dec. 17/08
+		# reason could be that the site is a degenerate - try one more time with BioPython
+		tmpSeq = Bio.Seq.Seq(sequence)
+		
+		# Jan. 6/09: Gateway sites are not in enzDict
+		if sHandler.enzDict.has_key(three_prime_site):
+			tp_cs = sHandler.enzDict[three_prime_site]
+			
+			# dec. 18/08
+			tp_seq = tp_cs.elucidate().replace("_", "")
+			tp_clvg = tp_seq.find("^")
+			tp_flank = tp_seq[0:tp_clvg]
+
+			tmp_tp_pos = tp_cs.search(tmpSeq)
+			tmp_tp_pos.sort()
+
+			if len(tmp_tp_pos) > 0:
+				three_start_pos = tmp_tp_pos[len(tmp_tp_pos)-1] - len(tp_flank)
+				three_end_pos = three_start_pos + len(tp_cs.site) - 1 	# Jan. 7/09: DO NOT use fp_seq; it contains the extra ^ char!!!
+				
+				if three_start_pos == 0:
+					three_start_pos = 0
+					three_end_pos = 0
+			else:
+				three_start_pos = 0
+				three_end_pos = 0
+		else:
+			# Jan. 6/09: Could simply be that a gateway site is not found in the sequence
+			three_start_pos = 0
+			three_end_pos = 0	
+			
+	#print five_start_pos
+	#print five_end_pos
+	
+	#print three_start_pos
+	#print three_end_pos
+	
+	# Insert new values for sites
+	rHandler.addReagentProperty(insertID, fpcs_prop_id, five_prime_site, five_start_pos, five_end_pos)
+	rHandler.addReagentProperty(insertID, tpcs_prop_id, three_prime_site, three_start_pos, three_end_pos)
+	
+	insertParentVector = parents["insert parent vector id"]
+	senseOligo = parents["sense oligo"]
+	antisenseOligo = parents["antisense oligo"]
+	
+	utils.redirect(hostname + "Reagent.php?View=2&Step=2&Type=Insert&rID=" + `insertID` + "&Seq=" + `seqID` + "&PIV=" + insertParentVector + "&SO=" + senseOligo + "&AS=" + antisenseOligo)
+	
+
+# Updated Sept. 8/08: Restrict parent access by project
+#def previewInsertSequence(insertID, parents):
+def previewInsertSequence(insertID, parents, currUser, uPackets):
+	
+	#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+	#print					# DITTO
+	#print `uPackets`
+	
+	# Delete any previous information for this reagent - for Inserts it's sequence and cloning sites - update July 9/09
+	seqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+	rHandler.deleteReagentProperty(insertID, seqPropID)
+	
+	# July 9/09
+	fpcs_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	tpcs_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	
+	# July 9/09
+	fp_linker_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	tp_linker_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	
+	# update July 9/09
+	rHandler.deleteReagentProperty(insertID, fpcs_prop_id)
+	rHandler.deleteReagentProperty(insertID, tpcs_prop_id)
+	
+	# Get parent values
+	senseOligo = parents["sense oligo"]
+	antisenseOligo = parents["antisense oligo"]
+	insertParentVector = parents["insert parent vector id"]
+	
+	# Store associations - Delete previous entries first!!!
+	assocID = raHandler.findReagentAssociationID(insertID)
+	
+	if assocID <= 0:
+		assocID = rHandler.createReagentAssociation(insertID, reagentType_Name_ID_Map["Insert"])
+	
+	senseAssocProp = aHandler.findAssocPropID("sense oligo")
+	antisenseAssocProp = aHandler.findAssocPropID("antisense oligo")
+	ipvAssocProp = aHandler.findAssocPropID("insert parent vector id")
+	
+	#packetPropID = pHandler.findPropID("packet id")
+	packetPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["packet id"], prop_Category_Name_ID_Map["General Properties"])
+	
+	# Sept. 8/08: Check each of the parent projects separately
+	# If a parent belongs to a project the creator does not have *read* access to, disallow creation
+	try:
+		# sense oligo
+		if (len(senseOligo) > 0):
+			try:
+				senseID = rHandler.convertReagentToDatabaseID(senseOligo)
+				senseProjectID = int(rHandler.findSimplePropertyValue(senseID, packetPropID))		# need to cast
+				#print "Sense " + `senseProjectID`
+				
+				if currUser.getCategory() != 'Admin' and senseProjectID not in uPackets:
+					i = SenseProjectAccessException("You do not have read access to this project")
+					
+					# Navigate to error page ("AP" stands for "Association Property")
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `insertID` + "&Type=Insert&SO=" + senseOligo + "&AS=" + antisenseOligo + "&PIV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `senseAssocProp`)
+					
+			except ReagentDoesNotExistException:
+					i = ReagentDoesNotExistException("Non-existing parent")
+
+					# Navigate to error page ("AP" stands for "Association Property")
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `insertID` + "&Type=Insert&SO=" + senseOligo + "&AS=" + antisenseOligo + "&PIV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `senseAssocProp`)
+		
+		# antisense oligo
+		if (len(antisenseOligo) > 0):
+			
+			try:
+				antisenseID = rHandler.convertReagentToDatabaseID(antisenseOligo)
+				antisenseProjectID = int(rHandler.findSimplePropertyValue(antisenseID, packetPropID))	# need to cast
+				#print "Antiense " + `antisenseProjectID`
+				
+				if currUser.getCategory() != 'Admin' and antisenseProjectID not in uPackets:
+					i = AntisenseProjectAccessException("You do not have read access to this project")
+					
+					# Navigate to error page ("AP" stands for "Association Property")
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `insertID` + "&Type=Insert&SO=" + senseOligo + "&AS=" + antisenseOligo + "&PIV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `senseAssocProp`)
+			
+			except ReagentDoesNotExistException:
+				i = ReagentDoesNotExistException("Non-existing parent")
+	
+				# Navigate to error page ("AP" stands for "Association Property")
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `insertID` + "&Type=Insert&SO=" + senseOligo + "&AS=" + antisenseOligo + "&PIV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `senseAssocProp`)
+			
+		# IPV
+		if (len(insertParentVector) > 0):
+			
+			try:
+				ipvID = rHandler.convertReagentToDatabaseID(insertParentVector)
+				ipvProjectID = int(rHandler.findSimplePropertyValue(ipvID, packetPropID))		# need to cast
+				#print "IPV " + `ipvProjectID`
+					
+				if currUser.getCategory() != 'Admin' and ipvProjectID not in uPackets:
+					i = IPVProjectAccessException("You do not have read access to this project")
+					
+					# Navigate to error page ("AP" stands for "Association Property")
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `insertID` + "&Type=Insert&SO=" + senseOligo + "&AS=" + antisenseOligo + "&PIV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `senseAssocProp`)
+					
+			except ReagentDoesNotExistException:
+				i = ReagentDoesNotExistException("Non-existing parent")
+				
+				# Navigate to error page ("AP" stands for "Association Property")
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `insertID` + "&Type=Insert&SO=" + senseOligo + "&AS=" + antisenseOligo + "&PIV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `senseAssocProp`)	
+		
+	except (TypeError, ValueError, IndexError):
+		# what to do here? throw an Invalid parent project exception?
+		parentProjectID = 0
+	
+	
+	# otherwise store parent values
+	for assocName in parents:
+		try:
+			parentValue = rHandler.convertReagentToDatabaseID(parents[assocName])
+			assocPropID = aHandler.findAssocPropID(assocName)
+				
+			# first delete, then insert
+			rHandler.deleteReagentAssociationProp(insertID, assocPropID)
+			rHandler.addAssociationValue(insertID, assocPropID, parentValue, assocID)
+
+		except ReagentDoesNotExistException:
+			i = ReagentDoesNotExistException("Parent does not exist")
+			utils.redirect(hostname + "Reagent.php?View=2&rID=" + `insertID` + "&Step=1&Type=Insert&PIV=" + insertParentVector + "&SO=" + senseOligo + "&AS=" + antisenseOligo + "&Err=" + `i.err_code()`)
+			
+	utils.redirect(hostname + "Reagent.php?View=2&rID=" + `insertID` + "&Step=1&Type=Insert&PIV=" + insertParentVector + "&SO=" + senseOligo + "&AS=" + antisenseOligo)
+	
+	
+# Upload selected properties at Vector or Cell Line creation
+def preload():
+	
+	form = cgi.FieldStorage()
+	
+	#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+	#print					# DITTO
+	#print `form`
+	
+	if form.has_key("curr_username"):
+		# store the user ID for use throughout the session; add to other views in addition to create in PHP
+		currUname = form.getvalue("curr_username")
+		currUser = uHandler.getUserByDescription(currUname)
+		Session.setUser(currUser)
+	
+	uPackets = getCurrentUserProjects(currUser)
+	
+	parents = {}
+	
+	# Initialize them both to False, but remember the difference! (see note on previewVectorSequence() function)
+	reverse_complement = False	# Jan. 21/09
+	reverse_insert = False		# Jan. 21/09
+
+	if form.has_key("preload"):
+		rType = form.getvalue("reagentType")
+		
+		# April 14/08: Create a new Reagent instance - IFF not returning to this view from a later page to update parents!!!
+		if form.has_key("reagent_id_hidden"):
+			rID = int(form.getvalue("reagent_id_hidden"))
+		else:
+			rID = rHandler.createNewReagent(rType)
+		
+		#print `rID`
+
+		reagent = rHandler.createReagent(rID)
+		
+		if rType == 'Vector':
+			subtype = form.getvalue("vectorSubtype")
+			reagent.setSubtype(subtype)
+			
+			# select parents according to subtype
+			if subtype == 'nonrecomb' or subtype == 'gateway_entry':
+				
+				pvAssocProp = aHandler.findAssocPropID("vector parent id")
+				insertAssocProp = aHandler.findAssocPropID("insert id")
+				
+				parentVectorID = form.getvalue("nr_parent_vector").strip()	# human-readable (e.g. V123)
+				insertID = form.getvalue("insert_id").strip()
+				
+				# April 28/08: Assign associations - on db level only, no benefit in creating Reagent objects for parents
+				try:
+					pv_db_id = rHandler.convertReagentToDatabaseID(parentVectorID)		# internal db ID
+				
+				except ReagentDoesNotExistException:
+					i = ReagentDoesNotExistException("Parent Vector ID not found in database")
+					
+					# "AP" stands for "Association Property"
+					# April 30/08: Added rID parameter
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&AP=" + `pvAssocProp`)
+				
+				try:
+					insert_db_id = rHandler.convertReagentToDatabaseID(insertID)
+		
+					parents["vector parent id"] = pv_db_id
+					parents["insert id"] = insert_db_id
+	
+					# Nov. 19/08
+					sites = []
+					
+					fpcs = ""
+					tpcs = ""
+					
+					if form.has_key("custom_sites"):
+						insert_fp_custom = form.getvalue("insert_custom_five_prime")
+						insert_tp_custom = form.getvalue("insert_custom_three_prime")
+						
+						pv_fp_custom = form.getvalue("pv_custom_five_prime")
+						pv_tp_custom = form.getvalue("pv_custom_three_prime")
+						
+						if insert_fp_custom == pv_fp_custom:
+							fpcs = pv_fp_custom
+						else:
+							fpcs = pv_fp_custom + "-" + insert_fp_custom
+					
+						if insert_tp_custom == pv_tp_custom:
+							tpcs = pv_tp_custom
+						else:
+							tpcs = insert_tp_custom + "-" + pv_tp_custom 
+					
+						#print fpcs
+						#print tpcs
+					
+						sites.append(fpcs)
+						sites.append(tpcs)
+					
+					# Jan. 21/09
+					if form.has_key("reverse_complement"):
+						reverse_complement = True
+					
+					#print `reverse_complement`
+					#print "????????" + `sites`
+					previewVectorSequence(rID, reagent, parents, currUser, db, cursor, sites, False, reverse_complement)
+					
+				except ReagentDoesNotExistException:
+					i = ReagentDoesNotExistException("Insert ID not found in database")
+					
+					#"AP" stands for "Association Property"
+					# April 30/08: Added rID parameter
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&AP=" + `insertAssocProp`)
+			
+			elif subtype == 'recomb' or subtype == 'gateway_expression':
+				
+				# Association-related db field names - declare here to be visible by exception handling
+				pvAssocProp = aHandler.findAssocPropID("vector parent id")
+				ipvAssocProp = aHandler.findAssocPropID("parent insert vector")
+				insertAssocProp = aHandler.findAssocPropID("insert id")
+				
+				parentVectorID = form.getvalue("rec_parent_vector").strip()	# human-readable (e.g. V123)
+				insertParentVectorID = form.getvalue("insert_parent_vector").strip()
+				
+				# April 28/08: Assign associations - on db level only, no benefit in creating Reagent objects for parents
+				try:
+					pv_db_id = rHandler.convertReagentToDatabaseID(parentVectorID)		# internal db ID
+					
+				except ReagentDoesNotExistException:
+					i = ReagentDoesNotExistException("Parent Vector ID not found in database")
+					
+					# "AP" stands for "Association Property"
+					# April 30/08: Added rID parameter
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&IPV=" + insertParentVectorID + "&Err=" + `i.err_code()` + "&AP=" + `pvAssocProp`)
+				
+				try:
+					ipv_db_id = rHandler.convertReagentToDatabaseID(insertParentVectorID)
+					
+					parents["vector parent id"] = pv_db_id
+					parents["parent insert vector"] = ipv_db_id
+	
+					# May 8/08: Find the Insert that belongs to IPV and pass it to previewSequence along with PV and IPV
+					ipvInsertAssocID = raHandler.findReagentAssociationID(ipv_db_id)
+					ipvAssocPropID = aHandler.findAssocPropID("parent insert vector")
+					insertAssocPropID = aHandler.findAssocPropID("insert id")
+					
+					try:
+						insert_db_id = aHandler.findAssocPropValue(ipvInsertAssocID, insertAssocPropID)
+						
+						if insert_db_id > 0:
+							parents["insert id"] = insert_db_id
+	
+						previewVectorSequence(rID, reagent, parents, currUser, db, cursor)
+					
+					except ReagentDoesNotExistException:
+						i = ReagentDoesNotExistException("Insert Parent Vector ID not found in database")
+						
+						#"AP" stands for "Association Property"
+						# April 30/08: Added rID parameter
+						utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&AP=" + `insertAssocProp`)
+				
+				except ReagentDoesNotExistException:
+					i = ReagentDoesNotExistException("Insert Parent Vector ID not found in database")
+					
+					#"AP" stands for "Association Property"
+					# April 30/08: Added rID parameter
+					# May 30/08: For simplicity. redirect to a common error page for non-existing IPV or lack of Insert for that IPV
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&IPV=" + insertParentVectorID + "&Err=" + `i.err_code()` + "&AP=" + `ipvAssocProp`)
+				
+		elif rType == 'CellLine':
+			#print "Content-type:text/html"
+			#print
+			
+			subtype = form.getvalue('cellLineSubtype')
+			parents = []
+
+			if subtype == 'stable_cell_line':
+				
+				# load properties from cell line and vector parents
+				parentVector = form.getvalue('cell_line_parent_vector').strip()
+				parentCellLine = form.getvalue('parent_cell_line').strip()
+				
+				parents.append(parentVector)
+				parents.append(parentCellLine)
+				
+				previewCellLineProperties(rID, rType, subtype, parents, currUser, db, cursor)
+			
+				redirect(hostname + "Reagent.php?View=2&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&CL=" + parentCellLine)
+		
+		elif rType == 'Insert':
+			# Removed Jan. 6/09: Was generating a new insert ID twice
+			## April 14/08: Create a new Reagent instance - IFF not returning to this view from a later page to update parents!!!
+			#if form.has_key("reagent_id_hidden"):
+				#insertID = int(form.getvalue("reagent_id_hidden"))
+			#else:
+				#insertID = rHandler.createNewReagent("Insert")
+				
+			parents = {}
+			
+			if form.has_key("insert_parent_vector"):
+				insertParentVector = form.getvalue("insert_parent_vector")
+			else:
+				insertParentVector = ""
+			
+			if form.has_key("sense_oligo"):
+				senseOligo = form.getvalue("sense_oligo")
+			else:
+				senseOligo = ""
+				
+			if form.has_key("antisense_oligo"):
+				antisenseOligo = form.getvalue("antisense_oligo")
+			else:
+				antisenseOligo = ""
+			
+			parents["insert parent vector id"] = insertParentVector
+			parents["sense oligo"] = senseOligo
+			parents["antisense oligo"] = antisenseOligo
+			
+			# Updated Jan. 6/09: Was generating a new insert ID twice
+			#previewInsertSequence(insertID, parents, currUser, uPackets)
+			previewInsertSequence(rID, parents, currUser, uPackets)
+
+	# Case 2: Press "Change Parents" button
+	elif form.has_key("change_parents"):
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		rType = form.getvalue("reagent_type_hidden")
+		subtype = form.getvalue("subtype_hidden")
+		
+		prefix = "reagent_detailedview_"
+		postfix = "_prop"
+	
+		# Nov. 11/08: Create a new Reagent instance - IFF not returning to this view from a later page to update parents!!!
+		if form.has_key("reagent_id_hidden"):
+			rID = int(form.getvalue("reagent_id_hidden"))
+		else:
+			rID = rHandler.createNewReagent(rType)
+		
+		if rType == 'Vector':
+		
+			# get parent values depending on subtype
+			parents = {}
+			
+			if subtype == 'nonrecomb' or subtype == 'gateway_entry':
+
+				# get parent vector and insert
+				parentVectorID = form.getvalue(prefix + "parent_vector_id" + postfix).strip()
+				insertID = form.getvalue(prefix + "insert_id" + postfix).strip()
+
+				pvAssocProp = aHandler.findAssocPropID("vector parent id")
+				insertAssocProp = aHandler.findAssocPropID("insert id")
+			
+				#parents.append(parentVectorID)
+				#parents.append(insertID)
+				
+				try:
+					pv_db_id = rHandler.convertReagentToDatabaseID(parentVectorID)		# internal db ID
+				
+				except ReagentDoesNotExistException:
+					i = ReagentDoesNotExistException("Parent Vector ID not found in database")
+					
+					# "AP" stands for "Association Property"
+					# April 30/08: Added rID parameter
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&AP=" + `pvAssocProp`)
+				
+				try:
+					insert_db_id = rHandler.convertReagentToDatabaseID(insertID)
+			
+					# If Insert is ok, update the reagent's existing association values and proceed to preview
+					assocDict = {}
+					
+					pv_assoc_alias = assoc_Name_Alias_Map["vector parent id"]
+					insert_assoc_alias = assoc_Name_Alias_Map["insert id"]
+					
+					assocDict[pv_assoc_alias] = pv_db_id
+					assocDict[insert_assoc_alias] = insert_db_id
+				
+					rHandler.updateReagentAssociations(rID, assocDict)
+					
+					parents["vector parent id"] = pv_db_id
+					parents["insert id"] = insert_db_id
+					
+				except ReagentDoesNotExistException:
+					i = ReagentDoesNotExistException("Insert ID not found in database")
+					
+					#"AP" stands for "Association Property"
+					# April 30/08: Added rID parameter
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&AP=" + `insertAssocProp`)
+					
+			elif subtype == 'recomb' or subtype == 'gateway_expression':
+				
+				parentVector = form.getvalue(prefix + "parent_vector_id" + postfix).strip()
+				insertParentVector = form.getvalue(prefix + "insert_parent_vector" + postfix).strip()
+
+				# change ASAP
+				#parents.append(parentVector)
+				#parents.append(insertParentVector)
+
+			else:
+				raise Exception("Unknown Vector subtype")
+
+			previewVectorSequence(rID, reagent, parents, currUser, db, cursor)
+			
+		# Added Sept. 8/08
+		elif rType == "Insert":
+			#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+			#print					# DITTO
+			#print "1"
+			
+			if form.has_key("reagent_id_hidden"):
+				insertID = int(form.getvalue("reagent_id_hidden"))
+			else:
+				insertID = rHandler.createNewReagent("Insert")
+				
+			parents = {}
+			
+			if form.has_key("insert_parent_vector"):
+				insertParentVector = form.getvalue("insert_parent_vector")
+			else:
+				insertParentVector = ""
+			
+			if form.has_key("sense_oligo"):
+				senseOligo = form.getvalue("sense_oligo")
+			else:
+				senseOligo = ""
+				
+			if form.has_key("antisense_oligo"):
+				antisenseOligo = form.getvalue("antisense_oligo")
+			else:
+				antisenseOligo = ""
+			
+			parents["insert parent vector id"] = insertParentVector
+			parents["sense oligo"] = senseOligo
+			parents["antisense oligo"] = antisenseOligo
+			
+			previewInsertSequence(insertID, parents, currUser, uPackets)
+
+		elif rType == 'CellLine':
+			prefix = "INPUT_CELLLINE_info_"
+			postfix = "_prop"
+
+			# load properties from cell line and vector parents
+			parentVector = form.getvalue(prefix + "vector_id" + postfix).strip()
+			parentCellLine = form.getvalue(prefix + "cellline_id" + postfix).strip()
+		
+			currReadProj = packetHandler.findMemberProjects(currUser.getUserID(), 'Reader')
+			currWriteProj = packetHandler.findMemberProjects(currUser.getUserID(), 'Writer')
+			publicProj = packetHandler.findAllProjects(isPrivate="FALSE")
+			
+			# list of Packet OBJECTS
+			currUserWriteProjects = utils.unique(currReadProj + currWriteProj + publicProj)
+			
+			uPackets = []
+			
+			for p in currUserWriteProjects:
+				uPackets.append(p.getNumber())
+				
+			# Get project IDs of parents
+			#packetPropID = pHandler.findPropID("packet id")
+			packetPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["packet id"], prop_Category_Name_ID_Map["General Properties"])
+			
+			# parent vector
+			try:
+				pv_db_id = rHandler.convertReagentToDatabaseID(parentVector)
+				pvProjectID = int(rHandler.findSimplePropertyValue(pv_db_id, packetPropID))	# need to cast
+				
+				if currUser.getCategory() != 'Admin' and pvProjectID not in uPackets:
+				
+					i = PVProjectAccessException("You do not have read access to this project")
+			
+					clpvAssocProp = aHandler.findAssocPropID("cell line parent vector id")
+	
+					utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clpvAssocProp`)
+					
+				else:
+					
+					# parent vector ok, check cell line
+					try:
+						cl_db_id = rHandler.convertReagentToDatabaseID(parentCellLine)
+						
+						# Use 'try' again to capture the project ID
+						try:
+							clProjectID = int(rHandler.findSimplePropertyValue(cl_db_id, packetPropID))
+							
+							if currUser.getCategory() != 'Admin' and clProjectID > 0 and clProjectID not in uPackets:
+								i = CLProjectAccessException("You do not have read access to this project")
+						
+								clAssocProp = aHandler.findAssocPropID("parent cell line id")
+				
+								utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clAssocProp`)
+							
+							else:
+								# user may view project, proceed
+								utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&CL=" + parentCellLine)
+						
+						except (TypeError, ValueError, IndexError):
+							
+						#elif (clProjectID == None or clProjectID <= 0) and currUser.getCategory() != 'Admin':
+							
+							i = CLProjectAccessException("You do not have read access to this project")
+					
+							clAssocProp = aHandler.findAssocPropID("parent cell line id")
+			
+							utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clAssocProp`)
+							
+						#else:
+							# everything ok, proceed
+							#redirect(hostname + "Reagent.php?View=2&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&CL=" + parentCellLine)
+			
+					except ReagentDoesNotExistException:
+						i = ReagentDoesNotExistException("Parent Cell Line ID not found in database")
+						
+						# get "parent cell line" association type
+						clAssocProp = aHandler.findAssocPropID("parent cell line id")
+						
+						# "AP" stands for "Association Property"
+						utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clAssocProp`)
+					
+			except ReagentDoesNotExistException:
+				i = ReagentDoesNotExistException("Parent Vector ID not found in database")
+				
+				# get "parent vector" association type
+				clpvAssocProp = aHandler.findAssocPropID("cell line parent vector id")
+				
+				# "AP" stands for "Association Property"
+				utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clpvAssocProp`)
+
+	# added April 28/08
+	elif form.has_key("confirm_features"):
+		
+		rType = form.getvalue("reagent_type_hidden")
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+
+		reverse = False				# Jan. 21/09
+
+		# April 14/08: Create a new Reagent instance - IFF not returning to this view from a later page to update parents!!!
+		if form.has_key("reagent_id_hidden"):
+			rID = int(form.getvalue("reagent_id_hidden"))
+		else:
+			rID = rHandler.createNewReagent(rType)
+		
+		reagent = rHandler.createReagent(rID)
+		
+		prefix = "reagent_detailedview_"
+		postfix = "_prop"
+	
+		parents = {}
+		
+		seqID = -1
+		sequence = ""
+		
+		# Fetch the old sequence of the reagent for feature remapping - non-Novel vectors
+		if form.has_key(prefix + "sequence" + postfix):
+			sequence = utils.squeeze(form.getvalue(prefix + "sequence" + postfix).strip())
+			
+			# Jan. 6/09: Store Insert in lowercase
+			if rType == "Insert":
+				sequence = sequence.lower()
+
+			seqID = sHandler.matchSequence(sequence)
+			
+			if seqID <= 0:
+				seqID = sHandler.insertSequence(sequence)
+				
+		if form.has_key("seq_id_hidden"):
+			oldSeqID = int(form.getvalue("seq_id_hidden"))
+			
+		else:
+			oldSeqID = seqID
+			
+		if rType == "Vector":
+			
+			sites = {}	# nov. 18/08
+
+			subtype = form.getvalue("subtype_hidden")
+			reagent.setSubtype(subtype)
+
+			if subtype == 'nonrecomb' or subtype == 'gateway_entry':
+			
+				if form.has_key(prefix + assoc_Name_Alias_Map["vector parent id"] + postfix) and form.has_key(prefix + assoc_Name_Alias_Map["insert id"] + postfix):
+					
+					pv_db_id = int(form.getvalue(prefix + assoc_Name_Alias_Map["vector parent id"] + postfix).strip())
+					insert_db_id = int(form.getvalue(prefix + assoc_Name_Alias_Map["insert id"] + postfix).strip())
+					
+					parents["vector parent id"] = pv_db_id
+					parents["insert id"] = insert_db_id
+					
+				# Nov. 18/08
+				if form.has_key(prefix + prop_Name_Alias_Map["5' cloning site"] + postfix):
+					fpcs = form.getvalue(prefix + prop_Name_Alias_Map["5' cloning site"] + postfix)
+					sites["5' cloning site"] = fpcs
+					
+				if form.has_key(prefix + prop_Name_Alias_Map["3' cloning site"] + postfix):
+					tpcs = form.getvalue(prefix + prop_Name_Alias_Map["3' cloning site"] + postfix)
+					sites["3' cloning site"] = tpcs
+					
+			elif subtype == 'recomb' or subtype == 'gateway_expression':
+
+				if form.has_key(prefix + assoc_Name_Alias_Map["vector parent id"] + postfix) and form.has_key(prefix + assoc_Name_Alias_Map["parent insert vector"] + postfix):
+					
+					pv_db_id = int(form.getvalue(prefix + assoc_Name_Alias_Map["vector parent id"] + postfix).strip())
+					ipv_db_id = int(form.getvalue(prefix + assoc_Name_Alias_Map["parent insert vector"] + postfix).strip())
+					
+					parents["vector parent id"] = pv_db_id
+					parents["parent insert vector"] = ipv_db_id
+					
+					# May 8/08: Find the Insert that belongs to IPV and pass it to previewSequence along with PV and IPV
+					ipvInsertAssocID = raHandler.findReagentAssociationID(ipv_db_id)
+					insertAssocPropID = aHandler.findAssocPropID("insert id")
+					insert_db_id = aHandler.findAssocPropValue(ipvInsertAssocID, insertAssocPropID)
+					
+					if insert_db_id > 0:
+						parents["insert id"] = insert_db_id
+			else:
+				parents = []
+			
+			if form.has_key("reverse_complement") and form.getvalue("reverse_complement") == '1':
+				reverse = True
+				
+			#print form.getvalue("reverse_complement")
+			#print "rev " + `reverse`
+			
+			previewVectorFeatures(rID, reagent, parents, oldSeqID, seqID, sequence, currUser, db, cursor, sites, reverse)
+			
+		elif rType == 'Insert':
+			parents = {}
+			
+			if form.has_key(prefix + assoc_Name_Alias_Map["insert parent vector id"] + postfix):
+				insertParentVector = form.getvalue(prefix + assoc_Name_Alias_Map["insert parent vector id"] + postfix)
+			else:
+				insertParentVector = ""
+				
+				#ipv_db_id = rHandler.convertReagentToDatabaseID(insertParentVector)
+				
+			if form.has_key(prefix + assoc_Name_Alias_Map["sense oligo"] + postfix):
+				senseOligo = form.getvalue(prefix + assoc_Name_Alias_Map["sense oligo"] + postfix)
+			else:
+				senseOligo = ""
+				#sense_id = rHandler.convertReagentToDatabaseID(senseOligo)
+				
+			if form.has_key(prefix + assoc_Name_Alias_Map["antisense oligo"] + postfix):
+				antisenseOligo = form.getvalue(prefix + assoc_Name_Alias_Map["antisense oligo"] + postfix)
+			else:
+				antisenseOligo = ""
+				#antisense_id = rHandler.convertReagentToDatabaseID(antisenseOligo)
+			
+			parents["insert parent vector id"] = insertParentVector
+			parents["sense oligo"] = senseOligo
+			parents["antisense oligo"] = antisenseOligo
+			
+			# Find or assign an ID to the sequence provided
+			if form.has_key(prefix + prop_Name_Alias_Map["sequence"] + postfix):
+				sequence = utils.squeeze(form.getvalue(prefix + prop_Name_Alias_Map["sequence"] + postfix).strip().lower())	# Aug. 17/09: filter whitespaces
+			else:
+				sequence = ""
+			
+			seqID = sHandler.getSequenceID(sequence)
+			
+			# Grab cloning sites
+			five_prime_site = form.getvalue(prefix + prop_Name_Alias_Map["5' cloning site"] + postfix)
+			
+			if five_prime_site == "Other":
+				five_prime_site = form.getvalue("5_prime_cloning_site_name_txt")
+			
+			three_prime_site = form.getvalue(prefix + prop_Name_Alias_Map["3' cloning site"] + postfix)
+			
+			if three_prime_site == "Other":
+				three_prime_site = form.getvalue("3_prime_cloning_site_name_txt")
+
+			previewInsertFeatures(rID, five_prime_site, three_prime_site, parents, sequence, seqID)
+	
+	elif form.has_key("confirm_intro"):
+		
+		# Save all incoming features and redirect to final creation step
+		rType = form.getvalue("reagent_type_hidden")
+		rTypeID = reagentType_Name_ID_Map[rType]
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `prop_Alias_Name_Map`
+		#print `form`
+		
+		prefix = "reagent_detailedview_"
+		postfix = "_prop"
+		
+		rID = int(form.getvalue("reagent_id_hidden"))
+		reagent = rHandler.createReagent(rID)
+		
+		# get sequence for redirection
+		seqID = rHandler.findDNASequenceKey(rID)
+		
+		reverse = False		# Jan. 22/09
+
+		if rType == 'Vector':
+			
+			subtype = form.getvalue("subtype_hidden")
+			reagent.setSubtype(subtype)
+
+			if subtype == 'nonrecomb' or subtype == 'gateway_entry':
+				
+				# Jan. 22/09
+				if form.has_key("reverse_complement") and form.getvalue("reverse_complement") == '1':
+					reverse = True
+			
+				# define here for the sake of error handling
+				pvAssocAlias = assoc_Name_Alias_Map["vector parent id"]
+				insertAssocAlias = assoc_Name_Alias_Map["insert id"]
+				
+				#print prefix + pvAssocAlias + postfix
+				#print prefix + insertAssocAlias + postfix
+				
+				if form.has_key(prefix + pvAssocAlias + postfix) and form.has_key(prefix + insertAssocAlias + postfix):
+					
+					parentVectorID = form.getvalue(prefix + pvAssocAlias + postfix).strip()
+					#print `parentVectorID`
+					insertID = form.getvalue(prefix + insertAssocAlias + postfix).strip()
+					
+					pv_db_id = int(rHandler.convertReagentToDatabaseID(parentVectorID))
+					insert_db_id = int(rHandler.convertReagentToDatabaseID(insertID))
+				
+				url = hostname + "Reagent.php?View=2&Step=3&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + `pv_db_id` + "&I=" + `insert_db_id` + "&Seq=" + `seqID` + "&Rev=" + `reverse`
+				
+			elif subtype == 'recomb' or subtype == 'gateway_expression':
+				# define here for the sake of error handling
+				pvAssocAlias = assoc_Name_Alias_Map["vector parent id"]
+				ipvAssocAlias = assoc_Name_Alias_Map["parent insert vector"]
+
+				#ipvInsertAssocID = raHandler.findReagentAssociationID(ipv_db_id)
+				
+				if form.has_key(prefix + pvAssocAlias + postfix) and form.has_key(prefix + ipvAssocAlias + postfix):
+					
+					parentVectorID = form.getvalue(prefix + pvAssocAlias + postfix).strip()
+					ipvID = form.getvalue(prefix + ipvAssocAlias + postfix).strip()
+					
+					pv_db_id = int(rHandler.convertReagentToDatabaseID(parentVectorID))
+					ipv_db_id = int(rHandler.convertReagentToDatabaseID(ipvID))
+				
+				url = hostname + "Reagent.php?View=2&Step=3&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + `pv_db_id` + "&IPV=" + `ipv_db_id` + "&Seq=" + `seqID`
+			
+			else:
+				# Novel
+				url = hostname + "Reagent.php?View=2&Step=3&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&Seq=" + `seqID`
+				
+		elif rType == 'Insert':
+			
+			pivAssocAlias = assoc_Name_Alias_Map["insert parent vector id"]
+			senseAssocAlias = assoc_Name_Alias_Map["sense oligo"]
+			antisenseAssocAlias = assoc_Name_Alias_Map["antisense oligo"]
+			
+			insertParentVector = ""
+			senseOligo = ""
+			antisenseOligo = ""
+			
+			if form.has_key("from_primer") and form.getvalue("from_primer") == 'True':
+				insertAssoc = reagent.getAssociations()
+				
+				senseOligo = rHandler.convertDatabaseToReagentID(insertAssoc["sense oligo"])
+				antisenseOligo = rHandler.convertDatabaseToReagentID(insertAssoc["antisense oligo"])
+				
+				# PIV is optional at primer design
+				insertParentVector = rHandler.convertDatabaseToReagentID(insertAssoc["insert parent vector id"])
+				
+				if insertParentVector == "":
+					#print prefix + pivAssocAlias + postfix
+					
+					if form.has_key(prefix + pivAssocAlias + postfix):
+						insertParentVector = form.getvalue(prefix + pivAssocAlias + postfix)
+						ipv_db_id = rHandler.convertReagentToDatabaseID(insertParentVector)
+						
+						pivAssocProp = aHandler.findAssocPropID("insert parent vector id")
+					
+						assocID = raHandler.findReagentAssociationID(rID)
+						
+						rHandler.deleteReagentAssociationProp(rID, pivAssocProp)
+						rHandler.addAssociationValue(rID, pivAssocProp, ipv_db_id, assocID)
+		
+				url = hostname + "Reagent.php?View=2&Step=5&rID=" + `rID` + "&Type=" + rType + "&SO=" + senseOligo + "&AS=" + antisenseOligo + "&PIV=" + insertParentVector + "&Seq=" + `seqID`
+		
+			else:
+				if form.has_key(prefix + pivAssocAlias + postfix):
+					insertParentVector = form.getvalue(prefix + pivAssocAlias + postfix)
+					
+				if form.has_key(prefix + senseAssocAlias + postfix):
+					senseOligo = form.getvalue(prefix + senseAssocAlias + postfix)
+				
+				if form.has_key(prefix + antisenseAssocAlias + postfix):
+					antisenseOligo = form.getvalue(prefix + antisenseAssocAlias + postfix)
+					
+				url = hostname + "Reagent.php?View=2&Step=3&rID=" + `rID` + "&Type=" + rType + "&PIV=" + insertParentVector + "&SO=" + senseOligo + "&AS=" + antisenseOligo + "&Seq=" + `seqID`
+		
+		
+		# Save features - taken from 'update.py'
+		# (deletion is performed in updateFeatures function, no need to call here)
+		newPropsDict_name = {}			# e.g. ('status', 'Completed')
+		newPropsDict_id = {}			# e.g. ('3', 'Completed') - db ID instead of property name
+		
+		startPosDict = {}			# (propID, startpos)
+		endPosDict = {}				# (propID, endpos)
+		
+		# Store orientation
+		orientationDict = {}			# (propID, orientation)
+		
+		# March 12/08: Treat properties with multiple values and start/end positions (a.k.a. features) as objects
+		seqFeatures = []
+
+		# March 17/08: Fetch Insert feature descriptors - tag position and expression system
+		# Use built-in Insert function instead of 'if-else' blocks with hardcoded values
+		featureDescriptors = reagent.getFeatureDescriptors()
+
+		# Update Sept. 10/09: No longer can hardcode feature names - must retrieve from database!!
+		# Update Oct. 26/09: Keep "DNA Sequence Features" as category, since this code is executed only for Vector and Insert.  But replace "Insert" with 'rType', b/c features differ for Vector and Insert
+		sequenceFeatures = rtPropHandler.findReagentTypeAttributeNamesByCategory(reagentType_Name_ID_Map[rType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+
+		#sequenceFeatures = reagent.getSequenceFeatures()	# removed Sept. 10/09
+		#print `sequenceFeatures`
+
+		# Removed May 16/08 - not a very good idea to delete all features, including sites and linkers - linkers may hinder modification but are necessary for correct feature remapping during Vector sequence reconstitution.  See what happens
+		#singleValueFeatures = reagent.getSingleFeatures()	# March 18/08 - Differentiate between features such as promoter or tag type, which could have multiple values, and cloning sites and linkers, which only have one value and one position
+		
+		#featureNames = sequenceFeatures + singleValueFeatures
+		#if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		#print prefix
+		
+		
+		rHandler.deleteReagentFeatures(rID)
+		
+		featureNames = sequenceFeatures
+		
+		featureAliases = {}
+		features = {}
+		
+		for f in featureNames:
+			fAlias = prop_Name_Alias_Map[f]
+			
+			# July 9/09
+			#fPropID = prop_Name_ID_Map[f]
+			fPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[f], prop_Category_Name_ID_Map["DNA Sequence Features"])
+			
+			featureAliases[fAlias] = f
+			features[fPropID] = f
+		
+		#print `featureAliases`
+		#print `prop_Alias_Name_Map`
+		
+		for fAlias in featureAliases:
+			#print fAlias
+			
+			# Special case: cDNA start and stop positions
+			if prop_Alias_Name_Map[fAlias].lower() == 'cdna insert':
+				
+				# removed Oct. 31/08 - done deletion already!!
+				## May 22/08: NOT FOR NOVEL VECTORS!!!!!!!
+				#if rType == 'Vector' and subtype == 'novel':
+					# delete any previously (incorrectly!) stored cDNA value
+					#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["cdna insert"])
+					#continue
+				
+				# No value, positions only
+				## Still need to create a new Feature instance
+				#fTemp = SequenceFeature(SequenceFeature)
+				
+				# changed July 9/09 - alias map is also affected by property sharing!
+				fName = prop_Alias_Name_Map[fAlias].lower()
+				fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fName], prop_Category_Name_ID_Map["DNA Sequence Features"])
+				#fID = prop_Alias_ID_Map[fAlias]
+				
+				#fType = prop_ID_Name_Map[fID]
+				#fTemp.setFeatureType(fType)
+				
+				startFieldName = prefix + fAlias + "_startpos" + postfix
+				endFieldName = prefix + fAlias + "_endpos" + postfix
+				
+				if form.has_key(startFieldName):
+					tmpStartPos = form.getvalue(startFieldName)
+					#print `tmpStartPos`
+					#fTemp.setFeatureStartPos(tmpStartPos)
+				else:
+					tmpStartPos = 0
+
+				if form.has_key(endFieldName):
+					tmpEndPos = form.getvalue(endFieldName)
+					#fTemp.setFeatureEndPos(tmpEndPos)
+				else:
+					tmpEndPos = 0
+					
+				#print tmpStartPos
+				#seqFeatures.append(fTemp)
+				
+				rHandler.addReagentProperty(rID, fID, "", tmpStartPos, tmpEndPos)
+				
+				# Jan. 22/09: Store cDNA orientation if Insert is reverse complemented
+				orientationFieldName = prefix + fAlias + "_orientation" + postfix
+				
+				if form.has_key(orientationFieldName):
+					tmpDir = form.getvalue(orientationFieldName)
+					#print tmpDir
+				else:
+					tmpDir = 'forward'
+
+				# Update July 2/09: pass cdnaPropID to setPropertyDirection() function in combination with its category
+				cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+				rHandler.setPropertyDirection(rID, cdnaPropID, tmpDir)
+				
+			# May 27/08: Cloning sites and Linkers (code is somewhat redundant and could be optimized but keep as is for now)
+			elif prop_Alias_Name_Map[fAlias].lower() == "5' cloning site":
+				five_prime_site = form.getvalue(prefix + prop_Name_Alias_Map["5' cloning site"] + postfix)
+				
+				#print "5' site " + five_prime_site
+				
+				# May 28/08: Allow blank sites for Novel vectors
+				if five_prime_site:
+					if five_prime_site == "Other":
+						fVal = form.getvalue("5_prime_cloning_site_name_txt")
+					else:
+						fVal = five_prime_site
+				else:
+					# just ignore site altogether
+					continue
+				
+				#fTemp = SequenceFeature(SequenceFeature)
+				#fID = prop_Alias_ID_Map[fAlias]		# removed July 20/09
+				
+				# update July 21/09
+				fid_tmp = prop_Alias_ID_Map[fAlias]
+				fID = pHandler.findReagentPropertyInCategoryID(fid_tmp, prop_Category_Name_ID_Map["DNA Sequence Features"])
+				#print fID
+				
+				# June 3/08: No! Cloning sites have only one value, so their position field names don't contain actual site!
+				#startFieldName = prefix + fAlias + "_" + fVal + "_startpos" + postfix
+				#endFieldName = prefix + fAlias + "_" + fVal + "_endpos" + postfix
+				
+				startFieldName = prefix + fAlias + "_startpos" + postfix
+				endFieldName = prefix + fAlias + "_endpos" + postfix
+				
+				if form.has_key(startFieldName):
+					fStartPos = form.getvalue(startFieldName)
+				else:
+					fStartPos = 0
+				
+				#print "start " + `fStartPos`
+				
+				if form.has_key(endFieldName):
+					fEndPos = form.getvalue(endFieldName)
+				else:
+					fEndPos = 0
+				
+				#print "end " + `fEndPos`
+				
+				#fTemp.setFeatureStartPos(fStartPos)
+				#fTemp.setFeatureEndPos(fEndPos)
+				
+				# Sept. 3/08: Store orientation
+				orientationFieldName = prefix + fAlias + "_orientation" + postfix
+				
+				if form.has_key(orientationFieldName):
+					tmpDir = form.getvalue(orientationFieldName)
+					#print tmpDir
+				else:
+					tmpDir = 'forward'
+				
+				#fTemp.setFeatureDirection(tmpDir)
+				
+				#seqFeatures.append(fTemp)
+				
+				rHandler.addReagentProperty(rID, fID, fVal, fStartPos, fEndPos, tmpDir)
+		
+			elif prop_Alias_Name_Map[fAlias].lower() == "3' cloning site":
+				
+				three_prime_site = form.getvalue(prefix + prop_Name_Alias_Map["3' cloning site"] + postfix)
+				
+				# May 28/08: Allow blank sites for Novel vectors
+				if three_prime_site:
+					if three_prime_site == "Other":
+						fVal = form.getvalue("3_prime_cloning_site_name_txt")
+					else:
+						fVal = three_prime_site
+				else:
+					# just ignore site altogether
+					continue
+					
+				#fTemp = SequenceFeature(SequenceFeature)
+				
+				# change July 20/09
+				#fID = prop_Alias_ID_Map[fAlias]
+				
+				fid_tmp = prop_Alias_ID_Map[fAlias]
+				fID = pHandler.findReagentPropertyInCategoryID(fid_tmp, prop_Category_Name_ID_Map["DNA Sequence Features"])
+				
+				#fType = prop_ID_Name_Map[fID]
+				#fTemp.setFeatureType(fType)
+				
+				#fTemp.setFeatureName(fVal)
+				
+				# June 3/08: Cloning sites have only one value, so their position field names don't contain actual site!
+				#startFieldName = prefix + fAlias + "_" + fVal + "_startpos" + postfix
+				#endFieldName = prefix + fAlias + "_" + fVal + "_endpos" + postfix
+				
+				startFieldName = prefix + fAlias + "_startpos" + postfix
+				endFieldName = prefix + fAlias + "_endpos" + postfix
+				
+				if form.has_key(startFieldName):
+					fStartPos = form.getvalue(startFieldName)
+				else:
+					fStartPos = 0
+					
+				if form.has_key(endFieldName):
+					fEndPos = form.getvalue(endFieldName)
+				else:
+					fEndPos = 0
+					
+				#fTemp.setFeatureStartPos(fStartPos)
+				#fTemp.setFeatureEndPos(fEndPos)
+		
+				# Sept. 3/08: Store orientation
+				orientationFieldName = prefix + fAlias + "_orientation" + postfix
+				
+				if form.has_key(orientationFieldName):
+					tmpDir = form.getvalue(orientationFieldName)
+					#print tmpDir
+				else:
+					tmpDir = 'forward'
+					
+				#fTemp.setFeatureDirection(tmpDir)
+				
+				#seqFeatures.append(fTemp)
+				
+				rHandler.addReagentProperty(rID, fID, fVal, fStartPos, fEndPos, tmpDir)
+			
+			else:
+				tmpStart = -1
+				tmpEnd = -1
+				#print prefix
+				
+				featureType = "dna_sequence_features"
+				
+				for tmpPropName in form.keys():
+					#print tmpPropName
+					#print fAlias
+					
+					# Updated July 2/09
+					fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map["DNA Sequence Features"])
+					#print tmpPropName
+					#print fID
+						
+					if tmpPropName.find(prefix + fAlias + "_:_") >= 0:
+						pValStartInd = len(prefix + fAlias)+3
+						#print pValStartInd
+						#pValStopInd = tmpPropName.find("_", pValStartInd)	# rmvd nov 1/09
+						pValStopInd = tmpPropName.rfind("_start_", pValStartInd)
+						#print pValStopInd
+						
+						# actual feature value - BUT before saving this value, check if it has been changed to Other
+						tmpPropValue = tmpPropName[pValStartInd:pValStopInd]
+						#print " feature " + tmpPropName
+						#print ", value " + tmpPropValue
+						
+						if tmpPropValue and len(tmpPropValue) > 0:
+							#print tmpPropValue
+							# get positions - changed oct. 25/08
+							
+							# Update Nov 3/09
+							#start_ind1 = tmpPropName.find(tmpPropValue) + len(tmpPropValue) + len("_start_")
+							
+							start_ind1 = tmpPropName.rfind("_start_") + len("_start_")
+							start_ind2 = tmpPropName.find("_end_")
+							#print start_ind2
+	
+							tmpStart = tmpPropName[start_ind1:start_ind2]
+							#print "start " + tmpStart
+							
+							if tmpStart and len(tmpStart) > 0 and int(tmpStart) > 0:
+								end_ind_1 = start_ind2 + len("_end_")
+								#print end_ind_1
+								end_ind_2 = tmpPropName.find("_", end_ind_1)
+								#print end_ind_2
+		
+								tmpEnd = tmpPropName[end_ind_1:end_ind_2]
+								#print "end " + tmpEnd
+								
+								if tmpEnd and len(tmpEnd) > 0 and int(tmpEnd) > 0:
+									tmpDirName = prefix + fAlias + "_:_" + tmpPropValue + "_start_" + `int(tmpStart)` + "_end_" + `int(tmpEnd)` + "_orientation" + postfix
+									#print tmpDirName
+									
+									if form.has_key(tmpDirName):
+										tmpDir = form.getvalue(tmpDirName)
+										#print "FOUND DIRECTION " + tmpDirName
+							
+										# Nov. 13/08: If there are duplicates, select one
+										if utils.isList(tmpDir):
+											#print "Descriptor " + tmpDescr
+											tmpDir = tmpDir[0]
+							
+										#fID = prop_Alias_ID_Map[fAlias]
+										fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map[prop_Category_Alias_Name_Map[featureType]])
+										
+										#print tmpPropValue
+										#print form[tmpPropName].value
+										
+										# Jan. 28/10: add 'Other' values to list
+										# With features, since their type/name/start/end/direction are encoded in the field name, 'Other' is the form value
+										#if tmpPropValue.lower() == 'other':
+											#print "SAVING OTHER!!!!!" + tmpPropName
+											
+											#tmpPropOther_text = rType + "_"  + featureType + "_:_" + fAlias + "_name_txt"
+										
+											##print tmpDescr_text
+											#tmpPropValue = form.getvalue(tmpPropOther_text)
+								
+											##print "SAVING OTHER " + `tmpPropValue`
+											#newSetEntry = tmpPropValue
+											
+											#print newSetEntry
+			
+										# invoke handler to add textbox value to dropdown list
+										rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, fID)
+									
+										#print fAlias
+										#print rTypeAttributeID
+										
+										# update Nov. 18/09
+										setGroupID = sysHandler.findPropSetGroupID(fID)	# it must exist
+									
+										#sHandler.updateSet(rTypeAttributeID, rType + " " + propName, newSetEntry)
+										ssetID = sysHandler.findSetValueID(setGroupID, tmpPropValue)
+										
+										if ssetID <= 0:
+											ssetID = sysHandler.addSetValue(setGroupID, tmpPropValue)
+									
+										#print ssetID
+										#print rTypeAttributeID
+										
+										if not sysHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+											sysHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+										
+										# descriptor
+										if featureDescriptors.has_key(prop_Alias_Name_Map[fAlias]):
+											tmpDescrName = featureDescriptors[prop_Alias_Name_Map[fAlias]]
+											tmpDescrAlias = prop_Name_Alias_Map[tmpDescrName]
+											#print "DESCRIPTOR " + tmpDescrAlias
+										
+											tmpDescrID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[tmpDescrName], prop_Category_Name_ID_Map[prop_Category_Alias_Name_Map[featureType]])
+										
+											#print tmpDescrID
+									
+											tmpDescrField = prefix + tmpDescrAlias + "_:_" + tmpPropValue + "_start_" + tmpStart + "_end_" + tmpEnd + postfix
+
+											#print tmpDescrField
+											
+											if form.has_key(tmpDescrField):
+												tmpDescr = form.getvalue(tmpDescrField)
+												
+												# Nov. 13/08: If there are duplicates, select one
+												if utils.isList(tmpDescr):
+													#print "Descriptor " + tmpDescr
+													tmpDescr = tmpDescr[0]
+										
+												#print "??" + tmpDescr + "!!"
+										
+												# jan. 28/10: save 'other'
+												# June 8, 2010: For descriptor have to go to textbox to fetch Other values
+												if tmpDescr.lower() == 'other':
+													
+													if fAlias == "tag":
+														descrAlias = "tag_position"
+													elif fAlias == "promoter":
+														descrAlias = "expression_system"
+										
+													tmpDescr_text = prefix + tmpDescrAlias + "_:_" + tmpPropValue + "_start_" + tmpStart + "_end_" + tmpEnd + "_name_txt"
+										
+													#print tmpDescr_text
+										
+													tmpDescr = form.getvalue(tmpDescr_text)
+										
+													#print "SAVING OTHER " + `tmpDescr`
+										
+												if utils.isList(tmpDescr):
+													tmpDescr = tmpDescr[0]
+													#print tmpDescr
+									
+												newSetEntry = tmpDescr
+										
+												#print newSetEntry
+		
+												# invoke handler to add textbox value to dropdown list
+												rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, tmpDescrID)
+										
+												#print rTypeAttributeID
+												
+												# update Nov. 18/09
+												setGroupID = sysHandler.findPropSetGroupID(tmpDescrID)
+										
+												#print setGroupID
+												
+												ssetID = sysHandler.findSetValueID(setGroupID, newSetEntry)
+												
+												if ssetID <= 0:
+													ssetID = sysHandler.addSetValue(setGroupID, newSetEntry)
+										
+												#print ssetID
+												
+												if not sysHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+													sysHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+											else:
+												tmpDescr = ""
+										else:
+											tmpDescr = ""
+									
+										if not rHandler.existsPropertyValue(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDescr, tmpDir):
+											rHandler.addReagentProperty(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDir)
+											
+											rHandler.setReagentFeatureDescriptor(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDescr)
+									else:
+										pass
+								else:
+									pass
+							else:
+								pass
+						else:
+							pass
+					else:
+						pass
+					
+					## convert to lowercase b/c of PolyA
+					#if tmpPropName.lower().find(prefix + fAlias.lower()) >= 0:
+						##print tmpPropName
+
+						#pValStartInd = len(prefix + fAlias.lower())+1
+						##print pValStartInd
+						#pValStopInd = tmpPropName.lower().find("_", pValStartInd)
+						
+						## actual feature value
+						#tmpPropValue = tmpPropName[pValStartInd:pValStopInd]
+						##print tmpPropValue
+						
+						#if tmpPropValue and len(tmpPropValue) > 0:
+							## get positions - changed oct. 25/08
+							#start_ind1 = tmpPropName.find(tmpPropValue) + len(tmpPropValue) + len("_start_")
+							#start_ind2 = tmpPropName.find("_end_")
+	
+							#tmpStart = tmpPropName[start_ind1:start_ind2]
+							##print "start " + `tmpStart`
+							
+							#if tmpStart and len(tmpStart) > 0 and int(tmpStart) > 0:
+								#end_ind_1 = start_ind2 + len("_end_")
+								##print end_ind_1
+								#end_ind_2 = tmpPropName.find("_", end_ind_1)
+								##print end_ind_2
+		
+								#tmpEnd = tmpPropName[end_ind_1:end_ind_2]
+								##print "; end " + `tmpEnd`
+								
+								#if tmpEnd and len(tmpEnd) > 0 and int(tmpEnd) > 0:
+									#tmpDirName = prefix + fAlias + "_" + tmpPropValue + "_start_" + `int(tmpStart)` + "_end_" + `int(tmpEnd)` + "_orientation" + postfix
+									##print tmpDirName
+									
+									#if form.has_key(tmpDirName):
+										#tmpDir = form.getvalue(tmpDirName)
+										##print "FOUND DIRECTION " + tmpDirName
+										
+										## Nov. 13/08: If there are duplicates, select one
+										#if utils.isList(tmpDir):
+											##print "Descriptor " + tmpDescr
+											#tmpDir = tmpDir[0]
+										
+										## descriptor
+										#if featureDescriptors.has_key(prop_Alias_Name_Map[fAlias]):
+											#tmpDescrName = featureDescriptors[prop_Alias_Name_Map[fAlias]]
+											#tmpDescrAlias = prop_Name_Alias_Map[tmpDescrName]
+											#tmpDescrField = prefix + tmpDescrAlias + "_" + tmpPropValue + "_start_" + tmpStart + "_end_" + tmpEnd + postfix
+										
+											#if form.has_key(tmpDescrField):
+												#tmpDescr = form.getvalue(tmpDescrField)
+										
+												## Nov. 13/08: If there are duplicates, select one
+												#if utils.isList(tmpDescr):
+													##print "Descriptor " + tmpDescr
+													#tmpDescr = tmpDescr[0]
+											#else:
+												#tmpDescr = ""
+										#else:
+											#tmpDescr = ""
+										
+										##print tmpPropValue
+										
+										## Dec. 1/08: Add 'Other' values
+										##if tmpPropValue == "Other":
+											##tmpPropValue = form.getvalue(prefix + fAlias + "_name_start_" + tmpStart + "_end_" + tmpEnd + postfix)
+											##print tmpPropValue
+										
+											##print "ever here??" + tmpPropValue
+							
+										#if not rHandler.existsPropertyValue(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDescr, tmpDir):
+											#rHandler.addReagentProperty(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDir)
+											
+											#rHandler.setReagentFeatureDescriptor(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDescr)
+										
+											#rTypeID = reagentType_Name_ID_Map[rType]
+										
+											#rTypeAttrID = rtPropHandler.findReagentTypeAttributeID(rTypeID, fID)
+										
+											#comments = rType + " " + prop_Alias_Descr_Map[fAlias]
+										
+											##sysHandler.updateSet(fAlias, tmpPropValue)
+											##sysHandler.updateSet(rTypeAttrID, comments, tmpPropValue)
+								#else:
+									#pass
+							#else:
+								#pass
+						#else:
+							#pass
+					#else:
+						#pass
+
+		# Sept. 3/08: Add linkers (not included in sequenceFeatures list, do separately)
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print
+	
+		# delete old values, because linkers are not included in features list that gets deleted
+		
+		# update July 20/09
+		fp_linker_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+		tp_linker_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+
+		rHandler.deleteReagentProperty(rID, fp_linker_prop_id)
+		rHandler.deleteReagentProperty(rID, tp_linker_prop_id)
+		
+		fAlias = prop_Name_Alias_Map["5' linker"]
+		#print fAlias
+		fp_linker_prop = prefix + fAlias + postfix
+		#print fp_linker_prop
+		
+		if form.has_key(fp_linker_prop):
+			fVal = form.getvalue(fp_linker_prop)
+			#print fVal
+			
+			#fTemp = SequenceFeature(SequenceFeature)
+			
+			# change July 20/09
+			#fID = prop_Alias_ID_Map[fAlias]
+			fid_tmp = prop_Alias_ID_Map[fAlias]
+			fID = pHandler.findReagentPropertyInCategoryID(fid_tmp, prop_Category_Name_ID_Map["DNA Sequence Features"])
+
+			#fType = prop_ID_Name_Map[fID]
+			#fTemp.setFeatureType(fType)
+			
+			#fTemp.setFeatureName(fVal)
+			
+			startFieldName = prefix + fAlias + "_startpos" + postfix
+			endFieldName = prefix + fAlias + "_endpos" + postfix
+			
+			fStartPos = form.getvalue(startFieldName)
+			fEndPos = form.getvalue(endFieldName)
+			
+			#fTemp.setFeatureStartPos(fStartPos)
+			#fTemp.setFeatureEndPos(fEndPos)
+			
+			# Sept. 3/08: Store orientation
+			orientationFieldName = prefix + fAlias + "_orientation" + postfix
+			tmpDir = form.getvalue(orientationFieldName)
+			#print tmpDir
+			#fTemp.setFeatureDirection(tmpDir)
+			
+			#seqFeatures.append(fTemp)
+			
+			if not rHandler.existsPropertyValue(rID, fID, fVal, fStartPos, fEndPos, tmpDir):
+				rHandler.addReagentProperty(rID, fID, fVal, fStartPos, fEndPos, tmpDir)
+		
+		# 3' linker
+		fAlias = prop_Name_Alias_Map["3' linker"]
+		#print fAlias
+		tp_linker_prop = prefix + fAlias + postfix
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print tp_linker_prop
+		
+		if form.has_key(tp_linker_prop):
+			fVal = form.getvalue(tp_linker_prop)
+			#print fVal
+			
+			#fTemp = SequenceFeature(SequenceFeature)
+			
+			# change July 20/09
+			fid_tmp = prop_Alias_ID_Map[fAlias]
+			fID = pHandler.findReagentPropertyInCategoryID(fid_tmp, prop_Category_Name_ID_Map["DNA Sequence Features"])
+
+			#fID = prop_Alias_ID_Map[fAlias]
+			
+			#fType = prop_ID_Name_Map[fID]
+			#fTemp.setFeatureType(fType)
+			
+			#fTemp.setFeatureName(fVal)
+			
+			startFieldName = prefix + fAlias + "_startpos" + postfix
+			endFieldName = prefix + fAlias + "_endpos" + postfix
+			
+			fStartPos = form.getvalue(startFieldName)
+			fEndPos = form.getvalue(endFieldName)
+			
+			#fTemp.setFeatureStartPos(fStartPos)
+			#fTemp.setFeatureEndPos(fEndPos)
+			
+			# Sept. 3/08: Store orientation
+			orientationFieldName = prefix + fAlias + "_orientation" + postfix
+			tmpDir = form.getvalue(orientationFieldName)
+			#print tmpDir
+			#fTemp.setFeatureDirection(tmpDir)
+			
+			#seqFeatures.append(fTemp)
+				
+			if not rHandler.existsPropertyValue(rID, fID, fVal, fStartPos, fEndPos, tmpDir):
+				rHandler.addReagentProperty(rID, fID, fVal, fStartPos, fEndPos, tmpDir)
+		
+		utils.redirect(url)
+	
+	elif form.has_key("process_warning"):
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		# take the appropriate action
+		action = form["warning_change_input"].value
+		
+		if action == 'restart':
+			# Nov. 17/08: Delete all previous information
+			# Delete (deprecate) the reagent itself, its properties, protein/DNA sequence and associations
+			rID = int(form.getvalue("reagent_id_hidden"))
+			rHandler.deleteReagent(rID)
+			utils.redirect(hostname  + "Reagent.php?View=2")
+		
+		elif action == 'next':
+			newSeqID = sHandler.matchSequence("")
+			utils.redirect(url + "&Seq=" + `newSeqID`)
+		
+		else:
+			# get new input values
+			
+			rType = form.getvalue("reagent_type_hidden")
+			subtype = form.getvalue("subtype_hidden")
+			
+			# April 30/08
+			rID = int(form.getvalue("reagent_id_hidden"))
+			reagent = rHandler.createReagent(rID)
+			
+			if rType == "Vector":
+				reagent.setSubtype(subtype)
+
+				# get parent values depending on subtype
+				parents = {}
+				url = ""	# the URL to redirect to, will have varying parent name parameters
+				
+				# Redundant code, but keep separate, as these are two separate actions
+				if subtype == 'nonrecomb' or subtype == 'gateway_entry':
+
+					# define here for the sake of error handling
+					pvAssocProp = aHandler.findAssocPropID("vector parent id")
+					insertAssocProp = aHandler.findAssocPropID("insert id")
+	
+					if form.has_key("new_nr_parent_vector") and form.has_key("new_insert_id"):
+						
+						parentVectorID = form.getvalue("new_nr_parent_vector").strip()
+						insertID = form.getvalue("new_insert_id").strip()
+						
+						try:
+							pv_db_id = rHandler.convertReagentToDatabaseID(parentVectorID)		# internal db ID
+							
+							try:
+								insert_db_id = rHandler.convertReagentToDatabaseID(insertID)
+
+							except ReagentDoesNotExistException:
+								i = ReagentDoesNotExistException("Insert ID not found in database")
+								
+								# "AP" stands for "Association Property"
+								# April 30/08: Added rID parameter
+								utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&AP=" + `insertAssocProp`)
+			
+						except ReagentDoesNotExistException:
+							i = ReagentDoesNotExistException("Parent Vector ID not found in database")
+							
+							# "AP" stands for "Association Property"
+							# April 30/08: Added rID parameter
+							utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID + "&Err=" + `i.err_code()` + "&AP=" + `pvAssocProp`)
+						
+						# if all ok save parents
+						parents["vector parent id"] = pv_db_id
+						parents["insert id"] = insert_db_id
+		
+						url = hostname + "Reagent.php?View=2&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&I=" + insertID
+
+						#print `sites`
+						if action == 'reverse_insert':
+							reverse_insert = True
+							
+							#print "reverse insert??" + `reverse_insert`
+						
+							# Feb. 23/10: why in the world would we reverse the order here????????
+							
+							## Feb. 2/09: Get custom sites from page AND REVERSE THEIR ORDER!!
+							#sites = []
+							
+							#if form.has_key("pv_custom_five_prime"):
+						
+								#pv_fpcs = form.getvalue("pv_custom_five_prime")
+								#pv_tpcs = form.getvalue("pv_custom_three_prime")
+								
+								#insert_fpcs = form.getvalue("insert_custom_five_prime")
+								#insert_tpcs = form.getvalue("insert_custom_three_prime")
+								
+								#if pv_fpcs == insert_fpcs:
+									#fpcs = pv_fpcs
+								#else:
+									#fpcs = pv_fpcs + "-" + insert_fpcs
+									
+								#if pv_tpcs == insert_tpcs:
+									#tpcs = pv_tpcs
+								#else:
+									#tpcs = insert_tpcs + "-" + pv_tpcs
+									
+							#else:
+								#fpcs = form.getvalue("5_prime_cloning_site")
+								#tpcs = form.getvalue("3_prime_cloning_site")
+							
+							##print "5' site " + fpcs
+							##print "3' site " + tpcs
+							
+							#sites.append(tpcs)
+							#sites.append(fpcs)
+						else:
+							reverse_insert = False
+							
+						# Moved this code segment here on Feb. 24/10. CANNOT hybridize sites w/o checking if the used actually wants to RC Insert and no hybridization is required!
+						
+						## Modified May 27/08: NO!!!!!  Fetch sites too in case they're hybrid and call previewSequence function again
+						## and take the appropriate action - either change sites or parents
+						##if action == 'change_parents':
+							## Only change parents, don't touch cloning sites
+							##previewVectorSequence(rID, reagent, parents, currUser, db, cursor)
+						##else:
+							## Here, explicitly changing sites, making one or both hybrid - Parents unchanged
+						sites = []
+						
+						if form.has_key("pv_custom_five_prime"):
+						
+							pv_fpcs = form.getvalue("pv_custom_five_prime")
+							pv_tpcs = form.getvalue("pv_custom_three_prime")
+							
+							insert_fpcs = form.getvalue("insert_custom_five_prime")
+							insert_tpcs = form.getvalue("insert_custom_three_prime")
+							
+							if not reverse_insert:
+								if pv_fpcs == insert_fpcs:
+									fpcs = pv_fpcs
+								else:
+									fpcs = pv_fpcs + "-" + insert_fpcs
+									
+								if pv_tpcs == insert_tpcs:
+									tpcs = pv_tpcs
+								else:
+									tpcs = insert_tpcs + "-" + pv_tpcs
+							else:
+								fpcs = insert_fpcs
+								tpcs = insert_tpcs
+						else:
+							fpcs = form.getvalue("5_prime_cloning_site")
+							tpcs = form.getvalue("3_prime_cloning_site")
+					
+						sites.append(fpcs)
+						sites.append(tpcs)
+						
+						previewVectorSequence(rID, reagent, parents, currUser, db, cursor, sites, reverse_insert)
+					else:
+						print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+						print					# DITTO
+						print "Unknown request"
+						
+				elif subtype == 'recomb' or subtype == 'gateway_expression':	
+					pvAssocProp = aHandler.findAssocPropID("vector parent id")
+					pivAssocProp = aHandler.findAssocPropID("parent insert vector")
+					insertAssocPropID = aHandler.findAssocPropID("insert id")
+
+					if form.has_key("rec_parent_vector") and form.has_key("insert_parent_vector"):
+						parentVector = form.getvalue("rec_parent_vector").strip()
+						insertParentVector = form.getvalue("insert_parent_vector").strip()
+					
+						try:
+							pv_db_id = rHandler.convertReagentToDatabaseID(parentVector)	# internal db ID
+							
+							try:
+								ipv_db_id = rHandler.convertReagentToDatabaseID(insertParentVector)
+								
+								# June 4, 2010: This restriction was lifted yesterday.  From now on, ALLOW to use non-recombination, even novel vectors as donors - AS LONG AS SEQUENCE CAN BE RECOMBINED.  See previewVectorSequence() function above.
+								
+								'''
+								# June 2/08: Restrict reagent types here: Check explicitly IPV's ATypeID to make sure it's 1 - i.e. only allow the usage of non-recombination vectors as Donors
+								donorATypeID = raHandler.findReagentAssociationType(ipv_db_id)
+									
+								if donorATypeID != assoc_Name_Type_Map["INSERT"]:
+									i = ReagentTypeException("Invalid Insert Parent Vector type")
+									
+									utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `pivAssocProp`)
+								else:
+									# Once you know this is a non-recomb. vector continue
+									ipvAssocID = raHandler.findReagentAssociationID(ipv_db_id)
+	
+									if ipvAssocID:
+										insert_db_id = aHandler.findAssocPropValue(ipvAssocID, insertAssocPropID)
+										
+										if insert_db_id > 0:
+											parents["insert id"] = insert_db_id
+										else:
+											i = ReagentDoesNotExistException("Invalid Insert Parent Vector ID")
+									
+											# "AP" stands for "Association Property"
+											# April 30/08: Added rID parameter
+											utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `pivAssocProp`)
+						
+									else:
+										i = ReagentDoesNotExistException("Invalid Insert Parent Vector ID")
+									
+										# "AP" stands for "Association Property"
+										# April 30/08: Added rID parameter
+										utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `pivAssocProp`)
+								'''
+								
+							except ReagentDoesNotExistException:
+								i = ReagentDoesNotExistException("Insert Parent Vector ID not found in database")
+								
+								# "AP" stands for "Association Property"
+								# April 30/08: Added rID parameter
+								utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `pivAssocProp`)
+			
+						except ReagentDoesNotExistException:
+							i = ReagentDoesNotExistException("Parent Vector ID not found in database")
+							
+							# "AP" stands for "Association Property"
+							# April 30/08: Added rID parameter
+							utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector + "&Err=" + `i.err_code()` + "&AP=" + `pvAssocProp`)
+						
+						# if all ok save parents
+						parents["vector parent id"] = pv_db_id
+						parents["parent insert vector"] = ipv_db_id
+		
+						url = hostname + "Reagent.php?View=2&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&IPV=" + insertParentVector
+						
+						# and take the appropriate action - either change sites or parents
+						if action == 'change_parents':
+							# Only change parents, don't touch cloning sites
+							previewVectorSequence(rID, reagent, parents, currUser, db, cursor)
+						else:
+							# Here, explicitly changing sites, making one or both hybrid - Parents unchanged
+							sites = []
+							
+							fpcs = form.getvalue("5_prime_cloning_site")
+							tpcs = form.getvalue("3_prime_cloning_site")
+					
+							sites.append(fpcs)
+							sites.append(tpcs)
+				
+							previewVectorSequence(rID, reagent, parents, currUser, db, cursor, sites)
+					
+				else:
+					raise Exception("Unknown Vector subtype")
+			
+			elif rType == "Insert":
+				#utils.redirect(hostname + "Reagent.php?View=2")	# removed Sept. 8/08
+				
+				# Added Sept. 8/08
+				if form.has_key("reagent_id_hidden"):
+					insertID = int(form.getvalue("reagent_id_hidden"))
+				else:
+					insertID = rHandler.createNewReagent("Insert")
+					
+				parents = {}
+				
+				if form.has_key("insert_parent_vector"):
+					insertParentVector = form.getvalue("insert_parent_vector")
+				else:
+					insertParentVector = ""
+				
+				if form.has_key("sense_oligo"):
+					senseOligo = form.getvalue("sense_oligo")
+				else:
+					senseOligo = ""
+					
+				if form.has_key("antisense_oligo"):
+					antisenseOligo = form.getvalue("antisense_oligo")
+				else:
+					antisenseOligo = ""
+				
+				parents["insert parent vector id"] = insertParentVector
+				parents["sense oligo"] = senseOligo
+				parents["antisense oligo"] = antisenseOligo
+				
+				previewInsertSequence(insertID, parents, currUser, uPackets)
+
+			
+			elif rType == "CellLine":
+				
+				if subtype == "stable_cell_line":
+					parents = []
+					
+					parentVector = form.getvalue('cell_line_parent_vector').strip()
+					parentCellLine = form.getvalue('parent_cell_line').strip()
+					
+					# Verify parent packets!!!
+					currReadProj = packetHandler.findMemberProjects(currUser.getUserID(), 'Reader')
+					currWriteProj = packetHandler.findMemberProjects(currUser.getUserID(), 'Writer')
+					publicProj = packetHandler.findAllProjects(isPrivate="FALSE")
+					
+					# list of Packet OBJECTS
+					currUserWriteProjects = utils.unique(currReadProj + currWriteProj + publicProj)
+					
+					uPackets = []
+					
+					for p in currUserWriteProjects:
+						uPackets.append(p.getNumber())
+						
+					# Get project IDs of parents
+					#packetPropID = pHandler.findPropID("packet id")
+					packetPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["packet id"], prop_Category_Name_ID_Map["General Properties"])
+					
+					# parent vector
+					try:
+						pv_db_id = rHandler.convertReagentToDatabaseID(parentVector)
+						pvProjectID = int(rHandler.findSimplePropertyValue(pv_db_id, packetPropID))	# need to cast
+						
+						if currUser.getCategory() != 'Admin' and pvProjectID not in uPackets:
+						
+							i = PVProjectAccessException("You do not have read access to this project")
+					
+							clpvAssocProp = aHandler.findAssocPropID("cell line parent vector id")
+			
+							utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clpvAssocProp`)
+							
+						else:
+							
+							# parent vector ok, check cell line
+							try:
+								cl_db_id = rHandler.convertReagentToDatabaseID(parentCellLine)
+								
+								# Use 'try' again to capture the project ID
+								try:
+									clProjectID = int(rHandler.findSimplePropertyValue(cl_db_id, packetPropID))
+									
+									if currUser.getCategory() != 'Admin' and clProjectID > 0 and clProjectID not in uPackets:
+										i = CLProjectAccessException("You do not have read access to this project")
+								
+										clAssocProp = aHandler.findAssocPropID("parent cell line id")
+						
+										utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clAssocProp`)
+									
+									else:
+										# user may view project, proceed
+										utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&CL=" + parentCellLine)
+								
+								except (TypeError, ValueError, IndexError):
+									
+								#elif (clProjectID == None or clProjectID <= 0) and currUser.getCategory() != 'Admin':
+									
+									i = CLProjectAccessException("You do not have read access to this project")
+							
+									clAssocProp = aHandler.findAssocPropID("parent cell line id")
+					
+									utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clAssocProp`)
+									
+								#else:
+									# everything ok, proceed
+									#redirect(hostname + "Reagent.php?View=2&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVector + "&CL=" + parentCellLine)
+					
+							except ReagentDoesNotExistException:
+								i = ReagentDoesNotExistException("Parent Cell Line ID not found in database")
+								
+								# get "parent cell line" association type
+								clAssocProp = aHandler.findAssocPropID("parent cell line id")
+								
+								# "AP" stands for "Association Property"
+								utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clAssocProp`)
+							
+					except ReagentDoesNotExistException:
+						i = ReagentDoesNotExistException("Parent Vector ID not found in database")
+						
+						# get "parent vector" association type
+						clpvAssocProp = aHandler.findAssocPropID("cell line parent vector id")
+						
+						# "AP" stands for "Association Property"
+						utils.redirect(hostname + "Reagent.php?View=2&rID=" + `rID` + "&Type=" + rType + "&Sub=" + subtype + "&PV=" + parentVectorID + "&CL=" + parentCellLine + "&Err=" + `i.err_code()` + "&AP=" + `clpvAssocProp`)
+	
+					parents.append(parentVector)
+					parents.append(parentCellLine)
+					
+					# take the appropriate action
+					action = form["warning_change_input"].value
+					
+					if action == 'restart':
+						utils.redirect(hostname  + "Reagent.php?View=2&rID=" + `rID`)
+				
+					elif action == 'change_parents':
+						# Only change parents, don't touch cloning sites
+						previewCellLineProperties(rID, rType, subtype, parents, currUser, db, cursor)
+	
+	# Nov. 5/08: Add 'Cancel' function
+	elif form.has_key("cancel_creation"):
+		
+		# Delete (deprecate) the reagent itself, its properties, protein/DNA sequence and associations
+		rType = form.getvalue("reagent_type_hidden")
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `prop_Alias_Name_Map`
+		#print `form`
+		
+		prefix = "reagent_detailedview_"
+		postfix = "_prop"
+		
+		rID = int(form.getvalue("reagent_id_hidden"))
+		
+		# if this is an Insert made from Primer, delete the newly created Oligos too
+		if form.has_key("from_primer") and form.getvalue("from_primer") == 'True':
+			senseOligoID = iHandler.findSenseOligoID(rID)
+			antisenseOligoID = iHandler.findAntisenseOligoID(rID)
+			
+			rHandler.deleteReagent(senseOligoID)
+			rHandler.deleteReagent(antisenseOligoID)
+			rHandler.deleteReagent(rID)
+		else:
+			rHandler.deleteReagent(rID)
+		
+		utils.redirect(hostname + "Reagent.php?View=1")
+
+	cursor.close()
+	db.close()
+	
+preload()
diff --git a/OpenFreezer/cgi/prep.py b/OpenFreezer/cgi/prep.py
new file mode 100755
index 0000000..79c6fbb
--- /dev/null
+++ b/OpenFreezer/cgi/prep.py
@@ -0,0 +1,67 @@
+#!/usr/local/bin/python
+
+# python modules
+import cgi
+import cgitb; cgitb.enable()
+
+import SocketServer
+from SocketServer import BaseRequestHandler
+
+import MySQLdb
+
+import os
+import tempfile
+import stat
+import sys
+import string
+
+# Custom modules
+import utils
+
+from database_conn import DatabaseConn
+#from session import Session
+
+from general_handler import GeneralHandler
+from laboratory import Laboratory
+
+class PrepProperty:
+	
+	__propID = 0			# internal database ID
+	__propName = ""			# 'Method ID', 'Bacteria', 'Plates/Vial', etc.
+	__propValue = ""
+
+	def __init__(self, propID, propName, propValue):
+		
+		self.__propID = propID
+		self.__propName = propName
+		self.__propValue = propValue
+
+	
+	#################################################
+	# Assignment methods
+	#################################################
+	def setPropID(self, propID):
+		self.__propID = propID
+		
+		
+	def setPropName(self, propName):
+		self.__propName = propName
+		
+		
+	def setPropValue(self, propValue):
+		self.__propValue = propValue
+		
+		
+	#################################################
+	# Access methods
+	#################################################
+	def getPropID(self):
+		return self.__propID
+	
+	
+	def getPropName(self):
+		return self.__propName
+	
+	
+	def getPropValue(self):
+		return self.__propValue
\ No newline at end of file
diff --git a/OpenFreezer/cgi/preview.py b/OpenFreezer/cgi/preview.py
new file mode 100755
index 0000000..9ce3876
--- /dev/null
+++ b/OpenFreezer/cgi/preview.py
@@ -0,0 +1,64 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+	
+import MySQLdb
+import sys
+import string
+
+from database_conn import DatabaseConn	# april 20/07 
+from exception import *
+import utils
+
+from mapper import ReagentPropertyMapper, ReagentAssociationMapper, ReagentTypeMapper
+from general_handler import ReagentPropertyHandler, ReagentAssociationHandler, AssociationHandler
+from reagent_handler import ReagentHandler, InsertHandler
+from sequence_handler import DNAHandler, ProteinHandler
+from comment_handler import CommentHandler
+from system_set_handler import SystemSetHandler
+
+# User and Project info
+from user_handler import UserHandler
+from project_database_handler import ProjectDatabaseHandler
+from session import Session
+
+
+def preview():
+	dbConn = DatabaseConn()
+	db = dbConn.databaseConnect()
+	
+	cursor = db.cursor()
+	hostname = dbConn.getHostname()
+
+	rHandler = ReagentHandler(db, cursor)
+	propMapper = ReagentPropertyMapper(db, cursor)
+	
+	prop_Alias_ID_Map = propMapper.mapPropAliasID()
+	
+	form = cgi.FieldStorage(keep_blank_values="True")
+
+	#print "Content-type:text/html"		# REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+	#print					# DITTO
+	#print `form`
+	
+	propVal = ""
+	
+	if form.has_key("PV"):
+		pvVal = form.getvalue("PV")
+		pvID = rHandler.convertReagentToDatabaseID(pvVal)
+		
+	if form.has_key("propAlias"):
+		propAlias = form.getvalue("propAlias")
+	
+	
+	if prop_Alias_ID_Map.has_key(propAlias):
+		propID = prop_Alias_ID_Map[propAlias]	
+		propVal = rHandler.findSimplePropertyValue(pvID, propID)
+		
+	
+	print "Content-type:text/html"		# REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+	print					# DITTO
+	print propVal
+	
+preview()
\ No newline at end of file
diff --git a/OpenFreezer/cgi/project_database_handler.py b/OpenFreezer/cgi/project_database_handler.py
new file mode 100755
index 0000000..c8a3e66
--- /dev/null
+++ b/OpenFreezer/cgi/project_database_handler.py
@@ -0,0 +1,519 @@
+##############################################################################################
+# This module serves as an intermediate layer between the database and Packet module objects
+#
+# Written: May 25, 2007, by Marina Olhovsky
+# Last modified: July 5, 2007
+##############################################################################################
+
+import MySQLdb
+import utils
+
+from general_handler import GeneralHandler, ReagentPropertyHandler
+from comment_handler import CommentHandler
+from user_handler import UserHandler
+
+from packet import Packet
+from laboratory import Laboratory
+from user import User
+
+from exception import *
+
+class ProjectDatabaseHandler(GeneralHandler):
+
+	def __init__(self, db, cursor):
+		super(ProjectDatabaseHandler, self).__init__(db, cursor)
+
+
+	# Fetch all info on project identified by packetID
+	def findPacket(self, packetID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		uHandler = UserHandler(db, cursor)
+		
+		newPacket = None
+
+		cursor.execute("SELECT ownerID, packetName, is_private, comment FROM Packets_tbl p, GeneralComments_tbl c WHERE packetID=" + `packetID` + " AND p.packetDescription = c.commentID AND p.status='ACTIVE' AND c.status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			ownerID = int(result[0])
+			packetOwner = uHandler.getUserByID(ownerID)
+			
+			packetName = result[1]
+			
+			# private or public
+			accessType = result[2]
+			
+			# Value TRUE or FALSE is returned as a STRING, convert to Boolean
+			if accessType == 'TRUE':
+				isPrivate = True
+			else:
+				isPrivate = False
+
+			packetDescr = result[3]
+
+			packetReaders = self.findProjectMembers(packetID, 'Reader')
+			packetWriters = self.findProjectMembers(packetID, 'Writer')
+
+			newPacket = Packet(packetID, packetName, packetDescr, packetOwner, isPrivate, packetReaders, packetWriters)
+
+		return newPacket
+		
+
+	# Returns: INT, the value of column packetDescription in Packtes_tbl, refers to commentID in GeneralComments_tbl
+	def findPacketDescriptionID(self, packetID):
+		db = self.db
+		cursor = self.cursor
+		
+		descrCommID = -1
+		
+		cursor.execute("SELECT packetDescription FROM Packets_tbl WHERE packetID=" + `packetID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			descrCommID = int(result[0])
+			
+		return descrCommID
+			
+
+	# Returns: STRING, the actual text description of this project
+	def findPacketDescription(self, packetID):
+		db = self.db
+		cursor = self.cursor
+		
+		commHandler = CommentHandler(db, cursor)
+		
+		descrCommID = self.findPacketDescriptionID(packetID)
+		description = commHandler.findCommentByID(descrCommID)
+		
+		return description
+		
+
+	# Make an entry in Packets_tbl for a new Project
+	# Modified June 20/07: Take as arguments a Project instance
+	def insertPacket(self, packet):
+	
+		db = self.db
+		cursor = self.cursor
+	
+		# extract all attributes from 'packet'
+		projectID = packet.getNumber()
+		
+		# Owner is a User instance.  Get his user ID
+		owner = packet.getOwner()
+		packetOwner = owner.getUserID()		
+		
+		packetName = packet.getName()
+		packetDescription = packet.getDescription()	# may be empty
+		
+		packetReaders = packet.getReaders()		# list of User instances
+		packetWriters = packet.getWriters()
+		
+		# Create a Comment table entry for Project description
+		commHandler = CommentHandler(db, cursor)
+
+		# select 'Packet' commentLinkID
+		packetCommLinkID = commHandler.findCommentLinkID('Packet')
+		descrCommID = commHandler.insertComment(packetCommLinkID, packetDescription)
+
+		# Private or public
+		#isPrivate = packet.isPrivate()
+		
+		# convert Boolean values to text, not stored otherwise
+		if packet.isPrivate() == False:
+			isPrivate = 'FALSE'
+		else:
+			isPrivate = 'TRUE'
+			
+		cursor.execute("INSERT INTO Packets_tbl(packetID, ownerID, packetName, packetDescription, is_private) VALUES(" + `projectID` + ", " + `packetOwner` + ", " + `packetName` + ", " + `descrCommID` + ", " + `isPrivate` + ")")
+		packetID = int(db.insert_id())
+		
+		self.insertPacketReaders(packetID, packetReaders)
+		self.insertPacketWriters(packetID, packetWriters)
+		
+		return packetID
+		
+
+	# Update project information with new values
+	def updatePacket(self, projectID, ownerID, projectName, projectDescr, isPrivate, projectReaderIDs, projectWriterIDs):
+
+		db = self.db
+		cursor = self.cursor
+
+		commHandler = CommentHandler(db, cursor)
+
+		# simple: name and owner
+		cursor.execute("UPDATE Packets_tbl SET ownerID=" + `ownerID` + " WHERE packetID=" + `projectID`)
+		cursor.execute("UPDATE Packets_tbl SET packetName=" + `projectName` + " WHERE packetID=" + `projectID`)
+		
+		# private or public
+		# again, convert Boolean values to text; otherwise they're not stored
+		if isPrivate == False:
+			isPrivate = 'FALSE'
+		else:
+			isPrivate = 'TRUE'
+			
+		cursor.execute("UPDATE Packets_tbl SET is_private=" + `isPrivate` + " WHERE packetID=" + `projectID`)
+
+		# description
+		packetCommLinkID = commHandler.findCommentLinkID('Packet')
+		packetDescr = commHandler.findCommentID(projectDescr, packetCommLinkID)
+		cursor.execute("UPDATE Packets_tbl SET packetDescription=" + `packetDescr` + " WHERE packetID=" + `projectID`)
+
+		# members
+		self.updateProjectMembers(projectID, projectReaderIDs, 'Reader')
+		self.updateProjectMembers(projectID, projectWriterIDs, 'Writer')
+
+
+	# Is a project empty? i.e. no reagents associated with it
+	def isEmpty(self, pID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		rpHandler = ReagentPropertyHandler(db, cursor)
+		projectPropID = rpHandler.findPropID("packet id")
+		
+		cursor.execute("SELECT COUNT(reagentID) FROM ReagentPropList_tbl WHERE propertyID=" + `projectPropID` + " AND propertyValue=" + `pID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			numReagents = int(result[0])
+			return numReagents == 0
+		else:
+			return True
+
+
+	def isPrivate(self, pID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT is_private FROM Packets_tbl WHERE packetID=" + `pID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result[0] == 'TRUE':
+			return True
+		else:
+			return False
+
+
+	# Input: pID: INT, packet ID
+	def deleteProject(self, pID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		commHandler = CommentHandler(db, cursor)
+
+		# CHECK THAT THERE ARE NO REAGENTS ASSOCIATED WITH THIS PROJECT!!!
+		if self.isEmpty(pID):
+		
+			# update Packets, Comments and ProjectMembers tables
+			cursor.execute("UPDATE Packets_tbl SET status='DEP' WHERE packetID=" + `pID` + " AND status='ACTIVE'")
+
+			# find description
+			descrID = self.findPacketDescriptionID(pID)
+			commHandler.deleteComment(descrID)
+
+			# delete members
+			self.deleteAllProjectMembers(pID)
+			return True
+		else:
+			return False
+
+
+	# Find members of project identified by 'projectID' that function as role' in this project
+	# 'role': Reader/Writer
+	# Return: List of User **objects**
+	def findProjectMembers(self, projectID, role):
+
+		db = self.db
+		cursor = self.cursor
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		
+		uHandler = UserHandler(db, cursor)
+		
+		members = []
+		
+		# include status='ACTIVE' clause; otherwise a DEP member might be selected causing an error
+		cursor.execute("SELECT p.memberID, u.firstname, u.lastname, u.description, u.category, u.labID, l.lab_name, l.description FROM ProjectMembers_tbl p, Users_tbl u, LabInfo_tbl l WHERE p.packetID=" + `projectID` + " AND p.role=" + `role` + " AND u.userID=p.memberID AND l.labID=u.labID AND p.status='ACTIVE' AND u.status='ACTIVE' AND l.status='ACTIVE'")
+		results = cursor.fetchall()
+				
+		for result in results:
+			
+			memberID = int(result[0])
+			
+			# removed, more efficient and accurate to rewrite query here and include 'status=ACTIVE' clause
+			#member = uHandler.getUserByID(memberID)
+			
+			memberFirstName = result[1]
+			memberLastName = result[2]
+			memberFullName = result[3]
+			memberCategory = int(result[4])
+			memberLabID = result[5]
+			
+			labName = result[6]
+			labDescr = result[7]
+			tempLab = Laboratory(memberLabID, labName, labDescr)
+			
+			member = User(memberID, "", memberFirstName, memberLastName, memberFullName, tempLab, memberCategory)
+			
+			members.append(member)
+		
+		return members
+		
+	
+	# Given a member ID, find all his/her projects
+	# Return list of Project **OBJECTS**
+	# Updated Sept. 5/07: 'role' can be one of 'Reader', 'Writer', or OWNER
+	def findMemberProjects(self, memberID, role):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		projects = []
+		
+		if role.lower() == 'owner':
+			cursor.execute("SELECT p.packetID, p.packetName, p.ownerID, u.lastName FROM Packets_tbl p, Users_tbl u WHERE p.ownerID =" + `memberID` + " AND u.userID=p.ownerID AND p.status='ACTIVE'")	# project owner cannot be DEP in this case, since it's the user currently logged in, but some of his/her projects may very well be DEP - so only select ACTIVE projects for the current user
+		else:
+			# Omit clause 'u.status=ACTIVE', since project owner may be DEP but his packet is active
+			cursor.execute("SELECT p.packetID, p.packetName, p.ownerID, u.lastName FROM ProjectMembers_tbl m, Packets_tbl p, Users_tbl u WHERE m.memberID=" + `memberID` + " AND m.role=" + `role` + " AND m.packetID=p.packetID AND p.ownerID=u.userID AND m.status='ACTIVE' AND p.status='ACTIVE'")
+			
+		results = cursor.fetchall()
+
+		for result in results:
+		
+			packetID = int(result[0])
+			packetName = result[1]
+			ownerID = int(result[2])
+			ownerLastName = result[3]
+			
+			tmpOwner = User(ownerID, "", "", ownerLastName, "", None, "", "", "", [], [])
+			
+			project = Packet(packetID, packetName, "", tmpOwner)
+			projects.append(project)
+
+		return projects
+
+	
+	# Assign a list of project IDs to a member
+	# projects: linear list of INTEGER IDs
+	# role: one of 'Reader' or 'Writer'
+	def insertMemberProjects(self, memberID, projects, role):
+	
+		db = self.db
+		cursor = self.cursor
+	
+		for pID in projects:
+			if not self.existsProjectMember(pID, memberID, role):
+				self.addProjectMember(pID, memberID, role)
+			
+	
+	# Make an entry in ProjectMembers_tbl for projectID and each element in projectReaders, indicating 'Reader' for 'category'
+	def insertPacketReaders(self, projectID, projectReaders):
+	
+		db = self.db
+		cursor = self.cursor
+				
+		for reader in projectReaders:
+			if not self.existsProjectMember(projectID, reader.getUserID(), 'Reader'):
+				cursor.execute("INSERT INTO ProjectMembers_tbl(packetID, memberID, role) VALUES(" + `projectID` + ", " + `reader.getUserID()` + ", 'Reader')")
+
+
+	# Make an entry in ProjectMembers_tbl for projectID and each element in projectWriters, storing 'category' = 'Writer'
+	def insertPacketWriters(self, projectID, projectWriters):
+	
+		db = self.db
+		cursor = self.cursor
+				
+		for writer in projectWriters:
+			if not self.existsProjectMember(projectID, writer.getUserID(), 'Writer'):
+				cursor.execute("INSERT INTO ProjectMembers_tbl(packetID, memberID, role) VALUES(" + `projectID` + ", " + `writer.getUserID()` + ", 'Writer')")
+
+
+	# Delete (DEP) old members and insert new values
+	# members: a list of INT user IDs
+	def updateProjectMembers(self, projectID, members, role):
+
+		db = self.db
+		cursor = self.cursor
+
+		# Simply delete (DEP) old members and insert new values
+		self.deleteProjectMembers(projectID, role)
+		
+		for member in members:
+			self.addProjectMember(projectID, member, role)
+			
+	
+	# Update the list of projects for a particular user
+	# DEP old project values and insert new ones according to 'role'
+	# newProjects: list of INTEGER project IDs
+	def updateUserProjects(self, userID, newProjects, role):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		self.deleteMemberProjects(userID, role)
+		self.insertMemberProjects(userID, newProjects, role)
+	
+			
+	# Add a member to a project
+	# member: an INT user ID
+	def addProjectMember(self, projectID, member, role):
+	
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("INSERT INTO ProjectMembers_tbl(packetID, memberID, role) VALUES(" + `projectID` + ", " + `member` + ", " + `role` + ")")
+	
+
+	# Delete a project member
+	# 'role' parameter required, since a member may have more than one role in a project
+	def deleteMember(self, pID, memberID, role):
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("UPDATE ProjectMembers_tbl SET status='DEP' WHERE packetID=" + `pID` + " AND memberID=" + `memberID` + " AND role=" + `role` + " AND status='ACTIVE'")
+
+
+	# Delete all members in a specific role (reader/writer)
+	def deleteProjectMembers(self, pID, role):
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE ProjectMembers_tbl SET status='DEP' WHERE packetID=" + `pID` + " AND role=" + `role` + " AND status='ACTIVE'")
+
+
+	# Delete all projects that a member has 'role' access to (e.g. delete all readonly projects for user A)
+	# Useful when modifying member details
+	def deleteMemberProjects(self, memberID, role):
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("UPDATE ProjectMembers_tbl SET status='DEP' WHERE memberID=" + `memberID` + " AND status='ACTIVE' AND role=" + `role`)
+
+
+	# Delete ALL members of the given project
+	def deleteAllProjectMembers(self, pID):
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("UPDATE ProjectMembers_tbl SET status='DEP' WHERE packetID=" + `pID` + " AND status='ACTIVE'")
+
+
+	# This is useful when removing a user from the system - revoke his access to all projects
+	def deleteMemberFromllProjects(self, memberID):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("UPDATE ProjectMembers_tbl SET status='DEP' WHERE memberID=" + `memberID` + " AND status='ACTIVE'")
+		
+
+	# Updated June 20/07: check if current member has already been assigned to this project **in this role**
+	# Can one member have two distinct access types to a project (e.g. be BOTH reader and writer??)  
+	# Might occur by mistake; no big deal if the member was supposed to be a writer and gets assigned reader access; readers, however, should not be assigned writer access, unless their access is explicitly changed and they get promoted from reader to writer.  
+	# This check should be performed by the validation function DURING PROJECT MODIFICATION
+	def existsProjectMember(self, projectID, memberID, role):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT * FROM ProjectMembers_tbl WHERE packetID=" + `projectID` + " AND memberID=" + `memberID` + " AND role=" + `role` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+	
+		if results:
+			return True
+		else:
+			return False
+
+
+	# Go over the list of writers and return names of those who have previously been given read-only access to the project
+	def validateWriters(self, projectID, writersList):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		readers = []	# list of users in writersList who already have read access to this project
+		
+		for writer in writersList:
+			if self.existsProjectMember(projectID, writer, 'reader'):
+				readers.append(writer)
+		return readers
+		
+	
+	# Select all projects in the database
+	# Return a list of Project objects
+	# Modified August 12/07: add parameter isPrivate; allows selection of all projects with a specific access level (public or private)
+	def findAllProjects(self, isPrivate=""):
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+
+		db = self.db
+		cursor = self.cursor
+		
+		uHandler = UserHandler(db, cursor)
+		
+		projects = []
+		
+		if isPrivate == "":
+			cursor.execute("SELECT packetID, ownerID, packetName, packetDescription FROM Packets_tbl WHERE status='ACTIVE'")
+			results = cursor.fetchall()
+			
+			for result in results:
+				packetID = int(result[0])
+				ownerID = int(result[1])
+				packetName = result[2]
+				packetDescr = result[2]
+				
+				packetOwner = uHandler.getUserByID(ownerID)
+				newPacket = Packet(packetID, packetName, packetDescr, packetOwner)
+				
+				projects.append(newPacket)
+		else:
+			cursor.execute("SELECT packetID, ownerID, packetName, packetDescription FROM Packets_tbl WHERE is_private=" + `isPrivate` + " AND status='ACTIVE'")
+			results = cursor.fetchall()
+			
+			for result in results:
+				packetID = int(result[0])
+				ownerID = int(result[1])
+				packetName = result[2]
+				packetDescr = result[2]
+				
+				packetOwner = uHandler.getUserByID(ownerID)
+				newPacket = Packet(packetID, packetName, packetDescr, packetOwner)
+				
+				projects.append(newPacket)
+
+		return projects
+
+	# Match a keyword in project name
+	def matchProjectKeyword(self, keywd, multiple=False):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		packets = {}
+		
+		if not multiple:
+			# one-keyword search
+			cursor.execute("SELECT packetID, lastname, packetName FROM Packets_tbl p, Users_tbl u WHERE p.ownerID=u.userID AND p.status='ACTIVE' AND packetName LIKE '%" + keywd.strip() + "%'")
+			
+			results = cursor.fetchall()
+			
+			for result in results:
+				packetID = int(result[0])
+				owner = result[1]
+				packetName = result[2]
+				
+				pText = `packetID` + ": " + owner + ": " + packetName
+				
+				packets[packetID] = pText
+				
+		return packets
\ No newline at end of file
diff --git a/OpenFreezer/cgi/project_output.py b/OpenFreezer/cgi/project_output.py
new file mode 100755
index 0000000..1ed3262
--- /dev/null
+++ b/OpenFreezer/cgi/project_output.py
@@ -0,0 +1,703 @@
+#!/usr/local/bin/python
+
+import os
+#import tempfile
+import stat
+import sys
+
+from database_conn import DatabaseConn
+from user_handler import UserHandler
+from lab_handler import LabHandler
+
+from user import User
+from session import Session
+from laboratory import Laboratory
+
+from general_output import GeneralOutputClass
+
+import utils
+
+class ProjectOutputClass:
+
+	def printProjectInfo(self, cmd, project):
+		
+		dbConn = DatabaseConn()
+		hostname = dbConn.getHostname()		# to define form action URL
+		
+		db = dbConn.databaseConnect()
+		cursor = db.cursor()
+		
+		uHandler = UserHandler(db, cursor)
+		lHandler = LabHandler(db, cursor)
+
+		gOut = GeneralOutputClass()
+
+		currUser = Session.getUser()
+
+		if cmd == 'view':
+
+			projectID = project.getNumber()
+			projectOwner = project.getOwner()
+			ownerName = projectOwner.getFullName()
+			ownerID = projectOwner.getUserID()
+			projectName = project.getName()
+			projectDescr = project.getDescription()
+			
+			# private or public
+			isPrivate = project.isPrivate()
+			
+			if isPrivate:
+				accessType = 'Private'
+			else:
+				accessType = 'Public'
+			
+			# Only allow modification by owner or admin AND disallow project deletion if there are reagents in it!!!
+			modify_disabled = True
+			delete_disabled = True
+			
+			if (currUser.getUserID() == ownerID) or (currUser.getCategory() == 'Admin'):
+				modify_disabled = False
+
+			if project.isEmpty():
+				delete_disabled = False
+
+			# Aug. 18/08: Changed b/c of new format
+			#content = gOut.printHeader() + gOut.printMainMenu()
+			content = gOut.printHeader()
+			
+			content += '''
+				<FORM name="project_form" method="POST" action="%s">
+			
+					<!-- pass current user as hidden form field -->
+					<INPUT type="hidden" ID="username_hidden" NAME="username"'''
+					
+			content += "value=\"" + currUser.getFullName() + "\">"
+			
+			content += '''
+					<TABLE height="100%%">
+						<TABLE width="770px" cellpadding="5px" cellspacing="5px" class="detailedView_tbl">
+							<TR>
+								<TD class="detailedView_heading" style="white-space:nowrap;">
+									PROJECT DETAILS PAGE
+								</TD>
+								
+								<TD class="detailedView_heading" style="text-align:right">
+									'''
+			content += "<INPUT TYPE=\"submit\" name=\"modify_project\" value=\"Modify Project\""
+			
+			if modify_disabled:
+				content += " disabled>"
+			else:
+				content += ">"
+							
+			content += "<INPUT TYPE=\"submit\" style=\"margin-left:2px;\" name=\"delete_project\" value=\"Delete Project\" onClick=\"return confirmDeleteProject();\""
+			
+			if modify_disabled or delete_disabled:
+				content += " disabled>"
+			else:
+				content += ">"
+				
+			content += '''
+								</TD>
+	
+							</TR>
+	
+							<TR>
+								<TD class="projectDetailedViewName">
+									Project #
+								</TD>
+	
+								<TD class="detailedView_value" width="87%%">
+									%d
+									<INPUT TYPE="hidden" name="packetID" value="%d">
+								</TD>
+	
+							</TR>
+	
+							<TR>
+								<TD class="projectDetailedViewName">
+									Project Owner:
+								</TD>
+	
+								<TD class="detailedView_value">
+									%s
+									<INPUT TYPE="hidden" name="packetOwner" value="%d">
+								</TD>
+							</TR>
+	
+							<TR>
+								<TD class="projectDetailedViewName">
+									Project Name:
+								</TD>
+	
+								<TD class="detailedView_value">
+									%s
+									<INPUT TYPE="hidden" name="packetName" value="%s">
+								</TD>
+							</TR>
+	
+							<TR>
+								<TD class="projectDetailedViewName">
+									Project Description:
+								</TD>
+	
+								<TD class="detailedView_value">
+									%s
+									<INPUT TYPE="hidden" name="packetDescription" value="%s">
+								</TD>
+							</TR>
+							
+							<TR>
+								<TD class="projectDetailedViewName">
+									Access type:
+								</TD>
+	
+								<TD class="detailedView_value">
+									%s
+									<INPUT TYPE="hidden" name="private_or_public" value="%s">
+								</TD>
+							</TR>
+							
+							<TR>
+								<TD colspan="2">
+									<HR/>
+								</TD>
+							</TR>
+							
+							'''
+						
+			# Now here, show or hide members section depending on the user's access level
+			# Condition is the same as for determining whether modification is allowed - so use 'modify_disabled' variable
+			if not modify_disabled:
+				content += '''
+							<TR>
+								<TD class="projectDetailedViewName">
+									Project Members:
+								</TD>
+								
+								<TD> </TD>
+							</TR>
+							
+							<TR>
+								<TD class="detailedView_value" colspan="2">
+									<TABLE width="100%%">
+										<TR>
+											<TD style="font-weight:bold; padding-left:10px" width="30%%">
+												Readers:
+											</TD>
+	
+											<TD style="font-weight:bold; padding-left:10px">
+												Writers:
+											</TD>
+										</TR>
+	
+										<TR>
+											<TD class="detailedView_value" style="vertical-align:top">
+												<UL>
+												'''
+			
+				if not isPrivate:
+					content += "All OpenFreezer Users"
+				else:
+					# maintain the indent
+					readers = project.getReaders()
+					
+					# sort by labs
+					labs = []
+					rdrLabs = {}
+	
+					# First, iterate over readers list to extract all the labs
+					for rdr in readers:
+						lab = rdr.getLab().getID()
+	
+						if lab not in labs:
+							labs.append(lab)
+	
+					# Now iterate over the list of labs and link its readers to it
+					for lab in labs:
+						tmpRdrs = []		# list of members in one lab
+	
+						for rdr in readers:
+							tmpLab = rdr.getLab().getID()
+	
+							if tmpLab == lab:
+								# append reader to list of members of this lab
+								if rdrLabs.has_key(lab):
+									tmpRdrs = rdrLabs[lab]
+	
+								tmpRdrs.append(rdr)
+								rdrLabs[lab] = tmpRdrs
+	
+					#for rdr in readers:
+					for lab_id in rdrLabs.keys():
+						rdrs = rdrLabs[lab_id]		# list of objects!!
+						tmp_lab_name = lHandler.findLabName(lab_id)
+	
+						# print out the lab name
+						
+						if currUser.getCategory() == 'Admin':
+							content += "<span class=\"linkShow\" style=\"color:#2E8B57\" onClick=\"goToLabViewFromProject(" + `lab_id` + ");\">" + tmp_lab_name + "</span><BR/>"
+						else:
+							content += "<span style=\"color:#2E8B57\">" + tmp_lab_name + "</span><BR/>"
+	
+						# print reader names
+						for rdr in rdrs:
+							content += "<INPUT TYPE=\"hidden\" name=\"projectReaders\" value=\"" + `rdr.getUserID()` + "\"></INPUT>"
+							
+							# Only show hyperlinks if the viewer is an Admin; otherwise just output plain names
+							if currUser.getCategory() == 'Admin':
+								content += "<LI style=\"list-style:none; padding-left:6px;\">--  <span class=\"linkShow\" onClick=\"redirectToUserFromProject(" + `rdr.getUserID()` + ");\">" + rdr.getFullName() + "</span></LI>"
+							else:
+								content += "<LI style=\"list-style:none; padding-left:6px;\">--  " + rdr.getFullName() + "</LI>"
+											
+				content += '''			
+											</UL>
+										</TD>
+
+
+										<TD class="detailedView_value" style="width:250px; vertical-align:top">
+											<UL>
+											'''
+				writers = project.getWriters()
+				
+				# sort them by lab too, same as for readers
+				labs = []
+				wrtrLabs = {}
+
+				# First, iterate over readers list to extract all the labs
+				for wrtr in writers:
+					lab = wrtr.getLab().getID()
+
+					if lab not in labs:
+						labs.append(lab)
+
+				# Now iterate over the list of labs and link its readers to it
+				for lab in labs:
+					tmpWrtrs = []		# list of members in one lab
+
+					for wrtr in writers:
+						tmpLab = wrtr.getLab().getID()
+
+						if tmpLab == lab:
+							# append reader to list of members of this lab
+							if wrtrLabs.has_key(lab):
+								tmpWrtrs = wrtrLabs[lab]
+
+							tmpWrtrs.append(wrtr)
+							wrtrLabs[lab] = tmpWrtrs
+
+
+				for lab_id in wrtrLabs.keys():
+					wrtrs = wrtrLabs[lab_id]		# list of objects!!
+					tmp_lab_name = lHandler.findLabName(lab_id)
+
+					# print out the lab name
+					if currUser.getCategory() == 'Admin':
+						content += "<span class=\"linkShow\" style=\"color:#2E8B57\" onClick=\"goToLabViewFromProject(" + `lab_id` + ");\">" + tmp_lab_name + "</span><BR/>"
+					else:
+						content += "<span style=\"color:#2E8B57\" " + `lab_id` + ");\">" + tmp_lab_name + "</span><BR/>"
+
+					for wrtr in wrtrs:
+	
+						content += "<INPUT TYPE=\"hidden\" name=\"projectWriters\" value=\"" + `wrtr.getUserID()` + "\">"
+						
+						if currUser.getCategory() == 'Admin':
+							content += "<LI style=\"list-style:none; padding-left:6px;\">--  <span class=\"linkShow\" onClick=\"redirectToUserFromProject(" + `wrtr.getUserID()` + ");\">" + wrtr.getFullName() + "</span></LI>"
+						else:
+							content += "<LI style=\"list-style:none; padding-left:6px;\">--  " + wrtr.getFullName() + "</LI>"
+							
+				content += '''
+											</UL>
+										</TD>
+									</TR>
+								</TABLE>
+							</TD>	
+						</TR>
+					</TABLE>
+				</FORM>
+				
+				<FORM id="viewUserForm" method="POST" action="%s">
+					<INPUT type="hidden" id="view_user_hidden" name="view_user">
+					<INPUT type="hidden" ID="curr_userid_hidden" NAME="curr_user_id" value="%d">
+				</FORM>
+				
+				<FORM id="viewLabForm" method="POST" action="%s">
+					<INPUT type="hidden" ID="curr_userid_hidden" NAME="curr_user_id" value="%d">
+					<INPUT type="hidden" id="view_lab_hidden" name="view_lab">
+				</FORM>
+				</TABLE>
+				'''
+				
+				content += gOut.printFooter()
+				
+			else:
+				content += '''
+					</TABLE>
+				</FORM>
+				</TABLE>
+				'''
+				
+				content += gOut.printFooter()
+
+			# and here, depending on what sections of the project view were printed, the number of arguments would vary
+			if not modify_disabled:
+				page_content = content % (hostname + "cgi/project_request_handler.py", projectID, projectID, ownerName, ownerID, projectName, projectName, projectDescr, projectDescr, accessType, accessType, hostname + "cgi/user_request_handler.py", currUser.getUserID(), hostname + "cgi/user_request_handler.py", currUser.getUserID())
+			else:
+				page_content = content % (hostname + "cgi/project_request_handler.py", projectID, projectID, ownerName, ownerID, projectName, projectName, projectDescr, projectDescr, accessType, accessType)
+
+			print "Content-type:text/html"		# THIS IS PERMANENT; DO NOT REMOVE
+			print					# DITTO
+			print page_content
+
+		elif cmd == 'edit':
+				
+			projectID = project.getNumber()
+			projectOwner = project.getOwner()
+			ownerName = projectOwner.getFullName()
+			ownerID = projectOwner.getUserID()
+			projectName = project.getName()
+			projectDescr = project.getDescription()
+			isPrivate = project.isPrivate()
+			
+			content = gOut.printHeader()
+			#content += gOut.printMainMenu()
+			
+			content += '''
+				<FORM name="project_form" method="POST" action="%s">
+
+					<!-- pass current user as hidden form field -->
+					<INPUT type="hidden" ID="username_hidden" NAME="username"'''
+			content += "value=\"" + currUser.getFullName() + "\">"
+
+			content += '''
+					<TABLE width="770px" cellpadding="5px" cellspacing="5px" style="border:1px solid black" frame="box" rules="rows">
+					<TR>
+						<TD colspan="3" style="padding-left:200px; text-align:center">
+							
+							<span style="color:#0000FF; font-weight:bold">MODIFY PROJECT </span>
+							<span style="color:#FF0000; font-weight:bold">%d</span>
+							
+							<INPUT TYPE="hidden" name="packetID" value="%d">
+							
+							<INPUT TYPE="submit" style="margin-left:200px;" name="save_project" value="Save" onClick=\"alert('Please note: If your project writers list contains names of users who have read-only access to OpenFreezer, their names will be removed from the list during saving.'); addProjectOwnerToWritersList(); selectAllElements('readers_target_list'); selectAllElements('writers_target_list'); return verifyProjectOwner('projectOwnersList') && verifyProjectName('packet_name') && verifyProjectDesc [...]
+							
+							<INPUT TYPE="submit" style="margin-left:20px;" name="cancel_project" value="Cancel">
+						</TD>
+					</TR>
+
+					<TR>
+						<TD class="projectDetailedViewName">
+							Project Owner:
+						</TD>
+
+						<TD class="detailedView_value" colspan="2">
+							<SELECT ID="projectOwnersList" name="packetOwner">
+							'''
+
+			# Get list of all potential project owners - users with 'CREATOR' or higher privileges
+			# Returns list of User **objects**
+			creators = uHandler.findAllMembersInCategory('Creator', False, '<=')
+			creatorsDict = {}	# name, uid
+			
+			for creator in creators:
+				uid = creator.getUserID()
+				name = creator.getFullName()
+				creatorsDict[name] = uid
+				
+			names = creatorsDict.keys()
+			names.sort()
+			
+			#print "Content-type:text/html"
+			#print
+			
+			for name in names:
+				#print name
+				uid = creatorsDict[name]
+				#print uid
+				#print ownerID
+
+				if uid == ownerID:
+					content += "<OPTION SELECTED value=" + `uid` + ">" + name + "</OPTION>"
+				else:
+					content += "<OPTION value=" + `uid` + ">" + name + "</OPTION>"
+							
+			content += '''
+							</SELECT>
+							
+							<DIV ID="projectOwnerWarning" STYLE="display:none; color:#FF0000; font-weight:normal;">
+								<BR>Please select a name from the list above.
+							</DIV>
+						</TD>
+					</TR>
+
+					<TR>
+						<TD class="projectDetailedViewName">
+							Project Name:
+						</TD>
+
+						<TD class="detailedView_value" colspan="2">
+							<INPUT TYPE="text" id="packet_name" name="packetName" value="%s">
+							
+							<DIV ID="projectNameWarning" STYLE="display:none; color:#FF0000; font-weight:normal;">
+								<BR>Please provide a project name.
+							</DIV>
+						</TD>
+					</TR>
+
+					<TR>
+						<TD class="projectDetailedViewName">
+							Project Description:
+						</TD>
+
+						<TD class="detailedView_value" colspan="2">
+							<INPUT TYPE="text" id="packet_descr" name="packetDescription" value="%s">
+							
+							<DIV ID="projectDescrWarning" STYLE="display:none; color:#FF0000; font-weight:normal;">
+								<BR>Please provide a project description.
+							</DIV>
+						</TD>
+					</TR>
+					
+					
+					<TR>
+						<TD class="projectDetailedViewName">
+							Access type:
+						</TD>
+
+						<TD class="detailedView_value" style="width:400px">
+						'''
+			if not isPrivate:
+				content += "<INPUT TYPE=\"RADIO\" NAME=\"private_or_public\" VALUE=\"public\" checked>Public    "
+				content += "<INPUT TYPE=\"RADIO\" NAME=\"private_or_public\" VALUE=\"private\">Private"
+			else:
+				content += "<INPUT TYPE=\"RADIO\" NAME=\"private_or_public\" VALUE=\"public\">Public    "
+				content += "<INPUT TYPE=\"RADIO\" NAME=\"private_or_public\" VALUE=\"private\" checked>Private"
+				
+			content += '''
+						</TD>
+					</TR>
+
+					<TR>
+						<TD class="projectDetailedViewName">
+							Project Members:
+						</TD>
+
+						<TD class="detailedView_value" colspan="2">
+							 
+						</TD>
+					</TR>
+					
+					<TR>
+						<TD class="detailedView_value" colspan="3">
+							Edit existing project members lists:
+						</TD>
+					</TR>
+
+					<TR>
+						<TD style="width:100px">
+							<SELECT multiple size="10" id="readers_target_list" name="readersList">
+						'''
+			# Readers and writers associated with this project
+			currReaders = project.getReaders()
+			currWriters = project.getWriters()
+	
+			# Since object comparison is done by reference, cannot check if a User object returned by findAllMembers is a member of this project by using 'in array'.  Need to compare user IDs explicitly
+			currReaderIDs = []
+			currWriterIDs = []
+
+			currReaderNames = []
+			currWriterNames = []
+
+			currReadersDict = {}	# name, id
+			currWritersDict = {}
+
+			# need lab IDs too - to match members to their labs when moved between lists, but having a 'memberID, labID' dictionary is too clumsy.  Easiest approach: have 'memberID, Member Object' dictionary
+			currReaderObjDict = {}	# id, User object
+			currWriterObjDict = {}
+
+			for r in currReaders:
+				rID = r.getUserID()
+				rName = r.getFullName()
+				
+				# associate rID with its containing object 
+				currReaderObjDict[rID] = r
+				
+				currReaderIDs.append(rID)
+				currReaderNames.append(rName)
+				currReadersDict[rName] = rID
+
+
+			for w in currWriters:
+				wID = w.getUserID()
+				wName = w.getFullName()
+				
+				currWriterObjDict[wID] = w
+
+				currWriterIDs.append(wID)
+				currWriterNames.append(wName)
+				currWritersDict[wName] = wID
+
+			currReaderNames.sort()
+			currWriterNames.sort()
+			
+			for rName in currReaderNames:
+				rID = currReadersDict[rName]
+				rdr = currReaderObjDict[rID]
+				rdrLabID = rdr.getLab().getID()
+				
+				#content += "<OPTION id=" + `rID` + " value=" + `rID` + ">" + rName + "</OPTION>"
+				
+				# June 28/07: Include labID in the option id 
+				content += "<OPTION id=\"user_" + `rID` + "_lab_" + `rdrLabID` + "\" value=" + `rID` + ">" + rName + "</OPTION>"
+
+			content += '''
+							</SELECT>
+							<BR/>
+							<INPUT TYPE="checkbox" style="margin-top:10px" onClick="selectAll(this.id, 'readers_target_list')" id="select_all_reader_chkbx"> Select All</INPUT>
+						</TD>
+
+						<TD width="30px">
+							<input onclick="addMembers('readers_target_list', 'write')" value="   Make Writer >>" type="button"></INPUT><BR/>
+							<input style="margin-top:10px;" onclick="addMembers('writers_target_list', 'read')" value="<< Make Reader" type="button"></INPUT><BR/>
+							<input style="margin-top:10px;" onclick="removeProjectMembers()" value="Remove Selected" type="button"></INPUT>
+						</TD>
+
+						<TD>
+							<SELECT multiple size="10" id="writers_target_list" name="writersList">
+						'''
+			for wName in currWriterNames:
+				wID = currWritersDict[wName]
+				wrtr = currWriterObjDict[wID]
+				wrtrLabID = wrtr.getLab().getID()
+				
+				#content += "<OPTION id=" + `wID` + " value=" + `wID` + ">" + wName + "</OPTION>"
+				
+				# June 28/07: Include labID in the option id 
+				content += "<OPTION id=\"user_" + `wID` + "_lab_" + `wrtrLabID` + "\" value=" + `wID` + ">" + wName + "</OPTION>"
+
+			content += '''
+							</SELECT>
+							
+							<BR/>
+							<INPUT style="margin-top:10px;" TYPE="checkbox" onClick="selectAll(this.id, 'writers_target_list')" id="select_all_writer_chkbx"> Select All</INPUT>
+						</TD>
+					</TR>
+					
+					<TR>
+						<TD class="detailedView_value" colspan="3">
+							Add new members to this project:
+						</TD>
+					</TR>
+					
+					<TR>
+						<TD class="detailedView_value" colspan="3">
+							Laboratory:    
+			
+							<SELECT id="labList" name="labs" onChange="showLabMembersList()">
+							'''
+			# fetch lab list - Updated August 90/7: Fetch ALL labs, with any access - then if a read-only lab has members with higher access, would show these members in list
+			#labs = lHandler.findAllLabs('Writer', '<=')
+			labs = lHandler.findAllLabs()
+			
+			# sort lab names alphabetically
+			labNames = []
+			labsDict = {}	# name, id
+			
+			for labID in labs.keys():
+				labName = labs[labID]
+				labNames.append(labName)
+				labsDict[labName] = labID
+			
+			labNames.sort()
+			
+			currLab = projectOwner.getLab()
+			currLabID = currLab.getID()
+			
+			#for labID in labs.keys():
+			for labName in labNames:
+				#labName = labs[labID]
+				labID = labsDict[labName]
+				
+				if labID == currLabID:
+					content += "<OPTION SELECTED id='" + `labID` + "' NAME='lab_optn' value=" + `labName` + ">" + labName + "</OPTION>"
+				else:
+					content += "<OPTION id='" + `labID` + "' NAME='lab_optn' value=" + `labName` + ">" + labName + "</OPTION>"
+
+			content += '''
+							</SELECT>
+						</TD>
+					</TR>
+					
+					<TR>
+						<TD width="100px">
+							'''
+							
+			# For each lab, print a list of its members
+			for labID in labs.keys():
+	
+				# First, fetch a list of users 
+				# These are **User instances** - need to get their names and IDs for comparison
+				
+				# August 9/07: Don't fetch only writers, fetch readers too - it's up to the project owner to grant them access to the project
+				#writers = uHandler.findAllMembersInCategory('Writer', True, '<=', labID)
+				writers = uHandler.findAllMembersInCategory('Reader', True, '<=', labID)
+				writersDict = {}	# name, uid
+				writersObjDict = {}	# id, User object
+				
+				# Fetch user IDs and sort their names alphabetically
+				for writer in writers:
+					name = writer.getFullName()
+					uid = writer.getUserID()
+					labID = (writer.getLab()).getID()
+					writersDict[name] = uid
+					writersObjDict[uid] = writer
+					
+				names = writersDict.keys()
+				names.sort()
+
+				# Show members for one lab at a time
+				if labID == currLabID:
+					display = "inline"
+				else:
+					display = "none"
+				
+				content += "<SELECT MULTIPLE id=\"lab_source_list_" + `labID` + "\" name=\"labSourceMembers_" + `labID` + "\" SIZE=\"10\" style=\"display:" + display + "\">"
+
+				for name in names:
+					uid = writersDict[name]
+					labID = writersObjDict[uid].getLab().getID()
+					
+					if uid not in currReaderIDs and uid not in currWriterIDs:
+						#content += "<OPTION value=" + `uid` + ">" + name + "</OPTION>"
+						content += "<OPTION id=\"user_" + `uid` + "_lab_" + `labID` + "\" value=" + `uid` + ">" + name + "</OPTION>"
+				
+				content += "</SELECT>"
+				
+			content += '''
+							<BR/>
+							<INPUT TYPE="checkbox" style="margin-top:8px" onClick="selectAll(this.id, 'lab_source_list_' + getSelectedLab())" id="add_all_chkbx"> Select All Members</INPUT>
+						</TD>
+
+						<TD colspan="2" style="vertical-align:top">
+							Add selected members to:
+							
+							<P style="font-size:9pt; margin-top:5px;">
+								<input type="radio" id="access_level_radio_read" name="access_levels" value="read" checked>Readers list</INPUT><BR/> 
+								<input type="radio" id="access_level_radio_write" name="access_levels" value="write">Writers list</INPUT><BR/>
+								<input style="margin-top:8px" onclick="addMembers('lab_source_list_' + getSelectedLab(), getSelectedRole('1'))" value="Go" type="button"></INPUT>
+								<BR/>
+							</P>
+
+						</TD>
+					</TR>
+				</TABLE>
+			</FORM>
+			'''
+				
+			content += gOut.printFooter()
+		
+			page_content = content % (hostname + "cgi/project_request_handler.py", project.getNumber(),  project.getNumber(), project.getName(), project.getDescription())		
+
+			print "Content-type:text/html"		# THIS IS PERMANENT; DO NOT REMOVE
+			print					# DITTO
+			print page_content
diff --git a/OpenFreezer/cgi/project_request_handler.py b/OpenFreezer/cgi/project_request_handler.py
new file mode 100755
index 0000000..073062a
--- /dev/null
+++ b/OpenFreezer/cgi/project_request_handler.py
@@ -0,0 +1,427 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+
+import SocketServer
+from SocketServer import BaseRequestHandler
+
+import stat
+import MySQLdb
+
+import os
+import sys
+import string
+
+# Custom modules
+import utils
+
+from database_conn import DatabaseConn
+from exception import *
+
+from packet import Packet
+from user import User
+
+from project_database_handler import ProjectDatabaseHandler
+from user_handler import UserHandler
+
+from project_output import ProjectOutputClass
+
+from session import Session
+
+#####################################################################################
+# Contains functions to handle project creation, modification and deletion requests
+# Extends abstract class BaseRequestHandler
+#
+# Written June 22, 2007, by Marina Olhovsky
+# Last modified: August 20, 2007
+#####################################################################################
+#class ProjectRequestHandler(BaseRequestHandler):
+class ProjectRequestHandler:
+	__db = None
+	__cursor = None
+	__hostname = ""
+	
+	##########################################################
+	# Constructor
+	##########################################################
+	def __init__(self):
+	
+		dbConn = DatabaseConn()
+		db = dbConn.databaseConnect()
+		cursor = db.cursor()
+		hostname = dbConn.getHostname()
+
+		self.__db = db
+		self.__cursor = cursor
+		self.__hostname = hostname
+		
+		
+	##########################################################
+	# Override parent method
+	##########################################################
+	def handle(self):
+		
+		db = self.__db
+		cursor = self.__cursor
+		
+		form = cgi.FieldStorage(keep_blank_values="True")
+		
+		uHandler = UserHandler(db, cursor)
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		if form.has_key("username"):
+			# store the user ID for use throughout the session; add to other views in addition to create in PHP
+			currUname = form.getvalue("username")
+			currUser = uHandler.getUserByDescription(currUname)
+			Session.setUser(currUser)
+				
+		elif form.has_key("curr_user_id"):
+			currUID = form.getvalue("curr_user_id")
+			currUser = uHandler.getUserByID(currUID)
+			Session.setUser(currUser)		
+		
+		if form.has_key("create_project"):
+			self.createProject(form)
+		
+		elif form.has_key("modify_project"):
+			self.modifyProject(form)
+		
+		elif form.has_key("save_project"):
+			self.saveProject(form)
+		
+		elif form.has_key("cancel_project"):
+			self.cancelModification(form)
+
+		elif form.has_key("delete_project"):
+			self.deleteProject(form)
+			
+		elif form.has_key("view_project"):
+			self.printProjectInfo(form)
+			
+		elif form.has_key("view_packet"):
+			# go to project view from User detailed view
+			self.viewPacket(form)
+			
+		# Oct. 12, 2010
+		elif form.has_key("search_project_by_keyword"):
+			self.findPacket(form)
+
+		cursor.close()
+		db.close()
+		
+	##########################################################
+	# Process Project (Packet) creation request
+	##########################################################
+	def createProject(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		# Handlers
+		pHandler = ProjectDatabaseHandler(db, cursor)
+		uHandler = UserHandler(db, cursor)
+
+		# Get form values
+		projectID = form.getvalue("packetID")
+		ownerID = form.getvalue("packetOwner")
+
+		# get owner's name
+		packetOwner = uHandler.getUserByID(ownerID)
+
+		packetName = form.getvalue("packetName")
+		packetDescription = form.getvalue("packetDescription")
+		
+		# private or public
+		if form.getvalue("private_or_public") == "public":
+			isPrivate = False
+		else:
+			isPrivate = True
+		
+		# Lists of project readers & editors
+		# These are lists of INTEGER USER IDs!!!!!
+		# A User instance needs to be created for each!!!!!!!
+		projectReaderIDs = form.getlist("readersTargetList")
+		projectWriterIDs = form.getlist("writersTargetList")
+
+		projectReaders = []
+		projectWriters = []
+
+		for rID in projectReaderIDs:
+			tmpReader = uHandler.getUserByID(rID)
+			projectReaders.append(tmpReader)
+		
+		for wID in projectWriterIDs:
+			tmpWriter = uHandler.getUserByID(wID)
+			
+			# Now check if the user is an OpenFreezer writer - otherwise cannot be made Writer on a project
+			if tmpWriter.getCategory() != 'Reader':
+				projectWriters.append(tmpWriter)
+			
+		newProject = Packet(projectID, packetName, packetDescription, packetOwner, isPrivate, projectReaders, projectWriters)
+		packetID = pHandler.insertPacket(newProject)		# new project is empty by default
+
+		self.showProjectDetails('view', newProject)
+		
+
+	####################################################################
+	# Redirect to Modify view - output project details in 'modify' mode
+	####################################################################
+	def modifyProject(self, form):
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		# Handlers
+		pHandler = ProjectDatabaseHandler(db, cursor)
+		uHandler = UserHandler(db, cursor)
+		
+		# Get project ID from form
+		projectID = form.getvalue("packetID")
+		ownerID = form.getvalue("packetOwner")
+
+		# get owner's name
+		packetOwner = uHandler.getUserByID(ownerID)
+
+		packetName = form.getvalue("packetName")
+		packetDescription = form.getvalue("packetDescription")
+	
+		# access type:
+		accessType = form.getvalue("private_or_public")
+		
+		if accessType == 'Private':
+			isPrivate = True
+		else:
+			isPrivate = False
+	
+		# Lists of project readers & editors
+		# In this view, these are list of INTEGER USER IDs
+		# A User instance needs to be created for each!!!!!!!
+		projectReaderIDs = form.getlist("projectReaders")
+		projectWriterIDs = form.getlist("projectWriters")
+
+		projectReaders = []
+		projectWriters = []
+
+		for rID in projectReaderIDs:
+			tmpReader = uHandler.getUserByID(rID)
+			projectReaders.append(tmpReader)
+		
+		for wID in projectWriterIDs:
+			tmpWriter = uHandler.getUserByID(wID)
+			projectWriters.append(tmpWriter)		
+	
+		newProject = Packet(projectID, packetName, packetDescription, packetOwner, isPrivate, projectReaders, projectWriters)
+		
+		self.showProjectDetails('edit', newProject)
+
+
+	########################################################################################################################################################
+	# Save modified project on exit from Modify view - process form input, update database and print the updated project (redirect to Project Details View)
+	########################################################################################################################################################
+	def saveProject(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		# Handlers
+		pHandler = ProjectDatabaseHandler(db, cursor)
+		uHandler = UserHandler(db, cursor)
+		
+		# Get project ID from form
+		projectID = form.getvalue("packetID")
+		ownerID = form.getvalue("packetOwner")
+
+		# get owner's name
+		packetOwner = uHandler.getUserByID(ownerID)
+
+		packetName = form.getvalue("packetName")
+		packetDescription = form.getvalue("packetDescription")
+
+		# private or public
+		if form.getvalue("private_or_public") == "public":
+			isPrivate = False
+		else:
+			isPrivate = True
+		
+		# Lists of project readers & editors
+		# Updated Sept. 3/08: Do NOT save readers for a public project
+		if isPrivate:
+			projectReaderIDs = form.getlist("readersList")
+		else:
+			projectReaderIDs = []
+			
+		# writers are always needed
+		projectWriterIDs = form.getlist("writersList")
+		
+		projectReaders = []
+		projectWriters = []
+
+		for rID in projectReaderIDs:
+			tmpReader = uHandler.getUserByID(rID)
+			projectReaders.append(tmpReader)
+
+		for wID in projectWriterIDs:
+			tmpWriter = uHandler.getUserByID(wID)
+			
+			# check categories - a Reader cannot be given Write access to a project
+			if tmpWriter.getCategory() != 'Reader':
+				projectWriters.append(tmpWriter)
+			
+			#projectWriters.append(tmpWriter)
+
+		# Update database values
+		pHandler.updatePacket(projectID, ownerID, packetName, packetDescription, isPrivate, projectReaderIDs, projectWriterIDs)
+
+		# Output new values
+		newProject = Packet(projectID, packetName, packetDescription, packetOwner, isPrivate, projectReaders, projectWriters)
+		
+		self.showProjectDetails('view', newProject)
+
+	
+	##########################################################
+	# Exit Modify view without saving
+	##########################################################
+	def cancelModification(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		
+		pHandler = ProjectDatabaseHandler(db, cursor)
+		
+		# form values
+		projectID = int(form.getvalue('packetID'))
+		newProject = pHandler.findPacket(projectID)
+		
+		self.showProjectDetails('view', newProject)
+
+
+	##########################################################
+	# Process Project deletion request
+	##########################################################
+	def deleteProject(self, form):
+
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+
+		pHandler = ProjectDatabaseHandler(db, cursor)
+
+		# Get form values
+		pID = int(form.getvalue("packetID"))
+		success = int(pHandler.deleteProject(pID))
+		utils.redirect(hostname + "Project.php?View=3&Success=" + `success` + "&pID=" + `pID`)
+
+
+	##########################################################
+	# Redirect to Packet view from User detailed view
+	##########################################################
+	def viewPacket(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+
+		pHandler = ProjectDatabaseHandler(db, cursor)
+		
+		# Get form values
+		projectID = int(form.getvalue("view_packet"))
+		
+		newProject = pHandler.findPacket(projectID)
+		self.showProjectDetails('view', newProject)
+		
+
+	##########################################################
+	# Print Project Details
+	##########################################################
+	def printProjectInfo(self, form):
+
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		projectID = int(form.getvalue('packets'))
+		pHandler = ProjectDatabaseHandler(db, cursor)
+		
+		newProject = pHandler.findPacket(projectID)
+		
+		self.showProjectDetails('view', newProject)
+
+	
+	############################################################################
+	# Print Project Details page upon exit from creation and modification views
+	# newProject: Project INSTANCE
+	############################################################################
+	def showProjectDetails(self, cmd, newProject):
+
+		pOut = ProjectOutputClass()
+		pOut.printProjectInfo(cmd, newProject)
+		
+	
+	# New Oct. 12, 2010: added project search functionality on 'add user' page
+	def findPacket(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		pHandler = ProjectDatabaseHandler(db, cursor)
+		
+		packets = []
+		pString = ""
+		
+		keyword = form.getvalue("keyword")
+		packetsList = pHandler.matchProjectKeyword(keyword)
+		
+		for pID in packetsList:
+			pText = packetsList[pID]
+			packets.append(pText)
+
+			pString = string.join(packets, ", ")
+		
+		print "Content-type:text/html"
+		print
+		print pString
+
+##########################################################
+# Central callable function
+##########################################################
+def main():
+
+	pReqHandler = ProjectRequestHandler()
+	pReqHandler.handle()
+	#pReqHandler.finish()
+main()
diff --git a/OpenFreezer/cgi/reagent.py b/OpenFreezer/cgi/reagent.py
new file mode 100755
index 0000000..ac9a147
--- /dev/null
+++ b/OpenFreezer/cgi/reagent.py
@@ -0,0 +1,681 @@
+import utils
+
+##################################################################
+# This module represents objects of type Reagent in OpenFreezer
+# Written by: Marina Olhovsky
+# Last modified: March 17, 2008
+##################################################################
+
+#############################################################
+# Reagent Class
+#############################################################
+# Top-level abstraction for this module's object hierarchy
+class Reagent:
+	
+	# Instance variables
+	__id = 0		# corresponds to groupID in Reagents_tbl
+	__dnaSeq = None
+	__properties = {}	# list of (property NAME, property value) tuples (database IDs have NOTHING to do with Reagent objects)
+	__associations = {}	# list of (association type name, associated reagent) tuples
+
+	__type = ""		# New April 12, 2009: Reagent will now serve as a template for addition of new reagent types
+	
+	__cloning_method = 0	# May 7/09
+	
+	# April 10/08: List of names of general (intro) properties, common to all reagent types
+	# Updated May 6/08: added 'reagent source' and 'restriction on use'
+	__generalProps = ["name", "status", "packet id", "verification", "verification comments", "description", "comments", "reagent source", "restrictions on use"]
+	
+	# May 14/09 - Features that are common to all
+	__sequenceFeatures = ["tag", "promoter", "selectable marker", "polya", "origin of replication", "miscellaneous", "intron", "cleavage site", "restriction site", "transcription terminator", "5' cloning site", "3' cloning site", "cdna insert"]
+	
+	# Feature descriptors - only two for now
+	__featureDescriptors = {"tag":"tag position", "promoter":"expression system"}
+	
+	__classifiers = ["species", "cloning method", "protocol", "developmental stage", "morphology"]
+	
+	__assoc_types = []
+	
+	# April 28/09
+	__checkboxProps = []
+	
+	# added Oct. 23/08 - a list of actual SequenceFeature OBJECTS
+	__allFeatures = []
+	
+	# Default constructor - initialize all variables to their default values
+	def __init__(self):
+		self.__id = 0
+		self.__dnaSeq = None
+		self.__properties = {}
+		self.__type = ""
+		self.__cloning_method = 0	# May 7/09
+
+	# Overloaded constructor: Create a reagent of the given type with the given group ID
+	def __init__(self, lims_id, rType=""):
+		self.__id = lims_id
+		self.__type = rType
+	
+	############################
+	# Assignment methods
+	############################
+	
+	# Assign a set of properties to the reagent
+	# Parameters: propDict = list of (property NAME, property value) tuples
+	def setProperties(self, propDict):
+		self.__properties = propDict
+	
+	
+	# Sets this reagent's sequence to the given value
+	# Input: seq - an OBJECT of type DNASequence 
+	def setDNASequence(self, seq):
+		self.__dnaSeq = seq
+
+
+	# Input: assocDict: contains (assoc type name, associated reagent human-readable OpenFreezer ID) tuples
+	def setAssociations(self, assocDict):
+		self.__associations = assocDict
+		
+		
+	# oct. 23/08
+	def setFeatures(self, features):
+		self.__allFeatures = features
+
+	# May 7/09
+	def setCloningMethod(self, cm):
+		self.__cloning_method = cm
+		
+	############################
+	# Access methods
+	############################
+	
+	# return properties dictionary
+	def getProperties(self):
+		return self.__properties
+		
+	# return associations dictionary
+	def getAssociations(self):
+		return self.__associations
+	
+	# get nucleotide sequence
+	def getDNASequence(self):
+		return self.__dnaSeq
+	
+	# April 10/08: Return general properties
+	def getGeneralProperties(self):
+		return self.__generalProps
+
+	@classmethod
+	def getReagentGeneralProperties(Reagent):
+		return Reagent.__generalProps
+	
+	# April 27/09
+	@classmethod
+	def getSequenceFeatures(Reagent):
+		return Reagent.__sequenceFeatures
+
+	# April 28/09
+	@classmethod
+	def getFeatureDescriptors(Reagent):
+		return Reagent.__featureDescriptors
+	
+	# April 28/09
+	def getCheckboxProps(self):
+		return self.__checkboxProps
+
+	# oct. 23/08
+	def getAllFeatures(self):
+		return self.__allFeatures
+	
+	# Aug. 11/09
+	def getType(self):
+		return self.__type
+	
+	# Aug. 11/09
+	def getAssociationTypes(self):
+		return self.__assoc_types
+
+	def getCloningMethod(self):
+		return self.__cloning_method
+	
+	def getClassifiers(self):
+		return self.__classifiers
+	
+
+#############################################################
+# Vector Class
+# Written March 30/07 by Marina
+#############################################################
+class Vector(Reagent):
+
+	#############################################################
+	# Vector-speecific attributes
+	#############################################################
+
+	# Simple properties
+	__peptideSeq = None		# ProteinSequence object
+	__restrictionSites = []
+	
+	# April 28/08: A simple string to describe the vector subtype; corresponds to 'nonrecomb', 'recomb', etc.
+	# **NOT** THE SAME AS cloning_method!!!!!
+	__subtype = ""
+	
+	#############################################################
+	# Vector-specific parent-child associations
+	# One or all of the following may be empty
+	#############################################################
+	
+	__parentVector = None		# Vector object
+	__parentInsert = None		# Insert object
+	__parentInsertVector = None	# Vector object
+	
+	###################################################################################
+	# April 21/08: Override general reagent properties with a list specific to Vector
+	###################################################################################
+	
+	# removed May 6/08 - a better way would be to inherit __generalProps common to all (name, status, project, etc.) from Reagent, and define own set of generic properties specific to Vector (e.g. vector type)	
+	#__generalProps = ["name", "status", "packet id", "verification", "verification comments", "description", "comments", "vector type", "reagent source", "restriction on use"]
+	
+	# added May 6/08
+	__vectorProps = ["vector type"]
+
+	__assocTypes = ["insert id", "vector parent id", "parent insert vector"]
+	
+	# August 23/07
+	__cloning_method = ""	# For simplicity, an INTEGER, representing the reagent type; what is meant is 'recombination', 'non-recombination', 'novel', but will set to actual database values, such as '1'->'Insert', '2'->'Basic', '3'->'Loxp', etc.
+	
+	########################################################################################################
+	# Special properties that have multiple values (represented graphically as checkboxes, hence the name)
+	# For Vectors: antibiotic resistance => Changed to 'selectable marker' Feb. 27/08
+	# June 11/08: Removed - no longer a checkbox property
+	########################################################################################################
+	#__checkboxProps = ["antibiotic resistance"]
+	#__checkboxProps = ["selectable marker"]		# removed June 11/08
+	__checkboxProps = []
+	
+	# April 16/08, updated Sept. 18/08 - added features from Karen's latest list
+	__sequenceFeatures = ["tag", "promoter", "selectable marker", "polya", "origin of replication", "miscellaneous", "intron", "cleavage site", "restriction site", "transcription terminator", "5' cloning site", "3' cloning site", "cdna insert"]
+
+	__featureDescriptors = {"tag":"tag position", "promoter":"expression system"}
+	__singleValueFeatures = ["5' cloning site", "3' cloning site", "5' linker", "3' linker"]
+	__classifiers = []
+	
+	#######################################################################################################################################
+	# A dictionary containing association names and their corresponding values (e.g. 'parent vector'-->'V1', 'sense oligo'-->'O12', etc.)
+	#######################################################################################################################################
+	__associations = {}
+
+	# will add children later; now only concerned with parents for modification
+	
+	# Overloaded constructor
+	def __init__(self, lims_id):
+	
+		self.__id = lims_id
+		
+		# Vector-specific properties, not inherited from parent
+		self.__peptideSeq = None
+		self.__restrictionSites = []
+
+		# Vector associations
+		self.__parentVector = None
+		self.__parentInsert = None
+		self.__parentInsertVector = None
+		
+		self.__associations["insert id"] = self.__parentInsert
+		self.__associations["parent vector id"] = self.__parentVector
+		self.__associations["parent insert vector"] = self.__parentInsertVector
+
+
+	###########################################################################################
+	# Assignment methods - Set the value of the appropriate attibute to the function argument 
+	###########################################################################################
+
+	# Input: pSeq: PeptideSequence object
+	def setProteinSequence(self, pSeq):
+		self.__peptideSeq = pSeq
+
+	# Input: pv: Vector instance
+	def setParentVector(self, pv):
+		self.__parentVector = pv
+		
+	# Input: piv: Vector instance
+	def setParentInsertVector(self, piv):
+		self.__parentInsertVector = piv
+
+	# Input: pi: Insert instance
+	def setInsert(self, pi):
+		self.__parentInsert = pi
+
+	# Input: pi: Insert instance
+	def setSenseOligo(self, pi):
+		self.__parentInsert = pi
+
+	def setRestrictionSites(self, sites):
+		self.__restrictionSites = sites
+
+	def setCloningMethod(self, cm):
+		self.__cloning_method = cm
+
+	# Added April 28/08
+	def setSubtype(self, subtype):
+		self.__subtype = subtype
+		
+	def setClassifiers(self, classifiers):
+		self.__classifiers = classifiers
+	
+	####################################################################################
+	# Access methods - Return the value of each attribute
+	####################################################################################
+
+	# Return the translated protein sequence
+	def getPeptideSequence(self):
+		return self.__peptideSeq
+	
+	# Return the list of constant Insert properties
+	def getCheckboxProps(self):
+		return self.__checkboxProps
+
+	def getParentVector(self):
+		return self.__parentVector
+
+	def getInsert(self):
+		return self.__parentInsert
+
+	def getParentInsertVector(self):
+		return self.__parentInsertVector
+
+	def getAssociationTypes(self):
+		return self.__assocTypes
+
+	def getRestrictionSites(self):
+		return self.__restrictionSites
+
+	def getCloningMethod(self):
+		return self.__cloning_method
+	
+	# Redefined in each reagent type class
+	def getType(self):
+		return "Vector"
+
+	# Modified June 30/08: Made class method
+	@classmethod
+	def getSequenceFeatures(Vector):
+		return Vector.__sequenceFeatures
+
+	# April 16/08
+	# Returns a dictionary of ('feature', 'descriptor') tuples
+	@classmethod
+	def getFeatureDescriptors(Vector):
+		return Vector.__featureDescriptors
+	
+	# Removed June 30/08 - temporarily, see if other modules are affected
+	#def getSingleFeatures(self):
+		#return self.__singleValueFeatures
+		
+	# Modified June 30/08: Made class method
+	@classmethod
+	def getSingleFeatures(Vector):
+		return Vector.__singleValueFeatures
+		
+	# April 21/08: Override general reagent method
+	def getGeneralProperties(self):
+		return Vector.getVectorGeneralProperties()
+	
+	# Sept. 9/09
+	def getClassifiers(self):
+		return Vector.getVectorClassifiers()
+
+	# May 5/08
+	@classmethod
+	def getVectorGeneralProperties(Vector):
+		genProps = Reagent.getReagentGeneralProperties()
+		vProps = Vector.__vectorProps
+		
+		for vp in vProps:
+			genProps.append(vp)
+			
+		return genProps
+
+	# Sept. 9/09
+	@classmethod
+	def getVectorClassifiers(Vector):
+		#return Reagent.getClassifiers()
+		return Vector.__classifiers
+
+	# April 28/08
+	def getSubtype(self):
+		return self.__subtype
+	
+#############################################################
+# Insert Class
+#############################################################
+# Represents reagents of type Insert in OpenFreezer
+# Subclass of Reagent class
+class Insert(Reagent):
+	
+	#############################################################
+	# Insert-speecific attributes
+	#############################################################
+
+	# Simple properties
+	__peptideSeq = None		# ProteinSequence object
+	
+	__insertParentVector = None
+	__senseOligo = None		# Oligo object
+	__antisenseOligo = None		# Oligo object
+	
+	
+	# Special properties that have multiple values (in earlier versions were represented graphically as checkboxes, hence the name)
+	# Currently only one for Inserts: alternate ID; its values include IMAGE, Kazusa, RIKEN, ADDGENE, HIP, etc.
+	__checkboxProps = ["alternate id"]
+	
+	# New March 6/08: Features - can have multiple values for the same feature type
+	# (placing in Insert subclass rather than Reagents since features are not shared by all reagent types - MAY BE SUBJECT TO CHANGE
+	__singleValueFeatures = ["5' cloning site", "3' cloning site", "5' linker", "3' linker"]
+	
+	__sequenceFeatures = ["tag", "promoter", "selectable marker", "polya", "origin of replication", "miscellaneous", "intron", "cleavage site", "restriction site", "transcription terminator", "5' cloning site", "3' cloning site", "cdna insert"]
+	
+	__featureDescriptors = {"tag":"tag position", "promoter":"expression system"}
+	
+	# April 10/08: Annotations
+	__annotations = ["accession number", "entrez gene id", "ensembl gene id", "official gene symbol", "alternate id"]
+	
+	# April 10/08: Classifiers
+	__classifiers = ["type of insert", "open/closed", "species", "insert cloning method"]
+	
+	# August 23/07
+	__cloning_method = ""		# An INTEGER that corresponds to ATypeID column values in AssocType_tbl
+	
+	#############################################################
+	# List of parent/child associations
+	#############################################################
+	
+	# Insert parents are reagents that served in the preparation of this Insert - an Vector, referred to as 'Insert Parent Vector ID', and two Oligos, Sense and Antisense, used as primers
+	# Preserving the word "id" in 'insert parent vector id' for consistency with the original HTML, PHP and database
+	__assocTypes = ["insert parent vector id", "sense oligo", "antisense oligo"]
+
+	# A dictionary containing association names and their corresponding values (e.g. 'parent vector'-->'V1', 'sense oligo'-->'O12', etc.)
+	__associations = {}
+
+	# will add children later; now only concerned with parents for modification
+	
+	# Overloaded constructor
+	def __init__(self, lims_id):
+		self.__id = lims_id
+		
+		# Insert-specific properties, not inherited from parent
+		self.__peptideSeq = None
+		
+		# Insert associations
+		self.__senseOligo = None
+		self.__antisenseOligo = None
+		self.__insertParentVector = None
+		
+		self.__associations["insert parent vector id"] = self.__insertParentVector
+		self.__associations["sense oligo"] = self.__senseOligo
+		self.__associations["antisense oligo"] = self.__antisenseOligo		
+
+
+	###########################################################################################
+	# Assignment methods - Set the value of the appropriate attibute to the function argument 
+	###########################################################################################
+
+	# Input: pSeq: PeptideSequence object
+	def setProteinSequence(self, pSeq):
+		self.__peptideSeq = pSeq
+
+	# Input: ipv: Vector instance
+	def setInsertParentVector(self, ipv):
+		self.__insertParentVector = ipv
+
+	# Input: sense: Oligo instance
+	def setSenseOligo(self, sense):
+		self.__senseOligo = sense
+
+	# Input: antisense: Oligo instance
+	def setAntisenseOligo(self, antisense):
+		self.__antisenseOligo = antisense
+
+	def setCloningMethod(self, cm):
+		self.__cloning_method = cm
+
+	####################################################################################
+	# Access methods - Return the value of each attribute
+	####################################################################################
+
+	# Return the translated protein sequence
+	def getPeptideSequence(self):
+		return self.__peptideSeq
+	
+	# Return the list of constant Insert properties
+	def getCheckboxProps(self):
+		return self.__checkboxProps
+
+	def getInsertParentVector(self):
+		return self.__insertParentVector
+
+	def getSenseOligo(self):
+		return self.__senseOligo
+
+	def getAntisenseOligo(self):
+		return self.__antisenseOligo
+
+	def getAssociationTypes(self):
+		return self.__assocTypes
+
+	def getCloningMethod(self):
+		return self.__cloning_method
+	
+	def getType(self):
+		return "Insert"
+	
+	# March 6/08, updated April 27/09 - making class method
+	@classmethod
+	def getSequenceFeatures(Insert):
+		return Insert.__sequenceFeatures
+	
+	# Returns a dictionary of ('feature', 'descriptor') tuples - May 14/09: Making class method
+	@classmethod
+	def getFeatureDescriptors(Insert):
+		return Insert.__featureDescriptors
+	
+	# March 18/08
+	def getSingleFeatures(self):
+		return self.__singleValueFeatures
+	
+	# April 10/08
+	def getAnnotations(self):
+		return self.__annotations
+	
+	# April 10/08
+	def getClassifiers(self):
+		return self.__classifiers
+	
+	# May 13/08
+	@classmethod
+	def getInsertGeneralProperties(Insert):
+		genProps = Reagent.getReagentGeneralProperties()
+		iProps = Insert.__annotations + Insert.__classifiers + Insert.__checkboxProps
+		
+		for ip in iProps:
+			genProps.append(ip)
+			
+		return genProps
+
+
+#############################################################
+# Oligo Class
+#############################################################
+# Represents reagents of type Oligo in OpenFreezer
+# Subclass of Reagent class
+class Oligo(Reagent):
+	
+	#############################################################	
+	# Instance variables
+	#############################################################
+	
+	__sense = False		# Boolean value indicating whether this oligo is Sense or Antisense
+	
+	# Special Oligo properties
+	__constProps = [""]
+	
+	__sequenceFeatures = []
+	__featureDescriptors = {}
+	__singleValueFeatures = []
+	__annotations = []
+	__classifiers = []
+	
+	__cloning_method = ""		# no AssocType_tbl entries for Oligos
+	
+	# Zero-argument constructor (need to rewrite for elegant inheritance)
+	def __init__(self, lims_id=0, sense=False):
+		self.__id = lims_id
+		self.__dnaSeq = None
+		self.__properties = {}	# list of (property ID, property value) tuples
+		self.__sense = sense
+		
+	def isSense(self):
+		return self.__sense
+		
+	def setSenseValue(self, sense):
+		self.__sense = sense
+
+	def setCloningMethod(self, cm):
+		self.__cloning_method = cm
+
+	# There are no checkbox properties for Oligos, but need to add function definition for consistency and have it return null
+	def getCheckboxProps(self):
+		return None
+	
+	def getType(self):
+		return "Oligo"
+	
+	@classmethod
+	def getSequenceFeatures(Oligo):
+		return Oligo.__sequenceFeatures
+	
+	# Returns a dictionary of ('feature', 'descriptor') tuples
+	def getFeatureDescriptors(self):
+		return self.__featureDescriptors
+	
+	# March 18/08
+	def getSingleFeatures(self):
+		return self.__singleValueFeatures
+	
+	# April 10/08
+	def getAnnotations(self):
+		return self.__annotations
+	
+	# April 10/08
+	def getClassifiers(self):
+		return self.__classifiers
+	
+	def getCloningMethod(self):
+		return self.__cloning_method
+	
+	# the rest is inherited from parent class
+
+
+#############################################################
+# CellLine Class
+#############################################################
+class CellLine(Reagent):
+
+	# Cell-Line specific properties
+	__stable = False;			# boolean indicating whether the cell line is parent or stable
+
+	# Cell Line associations: Parent Vector and Parent Cell Line (applies to Stable Cell Lines only)
+	__assocTypes = ["cell line parent vector id", "parent cell line id"]
+
+	# A dictionary containing association names and their corresponding values (e.g. 'parent vector'-->'V1', 'sense oligo'-->'O12', etc.)
+	__associations = {}
+	
+	__parentVector = None
+	__parentCellLine = None
+
+	# will add children later; now only concerned with parents for creation and modification
+
+	# Checkbox properties: alternate id and resistance marker
+	__checkboxProps = ["alternate id", "selectable marker"]
+
+	__cloning_method = ""		# corresponds to 5 => 'Cell Line Stable'
+	
+	# Nov. 11/08 - empty lists for now
+	#__sequenceFeatures = ["selectable marker"]	# removed Dec. 8/08
+	__sequenceFeatures = []				# added Dec. 8/08
+	__featureDescriptors = {}
+	__singleValueFeatures = []
+	__annotations = []
+	__classifiers = []
+	
+	# Overloaded constructor
+	def __init__(self, lims_id):
+		self.__id = lims_id
+	
+		# CellLine-specific properties, not inherited from parent
+		self.__peptideSeq = None
+		
+		# Associations
+		self.__parentVector = None
+		self.__parentCellLine = None
+
+		self.__associations["vector id"] = self.__parentVector
+		self.__associations["cell line id"] = self.__parentCellLine
+
+	###########################################################################################
+	# Assignment methods - Set the value of the appropriate attibute to the function argument 
+	###########################################################################################
+
+	# Input: pv: Vector instance
+	def setParentVector(self, pv):
+		self.__parentVector = pv
+
+	# Input: cellLine: CellLine instance
+	def setParentCellLine(self, cellLine):
+		self.__parentCellLine = cellLine
+
+	def setCloningMethod(self, cm):
+		self.__cloning_method = cm
+		
+	####################################################################################
+	# Access methods - Return the value of each attribute
+	####################################################################################
+	
+	# Return the list of constant Insert properties
+	def getCheckboxProps(self):
+		return self.__checkboxProps
+
+	def getParentVector(self):
+		return self.__parentVector
+
+	def getParentCellLine(self):
+		return self.__parentCellLine
+
+	def getAssociationTypes(self):
+		return self.__assocTypes
+	
+	def getCloningMethod(self):
+		return self.__cloning_method
+
+	def getType(self):
+		return "CellLine"
+	
+	@classmethod
+	def getSequenceFeatures(CellLine):
+		return CellLine.__sequenceFeatures
+	
+	# Returns a dictionary of ('feature', 'descriptor') tuples
+	def getFeatureDescriptors(self):
+		return self.__featureDescriptors
+	
+	# March 18/08
+	def getSingleFeatures(self):
+		return self.__singleValueFeatures
+	
+	# April 10/08
+	def getAnnotations(self):
+		return self.__annotations
+	
+	# April 10/08
+	def getClassifiers(self):
+		return self.__classifiers
+	
\ No newline at end of file
diff --git a/OpenFreezer/cgi/reagent_handler.py b/OpenFreezer/cgi/reagent_handler.py
new file mode 100755
index 0000000..479349e
--- /dev/null
+++ b/OpenFreezer/cgi/reagent_handler.py
@@ -0,0 +1,3385 @@
+import MySQLdb
+
+import re, string, types
+
+from string import *
+
+from general_handler import *
+from sequence_handler import *
+from comment_handler import CommentHandler
+from reagent import Reagent, Vector, Insert, Oligo, CellLine
+from mapper import ReagentPropertyMapper, ReagentAssociationMapper, ReagentTypeMapper
+from exception import *
+
+import utils
+from sequence_feature import SequenceFeature
+from sequence import *
+from location_database_handler import LocationHandler
+
+import Bio
+from Bio.Seq import Seq
+#from Bio import Enzyme
+from Bio.Restriction import *
+
+##################################################################################################################
+# This module contains classes that map Reagent objects to corresponding database entities in OpenFreezer
+# All SQL queries are performed by these classes, thereby encapsulating the database layer and separating it from the object model
+
+# Written by: Marina Olhovsky
+# Last modified: March 19, 2010
+##################################################################################################################
+
+###################################################################
+# ReagentHandler class
+# Written October 12, 2006, by Marina Olhovsky
+# Last modified: August 7, 2008
+###################################################################
+
+# Top-level abstraction for ReagentHandler hierarchy; extends GeneralHandler
+class ReagentHandler(GeneralHandler):
+	"Top-level abstraction for ReagentHandler hierarchy"
+
+	def __init__(self, db, cursor):
+		super(ReagentHandler, self).__init__(db, cursor)
+
+	# Create a Reagent object matching an internal db reagent ID (rID parameter)
+	def createReagent(self, rID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		rTypeID = self.findReagentTypeID(rID)	# fetch the type of this reagent
+		rGroup = self.findReagentGroup(rID)	# fetch the reagent's group ID
+		
+		rMapper = ReagentTypeMapper(db, cursor)
+		rType_ID_Name_Map = rMapper.mapTypeIDName()
+
+		# Create an appropriate type of reagent based on type ID
+		if rTypeID == 1:
+			reagent = Vector(rGroup)
+		elif rTypeID == 2:
+			reagent = Insert(rGroup)
+		elif rTypeID == 3:
+			reagent = Oligo(rGroup)
+		elif rTypeID == 4:
+			reagent = CellLine(rGroup)
+		else:
+			# Updated April 27/09: Adding ability to create new reagent types
+			#return		# removed April 27/09
+			reagent = Reagent(rGroup, rType_ID_Name_Map[rTypeID])
+		
+		# fetch the properties of this reagent and assign them to the newly created instance
+		propDict = self.findAllReagentPropertiesByName(rID)
+		reagent.setProperties(propDict)
+		
+		# same for associations
+		assocDict = self.findAllReagentAssociationsByName(rID)
+		reagent.setAssociations(assocDict)
+		
+		# oct. 23/08: - UPDATED FEB. 2/09, REVERT IF NOT WORKING
+		#seqFeatureNames = reagent.getSequenceFeatures()
+		#features = self.findAllReagentFeatures(reagent, rID, seqFeatureNames)
+		features = self.findAllReagentFeatures(reagent, rID)
+		
+		reagent.setFeatures(features)
+		#print `features`
+		
+		return reagent
+		
+	# Update Feb. 2/09 - why need seqFeatureNames parameter if passing 'reagent' and can get its features through it?
+	#def findAllReagentFeatures(self, reagent, rID, seqFeatureNames):
+	def findAllReagentFeatures(self, reagent, rID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		#seqFeatureNames = reagent.getSequenceFeatures()	# added Feb. 2/09 - Removed Sept. 10/09, see fix below
+
+		mapper = ReagentPropertyMapper(db, cursor)
+		pHandler = ReagentPropertyHandler(db, cursor)
+		rtPropHandler = ReagentTypePropertyHandler(db, cursor)
+		
+		prop_Name_ID_Map = mapper.mapPropNameID()	# (prop name, prop id)
+		prop_ID_Name_Map = mapper.mapPropIDName()	# (prop id, prop name)
+		
+		prop_Category_Name_ID_Map = mapper.mapPropCategoryNameID()
+		
+		# Update Sept. 10/09: No longer can rely on preset list - must retrieve database values according to reagent type
+		rTypeID = self.findReagentTypeID(rID)
+		
+		seqFeatureNames = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, prop_Category_Name_ID_Map["DNA Sequence Features"])
+		
+		desciptorMap = reagent.getFeatureDescriptors()
+		
+		sf_list = ""
+		
+		features = []		# resulting list
+		
+		if len(seqFeatureNames) == 0:
+			return features
+		
+		for sf in seqFeatureNames:
+			# update July 2/09
+			sfID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[sf], prop_Category_Name_ID_Map["DNA Sequence Features"])
+			#sfID = prop_Name_ID_Map[sf]
+			
+			if len(sf_list) == 0:
+				sf_list += `sfID`
+			else:
+				sf_list += ", " + `sfID`
+		
+		# Update March 8, 2010: changed selection to "...AND p.propertyID IN (" + sf_list + ") ...", NOT t.propertyID!!!!!!
+		cursor.execute("SELECT t.propertyID, propertyValue, startPos, endPos, direction, descriptor FROM ReagentPropList_tbl p, ReagentPropertyCategories_tbl c, ReagentPropType_tbl t WHERE reagentID= " + `rID` + " AND p.propertyID=propCatID AND t.propertyID=c.propID AND p.propertyID IN (" + sf_list + ") AND p.status='ACTIVE' AND t.status='ACTIVE' AND c.status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		for result in results:
+			fID = int(result[0])
+			fName = prop_ID_Name_Map[fID]
+			fVal = result[1]
+			fStart = int(result[2])
+			fEnd = int(result[3])
+			fDir = result[4]
+			
+			if desciptorMap.has_key(fName):
+				fDescrType = desciptorMap[fName]
+			else:
+				fDescrType = ""
+				
+			fDescr = result[5]
+			
+			f = SequenceFeature(fName, fVal, fStart, fEnd, fDir, fDescrType, fDescr)
+			features.append(f)
+			
+		return features
+	
+	
+	# Added March 30/07: Create a new database Reagent entry of the given type
+	# Input: rType: STRING, verbal reagent type name, e.g. Vector, Oligo, etc.
+	# Output: database ID of new reagent entry
+	def createNewReagent(self, rType):
+	
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		tHandler = ReagentTypeHandler(db, cursor)
+		
+		'''
+		MGC_START = 50000	# constant, lowest group ID assigned to MGC clones
+		
+		tHandler = ReagentTypeHandler(db, cursor)
+		tMapper = ReagentTypeMapper(db, cursor)
+		typeMap = tMapper.mapTypeNameID()
+		'''
+		
+		newGroupID = -1
+		newReagentID = -1
+		
+		# find the type ID of rType
+		rTypeID = tHandler.findReagentTypeID(rType)
+		
+		# Sept. 4/07: At the moment MGC clones are parsed into the system from an external source; therefore, assume non-MGC group ID is required
+		newGroupID = self.findNextGroupID(rTypeID, False)
+		
+		cursor.execute("INSERT INTO Reagents_tbl(reagentTypeID, groupID) VALUES(" + `rTypeID` + ", " + `newGroupID` + ")")
+		newReagentID = int(db.insert_id())
+		
+		return newReagentID
+		
+		
+	# Find the next highest group ID for the given reagent type
+	# If isMGC == True, this reagent is an MGC clone; its group ID is >= 50,000
+	
+	# November 19, 2009: IMPORTANT: Now, that we allow reagent deletion, if a reagent, e.g. V1, has been deleted and its status set to DEP, CANNOT select '1' again as the next ACTIVE group ID, because, essentially, V1 may not be re-used.
+	def findNextGroupID(self, rTypeID, isMGC=False):
+		
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		tHandler = ReagentTypeHandler(db, cursor)
+		tMapper = ReagentTypeMapper(db, cursor)
+		typeMap = tMapper.mapTypeNameID()
+		
+		# Remember group IDs > 50000 for MGC clones - if the new reagent is a Vector or an Insert, find the highest current group ID LESS THAN 50,000 - cutoff for MGC clones.
+		MGC_START = 50000	# constant, lowest group ID assigned to MGC clones
+		
+		# Jan. 27, 2011: Opensourcing, sending empty database - MAX(groupID) will return null and cause an error
+		cursor.execute("SELECT COUNT(reagentID) FROM Reagents_tbl WHERE reagentTypeID=" + `rTypeID`)
+		result = cursor.fetchone()
+
+		if int(result[0]) == 0:
+			return 1
+
+		newGroupID = -1
+		
+		if rTypeID == typeMap["Vector"] or rTypeID == typeMap["Insert"]:
+			
+			# select highest non-MGC group ID - Update Nov. 20/09: DO NOT REUSE IDs, i.e. DON'T CHECK STATUS='ACTIVE'
+			#cursor.execute("SELECT MAX(groupID) FROM Reagents_tbl WHERE reagentTypeID=" + `rTypeID` + " AND groupID < " + `MGC_START` + " AND status='ACTIVE'")
+			
+			cursor.execute("SELECT MAX(groupID) FROM Reagents_tbl WHERE reagentTypeID=" + `rTypeID` + " AND groupID < " + `MGC_START`)
+			result = cursor.fetchone()
+			
+			if result:
+				newGroupID = int(result[0]) + 1		# next available group ID
+			else:
+				# This is the case where non-MGC group IDs have reached 50,000.  In this case, just assign the next highest group ID, without regard to MGC
+				
+				#cursor.execute("SELECT MAX(groupID) FROM Reagents_tbl WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+				# Update Nov. 20/09: DO NOT REUSE IDs, i.e. DON'T CHECK STATUS='ACTIVE'
+				cursor.execute("SELECT MAX(groupID) FROM Reagents_tbl WHERE reagentTypeID=" + `rTypeID`)
+				result = cursor.fetchone()	
+				newGroupID = int(result[0]) + 1
+		
+		#else:	# removed April 27/09
+		
+		elif rTypeID == typeMap["Oligo"] or rTypeID == typeMap["CellLine"]:		# replaced April 27/09
+			# For Oligos and Cell Lines, there's no MGC restriction - just select the highest group ID
+			# But Dec. 7/09 - same restriction as above - don't reuse!
+			#cursor.execute("SELECT MAX(groupID) FROM Reagents_tbl WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+			cursor.execute("SELECT MAX(groupID) FROM Reagents_tbl WHERE reagentTypeID=" + `rTypeID`)
+			result = cursor.fetchone()	
+			newGroupID = int(result[0]) + 1
+		
+		# April 27/09: New reagent types - keep separate from VICO for now
+		else:
+			# Dec. 7/09 - same restriction - don't reuse IDs!
+			#cursor.execute("SELECT MAX(groupID) FROM Reagents_tbl WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+			cursor.execute("SELECT MAX(groupID) FROM Reagents_tbl WHERE reagentTypeID=" + `rTypeID`)
+			result = cursor.fetchone()
+			
+			if result and result[0]:
+				newGroupID = int(result[0]) + 1
+				
+			else:
+				# happens when user has just created a new reagent type and wants to add the first reagent of its kind
+				newGroupID = 1
+
+		#print "Content-type:text/html"
+		#print
+		#print `newGroupID`
+		
+		return newGroupID
+
+	
+	# Retrieve reagent type **ID** from the database
+	# Return: INTEGER
+	def findReagentTypeID(self, rID):
+	
+		db = self.db
+		cursor = self.cursor	# for easy access
+		rTypeID = 0
+		
+		cursor.execute("SELECT reagentTypeID FROM Reagents_tbl WHERE reagentID=" + `rID` + " AND status='ACTIVE'")
+		reagentResult = cursor.fetchone()		# better not be > 1!
+		
+		if reagentResult:
+			rTypeID = int(reagentResult[0])
+		
+		return rTypeID
+		
+		
+	# Feb. 11, 2010
+	def findReagentPrefix(self, rID):
+		db = self.db
+		cursor = self.cursor	# for easy access
+		
+		rTypeID = self.findReagentTypeID(rID)
+		
+		cursor.execute("SELECT reagent_prefix FROM ReagentType_tbl WHERE reagentTypeID=" + `rTypeID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		prefix = ""
+		
+		if result:
+			prefix = result[0].strip()
+			
+		return prefix
+		
+		
+	# Retrieve reagent group ID from the database
+	def findReagentGroup(self, rID):
+	
+		db = self.db
+		cursor = self.cursor	# for easy access
+		rGroup = 0
+		
+		cursor.execute("SELECT groupID FROM Reagents_tbl WHERE reagentID=" + `rID` + " AND status='ACTIVE'")
+		reagentResult = cursor.fetchone()		# better not be > 1!
+		
+		if reagentResult:
+			rGroup = int(reagentResult[0])
+
+		return rGroup
+	
+	
+	# Transform internal database ID 'rID' into human-readable form (V123)
+	# Return: String
+	def convertDatabaseToReagentID(self, rID):
+		
+		db = self.db
+		cursor = self.cursor
+				
+		reagentID = ""
+		
+		cursor.execute("SELECT t.reagent_prefix, r.groupID FROM Reagents_tbl r, ReagentType_tbl t WHERE r.reagentID=" + `rID` + " AND r.reagentTypeID=t.reagentTypeID AND r.status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			prefix = result[0]
+			groupID = int(result[1])
+			reagentID = prefix.upper() + `groupID`
+		
+		return reagentID
+
+	
+	# Equal and opposite: Find the internal database ID of alphanumeric 'lims_id' (e.g. V1 --> return '1')
+	# Return: INT, internal database ID of lims_id
+	def convertReagentToDatabaseID(self, lims_id):
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO	
+		#print lims_id
+		
+		db = self.db
+		cursor = self.cursor
+		
+		rID = -1
+		
+		## Get all prefixes from db
+		#prefixes = []
+		
+		#cursor.execute("SELECT reagent_prefix FROM ReagentType_tbl WHERE status='ACTIVE'")
+		#results = cursor.fetchall()
+		
+		#for result in results:
+			#prefixes.append(result[0])
+		
+		# lims_id consists of a letter corresponding to one of 4 available reagent prefixes, followed by a numeric indexing portion
+		# May 15/08: However, the LIMS ID could just be the empty string - in which case, return -1
+		if len(lims_id) == 0:
+			return -1
+		
+		try:
+			assert len(lims_id) > 1		# must contain AT LEAST ONE alpha character followed by digit
+			
+			# Aug. 11/09: THE MOMENT OF TRUTH: NOW WITH FLEXIBLE PREFIXES NO LONGER LIMITED TO A SINGLE CHARACTER!!!!!
+			#prefix = lims_id[0].upper()		# removed Aug. 12/09
+			
+			# Changed Aug. 12/09: Split LIMS ID into alpha and numeric portions
+			m = re.match('[a-zA-Z]+', lims_id)
+			
+			if m:
+				prefix = m.group()
+			else:
+				raise ReagentDoesNotExistException("This reagent ID does not exist in the database")
+			
+			#print "PREFIX " + `prefix`
+			#print "group should be " + lims_id[len(prefix):]
+			
+			try:
+				#assert prefix in prefixes
+				
+				try:
+					groupID = int(lims_id[len(prefix):])
+					#print groupID
+					assert groupID > 0
+					
+					#print "SELECT r.reagentID FROM Reagents_tbl r, ReagentType_tbl t WHERE t.reagent_prefix=" + `prefix` + " AND r.groupID=" + `groupID` + " AND r.reagentTypeID=t.reagentTypeID AND r.status='ACTIVE'"
+					
+					cursor.execute("SELECT r.reagentID FROM Reagents_tbl r, ReagentType_tbl t WHERE t.reagent_prefix=" + `prefix` + " AND r.groupID=" + `groupID` + " AND r.reagentTypeID=t.reagentTypeID AND r.status='ACTIVE'")
+					result = cursor.fetchone()
+					
+					if result:
+						rID = int(result[0])
+					else:
+						raise ReagentDoesNotExistException("This reagent ID does not exist in the database")
+				
+				except ValueError:
+					raise ReagentDoesNotExistException("This reagent ID does not exist in the database")
+					
+				except AssertionError:
+					raise ReagentDoesNotExistException("This reagent ID does not exist in the database")
+					
+				# added April 30/08 - In EXTREME cases, if user provides an unreasonable ID with enormously long group index that is too large to cast to INT, the query would break with OperationalError - Unknown column '111111111111111111...L'
+				except MySQLdb.OperationalError:
+					raise ReagentDoesNotExistException("This reagent ID does not exist in the database")
+				
+			except AssertionError:
+				raise ReagentDoesNotExistException("This reagent ID does not exist in the database")
+
+		except AssertionError:
+			raise ReagentDoesNotExistException("This reagent ID does not exist in the database")
+			
+		return rID
+
+
+	# Return the value of a simple reagent property - i.e. not sequence, comments or packet (and not checkbox properties either)
+	def findSimplePropertyValue(self, rID, propID):
+		
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		cursor.execute("SELECT `propertyValue` FROM `ReagentPropList_tbl` WHERE `reagentID`=" + `rID` + " AND `propertyID`=" + `propID` + " AND `status`='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return result[0]
+			
+		return None
+	
+
+	# Here, return the numerical index to a different table
+	# Used to retrieve sequence, comments, packet
+	def findIndexPropertyValue(self, rID, propID):
+	
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		cursor.execute("SELECT `propertyValue` FROM `ReagentPropList_tbl` WHERE `propertyID`=" + `propID` + " AND `reagentID`=" + `rID` + " AND `status`='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			try:
+				return int(result[0])
+			except ValueError:
+				return -1
+			
+		return -1
+	
+	
+	# March 13/08 - For properties with multiple values (such as features), check if a particular value exists
+	# Updated April 23/08 - include positions in query, account for features with multiple values
+	def existsPropertyValue(self, rID, propID, propVal, pStart=0, pEnd=0, tmpDescr="", tmpDir='forward'):
+		
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+
+		#print "Content-type:text/html"
+		#print
+		#print "SELECT `propListID` FROM `ReagentPropList_tbl` WHERE `reagentID`=" + `rID` + " AND `propertyID`=" + `propID` + " AND propertyValue=" + `propVal` + " AND startPos=" + `pStart` + " AND endPos=" + `pEnd` + " AND `status`='ACTIVE'"
+
+		# Update June 3, 2010: This function CAN and should be used to check for features too, BUT where positions are not known and defaulted to 0, don't tell the query to look for start and end positions 0!!!!
+		if pStart != 0 and pEnd != 0:	# june 3, 2010
+			cursor.execute("SELECT `propListID` FROM `ReagentPropList_tbl` WHERE `reagentID`=" + `rID` + " AND `propertyID`=" + `propID` + " AND propertyValue=" + `propVal` + " AND startPos=" + `pStart` + " AND endPos=" + `pEnd` + " AND descriptor=" + `tmpDescr` + " AND direction=" + `tmpDir` + " AND `status`='ACTIVE'")
+		else:
+			# assume positions are not known so don't check for them at all (June 3, 2010)
+			# also, just checked and ccdB is stored in REVERSE orientation for many parents.  So don't include description or direction in this query at all - just the property name (an example is when checking for the presence of ccdB in Gateway parent destination vectors - it is a feature but all we know is its type and name - selectable marker ccdB, no positions or direction)
+			cursor.execute("SELECT `propListID` FROM `ReagentPropList_tbl` WHERE `reagentID`=" + `rID` + " AND `propertyID`=" + `propID` + " AND propertyValue=" + `propVal` + " AND `status`='ACTIVE'")
+
+		result = cursor.fetchall()	# retrieve all values
+
+		if result:
+			return 1
+		else:
+			return 0
+		
+		
+	# Fetch a list of all property values of a specific reagent in the form of (property **NAME**, property value) tuples (e.g. ('type of insert', 'ORF'), etc.)
+	# Modified July 2/09: propertyID column in ReagentPropList_tbl no longer corresponds to propertyID column in ReagentPropType_tbl but to propCatID column in ReagentPropertyCategories_tbl, i.e. property in conjunction with its category (because now, with a module to add new reagent types, property names may be shared between categories)
+	def findAllReagentPropertiesByName(self, rID):
+	
+		cursor = self.cursor	# for easy access
+		propDict = {}
+		
+		cursor.execute("SELECT t.propertyName, p.propertyValue FROM ReagentPropList_tbl p, ReagentPropertyCategories_tbl c, ReagentPropType_tbl t WHERE p.reagentID=" + `rID` + " AND c.propCatID = p.propertyID AND c.propID=t.propertyID AND p.status='ACTIVE' AND c.status='ACTIVE' AND t.status='ACTIVE'")
+		reagentPropResultSet = cursor.fetchall()
+			
+		if reagentPropResultSet:
+			for result in reagentPropResultSet:
+				propName = result[0]
+				propVal = result[1]
+				propDict[propName] = propVal
+				
+		return propDict
+		
+		
+	# Fetch a list of properties of a specific reagent in the form of (property **ID**, property value) tuples (e.g. ('48', 'ORF'), etc.)
+	def findAllReagentPropertiesByID(self, rID):
+	
+		db = self.db			# for easy access
+		cursor = self.cursor	# for easy access
+		propDict = {}
+		
+		cursor.execute("SELECT propertyID, propertyValue FROM ReagentPropList_tbl WHERE reagentID=" + `rID` + " AND status='ACTIVE'")
+		reagentPropResultSet = cursor.fetchall()
+			
+		if reagentPropResultSet:
+			for result in reagentPropResultSet:
+				propID = int(result[0])
+				propVal = result[1]
+				propDict[propID] = propVal
+				
+		return propDict
+
+
+	# May 17, 2010
+	def findAllReagentPropertyIDsByCategory(self, rID, categoryID):
+	
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		propDict = {}
+		
+		#print "Content-type:text/html"		# REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		
+		propHandler = ReagentPropertyHandler(db, cursor)
+		mapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Name_ID_Map = mapper.mapPropNameID()	# (prop name, prop id)
+		prop_Category_Name_ID_Map = mapper.mapPropCategoryNameID()
+	
+		cursor.execute("SELECT p.propertyID, p.propertyValue FROM ReagentPropList_tbl p, ReagentPropertyCategories_tbl  c WHERE p.reagentID=" + `rID` + " AND p.status='ACTIVE' AND p.propertyID=c.propCatID AND c.categoryID=" + `categoryID` + " AND c.status='ACTIVE'")
+
+		#print "SELECT p.propertyID, p.propertyValue FROM ReagentPropList_tbl p, ReagentPropertyCategories_tbl  c WHERE p.reagentID=" + `rID` + " AND p.status='ACTIVE' AND p.propertyID=c.propCatID AND c.categoryID=" + `categoryID` + " AND c.status='ACTIVE'"
+		
+		reagentPropResultSet = cursor.fetchall()
+
+		if reagentPropResultSet:
+			for result in reagentPropResultSet:
+				propID = int(result[0])
+				propVal = result[1]
+				propDict[propID] = propVal
+		
+		#print `propDict`
+		return propDict
+	
+	
+	# Retrieve the DNA sequence of a given reagent:
+	def findDNASequenceKey(self, rID):
+	
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		propHandler = ReagentPropertyHandler(db, cursor)
+		mapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Name_ID_Map = mapper.mapPropNameID()	# (prop name, prop id)
+		prop_Category_Name_ID_Map = mapper.mapPropCategoryNameID()
+		
+		#seqPropID = propHandler.findPropID("sequence")
+		seqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+		seqID = self.findIndexPropertyValue(rID, seqPropID)
+		
+		return seqID
+	
+	
+	def findRNASequenceKey(self, rID):
+	
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		propHandler = ReagentPropertyHandler(db, cursor)
+		mapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Name_ID_Map = mapper.mapPropNameID()	# (prop name, prop id)
+		prop_Category_Name_ID_Map = mapper.mapPropCategoryNameID()
+		
+		#seqPropID = propHandler.findPropID("sequence")
+		seqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["rna sequence"], prop_Category_Name_ID_Map["RNA Sequence"])
+		seqID = self.findIndexPropertyValue(rID, seqPropID)
+		
+		return seqID
+
+	# Retrieve the PROTEIN sequence of a given reagent:
+	# Oct. 27/09: Differentiate between protein translation of a DNA sequence and an actual protein sequence of a reagent
+	def findProteinSequenceKey(self, rID, isProtein=False):
+
+		#print "Content-type:text/html"		# REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		propHandler = ReagentPropertyHandler(db, cursor)
+		mapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Name_ID_Map = mapper.mapPropNameID()	# (prop name, prop id)
+		prop_Category_Name_ID_Map = mapper.mapPropCategoryNameID()
+		
+		# Update July 2/09
+		#seqPropID = propHandler.findPropID("protein sequence")
+		
+		# Oct. 27/09
+		if not isProtein:
+			seqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein translation"], prop_Category_Name_ID_Map["DNA Sequence"])
+		else:
+			seqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein sequence"], prop_Category_Name_ID_Map["Protein Sequence"])
+		
+		#print seqID
+		seqID = self.findIndexPropertyValue(rID, seqPropID)
+		
+		return seqID
+
+	
+	# Written March 30/07 by Marina
+	# Assign properties to a new reagent at creation
+	# Parameters: propDict = (propID, propValue)
+	# July 2/09: "propID" in dictionary keys now refers to a property in conjunction with its category - PropertyCategories_tbl->propCatID column value
+	def addReagentProperties(self, rID, propDict):
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print						# DITTO
+		#print `propDict`
+
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		# Various handlers used in implementation
+		dnaHandler = DNAHandler(db, cursor)
+		commHandler = CommentHandler(db, cursor)
+		protHandler = ProteinHandler(db, cursor)
+		iHandler = InsertHandler(db, cursor)		# feb. 26/08
+		pHandler = ReagentPropertyHandler(db, cursor)
+		rnaHandler = RNAHandler(db, cursor)	# Oct. 22/09
+
+		# Rather than look up the ID of each individual property, prepare a map of (prop name, prop id) up front -- improves performance (March 14/07)
+		mapper = ReagentPropertyMapper(db, cursor)
+		
+		prop_Name_ID_Map = mapper.mapPropNameID()	# (prop name, prop id)
+		prop_ID_Name_Map = mapper.mapPropIDName()	# (prop id, prop name)
+		
+		reagent = self.createReagent(rID)
+		
+		rTypeMapper = ReagentTypeMapper(db, cursor)
+		typeMap = rTypeMapper.mapTypeIDName()
+
+		rTypeID = self.findReagentTypeID(rID)
+		rType = typeMap[rTypeID]
+		
+		# Fetch a list of the reagent's CURRENT properties
+		oldProps = reagent.getProperties()
+
+		rtpHandler = ReagentTypePropertyHandler(db, cursor)
+		
+		# Fetch this reagent's checkbox property names
+		checkboxPropNames = reagent.getCheckboxProps()
+
+		prop_Category_Name_ID_Map = mapper.mapPropCategoryNameID()
+
+		#print "Content-type:text/html"
+		#print
+		#print `propDict`
+		#print `checkboxPropNames`
+
+		# map checkbox prop names to their IDs
+		checkboxProps = {}			# will store (checkboxPropID, checkboxPropName)
+
+		# 'if' added April 2/07 by Marina, since not all reagent types have checkbox properties (Oligo doesn't)
+		if checkboxPropNames:
+			for c in checkboxPropNames:
+				
+				# July 2/09: Need category to fetch ID, but hard to find out here.  Hard-code selectable marker and alternate ID for now
+				if c == 'alternate id':
+					tmp_cat = "External Identifiers"
+					
+				elif c == 'selectable marker':
+					if rTypeID != 4:
+						tmp_cat = "Classifiers"
+					else:
+						tmp_cat = "Growth Properties"
+					
+				cPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[c], prop_Category_Name_ID_Map[tmp_cat])
+				
+				#print c
+				#print cPropID
+				#cPropID = prop_Name_ID_Map[c]		# removed July 2/09
+				checkboxProps[cPropID] = c
+		
+		# Combine regular properties with checkbox
+		allProps = utils.merge(propDict.keys(), checkboxProps.keys())
+		
+		#print `propDict`
+		#print `allProps`
+
+		# Compare the set of ALL properties for this reagent to POST values and add, update or delete accordingly
+		
+		# July 14/09: propID now is essentially propCatID - a property together with its category
+		for propID in allProps:
+			#print pHandler.findReagentPropertyInCategory(propID)
+			#print propID
+			
+			#if propID <= 0:
+				#continue
+			
+			propName = prop_ID_Name_Map[pHandler.findReagentPropertyInCategory(propID)]	# replaced July 14/09
+			
+			# property could be empty
+			if propDict.has_key(propID):
+				propVal = propDict[propID]
+				
+				#if len(propVal) > 0:		# added April 30/09 and removed July 14/09 - len() doesn't work well with integer values
+				if propVal:			# replaced July 14/09
+					#print "What is this " + propName
+					
+					# special properties - Update Jan. 22, 2010: compute MW, Tm and GC for sequences, if they are attributes of this reagent type
+					if propName == "sequence":
+						#print propVal
+	
+						#if len(propVal) > 0:	# removed April 30/09
+						
+						# Store both DNA and protein sequences if available
+						newSeqID = dnaHandler.getSequenceID(propVal)
+						self.addReagentProperty(rID, propID, newSeqID)
+						
+						# Jan. 25, 2010
+						mwPropID =  pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["molecular weight"], prop_Category_Name_ID_Map["DNA Sequence"])
+						
+						#print mwPropID
+						
+						#if rtpHandler.existsReagentTypeAttribute(rTypeID, mwPropID):
+						mw = str(float(dnaHandler.calculateMW(propVal)))
+						#print mw
+						#self.addReagentProperty(rID, mwPropID, mw)
+						dnaHandler.updateMolecularWeight(newSeqID, mw)
+
+						# For Inserts, translate DNA sequence and store the translated protein sequence
+						if rType == 'Insert':
+							
+							# July 2/09
+							#ocPropID = prop_Name_ID_Map["open/closed"]
+							ocPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["open/closed"], prop_Category_Name_ID_Map["Classifiers"])
+							
+							if propDict.has_key(ocPropID):
+								openClosed = propDict[ocPropID]
+	
+								# June 1/07: IF OPEN/CLOSED IS BLANK, CHECK IF INSERT TYPE IS CDNA W/ UTRs!!!!!
+								if len(openClosed) == 0:
+									# July 2/09
+									#insertTypePropID = prop_Name_ID_Map["type of insert"]
+									insertTypePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["type of insert"], prop_Category_Name_ID_Map["Classifiers"])
+		
+									insertType = propDict[insertTypePropID]
+									
+									if insertType.lower() == 'cdna with utrs':
+										openClosed = "special cdna with utrs"
+	
+							# Feb. 26/08: Change: Translating only cDNA sequence now
+							newProtSeq = iHandler.translateInsertCDNA(rID, openClosed)	# added feb 26/08
+							#newProtSeq = protHandler.translateAll(newSeqID, openClosed)	# removed feb 26/08
+							#newProtSeq = protHandler.translateAll(newSeq, openClosed)	# feb 26/08 ?????
+							newProtSeqID = protHandler.getSequenceID(newProtSeq)
+							
+							# July 2/09
+							protSeqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein translation"], prop_Category_Name_ID_Map["DNA Sequence"])
+						
+							self.addReagentProperty(rID, protSeqPropID, newProtSeqID)
+						else:
+							# Aug. 10/09: For reagent types other than Insert, translate sequence from start to end and choose the longest ORF
+							newProt = protHandler.translateAllFrames(utils.squeeze(propVal))
+
+							if newProt:
+								newProtSeq = newProt.getSequence()
+								
+								if len(newProtSeq) > 0:
+									#print newProtSeq
+									newProtSeqID = protHandler.getSequenceID(newProt)
+									self.updateProteinSequence(rID, newProtSeqID)
+									
+									# Jan. 25/10: update MW
+									protMW = protHandler.calculatePeptideMass(newProtSeq)
+									protHandler.updateMolecularWeight(newProtSeqID, protMW)
+							else:
+								protSeqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein translation"], prop_Category_Name_ID_Map["DNA Sequence"])
+								self.deleteReagentProperty(rID, protSeqPropID)
+						
+						# Jan. 22, 2010: compute Tm - safe to treat as a property of the reagent
+						tmPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["melting temperature"], prop_Category_Name_ID_Map["DNA Sequence"])
+						
+						if rtpHandler.existsReagentTypeAttribute(rTypeID, tmPropID):
+							tm = str(float(dnaHandler.calculateTm(propVal)))
+							#print tm
+							self.addReagentProperty(rID, tmPropID, tm)
+
+
+						# June 25, 2010: GC content
+						gcPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["gc content"], prop_Category_Name_ID_Map["DNA Sequence"])
+						
+						if rtpHandler.existsReagentTypeAttribute(rTypeID, gcPropID):
+							dnaGC = dnaHandler.calculateGC(propVal)
+							self.addReagentProperty(rID, gcPropID, dnaGC)
+						
+
+					# Aug. 13/09
+					elif propName == "protein sequence":
+						if len(propVal) > 0:
+							protSeq = ProteinSequence(propVal)
+							
+							# Jan. 25/10
+							protMW = protHandler.calculatePeptideMass(propVal)
+							protSeq.setMW(protMW)
+							
+							# Store both DNA and protein sequences if available
+							newSeqID = protHandler.getSequenceID(protSeq)
+							self.addReagentProperty(rID, propID, newSeqID)
+
+							# May 6, 2011: Clarification - updateMolecularWeight() updates Sequences_tbl.  Need an extra function call to update ReagentPropList_tbl (see below)
+							#protHandler.updateMolecularWeight(newSeqID, protMW)
+
+							# May 6, 2011: Update ReagentPropList_tbl
+							mwPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["molecular weight"], prop_Category_Name_ID_Map["Protein Sequence"])
+							self.addReagentProperty(rID, mwPropID, protMW)
+
+					elif propName == "rna sequence":
+						
+						rnaSeq = RNASequence(propVal)
+						
+						# Jan. 25/10
+						rnaMW = rnaHandler.calculateMW_RNA(propVal)
+						rnaSeq.setMW(rnaMW)
+						
+						# Store both DNA and protein sequences if available
+						newSeqID = rnaHandler.getSequenceID(rnaSeq)
+						self.addReagentProperty(rID, propID, newSeqID)
+
+					# Comments
+					elif commHandler.isComment(propID):
+						#print propID
+						# Reference to GeneralComments_tbl
+						self.addComment(rID, propID, propVal)
+						
+					else:
+						#print propID
+						#print propVal
+						self.addReagentProperty(rID, propID, propVal)
+		
+	
+	# March 28/08
+	def deleteReagentFeatures(self, rID, isProtein=False, isRNA=False):
+		
+		#print "Content-type:text/html"		# REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+	
+		db = self.db				# for easy access
+		cursor = self.cursor			# for easy access
+		
+		# May 26/09: Handlers and mappers
+		pHandler = ReagentPropertyHandler(db, cursor)
+		rtHandler = ReagentTypeHandler(db, cursor)
+		mapper = ReagentPropertyMapper(db, cursor)
+		rtPropHandler = ReagentTypePropertyHandler(db, cursor)		# Aug. 31/09
+		
+		# May 26/09
+		prop_Category_Name_ID_Map = mapper.mapPropCategoryNameID()
+		prop_Category_Alias_ID_Map = mapper.mapPropCategoryAliasID()
+		prop_Name_ID_Map = mapper.mapPropNameID()	# (prop name, prop id)
+		
+		# May 26/09
+		rTypeID = self.findReagentTypeID(rID)
+		#print rTypeID
+		reagent = self.createReagent(rID)
+		
+		# May 26/09: don't mess with Insert and Vectors!!  Also, here rTypeID is an INTEGER, as opposed to update.py where form values are of type TEXT
+		# July 10/09: no, let's try to generalize
+		#if rTypeID != 1 and rTypeID != 2:
+		
+		if isProtein:
+			features = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, prop_Category_Name_ID_Map["Protein Sequence Features"])
+		elif isRNA:
+			features = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, prop_Category_Name_ID_Map["RNA Sequence Features"])
+		else:
+			features = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, prop_Category_Name_ID_Map["DNA Sequence Features"])
+			
+		#else:	# May 15/09 - keep existing code for Inserts and Vectors
+			#features = Reagent.getSequenceFeatures()
+			#print `features`
+			
+		#print `features`
+		
+		for f in features:
+			#print f
+			
+			# july 10/09
+			#fID = prop_Name_ID_Map[f]
+			if isProtein:
+				fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[f], prop_Category_Name_ID_Map["Protein Sequence Features"])
+			elif isRNA:
+				fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[f], prop_Category_Name_ID_Map["RNA Sequence Features"])
+			else:
+				fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[f], prop_Category_Name_ID_Map["DNA Sequence Features"])
+		
+			if self.existsProperty(rID, fID):
+				self.deleteReagentProperty(rID, fID)
+			
+
+	# Written March 12, 2008
+	# Input: seqFeatures - list of Feature OBJECTS
+	# Modified March 28/08: Delete and re-insert values
+	# Corrected April 23/08: Don't delete on creation
+	# Updated Aug. 7/08: Added positions to differentiate between multiple features with the same name and type
+	def updateReagentSequenceFeatures(self, rID, seqFeatures):
+		
+		db = self.db				# for easy access
+		cursor = self.cursor			# for easy access
+		
+		mapper = ReagentPropertyMapper(db, cursor)
+		pHandler = ReagentPropertyHandler(db, cursor)
+		
+		prop_Name_ID_Map = mapper.mapPropNameID()	# (prop name, prop id)
+		prop_Category_Name_ID_Map = mapper.mapPropCategoryNameID()
+		
+		tmpFeatureDict = {}				# (featureID, [list of values])
+		
+		# DEBUG
+		#print "Content-type:text/html"
+		#print
+		
+		#for f in seqFeatures:
+			#fType = f.getFeatureType()
+			#fName = f.getFeatureName()
+			#fStart = f.getFeatureStartPos()
+			#fEnd = f.getFeatureEndPos()
+			
+			#print fType
+			#print `fName`
+			#print `fStart`
+			#print `fEnd`
+		
+		self.deleteReagentFeatures(rID)			# March 28/08
+		
+		for f in seqFeatures:
+			# Get the name/value of each feature (retrieve from object), MAKE A LIST and pass to changePropertyValue function
+			fType = f.getFeatureType()
+			#print fType
+			fName = f.getFeatureName()
+			#print fName
+			
+			# update July 2/09
+			#fID = prop_Name_ID_Map[fType]
+			fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+			#print `fID`
+			fStart = f.getFeatureStartPos()
+			#print `fStart`
+			fEnd = f.getFeatureEndPos()
+			#print `fEnd`
+			
+			# added Dec. 9/08, at launch
+			if (fEnd-fStart) >= 10:
+				if not self.existsPropertyValue(rID, fID, fName, fStart, fEnd):
+					self.addReagentProperty(rID, fID, fName, fStart, fEnd)
+		
+			# March 17/08: Update feature descriptor if not empty
+			fDescr = f.getFeatureDescrName()
+			#print fDescr
+			
+			if len(fDescr) > 0:
+				# Updated Aug. 7/08: Again, differentiate multiple features with the same name and descriptor by position
+				self.setReagentFeatureDescriptor(rID, fID, fName, fStart, fEnd, fDescr)
+				
+			# March 17/08: Update feature direction
+			fDir = f.getFeatureDirection()
+			#print "Direction ??? " + `fDir`
+			
+			# There are only 2 direction values: default forward and reverse.  Only need to update if it's 'reverse'
+			if fDir == 'reverse':
+				# Updated Aug. 7/08: Here too, differentiate multiple features with the same name and descriptor by position
+				self.updateFeatureDirection(rID, fID, fName, fStart, fEnd, fDir)
+					
+	
+	# March 17/08: Set the value of column 'direction' in ReagentPropList_tbl to 'fDir' for the given feature value
+	# Updated Aug. 7/08: Added 'featureStart' and 'featureEnd' arguments to differentiate between multiple features with the same name
+	def updateFeatureDirection(self, rID, featureID, featureValue, featureStart, featureEnd, featureDirection):
+		
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		if self.existsProperty(rID, featureID):
+			cursor.execute("UPDATE ReagentPropList_tbl SET direction=" + `featureDirection` + " WHERE reagentID=" + `rID` + " AND propertyID=" + `featureID` + " AND propertyValue=" + `featureValue` + " AND startPos=" + `featureStart` + " AND endPos=" + `featureEnd` + " AND status='ACTIVE'")
+
+	
+	# March 17/08: Set the value of column 'descriptor' in ReagentPropList_tbl to 'descriptor' for the given feature value
+	# Updated Aug. 7/08: Added 'featureStart' and 'featureEnd' arguments to differentiate between multiple features with the same name
+	def setReagentFeatureDescriptor(self, rID, featureID, featureValue, featureStart, featureEnd, featureDescriptor):
+		
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		if self.existsProperty(rID, featureID):
+			cursor.execute("UPDATE ReagentPropList_tbl SET descriptor=" + `featureDescriptor` + " WHERE reagentID=" + `rID` + " AND propertyID=" + `featureID` + " AND propertyValue=" + `featureValue` + " AND startPos=" + `featureStart` + " AND endPos=" + `featureEnd` + " AND status='ACTIVE'")
+
+
+	# May 17, 2010: Need a modification of updateReagentProperties() function, as reagent categories are edited separately from e.o.
+	# Instead of comparing input against ALL properties, only compare to properties WITHIN THE GIVEN CATEGORY
+	def updateReagentPropertiesInCategory(self, rID, categoryID, propDict):
+
+		#print "Content-type:text/html"		# REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+	
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		# Various handlers used in implementation
+		dnaHandler = DNAHandler(db, cursor)
+		commHandler = CommentHandler(db, cursor)
+		protHandler = ProteinHandler(db, cursor)
+		iHandler = InsertHandler(db, cursor)		# feb. 26/08
+		rnaHandler = RNAHandler(db, cursor)		# Oct. 22/09
+
+		# Instead of looking up the ID of each individual property, prepare a map of (prop name, prop id) up front -- improves performance (March 14/07)
+		propHandler = ReagentPropertyHandler(db, cursor)
+		mapper = ReagentPropertyMapper(db, cursor)
+		
+		prop_Name_ID_Map = mapper.mapPropNameID()	# (prop name, prop id)
+		prop_ID_Name_Map = mapper.mapPropIDName()	# (prop id, prop name)
+		
+		prop_Category_Name_ID_Map = mapper.mapPropCategoryNameID()
+		
+		reagent = self.createReagent(rID)
+		
+		rTypeMapper = ReagentTypeMapper(db, cursor)
+		typeMap = rTypeMapper.mapTypeIDName()
+
+		rTypeID = self.findReagentTypeID(rID)
+		rType = typeMap[rTypeID]
+		
+		rtPropHandler = ReagentTypePropertyHandler(db, cursor)
+
+		oldProps = self.findAllReagentPropertyIDsByCategory(rID, categoryID)
+		#print `oldProps`
+		#print `propDict`
+		
+		seqAttrs = DNASequence.getDNASequenceAttributes()
+		
+		allCategoryAttributes = rtPropHandler.findReagentTypeAttributeIDsByCategory(rTypeID, categoryID)
+	
+		for attrID in allCategoryAttributes:
+			#print "Attr " + `attrID`
+			propID = rtPropHandler.findReagentTypeAttributePropertyID(attrID)
+			#print "prop id " + `propID`
+			propName = propHandler.findPropName(propID)
+			#print propName
+			
+			if propDict.has_key(propID):
+				propVal = propDict[propID]
+				#print propVal
+				
+				# Now need to differentiate between simple and composite properties involving cross-table reference (such as sequence, comments, etc)
+				
+				# Sequence
+				if propName == "sequence":
+					
+					if len(propVal) > 0:
+					
+						# assign the new sequence input value to the reagent
+						newSeqID = dnaHandler.getSequenceID(propVal)
+						#print `newSeqID`
+						self.updateDNASequence(rID, newSeqID)
+						
+						# Jan. 25/10: Molecular weight
+						mwPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["molecular weight"], prop_Category_Name_ID_Map["DNA Sequence"])
+						
+						if rtPropHandler.existsReagentTypeAttribute(rTypeID, mwPropID):
+							dnaMolWeight = dnaHandler.calculateMW(propVal)
+							dnaHandler.updateMolecularWeight(newSeqID, dnaMolWeight)
+						
+						# Jan. 25/10: Melting temperature
+						tmPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["melting temperature"], prop_Category_Name_ID_Map["DNA Sequence"])
+						
+						if rtPropHandler.existsReagentTypeAttribute(rTypeID, tmPropID):
+							dnaTm = dnaHandler.calculateTm(propVal)
+							self.changePropertyValue(rID, tmPropID, dnaTm)
+						
+						# June 23, 2010: Recompute GC content upon sequence modificaion
+						gcPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["gc content"], prop_Category_Name_ID_Map["DNA Sequence"])
+						
+						if rtPropHandler.existsReagentTypeAttribute(rTypeID, gcPropID):
+							gc_cont = dnaHandler.calculateGC(propVal)
+							#print gc_cont
+							self.changePropertyValue(rID, gcPropID, gc_cont)
+						
+						# Update protein sequence accordingly - FOR INSERTS ONLY
+						if rType == 'Insert':
+							# Must first find out the insert's open/closed property value; if this value is empty, sequence translation is not possible
+							
+							# Modified July 2/09
+							ocPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["open/closed"], prop_Category_Name_ID_Map["Classifiers"])
+	
+							if propDict.has_key(ocPropID):
+								openClosed = propDict[ocPropID]
+								#print `openClosed`
+								
+								# June 1/07: IF OPEN/CLOSED IS BLANK, CHECK IF INSERT TYPE IS CDNA W/ UTRs!!!!!
+								if len(openClosed) == 0:
+									insertTypePropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["type of insert"], prop_Category_Name_ID_Map["Classifiers"])
+		
+									insertType = propDict[insertTypePropID]
+	
+									if insertType.lower() == 'cdna with utrs':
+										openClosed = "special cdna with utrs"
+							# May 19, 2011
+							else:
+								openClosed = self.findSimplePropertyValue(rID, ocPropID)
+								
+								if not openClosed or len(openClosed) == 0:
+									insertTypePropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["type of insert"], prop_Category_Name_ID_Map["Classifiers"])
+		
+									if propDict.has_key(insertTypePropID):
+										insertType = propDict[insertTypePropID]
+									else:
+										insertType = self.findSimplePropertyValue(rID, insertTypePropID)
+	
+									if insertType.lower() == 'cdna with utrs':
+										openClosed = "special cdna with utrs"
+									
+							# Feb. 26/08: Change: Translating only cDNA sequence now
+							newProtSeq = iHandler.translateInsertCDNA(rID, openClosed)	# added feb 26/08
+							
+							newProtSeqID = protHandler.getSequenceID(newProtSeq)
+							#print newProtSeqID
+							self.updateProteinSequence(rID, newProtSeqID)
+							
+							# June 1/07: Do NOT delete old sequence, as it may be shared by other reagents!!!!!!!!!!!!!!!!!!
+						else:
+							# Aug. 10/09: For reagent types other than Insert, translate sequence from start to end and choose the longest ORF
+							#print utils.squeeze(propVal)
+							
+							# Jan. 25/10: but only translate if feasible, i.e. if this reagent type should have a protein translation
+							protTransPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein translation"], prop_Category_Name_ID_Map["DNA Sequence"])
+							
+							if rtPropHandler.existsReagentTypeAttribute(rTypeID, protTransPropID):
+								newProt = protHandler.translateAllFrames(utils.squeeze(propVal))
+								
+								if newProt:
+									newProtSeq = newProt.getSequence()
+									#print newProtSeq
+									
+									if len(newProtSeq) > 0:
+										#print newProtSeq
+										newProtSeqID = protHandler.getSequenceID(newProt)
+										self.updateProteinSequence(rID, newProtSeqID)
+								else:
+									protSeqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein translation"], prop_Category_Name_ID_Map["DNA Sequence"])
+									self.deleteReagentProperty(rID, protSeqPropID)
+					else:
+						# Delete both DNA and protein sequences
+						self.deleteReagentProperty(rID, propID)
+						
+						# Update July 2/09
+						protSeqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein translation"], prop_Category_Name_ID_Map["DNA Sequence"])
+						self.deleteReagentProperty(rID, protSeqPropID)
+
+				# Aug. 13/09
+				elif propName == "protein sequence":
+					protSeq = ProteinSequence(propVal)
+					
+					# Jan. 25/10
+					protMW = protHandler.calculatePeptideMass(propVal)
+					#print protMW
+
+					protSeq.setMW(protMW)
+					
+					newSeqID = protHandler.getSequenceID(protSeq)
+					
+					#if oldProps.has_key(propName):
+					if oldProps.has_key(propID):
+						if newSeqID and newSeqID > 0:
+							#if oldProps[propName] != newSeqID:
+							if oldProps[propID] != newSeqID:
+								self.changePropertyValue(rID, propID, newSeqID)
+						else:
+							self.deleteReagentProperty(rID, propID)
+					else:
+						self.addReagentProperty(rID, propID, newSeqID)
+					
+					# Jan. 25/10: Update MW separately for this sequence (in case it hasn't been previously stored) - somewhat redundant but more complete
+					# May 6, 2011: Clarification - updateMolecularWeight() updates Sequences_tbl.  Need an extra function call to update ReagentPropList_tbl (see below)
+					protHandler.updateMolecularWeight(newSeqID, protMW)
+
+					# May 6, 2011: Update ReagentPropList_tbl
+					mwPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["molecular weight"], prop_Category_Name_ID_Map["Protein Sequence"])
+					self.changePropertyValue(rID, mwPropID, protMW)
+					
+				elif propName == "rna sequence":
+					rnaSeq = RNASequence(propVal)
+					newSeqID = rnaHandler.getSequenceID(rnaSeq)
+					
+					# Jan. 25/10
+					rnaMW = rnaHandler.calculateMW_RNA(propVal)
+					rnaSeq.setMW(rnaMW)
+					
+					#if oldProps.has_key(propName):
+					if oldProps.has_key(propID):
+						if newSeqID and newSeqID > 0:
+							#if oldProps[propName] != newSeqID:
+							if oldProps[propID] != newSeqID:
+								self.changePropertyValue(rID, propID, newSeqID)
+						else:
+							self.deleteReagentProperty(rID, propID)
+					else:
+						self.addReagentProperty(rID, propID, newSeqID)
+					
+					# Jan. 25/10: Update MW separately for this sequence (in case it hasn't been previously stored) - somewhat redundant but more complete
+					rnaHandler.updateMolecularWeight(newSeqID, rnaMW)
+					
+				# Correction May 17, 2010: Develop a generic solution
+				## March 19/09: Store multiple accessions
+				#elif propName == "accession number" or propName == 'alternate id' or propName == 'selectable marker':
+					## delete and re-insert
+					#self.deleteReagentProperty(rID, propID)
+					
+					##print propName
+					
+					##print propID
+					##print `propVal`
+					
+					#if utils.isList(propVal):
+						#accs = propVal
+					#else:
+						#accs = propVal.split(",")
+					
+					##print `accs`
+					
+					#for acc in accs:
+						#if len(acc) > 0:
+							#self.addReagentProperty(rID, propID, acc.strip())
+	
+				# Comments
+				elif commHandler.isComment(propID):
+					#print propID
+					# Reference to GeneralComments_tbl
+					self.updateComments(rID, propID, propDict[propID])
+	
+				else:
+					# May 10, 2010: Multiples
+					#print propName
+					
+					#rtAttrID = rtPropHandler.findReagentTypeAttributeID(rTypeID, propID)
+					#print rtAttrID
+					
+					if rtPropHandler.isMultiple(attrID):
+						#print "multiple " + propName
+						self.deleteReagentProperty(rID, propID)
+						
+						if propVal != "":
+							self.addReagentProperty(rID, propID, propVal)
+					else:
+						#print "Single! " + propName
+						
+						# CHECK IF PROPERTY EXISTS!!!!!!!!!!!!
+						#if oldProps.has_key(propName):
+						if oldProps.has_key(propID):
+							#print propName + " exists"
+							
+							# May 2, 2011: Account for autocomputed integer properties, such as MW, Tm, length
+							if propVal:
+								try:
+									propVal = int(propVal)
+
+									if oldProps[propID] != propVal:
+										# Non-empty, change
+										#print "should change " + propVal
+										self.changePropertyValue(rID, propID, propVal)
+									
+								except (TypeError, ValueError):
+									# property exists, either update or delete depending on its value
+									#if propVal and len(propVal) > 0:
+									if len(propVal) > 0:
+										#print "but not here??" + propName
+										if oldProps[propID] != propVal:
+											# Non-empty, change
+											#print "should change " + propVal
+											self.changePropertyValue(rID, propID, propVal)
+										
+										# otherwise don't do anything!!!!!!!!!!!!!!
+								
+									else:
+										#print "yes " + propName
+										# Empty property, delete
+										self.deleteReagentProperty(rID, propID)
+
+							# May 11, 2011: not sure about this, must have been a reason I didn't include this in the first place...
+							else:
+								# delete
+								self.deleteReagentProperty(rID, propID)
+						else:
+							# does not exist, insert if not empty
+							#print propName + " does not exist, insert if not empty"
+							if propVal != "":
+								self.addReagentProperty(rID, propID, propVal)
+			
+			else:
+				# May 17/10: within this category can delete if empty
+				# This property did not arrive in the list of POST variables; hence, it should be deleted
+				#print "Deleting " + propName
+				
+				# May 14, 2010: EXCEPT automatically computed properties, such as protein translation, MW, Tm - they're not passed in dictionary but should not be deleted!!
+				if propName not in seqAttrs:
+					self.deleteReagentProperty(rID, propID)
+
+
+	# Update a set of reagent properties to new values that are given as a list of {propertyID, propertyValue} tuples
+	# Central usage: save modified reagent properties on return from the "Modify" view
+	def updateReagentProperties(self, rID, propDict):
+		
+		#print "Content-type:text/html"		# REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `propDict`
+		
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		# Various handlers used in implementation
+		dnaHandler = DNAHandler(db, cursor)
+		commHandler = CommentHandler(db, cursor)
+		protHandler = ProteinHandler(db, cursor)
+		iHandler = InsertHandler(db, cursor)		# feb. 26/08
+		rnaHandler = RNAHandler(db, cursor)		# Oct. 22/09
+
+		# Instead of looking up the ID of each individual property, prepare a map of (prop name, prop id) up front -- improves performance (March 14/07)
+		propHandler = ReagentPropertyHandler(db, cursor)
+		mapper = ReagentPropertyMapper(db, cursor)
+		
+		prop_Name_ID_Map = mapper.mapPropNameID()	# (prop name, prop id)
+		prop_ID_Name_Map = mapper.mapPropIDName()	# (prop id, prop name)
+		
+		prop_Category_Name_ID_Map = mapper.mapPropCategoryNameID()
+		
+		reagent = self.createReagent(rID)
+		
+		rTypeMapper = ReagentTypeMapper(db, cursor)
+		typeMap = rTypeMapper.mapTypeIDName()
+
+		rTypeID = self.findReagentTypeID(rID)
+		rType = typeMap[rTypeID]
+		
+		rtPropHandler = ReagentTypePropertyHandler(db, cursor)
+
+		# Fetch a list of the reagent's CURRENT properties
+		# Update Dec. 16/09: with shared property names across categories cannot rely on reagent.getProperties() that returns a list of names.  Need a list of propCatIDs, where each property is linked to a category
+		#oldProps = reagent.getProperties()
+		oldProps = self.findAllReagentPropertiesByID(rID)
+		#print `oldProps`
+		
+		allAttributes = rtPropHandler.findAllReagentTypeAttributes(rTypeID)
+		
+		# Compare the set of ALL properties for this reagent to POST values and add, update or delete accordingly
+		for attrID in allAttributes:
+			propID = rtPropHandler.findReagentTypeAttributePropertyID(attrID)
+			#print propID
+			propName = propHandler.findPropName(propID)
+			#print propName
+			
+			# determine whether the property is to be changed or deleted
+			if propDict.has_key(propID):
+				# change
+				propVal = propDict[propID]
+
+				#print propName
+				#print propVal
+				
+				# Now need to differentiate between simple and composite properties involving cross-table reference (such as sequence, comments, etc)
+				
+				# Sequence
+				if propName == "sequence":
+					
+					if len(propVal) > 0:
+					
+						# assign the new sequence input value to the reagent
+						newSeqID = dnaHandler.getSequenceID(propVal)
+						#print `newSeqID`
+						self.updateDNASequence(rID, newSeqID)
+						
+						# Jan. 25/10: Molecular weight
+						mwPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["molecular weight"], prop_Category_Name_ID_Map["DNA Sequence"])
+						
+						if rtPropHandler.existsReagentTypeAttribute(rTypeID, mwPropID):
+							dnaMolWeight = dnaHandler.calculateMW(propVal)
+							dnaHandler.updateMolecularWeight(newSeqID, dnaMolWeight)
+						
+						# Jan. 25/10: Melting temperature
+						tmPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["melting temperature"], prop_Category_Name_ID_Map["DNA Sequence"])
+						
+						if rtPropHandler.existsReagentTypeAttribute(rTypeID, tmPropID):
+							dnaTm = dnaHandler.calculateTm(propVal)
+							self.changePropertyValue(rID, tmPropID, dnaTm)
+						
+						# June 25, 2010: GC content
+						gcPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["gc content"], prop_Category_Name_ID_Map["DNA Sequence"])
+						
+						if rtPropHandler.existsReagentTypeAttribute(rTypeID, gcPropID):
+							dnaGC = dnaHandler.calculateGC(propVal)
+							self.changePropertyValue(rID, tmPropID, dnaGC)
+						
+						# Update protein sequence accordingly - FOR INSERTS ONLY
+						if rType == 'Insert':
+							# Must first find out the insert's open/closed property value; if this value is empty, sequence translation is not possible
+							
+							# Modified July 2/09
+							#ocPropID = prop_Name_ID_Map["open/closed"]
+							ocPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["open/closed"], prop_Category_Name_ID_Map["Classifiers"])
+	
+							if propDict.has_key(ocPropID):
+								openClosed = propDict[ocPropID]
+								#print `openClosed`
+								
+								# June 1/07: IF OPEN/CLOSED IS BLANK, CHECK IF INSERT TYPE IS CDNA W/ UTRs!!!!!
+								if len(openClosed) == 0:
+									
+									# July 2/09
+									#insertTypePropID = prop_Name_ID_Map["type of insert"]
+									insertTypePropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["type of insert"], prop_Category_Name_ID_Map["Classifiers"])
+		
+									insertType = propDict[insertTypePropID]
+	
+									if insertType.lower() == 'cdna with utrs':
+										openClosed = "special cdna with utrs"
+	
+							# Feb. 26/08: Change: Translating only cDNA sequence now
+							#newProtSeq = protHandler.translateAll(newSeqID, openClosed)	# removed feb 26/08
+							newProtSeq = iHandler.translateInsertCDNA(rID, openClosed)	# added feb 26/08
+							#print newProtSeq
+							newProtSeqID = protHandler.getSequenceID(newProtSeq)
+							self.updateProteinSequence(rID, newProtSeqID)
+							
+							# June 1/07: Do NOT delete old sequence, as it may be shared by other reagents!!!!!!!!!!!!!!!!!!
+						else:
+							# Aug. 10/09: For reagent types other than Insert, translate sequence from start to end and choose the longest ORF
+							#print utils.squeeze(propVal)
+							
+							# Jan. 25/10: but only translate if feasible, i.e. if this reagent type should have a protein translation
+							protTransPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein translation"], prop_Category_Name_ID_Map["DNA Sequence"])
+							
+							if rtPropHandler.existsReagentTypeAttribute(rTypeID, protTransPropID):
+								newProt = protHandler.translateAllFrames(utils.squeeze(propVal))
+								
+								if newProt:
+									newProtSeq = newProt.getSequence()
+									#print newProtSeq
+									
+									if len(newProtSeq) > 0:
+										#print newProtSeq
+										newProtSeqID = protHandler.getSequenceID(newProt)
+										self.updateProteinSequence(rID, newProtSeqID)
+								else:
+									protSeqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein translation"], prop_Category_Name_ID_Map["DNA Sequence"])
+									self.deleteReagentProperty(rID, protSeqPropID)
+					else:
+						# Delete both DNA and protein sequences
+						self.deleteReagentProperty(rID, propID)
+						
+						# Update July 2/09
+						protSeqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein translation"], prop_Category_Name_ID_Map["DNA Sequence"])
+						self.deleteReagentProperty(rID, protSeqPropID)
+				
+				# Aug. 13/09
+				elif propName == "protein sequence":
+					protSeq = ProteinSequence(propVal)
+					
+					# Jan. 25/10
+					protMW = protHandler.calculatePeptideMass(propVal)
+					protSeq.setMW(protMW)
+					
+					newSeqID = protHandler.getSequenceID(protSeq)
+					
+					#if oldProps.has_key(propName):
+					if oldProps.has_key(propID):
+						if newSeqID and newSeqID > 0:
+							#if oldProps[propName] != newSeqID:
+							if oldProps[propID] != newSeqID:
+								self.changePropertyValue(rID, propID, newSeqID)
+						else:
+							self.deleteReagentProperty(rID, propID)
+					else:
+						self.addReagentProperty(rID, propID, newSeqID)
+					
+					# Jan. 25/10: Update MW separately for this sequence (in case it hasn't been previously stored) - somewhat redundant but more complete
+					protHandler.updateMolecularWeight(newSeqID, protMW)
+					
+				elif propName == "rna sequence":
+					rnaSeq = RNASequence(propVal)
+					newSeqID = rnaHandler.getSequenceID(rnaSeq)
+					
+					# Jan. 25/10 - REMOVED APRIL 14, 2011, Karen said don't compute RNA MW automatically
+					#rnaMW = rnaHandler.calculateMW_RNA(propVal)
+					#print rnaMW
+					#rnaSeq.setMW(rnaMW)
+					
+					#if oldProps.has_key(propName):
+					if oldProps.has_key(propID):
+						if newSeqID and newSeqID > 0:
+							#if oldProps[propName] != newSeqID:
+							if oldProps[propID] != newSeqID:
+								self.changePropertyValue(rID, propID, newSeqID)
+						else:
+							self.deleteReagentProperty(rID, propID)
+					else:
+						self.addReagentProperty(rID, propID, newSeqID)
+					
+					# April 14, 2011: don't do this
+					## Jan. 25/10: Update MW separately for this sequence (in case it hasn't been previously stored) - somewhat redundant but more complete
+					#rnaHandler.updateMolecularWeight(newSeqID, rnaMW)
+
+					## April 12, 2011: change MW **property** - Removed April 14, 2011
+					#mwPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["molecular weight"], prop_Category_Name_ID_Map["RNA Sequence"])
+					#self.changePropertyValue(rID, mwPropID, rnaMW)
+					
+				# Correction May 17, 2010: Develop a generic solution
+				## March 19/09: Store multiple accessions
+				#elif propName == "accession number" or propName == 'alternate id' or propName == 'selectable marker':
+					## delete and re-insert
+					#self.deleteReagentProperty(rID, propID)
+					
+					##print propName
+					
+					##print propID
+					##print `propVal`
+					
+					#if utils.isList(propVal):
+						#accs = propVal
+					#else:
+						#accs = propVal.split(",")
+					
+					##print `accs`
+					
+					#for acc in accs:
+						#if len(acc) > 0:
+							#self.addReagentProperty(rID, propID, acc.strip())
+	
+				# Comments
+				elif commHandler.isComment(propID):
+					#print propID
+					# Reference to GeneralComments_tbl
+					self.updateComments(rID, propID, propDict[propID])
+	
+				else:
+					# May 10, 2010: Multiples
+					#print propName
+					
+					rtAttrID = rtPropHandler.findReagentTypeAttributeID(rTypeID, propID)
+					#print rtAttrID
+					if rtPropHandler.isMultiple(rtAttrID):
+						#print "well, yeah " + propName
+						self.deleteReagentProperty(rID, propID)
+						
+						if propVal != "":
+							self.addReagentProperty(rID, propID, propVal)
+					else:
+						#print "Content-type:text/html"
+						#print
+
+						# CHECK IF PROPERTY EXISTS!!!!!!!!!!!!
+						#if oldProps.has_key(propName):
+						if oldProps.has_key(propID):
+							#print propName + " exists"
+						
+							# property exists, either update or delete depending on its value
+							if propVal and len(propVal) > 0:
+								if oldProps[propID] != propVal:
+									# Non-empty, change
+									#print "should change " + propVal
+
+									self.changePropertyValue(rID, propID, propVal)
+								
+								# otherwise don't do anything!!!!!!!!!!!!!!
+							else:
+								# Empty property, delete
+								self.deleteReagentProperty(rID, propID)
+						else:
+							# does not exist, insert if not empty
+							#print propName + " does not exist, insert if not empty"
+							if propVal != "":
+								self.addReagentProperty(rID, propID, propVal)
+			
+			# May 15, 2010: NO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+			# THIS DELETES ANY PROPERTY IN ANY CATEGORY THAT WAS NOT FILLED IN.  WRONG!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+			
+			# May 13, 2011: Yes, but now the only time this function is used is to update Cell Line properties from a parent change - which means the old form where properties are not passed in categories.  Try putting this back and see if it causes problems (so far so good)
+
+			# May 20, 2011: Yes, it does cause problems - because this function is not only used for Cell Lines, but to save the last step of multi-step creation for Vectors and Inserts!
+
+			else:
+				# This property did not arrive in the list of POST variables; hence, it should be deleted
+				#print "WHY HERE?? " + propName
+				self.deleteReagentProperty(rID, propID)
+	
+	
+	# April 7/08: Recompute sequence feature positions if sequence is modified
+	# updated Oct. 15/08 - use findAllReagentPropertiesByName() instead of SQL query
+	def updateFeaturePositions(self, rID, oldSeq, newSeq, isProtein=False, isRNA=False):
+		
+		#print "Content-type:text/html"		# REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		
+		db = self.db
+		cursor = self.cursor
+		
+		reagent = self.createReagent(rID)
+		
+		# Removed July 27/09
+		'''
+		# oct. 23/08
+		#allFeatures = reagent.getAllFeatures()
+		
+		#print `allFeatures`
+		
+		#seqFeatures = reagent.getSequenceFeatures()
+		#singleFeatues = reagent.getSingleFeatures()
+		
+		#features = seqFeatures + singleFeatues
+		'''
+		
+		# changed July 27/09
+		allFeatures = self.findReagentSequenceFeatures(rID, isProtein, isRNA)
+		#print `allFeatures`
+		
+		#print `allFeatures`
+		
+		sHandler = DNAHandler(db, cursor)
+		propHandler = ReagentPropertyHandler(db, cursor)
+		mapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Category_Name_ID_Map = mapper.mapPropCategoryNameID()
+		
+		# april 14/08
+		enzDict = utils.join(sHandler.sitesDict, sHandler.gatewayDict)
+		
+		# april 21/08 - include LoxP
+		enzDict = utils.join(enzDict, sHandler.recombDict)
+		
+		# add 'None'
+		enzDict['None'] = ""
+		
+		#print `enzDict`
+		
+		prop_Name_ID_Map = mapper.mapPropNameID()	# (prop name, prop id)
+		tmpFeatureDict = {}				# (featureID, [list of values])
+		
+		# Length of old and new sequence
+		oldSeqLen = len(oldSeq)
+		newSeqLen = len(newSeq)
+		
+		#allProps = self.findAllReagentPropertiesByName(rID)	# Oct. 15/08, removed July 27/09
+		
+		# updated Oct. 23/08
+		for f in allFeatures:
+			featureType = f.getFeatureType()
+			#print featureType
+			
+			# July 2/09
+			#featureID = prop_Name_ID_Map[featureType]
+			if isProtein:
+				featureID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[featureType.lower()], prop_Category_Name_ID_Map["Protein Sequence Features"])
+			
+			elif isRNA:
+				featureID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[featureType.lower()], prop_Category_Name_ID_Map["RNA Sequence Features"])
+				
+			else:
+				featureID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[featureType.lower()], prop_Category_Name_ID_Map["DNA Sequence Features"])
+			
+			featureValue = f.getFeatureName()
+			featureStartPos = f.getFeatureStartPos()
+			featureEndPos = f.getFeatureEndPos()
+			featureDirection = f.getFeatureDirection()
+			
+			#featureDescriptorType = f.getFeatureDescriptorType()
+			featureDescriptor = f.getFeatureDescrName()
+			
+			#featureDescriptor = f.getFeatureDescriptor()
+			
+			#print "Feature " + `featureType` + ", " + featureValue + ", " + `featureStartPos` + "-" + `featureEndPos` + ", direction " + featureDirection
+			
+			if featureType.lower() == "5' cloning site" or featureType.lower() == "3' cloning site":
+				#if enzDict.has_key(featureValue.lower()):	# WHY LOWERCAASE ENZYME **NAME**???!!!!!!!!!
+				if enzDict.has_key(featureValue):		# correction Oct. 1, 2010
+					fSeq = enzDict[featureValue].lower()
+				elif sHandler.isHybrid(utils.make_array(featureValue)):
+					fSeq = sHandler.hybridSeq(utils.make_array(featureValue)).lower()
+				else:
+					#fSeq = ""	# no, removed Oct. 1, 2010 - can get infinite remapping
+					
+					# Instead: Oct 1, 2010
+					print "Content-type:text/html"
+					print
+					print "Unknown cloning site: " + `featureValue`
+					
+					#print `enzDict`
+			else:
+				# July 27/09: If old sequence was empty naturally don't adjust anything
+				#if len(oldSeq) > 0:
+				fSeq = oldSeq[featureStartPos-1:featureEndPos].lower()
+				#else:
+					#return
+			
+			#print "old feature seq " + fSeq + "!!"
+			
+			# April 18/08 - when sequence is deleted all features should be deleted too
+			if newSeqLen == 0:
+				self.deleteReagentFeature(rID, featureID)
+			else:
+				# April 8/08: Look for feature on the new sequence AND return ALL occurrences as opposed to just the first one
+				# Minimum feature length cutoff 10 nts
+				
+				if featureType.lower() != "5' cloning site" and featureType.lower() != "3' cloning site":
+					# Delete old feature value first - KEEP DESCRIPTORS!!!!
+					fDescr = self.findReagentFeatureDescriptor(rID, featureID, featureValue)
+					#print fDescr
+					
+					# April 21/08 - Check feature length and only remap features that are over 10 nts long
+					fLength = featureEndPos - featureStartPos + 1
+					
+					if fLength >= 10:
+						self.deleteReagentFeature(rID, featureID, featureValue, featureStartPos, featureEndPos, featureDirection, featureDescriptor)
+					
+						# Now find all occurrences of this feature on the new sequence and record them
+						# (april 21/08: don't need this check anymore)
+						#if featureID != prop_Name_ID_Map["5' linker"] and featureID != prop_Name_ID_Map["3' linker"]:
+					
+						numOccur = newSeq.count(fSeq)
+						nextStart = 0
+						i = 0
+						
+						#print "Feature " + `featureID` + " found " + `numOccur` + " times"
+						
+						while i < numOccur:
+							#print "Counter " + `i`
+							#print "Feature " + `featureID` + ": " + fSeq
+							
+							if newSeq.find(fSeq, nextStart) >= 0:
+								newFStart = newSeq.index(fSeq, nextStart) + 1
+								#print " New start " + `newFStart`
+								newFEnd = newFStart+len(fSeq)-1
+								#print " New end " + `newFEnd`
+								nextStart = newFEnd + 1
+								#print `nextStart`
+								
+								# Dec. 17/09: Check for existence.  Reason: e.g. LoxP on V50059: occurs twice in the sequence, at pos. 14-47 and 1802-1835.  If this check not done, each instance will be saved twice - i.e. will have 4 table rows, 2 that say 'Loxp 14-47' and 2 that say 'LoxP 1802-1835'
+								if not self.existsFeature(rID, featureID, featureValue, newFStart, newFEnd, featureDirection, featureDescriptor):
+								
+									# July 27/09: Need to include orientation in arguments list; otherwise, everything gets reset to forward
+									self.addReagentProperty(rID, featureID, featureValue, newFStart, newFEnd, featureDirection)
+									
+									# put the descriptor back if applicable
+									if fDescr:
+										self.setReagentFeatureDescriptor(rID, featureID, featureValue, newFStart, newFEnd, featureDescriptor)
+							else:
+								self.deleteReagentFeature(rID, featureID, featureValue, featureStartPos, featureEndPos, featureDirection, featureDescriptor)
+				
+							# increment loop counter
+							i += 1
+					else:
+						# April 21/08: Keep feature, delete positions
+						self.deletePropertyPosition(rID, featureID, "startPos", featureValue)
+						self.deletePropertyPosition(rID, featureID, "endPos", featureValue)
+	
+	# Added June 8/08
+	# Find the given cloning sites are present on a sequence (by string search) - save positions if found
+	def updateSitePositions(self, rID, newSeq, five_prime_site, three_prime_site):
+		
+		#print "Content-type:text/html"
+		#print
+		
+		db = self.db
+		cursor = self.cursor
+
+		dnaHandler = DNAHandler(db, cursor)
+		rHandler = ReagentHandler(db, cursor)
+		propMapper = ReagentPropertyMapper(db, cursor)
+
+		pHandler = ReagentPropertyHandler(db, cursor)
+
+		prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+
+		enzDict = utils.join(dnaHandler.sitesDict, dnaHandler.gatewayDict)
+		enzDict = utils.join(enzDict, dnaHandler.recombDict)		# add LoxP
+		enzDict['None'] = ""						# add 'None'
+		
+		prop_Name_ID_Map = propMapper.mapPropNameID()			# (prop name, prop id)
+		
+		fpSitePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+		
+		tpSitePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	
+		if five_prime_site:
+			fpcs = utils.make_array(five_prime_site)
+		else:
+			self.deleteReagentProperty(rID, fpSitePropID)
+			return
+			
+		if three_prime_site:
+			tpcs = utils.make_array(three_prime_site)
+		else:
+			self.deleteReagentProperty(rID, tpSitePropID)
+			return
+		
+		if dnaHandler.isHybrid(fpcs):
+			fp_seq = dnaHandler.hybridSeq(fpcs).lower()
+
+		else:
+			if len(five_prime_site) > 0:
+				fp_seq = enzDict[five_prime_site].lower()
+			else:
+				fp_seq = ""
+
+		#print fp_seq
+
+		if dnaHandler.isHybrid(tpcs):
+			tp_seq = dnaHandler.hybridSeq(tpcs).lower()
+			
+		else:
+			if len(three_prime_site) > 0:
+				tp_seq = enzDict[three_prime_site].lower()
+			else:
+				tp_seq = ""
+
+		# Start positions from 1 to make them human-readable
+		if len(fp_seq) > 0 and newSeq.lower().find(fp_seq) >= 0:
+			five_start_pos = newSeq.lower().index(fp_seq) + 1
+			five_end_pos = five_start_pos + len(fp_seq) - 1
+		else:
+			# Dec. 17/08: If sites are not found, use BioPython to look for degenerate sites with variable sequences
+			tmpSeq = Bio.Seq.Seq(newSeq)
+			
+			# Jan. 6/09
+			if dnaHandler.enzDict.has_key(five_prime_site):
+				fp_cs = dnaHandler.enzDict[five_prime_site]
+				
+				if len(fp_cs.search(tmpSeq)) > 0:
+					five_start_pos = fp_cs.search(tmpSeq)[0] - len(fp_cs.ovhgseq) + 1
+					five_end_pos = five_start_pos + len(fp_seq) - 1
+					
+					if five_start_pos == 0:
+						five_start_pos = 0
+						five_end_pos = 0
+				else:
+					five_start_pos = 0
+					five_end_pos = 0
+			# Jan. 6/09
+			else:
+				five_start_pos = 0
+				five_end_pos = 0
+			
+		# Insert new values for sites
+		rHandler.deleteReagentProperty(rID, fpSitePropID)
+		rHandler.addReagentProperty(rID, fpSitePropID, five_prime_site, five_start_pos, five_end_pos)
+		
+		# 3' site: Regular search, no need to reverse complement
+		# July 15/08: For LoxP, since there are 2, start searching for 3' site from end of sequence
+		if three_prime_site == 'LoxP':
+			if newSeq.lower().rfind(tp_seq) >= 0:
+				three_start_pos = newSeq.lower().rindex(tp_seq) + 1
+				three_end_pos = three_start_pos + len(tp_seq) - 1
+			else:
+				three_start_pos = 0
+				three_end_pos = 0
+		else:	
+			if len(tp_seq) > 0 and newSeq.lower().rfind(tp_seq) >= 0:
+				three_start_pos = newSeq.lower().rindex(tp_seq) + 1
+				three_end_pos = three_start_pos + len(tp_seq) - 1
+			else:
+				# Dec. 17/08: If sites are not found, use BioPython to look for degenerate sites with variable sequences
+				tmpSeq = Bio.Seq.Seq(newSeq)
+				
+				# Jan. 6/09
+				if dnaHandler.enzDict.has_key(three_prime_site):
+					tp_cs = dnaHandler.enzDict[three_prime_site]
+					
+					if len(tp_cs.search(tmpSeq)) > 0:
+						three_start_pos = tp_cs.search(tmpSeq)[len(tp_cs.search(tmpSeq))-1] - len(tp_cs.ovhgseq) + 1
+						three_end_pos = three_start_pos + len(tp_seq) - 1
+						
+						if three_start_pos == 0:
+							three_start_pos = 0
+							three_end_pos = 0
+					else:
+						three_start_pos = 0
+						three_end_pos = 0
+				# Jan. 6/09
+				else:
+					three_start_pos = 0
+					three_end_pos = 0
+
+		self.deleteReagentProperty(rID, tpSitePropID)
+		self.addReagentProperty(rID, tpSitePropID, three_prime_site, three_start_pos, three_end_pos)	
+
+
+	# Set the start/end value of a reagent property
+	#
+	# propID: the ID of the property to set position for (e.g0. propID '1' => "5' linker"; '14' => "5' cloning site", etc.)
+	# posType: one of "startPos" or "endPos"
+	# position: actual INT value of property start or end
+	#
+	# Updated March 13/08: Added propVal argument, to account for multiple property values (e.g. when updating features).  May be left blank by default if the property identified by propID has only one value
+	def setPropertyPosition(self, rID, propID, posType, position, propVal=""):
+		#print "Content-type:text/html"
+		#print
+		
+		db = self.db
+		cursor = self.cursor
+		
+		if len(propVal) == 0:
+			if self.existsProperty(rID, propID):
+				cursor.execute("UPDATE ReagentPropList_tbl SET " + posType + "=" + `position` + " WHERE reagentID=" + `rID` + " AND propertyID=" + `propID`)
+			else:
+				cursor.execute("INSERT INTO ReagentPropList_tbl(reagentID, propertyID, " + posType + ") VALUES(" + `rID` + ", " + `propID` + ", " + `position` + ")")
+		else:
+			if self.existsPropertyValue(rID, propID, propVal):
+				cursor.execute("UPDATE ReagentPropList_tbl SET " + posType + "=" + `position` + " WHERE reagentID=" + `rID` + " AND propertyID=" + `propID` + " AND propertyValue=" + `propVal` + " AND status='ACTIVE'")
+			else:
+				cursor.execute("INSERT INTO ReagentPropList_tbl(reagentID, propertyID, propertyValue, " + posType + ") VALUES(" + `rID` + ", " + `propID` + ", " + `propVal` + ", " + `position` + " AND status='ACTIVE')")
+
+	
+	# Set the given property position to 0
+	# propID: the ID of the property to delete position for (e.g. propID '1' => "5' linker"; '14' => "5' cloning site", etc.)
+	# posType: one of "startPos" or "endPos"
+	# Updated April 21/08: added propVal argument for features
+	def deletePropertyPosition(self, rID, propID, posType, propVal=""):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		if len(propVal) == 0:
+			cursor.execute("UPDATE ReagentPropList_tbl SET " + posType + "=DEFAULT WHERE reagentID=" + `rID` + " AND propertyID=" + `propID`)
+		else:
+			cursor.execute("UPDATE ReagentPropList_tbl SET " + posType + "=DEFAULT WHERE reagentID=" + `rID` + " AND propertyID=" + `propID` + " AND propertyValue=" + `propVal`)
+
+
+	# Feb. 26/08: Find feature start position
+	# Updated April 7/08: Aadded fVal argument - for features with multiple values
+	# FEB. 4/09: CAUTION: FEATURES WITH IDENTICAL VALUES MAY **ALSO** HAVE MULTIPLE POSITIONS, i.e. A FEATURE MAY OCCUR MORE THAN ONCE IN A SEQUENCE - e.g. a Vector sequence may have > 1 splice donor!  This function should return a LIST - fix at the earliest!!!  Ditto for endPos
+	def findReagentFeatureStart(self, rID, fID, fVal=""):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		if len(fVal) != 0:
+			#print "SELECT startPos FROM ReagentPropList_tbl WHERE reagentID=" + `rID` + " AND propertyID=" + `fID` + " AND propertyValue=" + `fVal` + " AND status='ACTIVE'"
+			
+			cursor.execute("SELECT startPos FROM ReagentPropList_tbl WHERE reagentID=" + `rID` + " AND propertyID=" + `fID` + " AND propertyValue=" + `fVal` + " AND status='ACTIVE'")
+			result = cursor.fetchone()
+			
+			if result:
+				return int(result[0])
+		else:
+			cursor.execute("SELECT startPos FROM ReagentPropList_tbl WHERE reagentID=" + `rID` + " AND propertyID=" + `fID` + " AND status='ACTIVE'")
+			result = cursor.fetchone()
+			
+			if result:
+				return int(result[0])
+			
+		return 0
+
+
+	# Feb. 26/08: Find feature end position
+	# Updated April 7/08: See findReagentFeatureStart comments
+	# FEB. 4/09: CAUTION: FEATURES WITH IDENTICAL VALUES MAY **ALSO** HAVE MULTIPLE POSITIONS, i.e. A FEATURE MAY OCCUR MORE THAN ONCE IN A SEQUENCE - e.g. a Vector sequence may have > 1 splice donor!  This function should return a LIST - fix at the earliest!!!  Ditto for startPos
+	def findReagentFeatureEnd(self, rID, fID, fVal=""):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		if len(fVal) != 0:
+			cursor.execute("SELECT endPos FROM ReagentPropList_tbl WHERE reagentID=" + `rID` + " AND propertyID=" + `fID` + " AND propertyValue=" + `fVal` + " AND status='ACTIVE'")
+			result = cursor.fetchone()
+			
+			if result:
+				return int(result[0])
+		else:
+			cursor.execute("SELECT endPos FROM ReagentPropList_tbl WHERE reagentID=" + `rID` + " AND propertyID=" + `fID` + " AND status='ACTIVE'")
+			result = cursor.fetchone()
+			
+			if result:
+				return int(result[0])
+			
+		return 0
+	
+	
+	# April 10/08
+	def findReagentFeatureDescriptor(self, rID, fID, fVal=""):
+		
+		db = self.db
+		cursor = self.cursor
+
+		#print "Content-type:text/html"		# REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!		
+		#print
+		
+		if len(fVal) != 0:
+			#print "SELECT descriptor FROM ReagentPropList_tbl WHERE reagentID=" + `rID` + " AND propertyID=" + `fID` + " AND propertyValue=" + `fVal` + " AND status='ACTIVE'"
+			
+			cursor.execute("SELECT descriptor FROM ReagentPropList_tbl WHERE reagentID=" + `rID` + " AND propertyID=" + `fID` + " AND propertyValue=" + `fVal` + " AND status='ACTIVE'")
+			result = cursor.fetchone()
+			
+			if result:
+				return result[0]
+		else:
+			cursor.execute("SELECT descriptor FROM ReagentPropList_tbl WHERE reagentID=" + `rID` + " AND propertyID=" + `fID` + " AND status='ACTIVE'")
+			result = cursor.fetchone()
+			
+			if result:
+				return result[0]
+
+		return 0
+	
+	
+	# April 16/08: Find ALL the values of a current feature
+	# Similar in action to findSimplePropertyValue, except return a list of values instead of a single value
+	def findReagentFeatureValues(self, rID, featureID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		fVals = []
+		
+		cursor.execute("SELECT propertyValue FROM ReagentPropList_tbl WHERE reagentID=" + `rID` + " AND propertyID=" + `featureID` + " AND propertyValue != '' AND status='ACTIVE'")
+		
+		f_results = cursor.fetchall()
+		
+		for fRes in f_results:
+			fVal = fRes[0]
+			fVals.append(fVal)
+		
+		return fVals
+		
+		
+	# April 16/08: Get all the features of a given reagent (sequence features - tag type, polyA, origin, etc.)
+	# Return: list of Feature OBJECTS
+	def findReagentSequenceFeatures(self, rID, isProtein=False, isRNA=False):
+		
+		db = self.db
+		cursor = self.cursor
+
+		tmpReagent = self.createReagent(rID)
+		
+		#rFeatures = tmpReagent.getSequenceFeatures()	# list of feature names - Removed Sept. 10/09, see fix below
+		fDescr = tmpReagent.getFeatureDescriptors()
+
+		mapper = ReagentPropertyMapper(db, cursor)
+		pHandler = ReagentPropertyHandler(db, cursor)
+		rtPropHandler = ReagentTypePropertyHandler(db, cursor)
+		
+		prop_Name_ID_Map = mapper.mapPropNameID()	# (prop name, prop id)
+		prop_Category_Name_ID_Map = mapper.mapPropCategoryNameID()
+		
+		# Update Sept. 10/09: No longer can rely on preset list - must retrieve database values according to reagent type
+		rTypeID = self.findReagentTypeID(rID)
+		
+		if isProtein:
+			rFeatures = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, prop_Category_Name_ID_Map["Protein Sequence Features"])
+			fTypeCat = "Protein Sequence Features"
+			
+		elif isRNA:
+			rFeatures = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, prop_Category_Name_ID_Map["RNA Sequence Features"])
+			fTypeCat = "RNA Sequence Features"
+		else:
+			rFeatures = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, prop_Category_Name_ID_Map["DNA Sequence Features"])
+			fTypeCat = "DNA Sequence Features"
+		
+		features = []					# list of Feature OBJECTS
+		
+		#print "Content-type:text/html"
+		#print
+		
+		for rf in rFeatures:
+			#print rf
+			
+			#featureID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[rf.lower()], prop_Category_Name_ID_Map["DNA Sequence Features"])
+
+			featureID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[rf.lower()], prop_Category_Name_ID_Map[fTypeCat])
+			#print "?? " + rf + `featureID`
+			
+			#print "SELECT propertyValue, startPos, endPos, direction, descriptor FROM ReagentPropList_tbl p WHERE p.reagentID=" + `rID` + " AND p.propertyID=" + `featureID` + " AND p.status='ACTIVE'"
+			
+			cursor.execute("SELECT propertyValue, startPos, endPos, direction, descriptor FROM ReagentPropList_tbl p WHERE p.reagentID=" + `rID` + " AND p.propertyID=" + `featureID` + " AND p.status='ACTIVE'")
+			
+			f_results = cursor.fetchall()
+			
+			for fRes in f_results:
+				
+				fVal = fRes[0]
+				fStart = int(fRes[1])
+				fEnd = int(fRes[2])
+				fDir = fRes[3]
+				
+				#print fVal
+				#print `fDescr`
+				#print fDir
+				
+				if fDescr.has_key(rf):
+					#print "Feature " + rf + ", "
+					#print `fRes`
+					
+					if len(fRes) > 4 and fRes[4]:
+						fdType = fDescr[rf]
+						#print fdType
+						fdName = fRes[4]
+						#print fdName
+					else:
+						fdType = None
+						fdName = None
+						
+					tmpFeature = SequenceFeature(rf, fVal, fStart, fEnd, fDir, fdType, fdName)
+				
+				else:
+					tmpFeature = SequenceFeature(rf, fVal, fStart, fEnd, fDir)
+				
+				#print `tmpFeature`
+				
+				#print "Feature " + rf + ": " + fVal + ", start " + `fStart` + ", end " + `fEnd` + ", direction " + fDir + ", descriptor " + `tmpFeature.getFeatureDescrName()`
+				
+				features.append(tmpFeature)
+		
+		#print `features`
+		return features
+	
+	
+	# Set the orientation (direction) of a reagent property to the value of propDirection - either 'forward' or 'reverse'
+	# (using the term 'direction' to distinguish between global sequence orientation, even though the concept is the same)
+	# Input: propDirection - STRING, one of 'forward' or 'reverse' - in LOWERCASE
+	def setPropertyDirection(self, rID, propID, propDirection):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		if self.existsProperty(rID, propID):
+			cursor.execute("UPDATE ReagentPropList_tbl SET direction=" + `propDirection` + " WHERE  reagentID=" + `rID` + " AND propertyID=" + `propID`)
+		else:
+			cursor.execute("INSERT INTO ReagentPropList_tbl(reagentID, propertyID, direction) VALUES(" + `rID` + ", " + `propID` + ", " + `propDirection` + ")")
+			
+
+	# Check if a property exists for this reagent:
+	def existsProperty(self, rID, propID):
+		
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+
+		cursor.execute("SELECT `propListID` FROM `ReagentPropList_tbl` WHERE `reagentID`=" + `rID` + " AND `propertyID`=" + `propID` + " AND `status`='ACTIVE'")
+		result = cursor.fetchall()	# e.g. for checkbox properties - there are multiple values
+
+		if result:
+			return 1
+		else:
+			return 0
+
+	# Dec. 17/09
+	def existsFeature(self, rID, fID, fVal, fStart, fEnd, fDir, fDescr=None):
+		
+		#print "Content-type:text/html"
+		#print
+		#print "SELECT propListID FROM ReagentPropList_tbl WHERE reagentID=" + `rID` + " AND propertyID=" + `fID` + " AND propertyValue=" + `fVal` + " AND startPos=" + `fStart` + " AND endPos=" + `fEnd` + " AND direction=" + `fDir` + " AND descriptor=" + `fDescr` + " AND status='ACTIVE'"
+		
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+
+		if fDescr:
+			cursor.execute("SELECT propListID FROM ReagentPropList_tbl WHERE reagentID=" + `rID` + " AND propertyID=" + `fID` + " AND propertyValue=" + `fVal` + " AND startPos=" + `fStart` + " AND endPos=" + `fEnd` + " AND direction=" + `fDir` + " AND descriptor=" + `fDescr` + " AND status='ACTIVE'")
+		else:
+			cursor.execute("SELECT propListID FROM ReagentPropList_tbl WHERE reagentID=" + `rID` + " AND propertyID=" + `fID` + " AND propertyValue=" + `fVal` + " AND startPos=" + `fStart` + " AND endPos=" + `fEnd` + " AND direction=" + `fDir` + " AND status='ACTIVE'")
+			
+		results = cursor.fetchall()
+		
+		if len(results) == 0:
+			return False
+		
+		#elif len(results) > 0:
+			#for result in resuls:
+				#if not result:
+					#return False
+		
+		return True
+	
+	
+	# Store a new property value for this reagent
+	# Updated Feb. 12/08: Record start and end positions if applicable
+	# June 9/08: Added 'pDir' parameter representing orientation
+	# propID == propCatID
+	def addReagentProperty(self, rID, propID, propVal, pStart=0, pEnd=0, pDir="forward"):
+		
+		#print "Content-type:text/html"
+		#print
+		#print "Inserting "
+		#print propID
+		#print propVal
+		#print `pStart`
+		#print `pEnd`
+		#print `pDir`
+
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		if utils.isList(propVal):	# checkboxes
+			for v in propVal:
+				if len(v) > 0:
+					# May 30/08: Sometimes during preprocessing empty position values may end up < 0. Catch here and remedy
+					if pStart < 0:
+						query = "INSERT INTO ReagentPropList_tbl(reagentID, propertyID, propertyValue, startPos, endPos, direction) VALUES(" + `rID` + ", " + `propID` + ", " + `v` + ", '0', " + `pEnd` + ", " + `pDir` + ")"
+					elif pEnd < 0:
+						query = "INSERT INTO ReagentPropList_tbl(reagentID, propertyID, propertyValue, startPos, endPos, direction) VALUES(" + `rID` + ", " + `propID` + ", " + `v` + ", " + `pStart` + ", '0', " + ", " + `pDir` + ")"
+					else:
+						query = "INSERT INTO ReagentPropList_tbl(reagentID, propertyID, propertyValue, startPos, endPos, direction) VALUES(" + `rID` + ", " + `propID` + ", " + `v` + ", " + `pStart` + ", " + `pEnd` + ", " + `pDir` + ")"
+						
+					cursor.execute(query)	# needs to be executed FOR EVERY VALUE IN LIST
+		else:
+			# May 30/08: Sometimes during preprocessing empty position values may end up < 0. Catch here and remedy
+			if pStart < 0:
+				query = "INSERT INTO ReagentPropList_tbl(reagentID, propertyID, propertyValue, startPos, endPos, direction) VALUES(" + `rID` + ", " + `propID` + ", " + `propVal` +  ", '0', " + `pEnd` + ", " + `pDir` + ")"
+			elif pEnd < 0:
+				query = "INSERT INTO ReagentPropList_tbl(reagentID, propertyID, propertyValue, startPos, endPos, direction) VALUES(" + `rID` + ", " + `propID` + ", " + `propVal` +  ", " + `pStart` + ", '0', " + `pDir` + ")"
+			else:
+				# Update June 24, 2010: Do not use backticks, as they distort floating-point precision
+				if type(propVal) == types.FloatType:
+					query = "INSERT INTO ReagentPropList_tbl(reagentID, propertyID, propertyValue, startPos, endPos, direction) VALUES(" + `rID` + ", " + `propID` + ", '" + str(propVal) +  "', " + `pStart` + ", " + `pEnd` + ", " + `pDir` + ")"
+				else:
+					query = "INSERT INTO ReagentPropList_tbl(reagentID, propertyID, propertyValue, startPos, endPos, direction) VALUES(" + `rID` + ", " + `propID` + ", " + `propVal` +  ", " + `pStart` + ", " + `pEnd` + ", " + `pDir` + ")"
+		
+			#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+			#print					# DITTO
+			#print query
+	
+			cursor.execute(query)
+	
+	
+	# Delete (deprecate) reagent FEATURE - account for multiple values
+	# Written April 8, 2008 
+	def deleteReagentFeature(self, rID, fID, fVal = "", fStart=0, fEnd=0, fDir='forward', fDescr=""):
+		
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		if len(fVal) == 0:
+			cursor.execute("UPDATE `ReagentPropList_tbl` SET `status`='DEP' WHERE `reagentID`=" + `rID` + " AND `propertyID`=" + `fID` + " AND `status`='ACTIVE'")
+			
+		else:
+			if fDescr and len(fDescr) > 0:
+				cursor.execute("UPDATE `ReagentPropList_tbl` SET `status`='DEP' WHERE `reagentID`=" + `rID` + " AND `propertyID`=" + `fID` + " AND propertyValue=" + `fVal` + " AND startPos=" + `fStart` + " AND endPos=" + `fEnd` + " AND descriptor=" + `fDescr` + " AND direction=" + `fDir` + " AND `status`='ACTIVE'")
+			else:			
+				cursor.execute("UPDATE `ReagentPropList_tbl` SET `status`='DEP' WHERE `reagentID`=" + `rID` + " AND `propertyID`=" + `fID` + " AND propertyValue=" + `fVal` + " AND startPos=" + `fStart` + " AND endPos=" + `fEnd` + " AND direction=" + `fDir` + " AND `status`='ACTIVE'")
+
+		
+	# Delete (deprecate) a specific property for this reagent
+	def deleteReagentProperty(self, rID, propID):
+		
+		#print "Content-type:text/html"
+		#print
+		#print "UPDATE `ReagentPropList_tbl` SET `status`='DEP' WHERE `reagentID`=" + `rID` + " AND `propertyID`=" + `propID` + " AND `status`='ACTIVE'"
+		
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		cursor.execute("UPDATE `ReagentPropList_tbl` SET `status`='DEP' WHERE `reagentID`=" + `rID` + " AND `propertyID`=" + `propID` + " AND `status`='ACTIVE'")
+		
+	
+	# Insert a new set of properties into the database for the given reagent ID
+	def insertReagentProperties(self, rID, propDict):
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		#print "Content-type:text/html"
+		#print
+		
+		for propID in propDict.keys():
+			propVal = propDict[propID]
+			#print "INSERT INTO `ReagentPropList_tbl`(`reagentID`, `propertyID`, `propertyValue`) VALUES(" + `rID` + ", " + `propID` + ", " + `propVal` + ")"
+			cursor.execute("INSERT INTO `ReagentPropList_tbl`(`reagentID`, `propertyID`, `propertyValue`) VALUES(" + `rID` + ", " + `propID` + ", " + `propVal` + ")")
+	
+	
+	# Update the value of one property of the given reagent in ReagentPropList_tbl
+	def changePropertyValue(self, rID, propID, propVal):
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"		# REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print propID
+		
+		# added check for existence here again Jan. 25/10
+		if self.existsProperty(rID, propID):
+			# For multiple property values == checkboxes - don't UPDATE, too complicated - just delete old values and insert new ones
+			if utils.isList(propVal):
+				self.deleteReagentProperty(rID, propID)
+				self.addReagentProperty(rID, propID, propVal)
+			else:
+				# otherwise, for simple properties just change their value
+				#pVal = ""
+				
+				# June 23, 2010: Backticks ruin the set floating-point precision, discard rounding:
+				# e.g. 33.33 is converted to 33.32999999999
+				#
+				#if type(propVal) == types.FloatType:
+					#pVal = str(propVal)
+					#query = "UPDATE ReagentPropList_tbl SET propertyValue='" + pVal + "' WHERE reagentID=" + `rID` + " AND propertyID=" + `propID` + " AND status='ACTIVE'"
+					#cursor.execute(query)
+				#else:
+
+				#print "UPDATE ReagentPropList_tbl SET propertyValue='" + str(propVal).replace("'", "\\'") + "' WHERE reagentID=" + `rID` + " AND propertyID=" + `propID` + " AND status='ACTIVE'"
+
+				cursor.execute("UPDATE ReagentPropList_tbl SET propertyValue='" + str(propVal).replace("'", "\\'") + "' WHERE reagentID=" + `rID` + " AND propertyID=" + `propID` + " AND status='ACTIVE'")
+		else:
+			self.addReagentProperty(rID, propID, propVal)
+
+	# Set reagent's DNA sequence property value to seqID argument if seqID > 0; otherwise delete
+	def updateDNASequence(self, rid, newSeqID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		propHandler = ReagentPropertyHandler(db, cursor)
+		mapper = ReagentPropertyMapper(db, cursor)
+		
+		prop_Category_Name_ID_Map = mapper.mapPropCategoryNameID()
+		prop_Name_ID_Map = mapper.mapPropNameID()			# (prop name, prop id)
+		
+		#seqPropID = propHandler.findPropID("sequence")
+		seqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+
+		if newSeqID > 0:
+			# Check if a DNA sequence existed for this reagent in the first place	
+			oldSeq_id = self.findIndexPropertyValue(rid, seqPropID)
+			
+			if oldSeq_id > 0:
+				# there is a DNA sequence for this reagent
+				
+				# check if it is identical to translated value
+				if oldSeq_id != newSeqID:
+				
+					# Not identical, change (overwrite old sequence ID in ReagentPropList_tbl)
+					self.changePropertyValue(rid, seqPropID, newSeqID)
+					
+				# otherwise don't do anything
+				
+			else:
+				# No DNA sequence had been stored for this reagent at all.  Insert new value:
+				self.insertReagentProperties(rid, {seqPropID:newSeqID})
+		else:
+			# Delete the sequence for this reagent
+			self.deleteReagentProperty(rid, seqPropID)
+		
+		
+	# Set reagent's protein sequence property value to seqID argument if seqID > 0; otherwise delete
+	def updateProteinSequence(self, rid, newProtSeqID):
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"
+		#print
+		
+		propHandler = ReagentPropertyHandler(db, cursor)
+		propMapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Name_ID_Map = propMapper.mapPropNameID()			# (prop name, prop id)
+		
+		# changes made July 2/09
+		prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+		prop_Category_ID_Name_Map = propMapper.mapPropCategoryNameID()
+		
+		protSeqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein translation"], prop_Category_Name_ID_Map["DNA Sequence"])
+		
+		#print protSeqPropID
+		
+		if newProtSeqID > 0:
+		
+			# Check if a protein sequence existed for this reagent in the first place
+			oldProtSeq_id = self.findIndexPropertyValue(rid, protSeqPropID)
+			#print oldProtSeq_id
+		
+			if oldProtSeq_id > 0:
+				# there is a protein sequence for this reagent
+				
+				# check if it is identical to translated value
+				if oldProtSeq_id != newProtSeqID:
+					# Not identical, change (overwrite old sequence ID in ReagentPropList_tbl)
+					self.changePropertyValue(rid, protSeqPropID, newProtSeqID)
+
+				# otherwise don't do anything
+
+			else:
+				# No protein sequence has been stored for this reagent at all.  Insert translated value:
+				#print "ok, inserting?"
+				self.insertReagentProperties(rid, {protSeqPropID:newProtSeqID})
+		else:
+			#print "and now deleting again"
+			# Delete protein sequence for this reagent
+			self.deleteReagentProperty(rid, protSeqPropID)
+
+		#self.updatePeptideMass(rid, newProtSeqID)
+
+	
+	'''
+	# Jan. 22, 2010
+	def updatePeptideMass(self, rID, newProtSeqID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"
+		#print
+		
+		propHandler = ReagentPropertyHandler(db, cursor)
+		propMapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Name_ID_Map = propMapper.mapPropNameID()			# (prop name, prop id)
+		
+		# changes made July 2/09
+		prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+		prop_Category_ID_Name_Map = propMapper.mapPropCategoryNameID()
+		
+		protSeqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein translation"], prop_Category_Name_ID_Map["DNA Sequence"])
+		
+		# Jan. 22, 2010: calculate MW of translated protein sequence
+		protHandler = ProteinHandler(db, cursor)
+		
+		peptideMassPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["molecular weight"], prop_Category_Name_ID_Map["Protein Sequence"])
+		
+		#print "peptideMassPropID " + `peptideMassPropID`
+		#print protSeqPropID
+		
+		# Jan. 22, 2010: get the original sequence to compute its MW
+		newProtSeq = protHandler.findSequenceByID(newProtSeqID)
+		
+		peptideMass = protHandler.calculatePeptideMass(newProtSeq)
+		
+		#print newProtSeq
+		#print "peptideMass " + `peptideMass`
+		
+		if not self.existsProperty(rID, peptideMassPropID):
+			# Jan. 22, 2010: store MW
+			self.addReagentProperty(rID, peptideMassPropID, peptideMass)
+			
+		elif len(newProtSeq) == 0:
+			self.deleteReagentProperty(rID, peptideMassPropID)
+			
+		else:
+			self.changePropertyValue(rID, peptideMassPropID, peptideMass)
+	'''	
+	
+	# March 30/07, Marina: Add new comment value for the given reagent
+	def addComment(self, rID, commPropID, comment):
+
+		db = self.db
+		cursor = self.cursor
+
+		commHandler = CommentHandler(db, cursor)
+
+		# Create a Comment table entry
+
+		# May 31/07: Select a CommentLinkID first - always 1 for reagent
+		commLinkID = commHandler.findCommentLinkID('Reagent')
+		newCommID = commHandler.insertComment(commLinkID, comment)
+
+		# store comment ID as a property
+		self.addReagentProperty(rID, commPropID, newCommID)
+
+
+	# Update experimental/verificaiton comment or description for this reagent
+	# DO NOT CHANGE COMMENT VALUE IN GeneralComments_tbl!! ONLY update ReagentPropList_tbl - change the comment ID for reagent identified by rID
+	def updateComments(self, rID, commPropID, comment):
+
+		#print "Content-type:text/html"		# REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+
+		db = self.db
+		cursor = self.cursor
+		commHandler = CommentHandler(db, cursor)
+
+		newCommID = -1
+
+		# First, check if the new comment exists in OpenFreezer
+		if utils.isList(comment):
+			for c in comment:
+				#self.updateComments(rID, commPropID, c)
+				newCommID = commHandler.existsComment(1, c)
+
+				if newCommID < 0:
+					# does not exist, insert
+
+					# Select a CommentLinkID first - always 1 for reagent
+					commLinkID = commHandler.findCommentLinkID('Reagent')
+					newCommID = commHandler.insertComment(commLinkID, c)
+
+				# Now check if the reagent has a comment assigned to it and, if yes, whether that comment is identical to the new value
+				if self.existsProperty(rID, commPropID):
+
+					oldCommID = self.findIndexPropertyValue(rID, commPropID)
+					oldCommentVal = commHandler.findCommentByID(oldCommID)
+
+					#if oldCommentVal != c:
+					self.changePropertyValue(rID, commPropID, newCommID)
+
+					# otherwise they're identical - don't do anything
+				else:
+					
+					# This reagent doesn't have a comment at all, insert new value
+					self.addReagentProperty(rID, commPropID, newCommID)
+		else:
+			newCommID = commHandler.existsComment(1, comment)
+			
+			if newCommID < 0:
+				# does not exist, insert
+
+				# Select a CommentLinkID first - always 1 for reagent
+				commLinkID = commHandler.findCommentLinkID('Reagent')
+				newCommID = commHandler.insertComment(commLinkID, comment)
+
+			# Now check if the reagent has a comment assigned to it and, if yes, whether that comment is identical to the new value
+			if self.existsProperty(rID, commPropID):
+				
+				oldCommID = self.findIndexPropertyValue(rID, commPropID)
+				
+				## Check added May 6/08 - comment could exist but still be empty
+				#if oldCommID < 0:
+					## change empty comment to argument value
+					#self.changePropertyValue(rID, commPropID, newCommID)
+				#else:
+				oldCommentVal = commHandler.findCommentByID(oldCommID)
+
+				if oldCommentVal != comment:
+					self.changePropertyValue(rID, commPropID, newCommID)
+
+				# otherwise they're identical - don't do anything
+			else:
+				# This reagent doesn't have a comment at all, insert new value
+				self.addReagentProperty(rID, commPropID, newCommID)
+
+
+	# Add associations to a new reagent at creation
+	def addReagentAssociations(self, rID, assocPropsDict):
+
+		db = self.db
+		cursor = self.cursor
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print "2: " + `assocPropsDict`
+
+		assocMapper = ReagentAssociationMapper(db, cursor)
+		aHandler = ReagentAssociationHandler(db, cursor)
+		rtMapper = ReagentTypeMapper(db, cursor)
+		rtaHandler = ReagentTypeAssociationHandler(db, cursor)
+
+		assoc_Alias_ID_Map = assocMapper.mapAssocAliasID()
+		assoc_Alias_Name_Map = assocMapper.mapAssocAliasName()	# (assocAlias, assocName)
+		assoc_Name_ID_Map = assocMapper.mapAssocNameID()	# (assocName, assocID)
+		assoc_ID_Name_Map = assocMapper.mapAssocIDName()	# (assocID, assocName)
+
+		#print `assoc_ID_Name_Map`
+
+		rType_Name_ID_Map = rtMapper.mapTypeNameID()
+		reagent = self.createReagent(rID)
+
+		# Added Sept. 11/07: get association type
+		rType = reagent.getType()
+		rTypeID = rType_Name_ID_Map[rType]
+
+		currAssocTypes = reagent.getAssociationTypes()		# associations for the given reagent type (as the form input contains hidden association fields for reagent types other than the one being created)
+
+		# Create association (Association_tbl entry) to assign properties to it IFF not done already (depends on reagent type)
+		if aHandler.findReagentAssociationID(rID) <= 0:
+
+			# Create new association   
+			# Find ATypeID (returned by getCloningMethod() function)
+			if not reagent.getCloningMethod():
+
+				# No ATypeID assigned yet, find it based on reagent type
+				aTypeID = rtaHandler.findAssociationByReagentType(rTypeID)
+			else:
+				aTypeID = reagent.getCloningMethod()
+
+			# added Jan. 25, 2010: have to account for reagent types w/o parents now
+			if aTypeID > 0:
+				assocID = self.createReagentAssociation(rID, aTypeID)
+	
+				for assocPropAlias in assocPropsDict.keys():
+					#print assocPropsDict[assocPropAlias]
+					newAssocVal = assocPropsDict[assocPropAlias]
+					#print len(newAssocVal)
+					assocPropName = assoc_Alias_Name_Map[assocPropAlias]
+					assocPropID = assoc_Name_ID_Map[assocPropName]
+				
+					if len(newAssocVal) > 0:  
+						self.addAssociationValue(rID, assocPropID, self.convertReagentToDatabaseID(newAssocVal), assocID)
+		else:
+
+			# otherwise, DELETE old values before inserting new ones - May 5/08
+			assocID = aHandler.findReagentAssociationID(rID)
+
+			for assocPropID in assocPropsDict.keys():
+
+				# Aug. 25/09: can now save multiple parents for new reagent types
+				#newAssocVal = assocPropsDict[assocPropAlias]
+
+				if utils.isList(assocPropsDict[assocPropID]):
+					assocList = assocPropsDict[assocPropID]
+					
+					assocPropName = assoc_ID_Name_Map[assocPropID]
+					self.deleteReagentAssociationProp(rID, assocPropID)	# May 5/08
+					
+					for newAssocVal in assocList:
+					
+						if len(newAssocVal) > 0:
+							self.addAssociationValue(rID, assocPropID, self.convertReagentToDatabaseID(newAssocVal), assocID)
+				else:
+					newAssocVal = assocPropsDict[assocPropID]
+
+					assocPropName = assoc_ID_Name_Map[assocPropID]
+
+					if len(newAssocVal) > 0:
+						self.deleteReagentAssociationProp(rID, assocPropID)	# May 5/08
+						self.addAssociationValue(rID, assocPropID, self.convertReagentToDatabaseID(newAssocVal), assocID)
+
+
+	# Update parent/child associations of a reagent (primarily parent)
+	# Parameters: assocPropsDict: (assocPropID, value)
+	def updateReagentAssociations(self, rID, assocPropsDict):
+
+		db = self.db
+		cursor = self.cursor
+
+		# DEBUGGING
+		#print "Content-type:text/html"
+		#print
+		#print `assocPropsDict`
+
+		aHandler = ReagentAssociationHandler(db, cursor)
+		assocMapper = ReagentAssociationMapper(db, cursor)
+		rtaHandler = ReagentTypeAssociationHandler(db, cursor)
+
+		assoc_Alias_ID_Map = assocMapper.mapAssocAliasID()
+		assoc_Alias_Name_Map = assocMapper.mapAssocAliasName()	# (assocAlias, assocName)
+		assoc_Name_ID_Map = assocMapper.mapAssocNameID()	# (assocName, assocID)
+		assoc_ID_Name_Map = assocMapper.mapAssocIDName()
+
+		reagent = self.createReagent(rID)		
+		oldAssoc = reagent.getAssociations()			# (assocName, assocValue)
+
+		#print `oldAssoc`
+
+		rType = reagent.getType()
+
+		# Dec. 9/09: removed 'Oligo'
+		#if rType == 'Vector' or rType == 'Insert' or rType == 'Oligo' or rType == 'CellLine':
+		if rType == 'Vector' or rType == 'Insert' or rType == 'CellLine':
+
+			for assocPropID in assocPropsDict.keys():
+				#print assocPropID
+				assocPropName = assoc_ID_Name_Map[assocPropID]
+
+				# Feb. 11/10: this IS a list, after all (e.g. 2 parent vectors for a new reagent type)
+				newAssocVals = assocPropsDict[assocPropID]
+
+				#newAssocVal = assocPropsDict[assocPropID]
+				#print newAssocVal
+				
+				if not utils.isList(newAssocVals):
+					newAssocVals = utils.toArray(newAssocVals)
+
+				for newAssocVal in newAssocVals:
+					
+					if len(newAssocVal) > 0:
+						# Association value is not empty
+						if oldAssoc.has_key(assocPropName):
+							
+							oldAssocVal = self.convertDatabaseToReagentID(oldAssoc[assocPropName])
+							#print oldAssocVal
+	
+							# check if value is the same
+							if oldAssocVal != newAssocVal:
+	
+								# check still redundant (feb. 16/10)
+								## check if new value is empty, in which case it should be deleted
+								#if len(newAssocVal) > 0:
+									#print newAssocVal
+	
+								# non-empty, update
+								rAssocType = reagent.getCloningMethod()
+
+								if utils.isList(newAssocVal):
+									for tmpAssocVal in newAssocVal:
+										self.updateAssociationValue(rID, rAssocType, assocPropID, self.convertReagentToDatabaseID(tmpAssocVal))
+								else:
+									self.updateAssociationValue(rID, rAssocType, assocPropID, self.convertReagentToDatabaseID(newAssocVal))
+									
+								#else:
+									## delete
+									#self.deleteReagentAssociationProp(rID, assocPropID)
+	
+							# don't do anything if old and new values are identical
+	
+						else:
+							# Association didn't exist before, insert if not empty
+							if len(newAssocVal) > 0:
+	
+								# Here need to do a bit of preliminary work: determine ATypeID from reagent type
+								# Since this function currently only applies to Inserts, the code is straightforward
+								rTypeID = self.findReagentTypeID(rID)
+	
+								# Updated August 23/07
+								if rTypeID == 2:
+									aTypeID = rtaHandler.findAssociationByReagentType(rTypeID)
+								else:
+									aTypeID = reagent.getCloningMethod()
+	
+								# Aug 24/07: First check if an ASSOCIATION (an entry in Association_tbl) exists for this reagent, only there are no properties associated with it (no entries for this assID in AssocProp_tbl)
+								assocID = aHandler.findReagentAssociationID(rID)
+	
+								if assocID <= 0:
+									# only in this case create a new association for this reagent
+									assocID = self.createReagentAssociation(rID, aTypeID)
+								
+								self.addAssociationValue(rID, assocPropID, self.convertReagentToDatabaseID(newAssocVal), assocID)
+							else:
+								# Delete
+								self.deleteReagentAssociationProp(rID, assocPropID)
+					else:
+						self.deleteReagentAssociationProp(rID, assocPropID)
+		else:
+			# delete old values and create new association
+			for assocName in oldAssoc.keys():
+				assocPropID = assoc_Name_ID_Map[assocName]
+				self.deleteReagentAssociationProp(rID, assocPropID)
+
+			self.addReagentAssociations(rID, assocPropsDict)
+
+
+	# Add a new reagent ASSOCIATION - i.e. a NEW ENTRY IN ASSOCIATION_TBL
+	def createReagentAssociation(self, rID, aTypeID):
+
+		db = self.db
+		cursor = self.cursor
+
+		aHandler = ReagentAssociationHandler(db, cursor)
+		#aTypeID = aHandler.findReagentAssociationType(rID)
+
+		assocID = -1
+
+		# Jan. 25/10: removed assertion, dealing with reagent types w/o parents now
+		#try:
+			#assert aTypeID > 0
+
+		cursor.execute("INSERT INTO Association_tbl(reagentID, ATypeID) VALUES(" + `rID` + ", " + `aTypeID` + ")")
+		assocID = int(db.insert_id())
+
+		#except AssertionError:
+			#print "Content-type:text/html"
+			#print
+			#print "Error: Invalid ATypeID: must be greater than 0"
+
+		return assocID
+
+
+	# Add a new association VALUE for the given reagent (e.g. if an Insert had oligos filled in but not IPV, it already has an entry in Association_tbl, just need to add IPV value to list of assocProps for that Insert)
+	# Creating a new entry in **AssocProp_tbl**
+	# Updated August 24/07: Add assocID argument; may be empty
+	def addAssociationValue(self, rID, assocPropID, newAssocValue, assocID=0):
+
+		db = self.db
+		cursor = self.cursor
+
+		if assocID == 0:
+			aHandler = ReagentAssociationHandler(db, cursor)
+			assocID = aHandler.findReagentAssociationID(rID)
+
+		try:
+			assert assocID > 0
+			#print "INSERT INTO AssocProp_tbl(assID, APropertyID, propertyValue) VALUES(" + `assocID` + ", " + `assocPropID` + ", " + `newAssocValue` + ")"
+
+			cursor.execute("INSERT INTO AssocProp_tbl(assID, APropertyID, propertyValue) VALUES(" + `assocID` + ", " + `assocPropID` + ", " + `newAssocValue` + ")")
+
+		except AssertionError:
+			# shouldn't happen
+			print "Content-type:text/html"
+			print
+			print "This shouldn't happen!"
+
+
+	# Update the value of an existing reagent association
+	def updateAssociationValue(self, rID, rAssocType, assocPropID, newAssocValue):
+
+		db = self.db
+		cursor = self.cursor
+
+		aHandler = ReagentAssociationHandler(db, cursor)
+		assocID = aHandler.findReagentAssociationID(rID)
+
+		try:
+			assert assocID > 0
+			cursor.execute("UPDATE AssocProp_tbl SET propertyValue=" + `newAssocValue` + " WHERE assID=" + `assocID` + " AND APropertyID=" + `assocPropID` + " AND status='ACTIVE'")
+
+		except AssertionError:
+
+			# This is probably the case where the reagent has no associations and user wants to add parents thru Modify view.  Create the association first, then assign values to it
+			assID = self.createReagentAssociation(rID, rAssocType)
+			self.addAssociationValue(rID, assocPropID, newAssocValue)
+
+
+	# Delete the given association for a reagent
+	def deleteReagentAssociationProp(self, rID, assocPropID):
+
+		db = self.db
+		cursor = self.cursor
+
+		aHandler = ReagentAssociationHandler(db, cursor)
+
+		# Updated Nov. 27/07: For Inserts there is more than one assID per rID, for different ATypeIDs: 4 for "Insert Oligos" and 6 for IPV - hence, for Inserts should also include assocPropID in assID selection
+		#assocID = aHandler.findReagentAssociationID(rID)
+		assocID = aHandler.findSpeReagentAssociationPropertyID(rID, assocPropID)
+
+		if assocID > 0:
+			aHandler.deleteReagentAssociationPropertyValue(assocID, assocPropID)
+
+		# otherwise don't have to do anything; nothing to delete if the association didn't exist in the first place
+
+
+	###################################################################################################################################
+	# Find parent/child values of the reagent identified by rID
+	# Returns: dictionary containing (assocPropType**ID**, assocValue) for this reagent
+	# e.g. rID = '13' (represents V13); assocPropTypeID representing 'Parent Vector' = 1; parent vector of V13 is V26 (rID 26)
+	# Then the entry representing this association in the resulting dictionary is (1, 26)
+	#######################################################################################################################################
+	def findAllReagentAssociationsByID(self, rID):
+
+		db = self.db
+		cursor = self.cursor
+
+		aHandler = ReagentAssociationHandler(db, cursor)
+		assocID = aHandler.findReagentAssociationID(rID)
+
+		assocDict = {}
+
+		try:
+			assert assocID > 0
+			cursor.execute("SELECT APropertyID, propertyValue FROM AssocProp_tbl WHERE assID=" + `assocID` + " AND status='ACTIVE'")
+			results = cursor.fetchall()
+
+			for result in results:
+
+				assocTypeID = int(result[0])
+				assocValue = int(result[1])
+
+				assocDict[assocTypeID] = assocValue 
+
+		except AssertionError:
+
+			# Need better exception handling, change this
+			print "Content-type:text/html"
+			print
+			print "AssertionError: Reagent " + `rID` + " has no associations"
+
+		return assocDict
+
+
+	#######################################################################################################################################
+	# Find parent/child values of the reagent identified by rID, where the association type (parent vector, insert, etc) is in human-readable form
+	# The association values are the **internal database reagent IDs** (reagentID column)
+	# e.g. rID = '13' (represents V13); assocPropTypeID representing 'Parent Vector' = 1; parent vector of V13 is V26 (rID 26)
+	# Then the entry representing this association in the resulting dictionary is ('parent vector', 26)
+	#######################################################################################################################################
+	def findAllReagentAssociationsByName(self, rID):
+
+		db = self.db
+		cursor = self.cursor
+
+		aHandler = ReagentAssociationHandler(db, cursor)
+		assocID = aHandler.findReagentAssociationID(rID)
+
+		assocDict = {}
+
+		if assocID > 0:
+			cursor.execute("SELECT t.APropName, p.propertyValue FROM Assoc_Prop_Type_tbl t, AssocProp_tbl p WHERE p.assID=" + `assocID` + " AND p.APropertyID=t.APropertyID AND p.status='ACTIVE' AND t.status='ACTIVE'")
+			results = cursor.fetchall()
+
+			for result in results:
+				assocType = result[0]
+				assocValue = int(result[1])
+
+				assocDict[assocType] = assocValue
+
+		# otherwise the reagent may just not have any associations - that's fine
+
+		return assocDict
+
+
+	# Nov. 5/08, updated June 8/09 - deprecate reagent ID, its properties, features, DNA/protein sequences and associations
+	def deleteReagent(self, rID):
+		db = self.db
+		cursor = self.cursor
+
+		aHandler = ReagentAssociationHandler(db, cursor)
+		lHandler = LocationHandler(db, cursor)
+
+		# Disallow deletion if there are active preps for this reagent
+		expID = self.findExperimentID(rID)
+
+		if not self.hasPreps(expID):
+			# ok, delete
+			assocID = aHandler.findReagentAssociationID(rID)
+
+			# delete (deprecate) all assoc props 
+			aHandler.deleteAllAssociationPropertyValues(assocID)
+
+			# delete (deprecate) all associations (Association_tbl entry) for this rID
+			self.deleteReagentAssociations(rID)
+
+			self.deleteReagentProperties(rID)
+
+			# delete reagent itself
+			cursor.execute("UPDATE Reagents_tbl SET status='DEP' WHERE reagentID=" + `rID` + " AND status='ACTIVE'")
+
+			# Delete Locations
+			lHandler.deleteLocation(expID)
+
+			return 1
+		else:
+			return 0
+
+
+	def hasPreps(self, expID):
+		db = self.db
+		cursor = self.cursor
+
+		lHandler = LocationHandler(db, cursor)
+
+		isolates = lHandler.findIsolates(expID)
+
+		for isolateID in isolates:
+			preps = lHandler.findPreps(isolateID)
+
+			if len(preps) > 0:
+				return True
+
+		return False
+
+
+	def findExperimentID(self, rID):
+		db = self.db
+		cursor = self.cursor
+
+		cursor.execute("SELECT expID FROM Experiment_tbl WHERE reagentID=" + `rID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+
+		if result:
+			return int(result[0])
+
+		return 0
+
+
+	# June 8/09
+	def deleteReagentProperties(self, rID):
+		db = self.db
+		cursor = self.cursor
+
+		# delete reagent properties
+		cursor.execute("UPDATE ReagentPropList_tbl SET status='DEP' WHERE reagentID=" + `rID` + " AND status='ACTIVE'")
+
+
+	# June 8/09
+	def deleteReagentAssociations(self, rID):
+		db = self.db
+		cursor = self.cursor
+
+		cursor.execute("UPDATE Association_tbl SET status='DEP' WHERE reagentID=" + `rID` + " AND status='ACTIVE'")
+
+
+###################################################################
+# InsertHandler class
+# Written October 12, 2006, by Marina Olhovsky
+# Last modified: February 13, 2008
+###################################################################
+
+# Inherits from ReagentHandler
+# Contains handler methods specifically for reagents of type Insert
+class InsertHandler(ReagentHandler):
+	"Contains handler methods specifically for reagents of type Insert"
+
+	#def __init__(self, rID, db, cursor):
+		#super(InsertHandler, self).__init__(db, cursor)
+		#self.__rID = rID
+
+	# Retrieve the type of a specific insert ('type of insert' property)
+	def findTypeOfInsert(self, rID):
+
+		db = self.db
+		cursor = self.cursor
+
+		propHandler = ReagentPropertyHandler(db, cursor)
+		itPropID = propHandler.findPropID("type of insert")
+
+		iType = ""
+
+		cursor.execute("SELECT `propertyValue` FROM `ReagentPropList_tbl` WHERE `propertyID`=" + `itPropID` + " AND `reagentID`=" + `rID` + " AND `status`='ACTIVE'")
+		result = cursor.fetchone()  
+
+		if result:
+			iType = result[0].strip().lower()
+
+		return iType
+
+
+	# Retrieve the open/closed status of rID
+	def findOpenClosed(self, rID):
+
+		db = self.db
+		cursor = self.cursor
+
+		propHandler = ReagentPropertyHandler(db, cursor)
+		ocPropID = propHandler.findPropID("open/closed")
+
+		openClosed = ""
+
+		cursor.execute("SELECT `propertyValue` FROM `ReagentPropList_tbl` WHERE `propertyID`=" + `ocPropID` + " AND `reagentID`=" + `rID`)	
+		result = cursor.fetchone()  
+
+		if result:
+			openClosed = result[0].strip().lower()
+
+		return openClosed
+
+	# Find the Sense Oligo for this Insert
+	# Return: Oligo ID
+	def findSenseOligoID(self, rID):
+
+		db = self.db
+		cursor = self.cursor
+
+		senseOligoID = -1
+
+		raHandler = ReagentAssociationHandler(db, cursor)
+		assocID = raHandler.findReagentAssociationID(rID)
+
+		aHandler = AssociationHandler(db, cursor)
+		senseOligoPropID = aHandler.findAssocPropID("sense oligo")
+		senseOligoID = aHandler.findAssocPropValue(assocID, senseOligoPropID)
+
+		return senseOligoID
+
+	# The same only for Antisense Oligo
+	def findAntisenseOligoID(self, rID):
+
+		db = self.db
+		cursor = self.cursor
+
+		antisenseOligoID = -1
+
+		raHandler = ReagentAssociationHandler(db, cursor)
+		assocID = raHandler.findReagentAssociationID(rID)
+
+		aHandler = AssociationHandler(db, cursor)
+		antisenseOligoPropID = aHandler.findAssocPropID("antisense oligo")
+		antisenseOligoID = aHandler.findAssocPropValue(assocID, antisenseOligoPropID)
+
+		return antisenseOligoID
+
+
+	# Find the Insert Parent Vector of the Insert identified by rID
+	# Return: IPV ID             
+	def findInsertParentVectorID(self, rID):
+
+		db = self.db
+		cursor = self.cursor
+
+		raHandler = ReagentAssociationHandler(db, cursor)
+		aHandler = AssociationHandler(db, cursor)
+
+		ipvID = -1
+
+		assocID = raHandler.findReagentAssociationID(rID)
+		ipvPropID = aHandler.findAssocPropID("insert parent vector id")
+		ipvID = aHandler.findAssocPropValue(assocID, ipvPropID)
+
+		return ipvID
+
+
+	# Feb. 26/08: Find cDNA start position on Insert sequence
+	# It's is an Insert-specific property, handy to have - so no harm adding this function here
+	def findCDNAStart(self, rID):
+
+		db = self.db
+		cursor = self.cursor
+
+		propHandler = ReagentPropertyHandler(db, cursor)
+		propMapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Name_ID_Map = propMapper.mapPropNameID()			# (prop name, prop id)
+
+		# changes made July 2/09    
+		prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+
+		#cdnaPropID = propHandler.findPropID("cdna insert")	# removed July 2/09
+		cdnaPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+		cdnaStart = self.findReagentFeatureStart(rID, cdnaPropID)
+
+		return cdnaStart
+
+
+	# Feb. 26/08: Find cDNA end position on Insert sequence
+	# cDNA is an Insert-specific property, handy to have - so no harm adding this function here
+	def findCDNAEnd(self, rID):
+
+		db = self.db
+		cursor = self.cursor
+
+		propHandler = ReagentPropertyHandler(db, cursor)
+		propMapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+		prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+
+		#cdnaPropID = propHandler.findPropID("cdna insert")
+		cdnaPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+
+		cdnaEnd = self.findReagentFeatureEnd(rID, cdnaPropID)
+		return cdnaEnd
+
+
+	# Feb. 26/08: Translate only the cDNA portion of a reagent's Insert sequence
+	def translateInsertCDNA(self, rID, openClosed):
+
+		db = self.db
+		cursor = self.cursor
+
+		dnaHandler = DNAHandler(db, cursor)   
+		protHandler = ProteinHandler(db, cursor)
+		propHandler = ReagentPropertyHandler(db, cursor)
+		
+		propHandler = ReagentPropertyHandler(db, cursor)
+		propMapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+		prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+
+		# June 5/08: Same strategy for locating positions - string search on original sequence
+		# Fetch the original Insert sequence
+		#seqPropID = propHandler.findPropID("sequence")
+		
+		seqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+
+		seqID = self.findIndexPropertyValue(rID, seqPropID)
+		sequence = dnaHandler.findSequenceByID(seqID)
+
+		#print "Content-type:text/html"
+		#print
+		#print sequence
+
+		# Translate only the cDNA portion
+		cdnaSeq = self.findInsertCDNASequence(rID)
+		#print cdnaSeq
+		newProtSeq = protHandler.translateAll(cdnaSeq, openClosed)
+
+		if newProtSeq:
+			#print newProtSeq.getSequence()
+
+			cdnaStart = self.findCDNAStart(rID)
+			cdnaEnd = self.findCDNAEnd(rID)
+
+			newStart = cdnaStart + newProtSeq.getSeqStart() - 1
+			#print `newStart`
+			#print `len(newProtSeq.getSequence())`
+			newEnd = newStart + len(newProtSeq.getSequence())*3 - 1
+			#print `newEnd`
+
+			# added June 5/08
+			#reverseDNA = newProtSeq.getReverseDNA()
+			#print reverseDNA
+
+			#protSeq = newProtSeq.getSequence()
+
+			#cdnaStart = sequence.lower().find(reverseDNA.lower()) + 1
+			#print "start " + `cdnaStart`
+
+			#if cdnaStart < 0:
+				## not found
+				#cdnaStart = 0
+				#cdnaEnd = 0
+			#else:
+				#cdnaEnd = cdnaStart + len(protSeq)*3 - 1
+
+			#print "End " + `cdnaEnd`
+
+			newProtSeq.setSeqStart(newStart)
+			newProtSeq.setSeqEnd(newEnd)
+			
+			# Jan. 22, 2010: get MW
+			mw = protHandler.calculatePeptideMass(newProtSeq.getSequence())
+			newProtSeq.setMW(mw)
+
+		return newProtSeq
+
+
+	# Feb. 26/08: Find the cDNA portion of a reagent's Insert sequence
+	def findInsertCDNASequence(self, rID):
+
+		db = self.db
+		cursor = self.cursor
+
+		cdnaSeq = ""
+
+		propHandler = ReagentPropertyHandler(db, cursor)
+		sHandler = SequenceHandler(db, cursor)
+
+		# Fetch the entire Insert sequence
+		#seqPropID = propHandler.findPropID("sequence")
+		propMapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+		prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+
+		seqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+
+		seqID = self.findIndexPropertyValue(rID, seqPropID)
+		sequence = sHandler.findSequenceByID(seqID)
+
+		cdnaStart = self.findCDNAStart(rID)
+		cdnaEnd = self.findCDNAEnd(rID)
+
+		#print "Content-type:text/html"
+		#print
+
+		#print "cdna start " + `cdnaStart`
+		#print "cdna end " + `cdnaEnd`
+
+		# 'start' can be 0 but 'end' cannot
+		if cdnaEnd > 0:
+			cdnaSeq = sequence[cdnaStart-1:cdnaEnd]
+
+		return cdnaSeq
+
+
+	# April 21/08: Update protein translation if cDNA boundaries are modified
+	def updateInsertProteinSequence(self, rID, insertType=None, openClosed=None):
+
+		db = self.db
+		cursor = self.cursor
+
+		propHandler = ReagentPropertyHandler(db, cursor)
+		sHandler = SequenceHandler(db, cursor)
+		protHandler = ProteinHandler(db, cursor)
+		propMapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+		prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+
+		# July 2/09
+		ocPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["open/closed"], prop_Category_Name_ID_Map["Classifiers"])
+		insertTypePropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["type of insert"], prop_Category_Name_ID_Map["Classifiers"])
+
+		#ocPropID = prop_Name_ID_Map["open/closed"]		# removed July 2/09
+		#insertTypePropID = prop_Name_ID_Map["type of insert"]	# removed July 2/09
+
+		if not insertType:
+			insertType = self.findSimplePropertyValue(rID, insertTypePropID)
+
+		if not openClosed:
+			openClosed = self.findSimplePropertyValue(rID, ocPropID)
+
+		if insertType and insertType.lower() == 'cdna with utrs':
+			openClosed = "special cdna with utrs"
+
+		# Feb. 26/08: Change: Translating only cDNA sequence now
+		newProtSeq = self.translateInsertCDNA(rID, openClosed)	# added feb 26/08
+		newProtSeqID = protHandler.getSequenceID(newProtSeq)
+		#print `newProtSeqID`
+
+		self.updateProteinSequence(rID, newProtSeqID)
+
+
+###################################################################
+# OligoHandler class
+# Written July 13, 2009, by Marina Olhovsky
+# Last modified March 19, 2010
+###################################################################
+
+# Inherits from ReagentHandler
+# Contains handler methods specifically for reagents of type Oligo
+class OligoHandler(ReagentHandler):
+	"Contains handler methods specifically for reagents of type Oligo"
+
+	__base_mw_table = {'A':313.209, 'C':289.184, 'G':329.208, 'T':304.196}
+	
+	def calculateMW(self, sequence):
+		if len(sequence) == 0:
+			return None
+		
+		sequence = utils.squeeze(sequence).strip().upper()
+		
+		num_a = string.count(sequence, 'A')
+		num_c = string.count(sequence, 'C')
+		num_g = string.count(sequence, 'G')
+		num_t = string.count(sequence, 'T')
+		
+		a_weight = float(num_a * self.__base_mw_table['A'])
+		c_weight = float(num_c * self.__base_mw_table['C'])
+		g_weight = float(num_g * self.__base_mw_table['G'])
+		t_weight = float(num_t * self.__base_mw_table['T'])
+		
+		base_weight = float(a_weight) + float(c_weight) + float(g_weight) + float(t_weight)
+		
+		mw = base_weight - 61.964
+		
+		return utils.trunc(mw, 3)
+
+
+	def calculateTm(self, sequence):
+		if len(sequence) == 0:
+			return None
+		
+		#sequence = utils.squeeze(sequence).strip().upper()	# don't use this; squeeze() needs an update to filter out \r
+		
+		tmp_seq = ""
+		
+		for char in sequence.upper():
+			if char == 'A' or char == 'C' or char == 'G' or char == 'T':
+				tmp_seq += char
+				
+		sequence = tmp_seq
+			
+		#sequence = sequence.replace(" ", "")
+		#sequence = sequence.replace("\r", "")
+		#sequence = sequence.replace("\n", "")
+		#sequence = sequence.replace("\t", "")
+		
+		#sequence = sequence.upper()
+		
+		seqLen = float(len(sequence))
+		
+		num_a = float(string.count(sequence, 'A'))
+		#print `num_a` + "A"
+		num_c = float(string.count(sequence, 'C'))
+		#print `num_c` + "C"
+		num_g = float(string.count(sequence, 'G'))
+		#print `num_g` + "G"
+		num_t = float(string.count(sequence, 'T'))
+		#print `num_t` + "T"
+		
+		if seqLen < 14.0:
+			temp = 2 * (num_a + num_t) + 4 * (num_g + num_c)
+		else:
+			temp = 64.9 + 41.0 * (num_g + num_c - 16.4) / seqLen
+
+		#print temp
+
+		# Truncate the string to 2 significant digits BUT round first!!! (e.g. 69.61900000000 => 69.62; w.o. calling round() first the answer is 69.61)
+		return utils.trunc(round(temp, 2), 2)
+		
+		
+	def findOligoType(self, oligoID):
+		
+		db = self.db
+		cursor = self.cursor
+
+		propHandler = ReagentPropertyHandler(db, cursor)
+		propMapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+		prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+
+		oTypePropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["oligo type"], prop_Category_Name_ID_Map["General Properties"])
+		
+		oligoType = self.findSimplePropertyValue(oligoID, oTypePropID)
+		
+		return oligoType
+		
+	
+	def isSenseOligo(self, oligoID):
+		
+		oType = self.findOligoType(oligoID)
+		
+		if oType:
+			return oType.lower() == "sense"
+		else:
+			return False
+	
+	
+	def isAntiSenseOligo(self, oligoID):
+		oType = self.findOligoType(oligoID)
+		
+		if oType:
+			return oType.lower() == "antisense"
+		else:
+			return False
+	
diff --git a/OpenFreezer/cgi/reagent_output.py b/OpenFreezer/cgi/reagent_output.py
new file mode 100755
index 0000000..3854527
--- /dev/null
+++ b/OpenFreezer/cgi/reagent_output.py
@@ -0,0 +1,946 @@
+#!/usr/local/bin/python
+
+import os
+#import tempfile
+import stat
+import sys
+
+from database_conn import DatabaseConn
+from session import Session
+
+from reagent_handler import ReagentHandler, InsertHandler
+from project_database_handler import ProjectDatabaseHandler
+from system_set_handler import SystemSetHandler
+
+from general_output import GeneralOutputClass
+
+import utils
+
+class ReagentOutputClass:
+
+	# This function may be called with or without an error message
+	def printReagentInfo(self, cmd, reagent, errMsg=""):
+		
+		dbConn = DatabaseConn()
+		hostname = dbConn.getHostname()		# to define form action URL
+		
+		db = dbConn.databaseConnect()
+		cursor = db.cursor()
+		
+		gOut = GeneralOutputClass()
+
+		currUser = Session.getUser()
+		currUserID = currUser.getUserID()
+		
+		sHandler = SystemSetHandler(db, cursor)
+		pHandler = ProjectDatabaseHandler(db, cursor)
+		
+		# print menu
+		content = gOut.printHeader() + gOut.printMainMenu()
+		
+		# common to all reagent types
+		projectList = utils.unique(pHandler.findMemberProjects(currUserID, 'Writer') + pHandler.findMemberProjects(currUserID, 'Owner'))
+		
+		# Differentiate other properties by reagent type
+		if reagent.getType() == 'Insert':
+			
+			# Fetch dropdown list values to output on the form
+			iTypeList = sHandler.findAllSetValues("type of insert")
+			statusList = sHandler.findAllSetValues("status")
+			cloningMethodList = sHandler.findAllSetValues("insert cloning method")
+			fpcsList = sHandler.findAllSetValues("5' cloning site")
+			tpcsList = sHandler.findAllSetValues("3' cloning site")
+			tagTypeList = sHandler.findAllSetValues("tag")
+			tagPositionList = sHandler.findAllSetValues("tag position")
+			openClosedList = sHandler.findAllSetValues("open/closed")
+			speciesList = sHandler.findAllSetValues("species")
+			verificationList = sHandler.findAllSetValues("verification")
+		
+			# Initialize property values
+			iType = ""
+			iName = ""
+			iStatus = ""
+			cloningMethod = ""
+			projectID = ""
+			fpcs = ""
+			tpcs = ""
+			tagType = ""
+			tagPosition = ""
+			openClosed = ""
+			species = ""
+			accession = ""
+			altID = ""
+			geneID = ""
+			ensemblID = ""
+			geneSymbol = ""
+			fp_start = ""
+			tp_stop = ""
+			fwd_linker = ""
+			rev_linker = ""
+			funcDescr = ""
+			verification = ""
+			expComm = ""
+			verComm = ""
+			sequence = ""
+		
+			# Fetch POST values if available:
+			allProps = reagent.getProperties()
+			
+			if allProps.has_key("type of insert"):
+				iType = allProps["type of insert"]
+			
+			if allProps.has_key("name"):
+				iName = allProps["name"]
+				
+			if allProps.has_key("status"):
+				iStatus = allProps["status"]
+			
+			if allProps.has_key("insert cloning method"):
+				cloningMethod = allProps["insert cloning method"]
+			
+			if allProps.has_key("packet id"):
+				projectID = int(allProps["packet id"])
+				
+			if allProps.has_key("5' cloning site"):
+				fpcs = allProps["5' cloning site"]
+			
+			if allProps.has_key("3' cloning site"):
+				tpcs = allProps["3' cloning site"]
+			
+			if allProps.has_key("tag"):
+				tagType = allProps["tag"]
+			
+			if allProps.has_key("tag position"):
+				tagPosition = allProps["tag position"]
+				
+			if allProps.has_key("open/closed"):
+				openClosed = allProps["open/closed"]
+			
+			if allProps.has_key("species"):
+				species = allProps["species"]
+				
+			if allProps.has_key("accession number"):
+				accession = allProps["accession number"]
+			
+			if allProps.has_key("alternate id"):
+				altID = allProps["alternate id"]
+			
+			if allProps.has_key("entrez gene id"):
+				geneID = allProps["entrez gene id"]
+			
+			if allProps.has_key("ensembl gene id"):
+				ensemblID = allProps["ensembl gene id"]
+				
+			if allProps.has_key("official gene symbol"):
+				geneSymbol = allProps["official gene symbol"]
+				
+			if allProps.has_key("5' start"):
+				fp_start = allProps["5' start"]
+				
+			if allProps.has_key("3' stop"):
+				tp_stop = allProps["3' stop"]
+				
+			if allProps.has_key("5' linker"):
+				fwd_linker = allProps["5' linker"]
+				
+			if allProps.has_key("3' linker"):
+				rev_linker = allProps["3' linker"]
+				
+			if allProps.has_key("description"):
+				funcDescr = allProps["description"]
+				
+			if allProps.has_key("verification"):
+				verification = allProps["verification"]
+				
+			if allProps.has_key("comments"):
+				expComm = allProps["comments"]
+			
+			if allProps.has_key("verification comments"):
+				verComm = allProps["verification comments"]
+					
+			if allProps.has_key("sequence"):
+				sequence = allProps["sequence"]
+			
+			# associations
+			ipvID = ""
+			senseOligoID = ""
+			antisenseOligoID = ""
+			
+			allAssoc = reagent.getAssociations()
+			
+			'''
+			if allAssoc.has_key("insert_parent_vector"):
+				ipvID = allAssoc["insert_parent_vector"]
+			
+			if allAssoc.has_key("sense_oligo"):
+				senseOligoID = allAssoc["sense_oligo"]
+			
+			if allAssoc.has_key("antisense_oligo"):
+				antisenseOligoID = allAssoc["antisense_oligo"]
+			'''
+			
+			# Action: Output form with POST values if set
+			if cmd == 'create':
+				content += '''
+					<div class="main">
+						<form NAME="create_insert_form" ACTION="%s" METHOD="POST" onSubmit="return validateInsert() && verifyParents();">
+						'''
+	
+				content += "<INPUT type=\"hidden\" ID=\"curr_username_hidden\" NAME=\"curr_username\" value=\"" + currUser.getFullName() + "\">"
+				
+				content += '''
+							<input type="hidden" name="reagent_type_hidden" value="Insert">
+							
+							<table id="vector_insertproperty_table_id" border="1" width="780px" cellpadding="4" frame="box" rules="all">
+							'''
+				if errMsg != "":
+					content += "<th colspan=\"3\" style=\"color:#0000FF; text-align:left; font-weight:normal\">There was a problem:<br><P>" + errMsg + "<BR><BR></th>"
+
+				content += '''
+								<tr>
+									<td colspan="3" style="text-align:center">
+										<span style="color:#0000CD; font-size:13pt; font-weight:bold">
+											Insert Information
+										</span>
+										<br>
+										
+										<span style="font-size:8pt; color:#FF0000">
+										Fields marked with a red asterisk (*) are mandatory
+										</span>
+									</td>
+								</tr>
+					
+								<tr>
+									<td width="180px">
+										    Type of Insert  
+										<span style="font-size:8pt; color:#FF0000; font-weight:bold">*</span>
+									</td>
+								
+									<td width="275px">
+										<SELECT  id="itype_list" size="1" NAME="INPUT_INSERT_info_insert_type_prop">
+										'''
+				# default option
+				content += "<OPTION VALUE=\"\" "
+
+				if len(iType) == 0:
+					content += "SELECTED></OPTION>"
+				else:
+					content += "></OPTION>"
+				
+				for it in iTypeList:
+					content += "<OPTION VALUE=\"" + it + "\""
+					
+					if it == iType:
+						content += " SELECTED>" + it + "</OPTION>"
+					else:
+						content += ">" + it + "</OPTION>"
+						
+				content += '''
+										</SELECT>
+									</td>
+									
+									<td>
+										Describes the type of insert.  Users select from a pre-defined list.  Designed to make insert use more apparent and searches easier.
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    Name
+									</td>
+
+									<td>
+									'''
+									
+				content += "<INPUT type=\"text\" name=\"INPUT_INSERT_info_name_prop\" value=\"" + iName + "\">"
+				
+				content += '''
+									</td>
+									
+									<td>
+										Name that describes the reagent - free text field
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    Status
+									</td>
+					
+									<td>
+										<SELECT id="status_list" name="INPUT_INSERT_info_status_prop">
+									'''
+				# default option
+				content += "<OPTION VALUE=\"\" "
+
+				if len(iStatus) == 0:
+					content += "SELECTED></OPTION>"
+				else:
+					content += "></OPTION>"
+
+						
+				for s in statusList:
+					content += "<OPTION VALUE=\"" + s + "\""
+					
+					if s == iStatus:
+						content += " SELECTED>" + s + "</OPTION>"
+					else:
+						content += ">" + s + "</OPTION>"
+
+				content += '''	
+									</td>
+									
+									<td>
+										Indicates the status and availability of the reagent.  Users select from a pre-defined list.
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    Insert Cloning Method
+									</td>
+					
+									<td>
+										<SELECT size="1" id="cm_list" name="INPUT_INSERT_info_cloning_method_prop" onChange="showCMText()">
+									'''
+				# default option
+				content += "<OPTION VALUE=\"\" "
+
+				if len(cloningMethod) == 0:
+					content += "SELECTED></OPTION>"
+				else:
+					content += "></OPTION>"
+
+				
+				for cm in cloningMethodList:
+					content += "<OPTION VALUE=\"" + cm + "\""
+					
+					if cm == cloningMethod:
+						content += " SELECTED>" + cm + "</OPTION>"
+					else:
+						content += ">" + cm + "</OPTION>"
+
+				content += '''	
+									</td>
+									
+									<td>
+										Describes the method used to create the insert (e.g. PCR or RE (restriction enzyme)) and provides additional information for its cloning into a vector (eg. by RE, In Fusion or BP reaction)
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    Project ID  <span style="font-size:8pt; color:#FF0000; font-weight:bold">*</span>
+									</td>
+					
+									<td>
+										<select id="packetList_insert" size="1" name="INPUT_INSERT_info_packet_id_prop">
+										'''
+				# need to sort projects
+				pNums = []
+				projects = {}			# (pID, Packet)
+				
+				for p in projectList:
+					pID = p.getNumber()
+					pNums.append(pID)
+					projects[pID] = p
+				
+				pNums.sort()
+
+				for pID in pNums:
+					p = projects[pID]
+					content += "<OPTION VALUE=\"" + `p.getNumber()` + "\""
+
+					if p.getNumber() == projectID:
+						content += " SELECTED>" + `p.getNumber()` + ": " + p.getOwner().getLastName() + ": " + p.getName() + "</OPTION>"
+					else:
+						content += ">" + `p.getNumber()` + ": " + p.getOwner().getLastName() + ": " + p.getName() + "</OPTION>"
+
+				content += '''
+										</select>
+										<BR>
+										<div id="packet_warning_insert" style="display:none; color:#FF0000">Please select a Project ID from the dropdown list</div>
+									</td>
+									
+									<td>
+										Indicates what person and project originally created the reagent.
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    5' Cloning Site on Insert
+									</td>
+					
+									<td>
+										<SELECT size="1" id="fpcs_list"  name="INPUT_INSERT_info_5_prime_cloning_site_prop">
+									'''
+				# default option
+				content += "<OPTION VALUE=\"\" "
+
+				if len(fpcs) == 0:
+					content += "SELECTED></OPTION>"
+				else:
+					content += "></OPTION>"
+				
+				for fps in fpcsList:
+					content += "<OPTION VALUE=\"" + fps + "\""
+					
+					if fps == fpcs:
+						content += " SELECTED>" + fps + "</OPTION>"
+					else:
+						content += ">" + fps + "</OPTION>"
+
+				content += '''	
+									</td>
+									
+									<td>
+										Indicates what 5' site on the insert was used to clone it into a vector.  May not necessarily be the same as for the vector.  Users select from a pre-defined list.
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    3' Cloning Site on Insert
+									</td>
+					
+									<td>
+										<SELECT size="1" id="tpcs_list"  name="INPUT_INSERT_info_3_prime_cloning_site_prop">
+									'''
+				# default option
+				content += "<OPTION VALUE=\"\" "
+
+				if len(tpcs) == 0:
+					content += "SELECTED></OPTION>"
+				else:
+					content += "></OPTION>"
+				
+				for tps in tpcsList:
+					content += "<OPTION VALUE=\"" + tps + "\""
+					
+					if tps == tpcs:
+						content += " SELECTED>" + tps + "</OPTION>"
+					else:
+						content += ">" + tps + "</OPTION>"
+
+				content += '''	
+									</td>
+									
+									<td>
+										Indicates what 3' site on the insert was used to clone it into a vector.  May not necessarily be the same as for the vector.  Users select from a pre-defined list.
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    Tag
+									</td>
+					
+									<td>
+										<SELECT size="1" id="tag_list" name="INPUT_INSERT_info_tag_prop" onChange="showTagTypeBox()">
+									'''
+				# default option
+				content += "<OPTION VALUE=\"\" "
+
+				if len(tagType) == 0:
+					content += "SELECTED></OPTION>"
+				else:
+					content += "></OPTION>"
+				
+				
+				for tt in tagTypeList:
+					content += "<OPTION VALUE=\"" + tt + "\""
+					
+					if tt == tagType:
+						content += " SELECTED>" + tt + "</OPTION>"
+					else:
+						content += ">" + tt + "</OPTION>"
+
+				content += '''	
+									</td>
+									
+									<td>
+										Indicates if the insert itself has a tag associated with it (outside of the backbone vector).  Users select from a pre-defined list.
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    Tag Position
+									</td>
+					
+									<td>
+										<SELECT size="1" name="INPUT_INSERT_info_tag_position_prop">
+									'''
+				# default option
+				content += "<OPTION VALUE=\"\" "
+
+				if len(tagPosition) == 0:
+					content += "SELECTED></OPTION>"
+				else:
+					content += "></OPTION>"
+				
+				for tp in tagPositionList:
+					content += "<OPTION VALUE=\"" + tp + "\""
+					
+					if tp == tagPosition:
+						content += " SELECTED>" + tp + "</OPTION>"
+					else:
+						content += ">" + tp + "</OPTION>"
+
+				content += '''	
+									</td>
+									
+									<td>
+										Describes the position of the tag on the insert.  Users select from a pre-defined list.
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    Open/Closed
+									</td>
+					
+									<td>
+										<SELECT id="oc_list" size="1" name="INPUT_INSERT_info_open_closed_prop">
+									'''
+				# default option
+				content += "<OPTION VALUE=\"\" "
+
+				if len(openClosed) == 0:
+					content += "SELECTED></OPTION>"
+				else:
+					content += "></OPTION>"
+				
+				for oc in openClosedList:
+					content += "<OPTION VALUE=\"" + oc + "\""
+					
+					if oc == openClosed:
+						content += " SELECTED>" + oc + "</OPTION>"
+					else:
+						content += ">" + oc + "</OPTION>"
+
+				content += '''	
+									</td>
+									
+									<td>
+										Indicates for an Open Reading Frame if there is a start codon (ATG) or stop codon (open - no stop codon, closed - stop codon).
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    Species
+									</td>
+					
+									<td>
+										<SELECT  size="1" style="color:000000" id = "species_list" name="INPUT_INSERT_info_species_prop" onChange="showSpeciesBox()">
+									'''
+				# default option
+				content += "<OPTION VALUE=\"\" "
+
+				if len(species) == 0:
+					content += "SELECTED></OPTION>"
+				else:
+					content += "></OPTION>"
+				
+				for sp in speciesList:
+					content += "<OPTION VALUE=\"" + sp + "\""
+					
+					if sp == species:
+						content += " SELECTED>" + sp + "</OPTION>"
+					else:
+						content += ">" + sp + "</OPTION>"
+
+				content += '''	
+									</td>
+									
+									<td>
+										Indicates the species from which the Insert was derived.  User selects species from a pre-defined list.
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    Accession Number
+									</td>
+									
+									<td>
+									'''
+				content += "<INPUT type=\"text\" name=\"INPUT_INSERT_info_accession_number_prop\" value=\"" + accession + "\">"
+
+				content += '''
+									</td>
+									
+									<td>
+										The Accession Number from which the insert was cloned or to which the sequence maps.
+									</td>
+								</tr>
+									
+								<tr>
+									<td>
+										    Alternate ID
+									</td>
+									
+									<td>
+										<input type="checkbox" name="INPUT_INSERT_info_alternate_id_prop[]" value="IMAGE" id="_alternate_id_IMAGE_checkbox" onClick="showAltIDTextBox('_alternate_id_IMAGE_checkbox', '_alternate_id_IMAGE_textbox')">IMAGE  <INPUT style="display:none" id="_alternate_id_IMAGE_textbox" name="alternate_id_IMAGE_textbox_name" size="15"></INPUT><br>
+										
+										<input type="checkbox" name="INPUT_INSERT_info_alternate_id_prop[]" value="RIKEN" id="_alternate_id_RIKEN_checkbox" onClick="showAltIDTextBox('_alternate_id_RIKEN_checkbox', '_alternate_id_RIKEN_textbox')">RIKEN  <INPUT style="display:none" id="_alternate_id_RIKEN_textbox" name="alternate_id_RIKEN_textbox_name" size="15"></INPUT><br>
+										
+										<input type="checkbox" name="INPUT_INSERT_info_alternate_id_prop[]" value="Kazusa" id="_alternate_id_Kazusa_checkbox" onClick="showAltIDTextBox('_alternate_id_Kazusa_checkbox', '_alternate_id_Kazusa_textbox')">Kazusa  <INPUT style="display:none" id="_alternate_id_Kazusa_textbox" name="alternate_id_Kazusa_textbox_name" size="15"></INPUT><br>
+										
+										<input type="checkbox" name="INPUT_INSERT_info_alternate_id_prop[]" value="LIFESEQ" id="_alternate_id_LIFESEQ_checkbox" onClick="showAltIDTextBox('_alternate_id_LIFESEQ_checkbox', '_alternate_id_LIFESEQ_textbox')">LIFESEQ  <INPUT style="display:none" id="_alternate_id_LIFESEQ_textbox" name="alternate_id_LIFESEQ_textbox_name" size="15"></INPUT><br>
+										
+										<input type="checkbox" name="INPUT_INSERT_info_alternate_id_prop[]" value="RZPD" id="_alternate_id_RZPD_checkbox" onClick="showAltIDTextBox('_alternate_id_RZPD_checkbox', '_alternate_id_RZPD_textbox')">RZPD  <INPUT style="display:none" id="_alternate_id_RZPD_textbox" name="alternate_id_RZPD_textbox_name" size="15"></INPUT><br>
+										
+										<input type="checkbox" name="INPUT_INSERT_info_alternate_id_prop[]" value="HIP" id="_alternate_id_HIP_checkbox" onClick="showAltIDTextBox('_alternate_id_HIP_checkbox', '_alternate_id_HIP_textbox')">HIP  <INPUT style="display:none" id="_alternate_id_HIP_textbox" name="alternate_id_HIP_textbox_name" size="15"></INPUT><br>
+										
+										<input type="checkbox" name="INPUT_INSERT_info_alternate_id_prop[]" value="ADDGENE" id="_alternate_id_ADDGENE_checkbox" onClick="showAltIDTextBox('_alternate_id_ADDGENE_checkbox', '_alternate_id_ADDGENE_textbox')">ADDGENE  <INPUT style="display:none" id="_alternate_id_ADDGENE_textbox" name="alternate_id_ADDGENE_textbox_name" size="15"></INPUT><br>
+										
+										<input type="checkbox" name="INPUT_INSERT_info_alternate_id_prop[]" value="PMID" id="_alternate_id_PMID_checkbox" onClick="showAltIDTextBox('_alternate_id_PMID_checkbox', '_alternate_id_PMID_textbox')">PMID  <INPUT style="display:none" id="_alternate_id_PMID_textbox" name="alternate_id_PMID_textbox_name" size="15"></INPUT><br>
+										
+										<input type="checkbox" id="_other_Alt_ID_chkbx" name="INPUT_INSERT_info_alternate_id_prop[]" value="Other" onClick="showSpecificOtherCheckbox('_alternate_id_txt')">Other: <INPUT style="display:none" id="_alternate_id_txt" name="alternate_id_name_txt" size="15"></INPUT>
+									</td>
+								
+									<td>
+										Indicates any other ID's that identify the insert, including but not limited to IMAGE, Kazusa, RIKEN, and other.  <BR><BR><BR><BR>For 'Other', please enter the source name and ID separated by a semicolon (e.g. IMAGE:123456)
+									</td>
+								</tr>
+									
+								<tr>
+									<td>
+										    Entrez Gene ID
+									</td>
+									
+									<td>
+									'''
+
+				content += "<INPUT type=\"text\" name=\"INPUT_INSERT_info_gene_id_prop\" value=\"" + geneID + "\">"
+
+				content += '''
+									</td>
+									
+									<td>
+										The NCBI Gene ID to which the sequence maps.
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    Ensembl Gene ID
+									</td>
+									
+									<td>
+									'''
+
+				content += "<INPUT type=\"text\" name=\"INPUT_INSERT_info_ensembl_gene_id_prop\" value=\"" + ensemblID + "\">"
+
+				content += '''
+									</td>
+									
+									<td>
+										The Ensembl Gene ID to which the sequence maps.
+									</td>
+								</tr>
+							
+								<tr>
+									<td>
+										    Official Gene Symbol
+									</td>
+									
+									<td>
+									'''
+
+				content += "<INPUT type=\"text\" name=\"INPUT_INSERT_info_gene_symbol_prop\" value=\"" + geneSymbol + "\">"
+
+				content += '''
+									</td>
+									
+									<td>
+										The official gene symbol for this Insert.
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    5' Start
+									</td>
+					
+									<td>
+									'''
+
+				content += "<INPUT type=\"text\" name=\"INPUT_INSERT_info_5_prime_start_prop\" value=\"" + fp_start + "\">"
+
+				content += '''
+									</td>
+									
+									<td>
+										Users can map the start of the sequence onto its accession number by indicating at what nucleotide position on the accession number that the sequence starts.
+									</td>
+								</tr>
+							
+								<tr>
+									<td>
+										    3' Stop
+									</td>
+					
+									<td>
+									'''
+
+				content += "<INPUT type=\"text\" name=\"INPUT_INSERT_info_3_prime_stop_prop\" value=\"" + tp_stop + "\">"
+
+				content += '''
+									</td>
+									
+									<td>
+										Users can map the stop of the sequence onto its accession number by indicating at what nucleotide position on the accession number that the sequence stops
+									</td>
+								</tr>
+							
+								<tr>
+									<td>
+										    5' Linker
+									</td>
+					
+									<td>
+									'''
+
+				content += "<INPUT type=\"text\" name=\"INPUT_INSERT_info_5_prime_linker_prop\" value=\"" + fwd_linker + "\">"
+
+				content += '''
+									</td>
+									
+									<td>
+										Indicates any sequence added to the 5' end of an insert that does not map to a cDNA sequence but should be included as part of the insert - eg kozak sequences, any nucleotides added to maintain frame.
+									</td>
+								</tr>
+									
+								<tr>
+									<td>
+										    3' Linker
+									</td>
+					
+									<td>
+									'''
+
+				content += "<INPUT type=\"text\" name=\"INPUT_INSERT_info_3_prime_linker_prop\" value=\"" + rev_linker + "\">"
+
+				content += '''
+									</td>
+									
+									<td>
+										Indicates any sequence added to the 3' end of an insert that does not map to a cDNA sequence but should be included as part of the insert - eg any nucleotides added to maintain frame.
+									</td>
+								</tr>
+							
+								<tr>
+									<td>
+										    Functional Description
+									</td>
+					
+									<td>
+									'''
+
+				content += "<INPUT type=\"text\" name=\"INPUT_INSERT_info_description_prop\" value=\"" + funcDescr + "\">"
+
+				content += '''
+									</td>
+									
+									<td>
+										Describes the purpose of the reagent and any information that may be key to working with the reagent.
+									</td>
+								</tr>
+								
+								<tr>
+
+									<td>
+										    Verification
+									</td>
+					
+									<td>
+										<select size="1" name="INPUT_INSERT_info_verification_prop">
+									'''
+				# default option
+				content += "<OPTION VALUE=\"\" "
+
+				if len(verification) == 0:
+					content += "SELECTED></OPTION>"
+				else:
+					content += "></OPTION>"
+				
+				
+				for v in verificationList:
+					content += "<OPTION VALUE=\"" + v + "\""
+					
+					if v == verification:
+						content += " SELECTED>" + v + "</OPTION>"
+					else:
+						content += ">" + v + "</OPTION>"
+
+				content += '''
+										</select>
+									</td>
+									
+									<td>
+										Indicates if the reagent has been verified and how.  Users select from a pre-defined list.
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    Verification comments
+									</td>
+					
+									<td>
+									'''
+
+				content += "<INPUT type=\"text\" name=\"INPUT_INSERT_info_verification_comments_prop\" value=\"" + verComm + "\">"
+
+				content += '''
+									</td>
+									
+									<td>
+										Allows user to provide a description of the verification status - eg comments on sequence changes, expression levels.
+									</td>
+								</tr>
+								
+								<tr>
+									<td>
+										    Experimental comments
+									</td>
+					
+									<td>
+									'''
+
+				content += "<INPUT type=\"text\" name=\"INPUT_INSERT_info_comments_prop\" value=\"" + expComm + "\">"
+
+				content += '''
+									</td>
+									
+									<td>
+										Used to describe any information that descrbes how the reagent works in the experimental context - eg low expression, difficult to grow, etc.
+									</td>
+								</tr>
+									
+								<tr>
+									<td>
+										    Sequence
+									</td>
+					
+									<td>
+										 
+									</td>
+					
+									<td> 
+										The sequence of the insert that corresponds to a cDNA or fragment of interest.  Does include artificial start and stop codons.  Does not include linker sequences as described above.
+									</td>
+								</tr>
+						
+								<tr>
+									<td colspan="3">
+										<textarea rows="10" cols="93" id="dna_sequence" name="INPUT_INSERT_info_sequence_prop"> 
+										'''
+				content += sequence
+				content += '''
+										</textarea>
+									</td>
+								</tr>
+								'''
+									
+				content += self.printParents('Insert', allAssoc)
+				content += '''
+								<tr>
+									<td colspan="3">
+										<hr><br>
+										    <input type="submit" name="create_reagent" value="Create" onclick="document.pressed = this.value">
+									</td>
+								</tr>
+							</table>
+						</form>
+					</div>
+				'''
+
+			# Common to all
+			content += gOut.printFooter()
+			page_content = content % (hostname + "cgi/create.py")
+			
+			print "Content-type:text/html"		# THIS IS PERMANENT; DO NOT REMOVE
+			print					# DITTO
+			print page_content
+			
+	
+	# Output parent section based on reagent type
+	def printParents(self, rType, assocDict):
+		
+		if rType == 'Insert':
+			
+			if assocDict.has_key("insert_parent_vector"):
+				ipvID = assocDict["insert_parent_vector"]
+			
+			if assocDict.has_key("sense_oligo"):
+				senseOligoID = assocDict["sense_oligo"]
+			
+			if assocDict.has_key("antisense_oligo"):
+				antisenseOligoID = assocDict["antisense_oligo"]
+				
+			content = '''
+				<tr>
+					<td colspan="3" style="font-size:9pt; color:#0000CD; font-weight:bold; text-align:center">
+						Parent Information:
+					</td>
+				</tr>
+	
+				<tr>
+					<td>
+						    Sense Oligo ID
+					</td>
+	
+					<td>
+					'''
+			content += "<input type=\"text\" id=\"insertSenseOligo\" name=\"assoc_sense_oligo_prop\" value=\"" + senseOligoID + "\">"
+	
+			content += '''
+					</td>
+					
+					<td>
+						Link to the sense (5') oligonucleotide used to make the insert (if applicable)
+					</td>
+				</tr>
+	
+				<tr>
+					<td>
+						    AntiSense Oligo ID
+					</td>
+					
+					<td>
+					'''
+			content += "<input type=\"text\" id=\"insertAntisenseOligo\" name=\"assoc_antisense_oligo_prop\" value=\"" + antisenseOligoID + "\">"
+			
+			content += '''
+					</td>
+	
+					<td>
+						Link to the antisense (3') oligonucleotide used to make the insert (if applicable)	
+					</td>
+				</tr>
+			
+				<tr>
+					<td>
+						    Insert Parent Vector ID
+					</td>
+	
+					<td>
+					'''
+					
+			content += "<input type=\"text\" id=\"insertParentVector\" name=\"assoc_insert_parent_vector_prop\" value=\"" + ipvID + "\">"
+	
+			content += '''
+					</td>
+	
+					<td>
+						The vector that provided this insert
+					</td>
+				</tr>
+				'''
+			
+		return content
\ No newline at end of file
diff --git a/OpenFreezer/cgi/reagent_type_output.py b/OpenFreezer/cgi/reagent_type_output.py
new file mode 100755
index 0000000..7300bc8
--- /dev/null
+++ b/OpenFreezer/cgi/reagent_type_output.py
@@ -0,0 +1,2627 @@
+#!/usr/local/bin/python
+
+import cgi
+
+import os
+import sys
+import tempfile
+import stat
+
+from database_conn import DatabaseConn
+
+from reagent_handler import ReagentHandler
+from general_handler import *
+from mapper import *
+
+from reagent import Reagent
+from session import Session
+
+from general_output import GeneralOutputClass
+#from system_set_handler import SystemSetHandler
+
+from sequence import *
+
+import utils
+import urllib
+
+#############################################################################################################
+# This class handles the presentation layer of the website
+# Generates HTML content for Reagent Type views and writes it in files, which are then opened by Reagent.php
+#
+# Written April 12, 2009 by Marina Olhovsky
+# Last modified: April 12, 2009
+#############################################################################################################
+class ReagentTypeOutputClass:
+	
+	# Invoked at step 2 of Reagent Type creation - set values for new attributes
+	def printReagentTypeCreationPage(self, rTypeName, rTypePrefix, step, catDescrDict={}, categoryProps={}, parents=[], errCode=0):
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `categoryProps`
+		#print step
+		
+		#print rTypeName
+		#print rTypePrefix
+
+		rTypeName = rTypeName.replace("%", "%%")
+		
+		dbConn = DatabaseConn()
+		hostname = dbConn.getHostname()		# to define form action URL
+		root_dir = dbConn.getRootDir()
+		
+		programmer_email = dbConn.getProgrammerEmail()	# June 14, 2010
+		
+		db = dbConn.databaseConnect()
+		cursor = db.cursor()
+		
+		sHandler = SystemSetHandler(db, cursor)
+		propMapper = ReagentPropertyMapper(db, cursor)
+		rtAssocHandler = ReagentTypeAssociationHandler(db, cursor)
+		rMapper = ReagentTypeMapper(db, cursor)
+		aMapper = ReagentAssociationMapper(db, cursor)
+		
+		rtPropHandler = ReagentTypePropertyHandler(db, cursor)		# Aug. 31/09
+		
+		prop_Alias_ID_Map = propMapper.mapPropAliasID()		# (propAlias, propID) - e.g. ('insert_type', '48')
+		prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+		prop_ID_Name_Map = propMapper.mapPropIDName()		# Added March 13/08 - (prop id, prop name)
+		prop_Name_Alias_Map = propMapper.mapPropNameAlias()	# (propName, propAlias)
+		prop_Alias_Name_Map = propMapper.mapPropAliasName()	# March 18/08 - (propAlias, propName)
+		prop_Alias_Descr_Map = propMapper.mapPropAliasDescription()
+		prop_Desc_Alias_Map = propMapper.mapPropDescAlias()
+		prop_ID_Desc_Map = propMapper.mapPropIDDescription()
+		prop_ID_Alias_Map= propMapper.mapPropIDAlias()
+		prop_Name_Desc_Map = propMapper.mapPropNameDescription()
+		prop_Desc_ID_Map = propMapper.mapPropDescID()
+
+		reagentType_Name_ID_Map =  rMapper.mapTypeNameID()
+		reagentType_ID_Name_Map =  rMapper.mapTypeIDName()
+		
+		assoc_ID_ParentTypeID_Map = aMapper.mapAssocIDParentType()
+
+		prop_ID_Order_map = propMapper.mapPropIDOrdering()
+		
+		# sort categories
+		category_ID_Order_Map = propMapper.mapPropCategoryIDOrdering()
+		category_Alias_ID_Map = propMapper.mapPropCategoryAliasID()
+		category_ID_Alias_Map = propMapper.mapPropCategoryIDAlias()
+		category_ID_Name_Map = propMapper.mapPropCategoryIDName()
+		category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+		category_Name_Alias_Map = propMapper.mapPropCategoryNameAlias()
+		
+		# Dec. 9/09
+		featureDescriptors = ["tag_position", "expression_system"]
+		
+		temp_categories = {}
+		new_cats = []
+		
+		#print `category_Alias_ID_Map`
+		#print `category_ID_Order_Map`
+		
+		for catAlias in categoryProps.keys():
+			#print catAlias
+			
+			if category_Alias_ID_Map.has_key(catAlias):
+				catID = category_Alias_ID_Map[catAlias]
+				#print catID
+				if category_ID_Order_Map.has_key(catID):
+					ordering = category_ID_Order_Map[catID]
+					#print ordering
+					temp_categories[ordering] = catAlias
+			else:
+				new_cats.append(catAlias)
+				
+		#print `new_cats`
+
+		if len(temp_categories) > 0:
+			new_start = max(temp_categories.keys())
+		else:
+			# only wish to add a new category
+			new_start = sys.maxint
+		
+		#print "Content-type:text/html"
+		#print
+		#print `new_cats`
+		#print new_start
+
+		for catAlias in new_cats:
+			#print "New " + catAlias
+			ordering = new_start + 1
+			temp_categories[ordering] = catAlias
+			new_start += 1
+		
+		#temp_categories.keys().sort()		# removed Oct. 8/09 - calling 'sorted()' further down
+
+		#print `temp_categories`
+
+		rHandler = ReagentHandler(db, cursor)
+		rtHandler = ReagentTypeHandler(db, cursor)
+		pHandler = ReagentPropertyHandler(db, cursor)
+
+		currUser = Session.getUser()
+		
+		gOut = GeneralOutputClass()
+
+		content = gOut.printHeader()
+		
+		rt_alias = string.join(rTypeName.split(" "), "_")
+		mandatoryProps = ["name", "status", "packet_id", "comments", "description", rt_alias + "_type"]
+		
+		display_plus = "inline"
+		display_minus = "none"
+		
+		# Aug. 5/09: User cannot toggle between freetext and dropdown to select the format for the following properties:
+		setFormatList = [prop_Name_Alias_Map["name"], prop_Name_Alias_Map["description"], prop_Name_Alias_Map["comments"], prop_Name_Alias_Map["verification comments"], prop_Name_Alias_Map["cdna insert"], prop_Name_Alias_Map["5' linker"], prop_Name_Alias_Map["3' linker"], prop_Name_Alias_Map["5' cloning site"], prop_Name_Alias_Map["3' cloning site"], prop_Name_Alias_Map["packet id"], prop_Name_Alias_Map["sequence"], prop_Name_Alias_Map["protein sequence"], prop_Name_Alias_Map["rna sequence"],  [...]
+		
+		multipleExceptionslist = [prop_Name_Desc_Map["status"], prop_Name_Desc_Map["packet id"], prop_Name_Desc_Map["restrictions on use"], prop_Name_Desc_Map["open/closed"]]
+		
+		hyperlinkExceptionsList = [prop_Name_Desc_Map["status"], prop_Name_Desc_Map["packet id"], prop_Name_Desc_Map["accession number"], prop_Name_Desc_Map["verification"], prop_Name_Desc_Map["restrictions on use"], prop_Name_Desc_Map["developmental stage"], prop_Name_Desc_Map["tissue type"], prop_Name_Desc_Map["morphology"], prop_Name_Desc_Map["melting temperature"], prop_Name_Desc_Map["molecular weight"], prop_Name_Desc_Map["protein sequence"], prop_Name_Desc_Map["sequence"], prop_Name_Desc [...]
+		
+		# Nov. 1/09:
+		if category_Name_Alias_Map["DNA Sequence"] in categoryProps or category_Name_Alias_Map["DNA Sequence Features"] in categoryProps:
+			setFormatList.append(prop_Name_Alias_Map["restriction site"])
+			setFormatList.append(prop_Name_Alias_Map["molecular weight"])
+			setFormatList.append(prop_Name_Alias_Map["melting temperature"])
+			
+		elif category_Name_Alias_Map["Protein Sequence"] in categoryProps or category_Name_Alias_Map["Protein Sequence Features"] in categoryProps:
+			setFormatList.append(prop_Name_Alias_Map["molecular weight"])
+			setFormatList.append(prop_Name_Alias_Map["melting temperature"])
+
+		if step == 2 or step == 3:
+			
+			# Oct. 31/09: Flip the categoryProps array to have descriptions as keys and aliases as values
+			cat_props_dict_flip = {}
+
+			for catKey in categoryProps.keys():
+				
+				cat_props = categoryProps[catKey]	# dictionary
+				tmp_dict = {}
+
+				for catAlias in cat_props.keys():
+					catProp = cat_props[catAlias]
+					#print `catProp`
+					
+					tmp_dict[catProp] = catAlias
+
+					# add descriptors
+					tmp_dict["Tag Position"] = "tag_position"
+					tmp_dict["Expression System"] = "expression_system"
+
+					#cat_props_dict_flip[catProp] = catAlias
+					cat_props_dict_flip[catKey] = tmp_dict
+
+			#print `cat_props_dict_flip`
+
+		if step == 1:
+			#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+			#print					# DITTO
+			#print `categoryProps`
+
+			content += '''
+				<FORM METHOD="POST" ID="updateReagentTypeForm" ACTION="%s" onSubmit="enableCheckboxes(); return checkEmptyDropdowns('updateReagentTypeForm');">
+
+					<!-- pass current user as hidden form field -->
+					<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username"
+					'''
+					
+			content += "value=\"" + currUser.getFullName() + "\">"
+			
+			content += '''
+					<INPUT TYPE="hidden" ID=\"reagent_type_name\" NAME="reagentTypeName" VALUE=\"%s\">
+					<INPUT TYPE="hidden" ID=\"reagent_type_prefix\" NAME="reagentTypePrefix" VALUE=\"%s\">
+					
+					<INPUT TYPE="hidden" ID=\"reagent_type_modify\">
+					
+					<TABLE width="760px" cellpadding="4" cellspacing="4" border="0">
+						<TH colspan="4" style="font-size:14pt; font-weight:bold; color:#011FF0; padding-top: 10px; padding-top:5px; padding-bottom:15px;">
+							MODIFY REAGENT TYPE %s
+							<BR>
+						</TH>
+						
+						<TR>
+							<TD colspan="2" style=\"border-top:2px groove green; border-bottom:2px groove green;\">
+								<DIV style=\"padding-top:15px; padding-left:15px; padding-bottom:5px; padding-right:15px;\">
+								
+								This page allows you to:<BR>
+								<UL>
+									<LI>Modify basic reagent type information
+									<LI>Add, change or remove reagent type attributes and their values
+									<LI>Select different reagent types as parents for this reagent type.
+								</UL>
+								</DIV>
+							</TD>
+						</TR>
+		
+						<TR ID="rTypePrefixRow">
+							<TD style="text-align:justify; font-weight:bold;">
+								<BR>Reagent Type Prefix: <span style=\"color:#011FF0; font-size:13pt;\">%s</span>
+							</TD>
+						</TR>
+						'''
+				
+			if rTypeName != 'Vector' and rTypeName != 'Insert' and rTypeName != 'Oligo' and rTypeName != 'CellLine':
+				
+				content += '''
+			
+							<TR ID="rTypeAssocRow">
+								<TD style="width:65px; padding-left:8px; white-space:nowrap;">
+									<HR><BR><span style="font-weight:bold; color:blue;">Edit Reagent Type Parents:</span><BR><P>
+									'''
+	
+				content += "<TABLE style=\"font-weight:normal;\" border=\"0\">"
+				
+				content += "<TR><TD style=\"font-weight:bold;\">Parents currently assigned <BR> to reagent type " + rTypeName + ":</TD>"
+				
+				content += "<TD colspan=\"2\"> </TD><TD colspan=\"2\" style=\"font-weight:bold; white-space:nowrap;\">Other parent types available in OpenFreezer:</TD></TR>"
+				
+				content += "<TR><TD colspan=\"2\"><SELECT SIZE=\"10\" MULTIPLE style=\"margin-top:5px; margin-left:2px;\" ID=\"parentListCurr_" + `reagentType_Name_ID_Map[rTypeName]` + "\" NAME=\"add_reagent_type_parents\">"
+				
+				rTypeParents = rtAssocHandler.getReagentTypeAssociations(reagentType_Name_ID_Map[rTypeName])
+				#print `rTypeParents`
+				reagent_type_parents = []
+				
+				for assocID in rTypeParents.keys():
+					#print assocID
+					parentTypeID = rtAssocHandler.findAssocParentType(reagentType_Name_ID_Map[rTypeName], assocID)
+					#print parentTypeID
+					reagent_type_parents.append(parentTypeID)
+					
+					if rtAssocHandler.isUsedReagentTypeAssociation(reagentType_Name_ID_Map[rTypeName], parentTypeID):
+						parent_disabled = "DISABLED"
+					else:
+						parent_disabled = ""
+					
+					content += "<OPTION ID=\"" + `parentTypeID` + "\" " + parent_disabled + " VALUE=\"" + reagentType_ID_Name_Map[parentTypeID] + "\">" + reagentType_ID_Name_Map[parentTypeID] + "</OPTION>"
+				
+				content += "</SELECT></TD>"
+				
+				content += "<TD style=\"padding-right:35px;\">"
+				
+				content += "<INPUT TYPE=\"button\" VALUE=\"-->\" onClick=\"moveListElements('parentListCurr_" + `reagentType_Name_ID_Map[rTypeName]` + "', 'parentListAll_" + `reagentType_Name_ID_Map[rTypeName]` + "', false);\">"
+				
+				content += "<BR><BR><INPUT TYPE=\"button\" VALUE=\"<--\" onClick=\"moveListElements('parentListAll_" + `reagentType_Name_ID_Map[rTypeName]` + "', 'parentListCurr_" + `reagentType_Name_ID_Map[rTypeName]` + "', false);\">"
+				
+				content += "</TD>"
+				
+				#content += "<b>Other parent types available in OpenFreezer:</b><BR><BR>"
+				
+				content += "<TD><SELECT SIZE=\"10\" MULTIPLE style=\"margin-top:5px; margin-left:2px;\" ID=\"parentListAll_" + `reagentType_Name_ID_Map[rTypeName]` + "\">"
+				
+				#print `reagent_type_parents`
+				
+				for parentID in reagentType_ID_Name_Map.keys():
+					#print parentID
+					if parentID not in reagent_type_parents:
+						content += "<OPTION ID=\"" + `parentID` + "\" VALUE=\"" + reagentType_ID_Name_Map[parentID] + "\">" + reagentType_ID_Name_Map[parentID] + "</OPTION>"
+				
+				content += "</SELECT>"
+				
+				content += "</TD></TR></TABLE></TD></TR>"
+				
+			content += '''
+						<TR ID="rTypePropsRow">
+							<TD>
+								<HR><BR><SPAN STYLE=\"margin-left:4px; font-weight:bold; color:blue;\">Edit Reagent Type Properties:</span>
+								<TABLE ID="addReagentPropsTbl">
+									<TR>
+										<td colspan="4" style="padding-left:6px; padding-right:10px; font-size:10pt; font-weight:bold; padding-top:5px; white-space:nowrap;"><BR>Select properties that you wish to add, modify or delete:<BR>
+										
+											<P><DIV style=\"border:2px groove green; padding-right:15px;\">
+												<P style=\"padding-left:18px; font-weight:normal;\">- In <span style=\"color:#00B800; font-weight:bold;\"><u>green</u></span> are names of properties that <u>have already been assigned</u> to this reagent type; they may be selected for <span style=\"color:#00B800; font-weight:bold; text-decoration:underline;\">modification</span> or <span style=\"color:#00B800; font-weight:bold; text-decoration:underline;\">deletion</span>.
+											
+												<BR><P style=\"padding-left:18px; font-weight:normal;\">- In <span style=\"font-weight:bold; color:#000000;\"><u>black</u></span> are names of properties that <u>have <b>not</b> been assigned</u> to this reagent type; they will be <u><b>added</b></u> if selected.<BR>
+											
+												<P style=\"padding-left:25px; font-weight:bold; color:red;\">Properties that are NOT selected <u>will remain unchanged</u>.
+										
+												<P style=\"padding-left:25px; color:purple; font-weight:normal;  padding-top:5px;\">To change the order of properties within a category, use '<u>Check All in Use</u>' to select all the properties assigned to the reagent type in that category and update their order at step 2.
+										
+												<P><DIV style=\"font-weight:normal; font-size:10pt; padding-left:25px; padding-bottom:15px; padding-right:5px;\">
+												E.g. If 'Accession Number', 'Alternate ID' and 'Gene Symbol' are attributes assigned to this reagent type, and you wish to have them displayed in the order 'Gene Symbol', 'Accession  Number',<BR>'Alternate ID' on reagent detailed view, select all three of these properties, and on the next page, change their order values, checking to make sure that each property has a distinct order number.<BR>Properties with identical order numbers are displayed next to each other in random f [...]
+										
+												<div style=\"font-weight:normal; font-size:10pt; padding-left:25px; padding-bottom:15px; color:#FF0000; padding-right:5px;\">LeTTeRcAsE of property names CANNOT be changed by unchecking and re-entering.    If you wish to change the lettercase of a property name, please <a href=\"mailto:%s\">contact the programmer</a>.</div>
+											</DIV>
+										</td>
+									</TR>
+									'''
+
+			for rTypeID in reagentType_ID_Name_Map.keys():
+				r_type_name = reagentType_ID_Name_Map[rTypeID]
+				
+				if (r_type_name == "CellLine"):
+					r_type_name = "Cell Line"
+				
+				setFormatList.append(r_type_name + " Type")
+			
+			setFormatList.append("Type of Insert")
+			setFormatList.append("Open/Closed")
+			
+			content += '''
+						<TR>
+							<TD style=\"white-space:nowrap;\">
+							'''
+			
+			#toIgnoreProps = ['name', 'status', 'packet_id', rTypeName + '_type', 'description', 'comments', 'length', 'protein_translation']
+			
+			for categoryID in category_ID_Name_Map:
+				catAlias = category_ID_Alias_Map[categoryID]
+				category = category_ID_Name_Map[categoryID]
+				
+				if categoryID != category_Name_ID_Map['DNA Sequence'] and categoryID != category_Name_ID_Map['Protein Sequence'] and categoryID != category_Name_ID_Map['RNA Sequence'] and categoryID != category_Name_ID_Map['DNA Sequence Features'] and categoryID != category_Name_ID_Map['Protein Sequence Features'] and categoryID != category_Name_ID_Map['RNA Sequence Features']:
+					
+					content += "<P><TABLE ID=\"addReagentTypePropsTbl_" + catAlias.replace("'", "\'") + "\" style=\"white-space:nowrap; width:auto;\">"
+					
+					content += "<TR ID=\"" + catAlias.replace("'", "\'") + "_row\">"
+
+					content += "<TD style=\"font-weight:bold; padding-top:12px; color:#0000D2; white-space:nowrap;\" colspan=\"4\">"
+					
+					content += "<IMG ID=\"" + `categoryID` + "_expand_img\" SRC=\"" + hostname + "pictures/arrow_collapse.gif\" WIDTH=\"20\" HEIGHT=\"15\" BORDER=\"0\" ALT=\"plus\" class=\"menu-expanded\" style=\"display:inline;\" onClick=\"showHideCategory('" + `categoryID` + "')\">"
+					
+					content += "<IMG ID=\"" + `categoryID` + "_collapse_img\" SRC=\"" + hostname + "pictures/arrow_expand.gif\" WIDTH=\"40\" HEIGHT=\"34\" BORDER=\"0\" ALT=\"plus\" class=\"menu-collapsed\" style=\"display:none;\" onClick=\"showHideCategory('" + `categoryID` + "')\">"
+					
+					content += category
+					
+					content += '''
+									</TD>
+								</TR>
+								
+								<TR>
+									<TD style=\"white-space:nowrap;\">
+									'''
+					
+					content += "<TABLE ID=\"category_" + `categoryID` + "_section\" cellpadding=\"4\">"
+		
+					content += '''
+							<TR>
+								<TD colspan="4" style="padding-left:15px; white-space:nowrap">
+								'''
+					
+					#tmp_cat = "escape(category_descriptor_" + catAlias.replace("'", "\\'") + ")"
+					#print tmp_cat
+					tmp_cat1 = "escape(\'" + catAlias.replace("'", "\\'") + "\')"
+					
+					content += "<input type=\"hidden\" name=\"category[]\" value=\"" + catAlias.replace("'", "\\'") + "\">"
+					content += "<input type=\"hidden\" name=\"category_descriptor_" + catAlias.replace("'", "\\'") + "\" value=\"" + category + "\">"
+
+					content += "<span class=\"linkShow\" style=\"margin-left:10px;font-size:8pt; font-weight:normal;\" ID=\"checkAll\" onClick=\"checkAll(" + tmp_cat1 + ");\">Check All</span>"
+					
+					content += "<span class=\"linkShow\" style=\"margin-left:10px;font-size:8pt; font-weight:normal;\" ID=\"uncheckAll\" onClick=\"uncheckAll(" + tmp_cat1 + ", Array());\">Uncheck All</span>"
+	
+					content += "<span class=\"linkShow\" style=\"margin-left:10px;font-size:8pt; font-weight:normal;\" ID=\"checkAll\" onClick=\"checkAllExclude('" + catAlias.replace("'", "\'") + "');\">Check All in Use</span>"
+					
+					content += '''
+									</TD>
+								</TR>
+
+								<TR>
+								'''
+
+					if category_Alias_ID_Map.has_key(catAlias):
+						props = pHandler.findPropertiesByCategory(category_Alias_ID_Map[catAlias])
+					else:
+						props = []
+						
+					#print `props`
+					
+					if categoryProps.has_key(catAlias):
+						propsList = categoryProps[catAlias]
+					else:
+						propsList = []
+						
+					#print `propsList`
+					
+					# April 19/10: try ordering checkboxes - in a slightly different way; just sort by ordering column
+					ordered_props = {}
+					tmp_ord = []
+					
+					for propID in props:
+						if prop_ID_Order_map.has_key(propID):
+							tmpPropOrder = prop_ID_Order_map[propID]
+							
+							if ordered_props.has_key(tmpPropOrder):
+								tmp_ord = ordered_props[tmpPropOrder]
+							else:
+								tmp_ord = []
+							
+							tmp_ord.append(propID)
+							ordered_props[tmpPropOrder] = tmp_ord
+					
+					ordered_props.keys().sort()
+					
+					pCount = 0
+
+					for p_ord in ordered_props.keys():
+						o_props = ordered_props[p_ord]
+						
+						for propID in o_props:
+
+					#for propID in props:
+							propName = prop_ID_Name_Map[propID]
+							#print propName
+							
+							# KEEP THIS!!!!!!!!!
+							# (temporarily converting full prop name just to 'type' required!
+							if propName == rTypeName + " type":
+								propName = "type"
+							
+							propDescr = prop_ID_Desc_Map[propID]
+							propAlias = prop_ID_Alias_Map[propID]
+							
+							if propAlias in propsList:
+								#print propAlias
+								color = "#00B800"
+								
+								#if propAlias in used_props:
+									#readOnly = "DISABLED"
+							else:
+								color = "#000000"
+								content += "<INPUT TYPE=\"hidden\" NAME=\"" + catAlias.replace("'", "\'") + "_exclude[]\" VALUE=\"" + propAlias + "\">"
+								
+							toIgnore = 0
+							
+							for val in setFormatList:
+								if propName.lower() == val.lower():
+									toIgnore = 1
+									#break
+							
+							#if toIgnore == 1:
+								#continue
+	
+							if pCount%4 == 0:
+								content += "</TR><TR>"
+								
+							if propName.lower() in mandatoryProps:
+								#action = "onClick=\"this.checked = true;\""
+								action = ""
+								readOnly = "DISABLED"
+							else:
+								readOnly = ""
+								action = ""
+						
+							#print propName
+							
+							# KEEP THIS!!!!!!!!!  Now convert back to show 'type' in list!!!
+							if propName == "type":
+								propName = rTypeName + " type"
+							
+							content += "<TD style=\"padding-left:20px; white-space:nowrap;\"><INPUT TYPE=\"checkbox\" ID=\"" + catAlias.replace("'", "\'") + "_:_" + propAlias + "\" NAME=\"" + catAlias.replace("'", "\'") + "[]\" VALUE=\"" + prop_Name_Alias_Map[propName] + "\" " + action + "><SPAN style=\"color:" + color + ";\" ID=\"" + catAlias + "_:_" + prop_Name_Alias_Map[propName] + "_desc_hidden\">" + propDescr + "</SPAN></TD>"
+	
+							pCount += 1
+				
+					content += "</TR>"
+		
+					content += '''
+							<TR>
+								<td colspan="4" style="padding-left:20px; padding-top:10px; white-space:nowrap;">
+								'''
+
+					content += "<b>Add new " + category + " property:<b>  "
+					
+					content += "<INPUT type=\"text\" size=\"35\" ID=\"" + catAlias.replace("'", "\'") + "_other\" name=\"" + catAlias.replace("'", "\'") + "Other\" onKeyPress=\"return disableEnterKey(event);\">  "
+
+					content += "<input onclick=\"updateCheckboxListFromInput('" + catAlias.replace("'", "\'") + "_other', '" + catAlias.replace("'", "\'") + "', 'category_" + `categoryID` + "_section', 'updateReagentTypeForm'); document.getElementById('" + catAlias.replace("'", "\'") + "_other').focus();\" value=\"Add\" type=\"button\" style=\"font-size:10pt;\"></INPUT>"
+
+					content += '''
+									</td>
+								</TR>
+							</TABLE>
+							
+							</TD>
+						</TR>
+					</table>
+					'''
+
+			# Sequence sections
+			
+			# Find out first which of the 3 sequence types this reagent type has:
+			if categoryProps.has_key(category_Name_Alias_Map["DNA Sequence"]):
+				hasDNA = True
+				hasRNA = False
+				hasProtein = False
+				
+				dnaDisplay = "table-row"
+				dnaChecked = "checked"
+				
+				protDisplay = "none"
+				protChecked = ""
+				
+				rnaDisplay = "none"
+				rnaChecked = ""
+				
+				noneChecked = ""
+				
+				dnaSeqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], category_Name_ID_Map["DNA Sequence"])
+				
+				# Nov. 19/09: AT KAREN'S REQUEST, DISALLOW SEQUENCE TYPE CHANGE COMPLETELY
+				#if rtPropHandler.isUsedProperty(reagentType_Name_ID_Map[rTypeName], dnaSeqPropID):
+				protDisabled = "disabled"
+				rnaDisabled = "disabled"
+				dnaDisabled = ""
+				noneDisabled = "disabled"
+				#else:
+					#noneDisabled = ""
+					#protDisabled = ""
+					#rnaDisabled = ""
+					#dnaDisabled = ""
+				
+			elif categoryProps.has_key(category_Name_Alias_Map["Protein Sequence"]):
+				hasProtein = True
+				hasRNA = False
+				hasDNA = False
+				
+				protDisplay = "table-row"
+				protChecked = "checked"
+				
+				dnaDisplay = "none"
+				dnaChecked = ""
+				
+				rnaDisplay = "none"
+				rnaChecked = ""
+				
+				noneChecked = ""
+				
+				protSeqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein sequence"], category_Name_ID_Map["Protein Sequence"])
+				
+				# Nov. 19/09: AT KAREN'S REQUEST, DISALLOW SEQUENCE TYPE CHANGE COMPLETELY
+				#if rtPropHandler.isUsedProperty(reagentType_Name_ID_Map[rTypeName], protSeqPropID):
+				protDisabled = ""
+				rnaDisabled = "disabled"
+				dnaDisabled = "disabled"
+				noneDisabled = "disabled"
+				#else:
+					#noneDisabled = ""
+					#protDisabled = ""
+					#rnaDisabled = ""
+					#dnaDisabled = ""
+
+				
+				#dnaDisabled = "disabled"
+				#rnaDisabled = "disabled"
+				#protDisabled = ""
+				
+			elif categoryProps.has_key(category_Name_Alias_Map["RNA Sequence"]):
+				hasRNA = True
+				hasDNA = False
+				hasProtein = False
+				
+				rnaDisplay = "table-row"
+				rnaChecked = "checked"
+				
+				protDisplay = "none"
+				protChecked = ""
+				
+				dnaDisplay = "none"
+				dnaChecked = ""
+				
+				noneChecked = ""
+				
+				rnaSeqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["rna sequence"], category_Name_ID_Map["RNA Sequence"])
+				
+				# Nov. 19/09: AT KAREN'S REQUEST, DISALLOW SEQUENCE TYPE CHANGE COMPLETELY
+				#if rtPropHandler.isUsedProperty(reagentType_Name_ID_Map[rTypeName], rnaSeqPropID):
+				protDisabled = "disabled"
+				rnaDisabled = ""
+				dnaDisabled = "disabled"
+				noneDisabled = "disabled"
+				#else:
+					#noneDisabled = ""
+					#protDisabled = ""
+					#rnaDisabled = ""
+					#dnaDisabled = ""
+
+				
+				#dnaDisabled = "disabled"
+				#protDisabled = "disabled"
+				#rnaDisabled = ""
+				
+			else:
+				hasRNA = False
+				hasDNA = False
+				hasProtein = False
+				
+				rnaDisplay = "none"
+				rnaChecked = ""
+				
+				protDisplay = "none"
+				protChecked = ""
+				
+				dnaDisplay = "none"
+				dnaChecked = ""
+				
+				noneChecked = "checked"
+			
+				# Nov. 19/09: AT KAREN'S REQUEST, DISALLOW SEQUENCE TYPE CHANGE COMPLETELY
+				protDisabled = "disabled"
+				rnaDisabled = "disabled"
+				dnaDisabled = "disabled"
+				noneDisabled = ""
+				
+			# DNA
+			if categoryProps.has_key(category_Name_Alias_Map["DNA Sequence"]):
+				propsList = categoryProps[category_Name_Alias_Map["DNA Sequence"]]
+			
+			elif categoryProps.has_key(category_Name_Alias_Map["RNA Sequence"]):
+				propsList = categoryProps[category_Name_Alias_Map["RNA Sequence"]]
+			
+			elif categoryProps.has_key(category_Name_Alias_Map["Protein Sequence"]):
+				propsList = categoryProps[category_Name_Alias_Map["Protein Sequence"]]
+			
+			else:
+				propsList = []
+				
+			#print `propList`
+			
+			content += '''
+					<TR>
+						<TD>
+							<TABLE>
+								<TR>
+									<TD colspan="4" style="white-space:nowrap; padding-top:10px;">
+									'''
+									
+			content += "<IMG id=\"sequence_expand_img\" SRC=\"" + hostname + "pictures/arrow_collapse.gif\" WIDTH=\"20\" HEIGHT=\"15\" BORDER=\"0\" ALT=\"plus\" class=\"menu-expanded\" style=\"display:inline\" onClick=\"showHideCategory('sequence');\">"
+			
+			content += "<IMG id=\"sequence_collapse_img\" SRC=\"" + hostname + "pictures/arrow_expand.gif\" WIDTH=\"40\" HEIGHT=\"34\" BORDER=\"0\" ALT=\"plus\" class=\"menu-collapsed\" style=\"display:none\" onClick=\"showHideCategory('sequence');\">"
+
+			content += '''
+										<span style="font-weight:bold; color:#0000D2;">Sequence</span>
+							
+										<DIV ID="category_sequence_section">
+											<P><SPAN style="margin-left:25px;">Select one of the following sequence types:</SPAN><BR>
+	
+											<P>
+											'''
+
+			content += "<INPUT style=\"margin-left:25px; font-size:11pt;\" TYPE=\"radio\" ID=\"sequenceRadioNone\" NAME=\"sequenceType\" " + noneChecked + " " + noneDisabled + " onClick=\"hideSequenceSections();\">None"
+
+			content += "<INPUT style=\"margin-left:25px; font-size:11pt;\" TYPE=\"radio\" ID=\"sequenceRadioDNA\" NAME=\"sequenceType\" VALUE=\"DNA Sequence\" " + dnaChecked + " " + dnaDisabled + " onClick=\"showDNASequenceSection();\">DNA Sequence"
+			
+			content += "<INPUT style=\"margin-left:25px; font-size:11pt;\" TYPE=\"radio\" ID=\"sequenceRadioProtein\" NAME=\"sequenceType\" VALUE=\"Protein Sequence\" " + protChecked + " " + protDisabled + " onClick=\"showProteinSequenceSection();\">Protein Sequence"
+
+			content += "<INPUT style=\"margin-left:25px; font-size:11pt;\" TYPE=\"radio\" ID=\"sequenceRadioRNA\" NAME=\"sequenceType\" VALUE=\"RNA Sequence\" " + rnaChecked + " " + rnaDisabled + " onClick=\"showRNASequenceSection();\">RNA Sequence"
+
+			content += '''
+										</DIV>
+									</TD>
+								</TR>
+								'''
+
+			content += "<TR ID=\"dna_sequence_heading_row\" style=\"display:" + dnaDisplay + ";\">"
+			
+			content += '''
+									<TD colspan="4" style="padding-top:10px; white-space:nowrap; padding-left:25px;">
+									'''
+
+			content += "<BR><IMG SRC=\"" + hostname + "pictures/star_bullet.gif\" WIDTH=\"10\" HEIGHT=\"10\" BORDER=\"0\" ALT=\"bullet\" style=\"padding-right:8px; vertical-align:middle; padding-bottom:2px;\"><b>DNA Sequence</b>"
+			
+			content += '''
+										<input type="hidden" ID="dnaSequenceCategoryInput" name="category[]" value="sequence_properties">
+			
+										<input type="hidden" ID="dnaSequenceCategoryDescriptionInput" name="category_descriptor_sequence_properties" value="DNA Sequence">
+				
+										<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="checkAll" onClick="checkAll('sequence_properties');">Check All</span>
+										'''
+			
+			temp_ar = []
+			temp_ar.append(category_Name_Alias_Map["DNA Sequence"] + "_:_" + prop_Name_Alias_Map["sequence"])
+			temp_ar.append(category_Name_Alias_Map["DNA Sequence"] + "_:_" + prop_Name_Alias_Map["protein translation"])
+			
+			content += "<span class=\"linkShow\" style=\"margin-left:10px;font-size:8pt; font-weight:normal;\" ID=\"uncheckAll\" onClick=\"uncheckAll('sequence_properties', " + `temp_ar` + ");\">Uncheck All</span>"
+			
+			content += "<span class=\"linkShow\" style=\"margin-left:10px;font-size:8pt; font-weight:normal;\" ID=\"checkAll\" onClick=\"checkAllExclude('" + category_Name_Alias_Map["DNA Sequence"] + "');\">Check All in Use</span>"
+			
+			content += '''
+									</TD>
+								</TR>
+								'''
+								
+			content += "<tr ID=\"dna_sequence_props_row\" style=\"display:" + dnaDisplay + ";\">"
+			
+			content += '''
+									<TD colspan="4" style="padding-left:35px;">
+										<TABLE cellspacing="4" ID="addReagentTypeSequenceProperties">
+											<TR>
+											'''
+			pCount = 0
+
+			seqCatAlias = category_Name_Alias_Map["DNA Sequence"]
+			seqPropSet = pHandler.findPropertiesByCategory(category_Alias_ID_Map[seqCatAlias])
+			
+			if categoryProps.has_key(seqCatAlias):
+				seqPropsList = categoryProps[seqCatAlias]
+			else:
+				seqPropsList = []
+			
+			for propID in seqPropSet:	# this is propertyID, NOT propCatID!!
+				value = prop_ID_Name_Map[propID]
+				seqPropAlias = prop_ID_Alias_Map[propID]
+				
+				if pCount%4 == 0:
+					content += "</TR><TR>"
+
+				if value.lower() == "sequence" or value.lower() == "protein translation" or value.lower() == "length":
+					action = "onClick=\"this.checked = true;\""
+					readOnly = "DISABLED"
+				else:
+					readOnly = ""
+					action = ""
+					
+				if seqPropAlias in seqPropsList:
+					color = "#00B800"
+					
+					if seqPropAlias == 'length':
+						readOnly = "DISABLED"
+				else:
+					if seqPropAlias == 'length':
+						readOnly = "DISABLED"
+					
+					color = "#000000"
+					
+					content += "<INPUT TYPE=\"hidden\" NAME=\"" + seqCatAlias + "_exclude[]\" VALUE=\"" + seqPropAlias + "\">"
+				
+				content += "<TD style=\"white-space:nowrap; padding-right:10px;\"><INPUT TYPE=\"checkbox\" ID=\"" + seqCatAlias + "_:_" + seqPropAlias + "\" NAME=\"sequence_properties[]\" VALUE=\"" + seqCatAlias + "_:_" + prop_Name_Alias_Map[value.lower()] + "\" " + action + " " + readOnly + "><SPAN ID=\"" + seqCatAlias + "_:_" + prop_Name_Alias_Map[value.lower()] + "_desc_hidden\" style=\"color:" + color + ";\">" + prop_Name_Desc_Map[value.lower()] + "</SPAN></TD>"
+
+				pCount += 1
+			
+			content += '''
+											</TR>
+										</TABLE>
+									</TD>
+								</TR>
+								'''
+			
+			content += "<TR ID=\"dna_sequence_add_new_props_row\" style=\"display:" + dnaDisplay + ";\">"
+			
+			content += '''
+									<td colspan="4" style="padding-left:45px; padding-top:10px; white-space:nowrap;">
+										<b>Add new DNA sequence property:<b>  
+										<INPUT type="text" size="35" ID="seqProp_other" value="" name="seqPropOther" onKeyPress="return disableEnterKey(event);">  
+	
+										<input onclick="updateCheckboxListFromInput('seqProp_other', 'sequence_properties', 'addReagentTypeSequenceProperties', 'updateReagentTypeForm'); document.getElementById('seqProp_other').focus();" value="Add" type="button" style="font-size:10pt;"></INPUT>
+									</td>
+								</tr>
+								'''
+								
+			content += "<TR ID=\"dna_sequence_features_heading_row\" style=\"display:" + dnaDisplay + ";\">"
+			
+			content += '''
+									<TD colspan="4" style="padding-left:25px; padding-top:10px;">
+									'''
+
+			content += "<BR><IMG SRC=\"" + hostname + "pictures/star_bullet.gif\" WIDTH=\"10\" HEIGHT=\"10\" BORDER=\"0\" ALT=\"bullet\" style=\"padding-right:8px; vertical-align:middle; padding-bottom:2px;\"><b>DNA Sequence Features</b>"
+			
+			content += '''
+										<input type="hidden" ID="dnaFeaturesCategoryInput" name="category[]" value="dna_sequence_features">
+	
+										<input type="hidden" ID="dnaFeaturesCategoryDescriptorInput" name="category_descriptor_dna_sequence_features" value="DNA Sequence Features">
+				
+										<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="checkAll" onClick="checkAll('dna_sequence_features');">Check All</span>
+										<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="uncheckAll" onClick="uncheckAll('dna_sequence_features', []);">Uncheck All</span>
+										
+										<span class=\"linkShow\" style=\"margin-left:10px;font-size:8pt; font-weight:normal;\" ID=\"checkAll\" onClick=\"checkAllExclude('dna_sequence_features');\">Check All in Use</span>
+				
+										<BR><span style="font-size:9pt; padding-left:18px; font-weight:normal;">Properties that are linked to a sequence at specific positions and do not exist independently of it</span>
+									</TD>
+								</TR>
+								'''
+			
+			content += "<TR ID=\"dna_sequence_features_row\" style=\"display:" + dnaDisplay + ";\">"
+			
+			content += '''
+									<TD colspan="4" style="padding-left:35px;">
+										<P><TABLE cellspacing="4" ID="addReagentTypeFeatures">
+											<TR>
+											'''
+										
+			fCount = 0
+
+			fCatAlias = category_Name_Alias_Map["DNA Sequence Features"]
+			
+			# Get ALL features currently assigned to this reagent type
+			featureSet = pHandler.findPropertiesByCategory(category_Alias_ID_Map[fCatAlias])
+			
+			# Get the list of basic features, in case none of them have been assigned to this reagent type
+			dna_features = DNASequence.getDNASequenceFeatureNames()
+			
+			# Merge the default list with the actual assigned list
+			for df in dna_features:
+				df_id = prop_Desc_ID_Map[df]
+				
+				if not df_id in featureSet:
+					featureSet.append(df_id)
+			
+			if categoryProps.has_key(fCatAlias):
+				fList = categoryProps[fCatAlias]
+			else:
+				fList = []
+
+			dna_features_sorted = []	# list of Descriptions
+			dna_features = {}		# description, fID
+			
+			for fID in featureSet:
+				fDescr = prop_ID_Desc_Map[fID]
+				
+				dna_features_sorted.append(fDescr)
+				dna_features[fDescr] = fID
+				
+			dna_features_sorted.sort()
+			
+			for x in dna_features_sorted:
+				fID = dna_features[x]
+			
+			#for fID in featureSet:
+				fVal = prop_ID_Name_Map[fID]
+				fAlias = prop_ID_Alias_Map[fID]
+				
+				if fAlias in fList:
+					color = "#00B800"
+					#readOnly = ""
+					
+					#if fAlias == 'length':
+						#readOnly = "DISABLED"
+					#else:
+					readOnly = ""
+				else:
+					#if fAlias == 'length':
+						#readOnly = "DISABLED"
+					#else:
+					
+					color = "#000000"
+					readOnly = ""
+					
+					content += "<INPUT TYPE=\"hidden\" NAME=\"" + fCatAlias + "_exclude[]\" VALUE=\"" + fAlias + "\">"
+			
+				if fCount%4 == 0:
+					content += "</TR><TR>"
+
+				f_value = category_Name_Alias_Map["DNA Sequence Features"] + "_:_" +  prop_Name_Alias_Map[fVal.lower()]
+				#x = prop_Name_Desc_Map[fVal.lower()]
+
+				if fAlias not in featureDescriptors:
+					content += "<TD style=\"white-space:nowrap; padding-right:10px;\"><INPUT TYPE=\"checkbox\" ID=\"" + fCatAlias + "_:_" + fAlias + "\" NAME=\"dna_sequence_features[]\" VALUE=\"" + f_value + "\" " + readOnly + "><SPAN style=\"color:" + color + ";\" ID=\"" + fCatAlias + "_:_" + fAlias + "_desc_hidden\">" + x + "</SPAN></TD>"
+					fCount += 1
+
+			content += '''
+											</TR>
+											'''
+			
+			content += "<tr ID=\"dna_sequence_add_new_features_row\" style=\"display:" + dnaDisplay + ";\">"
+			
+			content += '''
+												<td colspan="4" style="padding-top:10px; white-space:nowrap;">
+													<b>Add new DNA sequence feature:<b>  
+													<INPUT type="text" size="35" ID="features_other" value="" name="featuresOther" onKeyPress="return disableEnterKey(event);">  
+				
+													<input onclick="updateCheckboxListFromInput('features_other', 'dna_sequence_features', 'addReagentTypeFeatures', 'updateReagentTypeForm'); document.getElementById('features_other').focus();" value="Add" type="button" style="font-size:10pt;"></INPUT>
+												</td>
+											</tr>
+										</TABLE>
+									</TD>
+								</TR>
+								'''
+			
+			content += "<TR ID=\"protein_sequence_heading_row\" style=\"display:" + protDisplay + ";\">"
+			
+			content += '''
+									<TD colspan="4" style="padding-left:25px; padding-top:10px; white-space:nowrap">
+									'''
+
+			# Protein
+			if categoryProps.has_key(category_Name_Alias_Map["Protein Sequence"]):
+				propsList = categoryProps[category_Name_Alias_Map["Protein Sequence"]]
+			else:
+				propsList = []
+
+			content += "<BR><IMG SRC=\"" + hostname + "pictures/star_bullet.gif\" WIDTH=\"10\" HEIGHT=\"10\" BORDER=\"0\" ALT=\"bullet\" style=\"padding-right:8px; vertical-align:middle; padding-bottom:2px;\"><b>Protein Sequence</b>"
+			
+			content += '''
+										<input type="hidden" ID="proteinSequenceCategoryInput" name="category[]" value="protein_sequence_properties">
+										
+										<input type="hidden" ID="proteinSequenceCategoryDescriptorInput" name="category_descriptor_protein_sequence_properties" value="Protein Sequence">
+										
+										<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="checkAll" onClick="checkAll('protein_sequence_properties');">Check All</span>
+										
+										<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="uncheckAll" onClick="uncheckAll('protein_sequence_properties', []);">Uncheck All</span>
+										
+										<span class=\"linkShow\" style=\"margin-left:10px;font-size:8pt; font-weight:normal;\" ID=\"checkAll\" onClick=\"checkAllExclude('protein_sequence_properties');\">Check All in Use</span>
+									<TD>
+								</TR>
+								'''
+
+			content += "<tr ID=\"protein_sequence_props_row\" style=\"display:" + protDisplay + ";\">"
+			
+			content += '''
+									<TD colspan="4" style="padding-left:25px;">
+										<P><TABLE cellspacing="4" ID="addReagentTypeProteinSequenceProperties">
+											<TR>
+											'''
+			pCount = 0
+
+			protSeqCatAlias = category_Name_Alias_Map["Protein Sequence"]
+			protSeqPropSet = pHandler.findPropertiesByCategory(category_Alias_ID_Map[protSeqCatAlias])
+			
+			for propID in protSeqPropSet:
+				value = prop_ID_Name_Map[propID]
+				propAlias = prop_ID_Alias_Map[propID]
+				
+				if propAlias in propsList:
+					color = "#00B800"
+					readOnly = ""
+					
+					if propAlias == 'length' or propAlias == 'protein_sequence':
+						readOnly = "DISABLED"
+					else:
+						readOnly = ""
+				else:
+					if propAlias == 'length':
+						readOnly = "DISABLED"
+					else:
+						color = "#000000"
+						readOnly = ""
+						
+					content += "<INPUT TYPE=\"hidden\" NAME=\"" + protSeqCatAlias + "_exclude[]\" VALUE=\"" + propAlias + "\">"
+				
+				if pCount%4 == 0:
+					content += "</TR><TR>"
+
+				protSeqPropDescr = prop_Name_Desc_Map[value.lower()]
+
+				protSeqPropVal = category_Name_Alias_Map["Protein Sequence"] + "_:_" +  prop_Name_Alias_Map[value.lower()]
+				
+				content += "<TD style=\"white-space:nowrap; padding-right:10px;\"><INPUT TYPE=\"checkbox\" ID=\"" + protSeqCatAlias + "_:_" + propAlias + "\" NAME=\"protein_sequence_properties[]\" VALUE=\"" + protSeqPropVal + "\" " + readOnly + "><SPAN style=\"color:" + color + ";\" ID=\"" + protSeqCatAlias + "_:_" + propAlias + "_desc_hidden\">" + protSeqPropDescr + "</SPAN></TD>"
+
+				pCount += 1
+
+			content += '''
+											</TR>
+										</TABLE>
+									</TD>
+								</TR>
+								'''
+			
+			content += "<tr ID=\"protein_sequence_add_new_props_row\" style=\"display:" + protDisplay + ";\">"
+			
+			content += '''		
+									<td colspan="4" style="padding-left:25px; padding-top:10px; white-space:nowrap;">
+										<b>Add new protein sequence property:<b>  
+										
+										<INPUT type="text" size="35" ID="protSeqProp_other" value="" name="protSeqPropOther" onKeyPress="return disableEnterKey(event);">  
+	
+										<input onclick="updateCheckboxListFromInput('protSeqProp_other', 'protein_sequence_properties', 'addReagentTypeProteinSequenceProperties', 'updateReagentTypeForm'); document.getElementById('protSeqProp_other').focus();" value="Add" type="button" style="font-size:10pt;"></INPUT>
+									</td>
+								</tr>
+								'''
+
+			content += "<TR ID=\"protein_sequence_features_heading_row\" style=\"display:" + protDisplay + ";\">"
+
+			content += '''
+									<TD colspan="4" style="padding-left:20px; padding-top:10px;">
+									'''
+
+			content += "<BR><IMG SRC=\"" + hostname + "pictures/star_bullet.gif\" WIDTH=\"10\" HEIGHT=\"10\" BORDER=\"0\" ALT=\"bullet\" style=\"padding-right:8px; vertical-align:middle; padding-bottom:2px;\"><b>Protein Sequence Features</b>"
+
+			content += '''
+										<input type="hidden" name="category[]" ID="proteinFeaturesCategoryInput" value="protein_sequence_features">
+	
+										<input type="hidden" ID="proteinFeaturesCategoryDescriptorInput" name="category_descriptor_protein_sequence_features" value="Protein Sequence Features">
+				
+										<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="checkAll" onClick="checkAll('protein_sequence_features');">Check All</span>
+										<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="uncheckAll" onClick="uncheckAll('protein_sequence_features', []);">Uncheck All</span>
+										
+										<span class=\"linkShow\" style=\"margin-left:10px;font-size:8pt; font-weight:normal;\" ID=\"checkAll\" onClick=\"checkAllExclude('protein_sequence_features');\">Check All in Use</span>
+				
+										<BR><span style="font-size:9pt; padding-left:18px; font-weight:normal;">Properties that are linked to a sequence at specific positions and do not exist independently of it</span>
+									</TD>
+								</TR>
+								'''
+			
+			content += "<TR ID=\"protein_sequence_features_row\" style=\"display:" + protDisplay + ";\">"
+			
+			content += '''
+									<TD colspan="4" style="padding-left:25px;">
+										<P><TABLE cellspacing="4" ID="addReagentTypeProteinFeatures">
+											<TR>
+											'''
+			pCount = 0
+			
+			pfCatAlias = category_Name_Alias_Map["Protein Sequence Features"]
+			protFeatureSet = pHandler.findPropertiesByCategory(category_Alias_ID_Map[pfCatAlias])
+
+			prot_features = ProteinSequence.getProteinSequenceFeatureNames()
+			
+			for pf in prot_features:
+				pf_id = prop_Desc_ID_Map[pf]
+				
+				if not pf_id in protFeatureSet:
+					protFeatureSet.append(pf_id)
+
+			if categoryProps.has_key(pfCatAlias):
+				featuresList = categoryProps[pfCatAlias]
+			else:
+				featuresList = []
+			
+			#print `featuresList`
+			
+			prot_features_sorted = []	# list of Descriptions
+			prot_features = {}		# description, Feature
+			
+			# Flip the dictionary to sort alphabetically
+			for fID in protFeatureSet:
+				fDescr = prop_ID_Desc_Map[fID]
+				prot_features_sorted.append(fDescr)
+				prot_features[fDescr] = fID
+				
+			prot_features_sorted.sort()
+			
+			for z in prot_features_sorted:
+				pfID = prot_features[z]
+			
+			#for pfID in protFeatureSet:
+				pfValue = prop_ID_Name_Map[pfID]
+				pfAlias = prop_ID_Alias_Map[pfID]
+				
+				if pfAlias in featuresList:
+					color = "#00B800"
+				else:
+					color = "#000000"
+					
+					content += "<INPUT TYPE=\"hidden\" NAME=\"" + pfCatAlias + "_exclude[]\" VALUE=\"" + pfAlias + "\">"
+				
+				if pCount%4 == 0:
+					content += "</TR><TR>"
+				
+				protFeatureValue = category_Name_Alias_Map["Protein Sequence Features"] + "_:_" +  prop_Name_Alias_Map[pfValue.lower()]
+				
+				#z = prop_Name_Desc_Map[pfValue.lower()]
+				
+				content += "<TD style=\"white-space:nowrap; padding-right:10px;\"><INPUT TYPE=\"checkbox\" ID=\"" + pfCatAlias + "_:_" + pfAlias + "\" NAME=\"protein_sequence_features[]\" VALUE=\"" + protFeatureValue + "\"><SPAN style=\"color:" + color + ";\" ID=\"" + pfCatAlias + "_:_" + pfAlias + "_desc_hidden\">" + z + "</SPAN></TD>"
+
+				pCount += 1
+
+			content += '''
+											</TR>
+										</TABLE>
+									</TD>
+								</TR>
+								'''
+			
+			content += "<tr ID=\"protein_sequence_add_new_features_row\" style=\"display:" + protDisplay + ";\">"
+			
+			content += '''
+									<td colspan="4" style="padding-left:25px; padding-top:10px; white-space:nowrap;">
+										<b>Add new Protein sequence feature:<b>  
+										<INPUT type="text" size="35" ID="protein_features_other" value="" name="proteinFeaturesOther" onKeyPress="return disableEnterKey(event);">  
+										<input onclick="updateCheckboxListFromInput('protein_features_other', 'protein_sequence_features', 'addReagentTypeProteinFeatures', 'updateReagentTypeForm'); document.getElementById('protein_features_other').focus();" value="Add" type="button" style="font-size:10pt;"></INPUT>
+									</td>
+								</tr>
+								'''
+			
+			content += "<TR ID=\"rna_sequence_heading_row\" style=\"display:" + rnaDisplay + ";\">"
+			
+			content += '''
+									<TD colspan="4" style="padding-left:20px; padding-top:10px; white-space:nowrap">
+									'''
+
+			content += "<BR><IMG SRC=\"" + hostname + "pictures/star_bullet.gif\" WIDTH=\"10\" HEIGHT=\"10\" BORDER=\"0\" ALT=\"bullet\" style=\"padding-right:8px; vertical-align:middle; padding-bottom:2px;\"><b>RNA Sequence</b>"
+			content += '''	
+										<input type="hidden" name="category[]" ID="rnaSequenceCategoryInput" value="rna_sequence_properties">
+										
+										<input type="hidden" ID="rnaSequenceCategoryDescriptorInput" name="category_descriptor_rna_sequence_properties" value="RNA Sequence">
+										<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="checkAll" onClick="checkAll('rna_sequence_properties');">Check All</span>
+										
+										<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="uncheckAll" onClick="uncheckAll('rna_sequence_properties', []);">Uncheck All</span>
+										
+										<span class=\"linkShow\" style=\"margin-left:10px;font-size:8pt; font-weight:normal;\" ID=\"checkAll\" onClick=\"checkAllExclude('rna_sequence_properties');\">Check All in Use</span>
+									</TD>
+								</TR>
+								'''
+			
+			content += "<tr ID=\"rna_sequence_props_row\" style=\"display:" + rnaDisplay + ";\">"
+			
+			content += '''
+									<TD colspan="4" style="padding-left:25px;">
+										<P><TABLE cellspacing="4" ID="addReagentTypeRNASequenceProperties">
+											<TR>
+											'''
+			pCount = 0
+
+			rnaSeqCatAlias = category_Name_Alias_Map["RNA Sequence"]
+			rnaSeqPropSet = pHandler.findPropertiesByCategory(category_Alias_ID_Map[rnaSeqCatAlias])
+
+			# nov. 1/09
+			if categoryProps.has_key(rnaSeqCatAlias):
+				featuresList = categoryProps[rnaSeqCatAlias]
+			else:
+				featuresList = []
+
+			for propID in rnaSeqPropSet:
+				value = prop_ID_Name_Map[propID]
+				fAlias = prop_ID_Alias_Map[propID]
+
+				if fAlias == "rna_sequence" or fAlias == "length":
+					readonly = "DISABLED"
+				else:
+					readonly = ""
+
+				# nov 1/09: show used attributes in green
+				if fAlias in featuresList:
+					color = "#00B800"
+					
+					if fAlias == 'length':
+						readOnly = "DISABLED"
+				else:
+					color = "#000000"
+					
+					if fAlias == 'length':
+						readOnly = "DISABLED"
+					
+					content += "<INPUT TYPE=\"hidden\" NAME=\"" + rnaSeqCatAlias + "_exclude[]\" VALUE=\"" + fAlias + "\">"
+				
+				if pCount%4 == 0:
+					content += "</TR><TR>"
+
+				seqPropDescr = prop_Name_Desc_Map[value.lower()]
+
+				rnaSeqProp = category_Name_Alias_Map["RNA Sequence"] + "_:_" + prop_Name_Alias_Map[value.lower()]
+				seqPropDescr = prop_Name_Desc_Map[value.lower()]
+
+				content += "<TD style=\"white-space:nowrap; padding-right:10px;\"><INPUT TYPE=\"checkbox\" ID=\"" + rnaSeqCatAlias + "_:_" + fAlias + "\" NAME=\"rna_sequence_properties[]\" VALUE=\"" + rnaSeqProp + "\" " + readonly + "><SPAN style=\"color:" + color + ";\" ID=\"" + rnaSeqCatAlias + "_:_" + fAlias + "_desc_hidden\">" + seqPropDescr + "</SPAN></TD>"
+
+				pCount += 1
+
+			content += '''
+											</TR>
+										</TABLE>
+									</TD>
+								</TR>
+								'''
+			
+			content += "<tr ID=\"rna_sequence_add_new_props_row\" style=\"display:" + rnaDisplay + ";\">"
+			
+			content += '''
+									<td colspan="4" style="padding-left:25px; padding-top:10px; white-space:nowrap;">
+										<b>Add new RNA sequence property:<b>  
+										<INPUT type="text" size="35" ID="rnaSeqProp_other" value="" name="rnaSeqPropOther" onKeyPress="return disableEnterKey(event);">  
+										<input onclick="updateCheckboxListFromInput('rnaSeqProp_other', 'rna_sequence_properties', 'addReagentTypeRNASequenceProperties', 'updateReagentTypeForm'); document.getElementById('rnaSeqProp_other').focus();" value="Add" type="button" style="font-size:10pt;"></INPUT>
+									</td>
+								</tr>
+								'''
+			
+			content += "<TR ID=\"rna_sequence_features_heading_row\" style=\"display:" + rnaDisplay + ";\">"
+			
+			content += '''
+									<TD colspan="4" style="padding-left:20px; padding-top:10px;">
+									'''
+			
+			content += "<BR><IMG SRC=\"" + hostname + "pictures/star_bullet.gif\" WIDTH=\"10\" HEIGHT=\"10\" BORDER=\"0\" ALT=\"bullet\" style=\"padding-right:8px; vertical-align:middle; padding-bottom:2px;\"><b>RNA Sequence Features</b>"
+			
+			content += '''
+										<input type="hidden" name="category[]" ID="rnaFeaturesCategoryInput" value="rna_sequence_features">
+	
+										<input type="hidden" ID="rnaFeaturesCategoryDescriptorInput" name="category_descriptor_rna_sequence_features" value="RNA Sequence Features">
+				
+										<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="checkAll" onClick="checkAll('rna_sequence_features');">Check All</span>
+										<span class="linkShow" style="margin-left:10px;font-size:8pt; font-weight:normal;" ID="uncheckAll" onClick="uncheckAll('rna_sequence_features', []);">Uncheck All</span>
+										
+										<span class=\"linkShow\" style=\"margin-left:10px;font-size:8pt; font-weight:normal;\" ID=\"checkAll\" onClick=\"checkAllExclude('rna_sequence_features');\">Check All in Use</span>
+				
+										<BR><span style="font-size:9pt; padding-left:18px; font-weight:normal;">Properties that are linked to a sequence at specific positions and do not exist independently of it</span>
+									</TD>
+								</TR>
+								'''
+			
+			content += "<TR ID=\"rna_sequence_features_row\" style=\"display:" + rnaDisplay + ";\">"
+			
+			content += '''
+									<TD colspan="4" style="padding-left:25px;">
+										<P><TABLE cellspacing="4" ID="addReagentTypeRNAFeatures">
+											<TR>
+											'''
+			pCount = 0
+
+			rnaFeaturesCatAlias = category_Name_Alias_Map["RNA Sequence Features"]
+			rnaFeatureSet = pHandler.findPropertiesByCategory(category_Alias_ID_Map[rnaFeaturesCatAlias])
+
+			rna_features = RNASequence.getRNASequenceFeatureNames()
+			
+			for rf in rna_features:
+				rf_id = prop_Desc_ID_Map[rf]
+				
+				if not rf_id in rnaFeatureSet:
+					rnaFeatureSet.append(rf_id)
+
+			# nov. 1/09
+			if categoryProps.has_key(rnaFeaturesCatAlias):
+				featuresList = categoryProps[rnaFeaturesCatAlias]
+			else:
+				featuresList = []
+			
+			rna_features_sorted = []	# list of Descriptions
+			rna_features = {}		# description, Feature
+			
+			# Flip the dictionary to sort alphabetically
+			for fID in rnaFeatureSet:
+				fDescr = prop_ID_Desc_Map[fID]
+				rna_features_sorted.append(fDescr)
+				rna_features[fDescr] = fID
+				
+			rna_features_sorted.sort()
+			
+			for z in rna_features_sorted:
+				fID = rna_features[z]
+			
+			#for fID in rnaFeatureSet:
+				fValue = prop_ID_Name_Map[fID]
+				pfAlias = prop_ID_Alias_Map[fID]
+				
+				#print pfAlias
+
+				if pfAlias in featuresList:
+					color = "#00B800"
+					
+					if pfAlias == 'length':
+						readOnly = "DISABLED"
+				else:
+					color = "#000000"
+					
+					if pfAlias == 'length':
+						readOnly = "DISABLED"
+					
+					content += "<INPUT TYPE=\"hidden\" NAME=\"" + rnaFeaturesCatAlias + "_exclude[]\" VALUE=\"" + pfAlias + "\">"
+
+				if pCount%4 == 0:
+					content += "</TR><TR>"
+
+				fProp = category_Name_Alias_Map["RNA Sequence Features"] + "_:_" +  prop_Name_Alias_Map[fValue.lower()]
+				
+				z = prop_Name_Desc_Map[fValue.lower()]
+
+				content += "<TD style=\"white-space:nowrap; padding-right:10px;\"><INPUT TYPE=\"checkbox\" ID=\"" + rnaFeaturesCatAlias + "_:_" + pfAlias + "\" NAME=\"rna_sequence_features[]\" VALUE=\"" + fProp + "\"><SPAN style=\"color:" + color + ";\" ID=\"" + rnaFeaturesCatAlias + "_:_" + pfAlias + "_desc_hidden\">" + z + "</SPAN></TD>"
+
+				pCount += 1
+
+			content += '''
+											</TR>
+										</TABLE>
+									</TD>
+								</TR>
+								'''
+			
+			content += "<tr ID=\"rna_sequence_add_new_features_row\" style=\"display:" + rnaDisplay + ";\">"
+			
+			content += '''
+									<td colspan="4" style="padding-left:25px; padding-top:10px; white-space:nowrap;">
+										<b>Add new RNA sequence feature:<b>  
+										<INPUT type="text" size="35" ID="rna_features_other" value="" name="rnaFeaturesOther" onKeyPress="return disableEnterKey(event);">  
+	
+										<input onclick="updateCheckboxListFromInput('rna_features_other', 'rna_sequence_features', 'addReagentTypeRNAFeatures', 'updateReagentTypeForm'); document.getElementById('rna_features_other').focus();" value="Add" type="button" style="font-size:10pt;"></INPUT>
+									</td>
+								</tr>
+							</TABLE>
+						</TD>
+					</TR>
+					'''
+
+			content += '''
+					<TR ID="addCategoryRow">
+						<TD style="padding-top:10px; white-space:nowrap; padding-left:38px; font-weight:bold;">
+							<P><HR><BR>If the property you wish to add does not fit any of the above categories, please add your own category:<BR>
+							<P><INPUT type="text" size="35" ID="new_category" value="" name="newCategory" onKeyPress="return disableEnterKey(event);">  
+	
+							<input onclick="addPropertiesCategory('new_category', 'addReagentPropsTbl', 'addCategoryRow', 'updateReagentTypeForm');" value="Add" type="button" style="font-size:10pt;"></INPUT><BR><HR>
+						</TD>
+					</TR>
+					
+					<TR>
+						<TD>
+							<INPUT TYPE="hidden" name="step" value="1">
+							'''
+							
+			content += "<P><INPUT TYPE=\"submit\" name=\"save_rtype\" value=\"Update Selected Properties\" style=\"margin-left:25px; font-size:10pt;\" onClick=\"selectAllPropertyValues(true); enableParents('parentListCurr_" + `reagentType_Name_ID_Map[rTypeName]` + "'); collectReagentTypeProperties('updateReagentTypeForm');\">"
+			
+			content += '''
+								   <INPUT TYPE="submit" name="cancel_rtype_modify" value="Cancel" onClick="document.pressed='Cancel'; return confirm('Cancel reagent type modification?');" style="font-size:10pt;">
+							</TD>
+						</TR>
+					</TABLE>
+					
+					</TD></TR></table>	<!-- keep this!!! -->
+				</FORM>
+				'''
+			
+			content += gOut.printFooter()
+			
+			# Oct. 7/09: don't make reagent type name uppercase (e.g. 'RNAi')
+			page_content = content % (hostname + "cgi/reagent_type_request_handler.py", rTypeName, rTypePrefix,  rTypeName, rTypePrefix, programmer_email)
+	
+			print "Content-type:text/html"		# THIS IS PERMANENT!
+			print					# DITTO
+			print page_content
+
+		else:
+			if step == 2:
+				content += '''
+					<FORM METHOD="POST" ID="saveAttributeValuesForm" ACTION="%s" onSubmit="return checkEmptyDropdowns('saveAttributeValuesForm');">
+	
+						<!-- pass current user as hidden form field -->
+						<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username"'''
+						
+				content += "value=\"" + currUser.getFullName() + "\">"
+				
+				content += '''
+						<INPUT TYPE="hidden" NAME="reagentTypeName" VALUE=\"%s\">
+						<INPUT TYPE="hidden" NAME="reagentTypePrefix" VALUE=\"%s\">
+						
+						<TABLE width="760px" cellpadding="4" cellspacing="4">
+							<TR>
+								<TD colspan=\"4\">
+									<TABLE>
+										<TR>
+											<TH colspan="4" style="font-size:14pt; font-weight:bold; color:#011FF0; padding-top: 10px; padding-top:5px; padding-left:185px;">
+												ADD NEW REAGENT TYPE
+												
+												<BR><CENTER><SPAN style="font-size:10pt; color:gray; text-align:center; font-weight:bold; white-space:nowrap; padding-top:5px;">Step 2 - Set Attribute Values</SPAN></CENTER>
+											</TH>
+										</TR>
+										
+										<TR><TD></TD></TR>
+									</TABLE>
+								</TD>
+							</TR>
+							
+							<TR>
+								<TD style="padding-left:25px;">
+									<DIV style="padding-left:15px; padding-right:15px; border:3px groove green;">
+										<P><span style="color:brown;">For each of the <u><b>new</b></u> properties introduced for reagent type <b>%s</b>, please define its input format:</SPAN><BR>
+										
+										<UL style="padding-left:15px; padding-right:15px;">
+											<LI>You can either define a set of property values to be shown as a dropdown list (for properties with a limited set of defined values), or leave the input field as free text (for more disparate entries).<BR><BR>
+			
+											<LI>Name, Description and Comments are always entered as free text.  Project IDs are selected from a dropdown list (please refer to the "Project Management" module documentation).<BR><BR>
+										
+											<LI>External identifiers, such as Accession Number, Ensembl Gene and Transcript IDs, Entrez Gene ID, Gene Symbol are always entered as free text and displayed as a hyperlink to the corresponding external database.<BR><BR>
+											
+											<LI>Sequence Features are regions at specific positions on a sequence that do not exist independently of it.  They are always selected from a pre-defined list.  Cloning and Restriction sites are provided by the standard REBASE enzyme set.  Other feature value lists (polyA, tag, intron) may be customized.<BR><BR>
+										
+											<LI>cDNA is always defined in terms of its start and end positions on a DNA sequence.  It is the region of a DNA sequence that gets translated to protein.<BR><BR>
+											
+											<LI>Molecular Weight and Melting Temperature are automatically calculated for Oligos; for other sequence types they are entered as free text.<BR><BR>
+										
+											<!-- April 28, 2010: Add option to have multiple values for this property -->
+											<LI>Normally, when reagents are created, only one value can be assigned to each property (e.g. a reagent may only have a single Status or Accession Number).  However, in some cases assignment of multiple values to a property may be required, such as tracking an antibody that has multiple recognition species.  You may indicate that an attribute can potentially have multiple values by checking the "Multiple" checkbox under the corresponding property name.  When you create reagen [...]
+										</UL>
+									</DIV>
+								</TD>
+							</TR>
+							'''
+							
+							#<TR>
+								#<TD style="border: 1px groove black; padding:7px; text-align:justify;">
+									#<u><b>Please note</b></u>: The term <b>'Sequence Features'</b> refers to <u>regions at specific positions</u> on a sequence in forward or reverse orientation (e.g. PolyA Tail, Tag, Selectable Marker).  Their values <b>are always selected from a pre-defined list.</b>  Properties that describe the entire sequence rather than portions of it should be stored under a different category (e.g. 'Annotations' or 'Classifiers').
+								#</TD>
+							#</TR>
+			else:
+				content += '''
+					<FORM METHOD="POST" ID="saveAttributeValuesForm" ACTION="%s" onSubmit="return checkEmptyDropdowns('saveAttributeValuesForm');">
+	
+						<!-- pass current user as hidden form field -->
+						<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username"'''
+						
+				content += "value=\"" + currUser.getFullName() + "\">"
+
+				# Dec. 11/09: pass hidden reagent type to JS
+				content += "<INPUT type=\"hidden\" ID=\"reagent_type_name\" VALUE=\"" + rTypeName + "\">"
+				
+				content += '''
+						<INPUT TYPE="hidden" NAME="reagentTypeName" VALUE=\"%s\">
+						<INPUT TYPE="hidden" NAME="reagentTypePrefix" VALUE=\"%s\">
+						
+						<TABLE width="760px" cellpadding="4" cellspacing="4">
+							<TR>
+								<TD colspan=\"4\">
+									<TABLE>
+										<TR>
+											<TH colspan="4" style="font-size:14pt; font-weight:bold; color:#011FF0; padding-top: 10px; padding-top:5px; padding-left:185px;">
+												UPDATE REAGENT TYPE
+												'''
+				content += rTypeName
+				
+				content += '''
+												
+												<BR><CENTER><SPAN style="font-size:10pt; color:gray; text-align:center; font-weight:bold; white-space:nowrap; padding-top:5px;">Step 2 - Edit Attribute Values</SPAN></CENTER>
+											</TH>
+										</TR>
+										
+										<TR><TD></TD></TR>
+									</TABLE>
+								</TD>
+							</TR>
+							
+							<TR>
+								<TD>
+									<BR>For each of the <u><b>new</b></u> properties introduced for reagent type <b>%s</b>, please define its input format:<BR>
+									
+									<P>You can either define a set of property values to appear as a dropdown list (for properties with more than one value), or leave the input field as free-text (for single-valued properties).<BR>
+	
+									<P>E.g. The 'Name' field would always be a text field, whereas 'Cloning Sites' are selected from a pre-defined list of values.
+								</TD>
+							</TR>
+							
+							<TR>
+								<TD style="border: 1px groove black; padding:7px; text-align:justify;">
+									<u><b>Please note</b></u>: The term <b>'Sequence Features'</b> refers to <u>regions at specific positions</u> on a sequence in forward or reverse orientation (e.g. PolyA Tail, Tag, Selectable Marker).  Their values <b>are always selected from a pre-defined list.</b>  Properties that describe the entire sequence rather than portions of it should be stored under a different category (e.g. 'Annotations' or 'Classifiers').
+								</TD>
+							</TR>
+							'''
+			#print "Content-type:text/html"
+			#print
+			#print `categoryProps`
+			#print `temp_categories`
+			
+			# Nov. 30/09: What about novel categories??
+			
+			# Change Aug. 4/09: output categories in order - Oct. 8/09: USE sorted()
+			for categoryOrder in sorted(temp_categories.keys()):
+				catAlias = temp_categories[categoryOrder]
+				#print catAlias
+				
+				# Update June 17/09: for novel categories, add check 'if exists in alias map', get error otherwise
+				if category_Alias_ID_Map.has_key(catAlias):
+					categoryID = category_Alias_ID_Map[catAlias]
+					currCategoryProps = pHandler.findPropertiesByCategory(category_Alias_ID_Map[catAlias])	# moved here Nov. 16/09
+				else:
+					categoryID = -1
+					currCategoryProps = []
+				
+				content += "<INPUT TYPE=\"hidden\" NAME=\"category[]\" VALUE=\"" + catAlias.replace("'", "\'") + "\">"
+				content += "<INPUT TYPE=\"hidden\" NAME=\"categoryID[]\" VALUE=\"" + `categoryID` + "\">"
+				content += "<input type=\"hidden\" name=\"category_descriptor_" + catAlias.replace("'", "\'") + "\" value=\"" + catDescrDict[catAlias] + "\">"
+				
+				propsList = categoryProps[catAlias]
+				#print `propsList`
+
+				# nov. 1/09: add descriptors
+				if propsList.has_key("tag") and not propsList.has_key("tag_position"):
+					propsList["tag_position"] = "Tag Position"
+					tmp_list = {}
+					tmp_list["tag_position"] = "Tag Position"
+					categoryProps[catAlias] = tmp_list
+				
+				if propsList.has_key("promoter") and not propsList.has_key("expression_system"):
+					propsList["expression_system"] = "Expression System"
+					tmp_list = {}
+					tmp_list["expression_system"] = "Expression System"
+					categoryProps[catAlias] = tmp_list
+
+				rTypePropSorted = {}		# order => [list of props]
+
+				for pAlias in propsList.keys():
+					#print pAlias
+					
+					## oct. 31/09: no, look by description
+					#propID = pHandler.findPropIDByDescription(propsList[pAlias])
+
+					if prop_Alias_ID_Map.has_key(pAlias):
+						propID = prop_Alias_ID_Map[pAlias]
+					else:
+						propID = -1
+					
+					pName = propsList[pAlias]
+					#print propID
+					#print pName
+					
+					# Change April 14, 2010: property ordering is now linked to a specific property within a specific category for a specific reagent, i.e. it is now a column in ReagentTypeAttributes_tbl and is associated with ReagentPropertyCategories_tbl.propCatID as opposed to ReagentPropType_tbl.propertyID
+					if reagentType_Name_ID_Map.has_key(rTypeName):
+						rTypeID = reagentType_Name_ID_Map[rTypeName]
+						tmpPropID = pHandler.findReagentPropertyInCategoryID(propID, categoryID)
+						#print tmpPropID
+						
+						if rTypeID and rTypeID > 0 and tmpPropID and tmpPropID > 0:
+							pOrder = rtPropHandler.getReagentTypePropertyOrdering(rTypeID, tmpPropID)
+						else:
+							#pOrder = sys.maxint
+							pOrder = len(propsList)
+							#print pOrder
+					else:
+						#pOrder = sys.maxint
+						pOrder = len(propsList)
+					
+					#print pOrder
+	
+					if rTypePropSorted.has_key(pOrder):
+						tmp_order_list = rTypePropSorted[pOrder]
+						# don't do any more sorting here!
+					else:
+						tmp_order_list = []
+	
+					tmp_order_list.append(pName)
+					rTypePropSorted[pOrder] = tmp_order_list
+				
+				rTypePropSorted.keys().sort()
+				#print `rTypePropSorted`
+				
+				#print "Category " + catAlias + ", props " + `propsList`
+				#print `ignoreList`
+				#print `propsList`
+				#print `propsList.keys()`
+
+				# oct. 31/09
+				propDescID_list = {}
+				
+				# June 26/09: Output by categories - Repetitive code but the most robust way to determine unique new category headings
+				for pAlias in propsList.keys():
+					#print "after: " + pAlias
+					pName = propsList[pAlias]
+					#print pName
+					
+					# try to find propID from description
+					tmpPropID = pHandler.findPropIDByDescription(pName, True)
+					#print tmpPropID
+
+					propDescID_list[pName] = tmpPropID	# oct. 31/09
+				
+					#if (tmpPropID < 0) or (catAlias not in category_Alias_ID_Map.keys()) or (category_Alias_ID_Map.has_key(catAlias) and tmpPropID > 0 and not pHandler.existsPropertyInCategory(tmpPropID, category_Alias_ID_Map[catAlias])):
+					content += "<TR>"
+					content += "<TD style=\"font-weight:bold; color:#0000D2; padding-top:25px; padding-left:15px; white-space:nowrap;\">"
+					
+					#content += "<IMG SRC=\"" + hostname + "pictures/star_bullet.gif\" WIDTH=\"10\" HEIGHT=\"10\" BORDER=\"0\" ALT=\"bullet\"  style=\"padding-right:8px; vertical-align:middle; padding-bottom:2px;\">"
+					
+					# Aug. 10/09: Make collapsible sections
+					#if categoryID == 1:
+					display_plus = "inline"
+					display_minus = "none"
+					#else:
+						#display_plus = "none"
+						#display_minus = "inline"
+					
+					content += "<IMG id=\"" + `categoryID` + "_expand_img\" SRC=\"" + hostname + "pictures/arrow_collapse.gif\" WIDTH=\"20\" HEIGHT=\"15\" BORDER=\"0\" ALT=\"plus\" class=\"menu-expanded\" style=\"display:" + display_plus + "\" onClick=\"showHideCategory('" + `categoryID` + "');\">"
+
+					content += "<IMG id=\"" + `categoryID` + "_collapse_img\" SRC=\"" + hostname + "pictures/arrow_expand.gif\" WIDTH=\"40\" HEIGHT=\"34\" BORDER=\"0\" ALT=\"plus\" class=\"menu-collapsed\" style=\"display:" + display_minus + "\" onClick=\"showHideCategory('" + `categoryID` + "');\">"
+
+					content += catDescrDict[catAlias]
+					
+					content += "</TD>"
+					content += "</TR>"
+					break		# need here to only print category names once
+				
+				# Aug. 10/09: make collapsible
+				content += "<TR>"
+				content += "<TD ID=\"category_" + `categoryID` + "_section\" style=\"display:" + display_plus + "\" style=\"padding-left:35px;\">"
+				content += "<TABLE style=\"background-color:#F5F5DC; width:750px; margin-left:35px; padding:6px;\" cellspacing=\"2\">"
+				
+				for pOrd in rTypePropSorted.keys():
+					pNames = rTypePropSorted[pOrd]		# these are in fact DESCRIPTIONS, user input!
+					#print `pNames`
+					
+					for pName in pNames:
+						#print pName
+						
+						# Oct. 31/09: LOOK BY DESCRIPTION, DON'T RELY ON MAPS HERE!!!!!!
+						pAlias = cat_props_dict_flip[catAlias][pName]
+						#pAlias = cat_props_dict_flip[pName]
+						#print pAlias
+						
+						if pAlias == rTypeName + " Type":
+							pAlias = rTypeName + "_type"
+						
+						tmp_val = (catAlias + "_:_" + pAlias).replace("%", "%%")
+						#print tmp_val
+						
+						# pass ALL properties through form, BUT on the property values input page print only NEW ones
+						# REMOVED Feb. 8/10 - deletes the wrong field!!
+						#content += "<input type=\"hidden\" ID=\"" + tmp_val + "_input\" name=\"" + catAlias.replace("'", "\'") + "[]\" value=\"" + pAlias + "\">"
+						
+						## Nov. 6/09: Do the replacement here!!!!!
+						#content += "<input type=\"hidden\" ID=\"remove_" + tmp_val.replace("'", "\\'") + "_input\" name=\"remove_" + tmp_val + "_prop\">"
+						
+						if pAlias.find(catAlias + "_:_") == 0:
+							pAlias = pAlias[len(catAlias + "_:_"):]
+						
+						if pAlias.lower() not in setFormatList:
+							isDisabled = ""
+						else:
+							isDisabled = "DISABLED"
+							
+						# try to find propID from description
+						#print pName
+						tmpPropID = pHandler.findPropIDByDescription(pName, True)
+						
+						rTypeAttrID = -1
+						
+						if tmpPropID and tmpPropID > 0:
+							propCatID = pHandler.findReagentPropertyInCategoryID(tmpPropID, categoryID)
+						else:
+							propCatID = -1
+						
+						if step == 3:
+							# Aug. 4/09: Modification - Prefill with existing values
+							#print "pc " + `propCatID`
+							
+							if propCatID and propCatID > 0:
+								rTypeID = reagentType_Name_ID_Map[rTypeName]
+								rTypeAttrID = rtPropHandler.findReagentTypeAttributeID(rTypeID, propCatID)
+								#print "atr " + `rTypeAttrID`
+								
+								if rtPropHandler.isUsedProperty(rTypeID, propCatID):
+									isDisabled = "DISABLED"
+									
+								# Update Oct. 13/09
+								allSetValues = sHandler.findAllPropSetValues(propCatID)
+								currSetValues = sHandler.findReagentTypeAttributeSetValues(rTypeAttrID)
+								#print `currSetValues`
+							else:
+								allSetValues = []
+								currSetValues = []
+						else:
+							# Creation - no attribute values assigned to reagent type yet
+							if propCatID and propCatID > 0:
+								allSetValues = sHandler.findAllPropSetValues(propCatID)
+								currSetValues = []
+							else:
+								allSetValues = []
+								currSetValues = []
+						
+						# May 11, 2010: Pre-check if set!!
+						hl_chkd = ""
+						m_chkd = ""
+						o_chkd = ""
+						
+						if rTypeAttrID:
+							if rTypeAttrID > 0:
+								if rtPropHandler.isHyperlink(rTypeAttrID):
+									hl_chkd = "CHECKED"
+						
+								if rtPropHandler.isMultiple(rTypeAttrID):
+									m_chkd = "CHECKED"
+									
+								if rtPropHandler.isCustomizeable(rTypeAttrID):
+									o_chkd = "CHECKED"
+
+						content += "<TR ID=\"" + tmp_val + "_prop_row\">"
+						
+						content += "<TD style=\"padding-left:15px; background-color:#FFFFFF; width:750px;\">"
+						
+						content += "<IMG SRC=\"" + hostname + "pictures/sphere_bullet.jpeg\" WIDTH=\"5\" HEIGHT=\"5\" BORDER=\"0\" ALT=\"sphere\" style=\"padding-right:6px; vertical-align:middle; padding-bottom:2px;\"></IMG>"
+						
+						content += "<span style=\"font-size:10pt; font-weight:bold\">" + pName + "</span>"
+						
+						# April 9, 2010: ORDERING
+						content += "   "
+						
+						if propCatID > 0:
+							content += "<SELECT ID=\"prop_order_list_" + `propCatID` + "\" NAME=\"propOrder_" + `propCatID` + "\">"
+						else:
+							content += "<SELECT ID=\"prop_order_list_" + `propCatID` + "\" NAME=\"propOrder_" + tmp_val + "\">"
+						
+						pnum = 1
+						
+						if step == 3:
+							pOrd = rtPropHandler.getReagentTypePropertyOrdering(rTypeID, propCatID)
+							
+							# when modifying, get ALL properties w/in this category - April 21,10: PLUS any newly added properties!
+							
+							numProps = len(rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, categoryID))
+							
+							# run through the props loop again to figure out the length of the ordering list
+							for tmp_palias in propsList.keys():
+								tmp_pname = propsList[tmp_palias]
+								tmp_pID = pHandler.findPropIDByDescription(tmp_pname, True)
+							
+								if tmp_pID and tmp_pID > 0:
+									tmp_pc_id = pHandler.findReagentPropertyInCategoryID(tmp_pID, categoryID)
+									
+									if not rtPropHandler.existsReagentTypeAttribute(rTypeID, tmp_pc_id):
+										numProps += 1
+								else:
+									numProps += 1
+						else:
+							pOrd = 0
+							numProps = len(propsList)	# here it's whatever came in
+						
+						#print pOrd
+						
+						#print "Content-type:text/html"
+						#print
+						#print numProps
+						
+						while pnum <= numProps:
+							#print pnum
+							if pOrd > 0 and pOrd == pnum:
+								content += "<OPTION SELECTED VALUE=\"" + `pnum` + "\">" + `pnum` + "</OPTION>"
+								
+							else:
+								content += "<OPTION VALUE=\"" + `pnum` + "\">" + `pnum` + "</OPTION>"
+								
+							pnum += 1
+							
+						content += "</SELECT>"
+						
+						if catAlias != 'dna_sequence_features' and catAlias != 'protein_sequence_features' and catAlias != 'rna_sequence_features':
+							
+							if step == 3:
+								setToCheck = utils.merge(currSetValues, allSetValues)
+							else:
+								setToCheck = allSetValues
+							
+							if pName in hyperlinkExceptionsList:
+								content += "<INPUT TYPE=\"hidden\" ID=\"no_hl_" + tmp_val + "\" VALUE=\"1\">"
+							
+							if pName in multipleExceptionslist:
+								content += "<INPUT TYPE=\"hidden\" ID=\"no_mult_" + tmp_val + "\" VALUE=\"1\">"
+
+							# May 31, 2010
+							if rTypeAttrID > 0:
+								if rtPropHandler.isDropdown(rTypeAttrID):
+									is_dropdown = True
+								else:
+									is_dropdown = False
+
+							elif len(setToCheck) > 0:
+								is_dropdown = True
+
+							else:
+								is_dropdown = False
+							
+							# changed May 31, 2010
+							#if len(setToCheck) == 0:
+							if not is_dropdown:
+								# project is an exception, b/c it's not selected from standard dropdowns table, but it's not a freetext either, dropdown option needs to be selected
+								if pName != prop_Name_Desc_Map["packet id"]:
+									
+									if pName not in hyperlinkExceptionsList:
+										# hyperlink
+										content += "<span ID=\"make_hl_" + tmp_val + "\">  <INPUT TYPE=\"checkbox\" NAME=\"hyperlink_" + tmp_val + "\" " + hl_chkd + ">Make hyperlink</span>"
+									else:
+										content += "<span ID=\"make_hl_" + tmp_val + "\" style=\"display:none;\">  <INPUT TYPE=\"checkbox\" NAME=\"hyperlink_" + tmp_val + "\" " + hl_chkd + ">Make hyperlink</span>"
+										
+									content += "<span ID=\"make_mult_" + tmp_val + "\" style=\"display:none;\">  <INPUT TYPE=\"CHECKBOX\" ID=\"mult_cb_" + tmp_val + "\" NAME=\"isMultiple_" + tmp_val + "\" " + m_chkd + ">Allow multiple</span>"
+									
+									content += "<span ID=\"allow_other_" + tmp_val + "\" style=\"display:none;\">  <INPUT TYPE=\"CHECKBOX\" ID=\"customize_cb_" + tmp_val + "\" NAME=\"allowOther_" + tmp_val + "\" " + o_chkd + ">Allow Other</span>"
+								else:
+									# but  for project, DON'T give option to hyperlink, customize or make multiple!
+									content += "<span ID=\"make_hl_" + tmp_val + "\" style=\"display:none;\">  <INPUT TYPE=\"checkbox\" NAME=\"hyperlink_" + tmp_val + "\" " + hl_chkd + ">Make hyperlink</span>"
+									
+									content += "<span ID=\"make_multiple_" + tmp_val + "\" style=\"display:none;\">  <INPUT TYPE=\"CHECKBOX\" ID=\"mult_cb_" + tmp_val + "\" NAME=\"isMultiple_" + tmp_val + "\" " + m_chkd + ">Allow multiple</span>"
+									
+									content += "<span ID=\"allow_other_" + tmp_val + "\" style=\"display:none;\">  <INPUT TYPE=\"CHECKBOX\" ID=\"customize_cb_" + tmp_val + "\" NAME=\"allowOther_" + tmp_val + "\" " + o_chkd + ">Allow Other</span>"
+							# DROPDOWN
+							else:
+								if pName not in multipleExceptionslist:
+									if pName not in hyperlinkExceptionsList:
+										content += "<span ID=\"make_hl_" + tmp_val + "\" style=\"display:none;\">  <INPUT TYPE=\"checkbox\" NAME=\"hyperlink_" + tmp_val + "\" " + hl_chkd + ">Make hyperlink</span>"
+									else:
+										content += "<span ID=\"make_hl_" + tmp_val + "\" style=\"display:none;\">  <INPUT TYPE=\"checkbox\" NAME=\"hyperlink_" + tmp_val + "\" " + hl_chkd + ">Make hyperlink</span>"
+								
+									# multiple
+									
+									# May 19, 2010: if values have been assigned, allow going from multiple to single but not vice versa
+									# May 25, 2010: Differentiate b/w creation and modification
+									if step == 3:	# modification
+										if rtPropHandler.isUsedProperty(rTypeID, propCatID):
+											if pName == prop_Name_Desc_Map["alternate id"]:
+												mult_disabled = "DISABLED"
+												m_chkd = "CHECKED"
+											elif not rtPropHandler.isMultiple(rTypeAttrID):
+												mult_disabled = ""
+											else:
+												mult_disabled = "DISABLED"
+										else:
+											if pName == prop_Name_Desc_Map["alternate id"]:
+												mult_disabled = "DISABLED"
+												m_chkd = "CHECKED"
+											else:
+												mult_disabled = ""
+									else:
+										if pName == prop_Name_Desc_Map["alternate id"]:
+											mult_disabled = "DISABLED"
+											m_chkd = "CHECKED"
+										else:
+											mult_disabled = ""
+								
+									content += "<span ID=\"make_mult_" + tmp_val + "\">  <INPUT TYPE=\"CHECKBOX\" " + mult_disabled + " ID=\"mult_cb_" + tmp_val + "\" NAME=\"isMultiple_" + tmp_val + "\" " + m_chkd + ">Allow multiple</span>"
+									
+									# June 15, 2010: Alternate IDs are printed with 'other' option anyway, so even if user does not check 'allow other' here, still 'Other' checkbox will be printed in the Alt. ID list - so just don't print it here to avoid confusion
+									if pName != prop_Name_Desc_Map["alternate id"]:
+										content += "<span ID=\"allow_other_" + tmp_val + "\">  <INPUT TYPE=\"CHECKBOX\" ID=\"customize_cb_" + tmp_val + "\" NAME=\"allowOther_" + tmp_val + "\" " + o_chkd + ">Allow Other</span>"
+									else:
+										content += "<span ID=\"allow_other_" + tmp_val + "\">  <INPUT TYPE=\"CHECKBOX\" DISABLED CHECKED ID=\"customize_cb_" + tmp_val + "\" NAME=\"allowOther_" + tmp_val + "\">Allow Other</span>"
+								else:
+									if pName not in hyperlinkExceptionsList:
+										content += "<span ID=\"make_hl_" + tmp_val + "\" style=\"display:none;\">  <INPUT TYPE=\"checkbox\" NAME=\"hyperlink_" + tmp_val + "\" " + hl_chkd + ">Make hyperlink</span>"
+
+									else:
+										content += "<span ID=\"make_hl_" + tmp_val + "\" style=\"display:none;\">  <INPUT TYPE=\"checkbox\" NAME=\"hyperlink_" + tmp_val + "\" " + hl_chkd + ">Make hyperlink</span>"
+								
+									# Multiples are allowed
+									content += "<span ID=\"make_mult_" + tmp_val + "\" style=\"display:none;\">  <INPUT TYPE=\"CHECKBOX\" " + isDisabled + " ID=\"mult_cb_" + tmp_val + "\" NAME=\"isMultiple_" + tmp_val + "\" " + m_chkd + ">Allow multiple</span>"
+									
+									# 'Other' - show disabled for Alt. ID, normal for rest
+									if pName != prop_Name_Desc_Map["alternate id"]:
+										content += "<span ID=\"allow_other_" + tmp_val + "\">  <INPUT TYPE=\"CHECKBOX\" ID=\"customize_cb_" + tmp_val + "\" NAME=\"allowOther_" + tmp_val + "\" " + o_chkd + ">Allow Other</span>"
+									else:
+										content += "<span ID=\"allow_other_" + tmp_val + "\">  <INPUT TYPE=\"CHECKBOX\" CHECKED DISABLED ID=\"customize_cb_" + tmp_val + "\" NAME=\"allowOther_" + tmp_val + "\">Allow Other</span>"
+						# June 7, 2010: Features
+						else:
+							#print "Content-type:text/html"
+							#print
+							#print "this is a feature? " + tmp_val
+							
+							if pAlias not in setFormatList:
+								content += "<span ID=\"allow_other_" + tmp_val + "\">  <INPUT TYPE=\"CHECKBOX\" ID=\"customize_cb_" + tmp_val + "\" NAME=\"allowOther_" + tmp_val + "\" " + o_chkd + ">Allow Other</span>"
+							
+						# Modification - check if property or its values are used by reagents of this type
+						if step == 3:
+							rTypeID = reagentType_Name_ID_Map[rTypeName]
+							
+							# Check if used - if property is a descriptor need special code below
+							if pName.lower() == "tag position" or pName.lower() == "expression system":
+								if pName.lower() == "tag position":
+									tmpPropID = prop_Name_ID_Map["tag"]
+								elif pName.lower() == "expression system":
+									tmpPropID = prop_Name_ID_Map["promoter"]
+								
+								tmpPropCatID = pHandler.findReagentPropertyInCategoryID(tmpPropID, categoryID)
+								
+								#tmp_val = (catAlias + "_:_" + pAlias).replace("'", "\\'")
+								
+								#actn = "escape(\'" + tmp_val.replace("\'", "'") + "_prop_row\')"
+								
+								actn = tmp_val.replace("'", "\\'") + "_prop_row"
+								
+								if not rtPropHandler.propertyUsedForReagentType(rTypeID, tmpPropCatID, True) and pAlias not in featureDescriptors:
+									content += "<SPAN class=\"linkShow\" style=\"font-size:7pt; margin-left:12px; font-weight:normal;\" onClick=\"deleteReagentTypeAttribute('" + actn + "', 'saveAttributeValuesForm');\">Remove</SPAN>"
+							else:
+								#print `mandatoryProps`
+								
+								# Rest of properties are normal
+								if pAlias != rTypeName + "_type" and pAlias not in mandatoryProps and not rtPropHandler.propertyUsedForReagentType(rTypeID, propCatID) and pAlias not in featureDescriptors:
+									#tmp_val = (catAlias + "_:_" + pAlias).replace("'", "\\'")
+								
+									# Nov. 6/09: Do the replacement here!!!!!
+									actn = tmp_val.replace("'", "\\'") + "_prop_row"
+									#print actn
+									
+									content += "<SPAN class=\"linkShow\" style=\"font-size:7pt; margin-left:12px; font-weight:normal;\" onClick=\"deleteReagentTypeAttribute('" + actn + "', 'saveAttributeValuesForm');\">Remove</SPAN>"
+								#else:
+									#print "what is this: " + pAlias
+								
+						# Creation - may remove if not mandatory
+						else:
+							if pAlias not in mandatoryProps and pAlias not in featureDescriptors:
+								#tmp_val = (catAlias + "_:_" + pAlias).replace("'", "\\'")
+								
+								#actn = "escape(\'" + tmp_val.replace("\'", "'") + "_prop_row\')"
+								actn = tmp_val.replace("'", "\\'") + "_prop_row"
+								#print actn
+								
+								content += "<SPAN class=\"linkShow\" style=\"font-size:7pt; margin-left:12px; font-weight:normal;\" onClick=\"deleteReagentTypeAttribute('" + actn + "', 'saveAttributeValuesForm');\">Remove</SPAN>"
+
+						# Moved down here on Feb. 8/10 - up in the loop above this field was hidden inside its preceding row; therefore, when the previous property was removed, the next one after it was removed too.  Keep it here!!!
+						content += "<input type=\"hidden\" ID=\"" + tmp_val + "_input\" name=\"" + catAlias.replace("'", "\'") + "[]\" value=\"" + pAlias + "\">"
+						
+						content += "<BR><P>"
+						
+						#print pAlias
+						#print `allSetValues`
+						#print `len(currSetValues)`
+						
+						# Nov. 5/09
+						if step == 3:
+							setToCheck = utils.merge(currSetValues, allSetValues)
+						else:
+							setToCheck = allSetValues
+						
+						if catAlias != 'dna_sequence_features' and catAlias != 'protein_sequence_features' and catAlias != 'rna_sequence_features':
+							content += "    Do you want its value(s) to be entered as free text or selected from a list?<BR><P>   "
+							
+							# May 31, 2010
+							#if len(setToCheck) == 0:
+							if not is_dropdown:
+								actn = tmp_val.replace("'", "\\'")
+								
+								#print "num_vals_" +  tmp_val + `len(setToCheck)`
+								
+								# project ID won't return a set, but it has to be a dropdown
+								if pName == prop_Name_Desc_Map["packet id"]:
+									content += "<INPUT TYPE=\"radio\" ID=\"input_format_radio_text_" + tmp_val + "\" " + isDisabled + " NAME=\"num_vals_" +  tmp_val + "\" VALUE=\"freeform\" onClick=\"showHideAddPropertyValuesInput('" + actn + "');\">Free text"
+					
+									content += "  "
+					
+									content += "<INPUT TYPE=\"radio\" ID=\"input_format_radio_list_" + tmp_val + "\" " + isDisabled + " CHECKED NAME=\"num_vals_" +  tmp_val + "\" VALUE=\"predefined\" onClick=\"showHideAddPropertyValuesInput('" + actn + "');\">Dropdown<BR>"
+									
+								else:
+									content += "<INPUT TYPE=\"radio\" ID=\"input_format_radio_text_" + tmp_val + "\" " + isDisabled + " NAME=\"num_vals_" +  tmp_val + "\" VALUE=\"freeform\" CHECKED onClick=\"showHideAddPropertyValuesInput('" + actn + "');\">Free text"
+					
+									content += "  "
+					
+									content += "<INPUT TYPE=\"radio\" ID=\"input_format_radio_list_" + tmp_val + "\" " + isDisabled + " NAME=\"num_vals_" +  tmp_val + "\" VALUE=\"predefined\" onClick=\"showHideAddPropertyValuesInput('" + actn + "');\">Dropdown<BR>"
+									
+								content += "<DIV ID=\"propertyValuesInputDiv_" + tmp_val + "\" style=\"display:none; margin-left:15px;\">"
+								
+								content += "<span style=\"font-size:9pt; margin-left:5px;\">Use the textbox and 'Add'/'Remove' buttons below to populate the list:</span>"
+								
+								content += "<TABLE style=\"margin-left:10px; margin-top:10px;\">"
+								content += "<TR>"
+								
+								content += "<TD style=\"padding-bottom:5px;\">"
+								
+								content += "<span style=\"font-size:9pt; margin-left:8px;\">Values currently assigned to</SPAN><BR><SPAN style=\"font-size:9pt; margin-left:8px;\">reagent type <b>" + rTypeName + "</b>:</span><BR><P>"
+								
+								content += "</TD>"
+								
+								content += "<TD></TD>"
+								
+								content += "<TD>"
+								content += "<span style=\"font-size:9pt; margin-left:10px;\">Additional <b>" + pName + "</b> values available in OpenFreezer:</SPAN><BR><P>"
+								content += "</TD></TR>"
+								
+								content += "<TR><TD>"
+								
+								content += "<SELECT SIZE=\"10\" MULTIPLE style=\"margin-left:8px;\" ID=\"propertyValuesInputList_" + tmp_val + "\" NAME=\"propertyValues_" + tmp_val + "\"></SELECT>"
+								
+								content += "</TD>"
+								
+								actn1 = "escape(\'propertyValuesInputList_" + tmp_val.replace("'", "\\'") + "\')"
+								actn2 = "escape(\'propertyValuesPoolList_" + tmp_val.replace("'", "\\'") + "\')"
+								
+								content += "<TD>"
+								content += "   <INPUT TYPE=\"BUTTON\" VALUE=\"-->\" onClick=\"moveListElements(" + actn1 + ", " + actn2 + ", 'false')\"><BR><BR>   <INPUT TYPE=\"BUTTON\" VALUE=\"<--\" onClick=\"moveListElements(" + actn2 + ", " + actn1 + ", 'false')\">"
+								content += "</TD>"
+								
+								content += "<TD>"
+								content += "<SELECT MULTIPLE style=\"margin-left:8px;\" SIZE=\"10\" ID=\"propertyValuesPoolList_" + tmp_val + "\" NAME=\"allVals_" + tmp_val + "\">"
+								
+								for setValue in allSetValues:
+									if setValue not in currSetValues:
+										content += "<OPTION value=\"" + setValue + "\">" + setValue + "</OPTION>"
+							
+								content += "</SELECT>"
+								content += "</TD>"
+								
+								content += "</TR>"
+								
+								content += "<TR>"
+								content += "<TD colspan=\"2\">"
+								
+								content += "<INPUT TYPE=\"checkbox\" style=\"margin-top:5px; margin-left:8px; font-size:8pt;\" onClick=\"selectAll(this.id, " + actn1 + ", false)\" id=\"add_all_chkbx_" + tmp_val + "_inputList\"> Select All</INPUT>"
+								
+								content += "</TD>"
+								
+								content += "<TD>"
+								
+								content += "<INPUT TYPE=\"checkbox\" style=\"margin-top:5px; margin-left:8px; font-size:8pt;\" onClick=\"selectAll(this.id, " + actn2 + ", false)\" id=\"add_all_chkbx_" + tmp_val + "_poolList\"> Select All</INPUT>"
+								
+								content += "</TD>"
+								content += "</TR>"
+								
+								content += "</TABLE>"
+								
+								content += "<BR>"
+								
+								content += "<INPUT TYPE=\"TEXT\" style=\"margin-left:18px;\" id=\"addPropertyValue_" + tmp_val + "_txt\" onKeyPress=\"return disableEnterKey(event);\">"
+								
+								#actn = "escape(\'" + tmp_val.replace("'", "\\'") + "\')"
+								#print actn
+							
+								actn1 = "escape(\'addPropertyValue_" + tmp_val.replace("'", "\\'") + "_txt\')"
+								#print actn1
+								
+								actn2 = "escape(\'propertyValuesInputList_" + tmp_val.replace("'", "\\'") + "\')"
+								#print actn2
+							
+								content += " <INPUT TYPE=\"BUTTON\" id=\"addPropertyValue_" + tmp_val + "_btn\" onClick=\"addElementToListFromInput(" + actn1 + ", " + actn2 + ");\" VALUE=\"Add\">"
+				
+								actn3 = "escape(\'" + tmp_val.replace("'", "\\'") + "\')"
+				
+								content += " <INPUT TYPE=\"BUTTON\" id=\"removePropertyValue_" + tmp_val + "_btn\" onClick=\"removePropertyListValue(" + actn3 + ");\" VALUE=\"Remove Selected\">"
+								
+								content += "<P><SPAN ID=\"" + tmp_val + "_warning\" style=\"margin-left:10px; display:none; font-weight:bold; color:red;\">Please provide a set of values for " + pName + ", or select 'Free Text' as input format if applicable.</SPAN>"
+				
+								content += "</DIV>"
+							else:
+								actn = tmp_val.replace("'", "\\'")
+								
+								content += "<INPUT TYPE=\"radio\" ID=\"input_format_radio_text_" + tmp_val + "\" " + isDisabled + " NAME=\"num_vals_" +  tmp_val + "\" VALUE=\"freeform\" onClick=\"showHideAddPropertyValuesInput('" + actn + "');\">Free text"
+				
+								content += "  "
+				
+								content += "<INPUT TYPE=\"radio\" ID=\"input_format_radio_list_" + tmp_val + "\" " + isDisabled + " NAME=\"num_vals_" +  tmp_val + "\" VALUE=\"predefined\" CHECKED onClick=\"showHideAddPropertyValuesInput('" + actn + "');\">Dropdown<BR>"
+								
+								#print "Content-type:text/html"
+								#print
+								#print "input_format_radio_list_" + tmp_val
+								
+								content += "<DIV ID=\"propertyValuesInputDiv_" + tmp_val + "\" style=\"display:inline; margin-left:15px;\">"
+								
+								content += "<span style=\"font-size:9pt; margin-left:5px;\">Use the textbox and 'Add'/'Remove' buttons below to populate the list:</span><BR>"
+		
+								content += "<TABLE style=\"margin-left:10px; margin-top:10px;\">"
+								
+								## April 28, 2010: multiple
+								#content += "<TR>"
+								#content += "<TD style=\"padding-left:5px; padding-bottom:5px;\">"
+								
+								# either give options as radio buttons
+								#content += "Is multiple? <INPUT TYPE=\"radio\" NAME=\"isMultiple_" + tmp_val + "\" VALUE=\"No\" CHECKED>No"
+								#content += "   "
+								#content += "<INPUT TYPE=\"radio\" NAME=\"isMultiple_" + tmp_val + "\" VALUE=\"Yes\">Yes"
+								
+								# or checkbox
+								#content += "<INPUT TYPE=\"CHECKBOX\" NAME=\"isMultiple_" + tmp_val + "\">Allow multiple"
+								
+								#content += "</TD>"
+								#content += "</TR>"
+								
+								content += "<TR>"
+								
+								content += "<TD style=\"padding-bottom:5px;\">"
+								
+								content += "<span style=\"font-size:9pt; margin-left:8px;\">Values currently assigned to</SPAN><BR><SPAN style=\"font-size:9pt; margin-left:8px;\">reagent type <b>" + rTypeName + "</b>:</span><BR><P>"
+								
+								content += "</TD>"
+								
+								content += "<TD></TD>"
+								
+								content += "<TD>"
+								content += "<span style=\"font-size:9pt; margin-left:10px;\">Additional <b>" + pName + "</b> values available in OpenFreezer:</SPAN><BR><P>"
+								content += "</TD></TR>"
+								
+								content += "<TR><TD>"
+
+								content += "<SELECT MULTIPLE SIZE=\"10\" style=\"margin-left:8px;\" ID=\"propertyValuesInputList_" + tmp_val + "\" NAME=\"propertyValues_" + tmp_val + "\">"
+								
+								for setValue in currSetValues:
+									
+									if pName.lower() == "tag position" or pName.lower() == "expression system":
+										if pName.lower() == "tag position":
+											tmpPropID = prop_Name_ID_Map["tag"]
+										elif pName.lower() == "expression system":
+											tmpPropID = prop_Name_ID_Map["promoter"]
+										
+										tmpPropCatID = pHandler.findReagentPropertyInCategoryID(tmpPropID, categoryID)
+										
+										if sHandler.isUsedSetValue(rTypeID, tmpPropCatID, setValue, True):
+											val_disabled = "DISABLED"
+										else:
+											val_disabled = ""
+									
+									else:
+										if sHandler.isUsedSetValue(rTypeID, propCatID, setValue):
+											val_disabled = "DISABLED"
+										
+										# Jan. 29/10: For Alternate IDs, list values are only the prefixes (IMAGE, RIKEN, etc.) - db values are PREFIX:NUMERIC_INDEX
+										elif propCatID == pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["alternate id"], category_Name_ID_Map["External Identifiers"]):
+											if rtPropHandler.existsPropertyValue(rTypeID, propCatID, setValue+":"):
+												val_disabled = "DISABLED"
+											else:
+												val_disabled = ""
+										else:
+											val_disabled = ""
+									
+									content += "<OPTION " + val_disabled + " value=\"" + setValue + "\">" + setValue + "</OPTION>"
+							
+								content += "</SELECT>"
+								content += "</TD>"
+							
+								content += "<TD style=\"padding-bottom:5px;\">"
+								content += "   <INPUT TYPE=\"BUTTON\" VALUE=\"-->\" onClick=\"moveListElements('propertyValuesInputList_" + tmp_val.replace("'", "\\'") + "', 'propertyValuesPoolList_" + tmp_val.replace("'", "\\'") + "', 'false')\"><BR><BR>   <INPUT TYPE=\"BUTTON\" VALUE=\"<--\" onClick=\"moveListElements('propertyValuesPoolList_" + tmp_val.replace("'", "\\'") + "', 'propertyValuesInputList_" + tmp_val.replace("'", "\\'") + "', 'false')\">"
+								content += "</TD>"
+								
+								content += "<TD style=\"white-space:nowrap; padding-bottom:5px;\">"
+
+								content += "<SELECT MULTIPLE style=\"margin-left:8px;\" SIZE=\"10\" ID=\"propertyValuesPoolList_" + tmp_val + "\" NAME=\"allVals_" + tmp_val + "\">"
+								
+								for setValue in allSetValues:
+									if setValue not in currSetValues:
+										content += "<OPTION value=\"" + setValue + "\">" + setValue + "</OPTION>"
+							
+								content += "</SELECT>"
+								
+								content += "</TD></TR>"
+								
+								content += "<TR>"
+								content += "<TD colspan=\"2\">"
+								
+								
+								content += "<INPUT TYPE=\"checkbox\" style=\"margin-top:5px; margin-left:8px; font-size:8pt;\" onClick=\"selectAll(this.id, 'propertyValuesInputList_" + tmp_val + "', false)\" id=\"add_all_chkbx_" + tmp_val + "_inputList\"> Select All</INPUT>"
+								
+								content += "</TD>"
+								
+								content += "<TD>"
+								
+								content += "<INPUT TYPE=\"checkbox\" style=\"margin-top:5px; margin-left:8px; font-size:8pt;\" onClick=\"selectAll(this.id, 'propertyValuesPoolList_" + tmp_val + "', false)\" id=\"add_all_chkbx_" + tmp_val + "_poolList\"> Select All</INPUT>"
+								
+								content += "</TD>"
+								content += "</TR>"
+								
+								content += "</TABLE><BR>"
+									
+								content += "<INPUT TYPE=\"TEXT\" style=\"margin-left:18px;\" id=\"addPropertyValue_" + tmp_val + "_txt\" onKeyPress=\"return disableEnterKey(event);\">"
+
+								actn1 = "escape(\'addPropertyValue_" + tmp_val.replace("'", "\\'") + "_txt\')"
+								#print actn1
+								
+								actn2 = "escape(\'propertyValuesInputList_" + tmp_val.replace("'", "\\'") + "\')"
+								#print actn2
+								
+								content += " <INPUT TYPE=\"BUTTON\" id=\"addPropertyValue_" + tmp_val + "_btn\" onClick=\"addElementToListFromInput(" + actn1 + ", " + actn2 + ");\" VALUE=\"Add\">"
+				
+								content += " <INPUT TYPE=\"BUTTON\" id=\"removePropertyValue_" + tmp_val + "_btn\" onClick=\"removePropertyListValue('" + tmp_val.replace("'", "\\'") + "');\" VALUE=\"Remove Selected\">"
+								
+								content += "<P><SPAN ID=\"" + tmp_val + "_warning\" style=\"display:none; margin-left:10px; font-weight:bold; color:red;\">Please provide a set of values for " + pName + ", or select 'Free Text' as input format if applicable.</SPAN>"
+								
+						else:
+							#print "Content-type:text/html"
+							#print
+							#print "this is a feature? " + tmp_val
+							
+							if pAlias not in setFormatList:
+								content += "<INPUT TYPE=\"hidden\" NAME=\"num_vals_" + tmp_val + "\" VALUE=\"predefined\">"
+									
+								content += "<span style=\"font-size:9pt; margin-left:5px;\">Use the textbox and 'Add'/'Remove' buttons below to populate the list:</span><BR><P>"
+				
+								content += "<TABLE>"
+								content += "<TR>"
+								
+								content += "<TD colspan=\"2\" style=\"padding-bottom:5px;\">"
+								content += "<span style=\"font-size:9pt; margin-left:10px;\">Values currently assigned to reagent type <b>" + rTypeName + "</b>:</span><BR><P>"
+								content += "</TD>"
+								
+								content += "<TD style=\"padding-bottom:5px;\">"
+								content += "<span style=\"font-size:9pt; margin-left:10px;\">Additional <b>" + pName + "</b> values available in OpenFreezer:</SPAN><BR><P></TD>"
+								
+								content += "</TR>"
+								
+								content += "<TR>"
+								content += "<TD>"
+								
+								content += "<SELECT MULTIPLE style=\"margin-left:8px;\" SIZE=\"10\" ID=\"propertyValuesInputList_" + tmp_val + "\" NAME=\"propertyValues_" + tmp_val + "\">"
+								#content += "<OPTION value=\"default\">-- Select " + pName + " --</OPTION>"
+								
+								for setValue in currSetValues:
+									if pName.lower() == "tag position" or pName.lower() == "expression system":
+										if pName.lower() == "tag position":
+											tmpPropID = prop_Name_ID_Map["tag"]
+										elif pName.lower() == "expression system":
+											tmpPropID = prop_Name_ID_Map["promoter"]
+										
+										tmpPropCatID = pHandler.findReagentPropertyInCategoryID(tmpPropID, categoryID)
+										
+										if sHandler.isUsedSetValue(rTypeID, tmpPropCatID, setValue, True):
+											val_disabled = "DISABLED"
+										else:
+											val_disabled = ""
+									else:
+										if sHandler.isUsedSetValue(rTypeID, propCatID, setValue):
+											val_disabled = "DISABLED"
+										else:
+											val_disabled = ""
+										
+									content += "<OPTION " + val_disabled + " value=\"" + setValue + "\">" + setValue + "</OPTION>"
+							
+								content += "</SELECT>"
+								content += "</TD>"
+								
+								#tmp_val = (catAlias + "_:_" + pAlias).replace("'", "\\'")
+								
+								content += "<TD>"
+								content += "   <INPUT TYPE=\"BUTTON\" VALUE=\"-->\" onClick=\"moveListElements('propertyValuesInputList_" + tmp_val  + "', 'propertyValuesPoolList_" + tmp_val + "', 'false')\"><BR><BR>   <INPUT TYPE=\"BUTTON\" VALUE=\"<--\" onClick=\"moveListElements('propertyValuesPoolList_" + tmp_val + "', 'propertyValuesInputList_" + tmp_val + "', 'false')\">"
+								content += "</TD>"
+								
+								content += "<TD>"
+								
+								content += "<SELECT MULTIPLE style=\"margin-left:8px;\" SIZE=\"10\" ID=\"propertyValuesPoolList_" + tmp_val + "\" NAME=\"allVals_" + tmp_val + "\">"
+								#content += "<OPTION value=\"default\">-- Select " + pName + " --</OPTION>"
+								
+								for setValue in allSetValues:
+									if setValue not in currSetValues:
+										content += "<OPTION value=\"" + setValue + "\">" + setValue + "</OPTION>"
+							
+								content += "</SELECT>"
+								content += "</TD>"
+								
+								content += "</TR>"
+								
+								content += "<TR>"
+								content += "<TD colspan=\"2\">"
+								
+								
+								content += "<INPUT TYPE=\"checkbox\" style=\"margin-top:5px; margin-left:8px; font-size:8pt;\" onClick=\"selectAll(this.id, 'propertyValuesInputList_" + tmp_val + "', false)\" id=\"add_all_chkbx_" + tmp_val + "_inputList\"> Select All</INPUT>"
+								
+								content += "</TD>"
+								
+								content += "<TD>"
+								
+								content += "<INPUT TYPE=\"checkbox\" style=\"margin-top:5px; margin-left:8px; font-size:8pt;\" onClick=\"selectAll(this.id, 'propertyValuesPoolList_" + tmp_val + "', false)\" id=\"add_all_chkbx_" + tmp_val + "_poolList\"> Select All</INPUT>"
+								
+								content += "</TD>"
+								content += "</TR>"
+								
+								content += "</TABLE>"
+								
+								content += "<BR><P>"
+					
+								content += "<INPUT TYPE=\"TEXT\" style=\"margin-left:8px;\" id=\"addPropertyValue_" + tmp_val + "_txt\" onKeyPress=\"return disableEnterKey(event);\">"
+							
+								#tmp_val = (catAlias + "_:_" + pAlias).replace("'", "\\'")
+								
+								actn1 = "escape(\'addPropertyValue_" + tmp_val.replace("'", "\\'") + "_txt\')"
+								#print actn1
+								
+								actn2 = "escape(\'propertyValuesInputList_" + tmp_val.replace("'", "\\'") + "\')"
+								#print actn2
+								
+								content += " <INPUT TYPE=\"BUTTON\" id=\"addPropertyValue_" + tmp_val + "_btn\" onClick=\"addElementToListFromInput(" + actn1 + ", " + actn2 + ");\" VALUE=\"Add\">"
+				
+								content += " <INPUT TYPE=\"BUTTON\" id=\"removePropertyValue_" + tmp_val + "_btn\" onClick=\"removePropertyListValue('" + tmp_val.replace("'", "\\'")+ "');\" VALUE=\"Remove Selected\">"
+				
+								content += "<P><SPAN ID=\"" + tmp_val + "_warning\" style=\"display:none; margin-left:10px; font-weight:bold; color:red;\">Please provide a set of values for " + pName + ", or select 'Free Text' as input format if applicable.</SPAN>"
+			
+								content += "</TD>"
+								content += "</TR>"
+								
+								# don't need these here
+								#content+= "<TR><TD></TD></TR>"
+								#content += "</TABLE>"
+
+							elif pName.lower() == "cdna" or pName.lower() == "cdna insert" or pName.lower() == "5' linker" or pName.lower() == "3' linker":
+								content += "<TABLE>"
+								content += "<TR>"
+								content += "<TD>"
+								
+								content += "<INPUT TYPE=\"radio\" ID=\"input_format_radio_text_" + tmp_val + "\" CHECKED DISABLED NAME=\"num_vals_" + tmp_val + "\" VALUE=\"freeform\">Free text"
+				
+								content += "  "
+				
+								content += "<INPUT TYPE=\"radio\" ID=\"input_format_radio_list_" + tmp_val + "\" DISABLED NAME=\"num_vals_" +  tmp_val + "\" VALUE=\"predefined\">Dropdown"
+
+								content += "</TD>"
+								content += "</TR>"
+								
+								content+= "<TR><TD></TD></TR>"
+								
+								content += "</TABLE>"
+						
+							elif pName.lower() == "5' cloning site" or pName.lower() == "3' cloning site" or pName.lower() == "restriction site":
+								#print "HERE!! " + pAlias + ", " + tmp_val
+								content += "<TABLE>"
+								content += "<TR>"
+								content += "<TD>"
+								
+								content += "<INPUT TYPE=\"radio\" ID=\"input_format_radio_text_" + tmp_val + "\" DISABLED NAME=\"num_vals_" +  tmp_val + "\" VALUE=\"freeform\">Free text"
+				
+								content += "  "
+				
+								content += "<INPUT TYPE=\"radio\" ID=\"input_format_radio_list_" + tmp_val + "\" CHECKED DISABLED NAME=\"num_vals_" +  tmp_val + "\" VALUE=\"predefined\">Dropdown"
+							
+								content += "</TD>"
+								content += "</TR>"
+								
+								content+= "<TR><TD></TD></TR>"
+								
+								content += "</TABLE>"
+
+						# property either does not exist at all or exists in a different category
+						#print tmpPropID
+						if (tmpPropID < 0) or (catAlias not in category_Alias_ID_Map.keys()) or (category_Alias_ID_Map.has_key(catAlias) and tmpPropID > 0 and not pHandler.existsPropertyInCategory(tmpPropID, category_Alias_ID_Map[catAlias])):
+							#print "new " + pAlias
+							
+							content += "<INPUT TYPE=\"hidden\" ID=\"" + tmp_val + "_input\" NAME=\"newPropName\" VALUE=\"" + tmp_val + "\">"	# alias, e.g. "Antigen_sequence"
+							
+							content += "<INPUT TYPE=\"hidden\" NAME=\"newPropDescr_" + tmp_val + "\" VALUE=\"" + pName + "\">"	# actual description, e.g. "Antigen Sequence"
+		
+						#content += "</TD>"
+						#content += "</TR>"
+
+						#else:	# for properties with default input values don't need to let user select input format but still need to save them!
+
+							#content += "<INPUT TYPE=\"hidden\" ID=\"" + tmp_val + "_input\" NAME=\"newPropDescr_" + tmp_val + "\" VALUE=\"" + pName + "\">"	# actual description, e.g. "Antigen Sequence"
+			
+							#content += "</TD>"
+							#content += "</TR>"
+						
+						content += "</DIV>"
+						
+				content += "</TABLE></TD></TR>"
+				
+			if step == 2:
+				content += '''
+						</TABLE>
+						
+						<!-- Jan. 29, 2010: DISABLED RADIO BUTTONS ARE NOT SUBMITTED WITH FORM -->
+						
+						<P><INPUT TYPE="submit" name="create_rtype" value="Continue" style="font-size:10pt;" onClick="enableSelect(); enableRadio(); selectAllPropertyValues(true); enableCheckboxes();">
+						
+						   <INPUT TYPE="submit" name="cancel_rtype_create" value="Cancel" onClick="document.pressed='Cancel'; return confirm('Cancel reagent type creation?');" style="font-size:10pt;">
+						<INPUT TYPE="hidden" name="step" value="2">
+						'''
+			else:
+				content += '''
+						</TABLE>
+	
+						<P><INPUT TYPE="submit" name="save_rtype" value="Continue" style="font-size:10pt;" onClick="enableSelect(); enableRadio(); selectAllPropertyValues(true); enableCheckboxes();">
+						
+						   <INPUT TYPE="submit" name="cancel_rtype_modify" value="Cancel" onClick="document.pressed='Cancel'; return confirm('Cancel reagent type modification?');" style="font-size:10pt;">
+						<INPUT TYPE="hidden" name="step" value="3">
+						'''
+				
+			for parent in parents:
+				content += "<INPUT TYPE=\"hidden\" NAME=\"addReagentTypeParents\" VALUE=\"" + parent + "\">"
+
+			content += '''
+				</FORM>
+				'''
+
+			content += gOut.printFooter()
+			
+			# Oct. 7/09: don't make reagent type name uppercase (e.g. 'RNAi')
+			page_content = content % (hostname + "cgi/reagent_type_request_handler.py", rTypeName, rTypePrefix, rTypeName)
+	
+			print "Content-type:text/html"		# THIS IS PERMANENT!
+			print					# DITTO
+			print page_content
+
+
+	#def printReagentTypeView(self, rTypeName, rTypePrefix, catDescrDict, categoryProps, err=""):
+	def printReagentTypeView(self, rTypeID):
+		
+		#print "Content-type:text/html"
+		#print
+		
+		dbConn = DatabaseConn()
+		hostname = dbConn.getHostname()		# to define form action URL
+		
+		db = dbConn.databaseConnect()
+		cursor = db.cursor()
+		root_dir = dbConn.getRootDir()
+		
+		propMapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Alias_ID_Map = propMapper.mapPropAliasID()		# (propAlias, propID) - e.g. ('insert_type', '48')
+		prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+		prop_ID_Name_Map = propMapper.mapPropIDName()		# Added March 13/08 - (prop id, prop name)
+		prop_Name_Alias_Map = propMapper.mapPropNameAlias()	# (propName, propAlias)
+		prop_Alias_Name_Map = propMapper.mapPropAliasName()	# March 18/08 - (propAlias, propName)
+		
+		prop_Alias_Desc_Map = propMapper.mapPropAliasDescription()	# April 20/09 - (propAlias, propDesc)
+		prop_Desc_Alias_Map = propMapper.mapPropDescAlias()		# April 20/09 - (propDesc, propAlias)
+		prop_Desc_ID_Map = propMapper.mapPropDescID()
+		
+		category_Alias_ID_Map = propMapper.mapPropCategoryAliasID()
+		category_ID_Name_Map = propMapper.mapPropCategoryIDName()
+		prop_ID_Desc_Map = propMapper.mapPropIDDescription()
+		
+		propCategory_ID_Order_Map = propMapper.mapPropCategoryIDOrdering()
+		
+		rHandler = ReagentHandler(db, cursor)
+		rtHandler = ReagentTypeHandler(db, cursor)
+		rtPropHandler = ReagentTypePropertyHandler(db, cursor)		# Aug. 31/09
+		pHandler = ReagentPropertyHandler(db, cursor)
+		rtAssocHandler = ReagentTypeAssociationHandler(db, cursor)
+		
+		sHandler = SystemSetHandler(db, cursor)
+		
+		currUser = Session.getUser()
+		
+		# July 28/09
+		rTypeName = rtHandler.findReagentType(rTypeID)
+		rTypePrefix = rtHandler.findReagentTypePrefix(rTypeName)
+		
+		prop_ID_Order_map = propMapper.mapPropIDOrdering()	# keep
+		
+		rTypeAttrIDs = rtPropHandler.findAllReagentTypeAttributes(rTypeID)
+		#print `rTypeAttrIDs`
+
+		propList = {}		# (categoryID, [categoryProps]) dictionary
+	
+		# Find out what categories this reagent type has
+		#for attrID in rTypeAttrIDs:	# this is equivalent to propCatID - changed Aug. 5/09
+		for aKey in rTypeAttrIDs:
+			#print "Attribute " + `aKey`
+			attrID = rTypeAttrIDs[aKey]	# this is equivalent to propCatID
+			#print "PropCatID " + `attrID`
+			
+			propID = pHandler.findReagentPropertyInCategory(attrID)
+			#print propID
+			categoryID = pHandler.findReagentPropertyCategory(attrID)
+			
+			if propList.has_key(categoryID):
+				tmpProps = propList[categoryID]
+			else:
+				tmpProps = []
+				
+			tmpProps.append(propID)
+			propList[categoryID] = tmpProps
+	
+		#print `propList`
+		gOut = GeneralOutputClass()
+
+		modify_disabled = True
+		delete_disabled = True
+		
+		if currUser.getCategory() == 'Admin':
+			modify_disabled = False
+
+		if rtHandler.isEmpty(rtHandler.findReagentTypeID(rTypeName)):
+			delete_disabled = False
+			
+		if rTypeName == 'CellLine':
+			rTypeDescr = "CELL LINE"
+		else:
+			# Oct. 7/09: don't make reagent type name uppercase (e.g. 'RNAi')
+			#rTypeDescr = rTypeName.upper()
+			rTypeDescr = rTypeName
+
+		content = gOut.printHeader()
+		
+		content += '''
+				<FORM name="reagent_type_form" method="POST" action="%s">
+
+					<!-- pass current user as hidden form field -->
+					<INPUT type="hidden" ID="username_hidden" NAME="curr_username"'''
+					
+		content += "value=\"" + currUser.getFullName() + "\">"
+		
+		content += '''
+				<TABLE width="760px" cellpadding="5" cellspacing="5" border="1" frame="box" rules="none" style="padding-left:5px; vertical-align:middle" name="reagent_props" class="detailedView_tbl">
+					<TR>
+						<TD colspan="4">
+							<table width="760px">
+								<tr>
+									<td class="detailedView_heading" style="white-space:nowrap; color:blue; color:#0000DF; padding-left:200px;">
+										%s (%s) Details Page
+										<INPUT TYPE="hidden" name="reagentType" value="%s">
+									</td>
+								
+									<TD class="detailedView_heading" style="text-align:right">
+									'''
+		content += "<INPUT TYPE=\"submit\" name=\"modify_rtype\" value=\"Modify\""
+
+		if modify_disabled:
+			content += " disabled>"
+		else:
+			content += ">"
+				
+		content += "<INPUT TYPE=\"submit\" style=\"margin-left:2px;\" name=\"delete_rtype\" value=\"Delete\" onClick=\"return confirmDeleteReagentType();\""
+		
+		if modify_disabled or delete_disabled:
+			content += " disabled>"
+		else:
+			content += ">"
+	
+		content += '''
+									</td>
+								</tr>
+							</table>
+						</TD>
+					</TR>
+
+					<TR><TD colspan="4"><HR></TD></TR>
+					'''
+		
+		# output them in order
+		for categoryID in propCategory_ID_Order_Map.keys():
+			
+			if propList.has_key(categoryID):
+				categoryOrder = propCategory_ID_Order_Map[categoryID]
+				category = category_ID_Name_Map[categoryID]
+				#print category
+				
+				content += "<TR><TD colspan=\"4\" class=\"detailedView_heading\" style=\"text-align:left; padding-left:7px; padding-right:6px; padding-top:0; color:#0000DF; font-size:9pt; font-family:Helvetica; white-space:nowrap;\">" + category + "</TD></TR>"
+				
+				rTypeProps = propList[categoryID]	# list of IDs
+				#print `rTypeProps`
+				rTypePropSorted = {}
+				
+				descrAttrID_map = {}
+
+				for propID in rTypeProps:
+					# April 9, 2010
+					tmpPropCatID = pHandler.findReagentPropertyInCategoryID(propID, categoryID)
+					#print tmpPropCatID
+					
+					pOrder = rtPropHandler.getReagentTypePropertyOrdering(rTypeID, tmpPropCatID)
+					#print pOrder
+				
+					#print propID
+					if prop_ID_Desc_Map.has_key(propID):
+						pDescr = prop_ID_Desc_Map[propID]
+	
+					if rTypePropSorted.has_key(pOrder):
+						tmp_order_list = rTypePropSorted[pOrder]
+						# don't do any more sorting here!
+					else:
+						tmp_order_list = []
+	
+					tmp_order_list.append(pDescr)
+					rTypePropSorted[pOrder] = tmp_order_list
+					
+					# April 29, 2010: show property format
+					rTypeAttrID = rtPropHandler.findReagentTypeAttributeID(rTypeID, tmpPropCatID)
+					descrAttrID_map[pDescr] = rTypeAttrID
+					
+				rTypePropSorted.keys().sort()
+				#print `rTypePropSorted`
+
+				for pOrd in rTypePropSorted.keys():
+					pDescrs = rTypePropSorted[pOrd]
+					
+					for pDescr in pDescrs:
+						#print `pDescr`
+						
+						content += "<TR>"
+						content += "<TD class=\"detailedView_colName\" style=\"padding-left:12px;\">" + pDescr.replace('%', '%%') + "</TD>"
+						#content += "<TD class=\"detailedView_value\"></TD>"
+						#content += "</TR>"
+						
+						# April 29, 2010: show property format
+						rTypeAttrID = descrAttrID_map[pDescr]
+						
+						if rtPropHandler.isDropdown(rTypeAttrID):
+							dForm = "Dropdown"
+						
+						# May 28, 2010: Introducing change: where you don't want to fill in list values and just want to check 'Other' and let users populate, System_Set_tbl will be empty and sHandler.isDropdown(rTypeAttrID) will return false, so may end up with something like 'Freetext Customizeable Multiple'.  If sHandler.isDropdown(rTypeAttrID) returns false, check again to see if 'isMultiple' or 'isCustomizeable' have been set - because if they were, this cannot be freetext.  Likewise, a dropdown CANN [...]
+						elif rtPropHandler.isMultiple(rTypeAttrID) or rtPropHandler.isCustomizeable(rTypeAttrID) and not rtPropHandler.isHyperlink(rTypeAttrID):
+							dForm = "Dropdown"
+						else:
+							if pDescr != 'Project ID' and pDescr != "5' Cloning Site" and pDescr != "3' Cloning Site" and pDescr != "Restriction Site":
+								dForm = "Freetext"
+							else:
+								dForm = "Dropdown"
+							
+						content += "<TD class=\"detailedView_value\" style=\"padding-left:12px;\">" + dForm
+						
+						#content += "<TD class=\"detailedView_value\"></TD>"
+						
+						if rtPropHandler.isMultiple(rTypeAttrID) or pDescr == "Alternate ID":
+							content += "  MULTIPLE"
+						
+						if rtPropHandler.isHyperlink(rTypeAttrID):
+							content += "  HYPERLINK"
+							
+						if rtPropHandler.isCustomizeable(rTypeAttrID):
+							content += "  CUSTOMIZABLE"
+							
+							# nice but don't use an image on this view, use it on reagent creation form
+							#content += "<IMG src=\"" + hostname + "pictures/link7.png\" WIDTH=\"21\" HEIGHT=\"10\" ALT=\"link_icon\" style=\"cursor:auto\">"
+						
+						content += "</TD>"
+						
+						#if pDescr.lower() == "3' cloning site" or pDescr.lower() == "3' linker" or pDescr.lower() == "cdna" or pDescr.lower() == rTypeName.lower() + " type" or pDescr.lower() == "verification comments":
+							#content += "<TR><TD></TD></TR>"
+						
+						content += "<TD class=\"detailedView_value\"></TD>"
+		
+						content += "</TR>"
+						
+						
+				content += "<TR><TD colspan=\"4\"><HR></TD></TR>"
+	
+	
+		# Aug. 11/09: Print associations
+		assocTypes = rtAssocHandler.getReagentTypeAssociations(rTypeID)
+		
+		if len(assocTypes) > 0:
+			content += "<TR><TD class=\"detailedView_heading\" style=\"text-align:left; padding-left:7px; padding-right:6px; padding-top:0; color:#0000DF; font-size:9pt; font-family:Helvetica; white-space:nowrap;\">Parent Types</TD></TR>"
+			
+			for assocID in assocTypes:
+				assocName = assocTypes[assocID]
+				
+				content += "<TR>"
+				content += "<TD width=\"150px\" class=\"detailedView_colName\" style=\"padding-left:12px;\">" + assocName + "</TD>"
+				content += "<TD class=\"detailedView_value\"></TD>"
+				content += "</TR>"
+				content += "<INPUT TYPE=\"hidden\" NAME=\"reagentTypeParents\" VALUE=\"" + assocName + "\">"
+	
+		content += '''
+				</TABLE>
+				</FORM>
+				'''
+
+		content += gOut.printFooter()
+
+		page_content = content % (hostname + "cgi/reagent_type_request_handler.py", rTypeDescr, rTypePrefix, rTypeName)
+
+		print "Content-type:text/html"		# PERMANENT
+		print					# DITTO
+		print page_content
\ No newline at end of file
diff --git a/OpenFreezer/cgi/reagent_type_request_handler.py b/OpenFreezer/cgi/reagent_type_request_handler.py
new file mode 100755
index 0000000..8200ed6
--- /dev/null
+++ b/OpenFreezer/cgi/reagent_type_request_handler.py
@@ -0,0 +1,2093 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+
+import SocketServer
+from SocketServer import BaseRequestHandler
+#import urllib
+
+import stat
+import MySQLdb
+
+import os
+import sys
+import string
+
+# Custom modules
+import utils
+
+from database_conn import DatabaseConn
+from exception import *
+
+from reagent import Reagent
+from user import User
+
+from reagent_handler import ReagentHandler
+from user_handler import UserHandler
+#from system_set_handler import SystemSetHandler
+
+from reagent_type_output import ReagentTypeOutputClass
+from location_type_database_handler import LocationTypeHandler
+
+from general_handler import *
+from mapper import *
+
+from session import Session
+
+# Handlers and Mappers
+dbConn = DatabaseConn()
+db = dbConn.databaseConnect()
+cursor = db.cursor()
+hostname = dbConn.getHostname()
+
+rtHandler = ReagentTypeHandler(db, cursor)
+rtPropHandler = ReagentTypePropertyHandler(db, cursor)		# Aug. 31/09
+pHandler = ReagentPropertyHandler(db, cursor)
+uHandler = UserHandler(db, cursor)
+
+propMapper = ReagentPropertyMapper(db, cursor)
+rMapper = ReagentTypeMapper(db, cursor)
+
+rtOut = ReagentTypeOutputClass()
+
+reagentType_Name_ID_Map =  rMapper.mapTypeNameID()
+reagentType_ID_Name_Map = rMapper.mapTypeIDName()
+
+prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+prop_Name_Alias_Map = propMapper.mapPropNameAlias()	# (propName, propAlias)
+
+prop_ID_Name_Map = propMapper.mapPropIDName()		# Added March 13/08 - (prop id, prop name)
+prop_ID_Alias_Map = propMapper.mapPropIDAlias()		
+
+prop_Alias_Name_Map = propMapper.mapPropAliasName()	# March 18/08 - (propAlias, propName)
+prop_Alias_ID_Map = propMapper.mapPropAliasID()		# (propAlias, propID) - e.g. ('insert_type', '48')
+prop_Alias_Desc_Map = propMapper.mapPropAliasDescription()
+
+prop_Desc_Alias_Map = propMapper.mapPropDescAlias()
+prop_Desc_Name_Map = propMapper.mapPropDescName()
+prop_Desc_ID_Map = propMapper.mapPropDescID()
+prop_ID_Desc_Map = propMapper.mapPropIDDescription()
+
+prop_Name_Desc_Map = propMapper.mapPropNameDescription()
+
+# added June 3/09
+category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+category_ID_Name_Map = propMapper.mapPropCategoryIDName()
+category_Name_Alias_Map = propMapper.mapPropCategoryNameAlias()
+category_Alias_ID_Map = propMapper.mapPropCategoryAliasID()
+
+rtOut = ReagentTypeOutputClass()
+
+aHandler = AssociationHandler(db, cursor)
+raHandler = ReagentAssociationHandler(db, cursor)
+rtAssocHandler = ReagentTypeAssociationHandler(db, cursor)
+
+## Aug. 11/09: make globals??
+#parents = []
+#children = []
+
+#####################################################################################
+# Contains functions to handle reagent type creation, modification and deletion requests
+#
+# Written April 12, 2009, by Marina Olhovsky
+# Last modified: April 12, 2009
+#####################################################################################
+class ReagentTypeRequestHandler:
+	__db = None
+	__cursor = None
+	__hostname = ""
+	
+	##########################################################
+	# Constructor
+	##########################################################
+	def __init__(self):
+	
+		self.__db = db
+		self.__cursor = cursor
+		self.__hostname = hostname
+		
+		
+	##########################################################
+	# Main action method
+	##########################################################
+	def handle(self):
+		
+		db = self.__db
+		cursor = self.__cursor
+		
+		form = cgi.FieldStorage(keep_blank_values="True")
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		if form.has_key("curr_username"):
+			currUname = form.getvalue("curr_username")
+			currUser = uHandler.getUserByDescription(currUname)
+			Session.setUser(currUser)
+				
+		elif form.has_key("curr_user_id"):
+			currUID = form.getvalue("curr_user_id")
+			currUser = uHandler.getUserByID(currUID)
+			Session.setUser(currUser)
+			
+		if form.has_key("reagentTypeName"):
+			rTypeName = form.getvalue("reagentTypeName")		# capitalize first letter????
+		
+		if form.has_key("reagentTypePrefix"):
+			rTypePrefix = form.getvalue("reagentTypePrefix")	# should the prefix always be capitalized??
+		
+		if form.has_key("create_rtype"):
+			if form.has_key("step"):
+				step = form.getvalue("step")
+
+				# Aug. 11/09: Save associations
+				if form.has_key("addReagentTypeParents"):
+					parents = form.getlist("addReagentTypeParents")
+				else:
+					parents = []
+					
+				#if form.has_key("addReagentTypeChildren"):
+					#children = form.getlist("addReagentTypeChildren")
+
+				if int(step) == 1:
+					self.previewReagentTypePropertyValues(form)
+					
+				elif int(step) == 2:
+					rTypeID = self.createReagentType(form)
+					self.saveReagentTypeAssociations(rTypeID, rTypeName, parents)
+			
+					rtOut.printReagentTypeView(rTypeID)
+		
+		elif form.has_key("view_reagent_type"):
+			rTypeName = form.getvalue("reagentType")
+			rTypePrefix = rtHandler.findReagentTypePrefix(rTypeName)
+			
+			catDescrDict = {}	# categoryAlias, categoryDescription
+			categoryProps = {}	# categoryAlias, rTypeProps (see below)
+			
+			rTypeID = reagentType_Name_ID_Map[rTypeName]
+			rTypeAttributeIDs = rtPropHandler.findAllReagentTypeAttributes(rTypeID)
+			#print `rTypeAttributeIDs`
+			
+			#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+			#print
+			
+			#for attrID in rTypeAttributeIDs:	# update Aug. 5/09
+			for aKey in rTypeAttributeIDs:
+				#print aKey
+				attrID = rTypeAttributeIDs[aKey]
+				#print attrID
+				categoryID = pHandler.findReagentPropertyCategory(attrID)
+				
+				if category_ID_Name_Map.has_key(categoryID):
+					category = category_ID_Name_Map[categoryID]
+					#print "Category " + category
+					catAlias = category_Name_Alias_Map[category]
+					#print catAlias
+					catDescrDict[catAlias] = category
+					cp = pHandler.findReagentPropertyInCategory(attrID)
+					#print cp
+					#print `cat_propList`
+					
+					#print "Property " + cAlias
+					
+					if categoryProps.has_key(catAlias):
+						cat_propList = categoryProps[catAlias]
+					else:
+						cat_propList = []
+					
+					if prop_ID_Alias_Map.has_key(cp):
+						cAlias = prop_ID_Alias_Map[cp]
+						cat_propList.append(cAlias)
+					# this would happen only in case of incomplete db deletion!
+					#else:
+						#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+						#print
+						
+					#print `cat_propList`
+					
+					categoryProps[catAlias] = cat_propList
+					#print `categoryProps`
+
+			#rtOut.printReagentTypeView(rTypeName, rTypePrefix, catDescrDict, categoryProps)
+			rtOut.printReagentTypeView(rTypeID)
+			
+		elif form.has_key("modify_rtype"):
+			
+			# Go to "Modify Reagent Type" page
+			rTypeName = form.getvalue("reagentType")
+			rTypePrefix = rtHandler.findReagentTypePrefix(rTypeName)
+			
+			catDescrDict = {}	# categoryAlias, categoryDescription
+			categoryProps = {}	# categoryAlias, rTypeProps (see below)
+			
+			rTypeID = reagentType_Name_ID_Map[rTypeName]
+			rTypeAttributeIDs = rtPropHandler.findAllReagentTypeAttributes(rTypeID)
+			#print `rTypeAttributeIDs`
+
+			if form.has_key("reagentTypeParents"):
+				parents = form.getlist("reagentTypeParents")
+			else:
+				parents = []
+
+			for aKey in rTypeAttributeIDs.keys():
+				attrID = rTypeAttributeIDs[aKey]	# this is propCatID
+				#print attrID
+				categoryID = pHandler.findReagentPropertyCategory(attrID)
+				
+				if category_ID_Name_Map.has_key(categoryID):
+					category = category_ID_Name_Map[categoryID]
+					#print "Category " + category
+					catAlias = category_Name_Alias_Map[category]
+					catDescrDict[catAlias] = category
+					cp = pHandler.findReagentPropertyInCategory(attrID)
+					#print cp
+					#print `cat_propList`
+					if prop_ID_Alias_Map.has_key(cp):
+						cAlias = prop_ID_Alias_Map[cp]		# gave error here on 'pralias issue' reagentt type, check if others
+						#print "Property " + cAlias
+						
+						if categoryProps.has_key(catAlias):
+							cat_propList = categoryProps[catAlias]
+						else:
+							cat_propList = []
+						
+						#print cAlias + " not used"
+						cat_propList.append(cAlias)
+		
+						#print `cat_propList`
+						categoryProps[catAlias] = cat_propList
+				
+			#print `categoryProps`
+			rtOut.printReagentTypeCreationPage(rTypeName, rTypePrefix, 1, catDescrDict, categoryProps, parents, 0)
+
+		elif form.has_key("save_rtype"):
+			self.updateReagentType(form)
+
+		elif form.has_key("delete_rtype"):
+			self.deleteReagentType(form)
+			utils.redirect(hostname + "Reagent.php?View=5&Del=1")
+			
+		elif form.has_key("cancel_rtype_create"):
+			utils.redirect(hostname + "Reagent.php?View=2")
+			
+		elif form.has_key("cancel_rtype_modify"):
+			rTypeName = form.getvalue("reagentTypeName")
+			rTypeID = reagentType_Name_ID_Map[rTypeName]
+			rtOut.printReagentTypeView(rTypeID)
+		
+		cursor.close()
+		db.close()
+	
+	
+	def saveReagentTypeAssociations(self, rTypeID, rTypeName, parents):
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `parents`
+		
+		aTypeID = rtAssocHandler.findAssociationByReagentType(rTypeID)
+		
+		if aTypeID <= 0:
+			# create AType_tbl entry
+			aHandler.createAssociation(rTypeName)	# just plain and simple store this reagent type name as association descriptor
+			
+		for pType in parents:
+			if reagentType_Name_ID_Map.has_key(pType):
+				pTypeID = reagentType_Name_ID_Map[pType]
+				
+			elif pType == rTypeName:
+				# nov. 24/09: include the reagent type currently being saved!!!!!!!!!!
+				pTypeID = rTypeID
+			
+			assocName = "parent " + pType.lower()
+			alias = "parent_" + pType.lower() + "_id"
+			description = "Parent " + pType + " ID"
+		
+			# also check if not exist
+			rtAssocHandler.addReagentTypeAssociationPropertyValue(rTypeID, assocName, alias, description, pTypeID)
+
+
+	def deleteReagentTypeAssociations(self, rTypeID):
+		
+		db = self.__db
+		cursor = self.__cursor
+		
+		#rTypeID = reagentType_Name_ID_Map[rTypeName]
+		
+		# Jan. 28/10: this code deletes this reagent type as a child of other types
+		aTypeID = rtAssocHandler.findAssociationByReagentType(rTypeID)
+		assocProps = rtAssocHandler.findReagentTypeAssocProps(rTypeID)
+		
+		for aPropID in assocProps.keys():
+			aHandler.deleteAssociationProperty(aPropID)
+
+		# Jan. 28/10: also need to delete this rtype as parent of other rtypes
+		aHandler.deleteReagentTypeAssociations(rTypeID)
+		aHandler.deleteAssociation(aTypeID)
+
+
+	def updateReagentType(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		rtHandler = ReagentTypeHandler(db, cursor)
+		pHandler = ReagentPropertyHandler(db, cursor)
+		rtAssocHandler = ReagentTypeAssociationHandler(db, cursor)
+		
+		sHandler = SystemSetHandler(db, cursor)
+		
+		propMapper = ReagentPropertyMapper(db, cursor)
+		rtAssocMapper = ReagentAssociationMapper(db, cursor)
+
+		prop_Alias_ID_Map = propMapper.mapPropAliasID()		# (propAlias, propID) - e.g. ('insert_type', '48')
+		category_Alias_ID_Map = propMapper.mapPropCategoryAliasID()
+		
+		#rType_assoc_ID_Parent_Map = rtAssocMapper.mapAssocIDParentType()
+
+		rtOut = ReagentTypeOutputClass()
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		catDescrDict = {}	# categoryAlias, categoryDescription
+		categoryProps = {}	# categoryAlias, rTypeProps (see below)
+		
+		rTypeName = form.getvalue("reagentTypeName")
+		old_rTypePrefix = form.getvalue("reagentTypePrefix")
+
+		if reagentType_Name_ID_Map.has_key(rTypeName):
+			rTypeID = reagentType_Name_ID_Map[rTypeName]
+		else:
+			print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+			print
+			print "Error: Unknown reagent type " + rTypeName
+		
+		
+		# Nov. 20-23/09: PARENTS
+		# NOTE: Disabled options are NOT submitted.  I.e. if for Inserts have 'RNAi', 'Vector' and 'Oligo' parents, and want to remove RNAi so that only V+O remain - since V and O options are disabled, the select list is NOT submitted; hence, the 'delete' statement is never called and RNAi remains in the list.  Modify display code to enable all options at submission.
+		if form.has_key("add_reagent_type_parents"):
+			parentList = form.getlist("add_reagent_type_parents")
+			#print "parents " + `parentList`
+
+			rTypeAssocParents = rtAssocHandler.findReagentAssociationParentTypes(reagentType_Name_ID_Map[rTypeName])
+
+			for assocTypeID in rTypeAssocParents.keys():
+				pTypeID = rTypeAssocParents[assocTypeID]
+				
+				if not rtAssocHandler.isUsedReagentTypeAssociation(reagentType_Name_ID_Map[rTypeName], pTypeID):
+					aHandler.deleteAssociationProperty(assocTypeID)
+
+			self.saveReagentTypeAssociations(rTypeID, rTypeName, parentList)
+
+			#if len(parentList) == 0:
+				#self.deleteReagentTypeAssociations(rTypeName)
+			#else:
+					
+				#for parentType in parentList:
+					#print parentType
+
+					#assocTypeID = rtAssocHandler.findParentAssocType(reagentType_Name_ID_Map[rTypeName], reagentType_Name_ID_Map[parentType])
+
+					#if not rtAssocHandler.isUsedReagentTypeAssociation(reagentType_Name_ID_Map[rTypeName], reagentType_Name_ID_Map[parentType]):
+						##self.deleteReagentTypeAssociations(rTypeName)
+						#aHandler.deleteAssociationProperty(assocTypeID)
+
+				#self.saveReagentTypeAssociations(rTypeID, rTypeName, parentList)
+	
+		# Sept. 4/09: NO - do NOT allow changing reagent type name - see comments file
+		#if form.has_key("newReagentTypeName"):
+			#rTypeName = form.getvalue("newReagentTypeName")
+		
+			#if old_rTypeName != rTypeName:
+				## change rtypename
+				#rtHandler.setReagentTypeName(rTypeID, rTypeName)
+		#else:
+			#rTypeName = old_rTypeName
+			
+		if form.has_key("newReagentTypePrefix"):
+			rTypePrefix = form.getvalue("newReagentTypePrefix")
+			
+			if old_rTypePrefix != rTypePrefix:
+				# change rtypePrefix
+				rtHandler.setReagentTypePrefix(rTypeID, rTypePrefix)
+		else:
+			rTypePrefix = old_rTypePrefix
+
+		if form.has_key("addReagentTypeParents"):
+			parents = form.getlist("addReagentTypeParents")
+		else:
+			parents = []
+		
+		if form.has_key("addReagentTypeChildren"):
+			children = form.getlist("addReagentTypeChildren")
+
+		#print `catDescrDict`
+
+		# June 11/09: Select only one sequence type
+		sequenceTypeCategoryAliases = {"DNA Sequence":["sequence_properties", "dna_sequence_features"], "Protein Sequence":["protein_sequence_properties", "protein_sequence_features"], "RNA Sequence":["rna_sequence_properties", "rna_sequence_features"]}
+	
+		ignoreSequenceAttributes = []
+		
+		if form.has_key("sequenceType"):
+			sequenceType = form.getvalue("sequenceType")
+			
+			for st in sequenceTypeCategoryAliases.keys():
+				if st != sequenceType:
+					ignore_props_list = sequenceTypeCategoryAliases[st]
+					ignoreSequenceAttributes += ignore_props_list
+
+		step = form.getvalue("step")
+		
+		#print step
+
+		if step == '1':
+			if form.has_key("category[]"):
+				categories = form.getlist("category[]")
+				
+				#print "Content-type:text/html"
+				#print
+				#print `categories`
+				
+				for category in categories:	# this is an alias, e.g. "general_properties" => 'General Properties'
+					rTypeProps = {}		# propAlias, propDescr
+					
+					category = category.replace("'", "\\'")
+					
+					#print "CATEGORY " + category
+					
+					if (len(ignoreSequenceAttributes) == 0) or (len(ignoreSequenceAttributes) > 0 and category not in ignoreSequenceAttributes):
+						#print "?????????????Category " + category
+						
+						#print "what's this: " + "category_descriptor_" + category
+						
+						#print `form.has_key("category_descriptor_" + category)`
+						
+						# April 15, 2009
+						categoryDescriptor = form.getvalue("category_descriptor_" + category)
+						#print "???" + categoryDescriptor + "!!"
+			
+						# Update Nov. 30/09: Now novel properties are prefixed by "createReagentType_" but old properties are not
+						checkboxAliases = form.getlist("createReagentType_" + category+"[]") + form.getlist(category+"[]")
+						
+						# Aug. 13/09: Don't save empty categories
+						if len(checkboxAliases) > 0:
+							catDescrDict[category] = categoryDescriptor
+			
+						#print `checkboxAliases`
+						
+						for cbAlias in checkboxAliases:
+							#print "Alias " + cbAlias
+							
+							cbAlias = cbAlias.strip()
+							
+							if cbAlias == 'type':
+								# prepend reagent type name to it
+								pDescr = rTypeName + " Type"
+								pAlias = string.join(rTypeName.split(" "), "_") + "_type"
+							
+							elif form.has_key("createReagentType_" + category + "_:_" + cbAlias):
+								tmpDescr = form.getvalue("createReagentType_" + category + "_:_" + cbAlias)
+								
+								if pHandler.findPropertyDescriptionFromAlias(cbAlias) > 0:
+									pAlias = cbAlias
+									pDescr = pHandler.findPropertyDescriptionFromAlias(pAlias)
+									pName = pDescr.lower()
+								
+								elif pHandler.findPropertyAliasFromDescription(tmpDescr):
+									pAlias = pHandler.findPropertyAliasFromDescription(tmpDescr)
+									pDescr = tmpDescr
+									pName = pDescr.lower()
+									
+								#elif form.has_key(category + "_:_" + cbAlias):
+									#pAlias = cbAlias
+									#pDescr = form.getvalue(category + "_:_" + cbAlias)
+									#pName = pDescr.lower()
+								
+								else:
+									pAlias = cbAlias
+									pDescr = tmpDescr
+									pName = pDescr.lower()
+									
+									#print "Content-type:text/html"
+									#print
+									#print "Unknown alias: " + pAlias
+								
+							# Existing properties
+							elif pHandler.findPropertyDescriptionFromAlias(cbAlias) > 0:
+								pDescr = pHandler.findPropertyDescriptionFromAlias(cbAlias)
+								pName = pDescr.lower()
+								pAlias = cbAlias
+							
+							elif cbAlias.find(category + "_:_") == 0:
+								# Existing properties
+								pAlias = cbAlias[len(category + "_:_"):]
+								#print "pAlias " + pAlias
+								#print category
+								#print category + "_:_" + pAlias
+								
+								if form.has_key(category + "_:_" + pAlias):
+									pDescr = form.getvalue(category + "_:_" + pAlias)
+									#print pDescr
+									
+									# Nov. 2/09: This is a new property - BUT check if it exists in the database; if yes grab its alias
+									if pHandler.findPropertyAliasFromDescription(pDescr):
+										pAlias = pHandler.findPropertyAliasFromDescription(pDescr)
+									
+								elif pHandler.findPropertyDescriptionFromAlias(pAlias) > 0:
+									pDescr = pHandler.findPropertyDescriptionFromAlias(pAlias)
+									#pDescr = pHandler.findPropertyDescription(prop_Alias_ID_Map[pAlias])
+									#pDescr = prop_ID_Desc_Map[prop_Alias_ID_Map[pAlias]]
+									
+								else:
+									print "Content-type:text/html"
+									print
+									print "Unknown alias: " + pAlias
+
+								if prop_Alias_ID_Map.has_key(pAlias):
+								#if pHandler.findPropertyIDFromAlias(pAlias, True):
+									#pID = pHandler.findPropertyIDFromAlias(pAlias, True)
+									pID = prop_Alias_ID_Map[pAlias]
+									#pDescr = pHandler.findPropertyDescription(pID)
+									pDescr = prop_ID_Desc_Map[pID]
+								else:
+									pDescr = form.getvalue(category + "_:_" + pAlias)
+									#print `pDescr`
+								
+								#print "Description " + `pDescr`
+							else:
+								print "Content-type:text/html"
+								print
+								print "Unknown alias: " + cbAlias
+							
+							#else:
+								## Novel properties
+								#if form.has_key(category + "_:_" + cbAlias):
+									#pDescr = form.getvalue(category + "_:_" + cbAlias)
+									##pName = pDescr.lower()
+									#pAlias = cbAlias
+									
+								##print cbAlias
+								##print `prop_Alias_ID_Map[cbAlias]`
+								
+								#elif prop_Alias_ID_Map.has_key(cbAlias):
+									#pID = prop_Alias_ID_Map[cbAlias]
+									#pDescr = prop_ID_Desc_Map[pID]
+									#pAlias = cbAlias
+									
+								#else:
+									#print "Content-type:text/html"
+									#print
+									#print "Unknown alias: " + cbAlias
+							
+							# added check for list June 18/09 - catch duplicates
+							if utils.isList(pDescr):
+								for desc in pDescr:
+									pName = desc.lower()
+									
+									# use one dictionary for all props - June 17/09 update: don't store duplicate values
+									if not desc in rTypeProps.values():
+										rTypeProps[pAlias] = desc
+							else:
+								pName = pDescr.lower()
+								#print "Name " + pName
+				
+								# use one dictionary for all props - June 17/09 update: don't store duplicate values
+								if not pDescr in rTypeProps.values():
+									rTypeProps[pAlias] = pDescr
+						
+						#print "Category " + category + ", description " + pDescr
+						#print `rTypeProps`
+						
+						#print "Description " + pDescr
+						
+						# check again for non-empty props list
+						if len(rTypeProps) > 0:
+							categoryProps[category] = rTypeProps
+				
+				if len(categoryProps) > 0:
+					rtOut.printReagentTypeCreationPage(rTypeName, rTypePrefix, 3, catDescrDict, categoryProps, parents)
+				else:
+					rtOut.printReagentTypeView(rTypeID)
+
+		elif step == '3':
+			
+			#print "Content-type:text/html"
+			#print
+			#print `form`
+			
+			# For new properties, save predefined values
+			cat_newProps = form.getlist("newPropName")
+			all_newProps = {}
+	
+			for c_prop in cat_newProps:
+				pList = []
+	
+				if c_prop.find("_:_") >= 0:
+					tmpStart = c_prop.index("_:_")
+					tmpEnd = tmpStart + len("_:_")
+					tmpCat = c_prop[0:tmpStart]
+					newProp = c_prop[tmpEnd:]
+					
+					#print newProp
+					
+					if all_newProps.has_key(tmpCat):
+						pList = all_newProps[tmpCat]
+						
+						if newProp not in pList:
+							pList.append(newProp)
+							all_newProps[tmpCat] = pList
+					else:
+						pList = []
+						pList.append(newProp)
+						all_newProps[tmpCat] = pList
+				
+			#print "New: " + `all_newProps`
+			propsToRemove = []
+			
+			# Feb. 1/10: do removal here, doesn't work otherwise... Feb. 3/10: well, no, these may be NEW props/categories...
+			for cat_alias in category_Alias_ID_Map.keys():
+				cat_id = category_Alias_ID_Map[cat_alias]
+				allCatPropIDs = pHandler.findPropertiesByCategory(cat_id)
+				
+				for pID in allCatPropIDs:
+					pAlias = prop_ID_Alias_Map[pID]
+					
+					if form.has_key("remove_" + cat_alias + "_:_" + pAlias + "_prop"):
+						rmvFlag = form.getvalue("remove_" + cat_alias + "_:_" + pAlias + "_prop")
+						
+						if rmvFlag == "1":
+							propsToRemove.append(pAlias)
+							pcID = pHandler.findReagentPropertyInCategoryID(pID, cat_id)
+							rtPropHandler.deleteReagentTypeAttribute(rTypeID, pcID)
+	
+			#print `propsToRemove`
+	
+			# Save remaining properties as attributes of this reagent type
+			if form.has_key("category[]"):
+				categories = form.getlist("category[]")
+				#print "All categories: " + `categories`
+				
+				for category in categories:	# this is an alias, e.g. "general_properties" => 'General Properties'
+					#print category
+					
+					if all_newProps.has_key(category):
+						newProps = all_newProps[category]
+					else:
+						newProps = []
+
+					#print "New props " + `newProps`
+					
+					# Jan. 26/10: need to record special info for features, e.g. colour
+					if category == category_Name_Alias_Map["DNA Sequence Features"] or category == category_Name_Alias_Map["RNA Sequence Features"] or category == category_Name_Alias_Map["Protein Sequence Features"]:
+						isSeqFeature = True
+					else:
+						isSeqFeature = False
+					
+					categoryDescriptor = form.getvalue("category_descriptor_" + category)
+					
+					if not pHandler.existsReagentPropertyCategory(categoryDescriptor) or not category_Alias_ID_Map.has_key(category):
+						categoryID = pHandler.addReagentPropertyCategory(categoryDescriptor, category)
+					else:
+						categoryID = category_Alias_ID_Map[category]
+					
+					#print `categoryID`
+					
+					propAliases = form.getlist(category+"[]")
+					#print `propAliases`
+					
+					#print `newProps`
+					
+					for pAlias in propAliases:
+						#print pAlias
+						
+						if pAlias in propsToRemove:
+							continue
+						
+						if form.has_key("remove_" + category + "_:_" + pAlias + "_prop"):
+							if form.getvalue("remove_" + category + "_:_" + pAlias + "_prop") == "1":
+								continue
+							
+						#if pAlias.lower() == prop_Name_Alias_Map["tag type"]:
+							#propAliases.append("tag_position")
+							
+						#if pAlias.lower() == prop_Name_Alias_Map["promoter"]:
+							#propAliases.append("expression_system")
+						#removeFlag = form.getvalue("remove_" + category + "_:_" + pAlias + "_prop")
+						
+						if pAlias == rTypeName + "_type":
+							# prepend reagent type name to it
+							#pAlias = rTypeName + "_type"
+							pName = rTypeName + " type"
+							pDescr = rTypeName + " Type"
+							
+							newPropAlias = category + "_:_" + pAlias
+							
+							#if removeFlag == "1":
+								#propCatID = pHandler.findReagentPropertyInCategoryID(newPropID, categoryID)
+								
+								#if propCatID > 0:
+									#rtPropHandler.deleteReagentTypeAttribute(rTypeID, propCatID)
+								## otherwise don't do anything
+								#continue
+							
+							# 'if exists' added June 17/09
+							if not pHandler.existsReagentPropertyType(pName):
+								# correction June 22/09: don't include category in argument list
+								# (obviously this is not a feature, no need to set parameter - jan. 26/10)
+								newPropID = pHandler.addReagentPropertyType(pName, pAlias, pDescr)
+							else:
+								newPropID = pHandler.findPropID(pName, True)
+								#newPropID = prop_ID_Name_Map[pName]
+							
+							# June 27/09: set ordering to place 'type' after Name, Status and Project ID on the detailed view
+							#pHandler.setPropertyOrdering(newPropID, 4)
+							
+							# added June 17/09
+							if not pHandler.existsPropertyInCategory(newPropID, categoryID):
+								propCatID = pHandler.addReagentPropertyToCategory(newPropID, categoryID)
+							else:
+								propCatID = pHandler.findReagentPropertyInCategoryID(newPropID, categoryID)
+	
+							# 'if exists' added June 17/09
+							if not rtPropHandler.existsReagentTypeAttribute(rTypeID, propCatID):
+								rTypeAttrID = rtPropHandler.addReagentTypeAttribute(rTypeID, propCatID)
+							else:
+								rTypeAttrID = rtPropHandler.findReagentTypeAttributeID(rTypeID, propCatID)
+	
+							# April 9, 2010
+							if propCatID > 0 and form.has_key("propOrder_" + `propCatID`):
+								pOrder = form.getvalue("propOrder_" + `propCatID`)
+								#print "Setting order " + `pOrder` + " for " + pAlias
+								rtPropHandler.setReagentTypeAttributeOrdering(rTypeAttrID, pOrder)
+							else:
+								#print "HERE!!! this is a new property!!"
+								tmp_prop_cat_alias = category + "_:_" + pAlias
+								
+								if form.has_key("propOrder_" + tmp_prop_cat_alias):
+									pOrder = form.getvalue("propOrder_" + tmp_prop_cat_alias)
+									rtPropHandler.setReagentTypeAttributeOrdering(rTypeAttrID, pOrder)
+
+							# update list for multiple values
+							numVals = form.getvalue("num_vals_" + newPropAlias)
+							
+							comms = categoryDescriptor + " " + pName
+							
+							if not sHandler.existsSetGroup(propCatID):
+								ssetGroupID = sHandler.addSetGroupID(propCatID, comms)
+							else:
+								ssetGroupID = sHandler.findPropSetGroupID(propCatID)
+							
+							sHandler.deleteReagentTypeAttributeSetValues(rTypeAttrID)
+							
+							#print numVals
+							
+							if numVals == 'predefined':		# dropdown list of values
+								#print "predef " + newPropAlias
+								
+								# May 28/10: only if list allow multiple and other!!!
+								# Apr. 29, 2010: Hyperlinks and multiples
+								if form.has_key("isMultiple_" + newPropAlias):
+									rtPropHandler.makeMultiple(rTypeAttrID)
+								else:
+									rtPropHandler.makeSingle(rTypeAttrID)
+								
+								if form.has_key("allowOther_" + newPropAlias):
+									rtPropHandler.makeCustomizeable(rTypeAttrID)
+								else:
+									rtPropHandler.removeCustomizeable(rTypeAttrID)
+							
+								# do this to change free-text to dropdown!!!!
+								rtPropHandler.removeHyperlink(rTypeAttrID)
+							
+								propVals = form.getlist("propertyValues_" + newPropAlias)
+								#print `propVals`
+								
+								for pVal in propVals:
+									if pVal != 'default':
+										#print pVal
+										#sHandler.updateSet(pName, pVal)
+										#setComms = pDescr
+										#sHandler.updateSet(rTypeAttrID, setComms, pVal)
+										sID = sHandler.findSetValueID(ssetGroupID, pVal)
+										
+										if sID <= 0:
+											sID = sHandler.addSetValue(ssetGroupID, pVal)
+										
+										if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttrID, sID):
+											sHandler.addReagentTypeAttributeSetEntry(rTypeAttrID, sID)
+							else:
+								if form.has_key("hyperlink_" + newPropAlias):
+									rtPropHandler.makeHyperlink(rTypeAttrID)
+								else:
+									rtPropHandler.removeHyperlink(rTypeAttrID)
+	
+								# convert from d/d to f/t
+								rtPropHandler.removeCustomizeable(rTypeAttrID)
+								rtPropHandler.makeSingle(rTypeAttrID)
+	
+						elif pAlias not in newProps:
+							#print "Alias " + pAlias
+	
+							# think I've stripped category from the alias already but test more to make sure
+							if pAlias.find(category + "_:_") == 0:
+								pAlias = pAlias[len(category + "_:_"):]
+
+							# June 14, 2010: Ok, try to make alias lowercase - pray this doesn't break anything
+							pAlias = pAlias.lower()
+							
+							tmpPropID = pHandler.findPropertyIDFromAlias(pAlias, True)
+							
+							#print "alias " + pAlias + ", propID " + `tmpPropID`
+
+							# change Oct. 31/09
+							#pDescr = prop_Alias_Desc_Map[pAlias]
+							pDescr = pHandler.findPropertyDescriptionFromAlias(pAlias, True)
+							
+							#if not pDescr:
+								#pDescr = pAlias
+							
+							#print pDescr
+							
+							# June 15/09: Now that we allow property names to be shared between categories, need to specify the category when checking if a property exists in the database.  Check if this property exists specifically under our category; if not, insert as a new ReagentPropType_tbl entry
+							if not pHandler.existsPropertyInCategory(tmpPropID, categoryID):
+								#print "Adding property " + pAlias + " to category " + `categoryID`
+								propCatID = pHandler.addReagentPropertyToCategory(tmpPropID, categoryID)
+							else:
+								propCatID = pHandler.findReagentPropertyInCategoryID(tmpPropID, categoryID)
+
+							#print propCatID
+							
+							# See if this property needs to be deleted
+							#removeFlag = form.getvalue("remove_" + (category + "_:_" + pAlias) + "_prop")
+							#print removeFlag + " remove " + category + "_:_" + pAlias
+							
+							#if removeFlag == "1":
+								##print removeFlag + " remove " + category + "_:_" + pAlias
+								#rtPropHandler.deleteReagentTypeAttribute(rTypeID, propCatID)
+							
+							#if pAlias in propsToRemove:
+								#continue
+							
+							if not rtPropHandler.existsReagentTypeAttribute(rTypeID, propCatID):
+								rTypeAttrID = rtPropHandler.addReagentTypeAttribute(rTypeID, propCatID)
+							else:
+								rTypeAttrID = rtPropHandler.findReagentTypeAttributeID(rTypeID, propCatID)
+							
+							# April 9, 2010
+							if propCatID > 0 and form.has_key("propOrder_" + `propCatID`):
+								pOrder = form.getvalue("propOrder_" + `propCatID`)
+								rtPropHandler.setReagentTypeAttributeOrdering(rTypeAttrID, pOrder)
+							else:
+								tmp_prop_cat_alias = category + "_:_" + pAlias
+								
+								if form.has_key("propOrder_" + tmp_prop_cat_alias):
+									pOrder = form.getvalue("propOrder_" + tmp_prop_cat_alias)
+									rtPropHandler.setReagentTypeAttributeOrdering(rTypeAttrID, pOrder)
+
+							oldInputFormat = rtPropHandler.getAttributeInputFormat(rTypeAttrID)
+							
+							#print oldInputFormat
+
+							#print `rTypeAttrID` + "??"
+							
+							# Still have to update dropdown set
+							numVals = form.getvalue("num_vals_" + (category + "_:_" + pAlias).replace("'", "\\'"))
+							
+							#print pAlias + " " + `numVals`
+							#print pDescr
+							
+							comms = categoryDescriptor + " " + pDescr
+
+							if numVals == 'predefined':		# dropdown list of values
+								
+								if not sHandler.existsSetGroup(propCatID):
+									ssetGroupID = sHandler.addSetGroupID(propCatID, comms)
+								else:
+									ssetGroupID = sHandler.findPropSetGroupID(propCatID)
+								
+								#print ssetGroupID
+								
+								sHandler.deleteReagentTypeAttributeSetValues(rTypeAttrID)
+
+								propVals = form.getlist("propertyValues_" + (category + "_:_" + pAlias).replace("'", "\\'"))
+								
+								for pVal in propVals:
+									sID = sHandler.findSetValueID(ssetGroupID, pVal)
+									
+									if sID <= 0:
+										sID = sHandler.addSetValue(ssetGroupID, pVal)
+									
+									if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttrID, sID):
+										sHandler.addReagentTypeAttributeSetEntry(rTypeAttrID, sID)
+								
+								# moved here on May 28/10: do this intelligently!
+								
+								# customizable
+								if form.has_key("allowOther_" + category + "_:_" + pAlias):
+									rtPropHandler.makeCustomizeable(rTypeAttrID)
+								else:
+									rtPropHandler.removeCustomizeable(rTypeAttrID)
+								
+								# Apr. 29, 2010: Hyperlinks and multiples
+								if form.has_key("isMultiple_" + category + "_:_" + pAlias):
+									rtPropHandler.makeMultiple(rTypeAttrID)
+								else:
+									rtPropHandler.makeSingle(rTypeAttrID)
+								
+								rtPropHandler.removeHyperlink(rTypeAttrID)
+
+							else:
+								# Freetext; check if change from dropdown
+								if numVals != oldInputFormat:
+									ssetGroupID = sHandler.findPropSetGroupID(propCatID)
+									
+									# change dropdown to freetext
+									sHandler.deleteReagentTypeAttributeSetValues(rTypeAttrID)
+									
+								if form.has_key("hyperlink_" + category + "_:_" + pAlias):
+									#print "MAKING HYPERLINK"
+									rtPropHandler.makeHyperlink(rTypeAttrID)
+								else:
+									rtPropHandler.removeHyperlink(rTypeAttrID)
+									
+								# remove dropdown attributes
+								rtPropHandler.makeSingle(rTypeAttrID)
+								rtPropHandler.removeCustomizeable(rTypeAttrID)
+
+						else:
+							#print category
+							tmp_new_props = all_newProps[category]
+							#print `tmp_new_props`
+							
+							for tmp_alias in tmp_new_props:
+								#newPropAlias = pAlias
+								
+								# Final decision Nov. 19/09: Make LOWERCASE
+								newPropAlias = tmp_alias.lower()
+								
+								if form.has_key("newPropDescr_" + category + "_:_" + tmp_alias):
+									descriptions = form.getvalue("newPropDescr_" + category + "_:_" + tmp_alias)	# is this a list?
+									#print `descriptions`
+									
+									if utils.isList(descriptions):
+										for pDescr in descriptions:
+											# Final decision Nov. 19/09: Make LOWERCASE
+											pName = pDescr.lower()
+									else:
+										pDescr = descriptions
+										
+										# Final decision Nov. 19/09: Make LOWERCASE
+										pName = pDescr.lower()
+								else:
+									pDescr = newPropAlias
+									
+									if pDescr.find(category + "_:_" + newPropAlias + "_:_") == 0:
+										pDescr = pDescr[len(category + "_:_" + newPropAlias + "_:_"):]
+										
+									# Final decision Nov. 19/09: Make LOWERCASE
+									pName = pDescr.lower()
+	
+								if not pHandler.existsReagentPropertyType(pName):
+									# correction June 22/09: don't include category in arguments list
+									newPropID = pHandler.addReagentPropertyType(pName, newPropAlias, pDescr, isSeqFeature)
+								else:
+									newPropID = pHandler.findPropID(pName)
+
+								#print newPropID
+								
+								tmpCatID = pHandler.findReagentPropertyInCategoryID(newPropID, categoryID)
+								
+								if tmpCatID <= 0:
+									tmpCatID = pHandler.addReagentPropertyToCategory(newPropID, categoryID)
+									
+								#print tmpCatID
+								
+								# isn't the check for existence redundant?  this is a new property!
+								if not rtPropHandler.existsReagentTypeAttribute(rTypeID, tmpCatID):
+									rTypeAttrID = rtPropHandler.addReagentTypeAttribute(rTypeID, tmpCatID)
+								else:
+									rTypeAttrID = rtPropHandler.findReagentTypeAttributeID(rTypeID, tmpCatID)
+									
+								#print rTypeAttrID
+								
+								#print propCatID
+								
+								if tmpCatID > 0 and form.has_key("propOrder_" + `tmpCatID`):
+									pOrder = form.getvalue("propOrder_" + `tmpCatID`)
+									#print "Setting order " + `pOrder` + " for " + pAlias
+									rtPropHandler.setReagentTypeAttributeOrdering(rTypeAttrID, pOrder)
+								else:
+									#print "HERE!!! this is a new property!!"
+									tmp_prop_cat_alias = category + "_:_" + tmp_alias
+									
+									if form.has_key("propOrder_" + tmp_prop_cat_alias):
+										pOrder = form.getvalue("propOrder_" + tmp_prop_cat_alias)
+										rtPropHandler.setReagentTypeAttributeOrdering(rTypeAttrID, pOrder)
+
+								# update list for multiple values
+								numVals = form.getvalue("num_vals_" + category + "_:_" + tmp_alias)	# THIS IS RIGHT
+								#print `numVals`
+								
+								if numVals == 'predefined':		# dropdown list of values
+									
+									# moved here May 28/10: do this intelligently
+									
+									# Apr. 29, 2010: Hyperlinks and multiples
+									if form.has_key("isMultiple_" + tmp_prop_cat_alias):
+										#print "MAKING MULTIPLE"
+										rtPropHandler.makeMultiple(rTypeAttrID)
+									else:
+										rtPropHandler.makeSingle(rTypeAttrID)
+										
+									if form.has_key("allowOther_" + tmp_prop_cat_alias):
+										rtPropHandler.makeCustomizeable(rTypeAttrID)
+									else:
+										rtPropHandler.removeCustomizeable(rTypeAttrID)
+									
+									rtPropHandler.removeHyperlink(rTypeAttrID)
+									
+									propVals = form.getlist("propertyValues_" + category + "_:_" + tmp_alias)
+									
+									comms = categoryDescriptor + " " + pName
+									
+									if not sHandler.existsSetGroup(tmpCatID):
+										ssetGroupID = sHandler.addSetGroupID(tmpCatID, comms)
+									else:
+										ssetGroupID = sHandler.findPropSetGroupID(tmpCatID)
+									
+									sHandler.deleteReagentTypeAttributeSetValues(rTypeAttrID)
+			
+									#print `propVals`
+									for pVal in propVals:
+										if pVal != 'default':
+											#print pVal
+											#setComms = rTypeName + " " + pDescr
+											#print setComms
+											#sHandler.updateSet(rTypeAttrID, setComms, pVal)
+											sID = sHandler.findSetValueID(ssetGroupID, pVal)
+										
+											if sID <= 0:
+												sID = sHandler.addSetValue(ssetGroupID, pVal)
+											
+											if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttrID, sID):
+												sHandler.addReagentTypeAttributeSetEntry(rTypeAttrID, sID)
+								# Added May 28, 2010
+								else:
+									if form.has_key("hyperlink_" + tmp_prop_cat_alias):
+										#print "MAKING HYPERLINK"
+										rtPropHandler.makeHyperlink(rTypeAttrID)
+									else:
+										rtPropHandler.removeHyperlink(rTypeAttrID)
+				
+									rtPropHandler.removeCustomizeable(rTypeAttrID)
+									rtPropHandler.makeSingle(rTypeAttrID)
+
+			rtOut.printReagentTypeView(rTypeID)
+
+	# Let user define property input format
+	def previewReagentTypePropertyValues(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		rtHandler = ReagentTypeHandler(db, cursor)
+		pHandler = ReagentPropertyHandler(db, cursor)
+		
+		propMapper = ReagentPropertyMapper(db, cursor)
+		
+		rtOut = ReagentTypeOutputClass()
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		prop_Alias_ID_Map = propMapper.mapPropAliasID()			# (propAlias, propID) - e.g. ('insert_type', '48')
+		category_Alias_ID_Map = propMapper.mapPropCategoryAliasID()
+		
+		catDescrDict = {}	# categoryAlias, categoryDescription
+		categoryProps = {}	# categoryAlias, rTypeProps (see below)
+		
+		if form.has_key("reagentTypeName"):
+			rTypeName = form.getvalue("reagentTypeName")		# capitalize first letter????  NO!!!
+		
+		if form.has_key("reagentTypePrefix"):
+			# should the prefix always be capitalized?? --> Karen: YES --> Marina Oct. 22/09: NO.  What if want "Ri" prefix for RNAi??  Don't capitalize!!
+			rTypePrefix = form.getvalue("reagentTypePrefix")
+	
+		# June 11/09: Select only one sequence type
+		sequenceTypeCategoryAliases = {"DNA Sequence":["sequence_properties", "dna_sequence_features"], "Protein Sequence":["protein_sequence_properties", "protein_sequence_features"], "RNA Sequence":["rna_sequence_properties", "rna_sequence_features"]}
+	
+		ignoreSequenceAttributes = []
+		
+		if form.has_key("sequenceType"):
+			sequenceType = form.getvalue("sequenceType")
+			
+			if sequenceType == "None":
+				ignoreSequenceAttributes = ["protein_sequence_properties", "protein_sequence_features", "rna_sequence_properties", "rna_sequence_features", "sequence_properties", "dna_sequence_features"]
+				
+			elif sequenceType == "DNA Sequence":
+				ignoreSequenceAttributes = ["protein_sequence_properties", "protein_sequence_features", "rna_sequence_properties", "rna_sequence_features"]
+				
+			elif sequenceType == "Protein Sequence":
+				ignoreSequenceAttributes = ["rna_sequence_properties", "rna_sequence_features", "sequence_properties", "dna_sequence_features"]
+				
+			elif sequenceType == "RNA Sequence":
+				ignoreSequenceAttributes = ["protein_sequence_properties", "protein_sequence_features", "sequence_properties", "dna_sequence_features"]
+			
+			#for st in sequenceTypeCategoryAliases.keys():
+				#if st != sequenceType:
+					#ignore_props_list = sequenceTypeCategoryAliases[st]
+					#ignoreSequenceAttributes += ignore_props_list
+
+		#print "to ignore " + `ignoreSequenceAttributes`
+		
+		if form.has_key("category[]"):
+			categories = form.getlist("category[]")
+			#print `categories`
+			
+			for category in categories:	# this is an alias, e.g. "general_properties" => 'General Properties'
+				rTypeProps = {}		# propAlias, propDescr
+				
+				# Dec. 4/09: Remove this - sequence is not saved
+				#if len(ignoreSequenceAttributes) > 0 and category not in ignoreSequenceAttributes:
+				if category not in ignoreSequenceAttributes:
+					
+					#print "Category: " + category
+	
+					# April 15, 2009
+					categoryDescriptor = form.getvalue("category_descriptor_" + category)
+					#print categoryDescriptor
+	
+					categoryDescriptor = categoryDescriptor.replace('%', '%%')
+	
+					checkboxAliases = form.getlist("createReagentType_" + category+"[]") + form.getlist(category+"[]")
+	
+					# Aug. 13/09: Don't save empty categories
+					if len(checkboxAliases) > 0:
+						catDescrDict[category] = categoryDescriptor
+		
+					#print `checkboxAliases`
+					
+					for cbAlias in checkboxAliases:
+						#print "Alias " + cbAlias
+						cbAlias = cbAlias.strip()
+						#print cbAlias
+						
+						if cbAlias == 'type':
+							# prepend reagent type name to it
+							pDescr = rTypeName + " Type"
+							pAlias = string.join(rTypeName.split(" "), "_") + "_type"
+							#print pDescr
+						
+						# Update Dec. 1/09
+						elif form.has_key("createReagentType_" + category + "_:_" + cbAlias):
+							tmpDescr = form.getvalue("createReagentType_" + category + "_:_" + cbAlias)
+							
+							if pHandler.findPropertyDescriptionFromAlias(cbAlias) > 0:
+								pAlias = cbAlias
+								pDescr = pHandler.findPropertyDescriptionFromAlias(pAlias)
+								pName = pDescr.lower()
+							
+							elif pHandler.findPropertyAliasFromDescription(tmpDescr):
+								pAlias = pHandler.findPropertyAliasFromDescription(tmpDescr)
+								pDescr = tmpDescr
+								pName = pDescr.lower()
+								
+							#elif form.has_key(category + "_:_" + cbAlias):
+								#pAlias = cbAlias
+								#pDescr = form.getvalue(category + "_:_" + cbAlias)
+								#pName = pDescr.lower()
+							
+							else:
+								pAlias = cbAlias
+								pDescr = tmpDescr
+								pName = pDescr.lower()
+								
+								#print "Content-type:text/html"
+								#print
+								#print "Unknown alias: " + pAlias
+							
+						# Existing properties
+						elif pHandler.findPropertyDescriptionFromAlias(cbAlias) > 0:
+							pDescr = pHandler.findPropertyDescriptionFromAlias(cbAlias)
+							pName = pDescr.lower()
+							pAlias = cbAlias
+						
+						else:
+							print "Content-type:text/html"
+							print
+							print "Unknown alias: " + cbAlias
+						
+						#print "Category " + category + ", description " + `pDescr`
+						
+						pAlias = pAlias.replace('%', '%%')
+	
+						# added check for list June 18/09 - catch duplicates
+						if utils.isList(pDescr):
+							for desc in pDescr:
+								desc = desc.replace('%', '%%')
+								pName = desc.lower()
+								
+								# use one dictionary for all props - June 17/09 update: don't store duplicate values
+								if not desc in rTypeProps.values():
+									rTypeProps[pAlias] = desc
+						else:
+							#print "Name " + `pDescr`
+							pDescr = pDescr.replace('%', '%%')
+							pName = pDescr.lower()
+							
+							# use one dictionary for all props - June 17/09 update: don't store duplicate values
+							if not pDescr in rTypeProps.values():
+								rTypeProps[pAlias] = pDescr
+	
+						# add descriptors - nov. 1/09: why the 'if not new' restriction??
+						#if pAlias.lower() == prop_Name_Alias_Map["tag type"] and not form.has_key("is_new_" + category + "_:_" + pAlias):
+						
+						#print "final alias: " + pAlias
+						
+						# HARD-CODE (Nov. 1/09)
+						#if pAlias.lower() == prop_Name_Alias_Map["tag type"]:
+						if pDescr.lower() == "tag":
+							rTypeProps["tag_position"] = "Tag Position"
+							
+						#if pAlias.lower() == prop_Name_Alias_Map["promoter"] and not form.has_key("is_new_" + category + "_:_" + pAlias):
+						if pAlias.lower() == prop_Name_Alias_Map["promoter"]:
+							rTypeProps["expression_system"] = "Expression System"
+						
+					#print "Category " + category + ", description " + pDescr
+					#print `rTypeProps`
+					
+					#print "Description " + pDescr
+					
+					category = category.replace('%', '%%')
+					
+					# check again for non-empty props list
+					if len(rTypeProps) > 0:
+						categoryProps[category] = rTypeProps
+
+		#print `rTypeProps`
+		#print `categoryProps`
+		
+		# Aug. 11/09: Save associations
+		if form.has_key("addReagentTypeParents"):
+			parents = form.getlist("addReagentTypeParents")
+		else:
+			parents = []
+		
+		if form.has_key("addReagentTypeChildren"):
+			children = form.getlist("addReagentTypeChildren")
+
+		# Go to step 2 IFF there are properties whose values need to be set
+		if len(categoryProps) > 0:
+			if form.has_key("save_rtype"):
+				rtOut.printReagentTypeCreationPage(rTypeName, rTypePrefix, 3, catDescrDict, categoryProps, parents)
+			else:
+				rtOut.printReagentTypeCreationPage(rTypeName, rTypePrefix, 2, catDescrDict, categoryProps, parents)
+				
+		# otherwise just process changes
+		else:
+			self.updateReagentType(form)
+		
+
+	# Save all properties for new reagent type creation
+	def createReagentType(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+
+		rtHandler = ReagentTypeHandler(db, cursor)			# April 3/09
+		pHandler = ReagentPropertyHandler(db, cursor)
+		sHandler = SystemSetHandler(db, cursor)
+
+		propMapper = ReagentPropertyMapper(db, cursor)
+
+		prop_Alias_ID_Map = propMapper.mapPropAliasID()			# (propAlias, propID) - e.g. ('insert_type', '48')
+		
+		category_Alias_ID_Map = propMapper.mapPropCategoryAliasID()
+		#print `category_Alias_ID_Map`
+
+		if form.has_key("reagentTypeName"):
+			rTypeName = form.getvalue("reagentTypeName")		# capitalize first letter????  NO!!!!!
+		
+		if form.has_key("reagentTypePrefix"):
+			rTypePrefix = form.getvalue("reagentTypePrefix")	# should the prefix always be capitalized??  NO!!!!!
+	
+		# create a new reagent type table entry
+		if not rtHandler.existsReagentType(rTypeName, rTypePrefix):
+			newRTypeID = rtHandler.addReagentType(rTypeName, rTypePrefix)
+		else:
+			newRTypeID = rtHandler.findReagentTypeID(rTypeName)
+
+		#print newRTypeID
+		
+		# For new properties, save predefined values
+		cat_newProps = form.getlist("newPropName")
+		all_newProps = {}
+		
+		cursor.execute("SELECT MAX(propertyID) FROM ReagentPropType_tbl")
+		result = cursor.fetchone()
+		nextPropID = int(result[0]) + 1
+		
+		#print `cat_newProps`
+		
+		for c_prop in cat_newProps:
+			pList = []
+
+			if c_prop.find("_:_") >= 0:
+				tmpStart = c_prop.index("_:_")
+				tmpEnd = tmpStart + len("_:_")
+				tmpCat = c_prop[0:tmpStart]
+				newProp = c_prop[tmpEnd:]
+				
+				newProp = newProp.replace("\\'", "'")
+				
+				if all_newProps.has_key(tmpCat):
+					pList = all_newProps[tmpCat]
+					
+					if newProp not in pList:
+						pList.append(newProp)
+						all_newProps[tmpCat] = pList
+				else:
+					pList = []
+					pList.append(newProp)
+					all_newProps[tmpCat] = pList
+		
+		#print "New: " + `all_newProps`
+
+		# NO!!!!!!!!  What if category/properties are NEW, not in map?????
+		#propsToRemove = []
+
+		## Feb. 1/10: do removal here, doesn't work otherwise
+		#for cat_alias in category_Alias_ID_Map.keys():
+			#cat_id = category_Alias_ID_Map[cat_alias]
+			#allCatPropIDs = pHandler.findPropertiesByCategory(cat_id)
+			
+			#for pID in allCatPropIDs:
+				#pAlias = prop_ID_Alias_Map[pID]
+				
+				#if form.has_key("remove_" + cat_alias + "_:_" + pAlias + "_prop"):
+					#rmvFlag = form.getvalue("remove_" + cat_alias + "_:_" + pAlias + "_prop")
+					
+					#if rmvFlag == "1":
+						#propsToRemove.append(pAlias)
+						#pcID = pHandler.findReagentPropertyInCategoryID(pID, cat_id)
+						#rtPropHandler.deleteReagentTypeAttribute(newRTypeID, pcID)
+		
+		# Save remaining properties as attributes of this reagent type
+		if form.has_key("category[]"):
+			categories = form.getlist("category[]")
+			#print "All categories: " + `categories`
+
+			for category in categories:	# this is an alias, e.g. "general_properties" => 'General Properties'
+				#print category
+				
+				# Jan. 26/10: need to record special info for features, e.g. colour
+				if category == category_Name_Alias_Map["DNA Sequence Features"] or category == category_Name_Alias_Map["RNA Sequence Features"] or category == category_Name_Alias_Map["Protein Sequence Features"]:
+					isSeqFeature = True
+				else:
+					isSeqFeature = False
+				
+				if all_newProps.has_key(category):
+					newProps = all_newProps[category]
+				else:
+					newProps = []
+				
+				categoryDescriptor = form.getvalue("category_descriptor_" + category)
+				
+				categoryDescriptor = categoryDescriptor.replace("\\'", "'")
+				#print "??" + categoryDescriptor + "!!"
+				
+				if not pHandler.existsReagentPropertyCategory(categoryDescriptor) or not category_Alias_ID_Map.has_key(category):
+					categoryID = pHandler.addReagentPropertyCategory(categoryDescriptor, category)
+				else:
+					categoryID = category_Alias_ID_Map[category]
+				
+				#print `categoryID`
+				
+				propAliases = form.getlist(category+"[]")
+				#print `propAliases`
+				#print `propsToRemove`
+				
+				#print `newProps`
+				
+				for pAlias in propAliases:
+					#print pAlias
+					
+					pAlias = pAlias.replace("\\'", "'")	# Nov. 1/09: make lowercase??
+					#pAlias = pAlias.replace("'", "prime")
+					#print "SAVING " + pAlias
+					
+					#if form.has_key("remove_" + category + "_:_" + pAlias + "_prop"):
+						##print "REMOVING " + pAlias
+						#rmvFlag = form.getvalue("remove_" + category + "_:_" + pAlias + "_prop")
+						##print "remove_" + category + "_:_" + pAlias + "_prop"
+						
+						#if rmvFlag == "1":
+							#continue
+					# this is just a debugging print statement
+					#else:
+						#print "NOT remove " + pAlias
+					
+					if pAlias == rTypeName + "_type":
+						# prepend reagent type name to it
+						#pAlias = rTypeName + "_type"
+						pName = rTypeName + " type"
+						pDescr = rTypeName + " Type"
+						
+						newPropAlias = category + "_:_" + pAlias
+						
+						# 'if exists' added June 17/09
+						if not pHandler.existsReagentPropertyType(pName):
+							# correction June 22/09: don't include category in argument list
+							# (obviously this is not a feature, no need to set parameter - jan. 26/10)
+							newPropID = pHandler.addReagentPropertyType(pName, pAlias, pDescr)
+						else:
+							#newPropID = prop_Alias_ID_Map[pAlias]
+							newPropID = pHandler.findPropID(pName, True)
+						
+						#print pAlias
+						#print newPropID
+
+						# added June 17/09
+						if not pHandler.existsPropertyInCategory(newPropID, categoryID):
+							#print "here??"
+							propCatID = pHandler.addReagentPropertyToCategory(newPropID, categoryID)
+						else:
+							propCatID = pHandler.findReagentPropertyInCategoryID(newPropID, categoryID)
+
+						#print `propCatID`
+
+						# 'if exists' added June 17/09
+						if not rtPropHandler.existsReagentTypeAttribute(newRTypeID, propCatID):
+							rTypeAttrID = rtPropHandler.addReagentTypeAttribute(newRTypeID, propCatID)
+						else:
+							rTypeAttrID = rtPropHandler.findReagentTypeAttributeID(newRTypeID, propCatID)
+						
+						# NOOO, this is a NEW property, where would propCatID come from??
+						if propCatID > 0 and form.has_key("propOrder_" + `propCatID`):
+							pOrder = form.getvalue("propOrder_" + `propCatID`)
+							#print "Setting order " + `pOrder` + " for " + pAlias
+							rtPropHandler.setReagentTypeAttributeOrdering(rTypeAttrID, pOrder)
+						else:
+							#print "HERE!!! this is a new property!!"
+							tmp_prop_cat_alias = category + "_:_" + pAlias
+							
+							if form.has_key("propOrder_" + tmp_prop_cat_alias):
+								pOrder = form.getvalue("propOrder_" + tmp_prop_cat_alias)
+								rtPropHandler.setReagentTypeAttributeOrdering(rTypeAttrID, pOrder)
+						
+						# June 16, 2010
+						rtPropHandler.makeSingle(rTypeAttrID)
+						rtPropHandler.removeCustomizeable(rTypeAttrID)
+						
+						if form.has_key("hyperlink_" + newPropAlias):
+							#print "MAKING HYPERLINK"
+							rtPropHandler.makeHyperlink(rTypeAttrID)
+						else:
+							rtPropHandler.removeHyperlink(rTypeAttrID)
+		
+						# update list for multiple values
+						numVals = form.getvalue("num_vals_" + newPropAlias)
+						
+						#print numVals
+						
+						if numVals == 'predefined':		# dropdown list of values
+							#print newPropAlias
+							
+							# June 16, 2010
+							rtPropHandler.removeHyperlink(rTypeAttrID)
+							
+							# Apr. 29, 2010: Hyperlinks and multiples
+							if form.has_key("isMultiple_" + newPropAlias):
+								#print "MAKING MULTIPLE"
+								rtPropHandler.makeMultiple(rTypeAttrID)
+							else:
+								rtPropHandler.makeSingle(rTypeAttrID)
+							
+							if form.has_key("allowOther_" + newPropAlias):
+								rtPropHandler.makeCustomizeable(rTypeAttrID)
+							else:
+								rtPropHandler.removeCustomizeable(rTypeAttrID)
+							
+							comms = categoryDescriptor + " " + pName
+							
+							if not sHandler.existsSetGroup(propCatID):
+								ssetGroupID = sHandler.addSetGroupID(propCatID, comms)
+							else:
+								ssetGroupID = sHandler.findPropSetGroupID(propCatID)
+							
+							propVals = form.getlist("propertyValues_" + newPropAlias)
+							#print `propVals`
+							
+							for pVal in propVals:
+								if pVal != 'default':
+									#print pVal
+									#sHandler.updateSet(pName, pVal)
+									#setComms = pDescr
+									#sHandler.updateSet(rTypeAttrID, setComms, pVal)
+									sID = sHandler.findSetValueID(ssetGroupID, pVal)
+									
+									if sID <= 0:
+										sID = sHandler.addSetValue(ssetGroupID, pVal)
+									
+									if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttrID, sID):
+										sHandler.addReagentTypeAttributeSetEntry(rTypeAttrID, sID)
+
+					elif pAlias not in newProps:
+						pAlias = pAlias.lower()
+						#print "Alias existing: " + pAlias
+
+						# think I've stripped category from the alias already but test more to make sure
+						#if pAlias.find(category + "_:_") == 0:
+							#pAlias = pAlias[len(category + "_:_"):]
+
+						tmpPropID = pHandler.findPropertyIDFromAlias(pAlias)
+						#print `prop_Alias_ID_Map`
+
+						#tmpPropID = prop_Alias_ID_Map[pAlias]
+						#pDescr = prop_Alias_Desc_Map[pAlias]	# nov. 1/09: verify this
+
+						pDescr = pHandler.findPropertyDescriptionFromAlias(pAlias)
+						
+						#removeFlag = form.getvalue("remove_" + (category + "_:_" + pAlias).replace("'", "\\'") + "_prop")
+						
+						#if removeFlag == "1":
+							##print "REMOVING " + pAlias + " from category " + category
+
+							#if pHandler.existsPropertyInCategory(tmpPropID, categoryID):
+								#propCatID = pHandler.findReagentPropertyInCategoryID(tmpPropID, categoryID)
+								#rtPropHandler.deleteReagentTypeAttribute(newRTypeID, propCatID)
+							
+						#else:
+						if not pHandler.existsPropertyInCategory(tmpPropID, categoryID):
+							#print "Adding property " + pAlias + " to category " + `categoryID`
+							propCatID = pHandler.addReagentPropertyToCategory(tmpPropID, categoryID)
+						else:
+							propCatID = pHandler.findReagentPropertyInCategoryID(tmpPropID, categoryID)
+						
+						#print propCatID
+						
+						if not rtPropHandler.existsReagentTypeAttribute(newRTypeID, propCatID):
+							rTypeAttrID = rtPropHandler.addReagentTypeAttribute(newRTypeID, propCatID)
+						else:
+							rTypeAttrID = rtPropHandler.findReagentTypeAttributeID(newRTypeID, propCatID)
+					
+						#print rTypeAttrID
+						
+						# April 20, 2010
+						if propCatID > 0 and form.has_key("propOrder_" + `propCatID`):
+							pOrder = form.getvalue("propOrder_" + `propCatID`)
+							#print "Setting order " + `pOrder` + " for " + pAlias
+							rtPropHandler.setReagentTypeAttributeOrdering(rTypeAttrID, pOrder)
+						else:
+							#print "HERE!!! this is a new property!!"
+							tmp_prop_cat_alias = category + "_:_" + pAlias
+							
+							if form.has_key("propOrder_" + tmp_prop_cat_alias):
+								pOrder = form.getvalue("propOrder_" + tmp_prop_cat_alias)
+								rtPropHandler.setReagentTypeAttributeOrdering(rTypeAttrID, pOrder)
+
+						# June 16, 2010
+						rtPropHandler.makeSingle(rTypeAttrID)
+						rtPropHandler.removeCustomizeable(rTypeAttrID)
+						
+						if form.has_key("hyperlink_" + category + "_:_" + pAlias):
+							#print "MAKING HYPERLINK"
+							rtPropHandler.makeHyperlink(rTypeAttrID)
+						else:
+							rtPropHandler.removeHyperlink(rTypeAttrID)
+	
+						# Still have to update dropdown set
+						numVals = form.getvalue("num_vals_" + category + "_:_" + pAlias)
+						#print category  + ": " + `numVals`
+						
+						if numVals == 'predefined':		# dropdown list of values
+							propVals = form.getlist("propertyValues_" + category + "_:_" + pAlias)
+							#print `propVals`
+							
+							# June 16, 2010
+							rtPropHandler.removeHyperlink(rTypeAttrID)
+	
+							# Apr. 29, 2010: Hyperlinks and multiples
+							if form.has_key("isMultiple_" + category + "_:_" + pAlias):
+								#print "MAKING MULTIPLE " + pAlias
+								rtPropHandler.makeMultiple(rTypeAttrID)
+							else:
+								rtPropHandler.makeSingle(rTypeAttrID)
+							
+							if form.has_key("allowOther_" + category + "_:_" + pAlias):
+								rtPropHandler.makeCustomizeable(rTypeAttrID)
+							else:
+								rtPropHandler.removeCustomizeable(rTypeAttrID)
+								
+							comms = categoryDescriptor + " " + pDescr
+							
+							if not sHandler.existsSetGroup(propCatID):
+								ssetGroupID = sHandler.addSetGroupID(propCatID, comms)
+							else:
+								ssetGroupID = sHandler.findPropSetGroupID(propCatID)
+							
+							for pVal in propVals:
+								if pVal != 'default':
+									#print pVal
+									#sHandler.updateSet(pName, pVal)
+									#setComms = rTypeName + " " + pDescr
+									#sHandler.updateSet(rTypeAttrID, setComms, pVal)
+									sID = sHandler.findSetValueID(ssetGroupID, pVal)
+									
+									if sID <= 0:
+										sID = sHandler.addSetValue(ssetGroupID, pVal)
+									
+									if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttrID, sID):
+										sHandler.addReagentTypeAttributeSetEntry(rTypeAttrID, sID)
+					else:
+						######################################################################################
+						# Oct. 27/09: This might be a completely new property that does not exist in the database.
+						#
+						# Alternatively, it could be an existing property under a different category.
+						#
+						# However, property names don't always correspond to property descriptions in lowercase (hence the distinction between the table columns) - e.g. 'mw' propertyName => 'Molecular Weight (MW)' description, or 'tag type' propertyName ==> 'Tag' description.  Attempting to match property ID by assuming propertyMame is lowercase description and searching for it is not correct.
+						#
+						# Either search by the description provided, OR rely on the alias.
+						######################################################################################
+						
+						#print "NEW " + pAlias
+						#print category
+						
+						tmp_new_props = all_newProps[category]
+						#print `tmp_new_props`
+						
+						for tmp_alias in tmp_new_props:
+							#print tmp_alias
+							
+							#newPropAlias = pAlias
+							newPropAlias = tmp_alias.lower()	# ?????????
+							#print newPropAlias + ", " + pAlias
+							
+							temp_val = (category + "_:_" + tmp_alias).replace("'", "\\'")
+							
+							if form.has_key("newPropDescr_" + category + "_:_" + tmp_alias):
+								descriptions = form.getvalue("newPropDescr_" + category + "_:_" + tmp_alias)	# is this a list?
+								#print `descriptions`
+								
+								if utils.isList(descriptions):
+									for pDescr in descriptions:
+										#if prop_Desc_Name_Map.has_key(pDescr):
+										if pHandler.findPropNameByDescription(pDescr):
+											pName = pHandler.findPropNameByDescription(pDescr)
+											#pName = prop_Desc_Name_Map[pDescr]
+										else:
+											# Nov. 3/09: CHECK FOR EXISTENCE ***IN ANY CASE***
+											# Because might end up w/ smtg like 'Tag Type' being added => the name 'tag type' exists, even though its description is 'Tag'.
+										
+											if not phandler.existsPropertyName(pDescr.lower()):
+												pName = pDescr.lower()	# Nov. 2/09: yes, make lowercase!!
+											else:
+												# Nov. 1/09: Generate a NEW name
+												pName = pDescr.lower() + `nextPropID`
+								else:
+									pDescr = descriptions
+									
+									if pHandler.findPropNameByDescription(pDescr):
+									#if prop_Desc_Name_Map.has_key(pDescr):
+										#pName = prop_Desc_Name_Map[pDescr]
+										pName = pHandler.findPropNameByDescription(pDescr)
+	
+										#print "name found " + pName
+									else:
+										# Oct. 29/09: This is a new description.  However, the alias or name may exist! - e.g. "Tag Type" description would map to 'Tag_Type' alias in lowercase => and the name would be 'tag type'.  No good!  If description is not found here, still check name and alias!!
+	
+										#if prop_Alias_ID_Map.has_key(newPropAlias):
+										if pHandler.findPropertyIDFromAlias(newPropAlias) > 0:
+											# make a new table entry - the description provided by the user, a new alias and a new name
+											newPropAlias = newPropAlias + "_" + `nextPropID`	# don't make lowercase
+	
+											#print "changed alias"
+	
+											# check name
+											#if prop_Desc_Name_Map.has_key(pDescr):
+											if pHandler.findPropNameByDescription(pDescr):
+												# Different description and alias but same name => make a new entry, just not lowercase
+												pName = pDescr.lower() + "_" + `nextPropID`
+											else:
+												# still check for existence!!! (nov. 1/09)
+												if not pHandler.existsPropertyName(pDescr.lower()):
+													pName = pDescr.lower()	# Nov. 2/09: yes, make lowercase!!
+												else:
+													# Nov. 1/09: Generate a NEW name
+													pName = pDescr.lower() + `nextPropID`
+										
+												#pName = pDescr.lower()	# Nov. 1/09
+										else:
+											# descr and alias are new; check name
+											if pHandler.findPropNameByDescription(pDescr):
+											#if prop_Desc_Name_Map.has_key(pDescr):
+												# Different description and alias but same name => make a new entry
+												pName = pDescr.lower() + "_" + `nextPropID`
+											else:
+												# check for existence again
+												if not pHandler.existsPropertyName(pDescr.lower()):
+													pName = pDescr.lower()	# Nov. 2/09: yes, make lowercase!!
+												else:
+													# Nov. 1/09: Generate a NEW name
+													pName = pDescr.lower() + `nextPropID`
+										
+												#pName = pDescr.lower()
+	
+										#print "name " + pName
+								
+								# increment here
+								nextPropID += 1
+								
+							elif form.has_key("newPropDescr_" + temp_val):
+								descriptions = form.getvalue("newPropDescr_" + temp_val)
+								
+								if utils.isList(descriptions):
+									for pDescr in descriptions:
+										#if prop_Desc_Name_Map.has_key(pDescr):
+										if pHandler.findPropNameByDescription(pDescr):
+											#pName = prop_Desc_Name_Map[pDescr]
+											pName = pHandler.findPropNameByDescription(pDescr)
+										else:
+											#pName = pDescr.lower()
+										
+											if not pHandler.existsPropertyName(pDescr.lower()):
+												pName = pDescr.lower()	# Nov. 2/09: yes, make lowercase!!
+											else:
+												# Nov. 1/09: Generate a NEW name
+												pName = pDescr.lower() + `nextPropID`
+								else:
+									pDescr = descriptions
+									
+									#if prop_Desc_Name_Map.has_key(pDescr):
+									if pHandler.findPropNameByDescription(pDescr):
+										pName = pHandler.findPropNameByDescription(pDescr)
+										#pName = prop_Desc_Name_Map[pDescr]
+									else:
+										#pName = pDescr.lower()
+										
+										if not pHandler.existsPropertyName(pDescr.lower()):
+											pName = pDescr.lower()	# Nov. 2/09: yes, make lowercase!!
+										else:
+											# Nov. 1/09: Generate a NEW name
+											pName = pDescr.lower() + `nextPropID`
+							else:
+								pDescr = newPropAlias
+								
+								if pDescr.find(category + "_:_" + newPropAlias + "_:_") == 0:
+									pDescr = pDescr[len(category + "_:_" + newPropAlias + "_:_"):]
+								
+								#if prop_Desc_Name_Map.has_key(pDescr):
+								if pHandler.findPropNameByDescription(pDescr):
+									pName = pHandler.findPropNameByDescription(pDescr)
+									#pName = prop_Desc_Name_Map[pDescr]
+								else:
+									#pName = pDescr.lower()
+									
+									if not pHandler.existsPropertyName(pDescr.lower()):
+										pName = pDescr.lower()	# Nov. 2/09: yes, make lowercase!!
+									else:
+										# Nov. 1/09: Generate a NEW name
+										pName = pDescr.lower() + `nextPropID`
+							
+							#print pName
+							#print pDescr
+	
+							#print `prop_Desc_ID_Map`
+	
+							#if not pHandler.existsReagentPropertyType(pName, True):
+							if pHandler.findPropIDByDescription(pDescr) <= 0:
+							#if not prop_Desc_ID_Map.has_key(pDescr):
+								# correction June 22/09: don't include category in arguments list
+								newPropID = pHandler.addReagentPropertyType(pName, newPropAlias, pDescr, isSeqFeature)
+								#print newPropID
+							else:
+								#print "what, here??"
+								#newPropID = pHandler.findPropID(pName, True)
+	
+								# Nov. 1/09: don't search by name, search description!
+								newPropID = pHandler.findPropIDByDescription(pDescr)
+								
+							#print newPropID
+							
+							tmpCatID = pHandler.findReagentPropertyInCategoryID(newPropID, categoryID)
+							
+							if tmpCatID <= 0:
+								tmpCatID = pHandler.addReagentPropertyToCategory(newPropID, categoryID)
+								
+							#print tmpCatID
+							
+							#removeFlag = form.getvalue("remove_" + (category + "_:_" + newPropAlias).replace("'", "\\'") + "_prop")
+							
+							#print "remove_" + category + "_:_" + pAlias + "_prop"
+							#print "?? " + removeFlag + "!!"
+							
+							#if not removeFlag or removeFlag != "1":
+								#print newPropID
+							
+							# isn't the check for existence redundant?  this is a new property!
+							if not rtPropHandler.existsReagentTypeAttribute(newRTypeID, tmpCatID):
+								rTypeAttrID = rtPropHandler.addReagentTypeAttribute(newRTypeID, tmpCatID)
+								#print "rtypeattr " + `rTypeAttrID`
+							else:
+								rTypeAttrID = rtPropHandler.findReagentTypeAttributeID(newRTypeID, tmpCatID)
+							
+							# April 20, 2010
+							# this is highly unlikely but keep for robustness
+							if propCatID > 0 and form.has_key("propOrder_" + `tmpCatID`):
+								pOrder = form.getvalue("propOrder_" + `tmpCatID`)
+								#print "Setting order " + `pOrder` + " for " + pAlias
+								rtPropHandler.setReagentTypeAttributeOrdering(rTypeAttrID, pOrder)
+							else:
+								if form.has_key("propOrder_" + temp_val):
+									pOrder = form.getvalue("propOrder_" + temp_val)
+									rtPropHandler.setReagentTypeAttributeOrdering(rTypeAttrID, pOrder)
+						
+							#print "was ist das? " + "isMultiple_" + temp_val
+							
+							# Set multiple and other for dropdowns only
+							rtPropHandler.makeSingle(rTypeAttrID)
+							rtPropHandler.removeCustomizeable(rTypeAttrID)
+							
+							if form.has_key("hyperlink_" + temp_val):
+								#print "MAKING HYPERLINK??????????????"
+								rtPropHandler.makeHyperlink(rTypeAttrID)
+							else:
+								rtPropHandler.removeHyperlink(rTypeAttrID)
+
+							#print "rtypeattr " + `rTypeAttrID`
+							
+							# change Oct. 19/09 - catch single quotes
+							# update list for multiple values
+							numVals = form.getvalue("num_vals_" + category + "_:_" + tmp_alias)	# THIS IS RIGHT
+
+							#numVals = form.getvalue("num_vals_" + (category + "_:_" + newPropAlias).replace("'", "\\'"))
+
+							#print "num_vals_" + category + "_:_" + pAlias
+
+							#numVals = form.getvalue("num_vals_" + (category + "_:_" + tmp_alias).replace("'", "\\'"))
+							
+							#print "palias " + pAlias
+							#print ", newPropAlias " + newPropAlias
+							#print ", numvals " + `numVals`
+							
+							comms = categoryDescriptor + " " + pDescr
+							
+							if numVals == 'predefined':		# dropdown list of values
+								
+								# remove hyperlink for dropdowns
+								rtPropHandler.removeHyperlink(rTypeAttrID)
+
+								# Apr. 29, 2010: Hyperlinks and multiples
+								if form.has_key("isMultiple_" + temp_val):
+									#print "MAKING MULTIPLE " + pDescr
+									rtPropHandler.makeMultiple(rTypeAttrID)
+								else:
+									rtPropHandler.makeSingle(rTypeAttrID)
+									
+								if form.has_key("allowOther_" + temp_val):
+									rtPropHandler.makeCustomizeable(rTypeAttrID)
+								else:
+									rtPropHandler.removeCustomizeable(rTypeAttrID)
+								
+								if not sHandler.existsSetGroup(tmpCatID):
+									ssetGroupID = sHandler.addSetGroupID(tmpCatID, comms)
+								else:
+									ssetGroupID = sHandler.findPropSetGroupID(tmpCatID)
+									
+								#print "????? " + `ssetGroupID`
+								
+								#if pHandler.findPropertyIDFromAlias(newPropAlias, True) > 0:
+								if form.has_key("propertyValues_" + (category + "_:_" + newPropAlias).replace("'", "\\'")):
+									propVals = form.getlist("propertyValues_" + (category + "_:_" + newPropAlias).replace("'", "\\'"))
+									#print "HERE???"
+								elif form.has_key("propertyValues_" + category + "_:_" + tmp_alias):
+									propVals = form.getlist("propertyValues_" + category + "_:_" + tmp_alias)
+									#print "OR HERE???"
+								else:
+									propVals = []
+								
+								#print "new alias " + newPropAlias
+								#print "alias " + pAlias
+
+								#print "INSERTING " + `propVals`
+								
+								for pVal in propVals:
+									if pVal != 'default':
+										#print rTypeAttrID
+										#print pVal
+										#setComms = rTypeName + " " + pDescr
+										#print setComms
+										#print "UPDATING SET!!! " + pAlias
+										#sHandler.updateSet(rTypeAttrID, setComms, pVal)
+									
+										sID = sHandler.findSetValueID(ssetGroupID, pVal)
+										
+										if sID <= 0:
+											sID = sHandler.addSetValue(ssetGroupID, pVal)
+										
+										#print `sID`
+									
+										if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttrID, sID):
+											sHandler.addReagentTypeAttributeSetEntry(rTypeAttrID, sID)
+
+				#print newPropID
+
+		return newRTypeID
+
+
+	def deleteReagentType(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		rtHandler = ReagentTypeHandler(db, cursor)
+		rtPropHandler = ReagentTypePropertyHandler(db, cursor)		# Aug. 31/09
+		pHandler = ReagentPropertyHandler(db, cursor)
+		sHandler = SystemSetHandler(db, cursor)
+		ltHandler = LocationTypeHandler(db, cursor)
+		
+		propMapper = ReagentPropertyMapper(db, cursor)
+		rMapper = ReagentTypeMapper(db, cursor)
+		
+		prop_Alias_ID_Map = propMapper.mapPropAliasID()		# (propAlias, propID) - e.g. ('insert_type', '48')
+		
+		category_Alias_ID_Map = propMapper.mapPropCategoryAliasID()
+		category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+		
+		#print `category_Alias_ID_Map`
+
+		reagentType_Name_ID_Map =  rMapper.mapTypeNameID()
+		reagentType_ID_Name_Map = rMapper.mapTypeIDName()
+
+		# March 10, 2011
+		ignoreList = ["sequence", "length", "melting temperature", "molecular weight", "protein sequence", "rna sequence"]
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+	
+		# search and creation views have different input names
+		if form.has_key("reagentType"):
+			rTypeName = form.getvalue("reagentType")
+		elif form.has_key("reagentTypeName"):
+			rTypeName = form.getvalue("reagentTypeName")
+		else:
+			raise UnknownReagentTypeException("Unknown reagent type")
+		
+		#print rTypeName
+		rTypeID = rtHandler.findReagentTypeID(rTypeName)
+		rTypePrefix = rtHandler.findReagentTypePrefix(rTypeName)
+		
+		rTypeAttributes = rtPropHandler.findAllReagentTypeAttributes(rTypeID)
+		allSetIDs = []
+		
+		# Find all currently available reagent type dropdown values
+		for r_type_id in reagentType_ID_Name_Map.keys():
+			#print "Checking rtype " + `r_type_id`
+			
+			if r_type_id != rTypeID:
+				attrs = rtPropHandler.findAllReagentTypeAttributes(r_type_id)
+				#print "Its attributes are: " + `attrs`
+				
+				for attr in attrs:
+					set_ids = sHandler.findReagentTypeAttributeSetIDs(attr)
+					#print "For attr " + `attr` + ", the set ids are: " + `set_ids`
+					
+					allSetIDs += set_ids
+		
+		#print `allSetIDs`
+		
+		for aKey in rTypeAttributes:
+			attrID = rTypeAttributes[aKey]		# this is propCatID
+			#print "Attr ID " + `attrID`
+			
+			# Before deprecating attrID:
+			propCatID = rtPropHandler.findReagentTypeAttributePropertyID(aKey)
+			#print "propCatID " + `propCatID`
+			
+			# Aug. 5/09: Delete System_Set_Group values - Nov. 16/09: modified code
+			setGroupID = sHandler.findPropSetGroupID(propCatID)
+			#print "setGroupID " + `setGroupID`
+			
+			# Find its values AND check again to make sure they're not used for other reagent types!  Then delete
+			setIDs = sHandler.findAllSetIDs(setGroupID)
+			
+			#print `setIDs`
+			
+			for sID in setIDs:
+				if sID not in allSetIDs:
+					#print "Deleting set id " + `sID`
+					sHandler.deleteSetValue(sID)
+			
+			# and now can delete 'orphaned' groups
+			if len(sHandler.findAllSetIDs(setGroupID)) == 0:
+				sHandler.deleteSetGroup(setGroupID)
+			
+			#sHandler.deleteSetValues(setGroupID)
+			
+			sHandler.deleteReagentTypeAttributeSetValues(aKey)
+			
+			# Aug. 11/09: Find its category here - will delete later if empty
+			attr_category = pHandler.findReagentPropertyCategory(attrID)
+			#attr_propID = pHandler.findReagentPropertyInCategory(attrID)
+
+			# March 10, 2011
+			propID = pHandler.findReagentPropertyInCategory(propCatID)
+
+			#print "pcid" + `propCatID`
+			#print "propid " + `propID`
+
+			# don't touch ReagentPropType_tbl but delete property from category **IFF** not used anywhere else!!!!!!!!!!!!!!!!
+			cursor.execute("SELECT * FROM ReagentTypeAttributes_tbl WHERE propertyTypeID=" + `attrID` + " AND reagentTypeID != " + `rTypeID` + " AND status='ACTIVE'")
+			results = cursor.fetchall()
+
+			# March 10, 2011
+			if prop_ID_Name_Map[propID] not in ignoreList:
+			
+				if not results or len(results) == 0:
+					pHandler.deleteReagentPropertyInCategory(attrID)
+
+				# Remove ReagentTypeAttributes table entry March 10, 2011: **EXCEPT** Protein Sequence and RNA Sequence!!!!!!!!!
+				rtPropHandler.deleteReagentTypeAttribute(rTypeID, attrID)
+
+			# delete category if empty, EXCLUDE DEFAULT CATEGORIES (i.e. even if no other reagent type has RNA sequence, don't delete 'RNA Sequence' category!!!!!!!
+			if attr_category != category_Name_ID_Map["General Properties"] and attr_category != category_Name_ID_Map["DNA Sequence"] and attr_category != category_Name_ID_Map["External Identifiers"] and attr_category != category_Name_ID_Map["Classifiers"] and attr_category != category_Name_ID_Map["DNA Sequence Features"] and attr_category != category_Name_ID_Map["RNA Sequence"] and attr_category != category_Name_ID_Map["RNA Sequence Features"] and attr_category != category_Name_ID_Map["Protein Se [...]
+				#print "DELETEING CATEGORY " + `attr_category`
+				pHandler.deleteReagentPropertyCategory(attr_category)
+
+		# Aug. 10/09: Delete "thisReagentType Type" property, e.g. if deleting Virus also delete 'Virus type' property - it's not going to be used anywhere else
+		if prop_Name_ID_Map.has_key(rTypeName + " type"):
+			pHandler.deleteReagentProperty(prop_Name_ID_Map[rTypeName + " type"])
+		
+		# Aug. 27/09: Delete associations - Update Dec. 22/09: changed rTypeName to rTypeID
+		self.deleteReagentTypeAssociations(rTypeID)
+		
+		# Feb. 25/10
+		ltHandler.deleteContainerReagentType(rTypeID)
+	
+		rtHandler.deleteReagentType(rTypeID)
+
+
+##########################################################
+# Central callable function
+##########################################################
+def main():
+
+	rtReqHandler = ReagentTypeRequestHandler()
+	rtReqHandler.handle()
+
+main()
\ No newline at end of file
diff --git a/OpenFreezer/cgi/restriction.py b/OpenFreezer/cgi/restriction.py
new file mode 100755
index 0000000..24e18a0
--- /dev/null
+++ b/OpenFreezer/cgi/restriction.py
@@ -0,0 +1,154 @@
+#!/usr/local/bin/python
+
+import cgi
+
+import utils
+from sequence_handler import DNAHandler
+from database_conn import DatabaseConn
+
+import Bio
+from Bio.Seq import Seq
+from Bio.Restriction import *
+
+dbConn = DatabaseConn()
+db = dbConn.databaseConnect()
+cursor = db.cursor()
+
+dnaHandler = DNAHandler(db, cursor)
+
+form = cgi.FieldStorage()
+
+lims_id = form.getvalue("limsID")		# always exists
+
+print "Content-type: application/octet-stream"
+print "Content-Disposition: attachment; filename=" + lims_id + ".txt"
+print "Pragma: no-cache"
+print "Expires: 0"
+#print "Content-type:text/html"
+print
+
+# sequence may be empty
+if form.has_key("vector_sequence"):
+	mySeq = form.getvalue("vector_sequence")
+	isLinear = False	# Do NOT call the variable 'linear' - it's a reserved keyword for function argument
+	
+	# Construct a Seq object readable by BioPython:
+	rb = RestrictionBatch(AllEnzymes)
+	
+	bioSeq = Seq(mySeq)
+	fSeq = FormattedSeq(bioSeq, linear=isLinear)             # default linear = TRUE
+	
+	analysis = Analysis(rb, fSeq)   # linear = true
+	result = analysis.full()
+	
+	cutsDict = {}	# stores ('nCuts', 'enzyme') tuples
+	nonCuts = []	# enzymes that don't cut the sequence
+	
+	for a in AllEnzymes.elements():
+		enz = rb.get(a)
+		#print result[enz]
+		
+		if result.has_key(enz):
+			cuts = len(result[enz])
+			
+			if cuts > 0:
+				if not cutsDict.has_key(cuts):
+					cutsDict[cuts] = [enz]
+				else:
+					cutsDict[cuts].append(enz)
+			else:
+				nonCuts.append(enz)
+		else:
+			nonCuts.append(enz)
+	
+	print "Restriction map for " + lims_id + ", " + `len(mySeq)` + " nucleotides\n"
+	
+	nCuts = cutsDict.keys()
+	nCuts.sort()
+		
+	for n in nCuts:
+		print "Enzymes that cut the sequence " + `n` + " times:\n"
+		print "Enzyme\tPositions\n"
+		
+		for e in cutsDict[n]:		# enzyme
+			print `e` + '\t' + `result[e]`
+	
+		print ""
+	
+	#nonCuts.sort()		# do NOT use!!!!!!!!!!
+	
+	print "Enzymes that do not cut the sequence: \n"
+	
+	for e in nonCuts:
+		print `e`
+		
+	print ""
+	
+	# output enzymes with their cutting positions, sorted numerically
+	#analysis.print_as('number')
+	#analysis.print_that(title="Restriction Map for " + lims_id + " (indicates exact cutting position on sequence):\n")
+	
+elif form.has_key("insert_sequence"):
+	
+	mySeq = form.getvalue("insert_sequence")	
+	isLinear = True
+
+	# Construct a Seq object readable by BioPython:
+	bioSeq = Seq(mySeq)
+	fSeq = FormattedSeq(bioSeq, linear=isLinear)             # default linear = TRUE
+
+	# Construct a Seq object readable by BioPython:
+	rb = RestrictionBatch(AllEnzymes)
+	
+	bioSeq = Seq(mySeq)
+	fSeq = FormattedSeq(bioSeq, linear=isLinear)             # default linear = TRUE
+	
+	analysis = Analysis(rb, fSeq)   # linear = true
+	result = analysis.full()
+	
+	# output enzymes with their cutting positions, sorted numerically
+	cutsDict = {}	# stores ('nCuts', 'enzyme') tuples
+	nonCuts = []	# enzymes that don't cut the sequence
+	
+	print "Restriction map for " + lims_id + ", " + `len(mySeq)` + " nucleotides\n"
+	
+	for a in AllEnzymes.elements():
+		enz = rb.get(a)
+		#print result[enz]
+		
+		if result.has_key(enz):
+			cuts = len(result[enz])
+			
+			if cuts > 0:
+				if not cutsDict.has_key(cuts):
+					cutsDict[cuts] = [enz]
+				else:
+					cutsDict[cuts].append(enz)
+			else:
+				nonCuts.append(enz)
+		else:
+			nonCuts.append(enz)
+		
+	nCuts = cutsDict.keys()
+	nCuts.sort()
+		
+	for n in nCuts:
+		print "Enzymes that cut the sequence " + `n` + " times:\n"
+		print "Enzyme\tPositions\n"
+		
+		for e in cutsDict[n]:		# enzyme
+			print `e` + '\t' + `result[e]`
+		
+		print ""
+	
+	print "Enzymes that do not cut the sequence: \n"
+	
+	for e in nonCuts:
+		print `e`
+		
+	print ""
+	#analysis.print_as('number')
+	#analysis.print_that(title="Restriction Map for " + lims_id + " (indicates exact cutting position on sequence):\n")
+	
+else:
+	print("Sequence for " + lims_id + " is empty\n")
\ No newline at end of file
diff --git a/OpenFreezer/cgi/restriction_map.py b/OpenFreezer/cgi/restriction_map.py
new file mode 100755
index 0000000..8640101
--- /dev/null
+++ b/OpenFreezer/cgi/restriction_map.py
@@ -0,0 +1,135 @@
+import cgi
+import MySQLdb
+import sys
+import string
+import Bio
+
+from Bio.Seq import Seq
+from Bio.Restriction import *
+
+from general_handler import GeneralHandler
+from reagent_handler import ReagentHandler, InsertHandler
+from sequence_handler import SequenceHandler
+#from system_set_handler import SystemSetHandler
+
+from database_conn import DatabaseConn
+
+from Numeric import *
+
+# Creates a Restriction Map for reagent sequences (right now only doing for Insert - linear)
+# Construct Bio.Seq object and build a restriction map
+
+# Output restriction analysis for specific enzymes
+def rMap_specific(f_in, f_out, enz_list):
+	
+	# Database connection parameters
+	dbConn = DatabaseConn()
+	db = dbConn.databaseConnect()
+	cursor = db.cursor()
+	
+	gHandler = GeneralHandler(db, cursor)
+	rHandler = ReagentHandler(db, cursor)
+	seqHandler = SequenceHandler(db, cursor)
+
+	infile = open(f_in, 'r')
+	outfile = open(f_out, 'w')	
+
+	for line in infile.readlines():
+		reagentID = line.strip()	# e.g. V123
+		rID = rHandler.convertReagentToDatabaseID(reagentID)
+		seqID = rHandler.findDNASequenceKey(rID)
+
+		if seqID:
+			mySeq = seqHandler.findSequenceByID(seqID)
+			
+			# Construct a Seq object readable by BioPython:
+			bioSeq = Seq(mySeq)
+			fSeq = FormattedSeq(bioSeq, linear=False)		# linear = FALSE, we're dealing w/ VECTORS
+
+			analysis = Analysis(enz_list, fSeq, linear=False)  	# linear = FALSE again for VECTORS
+			result = analysis.full()
+
+			outfile.write(reagentID + ": " + '\n')
+
+			# calculate bandwidths
+			allSites = []
+			
+			for enz in result.keys():
+				sites = result[enz]
+				
+				if len(allSites) == 0:
+					allSites = sites
+				else:
+					# concatenate
+					for s in sites:
+						allSites.append(s)
+
+			allSites.sort()
+
+			if len(allSites) > 0:
+				
+				# calculate distances between sites
+				bandSizes = []
+				
+				i = 1
+				
+				while i < len(allSites):
+					tmpLen = allSites[i] - allSites[i-1]
+					bandSizes.append(tmpLen)
+					i += 1
+				
+				# last band
+				tmpLen = len(mySeq) - allSites[i-1] + allSites[0]
+				bandSizes.append(tmpLen)
+				
+				bandSizes.sort()
+				
+				outfile.write(`bandSizes` + '\n')
+
+			outfile.write('\n')
+			
+	infile.close()
+	outfile.close()
+	cursor.close()
+	db.close()
+
+
+# Full restriction map - REDO
+# Anna's suggestion: Don't output the entire list of enzymes; set a cutoff by maximum number of cutting sites 3
+# (i.e. output only enzymes that have a max. of 3 cutting sites and discard the rest)
+def rMap_full(f_in, f_out):
+	
+	# Database connection parameters
+	dbConn = DatabaseConn()
+	db = dbConn.databaseConnect()
+	cursor = db.cursor()
+
+	gHandler = GeneralHandler(db, cursor)
+	rHandler = ReagentHandler(db, cursor)
+	seqHandler = SequenceHandler(db, cursor)
+
+	infile = open(f_in, 'r')
+	outfile = open(f_out, 'w')
+	
+	for line in infile.readlines():
+		reagentID = line.strip()	# e.g. V123
+		
+		rID = rHandler.convertReagentToDatabaseID(reagentID)
+		seqID = rHandler.findDNASequenceKey(rID)
+		
+		if seqID:
+			mySeq = seqHandler.findSequenceByID(seqID)
+
+                	# Construct a Seq object readable by BioPython:
+			bioSeq = Seq(mySeq)
+			fSeq = FormattedSeq(bioSeq)             # default linear = TRUE
+
+			analysis = Analysis(AllEnzymes, fSeq)   # linear = true
+			result = analysis.full()
+			header = "==============================================\nRestriction analysis for " + reagentID + "\n==============================================\n"
+			analysis.print_that(title=header+'\n\n')
+
+
+#rMap_full('/home/olhovsky/anna.txt', '/home/olhovsky/anna_full_restriction.out')
+#rMap_specific('/home/olhovsky/anna.txt', '/home/olhovsky/anna_specific_restriction.txt', ['HpaI', 'XbaI'])
+rMap_specific('/home/olhovsky/anna.txt', '/home/olhovsky/anna_specific_restriction.txt', ['SpeI', 'PstI'])
diff --git a/OpenFreezer/cgi/restriction_sites.py b/OpenFreezer/cgi/restriction_sites.py
new file mode 100755
index 0000000..ce145c0
--- /dev/null
+++ b/OpenFreezer/cgi/restriction_sites.py
@@ -0,0 +1,18 @@
+#!/usr/local/bin/python
+
+import Bio
+from Bio.Seq import Seq
+from Bio.Restriction import *
+
+rb = RestrictionBatch(AllEnzymes)
+
+print "Content-type:text/html"
+print
+
+result = " "
+
+for a in AllEnzymes.elements():
+	enz = rb.get(a)
+	result += `enz` + " "
+	
+print result
\ No newline at end of file
diff --git a/OpenFreezer/cgi/sequence.py b/OpenFreezer/cgi/sequence.py
new file mode 100755
index 0000000..60bd38b
--- /dev/null
+++ b/OpenFreezer/cgi/sequence.py
@@ -0,0 +1,258 @@
+from sequence_feature import *
+
+##################################################################################
+# Module Sequence
+#
+# Contains classes that represent Sequence objects (dna or protein) in OpenFreezer
+# Written October 10, 2006, by Marina Olhovsky
+#
+# Last modified: October 30, 2006
+##################################################################################
+class Sequence(object):
+	"Top-level hierarchy for other sequence types"
+	
+	# Attributes common to all sequences
+	__seq = ""
+	__length = 0
+	
+	def __init__(self, seq):
+		self.__seq = seq
+		self.__length = len(seq)
+	
+	# Simple access methods:	
+	def getSequence():
+		return self.__sequence
+	
+	def getLength():
+		return self.__length
+	
+	########################################################################
+	# Plain access methods
+	# Simply return various attributes, without going to the database
+	########################################################################
+	
+	def getSequence(self):
+		return self.__seq
+	
+	def getLength(self):
+		return self.__length
+
+
+################################################################################
+# Class ProteinSequence
+# This class represents a Protein sequence object in OpenFreezer
+# Written October 10, 2006, by Marina Olhovsky
+# Last modified: June 5/08
+################################################################################
+class ProteinSequence(Sequence):
+	"Represents a Protein sequence object in OpenFreezer"
+	
+	# Initialize private vars
+	__frame = 0
+	__start = -1
+	__end = -1
+	__seq = ""
+	__orientation = 'forward'	# jan. 26/09
+	__mw = 0.00			# jan. 30/09
+
+	# Nov. 19/09 - this is a list of SequenceFeature objects
+	__featureNames = ["Cleavage Site", "Miscellaneous", "Tag"]
+	__features = []
+	
+	# Constructor
+	# Updated Jan. 30/09: added optional peptideMass argument
+	def __init__(self, seq, frame=0, start=0, end=0, mw=0.0):
+		super(ProteinSequence, self).__init__(seq)
+		self.__seq = seq
+		self.__frame = frame
+		self.__start = start
+		self.__end = end
+		self.__mw = mw
+		
+		for f in self.__featureNames:
+			tmpFeature = SequenceFeature(f)
+			#tmpFeature.setFeatureType(f)
+			self.__features.append(tmpFeature)
+
+	# Return protein sequence
+	def getSequence(self):
+		return self.__seq
+	
+	# Return sequence start
+	def getSeqStart(self):
+		return self.__start
+	
+	# Return sequence end
+	def getSeqEnd(self):
+		return self.__end
+	
+	# Return frame
+	def getFrame(self):
+		return self.__frame
+	
+	# Jan. 26/09
+	def getOrientation(self):
+		return self.__orientation
+	
+	# Jan. 30/09: Return MW
+	def getMW(self):
+		return self.__mw
+	
+	# Change frame to parameter value
+	def setFrame(self, frame):
+		self.__frame = frame
+		
+	# Change sequence start to parameter value
+	def setSeqStart(self, start):
+		self.__start = start
+		
+	# Change sequence end to parameter value
+	def setSeqEnd(self, end):
+		self.__end = end
+	
+	# Jan. 30/09
+	def setMW(self, mw):
+		self.__mw = mw
+	
+	# jan. 26/09
+	def setOrientation(self, orientation):
+		self.__orientation = orientation
+		
+	def isProtein(self):
+		return True
+	
+	# Nov. 19/09
+	@classmethod
+	def getProteinSequenceFeatures(ProteinSequence):
+		return ProteinSequence.__features
+	
+	# Nov. 19/09
+	@classmethod
+	def getProteinSequenceFeatureNames(ProteinSequence):
+		return ProteinSequence.__featureNames
+	
+################################################################################
+# Class DNASequence
+# This class represents a DNA sequence object in OpenFreezer
+# Written October 27, 2006, by Marina Olhovsky
+################################################################################
+class DNASequence(Sequence):
+	"Represents a DNA sequence object in OpenFreezer"
+
+	# Nov. 19/09
+	__featureNames = ["5' Cloning Site", "3' Cloning Site", "5' Linker", "3' Linker", "cDNA", "Cleavage Site", "Intron", "Miscellaneous", "Origin of Replication", "PolyA Tail", "Promoter", "Restriction Site", "Selectable Marker", "Tag", "Transcription Terminator"]
+	
+	__features = []		# Nov. 19/09 - this is a list of SequenceFeature objects
+	
+	# May 17, 2010: MW, Tm, translation - calculated automatically
+	__dnaSeqAttributes = ["molecular weight", "protein translation", "melting temperature", "gc content"]
+	
+	# Constructor
+	def __init__(self, seq):
+		
+		for f in self.__featureNames:
+			tmpFeature = SequenceFeature(f)
+			#tmpFeature.setFeatureType(f)
+			self.__features.append(tmpFeature)
+
+		super(DNASequence, self).__init__(seq)
+		
+	def isDNA(self):
+		return True
+	
+	# Nov. 19/09
+	@classmethod
+	def getDNASequenceFeatures(DNASequence):
+		return DNASequence.__features
+	
+	# Nov. 19/09
+	@classmethod
+	def getDNASequenceFeatureNames(DNASequence):
+		return DNASequence.__featureNames
+	
+	# May 14, 2010
+	@classmethod
+	def getDNASequenceAttributes(DNASequence):
+		return DNASequence.__dnaSeqAttributes
+	
+	
+################################################################################
+# Class RNASequence
+# This class represents an RNA sequence object in OpenFreezer
+# Written October 22, 2009, by Marina Olhovsky
+################################################################################
+class RNASequence(Sequence):
+	
+	# Initialize private vars
+	__start = -1
+	__end = -1
+	__seq = ""
+	__orientation = 'forward'
+	__mw = 0.0			# Jan. 25/10
+	
+	__featureNames = []	# April 11, 2011: made empty
+	
+	__features = []		# Nov. 19/09 - this is a list of SequenceFeature objects
+	
+	# Constructor
+	def __init__(self, seq, start=0, end=0, mw=0):
+		super(RNASequence, self).__init__(seq)
+		self.__seq = seq
+		self.__start = start
+		self.__end = end
+		self.__mw = mw
+		
+		for f in self.__featureNames:
+			tmpFeature = SequenceFeature(f)
+			#tmpFeature.setFeatureType()
+			self.__features.append(tmpFeature)
+
+	# Return RNA sequence
+	def getSequence(self):
+		return self.__seq
+	
+	# Return sequence start
+	def getSeqStart(self):
+		return self.__start
+	
+	# Return sequence end
+	def getSeqEnd(self):
+		return self.__end
+	
+	# Jan. 26/09
+	def getOrientation(self):
+		return self.__orientation
+	
+	# Jan. 25/10
+	def getMW(self):
+		return self.__mw
+		
+	# Change sequence start to parameter value
+	def setSeqStart(self, start):
+		self.__start = start
+		
+	# Change sequence end to parameter value
+	def setSeqEnd(self, end):
+		self.__end = end
+	
+	# jan. 26/09
+	def setOrientation(self, orientation):
+		self.__orientation = orientation
+		
+	# Jan. 25/10
+	def setMW(self, mw):
+		self.__mw = mw
+	
+	def isRNA(self):
+		return True
+		
+	# Nov. 19/09
+	@classmethod
+	def getRNASequenceFeatures(RNASequence):
+		return RNASequence.__features
+	
+	
+	# Nov. 19/09
+	@classmethod
+	def getRNASequenceFeatureNames(RNASequence):
+		return RNASequence.__featureNames
\ No newline at end of file
diff --git a/OpenFreezer/cgi/sequence_feature.py b/OpenFreezer/cgi/sequence_feature.py
new file mode 100755
index 0000000..84f73dc
--- /dev/null
+++ b/OpenFreezer/cgi/sequence_feature.py
@@ -0,0 +1,101 @@
+import math
+
+##################################################################
+# This module represents Sequence Feature objects
+# Written by: Marina Olhovsky on March 12, 2008
+# Last modified: July 11, 2008
+##################################################################
+class SequenceFeature:
+	
+	# Instance variables
+	__fType = ""
+	__fName = ""
+	__fStart = 0
+	__fEnd = 0
+	__fDirection = 'forward'	# added March 17/08
+	__fSize = 0			# added July 11/08
+	
+	# Formerly another reagent property that in the new design is used in conjunction with a feature to describe it
+	# e.g. 'Tag Position' is now a descriptor for 'Tag Type', and 'Expression System' is the descriptor for 'Promoter'
+	__fDescrType = ""		# type of the descriptor (tag position or expression system)
+	__fDescrName = ""		# actual descriptor value ('N-terminus' or 'Bacteria')
+
+	# Default constructor - initialize all variables to their default values
+	def __init__(self):
+		self.__fType = ""
+		self.__fName = ""
+		self.__fStart = 0
+		self.__fEnd = 0
+		self.__fSize = 0
+		self.__fDescrType = ""
+		self.__fDescrName = ""
+		self.__fDirection = 'forward'
+		
+
+	# Overloaded constructor: Create a feature of the given type, with a given name, start and end positions
+	def __init__(self, fType, fName="", fStart=0, fEnd=0, fDir='forward', fDescrType="", fDescrName=""):
+		self.__fType = fType
+		self.__fName = fName
+		self.__fStart = fStart
+		self.__fEnd = fEnd
+		self.__fDirection = fDir
+		self.__fDescrType = fDescrType
+		self.__fDescrName = fDescrName
+		self.__fSize = math.fabs(fEnd-fStart)
+		
+
+	################################################
+	# Assignment methods
+	################################################
+
+	def setFeatureType(self, fType):
+		self.__fType = fType
+
+	def setFeatureName(self, fName):
+		self.__fName = fName
+
+	def setFeatureStartPos(self, fStart):
+		self.__fStart = fStart
+
+	def setFeatureEndPos(self, fEnd):
+		self.__fEnd = fEnd
+		
+	def setFeatureDescrType(self, fDescrType):
+		self.__fDescrType = fDescrType
+		
+	def setFeatureDescrName(self, fDescrName):
+		self.__fDescrName = fDescrName
+		
+	def setFeatureDirection(self, fDir):
+		self.__fDirection = fDir
+		
+	def setFeatureSize(self, fSize):
+		self.__fSize = fSize
+
+	###############################################
+	# Access methods
+	###############################################
+
+	def getFeatureType(self):
+		return self.__fType
+
+	def getFeatureName(self):
+		return self.__fName
+
+	def getFeatureStartPos(self):
+		return self.__fStart
+
+	def getFeatureEndPos(self):
+		return self.__fEnd
+	
+	def getFeatureDescrType(self):
+		return self.__fDescrType
+	
+	def getFeatureDescrName(self):
+		return self.__fDescrName
+	
+	def getFeatureDirection(self):
+		return self.__fDirection
+	
+	def getFeatureSize(self):
+		return self.__fSize
\ No newline at end of file
diff --git a/OpenFreezer/cgi/sequence_handler.py b/OpenFreezer/cgi/sequence_handler.py
new file mode 100755
index 0000000..fe48915
--- /dev/null
+++ b/OpenFreezer/cgi/sequence_handler.py
@@ -0,0 +1,2412 @@
+import string
+import MySQLdb
+import re
+import sys
+import math
+
+from decimal import Decimal
+
+from general_handler import GeneralHandler, ReagentPropertyHandler
+from mapper import ReagentPropertyMapper
+from sequence import *
+from exception import *
+
+import utils
+
+import Bio
+from Bio.Seq import Seq
+#from Bio import Enzyme
+from Bio.Restriction import *
+
+################################################################################
+# Module sequence_handler
+# An interface to Sequences_tbl in OpenFreezer
+#
+# This module performs sequence translation, database retrieval and update
+# Written October 11, 2006 by Marina Olhovsky
+#
+# Last modified: February 12, 2008
+################################################################################
+
+################################################################################
+# SequenceHandler class
+# Subclass of general Handler class, parent of other Sequence handlers
+# Written October 11, 2006, by Marina Olhovsky
+#
+# Last modified: January 22, 2010
+################################################################################
+class SequenceHandler(GeneralHandler):
+	"This class performs sequence translation, database retrieval and update"
+	def __init__(self, db, cursor):
+		self.db = db
+		self.cursor = cursor
+		
+	# Utility function to filter whitespaces from sequence
+	def filter_spaces(self, seq):
+		new_seq = ""
+		tokens = seq.split(" ")
+			
+		for i in tokens:
+			new_seq += i
+		
+		return new_seq
+	
+	
+	# Pull out the actual sequence (string) identified by seqID
+	# Return: sequence = String
+	def findSequenceByID(self, seqID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		sequence = ""
+		
+		cursor.execute("SELECT `sequence` FROM `Sequences_tbl` WHERE `seqID`=" + `seqID` + " AND `status`='ACTIVE'")
+		result = cursor.fetchone()	# must be unique
+		
+		if result:
+			sequence = result[0].strip()
+			
+		return sequence
+		
+	
+	# Set the status of the sequence identified by seqID to DEP
+	def deleteSequence(self, seqID):
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE Sequences_tbl SET status='DEP' WHERE seqID=" + `seqID`)
+
+	
+	# Jan. 25, 2010
+	def updateMolecularWeight(self, seqID, newMW):
+		
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+
+		cursor.execute("UPDATE Sequences_tbl SET mw=" + `newMW` + " WHERE seqID=" + `seqID` + " AND status='ACTIVE'")
+	
+################################################################################
+# Class ProteinHandler
+#
+# Descendant of SequenceHandler, contains functions to translate DNA sequence into protein,
+# locate existing protein sequences and store newly translated sequences in OpenFreezer database
+#
+# Written October 23, 2006, by Marina Olhovsky
+################################################################################
+class ProteinHandler(SequenceHandler):
+	"Contains functions and attributes specific to protein sequences"
+	
+	def __init__(self, db, cursor):
+		super(ProteinHandler, self).__init__(db, cursor)
+
+	# Aug. 24/09: Amino acids
+
+	# O and U are not used
+	amino_acids = ['A', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'Y']
+	
+	# B, X, Z, J represent ambiguous amino acids
+	ambiguous_aa = ['B', 'J', 'X', 'Z']
+	
+	peptideMassDict = {'A':71.08, 'C':103.14, 'D':115.09, 'E':129.12, 'F':147.18, 'G':57.05, 'H':137.14, 'I':113.16, 'K':128.17, 'L':113.16, 'M':131.19, 'N':114.1, 'P':97.12, 'Q':128.13, 'R':156.19, 'S':87.08, 'T':101.11, 'V':99.13, 'W':186.21, 'Y':163.18}
+	
+	# Construct a ProteinSequence object given its database identifier
+	def createProteinSequence(self, seqID):
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT `sequence`, `frame`, `start`, `end` FROM `Sequences_tbl` WHERE `seqID`=" + `seqID` + " AND `status`='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			sequence = result[0]
+			frame = int(result[1])
+			start = int(result[2])
+			end = int(result[3])
+			
+			return ProteinSequence(sequence, frame, start, end)
+		
+		return None
+	
+	
+	# Aug. 24/09
+	def squeeze(self, seq):
+		new_seq = ""
+		nextInd = 0
+		
+		while nextInd < len(seq):
+			nextChar = seq[nextInd]
+			
+			if nextChar in self.amino_acids or nextChar in self.ambiguous_aa or nextChar == '*':
+				new_seq += nextChar
+				
+			nextInd += 1
+		
+		return new_seq
+	
+	
+	def translateAllFrames(self, sequence):
+		
+		longest = None
+		max_len = 0
+		
+		results = []
+		
+		#print "Content-type:text/html"		# REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		
+		triplets = DNAHandler.triplets
+		
+		for frame in range(1,4):
+			
+			protein = ""
+			start = frame-1
+			
+			# CONVERT SEQUENCE TO UPPERCASE!!!!!!!!!!!!!!!!!!!!!!
+			sequence = sequence.upper()
+			seqLen = len(sequence)
+			
+			seqStart = -1
+			seqEnd = -1
+			
+			# Translate the entire DNA sequence first:
+			while start < seqLen:
+				codon = sequence[start:start+3]
+				
+				if triplets.has_key(codon):
+					protein += triplets[codon]
+					start += 3
+				else:
+					start += 3
+			
+			#print protein
+			chunks = protein.split("*")
+			#print `chunks`
+			
+			for chunk in chunks:
+				#if len(chunk) > 100:
+				#print chunk
+				met_start = chunk.find('M')
+				#print met_start
+				
+				if met_start >= 0:
+					#print met_start
+					orf = chunk[met_start:] + '*'
+					
+					#if len(orf) > 100:
+					#print "ORF " + orf
+					
+					subStart = protein.find(orf)
+					subEnd = subStart + len(orf)
+		
+					# now map them back to dna
+					seqStart = subStart*3 + frame
+					#print seqStart
+					seqEnd = seqStart + len(orf)*3 - 1
+					#print seqEnd
+					#print '\n'
+					peptideMass = self.calculatePeptideMass(orf)
+					#print `peptideMass`
+					newProt = ProteinSequence(orf, frame, seqStart, seqEnd, peptideMass)
+					
+					if len(orf) > max_len:
+						max_len = len(orf)
+						longest = newProt
+		
+		#print longest.getSequence()
+		return longest
+
+	
+	# Translate ALL frames and pick the longest
+	# Returns: ProteinSequence OBJECT
+	# Modified Feb. 26/08: Changed seqID parameter to 'seq' - an actual text value, not db ID
+	#def translateAll(self, seqID, openClosed):
+	def translateAll(self, seq, openClosed):
+		
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		#print "Content-type:text/html"
+		#print
+		#print seq
+		#print openClosed
+		
+		# Nov. 2/08: from latest backfill
+		tmpLongest = None
+	
+		# Translate sequence in all frames and select the longest
+		longest = 0		# length of longest ORF (reset to 0)
+		longestORF = None	# protein sequence OBJECT
+		longestFrame = -1	
+
+		if openClosed and seq:	# added June 16/09	
+			if len(seq) > 0 and len(openClosed) > 0:	# March 13/08 - if Insert is a non-coding sequence, open/closed will be blank
+				
+				frame = 1
+			
+				while frame <= 3:
+					#print frame
+					protEntry = self.translate(seq, frame, openClosed)
+		
+					# March 2, 2011
+					if not protEntry:
+						peptideSeq = ""
+						sStart = -1
+						sEnd = -1
+					else:
+						peptideSeq = protEntry.getSequence()
+						#print peptideSeq
+					
+						sStart = protEntry.getSeqStart()
+						sEnd = protEntry.getSeqEnd()
+					
+					if len(peptideSeq) > 0 and sStart > 0 and sEnd > 0:
+						
+						# compare length to previous ORFs
+						if len(peptideSeq) > longest:
+							longest = len(peptideSeq)
+							longestORF = protEntry
+							longestFrame = frame
+					
+					# increment loop counter
+					frame += 1
+
+		#print longestORF.getSequence()
+		return longestORF
+
+
+	def findVectorORFs(self, sequence, frame):
+		triplets = {"TTT":'F', "TCT":'S', "TAT":'Y', "TGT":'C', "TTC":'F', "TCC":'S', "TAC":'Y', "TGC":'C', "TTA":'L', "TCA":'S', "TAA":'*', "TGA":'*', "TTG":'L', "TCG":'S', "TAG":'*', "TGG":'W', "CTT":'L', "CCT":'P', "CAT":'H', "CGT":'R', "CTC":'L', "CCC":'P', "CAC":'H', "CGC":'R', "CTA":'L', "CCA":'P', "CAA":'Q', "CGA":'R', "CTG":'L', "CCG":'P', "CAG":'Q', "CGG":'R', "ATT":'I', "ACT":'T', "AAT":'N', "AGT":'S', "ATC":'I', "ACC":'T', "AAC":'N', "AGC":'S', "ATA":'I', "ACA":'T', "AAA":'K', "AGA" [...]
+	
+		protein = ""
+		start = frame-1
+		
+		#print "Frame " + `frame`
+		#print sequence
+		results = []
+		
+		# CONVERT SEQUENCE TO UPPERCASE!!!!!!!!!!!!!!!!!!!!!!
+		sequence = sequence.upper()
+		seqLen = len(sequence)
+		
+		seqStart = -1
+		seqEnd = -1
+		
+		# Translate the entire DNA sequence first:
+		while start < seqLen:
+			codon = sequence[start:start+3]
+			
+			if triplets.has_key(codon):
+				protein += triplets[codon]
+				start += 3
+			else:
+				start += 3
+
+		#print protein
+		chunks = protein.split("*")
+		#print `chunks`
+		
+		for chunk in chunks:
+			if len(chunk) > 100:
+				#print chunk
+				met_start = chunk.find('M')
+				#print met_start
+				
+				if met_start >= 0:
+					#print met_start
+					orf = chunk[met_start:] + '*'
+					
+					if len(orf) > 100:
+						#print "ORF " + orf
+					
+						subStart = protein.find(orf)
+						subEnd = subStart + len(orf)
+			
+						# now map them back to dna
+						seqStart = subStart*3 + frame
+						#print seqStart
+						seqEnd = seqStart + len(orf)*3 - 1
+						#print seqEnd
+						#print '\n'
+						peptideMass = self.calculatePeptideMass(orf)
+						
+						results.append(ProteinSequence(orf, frame, seqStart, seqEnd, peptideMass))
+		#print `results`
+		#print
+		return results
+		
+
+	################################################################################################
+	# Written January 30, 2009
+	# Return the molecular weight of a protein sequence based on its amino acid composition
+	# Input:  protein: STRING
+	# Return: mw: FLOAT
+	#
+	# Jan. 25/10: MW of ambiguous aa's is calculated based on NCBI rules as follows:
+	# (quoting from http://www.ncbi.nlm.nih.gov/bookshelf/br.fcgi?book=helpentrez&part=EntrezHelp):
+	# "If completely unknown amino acids (e.g., "X") are found, a molecular weight is not calculated. Ambiguous amino acids are calculated as one of their possible forms:
+	# B means D or N -- molecular weight is calculated as D
+	# Z means E or Q -- molecular weight is calculated as E"
+	#
+	################################################################################################
+	def calculatePeptideMass(self, protein):
+		
+		mw = 0.0
+		
+		#print "Content-type:text/html"
+		#print
+		#print protein
+		#print `self.peptideMassDict`
+		
+		protein = utils.squeeze(protein).strip()
+		
+		if len(protein) == 0 or protein.upper().find('X') >= 0:
+			return 0.0
+		
+		for aa in protein:
+			if aa == '*':
+				break
+			
+			if self.peptideMassDict.has_key(aa.upper()):
+				pm = self.peptideMassDict[aa.upper()]
+				mw += pm
+			elif aa.upper() == 'B':				# jan. 25/10
+				pm = self.peptideMassDict['D']
+				mw += pm
+			elif aa.upper() == 'Z':				# jan. 25/10
+				pm = self.peptideMassDict['E']
+				mw += pm
+			else:
+				print "Content-type:text/html"
+				print
+				print "Unknown Amino Acid: " + aa
+				return 0.0
+	
+		# add water weight - ROUGHLY 18
+		mw += 18.0
+	
+		mw = mw/1000	# Feb. 1/10: in kDa
+	
+		#print "Content-type:text/html"
+		#print
+		#print mw
+	
+		#return ("%.2d", mw)[1]		# output to 2 decimal places
+		return mw
+		
+		#TWOPLACES = Decimal(10) ** -2
+		#return float(Decimal(str(mw)).quantize(TWOPLACES))
+
+
+	# Compare two sequences to determine which is longest
+	# Arguments: pep1, pep2 - ProteinSequence OBJECTS
+	def selectLongest(self, pep1, pep2):
+		
+		# ignore null checks for now, assume both arguments are valid
+		seq1 = pep1.getSequence()
+		seq2 = pep2.getSequence()
+		
+		if len(seq1) >= len(seq2):
+			return pep1
+		else:
+			return pep2
+	
+	
+	# Translate a specific DNA frame into protein, taking into account its open/closed status
+	# Return: ProteinSequence object
+	def translate(self, sequence, frame, openClosed):
+		
+		#print "Content-type:text/html"
+		#print
+		
+		#print "Reagent ID " + `reagentID`
+		#print sequence
+		#print "FRAME " + `frame`
+		
+		# All possible amino acid codons
+		triplets = {"TTT":'F', "TCT":'S', "TAT":'Y', "TGT":'C', "TTC":'F', "TCC":'S', "TAC":'Y', "TGC":'C', "TTA":'L', "TCA":'S', "TAA":'*', "TGA":'*', "TTG":'L', "TCG":'S', "TAG":'*', "TGG":'W', "CTT":'L', "CCT":'P', "CAT":'H', "CGT":'R', "CTC":'L', "CCC":'P', "CAC":'H', "CGC":'R', "CTA":'L', "CCA":'P', "CAA":'Q', "CGA":'R', "CTG":'L', "CCG":'P', "CAG":'Q', "CGG":'R', "ATT":'I', "ACT":'T', "AAT":'N', "AGT":'S', "ATC":'I', "ACC":'T', "AAC":'N', "AGC":'S', "ATA":'I', "ACA":'T', "AAA":'K', "AGA" [...]
+	
+		protein = ""
+		start = frame-1
+		
+		# CONVERT SEQUENCE TO UPPERCASE!!!!!!!!!!!!!!!!!!!!!!
+		sequence = sequence.upper()
+		seqLen = len(sequence)
+		
+		seqStart = -1
+		seqEnd = -1
+		
+		# Translation varies by open/closed values
+		# Guidelines: open = no stop codon; closed = stop codon; ATG = self-explanatory
+		
+		openClosed = openClosed.lower()		# convert all to lowercase, since db values are inconsistent
+	
+		if openClosed == "open with atg":
+			# From first ATG to end of sequence
+			#seqEnd = len(sequence)		# open, hence translation ends at last nucleotide
+			#print seqEnd
+			#seqEnd = len(sequence) - 1
+	
+			while start < seqLen:
+				codon = sequence[start:start+3]
+				
+				if triplets.has_key(codon):
+					if codon != 'ATG' and len(protein) == 0:
+						# ORF not found yet, keep looking
+						start += 3	
+					elif triplets[codon] == '*':
+						# Not allowed, this is the wrong frame.  Disregard the sequence altogether
+						protein = ""
+						break
+					else:
+						if codon == 'ATG' and len(protein) == 0:
+							# Record start of translation
+							#seqStart = start + frame-1	# rmvd sept. 11/08
+							seqStart = start + 1		# added sept. 11/08
+							#print `seqStart`
+							
+						protein += triplets[codon]
+						start += 3
+				else:
+					start += 3
+
+			seqEnd = seqStart + len(protein)*3 - 1
+					
+		elif openClosed == "open no atg" or openClosed == "open, no atg":
+			# From start to end
+			seqStart = frame
+			#seqStart = 0
+			#seqEnd = len(sequence)
+			#seqEnd = len(sequence) - 1
+			
+			while start < seqLen:
+				codon = sequence[start:start+3]
+				
+				if triplets.has_key(codon):
+					if triplets[codon] == '*':
+						# Not allowed, this is the wrong frame.  Discared the sequence
+						protein = ""
+						break
+					else:
+						protein += triplets[codon]
+						start += 3
+				else:
+					start += 3
+
+			seqEnd = seqStart + len(protein)*3 - 1
+	
+		elif openClosed == "closed with atg":
+			# From ATG to first stop codon
+			while start < seqLen:
+				codon = sequence[start:start+3]
+				
+				if triplets.has_key(codon):
+					if codon != 'ATG' and len(protein) == 0:
+						# ORF not found yet, keep looking
+						start += 3
+					elif codon == 'ATG' and len(protein) == 0:
+						seqStart = start+1		# record start of translation
+						#seqStart = start
+						protein += triplets[codon]
+						start += 3
+					else:
+						protein += triplets[codon]
+							
+						if triplets[codon] != '*':	# have not reached a stop codon
+							# advance counter
+							start += 3
+						else:
+							seqEnd = start+3	# record end of translation
+							#seqEnd = start
+							
+							#print "Content-type:text/html"
+							#print
+							#print seqEnd
+							break			# reached a stop codon, discard the rest of the sequence
+				else:
+					start += 3
+			
+			
+		elif openClosed == "closed, no atg" or openClosed == "closed no atg":		# inconsistent db values
+			
+			# From start to first stop codon
+			seqStart = frame
+			#seqStart = 0
+			
+			while start < seqLen:
+				codon = sequence[start:start+3]
+				
+				if triplets.has_key(codon):
+					protein += triplets[codon]
+					
+					if triplets[codon] != '*':	# have not reached a stop codon
+						# advance counter
+						start += 3
+					else:
+						seqEnd = start+3	# end of translation
+						#seqEnd = start
+						break			# reached a stop codon, discard the rest of the sequence
+				else:
+					start += 3
+		
+		elif openClosed == "special cdna with utrs":
+			
+			# Translate the entire DNA sequence first:
+			while start < seqLen:
+				codon = sequence[start:start+3]
+				
+				if triplets.has_key(codon):
+					protein += triplets[codon]
+					start += 3
+				else:
+					start += 3
+					
+			# Find longest subsequence between 2 stop codons
+			lastStopIndex = len(protein)
+			longestSub = ""
+			longest = -1
+			
+			original = protein
+
+			# March 2, 2011: What if the frame doesn't contain a stop codon at all?? discard it!!
+			if protein.find("*") < 0:
+				# wrong frame
+				return
+
+			#print "ORIGINAL " + original
+
+			while lastStopIndex > 0:
+				
+				tmp_end_1 = protein.rfind('*')
+				sub1 = protein[0:tmp_end_1]
+				
+				tmp_end_2 = sub1.rfind('*')
+				sub2 = sub1[tmp_end_2+1:]
+				
+				metIndex = sub2.find('M')
+				
+				if metIndex >= 0:
+					tmp_orf = sub2[metIndex:]
+					
+					if len(tmp_orf) > longest:
+						longestSub = tmp_orf
+						longest = len(tmp_orf)
+	
+				#print "Longest subseq b/w stop codons: " + longestSub
+	
+				protein = sub1
+				lastStopIndex = len(protein)
+				
+			#print "Longest ORF: " + longestSub
+			
+			# Start and stop index of longest ORF in original DNA sequence:
+			# Modified Nov. 7/06
+			
+			# March 2, 2011
+			if len(longestSub) > 0:
+		
+				# Aug. 25/08: these are the positions in the translated Protein sequence!!
+				subStart = original.find(longestSub)
+				subEnd = subStart + len(longestSub)
+				
+				# now map them back to dna
+				seqStart = subStart*3 + frame
+				#seqStart = subStart*3
+				
+				##############################################################
+				# This is the optimal formula, don't change!!!
+				#
+				# seqEnd varies according to frame as follows:
+				#
+				# F3: seqEnd = seqStart + len(longestSub)*3 + frame-1
+				# F2: seqEnd = seqStart + len(longestSub)*3 + frame
+				# F1: seqEnd = seqStart + len(longestSub)*3 + frame + 1
+				#
+				# Hence, for all frames the common formula is:
+				#
+				# seqEnd = seqStart + len(longestSub)*3 + 2
+				#
+				##############################################################
+				
+				#seqEnd = seqStart + len(longestSub)*3 + 2
+				#seqEnd = seqStart + len(longestSub)*3 + frame + 1
+				
+				# include last codon
+				protein = original[subStart:subEnd+1]
+			else:
+				protein = longestSub
+
+			seqEnd = seqStart + len(protein)*3 - 1
+
+		# Dec. 18/09
+		elif openClosed == "non-coding" or openClosed == "none":
+			pass
+		
+		else:
+			print "Content-type:text/html"
+			print
+			print "Unknown Insert Type/Open Closed value: " + openClosed
+			print sequence
+
+
+		return ProteinSequence(protein, frame, seqStart, seqEnd)
+		
+	
+	# Parameters: seq = ProteinSequence object
+	def matchSequence(self, seq):
+		db = self.db			# localize for easy access
+		cursor = self.cursor		# ditto
+		newProtSeqID = 0
+		
+		if seq.isProtein():
+			prot_seq = seq.getSequence()
+			frame = seq.getFrame()
+			start = seq.getSeqStart()
+			end = seq.getSeqEnd()
+			prot_len = len(prot_seq)
+			
+			if prot_len > 0:
+					
+				cursor.execute("SELECT `seqID` FROM `Sequences_tbl` WHERE `seqTypeID`='2' AND `sequence`=" + `prot_seq` + " AND `frame`=" + `frame` + " AND `start`=" + `start` + " AND `end`=" + `end` + " AND `length`=" + `prot_len` + " AND `status`='ACTIVE'")
+				result = cursor.fetchone()	# technically there should only be one; if more it's an error, but just assume one for now and add error checks later
+
+				if result:
+					newProtSeqID = int(result[0])
+					
+		return int(newProtSeqID)
+	
+
+	# Insert a new sequence into OpenFreezer
+	# Parameters: seq = ProteinSequence object
+	def insertSequence(self, seq):
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		newProtSeqID = 0
+		
+		if seq.isProtein():
+			prot_seq = seq.getSequence()
+			frame = seq.getFrame()
+			start = seq.getSeqStart()
+			end = seq.getSeqEnd()
+			mw = seq.getMW()	# jan. 22, 2010
+			
+			# March 3/10
+			if not mw:
+				mw = self.calculatePeptideMass(prot_seq)
+			
+			#print "Content-type:text/html"
+			#print
+			#print prot_seq
+			#print mw
+			
+			prot_len = len(prot_seq)
+			
+			if prot_len > 0:
+				cursor.execute("INSERT INTO `Sequences_tbl`(`seqTypeID`, `sequence`, `frame`, `start`, `end`, `length`, mw) VALUES('2', " + `prot_seq` + ", " + `frame` + ", " + `start` + ", " + `end` + ", " + `prot_len` + ", " + `mw` + ")")
+				newProtSeqID = int(db.insert_id())
+			
+		return newProtSeqID
+	
+	
+	# Return the internal database identified of the given sequence argument
+	# Parameters: seq = ProteinSequence OBJECT
+	# Return: seqID = int; internal database identifier
+	def getSequenceID(self, seq):
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+
+		# Feb. 26/08: Make sure seq is not null
+		if seq:
+			if seq.isProtein():
+				prot_seq = seq.getSequence()
+				frame = seq.getFrame()
+				start = seq.getSeqStart()
+				end = seq.getSeqEnd()
+				prot_len = len(prot_seq)
+	
+				if len(prot_seq) > 0:
+					# First check if this sequence is already stored in LIMS
+					newProtSeqID = self.matchSequence(seq)
+				
+					if newProtSeqID == 0:
+						newProtSeqID = self.insertSequence(seq)
+						
+					return newProtSeqID
+		return -1
+
+	
+##################################################################################
+# Class DNAHandler
+# Descendant of SequenceHandler, handles DNA sequence operations
+# Written October 27, 2006, by Marina Olhovsky
+##################################################################################
+class DNAHandler(SequenceHandler):
+	"Contains functions and attributes specific to DNA sequences"
+
+	# global variable
+	sitesDict = {}
+	enzDict = {}
+	
+	allEnzymes = Bio.Restriction.AllEnzymes
+	
+	for enz in allEnzymes:
+		enzSeq = enz.site
+		sitesDict[enz.__name__] = enzSeq
+		enzDict[enz.__name__] = enz
+
+	# Jan. 19/09: Degenerate nucleotides
+	degenerateNucleotides = ['R', 'M', 'W', 'K', 'S', 'Y', 'H', 'B', 'D', 'N', 'V']
+	degenerateNucleotidesDictionary = {'R':['A', 'G'], 'M':['A', 'C'], 'W':['A', 'T'], 'K':['G', 'T'], 'S':['G', 'C'], 'Y':['C', 'T'], 'H':['A', 'T', 'C'], 'B':['G', 'T', 'C'], 'D':['G', 'A', 'T'], 'N':['A', 'C', 'G', 'T'], 'V':['G', 'A', 'C']}
+	
+	# Aug. 10/09
+	triplets = {"TTT":'F', "TCT":'S', "TAT":'Y', "TGT":'C', "TTC":'F', "TCC":'S', "TAC":'Y', "TGC":'C', "TTA":'L', "TCA":'S', "TAA":'*', "TGA":'*', "TTG":'L', "TCG":'S', "TAG":'*', "TGG":'W', "CTT":'L', "CCT":'P', "CAT":'H', "CGT":'R', "CTC":'L', "CCC":'P', "CAC":'H', "CGC":'R', "CTA":'L', "CCA":'P', "CAA":'Q', "CGA":'R', "CTG":'L', "CCG":'P', "CAG":'Q', "CGG":'R', "ATT":'I', "ACT":'T', "AAT":'N', "AGT":'S', "ATC":'I', "ACC":'T', "AAC":'N', "AGC":'S', "ATA":'I', "ACA":'T', "AAA":'K', "AGA": [...]
+	
+	nucleotides = ['A', 'a', 'C', 'c', 'G', 'g', 'T', 't', 'N', 'n']
+
+	#print "Content-type:text/html"
+	#print
+	#print `sitesDict`
+	
+	#sitesDict = {"AgeI":"A'CCGGT", "ApaI":"GGGCC'C", "AscI":"GG'CGCGCC", "AvrII":"C'CTAGG", "BamHI":"G'GATCC", "BglII":"A'GATCT", "BsrGI":"T'GTACA", "BstBI":"TT'CGAA", "ClaI":"AT'CGAT", "EcoRI":"G'AATTC", "EcoRV":"GAT'ATC", "HindIII":"A'AGCTT", "HpaI":"GTT'AAC", "KpnI":"GGTAC'C", "MfeI":"C'AATTG", "MluI":"A'CGCGT", "MscI":"TGG'CCA", "NarI":"GG'CGCC", "NcoI":"C'CATGG", "NdeI":"CA'TATG", "NheI":"G'CTAGC", "NotI":"GC'GGCCGC", "PacI":"TTAAT'TAA", "PstI":"CTGCA'G", "SacI":"GAGCT'C", "SalI":"G'T [...]
+	
+	# Modified May 29/08: Discussed with Karen and agreed on different core sequences
+	gatewayDict = {'attB1':"gtacaaaaaa", 'attB2':"tttcttgtac", 'attL1':"TTTGTACAAAAAA", 'attL2':"TTTCTTGTACAAAGT", 'attP1':"TTTGTACAAAAAA", 'attP2':"TTTCTTGTACAAAGT", 'attR1':"TTTGTACAAAAAA", 'attR2':"TTTCTTGTAC"}
+	
+	recombDict = {'LoxP':"ATAACTTCGTATAGCATACATTATACGAAGTTAT"}
+	
+	# Added May 29/08: Join all sites into one dictionary
+	sitesDict = utils.join(sitesDict, gatewayDict)
+	sitesDict = utils.join(sitesDict, recombDict)		# add LoxP
+	sitesDict['None'] = ""					# add 'None'
+
+	def __init__(self, db, cursor):
+		super(DNAHandler, self).__init__(db, cursor)	
+
+
+	# Squeeze unwanted characters from DNA sequence, leaving only nucleotides - A, C, G, T
+	# Update June 5/09: include N
+	# Moved into DNAHandler on Aug. 24/09
+	def squeeze(self, seq):
+		new_seq = ""
+		nextInd = 0
+		
+		while nextInd < len(seq):
+			nextChar = seq[nextInd]
+			
+			if nextChar in self.nucleotides:
+				new_seq += nextChar
+				
+			nextInd += 1
+		
+		return new_seq
+
+
+	# Construct a DNASequence object given its database identifier
+	def createDNASequence(self, seqID):
+		db = self.db
+		cursor = self.cursor
+		
+		sequence = self.findSequenceByID(seqID)
+		
+		return DNASequence(sequence)
+		
+
+	# Parameters: seq = STRING, not object!
+	def matchSequence(self, dna_seq):
+		db = self.db			# localize for easy access
+		cursor = self.cursor		# ditto
+		newDNASeqID = 0
+		
+		# no frame/start/end for DNA sequences; seqType = 1; length is not always (in fact, never should be) stored in Sequences_tbl, only match sequence by string comparison and its status should be active
+		cursor.execute("SELECT `seqID` FROM `Sequences_tbl` WHERE `seqTypeID`='1' AND sequence=" + `dna_seq` + " AND `status`='ACTIVE'")
+		
+		# should only be one; if there's more than one it is an error, but just assume one for now and add error checking later
+		result = cursor.fetchone()
+
+		if result:
+			newDNASeqID = int(result[0])
+		
+		return newDNASeqID
+	
+	
+	# Insert a new DNA sequence into OpenFreezer
+	# Parameters: seq = STRING (not object!)
+	def insertSequence(self, seq):
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		newDNASeqID = 0
+		
+		if len(seq) > 0:
+			cursor.execute("INSERT INTO `Sequences_tbl`(`seqTypeID`, `sequence`) VALUES('1', " + `seq` + ")")
+			newDNASeqID = int(db.insert_id())
+			
+		return newDNASeqID
+	
+	
+	# Return the internal database identified of the given sequence argument
+	# Parameters: seq = String (not object!)
+	# Return: seqID = int; internal database identifier
+	def getSequenceID(self, seq):
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+
+		# filter spaces
+		seq = self.filter_spaces(seq)
+		seq = self.squeeze(seq)
+		
+		if len(seq) > 0:
+			# First check if this sequence is already stored in OF
+			newDNASeqID = self.matchSequence(seq)
+			
+			if newDNASeqID <= 0:
+				newDNASeqID = self.insertSequence(seq)
+			
+			return newDNASeqID
+		
+		return -1
+
+
+	# June 23, 2010: Calculate GC content of DNA sequence as percentage
+	def calculateGC(self, sequence):	
+		sequence = utils.squeeze(sequence.upper()).strip()
+
+		#print "Content-type:text/html"
+		#print
+		#print sequence
+		#print utils.numOccurs(sequence, 'G')
+		#print utils.numOccurs(sequence, 'C')
+		#print len(sequence)
+
+		if len(sequence) > 0:
+			gc_cont = 100*(float(utils.numOccurs(sequence, 'G')) + float(utils.numOccurs(sequence, 'C'))) / float(len(sequence))
+			return round(gc_cont, 2)
+	
+		#print gc_cont
+		#print round(gc_cont, 2)
+
+		return 0
+
+		
+	# Jan. 22, 2010: Calculate the molecular weight of a DNA sequences
+	def calculateMW(self, sequence):
+		
+		mw = 0.0
+		sequence = sequence.upper()
+		
+		if len(sequence) == 0:
+			return -1
+		
+		mw_dict = {'A': 313.209, 'G':329.208, 'C':289.184, 'T':304.196}
+		
+		num_A = float(sequence.count('A'))
+		num_C = float(sequence.count('C'))
+		num_G = float(sequence.count('G'))
+		num_T = float(sequence.count('T'))
+		
+		weight_A = num_A * mw_dict['A']
+		weight_C = num_C * mw_dict['C']
+		weight_G = num_G * mw_dict['G']
+		weight_T = num_T * mw_dict['T']
+		
+		base_weight = float(weight_A) + float(weight_C) + float(weight_G) + float(weight_T)
+		
+		mw = base_weight - 61.964
+		
+		return round(mw, 2)
+	
+		#TWOPLACES = Decimal(10) ** -2
+		#print "Content-type:text/html"
+		#print
+		#print Decimal(str(mw)).quantize(TWOPLACES)
+		#return Decimal(str(mw)).quantize(TWOPLACES)
+
+
+	# Jan. 22, 2010
+	def calculateTm(self, sequence):
+		tm = 0.0
+		
+		sequence = sequence.upper()
+		
+		if len(sequence) == 0:
+			return -1
+		
+		seqLen = float(len(sequence))
+
+		num_A = float(sequence.count('A'))
+		num_C = float(sequence.count('C'))
+		num_G = float(sequence.count('G'))
+		num_T = float(sequence.count('T'))
+		
+		if seqLen < 14.0:
+			tm = 2 * (num_A + num_T) + 4 * (num_G + num_C)
+		else:
+			tm = 64.9 + 41.0 * (num_G + num_C - 16.4) / seqLen
+		
+		return utils.trunc(round(tm, 2), 2)	# can I just use round(), w/o trunc??
+		
+		#TWOPLACES = Decimal(10) ** -2
+		#return Decimal(str(tm)).quantize(TWOPLACES)
+
+
+	#############################################################################################################################
+	# The next functions were added on March 27/07 by Marina to construct vector sequence from the sequences of its parents
+	#############################################################################################################################
+
+	#####################################################################################################
+	# Returns true if 'site' is an array, representing a hybrid restriction site
+	#####################################################################################################
+	def isHybrid(self, site):
+	   return utils.isList(site)
+
+	#####################################################################################################
+	# Returns the first portion of a hybrid site (in Python terms, the first element of array 'h_site')
+	#####################################################################################################
+	def get_H_1(self, h_site):
+		return h_site[0].strip()
+
+
+	#####################################################################################################
+	# Returns the first portion of a hybrid site (in Python terms, the first element of array 'h_site')
+	#####################################################################################################
+	def get_H_2(self, h_site):
+		return h_site[1].strip()
+
+
+	# Returns an Enzyme object matching enzName
+	def makeEnzyme(self, enzName):
+		for e in AllEnzymes:
+			if e.__name__ == enzName:
+				return e
+			
+		return None
+		
+		
+	# Returns the reverse complement of a sequence
+	def reverse_complement(self, seq):
+		bioSeq = Bio.Seq.Seq(seq)
+		return bioSeq.reverse_complement().tostring().lower()
+
+
+	#####################################################################################################
+	# Generates a sequence for the given hybrid restriction site
+	# CHANGES MADE OCTOBER 19/07 - CURRENT ENZYME LIST REPLACED WITH BIOPYTHON RESTRICTION PACKAGE
+	#####################################################################################################
+	def hybridSeq(self, site):
+	    hybrid_seq = None
+
+	    # Get individual sites from hybrid
+	    h1 = self.makeEnzyme(self.get_H_1(site))
+	    h2 = self.makeEnzyme(self.get_H_2(site))
+
+	    # get their individual sequences
+	    h1_site = h1.site
+	    h2_site = h2.site
+
+	    # March 5, 2010: Check compatibility of 5' Insert to 5' Vector and 3' Insert to 3' vector
+	    if h2 not in h1.compatible_end(): 
+		raise HybridizationException("")
+
+	    if not self.isDegenerate(h1) and not self.isDegenerate(h2):
+		h1_seq = h1.elucidate().replace("_", "")
+		h2_seq = h2.elucidate().replace("_", "")
+	
+		# The sticky ends from two molecules cut with two different restriction enzymes can be joined if the overhangs can hybridize
+		# meaning, the 3' overhang is reverse complement to the 5' overhang
+		# However, since the sequences are given to us as one strand (5' strand), compare the overhangs to see if they're the same
+	
+		# Find the cutting position (cleavage) - marked by "^"
+		fp_clvg = h1_seq.find("^")
+		tp_clvg = h2_seq.find("^")
+		
+		#print "Content-type:text/html"
+		#print
+		
+		#print h1
+		#print h1_seq
+		#print h2
+		
+		#print fp_clvg
+	
+		# get the flanking ends
+		# CHANGE MARCH 5, 2010: The enzyme may actually cut 3'->5'
+		if fp_clvg < h1.elucidate().find("_"):
+			fp_flank = h1_seq[0:fp_clvg]
+		else:
+			fp_flank = h1_seq[len(h1_seq)-fp_clvg:]
+			
+		if tp_clvg > h2.elucidate().find("_"):
+			tp_flank = h2_seq[0:tp_clvg]
+		else:
+			tp_flank = h2_seq[len(h2_seq)-tp_clvg:]     # cleaved nts from ***end*** of seq
+			
+		#print "5' flank: " + fp_flank
+		#print "3' flank: " + tp_flank
+	
+		# Find overhang - March 5, 2010: get the overhang between the "_" and "^"
+		fp_oh = h1_seq[fp_clvg+1:len(h1_seq)-fp_clvg]
+		tp_oh = h2_seq[tp_clvg+1:len(h2_seq)-tp_clvg]
+	
+		# compare the overhangs to see if they're the same
+		if fp_oh == tp_oh:
+			# hybridize
+			hybrid_seq = fp_flank + fp_oh + tp_flank
+			
+	    	return hybrid_seq
+	
+	    else:
+		raise DegenerateHybridException("")
+
+
+	#########################################################################################
+	# Fill in hybrid restriction sites
+	# Return new vector sequence
+	#########################################################################################
+	def hybrid(self, five_site, three_site, pvSeq, insertSeq):
+		newSeq = ""
+		
+		#print "Content-type:text/html"
+		#print
+		#print pvSeq
+		#print insertSeq
+		
+		parentVectorSequence = Seq(pvSeq)
+		insertSequence = Seq(insertSeq)
+		
+		if not self.isHybrid(five_site):
+			five_pv_1 = self.enzDict[five_site]
+			five_pv_2 = self.enzDict[five_site]
+		else:
+			five_pv_1 = self.enzDict[self.get_H_1(five_site)]
+			five_pv_2 = self.enzDict[self.get_H_2(five_site)]
+			
+		#print five_pv_1
+		#print five_pv_2
+		
+		if not self.isHybrid(three_site):
+			three_pv_1 = self.enzDict[three_site]
+			three_pv_2 = self.enzDict[three_site]
+		else:
+			three_pv_1 = self.enzDict[self.get_H_1(three_site)]
+			three_pv_2 = self.enzDict[self.get_H_2(three_site)]
+		
+		#print three_pv_1
+		#print three_pv_2
+		
+		# Added here Jan. 14/09, after V2229 sequence construction failed (single BamHI on PV and 5'=3'=BglII on Insert) => failed b/c 'linear' was set to 'True'
+		if five_pv_2 != three_pv_1:
+			linear = False
+		else:
+			# Do NOT use linear=False in searching Insert sequence for IDENTICAL sites!!! (e.g. EcoRI children of V2327 Topo)
+			linear = True
+		
+		#print linear
+		
+		#print five_pv_1.ovhgseq
+		#print five_pv_2.ovhgseq
+		
+		if not five_pv_1.is_ambiguous() and not five_pv_2.is_ambiguous() and not three_pv_1.is_ambiguous() and not three_pv_2.is_ambiguous():
+			# Nov. 18/08: COMPARE OVERHANGS!!!!!!!
+			if five_pv_1.ovhgseq != five_pv_2.ovhgseq or three_pv_1.ovhgseq != three_pv_2.ovhgseq:
+				raise HybridizationException("")
+		
+		# still, we don't just need a check here, we need the actual degenerate sequence from parents
+		#elif self.isDegenerate(five_pv_1) or self.isDegenerate(five_pv_2):
+			#if five_pv_2 not in five_pv_1.compatible_end():
+				#raise HybridizationException("")
+		
+		#elif  self.isDegenerate(three_pv_1) or self.isDegenerate(three_pv_2):
+			#if three_pv_2 not in three_pv_1.compatible_end():
+				#raise HybridizationException("")
+		
+			pv_five_prime_pos = five_pv_1.search(parentVectorSequence, linear)
+			#print `pv_five_prime_pos`
+			
+			pv_five_prime_pos.sort()
+			
+			if len(pv_five_prime_pos) == 0:
+				raise InsertSitesNotFoundOnParentSequenceException("")
+			
+			# Feb. 6/09: FIRST OF ALL, CHECK THAT BOTH SITES ACTUALLY EXIST ON THE INSERT (i.e. that search() 5' != search() 3')
+			insert_five_prime_pos = five_pv_2.search(insertSequence, linear)
+			insert_three_prime_pos = three_pv_1.search(insertSequence, linear)
+			
+			insert_five_prime_pos.sort()
+			insert_three_prime_pos.sort()
+			
+			#print `insert_five_prime_pos`
+			#print `insert_three_prime_pos`
+			
+			if len(insert_five_prime_pos) == 1 and len(insert_three_prime_pos) == 1:
+				if insert_five_prime_pos[0] == insert_three_prime_pos[0]:
+					raise CloningSitesNotFoundInInsertException("")
+				
+			if len(insert_five_prime_pos) == 0:
+				raise CloningSitesNotFoundInInsertException("Insert sequence does not contain restriction site")
+			
+			if len(insert_three_prime_pos) == 0:
+				raise CloningSitesNotFoundInInsertException("Insert sequence does not contain restriction site")
+			
+			fp_start_pv = int(pv_five_prime_pos[0]) - 1
+			pvSeqPre = pvSeq[0:fp_start_pv].upper()
+			
+			# get the remaining portion of the cloning site from the Insert
+			fp_start_insert = int(insert_five_prime_pos[0]) - 1
+			
+			# for the 3' site on Insert, grab its LAST cutting position
+			# Updated Nov. 27/08: Add argument linear=False, only then it would consider a case where the cut occurs at the last nucleotide (e.g. ApaI)
+			#if len(insert_three_prime_pos) > 0:
+			tp_end_insert = int(insert_three_prime_pos[len(insert_three_prime_pos)-1]) - 1
+			#print `tp_end_insert`
+			
+			# March 10/10: check 5' before 3' on INSERT sequence!!!!
+			tp_start_insert = int(insert_three_prime_pos[0])-1
+			#print tp_start_insert
+			
+			if fp_start_insert > tp_start_insert:
+				raise InsertFivePrimeAfterThreePrimeException("")
+			
+			insertSeq = insertSeq[fp_start_insert:tp_end_insert].lower()
+			#print insertSeq
+			
+			# Get the LAST cutting position of the 3' site on PV sequence
+			pv_three_prime_pos = three_pv_2.search(parentVectorSequence, linear)
+			#print `pv_three_prime_pos`
+			pv_three_prime_pos.sort()
+			
+			if len(pv_three_prime_pos) == 0:
+				raise InsertSitesNotFoundOnParentSequenceException("")
+			
+			tp_end_pv = int(pv_three_prime_pos[len(pv_three_prime_pos)-1]) - 1
+			
+			pvSeqPost = pvSeq[tp_end_pv:].upper()
+			
+			newSeq = pvSeqPre + insertSeq + pvSeqPost
+			return newSeq
+		else:
+			# For degenerate sites, read the overhang directly from the parent sequence
+			pv_five_prime_pos = five_pv_1.search(parentVectorSequence, linear)
+			#print `pv_five_prime_pos`
+			
+			pv_five_prime_pos.sort()
+			
+			if len(pv_five_prime_pos) == 0:
+				raise InsertSitesNotFoundOnParentSequenceException("")
+			
+			# Feb. 6/09: FIRST OF ALL, CHECK THAT BOTH SITES ACTUALLY EXIST ON THE INSERT (i.e. that search() 5' != search() 3')
+			insert_five_prime_pos = five_pv_2.search(insertSequence, linear)
+			insert_three_prime_pos = three_pv_1.search(insertSequence, linear)
+			
+			insert_five_prime_pos.sort()
+			insert_three_prime_pos.sort()
+			
+			#print `insert_five_prime_pos`
+			#print `insert_three_prime_pos`
+			
+			if len(insert_five_prime_pos) == 1 and len(insert_three_prime_pos) == 1:
+				if insert_five_prime_pos[0] == insert_three_prime_pos[0]:
+					raise CloningSitesNotFoundInInsertException("")
+				
+			if len(insert_five_prime_pos) == 0:
+				raise CloningSitesNotFoundInInsertException("Insert sequence does not contain restriction site")
+			
+			if len(insert_three_prime_pos) == 0:
+				raise CloningSitesNotFoundInInsertException("Insert sequence does not contain restriction site")
+			
+			fp_start_pv = int(pv_five_prime_pos[0]) - 1
+			
+			# March 5, 2010: Differentiate between 5' overhang and 3' overhang!!!!!!!!!!
+			if five_pv_1.ovhg < five_pv_1.elucidate().find("_"):
+				fp_pv_ovhg = pvSeq[fp_start_pv:fp_start_pv+len(five_pv_1.ovhgseq)]
+			else:
+				fp_pv_ovhg = pvSeq[fp_start_pv-len(five_pv_1.ovhgseq):fp_start_pv]
+				
+			#print "5' PV overhang?????? " + fp_pv_ovhg
+			
+			pvSeqPre = pvSeq[0:fp_start_pv].upper()
+			
+			#print pvSeqPre
+			
+			# get the remaining portion of the cloning site from the Insert
+			fp_start_insert = int(insert_five_prime_pos[0]) - 1
+			
+			#print five_pv_2.ovhgseq
+			#print int(insert_five_prime_pos[0])
+			
+			if five_pv_2.ovhg < five_pv_2.elucidate().find("_"):
+				fp_insert_ovhg = insertSeq[fp_start_insert:fp_start_insert+len(five_pv_2.ovhgseq)]
+			else:
+				fp_insert_ovhg = insertSeq[fp_start_insert-len(five_pv_2.ovhgseq):fp_start_insert]
+					
+			#print "5' insert overhang: " + fp_insert_ovhg
+			
+			if fp_pv_ovhg.upper() != fp_insert_ovhg.upper():
+				raise HybridizationException("")
+			
+			# for the 3' site on Insert, grab its LAST cutting position
+			# Updated Nov. 27/08: Add argument linear=False, only then it would consider a case where the cut occurs at the last nucleotide (e.g. ApaI)
+			#if len(insert_three_prime_pos) > 0:
+			tp_end_insert = int(insert_three_prime_pos[len(insert_three_prime_pos)-1]) - 1
+			#print `tp_end_insert`
+			tp_start_insert = int(insert_three_prime_pos[0]) - 1
+			tp_insert_ovhg = insertSeq[tp_start_insert:tp_start_insert+len(three_pv_1.ovhgseq)]
+			#print "3' insert overhang: " + tp_insert_ovhg
+			
+			insertSeq = insertSeq[fp_start_insert:tp_end_insert].lower()
+			#print insertSeq
+			
+			# Get the LAST cutting position of the 3' site on PV sequence
+			pv_three_prime_pos = three_pv_2.search(parentVectorSequence, linear)
+			#print `pv_three_prime_pos`
+			pv_three_prime_pos.sort()
+			
+			tp_start_pv = int(pv_three_prime_pos[0]) - 1
+			tp_pv_ovhg = pvSeq[tp_start_pv:tp_start_pv+len(three_pv_2.ovhgseq)]
+			#print "3' PV overhang: " + tp_pv_ovhg
+			
+			if tp_pv_ovhg.upper() != tp_insert_ovhg.upper():
+				raise HybridizationException("")
+			
+			if len(pv_three_prime_pos) == 0:
+				raise InsertSitesNotFoundOnParentSequenceException("")
+			
+			tp_end_pv = int(pv_three_prime_pos[len(pv_three_prime_pos)-1]) - 1
+			
+			pvSeqPost = pvSeq[tp_end_pv:].upper()
+			
+			newSeq = pvSeqPre + insertSeq + pvSeqPost
+			return newSeq
+				
+			## 3 cases: both sites hybrid; only 5' hybrid; only 3' hybrid
+		
+			## Case 1: Only 5' site hybrid
+			#if self.isHybrid(five_site) and not self.isHybrid(three_site):
+				##print "case 1: 5' hybrid, 3' not"
+				
+				#five_pv = self.get_H_1(five_site)
+				##print "5' " + five_pv
+				#three_pv = three_site
+				##print "3' " + three_pv
+		
+				## Create a hybrid sequence for 5' site, 3' just regular
+				#five_seq = self.hybridSeq(five_site)
+				#three_seq = self.sitesDict[three_pv]
+				
+				## Find the NON-HYBRID 5' sequence
+				#five_non_hybrid_seq = self.sitesDict[five_pv]
+				
+				## Find restriction sites on pvSeq
+				#if five_non_hybrid_seq:
+					
+					#five_index = pvSeq.find(five_non_hybrid_seq)	# look for the non-hybrid 5' H1 part on the parent vector
+					#three_index = pvSeq.find(three_seq)		# just regular lookup
+					
+					#if five_index >= 0 and three_index >= 0:
+					
+						#preSeq = pvSeq[0:five_index]		# up to start of 5' site not including
+						#postSeq = pvSeq[three_index:]		# from start of 3' site including it to the end of the sequence
+						
+						## Now the 5' site gets replaced with HYBRID sequence
+						#if five_seq:
+							#newSeq = preSeq + five_seq + insertSeq + postSeq
+						#else:
+							#raise HybridizationException("Sites provided cannot be hybridized")
+				#else:
+					#raise InsertSitesNotFoundOnParentSequenceException("Sites not found on parent vector sequence")
+		
+			## Case 2: Both sites hybrid
+			#if self.isHybrid(five_site) and self.isHybrid(three_site):
+		
+				## Find boundaries on pvSeq
+				#five_pv = self.get_H_1(five_site)
+				#three_pv = self.get_H_2(three_site)
+				
+				## Get non-hybrid sequence of parent sites
+				#five_non_hybrid_seq = self.sitesDict[five_pv]
+				#three_non_hybrid_seq = self.sitesDict[three_pv]
+		
+				## Create hybrid sequences for both 5' and 3' sites
+				#five_seq = self.hybridSeq(five_site)
+				#three_seq = self.hybridSeq(three_site)
+		
+				#if five_seq and three_seq:
+				
+					## Find sites on parent vector, replace with hybrid sequence and add insert between them
+					#five_index = pvSeq.find(five_non_hybrid_seq)
+					#three_index = pvSeq.find(three_non_hybrid_seq)
+		
+					#if five_index > 0 and three_index > 0:
+						#preSeq = pvSeq[0:five_index]
+						#postSeq = pvSeq[three_index:]
+		
+						##newSeq = preSeq + five_seq + five_linker + insertSeq + three_linker + three_seq + postSeq	# need to replace sites on parent with hybrid sequences
+						#newSeq = preSeq + five_seq + insertSeq + three_seq + postSeq	# need to 
+					#else:
+						#raise InsertSitesNotFoundOnParentSequenceException("Sites not found on parent sequence")
+				#else:
+					#raise HybridizationException("Sites provided cannot be hybridized")
+		
+			## Case 3: Only 3' site hybrid
+			#if self.isHybrid(three_site) and not self.isHybrid(five_site):
+		
+				## Find boundaries on pvSeq
+				#three_pv = self.get_H_2(three_site)
+				#five_pv = five_site
+		
+				## Get hybrid sequence for 3'
+				#five_seq = self.sitesDict[five_site]
+				#three_seq = self.hybridSeq(three_site)
+		
+				#if three_seq:
+					## also find the non-hybrid sequence of 3'
+					#three_non_hybrid_seq = self.sitesDict[three_pv]
+				
+					## add Insert between sites
+					#five_index = pvSeq.find(five_seq)
+					#three_index = pvSeq.find(three_seq)
+		
+					#if five_index > 0 and three_index > 0:
+		
+						#preSeq = pvSeq[0:five_index]					# before 5'
+						#postSeq = pvSeq[three_index+len(three_non_hybrid_seq):]		# AFTER 3' b/c it will be replaced w/ hybrid seq
+		
+						## Replace 3' site with hybrid sequence
+						#newSeq = preSeq + five_seq + insertSeq + three_seq + postSeq
+					#else:
+						#raise InsertSitesNotFoundOnParentSequenceException("Sites not found on parent sequence")
+				#else:
+					#raise HybridizationException("Sites provided cannot be hybridized")
+				
+			#return newSeq
+
+	'''
+	def hybrid(self, five_site, three_site, pvSeq, insertSeq, five_linker, three_linker):
+		newSeq = None
+		
+		# May 27/08: Make pvSeq uppercase
+		pvSeq = pvSeq.upper()
+
+		# convert linker values to string - complains if they're None
+		if not five_linker:
+			five_linker = ""
+			
+		if not three_linker:
+			three_linker = ""
+
+		# 3 cases: both sites hybrid; only 5' hybrid; only 3' hybrid
+		# Case 1: Only 5' site hybrid
+		if self.isHybrid(five_site) and not self.isHybrid(three_site):
+                	five_pv = self.get_H_1(five_site)
+			three_pv = three_site
+			
+			# Create a hybrid sequence for 5' site, 3' just regular
+			five_seq = self.hybridSeq(five_site)
+                	three_seq = self.sitesDict[three_pv]
+
+			# Find the NON-HYBRID 5' sequence
+			five_non_hybrid_seq = self.sitesDict[five_pv]
+			
+			# Find restriction sites on pvSeq
+			if five_non_hybrid_seq:
+				
+				five_index = pvSeq.find(five_non_hybrid_seq)	# look for the non-hybrid 5' H1 part on the parent vector
+				three_index = pvSeq.find(three_seq)		# just regular lookup
+
+				# Place the Insert between restriction sites - IF FOUND
+				if five_index < 0 :
+					#raise InsertSitesNotFoundOnParentSequenceException("Sites not found on parent sequence")
+				
+					# May 27/08: V1886 (MGC backbone vector) contains the hybrid SalI-XhoI sequence rather than non-hybrid SalI.  So try searching for the hybrid sequence and place the cDNA with linkers after it. *** CONFIRM THIS WITH KAREN ***
+					five_index = pvSeq.find(five_seq)
+					
+					if five_index < 0:
+						raise InsertSitesNotFoundOnParentSequenceException("Sites not found on parent sequence")
+					else:
+						preSeq = pvSeq[0:five_index]
+						postSeq = pvSeq[three_index:]		# from start of 3' site including it to the end of the sequence
+				
+						newSeq = preSeq + five_seq + five_linker.upper() + insertSeq.lower() + three_linker.upper() + postSeq
+						
+				elif three_index < 0:
+					raise InsertSitesNotFoundOnParentSequenceException("Sites not found on parent sequence")
+				
+				else:
+					#if five_index > 0 and three_index > 0:
+				
+					preSeq = pvSeq[0:five_index]		# up to start of 5' site not including
+					postSeq = pvSeq[three_index:]		# from start of 3' site including it to the end of the sequence
+				
+					# Now the 5' site gets replaced with HYBRID sequence
+					if five_seq:
+						newSeq = preSeq + five_seq + five_linker + insertSeq.lower() + three_linker + postSeq
+					else:
+						raise HybridizationException("Sites provided cannot be hybridized")
+			else:
+				raise InsertSitesException("Unknown sites")
+				
+	
+		# Case 2: Both sites hybrid
+		if self.isHybrid(five_site) and self.isHybrid(three_site):
+
+			# Find boundaries on pvSeq
+			five_pv = self.get_H_1(five_site)
+			three_pv = self.get_H_2(three_site)
+			
+                	# Get non-hybrid sequence of parent sites
+                	five_non_hybrid_seq = self.sitesDict[five_pv]
+                	three_non_hybrid_seq = self.sitesDict[three_pv]
+
+			# Create hybrid sequences for both 5' and 3' sites
+			five_seq = self.hybridSeq(five_site)
+			three_seq = self.hybridSeq(three_site)
+
+			if five_seq and three_seq:
+			
+				# Find sites on parent vector, replace with hybrid sequence and add insert between them
+				five_index = pvSeq.find(five_non_hybrid_seq)
+				three_index = pvSeq.find(three_non_hybrid_seq)
+
+				if five_index > 0 and three_index > 0:
+					preSeq = pvSeq[0:five_index]
+					postSeq = pvSeq[three_index:]
+
+					newSeq = preSeq + five_seq + five_linker + insertSeq + three_linker + three_seq + postSeq	# need to replace sites on parent with hybrid sequences
+				else:
+					raise InsertSitesNotFoundOnParentSequenceException("Sites not found on parent sequence")
+			else:
+				raise HybridizationException("Sites provided cannot be hybridized")
+	
+		# Case 3: Only 3' site hybrid
+		if self.isHybrid(three_site) and not self.isHybrid(five_site):
+
+			# Find boundaries on pvSeq
+			three_pv = self.get_H_2(three_site)
+			five_pv = five_site
+
+			# Get hybrid sequence for 3'
+                	five_seq = self.sitesDict[five_site]
+			three_seq = self.hybridSeq(three_site)
+
+			if three_seq:
+			
+				# also find the non-hybrid sequence of 3'
+				three_non_hybrid_seq = self.sitesDict[three_pv]
+			
+				# add Insert between sites
+				five_index = pvSeq.find(five_seq)
+				three_index = pvSeq.find(three_seq)
+
+				if five_index > 0 and three_index > 0:
+
+					preSeq = pvSeq[0:five_index]					# before 5'
+					postSeq = pvSeq[three_index+len(three_non_hybrid_seq):]		# AFTER 3' b/c it will be replaced w/ hybrid seq
+
+					# Replace 3' site with hybrid sequence
+					newSeq = preSeq + five_seq + five_linker + insertSeq + three_linker + three_seq + postSeq
+				else:
+					raise InsertSitesNotFoundOnParentSequenceException("Sites not found on parent sequence")
+			else:
+				raise HybridizationException("Sites provided cannot be hybridized")
+			
+		return newSeq
+	'''
+	
+	def getHybridDegenerate(self, hybridSite, parentVectorSequence, insertSequence, hybrid_type):
+
+		#print "Content-type:text/html"
+		#print
+		#print hybridSite
+		#print hybrid_type
+		
+		if hybrid_type == "5 prime":
+			five_pv_1 = self.enzDict[self.get_H_1(hybridSite)]
+			five_pv_2 = self.enzDict[self.get_H_2(hybridSite)]
+			
+		elif hybrid_type == "3 prime":
+			five_pv_1 = self.enzDict[self.get_H_2(hybridSite)]
+			five_pv_2 = self.enzDict[self.get_H_1(hybridSite)]
+			
+		#print five_pv_1
+		#print five_pv_2
+		
+		pv_five_prime_pos = five_pv_1.search(parentVectorSequence)
+		#print `pv_five_prime_pos`
+		pv_five_prime_pos.sort()
+		
+		#if len(pv_five_prime_pos) == 0:
+			#raise InsertSitesNotFoundOnParentSequenceException("")
+		
+		# Feb. 6/09: FIRST OF ALL, CHECK THAT BOTH SITES ACTUALLY EXIST ON THE INSERT (i.e. that search() 5' != search() 3')
+		
+		insert_five_prime_pos = five_pv_2.search(insertSequence)
+		insert_five_prime_pos.sort()
+		
+		tp_start_pv = insert_five_prime_pos[0] - 1
+		tp_seq = five_pv_2.elucidate()
+		
+		insertSeq = insertSequence.tostring()
+		#print fp_insert_ovhg
+		#print `insert_five_prime_pos`
+		
+		#if len(insert_five_prime_pos) == 0:
+			#raise CloningSitesNotFoundInInsertException("Insert sequence does not contain restriction site")
+		
+		fp_start_pv = int(pv_five_prime_pos[0]) - 1
+		
+		fp_seq = five_pv_1.elucidate()
+		#print fp_seq
+		
+		pvSeq = parentVectorSequence.tostring()
+		
+		if five_pv_1.is_5overhang():
+			fp_pv_ovhg = pvSeq[fp_start_pv:fp_start_pv+len(five_pv_1.ovhgseq)]
+			#print fp_pv_ovhg
+			fp_pv_flank = fp_seq[0:fp_seq.find("^")]
+			#print fp_pv_flank
+			tp_pv_flank = fp_seq[fp_seq.find("_")+1:]
+			#print tp_pv_flank
+			tp_pv_ovhg = pvSeq[fp_start_pv:fp_start_pv+len(five_pv_1.ovhgseq)]
+			#print tp_pv_ovhg
+		else:
+			fp_pv_ovhg = pvSeq[fp_start_pv-len(five_pv_1.ovhgseq):fp_start_pv]
+			#print fp_pv_ovhg
+			fp_pv_flank = fp_seq[fp_seq.find("^")+1:]
+			#print fp_pv_flank
+			tp_pv_flank = fp_seq[0:fp_seq.find("_")]
+			#print tp_pv_flank
+		
+		if five_pv_2.is_5overhang():
+			#print tp_seq
+			fp_insert_flank = tp_seq[0:tp_seq.find("^")].lower()
+			#print fp_insert_flank
+			tp_insert_flank = tp_seq[tp_seq.find("_")+1:].lower()
+			#print tp_insert_flank
+			fp_insert_ovhg = insertSeq[tp_start_pv:tp_start_pv+len(five_pv_2.ovhgseq)]
+			#print fp_insert_ovhg
+		else:
+			fp_insert_flank = tp_seq[tp_seq.find("_")+1:].lower()
+			tp_insert_flank = tp_seq[0:tp_seq.find("^")].lower()
+			tp_insert_ovhg = insertSeq[tp_start_pv:tp_start_pv+len(five_pv_2.ovhgseq)]
+		
+		#fp_pv_ovhg = pvSeq[fp_start_pv:fp_start_pv+len(five_pv_1.ovhgseq)]
+		#print fp_pv_ovhg
+		#fp_site = fp_pv_flank + fp_pv_ovhg + tp_pv_flank
+		
+		if hybrid_type == "5 prime":
+			fp_site = fp_pv_flank + fp_insert_ovhg + tp_insert_flank
+			#print fp_site
+			return fp_site
+		else:
+			tp_site = fp_insert_flank + tp_pv_ovhg + tp_pv_flank
+			#print tp_site
+			return tp_site
+	
+	
+	#######################################################################################################################
+	# Special case: 5' site == 3' site
+	#
+	# Updated May 15/08: Since Insert sequence now contains the site, "cut out" the site and replace with Insert sequence
+	#######################################################################################################################
+	def identical_sites(self, siteSeq, pvSeq, insertSeq):
+
+		# Parent vector should only have this site once
+		if utils.numOccurs(pvSeq, siteSeq) == 1:
+
+			# locate the site on pvSeq
+			fp_start = pvSeq.find(siteSeq)
+			
+			# modified May 15/08
+			#insert_start = fp_start + len(siteSeq)			# removed May 15/08
+			insert_start = fp_start					# added May 15/08
+
+			seqPre = pvSeq[0:insert_start]
+			seqPost = pvSeq[insert_start:]
+
+			#newSeq = seqPre + insertSeq + siteSeq + seqPost	# removed May 15/08
+			newSeq = seqPre + insertSeq + seqPost			# added May 15/08
+			
+			return newSeq
+		else:
+			raise MultipleSiteOccurrenceException("Multiple site occurrences on parent vector sequence")
+
+
+	def isDegenerate(self, enz):
+		rSite = enz.site
+		
+		for nt in self.degenerateNucleotides:
+			if rSite.find(nt) >= 0:
+				return True
+		
+		return False
+	
+	
+	#################################################################################################################
+	# VECTOR SEQUENCE RECONSTITUTION
+	#################################################################################################################
+	
+	# Determine Vector information and invoke the appropriate function call for sequence reconstitution
+	#def constructSequence(self, rID):	
+	
+	#################################################################################################################
+	# Reconstitute NON=RECOMBINATION vector sequence from the sequences of its Insert and parent vector
+	#
+	# Since this function is called at new Vector creation and no information on the new vector exists,
+	# relying only on its parent information to construct the sequence (and let users change later as they please)
+	#
+	# Therefore: cloning sites are fetched from the Insert
+	#
+	# Input: parentVector ID, insertID
+	# Output: existing or newly added seqID of the reconstituted sequence
+	#
+	# Updated May 15/08: Insert sequence contains sites and linkers
+	#################################################################################################################
+	#def constructNonRecombSequence(self, pvSeqID, insertSeqID, cloning_sites, linkers):
+	def constructNonRecombSequence(self, pvSeqID, insertSeq, cloning_sites, reverse_insert=False):
+		
+		#print "Content-type:text/html"
+		#print
+		#print `cloning_sites`
+		#print `reverse_insert`
+		
+		db = self.db
+		cursor = self.cursor
+		sitesDict = self.sitesDict
+		
+		pHandler = ReagentPropertyHandler(db, cursor)
+		
+		# Database IDs of simple reagent properties
+		seqPropID = pHandler.findPropID('sequence')
+
+		# Actual property values - Updated Oct. 31/08
+		#fp_insert_cs = cloning_sites[0]
+		#tp_insert_cs = cloning_sites[1]
+
+		# oct. 31/08
+		if len(cloning_sites) > 0:
+			fp_insert_cs = cloning_sites[0]
+			
+			if len(cloning_sites) > 1:
+				tp_insert_cs = cloning_sites[1]
+			else:
+				tp_insert_cs = 'None'
+		else:
+			fp_insert_cs = 'None'
+			
+		#print "Cloning sites " + `cloning_sites`
+		#print "Linkers " + `linkers`
+
+		newSeq = ""	# resulting sequence
+
+		# Dec. 9/08: Added right before launch: VERY important for directional cloning - CANNOT just blindly always set Insert linear to 'false'!
+		if fp_insert_cs != tp_insert_cs:
+			linear = False
+		else:
+			# Do NOT use linear=False in searching Insert sequence for IDENTICAL sites!!! (e.g. EcoRI children of V2327 Topo)
+			linear = True
+			
+		#print `linear`
+		
+		# Fetch sequences of the Insert and Parent Vector
+		pvSeq = self.findSequenceByID(pvSeqID).upper()			# uniform case
+		
+		if reverse_insert:
+			#print "reversing insert"
+			insertSeq = self.reverse_complement(insertSeq)
+			
+			# NO!!!!!!!!  removed Feb. 24/10; modified PHP input page, sites will arrive in correct order
+			## Jan. 30/09: MUST change sites order too!!!!!!!!!!!!!!!!!!!!!!!!
+			#fp_insert_cs = cloning_sites[1]
+			#tp_insert_cs = cloning_sites[0]
+			
+		#print fp_insert_cs
+		#print tp_insert_cs
+		
+		#print insertSeq
+		
+		# removed May 15/08
+		#insertSeq = self.findSequenceByID(insertSeqID).lower()
+		
+		# Check is the cloning sites are hybrid
+		five_prime_site = utils.make_array(fp_insert_cs)
+		three_prime_site = utils.make_array(tp_insert_cs)
+
+		if self.isHybrid(five_prime_site) or self.isHybrid(three_prime_site):
+			#print "HYBRID SITES!!"
+			#print `five_prime_site`
+			#newSeq = self.hybrid(five_prime_site, three_prime_site, pvSeq, insertSeq, fp_insert_linker, tp_insert_linker)
+			
+			# oct 31/08
+			newSeq = self.hybrid(five_prime_site, three_prime_site, pvSeq, insertSeq)	# no linkers
+			
+			if not newSeq:
+				# Reverse the **********INSERT*******!!!!!!!!!!!!!!!!!
+				insertSeq = self.reverse_complement(insertSeq).upper()
+				newSeq = self.hybrid(five_prime_site, three_prime_site, pvSeq, insertSeq)	
+
+		# Update March 8, 2010: SfiI will now be treated the same as the rest of degenerate sites
+		# This exception will most likely be raised if the Insert contains gateway (attB) sites - Moved here Nov, 17/08
+		#elif fp_insert_cs not in self.sitesDict or tp_insert_cs not in self.sitesDict and fp_insert_cs != "SfiI" and tp_insert_cs != "SfiI":
+		elif fp_insert_cs not in self.sitesDict or tp_insert_cs not in self.sitesDict:
+			raise InsertSitesException()
+		
+		# Oct. 31/08 - Removed March 8/10: no, SfiI will now be the same as the rest of degenerates
+		#elif cloning_sites[0] == "SfiI" and cloning_sites[1] == "SfiI":
+			#fpSite = "GGCCATTACGGCC"
+			#tpSite = "GGCCGCCTCGGCC"
+			
+			#fp_start_pv = pvSeq.upper().find(fpSite)
+			
+			#if fp_start_pv < 0:
+				#fpSite = "GGCCATTATGGCC"
+				#fp_start_pv = pvSeq.upper().find(fpSite)
+				
+				#if fp_start_pv >= 0:
+					#tp_start_pv = pvSeq.upper().find(tpSite)
+					
+					#if fp_start_pv > tp_start_pv:
+						##print "Error: 5' before 3'"
+						#newSeq = ""
+					
+					#elif fp_start_pv > 0:
+						#pvSeqPre = pvSeq[0:fp_start_pv+8]	# SfiI cleaves after 8th nt
+						#pvSeqPost = pvSeq[tp_start_pv+8:]
+						
+						## get the remaining portion of the cloning site from the Insert
+						#fp_start_insert = insertSeq.find(fpSite.lower())
+						#tp_start_insert = insertSeq.find(tpSite.lower())
+						
+						## here, add 1 to 5' cleavage position
+						#insertSeq = insertSeq[fp_start_insert+8:tp_start_insert+8]
+						#newSeq = pvSeqPre + insertSeq + pvSeqPost
+
+			#else:
+				#tp_start_pv = pvSeq.upper().find(tpSite)
+				
+				#pvSeqPre = pvSeq[0:fp_start_pv+8]	# SfiI cleaves after 8th nt, subtract 1 get 7
+				#pvSeqPost = pvSeq[tp_start_pv+8:]
+				
+				## get the remaining portion of the cloning site from the Insert
+				#fp_start_insert = insertSeq.find(fpSite.lower())
+				#tp_start_insert = insertSeq.find(tpSite.lower())
+				
+				## here, add 1 to 5' cleavage position
+				#insertSeq = insertSeq[fp_start_insert+8:tp_start_insert+8]
+				#newSeq = pvSeqPre + insertSeq + pvSeqPost
+		else:
+			## March 5, 2010: CHECK COMPATIBILITY
+			#if self.makeEnzyme(tp_insert_cs) not in self.makeEnzyme(fp_insert_cs).compatible_end():
+				#raise HybridizationException("")
+			
+			if self.enzDict.has_key(fp_insert_cs):
+				fp_insert_cs = self.enzDict[fp_insert_cs]
+				
+			if self.enzDict.has_key(tp_insert_cs):
+				tp_insert_cs = self.enzDict[tp_insert_cs]
+			
+			# Dec. 14/09: Added empty sequence exception handling
+			if len(utils.squeeze(pvSeq).strip()) > 0:
+				# Updated Oct. 2/08
+				parentVectorSequence = Seq(pvSeq)
+			else:
+				raise EmptyParentVectorSequenceException("Empty parent vector sequence")
+			
+			if len(utils.squeeze(insertSeq).strip()) > 0:
+				insertSequence = Seq(insertSeq.upper())
+			else:
+				raise EmptyParentInsertSequenceException("Empty parent insert sequence")
+			
+			# BioPython "search" returns a LIST of ALL positions where the enzyme cuts the sequence.  Get the appropriate position (for 5' on PV it's usually the first) and subtract 1 to convert from biological to computer notation
+			
+			pv_five_prime_pos = fp_insert_cs.search(parentVectorSequence, linear)
+			pv_three_prime_pos = tp_insert_cs.search(parentVectorSequence, linear)
+			
+			#print "5' positions on PV sequence: " + `pv_five_prime_pos`
+			#print "3' positions on PV sequence: " + `pv_three_prime_pos`
+			
+			pv_five_prime_pos.sort()
+			pv_three_prime_pos.sort()
+			
+			#print `linear`
+			#print `pv_five_prime_pos`
+			#print `pv_three_prime_pos`
+			
+			# March 5, 2010: Still, for degenerates, above check wouldn't work: e.g. AscI is potentially compatible with AflIII IFF overhangs are compatible.  So for degenerate sites get actual overhang from sequence
+			if tp_insert_cs.is_ambiguous() or fp_insert_cs.is_ambiguous():
+				fp_start_pv = int(pv_five_prime_pos[0]) - 1
+				
+				# March 9, 2010: Different behaviour for identical sites
+				if fp_insert_cs != tp_insert_cs:
+					tp_start_pv = int(pv_three_prime_pos[0]) - 1
+				else:
+					tp_start_pv = int(pv_five_prime_pos[len(pv_five_prime_pos)-1]) - 1
+				
+				# correction March 5/10 
+				# Updated March, 9/10: ovhg position comparison doesn't work with our existing SfiI: its fp_insert_cs.ovhg is 3 but it's still a 3' overhang enzyme, fp_insert_cs.elucidate().find("_") is 5, so, even though the condition holds, testing with V1889 and I50004 RC yields incorrect results!!!!!
+				#if fp_insert_cs.ovhg < fp_insert_cs.elucidate().find("_"):
+				if fp_insert_cs.is_5overhang():
+					fp_pv_ovhg = pvSeq[fp_start_pv:fp_start_pv+len(fp_insert_cs.ovhgseq)]
+				else:
+					fp_pv_ovhg = pvSeq[fp_start_pv-len(fp_insert_cs.ovhgseq):fp_start_pv]
+				
+				#fp_pv_ovhg = pvSeq[fp_start_pv:fp_start_pv+len(fp_insert_cs.ovhgseq)]
+				
+				if  tp_insert_cs.is_5overhang():
+				#if tp_insert_cs.ovhg < tp_insert_cs.elucidate().find("_"):
+					tp_pv_ovhg = pvSeq[tp_start_pv:tp_start_pv+len(tp_insert_cs.ovhgseq)]
+				else:
+					tp_pv_ovhg = pvSeq[tp_start_pv-len(tp_insert_cs.ovhgseq):tp_start_pv]
+				
+				#tp_pv_ovhg = pvSeq[tp_start_pv:tp_start_pv+len(tp_insert_cs.ovhgseq)]
+				
+				#print "5' PV overhang: " + fp_pv_ovhg
+				#print "3' PV overhang: " + tp_pv_ovhg
+				
+				insert_five_prime_pos = fp_insert_cs.search(insertSequence, linear)
+				insert_three_prime_pos = tp_insert_cs.search(insertSequence, linear)
+				
+				#print "5' positions on Insert sequence: " + `insert_five_prime_pos`
+				#print "3' positions on Insert sequence: " + `insert_three_prime_pos`
+				
+				fp_start_insert = int(insert_five_prime_pos[0]) - 1
+				
+				# March 9, 2010: identical sites
+				if fp_insert_cs != tp_insert_cs:
+					tp_start_insert = int(insert_three_prime_pos[0]) - 1
+				else:
+					tp_start_insert = int(insert_three_prime_pos[len(insert_three_prime_pos)-1]) - 1
+					
+				if fp_insert_cs.is_5overhang():
+					fp_insert_ovhg = insertSeq[fp_start_insert:fp_start_insert+len(fp_insert_cs.ovhgseq)]
+				else:
+					fp_insert_ovhg = insertSeq[fp_start_insert-len(fp_insert_cs.ovhgseq):fp_start_insert]
+					
+				if tp_insert_cs.is_5overhang():
+					tp_insert_ovhg = insertSeq[tp_start_insert:tp_start_insert+len(tp_insert_cs.ovhgseq)]
+				else:
+					tp_insert_ovhg = insertSeq[tp_start_insert-len(tp_insert_cs.ovhgseq):tp_start_insert]
+				
+				#print "5' insert overhang: " + fp_insert_ovhg
+				#print "3' insert overhang: " + tp_insert_ovhg
+				
+				if fp_pv_ovhg.upper() != fp_insert_ovhg.upper():
+					raise IncompatibleFivePrimeOverhangsException("Incompatible 5' overhangs")
+				
+				if tp_pv_ovhg.upper() != tp_insert_ovhg.upper():
+					raise IncompatibleThreePrimeOverhangsException("Incompatible 3' overhangs")
+				
+			if len(pv_five_prime_pos) > 0:
+				fp_start_pv = int(pv_five_prime_pos[0]) - 1
+			
+				#print `fp_start_pv`
+			
+				# Nov. 3/08: Check 5' after 3'
+				
+				if len(pv_three_prime_pos) > 0:
+					tp_start_pv = int(pv_three_prime_pos[len(pv_three_prime_pos)-1]) - 1
+					
+					#print "5' pv " + `fp_start_pv`
+					#print "3' pv " + `tp_start_pv`
+					
+					if fp_start_pv > tp_start_pv:
+						#if not reverse_insert:
+						raise FivePrimeAfterThreePrimeException("5' site occurs after 3' site on parent vector sequence")
+					else:	
+						#print "Here!" + insertSeq
+						pvSeqPre = pvSeq[0:fp_start_pv]
+						#print pvSeqPre
+						
+						# get the remaining portion of the cloning site from the Insert
+						insert_five_prime_pos = fp_insert_cs.search(insertSequence, linear)
+						#print `insert_five_prime_pos`
+						insert_five_prime_pos.sort()
+						
+						if len(insert_five_prime_pos) > 0:	
+							fp_start_insert = int(insert_five_prime_pos[0]) - 1
+							#print `fp_start_insert`
+							
+							# for the 3' site on Insert, grab its LAST cutting position
+							#print tp_insert_cs
+							#print insertSequence
+							insert_three_prime_pos = tp_insert_cs.search(insertSequence, linear)
+							#print `insert_three_prime_pos`
+							insert_three_prime_pos.sort()
+							
+							if len(insert_three_prime_pos) > 0:
+								tp_end_insert = int(insert_three_prime_pos[len(insert_three_prime_pos)-1]) - 1
+								#print `tp_end_insert`
+								
+								# March 10/10: check 5' before 3' on INSERT sequence!!!!
+								tp_start_insert = int(insert_three_prime_pos[0])-1
+								
+								if fp_start_insert > tp_start_insert:
+									raise InsertFivePrimeAfterThreePrimeException("")
+							else:
+								# Dec. 2/08: NO!!!!!!!! THIS IS THE WHOLE POINT, TO DISALLOW C0MBINING NON-COMPATIBLE INSERT AND VECTOR!  Do NOT do this!!!
+								'''
+								## Oct. 7/08: Use entire Insert		# removed Dec. 2/08
+								#fp_start_insert = 0			# removed Dec. 2/08
+								#tp_end_insert = len(insertSeq)		# removed Dec. 2/08
+								'''
+								#print "????"
+								raise CloningSitesNotFoundInInsertException("")		# dec. 2/08
+						else:
+							# Dec. 2/08: NO!!!!!!!!!!!!!!!!!!!!! THAT'S THE WHOLE POINT, TO DISALLOW C0MBINING NON-COMPATIBLE INSERT AND VECTOR!!!!!!!!!!!!!!!!
+							
+							## Oct. 7/08: Use entire Insert		# removed Dec. 2/08
+							#fp_start_insert = 0			# removed Dec. 2/08
+							#tp_end_insert = len(insertSeq)		# removed Dec. 2/08
+							#print "????"
+							raise CloningSitesNotFoundInInsertException("")		# replaced Dec. 2/08
+							
+						insertSeq = insertSeq[fp_start_insert:tp_end_insert]
+						#print insertSeq
+						
+						# Get the LAST cutting position of the 3' site on PV sequence
+						#pv_three_prime_pos = tp_insert_cs.search(parentVectorSequence, False)
+						
+						#if len(pv_three_prime_pos) > 0:
+						tp_end_pv = int(pv_three_prime_pos[len(pv_three_prime_pos)-1]) - 1
+						#print `pv_three_prime_pos`
+						#print tp_end_pv
+						
+						if tp_end_pv > 0:
+							pvSeqPost = pvSeq[tp_end_pv:]
+							#print pvSeqPost
+							
+							newSeq = pvSeqPre + insertSeq + pvSeqPost
+							#print newSeq
+				else:
+					raise InsertSitesNotFoundOnParentSequenceException("5' site not found on PV sequence")
+			else:
+				raise InsertSitesNotFoundOnParentSequenceException("5' site not found on PV sequence")
+			
+		return newSeq
+
+
+	############################################
+	### LOXP Recombinmation Vector sequences ###
+	############################################
+	
+	#def constructRecombSequence(self, pvSeqID, ipvSeqID, insertSeqID, insertLinkers):
+	def constructRecombSequence(self, pvSeqID, ipvSeqID):
+	
+		#print "Content-type:text/html"
+		#print
+		
+		db = self.db
+		cursor = self.cursor
+		
+		loxp_seq = "ATAACTTCGTATAGCATACATTATACGAAGTTAT"
+		
+		# Fetch sequences of the Parent Vector and Insert Parent Vector
+		pvSeq = self.findSequenceByID(pvSeqID).upper()
+		ipvSeq = self.findSequenceByID(ipvSeqID).upper()
+		
+		# Dec. 14/09: Added empty sequence exception handling
+		if len(utils.squeeze(pvSeq).strip()) == 0:
+			raise EmptyParentVectorSequenceException("Empty parent vector sequence")
+		
+		if len(utils.squeeze(ipvSeq).strip()) == 0:
+			raise EmptyInsertParentVectorSequenceException("Empty insert parent vector sequence")
+		
+		# resulting sequence
+		newSeq = ""
+	
+		# Replace the single loxP sequence on PV sequence with the Insert sequence portion between two loxP sites (from start of first loxP to the end of second loxP) of the IPV sequence
+
+		# Make sure pvSeq contains LoxP exactly once
+		numLoxp_pv = utils.numOccurs(pvSeq, loxp_seq)
+		
+		if numLoxp_pv == 1:
+			ipv_loxp_1 = ipvSeq.upper().find(loxp_seq) + len(loxp_seq)
+			ipv_loxp_2 = ipvSeq.upper().rfind(loxp_seq)
+			
+			# October 31, 2008, Karen: We agreed that it is okay for Insert to be in lowercase and cDNA to be defined by position
+			ipv_insert_seq = loxp_seq.upper() + ipvSeq[ipv_loxp_1:ipv_loxp_2].lower() + loxp_seq.upper()
+			newSeq = pvSeq.replace(loxp_seq, ipv_insert_seq)
+
+		elif numLoxp_pv == 0:
+			raise InsertSitesNotFoundOnParentSequenceException("LOXP sites not found on parent vector sequence")
+
+		elif numLoxp_pv > 1:
+			raise MultipleSiteOccurrenceException("LOXP found more than once on parent vector sequence")
+
+		return newSeq
+		
+
+	#########################
+	### Gateway sequences ###
+	#########################
+	
+	##############################################################################################
+	# Find the linker portion between attB site and start of insert on primer sequence recursively
+	# Input: insert_seq: string
+	#	 primer_seq: string, trailing portion of oligo sequence after attB site
+	# 	 linker: string
+	# Output: linker: string
+	##############################################################################################
+	#def linker_from_oligo(insert_seq, primer_seq, linker):
+	def linker_from_oligo(self, insert_seq, primer_seq, linker=""):
+		
+		if insert_seq.find(primer_seq) != 0:
+			linker += primer_seq[0]
+			primer_seq = primer_seq[1:]
+			return self.linker_from_oligo(insert_seq, primer_seq, linker)
+	
+		return linker
+		
+		
+	# Nov. 12/09: had an error, so took code from TEST
+	def entryVectorSequence(self, pvSeqID, insertSeq):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		# property map
+		propMapper = ReagentPropertyMapper(db, cursor)
+		prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+
+		parentVectorSequence = self.findSequenceByID(pvSeqID)
+	
+		# Dec. 14/09: Added empty sequence exception handling
+		if len(utils.squeeze(parentVectorSequence).strip()) == 0:
+			raise EmptyParentVectorSequenceException("Empty parent vector sequence")
+		
+		if len(utils.squeeze(insertSeq).strip()) == 0:
+			raise EmptyParentInsertSequenceException("Empty parent insert sequence")
+		
+		# output value
+		newSeq = ""
+		
+		# Initialize new sequence of entry vector to sequence of its parent vector
+		entryVectorSeq = parentVectorSequence
+		
+		# CHANGED MAY 14/08: INSERT SEQUENCE CONTAINS SITES ALREADY; the new Insert sequence is a portion of original Insert between 5' start and 3' end
+		
+		# Update September 8, 2009: NO!!!  Inserts made through Primer Design contain an extension before the att site, and preload.py passes the ENTIRE sequence to this function - so still need to trim off the extra portion of the Insert.  See below (define sites first, then trim Insert)
+		
+		# June 8/08:
+		attB1_a = "gtacaaaaaa"
+		attB1_b = "gttggcacc"			# 5' GW Donor linker (stop codon not included for uniformity)
+
+		attP1_a = "CCAACTTT"
+		attP1_b = "GTACAAAAAA"
+
+		attP1 = attP1_a + attP1_b		# CCAACTTT|GTACAAAAAA
+
+		attL1 = attP1 + attB1_b			# CCAAC|TTT GTACAAAAAA GTTGGCACC
+
+		# attB2 site is the reverse complement of GW Donor 3' Linker ggggacaacttt gtacaagaaa gttgggta (stop codon not included)
+		attB2_a = "tacccaac"			# rev. compl. gttgggta
+		attB2_b = "TTTCTTGTAC"			# rev. compl. gtacaagaaa
+		
+		attB2 = attB2_a + attB2_b		# tacccaacTTTCTTGTAC
+
+		attP2_a = "TTCAGCTTT"
+		attP2_b = "AAAGTTGGCATTATAA"
+
+		attP2 = attP2_a + "CTTGTAC" + attP2_b	# TTCAGCTTT
+
+		attL2 = attB2 + attP2_b			# tacccaacTTTCTTGTACAAAGTTggcattataa
+
+		# Sept. 8/09: From above - trim off portion of Insert sequence to have it begin with attB1 and end with attB2
+		#print "Content-type:text/html"
+		#print
+		
+		insert_start = insertSeq.lower().find(attB1_a)
+		#print insertSeq
+		#print insert_start
+		
+		insert_end = insertSeq.lower().rfind(attB2_b.lower()) + len(attB2_b)
+		#print insert_end
+		
+		insertSeq = insertSeq[insert_start:insert_end]
+		#print insertSeq
+		
+		# check attP1 occurs exactly once on parent vector sequence - JUNE 8/08: CHECK CORE
+		numOcc_attP1_pv = utils.numOccurs(entryVectorSeq.upper(), self.gatewayDict['attP1'])
+		
+		if numOcc_attP1_pv > 1:
+			raise MultipleSiteOccurrenceException("attP1 found more than once on parent vector sequence")
+	
+		elif numOcc_attP1_pv == 0:
+			raise InsertSitesNotFoundOnParentSequenceException("attP1 site not found on parent vector sequence")	
+	
+		# check attP2 occurs exactly once on parent vector sequence
+		numOcc_attP2_pv = utils.numOccurs(entryVectorSeq.upper(), self.gatewayDict['attP2'])
+		
+		if numOcc_attP2_pv > 1:
+			raise MultipleSiteOccurrenceException("attP2 found more than once on parent vector sequence")
+	
+		elif numOcc_attP2_pv == 0:
+			raise InsertSitesNotFoundOnParentSequenceException("attP2 site not found on parent vector sequence")
+		
+		if entryVectorSeq.find(attP1) > 0 and entryVectorSeq.find(attP2):
+			
+			# Updated June 7/08
+			#startpos = entryVectorSeq.find(attP1) + len(attP1) - len(attB1)	# removed June 7/08
+			startpos = entryVectorSeq.find(attP1_a) + len(attP1_a)			# added June 7/08
+			endpos = entryVectorSeq.find(attP2_b)
+			
+			# check attP1 occurs before attP2 on parent sequence
+			if startpos > endpos:
+				raise FivePrimeAfterThreePrimeException("attP1 occurs after attP2 on parent vector sequence")
+			
+			# Modified May 16/08
+			sub_remove = entryVectorSeq[startpos:endpos]
+			
+			#print "Content-type:text/html"
+			#print
+			#print newInsertSeq
+			
+			# action
+			newSeq = entryVectorSeq.replace(sub_remove, insertSeq)
+			
+		else:
+			raise InsertSitesNotFoundOnParentSequenceException("attP sites not found on parent vector sequence")
+
+		return newSeq
+
+
+	###########################################
+	# Gateway Expression clones
+	# Modified June 8/08: Changed signature
+	###########################################
+	#def expressionVectorSequence(self, pvSeqID, insertSeqID, linkers):
+	def expressionVectorSequence(self, pvSeqID, ipvSeq):
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"
+		#print
+
+		# return value
+		newSeq = ""
+		
+		# Fetch Parent Vector sequence
+		pvSeq = self.findSequenceByID(pvSeqID).upper()
+	
+		# Dec. 14/09: Added empty sequence exception handling
+		if len(utils.squeeze(pvSeq).strip()) == 0:
+			raise EmptyParentVectorSequenceException("Empty parent vector sequence")
+		
+		if len(utils.squeeze(ipvSeq).strip()) == 0:
+			raise EmptyInsertParentVectorSequenceException("Empty insert parent vector sequence")
+			
+		# Modified Oct. 28/08
+		parentVectorSequence = pvSeq.upper()
+	
+		# Cut IPV at the appropriate places
+		fpSite = "GTACAAAAAA"
+		tpSite = "TTTCTTGTAC"
+		
+		fp_start = ipvSeq.upper().find(fpSite)
+		#print `fp_start`
+		
+		# nov. 28/08
+		if fp_start < 0:
+			raise InsertSitesNotFoundOnParentSequenceException("attR1 site not found on parent vector sequence")
+		
+		fp_end = fp_start + len(fpSite)
+	
+		tp_start = ipvSeq.upper().find(tpSite)
+		
+		# nov. 28/08
+		if tp_start < 0:
+			raise InsertSitesNotFoundOnParentSequenceException("attR1 site not found on parent vector sequence")
+		
+		tp_end = tp_start + len(tpSite)
+	
+		iSeq = ipvSeq[fp_start:tp_end]
+	
+		# removed Oct. 28/08
+		## June 8/08:
+		#attR1_a = "TACAAGTTT"
+		#attR2_b = "AAAGTGG"
+
+		# check core sequence
+		numAttR1_pv = utils.numOccurs(pvSeq, self.gatewayDict['attR1'])
+		
+		if numAttR1_pv == 0:
+			raise InsertSitesNotFoundOnParentSequenceException("attR1 site not found on parent vector sequence")
+		
+		elif numAttR1_pv > 1:
+			raise MultipleSiteOccurrenceException("attR1 found more than once on parent vector sequence")
+		
+		numAttR2_pv = utils.numOccurs(pvSeq, self.gatewayDict['attR2'])
+		
+		if numAttR2_pv == 0:
+			raise InsertSitesNotFoundOnParentSequenceException("attR2 site not found on parent vector sequence")
+		
+		elif numAttR2_pv > 1:
+			raise MultipleSiteOccurrenceException("attR2 found more than once on parent vector sequence")
+
+		# changed oct 28/08
+		#if pvSeq.find(attR1_a) > 0 and pvSeq.find(attR2_b) > 0:
+			## Changed June 8/08
+			#startpos = pvSeq.find(attR1_a) + len(attR1_a)
+			#endpos = pvSeq.find(attR2_b)
+
+			#if startpos > endpos:
+				#raise FivePrimeAfterThreePrimeException("attR1 occurs after attR2 on parent vector sequence")
+			
+			#seq_remove = pvSeq[startpos:endpos]
+
+			## action
+			#newSeq = pvSeq.replace(seq_remove, ipvSeq)
+		
+		# oct 28/08
+		if parentVectorSequence.find(self.gatewayDict['attR1']) >= 0 and parentVectorSequence.find(self.gatewayDict['attR2']) >= 0:
+			
+			#startpos = parentVectorSequence.find(attR1_a) + len(attR1_a)
+			startpos = parentVectorSequence.find(self.gatewayDict['attR1']) + 3		# cuts after the 'TTT'
+			#endpos = parentVectorSequence.find(attR2_b)
+			endpos = parentVectorSequence.find(self.gatewayDict['attR2']) + len(self.gatewayDict['attR2'])
+	
+			if startpos > endpos:
+				#raise FivePrimeAfterThreePrimeException("attR1 occurs after attR2 on parent vector sequence")
+				print "attR1 occurs after attR2 on parent vector sequence"
+				return newSeq
+			
+			seq_remove = parentVectorSequence[startpos:endpos]
+	
+			# action
+			newSeq = parentVectorSequence.upper().replace(seq_remove, iSeq.lower())
+		else:
+			raise InsertSitesNotFoundOnParentSequenceException("attR sites not found on parent vector sequence")
+
+		return newSeq
+
+
+##################################################################################
+# Class RNAHandler
+# Descendant of SequenceHandler, handles RNA sequence operations
+# Written October 22, 2009, by Marina Olhovsky
+##################################################################################
+class RNAHandler(SequenceHandler):
+	"Contains functions and attributes specific to RNA sequences"
+
+	# global variable
+	sitesDict = {}
+	enzDict = {}
+	
+	nucleotides = ['A', 'a', 'C', 'c', 'G', 'g', 'U', 'u', 'N', 'n']
+	
+	rnaSeqTypeID = 3
+
+	# Parameters: seq = RNASequence object
+	def matchSequence(self, seq):
+		db = self.db			# localize for easy access
+		cursor = self.cursor		# ditto
+		
+		newRNASeqID = 0
+		rnaSeqTypeID = self.rnaSeqTypeID
+		
+		if seq.isRNA():
+			rna_seq = seq.getSequence()
+			start = seq.getSeqStart()
+			end = seq.getSeqEnd()
+			rna_len = len(rna_seq)
+			
+			if rna_len > 0:
+				cursor.execute("SELECT `seqID` FROM `Sequences_tbl` WHERE `seqTypeID`=" + `rnaSeqTypeID` + " AND `sequence`=" + `rna_seq` + " AND `start`=" + `start` + " AND `end`=" + `end` + " AND `length`=" + `rna_len` + " AND `status`='ACTIVE'")
+				result = cursor.fetchone()	# technically there should only be one; if more it's an error, but just assume one for now and add error checks later
+
+				if result:
+					newRNASeqID = int(result[0])
+					
+		return int(newRNASeqID)
+	
+
+	# Insert a new sequence into OpenFreezer
+	# Parameters: seq = RNASequence object
+	def insertSequence(self, seq):
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+		
+		newRNASeqID = 0
+		rnaSeqTypeID = self.rnaSeqTypeID
+		
+		if seq.isRNA():
+			rna_seq = seq.getSequence()
+			start = seq.getSeqStart()
+			end = seq.getSeqEnd()
+			rna_len = len(rna_seq)
+			rna_mw = seq.getMW()
+			
+			if rna_len > 0:
+				cursor.execute("INSERT INTO Sequences_tbl(seqTypeID, sequence, start, end, length, mw) VALUES(" + `rnaSeqTypeID` + ", " + `rna_seq` + ", " + `start` + ", " + `end` + ", " + `rna_len` + ", " + `rna_mw` + ")")
+				newRNASeqID = int(db.insert_id())
+			
+		return newRNASeqID
+	
+	
+	def getSequenceID(self, seq):
+		db = self.db			# for easy access
+		cursor = self.cursor		# for easy access
+
+		# Feb. 26/08: Make sure seq is not null
+		if seq:
+			if seq.isRNA():
+				rna_seq = seq.getSequence()
+				start = seq.getSeqStart()
+				end = seq.getSeqEnd()
+				rna_len = len(rna_seq)
+	
+				if len(rna_seq) > 0:
+					# First check if this sequence is already stored in LIMS
+					newRNASeqID = self.matchSequence(seq)
+				
+					if newRNASeqID == 0:
+						newRNASeqID = self.insertSequence(seq)
+						
+					return newRNASeqID
+		return -1
+	
+	
+	def squeeze(self, seq):
+		new_seq = ""
+		nextInd = 0
+		
+		while nextInd < len(seq):
+			nextChar = seq[nextInd]
+			
+			if nextChar in self.nucleotides:
+				new_seq += nextChar
+				
+			nextInd += 1
+		
+		return new_seq
+
+
+	def calculateMW_RNA(self, sequence):
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print				
+		
+		mw = 0.0
+		sequence = sequence.upper()
+		#print sequence
+		
+		if len(sequence) == 0:
+			return 0
+		
+		# Molecular Weight = (An x 329.21) + (Un x 306.17) + (Cn x 305.18) + (Gn x 345.21) + 159.0
+
+		mw_dict = {'A': 313.209, 'G':329.208, 'C':289.184, 'U':306.17}
+		
+		num_A = float(sequence.count('A'))
+		num_C = float(sequence.count('C'))
+		num_G = float(sequence.count('G'))
+		num_U = float(sequence.count('U'))
+		
+		weight_A = num_A * mw_dict['A']
+		weight_C = num_C * mw_dict['C']
+		weight_G = num_G * mw_dict['G']
+		weight_U = num_U * mw_dict['U']
+		
+		base_weight = float(weight_A) + float(weight_C) + float(weight_G) + float(weight_U)
+		#print `base_weight`
+		
+		mw = base_weight + 159.00
+		#print round(mw, 2)
+		return round(mw, 2)
diff --git a/OpenFreezer/cgi/session.py b/OpenFreezer/cgi/session.py
new file mode 100755
index 0000000..3d407f1
--- /dev/null
+++ b/OpenFreezer/cgi/session.py
@@ -0,0 +1,50 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+
+import MySQLdb
+import os
+
+from database_conn import DatabaseConn
+from exception import *
+
+from user import User
+from user_handler import UserHandler
+
+from laboratory import Laboratory
+from lab_handler import LabHandler
+
+#####################################################################################
+# Stores OpenFreezer session information
+#
+# Written June 27, 2007, by Marina Olhovsky
+# Last modified: June 27, 2007
+#####################################################################################
+class Session:
+	
+	# Session variables
+	__user = None
+	
+	# ... more to come ...
+	
+	
+	##########################################################
+	# Constructor
+	##########################################################
+	def __init__(self):
+		self.__user = None
+		
+	@classmethod
+	def setUser(self, user):
+		self.__user = user
+				
+		
+	def setSessionVars(self, user):
+		self.__user = user
+		
+		# ... more to come ...
+
+	@classmethod
+	def getUser(self):
+		return self.__user
diff --git a/OpenFreezer/cgi/session_handler.py b/OpenFreezer/cgi/session_handler.py
new file mode 100755
index 0000000..926bb71
--- /dev/null
+++ b/OpenFreezer/cgi/session_handler.py
@@ -0,0 +1,131 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+
+import SocketServer
+from SocketServer import BaseRequestHandler
+
+import MySQLdb
+
+import os
+import sys
+import string
+
+# Custom modules
+import utils
+
+from database_conn import DatabaseConn
+from exception import *
+
+from user import User
+from user_handler import UserHandler
+
+from laboratory import Laboratory
+from lab_handler import LabHandler
+
+from Cookie import SimpleCookie
+#####################################################################################
+# Implements session handling for OpenFreezer
+# Extends abstract class BaseRequestHandler
+#
+# Written June 27, 2007, by Marina Olhovsky
+# Last modified: June 27, 2007
+#####################################################################################
+class SessionHandler(BaseRequestHandler):
+	
+	__db = None
+	__cursor = None
+	__hostname = ""
+	
+	__user = None
+	
+	##########################################################
+	# Constructor
+	##########################################################
+	def __init__(self):
+	
+		dbConn = DatabaseConn()
+		db = dbConn.databaseConnect()
+		cursor = db.cursor()
+		hostname = dbConn.getHostname()
+
+		self.__db = db
+		self.__cursor = cursor
+		self.__hostname = hostname
+		self.__user = None
+		
+		
+	##########################################################
+	# Override parent method
+	##########################################################
+	def handle(self):
+		
+		# For convenience, create local copies of global variables
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		uHandler = UserHandler(db, cursor)
+		
+		form = cgi.FieldStorage(keep_blank_values="True")
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		if form.has_key("loginsubmit"):
+			username = form.getvalue("loginusername_field")
+			passwd = form.getvalue("loginpassword_field")
+			
+			if self.checkPermissions(username, passwd):
+				session = SimpleCookie(os.environ['HTTP_COOKIE'])
+				phpsessid = session['PHPSESSID'].value
+				session["userinfo"] = self.__user
+
+				utils.redirect(os.environ['HTTP_REFERER'])
+			
+	
+	############################################################################
+	# Verify that a user is authorized to access the system using uname and pwd
+	############################################################################
+	def checkPermissions(self, uname, pwd):
+	
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		
+		db = self.__db
+		cursor = self.__cursor
+		
+		cursor.execute("SELECT u.userID, u.firstname, u.lastname, u.description, c.category, u.labID, l.lab_name, u.email FROM Users_tbl u, LabInfo_tbl l, UserCategories_tbl c WHERE u.username=" + `uname` + " AND u.password=MD5(" + `pwd` + ") AND u.labID=l.labID AND c.categoryID=u.category AND u.status='ACTIVE' AND l.status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			uid = int(result[0])
+			firstname = result[1]
+			lastname = result[2]
+			description = result[3]
+			category = result[4]
+			labID = int(result[5])
+			labname = result[6]
+			email = result[7]
+			
+			newLab = Laboratory(labID, labname)
+			newUser = User(uid, uname, firstname, lastname, description, newLab, category, email, pwd)
+			
+			self.__user = newUser
+			return True
+		else:
+			return False
+	
+			
+
+##########################################################
+# Central callable function
+##########################################################
+def main():
+
+	sessHandler = SessionHandler()
+	sessHandler.handle()
+
+main()
diff --git a/OpenFreezer/cgi/system_set_handler.py b/OpenFreezer/cgi/system_set_handler.py
new file mode 100755
index 0000000..678f6fd
--- /dev/null
+++ b/OpenFreezer/cgi/system_set_handler.py
@@ -0,0 +1,214 @@
+import string
+import MySQLdb
+
+from general_handler import *
+
+################################################################################
+# Module system_set_handler
+# An interface to System_Set_tbl and System_Set_Groups_tbl in OpenFreezer
+#
+# This module performs SQL queries to deal specifically with dropdown lists in
+# reagent creation and detailed views
+#
+# Written November 2, 2006 by Marina Olhovsky
+#
+# Last modified: July 15, 2009
+#####################################################################################################################
+
+#####################################################################################################################
+# SystemSetHandler class
+# Subclass of GeneralHandler class
+# Written November 2, 2006, by Marina Olhovsky
+#
+# Note on table structure change July 15/09:
+# - removed groupType and groupName columns from System_Set_Groups_tbl
+# - renamed propertyIDLink column to reagentTypeAttributeID
+# - reagentTypeAttributeID column is a foreign key referencing ReagentTypeAttributes_tbl(reagentTypePropertyID)
+#   (the purpose is to enable dropdown list value separation across reagent types)
+#####################################################################################################################
+class SystemSetHandler(GeneralHandler):
+
+	"This class handles reagent properties in OpenFreezer that are shown as dropdown lists on various views"
+
+	def __init__(self, db, cursor):
+		self.db = db
+		self.cursor = cursor
+
+	
+	# July 28/09: System_Set_Groups_tbl structure has been modified: Since we are now assigning certain properties and values to specific reagent types and the actual dropdown values may thus differ, the propertyIDLink column has been changed -- it is now called "reagentTypeAttributeID" and is a foreign key referencing ReagentTypeAttributeID column in ReagentTypeAttributes_tbl.  In other words, each dropdown is now associated with a particular property in a particular category for a particu [...]
+	def updateSet(self, rTypeAttrID, comments, entityVal):
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		
+		db = self.db
+		cursor = self.cursor
+		
+		setGroupID = self.findSetGroupID(rTypeAttrID)
+		
+		if setGroupID < 0:
+			setGroupID = self.addSetGroup(rTypeAttrID, comments)
+			
+		#print setGroupID
+			
+		self.addSetValue(setGroupID, entityVal)
+	
+	
+	# July 28/09: Add property to list of dropdowns
+	def addSetGroup(self, rTypeAttrID, comments):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		ssetGroupID = -1
+
+		cursor.execute("INSERT INTO System_Set_Groups_tbl(reagentTypeAttributeID, comments) VALUES(" + `rTypeAttrID` + ", " + `comments` + ")")
+		ssetGroupID = int(db.insert_id())
+		
+		return ssetGroupID
+		
+	
+	# July 28/09: Check whether ssetGroupID exists for this rTypeAttrID; create if doesn't
+	def findSetGroupID(self, rTypeAttrID):
+	
+		db = self.db
+		cursor = self.cursor
+
+		cursor.execute("SELECT ssetGroupID FROM System_Set_Groups_tbl WHERE reagentTypeAttributeID=" + `rTypeAttrID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+		
+		return -1
+		
+
+	# Add propVal to the appropriate dropdown list
+	# Input:
+	#   setGroupID = ssetGroupID column value in System_Set_tbl
+	#   entityVal = actual set value
+	# Return: new ssetGroupID
+	def addSetValue(self, setGroupID, entityVal):
+		db = self.db
+		cursor = self.cursor
+		
+		pHandler = ReagentPropertyHandler(db, cursor)		# April 13/09
+		
+		if not self.existsSetEntry(setGroupID, entityVal):
+			cursor.execute("INSERT INTO `System_Set_tbl`(`ssetGroupID`, `entityName`, `entityDesc`) VALUES(" + `setGroupID` + ", " + `entityVal` + ", " + `entityVal` + ")")
+
+
+	# Checks if the given set entry exists in System_Set_Groups_tbl
+	def existsSetEntry(self, ssetGroupID, entityVal):
+		db = self.db
+		cursor = self.cursor
+		
+		#cursor.execute("SELECT * FROM System_Set_Groups_tbl s1, System_Set_tbl s2 WHERE s1.groupDesc=" + `entityName` + " AND s1.ssetGroupID=s2.ssetGroupID AND s2.entityName=" + `entityVal` + " AND s1.status='ACTIVE' AND s2.status='ACTIVE'")
+		
+		cursor.execute("SELECT * FROM System_Set_tbl WHERE ssetGroupID=" + `ssetGroupID` + " AND entityName=" + `entityVal` + " AND status='ACTIVE'")
+		result = cursor.fetchall()
+		
+		if not result:
+			return 0	# the entity does NOT exist
+		else:
+			return 1
+		
+		
+	# Find a set of all values for a particular property (e.g. fetch all available Species, Insert Types, etc.)
+	# ssetGroupName: STRING, name of the property (Type of Insert, Species, etc.) - corresponds to 'groupName' column in System_Set_Groups_tbl
+	# Modified August 4/09
+	def findAllSetValues(self, ssetGroupID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		setValues = []
+		
+		#cursor.execute("SELECT s.entityName FROM System_Set_tbl s, System_Set_Groups_tbl g WHERE g.groupName=" + `ssetGroupName` + " AND g.ssetGroupID=s.ssetGroupID AND g.status='ACTIVE' AND s.status='ACTIVE' ORDER BY s.entityName")
+		cursor.execute("SELECT DISTINCT(s.entityName) FROM System_Set_tbl s, System_Set_Groups_tbl g WHERE g.ssetGroupID=s.ssetGroupID AND g.status='ACTIVE' AND s.status='ACTIVE' ORDER BY s.entityName")
+		results = cursor.fetchall()
+		
+		for result in results:
+			setVal = result[0]
+			setValues.append(setVal)
+			
+		return setValues
+
+
+	# Aug. 4/09: Find all dropdown set values for the attribute identified by propID in the given category for ALL reagent types currently existing in LIMS
+	def findAllPropSetValues(self, propID, categoryID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		setValues = []
+		
+		cursor.execute("SELECT DISTINCT(propCatID) FROM ReagentPropertyCategories_tbl WHERE propID=" + `propID` + " AND categoryID= " + `categoryID` + " AND status='ACTIVE'")
+		results = cursor.fetchall()
+		
+		propCatIDs = []
+		
+		for result in results:
+			propCatID = int(result[0])
+			propCatIDs.append("'" + `propCatID` + "'")
+		
+		if len(propCatIDs) > 0:
+			propCatIDList = "(" + string.join(propCatIDs, ", ") + ")"
+			
+			print "SELECT DISTINCT(reagentTypePropertyID) FROM ReagentTypeAttributes_tbl WHERE propertyTypeID IN " + propCatIDList + " AND status='ACTIVE'"
+			
+			cursor.execute("SELECT DISTINCT(reagentTypePropertyID) FROM ReagentTypeAttributes_tbl WHERE propertyTypeID IN " + propCatIDList + " AND status='ACTIVE'")
+			results = cursor.fetchall()
+			
+			rTypeAttrIDs = []
+			
+			for result in results:
+				rTypeAttrID = int(result[0])
+				rTypeAttrIDs.append("'" + `rTypeAttrID` + "'")
+				
+			if len(rTypeAttrIDs) > 0:
+				rTypeAttrIDList = "(" + string.join(rTypeAttrIDs, ", ") + ")"
+				
+				cursor.execute("SELECT DISTINCT(ssetGroupID) FROM System_Set_Groups_tbl WHERE reagentTypeAttributeID IN " + rTypeAttrIDList + " AND status='ACTIVE'")
+				results = cursor.fetchall()
+				
+				ssetGroupIDs = []
+				
+				for result in results:
+					ssetGroupID = int(result[0])
+					ssetGroupIDs.append("'" + `ssetGroupID` + "'")
+				
+				#print `ssetGroupIDs`
+				
+				if len(ssetGroupIDs) > 0:
+					ssetGroupIDList = "(" + string.join(ssetGroupIDs, ", ") + ")"
+					
+					#print ssetGroupIDList
+					#print "SELECT DISTINCT(s.entityName) FROM System_Set_tbl WHERE ssetGroupID IN " + ssetGroupIDList + " AND status='ACTIVE' ORDER BY s.entityName"
+					
+					cursor.execute("SELECT DISTINCT(entityName) FROM System_Set_tbl WHERE ssetGroupID IN " + ssetGroupIDList + " AND status='ACTIVE' ORDER BY entityName")
+					results = cursor.fetchall()
+					
+					for result in results:
+						setVal = result[0]
+						setValues.append(setVal)
+						
+		return setValues
+
+	
+	# June 3/09
+	def deleteSetValues(self, ssetGroupID):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE System_Set_tbl SET status='DEP' WHERE ssetGroupID=" + `ssetGroupID` + " AND status='ACTIVE'")
+	
+	
+	# Aug. 5/09
+	def deleteSetGroup(self, setGroupID):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("UPDATE System_Set_Groups_tbl SET status='DEP' WHERE ssetGroupID=" + `setGroupID` + " AND status='ACTIVE'")
diff --git a/OpenFreezer/cgi/update.py b/OpenFreezer/cgi/update.py
new file mode 100755
index 0000000..45fea74
--- /dev/null
+++ b/OpenFreezer/cgi/update.py
@@ -0,0 +1,4304 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+
+import MySQLdb
+import sys
+import string
+
+from database_conn import DatabaseConn
+
+from mapper import ReagentPropertyMapper, ReagentAssociationMapper, ReagentTypeMapper
+from general_handler import *
+from reagent_handler import ReagentHandler, InsertHandler
+from sequence_handler import *
+from comment_handler import CommentHandler
+#from system_set_handler import SystemSetHandler
+#from sequence_handler import SequenceHandler
+
+import utils
+
+from user_handler import UserHandler
+from project_database_handler import ProjectDatabaseHandler
+from session import Session
+from exception import *
+
+from sequence_feature import SequenceFeature
+
+from reagent import *
+
+import Bio
+from Bio.Seq import Seq
+#from Bio import Enzyme
+from Bio.Restriction import *
+
+########################################################
+# Global Variables
+########################################################
+
+dbConn = DatabaseConn()
+db = dbConn.databaseConnect()
+
+cursor = db.cursor()
+hostname = dbConn.getHostname()
+
+# Handlers and mappers
+rHandler = ReagentHandler(db, cursor)
+iHandler = InsertHandler(db, cursor)
+sHandler = SystemSetHandler(db, cursor)
+pHandler = ReagentPropertyHandler(db, cursor)
+raHandler = ReagentAssociationHandler(db, cursor)
+rtAssocHandler = ReagentTypeAssociationHandler(db, cursor)
+rtPropHandler = ReagentTypePropertyHandler(db, cursor)	# Aug. 31/09
+aHandler = AssociationHandler(db, cursor)
+rtHandler = ReagentTypeHandler(db, cursor)	# added June 3/09
+dnaHandler = DNAHandler(db, cursor)
+commHandler = CommentHandler(db, cursor)
+protHandler = ProteinHandler(db, cursor)
+rnaHandler = RNAHandler(db, cursor)
+
+propMapper = ReagentPropertyMapper(db, cursor)
+assocMapper = ReagentAssociationMapper(db, cursor)
+rMapper = ReagentTypeMapper(db, cursor)
+
+# Nov. 11/08
+reagentType_Name_ID_Map = rMapper.mapTypeNameID()
+reagentType_ID_Name_Map = rMapper.mapTypeIDName()
+
+# August 29/07: Restrict creation by user and project access
+packetHandler = ProjectDatabaseHandler(db, cursor)
+
+########################################################
+# Various maps
+########################################################
+
+prop_Alias_ID_Map = propMapper.mapPropAliasID()		# (propAlias, propID) - e.g. ('insert_type', '48') --> represents 'type of insert' property
+prop_Name_Alias_Map = propMapper.mapPropNameAlias()	# (propName, propAlias)
+prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+
+prop_ID_Name_Map = propMapper.mapPropIDName()		# Added March 13/08 - (prop id, prop name)
+prop_Alias_Name_Map = propMapper.mapPropAliasName()	# March 18/08 - (propAlias, propName)
+
+# July 2/09
+prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+prop_Category_ID_Name_Map = propMapper.mapPropCategoryNameID()
+
+prop_Category_Name_Alias_Map = propMapper.mapPropCategoryNameAlias()	# July 21/09
+prop_Category_Alias_Name_Map = propMapper.mapPropCategoryAliasName()
+
+# May 7/09: (property category name, property category ID) tuples, e.g. 'General Properties' => 1
+prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+prop_Category_Alias_ID_Map = propMapper.mapPropCategoryAliasID()
+
+# April 10/08
+assoc_Name_Alias_Map = assocMapper.mapAssocNameAlias()
+assoc_Name_ID_Map = assocMapper.mapAssocNameID()
+assoc_Alias_ID_Map = assocMapper.mapAssocAliasID()
+assoc_ID_Alias_Map = assocMapper.mapAssocIDAlias()
+
+# Get enzymes list for mapping sequence features
+enzDict = utils.join(dnaHandler.sitesDict, dnaHandler.gatewayDict)
+enzDict = utils.join(enzDict, dnaHandler.recombDict)		# add LoxP
+enzDict['None'] = ""						# add 'None'
+
+# Process reagent properties upon exit from Modify view
+def update():
+
+	form = cgi.FieldStorage(keep_blank_values="True")
+	
+	#print "Content-type:text/html"		# REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+	#print					# DITTO
+	#print `form`
+
+	rID = int(form.getvalue("reagent_id_hidden"))
+	
+	# Aug 29/07
+	uHandler = UserHandler(db, cursor)
+	
+	if form.has_key("curr_username"):
+		# store the user ID for use throughout the session; add to other views in addition to create in PHP
+		currUname = form.getvalue("curr_username")
+		currUser = uHandler.getUserByDescription(currUname)
+		
+		Session.setUser(currUser)
+	
+	# check if we're in modify or save mode
+	mode = form.getvalue("change_state")
+	#print "mode? " + `mode`
+	
+	if mode == "Modify":
+
+		# print Modify view
+		utils.redirect(hostname + "Reagent.php?View=6&mode=Modify&rid=" + `rID`)
+
+	elif mode == "Save":
+
+		#print "Content-type:text/html"
+		#print
+		#print `form`
+
+		prefix = "reagent_detailedview_"
+		postfix = "_prop"
+		
+		assocPrefix = "assoc_"
+		
+		# Feb. 25/08: Start and stop positions
+		startPostfix = "_startpos"
+		endPostfix = "_endpos"
+
+		# Feb. 26/08: Orientation
+		orientationPostfix = "_orientation"
+
+		if form.has_key("reagent_typeid_hidden"):
+			rTypeID = form.getvalue("reagent_typeid_hidden")
+			
+		if form.has_key("cloning_method_hidden"):
+			cloning_method = form.getvalue("cloning_method_hidden")
+		
+		if form.has_key("change_pv_flag"):
+			change_PV_Flag = form.getvalue("change_pv_flag")
+			
+			if change_PV_Flag != '1':
+				# hardcode temporarily, fix later
+				if rTypeID == '4':
+					if form.has_key("assoc_cell_line_parent_vector"):
+						utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID` + "&ErrCode=1&ErrVal=" + form.getvalue("assoc_cell_line_parent_vector"))
+		
+		if form.has_key("change_cl_flag"):
+			change_CL_Flag = form.getvalue("change_cl_flag")
+			
+			if change_CL_Flag != '1':
+				if form.has_key("reagent_typeid_hidden"):
+					rTypeID = form.getvalue("reagent_typeid_hidden")
+					
+					# hardcode temporarily, fix later
+					if rTypeID == '4':
+						if form.has_key("assoc_parent_cell_line"):
+							utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID` + "&ErrCode=2&ErrVal=" + form.getvalue("assoc_parent_cell_line"))
+		
+		########################################################
+		# Instance of Reagent that corresponds to rID
+		########################################################
+
+		#print "Content-type:text/html"
+		#print
+		
+		# July 20/09
+		section_to_save = form.getvalue("save_section")
+		#print `prop_Category_Name_Alias_Map`
+		#print section_to_save
+		
+		reagent = rHandler.createReagent(rID)
+		reagent.setCloningMethod(cloning_method)
+		
+		rType = reagentType_ID_Name_Map[rHandler.findReagentTypeID(rID)]
+		
+		checkboxPropNames = reagent.getCheckboxProps()		# NAMES of checkbox properties (e.g. "alternate id", 
+		
+		checkboxPropAliases = {}		# (checkboxPropAlias, checkboxPropName)
+		checkboxProps = {}			# (checkboxPropID, checkboxPropName)
+		newSetEntry = ""			# if set needs to be updated with a new value
+		
+		if checkboxPropNames and len(checkboxPropNames) > 0:	# have to add to avoid NoneType error
+			for c in checkboxPropNames:
+			
+				cAlias = prop_Name_Alias_Map[c]
+				cPropID = prop_Name_ID_Map[c]
+				
+				checkboxPropAliases[cAlias] = c
+				checkboxProps[cPropID] = c
+		
+		# April 7/08: Introduced reagent modification by sections
+		#if form.has_key("sequence_modify"):
+		if section_to_save == prop_Category_Name_Alias_Map["DNA Sequence"]:
+			
+			#print "Content-type:text/html"
+			#print
+			#print `form`
+			
+			dnaSeqCategoryID = prop_Category_Name_ID_Map["DNA Sequence"]
+			
+			# moved here April 10/08
+			newPropsDict_name = {}					# e.g. ('status', 'Completed')
+			newPropsDict_id = {}					# e.g. ('3', 'Completed') - db ID instead of property name
+			
+			# Save new DNA sequence, new type of Insert and open/closed, new translation, AND recompute feature positions
+			
+			# April 13, 2010: do only if sequence has actually been changed???
+			
+			newSeq = form.getvalue(prefix + prop_Name_Alias_Map["sequence"] + postfix)
+			
+			# July 2/09: propertyID <= propCatID
+			seqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], dnaSeqCategoryID)
+			newPropsDict_id[seqPropID] = newSeq
+			
+			# Whether the form includes Type of Insert and Open/Closed depends on the reagent type
+			if rTypeID == '2':
+				# May 18, 2011: REMOVED Type of Insert and Open/Closed from sequence section!
+				# so just get existing values
+				#newInsertType = form.getvalue(prefix + prop_Name_Alias_Map["type of insert"] + postfix)
+				#newOpenClosed = form.getvalue(prefix + prop_Name_Alias_Map["open/closed"] + postfix)
+
+				insertTypePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["type of insert"], prop_Category_Name_ID_Map["Classifiers"])
+				#print insertTypePropID
+				
+				openClosedPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["open/closed"], prop_Category_Name_ID_Map["Classifiers"])
+				#print openClosedPropID
+			
+				newInsertType = iHandler.findSimplePropertyValue(rID, insertTypePropID)
+				newOpenClosed = iHandler.findSimplePropertyValue(rID, openClosedPropID)
+				
+				#print "New Insert type: " + newInsertType
+				#print "New Open/Closed: " + newOpenClosed
+				
+				# Removed May 19, 2011 (see above)
+				'''
+				# May 17, 2010: but now cannot update with the rest, need to do them separately b/c they're under a different category!
+				#newPropsDict_id[insertTypePropID] = newInsertType	# removed May 17, 2010
+				#newPropsDict_id[openClosedPropID] = newOpenClosed	# removed May 17, 2010
+				
+				#rHandler.changePropertyValue(rID, insertTypePropID, newInsertType)
+				#rHandler.changePropertyValue(rID, openClosedPropID, newOpenClosed)
+				'''
+
+			# April 7/08: Recompute feature positions (do before calling 'update' to fetch previous sequence value)
+			# Grab the old sequence
+			oldSeqID = rHandler.findDNASequenceKey(rID)
+			oldSeq = dnaHandler.findSequenceByID(oldSeqID)
+			newSeq = dnaHandler.squeeze(newSeq)
+			
+			if rTypeID == '2':
+				# Update July 23/09: account for cases where insert type - open/closed are empty
+				iHandler.updateInsertProteinSequence(rID, newInsertType, newOpenClosed)
+
+			# Update the rest of the features
+			if len(oldSeq) > 0:
+				rHandler.updateFeaturePositions(rID, oldSeq.lower(), newSeq.lower())
+				
+				# Nov. 18/08 - do linkers separately, AFTER the rest of the features b/c updateFeaturePositions() deletes them
+				# Update July 2/09
+				fpLinkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+				tpLinkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	
+				insert_fp_linker = rHandler.findSimplePropertyValue(rID, fpLinkerPropID)
+				insert_tp_linker = rHandler.findSimplePropertyValue(rID, tpLinkerPropID)
+				
+				if insert_fp_linker and len(insert_fp_linker) >= 10 and newSeq.lower().find(insert_fp_linker.lower()) >= 0:
+					fpLinkerStartPos = newSeq.lower().find(insert_fp_linker.lower()) + 1
+					fpLinkerEndPos = fpLinkerStartPos + len(insert_fp_linker)
+					
+					rHandler.deleteReagentProperty(rID, fpLinkerPropID)
+					rHandler.addReagentProperty(rID, fpLinkerPropID, insert_fp_linker, fpLinkerStartPos, fpLinkerEndPos-1)
+				else:
+					rHandler.deleteReagentProperty(rID, fpLinkerPropID)
+					#fpLinkerStartPos = 0
+					#fpLinkerEndPos = 0
+					
+				# 3' linker
+				if insert_tp_linker and len(insert_tp_linker) >= 10 and newSeq.lower().find(insert_tp_linker.lower()) >= 0:
+					tpLinkerStartPos = newSeq.lower().find(insert_tp_linker.lower()) + 1
+					tpLinkerEndPos = tpLinkerStartPos + len(insert_tp_linker)
+					
+					rHandler.deleteReagentProperty(rID, tpLinkerPropID)
+					rHandler.addReagentProperty(rID, tpLinkerPropID, insert_tp_linker, tpLinkerStartPos, tpLinkerEndPos-1)
+				else:
+					rHandler.deleteReagentProperty(rID, tpLinkerPropID)
+					#tpLinkerStartPos = 0
+					#tpLinkerEndPos = 0
+				
+			# April 19, 2011: update other sequence properties (rare but could happen)
+			#print "Content-type:text/html"
+			#print
+
+			for sKey in form.keys():
+				propAlias = sKey.lstrip(prefix).rstrip(postfix)
+				propVal = form.getlist(sKey)
+
+				if prop_Alias_ID_Map.has_key(propAlias) and propAlias != prop_Name_Alias_Map["molecular weight"] and propAlias != prop_Name_Alias_Map["melting temperature"] and propAlias != prop_Name_Alias_Map["sequence"] and propAlias != prop_Name_Alias_Map["gc content"]:
+					
+					#print propAlias
+					#print `propVal`
+					
+					propCatID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[propAlias], prop_Category_Name_ID_Map["DNA Sequence"])
+					
+					rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, propCatID)
+
+					if len(propVal) > 1:
+						for pVal in propVal:
+							#print pVal
+
+							setGroupID = sHandler.findPropSetGroupID(propCatID)
+							ssetID = sHandler.findSetValueID(setGroupID, pVal)
+
+							if sHandler.findSetValueID(setGroupID, pVal) <= 0:
+								ssetID = sHandler.addSetValue(setGroupID, pVal)
+							
+							if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+								sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+					else:
+						pVal = propVal[0]
+						
+						if pVal.lower() == 'other':	
+							textBoxName = prefix + reagentType_ID_Name_Map[int(rTypeID)] + "_" + prop_Category_Name_Alias_Map["DNA Sequence"] + "_:_" + propAlias + "_name_txt"
+							
+							if form.has_key(textBoxName):
+								propVal = form.getvalue(textBoxName)
+
+								setGroupID = sHandler.findPropSetGroupID(propCatID)
+								ssetID = sHandler.findSetValueID(setGroupID, propVal)
+
+								# update set
+								if sHandler.findSetValueID(setGroupID, propVal) <= 0:
+									ssetID = sHandler.addSetValue(setGroupID, propVal)
+								
+								if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+									sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+
+					newPropsDict_id[propCatID] = propVal
+					#print `newPropsDict_id`
+
+			# May 17, 2010
+			rHandler.updateReagentPropertiesInCategory(rID, dnaSeqCategoryID, newPropsDict_id)
+
+			# June 8/08: Since sites are shorter than 10 nt and have been deleted remap them here
+			fpSitePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+			
+			tpSitePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+			
+			five_prime_site = rHandler.findSimplePropertyValue(rID, fpSitePropID)
+			three_prime_site = rHandler.findSimplePropertyValue(rID, tpSitePropID)
+
+			if five_prime_site and three_prime_site:	# added July 11/08, handle empty sequence/sites
+				rHandler.updateSitePositions(rID, newSeq, five_prime_site, three_prime_site)
+			
+			# return to detailed view - Moved here July 7/08
+			utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+			
+		elif section_to_save == prop_Category_Name_Alias_Map["RNA Sequence"]:
+			
+			#print "Content-type:text/html"
+			#print
+			#print `form`
+			
+			# moved here April 10/08
+			newPropsDict_name = {}		# e.g. ('status', 'Completed')
+			newPropsDict_id = {}		# e.g. ('3', 'Completed') - db ID instead of property name
+			
+			rnaSeqCategoryID = prop_Category_Name_ID_Map["RNA Sequence"]
+
+			newSeq = form.getvalue(prefix + prop_Name_Alias_Map["rna sequence"] + postfix)
+			#print newSeq
+			
+			# July 2/09: propertyID <= propCatID
+			seqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["rna sequence"], prop_Category_Name_ID_Map["RNA Sequence"])
+			newSeq = rnaHandler.squeeze(newSeq)
+			#print newSeq
+			newPropsDict_id[seqPropID] = newSeq
+			
+			# April 7/08: Recompute feature positions (do before calling 'update' to fetch previous sequence value)
+			# Grab the old sequence
+			oldSeqID = rHandler.findRNASequenceKey(rID)
+			oldSeq = rnaHandler.findSequenceByID(oldSeqID)
+			#print oldSeqID
+			
+			# Update the rest of the features
+			if len(oldSeq) > 0:
+				rHandler.updateFeaturePositions(rID, oldSeq.lower(), newSeq.lower(), False, True)
+				
+				# No linkers for RNA
+							
+			# April 12, 2011: Get Tm from input
+			tmPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["melting temperature"], prop_Category_Name_ID_Map["RNA Sequence"])
+
+			if form.has_key(prefix + prop_Name_Alias_Map["melting temperature"] + postfix):
+				tm_rna = form.getvalue(prefix + prop_Name_Alias_Map["melting temperature"] + postfix)
+				#print tm_rna
+				newPropsDict_id[tmPropID] = tm_rna
+
+			# April 14, 2011: Ditto MW
+			mwPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["molecular weight"], prop_Category_Name_ID_Map["RNA Sequence"])
+
+			if form.has_key(prefix + prop_Name_Alias_Map["molecular weight"] + postfix):
+				mw_rna = form.getvalue(prefix + prop_Name_Alias_Map["molecular weight"] + postfix)
+				newPropsDict_id[mwPropID] = mw_rna
+
+			# No sites for RNA either
+
+			# rest of RNA sequence properties
+			
+			#print `form`
+				
+			#print "pre " + prefix
+
+			for sKey in form.keys():
+				#print "key: " + sKey
+				#print "post " + postfix
+
+				t1 = sKey[0:sKey.find(postfix)]
+				t2 = t1[len(prefix):]
+				
+				propAlias = t2
+				
+				#print propAlias
+
+				propVal = form.getlist(sKey)
+
+				#print propAlias
+				#print `propVal`
+
+				if prop_Alias_ID_Map.has_key(propAlias) and propAlias != prop_Name_Alias_Map["rna sequence"]:
+					
+					#print propAlias
+					#print `propVal`
+					
+					propCatID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[propAlias], prop_Category_Name_ID_Map["RNA Sequence"])
+
+					#print "propcatid " + `propCatID`
+
+					rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, propCatID)
+
+					if len(propVal) > 1:
+						for pVal in propVal:
+							#print pVal
+
+							setGroupID = sHandler.findPropSetGroupID(propCatID)
+							ssetID = sHandler.findSetValueID(setGroupID, pVal)
+
+							if sHandler.findSetValueID(setGroupID, pVal) <= 0:
+								ssetID = sHandler.addSetValue(setGroupID, pVal)
+							
+							if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+								sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+					else:
+						pVal = propVal[0]
+						
+						if pVal.lower() == 'other':	
+							textBoxName = prefix + reagentType_ID_Name_Map[int(rTypeID)] + "_" + prop_Category_Name_Alias_Map["RNA Sequence"] + "_:_" + propAlias + "_name_txt"
+							
+							if form.has_key(textBoxName):
+								propVal = form.getvalue(textBoxName)
+
+								setGroupID = sHandler.findPropSetGroupID(propCatID)
+								ssetID = sHandler.findSetValueID(setGroupID, propVal)
+
+								# update set
+								if sHandler.findSetValueID(setGroupID, propVal) <= 0:
+									ssetID = sHandler.addSetValue(setGroupID, propVal)
+								
+								if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+									sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+
+					newPropsDict_id[propCatID] = propVal
+
+			#print `newPropsDict_id`
+
+			rHandler.updateReagentPropertiesInCategory(rID, rnaSeqCategoryID, newPropsDict_id)
+
+			# return to detailed view - Moved here July 7/08
+			utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+			
+		# April 10/08
+		#elif form.has_key("save_intro"):
+		elif section_to_save == prop_Category_Name_Alias_Map["General Properties"]:
+
+			#print "Content-type:text/html"
+			#print
+			#print `form`
+
+			# moved here April 10/08
+			newPropsDict_name = {}					# e.g. ('status', 'Completed')
+			newPropsDict_id = {}					# e.g. ('3', 'Completed') - db ID instead of property name
+			
+			gpCategoryID = prop_Category_Name_ID_Map["General Properties"]
+			
+			# Save only general reagent information, no effect on sequence, features, parents or annotations
+			
+			# Updated May 7/09
+			#generalPropNames = reagent.getGeneralProperties()		# removed May 7/09
+			generalPropNamesBasic = reagent.getGeneralProperties()		# added May 7/09
+			
+			#print `generalPropNamesBasic`
+			
+			# May 7/09: Get additional general properties that may have been assigned to this reagent type in addition to basic properties common to all
+			generalReagentAttributes = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, gpCategoryID)
+			generalPropNames = utils.merge(generalPropNamesBasic, generalReagentAttributes)		# May 7/09
+			#print `generalPropNames`
+			
+			generalPropertyAliases = {}
+			generalProperties = {}
+			
+			for g in generalPropNames:
+				
+				gpAlias = prop_Name_Alias_Map[g]
+				gPropID = prop_Name_ID_Map[g]
+				
+				generalPropertyAliases[gpAlias] = g
+				generalProperties[gPropID] = g
+				
+			#print `generalProperties`
+			
+			for gpAlias in generalPropertyAliases:
+				# Check if the form has this value
+				tmpPropName = prefix + gpAlias + postfix
+				
+				tmpPropVals = []	# in case of multiple properties (May 14/2010)
+			
+				#print tmpPropName
+				
+				if form.has_key(tmpPropName):
+					tmpPropVal = form.getvalue(tmpPropName)
+					#print tmpPropVal
+					
+					# May 14, 2010: move up here for speed
+					pcID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[gpAlias], gpCategoryID)
+					#print pcID
+					
+					rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(int(rTypeID), pcID)
+					#print rTypeAttributeID
+	
+					setGroupID = sHandler.findPropSetGroupID(pcID)
+					
+					if not utils.isList(tmpPropVal):	# this is a single value, either in a list or freetext
+						if tmpPropVal.lower() == 'other':
+							# look for a textbox
+							otherTextboxName = prefix + rType + "_" + section_to_save + "_:_" + gpAlias + "_name_txt"
+							#print otherTextboxName
+							
+							if form.has_key(otherTextboxName):
+								tmpPropVal = form.getvalue(otherTextboxName)
+								#print "this is other " + tmpPropVal
+						
+								# moved this back under 'if other text' May 27/10
+								ssetID = sHandler.findSetValueID(setGroupID, tmpPropVal)
+								#print ssetID
+								
+								if ssetID <= 0:
+									ssetID = sHandler.addSetValue(setGroupID, tmpPropVal)
+								
+								if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+									sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+					
+						# May 27/10: check if this is a single value under multiple d/d list
+						# We are not storing property format in database, only way of differentiating b/w freetext and dropdowns that should be updated is: a) If textbox is found - this is a dropdown, save value  b) If rtPropHandler.isMultiple() returns true, this is a multiple dropdown where only one value was entered - OK.  DO NOT ADD ANY OTHER VALUES TO SET!!!!!!!!!!
+					
+						if rtPropHandler.isMultiple(rTypeAttributeID):
+							tmp_ar = []
+							
+							tmp_ar.append(tmpPropVal)
+							
+							for val in tmp_ar:
+								
+								ssetID = sHandler.findSetValueID(setGroupID, val)
+								#print ssetID
+								
+								if ssetID <= 0:
+									ssetID = sHandler.addSetValue(setGroupID, val)
+								
+								if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+									sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+					
+					# May 14, 2010: still, update Other set even for multiple
+					else:
+						tmpPropVal = utils.unique(tmpPropVal)
+						
+						for t in tmpPropVal:
+							# check if each value is in set and, if not, update
+							ssetID = sHandler.findSetValueID(setGroupID, t)
+							#print ssetID
+							
+							if ssetID <= 0:
+								ssetID = sHandler.addSetValue(setGroupID, t)
+							
+							if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+								sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+
+					newPropsDict_name[gpAlias] = tmpPropVal		# moved here May 14, 2010
+			
+			#print `newPropsDict_name`
+			
+			# Match db IDs to property aliases
+			for tmpProp in newPropsDict_name.keys():
+				
+				#print tmpProp
+				
+				if prop_Alias_ID_Map.has_key(tmpProp):
+					
+					# July 2/09: propertyID <= propCatID
+					#propID = prop_Alias_ID_Map[tmpProp]	# removed July 2/09
+					propID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[tmpProp], gpCategoryID)
+					newPropsDict_id[propID] = newPropsDict_name[tmpProp]
+				
+			#print `newPropsDict_id`
+
+			# ACTION			
+			rHandler.updateReagentPropertiesInCategory(rID, gpCategoryID, newPropsDict_id)
+			
+			# return to detailed view - Moved here July 7/08
+			utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+			
+		# Annotations
+		#elif form.has_key("save_annos"):
+		elif section_to_save == prop_Category_Name_Alias_Map["External Identifiers"]:
+			
+			#print "Content-type:text/html"
+			#print
+			#print `form`
+			
+			eiCategoryID = prop_Category_Name_ID_Map["External Identifiers"]
+			
+			# moved here April 10/08
+			newPropsDict_name = {}			# e.g. ('status', 'Completed')
+			newPropsDict_id = {}			# e.g. ('3', 'Completed') - db ID instead of property name
+
+			annoNames = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, eiCategoryID)
+			
+			annoAliases = {}
+			annotations = {}
+				
+			# Now map annotation names to their db aliases and IDs
+			for anno in annoNames:
+				annoAlias = prop_Name_Alias_Map[anno]
+				annoAliases[annoAlias] = anno
+			
+			# Get annotation values from the form
+			for annoAlias in annoAliases:
+				tmpPropName = prefix + annoAlias + postfix
+				
+				if form.has_key(tmpPropName):
+					tmpPropVal = form.getvalue(tmpPropName)
+					newPropsDict_name[annoAlias] = tmpPropVal
+			
+					if annoAlias == "alternate_id":
+						
+						newPropVal = form.getlist(tmpPropName)
+						#print `newPropVal`
+						tmp_alt_ids = []
+						
+						for altID in newPropVal:
+							if form.has_key(annoAlias + "_" + altID + "_textbox_name"):
+								if altID.lower() == 'other':
+									tmp_alt_id = form.getvalue(annoAlias + "_" + altID + "_textbox_name")
+									
+									#print annoAlias
+									#print annoPropID
+									
+									# update list
+									pcID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[annoAlias], eiCategoryID)
+									#print pcID
+							
+									rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(int(rTypeID), pcID)
+									#print rTypeAttributeID
+									
+									setGroupID = sHandler.findPropSetGroupID(pcID)
+									#print setGroupID
+									
+									ssetID = sHandler.findSetValueID(setGroupID, tmp_alt_id[0:tmp_alt_id.find(":")])
+									#print ssetID
+									
+									if ssetID <= 0:
+										ssetID = sHandler.addSetValue(setGroupID, tmp_alt_id[0:tmp_alt_id.find(":")])
+									
+									if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+										sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+								else:
+									tmp_alt_id = altID + ":" + form.getvalue(annoAlias + "_" + altID + "_textbox_name")
+									#print tmp_alt_id
+									
+								tmp_alt_ids.append(tmp_alt_id)
+						
+						newPropVal = tmp_alt_ids
+						newPropsDict_name[annoAlias] = newPropVal
+					#else:
+						# delete???????????
+						#print tmpPropName
+						
+			#print `newPropsDict_name`
+			
+			# Match db IDs to property aliases
+			for tmpProp in newPropsDict_name.keys():
+				
+				if prop_Alias_ID_Map.has_key(tmpProp):
+					
+					# July 2/09: propertyID <= propCatID
+					#propID = prop_Alias_ID_Map[tmpProp]	# removed July 2/09
+					propID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[tmpProp], eiCategoryID)
+					newPropsDict_id[propID] = newPropsDict_name[tmpProp]
+
+					newPropsDict_id[propID] = newPropsDict_name[tmpProp]
+
+			# ACTION - Update May 17, 2010
+			rHandler.updateReagentPropertiesInCategory(rID, eiCategoryID, newPropsDict_id)
+		
+			# return to detailed view - Moved here July 7/08
+			utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+			
+		elif section_to_save == prop_Category_Name_Alias_Map["Classifiers"]:
+			
+			#print "Content-type:text/html"
+			#print
+			#print rTypeID
+			#print `form`
+			
+			newPropsDict_name = {}			# e.g. ('status', 'Completed')
+			newPropsDict_id = {}			# e.g. ('3', 'Completed') - db ID instead of property name
+			
+			classifiersCategoryID = prop_Category_Name_ID_Map["Classifiers"]
+			classifierNames = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, classifiersCategoryID)
+		
+			classifierAliases = {}
+			classifiers = {}
+			
+			# Map classifier names to aliases
+			for c in classifierNames:
+				cAlias = prop_Name_Alias_Map[c]
+				#cPropID = prop_Name_ID_Map[c]
+				
+				classifierAliases[cAlias] = c
+				#classifiers[cPropID] = c
+				
+			# Get classifier values from form
+			for cAlias in classifierAliases:
+				
+				tmpPropName = prefix + cAlias + postfix
+				#print tmpPropName
+				
+				if form.has_key(tmpPropName):
+					if not utils.isList(form.getvalue(tmpPropName)):
+						
+						newPropVal = form.getvalue(tmpPropName).strip()
+						#print newPropVal
+						
+						# Jan. 9/09: save 'other' values - Update Feb. 4/10
+						if newPropVal.lower() == 'other':
+
+							#textBox = cAlias + "_name_txt"		# rmvd Feb. 4/10
+							textBoxName = prefix + reagentType_ID_Name_Map[int(rTypeID)] + "_" + prop_Category_Name_Alias_Map["Classifiers"] + "_:_" + cAlias + "_name_txt"
+							
+							#print textBoxName
+							
+							if form.has_key(textBoxName):
+								newPropVal = form.getvalue(textBoxName).strip()
+								
+								# rmvd Feb. 4/10
+								#tmpPropVal = form[textBox].value.strip()
+								#newSetEntry = tmpPropVal
+								#sHandler.updateSet(cAlias, newSetEntry)
+								
+								pcID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[cAlias], classifiersCategoryID)
+								
+								rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, pcID)
+								
+								setGroupID = sHandler.findPropSetGroupID(pcID)
+								ssetID = sHandler.findSetValueID(setGroupID, newPropVal)
+								
+								if sHandler.findSetValueID(setGroupID, newPropVal) <= 0:
+									ssetID = sHandler.addSetValue(setGroupID, newPropVal)
+								
+								if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+									sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+					else:
+						newPropVal = utils.unique(form.getvalue(tmpPropName))
+						
+					newPropsDict_name[cAlias] = newPropVal
+				else:
+					# May 13, 2010: delete
+					pcID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[cAlias], classifiersCategoryID)
+					rHandler.deleteReagentProperty(rID, pcID)
+			
+			# Match db IDs to property aliases
+			for tmpProp in newPropsDict_name.keys():
+				
+				if prop_Alias_ID_Map.has_key(tmpProp):
+					
+					# July 2/09: propertyID <= propCatID
+					#propID = prop_Alias_ID_Map[tmpProp]	# removed July 2/09
+					propID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[tmpProp], prop_Category_Name_ID_Map["Classifiers"])
+					#print propID
+					newPropsDict_id[propID] = newPropsDict_name[tmpProp]
+
+			#print `newPropsDict_id`
+
+			# ACTION
+			rHandler.updateReagentPropertiesInCategory(rID, classifiersCategoryID, newPropsDict_id)
+			
+			# Jan. 9/09: Need to update Insert protein translation if its type or open/closed changes
+			if rTypeID == '2':
+				iHandler.updateInsertProteinSequence(rID)
+			
+			# return to detailed view - Moved here July 7/08
+			utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+		
+		# April 10/08: Features
+		#elif form.has_key("save_features"):
+		elif section_to_save == prop_Category_Name_Alias_Map["DNA Sequence Features"]:
+			
+			#print "Content-type:text/html"
+			#print
+			#print rTypeID
+			#print `form`
+			
+			# Save features - taken from 'preload.py'
+			# (deletion is performed in updateFeatures function, no need to call here)
+			newPropsDict_name = {}			# e.g. ('status', 'Completed')
+			newPropsDict_id = {}			# e.g. ('3', 'Completed') - db ID instead of property name
+			
+			startPosDict = {}			# (propID, startpos)
+			endPosDict = {}				# (propID, endpos)
+			
+			# Store orientation
+			orientationDict = {}			# (propID, orientation)
+			
+			# Nov. 6/08: Delete before update
+			fpSitePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+			
+			tpSitePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	
+			rHandler.deleteReagentProperty(rID, fpSitePropID)
+			rHandler.deleteReagentProperty(rID, tpSitePropID)
+			
+			# Sept. 8/08: Delete linkers too
+			fpLinkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+			tpLinkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	
+			rHandler.deleteReagentProperty(rID, fpLinkerPropID)
+			rHandler.deleteReagentProperty(rID, tpLinkerPropID)
+			
+			# features too
+			rHandler.deleteReagentFeatures(rID)
+
+			if form.has_key(prefix + prop_Name_Alias_Map["5' linker"] + postfix):
+				five_prime_linker = form.getvalue(prefix + prop_Name_Alias_Map["5' linker"] + postfix).replace(" ", "").strip()
+				fAlias = prop_Name_Alias_Map["5' linker"]
+
+				#fID = prop_Alias_ID_Map[fAlias]
+				fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map["DNA Sequence Features"])
+				
+				startFieldName = prefix + fAlias + "_startpos" + postfix
+				endFieldName = prefix + fAlias + "_endpos" + postfix
+				
+				if form.has_key(startFieldName):
+					fStartPos = form.getvalue(startFieldName)
+				else:
+					fStartPos = 0
+					
+				if form.has_key(endFieldName):
+					fEndPos = form.getvalue(endFieldName)
+				else:
+					fEndPos = 0
+
+				# orientation
+				orientationFieldName = prefix + fAlias + "_orientation" + postfix
+			
+				if form.has_key(orientationFieldName):
+					tmpDir = form.getvalue(orientationFieldName)
+					#print tmpDir
+				else:
+					tmpDir = 'forward'
+
+				rHandler.addReagentProperty(rID, fID, five_prime_linker, fStartPos, fEndPos, tmpDir)
+				
+			if form.has_key(prefix + prop_Name_Alias_Map["3' linker"] + postfix):
+				three_prime_linker = form.getvalue(prefix + prop_Name_Alias_Map["3' linker"] + postfix).replace(" ", "").strip()
+				
+				fAlias = prop_Name_Alias_Map["3' linker"]
+
+				#fID = prop_Alias_ID_Map[fAlias]
+				fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map["DNA Sequence Features"])
+				
+				startFieldName = prefix + fAlias + "_startpos" + postfix
+				endFieldName = prefix + fAlias + "_endpos" + postfix
+				
+				if form.has_key(startFieldName):
+					fStartPos = form.getvalue(startFieldName)
+				else:
+					fStartPos = 0
+					
+				if form.has_key(endFieldName):
+					fEndPos = form.getvalue(endFieldName)
+				else:
+					fEndPos = 0
+
+				# orientation
+				orientationFieldName = prefix + fAlias + "_orientation" + postfix
+			
+				if form.has_key(orientationFieldName):
+					tmpDir = form.getvalue(orientationFieldName)
+					#print tmpDir
+				else:
+					tmpDir = 'forward'
+					
+				rHandler.addReagentProperty(rID, fID, three_prime_linker, fStartPos, fEndPos, tmpDir)
+			
+			# March 12/08: Treat properties with multiple values and start/end positions (a.k.a. features) as objects
+			seqFeatures = []
+	
+			# Dec. 17/09: Use same code for all
+			
+			# May 15/09: Need to adjust for custom reagent types
+			#if rTypeID != '1' and rTypeID != '2':
+			featureCategoryID = prop_Category_Name_ID_Map["DNA Sequence Features"]
+			sequenceFeatures = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, featureCategoryID)
+			featureDescriptors = Reagent.getFeatureDescriptors()
+				
+			#else:	# May 15/09 - keep existing code for Inserts and Vectors: right now I'm focusing on custom reagent types and don't want to break anything that already works in the sytem; can always generalize later
+				# March 17/08: Fetch Insert feature descriptors - tag position and expression system
+				# Use built-in Insert function instead of 'if-else' blocks with hardcoded values
+				#sequenceFeatures = Reagent.getSequenceFeatures()
+				#featureDescriptors = Reagent.getFeatureDescriptors()
+				
+			#print `sequenceFeatures`
+		
+			# Nov. 13/08: Get Insert sequence
+			#seqPropID = prop_Name_ID_Map["sequence"]
+			seqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+			seqID = rHandler.findIndexPropertyValue(rID, seqPropID)
+			insertSeq = dnaHandler.findSequenceByID(seqID).lower()
+			
+			# Removed May 16/08 - not a very good idea to delete all features, including sites and linkers - linkers may hinder modification but are necessary for correct feature remapping during Vector sequence reconstitution.  See what happens
+			#singleValueFeatures = reagent.getSingleFeatures()	# March 18/08 - Differentiate between features such as promoter or tag type, which could have multiple values, and cloning sites and linkers, which only have one value and one position
+			
+			#featureNames = sequenceFeatures + singleValueFeatures
+			
+			featureNames = sequenceFeatures
+			
+			featureAliases = {}
+			features = {}
+		
+			for f in featureNames:
+				fAlias = prop_Name_Alias_Map[f]
+				fPropID = prop_Name_ID_Map[f]
+				
+				featureAliases[fAlias] = f
+				features[fPropID] = f
+			
+			for fAlias in featureAliases:
+				#print "alias " + fAlias
+				
+				# Special case: cDNA start and stop positions
+				if prop_Alias_Name_Map[fAlias].lower() == 'cdna insert':
+					
+					fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map["DNA Sequence Features"])
+					
+					startFieldName = prefix + fAlias + "_startpos" + postfix
+					endFieldName = prefix + fAlias + "_endpos" + postfix
+					
+					if form.has_key(startFieldName):
+						tmpStartPos = form.getvalue(startFieldName)
+					else:
+						tmpStartPos = 0
+
+					if form.has_key(endFieldName):
+						tmpEndPos = form.getvalue(endFieldName)
+						#fTemp.setFeatureEndPos(tmpEndPos)
+					else:
+						tmpEndPos = 0
+					
+					# Nov. 6/08: Orientation needed too (for reverse complemented Inserts)
+					orientationFieldName = prefix + fAlias + "_orientation" + postfix
+				
+					if form.has_key(orientationFieldName):
+						tmpDir = form.getvalue(orientationFieldName)
+						#print tmpDir
+					else:
+						tmpDir = 'forward'
+						
+					rHandler.addReagentProperty(rID, fID, "", tmpStartPos, tmpEndPos)
+					
+				elif prop_Alias_Name_Map[fAlias].lower() == "5' cloning site":
+					
+					five_prime_site = form.getvalue(prefix + prop_Name_Alias_Map["5' cloning site"] + postfix)
+					#print "5' site " + five_prime_site
+					
+					fAlias = prop_Name_Alias_Map["5' cloning site"]
+	
+					# May 28/08: Allow blank sites for Novel vectors
+					if five_prime_site:
+						if five_prime_site == "Other":
+							five_prime_site = form.getvalue("5_prime_cloning_site_name_txt")
+					
+						fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map["DNA Sequence Features"])
+					
+						startFieldName = prefix + fAlias + "_startpos" + postfix
+						endFieldName = prefix + fAlias + "_endpos" + postfix
+						
+						#print startFieldName
+						
+						if form.has_key(startFieldName):
+							fStartPos = form.getvalue(startFieldName)
+						else:
+							fStartPos = 0
+							
+						if form.has_key(endFieldName):
+							fEndPos = form.getvalue(endFieldName)
+						else:
+							fEndPos = 0
+		
+						# orientation
+						orientationFieldName = prefix + fAlias + "_orientation" + postfix
+					
+						if form.has_key(orientationFieldName):
+							tmpDir = form.getvalue(orientationFieldName)
+							#print tmpDir
+						else:
+							tmpDir = 'forward'
+		
+						rHandler.addReagentProperty(rID, fID, five_prime_site, fStartPos, fEndPos, tmpDir)
+					
+				elif prop_Alias_Name_Map[fAlias].lower() == "3' cloning site":
+					three_prime_site = form.getvalue(prefix + prop_Name_Alias_Map["3' cloning site"] + postfix)
+					#print "3' site: " + three_prime_site
+					
+					fAlias = prop_Name_Alias_Map["3' cloning site"]
+	
+					# May 28/08: Allow blank sites for Novel vectors
+					if three_prime_site:
+						if three_prime_site == "Other":
+							three_prime_site = form.getvalue("3_prime_cloning_site_name_txt")
+						#else:
+							#fVal = three_prime_site
+						
+					#fID = prop_Alias_ID_Map[fAlias]
+					
+						fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map["DNA Sequence Features"])
+					
+						startFieldName = prefix + fAlias + "_startpos" + postfix
+						endFieldName = prefix + fAlias + "_endpos" + postfix
+						
+						if form.has_key(startFieldName):
+							fStartPos = form.getvalue(startFieldName)
+						else:
+							fStartPos = 0
+							
+						if form.has_key(endFieldName):
+							fEndPos = form.getvalue(endFieldName)
+						else:
+							fEndPos = 0
+						
+						# Sept. 3/08: Store orientation
+						orientationFieldName = prefix + fAlias + "_orientation" + postfix
+						
+						if form.has_key(orientationFieldName):
+							tmpDir = form.getvalue(orientationFieldName)
+							#print tmpDir
+						else:
+							tmpDir = 'forward'
+		
+						rHandler.addReagentProperty(rID, fID, three_prime_site, fStartPos, fEndPos, tmpDir)
+					
+				else:
+					tmpStart = -1
+					tmpEnd = -1
+					
+					#tmpPropName = prefix + fAlias + postfix
+					featureType = "dna_sequence_features"
+				
+					for tmpPropName in form.keys():
+						#print tmpPropName
+						#print fAlias
+						
+						# convert to lowercase b/c of PolyA
+						if tmpPropName.find(prefix + fAlias + "_:_") >= 0:
+					
+							pValStartInd = len(prefix + fAlias)+3
+							#print pValStartInd
+							pValStopInd = tmpPropName.rfind("_start_", pValStartInd)
+							#print pValStopInd
+							
+							# actual feature value
+							tmpPropValue = tmpPropName[pValStartInd:pValStopInd]
+							
+							if tmpPropValue and len(tmpPropValue) > 0:
+								# get positions - changed oct. 25/08
+								
+								# Update Nov 3/09
+								#start_ind1 = tmpPropName.find(tmpPropValue) + len(tmpPropValue) + len("_start_")
+								
+								start_ind1 = tmpPropName.rfind("_start_") + len("_start_")
+								start_ind2 = tmpPropName.find("_end_")
+								#print start_ind2
+		
+								tmpStart = tmpPropName[start_ind1:start_ind2]
+								#print "start " + tmpStart
+								
+								if tmpStart and len(tmpStart) > 0 and int(tmpStart) > 0:
+									end_ind_1 = start_ind2 + len("_end_")
+									#print end_ind_1
+									end_ind_2 = tmpPropName.find("_", end_ind_1)
+									#print end_ind_2
+			
+									tmpEnd = tmpPropName[end_ind_1:end_ind_2]
+									#print "end " + tmpEnd
+									
+									if tmpEnd and len(tmpEnd) > 0 and int(tmpEnd) > 0:
+										tmpDirName = prefix + fAlias + "_:_" + tmpPropValue + "_start_" + `int(tmpStart)` + "_end_" + `int(tmpEnd)` + "_orientation" + postfix
+										#print tmpDirName
+										
+										if form.has_key(tmpDirName):
+											tmpDir = form.getvalue(tmpDirName)
+											#print "FOUND DIRECTION " + tmpDirName
+								
+											# Nov. 13/08: If there are duplicates, select one
+											if utils.isList(tmpDir):
+												#print "Descriptor " + tmpDescr
+												tmpDir = tmpDir[0]
+								
+											#fID = prop_Alias_ID_Map[fAlias]
+											fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map[prop_Category_Alias_Name_Map[featureType]])
+											
+											# descriptor
+											if featureDescriptors.has_key(prop_Alias_Name_Map[fAlias]):
+												tmpDescrName = featureDescriptors[prop_Alias_Name_Map[fAlias]]
+												tmpDescrAlias = prop_Name_Alias_Map[tmpDescrName]
+												#print "DESCRIPTOR " + tmpDescrAlias
+										
+												tmpDescrField = prefix + tmpDescrAlias + "_:_" + tmpPropValue + "_start_" + tmpStart + "_end_" + tmpEnd + postfix
+	
+												#print tmpDescrField
+												
+												if form.has_key(tmpDescrField):
+													
+													tmpDescr = form.getvalue(tmpDescrField)
+										
+													# Nov. 13/08: If there are duplicates, select one
+													if utils.isList(tmpDescr):
+														#print "Descriptor " + tmpDescr
+														tmpDescr = tmpDescr[0]
+										
+													# June 8, 2010: For descriptor have to go to textbox to fetch Other values
+													if tmpDescr.lower() == 'other':
+														
+														if fAlias == "tag":
+															descrAlias = "tag_position"
+														elif fAlias == "promoter":
+															descrAlias = "expression_system"
+											
+														tmpDescr_text = prefix + tmpDescrAlias + "_:_" + tmpPropValue + "_start_" + tmpStart + "_end_" + tmpEnd + "_name_txt"
+											
+														#print tmpDescr_text
+											
+														tmpDescr = form.getvalue(tmpDescr_text)
+										
+													if utils.isList(tmpDescr):
+														tmpDescr = tmpDescr[0]
+										
+													#print tmpDescr
+
+													# March 29, 2010: Update set
+													tmpDescrPropID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[tmpDescrAlias], prop_Category_Name_ID_Map[prop_Category_Alias_Name_Map[featureType]])
+										
+													rTypeDescrAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, tmpDescrPropID)
+													
+													descrSetGroupID = sHandler.findPropSetGroupID(tmpDescrPropID)
+													descr_ssetID = sHandler.findSetValueID(descrSetGroupID, tmpDescr)
+													
+													if sHandler.findSetValueID(descrSetGroupID, tmpDescr) <= 0:
+														descr_ssetID = sHandler.addSetValue(descrSetGroupID, tmpDescr)
+
+													if not sHandler.existsReagentTypeAttributeSetValue(rTypeDescrAttributeID, descr_ssetID):
+														#print "HERE, updating"
+														sHandler.addReagentTypeAttributeSetEntry(rTypeDescrAttributeID, descr_ssetID)
+												else:
+													tmpDescr = ""
+											else:
+												tmpDescr = ""
+										
+											if not rHandler.existsPropertyValue(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDescr, tmpDir):
+												#print "adding"
+												rHandler.addReagentProperty(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDir)
+												
+												rHandler.setReagentFeatureDescriptor(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDescr)
+											
+											# March 29, 2010: Update set
+											rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, fID)
+											
+											setGroupID = sHandler.findPropSetGroupID(fID)
+											ssetID = sHandler.findSetValueID(setGroupID, tmpPropValue)
+											
+											if sHandler.findSetValueID(setGroupID, tmpPropValue) <= 0:
+												ssetID = sHandler.addSetValue(setGroupID, tmpPropValue)
+											
+											if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+												sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+									
+										else:
+											pass
+									else:
+										pass
+								else:
+									pass
+							else:
+								pass
+						else:
+							pass
+			
+			# Match db IDs to property aliases
+			for tmpProp in newPropsDict_name.keys():
+				if prop_Alias_ID_Map.has_key(tmpProp):
+					# July 2/09: propertyID <= propCatID
+					#propID = prop_Alias_ID_Map[tmpProp]	# removed July 2/09
+					propID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[tmpProp], prop_Category_Name_ID_Map["DNA Sequence Features"])
+					newPropsDict_id[propID] = newPropsDict_name[tmpProp]
+			
+			# ACTION
+			#rHandler.updateReagentSequenceFeatures(rID, seqFeatures)
+
+			# June 8/08: Update sites
+			seqID = rHandler.findDNASequenceKey(rID)
+			seq = dnaHandler.findSequenceByID(seqID)
+			
+			#print `five_prime_site`
+			#rHandler.updateSitePositions(rID, seq, five_prime_site, three_prime_site)
+			
+			# June 16/08: Update protein translation
+			if rTypeID == '2':
+				iHandler.updateInsertProteinSequence(rID)
+			
+			# return to detailed view - Moved here July 7/08
+			utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+
+		# April 10/08: Associations
+		elif form.has_key("save_parents"):
+			
+			#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+			#print
+			#print `form`
+			#print "hoho"
+			
+			five_prime_site = []		# jan. 19/09 - initialize arrays for potential hybrid sites
+			three_prime_site = []		# jan. 19/09 - initialize arrays for potential hybrid sites
+			
+			assocPropsDict = {}
+			newPropsDict_name = {}			# e.g. ('status', 'Completed')
+			newPropsDict_id = {}			# e.g. ('3', 'Completed') - db ID instead of property name
+
+			#assocTypes = reagent.getAssociationTypes()
+			
+			assocTypes = rtAssocHandler.findReagentTypeAssocProps(rTypeID)
+			#print `assocTypes`
+			
+			assocAliases = {}
+			associations = {}
+			
+			rType = reagentType_ID_Name_Map[int(rTypeID)]
+			
+			for assocPropID in assocTypes:
+				#print assocPropID
+				
+				#assocAlias = assoc_ID_Alias_Map[assocPropID]
+				#assocID = assoc_Name_ID_Map[aType]
+				
+				#tmpPropName = assocPrefix + assocAlias + postfix
+				
+				tmpPropName = rType + "_" + assocPrefix + `assocPropID` + postfix
+				#print tmpPropName
+				
+				#assocAliases[assocAlias] = aType
+				#associations[assocID] = aType
+			
+			#for assocAlias in assocAliases:
+				#tmpPropName = assocPrefix + assocAlias + postfix
+				#print tmpPropName
+				
+			#for assocID in assocTypes:
+				#tmpPropName = assocPrefix + `assocID` + postfix
+				
+				if form.has_key(tmpPropName):
+					tmpPropVal = form.getvalue(tmpPropName)
+					#print tmpPropVal
+					#assocID = assoc_Alias_ID_Map[assocAlias]
+					#print assocID
+					#assocPropsDict[assocID] = tmpPropVal
+					assocPropsDict[assocPropID] = tmpPropVal
+			
+			#print `assocPropsDict`
+			
+			# Verify parent project access AND reconstruct the sequence IFF parent values are changed
+			newSeq = ""
+	
+			# Fetch projects the user has AT LEAST Read access to (i.e. if he is explicitly declared a Writer on a project but not declared a Reader, include that project, plus all public projects)
+			currReadProj = packetHandler.findMemberProjects(currUser.getUserID(), 'Reader')
+			currWriteProj = packetHandler.findMemberProjects(currUser.getUserID(), 'Writer')
+			publicProj = packetHandler.findAllProjects(isPrivate="FALSE")
+			
+			# list of Packet OBJECTS
+			currUserWriteProjects = utils.unique(currReadProj + currWriteProj + publicProj)
+			
+			uPackets = []
+			
+			for p in currUserWriteProjects:
+				uPackets.append(p.getNumber())
+		
+			# Get project IDs of parents
+			packetPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["packet id"], prop_Category_Name_ID_Map["General Properties"])
+
+			# July 7/08: site property IDs
+			insertCloningSites = []
+			
+			#fpcs_prop_id = prop_Name_ID_Map["5' cloning site"]
+			fpcs_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+			
+			#tpcs_prop_id = prop_Name_ID_Map["3' cloning site"]
+			tpcs_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' cloning site"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+
+			# Vector Function - needed later to determine sequence construction
+			#vFunc_prop_id = prop_Name_ID_Map["vector type"]
+			vFunc_prop_id = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["vector type"], prop_Category_Name_ID_Map["General Properties"])
+
+			vFunc = rHandler.findSimplePropertyValue(rID, vFunc_prop_id)
+			
+			seqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+			
+			fpLinkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+			
+			tpLinkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+
+			cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+			
+			namePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["name"], prop_Category_Name_ID_Map["General Properties"])
+			
+			vTypePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["vector type"], prop_Category_Name_ID_Map["General Properties"])
+			
+			projectPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["packet id"], prop_Category_Name_ID_Map["General Properties"])
+			
+			descrPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["description"], prop_Category_Name_ID_Map["General Properties"])
+			
+			verifPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["verification"], prop_Category_Name_ID_Map["General Properties"])
+
+			# Differentiate parents by reagent type and subtype
+			if rTypeID == '1':
+				#print "Content-type:text/html"
+				#print
+				#print `form`
+
+				# Vector.  Check Parent Vector, and either Insert or IPV, depending on the cloning method
+				# Modified July 7/08
+				#if form.has_key("assoc_parent_vector"):
+				if form.has_key("PV"):
+					pvVal = form.getvalue("PV")
+					#pvVal = form.getvalue("assoc_parent_vector")
+	
+					if len(pvVal) > 0:
+						pvID = rHandler.convertReagentToDatabaseID(pvVal)
+	
+						try:
+							pvProjectID = int(rHandler.findSimplePropertyValue(pvID, packetPropID))
+							pvSeqID = rHandler.findDNASequenceKey(pvID)
+							pvSequence = dnaHandler.findSequenceByID(pvSeqID)
+						
+						except TypeError:
+							
+							# July 4/08
+							i = PVProjectAccessException("Invalid Parent Vector project ID")
+							
+							print "Content-type:text/html"
+							print
+							print `i.err_code()`
+							return
+					else:
+						pvID = -1
+						pvProjectID = -1
+						#errVal = True
+						
+						# July 4/08
+						i = PVProjectAccessException("Invalid Parent Vector project ID")
+						
+						print "Content-type:text/html"
+						print
+						print `i.err_code()`
+						return
+				else:
+					pvProjectID = -1
+					#errVal = True
+					
+					# July 4/08
+					i = PVProjectAccessException("Invalid Parent Vector project ID")
+					
+					print "Content-type:text/html"
+					print
+					print `i.err_code()`
+					return
+	
+				if pvProjectID > 0 and currUser.getCategory() != 'Admin' and pvProjectID not in uPackets:
+					
+					# updated July 4/08
+					i = PVProjectAccessException("Invalid Parent Vector project ID")
+					
+					print "Content-type:text/html"
+					print
+					print `i.err_code()`
+					return
+					
+					#errVal = True
+					#utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID` + "&mode=Modify&ErrCode=3&PV=" + pvVal + "#rp")
+				
+				# Find out if parents were changed and, if yes, update sequence according to vector type
+				oldAssoc = rHandler.findAllReagentAssociationsByName(rID)
+	
+				# get the old parent vector association value
+				if oldAssoc.has_key("vector parent id"):
+					oldPVID = oldAssoc["vector parent id"]
+				else:
+					oldPVID = -1
+	
+				if cloning_method == '1':
+					
+					isGateway = False
+					
+					# Non-recombination vector - Get the Insert
+					if oldAssoc.has_key("insert id"):
+						oldInsertID = oldAssoc["insert id"]
+					else:
+						oldInsertID = -1
+					
+					# Modified July 7/08
+					#if form.has_key("assoc_insert_id"):
+						#insertVal = form.getvalue("assoc_insert_id")
+						
+					if form.has_key("I"):
+						insertVal = form.getvalue("I")
+						
+						if len(insertVal) > 0:
+							insertID = rHandler.convertReagentToDatabaseID(insertVal)
+							
+							try:
+								insertProjectID = int(rHandler.findSimplePropertyValue(insertID, packetPropID))
+								
+							except (TypeError, ValueError, IndexError):
+								insertProjectID = 0
+								
+							if currUser.getCategory() != 'Admin' and insertProjectID not in uPackets:
+								i = InsertProjectAccessException("You do not have read access to this project")
+						
+								print "Content-type:text/html"
+								print
+								print `i.err_code()`
+								return
+							
+							# get Insert sequence ID for reconstitution
+							insertSeqID = rHandler.findDNASequenceKey(insertID)
+							insertSeq = dnaHandler.findSequenceByID(insertSeqID)
+							
+							# Get linkers from Insert
+							insertLinkers = []
+							
+							# Update July 2/09
+							#fpLinkerPropID = prop_Name_ID_Map["5' linker"]		# removed July 2/09
+							#tpLinkerPropID = prop_Name_ID_Map["3' linker"]		# removed July 2/09
+							
+							fp_insert_linker = rHandler.findSimplePropertyValue(insertID, fpLinkerPropID)
+							tp_insert_linker = rHandler.findSimplePropertyValue(insertID, tpLinkerPropID)
+							
+							# sept. 3/07 - needed to cast to string
+							fwd_linker = ""
+						
+							if fp_insert_linker and len(fp_insert_linker) > 0 and fp_insert_linker != 0 and fp_insert_linker != '0':
+								fp_insert_linker = fwd_linker + fp_insert_linker
+							else:
+								fp_insert_linker = fwd_linker
+								
+							# April 24/08
+							if not tp_insert_linker or len(tp_insert_linker) == 0 or tp_insert_linker == 0 or tp_insert_linker == '0':
+								tp_insert_linker = ""
+
+							insertLinkers.append(fp_insert_linker)
+							insertLinkers.append(tp_insert_linker)
+							
+							if form.has_key("reverse_insert") and form.getvalue("reverse_insert") == 'true':
+								reverse_insert = True
+							else:
+								reverse_insert = False
+							
+							if form.has_key("custom_sites") and form.getvalue("custom_sites") == 'true':
+								insert_fp_custom = form.getvalue("insert_custom_five_prime")
+								insert_tp_custom = form.getvalue("insert_custom_three_prime")
+								
+								pv_fp_custom = form.getvalue("pv_custom_five_prime")
+								pv_tp_custom = form.getvalue("pv_custom_three_prime")
+							
+								if insert_fp_custom == pv_fp_custom:
+									fpcs = pv_fp_custom
+								else:
+									fpcs = pv_fp_custom + "-" + insert_fp_custom
+							
+								if insert_tp_custom == pv_tp_custom:
+									tpcs = pv_tp_custom
+								else:
+									tpcs = insert_tp_custom + "-" + pv_tp_custom
+							
+								insertCloningSites.append(fpcs)
+								insertCloningSites.append(tpcs)
+								
+								# Feb. 12/09
+								if fpcs != tpcs:
+									linear = False
+								else:
+									# Do NOT use linear=False in searching Insert sequence for IDENTICAL sites!!! (e.g. EcoRI children of V2327 Top) 
+									linear = True
+								
+								five_prime_site = utils.make_array(fpcs)
+								three_prime_site = utils.make_array(tpcs)
+								
+								if dnaHandler.isHybrid(five_prime_site):
+									fpSite = dnaHandler.hybridSeq(five_prime_site)
+									
+									fp_h1 = dnaHandler.get_H_1(five_prime_site)
+									pvSeq = Seq(pvSequence)
+									
+									if dnaHandler.enzDict.has_key(fp_h1):
+										fp_h1_enz = dnaHandler.enzDict[fp_h1]
+									
+										# added Dec. 18/08
+										fp_h1_seq = fp_h1_enz.elucidate().replace("_", "")
+										fp_h1_clvg = fp_h1_seq.find("^")
+										fp_h1_flank = fp_h1_seq[0:fp_h1_clvg]
+										
+										pv_fp_h1_pos = fp_h1_enz.search(pvSeq, False)
+										pv_fp_h1_pos.sort()
+										
+										if len(pv_fp_h1_pos) > 0:
+											fp_start = pv_fp_h1_pos[0] - len(fp_h1_flank)
+											fp_end = fp_start + len(fp_h1_seq)
+									
+											fpStartPos = fp_start
+											fpEndPos = fp_end
+										
+								if dnaHandler.isHybrid(three_prime_site):
+									tpSite = dnaHandler.hybridSeq(three_prime_site)
+									
+									if not tpSite:
+										i = HybridizationException("")
+										err = i.err_code()
+										print "Content-type:text/html"
+										print
+										print `err`
+										return
+									
+									tp_h2 = dnaHandler.get_H_2(three_prime_site)
+									pvSeq = Seq(pvSequence)
+									
+									if dnaHandler.enzDict.has_key(tp_h2):
+										tp_h2_enz = dnaHandler.enzDict[tp_h2]
+										#print tp_h2_enz
+										
+										tp_h2_seq = tp_h2_enz.elucidate().replace("_", "")
+										tp_h2_clvg = tp_h2_seq.find("^")
+										tp_h2_flank = tp_h2_seq[0:tp_h2_clvg]
+										
+										pv_tp_h2_pos = tp_h2_enz.search(pvSeq, False)
+										pv_tp_h2_pos.sort()
+										
+										if len(pv_tp_h2_pos) > 0:
+											pv_tp_start = pv_tp_h2_pos[len(pv_tp_h2_pos)-1] - len(tp_h2_flank)
+											pv_tp_end = pv_tp_start + len(tpSite)
+											
+											pv_post = pvSequence[pv_tp_end:].lower()
+											#print pv_post
+
+							else:
+								# get sites from Insert
+								
+								fp_insert_cs = rHandler.findSimplePropertyValue(insertID, fpcs_prop_id)
+								tp_insert_cs = rHandler.findSimplePropertyValue(insertID, tpcs_prop_id)
+								
+								five_prime_site = utils.make_array(fp_insert_cs)
+								three_prime_site = utils.make_array(tp_insert_cs)
+								
+								# Dec. 18/08: Check directional cloning
+								if fp_insert_cs != tp_insert_cs:
+									linear = False
+								else:
+									# Do NOT use linear=False in searching Insert sequence for IDENTICAL sites!!! (e.g. EcoRI children of V2327 Top) 
+									linear = True
+								
+								if fp_insert_cs:
+									# Check here if Insert sites are Gateway; if yes, compare them to Vector Type
+									if fp_insert_cs.lower().find("attb") >= 0:
+										isGateway = True
+										insertCloningSites.append(fp_insert_cs)
+									else:
+										insertCloningSites.append(fp_insert_cs)
+								else:
+									insertCloningSites.append("")
+								
+								if tp_insert_cs:
+									# again, check gateway (somewhat redundant but makes system more robust)
+									if tp_insert_cs.lower().find('attb') >= 0:
+										
+										# set GW sites later
+										isGateway = True
+										insertCloningSites.append(tp_insert_cs)
+									else:
+										insertCloningSites.append(tp_insert_cs)
+								else:
+									insertCloningSites.append("")
+							
+							try:
+								# Check if sites are empty
+								if len(insertCloningSites) == 0:
+									# Modified Feb. 12/09
+									i = EmptyCloningSitesException("")
+									err = i.err_code()
+									#err = 13
+									
+									print "Content-type:text/html"
+									print
+									print `err`
+									return
+								
+								if not isGateway:
+									
+									fp_insert_cs = insertCloningSites[0]
+									tp_insert_cs = insertCloningSites[1]
+									
+									# Jan. 19/09:
+									if not dnaHandler.isHybrid(five_prime_site):
+										# Sept. 30/08: SfiI sequences from V1889
+										if fp_insert_cs == 'SfiI':
+											fpSite = "GGCCATTACGGCC"
+										else:
+											if enzDict.has_key(fp_insert_cs):
+												fpSite = enzDict[fp_insert_cs]
+											else:
+												print "Content-type:text/html"
+												print
+												print "Unknown 5' site: " + fp_insert_cs
+												return
+										
+										fp_start = insertSeq.lower().find(fpSite) + 1
+										fp_end = fp_start + len(fpSite)
+										
+										if fp_start == 0:
+											# Dec. 17/08: If sites are not found, use BioPython to look for degenerate sites with variable sequences
+											tmpSeq = Bio.Seq.Seq(insertSeq)
+											fp_cs = dnaHandler.enzDict[fp_insert_cs]
+											
+											# added Dec. 18/08
+											fp_seq = fp_cs.elucidate().replace("_", "")
+											fp_clvg = fp_seq.find("^")
+											fp_flank = fp_seq[0:fp_clvg]
+											
+											#print "Content-type:text/html"
+											#print
+										
+											tmp_fp_pos = fp_cs.search(tmpSeq, linear)
+											tmp_fp_pos.sort()
+										
+											if len(tmp_fp_pos) > 0:
+												fp_start = tmp_fp_pos[0] - len(fp_flank)
+												fp_end = fp_start + len(fpSite)
+												
+												if fp_start == 0:
+													fp_start = 0
+													fp_end = 0
+											else:
+												fp_start = 0
+												fp_end = 0
+										
+										# Compare to site positions stored for this Insert
+										orig_fp_start = rHandler.findReagentFeatureStart(insertID, fpcs_prop_id)
+										orig_fp_end = rHandler.findReagentFeatureEnd(insertID, fpcs_prop_id)
+										
+										# update Feb. 12/09
+										if not reverse_insert and fp_insert_cs == fpSite and tp_insert_cs == tpSite and orig_fp_start != fp_start and orig_fp_end != fp_end:
+											# error
+											#err = 13
+										
+											# Modified Feb. 12/09
+											i = EmptyCloningSitesException("")
+											err = i.err_code()
+											
+											print "Content-type:text/html"
+											print
+											print `err`
+											return
+									
+									# 3' site
+									if not dnaHandler.isHybrid(three_prime_site):
+										# Sept. 30/08: Special case: SfiI from V1889
+										if tp_insert_cs == 'SfiI':
+											tpSite = "GGCCGCCTCGGCC"
+										else:
+											if enzDict.has_key(tp_insert_cs):
+												tpSite = enzDict[tp_insert_cs]
+												#print tpSite
+											else:
+												print "Content-type:text/html"
+												print
+												print "Unknown 3' site: " + tp_insert_cs
+												return
+									
+										# Jan. 22/09 - added 'rfind' and 'lower()'
+										tp_start = insertSeq.lower().rfind(tpSite.lower()) + 1
+										tp_end = tp_start + len(tpSite) - 1
+										
+										if tp_start == 0:
+											# check for degenerate
+											tmpSeq = Bio.Seq.Seq(insertSeq)
+											tp_cs = dnaHandler.enzDict[tp_insert_cs]
+											
+											tp_seq = tp_cs.elucidate().replace("_", "")
+											tp_clvg = tp_seq.find("^")
+											tp_flank = tp_seq[0:tp_clvg]
+											
+											tmp_tp_pos = tp_cs.search(tmpSeq, linear)
+											tmp_tp_pos.sort()
+										
+											if len(tmp_tp_pos) > 0:
+												tp_start = tmp_tp_pos[len(tmp_tp_pos)-1] - len(tp_flank)
+												tp_end = tp_start + len(tpSite)
+												
+												if tp_start == 0:
+													tp_start = 0
+													tp_end = 0
+											else:
+												tp_start = 0
+												tp_end = 0
+										
+										# Feb. 12/09
+										if not reverse_insert and fp_insert_cs == fpSite and tp_insert_cs == tpSite:
+											orig_tp_start = rHandler.findReagentFeatureStart(insertID, tpcs_prop_id)
+											orig_tp_end = rHandler.findReagentFeatureEnd(insertID, tpcs_prop_id)
+										
+											if orig_tp_start != tp_start and orig_tp_end != tp_end:
+												# error
+												#err = 13
+										
+												# Modified Feb. 12/09
+												i = EmptyCloningSitesException("")
+												err = i.err_code()
+												
+												print "Content-type:text/html"
+												print
+												print `err`
+												return
+								
+									# nov. 6/08
+									if (not dnaHandler.isHybrid(five_prime_site) and dnaHandler.gatewayDict.has_key(insertCloningSites[0])) or (not dnaHandler.isHybrid(three_prime_site) and dnaHandler.gatewayDict.has_key(insertCloningSites[1])) or (not dnaHandler.isHybrid(five_prime_site) and dnaHandler.recombDict.has_key(insertCloningSites[0])) or (not dnaHandler.isHybrid(three_prime_site) and dnaHandler.recombDict.has_key(insertCloningSites[1])):
+									
+										# Non-recombination vector attempted with gateway or LoxP Insert - disallow
+										i = InsertSitesException("Wrong sites on Insert")
+										err = i.err_code()
+									
+										print "Content-type:text/html"
+										print
+										print `err`
+										return
+									
+									cdnaStart = iHandler.findCDNAStart(insertID)
+									cdnaEnd = iHandler.findCDNAEnd(insertID)
+									
+									try:
+										newSeq = dnaHandler.constructNonRecombSequence(pvSeqID, insertSeq, insertCloningSites, reverse_insert)		# Oct. 30/08
+										
+										if dnaHandler.isHybrid(three_prime_site):
+											tp_start = newSeq.lower().find(pv_post.lower()) - len(tpSite)
+											tp_end = tp_start + len(tpSite)
+									
+											tpStartPos = tp_start
+											tpEndPos = tp_end
+										
+										newSeqID = int(dnaHandler.matchSequence(newSeq))
+							
+										if newSeqID <= 0:
+											newSeqID = int(dnaHandler.insertSequence(newSeq))
+											
+										# Now save parents - delete all previous information
+										pvAssocProp = aHandler.findAssocPropID("vector parent id")
+										insertAssocProp = aHandler.findAssocPropID("insert id")
+										
+										rAssocID = raHandler.findReagentAssociationID(rID)
+										
+										rHandler.deleteReagentAssociationProp(rID, pvAssocProp)
+										rHandler.addAssociationValue(rID, pvAssocProp, pvID, rAssocID)
+					
+										rHandler.deleteReagentAssociationProp(rID, insertAssocProp)
+										rHandler.addAssociationValue(rID, insertAssocProp, insertID, rAssocID)
+									
+										# Save new sequence
+										rHandler.updateDNASequence(rID, newSeqID)
+									
+										# Remap features - Delete old features first
+										rHandler.deleteReagentFeatures(rID)
+										
+										#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["5' cloning site"])
+										#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["3' cloning site"])
+										
+										# Nov. 6/08 - Delete linkers separately, as they're not included in features list (if they don't exist no harm done)
+										rHandler.deleteReagentProperty(rID, fpLinkerPropID)
+										rHandler.deleteReagentProperty(rID, tpLinkerPropID)
+
+										newSeq = utils.squeeze(newSeq).lower()
+										
+										# Avoid duplicate values - may already have ReagentPropList_tbl entries for this reagent, clear them before saving (for consistency)
+										
+										rHandler.deleteReagentProperty(rID, seqPropID)
+										rHandler.addReagentProperty(rID, seqPropID, newSeqID)
+										
+										# find cDNA portion on **ORIGINAL** Insert sequence
+										insert_cdnaStart = iHandler.findCDNAStart(insertID)
+										insert_cdnaEnd = iHandler.findCDNAEnd(insertID)
+										
+										# Updated June 1/08: added 'if-else'
+										if insert_cdnaStart > 0 and insert_cdnaEnd > 0:
+											cdnaSeq = insertSeq[insert_cdnaStart-1:insert_cdnaEnd]
+										else:
+											cdnaSeq = insertSeq
+										
+										# Jan. 21/09
+										if reverse_insert:
+											cdnaSeq = dnaHandler.reverse_complement(cdnaSeq)
+										
+											# Update July 2/09: pass cdnaPropID to setPropertyDirection() function in combination with its category
+											rHandler.setPropertyDirection(rID, cdnaPropID, 'reverse')
+										
+											cdnaStart = newSeq.lower().find(cdnaSeq.lower()) + 1
+											cdnaEnd = cdnaStart + len(cdnaSeq)
+									
+										# July 2/09
+										#cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+										rHandler.setPropertyPosition(rID, cdnaPropID, "startPos", cdnaStart)
+										rHandler.setPropertyPosition(rID, cdnaPropID, "endPos", cdnaEnd)
+										
+										# 5' cloning site (sequence in lowercase, search for site in lowercase too)
+										if not dnaHandler.isHybrid(five_prime_site):
+											if newSeq.find(fpSite.lower()) >= 0:
+												fpStartPos = newSeq.find(fpSite.lower()) + 1
+												fpEndPos = fpStartPos + len(fpSite)
+											else:
+												# Dec. 17/08
+												# reason could be that the site is a degenerate - try one more time with BioPython
+												tmpSeq = Bio.Seq.Seq(newSeq)
+												fp_cs = dnaHandler.enzDict[fp_insert_cs]
+										
+												# added Dec. 18/08
+												fp_seq = fp_cs.elucidate().replace("_", "")
+												fp_clvg = fp_seq.find("^")
+												fp_flank = fp_seq[0:fp_clvg]
+												
+												tmp_fp_pos = fp_cs.search(tmpSeq, linear)
+												tmp_fp_pos.sort()
+										
+												if len(tmp_fp_pos):
+													fpStartPos = tmp_fp_pos[0] - len(fp_flank)
+													fpEndPos = fpStartPos + len(fpSite)
+													
+													if fpStartPos == 0:
+														fpStartPos = 0
+														fpEndPos = 0
+												else:
+													fpStartPos = 0
+													fpEndPos = 0
+										
+										# 3' cloning site
+										if not dnaHandler.isHybrid(three_prime_site):
+											if newSeq.rfind(tpSite.lower()) >= 0:
+												tpStartPos = newSeq.rfind(tpSite.lower()) + 1		# look from END of sequence?????
+												tpEndPos = tpStartPos + len(tpSite)
+											else:	
+												# Dec. 17/08
+												# reason could be that the site is a degenerate - try one more time with BioPython
+												tmpSeq = Bio.Seq.Seq(newSeq)
+												tp_cs = dnaHandler.enzDict[tp_insert_cs]
+										
+												# added Dec. 18/08
+												tp_seq = tp_cs.elucidate().replace("_", "")
+												tp_clvg = tp_seq.find("^")
+												tp_flank = tp_seq[0:tp_clvg]
+												
+												tmp_tp_pos = tp_cs.search(tmpSeq, linear)
+												tmp_tp_pos.sort()
+										
+												if len(tmp_tp_pos) > 0:
+													tpStartPos = tmp_tp_pos[len(tmp_tp_pos)-1] - len(tp_flank)
+													tpEndPos = tpStartPos + len(tpSite)
+													
+													if tpStartPos == 0:
+														tpStartPos = 0
+														tpEndPos = 0
+												else:
+													tpStartPos = 0
+													tpEndPos = 0
+											
+										# Nov. 6/08: Map linkers in the same fashion
+										if fp_insert_linker and len(fp_insert_linker) >= 10:
+										
+											# Jan. 22/09
+											if reverse_insert:
+												fp_insert_linker = dnaHandler.reverse_complement(fp_insert_linker)
+											
+											fpLinkerStartPos = newSeq.find(fp_insert_linker.lower()) + 1
+											fpLinkerEndPos = fpLinkerStartPos + len(fp_insert_linker)
+											rHandler.addReagentProperty(rID, fpLinkerPropID, fp_insert_linker, fpLinkerStartPos, fpLinkerEndPos-1)
+										else:
+											fpLinkerStartPos = 0
+											fpLinkerEndPos = 0
+											
+										# 3' linker
+										if tp_insert_linker and len(tp_insert_linker) >= 10:
+											
+											# Jan. 22/09
+											if reverse_insert:
+												tp_insert_linker = dnaHandler.reverse_complement(tp_insert_linker)
+										
+											tpLinkerStartPos = newSeq.find(tp_insert_linker.lower()) + 1
+											tpLinkerEndPos = tpLinkerStartPos + len(tp_insert_linker)
+											rHandler.addReagentProperty(rID, tpLinkerPropID, tp_insert_linker, tpLinkerStartPos, tpLinkerEndPos-1)
+										else:
+											tpLinkerStartPos = 0
+											tpLinkerEndPos = 0
+										
+										# Nov. 3/08 - check if 5' site is after 3' - if yes, look for the reverse sequence
+										cdna_dir = 'forward'
+										
+										if fpStartPos > tpStartPos:
+											cdnaSeq = dnaHandler.reverse_complement(cdnaSeq)
+										
+											# Update July 2/09: pass cdnaPropID to setPropertyDirection() function in combination with its category
+											#cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+											rHandler.setPropertyDirection(rID, cdnaPropID, 'reverse')
+										
+										elif reverse_insert:
+											# set orientation='reverse' but don't RC cDNA!!!
+										
+											# Update July 2/09: pass cdnaPropID to setPropertyDirection() function in combination with its category
+											#cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+											rHandler.setPropertyDirection(rID, cdnaPropID, 'reverse')
+										
+										# cDNA (in lowercase already)
+										if newSeq.find(cdnaSeq) >= 0:
+											
+											cdnaStart = newSeq.find(cdnaSeq) + 1		# may 22/08
+											cdnaEnd = cdnaStart + len(cdnaSeq) - 1		# may 22/08
+										else:
+											cdnaStart = 0
+											cdnaEnd = 0
+										
+										# July 2/09
+										#cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+										rHandler.setPropertyPosition(rID, cdnaPropID, "startPos", cdnaStart)
+										rHandler.setPropertyPosition(rID, cdnaPropID, "endPos", cdnaEnd)
+										
+										rHandler.addReagentProperty(rID, fpcs_prop_id, fp_insert_cs, fpStartPos, fpEndPos-1)
+										rHandler.addReagentProperty(rID, tpcs_prop_id, tp_insert_cs, tpStartPos, tpEndPos-1)
+										
+										iFeatures = rHandler.findReagentSequenceFeatures(insertID)
+										pvFeatures = rHandler.findReagentSequenceFeatures(pvID)
+										
+										# changes made Oct. 14/08
+										tmp_dict = {}
+										
+										# Parent Vector features are found before 5' start and after 3' end on the new sequence
+										for f in pvFeatures:
+											fType = f.getFeatureType()
+											#print fType
+											
+											if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+											
+												# original feature positions on PV sequence
+												pv_fStart = f.getFeatureStartPos()
+												#print `pv_fStart`
+												pv_fEnd = f.getFeatureEndPos()
+												
+												fSeq = pvSequence[pv_fStart-1:pv_fEnd].lower()
+												tmp_dict[fSeq] = f
+										
+										for fSeq in tmp_dict.keys():
+											f_tmp = tmp_dict[fSeq]
+											
+											if len(fSeq) >= 10:
+												fList = utils.findall(newSeq.lower(), fSeq, [])
+												
+												for fIndex in fList:
+													fpStart = fIndex + 1
+													fpEnd = fpStart + len(fSeq) - 1
+													
+													if fpStart > 0 and fpEnd > 0:
+														# If found, make sure this feature occurs BETWEEN the CLONING SITES
+														if (fpStart < fpStartPos and fpEnd < fpStartPos) or (fpStart > fpEndPos and fpEnd > fpEndPos):
+															
+															fType = f_tmp.getFeatureType()
+															fVal =  f_tmp.getFeatureName()
+															pv_fDir = f_tmp.getFeatureDirection()
+													
+															# Nov. 4/08: fpStart >= tpEndPos, since tpEndPos is one greater than the actual site end value
+															if (fpStart < fpStartPos and fpEnd < fpStartPos) or (fpStart >= tpEndPos and fpEnd > tpEndPos):
+																#print fType + ": " + fVal + ": " + `fpStart` + "-" + `fpEnd`
+																fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+																#rHandler.addReagentProperty(rID, prop_Name_ID_Map[fType], fVal, fpStart, fpEnd, pv_fDir)
+																rHandler.addReagentProperty(rID, fID, fVal, fpStart, fpEnd, pv_fDir)
+														
+																if f_tmp.getFeatureDescrType():
+																	fDescr = f_tmp.getFeatureDescrName()
+																	fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+																	rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fpStart, fpEnd, fDescr)
+								
+										# Search for each Insert feature on the new sequence
+										tmp_i_dict = {}
+										
+										for f in iFeatures:
+											fType = f.getFeatureType()
+											#print fType
+											
+											if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+												# feature positions on the Insert sequence - Modified May 21/08: Account for the fact that NOT the entire Insert sequence is used, only a subsequence
+												fiStart = f.getFeatureStartPos()
+												fiEnd = f.getFeatureEndPos()
+												fSeq = insertSeq[fiStart:fiEnd].lower()
+												tmp_i_dict[fSeq] = f
+											
+											
+										for fSeq in tmp_i_dict.keys():
+											f_tmp = tmp_i_dict[fSeq]
+											
+											if len(fSeq) >= 10:
+												# Jan. 22/09
+												if reverse_insert:
+													fSeq = dnaHandler.reverse_complement(fSeq)
+												
+												fList = utils.findall(newSeq.lower(), fSeq, [])
+												
+												for fIndex in fList:
+													fStart = newSeq.lower().find(fSeq)
+													fEnd = fStart + len(fSeq)
+													
+													f_tmp.getFeatureName()
+													
+													# still, double check to make sure this feature occurs between the CLONING SITES on the resulting Vector sequence!!!!
+													if fStart >= fpStartPos and fEnd <= tpEndPos:
+														fType = f_tmp.getFeatureType()
+														fVal =  f_tmp.getFeatureName()
+														fiDir = f_tmp.getFeatureDirection()
+										
+														# Jan. 22/09
+														if reverse_insert:
+															fiDir = 'reverse'
+														
+														fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+			
+														#rHandler.addReagentProperty(rID, prop_Name_ID_Map[fType], fVal, fStart, fEnd, fiDir)
+														rHandler.addReagentProperty(rID, fID, fVal, fStart, fEnd, fiDir)
+													
+														if f.getFeatureDescrType():
+															fDescr = f_tmp.getFeatureDescrType()
+															
+															# Updated July 2/09
+															#fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+															rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fStart, fEnd, fDescr)
+									
+										
+										if form.has_key("newVectorName"):
+											newName = form.getvalue("newVectorName")
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["name"])
+											rHandler.deleteReagentProperty(rID, namePropID)
+											#rHandler.addReagentProperty(rID, prop_Name_ID_Map["name"], newName)
+											rHandler.addReagentProperty(rID, namePropID, newName)
+										else:
+											rHandler.deleteReagentProperty(rID, namePropID)
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["name"])
+										
+										if form.has_key("newVectorType"):
+											newVectorType = form.getvalue("newVectorType")
+											
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["vector type"])
+											rHandler.deleteReagentProperty(rID, vTypePropID)
+											#rHandler.addReagentProperty(rID, prop_Name_ID_Map["vector type"], newVectorType)
+											rHandler.addReagentProperty(rID, vTypePropID, newVectorType)
+										else:
+											rHandler.deleteReagentProperty(rID, vTypePropID)
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["vector type"])
+										
+										if form.has_key("newProjectID"):
+											newProjectID = form.getvalue("newProjectID")
+										
+											# Update July 2/09: pass projectPropID to changePropertyValue() function in combination with its category
+											rHandler.changePropertyValue(rID, projectPropID, newProjectID)
+										else:
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["project id"])
+											rHandler.deleteReagentProperty(rID, projectPropID)
+										
+										if form.has_key("newDescription"):
+											newDescription = form.getvalue("newDescription")
+											
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["description"])
+											rHandler.deleteReagentProperty(rID, descrPropID)
+											#rHandler.addComment(rID, prop_Name_ID_Map["description"], newDescription)
+											rHandler.addComment(rID, descrPropID, newDescription)
+										else:
+											rHandler.deleteReagentProperty(rID, descrPropID)
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["description"])
+										
+										if form.has_key("newVerification"):
+											newVerification = form.getvalue("newVerification")
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["verification"])
+										
+											rHandler.deleteReagentProperty(rID, verifPropID)
+											#rHandler.addReagentProperty(rID, prop_Name_ID_Map["verification"], newVerification)
+											rHandler.addReagentProperty(rID, verifPropID, newVerification)
+										else:
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["verification"])
+											rHandler.deleteReagentProperty(rID, verifPropID)
+								
+										print "Content-type:text/html"
+										print
+										print "0"
+										return
+								
+									except InsertSitesException:
+										i = InsertSitesException("Wrong sites on Insert")
+										err = i.err_code()
+									
+										print "Content-type:text/html"
+										print
+										print `err`
+										return
+								
+									except InsertSitesNotFoundOnParentSequenceException:
+										i = InsertSitesNotFoundOnParentSequenceException("Insert sites not found on parent vector sequence")
+										err = i.err_code()
+									
+										print "Content-type:text/html"
+										print
+										print `err`
+										return
+								
+									except MultipleSiteOccurrenceException:
+										i = MultipleSiteOccurrenceException("Site found more than once on parent vector sequence")
+										err = i.err_code()
+									
+										print "Content-type:text/html"
+										print
+										print `err`
+										return
+										
+									except HybridizationException:
+										i = HybridizationException("Sites cannot be hybridized")
+										err = i.err_code()
+									
+										print "Content-type:text/html"
+										print
+										print `err`
+										return
+								
+									except FivePrimeAfterThreePrimeException:
+										
+										i = FivePrimeAfterThreePrimeException("5' site occurs after 3' site on parent vector sequence")
+										err = i.err_code()
+									
+										print "Content-type:text/html"
+										print
+										print `err`
+										return
+								
+									# June 2/08
+									except InvalidDonorVectorSitesNotFoundException:
+										i = InvalidDonorVectorSitesNotFoundException("LoxP sites not found on donor sequence")
+										err = i.err_code()
+									
+										print "Content-type:text/html"
+										print
+										print `err`
+										return
+										
+									except InvalidDonorVectorMultipleSitesException:
+										i = InvalidDonorVectorMultipleSitesException("LoxP sites occur more than twice on donor sequence")
+										err = i.err_code()
+									
+										print "Content-type:text/html"
+										print
+										print `err`
+										return
+								
+									except InvalidDonorVectorSingleSiteException:
+										i = InvalidDonorVectorSingleSiteException("Donor vector sequence contains a singe LoxP site")
+										err = i.err_code()
+									
+										print "Content-type:text/html"
+										print
+										print `err`
+										return
+										
+									except CloningSitesNotFoundInInsertException:
+										i = CloningSitesNotFoundInInsertException("")
+										err = i.err_code()
+									
+										print "Content-type:text/html"
+										print
+										print `err`
+										return
+									
+									# Dec. 14/09
+									except EmptyParentVectorSequenceException:
+										i = EmptyParentVectorSequenceException("The sequence of the parent Vector provided is empty.")
+										err = i.err_code()
+									
+										print "Content-type:text/html"
+										print
+										print "Error: " + i.toString() + " Please verify your input."
+										return
+									
+									# Dec. 14/09
+									except EmptyParentInsertSequenceException:
+										i = EmptyParentInsertSequenceException("The sequence of the parent Insert provided is empty.")
+										err = i.err_code()
+									
+										print "Content-type:text/html"
+										print
+										print "Error: " + i.toString() + " Please verify your input."
+										return
+									
+									# Dec. 14/09
+									except EmptyInsertParentVectorSequenceException:
+										i = EmptyInsertParentVectorSequenceException("The sequence of the Insert Parent Vector provided is empty.")
+										err = i.err_code()
+									
+										print "Content-type:text/html"
+										print
+										print "Error: " + i.toString() + " Please verify your input."
+										return
+									
+								# Gateway Entry clone
+								else:
+									fp_insert_cs = 'attL1'
+									tp_insert_cs = 'attL2'
+									
+									# Special sequences - Changed May 29/08 after discussion with Karen
+									fpSite = 'tttgtacaaaaaa'
+									tpSite = 'tttcttgtacaaagtt'
+									
+									# recompute sequence
+									newSeq = dnaHandler.entryVectorSequence(pvSeqID, insertSeq)
+									newSeqID = int(dnaHandler.matchSequence(newSeq))
+								
+									if newSeqID <= 0:
+										newSeqID = int(dnaHandler.insertSequence(newSeq))
+									
+									newSeq = utils.squeeze(newSeq).lower()
+									
+									# update sequence
+									rHandler.deleteReagentProperty(rID, seqPropID)
+									rHandler.addReagentProperty(rID, seqPropID, newSeqID)
+
+									# Save parents - delete all previous information
+									pvAssocProp = aHandler.findAssocPropID("vector parent id")
+									insertAssocProp = aHandler.findAssocPropID("insert id")
+									
+									rAssocID = raHandler.findReagentAssociationID(rID)
+									
+									rHandler.deleteReagentAssociationProp(rID, pvAssocProp)
+									rHandler.addAssociationValue(rID, pvAssocProp, pvID, rAssocID)
+				
+									rHandler.deleteReagentAssociationProp(rID, insertAssocProp)
+									rHandler.addAssociationValue(rID, insertAssocProp, insertID, rAssocID)
+								
+									# find cDNA portion on **ORIGINAL** Insert sequence
+									insert_cdnaStart = iHandler.findCDNAStart(insertID)
+									insert_cdnaEnd = iHandler.findCDNAEnd(insertID)
+
+									if insert_cdnaStart > 0 and insert_cdnaEnd > 0:
+										cdnaSeq = insertSeq[insert_cdnaStart-1:insert_cdnaEnd]
+									else:
+										cdnaSeq = insertSeq
+
+									# Remap features - Delete old values first
+									rHandler.deleteReagentFeatures(rID)
+								
+									# Nov. 6/08 - Delete linkers separately, as they're not included in features list
+									#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["5' linker"])
+									#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["3' linker"])
+									
+									rHandler.deleteReagentProperty(rID, fpLinkerPropID)
+									rHandler.deleteReagentProperty(rID, tpLinkerPropID)
+									
+									#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["5' cloning site"])
+									#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["3' cloning site"])
+									
+									# 5' cloning site (sequence in lowercase, search for site in lowercase too)
+									if newSeq.find(fpSite.lower()) >= 0:
+										fpStartPos = newSeq.find(fpSite.lower()) + 1
+										fpEndPos = fpStartPos + len(fpSite)
+									else:
+										fpStartPos = 0
+										fpEndPos = 0
+										
+									# 3' cloning site
+									if newSeq.rfind(tpSite.lower()) >= 0:
+										tpStartPos = newSeq.rfind(tpSite.lower()) + 1		# look from END of sequence?????
+										tpEndPos = tpStartPos + len(tpSite)
+									else:	
+										tpStartPos = 0
+										tpEndPos = 0
+										
+									# Nov. 6/08: Map linkers in the same fashion
+									if fp_insert_linker and len(fp_insert_linker) >= 10:
+										fpLinkerStartPos = newSeq.find(fp_insert_linker.lower()) + 1
+										fpLinkerEndPos = fpLinkerStartPos + len(fp_insert_linker)
+										#rHandler.addReagentProperty(rID, prop_Name_ID_Map["5' linker"], fp_insert_linker, fpLinkerStartPos, fpLinkerEndPos-1)
+										rHandler.addReagentProperty(rID, fpLinkerPropID, fp_insert_linker, fpLinkerStartPos, fpLinkerEndPos-1)
+									else:
+										fpLinkerStartPos = 0
+										fpLinkerEndPos = 0
+										
+									# 3' linker
+									if tp_insert_linker and len(tp_insert_linker) >= 10:
+										tpLinkerStartPos = newSeq.find(tp_insert_linker.lower()) + 1
+										tpLinkerEndPos = tpLinkerStartPos + len(tp_insert_linker)
+										#rHandler.addReagentProperty(rID, prop_Name_ID_Map["3' linker"], tp_insert_linker, tpLinkerStartPos, tpLinkerEndPos-1)
+										rHandler.addReagentProperty(rID, tpLinkerPropID, tp_insert_linker, tpLinkerStartPos, tpLinkerEndPos-1)
+									else:
+										tpLinkerStartPos = 0
+										tpLinkerEndPos = 0
+									
+									# Nov. 3/08 - check if 5' site is after 3' - if yes, look for the reverse sequence
+									cdna_dir = 'forward'
+									
+									if fpStartPos > tpStartPos:
+										cdnaSeq = dnaHandler.reverse_complement(cdnaSeq)
+										
+										# Update July 2/09: pass cdnaPropID to setPropertyDirection() function in combination with its category
+										#cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+										rHandler.setPropertyDirection(rID, cdnaPropID, 'reverse')
+										
+									# cDNA (in lowercase already)
+									if newSeq.find(cdnaSeq) >= 0:
+										
+										cdnaStart = newSeq.find(cdnaSeq) + 1		# may 22/08
+										cdnaEnd = cdnaStart + len(cdnaSeq) - 1		# may 22/08
+									else:
+										cdnaStart = 0
+										cdnaEnd = 0
+									
+									# July 2/09
+									#cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+									
+									rHandler.setPropertyPosition(rID, cdnaPropID, "startPos", cdnaStart)
+									rHandler.setPropertyPosition(rID, cdnaPropID, "endPos", cdnaEnd)
+									
+									rHandler.addReagentProperty(rID, fpcs_prop_id, fp_insert_cs, fpStartPos, fpEndPos-1)
+									rHandler.addReagentProperty(rID, tpcs_prop_id, tp_insert_cs, tpStartPos, tpEndPos-1)
+									
+									# Remap features
+									iFeatures = rHandler.findReagentSequenceFeatures(insertID)
+									pvFeatures = rHandler.findReagentSequenceFeatures(pvID)
+									
+									# Parent Vector features are found before cDNA start and after cDNA end on the new sequence
+									for f in pvFeatures:
+										fType = f.getFeatureType()
+										
+										if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+										
+											# original feature positions on PV sequence
+											pv_fStart = f.getFeatureStartPos()
+											pv_fEnd = f.getFeatureEndPos()
+										
+											fVal = f.getFeatureName()
+											pv_fDir = f.getFeatureDirection()
+											
+											if pv_fStart > 0 and pv_fEnd > 0:
+												
+												# Features from PV are inherited IFF they are located **entirely** before the 5' cloning site or after 3' cloning site
+												# Hence: May 22/08 - Find 5' start and 3' end on **original** PV sequence
+												pv_fpcs_start = pvSequence.lower().find(fpSite)
+												pv_tpcs_end = pvSequence.lower().find(tpSite) + len(tpSite)
+												
+												fSeq = pvSequence[pv_fStart-1:pv_fEnd].lower()
+								
+												# June 4/08 - Search for the feature IFF > 10 nts
+												if len(fSeq) >= 10:
+								
+													# Look for this feature on the NEWly reconstituted Vector
+													fIndex = newSeq.lower().find(fSeq)
+								
+													if fIndex >= 0:
+														fpStart = fIndex + 1
+														fpEnd = fpStart + len(fSeq) - 1
+														
+														# If found, make sure this feature occurs either before or after the INSERT - i.e. before 5' cloning site start OR after 3' cloning site end
+														if (fpStart < fpStartPos and fpEnd < fpStartPos) or (fpStart >= tpEndPos and fpEnd > tpEndPos):
+															fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+															#rHandler.addReagentProperty(rID, prop_Name_ID_Map[fType], fVal, fpStart, fpEnd, pv_fDir)
+															rHandler.addReagentProperty(rID, fID, fVal, fpStart, fpEnd, pv_fDir)
+												
+															if f.getFeatureDescrType():
+																fDescr = f.getFeatureDescrName()
+										
+																# Updated July 2/09
+																#fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+																rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fpStart, fpEnd, fDescr)
+											
+									# Search for each Insert feature on the new sequence
+									# June 6/08: Added 'if' statement - needs testing
+									for f in iFeatures:
+										fType = f.getFeatureType()
+										#print fType
+										
+										if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+											# feature positions on the Insert sequence - Modified May 21/08: Account for the fact that NOT the entire Insert sequence is used, only a subsequence
+											fiStart = f.getFeatureStartPos()
+											fiEnd = f.getFeatureEndPos()
+											fVal = f.getFeatureName()
+											#print fVal
+											fSeq = insertSeq[fiStart:fiEnd].lower()
+										
+											if len(fSeq) >= 10:
+												fStart = newSeq.lower().find(fSeq)
+												fEnd = fStart + len(fSeq)
+											
+												if fStart >= 1:
+								
+													# Insert features, on the other hand, must occur entirely WITHIN the Insert - i.e. between the cloning sites (Oct. 30/08)
+													if fStart >= fpStartPos and fEnd <= tpEndPos:
+														# Orientation
+														fiDir = f.getFeatureDirection()
+														fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+											
+														#rHandler.addReagentProperty(rID, prop_Name_ID_Map[fType], fVal, fStart, fEnd, fiDir)
+														rHandler.addReagentProperty(rID, fID, fVal, fStart, fEnd, fiDir)
+													
+														if f.getFeatureDescrType():
+															fDescr = f.getFeatureDescrType()
+										
+															# Updated July 2/09
+															#fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+															rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fStart, fEnd, fDescr)
+										
+										if form.has_key("newVectorName"):
+											newName = form.getvalue("newVectorName")
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["name"])
+											rHandler.deleteReagentProperty(rID, namePropID)
+											#rHandler.addReagentProperty(rID, prop_Name_ID_Map["name"], newName)
+											rHandler.addReagentProperty(rID, namePropID, newName)
+										else:
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["name"])
+											rHandler.addReagentProperty(rID, namePropID, newName)
+										
+										if form.has_key("newVectorType"):
+											newVectorType = form.getvalue("newVectorType")
+											rHandler.deleteReagentProperty(rID, vTypePropID)
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["vector type"])
+											#rHandler.addReagentProperty(rID, prop_Name_ID_Map["vector type"], newVectorType)
+											rHandler.addReagentProperty(rID, vTypePropID, newVectorType)
+										else:
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["vector type"])
+											rHandler.deleteReagentProperty(rID, vTypePropID)
+										
+										if form.has_key("newProjectID"):
+											newProjectID = form.getvalue("newProjectID")
+										
+											# Update July 2/09: pass projectPropID to changePropertyValue() function in combination with its category
+											rHandler.changePropertyValue(rID, projectPropID, newProjectID)
+										else:
+											rHandler.deleteReagentProperty(rID, projectPropID)
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["project id"])
+										
+										if form.has_key("newDescription"):
+											newDescription = form.getvalue("newDescription")
+											rHandler.deleteReagentProperty(rID, descrPropID)
+											rHandler.addComment(rID, descrPropID, newDescription)
+										else:
+											rHandler.deleteReagentProperty(rID, descrPropID)
+											
+											#rHandler.deleteReagentProperty(rID, prop_Name_ID_Map["description"])
+										
+										if form.has_key("newVerification"):
+											newVerification = form.getvalue("newVerification")
+											rHandler.deleteReagentProperty(rID, verifPropID)
+											rHandler.addReagentProperty(rID, verifPropID, newVerification)
+										else:
+											rHandler.deleteReagentProperty(rID, verifPropID)
+										
+										print "Content-type:text/html"
+										print
+										print "0"
+										return
+										
+									else:
+										#err = 13
+										
+										# Modified Feb. 12/09
+										i = EmptyCloningSitesException("")
+										err = i.err_code()
+										
+										print "Content-type:text/html"
+										print
+										print `err`
+										return
+							
+							except InsertSitesException:
+								i = InsertSitesException("Wrong sites on Insert")
+								
+								print "Content-type:text/html"
+								print
+								print `i.err_code()`
+								return
+							
+							except InsertSitesNotFoundOnParentSequenceException:
+								i = InsertSitesNotFoundOnParentSequenceException("Insert sites not found on parent vector sequence")
+								
+								print "Content-type:text/html"
+								print
+								print `i.err_code()`
+								return
+							
+							except MultipleSiteOccurrenceException:
+								i = MultipleSiteOccurrenceException("Site found more than once on parent vector sequence")
+								
+								print "Content-type:text/html"
+								print
+								print `i.err_code()`
+								return
+								
+							except HybridizationException:
+								i = HybridizationException("Sites cannot be hybridized")
+								
+								print "Content-type:text/html"
+								print
+								print `i.err_code()`
+								return
+							
+							except FivePrimeAfterThreePrimeException:
+								i = FivePrimeAfterThreePrimeException("5' site occurs after 3' site on parent vector sequence")
+								
+								print "Content-type:text/html"
+								print
+								print `i.err_code()`
+								return
+							
+							except InvalidDonorVectorSitesNotFoundException:
+								i = InvalidDonorVectorSitesNotFoundException("LoxP sites not found on donor sequence")
+						
+								print "Content-type:text/html"
+								print
+								print `i.err_code()`
+								return
+							
+							except InvalidDonorVectorMultipleSitesException:
+								i = InvalidDonorVectorMultipleSitesException("LoxP sites occur more than twice on donor sequence")
+							
+								print "Content-type:text/html"
+								print
+								print `i.err_code()`
+								return
+							
+							except InvalidDonorVectorSingleSiteException:
+								i = InvalidDonorVectorSingleSiteException("Donor vector sequence contains a singe LoxP site")
+								
+								print "Content-type:text/html"
+								print
+								print `i.err_code()`
+								return
+							
+							# Dec. 14/09
+							except EmptyParentVectorSequenceException:
+								i = EmptyParentVectorSequenceException("The sequence of the parent Vector provided is empty.")
+								err = i.err_code()
+							
+								print "Content-type:text/html"
+								print
+								print "Error: " + i.toString() + " Please verify your input."
+								return
+							
+							# Dec. 14/09
+							except EmptyParentInsertSequenceException:
+								i = EmptyParentInsertSequenceException("The sequence of the parent Insert provided is empty.")
+								err = i.err_code()
+							
+								print "Content-type:text/html"
+								print
+								print "Error: " + i.toString() + " Please verify your input."
+								return
+							
+							# Dec. 14/09
+							except EmptyInsertParentVectorSequenceException:
+								i = EmptyInsertParentVectorSequenceException("The sequence of the Insert Parent Vector provided is empty.")
+								err = i.err_code()
+							
+								print "Content-type:text/html"
+								print
+								print "Error: " + i.toString() + " Please verify your input."
+								return
+
+				elif cloning_method == '2':
+					
+					# Get association property IDs here
+					pvAssocProp = aHandler.findAssocPropID("vector parent id")
+					ipvAssocProp = aHandler.findAssocPropID("parent insert vector")
+					insertAssocProp = aHandler.findAssocPropID("insert id")
+					
+					# get IPV
+					if oldAssoc.has_key("parent insert vector"):
+						oldIPVID = oldAssoc["parent insert vector"]
+					else:
+						oldIPVID = -1
+					
+					# Modified July 13/08
+					isGateway = False
+					
+					if form.has_key("IPV"):
+						ipvID = form.getvalue("IPV")			# added July 13/08
+						
+						if len(ipvID) > 0:
+							ipv_db_id = rHandler.convertReagentToDatabaseID(ipvID)
+							
+							try:
+								ipvProjectID = int(rHandler.findSimplePropertyValue(ipv_db_id, packetPropID))	# need to cast
+								
+							except TypeError:
+								i = PVProjectAccessException("Invalid Insert Parent Vector project ID")
+							
+								print "Content-type:text/html"
+								print
+								print `i.err_code()`
+								return
+
+							if currUser.getCategory() != 'Admin' and pvProjectID not in uPackets:
+								i = PVProjectAccessException("You do not have read access to this project")
+						
+								print "Content-type:text/html"
+								print
+								print `i.err_code()`
+								return
+								
+							if currUser.getCategory() != 'Admin' and ipvProjectID not in uPackets:
+								i = IPVProjectAccessException("You do not have read access to this project")
+						
+								print "Content-type:text/html"
+								print
+								print `i.err_code()`
+								return
+								
+							# A recombination clone can be either a Creator Expression Vector or a Gateway Expression Clone.
+							
+							# get IPV sequence
+							ipvSeqKey = rHandler.findDNASequenceKey(ipv_db_id)
+							ipvSeq = dnaHandler.findSequenceByID(ipvSeqKey).strip().upper()
+							
+							# Get the Insert that belongs to the donor vector
+							ipvInsertAssocID = raHandler.findReagentAssociationID(ipv_db_id)
+							insertAssocPropID = aHandler.findAssocPropID("insert id")
+							insertID = aHandler.findAssocPropValue(ipvInsertAssocID, insertAssocPropID)
+
+							# comment Dec. 6/10: what if there is no insert???  Dec. 7/10, Karen: lift off this restriction
+							## get Insert sequence						# removed Dec. 7/10
+							#insertSeqKey = rHandler.findDNASequenceKey(insertID)		# removed Dec. 7/10
+							#insertSeq = dnaHandler.findSequenceByID(insertSeqKey)		# removed Dec. 7/10
+							
+							# get sites from INSERT PARENT VECTOR
+							# (keep names since reusing code but in fact these are IPV sites, NOT Insert)
+							insertCloningSites = []
+	
+							# get linkers if there are any
+							insertLinkers = []
+						
+							# Update July 2/09
+							fpLinkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["5' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+							tpLinkerPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["3' linker"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+
+							#fpLinkerPropID = prop_Name_ID_Map["5' linker"]		# removed July 2/09
+							#tpLinkerPropID = prop_Name_ID_Map["3' linker"]		# removed July 2/09
+							
+							fp_insert_linker = rHandler.findSimplePropertyValue(insertID, fpLinkerPropID)
+							tp_insert_linker = rHandler.findSimplePropertyValue(insertID, tpLinkerPropID)
+							
+							# sept. 3/07 - needed to cast to string
+							fwd_linker = ""
+						
+							if fp_insert_linker and len(fp_insert_linker) > 0 and fp_insert_linker != 0 and fp_insert_linker != '0':
+								fp_insert_linker = fwd_linker + fp_insert_linker
+							else:
+								fp_insert_linker = fwd_linker
+								
+							# April 24/08
+							if not tp_insert_linker or len(tp_insert_linker) == 0 or tp_insert_linker == 0 or tp_insert_linker == '0':
+								tp_insert_linker = ""
+								
+							insertLinkers.append(fp_insert_linker)
+							insertLinkers.append(tp_insert_linker)
+							
+							fp_linker_start = rHandler.findReagentFeatureStart(insertID, fpLinkerPropID)
+							fp_linker_end = rHandler.findReagentFeatureEnd(insertID, fpLinkerPropID)
+							
+							tp_linker_start = rHandler.findReagentFeatureStart(insertID, tpLinkerPropID)
+							tp_linker_end = rHandler.findReagentFeatureEnd(insertID, tpLinkerPropID)
+						
+							# Don't go by cloning sites, just try to construct sequences
+							# Creator Expression Vector
+							# Check that LoxP occurs exactly twice on IPV sequence
+							loxp_seq = enzDict["LoxP"]
+							
+							numLoxp = utils.numOccurs(ipvSeq.lower(), loxp_seq.lower())
+							
+							if numLoxp == 0 or numLoxp == 1 or numLoxp > 2:
+								
+								# This might be a gateway expression vector
+								fp_insert_cs = 'attB1'
+								tp_insert_cs = 'attB2'
+								
+								fpSite = 'gtacaaaaaa'
+								tpSite = 'tttcttgtac'
+								
+								try:
+									newSeq = dnaHandler.expressionVectorSequence(pvSeqID, ipvSeq)
+									newSeqID = int(dnaHandler.matchSequence(newSeq))
+									
+									if newSeqID <= 0:
+										newSeqID = int(dnaHandler.insertSequence(newSeq))
+									
+									rHandler.deleteReagentProperty(rID, seqPropID)
+									rHandler.addReagentProperty(rID, seqPropID, newSeqID)
+	
+									# Remap features
+									newSeq = utils.squeeze(newSeq)
+								
+									# Delete old features first
+									rHandler.deleteReagentFeatures(rID)
+									
+									# cDNA
+									# CHANGE DEC. 6, 2010: SAME ERROR KAREN DISCOVERED AT CREATION: DO **NOT** MAP CDNA FROM INSERT!!!! IT SHOULD BE MAPPED FROM ENTRY CLONE
+									#insert_cdnaStart = iHandler.findCDNAStart(insertID)
+									#insert_cdnaEnd = iHandler.findCDNAEnd(insertID)
+									
+									# keep 'insert' in the name for consistency though
+									cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+									
+									insert_cdnaStart = rHandler.findReagentFeatureStart(ipv_db_id, cdnaPropID)
+									insert_cdnaEnd = rHandler.findReagentFeatureEnd(ipv_db_id, cdnaPropID)
+									
+									#print "start " + `insert_cdnaStart` + ", print " + `insert_cdnaEnd`
+	
+									# NO!!!!!!! DEC. 6/10: GET CDNA FROM ENTRY VECTOR!!!!
+									if insert_cdnaStart > 0 and insert_cdnaEnd > 0:
+										#cdnaSeq = insertSeq[insert_cdnaStart-1:insert_cdnaEnd]
+										cdnaSeq = ipvSeq[insert_cdnaStart-1:insert_cdnaEnd]
+										
+										# moved this code up here too
+										if newSeq.lower().find(cdnaSeq.lower()) >= 0:
+										
+											cdnaStart = newSeq.lower().find(cdnaSeq.lower()) + 1
+											cdnaEnd = cdnaStart + len(cdnaSeq) - 1
+										else:
+											cdnaStart = 0
+											cdnaEnd = 0
+
+									else:
+										# now not sure what to do here, check with Karen tomorrow
+										#cdnaSeq = insertSeq
+										cdnaSeq = ""	# temporary, probably wrong
+	
+									# commented out on Dec. 6, 2010
+									#if newSeq.lower().find(cdnaSeq.lower()) >= 0:
+										#cdnaStart = newSeq.lower().find(cdnaSeq) + 1
+										#cdnaEnd = cdnaStart + len(cdnaSeq) - 1
+									#else:
+										cdnaStart = 0
+										cdnaEnd = 0
+
+									# July 2/09
+									#cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+									rHandler.setPropertyPosition(rID, cdnaPropID, "startPos", cdnaStart)
+									rHandler.setPropertyPosition(rID, cdnaPropID, "endPos", cdnaEnd)
+						
+									fpStartPos = newSeq.lower().find(fpSite) + 1
+									fpEndPos = fpStartPos + len(fpSite)
+									
+									tpStartPos = newSeq.lower().find(tpSite) + 1
+									tpEndPos = tpStartPos + len(tpSite)
+									
+									rHandler.addReagentProperty(rID, fpcs_prop_id, "attB1", fpStartPos, fpEndPos-1)
+									rHandler.addReagentProperty(rID, tpcs_prop_id, "attB2", tpStartPos, tpEndPos-1)
+									
+									ipvFeatures = rHandler.findReagentSequenceFeatures(ipv_db_id)
+									pvFeatures = rHandler.findReagentSequenceFeatures(pvID)
+										
+									# Parent Vector features are found before cDNA start and after cDNA end on the new sequence
+									for f in pvFeatures:
+										fType = f.getFeatureType()
+										#print fType
+										
+										if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+										
+											# original feature positions on PV sequence
+											pv_fStart = f.getFeatureStartPos()
+											pv_fEnd = f.getFeatureEndPos()
+										
+											fVal = f.getFeatureName()
+											#print fVal
+											pv_fDir = f.getFeatureDirection()
+											
+											#print pv_fDir
+											
+											if pv_fStart > 0 and pv_fEnd > 0:
+												
+												# Features from PV are inherited IFF they are located **entirely** before the 5' cloning site or after 3' cloning site
+												# Hence: May 22/08 - Find 5' start and 3' end on **original** PV sequence
+												pv_fpcs_start = pvSequence.lower().find(fpSite)
+												pv_tpcs_end = pvSequence.lower().find(tpSite) + len(tpSite)
+												
+												fSeq = pvSequence[pv_fStart-1:pv_fEnd].lower()
+								
+												# June 4/08 - Search for the feature IFF > 10 nts
+												if len(fSeq) >= 10:
+								
+													# Look for this feature on the NEWly reconstituted Vector
+													fIndex = newSeq.lower().find(fSeq)
+								
+													if fIndex >= 0:
+														fpStart = fIndex + 1
+														fpEnd = fpStart + len(fSeq) - 1
+														
+														#print "start " + `fpStart`
+														#print "end " + `fpEnd`
+								
+														# If found, make sure this feature occurs either before or after the cDNA
+														if (fpStart < fpStartPos and fpEnd < fpStartPos) or (fpStart >= tpEndPos and fpEnd > tpEndPos):
+															
+															# June 9/08: Orientation
+															fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+										
+															rHandler.addReagentProperty(rID, fID, fVal, fpStart, fpEnd, pv_fDir)
+												
+															if f.getFeatureDescrType():
+																fDescr = f.getFeatureDescrName()
+																#print fVal
+																#print fDescr
+																
+																# Updated July 2/09
+																#fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+																rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fpStart, fpEnd, fDescr)
+											
+									# Search for each Insert feature on the new sequence
+									# June 6/08: Added 'if' statement - needs testing
+									for f in ipvFeatures:
+										fType = f.getFeatureType()
+										#print fType
+										
+										if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+											# feature positions on the Insert sequence - Modified May 21/08: Account for the fact that NOT the entire Insert sequence is used, only a subsequence
+											fiStart = f.getFeatureStartPos()
+											fiEnd = f.getFeatureEndPos()
+											fVal = f.getFeatureName()
+											#print fVal
+											
+											#fSeq = cdnaSeq[fiStart:fiEnd].lower()	# NO!!!!
+											
+											fSeq = ipvSeq[fiStart:fiEnd].lower()
+										
+											if len(fSeq) >= 10:
+												fStart = newSeq.lower().find(fSeq)
+												fEnd = fStart + len(fSeq)
+											
+												if fStart >= 1:
+								
+													# May 22/08: NO!!! This is precisely what we decided we're NOT going to do!!!
+													'''
+													## recompute based on cDNA start
+													#fiStart = fiStart - insert_cdnaStart
+													#fiEnd = fiEnd - insert_cdnaStart
+													
+													# feature positions on the new Vector sequence
+													#fStart = cdnaStart + fiStart
+													#fEnd = fStart + len(fSeq)
+													'''
+													
+													# still, double check to make sure this feature occurs between cloning sites on resulting Vector sequence
+													if fStart >= fpEndPos and fEnd <= tpStartPos:
+														
+														# June 9/08: Orientation
+														fiDir = f.getFeatureDirection()
+														fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+														
+														rHandler.addReagentProperty(rID, fID, fVal, fStart, fEnd, fiDir)
+													
+														if f.getFeatureDescrType():
+															fDescr = f.getFeatureDescrType()
+															
+															# Updated July 2/09
+															#fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+															rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fStart, fEnd, fDescr)
+								
+									# Now save parents - delete all previous information
+									rAssocID = raHandler.findReagentAssociationID(rID)
+									
+									rHandler.deleteReagentAssociationProp(rID, pvAssocProp)
+									rHandler.addAssociationValue(rID, pvAssocProp, pvID, rAssocID)
+				
+									rHandler.deleteReagentAssociationProp(rID, ipvAssocProp)
+									rHandler.addAssociationValue(rID, ipvAssocProp, ipv_db_id, rAssocID)
+								
+									# Finally: July 8/08: Update Vector details: name, type, description, project ID, verification
+									
+									#print "Content-type:text/html"
+									#print
+									#print `form`
+									
+									if form.has_key("newVectorName"):
+										newName = form.getvalue("newVectorName")
+										rHandler.deleteReagentProperty(rID, namePropID)
+										rHandler.addReagentProperty(rID, namePropID, newName)
+									else:
+										rHandler.deleteReagentProperty(rID, namePropID)
+									
+									if form.has_key("newVectorType"):
+										newVectorType = form.getvalue("newVectorType")
+										rHandler.deleteReagentProperty(rID, vTypePropID)
+										rHandler.addReagentProperty(rID, vTypePropID, newVectorType)
+									else:
+										rHandler.deleteReagentProperty(rID, vTypePropID)
+									
+									if form.has_key("newProjectID"):
+										newProjectID = form.getvalue("newProjectID")
+										rHandler.changePropertyValue(rID, projectPropID, newProjectID)
+									else:
+										rHandler.deleteReagentProperty(rID, projectPropID)
+									
+									if form.has_key("newDescription"):
+										newDescription = form.getvalue("newDescription")
+										rHandler.deleteReagentProperty(rID, descrPropID)
+										rHandler.addComment(rID, descrPropID, newDescription)
+									else:
+										rHandler.deleteReagentProperty(rID, descrPropID)
+									
+									if form.has_key("newVerification"):
+										newVerification = form.getvalue("newVerification")
+										rHandler.deleteReagentProperty(rID, verifPropID)
+										rHandler.addReagentProperty(rID, verifPropID, newVerification)
+									else:
+										rHandler.deleteReagentProperty(rID, verifPropID)
+									
+									print "Content-type:text/html"
+									print
+									print "0"
+									return
+								
+								# removed dec. 7/10: why twice??
+								#except InsertSitesNotFoundOnParentSequenceException:
+									#i = InsertSitesNotFoundOnParentSequenceException("")
+									#print "Content-type:text/html"
+									#print
+									#print `i.err_code()`
+									#return
+									
+								except MultipleSiteOccurrenceException:
+									i = MultipleSiteOccurrenceException("")
+									print "Content-type:text/html"
+									print
+									print `i.err_code()`
+									return
+									
+								except InsertSitesNotFoundOnParentSequenceException:
+									i = InsertSitesNotFoundOnParentSequenceException("")
+									print "Content-type:text/html"
+									print
+									print `i.err_code()`
+									return
+									
+								except MultipleSiteOccurrenceException:
+									i = MultipleSiteOccurrenceException("")
+									print "Content-type:text/html"
+									print
+									print `i.err_code()`
+									return
+									
+								# Dec. 14/09
+								except EmptyParentVectorSequenceException:
+									i = EmptyParentVectorSequenceException("The sequence of the parent Vector provided is empty.")
+									err = i.err_code()
+								
+									print "Content-type:text/html"
+									print
+									print "Error: " + i.toString() + " Please verify your input."
+									return
+								
+								# Dec. 14/09
+								except EmptyParentInsertSequenceException:
+									i = EmptyParentInsertSequenceException("The sequence of the parent Insert provided is empty.")
+									err = i.err_code()
+								
+									print "Content-type:text/html"
+									print
+									print "Error: " + i.toString() + " Please verify your input."
+									return
+								
+								# Dec. 14/09
+								except EmptyInsertParentVectorSequenceException:
+									i = EmptyInsertParentVectorSequenceException("The sequence of the Insert Parent Vector provided is empty.")
+									err = i.err_code()
+								
+									print "Content-type:text/html"
+									print
+									print "Error: " + i.toString() + " Please verify your input."
+									return
+
+							else:
+								try:
+									newSeq = dnaHandler.constructRecombSequence(pvSeqID, ipvSeqKey)
+								
+								except MultipleSiteOccurrenceException:
+									i = MultipleSiteOccurrenceException("")
+									print "Content-type:text/html"
+									print
+									print `i.err_code()`
+									return
+								
+								# Dec. 14/09
+								except EmptyParentVectorSequenceException:
+									i = EmptyParentVectorSequenceException("The sequence of the parent Vector provided is empty.")
+									err = i.err_code()
+								
+									print "Content-type:text/html"
+									print
+									print "Error: " + i.toString() + " Please verify your input."
+									return
+								
+								# Dec. 14/09
+								except EmptyParentInsertSequenceException:
+									i = EmptyParentInsertSequenceException("The sequence of the parent Insert provided is empty.")
+									err = i.err_code()
+								
+									print "Content-type:text/html"
+									print
+									print "Error: " + i.toString() + " Please verify your input."
+									return
+								
+								# Dec. 14/09
+								except EmptyInsertParentVectorSequenceException:
+									i = EmptyInsertParentVectorSequenceException("The sequence of the Insert Parent Vector provided is empty.")
+									err = i.err_code()
+								
+									print "Content-type:text/html"
+									print
+									print "Error: " + i.toString() + " Please verify your input."
+									return
+	
+								# added Dec. 7, 2010	
+								except InsertSitesNotFoundOnParentSequenceException:
+									i = InsertSitesNotFoundOnParentSequenceException("")
+									print "Content-type:text/html"
+									print
+									print `i.err_code()`
+									return
+									
+								fpSite = loxp_seq
+								tpSite = loxp_seq
+								
+								newSeqID = int(dnaHandler.matchSequence(newSeq))
+								
+								if newSeqID <= 0:
+									newSeqID = int(dnaHandler.insertSequence(newSeq))
+								
+								rHandler.deleteReagentProperty(rID, seqPropID)
+								rHandler.addReagentProperty(rID, seqPropID, newSeqID)
+
+								# Remap features
+								newSeq = utils.squeeze(newSeq)
+							
+								# Delete old features first
+								rHandler.deleteReagentFeatures(rID)
+								
+								# cDNA
+								# Update Dec. 7, 2010: don't map cDNA boundaries from Insert, get them from IPV
+								cdnaPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+
+								insert_cdnaStart = rHandler.findReagentFeatureStart(ipv_db_id, cdnaPropID)
+								insert_cdnaEnd = rHandler.findReagentFeatureEnd(ipv_db_id, cdnaPropID)
+							
+								#insert_cdnaStart = iHandler.findCDNAStart(insertID)
+								#insert_cdnaEnd = iHandler.findCDNAEnd(insertID)
+
+								if insert_cdnaStart > 0 and insert_cdnaEnd > 0:
+									# update Dec. 7/10
+									#cdnaSeq = insertSeq[insert_cdnaStart-1:insert_cdnaEnd]		# removed Dec. 7/10
+									cdnaSeq = ipvSeq[insert_cdnaStart-1:insert_cdnaEnd]		# replaced dec. 7/10
+
+									# moved this code up here too
+									if newSeq.lower().find(cdnaSeq.lower()) >= 0:
+										cdnaStart = newSeq.lower().find(cdnaSeq.lower()) + 1
+										cdnaEnd = cdnaStart + len(cdnaSeq) - 1
+									else:
+										cdnaStart = 0
+										cdnaEnd = 0
+									
+								else:
+									#cdnaSeq = insertSeq	# rmvd dec 7/10
+									cdnaSeq = ""		# replaced dec 7/10
+									
+								# commented out on Dec. 7, 2010
+								#if newSeq.lower().find(cdnaSeq.lower()) >= 0:
+									#cdnaStart = newSeq.lower().find(cdnaSeq) + 1
+									#cdnaEnd = cdnaStart + len(cdnaSeq) - 1
+								#else:
+									cdnaStart = 0
+									cdnaEnd = 0
+								
+								# July 2/09
+								rHandler.setPropertyPosition(rID, cdnaPropID, "startPos", cdnaStart)
+								rHandler.setPropertyPosition(rID, cdnaPropID, "endPos", cdnaEnd)
+					
+								fpStartPos = newSeq.lower().find(fpSite.lower()) + 1
+								fpEndPos = fpStartPos + len(fpSite.lower())
+								
+								tpStartPos = newSeq.lower().rfind(tpSite.lower()) + 1
+								tpEndPos = tpStartPos + len(tpSite.lower())
+								
+								rHandler.addReagentProperty(rID, fpcs_prop_id, "LoxP", fpStartPos, fpEndPos-1)
+								
+								#rHandler.deleteReagentProperty(rID, tpcs_prop_id)
+								rHandler.addReagentProperty(rID, tpcs_prop_id, "LoxP", tpStartPos, tpEndPos-1)
+								
+								# April 17/08: Map the rest of the features
+								ipvFeatures = rHandler.findReagentSequenceFeatures(ipv_db_id)
+								pvFeatures = rHandler.findReagentSequenceFeatures(pvID)
+								
+								# changes made Oct. 14/08
+								tmp_dict = {}
+								
+								# Parent Vector features are found before cDNA start and after cDNA end on the new sequence
+								for f in pvFeatures:
+									fType = f.getFeatureType()
+									
+									if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+									
+										# original feature positions on PV sequence
+										pv_fStart = f.getFeatureStartPos()
+										pv_fEnd = f.getFeatureEndPos()
+										
+										fSeq = pvSequence[pv_fStart-1:pv_fEnd].lower()
+										tmp_dict[fSeq] = f
+									
+								for fSeq in tmp_dict.keys():
+									f_tmp = tmp_dict[fSeq]
+									
+									if len(fSeq) >= 10:
+										#print f_tmp.getFeatureName()
+						
+										fList = utils.findall(newSeq.lower(), fSeq, [])
+										#print `fList`
+										
+										for fIndex in fList:
+											fpStart = fIndex + 1
+											fpEnd = fpStart + len(fSeq) - 1
+											
+											if fpStart > 0 and fpEnd > 0:
+												
+												fType = f_tmp.getFeatureType()
+												fVal =  f_tmp.getFeatureName()
+												#print fVal
+												pv_fDir = f_tmp.getFeatureDirection()
+										
+												# Nov. 4/08: In recombination vectors there's only one LoxP occurrence on the parent and it should be transferred onto the child as a restriction site; rest of features are all inherited.  So remove the site position check; don't replace it with check for a single LoxP site occurrence yet, see how it goes.
+												
+												# removed Nov. 6/08
+												##If found, make sure this feature occurs either before or after the CLONING SITES!!!!!!!!
+												#if (fpStart < fpStartPos and fpEnd < fpStartPos) or (fpStart >= tpEndPos and fpEnd > tpEndPos):
+													#print fType + ": " + fVal + ": " + `fpStart` + "-" + `fpEnd`
+										
+												fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+												
+												rHandler.addReagentProperty(rID, fID, fVal, fpStart, fpEnd, pv_fDir)
+										
+												if f_tmp.getFeatureDescrType():
+													fDescr = f_tmp.getFeatureDescrName()
+													#print fDescr
+										
+													# Updated July 2/09
+													rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fpStart, fpEnd, fDescr)
+						
+								# IPV features
+								tmp_ipv_dict = {}
+									
+								for f in ipvFeatures:
+									fType = f.getFeatureType()
+									#print fType
+									
+									if fType.lower() != "5' cloning site" and fType.lower() != "3' cloning site" and fType.lower() != "cdna insert":
+										# feature positions on the Insert sequence - Modified May 21/08: Account for the fact that NOT the entire Insert sequence is used, only a subsequence
+										fiStart = f.getFeatureStartPos()
+										fiEnd = f.getFeatureEndPos()
+										#fVal = f.getFeatureName()
+										#print fVal
+										fSeq = ipvSeq[fiStart:fiEnd].lower()
+										tmp_ipv_dict[fSeq] = f
+									
+								for fSeq in tmp_ipv_dict.keys():
+									f_tmp = tmp_ipv_dict[fSeq]
+									#print f_tmp.getFeatureName()
+						
+									if len(fSeq) >= 10:
+										fList = utils.findall(newSeq.lower(), fSeq, [])
+										#print `fList`
+						
+										for fIndex in fList:
+											fStart = newSeq.lower().find(fSeq)
+											#print "start " + `fStart`
+											fEnd = fStart + len(fSeq)
+											#print "end  " + `fEnd`
+											
+											# still, double check to make sure this feature occurs between Insert cDNA start and end on resulting Vector sequence
+											#print "cdna start " + `cdnaStart`
+											#print "cdna end " + `cdnaEnd`
+						
+											# features must be between the cloning sites - this check remains!!!
+											if fStart > fpEndPos and fEnd < tpEndPos:
+												fType = f_tmp.getFeatureType()
+												fVal =  f_tmp.getFeatureName()
+												fiDir = f_tmp.getFeatureDirection()
+												#print fType + ": " + fVal + ": " + `fStart` + "-" + `fEnd`
+										
+												fID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[fType], prop_Category_Name_ID_Map["DNA Sequence Features"])
+											
+												rHandler.addReagentProperty(rID, fID, fVal, fStart, fEnd, fiDir)
+											
+												if f.getFeatureDescrType():
+													fDescr = f_tmp.getFeatureDescrType()
+													#print fDescr
+										
+													# Updated Sept. 2/08
+										
+													# Updated July 2/09
+
+													# removed July 2/09 - why twice??
+													#rHandler.setReagentFeatureDescriptor(rID, prop_Name_ID_Map[fType], fVal, fDescr)
+										
+													rHandler.setReagentFeatureDescriptor(rID, fID, fVal, fStart, fEnd, fDescr)
+									
+								# Now save parents - delete all previous information
+								rAssocID = raHandler.findReagentAssociationID(rID)
+								
+								rHandler.deleteReagentAssociationProp(rID, pvAssocProp)
+								rHandler.addAssociationValue(rID, pvAssocProp, pvID, rAssocID)
+			
+								rHandler.deleteReagentAssociationProp(rID, ipvAssocProp)
+								rHandler.addAssociationValue(rID, ipvAssocProp, ipv_db_id, rAssocID)
+							
+								# Finally: July 8/08: Update Vector details: name, type, description, project ID, verification
+								
+								#print "Content-type:text/html"
+								#print
+								#print `form`
+									
+								if form.has_key("newVectorName"):
+									newName = form.getvalue("newVectorName")
+									rHandler.deleteReagentProperty(rID, namePropID)
+									rHandler.addReagentProperty(rID, namePropID, newName)
+								else:
+									rHandler.deleteReagentProperty(rID, namePropID)
+								
+								if form.has_key("newVectorType"):
+									newVectorType = form.getvalue("newVectorType")
+									rHandler.deleteReagentProperty(rID, vTypePropID)
+									rHandler.addReagentProperty(rID, vTypePropID, newVectorType)
+								else:
+									rHandler.deleteReagentProperty(rID, vTypePropID)
+								
+								if form.has_key("newProjectID"):
+									newProjectID = form.getvalue("newProjectID")
+									rHandler.changePropertyValue(rID, projectPropID, newProjectID)
+								else:
+									rHandler.deleteReagentProperty(rID, projectPropID)
+								
+								if form.has_key("newDescription"):
+									newDescription = form.getvalue("newDescription")
+									rHandler.deleteReagentProperty(rID, descrPropID)
+									rHandler.addComment(rID, descrPropID, newDescription)
+								else:
+									rHandler.deleteReagentProperty(rID, descrPropID)
+								
+								if form.has_key("newVerification"):
+									newVerification = form.getvalue("newVerification")
+									rHandler.deleteReagentProperty(rID, verifPropID)
+									rHandler.addReagentProperty(rID, verifPropID, newVerification)
+								else:
+									rHandler.deleteReagentProperty(rID, verifPropID)
+								
+								print "Content-type:text/html"
+								print
+								print "0"
+								return
+						else:
+							ipvSeqID = -1
+					else:
+						ipv_db_id = -1
+			
+			else:
+				rHandler.updateReagentAssociations(rID, assocPropsDict)
+				
+				# redirect to detailed view of the new reagent
+				utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+
+		# Aug. 13/09
+		elif section_to_save == prop_Category_Name_Alias_Map["Protein Sequence"]:
+			
+			#print "Content-type:text/html"
+			#print
+			#print `form`
+
+			# moved here April 10/08
+			newPropsDict_name = {}		# e.g. ('status', 'Completed')
+			newPropsDict_id = {}		# e.g. ('3', 'Completed') - db ID instead of property name
+			
+			protSeqCategoryID = prop_Category_Name_ID_Map["Protein Sequence"]
+
+			# CONVERT TO UPPERCASE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+			newSeq = form.getvalue(prefix + prop_Name_Alias_Map["protein sequence"] + postfix).upper()
+			#print newSeq
+			
+			# July 2/09: propertyID <= propCatID
+			seqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein sequence"], prop_Category_Name_ID_Map["Protein Sequence"])
+			
+			#print seqPropID 
+
+			newSeq = protHandler.squeeze(newSeq)
+			#print newSeq
+
+			newPropsDict_id[seqPropID] = newSeq
+			
+			# April 7/08: Recompute feature positions (do before calling 'update' to fetch previous sequence value)
+			# Grab the old sequence
+			oldSeqID = rHandler.findProteinSequenceKey(rID)
+			oldSeq = protHandler.findSequenceByID(oldSeqID)
+			#print oldSeqID
+			
+			# Update the rest of the features
+			if len(oldSeq) > 0:
+				rHandler.updateFeaturePositions(rID, oldSeq.lower(), newSeq.lower(), False, True)
+				
+				# No linkers for Protein
+							
+			# April 12, 2011: Get Tm from input
+			tmPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["melting temperature"], prop_Category_Name_ID_Map["Protein Sequence"])
+
+			if form.has_key(prefix + prop_Name_Alias_Map["melting temperature"] + postfix):
+				tm_prot = form.getvalue(prefix + prop_Name_Alias_Map["melting temperature"] + postfix)
+				#print tm_prot
+				newPropsDict_id[tmPropID] = tm_prot
+
+			# MW is autocomputed for protein - May 9, 2011: done in reagent_handler.py, removed code here
+			
+			# No sites for Protein either
+
+			# rest of Protein sequence properties
+			
+			for sKey in form.keys():
+				t1 = sKey[0:sKey.find(postfix)]
+				t2 = t1[len(prefix):]
+				
+				propAlias = t2
+				propVal = form.getlist(sKey)
+
+				if prop_Alias_ID_Map.has_key(propAlias) and propAlias != prop_Name_Alias_Map["protein sequence"]:
+					
+					propCatID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[propAlias], prop_Category_Name_ID_Map["Protein Sequence"])
+
+					rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, propCatID)
+
+					if len(propVal) > 1:
+						for pVal in propVal:
+							#print pVal
+
+							setGroupID = sHandler.findPropSetGroupID(propCatID)
+							ssetID = sHandler.findSetValueID(setGroupID, pVal)
+
+							if sHandler.findSetValueID(setGroupID, pVal) <= 0:
+								ssetID = sHandler.addSetValue(setGroupID, pVal)
+							
+							if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+								#print "Adding " + pVal
+								sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+					else:
+						pVal = propVal[0]
+						
+						if pVal.lower() == 'other':	
+							textBoxName = prefix + reagentType_ID_Name_Map[int(rTypeID)] + "_" + prop_Category_Name_Alias_Map["Protein Sequence"] + "_:_" + propAlias + "_name_txt"
+							
+							if form.has_key(textBoxName):
+								propVal = form.getvalue(textBoxName)
+
+								setGroupID = sHandler.findPropSetGroupID(propCatID)
+								ssetID = sHandler.findSetValueID(setGroupID, propVal)
+
+								# update set
+								if sHandler.findSetValueID(setGroupID, propVal) <= 0:
+									ssetID = sHandler.addSetValue(setGroupID, propVal)
+								
+								if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+									sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+
+					newPropsDict_id[propCatID] = propVal
+
+			#print `newPropsDict_id`
+
+			rHandler.updateReagentPropertiesInCategory(rID, protSeqCategoryID, newPropsDict_id)
+
+			# return to detailed view - Moved here July 7/08
+			utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+		
+		# Aug. 18/09
+		elif section_to_save == prop_Category_Name_Alias_Map["Protein Sequence Features"]:
+			
+			#print "Content-type:text/html"
+			#print
+			#print `form`
+			
+			# Save features - taken from 'preload.py'
+			# (deletion is performed in updateFeatures function, no need to call here)
+			newPropsDict_name = {}			# e.g. ('status', 'Completed')
+			newPropsDict_id = {}			# e.g. ('3', 'Completed') - db ID instead of property name
+			
+			startPosDict = {}			# (propID, startpos)
+			endPosDict = {}				# (propID, endpos)
+			
+			# Store orientation
+			orientationDict = {}			# (propID, orientation)
+			
+			# features too
+			rHandler.deleteReagentFeatures(rID, True)	# redo for protein
+			
+			# March 12/08: Treat properties with multiple values and start/end positions (a.k.a. features) as objects
+			seqFeatures = []
+	
+			featureCategoryID = prop_Category_Name_ID_Map["Protein Sequence Features"]
+			sequenceFeatures = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, featureCategoryID)
+			featureDescriptors = Reagent.getFeatureDescriptors()
+			
+			# Nov. 13/08: Get Insert sequence
+			#seqPropID = prop_Name_ID_Map["sequence"]
+			seqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protein sequence"], prop_Category_Name_ID_Map["Protein Sequence"])
+			seqID = rHandler.findIndexPropertyValue(rID, seqPropID)
+			insertSeq = dnaHandler.findSequenceByID(seqID).lower()
+			
+			# Removed May 16/08 - not a very good idea to delete all features, including sites and linkers - linkers may hinder modification but are necessary for correct feature remapping during Vector sequence reconstitution.  See what happens
+			#singleValueFeatures = reagent.getSingleFeatures()	# March 18/08 - Differentiate between features such as promoter or tag type, which could have multiple values, and cloning sites and linkers, which only have one value and one position
+			
+			#featureNames = sequenceFeatures + singleValueFeatures
+			
+			featureNames = sequenceFeatures
+			#print `featureNames`
+			
+			featureAliases = {}
+			features = {}
+		
+			for f in featureNames:
+				fAlias = prop_Name_Alias_Map[f]
+				#fPropID = prop_Name_ID_Map[f]
+				fPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[f], prop_Category_Name_ID_Map["Protein Sequence Features"])
+				
+				featureAliases[fAlias] = f
+				features[fPropID] = f
+			
+			#print `featureAliases`
+			#print `prop_Alias_Name_Map`
+		
+			for fAlias in featureAliases:
+				#print "alias " + fAlias
+			
+				tmpStart = -1
+				tmpEnd = -1
+				
+				#tmpPropName = prefix + fAlias + postfix
+				
+				featureType = "Protein Sequence Features"
+				
+				for tmpPropName in form.keys():
+					#print tmpPropName
+					#print fAlias
+					
+					fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map["Protein Sequence Features"])
+					
+					if tmpPropName.find(prefix + fAlias + "_:_") >= 0:
+						pValStartInd = len(prefix + fAlias)+3
+						#print pValStartInd
+						#pValStopInd = tmpPropName.find("_", pValStartInd)	# rmvd nov 1/09
+						pValStopInd = tmpPropName.rfind("_start_", pValStartInd)
+						#print pValStopInd
+						
+						# actual feature value
+						tmpPropValue = tmpPropName[pValStartInd:pValStopInd]
+						#print " feature " + tmpPropName
+						#print ", value " + tmpPropValue
+						
+						if tmpPropValue and len(tmpPropValue) > 0:
+							# get positions - changed oct. 25/08
+							
+							# Update Nov 3/09
+							#start_ind1 = tmpPropName.find(tmpPropValue) + len(tmpPropValue) + len("_start_")
+							
+							start_ind1 = tmpPropName.rfind("_start_") + len("_start_")
+							start_ind2 = tmpPropName.find("_end_")
+							#print start_ind2
+	
+							tmpStart = tmpPropName[start_ind1:start_ind2]
+							#print "start " + tmpStart
+							
+							if tmpStart and len(tmpStart) > 0 and int(tmpStart) > 0:
+								end_ind_1 = start_ind2 + len("_end_")
+								#print end_ind_1
+								end_ind_2 = tmpPropName.find("_", end_ind_1)
+								#print end_ind_2
+		
+								tmpEnd = tmpPropName[end_ind_1:end_ind_2]
+								#print "end " + tmpEnd
+								
+								if tmpEnd and len(tmpEnd) > 0 and int(tmpEnd) > 0:
+									tmpDirName = prefix + fAlias + "_:_" + tmpPropValue + "_start_" + `int(tmpStart)` + "_end_" + `int(tmpEnd)` + "_orientation" + postfix
+									#print tmpDirName
+									
+									if form.has_key(tmpDirName):
+										tmpDir = form.getvalue(tmpDirName)
+										#print "FOUND DIRECTION " + tmpDirName
+							
+										# Nov. 13/08: If there are duplicates, select one
+										if utils.isList(tmpDir):
+											#print "Descriptor " + tmpDescr
+											tmpDir = tmpDir[0]
+							
+										#fID = prop_Alias_ID_Map[fAlias]
+										fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map[featureType])
+										
+										# June 8, 2010: Update set
+										rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, fID)
+									
+										#print fAlias
+										#print rTypeAttributeID
+										
+										# update Nov. 18/09
+										setGroupID = sHandler.findPropSetGroupID(fID)	# it must exist
+									
+										#sHandler.updateSet(rTypeAttributeID, rType + " " + propName, newSetEntry)
+										ssetID = sHandler.findSetValueID(setGroupID, tmpPropValue)
+										
+										if ssetID <= 0:
+											ssetID = sHandler.addSetValue(setGroupID, tmpPropValue)
+									
+										#print ssetID
+										#print rTypeAttributeID
+										
+										if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+											sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+										
+										# descriptor
+										if featureDescriptors.has_key(prop_Alias_Name_Map[fAlias]):
+											tmpDescrName = featureDescriptors[prop_Alias_Name_Map[fAlias]]
+											tmpDescrAlias = prop_Name_Alias_Map[tmpDescrName]
+											#print "DESCRIPTOR " + tmpDescrAlias
+									
+											tmpDescrID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[tmpDescrName], prop_Category_Name_ID_Map["Protein Sequence Features"])
+										
+											tmpDescrField = prefix + tmpDescrAlias + "_:_" + tmpPropValue + "_start_" + tmpStart + "_end_" + tmpEnd + postfix
+
+											#print tmpDescrField
+											
+											if form.has_key(tmpDescrField):
+												#print "?????????"
+									
+												tmpDescr = form.getvalue(tmpDescrField)
+									
+												# Nov. 13/08: If there are duplicates, select one
+												if utils.isList(tmpDescr):
+													#print "Descriptor " + tmpDescr
+													tmpDescr = tmpDescr[0]
+										
+												# June 8, 2010: For descriptor have to go to textbox to fetch Other values
+												if tmpDescr.lower() == 'other':
+													
+													if fAlias == "tag":
+														descrAlias = "tag_position"
+													elif fAlias == "promoter":
+														descrAlias = "expression_system"
+										
+													tmpDescr_text = prefix + tmpDescrAlias + "_:_" + tmpPropValue + "_start_" + tmpStart + "_end_" + tmpEnd + "_name_txt"
+										
+													#print tmpDescr_text
+										
+													tmpDescr = form.getvalue(tmpDescr_text)
+										
+													#print "SAVING OTHER " + `tmpDescr`
+										
+												if utils.isList(tmpDescr):
+													tmpDescr = tmpDescr[0]
+													#print tmpDescr
+									
+												newSetEntry = tmpDescr
+										
+												#print newSetEntry
+		
+												# invoke handler to add textbox value to dropdown list
+												rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, tmpDescrID)
+										
+												#print tmpDescrID
+												#print rTypeAttributeID
+												
+												# update Nov. 18/09
+												setGroupID = sHandler.findPropSetGroupID(tmpDescrID)
+										
+												#print setGroupID
+												
+												ssetID = sHandler.findSetValueID(setGroupID, newSetEntry)
+												
+												if ssetID <= 0:
+													ssetID = sHandler.addSetValue(setGroupID, newSetEntry)
+										
+												#print ssetID
+												
+												if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+													sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+											else:
+												tmpDescr = ""
+										else:
+											tmpDescr = ""
+									
+										if not rHandler.existsPropertyValue(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDescr, tmpDir):
+											rHandler.addReagentProperty(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDir)
+											
+											rHandler.setReagentFeatureDescriptor(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDescr)
+									else:
+										pass
+								else:
+									pass
+							else:
+								pass
+						else:
+							pass
+					else:
+						pass
+		
+			# Match db IDs to property aliases
+			for tmpProp in newPropsDict_name.keys():
+				if prop_Alias_ID_Map.has_key(tmpProp):
+					# July 2/09: propertyID <= propCatID
+					#propID = prop_Alias_ID_Map[tmpProp]	# removed July 2/09
+					propID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[tmpProp], prop_Category_Name_ID_Map["Protein Sequence Features"])
+					newPropsDict_id[propID] = newPropsDict_name[tmpProp]
+			
+			seqID = rHandler.findDNASequenceKey(rID)
+			seq = dnaHandler.findSequenceByID(seqID)
+			
+			# June 16/08: Update protein translation
+			if rTypeID == '2':
+				iHandler.updateInsertProteinSequence(rID)
+			
+			# return to detailed view - Moved here July 7/08
+			utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+			
+		elif section_to_save == prop_Category_Name_Alias_Map["RNA Sequence Features"]:
+			
+			#print "Content-type:text/html"
+			#print
+			#print `form`
+
+			# Save features - taken from 'preload.py'
+			# (deletion is performed in updateFeatures function, no need to call here)
+			newPropsDict_name = {}			# e.g. ('status', 'Completed')
+			newPropsDict_id = {}			# e.g. ('3', 'Completed') - db ID instead of property name
+			
+			startPosDict = {}			# (propID, startpos)
+			endPosDict = {}				# (propID, endpos)
+			
+			# Store orientation
+			orientationDict = {}			# (propID, orientation)
+			
+			# features too
+			rHandler.deleteReagentFeatures(rID, False, True)
+			
+			# March 12/08: Treat properties with multiple values and start/end positions (a.k.a. features) as objects
+			seqFeatures = []
+	
+			featureCategoryID = prop_Category_Name_ID_Map["RNA Sequence Features"]
+			sequenceFeatures = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, featureCategoryID)
+			featureDescriptors = Reagent.getFeatureDescriptors()
+			
+			#print `featureDescriptors`
+			
+			# Nov. 13/08: Get Insert sequence
+			#seqPropID = prop_Name_ID_Map["sequence"]
+			seqPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["rna sequence"], prop_Category_Name_ID_Map["RNA Sequence"])
+			seqID = rHandler.findIndexPropertyValue(rID, seqPropID)
+			insertSeq = dnaHandler.findSequenceByID(seqID).lower()
+			
+			featureType = "rna_sequence_features"
+			
+			# Removed May 16/08 - not a very good idea to delete all features, including sites and linkers - linkers may hinder modification but are necessary for correct feature remapping during Vector sequence reconstitution.  See what happens
+			#singleValueFeatures = reagent.getSingleFeatures()	# March 18/08 - Differentiate between features such as promoter or tag type, which could have multiple values, and cloning sites and linkers, which only have one value and one position
+			
+			#featureNames = sequenceFeatures + singleValueFeatures
+			
+			featureNames = sequenceFeatures
+			#print `featureNames`
+			
+			featureAliases = {}
+			features = {}
+		
+			for f in featureNames:
+				fAlias = prop_Name_Alias_Map[f]
+				#fPropID = prop_Name_ID_Map[f]
+				fPropID = fPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[f], prop_Category_Name_ID_Map["RNA Sequence Features"])
+				
+				featureAliases[fAlias] = f
+				features[fPropID] = f
+			
+			for fAlias in featureAliases:
+				#print "alias " + fAlias
+			
+				tmpStart = -1
+				tmpEnd = -1
+				
+				#tmpPropName = prefix + fAlias + postfix
+				
+				for tmpPropName in form.keys():
+					#print tmpPropName
+					#print fAlias
+					
+					# UPDATE Nov. 4/09
+					if tmpPropName.find(prefix + fAlias + "_:_") >= 0:
+						pValStartInd = len(prefix + fAlias)+3
+						#print pValStartInd
+						#pValStopInd = tmpPropName.find("_", pValStartInd)	# rmvd nov 1/09
+						pValStopInd = tmpPropName.rfind("_start_", pValStartInd)
+						#print pValStopInd
+						
+						# actual feature value
+						tmpPropValue = tmpPropName[pValStartInd:pValStopInd]
+						#print " feature " + tmpPropName
+						#print ", value " + tmpPropValue
+						
+						if tmpPropValue and len(tmpPropValue) > 0:
+							# get positions - changed oct. 25/08
+							
+							# Update Nov 3/09
+							#start_ind1 = tmpPropName.find(tmpPropValue) + len(tmpPropValue) + len("_start_")
+							
+							start_ind1 = tmpPropName.rfind("_start_") + len("_start_")
+							start_ind2 = tmpPropName.find("_end_")
+							#print start_ind2
+	
+							tmpStart = tmpPropName[start_ind1:start_ind2]
+							#print "start " + tmpStart
+							
+							if tmpStart and len(tmpStart) > 0 and int(tmpStart) > 0:
+								end_ind_1 = start_ind2 + len("_end_")
+								#print end_ind_1
+								end_ind_2 = tmpPropName.find("_", end_ind_1)
+								#print end_ind_2
+		
+								tmpEnd = tmpPropName[end_ind_1:end_ind_2]
+								#print "end " + tmpEnd
+								
+								if tmpEnd and len(tmpEnd) > 0 and int(tmpEnd) > 0:
+									tmpDirName = prefix + fAlias + "_:_" + tmpPropValue + "_start_" + `int(tmpStart)` + "_end_" + `int(tmpEnd)` + "_orientation" + postfix
+									#print tmpDirName
+									
+									if form.has_key(tmpDirName):
+										tmpDir = form.getvalue(tmpDirName)
+										#print "FOUND DIRECTION " + tmpDirName
+							
+										# Nov. 13/08: If there are duplicates, select one
+										if utils.isList(tmpDir):
+											#print "Descriptor " + tmpDescr
+											tmpDir = tmpDir[0]
+							
+										#fID = prop_Alias_ID_Map[fAlias]
+										fID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[fAlias], prop_Category_Name_ID_Map[prop_Category_Alias_Name_Map[featureType]])
+										
+										# descriptor
+										if featureDescriptors.has_key(prop_Alias_Name_Map[fAlias]):
+											tmpDescrName = featureDescriptors[prop_Alias_Name_Map[fAlias]]
+											tmpDescrAlias = prop_Name_Alias_Map[tmpDescrName]
+											#print "DESCRIPTOR " + tmpDescrAlias
+									
+											tmpDescrField = prefix + tmpDescrAlias + "_:_" + tmpPropValue + "_start_" + tmpStart + "_end_" + tmpEnd + postfix
+
+											#print tmpDescrField
+											
+											if form.has_key(tmpDescrField):
+												#print "?????????"
+									
+												tmpDescr = form.getvalue(tmpDescrField)
+												#print tmpDescr
+										
+												# Nov. 13/08: If there are duplicates, select one
+												if utils.isList(tmpDescr):
+													#print "Descriptor " + tmpDescr
+													tmpDescr = tmpDescr[0]
+										
+												# June 8, 2010: For descriptor have to go to textbox to fetch Other values
+												if tmpDescr.lower() == 'other':
+													
+													if fAlias == "tag":
+														descrAlias = "tag_position"
+													elif fAlias == "promoter":
+														descrAlias = "expression_system"
+										
+													tmpDescr_text = prefix + tmpDescrAlias + "_:_" + tmpPropValue + "_start_" + tmpStart + "_end_" + tmpEnd + "_name_txt"
+										
+													#print tmpDescr_text
+										
+													tmpDescr = form.getvalue(tmpDescr_text)
+										
+												#print tmpDescr
+									
+												if utils.isList(tmpDescr):
+													tmpDescr = tmpDescr[0]
+										
+												# March 29, 2010: Update set
+												tmpDescrPropID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[tmpDescrAlias], prop_Category_Name_ID_Map[prop_Category_Alias_Name_Map[featureType]])
+									
+												rTypeDescrAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, tmpDescrPropID)
+												
+												descrSetGroupID = sHandler.findPropSetGroupID(tmpDescrPropID)
+												descr_ssetID = sHandler.findSetValueID(descrSetGroupID, tmpDescr)
+												
+												if sHandler.findSetValueID(descrSetGroupID, tmpDescr) <= 0:
+													descr_ssetID = sHandler.addSetValue(descrSetGroupID, tmpDescr)
+
+												#print descr_ssetID
+
+												if not sHandler.existsReagentTypeAttributeSetValue(rTypeDescrAttributeID, descr_ssetID):
+													#print "HERE, updating"
+													sHandler.addReagentTypeAttributeSetEntry(rTypeDescrAttributeID, descr_ssetID)
+
+											else:
+												tmpDescr = ""
+										else:
+											tmpDescr = ""
+									
+										if not rHandler.existsPropertyValue(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDescr, tmpDir):
+											rHandler.addReagentProperty(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDir)
+											
+											rHandler.setReagentFeatureDescriptor(rID, fID, tmpPropValue, tmpStart, tmpEnd, tmpDescr)
+										
+										# March 29, 2010: Update set
+										rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, fID)
+										
+										setGroupID = sHandler.findPropSetGroupID(fID)
+										ssetID = sHandler.findSetValueID(setGroupID, tmpPropValue)
+										
+										if sHandler.findSetValueID(setGroupID, tmpPropValue) <= 0:
+											ssetID = sHandler.addSetValue(setGroupID, tmpPropValue)
+										
+										if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+											sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+									else:
+										pass
+								else:
+									pass
+							else:
+								pass
+						else:
+							pass
+					else:
+						pass
+						
+			# Match db IDs to property aliases
+			for tmpProp in newPropsDict_name.keys():
+				if prop_Alias_ID_Map.has_key(tmpProp):
+					# July 2/09: propertyID <= propCatID
+					#propID = prop_Alias_ID_Map[tmpProp]	# removed July 2/09
+					propID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[tmpProp], prop_Category_Name_ID_Map["RNA Sequence Features"])
+					newPropsDict_id[propID] = newPropsDict_name[tmpProp]
+
+			# June 8/08: Update sites
+			seqID = rHandler.findDNASequenceKey(rID)
+			seq = dnaHandler.findSequenceByID(seqID)
+			
+			#print `five_prime_site`
+			#rHandler.updateSitePositions(rID, seq, five_prime_site, three_prime_site)
+			
+			# June 16/08: Update protein translation
+			if rTypeID == '2':
+				iHandler.updateInsertProteinSequence(rID)
+			
+			# return to detailed view - Moved here July 7/08
+			utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+		
+		# This is saving properties from Cell Line old form that preloads from parents
+		elif section_to_save == "associations":
+			
+			#print "Content-type:text/html"
+			#print
+			#print `form`
+			
+			assocPropsDict = {}
+			newPropsDict_name = {}			# e.g. ('status', 'Completed')
+			newPropsDict_id = {}			# e.g. ('3', 'Completed') - db ID instead of property name
+
+			assocTypes = reagent.getAssociationTypes()
+			#print `assocTypes`
+			
+			assocAliases = {}
+			associations = {}
+			
+			for aType in assocTypes:
+				#print aType
+				assocAlias = assoc_Name_Alias_Map[aType]
+				#print assocAlias
+				assocID = assoc_Name_ID_Map[aType]
+				
+				assocAliases[assocAlias] = aType
+				associations[assocID] = aType
+				
+			for assocAlias in assocAliases:
+				tmpPropName = assocPrefix + assocAlias + postfix
+				#print tmpPropName
+
+				if form.has_key(tmpPropName):
+					tmpPropVal = form.getvalue(tmpPropName)
+					assocPropsDict[assocAlias] = tmpPropVal
+			
+			#print `assocPropsDict`
+			packetPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["packet id"], prop_Category_Name_ID_Map["General Properties"])
+
+			
+			# Fetch projects the user has AT LEAST Read access to (i.e. if he is explicitly declared a Writer on a project but not declared a Reader, include that project, plus all public projects)
+			currReadProj = packetHandler.findMemberProjects(currUser.getUserID(), 'Reader')
+			currWriteProj = packetHandler.findMemberProjects(currUser.getUserID(), 'Writer')
+			publicProj = packetHandler.findAllProjects(isPrivate="FALSE")
+			
+			# list of Packet OBJECTS
+			currUserWriteProjects = utils.unique(currReadProj + currWriteProj + publicProj)
+			
+			uPackets = []
+			
+			for p in currUserWriteProjects:
+				uPackets.append(p.getNumber())
+		
+			# Cell Line.  Check Parent Vector, and parent cell line
+			pvVal = form.getvalue("assoc_cell_line_parent_vector_prop")
+			#print pvVal
+	
+			if len(pvVal) > 0:
+				pvID = rHandler.convertReagentToDatabaseID(pvVal)
+				#print pvID
+				#print packetPropID
+
+				try:
+					pvProjectID = int(rHandler.findSimplePropertyValue(pvID, packetPropID))
+					
+				except TypeError:
+					pvProjectID = 0
+			else:
+				pvID = 0
+				pvProjectID = 0
+
+			if pvID > 0:
+				if rHandler.findSimplePropertyValue(pvID, packetPropID):
+					pvProjectID = int(rHandler.findSimplePropertyValue(pvID, packetPropID))
+					
+					if currUser.getCategory() != 'Admin' and pvProjectID not in uPackets:
+						utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID` + "&mode=Modify&ErrCode=4&PV=" + pvVal)
+				else:
+					# Project value not recorded for the parent vector - catch this error
+					utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID` + "&mode=Modify&ErrCode=4&PV=" + pvVal)
+				
+			# cell line
+			pclVal = form.getvalue("assoc_parent_cell_line_prop")
+			#print pclVal
+			if len(pclVal) > 0:
+				pclID = rHandler.convertReagentToDatabaseID(pclVal)
+				#print pclID
+			else:
+				pclID = 0
+			
+			if pclID > 0:
+				if rHandler.findSimplePropertyValue(pclID, packetPropID):
+					pclProjectID = int(rHandler.findSimplePropertyValue(pclID, packetPropID))
+
+					if currUser.getCategory() != 'Admin' and pclProjectID not in uPackets:
+						utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID` + "&mode=Modify&ErrCode=4&CL=" + pclVal)
+				else:
+					# Project value not recorded for the parent cell line - catch this error
+					utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID` + "&mode=Modify&ErrCode=4&CL=" + pclVal)
+			
+			# Feb. 16/10
+			assocPropsDict = {}
+			
+			clpvAssocPropID = rtAssocHandler.findParentAssocType(reagentType_Name_ID_Map["CellLine"], reagentType_Name_ID_Map["Vector"])
+			#print `clpvAssocPropID`
+			
+			pclAssocPropID = rtAssocHandler.findParentAssocType(reagentType_Name_ID_Map["CellLine"], reagentType_Name_ID_Map["CellLine"])
+			#print `pclAssocPropID`
+			
+			assocPropsDict[clpvAssocPropID] = pvVal
+			assocPropsDict[pclAssocPropID] = pclVal
+			
+			# save rest of properties
+			prefix = "reagent_detailedview_"
+			postfix = "_prop"
+			
+			# For Cell Lines, update properties preloaded from parents
+			
+			# Find the actual names and database IDs of POST values
+			newPropsDict_name = {}		# e.g. ('status', 'Completed')
+        		newPropsDict_id = {}		# e.g. ('3', 'Completed') - db ID instead of property name
+			
+			# Find actual property values
+			for propName_tmp in form.keys():
+				
+				# new value that would be added to the set (dropdown/checkbox)
+				newSetEntry = ""
+				
+				#print propName_tmp
+			
+				if propName_tmp.find("_:_") > 0:
+					pToks = propName_tmp.split("_:_")
+					#print `pToks`
+					
+					if pToks[0].find(prefix + reagentType_ID_Name_Map[int(rTypeID)] + "_") == 0:
+						catAlias = pToks[0][len(prefix + reagentType_ID_Name_Map[int(rTypeID)] + "_"):]
+						categoryID = prop_Category_Alias_ID_Map[catAlias]
+					else:
+						continue
+						
+					if pToks[1].find(postfix) + len(postfix) == len(pToks[1]):
+						propAlias = pToks[1][0:pToks[1].find(postfix)]
+						propName = prop_Alias_Name_Map[propAlias]
+						propID = prop_Alias_ID_Map[propAlias]
+					else:
+						continue
+					
+					if utils.isList(form[propName_tmp]):
+						newPropVal = utils.unique(form.getlist(propName_tmp))
+					else:
+						newPropVal = form[propName_tmp].value.strip()
+					
+					#print propName
+					#print newPropVal
+
+					propCatID = pHandler.findReagentPropertyInCategoryID(propID, categoryID)
+					rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, propCatID)
+					
+					# Alternate ID - Combine the checkbox value representing external source name with the identifier for that source in a textbox
+					if propName.lower() == "alternate id":
+						#print `newPropVal`
+						
+						if utils.isList(newPropVal):
+							tmp_alt_ids = []
+						
+							for altID in newPropVal:
+								if form.has_key(propAlias + "_" + altID + "_textbox_name"):
+									if altID.lower() == 'other':
+										tmp_alt_id = form.getvalue(propAlias + "_" + altID + "_textbox_name")
+										
+										# update list
+										pcID = pHandler.findReagentPropertyInCategoryID(propID, categoryID)
+								
+										rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, pcID)
+										
+										setGroupID = sHandler.findPropSetGroupID(pcID)
+										ssetID = sHandler.findSetValueID(setGroupID, tmp_alt_id[0:tmp_alt_id.find(":")])
+										
+										if ssetID <= 0:
+											ssetID = sHandler.addSetValue(setGroupID, tmp_alt_id[0:tmp_alt_id.find(":")])
+										
+										if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+											sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+									else:
+										tmp_alt_id = altID + ":" + form.getvalue(propAlias + "_" + altID + "_textbox_name")
+										#print tmp_alt_id
+									
+									tmp_alt_ids.append(tmp_alt_id)
+							
+							newPropVal = tmp_alt_ids
+						else:
+							if form.has_key(propAlias + "_" + newPropVal + "_textbox_name"):
+								if newPropVal.lower() == 'other':
+									tmp_alt_id = form.getvalue(propAlias + "_" + newPropVal + "_textbox_name")
+									
+									# update list
+									pcID = pHandler.findReagentPropertyInCategoryID(propID, categoryID)
+							
+									rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, pcID)
+									
+									setGroupID = sHandler.findPropSetGroupID(pcID)
+									ssetID = sHandler.findSetValueID(setGroupID, tmp_alt_id[0:tmp_alt_id.find(":")])
+									
+									if ssetID <= 0:
+										ssetID = sHandler.addSetValue(setGroupID, tmp_alt_id[0:tmp_alt_id.find(":")])
+									
+									if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+										sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+								else:
+									tmp_alt_id = newPropVal + ":" + form.getvalue(propAlias + "_" + newPropVal + "_textbox_name")
+									#print tmp_alt_id
+							
+							newPropVal = tmp_alt_id
+					else:	
+						if utils.isList(newPropVal):
+							if len(newPropVal) > 1:
+								for pVal in newPropVal:
+									#print pVal
+
+									setGroupID = sHandler.findPropSetGroupID(propCatID)
+									ssetID = sHandler.findSetValueID(setGroupID, pVal)
+
+									if sHandler.findSetValueID(setGroupID, pVal) <= 0:
+										ssetID = sHandler.addSetValue(setGroupID, pVal)
+									
+									if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+										sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+							else:
+								newPropVal = newPropVal[0]
+						else:
+							if newPropVal.lower() == "other":
+								txtbox = propName_tmp.replace(postfix, "_name_txt")
+								#print txtbox
+								
+								if form.has_key(txtbox):
+									newPropVal = form.getvalue(txtbox)
+									
+									# update list
+									pcID = pHandler.findReagentPropertyInCategoryID(propID, categoryID)
+							
+									rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, pcID)
+									
+									setGroupID = sHandler.findPropSetGroupID(pcID)
+									ssetID = sHandler.findSetValueID(setGroupID, newPropVal)
+									
+									if sHandler.findSetValueID(setGroupID, newPropVal) <= 0:
+										ssetID = sHandler.addSetValue(setGroupID, newPropVal)
+									
+									if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+										sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+							
+					newPropsDict_id[propCatID] = newPropVal
+
+					## store new property alias and value in dictionary
+					#newPropsDict_name[propName] = newPropVal
+			
+			#print `newPropsDict_id`
+			
+			# Action
+			rHandler.updateReagentProperties(rID, newPropsDict_id)
+			#print `assocPropsDict`
+			
+			rHandler.updateReagentAssociations(rID, assocPropsDict)
+	
+			# return to detailed view
+			utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+
+		## return to detailed view
+		#utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+
+		# SAVE NOVEL CATEGORIES - AUG. 24/09
+		else:
+			#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+			#print
+			#print `form`
+			#print `prop_Category_Name_ID_Map`
+			#print section_to_save
+			
+			# Code taken from Classifiers
+			newPropsDict_name = {}			# e.g. ('status', 'Completed')
+			newPropsDict_id = {}			# e.g. ('3', 'Completed') - db ID instead of property name
+
+			# Nov. 12/09: Here, section_to_save is an ALIAS
+			#categoryID = prop_Category_Name_ID_Map[section_to_save]
+			categoryID = prop_Category_Alias_ID_Map[section_to_save]
+			classifierNames = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, categoryID)
+
+			classifierAliases = {}
+			classifiers = {}
+			
+			# Map property names to aliases
+			for c in classifierNames:
+				cAlias = prop_Name_Alias_Map[c]
+				#cPropID = prop_Name_ID_Map[c]
+				cPropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map[c], categoryID)
+				
+				classifierAliases[cAlias] = c
+				classifiers[cPropID] = c
+				
+			# Get property values from form
+			for cAlias in classifierAliases:
+				tmpPropName = prefix + cAlias + postfix
+				#print tmpPropName
+				
+				pcID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[cAlias], categoryID)
+				rTypeAttributeID = rtPropHandler.findReagentTypeAttributeID(rTypeID, pcID)
+				
+				if form.has_key(tmpPropName):
+					if not utils.isList(form.getvalue(tmpPropName)):
+						newPropVal = form.getvalue(tmpPropName).strip()
+					else:
+						#print tmpPropName
+						newPropVal = utils.unique(form.getlist(tmpPropName))
+					
+					#print newPropVal
+					#print rTypeAttributeID
+					
+					# May 20, 2010: Check for new list values here, and don't use isList to check; use isMultiple b/c even for multiple dropdowns, when only one value is added, it's not considered a list!!!
+					# the check for isMultiple here only tells us whether 'Other' values should be retrieved from a textbox or read from list one-by-one
+					if rtPropHandler.isMultiple(rTypeAttributeID):
+						tmp_ar = []
+						
+						if not utils.isList(newPropVal):
+							tmp_ar.append(newPropVal)
+						else:
+							tmp_ar = newPropVal
+							
+						for val in tmp_ar:
+							
+							# update set with new values
+							setGroupID = sHandler.findPropSetGroupID(pcID)
+							ssetID = sHandler.findSetValueID(setGroupID, val)
+							
+							if sHandler.findSetValueID(setGroupID, val) <= 0:
+								ssetID = sHandler.addSetValue(setGroupID, val)
+							
+							if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+								sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+					else:
+						# Jan. 9/09: save 'other' values - Update Feb. 4/10
+						#print tmpPropName
+						#print `newPropVal`
+						
+						if newPropVal.lower() == 'other':
+							textBoxName = prefix + reagentType_ID_Name_Map[int(rTypeID)] + "_" + section_to_save + "_:_" + cAlias + "_name_txt"
+							#print textBoxName
+							
+							if form.has_key(textBoxName):
+								#print "ok"
+								newPropVal = form.getvalue(textBoxName).strip()
+								#print newPropVal
+								
+								setGroupID = sHandler.findPropSetGroupID(pcID)
+								ssetID = sHandler.findSetValueID(setGroupID, newPropVal)
+								
+								if sHandler.findSetValueID(setGroupID, newPropVal) <= 0:
+									ssetID = sHandler.addSetValue(setGroupID, newPropVal)
+								
+								if not sHandler.existsReagentTypeAttributeSetValue(rTypeAttributeID, ssetID):
+									sHandler.addReagentTypeAttributeSetEntry(rTypeAttributeID, ssetID)
+
+					newPropsDict_name[cAlias] = newPropVal
+					#newPropsDict_name[cAlias] = tmpPropVal
+				#else:
+					## delete????
+					#pcID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[cAlias], categoryID)
+					#rHandler.deleteReagentProperty(rID, pcID)
+			
+			# Match db IDs to property aliases
+			for tmpProp in newPropsDict_name.keys():
+				
+				if prop_Alias_ID_Map.has_key(tmpProp):
+					
+					# July 2/09: propertyID <= propCatID
+					#propID = prop_Alias_ID_Map[tmpProp]	# removed July 2/09
+					
+					# Nov. 12/09: section_to_save is an alias for new categories
+					propID = pHandler.findReagentPropertyInCategoryID(prop_Alias_ID_Map[tmpProp], prop_Category_Alias_ID_Map[section_to_save])
+					newPropsDict_id[propID] = newPropsDict_name[tmpProp]
+
+			# ACTION			
+			rHandler.updateReagentPropertiesInCategory(rID, categoryID, newPropsDict_id)
+			
+			# return to detailed view - Moved here July 7/08
+			utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+
+	elif mode == "Cancel":
+
+		# return to detailed view w/o doing anything
+		utils.redirect(hostname + "Reagent.php?View=6&rid=" + `rID`)
+	
+	cursor.close()
+	db.close()
+	
+update()
diff --git a/OpenFreezer/cgi/user.py b/OpenFreezer/cgi/user.py
new file mode 100755
index 0000000..43b6d57
--- /dev/null
+++ b/OpenFreezer/cgi/user.py
@@ -0,0 +1,168 @@
+###################################################################################################
+# This module represents inidividual users of OpenFreezer
+#
+# Written: May 25, 2007, by Marina Olhovsky
+# Last modified: August 8, 2007
+###################################################################################################
+class User:
+
+	__userID = 0
+	__username = ""
+	__firstName = ""
+	__lastName = ""
+	__description = ""		# usually a full name - 'Firstname LastName' - e.g. John Smith
+	__lab = None			# a Laboratory instance
+	__category = ""			# plain text string: Admin, Creator, Writer, Reader
+	__email = ""
+	__passwd = ""
+	__status = 'ACTIVE'
+	__projects_readonly = []	# list of Project Class **INSTANCES** representing projects the user has READ-ONLY access to
+	__projects_write = []		# list of Project Class **INSTANCES** representing projects the user has WRITE access to
+	
+
+	# Plain list of mutable User object attributes (details that can be changed)
+	# userID is immutable; once assigned it cannot be changed; the rest of the information can be modified in the database
+	__userProperties = ["username", "firstname", "lastname", "description", "labID", "category", "email", "password", "status"]
+
+	##################################
+	# Constructors
+	##################################
+
+	# Complete initialization of all object variables
+	def __init__(self, uid, uname = "", fName = "", lName ="", descr="", lab = None, category = "", email = "", pw = "", projects_read = [], projects_write = []):
+		self.__userID = uid
+		self.__username = uname
+		self.__firstName = fName
+		self.__lastName = lName
+		self.__description = descr
+		self.__lab = lab
+		self.__category = category
+		self.__email = email
+		self.__passwd = pw
+		self.__projects_readonly = projects_read
+		self.__projects_write = projects_write
+		self.__status = 'ACTIVE'
+
+
+	############################
+	# Assignment methods
+	############################
+
+	def setUserID(self, uid):
+		self.__userID = uid
+
+
+	def setUsername(self, uname):
+		self.__username = uname
+
+
+	def setFirstName(self, fName):
+		self.__firstName = fName
+
+
+	def setLastName(self, lName):
+		self.__lastName = lName
+
+	
+	def setDescription(self, descr):
+		self.__description = descr
+	
+	def setLab(self, lab):
+		self.__lab = lab
+
+
+	def setCategory(self, category):
+		self.__category = category
+
+
+	def setEmail(self, email):
+		self.__email = email
+		
+		
+	def setPasswd(self, pw):
+		self.__passwd = pw
+
+		
+	def setReadProjects(self, readProjects):
+		self.__projects_readonly = readProjects
+
+
+	def setWriteProjects(self, writeProjects):
+		self.__projects_write = writeProjects
+
+
+	def setStatus(self, status):
+		self.__status = status
+		
+		
+	def addProject(self, project, projectType):
+		if projectType == 'read':
+			self.__projects_readonly.append(project)
+		else:
+			self.__projects_write.append(project)
+			
+
+	############################
+	# Access methods
+	############################
+
+	def getUserID(self):
+		return int(self.__userID)
+	
+
+	def getUsername(self):
+		return self.__username
+	
+	
+	def getFirstName(self):
+		return self.__firstName
+		
+		
+	def getLastName(self):
+		return self.__lastName
+
+
+	def getDescription(self):
+		return self.__description
+		
+
+	# Utility function, return "Firstname Lastname" if 'description' is unavailable
+	def getFullName(self):
+	
+		if self.__description == "":
+			return self.getFirstName() + " " + self.getLastName()
+		else:
+			return self.__description
+
+	def getLab(self):
+		return self.__lab
+		
+		
+	def getCategory(self):
+		return self.__category
+
+
+	def getEmail(self):
+		return self.__email
+
+
+	def getPassword(self):
+		return self.__passwd
+
+
+	def getStatus(self):
+		return self.__status
+		
+			
+	def getReadProjects(self):
+		return self.__projects_readonly
+
+
+	def getWriteProjects(self):
+		return self.__projects_write
+		
+		
+	# A static (class) method, called to fetch a list of general User attributes
+	@classmethod
+	def getUserProperties(self):
+		return self.__userProperties
diff --git a/OpenFreezer/cgi/user_handler.py b/OpenFreezer/cgi/user_handler.py
new file mode 100755
index 0000000..ce5d36d
--- /dev/null
+++ b/OpenFreezer/cgi/user_handler.py
@@ -0,0 +1,530 @@
+############################################################################################
+# This module serves as an intermediate layer between the database and User module objects
+#
+# Written: May 25, 2007, by Marina Olhovsky
+# Last modified: March 26, 2008
+############################################################################################
+
+import MySQLdb
+import utils
+
+from exception import *
+
+from laboratory import Laboratory
+from user import User
+
+from general_handler import GeneralHandler
+from mapper import UserCategoryMapper
+
+class UserHandler(GeneralHandler):
+
+	def __init__(self, db, cursor):
+		super(UserHandler, self).__init__(db, cursor)
+
+	
+	# Fetch all the details for the user identified by uid and wrap them in a User object
+	# Return: User instance
+	def getUserByID(self, uid):
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+	
+		db = self.db			# make local copies of global variables for easy access
+		cursor = self.cursor
+		
+		newUser = None
+		
+		# ATT'N: Removed 'user status=ACTIVE' clause, since this function may be called to retrieve a project owner, who may be gone, but his/her packet is still active
+
+		#print "SELECT u.username, u.firstname, u.lastname, u.description, c.category, u.labID, l.lab_name, u.email, u.password FROM Users_tbl u, LabInfo_tbl l, UserCategories_tbl c WHERE u.userID=" + `uid` + " AND u.labID=l.labID AND c.categoryID=u.category AND l.status='ACTIVE'"
+	
+		cursor.execute("SELECT u.username, u.firstname, u.lastname, u.description, c.category, u.labID, l.lab_name, u.email, u.password FROM Users_tbl u, LabInfo_tbl l, UserCategories_tbl c WHERE u.userID=" + `uid` + " AND u.labID=l.labID AND c.categoryID=u.category AND l.status='ACTIVE'")
+		
+		result = cursor.fetchone()
+		
+		if result:
+			username = result[0]
+			firstname = result[1]
+			lastname = result[2]
+			description = result[3]
+			category = result[4]
+			labID = int(result[5])
+			labname = result[6]
+			email = result[7]
+			password = result[8]
+			
+			newLab = Laboratory(labID, labname)
+			newUser = User(uid, username, firstname, lastname, description, newLab, category, email, password)
+		
+		return newUser
+
+	
+	# Fetch all the details for the user based on the user's full name - maps to 'description' column
+	# Return: User instance
+	def getUserByDescription(self, descr):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT u.userID, u.username, u.firstname, u.lastname, c.category, u.labID, l.lab_name, u.email, u.password FROM Users_tbl u, LabInfo_tbl l, UserCategories_tbl c WHERE u.description=" + `descr` + " AND u.labID=l.labID AND c.categoryID=u.category AND l.status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			uid = int(result[0])
+			username = result[1]
+			firstname = result[2]
+			lastname = result[3]
+			category = result[4]
+			labID = int(result[5])
+			labname = result[6]
+			email = result[7]
+			password = result[8]
+			
+			newLab = Laboratory(labID, labname)
+			newUser = User(uid, username, firstname, lastname, descr, newLab, category, email, password)
+			
+			return newUser
+		
+		else:
+			# Nov. 15/07: Retry, just select userID and category and labID - other attributes may be omitted - for ACTIVE users only
+			cursor.execute("SELECT u.userID, c.category FROM Users_tbl u, UserCategories_tbl c WHERE u.description=" + `descr` + " AND c.categoryID=u.category AND u.status='ACTIVE'")
+			result = cursor.fetchone()
+			
+			if result:
+				uid = int(result[0])
+				category = result[1]
+				newUser = User(uid, "", "", "", descr, None, category, "", "")
+				
+				return newUser
+
+	
+	# Fetch userID of the user identified by username, REGARDLESS OF STATUS
+	def findUserIDByUsername(self, username):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT userID FROM Users_tbl WHERE username=" + `username`)
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+			
+		return 0
+	
+	
+	# June 1, 2010
+	def findUserIDByDescription(self, userdesc):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		cursor.execute("SELECT userID FROM Users_tbl WHERE description=" + `userdesc`)
+		result = cursor.fetchone()
+		
+		if result:
+			return int(result[0])
+			
+		return 0
+
+
+	## June 1, 2010
+	#def findUserIDByEmail(self, email):
+		
+		#db = self.db
+		#cursor = self.cursor
+		
+		#cursor.execute("SELECT userID FROM Users_tbl WHERE email=" + `email`)
+		#result = cursor.fetchone()
+		
+		#if result:
+			#return int(result[0])
+			
+		#return 0
+
+	
+	"""
+	# Perform a match against a portion of the user's first name, last name or full name
+	# Used in user search page
+	def findUsersByKeyword(self, keyword):
+	
+		db = self.db
+		cursor = self.cursor
+		
+		users = []	# list of search results, in case multiple users match keyword
+			
+		cursor.execute("SELECT userID FROM Users_tbl WHERE firstName LIKE '%" + keyword + "%' OR lastName LIKE '%" + keyword + "%' OR description LIKE '%" + keyword + "%'")
+		results = cursor.fetchall()
+		
+		if results:
+			for result in results:
+				userID = int(result[0])
+				users.append(userID)
+				
+		return users
+	"""
+		
+	
+	# Insert a new entry into the User table
+	# Column values: function arguments
+	# Return: the ID of the newly inserted User table entry
+	#
+	# Error checking: Usernames must be unique; hence, a MySQL duplicate entry error is raised when a username is entered on the creation page that already exists in Users_tbl.  This scenario may occur if an admin wishes to restore a DEP user.  Thus, need to check for status, and if the new username already exists in the table with DEP status, reactivate status and overwrite entry with new column values
+	def insertUser(self, username, firstname, lastname, description, category, email, password, labID):
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		
+		db = self.db
+		cursor = self.cursor
+		
+		if not self.existsUsername(username, 'ACTIVE') and not self.existsUsername(username, 'DEP'):
+			cursor.execute("INSERT INTO Users_tbl(username, firstname, lastname, description, category, email, password, labID) VALUES(" + `username` + ", " + `firstname` + ", " + `lastname` + ", " + `description` + ", " + `category` + ", " + `email` + ", MD5(" + `password` + "), " + `labID` + ")")
+			userID = int(db.insert_id())
+			return userID
+		
+		#elif not self.existsUsername(username, 'ACTIVE') and self.existsUsername(username, 'DEP'):
+		#	raise DeletedUserException("The username provided exists in the system but is inactive")
+					
+		else:
+			raise DuplicateUsernameException("The username provided already exists in the system")
+		
+		
+	# Check if a username exists in the database
+	# 'status' is one of 'ACTIVE' or 'DEP'
+	def existsUsername(self, username, status):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("SELECT userID FROM Users_tbl WHERE username=" + `username` + " AND status=" + `status`)
+		result = cursor.fetchone()
+		
+		if result:
+			return True
+		else:
+			return False
+		
+		
+	# Verify that a user identified 'userID' exists and is active in the system
+	def existsUser(self, userID):
+		
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("SELECT * FROM Users_tbl WHERE userID=" + `userID` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			return True
+		else:
+			return False
+			
+		
+	# Revoke OpenFreezer access for the user identified by uid by setting the appropriate entry in Users_tbl to status='DEP'
+	def deleteUser(self, uid):
+	
+		db = self.db
+		cursor = self.cursor
+	
+		cursor.execute("UPDATE Users_tbl SET status='DEP' WHERE userID=" + `uid`)		
+	
+	"""
+	# Reactivate deleted user - likely during User creation
+	# Change status to ACTIVE and overwrite old attributes
+	def restoreUser(self, username):
+	
+		db = self.db
+		cursor = self.cursor
+	"""		
+			
+
+	# Find the username of the user identified by uid
+	def findUsername(self, uid):
+		
+		db = self.db			# make local copies of global variables for easy access
+		cursor = self.cursor
+		
+		username = ""
+		
+		cursor.execute("SELECT username FROM Users_tbl WHERE userID=" + `uid` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			username = result[0]
+			
+		return username
+			
+
+	# Find the first name of the user identified by uid
+	def findFirstname(self, uid):
+		
+		db = self.db			# make local copies of global variables for easy access
+		cursor = self.cursor
+		
+		firstname = ""
+
+		cursor.execute("SELECT firstname FROM Users_tbl WHERE userID=" + `uid` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			firstname = result[0]
+			
+		return firstname
+
+
+	# Find the last name of the user identified by uid
+	def findLastname(self, uid):
+		
+		db = self.db			# make local copies of global variables for easy access
+		cursor = self.cursor
+		
+		lastname = ""
+		
+		cursor.execute("SELECT lastname FROM Users_tbl WHERE userID=" + `uid` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			lastname = result[0]
+			
+		return lastname
+
+
+	# Find user's full name
+	def findDescription(self, uid):
+
+		db = self.db
+		cursor = self.cursor
+		
+		description = ""
+		
+		cursor.execute("SELECT description FROM Users_tbl WHERE userID=" + `uid` + " AND status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			description = result[0]
+			
+		return description
+
+	
+	# Find the category of the user identified by uid
+	def findCategory(self, uid):
+		
+		db = self.db			# make local copies of global variables for easy access
+		cursor = self.cursor
+		
+		category = ""
+		
+		cursor.execute("SELECT c.category FROM Users_tbl u, UserCategories_tbl c WHERE u.userID=" + `uid` + " AND u.category=c.categoryID AND u.status='ACTIVE'")
+		result = cursor.fetchone()
+		
+		if result:
+			category = result[0]
+			
+		return category
+
+
+	# Find the lab ID of the user identified by uid
+	def findLabID(self, uid):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		labID = 0
+
+		cursor.execute("SELECT labID FROM Users_tbl WHERE userID=" + `uid` + " AND status='ACTIVE'")
+		result = cursor.fetchone()	# a member can only belong to one lab
+
+		if result:
+			labID = int(result[0])
+
+		return labID
+
+
+	def findStatus(self, uid):
+
+		db = self.db
+		cursor = self.cursor		
+		
+		cursor.execute("SELECT status FROM Users_tbl WHERE userID=" + `uid`)
+		result = cursor.fetchone()
+
+		if result:
+			return result[0]
+			
+		return None
+
+
+	# March 26/08
+	def findEmail(self, uid):
+		
+		db = self.db
+		cursor = self.cursor		
+		
+		cursor.execute("SELECT email FROM Users_tbl WHERE userID=" + `uid`)
+		result = cursor.fetchone()
+
+		if result:
+			return result[0]
+			
+		return None
+	
+
+	# find a list of all properties and return them in the form of a dictionary
+	def findAllUserProperties(self, uid):
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+	
+		db = self.db
+		cursor = self.cursor
+		
+		properties = {}
+		
+		properties["username"] = self.findUsername(uid)
+		properties["firstName"] = self.findFirstname(uid)
+		properties["lastName"] = self.findLastname(uid)
+		properties["labID"] = self.findLabID(uid)
+		properties["category"] = self.findCategory(uid)
+		properties["status"] = self.findStatus(uid)
+		
+		return properties
+
+
+	# Fetch the list of all users who belong to 'category'
+	# Input: category = one of 4 possible entries in UserCategories_tbl: Admin, Creator, Writer, Reader
+	# oper - SQL comparison operator; by default it's '=', but could be '>=', '<' or '>' - depending on whether calling function needs exact category match (e.g. find all Writers or those who have **at least** writing privileges)
+	# Optional: may restrict search to members in a specific lab
+	# Return: list of User instances
+	def findAllMembersInCategory(self, category, active, oper = '=', labID = 0):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		
+		ucMapper = UserCategoryMapper(db, cursor)		# for category name/id mapping
+		category_Name_ID_Map = ucMapper.mapCategoryNameToID()
+
+		members = []	# list of User **objects**
+		
+		# When we include 'status=ACTIVE' restriction in the query, a DEP owner of an active project is not shown in project view.  However, we should not add DEP members to a project.
+		# Therefore, the calling function should specify whether it wants to restrict query by status.
+		# If 'active' parameter is True, add 'status=ACTIVE' clause
+		# In any case, **remember to fill in 'category' column for DEP users before the launch**
+		
+		if labID == 0:
+			if active:
+				cursor.execute("SELECT userID, firstname, lastname, description FROM Users_tbl u, UserCategories_tbl c WHERE c.categoryID " + oper + " " + `category_Name_ID_Map[category]` + " AND c.categoryID=u.category AND u.firstname <> '' AND u.lastname <> '' AND u.description <>'' AND u.status='ACTIVE'")
+			else:
+				cursor.execute("SELECT userID, firstname, lastname, description FROM Users_tbl u, UserCategories_tbl c WHERE c.categoryID " + oper + " " + `category_Name_ID_Map[category]` + " AND c.categoryID=u.category AND u.firstname <> '' AND u.lastname <> '' AND u.description <>''")
+		else:
+			if active:
+				cursor.execute("SELECT u.userID, u.firstname, u.lastname, u.description, l.lab_name FROM Users_tbl u, UserCategories_tbl c, LabInfo_tbl l WHERE c.categoryID " + oper + " " + `category_Name_ID_Map[category]` + " AND c.categoryID=u.category AND u.firstname <> '' AND u.lastname <> '' AND u.labID=" + `labID` + " AND l.labID=u.labID AND u.status='ACTIVE'")
+			else:
+				cursor.execute("SELECT u.userID, u.firstname, u.lastname, u.description, l.lab_name FROM Users_tbl u, UserCategories_tbl c, LabInfo_tbl l WHERE c.categoryID " + oper + " " + `category_Name_ID_Map[category]` + " AND c.categoryID=u.category AND u.firstname <> '' AND u.lastname <> '' AND u.description <>'' AND u.labID=" + `labID` + " AND l.labID=u.labID")
+			
+		results = cursor.fetchall()
+		
+		for result in results:
+		
+			userID = int(result[0])
+			firstName = result[1]
+			lastName = result[2]
+			description = result[3]
+			
+			tmpLab = Laboratory(labID)
+			
+			if len(result) == 5:
+				labName = result[4]
+				tmpLab.setName(labName)
+				
+			# create a User object
+			tmpUser = User(userID, "", firstName, lastName, description, tmpLab, category, "", "")
+			members.append(tmpUser)
+		
+
+		return members
+
+	# Change the value of an existing property (username, first name, last name, etc.)
+	# propName corresponds to an actual column name in Users_tbl - hence, column name is determined dynamically
+	# Do NOT check status='ACTIVE', as this procedure call is now used to restore DEP users
+	def setUserPropertyValue(self, uid, propName, propValue):
+
+		db = self.db
+		cursor = self.cursor
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		
+		ucMapper = UserCategoryMapper(db, cursor)
+		category_Name_ID_Map = ucMapper.mapCategoryNameToID()
+
+		if propName == "password":
+			cursor.execute("UPDATE Users_tbl SET " + propName + " = MD5(" + `propValue` + ") WHERE userID=" + `uid`)
+			
+		elif propName == "username":
+			
+			# Watch out again for duplicate username entries
+			
+			if not self.existsUsername(propValue, 'ACTIVE') and not self.existsUsername(propValue, 'DEP'):
+				cursor.execute("UPDATE Users_tbl SET " + propName + " = " + `propValue` + " WHERE userID=" + `uid`)
+
+			elif not self.existsUsername(propValue, 'ACTIVE') and self.existsUsername(propValue, 'DEP'):
+				raise DeletedUserException("The username provided exists in the system but is inactive")
+
+			else:
+				raise DuplicateUsernameException("The username provided already exists in the system")
+				
+		elif propName == "category":
+			cursor.execute("UPDATE Users_tbl SET " + propName + " = " + `category_Name_ID_Map[propValue]` + " WHERE userID=" + `uid`)
+
+		else:
+			cursor.execute("UPDATE Users_tbl SET " + propName + " = " + `propValue` + " WHERE userID=" + `uid`)
+
+	
+	# Update a list of user details (called at user modification view)
+	# newProps - dictionary of (property (=column) name, property value) tuples
+	def updateUserProperties(self, uid, newProps):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		# Fetch old user info, compare against new values, and either insert, change or delete
+		userProps = User.getUserProperties()
+		
+		oldProps = self.findAllUserProperties(uid)
+		
+		for propName in userProps:
+			
+			if oldProps.has_key(propName) :
+				oldPropVal = oldProps[propName]
+			else:
+				# property does not exist (wouldn't happen too often, since most properties are required to be filled in)
+				oldPropVal = ""
+
+			if newProps.has_key(propName):
+				newPropVal = newProps[propName]
+				
+				# Use the same procedure call for all 3 operations, Insert, Update and Delete alike - since a user entry already exists in the database, all changes to it are performed through UPDATE query
+				if (oldPropVal != newPropVal) or (oldPropVal == ""):
+					self.setUserPropertyValue(uid, propName, newPropVal)
+
+
+	# Find out what sections of the website a user is allowed to view based on his/her login privileges
+	def getAllowedSections(self, cat):
+		
+		db = self.db
+		cursor = self.cursor
+		
+		allowedSections = []		# contains names of website sections the user is allowed to view
+		
+		cursor.execute("SELECT section FROM UserPermission_tbl p, SecuredPages_tbl s WHERE p.categoryID>=" + `cat` + " AND p.pageID=s.pageID AND s.status='ACTIVE' AND p.status='ACTIVE'")
+		results = cursor.fetchall()
+
+		for result in results:
+			section = result[0]
+			allowedSections.append(section)
+			
+		return allowedSections
diff --git a/OpenFreezer/cgi/user_output.py b/OpenFreezer/cgi/user_output.py
new file mode 100755
index 0000000..f66336e
--- /dev/null
+++ b/OpenFreezer/cgi/user_output.py
@@ -0,0 +1,1304 @@
+#!/usr/local/bin/python
+
+import cgi
+
+import os
+import tempfile
+import stat
+
+from database_conn import DatabaseConn
+
+from user_handler import UserHandler
+from lab_handler import LabHandler
+from general_handler import UserCategoryHandler
+from project_database_handler import ProjectDatabaseHandler
+
+from mapper import UserCategoryMapper
+
+from user import User
+from session import Session
+
+from general_output import GeneralOutputClass
+
+import utils
+
+#############################################################################################################
+# This class handles the presentation layer of the website
+# Generates HTML content for User and Lab views and writes it in files, which are then opened by User.php
+#
+# Written June 22, 2007 by Marina Olhovsky
+# Last modified: July 5, 2007
+#############################################################################################################
+class UserOutputClass:
+
+	def printUserInfo(self, cmd, user, errCode=""):
+		
+		dbConn = DatabaseConn()
+		hostname = dbConn.getHostname()		# to define form action URL
+		
+		db = dbConn.databaseConnect()
+		cursor = db.cursor()
+		
+		uHandler = UserHandler(db, cursor)
+		lHandler = LabHandler(db, cursor)
+		pHandler = ProjectDatabaseHandler(db, cursor)
+		
+		ucMapper = UserCategoryMapper(db, cursor)
+		category_ID_Name_Map = ucMapper.mapCategoryIDToName()
+		category_Name_ID_Map = ucMapper.mapCategoryNameToID()
+
+		currUser = Session.getUser()
+		
+		gOut = GeneralOutputClass()
+					
+		if cmd =='create':
+			
+			username = user.getUsername()
+			firstname = user.getFirstName()
+			lastname = user.getLastName()
+			email = user.getEmail()
+			passwd = user.getPassword()
+			
+			lab = user.getLab()
+			uLabID = lab.getID()
+			uLabName = lab.getName()
+			
+			labs = lHandler.findAllLabs()
+
+			# changed Aug. 18/08 - new format
+			#content = gOut.printHeader() + gOut.printMainMenu()
+			content = gOut.printHeader()
+			
+			content += '''
+				<FORM NAME="create_user_form" METHOD="POST" ACTION="%s" onSubmit="return verifyAddUser();">
+
+					<!-- pass current user as hidden form field -->
+					<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username"'''
+					
+			content += "value=\"" + currUser.getFullName() + "\">"
+			
+			content += '''
+					<TABLE width="760px" cellpadding="5" cellspacing="5">
+
+						<TH colspan="4" style="color:#0000FF; border-top:1px groove black; border-bottom: 1px groove black; padding-top: 10px; padding-top:5px;">
+							ADD NEW USER
+							<P style="color:#FF0000; font-weight:normal; font-size:8pt; margin-top:5px;">Fields in red marked with an asterisk (<span style="font-size:9pt; color:#FF0000;">*</span>) are mandatory</P>
+						</TH>
+
+						<TR>
+							<TD style="width:150px; vertical-align:top; padding-top:10px; color:#FF0000;">
+								Laboratory: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+							</TD>
+
+							<TD style="vertical-align:top; padding-top:10px">
+								<SELECT id="labList" name="labs">
+									<OPTION>Select Lab</OPTION>
+								'''
+			# sort labs by name
+			labSortedDict = {}		# will store (labName, labID) tuples 
+			labNames = []			# just hold lab names
+			
+			for labID in labs.keys():
+				labName = labs[labID]
+				labNames.append(labName)
+				labSortedDict[labName] = labID
+				
+			labNames.sort()
+
+			#for labID in labs.keys():
+			for labName in labNames:
+				labID = labSortedDict[labName]
+				labName = labs[labID]
+				content += "<OPTION ID=\"" + `labID` + "\" NAME=\"lab_optn\" VALUE=\"" + `labID` + "\""
+				
+				if labID == uLabID:
+					content += " SELECTED>" + labName
+				else:
+					content += ">" + labName
+					
+				content += "</OPTION>"
+					
+			content += '''
+								</SELECT>
+								<BR/>
+								<P id="lab_warning" style="color:#FF0000; display:none">Please select a laboratory name from the dropdown list above.</P>
+							</TD>
+						</TR>
+
+						<TR>
+							<TD class="createViewColName" style="color:#FF0000;">
+								Username: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+							</TD>
+
+							<TD class="createViewColValue">
+								<INPUT TYPE="TEXT" SIZE="35px" id="user_name" NAME="username" VALUE="%s"/>
+								<BR/>
+								<!-- Warning anchor -->
+								<a name="w1" style="text-decoration:none; font-weight:normal; font-size:8pt">
+								
+								<P id="dup_uname_warning" style="color:#FF0000; display:inline">This username already exists.  Please specify a different username.</P>
+								</a>
+							</TD>
+
+							<TD style="font-size:8pt">
+								Alphanumeric string up to 10 characters used to log into the system.
+							</TD>
+						</TR>
+
+						<TR>
+							<TD class="createViewColName" style="color:#FF0000;">
+								Password: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+							</TD>
+
+							<TD class="createViewColValue">
+								<INPUT TYPE="PASSWORD" SIZE="35px" id="passwd" NAME="password" VALUE="%s"/>
+							</TD>
+						</TR>
+
+						<TR>
+							<TD class="createViewColName" style="color:#FF0000;">
+								First name: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+							</TD>
+
+							<TD class="createViewColValue">
+								<INPUT TYPE="TEXT" SIZE="35px" id="first_name" NAME="firstName" VALUE="%s"/>
+							</TD>
+						</TR>
+
+						<TR>
+							<TD class="createViewColName" style="color:#FF0000;">
+								Last name: <sup style="font-size:10pt; color:#FF0000;">*</sup>
+							</TD>
+
+							<TD class="createViewColName">
+								<INPUT TYPE="TEXT" SIZE="35px" id="last_name" NAME="lastName" VALUE="%s"/>
+							</TD>
+						</TR>
+
+						<TR>
+							<TD class="createViewColName">
+								Email:
+							</TD>
+
+							<TD class="createViewColValue">
+								<INPUT TYPE="TEXT" SIZE="35px" id="e_mail" NAME="email" VALUE="%s"/>
+							</TD>
+						</TR>
+
+						<TR>
+							<TD>
+								Access Level:
+							</TD>
+
+							<TD class="createViewColName"  colspan="3">
+								<INPUT TYPE="RADIO" name="system_access_level" value="Reader" style="margin-top:8px; font-size:9pt" checked>Reader<BR/>
+								<INPUT TYPE="RADIO" name="system_access_level" value="Writer" style="margin-top:8px; font-size:9pt">Writer<BR/>
+								<INPUT TYPE="RADIO" name="system_access_level" value="Creator" style="margin-top:8px; font-size:9pt">Creator<BR/>
+								<INPUT TYPE="RADIO" name="system_access_level" value="Admin" style="margin-top:8px; font-size:9pt">Admin<BR/>
+							</TD>
+						</TR>				
+
+						<TR id="project_access">
+							<TD colspan="4">
+								<TABLE width="100%%">
+									<TR>
+										<TD colspan="4" style="border-top:1px groove black; border-bottom:1px groove black; padding-top:8px; font-size:8pt; font-weight:bold">
+											Grant project access permissions to this user:
+										</TD>
+									</TR>
+
+									<TR>
+										<TD style="width:210px">
+											<SELECT id="packetList" name="packets" multiple size="15">
+											'''
+			# PRINT PROJECT LIST
+			projects = pHandler.findAllProjects()
+			
+			for project in projects:
+				projectNumber = project.getNumber()	
+				projectName = project.getName()
+				
+				tmpProject = `projectNumber` + ": " + projectName
+				
+				content += "<OPTION value=\"" + `projectNumber` + "\">" + tmpProject + "</OPTION>"
+				
+			content += '''
+											</SELECT>
+											<BR/>
+											<INPUT TYPE="checkbox" style="margin-top:10px; font-size:8pt;" onClick="selectAll(this.id, 'packetList')" id="add_all_chkbx"> Select All</INPUT>
+										</TD>
+
+										<TD style="vertical-align:top" colspan="3">
+											<span style="font-size:8pt; font-weight:bold">User's access level to selected projects:<BR/></span>
+											<input type="radio" id="access_level_radio_read" name="access_levels" value="read" style="margin-top:8px; font-size:9pt" checked>Read-Only    <BR/>
+											<input type="radio" id="access_level_radio_write" name="access_levels" value="write" style="margin-top:5px; font-size:9pt">Write    <BR/>
+											<input style="margin-top:8px" onclick="addProjects('packetList', getSelectedRole('1'))" value="Go" type="button"></INPUT>
+
+											<P style="font-size:8pt; border-top:1px groove black; padding-top:10px; padding-bottom:5px; margin-top:10px">
+											Access levels: <BR/>
+											<span style="font-size: 8pt; margin-left: 9px; font-weight:bold; ">- Read-Only:</span>  May view reagents in a project but may NOT modify them or add new reagents<BR/>
+
+											<span style="font-size: 8pt; margin-left: 9px; font-weight:bold;">- Write:</span>  May create and modify reagents in a project but may NOT change project details or add/remove members to/from the project<BR/>
+											</P>
+										</TD>
+									</TR>
+
+									<TR>
+										<TD colspan="4" style="border-top:1px groove black; border-bottom:1px groove black; font-size:8pt; font-weight:bold">
+											User's current project access privileges:
+										</TD>
+									</TR>
+
+									<TR>
+										<TD style="border-right:1px solid black; font-size:8pt">
+											<B>Read-Only</B><BR/>
+											<SELECT id="user_projects_readonly" name="userProjectsReadonly" style="margin-top:5px" multiple size="12">
+											'''
+			# August 10/07: Default reader access to all on public projects
+			publicProjects = pHandler.findAllProjects('FALSE')
+
+			for proj in publicProjects: 
+				pID = proj.getNumber()
+				pName = proj.getName();
+				
+				# concatenate project ID and name in the form '1:parent'
+				tmpDescr = `pID` + ": " + pName
+				
+				content += "<OPTION VALUE=\"" + `pID` + "\">" + tmpDescr + "</OPTION>"
+
+			content += '''
+											</SELECT><BR/>
+											<INPUT style="margin-top:10px;" TYPE="checkbox" onClick="selectAll(this.id, 'user_projects_readonly')" id="select_all_reader_chkbx"> Select All</INPUT>
+										</TD>
+
+										<TD style="text-align:center; width:100px; border-right: 1px solid black; padding-left:20px; padding-right:20px;">
+											<input onclick="addProjects('user_projects_readonly', 'write')" value="   Make Writeable >>" type="button"></INPUT><BR/>
+											<input style="margin-top:30px;" onclick="addProjects('user_projects_write', 'read')" value="<< Make Read-Only" type="button"></INPUT><BR/>
+											<input style="margin-top:30px;" onclick="addProjects('user_projects_write'); addProjects('user_projects_readonly')" value="Remove Selected" type="button"></INPUT>
+										</TD>
+
+										<TD style="padding-left:50px; font-size:8pt">
+											<B>Write</B><BR/>
+											<SELECT id="user_projects_write" name="userProjectsWrite" style="margin-top:5px" multiple size="12"></SELECT><BR/>
+											<INPUT style="margin-top:10px;" TYPE="checkbox" onClick="selectAll(this.id, 'user_projects_write')" id="select_all_writer_chkbx"> Select All</INPUT>
+										</TD>
+									</TR>
+								</TABLE>
+							</TD>
+						</TR>
+
+						<TR>
+							<TD colspan="4" style="border-top:1px groove black; border-bottom:1px groove black">
+								<INPUT TYPE="SUBMIT" id="addUser" NAME="add_user" VALUE="Add User" onClick="selectAllElements('user_projects_readonly'); selectAllElements('user_projects_write');">
+							</TD>
+						</TR>
+					</TABLE>
+				</FORM>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				
+				</div>
+				'''
+				
+			content += gOut.printFooter()
+			
+			page_content = content % (hostname + "cgi/user_request_handler.py", username, passwd, firstname, lastname, email)
+			
+			print "Content-type:text/html"		# THIS IS PERMANENT; DO NOT REMOVE
+			print					# DITTO
+			print page_content
+
+		elif cmd == 'view':
+
+			userID = user.getUserID()
+			username = user.getUsername()
+			firstname = user.getFirstName()
+			lastname = user.getLastName()
+			email = user.getEmail()
+			userCat = user.getCategory()
+			lab = user.getLab()
+			labID = lab.getID()
+			labName = lab.getName()
+			
+			# Only allow modification by admin
+			modify_disabled = True
+			
+			if (currUser.getCategory() == 'Admin'):
+				modify_disabled = False
+			
+			content = gOut.printHeader()
+			#content += gOut.printMainMenu()
+			
+			content += '''
+				<FORM name="user_form" method="POST" action="%s">
+							
+					<!-- pass current user as hidden form field -->
+					<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username"'''
+					
+			content += "value=\"" + currUser.getFullName() + "\">"
+			
+			content += '''
+					<TABLE width="767px" style="margin-left:2px" cellpadding="5px" cellspacing="5px" class="detailedView_tbl" border="1" frame="box" rules="none">
+						<TR>
+							<TD colspan="6" class="detailedView_heading" style="padding-left:265px">
+								USER DETAILS PAGE
+								'''
+			content += "<INPUT TYPE=\"submit\" style=\"margin-left:50px;\" name=\"modify_user\" value=\"Change User Details\""
+			
+			if modify_disabled:
+				content += " disabled>"
+			else:
+				content += ">"
+						
+			content += "<INPUT TYPE=\"submit\" style=\"margin-left:2px;\" name=\"delete_user\" value=\"Delete User\" onClick=\"return verifyDeleteUser();\""
+			
+			if modify_disabled:
+				content += " disabled>"
+			else:
+				content += ">"
+
+				
+			content += '''
+							</TD>
+
+						</TR>
+
+						<TR>
+							<TD class="projectDetailedViewName" width="50px">
+								Username:
+							</TD>
+
+							<TD class="detailedView_value" colspan="2" style="width:400px">
+								%s
+								<INPUT TYPE="hidden" name="username" value="%s">
+
+								<!-- user ID a hidden value -->
+								<INPUT TYPE="hidden" name="userID" value="%d">
+							</TD>
+						</TR>
+
+						<TR>
+							<TD class="projectDetailedViewName" width="50px">
+								First Name:
+							</TD>
+
+							<TD class="detailedView_value" colspan="2" style="width:400px">
+								%s
+								<INPUT TYPE="hidden" name="firstName" value="%s">
+							</TD>
+						</TR>
+
+						<TR>
+							<TD class="projectDetailedViewName" width="50px">
+								Last Name:
+							</TD>
+
+							<TD class="detailedView_value" colspan="2" style="width:400px">
+								%s
+								<INPUT TYPE="hidden" name="lastName" value="%s">
+							</TD>
+						</TR>
+						
+						<TR>
+							<TD class="projectDetailedViewName" width="50px">
+								Laboratory:
+							</TD>
+
+							<TD class="detailedView_value" colspan="2" style="width:400px">
+							'''
+			if modify_disabled:
+				content += labName
+			else:
+				content += "<span class=\"linkShow\" onClick=\"redirectToLabView(" + `labID` + ");\">" + labName + "</span>"
+			
+			content += '''
+								<INPUT TYPE="hidden" name="labID" value="%d">
+								<INPUT type="hidden" id="view_lab_hidden" name="view_lab">
+							</TD>
+						</TR>
+						
+						<TR>
+							<TD class="projectDetailedViewName" width="50px">
+								Email:
+							</TD>
+
+							<TD class="detailedView_value" colspan="2" style="width:400px">
+								%s
+								<INPUT TYPE="hidden" name="email" value="%s">
+							</TD>
+						</TR>
+						
+						<TR>
+							<TD class="projectDetailedViewName" width="50px">
+								Access Level:
+							</TD>
+
+							<TD class="detailedView_value" colspan="2" style="width:400px">
+								%s
+								<INPUT TYPE="hidden" name="system_access_level" value="%d">
+							</TD>
+						</TR>
+						
+						
+						<TR>
+							<TD class="projectDetailedViewName" width="50px">
+								Projects:
+							</TD>
+							
+						</TR>
+						
+						<TR>
+							<TD style="font-weight:bold; font-size:8pt; width:250px" colspan="2">
+								Read-Only:
+							</TD>
+							
+							<TD style="font-weight:bold; font-size:8pt">
+								Write:
+							</TD>
+						</TR>
+
+						<TR>
+							<TD style="vertical-align:top;" colspan="2">
+								<UL>
+								'''
+			# show projects for the user
+			publicProj = pHandler.findAllProjects("FALSE")
+			readOnlyProj = pHandler.findMemberProjects(userID, 'Reader')
+			readProj = utils.merge(publicProj, readOnlyProj)
+			writeProj = pHandler.findMemberProjects(userID, 'Writer')
+			
+			# sort read projects
+			readKeys = []
+			readSorted = {}
+			
+			for r in readProj:
+				rProjectID = r.getNumber()
+				readKeys.append(rProjectID)
+				readSorted[rProjectID] = r
+			
+			readKeys = utils.unique(readKeys)
+			readKeys.sort()
+			
+			#for r in readProj:
+			for rProjectID in readKeys:
+				#rProjectID = r.getNumber()
+				r = readSorted[rProjectID]
+				rProjectName = r.getName()
+				rProjectOwner = r.getOwner()
+
+				try:
+					rOwnerName = rProjectOwner.getLastName()
+				except AttributeError:
+					rOwnerName = ""
+
+				#content += "<LI>" + `rProjectID` + ": " + rOwnerName + ": " + rProjectName
+				
+				content += "<LI>"
+				content += "<span class=\"linkShow\" onClick=\"redirectToProjectDetailedView(" + `rProjectID` + ");\">" + `rProjectID` + ": " + rOwnerName + ": " + rProjectName + "</span>"
+				content += "</LI>"
+
+					
+			content += '''
+								</UL>
+							</TD>
+							
+							<TD style="vertical-align:top;">
+								<UL>
+								'''
+			# sort write projects
+			writeKeys = []
+			writeSorted = {}
+			
+			for w in writeProj:
+				wProjectID = w.getNumber()
+				writeKeys.append(wProjectID)
+				writeSorted[wProjectID] = w
+				
+			writeKeys = utils.unique(writeKeys)
+			writeKeys.sort()
+			
+			#for w in writeProj:
+			for wProjectID in writeKeys:
+				#wProjectID = w.getNumber()
+				w = writeSorted[wProjectID]
+				wProjectName = w.getName()
+				wProjectOwner = w.getOwner()
+				wOwnerName = wProjectOwner.getLastName()
+										
+				#content += "<LI>" + `wProjectID` + ": " + wProjectName
+			
+				content += "<LI>"
+				content += "<span class=\"linkShow\" onClick=\"redirectToProjectDetailedView(" + `wProjectID` + ");\">" + `wProjectID` + ": " + wOwnerName + ": " + wProjectName + "</span>"
+				content += "</LI>"
+
+			content += '''
+								</UL>
+							</TD>
+						</TR>
+					</TABLE>
+				</FORM>
+				
+				<FORM id="viewProjectForm" method="POST" action="%s">
+					<INPUT type="hidden" id="view_packet_hidden" name="view_packet">
+					<INPUT type="hidden" ID="curr_userid_hidden" NAME="curr_user_id" value="%d">
+				</FORM>
+				
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				
+			</div>
+			'''
+
+			content += gOut.printFooter()
+		
+			page_content = content % (hostname + "cgi/user_request_handler.py", username, username, userID, firstname, firstname, lastname, lastname, labID, email, email, userCat, category_Name_ID_Map[userCat], hostname + "cgi/project_request_handler.py", currUser.getUserID())
+
+			print "Content-type:text/html"		# 
+			print					# DITTO
+			print page_content
+
+		elif cmd == 'edit':
+					
+			userID = user.getUserID()
+			username = user.getUsername()
+			firstname = user.getFirstName()
+			lastname = user.getLastName()
+			email = user.getEmail()
+			passwd = user.getPassword()
+			userCat = user.getCategory()
+			
+			lab = user.getLab()
+			uLabID = lab.getID()
+			labName = lab.getName()
+			
+			labs = lHandler.findAllLabs()
+		
+			if errCode == "Dup_un":
+				un_warn_display = "inline"
+			else:
+				un_warn_display = "none"
+			
+			
+			content = gOut.printHeader()
+			#content += gOut.printMainMenu()
+			
+			content += '''
+				<FORM name="user_form" method="POST" action="%s" onSubmit="return verifyWriteProjects();">
+					
+					<!-- pass current user as hidden form field -->
+					<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username"'''
+					
+			content += "value=\"" + currUser.getFullName() + "\">"
+
+			content += '''
+					<TABLE width="760px" cellpadding="5px" cellspacing="5px" style="border:1px solid black" frame="box" rules="rows">
+					<TR>
+						<TD colspan="3" style="padding-left:200px; text-align:center">
+							<span style="color:#0000FF; font-weight:bold">CHANGE USER INFORMATION</span>
+							<INPUT TYPE="submit" style="margin-left:50px;" name="save_user" value="Save" onClick="selectAllElements('user_projects_readonly'); selectAllElements('user_projects_write');">
+							<INPUT TYPE="submit" style="margin-left:20px;" name="cancel_user" value="Cancel">
+						</TD>
+					</TR>
+					
+					<TR>
+						<TD class="projectDetailedViewName">
+							Username:
+						</TD>
+
+						<TD class="detailedView_value" style="width:400px">
+							<INPUT TYPE="text" size="50px" name="username" value="%s">
+							<BR/>
+							
+							<!-- Warning anchor -->
+							<a name="w1" style="text-decoration:none; font-weight:normal; font-size:8pt">
+							<P id="dup_uname_warning" style="color:#FF0000; display:%s">This username already exists.  Please specify a different username.</P>
+							</a>
+							
+							<!-- user ID hidden value -->
+							<INPUT TYPE="hidden" name="userID" value="%d">
+						</TD>
+					</TR>
+
+
+					<TR>
+						<TD class="projectDetailedViewName">
+							Laboratory:
+						</TD>
+
+						<TD style="vertical-align:top; padding-top:10px">
+							<SELECT id="labList" name="labs">
+							'''
+			# sort labs by name
+			labSortedDict = {}		# will store (labName, labID) tuples 
+			labNames = []			# just hold lab names
+			
+			for labID in labs.keys():
+				labName = labs[labID]
+				labNames.append(labName)
+				labSortedDict[labName] = labID
+				
+			labNames.sort()
+			
+			#for labID in labs.keys():
+			for labName in labNames:
+				labID = labSortedDict[labName]
+				labName = labs[labID]
+				content += "<OPTION ID=\"" + `labID` + "\" NAME=\"lab_optn\" VALUE=\"" + `labID` + "\""
+				
+				if labID == uLabID:
+					content += " SELECTED>" + labName
+				else:
+					content += ">" + labName
+					
+				content += "</OPTION>"
+					
+			content += '''
+							</SELECT>
+						</TD>
+					</TR>
+					
+					<TR>
+						<TD class="projectDetailedViewName">
+							First Name:
+						</TD>
+
+						<TD class="detailedView_value" colspan="2">
+							<INPUT TYPE="text" size="50px" name="firstName" value="%s">
+						</TD>
+					</TR>
+
+					<TR>
+						<TD class="projectDetailedViewName">
+							Last Name:
+						</TD>
+
+						<TD class="detailedView_value" colspan="2">
+							<INPUT TYPE="text" size="50px" name="lastName" value="%s">
+						</TD>
+					</TR>
+										
+					<TR>
+						<TD class="projectDetailedViewName">
+							Email:
+						</TD>
+
+						<TD class="detailedView_value" colspan="2">
+							<INPUT TYPE="text" size="50px" name="email" value="%s">
+						</TD>
+					</TR>
+					
+					<TR>
+						<TD class="projectDetailedViewName">
+							Access Level:
+						</TD>
+						
+						<TD class="detailedView_value" colspan="2">
+							<SELECT ID="user_category" NAME="system_access_level">
+						'''
+			ucHandler = UserCategoryHandler(db, cursor)
+			categories = ucHandler.findAllCategories()
+			
+			for cID in categories.keys():
+				
+				if categories[cID] == userCat:
+					content += "<OPTION VALUE=\"" + `cID` + "\" SELECTED>" + categories[cID] + "</OPTION>"
+				else:
+					content += "<OPTION VALUE=\"" + `cID` + "\">" + categories[cID] + "</OPTION>"
+
+			# Don't allow addition of Writeable projects to Readers thru Modify view
+			if userCat == 'Reader':
+				write_disabled = True
+			else:
+				write_disabled = False
+				
+			content += '''
+							</SELECT>
+						</TD>
+					</TR>
+					
+					<TR>
+						<TD class="detailedView_value" colspan="3">
+							Projects user has access to:
+						</TD>
+					</TR>
+
+					<TR>
+						<td colspan="3">
+							<table width="700px">
+								<tr>
+									<TD colspan="2" style="font-size:8pt; vertical-align:top"">
+										Read-Only
+									</TD>
+									
+									<TD style="font-size:8pt; vertical-align:top">
+									'''
+			if not write_disabled:
+				content += "Write"
+			else:
+				content += " "
+			
+			content += '''
+									</TD>
+								</TR>
+								
+								<TR>
+									<TD style="">
+										<SELECT id="user_projects_readonly" name="userProjectsReadonly" style="margin-top:5px" multiple size="12">
+										'''
+										
+			# show projects for the user
+			readProj = pHandler.findMemberProjects(userID, 'Reader')
+			writeProj = pHandler.findMemberProjects(userID, 'Writer')
+		
+			for r in readProj:
+				rProjectID = r.getNumber()
+				rProjectName = r.getName()
+				
+				content += "<OPTION name=\"project_read\" value=\"" + `rProjectID` + "\">" + `rProjectID` + ": " + rProjectName + "</OPTION>"
+					
+			content += '''
+										</SELECT>
+										<BR/>
+										
+										<INPUT TYPE="checkbox" style="margin-top:10px;" onClick="selectAll(this.id, 'user_projects_readonly')" id="select_all_reader_chkbx"> Select All</INPUT>
+						'''
+			if not write_disabled:
+				content += '''
+									</TD>
+			
+									<TD style="text-align:center; padding-right:15px;">
+			
+										<input onclick="addProjects('user_projects_readonly', 'write')" value="   Make Writeable >>" type="button"></INPUT><BR/>
+								
+										<input style="margin-top:30px;" onclick="addProjects('user_projects_write', 'read')" value="<< Make Read-Only" type="button"></INPUT><BR/>
+			
+										 <input type="button" style="margin-top:30px;" value="Remove" onclick="removeUserProjects();"></INPUT>
+									</TD>
+									'''
+			
+			else:
+				content += '''
+						 <input type="button" value="Remove Selected" onclick="removeUserProjects();"></INPUT>
+						'''
+			if not write_disabled:
+				content += '''	
+									<TD style="font-size:8pt">
+								
+										<SELECT id="user_projects_write" name="userProjectsWrite" style="margin-top:5px" multiple size="12">
+										'''
+				for w in writeProj:
+					wProjectID = w.getNumber()
+					wProjectName = w.getName()
+					
+					content += "<OPTION name=\"project_write\" value=\"" + `wProjectID` + "\">" + `wProjectID` + ": " + wProjectName + "</OPTION>"
+						
+				content += '''
+										</SELECT><BR/>
+										
+										<INPUT style="margin-top:10px;" TYPE="checkbox" onClick="selectAll(this.id, 'user_projects_write')" id="select_all_writer_chkbx"> Select All</INPUT>
+									</TD>
+									'''
+				
+			content += '''
+								</TR>
+							</table>
+						</td>
+					</tr>
+						
+					<TR>
+						<TD class="detailedView_value" colspan="3">
+							Add new projects:
+						</TD>
+					</TR>
+					
+					<TR>
+						<TD colspan="3">
+							<TABLE>
+								<TR>
+									<TD>
+										<SELECT multiple ID="packetList">
+							'''
+			# Fetch the list of read and write projects for this user and extract their IDs
+			readProjID = []	# list of numerical IDs of read projects
+			
+			for r in readProj:
+				rNum = r.getNumber()
+				readProjID.append(rNum)
+							
+			writeProjID = []
+			
+			for w in writeProjID:
+				wNum = w.getNumber()
+				writeProjID.append(wNum)
+			
+			allPackets = pHandler.findAllProjects()
+			
+			for p in allPackets:
+				pID = p.getNumber()
+				pName = p.getName()
+				pOwner = p.getOwner()
+			
+				#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+				#print					# DITTO
+				#print `pOwner`
+
+				# update March 11, 2011
+				try:
+					lastName = pOwner.getLastName()
+				except AttributeError:
+					lastName = ""
+
+				#pDesc = `pID` + " : " + pOwner + " : " + pName
+				pDesc = `pID` + " : " + lastName + " : " + pName
+				
+				if not pID in readProjID and not pID in writeProjID:
+					content += "<OPTION VALUE=\"" + `pID` + "\">" + pDesc
+
+			content += '''
+										</SELECT>
+										<BR>
+										<INPUT TYPE="checkbox" style="margin-top:10px; font-size:8pt;" onClick="selectAll(this.id, 'packetList')" id="add_all_chkbx"> Select All</INPUT>
+						'''
+
+			if not write_disabled:
+				content += '''	
+									</TD>
+								
+									<TD style="vertical-align:top">
+										<span style="font-size:8pt; font-weight:bold">User's access level to selected projects:<BR/></span>
+										<input type="radio" id="access_level_radio_read" name="access_levels" value="read" style="margin-top:8px; font-size:9pt" checked>Read-Only    <BR/>
+										<input type="radio" id="access_level_radio_write" name="access_levels" value="write" style="margin-top:5px; font-size:9pt">Write    <BR/>
+										<input style="margin-top:8px" onclick="addProjects('packetList', getSelectedRole('1'))" value="Add project" type="button"></INPUT>
+									</TD>
+								</TABLE>
+							</TD>
+						</TR>
+						'''
+			else:
+				content += '''
+						<input style="margin-left:5px; margin-top:8px" onclick="addProjects('packetList', 'read')" value="Add project" type="button"></INPUT>
+						'''
+
+			content += '''
+					</TR>
+				</TABLE>
+			</FORM>
+			
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>	
+			</div>
+			'''
+				
+			content += gOut.printFooter()
+		
+			page_content = content % (hostname + "cgi/user_request_handler.py", username, un_warn_display, userID, firstname, lastname, email)
+		
+			print "Content-type:text/html"		# THIS IS PERMANENT; DO NOT REMOVE
+			print					# DITTO
+			print page_content
+
+	
+	#############################################
+	# Laboratory detailed view
+	#############################################
+	def printLabInfo(self, cmd, newLab, errCode=""):
+		dbConn = DatabaseConn()
+		hostname = dbConn.getHostname()		# to define form action URL
+		
+		db = dbConn.databaseConnect()
+		cursor = db.cursor()
+		
+		uHandler = UserHandler(db, cursor)
+		lHandler = LabHandler(db, cursor)
+		
+		currUser = Session.getUser()
+		
+		gOut = GeneralOutputClass()
+
+		if cmd == 'view':
+
+			labID = newLab.getID()
+			labHead = newLab.getLabHead()
+			labName = newLab.getName()
+			labCode = newLab.getLabCode()
+			labDescr = newLab.getDescription()
+			address = newLab.getAddress()
+			accessLevel = newLab.getDefaultAccessLevel()
+			
+			# Determine if 'Delete' button should be disabled - if there are members in the lab, disallow deletion
+			labMembers = lHandler.findMembers(labID)
+
+			delete_disabled = True
+
+			if len(labMembers) == 0:
+				delete_disabled = False
+			
+			# Only allow modification by admin
+			modify_disabled = True
+			
+			# July 3/07: Can further disallow modification of labs other than the one currUser belongs to; however, this might be too restrictive.  Keep it in the back of our minds but out of the website for now.
+			#if (currUser.getCategory() == 'Admin') and (currUser.getLab().getID() == labID):
+			if (currUser.getCategory() == 'Admin'):
+				modify_disabled = False
+			
+			#content = gOut.printHeader() + gOut.printMainMenu()
+			content = gOut.printHeader()
+			
+			content += '''
+				<FORM name="lab_form" method="POST" action="%s">
+			
+					<!-- pass current user as hidden form field -->
+					<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username"'''
+					
+			content += "value=\"" + currUser.getFullName() + "\">"
+			
+			content += '''
+					<TABLE width="775px" cellpadding="5px" cellspacing="5px" class="detailedView_tbl">
+						<TR>
+							<TD colspan="6" class="detailedView_heading" style="padding-left:250px">
+								LABORATORY DETAILS PAGE
+								'''
+			content += "<INPUT TYPE=\"submit\" style=\"margin-left:50px;\" name=\"modify_lab\" value=\"Change Lab Info\""
+			
+			if modify_disabled:
+				content += " disabled>"
+			else:
+				content += ">"
+							
+			content += "<INPUT TYPE=\"submit\" style=\"margin-left:2px;\" name=\"delete_lab\" value=\"Delete Lab\" onClick=\"return verifyDeleteLab()\""
+			
+			if modify_disabled or delete_disabled:
+				content += " disabled>"
+			else:
+				content += ">"
+				
+			content += '''
+							</TD>
+
+						</TR>
+					
+						<TR>
+							<TD class="projectDetailedViewName">
+								Name:
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								%s
+								<INPUT TYPE="hidden" name="labName" value="%s">
+
+								<!-- lab ID a hidden value -->
+								<INPUT TYPE="hidden" name="labID" value="%d">
+							</TD>
+						</TR>
+
+						<TR>
+							<TD class="projectDetailedViewName">
+								Lab head:
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								%s
+								<INPUT TYPE="hidden" name="labHead" value="%s">
+							</TD>
+						</TR>
+
+						<TR>
+							<TD class="projectDetailedViewName">
+								Lab ID:
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								%s
+								<INPUT TYPE="hidden" name="labCode" value="%s">
+							</TD>
+						</TR>
+						
+						<TR>
+							<TD class="projectDetailedViewName">
+								Description:
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								%s
+								<INPUT TYPE="hidden" name="labDescription" value="%s">
+							</TD>
+						</TR>
+
+						<TR>
+							<TD class="projectDetailedViewName">
+								Location:
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								%s
+								<INPUT TYPE="hidden" name="address" value="%s">
+							</TD>
+						</TR>
+						
+						<TR>
+							<TD class="projectDetailedViewName" style="white-space:nowrap">
+								Default access level:
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								%s
+								<INPUT TYPE="hidden" name="access" value="%s">
+							</TD>
+						</TR>
+						
+						<!-- Members -->
+						<TR>
+							<TD class="projectDetailedViewName">
+								Members:
+							</TD>
+							
+							<TD class="detailedView_value" style="width:400px">
+								<UL>
+							'''
+			
+			content += "<INPUT type=\"hidden\" id=\"view_user_hidden\" name=\"view_user\">"
+				
+			for member in labMembers:
+				mName = member.getFullName()
+				memberID = member.getUserID()
+				#content += "<LI>" + mName
+				content += "<LI>"
+				content += "<span class=\"linkShow\" onClick=\"redirectToUserDetailedView(" + `memberID` + ");\">" + mName + "</span>"
+				content += "</LI>"
+
+			content += '''
+								</UL>
+							</TD>
+						</TR>
+					</TABLE>
+				</FORM>
+				
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+			</div>
+			'''
+				
+			content += gOut.printFooter()
+			
+			page_content = content % (hostname + "cgi/user_request_handler.py", labName, labName, labID,  labHead, labHead, labCode, labCode, labDescr, labDescr, address, address, accessLevel, accessLevel)
+
+			print "Content-type:text/html"		# THIS IS PERMANENT; DO NOT REMOVE
+			print					# DITTO
+			print page_content
+
+		elif cmd == 'edit':
+			
+			labID = newLab.getID()
+			labName = newLab.getName()
+			labHead = newLab.getLabHead()
+			labCode = newLab.getLabCode()
+			labDescr = newLab.getDescription()
+			address = newLab.getAddress()
+			accLev = newLab.getDefaultAccessLevel()
+			
+			# Disable name modification if there are members in lab
+			labMembers = lHandler.findMembers(labID)
+
+			name_readonly = True
+
+			if len(labMembers) == 0:
+				name_readonly = False
+
+			# hide/show duplicate lab code warning
+			if errCode == 14:
+				dup_lab_code_warn_display = "inline"
+			else:
+				dup_lab_code_warn_display = "none"
+			
+			#content = gOut.printHeader() + gOut.printMainMenu()
+			content = gOut.printHeader()
+			
+			content += '''
+				<FORM name="user_form" method="POST" action="%s">
+
+					<!-- pass current user as hidden form field -->
+					<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username"'''
+			content += "value=\"" + currUser.getFullName() + "\">"
+
+			content += '''
+					<TABLE width="760px" cellpadding="5px" cellspacing="5px" style="border:1px solid black" frame="box" rules="rows">
+					<TR>
+						<TD colspan="3" style="padding-left:100px; text-align:center">
+							<span style="color:#0000FF; font-weight:bold">CHANGE LABORATORY INFORMATION</span>
+							<INPUT TYPE="submit" style="margin-left:180px;" name="save_lab" value="Save" onClick="selectAllElements('labMembersList'); return checkLab();">
+							<INPUT TYPE="submit" style="margin-left:20px;" name="cancel_lab" value="Cancel">
+						</TD>
+					</TR>
+					
+					<TR>
+						<TD class="projectDetailedViewName">
+							Name:
+						</TD>
+
+						<TD class="detailedView_value" style="width:400px" colspan="2">
+							'''
+							
+			if name_readonly:
+				content += "<INPUT TYPE=\"text\" size=\"50px\" id=\"lab_name\" name=\"labName\" value=\"%s\" readonly>"
+			else:
+				content += "<INPUT TYPE=\"text\" size=\"50px\" id=\"lab_name\" name=\"labName\" value=\"%s\">"
+				
+			content += '''
+							<!-- lab ID hidden value -->
+							<INPUT TYPE="hidden" name="labID" value="%d">
+						</TD>
+					</TR>
+
+					<TR>
+						<TD class="projectDetailedViewName">
+							Lab head:
+						</TD>
+
+						<TD class="detailedView_value" style="width:400px" colspan="2">
+							<INPUT TYPE="text" size="50px" id="lab_head" name="labHead" value="%s">
+						</TD>
+					</TR>
+					
+					<TR>
+						<TD class="projectDetailedViewName">
+							Lab ID:
+						</TD>
+
+						<TD class="detailedView_value" style="width:400px" colspan="2">
+							<INPUT TYPE="text" size="50px" id="lab_id" name="labCode" value="%s">
+							<BR>
+							<SPAN id="dup_labcode_warning" style="vertical-align:bottom; color:#FF0000; display:%s">This identifier already exists.  Please specify a different lab ID.</SPAN>
+						</TD>
+					</TR>
+
+					<TR>
+						<TD class="projectDetailedViewName">
+							Description:
+						</TD>
+
+						<TD class="detailedView_value" colspan="2">
+							<INPUT TYPE="text" size="50px" id="lab_descr" name="description" value="%s">
+						</TD>
+					</TR>
+
+					<TR>
+						<TD class="projectDetailedViewName">
+							Location:
+						</TD>
+
+						<TD class="detailedView_value" colspan="2">
+							<INPUT TYPE="text" size="50px" id="lab_location" name="address" value="%s">
+						</TD>
+					</TR>
+										
+					<TR>
+						<TD style="width:50px; vertical-align:top; padding-top:10px; white-space:nowrap; font-size:8pt">
+							Default access level:
+						</TD>
+
+						<TD style="font-size:8pt; vertical-align:top; width:50px;">
+						'''
+			# Determine which category radio button should be checked
+			ucHandler = UserCategoryHandler(db, cursor)
+			categories = ucHandler.findAllCategories()
+			
+			for cID in categories.keys():
+				cat = categories[cID]
+				content += "<INPUT TYPE=\"RADIO\" name=\"system_access_level\" value=\"" + cat + "\" style=\"margin-top:8px; font-size:8pt\" onClick=\"showHideProjectAccess()\""
+				
+				if cat == accLev:
+					content += " checked"
+				
+				content += ">" + cat + "<BR/>"
+				
+			content += '''
+						</TD>
+					</TR>
+					
+					<!-- Members - allow deletion -->
+					<TR>
+						<TD style="width:50px; vertical-align:top; padding-top:10px; font-size:8pt">
+							<b>Members:</b>
+							<BR/><BR/>
+							Select one or more members to remove them from the system.<BR/><BR/>
+							
+							(hold down CTRL key to select multiple names)
+						</TD>
+
+						<TD style="font-size:8pt; vertical-align:top; width:50px;">
+							<SELECT MULTIPLE SIZE="10" ID="labMembersList" NAME="labMembers">
+						'''
+			members = lHandler.findMembers(labID)
+			
+			for  member in members:
+				mName = member.getFullName()
+				memberID = member.getUserID()
+				
+				content += "<OPTION value=\"" + `memberID` + "\">" + mName + "</OPTION>"
+			
+			content += '''
+							</SELECT>
+						</TD>
+						
+						<TD>
+							<INPUT TYPE=\"button\" onClick=\"removeLabMembers('labMembersList')\" value=\"Remove Selected Members\">
+						</TD>
+					</TR>
+				</TABLE>
+			</FORM>
+			
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+			<blockquote> </blockquote>
+		
+			</div>
+			'''
+			
+			content += gOut.printFooter()
+			
+			page_content = content % (hostname + "cgi/user_request_handler.py", labName, labID, labHead, labCode, dup_lab_code_warn_display, labDescr, address)
+
+			print "Content-type:text/html"		# THIS IS PERMANENT; DO NOT REMOVE
+			print					# DITTO
+			print page_content
diff --git a/OpenFreezer/cgi/user_request_handler.py b/OpenFreezer/cgi/user_request_handler.py
new file mode 100755
index 0000000..c2884b1
--- /dev/null
+++ b/OpenFreezer/cgi/user_request_handler.py
@@ -0,0 +1,990 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+
+import SocketServer
+from SocketServer import BaseRequestHandler
+
+import smtplib
+#import mimetypes,mimetools,MimeWriter		# deprecated
+
+import email
+from email import *
+
+#from email import MIMEText
+#from email import MIMEMultipart
+#from email import MIMEBase
+#from email import Utils 
+#from email.Utils import COMMASPACE, formatdate
+#from email import Encoders
+
+import MySQLdb
+
+import os
+import tempfile
+import stat
+import sys
+import string
+
+from random import choice	# June 1, 2010: random password generation
+
+# July 30, 2010
+import MimeWriter
+import mimetools
+import cStringIO
+
+# Custom modules
+import utils
+
+from database_conn import DatabaseConn
+from exception import DuplicateUsernameException, DeletedUserException, DuplicateLabCodeException
+from session import Session
+
+from packet import Packet
+from user import User
+from laboratory import Laboratory
+
+from project_database_handler import ProjectDatabaseHandler
+from user_handler import UserHandler
+from lab_handler import LabHandler
+from mapper import UserCategoryMapper
+
+from user_output import UserOutputClass
+
+#####################################################################################
+# Contains functions to handle User creation, modification and deletion requests
+#
+# Written June 28, 2007, by Marina Olhovsky
+# Last modified: Sept. 17, 2007
+#####################################################################################
+#class UserRequestHandler(BaseRequestHandler):
+class UserRequestHandler:
+	__db = None
+	__cursor = None
+	__hostname = ""
+	__clone_request = ""
+	__mail_programmer = ""
+	__mail_biologist = ""
+	__mail_server = ""		# August 19, 2011
+
+	##########################################################
+	# Constructor
+	##########################################################
+	def __init__(self):
+	
+		dbConn = DatabaseConn()
+		db = dbConn.databaseConnect()
+		cursor = db.cursor()
+		hostname = dbConn.getHostname()
+		clone_request = dbConn.getMailCloneRequest()
+		
+		mail_programmer = dbConn.getProgrammerEmail()
+		mail_biologist = dbConn.getBiologistEmail()
+		mail_admin = dbConn.getAdminEmail()		# August 19, 2011
+
+		mail_server = dbConn.getMailServer()		# August 19, 2011
+
+		self.__db = db
+		self.__cursor = cursor
+		self.__hostname = hostname
+		self.__clone_request = clone_request
+		self.__mail_programmer = mail_programmer	# July 30, 2010
+		self.__mail_biologist = mail_biologist		# July 30, 2010
+		self.__mail_admin = mail_admin			# August 19, 2011
+		self.__mail_server = mail_server		# August 19, 2011
+
+
+	##########################################################
+	# Override parent method
+	##########################################################
+	def handle(self):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+
+		mail_server = self.__mail_server		# August 19, 2011
+		mail_admin = self.__mail_admin			# August 19, 2011
+		
+		clone_request = self.__clone_request
+		
+		form = cgi.FieldStorage(keep_blank_values="True")
+		
+		uHandler = UserHandler(db, cursor)
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		if form.has_key("curr_username"):
+			# store the user ID for use throughout the session; add to other views in addition to create in PHP
+			currUname = form.getvalue("curr_username")
+			currUser = uHandler.getUserByDescription(currUname)
+			
+			Session.setUser(currUser)
+		
+		elif form.has_key("curr_user_id"):
+			currUID = form.getvalue("curr_user_id")
+			currUser = uHandler.getUserByID(currUID)
+			Session.setUser(currUser)
+		
+		
+		if form.has_key("add_user"):
+			self.addUser(form)
+		
+		elif form.has_key("modify_user"):
+			self.modifyUser(form)
+
+		elif form.has_key("cancel_user"):
+			self.cancelUserModification(form)
+		
+		elif form.has_key("save_user"):
+			self.saveUser(form)
+
+		elif form.has_key("delete_user"):
+			self.deleteUser(form)
+
+		elif form.has_key("view_user") and form.getvalue("view_user") != "" and not form.has_key("modify_lab") and not form.has_key("delete_lab"):
+			self.viewUser(form)
+
+		# Nov. 17/07 - Personal user page
+		elif form.has_key("view_user") and form.getvalue("view_user") == "" and not form.has_key("modify_lab") and not form.has_key("delete_lab"):
+			self.printUserInfo('view', currUser)
+		
+		elif form.has_key("add_lab"):
+			self.addLab(form)
+
+		elif form.has_key("view_lab"):
+			self.viewLab(form)
+
+		elif form.has_key("modify_lab"):
+			self.modifyLab(form)
+
+		elif form.has_key("save_lab"):
+			self.saveLab(form)
+			
+		elif form.has_key("cancel_lab"):
+			self.cancelLabModification(form)
+			
+		elif form.has_key("delete_lab"):
+			self.deleteLab(form)
+			
+		elif form.has_key("bug_report"):
+			self.submitBug(form)
+		
+		elif form.has_key("send_order"):
+			
+			######################################################################
+			# CHANGE SERVER NAME AND EMAIL TO YOUR LOCAL CREDENTIALS
+			######################################################################
+
+			userID = form.getvalue("curr_user_id")
+			userDescr = form.getvalue("curr_username")
+			
+			from_email = uHandler.findEmail(userID)
+			
+			if not from_email:
+				from_email = userDescr
+
+			to_email = clone_request
+			
+			email_subject = userDescr + ": Clone Request"
+			
+			f_in = form.getvalue("outputContent")
+			infile = open(f_in, 'rb')
+			
+			msg = email.MIMEMultipart.MIMEMultipart()
+ 			#msg.attach(email.MIMEText.MIMEText(infile.read()))	# no, this attaches plain text
+			msg['Subject'] = email_subject
+			
+			part = email.MIMEBase.MIMEBase('application', "octet-stream")
+			part.set_payload(infile.read())
+			email.Utils.base64.standard_b64encode(infile.read())
+			part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f_in))
+			msg.attach(part)
+			
+			server = smtplib.SMTP(mail_server)
+
+			server.set_debuglevel(1)
+
+			# Send a request to your clone request address
+			server.sendmail(from_email, to_email, msg.as_string())
+			
+			# AND send a copy to the user (change the subject)
+			#msg['Subject'] = "Clone request confirmation"		# doesn't change, investigate later
+			
+			# Return email text changed March 31/08
+			
+			#######################################
+			# CHANGE TEXT AS NEEDED
+			#######################################
+			msg.attach(email.MIMEText.MIMEText("This is a copy of your clone request.  Please retain for your records.  You will be notified by e-mail when your clone is ready."))
+			
+			server.sendmail(to_email, from_email, msg.as_string())
+			server.quit()
+			
+			# Method 2
+			#sendmail = "/usr/sbin/sendmail"
+			
+			#o = os.popen("%s -t" %  sendmail,"w")
+			#o.write("To: %s\r\n" %  to_email)
+			
+			#if from_email:
+				#o.write("From: %s\r\n" %  from_email)
+				#o.write("Subject: %s\r\n" %  email_subject)
+				#o.write("\r\n")
+				#o.write("%s\r\n" % msg)
+			
+			#o.close()
+			
+			os.remove(f_in)		# delete the file from /tmp dir
+			
+			utils.redirect(hostname + "User.php?View=8&Sent=1")
+		
+		# June 1, 2010: Automated password reset
+		elif form.has_key("reset_pw"):
+			
+			# change June 2, 2010: Don't enter email, rather, ask users to enter their username - more secure
+			#to_email = form.getvalue("email")
+			
+			from_email = mail_admin
+
+			#success = True
+			
+			chars = string.letters + string.digits
+			new_passwd = ""
+			
+			for i in range(10):
+				new_passwd += choice(chars)
+	
+			# reset it in the database
+			if form.has_key("uName"):
+				u_name = form.getvalue("uName")
+				
+				userID = uHandler.findUserIDByUsername(u_name)
+								
+				if userID > 0:
+					u_descr = uHandler.findDescription(userID)
+					
+					to_email = uHandler.findEmail(userID)
+
+					uHandler.setUserPropertyValue(userID, 'password', new_passwd)
+				
+					email_subject = "OpenFreezer Password Change"
+					
+					msg = email.MIMEMultipart.MIMEMultipart()
+					#msg.attach(email.MIMEText.MIMEText(infile.read()))	# no, this attaches plain text
+					
+					msg['Subject'] = email_subject
+					
+					###################################
+					# CHANGE TEXT AS NEEDED
+					###################################
+					msg.attach(email.MIMEText.MIMEText("Dear " + u_descr + ",\n\nYour password for OpenFreezer has been changed.\n\nYour temporary new password is: " + new_passwd + ".\n\nPlease change the temporary password as soon as you log into the system.\n\nYour username for OpenFreezer is '" + u_name + "'.\n\nFor any questions, please refer to http://openfreezer.org. \n\nSincerely,\nOpenFreezer support team.\n--------------------------------\nThis is an automatically generated e-mail message.  Pl [...]
+					
+					server = smtplib.SMTP(mail_server)
+
+					server.set_debuglevel(1)
+		
+					server.sendmail(from_email, to_email, msg.as_string())
+					server.quit()
+					
+					utils.redirect(hostname + "User.php?View=6&Reset=1&uid=" + `userID`)
+				else:
+					# retry by description
+					if form.has_key("uDesc"):
+						u_descr = form.getvalue("uDesc")
+						
+						# but account for whitespace
+						toks = u_descr.split(" ")
+						
+						tmp_descr = ""
+						
+						for tok in toks:
+							tmp_descr += tok.strip() + " "
+		
+						# strip extra whitespace from end
+						tmp_descr = tmp_descr.strip()
+					
+						userID = uHandler.findUserIDByDescription(tmp_descr)
+						
+						if userID > 0:
+							u_name = uHandler.findUsername(userID)
+							
+							to_email = uHandler.findEmail(userID)
+							uHandler.setUserPropertyValue(userID, 'password', new_passwd)
+							
+							email_subject = "OpenFreezer Password Change"
+							
+							msg = email.MIMEMultipart.MIMEMultipart()
+							#msg.attach(email.MIMEText.MIMEText(infile.read()))	# no, this attaches plain text
+							
+							msg['Subject'] = email_subject
+							
+							##############################
+							# CHANGE TEXT AS NEEDED
+							##############################
+							msg.attach(email.MIMEText.MIMEText("Dear " + u_descr + ",\n\nYour password for OpenFreezer has been changed.\n\nYour temporary new password is: " + new_passwd + ".\n\nPlease change the temporary password as soon as you log into the system.\n\nYour username for OpenFreezer is '" + u_name + "'.\n\nPlease refer to http://openfreezer.org for additional support.\n\nSincerely,\nOpenFreezer support team.\n--------------------------------\nThis is an automatically generated e-mail message [...]
+							
+							server = smtplib.SMTP(mail_server)
+							server.set_debuglevel(1)
+				
+							server.sendmail(from_email, to_email, msg.as_string())
+							server.quit()
+							
+							utils.redirect(hostname + "User.php?View=6&Reset=1&uid=" + `userID`)
+						else:
+							utils.redirect(hostname + "User.php?View=6&Reset=0")
+					else:
+						utils.redirect(hostname + "User.php?View=6&Reset=0")
+			else:
+				utils.redirect(hostname + "User.php?View=6&Reset=0")
+
+		cursor.close()
+		db.close()
+	
+	
+	##########################################################
+	# Process Add User request
+	##########################################################
+	def addUser(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		mail_server = self.__mail_server		# August 19, 2011
+
+		mail_programmer = self.__mail_programmer	# July 30, 2010
+		mail_biologist = self.__mail_biologist
+		mail_admin = self.__mail_admin
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		uHandler = UserHandler(db, cursor)
+		lHandler = LabHandler(db, cursor)
+		pHandler = ProjectDatabaseHandler(db, cursor)
+		
+		ucMapper = UserCategoryMapper(db, cursor)
+		category_Name_ID_Map = ucMapper.mapCategoryNameToID()
+		
+		# Get form values
+		labID = int(form.getvalue("labs"))
+		username = form.getvalue("username")
+		
+		firstName = form.getvalue("firstName")
+		lastName = form.getvalue("lastName")
+		description = firstName + " " + lastName
+		
+		to_email = form.getvalue("email")
+
+		from_email = mail_admin
+
+		# Change July 30, 2010 - random password generator
+		#passwd = form.getvalue("password")
+	
+		chars = string.letters + string.digits
+		passwd = ""
+		
+		for i in range(10):
+			passwd += choice(chars)
+		
+		# System access level: Lab default or override?
+		#if form.getvalue("privChoiceRadio") == 'override':
+		accessLevel = category_Name_ID_Map[form.getvalue("system_access_level")]
+		#else:
+		#accessLevel = lHandler.findDefaultAccessLevel(labID)
+		
+		newProps = {}
+		
+		try:
+			# Insert User information
+			userID = uHandler.insertUser(username, firstName, lastName, description, accessLevel, to_email, passwd, labID)
+			#newUser = uHandler.getUserByID(userID)
+			tmpLab = lHandler.findLabByID(labID)
+			#print tmpLab.getName()
+			
+			# Insert Project info
+			# Sept. 11/07: Differentiate between user categories Reader and Writer - different field names
+			if form.has_key("userProjectsReadonly"):
+				# list of IDs
+				readonlyProjects = utils.unique(form.getlist("userProjectsReadonly"))
+				#print `readonlyProjects`
+				pHandler.insertMemberProjects(userID, readonlyProjects, 'Reader')
+			
+			elif form.has_key("userProjectsReadonlyWrite"):
+				# list of IDs
+				readonlyProjects = utils.unique(form.getlist("userProjectsReadonlyWrite"))
+				#print `readonlyProjects`
+				pHandler.insertMemberProjects(userID, readonlyProjects, 'Reader')
+				
+			# Write projects exist only for Writers
+			if form.has_key("userProjectsWrite"):
+				writeProjects = utils.unique(form.getlist("userProjectsWrite"))
+				pHandler.insertMemberProjects(userID, writeProjects, 'Writer')
+			
+			# don't assign projects to a User instance - will retrieve them from db in output function
+			newUser = User(userID, username, firstName, lastName, description, tmpLab, form.getvalue("system_access_level"), to_email, passwd, [], [])
+			
+			email_subject = "OpenFreezer User Account"
+			
+			msg = email.MIMEMultipart.MIMEMultipart('alternative')
+			
+			msg['Subject'] = email_subject
+			msg['To'] = to_email
+
+			msgText = "Hi " + firstName + ",<BR><BR>An OpenFreezer account has been created for you.  Your access level is " + form.getvalue("system_access_level") + ", so you can "
+			
+			if form.getvalue("system_access_level") == 'Reader':
+				msgText += "search for clones.  If you wish to add/modify reagents or create projects, please contact the administrator to upgrade your access level.<BR>"
+			
+			elif form.getvalue("system_access_level") == 'Writer':
+				msgText += "search, add, and modify reagents.  If you wish to create projects, please contact the administrator to upgrade your access level.<BR>"
+			
+			elif form.getvalue("system_access_level") == 'Creator':
+				msgText += "search for clones, add and modify reagents, as well as create your own projects.<BR>"
+			
+
+			#####################################################
+			# CHANGE TEXT AS NEEDED
+			#####################################################
+
+			msgText += "<BR>The URL to access the system is <a href='" + hostname + "'>" + hostname + "</a>.  Your username is <b>" + username + "</b>, and your temporary password is <b>" + passwd + "</b>.  Please <u>change the temporary password as soon as you log into the website</u> - you can do it through the 'Change your password' link under the 'User Management' menu section.<BR><BR>Please refer to http://openfreezer.org for additional support.<BR><BR>Sincerely,<BR>OpenF [...]
+			
+			msgText = email.MIMEText.MIMEText(msgText, 'html')
+			msg.attach(msgText)
+			
+			server = smtplib.SMTP(mail_server)
+			server.set_debuglevel(1)
+
+			server.sendmail(from_email, [to_email], msg.as_string())
+			server.quit()
+			
+			self.printUserInfo('view', newUser)
+			
+		except DeletedUserException:
+		
+			# Without asking too many questions, reactivate the deleted user and overwrite his/her attributes with the form input values
+			userID = uHandler.findUserIDByUsername(username)
+			
+			newProps["firstname"] = firstName
+			newProps["lastname"] = lastName
+			newProps["description"] = description
+			newProps["email"] = email
+			newProps["status"] = "ACTIVE"
+			newProps["password"] = passwd
+
+			# Insert new database values and create new object
+			uHandler.updateUserProperties(userID, newProps)			# database update
+			newUser = uHandler.getUserByID(userID)		
+			
+			# Insert Project info
+			readProjects = []
+			writeProjects = []
+			
+			if form.has_key("userProjectsReadonly"):
+				# list of IDs
+				readonlyProjects = form.getlist("userProjectsReadonly")
+
+				for r in readonlyProjects:
+					pHandler.addProjectMember(r, userID, 'Reader')
+					
+					#tmpReadProject = pHandler.findPacket(r)
+					#readProjects.append(tmpReadProject)
+					#newUser.addProject(tmpReadProject, 'read')
+
+			if form.has_key("userProjectsWrite"):
+				writeProjects = form.getlist("userProjectsWrite")
+
+				for w in writeProjects:
+					pHandler.addProjectMember(w, userID, 'Writer')
+					
+					#tmpWriteProject = pHandler.findPacket(w)
+					#writeProjects.append(tmpWriteProject)
+					#newUser.addProject(tmpWriteProject, 'write')
+			
+			#newUser.setReadProjects(readProjects)
+			#newUser.setWriteProjects(writeProjects)
+			
+			self.printUserInfo('view', newUser)
+			#utils.redirect(hostname + "User.php?View=3&fd=" + filename)
+			
+		except DuplicateUsernameException:
+			
+			# return to the view with input values and error message
+			# Need to construct a dummy User instance to save form values for error output on the next page (otherwise they're lost as soon as Submit is pressed and creation view is exited)
+			newLab = lHandler.findLabByID(labID)
+			newUser = User(0, username, firstName, lastName, description, newLab, "", email, passwd)
+			
+			self.printUserInfo('create', newUser)
+			#utils.redirect(hostname + "User.php?View=1&fd=" + filename + "&ErrCode=Dup_un#w1")
+			
+	
+	##########################################################
+	# Process Change User Details request
+	##########################################################	
+	def modifyUser(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+
+		uHandler = UserHandler(db, cursor)
+		lHandler = LabHandler(db, cursor)
+		pHandler = ProjectDatabaseHandler(db, cursor)
+		
+		ucMapper = UserCategoryMapper(db, cursor)
+		category_Name_ID_Map = ucMapper.mapCategoryNameToID()
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+
+		# Get form values
+		userID = int(form.getvalue("userID")) 
+		newUser = uHandler.getUserByID(userID)
+
+		'''
+		labID = int(form.getvalue("labID"))
+		username = form.getvalue("username")
+		
+		firstName = form.getvalue("firstName")
+		lastName = form.getvalue("lastName")
+		description = firstName + " " + lastName
+		
+		email = form.getvalue("email")
+		passwd = form.getvalue("password")
+		'''
+		
+		readProjects = pHandler.findMemberProjects(userID, 'Reader')
+		newUser.setReadProjects(readProjects)
+		
+		writeProjects = pHandler.findMemberProjects(userID, 'Writer')
+		newUser.setWriteProjects(writeProjects)
+		
+		self.printUserInfo('edit', newUser)
+		#utils.redirect(hostname + "User.php?View=3&fd=" + filename)
+
+
+	##########################################################
+	# Exit Modify view without saving
+	##########################################################
+	def cancelUserModification(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		uHandler = UserHandler(db, cursor)
+		pHandler = ProjectDatabaseHandler(db, cursor)
+				
+		userID = int(form.getvalue('userID'))
+		newUser = uHandler.getUserByID(userID)
+		
+		self.printUserInfo('view', newUser)
+		#utils.redirect(hostname + "User.php?View=3&fd=" + filename)
+
+	
+	##########################################################
+	# Store user details upon exit from Modify view
+	##########################################################
+	def saveUser(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		uHandler = UserHandler(db, cursor)
+		lHandler = LabHandler(db, cursor)
+		pHandler = ProjectDatabaseHandler(db, cursor)
+		
+		ucMapper = UserCategoryMapper(db, cursor)
+		category_ID_Name_Map = ucMapper.mapCategoryIDToName()
+		
+		newProps = {}
+		
+		# Get form values
+		userID = int(form.getvalue("userID"))
+		newUser = uHandler.getUserByID(userID)
+		
+		labID = int(form.getvalue("labs"))
+		tmpLab = lHandler.findLabByID(labID)
+
+		# rest of user properties
+		username = form.getvalue("username")
+		firstName = form.getvalue("firstName")
+		lastName = form.getvalue("lastName")
+		description = firstName + " " + lastName
+		email = form.getvalue("email")
+		category = category_ID_Name_Map[int(form.getvalue("system_access_level"))]
+
+		newProps["labID"] = labID
+		newProps["username"] = username
+		newProps["firstname"] = firstName
+		newProps["lastname"] = lastName
+		newProps["description"] = description
+		newProps["email"] = email
+		newProps["category"] = category
+
+		try:
+			# Now do an update on database level AND on class level:
+			uHandler.updateUserProperties(userID, newProps)			# database update
+			
+			# Interface level
+			newUser.setUsername(username)
+			newUser.setFirstName(firstName)
+			newUser.setLastName(lastName)
+			newUser.setDescription(description)
+			newUser.setEmail(email)
+			newUser.setLab(tmpLab)
+			newUser.setCategory(category)
+
+			# update list of user's projects
+			if form.has_key("userProjectsReadonly"):
+				# list of IDs
+				readonlyProjects = utils.unique(form.getlist("userProjectsReadonly"))
+				pHandler.updateUserProjects(userID, readonlyProjects, 'Reader')
+			else:
+				# safe to assume should delete projects?
+				pHandler.deleteMemberProjects(userID, 'Reader')
+
+			if form.has_key("userProjectsWrite"):
+				writeProjects = utils.unique(form.getlist("userProjectsWrite"))
+				pHandler.updateUserProjects(userID, writeProjects, 'Writer')
+			else:
+				# safe to assume should delete projects?
+				pHandler.deleteMemberProjects(userID, 'Writer')
+				
+			# think about this
+			#newUser.setReadProjects(readProjects)
+			#newUser.setWriteProjects(writeProjects)
+
+			# return to detailed view
+			self.printUserInfo('view', newUser)
+			#utils.redirect(hostname + "User.php?View=3&fd=" + filename)
+
+		except DuplicateUsernameException:
+			
+			# return to the view with input values and error message
+			# Need to construct a dummy User instance to save form values for error output on the next page (otherwise they're lost as soon as Submit is pressed and creation view is exited)
+			newLab = lHandler.findLabByID(labID)
+			newUser = User(userID, username, firstName, lastName, description, newLab, category, email, "")
+			
+			self.printUserInfo('edit', newUser, "Dup_un")
+			#utils.redirect(hostname + "User.php?View=1&fd=" + filename + "&ErrCode=Dup_un#w1")
+		
+
+
+	##############################################
+	# Process Delete User request
+	##############################################
+	def deleteUser(self, form):
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		uHandler = UserHandler(db, cursor)
+		pHandler = ProjectDatabaseHandler(db, cursor)
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		uid = form.getvalue("userID")
+
+		# list of user IDs
+		#deletionCandidates = form.getlist("deletionCandidates")
+		
+		# Delete users and revoke their access to projects
+		#for uid in deletionCandidates:
+		uHandler.deleteUser(uid)
+		pHandler.deleteMemberFromllProjects(uid)
+		
+		utils.redirect(hostname + "User.php?View=2&Del=1")
+
+
+	##########################################################
+	# Redirect to User detailed view
+	##########################################################	
+	def viewUser(self, form):
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		uHandler = UserHandler(db, cursor)
+		
+		userID = form.getvalue("view_user")
+		newUser = uHandler.getUserByID(userID)
+		
+		self.printUserInfo('view', newUser)
+		#utils.redirect(hostname + "User.php?View=3&fd=" + filename)
+		
+
+	##########################################################
+	# Output User Detailed View page
+	##########################################################
+	def printUserInfo(self, cmd, newUser, errCode = ""):
+		userOutput = UserOutputClass()
+		userOutput.printUserInfo(cmd, newUser, errCode)
+
+
+	##########################################################
+	# Process Add Lab request
+	##########################################################	
+	def addLab(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		lHandler = LabHandler(db, cursor)
+		ucMapper = UserCategoryMapper(db, cursor)
+		category_Name_ID_Map = ucMapper.mapCategoryNameToID()
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+
+		# Get form values
+		labName = form.getvalue("labName")
+		labHeadTitle = form.getvalue("titles")
+		labHeadName = form.getvalue("labHead")
+		labHead = labHeadTitle + " " + labHeadName
+		labCode = form.getvalue("labCode").upper()
+		labDescr = form.getvalue("labDescription")
+		labAddress = form.getvalue("labAddress")
+		labAccess = form.getvalue("system_access_level")
+		defaultLabAccessLevel = category_Name_ID_Map[labAccess]		# map to database ID
+			
+		try:
+			newLabID = lHandler.insertLab(labName, labDescr, labAddress, defaultLabAccessLevel, labHead, labCode)
+			#print `newLabID`
+			newLab = Laboratory(newLabID, labName, labDescr, labAccess, labAddress, labHead, labCode)
+			self.printLabInfo('view', newLab)
+		
+		except DuplicateLabCodeException:
+		
+			d = DuplicateLabCodeException()
+			utils.redirect(hostname + "User.php?View=3&labName=" + labName + "&title=" + labHeadTitle + "&labHead=" + labHeadName + "&labCode=" + labCode + "&labDescr=" + labDescr + "&locn=" + labAddress + "&access=" + labAccess + "&ErrCode=" + `d.err_code()`)
+			
+
+	############################################################################
+	# All this essentially does is calls the print method of UserOutput class
+	############################################################################
+	def printLabInfo(self, cmd, newLab, errCode = ""):
+		userOutput = UserOutputClass()
+		userOutput.printLabInfo(cmd, newLab, errCode)
+
+
+	##################################################
+	# Redirect to lab detailed view
+	##################################################
+	def viewLab(self, form):
+	
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		userOutput = UserOutputClass()
+		lHandler = LabHandler(db, cursor)
+	
+		# request may come from different views, so field names may vary
+		if form.has_key("labs"):
+			# request received through 'View Labs' menu item
+			labID = int(form.getvalue("labs"))
+			
+		elif form.has_key("labID"):
+			# request came from User Detailed View to navigate back to the Lab Detailed View 
+			labID = int(form.getvalue("labID"))
+		
+		else:
+			labID = int(form.getvalue("view_lab"))
+			
+		newLab = lHandler.findLabByID(labID)
+		
+		self.printLabInfo('view', newLab)
+		#utils.redirect(hostname + "User.php?View=4&Lab=" + `labID` + "&fd=" + filename)
+
+
+	##########################################################
+	# Output Lab modification view
+	##########################################################	
+	def modifyLab(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+
+		lHandler = LabHandler(db, cursor)
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		labID = int(form.getvalue("labID"))
+		newLab = lHandler.findLabByID(labID)
+
+		self.printLabInfo('edit', newLab)
+		#utils.redirect(hostname + "User.php?View=5&Lab=" + `labID` + "&fd=" + filename)
+
+
+	##########################################################
+	# Store lab details upon exit from Modify view
+	##########################################################
+	def saveLab(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		# Handlers and mappers
+		lHandler = LabHandler(db, cursor)
+		ucMapper = UserCategoryMapper(db, cursor)
+		category_Name_ID_Map = ucMapper.mapCategoryNameToID()
+		
+		# Get form values
+		labID = int(form.getvalue("labID")) 
+		lab = Laboratory(labID)			# here need to use the default constructor and not findLabByID, because lab is being updated and need a fresh instance and set its attributes to new values
+		
+		newName = form.getvalue("labName")
+		newLabHead = form.getvalue("labHead")
+		newLabCode = form.getvalue("labCode").upper()
+		newDescr = form.getvalue("description")
+		newAddr = form.getvalue("address")
+		newAccess = form.getvalue("system_access_level")
+		newAccLev = category_Name_ID_Map[newAccess]
+		
+		# change database values
+		try:
+			lHandler.setLabName(labID, newName)
+			lHandler.setLabHead(labID, newLabHead)
+			lHandler.setLabCode(labID, newLabCode)
+			lHandler.setLabDescription(labID, newDescr)
+			lHandler.setLabAccessLevel(labID, newAccLev)
+			lHandler.setLocation(labID, newAddr)	
+		
+			#######################
+			# update members!
+			#######################
+
+			newMembers = form.getlist("labMembers")
+			lHandler.updateLabMembers(labID, newMembers)
+			
+			# change object values
+			lab.setName(newName)
+			lab.setLabHead(newLabHead)
+			lab.setLabCode(newLabCode)
+			lab.setDescription(newDescr)
+			lab.setAddress(newAddr)
+			lab.setDefaultAccessLevel(newAccess)
+
+			# return to detailed view
+			self.printLabInfo('view', lab)
+			#utils.redirect(hostname + "User.php?View=5&Lab=" + `labID` + "&fd=" + filename)
+		
+		except DuplicateLabCodeException:
+			
+			newLab = Laboratory(labID, newName, newDescr, newAccess, newAddr, newLabHead, newLabCode)
+			
+			d = DuplicateLabCodeException()
+			self.printLabInfo('edit', newLab, d.err_code())
+			
+
+	#################################################################
+	# Cancel Lab modification - return to detailed view w/o saving
+	#################################################################
+	def cancelLabModification(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+
+		lHandler = LabHandler(db, cursor)
+		
+		labID = int(form.getvalue("labID"))
+		lab = lHandler.findLabByID(labID)	# fetch old lab attribute values
+		
+		self.printLabInfo('view', lab)
+		#utils.redirect(hostname + "User.php?View=4&Lab=" + `labID` + "&fd=" + filename)
+		
+		
+		
+	##############################################
+	# Process Delete User request
+	##############################################
+	def deleteLab(self, form):
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		lHandler = LabHandler(db, cursor)
+		
+		#print "Content-type:text/html"		# TEMPORARY, REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+		#print					# DITTO
+		#print `form`
+		
+		labID = form.getvalue("labID")
+
+		lHandler.deleteLab(labID)
+
+		utils.redirect(hostname + "User.php?View=5")
+		
+		
+	##############################################
+	# July 1, 2010
+	##############################################
+	def submitBug(self, form):
+		
+		db = self.__db
+		cursor = self.__cursor
+		hostname = self.__hostname
+		
+		if form.has_key("request_type"):	# it must, but still
+			request_type = form.getvalue("request_type")
+
+		if form.has_key("modules"):
+			module = form.getvalue("modules")
+			
+		if form.has_key("bug_description"):
+			bug_description = form.getvalue("bug_description")
+			
+		if form.has_key("curr_userid"):
+			userID = int(form.getvalue("curr_userid"))
+		
+		# insert into database - NOT MAKING A SEPARATE bug_handler.py module now, no need to!!!
+		cursor.execute("INSERT INTO BugReport_tbl(bug_type, module, bug_descr, requested_by) VALUES(" + `request_type` + ", " + `module` + ", " + `bug_description` + ", " + `userID` + ")")
+		
+		utils.redirect(hostname + "bugreport.php?Req=1")
+
+
+##########################################################
+# Central callable function
+##########################################################
+def main():
+
+	uReqHandler = UserRequestHandler()
+	uReqHandler.handle()
+
+main()
diff --git a/OpenFreezer/cgi/utils.py b/OpenFreezer/cgi/utils.py
new file mode 100755
index 0000000..f0847d8
--- /dev/null
+++ b/OpenFreezer/cgi/utils.py
@@ -0,0 +1,256 @@
+#!/usr/local/bin python
+import types
+import re
+import string
+
+#############################################################################################
+# Module utils
+# Contains miscellaneous utility functions utilized by various modules throughout the code
+#
+# Written March 5, 2007 by Marina Olhovsky
+# Last modified: February 12, 2008
+#############################################################################################
+
+# Determines whether 'arg' is a scalar value or a list 
+def isList(arg):
+    return type(arg)==types.ListType
+
+
+# Merge two **dictionaries** into one, removing duplicates
+def join(dict1, dict2):
+	
+	keys1 = dict1.keys()
+	keys2 = dict2.keys()
+	keys = merge(keys1, keys2)
+	
+	result = {}
+	
+	for k in keys:
+		
+		if dict1.has_key(k):
+			val = dict1[k]
+			
+		elif dict2.has_key(k):
+			val = dict2[k]
+			
+		result[k] = val
+		
+	return result
+
+
+# Merge two lists, removing duplicates
+def merge(list1, list2):
+	return unique(list1 + list2)
+
+#####################################################################################################
+# Taken from ASPN Python Cookbook
+# Returns a list of dictionary elements without duplicates
+#####################################################################################################
+def unique(s):
+    """Return a list of the elements in s, but without duplicates.
+
+    For example, unique([1,2,3,1,2,3]) is some permutation of [1,2,3],
+    unique("abcabc") some permutation of ["a", "b", "c"], and
+    unique(([1, 2], [2, 3], [1, 2])) some permutation of
+    [[2, 3], [1, 2]].
+
+    For best speed, all sequence elements should be hashable.  Then
+    unique() will usually work in linear time.
+
+    If not possible, the sequence elements should enjoy a total
+    ordering, and if list(s).sort() doesn't raise TypeError it's
+    assumed that they do enjoy a total ordering.  Then unique() will
+    usually work in O(N*log2(N)) time.
+
+    If that's not possible either, the sequence elements must support
+    equality-testing.  Then unique() will usually work in quadratic
+    time.
+    """
+
+    n = len(s)
+    if n == 0:
+        return []
+
+    # Try using a dict first, as that's the fastest and will usually
+    # work.  If it doesn't work, it will usually fail quickly, so it
+    # usually doesn't cost much to *try* it.  It requires that all the
+    # sequence elements be hashable, and support equality comparison.
+    u = {}
+    try:
+        for x in s:
+            u[x] = 1
+    except TypeError:
+        del u  # move on to the next method
+    else:
+        return u.keys()
+
+    # We can't hash all the elements.  Second fastest is to sort,
+    # which brings the equal elements together; then duplicates are
+    # easy to weed out in a single pass.
+    # NOTE:  Python's list.sort() was designed to be efficient in the
+    # presence of many duplicate elements.  This isn't true of all
+    # sort functions in all languages or libraries, so this approach
+    # is more effective in Python than it may be elsewhere.
+    try:
+        t = list(s)
+        t.sort()
+    except TypeError:
+        del t  # move on to the next method
+    else:
+        assert n > 0
+        last = t[0]
+        lasti = i = 1
+        while i < n:
+            if t[i] != last:
+                t[lasti] = last = t[i]
+                lasti += 1
+            i += 1
+        return t[:lasti]
+
+    # Brute force is all that's left.
+    u = []
+    for x in s:
+        if x not in u:
+            u.append(x)
+    return u
+
+
+#####################################################################################################
+# Taken from ASPN Python Cookbook
+# Returns True if 'aStr' is an integer, False otherwise
+#####################################################################################################    
+def IsInt(aStr):
+   try:
+      num = int(aStr)
+      return 1
+   except ValueError:
+      return 0
+
+
+#####################################################################################################
+# Return a list of elements that are contained in list1 but not in list2
+# Elements in both lists must be of the same datatype
+#####################################################################################################
+def diff(list1, list2):
+	result = []
+		
+	for el in list1:
+		if el not in list2:
+			result.append(el)
+			
+	return result	
+	
+
+#####################################################################################################
+# Split a string that contains a hyphen or slash into two parts and place these parts in an array
+# If 'string' doesn't contain either separator, return whole string
+#####################################################################################################
+def make_array(string):
+
+    if string.find("-") > 0:
+        return re.split("-", string)
+
+    elif string.find("/") > 0:
+        return re.split("/", string)
+
+    else:
+        return string
+
+
+#####################################################################################################
+# Find the number of occurences of a pattern in a string
+#####################################################################################################
+def numOccurs(seq, pat):
+
+    num_occurs = 0
+    currIndex = seq.find(pat)
+
+    while currIndex >= 0:
+        num_occurs += 1
+        currIndex = seq.find(pat, currIndex+1)
+
+    return num_occurs
+
+
+#####################################################################################################
+# Redirect to the given url
+#####################################################################################################
+def redirect(url):
+	print 'Location:' + url
+	print
+
+
+#####################################################################################################
+# Swap dictionary keys and values (corresponds to PHP's array_flip)
+#####################################################################################################
+def swap(dict):
+	newDict = {}
+	
+	for k in dict.keys():
+		val = dict[k]
+		newDict[val] = k
+		
+	return newDict
+	
+
+# Added Oct. 28/08 - Find ALL occurrences of pat in seq
+# Return: list of positions
+def findall(seq, pat, fList):
+	#print "Searching for " + pat
+	
+	if numOccurs(seq, pat) > 0:
+		prev = seq.find(pat)
+		
+		while prev >= 0:
+			
+			#print prev
+			fList.append(prev)
+			#findall(seq[prev+len(pat):], pat, fList)
+			prev = seq.find(pat, prev+len(pat))
+		
+	else:
+		fList.append(seq.find(pat))
+		
+	return fList
+	
+	
+#####################################################################################################
+# Remove whitespace from sequence
+#####################################################################################################
+def squeeze(sequence):
+	
+	tmp_seq = ""
+	new_seq = ""
+	
+	sequence = sequence.replace('\r', '\n')
+	sequence = sequence.replace('\t', ' ')
+	
+	# First, filter newlines
+	toks = sequence.split('\n')
+	
+	for x in toks:
+		tmp_seq += x.strip()
+	
+	tokens = tmp_seq.split(" ")
+	
+	for i in tokens:
+		new_seq += i
+	
+	return new_seq
+	
+
+#####################################################################################################
+# July 15/09: Taken from http://stackoverflow.com/questions/783897/truncating-floats-in-python
+# Truncates/pads a float f to n decimal places without rounding
+#####################################################################################################
+def trunc(f, n):
+	slen = len('%.*f' % (n, f))
+	
+	return str(f)[:slen]
+
+
+def toArray(val):
+	tmp_ar = []
+	tmp_ar.append(val)
+	
+	return tmp_ar
\ No newline at end of file
diff --git a/OpenFreezer/cgi/vector_frames.py b/OpenFreezer/cgi/vector_frames.py
new file mode 100755
index 0000000..7cbd004
--- /dev/null
+++ b/OpenFreezer/cgi/vector_frames.py
@@ -0,0 +1,1138 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+
+import MySQLdb
+import sys
+import string
+
+from database_conn import DatabaseConn
+
+from mapper import ReagentPropertyMapper, ReagentAssociationMapper
+from general_handler import *
+from reagent_handler import ReagentHandler, InsertHandler
+from sequence_handler import DNAHandler, ProteinHandler
+from comment_handler import CommentHandler
+#from system_set_handler import SystemSetHandler
+from sequence_handler import SequenceHandler
+from reagent import *
+
+import utils
+
+from user_handler import UserHandler
+from project_database_handler import ProjectDatabaseHandler
+from session import Session
+from exception import *
+
+dbConn = DatabaseConn()
+db = dbConn.databaseConnect()
+
+cursor = db.cursor()
+hostname = dbConn.getHostname()
+root_path = dbConn.getRootDir()
+
+dnaHandler = DNAHandler(db, cursor)
+protHandler = ProteinHandler(db, cursor)
+rHandler = ReagentHandler(db, cursor)
+propHandler = ReagentPropertyHandler(db, cursor)
+
+propMapper = ReagentPropertyMapper(db, cursor)
+prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+
+prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+
+normal_frames = []
+orf_no = 1
+
+# Jan. 23/09
+# Translate sequence in 6 frames, including reverse
+def getAllFrames(rID, seq, vectorID):
+	global orf_no
+	global normal_frames
+	
+	fwd_frames = {}
+	rev_frames = {}
+	
+	# debug reverse
+	#seq = dnaHandler.reverse_complement(seq)
+	#print seq
+	#protHandler.findVectorORFs(seq, 1)
+	#return
+	
+	# Translate forward-oriented sequence in 3 frames
+	if len(seq) > 0:
+		for frame in range(1,4):
+			prots = protHandler.findVectorORFs(seq, frame)
+		
+			if len(prots) > 0:
+				for protEntry in prots:
+					peptideSeq = protEntry.getSequence()
+					sStart = protEntry.getSeqStart()
+					sEnd = protEntry.getSeqEnd()
+					
+					if len(peptideSeq) > 0 and sStart > 0 and sEnd > 0:
+							
+						if fwd_frames.has_key(frame):
+							tmp_fwd = fwd_frames[frame]
+							tmp_fwd.append(protEntry)
+							fwd_frames[frame] = tmp_fwd
+						else:
+							tmp_fwd = []
+							tmp_fwd.append(protEntry)
+							fwd_frames[frame] = tmp_fwd
+	
+			## increment loop counter
+			#frame += 1
+			
+	
+	# Translate REVERSE-oriented sequence in 3 frames
+	if len(seq) > 0:
+		seq = dnaHandler.reverse_complement(seq)
+	
+		for frame in range(1,4):
+			tmp_rev = []
+			
+			#print "Translating F" + `frame`
+			
+			#protEntry = protHandler.translate(seq, frame, openClosed)
+			prots = protHandler.findVectorORFs(seq, frame)
+			
+			if len(prots) > 0:
+				for protEntry in prots:
+					protEntry.setOrientation('reverse')
+					peptideSeq = protEntry.getSequence()
+					
+					sStart = protEntry.getSeqStart()
+					sEnd = protEntry.getSeqEnd()
+					
+					if len(peptideSeq) > 0 and sStart > 0 and sEnd > 0:
+						#f_ind = frame+1	# jan. 27/09: decided not to do this, too confusing
+						f_ind = frame
+						#print f_ind
+						
+						if rev_frames.has_key(f_ind):
+							tmp_rev = rev_frames[f_ind]
+							tmp_rev.append(protEntry)
+							rev_frames[f_ind] = tmp_rev
+						else:
+							tmp_rev = []
+							tmp_rev.append(protEntry)
+							rev_frames[f_ind] = tmp_rev
+	
+	# feature overlap
+	tmpVector = Vector(rID)
+	features = rHandler.findAllReagentFeatures(tmpVector, rID)
+	
+	content = ""
+	
+	#content += "======================================================\n"
+	content += "\nOpen Reading Frames for " + vectorID + "\n"
+	content += "======================================================\n\n"
+	#orf_no = 1
+
+	for f in fwd_frames.keys():
+		#print "Frame " + `f`	# don't use in browser
+		#print `fwd_frames`
+		if fwd_frames[f]:
+			fList = fwd_frames[f]
+			
+			if f != 1:
+				content += '\n'
+				
+			content += "******************************************************\n5'3' frame " + `f` + "\n******************************************************\n"
+			
+			for fTemp in fList:
+				frame = fTemp.getSequence()
+				
+				# Jan. 26/09
+				fStart = fTemp.getSeqStart()
+				fEnd = fTemp.getSeqEnd()
+				#print frame			# debug - don't use in browser
+				mw = fTemp.getMW()
+				
+				if len(frame) >= 100:
+					content += "\nORF no. " + `orf_no` + '\n======================\n'
+					
+					normal_frames.append(frame)
+
+					#f_out.write("Frame " + `f` + "\n")
+					#f_out.write(frame + '\n'+'\n')
+					
+					# Jan. 26/09
+					content += "Start position = " + `fStart` + "\n"
+					content += "Stop position = " + `fEnd` + "\n"
+					content += "Length: " + `len(frame)` + " aa\n"
+					
+					# add MW and feature overlap
+					content += "Molecular Weight: " + str(mw) + ' kDa\n\n'
+					
+					# Removed Feb. 5/09 - this layout is split in Word and most users don't like it - confirm with Karen
+					## Jan. 26/09: output sequence in chunks of 100
+					#i = 0
+					
+					#while i < len(frame):
+						#content += frame[i:i+100]
+						#content += '\t'
+						
+						#if len(frame) - i >= 100:
+							#content += `i+100` + '\n'
+							
+						#i += 100
+					
+					# Feb. 5/09
+					#content += "\n"
+					content += frame
+					#content += "\n"
+
+					# OVERLAPPING FEATURES
+					content += "\n\nOverlapping features:\n---------------------\n"
+					
+					for tmp_f in features:
+						tmp_fStart = tmp_f.getFeatureStartPos()
+						tmp_fEnd = tmp_f.getFeatureEndPos()
+						
+						# 4 cases:
+						# Feature contained within ORF (tmp_fStart >= fStart and tmp_fEnd <= fEnd)
+						# Feature starts inside ORF (tmp_fStart >= fStart and tmp_fStart <= fEnd)
+						# Feature ends inside ORF (tmp_fEnd >= fStart and tmp_fEnd <= fEnd)
+						# ORF contained within feature (tmp_fStart <= fStart and tmp_fEnd >= fEnd)
+						if (tmp_fStart >= fStart and tmp_fEnd <= fEnd) or (tmp_fEnd >= fStart and tmp_fEnd <= fEnd) or (tmp_fStart >= fStart and tmp_fStart <= fEnd) or (tmp_fStart <= fStart and tmp_fEnd >= fEnd):
+							if tmp_f.getFeatureType().lower() == 'cdna insert':
+								content += "cDNA"
+							elif tmp_f.getFeatureType().lower() == 'promoter':
+								content += tmp_f.getFeatureName().title() + " promoter"
+							elif tmp_f.getFeatureType().lower() == "5' cloning site" or tmp_f.getFeatureType().lower() == "3' cloning site":
+								content += tmp_f.getFeatureName().title() + " cloning site"
+							elif tmp_f.getFeatureType().lower() == 'restriction site':
+								content += tmp_f.getFeatureName().title() + " restriction site"
+							elif tmp_f.getFeatureType().lower() == 'polya':
+								content += tmp_f.getFeatureName().title() + " polyA"
+							#elif tmp_f.getFeatureType().lower() == 'intron':
+								#content += tmp_f.getFeatureName().title() + " intron"
+							elif tmp_f.getFeatureType().lower() == 'origin':
+								content += tmp_f.getFeatureName().title() + " ori."
+							#elif tmp_f.getFeatureType().lower() == 'tag':
+								#content += tmp_f.getFeatureName().title() + " tag"
+							elif tmp_f.getFeatureType().lower() == 'transcription terminator':
+								content += tmp_f.getFeatureName().title() + " tscn. ter."
+							else:
+								content += tmp_f.getFeatureName().title()
+								
+							content += ": " + `tmp_fStart` + "-" + `tmp_fEnd` + '\n'
+						
+					content += "\n"
+				#else:
+					##f_out.write("Frame " + `f` + "\n")
+					##f_out.write("Shorter than 100 nt\n\n")
+					
+					#content += ("Frame " + `f` + "\n")
+					#content += ("Shorter than 100 aa\n\n")
+					
+				orf_no += 1
+		#else:
+			#content += "Shorter than 100 aa\n\n"
+			
+	content += "\n"
+	#orf_no = 1	# no, don't reset, let increment after 5'3'
+
+	for f in rev_frames.keys():
+		#print "Frame " + `f`	# don't use in browser, only for command-line debugging
+		
+		if rev_frames[f]:
+			rList = rev_frames[f]
+			
+			if f != 1:
+				content += '\n'
+				
+			content += "******************************************************\n3'5' frame " + `f` + "\n******************************************************\n"
+			
+			for rTemp in rList:
+				frame = rTemp.getSequence()
+				
+				#print frame	# don't use in browser, only for command-line
+				
+				# Jan. 26/09
+				fStart = rTemp.getSeqStart()
+				fEnd = rTemp.getSeqEnd()
+				mw = rTemp.getMW()
+				
+				if len(frame) >= 100:
+					content += "\nORF no. " + `orf_no` + '\n======================\n'
+					
+					normal_frames.append(frame)
+				
+					#f_out.write("Frame " + `f` + "\n")
+					#f_out.write(frame + '\n'+'\n')
+					
+					# Jan. 28/09
+					revStart = len(seq) - fEnd + 1
+					revEnd = revStart + len(frame)*3 - 1
+					
+					# Jan. 26/09
+					#content += "Start position = " + `fStart` + "\n"
+					#content += "Stop position = " + `fEnd` + "\n"
+					
+					# Jan. 28/09: Because it's in reverse orientation, swap stop and start
+					content += "Start position = " + `revEnd` + "\n"
+					content += "Stop position = " + `revStart` + "\n"
+					
+					content += "Length: " + `len(frame)` + " aa\n"
+					
+					# add MW and feature overlap
+					content += "Molecular Weight: " + str(mw) + " kDa\n\n"
+					
+					# Removed Feb. 5/09 - this layout is split in Word and most users don't like it - confirm with Karen
+					## Jan. 26/09: output sequence in chunks of 100
+					#i = 0
+					
+					#while i < len(frame):
+						#content += frame[i:i+100]
+						#content += '\t'
+						
+						#if len(frame) - i >= 100:
+							#content += `i+100` + '\n'
+							
+						#i += 100
+					
+					# Feb. 5/09
+					#content += "\n"
+					content += frame
+					#content += "\n"
+					
+					# OVERLAPPING FEATURES
+					content += "\n\nOverlapping features:\n---------------------\n"
+					
+					for tmp_f in features:
+						tmp_fStart = tmp_f.getFeatureStartPos()
+						tmp_fEnd = tmp_f.getFeatureEndPos()
+						
+						# 4 cases:
+						# Feature contained within ORF (tmp_fStart >= revStart and tmp_fEnd <= revEnd)
+						# Feature starts inside ORF (tmp_fEnd >= revStart and tmp_fEnd <= revEnd)
+						# Feature ends inside ORF (tmp_fStart >= revStart and tmp_fStart <= revEnd)
+						# ORF contained within feature (tmp_fStart <= revStart and tmp_fEnd >= revEnd)
+						if (tmp_fStart >= revStart and tmp_fEnd <= revEnd) or (tmp_fEnd >= revStart and tmp_fEnd <= revEnd) or (tmp_fStart >= revStart and tmp_fStart <= revEnd) or (tmp_fStart <= revStart and tmp_fEnd >= revEnd):
+							if tmp_f.getFeatureType().lower() == 'cdna insert':
+								content += "cDNA"
+							#elif tmp_f.getFeatureType().lower() == 'intron':
+								#content += tmp_f.getFeatureName().title() + " intron"
+							elif tmp_f.getFeatureType().lower() == 'promoter':
+								content += tmp_f.getFeatureName().title() + " promoter"
+							elif tmp_f.getFeatureType().lower() == "5' cloning site" or tmp_f.getFeatureType().lower() == "3' cloning site":
+								content += tmp_f.getFeatureName().title() + " cloning site"
+							elif tmp_f.getFeatureType().lower() == 'restriction site':
+								content += tmp_f.getFeatureName().title() + " restriction site"
+							elif tmp_f.getFeatureType().lower() == 'intron':
+								content += tmp_f.getFeatureName().title() + " intron"
+							elif tmp_f.getFeatureType().lower() == 'polya':
+								content += tmp_f.getFeatureName().title() + " polyA"
+							elif tmp_f.getFeatureType().lower() == 'origin':
+								content += tmp_f.getFeatureName().title() + " ori."
+							#elif tmp_f.getFeatureType().lower() == 'tag type':
+								#content += tmp_f.getFeatureName().title() + " tag"
+							elif tmp_f.getFeatureType().lower() == 'transcription terminator':
+								content += tmp_f.getFeatureName().title() + " tscn. ter."
+							else:
+								content += tmp_f.getFeatureName().title()
+								
+							content += ": " + `tmp_fStart` + "-" + `tmp_fEnd` + '\n'
+						
+					content += "\n"
+				#else:
+					##f_out.write("Frame " + `f` + "\n")
+					##f_out.write("Shorter than 100 nt\n\n")
+					
+					#content += "Frame " + `f` + "\n"
+					#content += "Shorter than 100 aa\n\n"
+					
+				orf_no += 1
+		#else:
+			#content += "Shorter than 100 aa\n\n"
+	
+	#print content
+	return content
+	
+	
+def getSpliceORFs(rID, seq, vectorID):
+	global orf_no
+	global normal_frames
+	
+	content = ""
+	
+	# Feb. 4/09: Add SPLICE ORFs
+	# Not using findReagentFeatureStart here, because it does not return multiple values as of now - needs fixing in reagent_handler, but for this purpose use 'features' list that was used earlier
+	splice_donor_pos = {}
+	splice_acceptor_pos = {}
+	
+	fwd_frames = {}
+	rev_frames = {}
+	
+	tmpVector = Vector(rID)
+	features = rHandler.findAllReagentFeatures(tmpVector, rID)
+	
+	#print `features`
+	
+	for tmp_feature in features:
+		if tmp_feature.getFeatureType() == "miscellaneous":
+			if tmp_feature.getFeatureName() == "splice donor":
+				tmp_start_pos = tmp_feature.getFeatureStartPos()
+				tmp_end_pos = tmp_feature.getFeatureEndPos()
+				splice_donor_pos[tmp_start_pos] = tmp_end_pos
+			elif tmp_feature.getFeatureName() == "splice acceptor":
+				tmp_start_pos = tmp_feature.getFeatureStartPos()
+				tmp_end_pos = tmp_feature.getFeatureEndPos()
+				splice_acceptor_pos[tmp_start_pos] = tmp_end_pos
+	
+	#print "Donors: " + `splice_donor_pos`
+	#print "Acceptors: " + `splice_acceptor_pos`
+	
+	minDiff = len(seq)
+	tmpClosest = -1		# acceptor position (int)
+	closestPairs = {}	# (donor START, acceptor END) tuples
+	
+	for dStart in splice_donor_pos.keys():
+		for aStart in splice_acceptor_pos.keys():
+			if aStart > dStart:
+				tmpDiff = aStart - dStart
+				
+				if tmpDiff < minDiff:
+					minDiff = tmpDiff
+					aEnd = splice_acceptor_pos[aStart]
+					tmpClosest = aEnd
+		
+		if tmpClosest > 0:
+			closestPairs[dStart] = tmpClosest
+			
+		minDiff = len(seq)	# reset!!!!!!
+	
+	for donorStart in closestPairs.keys():
+		#print donorStart
+		acceptorEnd = closestPairs[donorStart]
+		#print acceptorEnd
+		seqPre = seq[0:donorStart-1]
+		#print "pre " + seqPre
+		seqPost = seq[acceptorEnd:]
+		fusionSeq = seqPre + seqPost
+		#print fusionSeq
+	
+		#content += getAllFrames(rID, fusionSeq, vectorID)
+		
+		# debug reverse
+		#seq = dnaHandler.reverse_complement(seq)
+		#print seq
+		#protHandler.findVectorORFs(fusionSeq, 1)
+		#return
+		
+		# Translate forward-oriented sequence in 3 frames
+		if len(fusionSeq) > 0:
+			for frame in range(1,4):
+				prots = protHandler.findVectorORFs(fusionSeq, frame)
+			
+				if len(prots) > 0:
+					for protEntry in prots:
+						peptideSeq = protEntry.getSequence()
+						sStart = protEntry.getSeqStart()
+						sEnd = protEntry.getSeqEnd()
+						
+						# Change end position to include the splice portion
+						origSeqEnd = sEnd + (acceptorEnd-donorStart) + 1
+						protEntry.setSeqEnd(origSeqEnd)
+						
+						if len(peptideSeq) > 0 and sStart > 0 and sEnd > 0:
+						
+							if fwd_frames.has_key(frame):
+								tmp_fwd = fwd_frames[frame]
+								tmp_fwd.append(protEntry)
+								fwd_frames[frame] = tmp_fwd
+							else:
+								tmp_fwd = []
+								tmp_fwd.append(protEntry)
+								fwd_frames[frame] = tmp_fwd
+		
+				## increment loop counter
+				#frame += 1
+				
+		
+		# Translate REVERSE-oriented sequence in 3 frames
+		if len(fusionSeq) > 0:
+			#print fusionSeq
+			fusionSeq = dnaHandler.reverse_complement(fusionSeq)
+			#print fusionSeq
+		
+			for frame in range(1,4):
+				tmp_rev = []
+				
+				#print "Translating REVERSE F" + `frame`
+				
+				#protEntry = protHandler.translate(seq, frame, openClosed)
+				prots = protHandler.findVectorORFs(fusionSeq, frame)
+				
+				if len(prots) > 0:
+					for protEntry in prots:
+						protEntry.setOrientation('reverse')
+						peptideSeq = protEntry.getSequence()
+						
+						sStart = protEntry.getSeqStart()
+						sEnd = protEntry.getSeqEnd()
+						
+						# Change end position to include the splice portion
+						
+						# Feb. 9/09: update splice donor/acceptor positions to be in reverse orientation too???
+						rev_donor_start = acceptorEnd
+						rev_acceptor_end = donorStart
+						
+						origSeqEnd = sEnd + (rev_donor_start-rev_acceptor_end) + 1
+						
+						protEntry.setSeqEnd(origSeqEnd)
+						
+						if len(peptideSeq) > 0 and sStart > 0 and sEnd > 0:
+							#f_ind = frame+1	# jan. 27/09: decided not to do this, too confusing
+							f_ind = frame
+							#print f_ind
+							
+							if rev_frames.has_key(f_ind):
+								tmp_rev = rev_frames[f_ind]
+								tmp_rev.append(protEntry)
+								rev_frames[f_ind] = tmp_rev
+							else:
+								tmp_rev = []
+								tmp_rev.append(protEntry)
+								rev_frames[f_ind] = tmp_rev
+
+		content = "===============================================================\nORFs generated from potential splicing events:\n"
+		content += "===============================================================\n\n"
+		
+		#print `normal_frames`
+		#print `fwd_frames`
+		#print `rev_frames`
+		
+		for f in fwd_frames.keys():
+		
+			#print "Frame " + `f`	# don't use in browser
+			#print `fwd_frames`
+			if fwd_frames[f]:
+				
+				fList = fwd_frames[f]
+				#print `fList`
+				#content += "******************************************************\n5'3' frame " + `f` + "\n******************************************************\n"
+				
+				for fTemp in fList:
+					frame = fTemp.getSequence()
+					#print frame
+					
+					# Only output new frames produced by splicing
+					if frame not in normal_frames:
+						if f != 1:
+							content += '\n'
+							
+						content += "******************************************************\n5'3' frame " + `f` + "\n******************************************************\n"
+				
+						# Jan. 26/09
+						fStart = fTemp.getSeqStart()
+						fEnd = fTemp.getSeqEnd()
+						#print frame			# debug - don't use in browser
+						mw = fTemp.getMW()
+						
+						if len(frame) >= 100:
+							content += "\nORF no. " + `orf_no` + '\n======================\n'
+							
+							#f_out.write("Frame " + `f` + "\n")
+							#f_out.write(frame + '\n'+'\n')
+							
+							# Jan. 26/09
+							content += "Start position = " + `fStart` + "\n"
+							content += "Stop position = " + `fEnd` + "\n"
+							content += "Length: " + `len(frame)` + " aa\n"
+							
+							# add MW and feature overlap
+							content += "Molecular Weight: " + str(mw) + ' kDa\n\n'
+							
+							# Removed Feb. 5/09 - this layout is split in Word and most users don't like it - confirm with Karen
+							## Jan. 26/09: output sequence in chunks of 100
+							#i = 0
+							
+							#while i < len(frame):
+								#content += frame[i:i+100]
+								#content += '\t'
+								
+								#if len(frame) - i >= 100:
+									#content += `i+100` + '\n'
+									
+								#i += 100
+								
+							# Feb. 5/09
+							#content += "\n"
+							content += frame
+							#content += "\n"
+							
+							# OVERLAPPING FEATURES
+							content += "\n\nOverlapping features:\n---------------------\n"
+							
+							for tmp_f in features:
+								tmp_fStart = tmp_f.getFeatureStartPos()
+								tmp_fEnd = tmp_f.getFeatureEndPos()
+								
+								# 4 cases:
+								# Feature contained within ORF (tmp_fStart >= fStart and tmp_fEnd <= fEnd)
+								# Feature starts inside ORF (tmp_fStart >= fStart and tmp_fStart <= fEnd)
+								# Feature ends inside ORF (tmp_fEnd >= fStart and tmp_fEnd <= fEnd)
+								# ORF contained within feature (tmp_fStart <= fStart and tmp_fEnd >= fEnd)
+								if (tmp_fStart >= fStart and tmp_fEnd <= fEnd) or (tmp_fEnd >= fStart and tmp_fEnd <= fEnd) or (tmp_fStart >= fStart and tmp_fStart <= fEnd) or (tmp_fStart <= fStart and tmp_fEnd >= fEnd):
+									if tmp_f.getFeatureType().lower() == 'cdna insert':
+										content += "cDNA"
+									elif tmp_f.getFeatureType().lower() == "5' cloning site" or tmp_f.getFeatureType().lower() == "3' cloning site":
+										content += tmp_f.getFeatureName().title() + " cloning site"
+									elif tmp_f.getFeatureType().lower() == 'restriction site':
+										content += tmp_f.getFeatureName().title() + " restriction site"
+									elif tmp_f.getFeatureType().lower() == 'origin':
+										content += tmp_f.getFeatureName().title() + " ori."
+									#elif tmp_f.getFeatureType().lower() == 'intron':
+										#content += tmp_f.getFeatureName().title() + " intron"
+									elif tmp_f.getFeatureType().lower() == 'polya':
+										content += tmp_f.getFeatureName().title() + " polyA"
+									elif tmp_f.getFeatureType().lower() == 'promoter':
+										content += tmp_f.getFeatureName().title() + " promoter"
+									#elif tmp_f.getFeatureType().lower() == 'tag type':
+										#content += tmp_f.getFeatureName().title() + " tag"
+									elif tmp_f.getFeatureType().lower() == 'transcription terminator':
+										content += tmp_f.getFeatureName().title() + " tscn. ter."
+									else:
+										content += tmp_f.getFeatureName().title()
+										
+									content += ": " + `tmp_fStart` + "-" + `tmp_fEnd` + '\n'
+									#content += "\n"
+						#else:
+							##f_out.write("Frame " + `f` + "\n")
+							##f_out.write("Shorter than 100 nt\n\n")
+							
+							#content += ("Frame " + `f` + "\n")
+							#content += ("Shorter than 100 aa\n\n")
+							
+						orf_no += 1
+				#else:
+					#content += "Shorter than 100 aa\n\n"
+			
+		content += "\n"
+		
+		for f in rev_frames.keys():
+			
+			if rev_frames[f]:
+				rList = rev_frames[f]
+				
+				for rTemp in rList:
+					frame = rTemp.getSequence()
+					
+					# Only output new frames produced by splicing
+					if frame not in normal_frames:
+						
+						if f != 1:
+							content += '\n'
+					
+						content += "******************************************************\n3'5' frame " + `f` + "\n******************************************************\n"
+				
+						#print "Frame " + `f`	# don't use in browser, only for command-line debugging
+						#print frame	# don't use in browser, only for command-line
+						
+						# Jan. 26/09
+						fStart = rTemp.getSeqStart()
+						fEnd = rTemp.getSeqEnd()
+						#print fEnd
+						mw = rTemp.getMW()
+						
+						if len(frame) >= 100:
+							content += "\nORF no. " + `orf_no` + '\n======================\n'
+							
+							#normal_frames.append(frame)
+						
+							#f_out.write("Frame " + `f` + "\n")
+							#f_out.write(frame + '\n'+'\n')
+							
+							# Jan. 28/09
+							revStart = len(seq) - fEnd + 1
+							revEnd = revStart + len(frame)*3 - 1
+							
+							#print revStart
+							#print revEnd
+							
+							# Jan. 26/09
+							#content += "Start position = " + `fStart` + "\n"
+							#content += "Stop position = " + `fEnd` + "\n"
+							
+							# Jan. 28/09: Because it's in reverse orientation, swap stop and start
+							content += "Start position = " + `revEnd` + "\n"
+							content += "Stop position = " + `revStart` + "\n"
+							
+							content += "Length: " + `len(frame)` + " aa\n"
+							
+							# add MW and feature overlap
+							content += "Molecular Weight: " + str(mw) + " kDa\n\n"
+							
+							#content += "\n"
+							
+							# Removed Feb. 5/09 - this layout is split in Word and most users don't like it - confirm with Karen
+							## Jan. 26/09: output sequence in chunks of 100
+							#i = 0
+							
+							#while i < len(frame):
+								#content += frame[i:i+100]
+								#content += '\t'
+								
+								#if len(frame) - i >= 100:
+									#content += `i+100` + '\n'
+									
+								#i += 100
+							
+							# Feb. 5/09
+							#content += "\n"
+							content += frame
+							#content += "\n"
+
+							# OVERLAPPING FEATURES
+							content += "\n\nOverlapping features:\n---------------------\n"
+							
+							for tmp_f in features:
+								#print tmp_f.getFeatureType()
+								tmp_fStart = tmp_f.getFeatureStartPos()
+								tmp_fEnd = tmp_f.getFeatureEndPos()
+								
+								# 4 cases:
+								# Feature contained within ORF (tmp_fStart >= revStart and tmp_fEnd <= revEnd)
+								# Feature starts inside ORF (tmp_fEnd >= revStart and tmp_fEnd <= revEnd)
+								# Feature ends inside ORF (tmp_fStart >= revStart and tmp_fStart <= revEnd)
+								# ORF contained within feature (tmp_fStart <= revStart and tmp_fEnd >= revEnd)
+								if (tmp_fStart >= revStart and tmp_fEnd <= revEnd) or (tmp_fEnd >= revStart and tmp_fEnd <= revEnd) or (tmp_fStart >= revStart and tmp_fStart <= revEnd) or (tmp_fStart <= revStart and tmp_fEnd >= revEnd):
+									if tmp_f.getFeatureType().lower() == 'cdna insert':
+										content += "cDNA"
+									elif tmp_f.getFeatureType().lower() == "5' cloning site" or tmp_f.getFeatureType().lower() == "3' cloning site":
+										content += tmp_f.getFeatureName().title() + " cloning site"
+									elif tmp_f.getFeatureType().lower() == 'restriction site':
+										content += tmp_f.getFeatureName().title() + " restriction site"
+									#elif tmp_f.getFeatureType().lower() == 'intron':
+										#content += tmp_f.getFeatureName().title() + " intron"
+									elif tmp_f.getFeatureType().lower() == 'polya':
+										content += tmp_f.getFeatureName().title() + " polyA"
+									elif tmp_f.getFeatureType().lower() == 'promoter':
+										content += tmp_f.getFeatureName().title() + " promoter"
+									elif tmp_f.getFeatureType().lower() == 'origin':
+										content += tmp_f.getFeatureName().title() + " ori."
+									#elif tmp_f.getFeatureType().lower() == 'tag type':
+										#content += tmp_f.getFeatureName().title() + " tag"
+									elif tmp_f.getFeatureType().lower() == 'transcription terminator':
+										content += tmp_f.getFeatureName().title() + " tscn. ter."
+									else:
+										content += tmp_f.getFeatureName().title()
+										
+									content += ": " + `tmp_fStart` + "-" + `tmp_fEnd` + '\n'
+									#content += "\n"
+						#else:
+							##f_out.write("Frame " + `f` + "\n")
+							##f_out.write("Shorter than 100 nt\n\n")
+							
+							#content += "Frame " + `f` + "\n"
+							#content += "Shorter than 100 aa\n\n"
+							
+						orf_no += 1
+				#else:
+					#content += "Shorter than 100 aa\n\n"
+	
+	# REVERSE-ORIENTED SEQUENCE
+	closestPairs_rev = {}	# (acceptor start, donor end) tuples
+	minDiff = len(seq)
+	
+	if len(closestPairs) == 0:
+		# Do the opposite for reverse-oriented sequences, where donor start > acceptor end
+		for aStart in splice_acceptor_pos.keys():
+			for dStart in splice_donor_pos.keys():
+				if dStart > aStart:
+					tmpDiff = dStart - aStart
+					
+					if tmpDiff < minDiff:
+						minDiff = tmpDiff
+						dEnd = splice_donor_pos[dStart]
+						tmpClosest_rev = dEnd
+			
+			closestPairs_rev[aStart] = tmpClosest_rev
+			minDiff = len(seq)	# reset!!!!!!
+		
+		#print `closestPairs_rev`
+		
+		#acceptorStart = closestPairs_rev[donorStart]
+		#donorEnd = splice_donor_pos[donorStart]
+		
+		for acceptorStart in closestPairs_rev.keys():
+			#print acceptorEnd
+			donorEnd = closestPairs_rev[acceptorStart]
+			#print donorStart
+			seqPre = seq[0:acceptorStart-1]
+			#print "pre " + seqPre
+			seqPost = seq[donorEnd:]
+			fusionSeq = seqPre + seqPost
+			#print fusionSeq
+		
+			#content += getAllFrames(rID, fusionSeq, vectorID)
+			
+			# debug reverse
+			#seq = dnaHandler.reverse_complement(seq)
+			#print seq
+			#protHandler.findVectorORFs(fusionSeq, 1)
+			#return
+			
+			# Translate forward-oriented sequence in 3 frames
+			if len(fusionSeq) > 0:
+				for frame in range(1,4):
+					prots = protHandler.findVectorORFs(fusionSeq, frame)
+				
+					if len(prots) > 0:
+						for protEntry in prots:
+							peptideSeq = protEntry.getSequence()
+							sStart = protEntry.getSeqStart()
+							sEnd = protEntry.getSeqEnd()
+							
+							# Change end position to include the splice portion
+							origSeqEnd = sEnd + (donorEnd-acceptorStart) + 1
+							protEntry.setSeqEnd(origSeqEnd)
+							
+							if len(peptideSeq) > 0 and sStart > 0 and sEnd > 0:
+							
+								if fwd_frames.has_key(frame):
+									tmp_fwd = fwd_frames[frame]
+									tmp_fwd.append(protEntry)
+									fwd_frames[frame] = tmp_fwd
+								else:
+									tmp_fwd = []
+									tmp_fwd.append(protEntry)
+									fwd_frames[frame] = tmp_fwd
+			
+					## increment loop counter
+					#frame += 1
+					
+			
+			# Translate REVERSE-oriented sequence in 3 frames
+			if len(fusionSeq) > 0:
+				#print fusionSeq
+				fusionSeq = dnaHandler.reverse_complement(fusionSeq)
+				#print fusionSeq
+			
+				for frame in range(1,4):
+					tmp_rev = []
+					
+					#print "Translating F" + `frame`
+					
+					#protEntry = protHandler.translate(seq, frame, openClosed)
+					prots = protHandler.findVectorORFs(fusionSeq, frame)
+					
+					if len(prots) > 0:
+						for protEntry in prots:
+							protEntry.setOrientation('reverse')
+							peptideSeq = protEntry.getSequence()
+							#print peptideSeq
+							
+							sStart = protEntry.getSeqStart()
+							#print sStart
+							sEnd = protEntry.getSeqEnd()
+							
+							
+							# Change end position to include the splice portion
+							# Feb. 9/09: update splice donor/acceptor positions to be in reverse orientation too
+							origSeqEnd = sEnd + (donorEnd-acceptorStart) + 1
+							
+							protEntry.setSeqEnd(origSeqEnd)
+							
+							if len(peptideSeq) > 0 and sStart > 0 and sEnd > 0:
+								#f_ind = frame+1	# jan. 27/09: decided not to do this, too confusing
+								f_ind = frame
+								#print f_ind
+								
+								if rev_frames.has_key(f_ind):
+									tmp_rev = rev_frames[f_ind]
+									tmp_rev.append(protEntry)
+									rev_frames[f_ind] = tmp_rev
+								else:
+									tmp_rev = []
+									tmp_rev.append(protEntry)
+									rev_frames[f_ind] = tmp_rev
+
+		content = "===============================================================\nORFs generated from potential splicing events:\n"
+		content += "===============================================================\n\n"
+		
+		#print `normal_frames`
+		#print `fwd_frames`
+		#print `rev_frames`
+		
+		for f in fwd_frames.keys():
+		
+			#print "Frame " + `f`	# don't use in browser
+			#print `fwd_frames`
+			if fwd_frames[f]:
+				
+				fList = fwd_frames[f]
+				#print `fList`
+				#content += "******************************************************\n5'3' frame " + `f` + "\n******************************************************\n"
+				
+				for fTemp in fList:
+					frame = fTemp.getSequence()
+					#print frame
+					
+					# Only output new frames produced by splicing
+					if frame not in normal_frames:
+						#print "yeah???"
+						if f != 1:
+							content += '\n'
+							
+						content += "******************************************************\n5'3' frame " + `f` + "\n******************************************************\n"
+				
+						# Jan. 26/09
+						fStart = fTemp.getSeqStart()
+						fEnd = fTemp.getSeqEnd()
+						#print frame			# debug - don't use in browser
+						mw = fTemp.getMW()
+						
+						if len(frame) >= 100:
+							content += "\nORF no. " + `orf_no` + '\n======================\n'
+							
+							#f_out.write("Frame " + `f` + "\n")
+							#f_out.write(frame + '\n'+'\n')
+							
+							# Jan. 26/09
+							content += "Start position = " + `fStart` + "\n"
+							content += "Stop position = " + `fEnd` + "\n"
+							content += "Length: " + `len(frame)` + " aa\n"
+							
+							# add MW and feature overlap
+							content += "Molecular Weight: " + str(mw) + ' kDa\n\n'
+							
+							# Removed Feb. 5/09 - this layout is split in Word and most users don't like it - confirm with Karen
+							## Jan. 26/09: output sequence in chunks of 100
+							#i = 0
+							
+							#while i < len(frame):
+								#content += frame[i:i+100]
+								#content += '\t'
+								
+								#if len(frame) - i >= 100:
+									#content += `i+100` + '\n'
+									
+								#i += 100
+								
+							# Feb. 5/09
+							#content += "\n"
+							content += frame
+							#content += "\n"
+							
+							# OVERLAPPING FEATURES
+							content += "\n\nOverlapping features:\n---------------------\n"
+							
+							for tmp_f in features:
+								tmp_fStart = tmp_f.getFeatureStartPos()
+								tmp_fEnd = tmp_f.getFeatureEndPos()
+								
+								# 4 cases:
+								# Feature contained within ORF (tmp_fStart >= fStart and tmp_fEnd <= fEnd)
+								# Feature starts inside ORF (tmp_fStart >= fStart and tmp_fStart <= fEnd)
+								# Feature ends inside ORF (tmp_fEnd >= fStart and tmp_fEnd <= fEnd)
+								# ORF contained within feature (tmp_fStart <= fStart and tmp_fEnd >= fEnd)
+								if (tmp_fStart >= fStart and tmp_fEnd <= fEnd) or (tmp_fEnd >= fStart and tmp_fEnd <= fEnd) or (tmp_fStart >= fStart and tmp_fStart <= fEnd) or (tmp_fStart <= fStart and tmp_fEnd >= fEnd):
+									if tmp_f.getFeatureType().lower() == 'cdna insert':
+										content += "cDNA"
+									elif tmp_f.getFeatureType().lower() == "5' cloning site" or tmp_f.getFeatureType().lower() == "3' cloning site":
+										content += tmp_f.getFeatureName().title() + " cloning site"
+									elif tmp_f.getFeatureType().lower() == 'restriction site':
+										content += tmp_f.getFeatureName().title() + " restriction site"
+									elif tmp_f.getFeatureType().lower() == 'origin':
+										content += tmp_f.getFeatureName().title() + " ori."
+									#elif tmp_f.getFeatureType().lower() == 'intron':
+										#content += tmp_f.getFeatureName().title() + " intron"
+									elif tmp_f.getFeatureType().lower() == 'polya':
+										content += tmp_f.getFeatureName().title() + " polyA"
+									elif tmp_f.getFeatureType().lower() == 'promoter':
+										content += tmp_f.getFeatureName().title() + " promoter"
+									#elif tmp_f.getFeatureType().lower() == 'tag type':
+										#content += tmp_f.getFeatureName().title() + " tag"
+									elif tmp_f.getFeatureType().lower() == 'transcription terminator':
+										content += tmp_f.getFeatureName().title() + " tscn. ter."
+									else:
+										content += tmp_f.getFeatureName().title()
+										
+									content += ": " + `tmp_fStart` + "-" + `tmp_fEnd` + '\n'
+									#content += "\n"
+						#else:
+							##f_out.write("Frame " + `f` + "\n")
+							##f_out.write("Shorter than 100 nt\n\n")
+							
+							#content += ("Frame " + `f` + "\n")
+							#content += ("Shorter than 100 aa\n\n")
+							
+						orf_no += 1
+				#else:
+					#content += "Shorter than 100 aa\n\n"
+			
+		content += "\n"
+		
+		for f in rev_frames.keys():
+			
+			if rev_frames[f]:
+				rList = rev_frames[f]
+				
+				for rTemp in rList:
+					frame = rTemp.getSequence()
+					
+					# Only output new frames produced by splicing
+					if frame not in normal_frames:
+						
+						if f != 1:
+							content += '\n'
+					
+						content += "******************************************************\n3'5' frame " + `f` + "\n******************************************************\n"
+				
+						#print "Frame " + `f`	# don't use in browser, only for command-line debugging
+						#print frame	# don't use in browser, only for command-line
+						
+						# Jan. 26/09
+						fStart = rTemp.getSeqStart()
+						fEnd = rTemp.getSeqEnd()
+						#print fEnd
+						mw = rTemp.getMW()
+						
+						if len(frame) >= 100:
+							content += "\nORF no. " + `orf_no` + '\n======================\n'
+							
+							#normal_frames.append(frame)
+						
+							#f_out.write("Frame " + `f` + "\n")
+							#f_out.write(frame + '\n'+'\n')
+							
+							# Jan. 28/09
+							revStart = len(seq) - fEnd + 1
+							revEnd = revStart + len(frame)*3 - 1
+							
+							#print revStart
+							#print revEnd
+							
+							# Jan. 26/09
+							#content += "Start position = " + `fStart` + "\n"
+							#content += "Stop position = " + `fEnd` + "\n"
+							
+							# Jan. 28/09: Because it's in reverse orientation, swap stop and start
+							content += "Start position = " + `revEnd` + "\n"
+							content += "Stop position = " + `revStart` + "\n"
+							
+							content += "Length: " + `len(frame)` + " aa\n"
+							
+							# add MW and feature overlap
+							content += "Molecular Weight: " + str(mw) + " kDa\n\n"
+							
+							#content += "\n"
+							
+							# Removed Feb. 5/09 - this layout is split in Word and most users don't like it - confirm with Karen
+							## Jan. 26/09: output sequence in chunks of 100
+							#i = 0
+							
+							#while i < len(frame):
+								#content += frame[i:i+100]
+								#content += '\t'
+								
+								#if len(frame) - i >= 100:
+									#content += `i+100` + '\n'
+									
+								#i += 100
+							
+							# Feb. 5/09
+							#content += "\n"
+							content += frame
+							#content += "\n"
+
+							# OVERLAPPING FEATURES
+							content += "\n\nOverlapping features:\n---------------------\n"
+							
+							for tmp_f in features:
+								tmp_fStart = tmp_f.getFeatureStartPos()
+								tmp_fEnd = tmp_f.getFeatureEndPos()
+								
+								# 4 cases:
+								# Feature contained within ORF (tmp_fStart >= revStart and tmp_fEnd <= revEnd)
+								# Feature starts inside ORF (tmp_fEnd >= revStart and tmp_fEnd <= revEnd)
+								# Feature ends inside ORF (tmp_fStart >= revStart and tmp_fStart <= revEnd)
+								# ORF contained within feature (tmp_fStart <= revStart and tmp_fEnd >= revEnd)
+								if (tmp_fStart >= revStart and tmp_fEnd <= revEnd) or (tmp_fEnd >= revStart and tmp_fEnd <= revEnd) or (tmp_fStart >= revStart and tmp_fStart <= revEnd) or (tmp_fStart <= revStart and tmp_fEnd >= revEnd):
+									if tmp_f.getFeatureType().lower() == 'cdna insert':
+										content += "cDNA"
+									elif tmp_f.getFeatureType().lower() == "5' cloning site" or tmp_f.getFeatureType().lower() == "3' cloning site":
+										content += tmp_f.getFeatureName().title() + " cloning site"
+									elif tmp_f.getFeatureType().lower() == 'restriction site':
+										content += tmp_f.getFeatureName().title() + " restriction site"
+									#elif tmp_f.getFeatureType().lower() == 'intron':
+										#content += tmp_f.getFeatureName().title() + " intron"
+									elif tmp_f.getFeatureType().lower() == 'polya':
+										content += tmp_f.getFeatureName().title() + " polyA"
+									elif tmp_f.getFeatureType().lower() == 'promoter':
+										content += tmp_f.getFeatureName().title() + " promoter"
+									elif tmp_f.getFeatureType().lower() == 'origin':
+										content += tmp_f.getFeatureName().title() + " ori."
+									#elif tmp_f.getFeatureType().lower() == 'tag type':
+										#content += tmp_f.getFeatureName().title() + " tag"
+									elif tmp_f.getFeatureType().lower() == 'transcription terminator':
+										content += tmp_f.getFeatureName().title() + " tscn. ter."
+									else:
+										content += tmp_f.getFeatureName().title()
+										
+									content += ": " + `tmp_fStart` + "-" + `tmp_fEnd` + '\n'
+									#content += "\n"
+						#else:
+							##f_out.write("Frame " + `f` + "\n")
+							##f_out.write("Shorter than 100 nt\n\n")
+							
+							#content += "Frame " + `f` + "\n"
+							#content += "Shorter than 100 aa\n\n"
+							
+						orf_no += 1
+				#else:
+					#content += "Shorter than 100 aa\n\n"
+					
+	return content
+
+def main():
+	
+	#print "Content-type:text/html"
+	#print
+	
+	form = cgi.FieldStorage(keep_blank_values="True")
+	
+	# DEBUG
+	#print "Content-type: text/html"
+	#print
+	#print `form`
+	#return
+	
+	print "Content-type: application/octet-stream"
+		
+	if form.has_key("rID"):
+		rID = form.getvalue("rID")
+		seq = form.getvalue("vector_sequence")
+	else:
+		# debug
+		rID = 89500	# V3302 - Rick, SDM
+		#rID = 115379	# V4539
+		
+		# update July 3/09
+		seqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+		seqID = rHandler.findIndexPropertyValue(rID, seqPropID)
+		
+		#seqID = rHandler.findIndexPropertyValue(rID, prop_Name_ID_Map["sequence"])		# removed July 3/09
+		seq = dnaHandler.findSequenceByID(seqID)
+	
+	vectorID = rHandler.convertDatabaseToReagentID(rID)
+	#print vectorID
+	
+	fname = vectorID + "_frames.doc"
+	
+	print "Content-Disposition: attachment; name=" + fname
+	
+	content1 = getAllFrames(rID, seq, vectorID)
+	content2 = getSpliceORFs(rID, seq, vectorID)
+	
+	print '\n' + content1 + '\n' + content2
+	#print content1
+	#print '\n' + content2
+	
+main()
\ No newline at end of file
diff --git a/OpenFreezer/cgi/vector_map.py b/OpenFreezer/cgi/vector_map.py
new file mode 100755
index 0000000..a5188c0
--- /dev/null
+++ b/OpenFreezer/cgi/vector_map.py
@@ -0,0 +1,917 @@
+#!/usr/local/bin/python
+
+#import reportlab
+
+#from reportlab.graphics.shapes import *
+#from reportlab.graphics.charts.doughnut import Doughnut
+#from reportlab.graphics import widgetbase
+#from reportlab.graphics import renderPDF
+#from reportlab.lib import *
+
+import reportlab
+import math
+import random
+
+from reportlab.pdfgen import canvas, pathobject
+from reportlab.pdfgen.canvas import *
+from reportlab.pdfgen.pathobject import *
+
+from reportlab.graphics import renderPDF
+from reportlab.graphics.shapes import *
+
+from reportlab.lib.units import cm
+from reportlab.lib.colors import *
+
+import cgi
+import cgitb; cgitb.enable()
+
+import MySQLdb
+import sys
+import os
+import stat
+import string
+
+from database_conn import DatabaseConn		# april 20/07
+from exception import *
+import utils
+
+from mapper import ReagentPropertyMapper, ReagentAssociationMapper, ReagentTypeMapper
+from general_handler import *
+from reagent_handler import ReagentHandler, InsertHandler
+from comment_handler import CommentHandler
+#from system_set_handler import SystemSetHandler
+from sequence_handler import DNAHandler, ProteinHandler
+
+from reagent import Reagent, Vector
+from sequence_feature import SequenceFeature
+
+# User and Project info
+from user_handler import UserHandler
+from project_database_handler import ProjectDatabaseHandler
+from session import Session
+
+# make global??
+dbConn = DatabaseConn()
+db = dbConn.databaseConnect()
+hostname = dbConn.getHostname()
+cursor = db.cursor()
+
+# Handlers and Mappers
+aHandler = AssociationHandler(db, cursor)
+rHandler = ReagentHandler(db, cursor)
+iHandler = InsertHandler(db, cursor)
+raHandler = ReagentAssociationHandler(db, cursor)
+sHandler = DNAHandler(db, cursor)
+pHandler = ReagentPropertyHandler(db, cursor)
+packetHandler = ProjectDatabaseHandler(db, cursor)
+uHandler = UserHandler(db, cursor)
+rtPropHandler = ReagentTypePropertyHandler(db, cursor)
+
+propMapper = ReagentPropertyMapper(db, cursor)
+aMapper = ReagentAssociationMapper(db, cursor)
+rMapper = ReagentTypeMapper(db, cursor)
+
+# Various maps
+reagentType_Name_ID_Map =  rMapper.mapTypeNameID()
+reagentType_ID_Name_Map = rMapper.mapTypeIDName()
+
+assoc_Type_Name_Map = aMapper.mapAssocTypeNameID()
+assoc_Name_Alias_Map = aMapper.mapAssocNameAlias()
+assoc_Name_Type_Map = aMapper.mapAssocTypeNameID()
+
+prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+prop_ID_Name_Map = propMapper.mapPropIDName()		# (prop id, prop name)
+prop_Name_Alias_Map = propMapper.mapPropNameAlias()	# (propName, propAlias)
+prop_Alias_Name_Map = propMapper.mapPropAliasName()	# (propAlias, propName)
+prop_Alias_ID_Map = propMapper.mapPropAliasID()		# (propAlias, propID) - e.g. ('insert_type', '48')
+
+prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+
+featureNameColorMap = propMapper.mapFeatureNameColor()
+
+#print `featureNameColorMap`
+
+# Get enzymes list for mapping sequence features
+enzDict = utils.join(sHandler.sitesDict, sHandler.gatewayDict)
+enzDict = utils.join(enzDict, sHandler.recombDict)	# add LoxP
+enzDict['None'] = ""					# add 'None'
+
+''' removed Jan. 26, 2010
+def loadColors():
+	
+	dbConn = DatabaseConn()
+	db = dbConn.databaseConnect()
+	
+	cursor = db.cursor()
+	hostname = dbConn.getHostname()
+
+	cursor.execute("SELECT propertyName FROM ReagentPropType_tbl WHERE status='ACTIVE'")
+	props = cursor.fetchall()
+	
+	features = Vector.getSequenceFeatures() + Vector.getSingleFeatures()
+	#print `features`
+	allColors = colors.getAllNamedColors()
+	#print `allColors`
+	i = 0
+	fColors = allColors.values()
+	
+	for prop in props:
+		propName = prop[0]
+		
+		if propName in features:
+			fColor = fColors.pop(i)
+			color = `fColor.rgb()`
+			#print `color`
+			#print "UPDATE ReagentPropType_tbl SET propertyColor=" + `color` + " WHERE propertyName=" + `propName` + " AND status='ACTIVE'"
+			cursor.execute("UPDATE ReagentPropType_tbl SET propertyColor=" + `color` + " WHERE propertyName=" + `propName` + " AND status='ACTIVE'")
+			i += 1
+'''
+
+def drawMap():
+	
+	dbConn = DatabaseConn()
+	db = dbConn.databaseConnect()
+	
+	cursor = db.cursor()
+	hostname = dbConn.getHostname()
+	root_path = dbConn.getRootDir()
+	
+	form = cgi.FieldStorage(keep_blank_values="True")
+	
+	#print "Content-type:text/html"
+	#print
+	#print `form`
+	
+	if form.has_key("rID"):
+		rID = form.getvalue("rID")
+	else:
+		#rID = 148913	# V4550
+		rID = 29125
+		#rID = 72 
+		#rID = 309
+		#rID = 1901	# small feature labels @ start of seq. overlap
+		#rID = 36415
+		#print rID
+
+	reagentID = rHandler.convertDatabaseToReagentID(rID)
+	
+	#print "Content-type:text/html"
+	#print
+	#print reagentID
+	
+	namePropID = pHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["name"], prop_Category_Name_ID_Map["General Properties"])
+		
+	rName = rHandler.findSimplePropertyValue(rID, namePropID)
+	#rName = rHandler.findSimplePropertyValue(rID, prop_Name_ID_Map["name"])
+	rTypeID = rHandler.findReagentTypeID(rID)
+	
+	try:
+		os.remove(root_path + "Reagent/vector_maps/" + reagentID + "_map.pdf")
+	except OSError:
+		pass
+	
+	#print root_path
+	
+	c = Canvas(root_path + "Reagent/vector_maps/" + reagentID + "_map.pdf")
+	
+	c.setPageSize((1000,1000))
+	c.setStrokeColorRGB(0,0,0)
+	c.saveState()
+	
+	# Draw circle
+	origin = 0
+	origin_x = 500
+	origin_y = 470
+	radius = 200
+
+	c.circle(origin_x, origin_y, radius)
+	c.restoreState()
+	
+	# Divide circle into 100-unit sectors
+	rSeqID = rHandler.findDNASequenceKey(rID)
+	rSeq = sHandler.findSequenceByID(rSeqID)
+	seqLen = len(rSeq)
+	
+	#print "Content-type:text/html"
+	#print
+	#print `rID`
+	
+	unit_angle_measure = float(360) / float(seqLen)
+	#print unit_angle_measure
+	
+	# Mark 1 on the circle - KEEP, Karen said!
+	c.setLineWidth(1)
+	c.setStrokeColor(black)
+	c.setFillColor(black)
+	c.saveState()
+	
+	path = c.beginPath()
+	path.moveTo(origin_x, origin_y+radius+7)
+	path.lineTo(origin_x-5, origin_y+radius+14)
+	path.lineTo(origin_x+5, origin_y+radius+14)
+	path.lineTo(origin_x, origin_y+radius+7)
+	c.drawPath(path, True, True)
+	
+	# label 1
+	t = c.beginText()
+	t.setStrokeColor(black)
+	t.setFillColor(black)
+	t.setFont("Helvetica-Bold", 16)
+	t.setTextOrigin(origin_x-5, origin_y+radius+19)
+	t.textOut("1")
+	c.drawText(t)
+	
+	c.restoreState()
+
+	# Calculate feature segment sizes
+	sequenceFeatures = rHandler.findReagentSequenceFeatures(rID)
+	#print `sequenceFeatures`
+	
+	# Draw legend
+	ox_legend = 800
+	oy_legend = 985
+	
+	prev_legend = oy_legend
+	
+	# draw frame
+	c.setStrokeColor(darkgray)
+	#c.setStrokeColor(white)
+	#c.setFillColor(lightgrey)
+	c.setFillColor(white)
+	c.saveState()
+	
+	# Output the rest of the features in alphabetical order - Moved here Jan. 26/10
+	#featureNames = featureNameColorMap.keys()
+	
+	#print `featureNameColorMap.keys()`
+	#print len(featureNameColorMap.keys())
+	
+	#fnames = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, prop_Category_Name_ID_Map["DNA Sequence Features"])
+	#fnames.remove('expression system')
+	#fnames.remove('tag position')
+	
+	#print `fnames`
+	#print len(fnames)
+	
+	featureNames = rtPropHandler.findReagentTypeAttributeNamesByCategory(rTypeID, prop_Category_Name_ID_Map["DNA Sequence Features"])
+	featureNames.sort()
+	
+	#print `featureNames`
+	#print prev_legend-240
+	#print prev_legend-15-len(featureNames)*15
+	
+	#c.rect(ox_legend-25, prev_legend-240, 215, 235, 1, 1)
+	#c.rect(ox_legend-25, prev_legend-15-len(featureNames)*15, 215, 10+len(featureNames)*15, 1, 1)	# good for list of all db features
+	
+	if len(featureNames) > 15:
+		origin_spacer = -19
+		coeff = 12
+	else:
+		origin_spacer = 65
+		coeff = 15
+	
+	#origin_legend = prev_legend+65-len(featureNames)*15
+	origin_legend = prev_legend+origin_spacer-len(featureNames)*coeff
+	
+	x = (990 - origin_legend) / len(featureNames)
+	#print x
+	
+	if x < 12:
+		x = 12
+		
+	legend_height = len(featureNames)*x + 15
+	#print legend_height
+	
+	c.rect(ox_legend-25, origin_legend-17, 215, legend_height, 1, 1)	# good for specific rtype attributes
+	
+	c.restoreState()
+	
+	# Order: 5' site, 3' site, 5' linker, 3' linker, then the rest
+	sites_color = featureNameColorMap["5' cloning site"]		# same for 3' site
+	
+	# 5' site
+	c.setStrokeColor(sites_color)
+	c.setFillColor(sites_color)
+	c.saveState()
+	c.rect(ox_legend-15, prev_legend-20, 25,8, 1, 1)
+	c.restoreState
+	
+	t = c.beginText()
+	#t.setStrokeColor(black)
+	t.setStrokeColor(sites_color)
+	#t.setFillColor(black)
+	t.setFillColor(sites_color)
+	t.setFont("Helvetica-Bold", 10)
+	t.setTextOrigin(ox_legend+12, prev_legend-20)
+	t.textOut(" - " + "5' CLONING SITE")
+	c.drawText(t)
+	c.restoreState
+	
+	prev_legend = prev_legend-15
+	
+	# 3' site
+	c.setStrokeColor(sites_color)
+	c.setFillColor(sites_color)
+	c.saveState()
+	c.rect(ox_legend-15, prev_legend-20, 25,8, 1, 1)
+	c.restoreState
+	
+	t = c.beginText()
+	#t.setStrokeColor(black)
+	#t.setFillColor(black)
+
+	t.setStrokeColor(sites_color)
+	t.setFillColor(sites_color)
+
+	t.setFont("Helvetica-Bold", 10)
+	t.setTextOrigin(ox_legend+12, prev_legend-20)
+	t.textOut(" - " + "3' CLONING SITE")
+	c.drawText(t)
+	c.restoreState
+
+	prev_legend = prev_legend-15
+	
+	# Show legend for linkers
+	linkers_color = featureNameColorMap["5' linker"]
+	
+	# 5' linker
+	c.setStrokeColor(linkers_color)
+	c.setFillColor(linkers_color)
+	c.saveState()
+	c.rect(ox_legend-15, prev_legend-20, 25,8, 1, 1)
+	c.restoreState
+	
+	t = c.beginText()
+	#t.setStrokeColor(black)
+	#t.setFillColor(black)
+	
+	t.setStrokeColor(linkers_color)
+	t.setFillColor(linkers_color)
+	
+	t.setFont("Helvetica-Bold", 10)
+	t.setTextOrigin(ox_legend+12, prev_legend-20)
+	t.textOut(" - " + "5' LINKER")
+	c.drawText(t)
+	c.restoreState
+
+	prev_legend = prev_legend-15
+	
+	# 3' linker
+	c.setStrokeColor(linkers_color)
+	c.setFillColor(linkers_color)
+	c.saveState()
+	c.rect(ox_legend-15, prev_legend-20, 25,8, 1, 1)
+	c.restoreState
+	
+	t = c.beginText()
+	#t.setStrokeColor(black)
+	#t.setFillColor(black)
+
+	t.setStrokeColor(linkers_color)
+	t.setFillColor(linkers_color)
+
+	t.setFont("Helvetica-Bold", 10)
+	t.setTextOrigin(ox_legend+12, prev_legend-20)
+	t.textOut(" - " + "3' LINKER")
+	c.drawText(t)
+	c.restoreState
+
+	prev_legend = prev_legend-15
+	
+	## Output the rest of the features in alphabetical order
+	#featureNames = featureNameColorMap.keys()
+	#featureNames.sort()
+	
+	#print `featureNames`
+	
+	for featureName in featureNames:
+		if featureNameColorMap.has_key(featureName):
+			color = featureNameColorMap[featureName]
+		#else:
+			#continue
+			
+			if featureName != "5' cloning site" and featureName != "3' cloning site" and featureName != "5' linker" and featureName != "3' linker" and color != None:
+				#print featureName
+				c.setStrokeColor(color)
+				c.setFillColor(color)
+				c.saveState()
+				c.rect(ox_legend-15, prev_legend-20, 25,8, 1, 1)
+				c.restoreState
+				
+				t = c.beginText()
+				
+				#t.setStrokeColor(black)
+				#t.setFillColor(black)
+				
+				t.setStrokeColor(color)
+				t.setFillColor(color)
+
+				t.setFont("Helvetica-Bold", 10)
+				t.setTextOrigin(ox_legend+12, prev_legend-20)
+				t.textOut(" - " + featureName.upper())
+				c.drawText(t)
+				
+				c.restoreState
+				
+				prev_legend = prev_legend-15
+	#print prev_legend
+	
+	# Print reagent ID and size at the centre of the circle and print name at the top of the page
+	c.setFont("Helvetica-Bold", 32)
+	c.setFillColor(black)
+	c.saveState()
+	
+	c.drawCentredString(origin_x, origin_y+35, reagentID)
+	c.drawCentredString(origin_x, origin_y+10, "nt 1 - " + `seqLen`)
+	
+	if rName:
+		c.setFillColor(blue)
+		c.drawCentredString(origin_x, 935, rName)
+	
+	c.restoreState()
+	
+	# SORT features by size, so that short features are not hidden behind the long ones
+	fSizes = []
+	sortedFeatures = []
+	
+	for feature in sequenceFeatures:
+		fSize = int(feature.getFeatureSize())
+		
+		if fSize > 0:
+			fSizes.append(fSize)
+	
+	fSizes.sort(reverse=True)
+	#print `fSizes`
+	
+	for fs in fSizes:
+		for feature in sequenceFeatures:
+			fSize = feature.getFeatureSize()
+
+			# added existence check July 17/08 - different features may have same sizes so end up with duplicate features in list (e.g. cloning sizes appeared twice on the map)
+			if fs == fSize and feature not in sortedFeatures:
+				sortedFeatures.append(feature)
+	
+	#print `sortedFeatures`
+	
+	ox_labels = 40
+	oy_labels = 910
+	prev_legend = oy_labels
+
+	t = c.beginText()
+	t.setStrokeColor(black)
+	t.setFillColor(black)
+	t.setFont("Helvetica-Bold", 10)
+	t.setTextOrigin(ox_labels, prev_legend-15)
+	t.textOut("Features shorter than 150 nt:")
+	c.drawText(t)
+	c.restoreState
+
+	prev_legend = prev_legend-18
+
+	#for feature in sequenceFeatures:
+	for feature in sortedFeatures:
+		fType = feature.getFeatureType()
+		fValue = feature.getFeatureName()
+		fSize = feature.getFeatureSize()
+		
+		#print fType
+		#print fValue
+		#print fSize
+		
+		fColor = featureNameColorMap[fType]
+		
+		if fType == 'cdna insert':
+			fValue = "cDNA Insert"
+			
+		elif fType == 'promoter':
+			fValue = fValue + " " + fType
+		
+		fStart = feature.getFeatureStartPos()
+		fEnd = feature.getFeatureEndPos()
+		fDir = feature.getFeatureDirection()
+		
+		if fSize > 0:
+			f_start = fStart * unit_angle_measure
+		
+			#print "Start " + `fStart`
+			#print "End " + `fEnd`
+		
+			startAngle = 90 - f_start
+			#print "Start angle " + `startAngle`
+			
+			f_end = fEnd * unit_angle_measure
+			endAngle = 90 - f_end
+			#print "End angle " + `endAngle`
+			
+			extAngle = -1*(f_end - f_start)
+			#print "Ext angle " + `extAngle`
+
+			x1 = origin_x - radius
+			y1 = origin_y - radius
+			
+			x2 = origin_x + radius
+			y2 = origin_y + radius
+			
+			p = c.beginPath()
+			#t = c.beginText()
+			
+			c.setLineWidth(10)
+			c.setLineJoin(1)
+			
+			fColor = featureNameColorMap[fType]
+			c.setStrokeColor(fColor)
+			c.saveState()
+			
+			p.arc(x1, y1, x2, y2, startAngle, extAngle)
+			c.drawPath(p)
+			c.restoreState()
+			
+			## jan. 27/10: this makes a contour for each arc
+			#p = c.beginPath()
+			#c.setLineWidth(1)
+			
+			##fColor = featureNameColorMap[fType]
+			#c.setStrokeColor(black)
+			#c.setFillColor(fColor)
+			#c.saveState()
+			
+			#p.arc(x1+5, y1+5, x2-5, y2-5, startAngle, extAngle)
+			#c.drawPath(p)
+			##c.restoreState()
+			
+			##c.setLineWidth(1)
+			
+			##fColor = featureNameColorMap[fType]
+			##c.setStrokeColor(black)
+			##c.setFillColor(fColor)
+			##c.saveState()
+			
+			#p.arc(x1-5, y1-5, x2+5, y2+5, startAngle, extAngle)
+			#c.drawPath(p)
+			#c.restoreState()	# jan. 27/10 modification ends here
+			
+			
+			# common to all
+			startAngle_rad = (startAngle * math.pi) / 180.0
+			endAngle_rad = (endAngle * math.pi) / 180.0
+			
+			#c.setStrokeColor(black)
+			#c.setFillColor(black)
+			
+			c.setStrokeColor(fColor)
+			c.setFillColor(fColor)
+			
+			c.setFont("Helvetica-Bold", 9)
+			c.saveState()
+			
+			arc_x_start = origin_x + (radius+5)*math.cos(startAngle_rad)
+			arc_y_start = origin_y + (radius+5)*math.sin(startAngle_rad)
+			
+			arc_x_end = origin_x+(radius+5)*math.cos(endAngle_rad)
+			arc_y_end = origin_y+(radius+5)*math.sin(endAngle_rad)
+			
+			# draw label
+			c.setStrokeColorRGB(0,0,1)
+			c.setFillColorRGB(0,0,1)
+			c.setFont("Helvetica-Bold", 12)
+			c.saveState()
+			
+			# draw line
+			delta = 45
+			
+			# Rotate labels only for SMALL features (they can be crammed together)
+			#if fSize > 100:
+				#delta = 45
+			#else:
+				#delta = 32
+			
+			if fStart < seqLen/2:
+				if arc_y_start > origin_y:
+					
+					#c.setStrokeColor(black)
+					#c.setFillColor(black)
+					
+					c.setStrokeColor(fColor)
+					c.setFillColor(fColor)
+					
+					c.setLineWidth(1)
+					c.saveState()
+					
+					#if fSize <= 100:
+						#c.line(arc_x_start, arc_y_start, arc_x_start+50*math.fabs(math.sin(delta)), arc_y_start+55*math.fabs(math.cos(delta)))
+					#else:
+
+					# July 17/08: Show labels for long features only
+					if fSize > 150:
+						c.line(arc_x_start, arc_y_start, arc_x_start+50*math.fabs(math.sin(delta)), arc_y_start+55*math.fabs(math.cos(delta)))
+				
+					c.restoreState()
+					
+					# July 17/08: Show labels for long features only
+					if fSize > 150:
+					
+						# draw label
+						
+						#c.setStrokeColorRGB(0,0,1)
+						#c.setFillColorRGB(0,0,1)
+						
+						c.setStrokeColor(fColor)
+						c.setFillColor(fColor)
+
+						c.setFont("Helvetica-Bold", 11)
+						c.saveState()
+
+						c.drawString(arc_x_start+50*math.fabs(math.sin(delta)), arc_y_start+55*math.fabs(math.cos(delta)), fValue + " (" + `fStart` + "-" + `fEnd` + ")")
+	
+					else:
+						c.setStrokeColor(fColor)
+						c.setFillColor(fColor)
+						c.saveState()
+						c.rect(ox_labels+5, prev_legend-15, 15,6, 1, 1)
+						c.restoreState
+
+						t = c.beginText()
+						#t.setStrokeColor(black)
+						#t.setFillColor(black)
+					
+						t.setStrokeColor(fColor)
+						t.setFillColor(fColor)
+					
+						t.setFont("Helvetica-Bold", 10)
+						t.setTextOrigin(ox_labels+25, prev_legend-15)
+						t.textOut(fValue + " (" + `fStart` + "-" + `fEnd` + ")")
+						c.drawText(t)
+						c.restoreState
+						prev_legend = prev_legend-15
+					
+					c.restoreState()
+					
+				else:
+					#c.setStrokeColor(black)
+					#c.setFillColor(black)
+					
+					c.setStrokeColor(fColor)
+					c.setFillColor(fColor)
+					
+					c.setLineWidth(1)
+					c.saveState()
+					
+					if fSize > 150:
+						c.line(arc_x_start, arc_y_start, arc_x_start+50*math.fabs(math.sin(delta)), arc_y_start-55*math.fabs(math.cos(delta)))
+						
+					c.restoreState()
+					
+					# draw label
+					if fSize > 150:
+						
+						#c.setStrokeColorRGB(0,0,1)
+						#c.setFillColorRGB(0,0,1)
+						
+						c.setStrokeColor(fColor)
+						c.setFillColor(fColor)
+
+						c.setFont("Helvetica-Bold", 11)
+						c.saveState()
+						
+						c.drawString(arc_x_start+50*math.fabs(math.sin(delta)), arc_y_start-55*math.fabs(math.cos(delta)), fValue + " (" + `fStart` + "-" + `fEnd` + ")")
+					else:
+						c.setStrokeColor(fColor)
+						c.setFillColor(fColor)
+						c.saveState()
+						c.rect(ox_labels+5, prev_legend-15, 15,6, 1, 1)
+						c.restoreState
+
+						t = c.beginText()
+						#t.setStrokeColor(black)
+						#t.setFillColor(black)
+						
+						t.setStrokeColor(fColor)
+						t.setFillColor(fColor)
+						
+						t.setFont("Helvetica-Bold", 10)
+						t.setTextOrigin(ox_labels+25, prev_legend-15)
+						t.textOut(fValue + " (" + `fStart` + "-" + `fEnd` + ")")
+						c.drawText(t)
+						c.restoreState
+						prev_legend = prev_legend-15
+						
+					c.restoreState()
+			else:
+				if arc_y_start > origin_y:
+					
+					#c.setStrokeColor(black)
+					#c.setFillColor(black)
+
+					c.setStrokeColor(fColor)
+					c.setFillColor(fColor)
+					
+					c.setLineWidth(1)
+					c.saveState()
+					
+					if fSize > 150:
+						c.line(arc_x_start, arc_y_start, arc_x_start-50*math.fabs(math.sin(delta)), arc_y_start+55*math.fabs(math.cos(delta)))
+						
+						#c.line(arc_x_start, arc_y_start, arc_x_start+10*math.fabs(math.sin(delta)), arc_y_start-10*math.fabs(math.cos(delta)))
+				
+					c.restoreState()
+					
+					# draw label
+					if fSize > 150:
+						#c.setStrokeColorRGB(0,0,1)
+						#c.setFillColorRGB(0,0,1)
+						
+						c.setStrokeColor(fColor)
+						c.setFillColor(fColor)
+
+						c.setFont("Helvetica-Bold", 11)
+						c.saveState()
+						
+						c.drawRightString(arc_x_start-50*math.fabs(math.sin(delta)), arc_y_start+55*math.fabs(math.cos(delta)), fValue + " (" + `fStart` + "-" + `fEnd` + ")")
+					else:
+						c.setStrokeColor(fColor)
+						c.setFillColor(fColor)
+						c.saveState()
+						c.rect(ox_labels+5, prev_legend-15, 15,6, 1, 1)
+						c.restoreState
+
+						t = c.beginText()
+						#t.setStrokeColor(black)
+						#t.setFillColor(black)
+						
+						t.setStrokeColor(fColor)
+						t.setFillColor(fColor)
+						
+						t.setFont("Helvetica-Bold", 10)
+						t.setTextOrigin(ox_labels+25, prev_legend-15)
+						t.textOut(fValue + " (" + `fStart` + "-" + `fEnd` + ")")
+						c.drawText(t)
+						c.restoreState
+						prev_legend = prev_legend-15
+							
+					c.restoreState()
+					
+				else:
+					#c.setStrokeColor(black)
+					#c.setFillColor(black)
+					
+					c.setStrokeColor(fColor)
+					c.setFillColor(fColor)
+					
+					c.setLineWidth(1)
+					c.saveState()
+					
+					if fSize > 150:
+						c.line(arc_x_start, arc_y_start, arc_x_start-50*math.fabs(math.sin(delta)), arc_y_start-55*math.fabs(math.cos(delta)))
+				
+					c.restoreState()
+					
+					# draw label
+					if fSize > 150:
+						
+						#c.setStrokeColorRGB(0,0,1)
+						#c.setFillColorRGB(0,0,1)
+						
+						c.setStrokeColor(fColor)
+						c.setFillColor(fColor)
+						
+						c.setFont("Helvetica-Bold", 11)
+						c.saveState()
+						
+						c.drawRightString(arc_x_start-50*math.fabs(math.sin(delta)), arc_y_start-55*math.fabs(math.cos(delta)), fValue + " (" + `fStart` + "-" + `fEnd` + ")")
+						
+						c.restoreState()
+					else:
+						c.setStrokeColor(fColor)
+						c.setFillColor(fColor)
+						c.saveState()
+						c.rect(ox_labels+5, prev_legend-15, 15,6, 1, 1)
+						c.restoreState
+
+						t = c.beginText()
+						#t.setStrokeColor(black)
+						#t.setFillColor(black)
+						
+						t.setStrokeColor(fColor)
+						t.setFillColor(fColor)
+						
+						t.setFont("Helvetica-Bold", 10)
+						t.setTextOrigin(ox_labels+25, prev_legend-15)
+						t.textOut(fValue + " (" + `fStart` + "-" + `fEnd` + ")")
+						c.drawText(t)
+						c.restoreState
+						prev_legend = prev_legend-15
+			
+	c.showPage()
+	c.save()
+	
+	# Feb. 2/09: Change permissions
+	#os.chmod("/tmp/vector_maps/" + reagentID + "_map.pdf", stat.S_IMODE(stat.S_IRWXU | stat.S_IRWXO | stat.S_IRWXG))
+	
+def drawMap2():
+	dbConn = DatabaseConn()
+	db = dbConn.databaseConnect()
+	
+	cursor = db.cursor()
+	hostname = dbConn.getHostname()
+
+	form = cgi.FieldStorage(keep_blank_values="True")
+	
+	#print "Content-type:text/html"
+	#print
+	#print `form`
+	
+	if form.has_key("rID"):
+		rID = form.getvalue("rID")
+	else:
+		#rID = 791
+		#print rID
+		rID = 154659 
+
+	reagentID = rHandler.convertDatabaseToReagentID(rID)
+	
+	d = Drawing(1000,1000)
+	
+	origin = 0
+	origin_x = 500
+	origin_y = 500
+	radius = 350
+	
+	c = Circle(origin_x, origin_y, radius)
+	
+	c.strokeColor = blue
+	c.fillColor = white
+	
+	d.add(c)
+	
+	c.line(origin_x, origin_y+radius-7, origin_x-7, origin_y+radius)
+	c.line(origin_x-7, origin_y+radius, origin_x, origin_y+radius+7)
+	c.line(origin_x, origin_y+radius+7, origin_x+7, origin_y+radius)
+	c.line(origin_x+7, origin_y+radius, origin_x, origin_y+radius-7)
+	
+	
+	p = c.beginPath()
+	c.setFillColor(black)
+	c.saveState()
+	p.moveTo(origin_x, origin_y+radius-7)
+	p.lineTo(origin_x-7, origin_y+radius)
+	p.lineTo(origin_x, origin_y+radius+7)
+	p.lineTo(origin_x+7, origin_y+radius)
+	p.close()
+	c.drawPath(p)
+	c.restoreState()
+	
+	# Divide circle into 100-unit sectors
+	rSeqID = rHandler.findDNASequenceKey(rID)
+	rSeq = sHandler.findSequenceByID(rSeqID)
+	seqLen = len(rSeq)
+	#print seqLen
+	
+	unit_angle_measure = float(360) / float(seqLen)
+	
+	# Calculate feature segment sizes
+	sequenceFeatures = rHandler.findReagentSequenceFeatures(rID)
+	
+	for feature in sequenceFeatures:
+		fType = feature.getFeatureType()
+		fValue = feature.getFeatureName()
+		
+		fStart = feature.getFeatureStartPos()
+		fEnd = feature.getFeatureEndPos()
+		fDir = feature.getFeatureDirection()
+		
+		f_start = fStart * unit_angle_measure
+		f_end = fEnd * unit_angle_measure
+		
+		if fStart > 0 and fEnd > 0:
+			print "Start " + `fStart`
+			print "End " + `fEnd`
+		
+			startAngle = 90 - f_start
+			extAngle = -1*(f_end - f_start)
+			
+			print "Angle " + `extAngle`
+			
+			x1 = origin_x - radius
+			y1 = origin_y - radius
+			
+			x2 = origin_x + radius
+			y2 = origin_y + radius
+			
+			p = ArcPath()
+			#p.dumpProperties()
+			
+			p.strokeWidth=15
+			p.strokeColor = black
+			p.fillColor = red
+			
+			#p.addArc(x1, y1, x2, y2, startAngle, extAngle)		# NO
+			
+			d.add(p)
+			
+			d.add(String(origin_x+fStart, origin_y+fStart, fValue))
+	
+	renderPDF.drawToFile(d, "V7066_map.png")
+	
+	
+drawMap()
+#drawMap2()
diff --git a/OpenFreezer/cgi/vector_oligos.py b/OpenFreezer/cgi/vector_oligos.py
new file mode 100755
index 0000000..7460d10
--- /dev/null
+++ b/OpenFreezer/cgi/vector_oligos.py
@@ -0,0 +1,336 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+
+import MySQLdb
+import sys
+import string
+
+from database_conn import DatabaseConn
+
+from mapper import ReagentPropertyMapper, ReagentAssociationMapper
+from general_handler import *
+from reagent_handler import *
+from sequence_handler import DNAHandler, ProteinHandler
+from comment_handler import CommentHandler
+#from system_set_handler import SystemSetHandler
+from sequence_handler import SequenceHandler
+from reagent import *
+
+import utils
+
+from user_handler import UserHandler
+from project_database_handler import ProjectDatabaseHandler
+from session import Session
+from exception import *
+
+dbConn = DatabaseConn()
+db = dbConn.databaseConnect()
+
+cursor = db.cursor()
+hostname = dbConn.getHostname()
+root_path = dbConn.getRootDir()
+
+dnaHandler = DNAHandler(db, cursor)
+protHandler = ProteinHandler(db, cursor)
+rHandler = ReagentHandler(db, cursor)
+oHandler = OligoHandler(db, cursor)
+propHandler = ReagentPropertyHandler(db, cursor)
+packetHandler = ProjectDatabaseHandler(db, cursor)
+
+propMapper = ReagentPropertyMapper(db, cursor)
+prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+
+prop_Category_Name_ID_Map = propMapper.mapPropCategoryNameID()
+
+
+# currUser is an INT user ID
+def getCurrentUserProjects(currUser):
+	
+	#print "Content-type:text/html"
+	#print
+	
+	# get projects user has AT LEAST Read access to (i.e. if he is explicitly declared a Writer on a project but not declared a Reader, that's allowed)
+	currReadProj = packetHandler.findMemberProjects(currUser, 'Reader')
+	currWriteProj = packetHandler.findMemberProjects(currUser, 'Writer')
+	publicProj = packetHandler.findAllProjects(isPrivate="FALSE")
+	
+	# list of Packet OBJECTS
+	currUserWriteProjects = utils.unique(currReadProj + currWriteProj + publicProj)
+	
+	if currUser == 1:
+		privateProjects = packetHandler.findAllProjects("TRUE")
+		currUserWriteProjects = utils.unique(privateProjects + publicProj)
+		
+	uPackets = []
+	
+	for p in currUserWriteProjects:
+		uPackets.append(p.getNumber())
+
+	return uPackets
+
+
+def getOligos(rID, seq, vectorID, userID):
+	
+	content = "\nSequencing Primers for " + vectorID + "\n\nVector length: " + `len(seq.strip())` + " nt\n"
+	
+	protocolPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["protocol"], prop_Category_Name_ID_Map["Classifiers"])
+	seqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+	
+	cdnaPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["cdna insert"], prop_Category_Name_ID_Map["DNA Sequence Features"])
+	
+	projectPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["packet id"], prop_Category_Name_ID_Map["General Properties"])
+	
+	namePropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["name"], prop_Category_Name_ID_Map["General Properties"])
+	
+	statusPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["status"], prop_Category_Name_ID_Map["General Properties"])
+	
+	cdnaStart = rHandler.findReagentFeatureStart(rID, cdnaPropID)
+	cdnaEnd = rHandler.findReagentFeatureEnd(rID, cdnaPropID)
+	
+	if cdnaStart > 0:
+		content += "\ncDNA: " + `cdnaStart` + "-" + `cdnaEnd` + "\n"
+	
+	# find all Oligos whose protocol is 'sequencing'
+	cursor.execute("SELECT r.reagentID, r.groupID, s.sequence FROM Sequences_tbl s, ReagentPropList_tbl p1, ReagentPropList_tbl p2, Reagents_tbl r WHERE p1.propertyID=" + `protocolPropID` + " AND p1.propertyValue='sequencing' AND p1.reagentID=r.reagentID AND r.reagentTypeID='3' AND p1.reagentID=p2.reagentID AND p2.propertyID=" + `seqPropID` + " AND p2.propertyValue=s.seqID AND p1.status='ACTIVE' AND p2.status='ACTIVE' AND r.status='ACTIVE' AND s.status='ACTIVE'")
+	results = cursor.fetchall()
+	
+	seq = utils.squeeze(seq).lower()
+	
+	uPackets = getCurrentUserProjects(userID)
+	
+	#print "Content-type:text/html"
+	#print
+	#print reagentID
+	uPackets.sort()
+	#print `uPackets`
+	
+	features = rHandler.findAllReagentFeatures(Vector(rID), rID)
+	overlapping_features = []
+	
+	tmp_features = {}	# linear list of oligos, regular array
+	
+	for result in results:
+		overlapping_features = []
+		
+		if result:
+			
+			#print "Content-type:text/html"
+			#print
+			#print len(result)
+			
+			oligoID = int(result[0])
+			groupID = int(result[1])
+			
+			oligo_lims_id = "O" + `groupID`
+			#print oligo_lims_id
+			
+			# April 26, 2010, Karen's request: Ignore Oligos whose status is 'Failed' or 'Do Not Use'
+			oligoStatus = rHandler.findSimplePropertyValue(oligoID, statusPropID)
+
+			if oligoStatus:
+				#print oligoStatus
+				if oligoStatus.lower() == 'failed' or oligoStatus.lower() == 'do not use':
+					continue
+			
+			oligoPacket = int(rHandler.findSimplePropertyValue(oligoID, projectPropID))
+			#print oligoPacket
+			
+			if oligoPacket:
+				if oligoPacket not in uPackets:
+					#print oligoPacket
+					continue
+			
+			oligoName = rHandler.findSimplePropertyValue(oligoID, namePropID)
+			
+			#if oligoName:
+				#oligoNamesDict[oligoID] = oligoName
+			#else:
+				#oligoNamesDict[oligoID] = ""
+			
+			#print `features`
+			
+			if len(result) == 3:
+				oligoSeq = utils.squeeze(result[2].strip()).lower()
+				#print oligoSeq
+				
+				tm = dnaHandler.calculateTm(oligoSeq)
+				
+				if seq.find(oligoSeq) >= 0:
+					fStart = seq.find(oligoSeq) + 1
+					fEnd = fStart + len(oligoSeq) - 1
+					
+					direction = "forward"
+					
+					for f_tmp in features:
+						tmp_f_Start = f_tmp.getFeatureStartPos()
+						tmp_f_End = f_tmp.getFeatureEndPos()
+						
+						# 4 cases:
+						# Feature contained within ORF (tmp_fStart >= fStart and tmp_fEnd <= fEnd)
+						# Feature starts inside ORF (tmp_fStart >= fStart and tmp_fStart <= fEnd)
+						# Feature ends inside ORF (tmp_fEnd >= fStart and tmp_fEnd <= fEnd)
+						# ORF contained within feature (tmp_fStart <= fStart and tmp_fEnd >= fEnd)
+						if (tmp_f_Start >= fStart and tmp_f_End <= fEnd) or (tmp_f_End >= fStart and tmp_f_End <= fEnd) or (tmp_f_Start >= fStart and tmp_f_Start <= fEnd) or (tmp_f_Start <= fStart and tmp_f_End >= fEnd):
+							overlapping_features.append(f_tmp)
+					
+				else:
+					revSeq = dnaHandler.reverse_complement(oligoSeq)
+					direction = "reverse"
+					
+					if seq.find(revSeq) < 0:
+						continue
+					
+					fStart = seq.find(revSeq) + 1
+					fEnd = fStart + len(revSeq)
+					
+					# Note: start pos > end pos, as we're talking about reverse Oligo sequence
+					revStart = fEnd - 1
+					revEnd = fStart
+				
+					for f_tmp in features:
+						tmp_f_Start = f_tmp.getFeatureStartPos()
+						tmp_f_End = f_tmp.getFeatureEndPos()
+						
+						# 4 cases: (remember, revStart > revEnd, e.g. O1100 for V2559 - start 2583, end 2559)
+						# Feature contained within ORF (tmp_f_Start <= revStart and tmp_f_End >= revEnd)
+						# Feature starts inside ORF (tmp_f_Start >= revStart and tmp_f_Start <= revEnd)
+						# Feature ends inside ORF (tmp_f_End >= revStart and tmp_f_End <= revEnd)
+						# ORF contained within feature (tmp_f_Start >= revStart and tmp_f_End <= revEnd)
+						if (tmp_f_Start >= revStart and tmp_f_End <= revEnd) or (tmp_f_End >= revStart and tmp_f_End <= revEnd) or (tmp_f_Start >= revStart and tmp_f_Start <= revEnd) or (tmp_f_Start <= revStart and tmp_f_End >= revEnd):
+							overlapping_features.append(f_tmp)
+					
+					fStart = revEnd
+					fEnd = revStart
+
+				oFeature = SequenceFeature(oligoName, oligo_lims_id, fStart, fEnd, direction, oligoSeq, tm)
+				tmp_features[oFeature] = overlapping_features
+	
+	tmp_oligos = {}
+	
+	for tmpFeature in tmp_features.keys():
+		
+		oligoStart = tmpFeature.getFeatureStartPos()
+		
+		if tmp_oligos.has_key(oligoStart):
+			tmp_o_list = tmp_oligos[oligoStart]
+		else:
+			tmp_o_list = []
+			tmp_oligos[oligoStart] = tmpFeature
+		
+		tmp_o_list.append(tmpFeature)
+		tmp_oligos[oligoStart] = tmp_o_list
+		
+	for oligoStart in sorted(tmp_oligos.keys()):
+		oFeatures = tmp_oligos[oligoStart]
+		
+		for tmpFeature in oFeatures:
+			
+			overlapping_features = tmp_features[tmpFeature]
+			
+			oligoName = tmpFeature.getFeatureType()
+			oligo_lims_id = tmpFeature.getFeatureName()
+			oligoSeq = tmpFeature.getFeatureDescrType()
+			tm = tmpFeature.getFeatureDescrName()
+			
+			fStart = tmpFeature.getFeatureStartPos()
+			fEnd = tmpFeature.getFeatureEndPos()
+			
+			direction = tmpFeature.getFeatureDirection()
+			
+			if oligoName:
+				content += '\n--------------------------------------------------\n' + oligo_lims_id + " " + oligoName + ": " + oligoSeq + ", " + direction + "\n\n"
+			
+			else:
+				content += '\n--------------------------------------------------\n' + oligo_lims_id + ": " + oligoSeq + ", " + direction + "\n\n"
+				
+			content += "Start position = " + `fStart` + "\n"
+			content += "Stop position = " + `fEnd` + "\n"
+			
+			content += "\nTm: " + tm + "ºC\n"
+	
+			if len(overlapping_features) > 0:
+				content += "\nOverlapping features:\n"
+			
+				for tmp_f in overlapping_features:
+					
+					tmp_fStart = tmp_f.getFeatureStartPos()
+					tmp_fEnd = tmp_f.getFeatureEndPos()
+			
+					if tmp_f.getFeatureType().lower() == 'cdna insert':
+						content += "cDNA"
+					#elif tmp_f.getFeatureType().lower() == 'intron':
+						#content += tmp_f.getFeatureName().title() + " intron"
+					elif tmp_f.getFeatureType().lower() == 'promoter':
+						content += tmp_f.getFeatureName().title() + " promoter"
+					elif tmp_f.getFeatureType().lower() == "5' cloning site" or tmp_f.getFeatureType().lower() == "3' cloning site":
+						content += tmp_f.getFeatureName().title() + " cloning site"
+					elif tmp_f.getFeatureType().lower() == 'restriction site':
+						content += tmp_f.getFeatureName().title() + " restriction site"
+					elif tmp_f.getFeatureType().lower() == 'intron':
+						content += tmp_f.getFeatureName().title() + " intron"
+					elif tmp_f.getFeatureType().lower() == 'polya':
+						content += tmp_f.getFeatureName().title() + " polyA"
+					elif tmp_f.getFeatureType().lower() == 'origin':
+						content += tmp_f.getFeatureName().title() + " ori."
+					elif tmp_f.getFeatureType().lower() == 'tag type':
+						content += tmp_f.getFeatureName().title() + " tag"
+					elif tmp_f.getFeatureType().lower() == 'transcription terminator':
+						content += tmp_f.getFeatureName().title() + " tscn. ter."
+					else:
+						content += tmp_f.getFeatureName().title()
+						
+					content += ": " + `tmp_fStart` + "-" + `tmp_fEnd` + '\n'
+
+	content +="\n--------------------------------------------------\n\nNOTE: Only Oligos in OpenFreezer whose protocol is 'sequencing' and whose sequence is an exact match to the vector are reported.\n"
+	return content
+	
+	
+def main():
+	
+	#print "Content-type:text/html"
+	#print
+	
+	form = cgi.FieldStorage(keep_blank_values="True")
+	
+	# DEBUG
+	#print "Content-type: text/html"
+	#print
+	#print `form`
+	#return
+	
+	print "Content-type: application/octet-stream"
+		
+	if form.has_key("rID"):
+		rID = form.getvalue("rID")
+		seq = form.getvalue("vector_sequence")
+	else:
+		# debug
+		#rID = 115818	# V4589
+		rID = 115379	# V4539
+		
+		# update July 3/09
+		seqPropID = propHandler.findReagentPropertyInCategoryID(prop_Name_ID_Map["sequence"], prop_Category_Name_ID_Map["DNA Sequence"])
+		seqID = rHandler.findIndexPropertyValue(rID, seqPropID)
+		
+		#seqID = rHandler.findIndexPropertyValue(rID, prop_Name_ID_Map["sequence"])		# removed July 3/09
+		seq = dnaHandler.findSequenceByID(seqID)
+	
+	if form.has_key("user_id_hidden"):
+		userID = form.getvalue("user_id_hidden")
+	else:	# command-line execution
+		userID = 1	# debug
+
+	vectorID = rHandler.convertDatabaseToReagentID(rID)
+	#print vectorID
+	
+	fname = vectorID + "_oligos.doc"
+	
+	print "Content-Disposition: attachment; name=" + fname
+	
+	content = getOligos(rID, seq, vectorID, userID)
+	
+	print '\n' + content
+	
+main()
\ No newline at end of file
diff --git a/OpenFreezer/cgi/vector_sequence.py b/OpenFreezer/cgi/vector_sequence.py
new file mode 100755
index 0000000..1e556bd
--- /dev/null
+++ b/OpenFreezer/cgi/vector_sequence.py
@@ -0,0 +1,505 @@
+#!/usr/local/bin/python
+
+import cgi
+import cgitb; cgitb.enable()
+	
+import MySQLdb
+import sys
+import string
+
+from database_conn import DatabaseConn
+
+from mapper import ReagentPropertyMapper, ReagentAssociationMapper
+from general_handler import *
+from reagent_handler import ReagentHandler, InsertHandler
+from sequence_handler import DNAHandler, ProteinHandler
+from comment_handler import CommentHandler
+#from system_set_handler import SystemSetHandler
+from sequence_handler import SequenceHandler
+
+import utils
+
+from user_handler import UserHandler
+from project_database_handler import ProjectDatabaseHandler
+from session import Session
+from exception import *
+
+
+# Reconstruct and preload new vector sequence if its parents are changed during modification
+def update():
+
+	dbConn = DatabaseConn()
+	db = dbConn.databaseConnect()
+	
+	cursor = db.cursor()
+	hostname = dbConn.getHostname()
+
+	form = cgi.FieldStorage(keep_blank_values="True")
+	
+	print "Content-type:text/html"		# REMOVE AFTER DEBUGGING TO HAVE SCRIPT REDIRECT PROPERLY!!!!!!
+	print					# DITTO
+	#print `form`
+
+	# Aug 29/07
+	uHandler = UserHandler(db, cursor)
+	
+	if form.has_key("curr_username"):
+		# store the user ID for use throughout the session; add to other views in addition to create in PHP
+		currUname = form.getvalue("curr_username")
+		currUser = uHandler.getUserByDescription(currUname)
+		
+		Session.setUser(currUser)
+		
+	#else:	# debug
+		#currUname = 'Administrator'
+		#currUser = uHandler.getUserByDescription(currUname)
+		
+		#Session.setUser(currUser)
+		
+	if form.has_key("cloning_method"):
+		cloning_method = form.getvalue("cloning_method")
+	
+	#else:	# debug
+		#cloning_method = '1'
+		
+	# Handlers and mappers
+	rHandler = ReagentHandler(db, cursor)
+	#sHandler = SystemSetHandler(db, cursor)
+	pHandler = ReagentPropertyHandler(db, cursor)
+	raHandler = ReagentAssociationHandler(db, cursor)
+	aHandler = AssociationHandler(db, cursor)
+
+	dnaHandler = DNAHandler(db, cursor)
+	commHandler = CommentHandler(db, cursor)
+	protHandler = ProteinHandler(db, cursor)	
+	
+	propMapper = ReagentPropertyMapper(db, cursor)
+	assocMapper = ReagentAssociationMapper(db, cursor)
+
+	# August 29/07: Restrict creation by user and project access
+	packetHandler = ProjectDatabaseHandler(db, cursor)
+
+	########################################################
+	# Various maps
+	########################################################
+
+	prop_Alias_ID_Map = propMapper.mapPropAliasID()		# (propAlias, propID) - e.g. ('insert_type', '48') --> represents 'type of insert' property
+	prop_Name_Alias_Map = propMapper.mapPropNameAlias()	# (propName, propAlias)
+	prop_Name_ID_Map = propMapper.mapPropNameID()		# (prop name, prop id)
+
+	
+	# Restriction sites
+	fpcs_prop_id = pHandler.findPropID("5' cloning site")
+	tpcs_prop_id = pHandler.findPropID("3' cloning site")
+
+	newFivePrime = form.getvalue("fpcs")
+	newThreePrime = form.getvalue("tpcs")
+
+	gatewaySites = ['attb', 'attl', 'attp', 'attr']		# nov. 16/07
+	
+	# resulting sequence
+	newSeq = ""
+
+	# Fetch projects the user has AT LEAST Read access to (i.e. if he is explicitly declared a Writer on a project but not declared a Reader, include that project, plus all public projects)
+	currReadProj = packetHandler.findMemberProjects(currUser.getUserID(), 'Reader')
+	currWriteProj = packetHandler.findMemberProjects(currUser.getUserID(), 'Writer')
+	publicProj = packetHandler.findAllProjects(isPrivate="FALSE")
+	
+	# list of Packet OBJECTS
+	currUserWriteProjects = utils.unique(currReadProj + currWriteProj + publicProj)
+	
+	uPackets = []
+	
+	for p in currUserWriteProjects:
+		uPackets.append(p.getNumber())
+
+	# Get project IDs of parents
+	packetPropID = pHandler.findPropID("packet id")
+
+		
+	# August 29/07: Need to verify parent project access AND (Sept. 12/07) reconstruct the sequence IFF parent values are changed
+	newSeq = ""
+	
+	# Fetch projects the user has AT LEAST Read access to (i.e. if he is explicitly declared a Writer on a project but not declared a Reader, include that project, plus all public projects)
+	currReadProj = packetHandler.findMemberProjects(currUser.getUserID(), 'Reader')
+	currWriteProj = packetHandler.findMemberProjects(currUser.getUserID(), 'Writer')
+	publicProj = packetHandler.findAllProjects(isPrivate="FALSE")
+	
+	# list of Packet OBJECTS
+	currUserWriteProjects = utils.unique(currReadProj + currWriteProj + publicProj)
+	
+	uPackets = []
+	
+	for p in currUserWriteProjects:
+		uPackets.append(p.getNumber())
+	
+	# Get project IDs of parents
+	packetPropID = pHandler.findPropID("packet id")
+	
+	if form.has_key("PV"):
+		pvVal = form.getvalue("PV")
+	
+		if len(pvVal) > 0:
+			pvID = rHandler.convertReagentToDatabaseID(pvVal)
+	
+			try:
+				pvProjectID = int(rHandler.findSimplePropertyValue(pvID, packetPropID))
+				pvSeqID = rHandler.findDNASequenceKey(pvID)	# get sequence for reconstitution later
+			except TypeError:
+				#pvProjectID = 0
+				e = PVProjectAccessException("You are not authorized to use this Parent Vector, since you do not have Read access to its project.")
+				print `e.err_code()`
+		else:
+			e = UnknownPVIDException("Unknown Parent Vector value")
+			print `e.err_code()`
+			return
+			
+	# else don't do anything, maybe want to delete parents!!!
+	#else:
+		#e = MissingPVException("No Parent Vector provided")
+		#print `e.err_code()`
+	
+	
+	if pvProjectID > 0 and currUser.getCategory() != 'Admin' and pvProjectID not in uPackets:
+		e = PVProjectAccessException("Not authorized to access parent")
+		print `e.err_code()`
+		return
+	
+	if cloning_method == '1':
+		
+		# Non-recombination vector - Get the Insert
+		if form.has_key("I"):
+			insertVal = form.getvalue("I")
+			
+			if len(insertVal) > 0:
+				insertID = rHandler.convertReagentToDatabaseID(insertVal)
+				insertSeqID = rHandler.findDNASequenceKey(insertID)	# fetch Insert sequence for reconstitution later
+				
+				try:
+					insertProjectID = int(rHandler.findSimplePropertyValue(insertID, packetPropID))
+					
+				except TypeError:
+					#insertProjectID = 0
+					e = InsertProjectAccessException("You are not authorized to use this Insert, since you do not have Read access to its project.")
+					print `e.err_code()`
+			else:
+				#insertID = -1
+				#insertProjectID = 0
+				#print "Invalid Insert value"
+				e = UnknownInsertIDException("Unknown Insert value")
+				print `e.err_code()`
+				return
+				
+		#else:	# NO!!!!!!!!
+			#e = MissingInsertException("No Insert provided")
+			#print `e.err_code()`
+	
+		if insertProjectID > 0 and currUser.getCategory() != 'Admin' and insertProjectID not in uPackets:
+			e = InsertProjectAccessException("You are not authorized to use this Insert, since you do not have Read access to its project.")
+			print `e.err_code()`
+			return
+	
+		if  pvID > 0 and insertID > 0 :
+			
+			# try to reconstruct sequence and issue warning if unable
+			if pvSeqID > 0 and insertSeqID > 0:
+				
+				# fetch insert cloning sites
+				insertCloningSites = []
+	
+				fpcs_prop_id = pHandler.findPropID("5' cloning site")
+				tpcs_prop_id = pHandler.findPropID("3' cloning site")
+		
+				fp_insert_cs = rHandler.findSimplePropertyValue(insertID, fpcs_prop_id)
+				tp_insert_cs = rHandler.findSimplePropertyValue(insertID, tpcs_prop_id)
+				
+				# Determine if this is a Gateway clone from sites
+				gwSites = False;
+		
+				if fp_insert_cs and tp_insert_cs and fp_insert_cs.lower() == 'attl' and tp_insert_cs.lower() == 'attl':
+					gwSites = True
+				elif not fp_insert_cs or not tp_insert_cs:
+					gwSites = True
+				# nov. 16/07: added this for check
+				elif fp_insert_cs.lower() in gatewaySites or tp_insert_cs.lower() in gatewaySites:
+					gwSites = True
+				else:
+					gwSites = False;
+		
+				if gwSites:
+					# this is a gateway clone
+					# if sites were changed to something other than gateway, clear sequence	
+					if newFivePrime.lower() != 'attl' or newThreePrime.lower() != 'attl':
+						e = InsertSitesNotFoundOnParentSequenceException()
+						print `e.err_code()`
+						return
+					else:
+						pvSeqKey = rHandler.findDNASequenceKey(pvID)
+						
+						# For Gateway clones, linkers are found from primers - so find the sense and antisense Oligos for this Insert
+						insertLinkers = []
+			
+						# Find Sense and Antisense Oligos for this Insert
+						# (not using antisense just yet - verify with Karen)
+						iHandler = InsertHandler(db, cursor)
+			
+						senseOligoID = iHandler.findSenseOligoID(insertID)
+						#antisenseOligoID = iHandler.findAntisenseOligoID(insert_db_id)
+			
+						# Find Oligo sequences
+						seqPropID = pHandler.findPropID("sequence")
+						senseOligoSeqID = rHandler.findIndexPropertyValue(senseOligoID, seqPropID)
+						senseOligoSequence = dnaHandler.findSequenceByID(senseOligoSeqID)
+			
+						# Fetch Insert sequence and find linkers from Oligo and Insert sequences
+						insertSequence = dnaHandler.findSequenceByID(insertSeqID)
+			
+						attB_const = "ggggacaactttgtacaaaaaagttggc"
+						fwd_primer_seq = senseOligoSequence[len(attB_const):]
+			
+						# First, find linkers from Oligos
+						fwd_linker = dnaHandler.linker_from_oligo(insertSequence, fwd_primer_seq)
+						#rev_linker = sHandler.linker_from_oligo(insertSequence, rev_primer_seq)
+						rev_linker = ""
+			
+						# Now see if the Insert had its own linkers stored and append them to the Oligo linker
+						fpLinkerPropID = pHandler.findPropID("5' linker")
+						tpLinkerPropID = pHandler.findPropID("3' linker")
+			
+						fp_insert_linker = rHandler.findSimplePropertyValue(insertID, fpLinkerPropID)
+						tp_insert_linker = rHandler.findSimplePropertyValue(insertID, tpLinkerPropID)
+			
+						if fp_insert_linker and len(fp_insert_linker) > 0 and fp_insert_linker != 0 and fp_insert_linker != '0':
+							fp_insert_linker = fwd_linker + fp_insert_linker
+						else:
+							fp_insert_linker = fwd_linker
+			
+						tp_insert_linker = rev_linker
+			
+						insertLinkers.append(fp_insert_linker)
+						insertLinkers.append(tp_insert_linker)
+			
+						try:
+							newSeq = dnaHandler.entryVectorSequence(pvSeqKey, insertSeqID, insertLinkers)
+							print newSeq
+							
+						except MultipleSiteOccurrenceException:
+							e = MultipleSiteOccurrenceException("Sites found more than once on parent vector sequence")
+							print `e.err_code()`
+							
+						except FivePrimeAfterThreePrimeException:
+							e = FivePrimeAfterThreePrimeException("5' after 3'")
+							print `e.err_code()`
+
+						except InsertSitesNotFoundOnParentSequenceException:
+							e = InsertSitesNotFoundOnParentSequenceException("Gateway sites not found on parent vector sequence")
+							print `e.err_code()`
+						
+				else:
+					# Non-Gateway non-recombination Vector
+					fp_insert_cs = newFivePrime
+					tp_insert_cs = newThreePrime
+					
+					if  fp_insert_cs:
+						insertCloningSites.append(fp_insert_cs)
+					else:
+						insertCloningSites.append("")
+	
+					if  tp_insert_cs:
+						insertCloningSites.append(tp_insert_cs)
+					else:
+						insertCloningSites.append("")
+					
+					# get linkers if there are any
+					insertLinkers = []
+	
+					fpLinkerPropID = pHandler.findPropID("5' linker")
+					tpLinkerPropID = pHandler.findPropID("3' linker")
+					
+					fp_insert_linker = rHandler.findSimplePropertyValue(insertID, fpLinkerPropID)
+					tp_insert_linker = rHandler.findSimplePropertyValue(insertID, tpLinkerPropID)
+	
+					# sept. 3/07
+					fwd_linker = ""
+	
+					if fp_insert_linker and len(fp_insert_linker) > 0 and fp_insert_linker != 0 and fp_insert_linker != '0':
+						fp_insert_linker = fwd_linker + fp_insert_linker
+					else:
+						fp_insert_linker = fwd_linker
+						
+					insertLinkers.append(fp_insert_linker)
+					insertLinkers.append(tp_insert_linker)
+					
+					try:
+						newSeq = dnaHandler.constructNonRecombSequence(pvSeqID, insertSeqID, insertCloningSites, insertLinkers)
+						print newSeq
+					
+					except (InsertSitesException):
+						e = InsertSitesException("Could not reconstitute sequence: Unknown sites on Insert.")
+						print e.err_code()
+						
+					except (InsertSitesNotFoundOnParentSequenceException):
+						e = InsertSitesNotFoundOnParentSequenceException("Could not reconstitute sequence: Parent vector sequence does not contain restriction sites.")
+						print e.err_code()
+						
+					except (MultipleSiteOccurrenceException):
+						e = MultipleSiteOccurrenceException("Could not reconstitute sequence: Restriction sites occur more than once on parent vector sequence")
+						print e.err_code()
+						
+					except (HybridizationException):
+						e = HybridizationException("Could not reconstitute sequence: Restriction sites cannot be hybridized.")
+						print e.err_code()
+						
+					except (FivePrimeAfterThreePrimeException):
+						e = FivePrimeAfterThreePrimeException("Could not reconstitute sequence: 5' site occurs after 3' site on parent vector sequence.")
+						print e.err_code()
+			else:
+				e = InvalidSequenceException("Invalid parent sequence")
+				print `e.err_code()`
+		else:
+			e = UnknownPVIDException("Unknown PV ID")
+			print `e.err_code()`
+	
+	elif cloning_method == '2':
+
+		# Recombination vector - check IPV
+		ipvVal = form.getvalue("IPV")
+	
+		if len(ipvVal) > 0:
+			ipvID = rHandler.convertReagentToDatabaseID(ipvVal)
+			ipvProjectID = int(rHandler.findSimplePropertyValue(ipvID, packetPropID))
+		else:
+			e = UnknownIPVIDException("Unknown IPV ID")
+			print `e.err_code()`
+	
+		if ipvProjectID > 0 and currUser.getCategory() != 'Admin' and ipvProjectID not in uPackets:
+			e = IPVProjectAccessException("Not authorized to view IPV")
+			print `e.err_code()`
+		
+		if ipvID > 0 and pvID > 0:
+			
+			# If restriction sites were modified to anything other than LoxP or gateway att sites, clear the sequence
+			if not (newFivePrime == newThreePrime and (newFivePrime.lower() == 'loxp' and newThreePrime.lower() == 'loxp') or (newFivePrime.lower() == 'attb' and newThreePrime.lower() == 'attb')):
+				e = InsertSitesNotFoundOnParentSequenceException("Invalid restriction sites for Non-Recombination Clone - must be LoxP only")
+				print `e.err_code()`
+			else:
+				# get internal db IDs
+				pv_db_id = rHandler.convertReagentToDatabaseID(pvVal)
+				ipv_db_id = rHandler.convertReagentToDatabaseID(ipvVal)
+		
+				# Get the Insert that belongs to the donor vector
+				ipvInsertAssocID = raHandler.findReagentAssociationID(ipv_db_id)
+				insertAssocPropID = aHandler.findAssocPropID("insert id")
+				insert_db_id = aHandler.findAssocPropValue(ipvInsertAssocID, insertAssocPropID)
+		
+				# Construct a sequence for the new vector from the sequences of its parents
+				pvSeqKey = rHandler.findDNASequenceKey(pv_db_id)
+				#print "pv seq " + `pvSeqKey`
+				ipvSeqKey = rHandler.findDNASequenceKey(ipv_db_id)
+				#print "ipv seq " + `ipvSeqKey`
+				insertSeqKey = rHandler.findDNASequenceKey(insert_db_id)
+				#print "i seq " + `insertSeqKey`
+		
+				if pvSeqKey > 0 and ipvSeqKey > 0 and insertSeqKey > 0:
+	
+					# See if there are linkers, although there most likely aren't any
+					insertLinkers = []
+			
+					fpLinkerPropID = pHandler.findPropID("5' linker")
+					tpLinkerPropID = pHandler.findPropID("3' linker")
+			
+					fp_insert_linker = rHandler.findSimplePropertyValue(insert_db_id, fpLinkerPropID)
+					tp_insert_linker = rHandler.findSimplePropertyValue(insert_db_id, tpLinkerPropID)
+			
+					# sept. 3/07
+					fwd_linker = ""
+			
+					if fp_insert_linker and len(fp_insert_linker) > 0 and fp_insert_linker != 0 and fp_insert_linker != '0':
+						fp_insert_linker = fwd_linker + fp_insert_linker
+					else:
+						fp_insert_linker = fwd_linker
+			
+					insertLinkers.append(fp_insert_linker)
+					insertLinkers.append(tp_insert_linker)
+			
+					# Differentiate by cloning sites whether this is a recombination vector or a Gateway Expression Vector
+					if newFivePrime == 'LoxP' and newThreePrime == 'LoxP':
+						# recombination
+						try:
+							newSeq = dnaHandler.constructRecombSequence(pvSeqKey, ipvSeqKey, insertSeqKey, insertLinkers)
+							newSeqID = dnaHandler.matchSequence(newSeq)
+							print newSeq
+						
+						except InsertSitesNotFoundOnParentSequenceException:
+							e = InsertSitesNotFoundOnParentSequenceException("LOXP sites not found on parent vector sequence")
+							print `e.err_code()`
+
+						except MultipleSiteOccurrenceException:
+
+							e = MultipleSiteOccurrenceException("LOXP found more than once on parent vector sequence")
+							print `e.err_code()`
+
+					elif newFivePrime == 'attB' and newThreePrime == 'attB':
+						
+						# Gateway Expression
+						iHandler = InsertHandler(db, cursor)
+						
+						senseOligoID = iHandler.findSenseOligoID(insert_db_id)
+						#antisenseOligoID = iHandler.findAntisenseOligoID(insert_db_id)
+			
+						# Find Oligo sequences
+						seqPropID = pHandler.findPropID("sequence")
+						senseOligoSeqID = rHandler.findIndexPropertyValue(senseOligoID, seqPropID)
+						senseOligoSequence = dnaHandler.findSequenceByID(senseOligoSeqID)
+			
+						# Fetch Insert sequence and find linkers from Oligo and Insert sequences
+						insertSequence = dnaHandler.findSequenceByID(insertSeqKey)
+			
+						attB_const = "ggggacaactttgtacaaaaaagttggc"
+						fwd_primer_seq = senseOligoSequence[len(attB_const):]
+			
+						# First, find linkers from Oligos
+						fwd_linker = dnaHandler.linker_from_oligo(insertSequence, fwd_primer_seq)
+						#rev_linker = sHandler.linker_from_oligo(insertSequence, rev_primer_seq)
+						rev_linker = ""
+			
+						# Now see if the Insert had its own linkers stored and append them to the Oligo linker
+						fpLinkerPropID = pHandler.findPropID("5' linker")
+						tpLinkerPropID = pHandler.findPropID("3' linker")
+			
+						fp_insert_linker = rHandler.findSimplePropertyValue(insert_db_id, fpLinkerPropID)
+						tp_insert_linker = rHandler.findSimplePropertyValue(insert_db_id, tpLinkerPropID)
+			
+						if fp_insert_linker and len(fp_insert_linker) > 0 and fp_insert_linker != 0 and fp_insert_linker != '0':
+							fp_insert_linker = fwd_linker + fp_insert_linker
+						else:
+							fp_insert_linker = fwd_linker
+			
+						tp_insert_linker = rev_linker
+			
+						insertLinkers.append(fp_insert_linker)
+						insertLinkers.append(tp_insert_linker)
+						
+						try:
+							newSeq = dnaHandler.expressionVectorSequence(pvSeqKey, insertSeqKey, insertLinkers)
+							print newSeq
+						
+						except MultipleSiteOccurrenceException:
+							e = MultipleSiteOccurrenceException("Sites found more than once on parent vector sequence")
+							print `e.err_code()`
+							
+						except FivePrimeAfterThreePrimeException:
+							e = FivePrimeAfterThreePrimeException("5' after 3'")
+							print `e.err_code()`
+
+						except InsertSitesNotFoundOnParentSequenceException:
+							e = InsertSitesNotFoundOnParentSequenceException("Gateway sites not found on parent vector sequence")
+							print `e.err_code()`
+
+				else:
+					e = InvalidSequenceException("Invalid parent sequence")
+					print `e.err_code()`
+		else:
+			e = ReagentDoesNotExistException("Unknown parent values")
+			print `e.err_code()`
+update()
\ No newline at end of file
diff --git a/OpenFreezer/cgi/well.py b/OpenFreezer/cgi/well.py
new file mode 100755
index 0000000..e22d66d
--- /dev/null
+++ b/OpenFreezer/cgi/well.py
@@ -0,0 +1,86 @@
+#!/usr/local/bin/python
+
+# python modules
+import cgi
+import cgitb; cgitb.enable()
+
+import SocketServer
+from SocketServer import BaseRequestHandler
+
+import MySQLdb
+
+import os
+import tempfile
+import stat
+import sys
+import string
+
+# Custom modules
+import utils
+
+from database_conn import DatabaseConn
+#from session import Session
+
+from general_handler import GeneralHandler
+from laboratory import Laboratory
+
+class Well:
+	
+	__wellID = 0			# internal database ID
+	__wellRowNum = 0		# row number (1 -> 'A', 2 -> 'B', etc.)
+	__wellRowChar = ""		# alphanumeric representation of the row number (numbers higher than 26 are represented with more than one character)
+	__wellCol = 0			# column number
+	
+	def __init__(self, wellID, wellRowNum, wellCol, contID):
+		
+		self.__wellID = wellID
+		self.__wellRowNum = wellRowNum
+		self.__wellRowChar = self.convertRowNumberToChar(self.__wellRowNum )
+		self.__wellCol = wellCol
+		self.__contID = contID
+
+	
+	#################################################
+	# Assignment methods
+	#################################################
+	def setWellID(self, wellID):
+		self.__wellID = wellID
+		
+		
+	def setWellColumn(self, wellCol):
+		self.__wellCol = wellCol
+		
+		
+	def setWellRowNumber(self, wellRowNum):
+		self.__wellRowNum = wellRowNum
+		
+	
+	def setContainerID(self, contID):
+		self.__contID = contID
+		
+		
+	#################################################
+	# Access methods
+	#################################################
+	def getWellID(self):
+		return self.__wellID
+	
+	
+	def getWellColumn(self):
+		return self.__wellCol
+	
+	
+	def getWellRowNumber(self):
+		return self.__wellRowNum
+		
+		
+	def getContainerID(self):
+		return self.contID
+	
+	#################################################
+	# Utilities
+	#################################################
+	@classmethod
+	def convertRowNumberToChar(Well, rowNum):
+		alphabet = string.letters		# this is only A-Z
+		return alphabet[rowNum-1].upper()
\ No newline at end of file
diff --git a/OpenFreezer/contacts.php b/OpenFreezer/contacts.php
new file mode 100755
index 0000000..752549d
--- /dev/null
+++ b/OpenFreezer/contacts.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ * Standard 'Contact Us' page
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license		http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+ * This file is part of OpenFreezer (TM)
+ *
+ * OpenFreezer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+
+ * OpenFreezer is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+ *
+*/
+	include "Classes/MemberLogin_Class.php";
+	include "Classes/Member_Class.php";
+	include "Classes/Session_Var_Class.php";
+	include "DatabaseConn.php";
+
+	session_start();
+
+	$loginBlock = new MemberLogin_Class();
+	$loginBlock->loginCheck($_POST);
+
+	header("Cache-control: private"); //IE 6 Fix 
+
+	include "HeaderFunctions.php";
+
+	// Global Session Variables.
+	// FIX IT: Should probably isolate this better
+	$sessionChecker = new Session_Var_Class();
+	$sessionChecker->checkSession_all();
+	unset( $sessionChecker );
+
+	if (!isset($_SESSION["userinfo"]))
+	{
+		# Disallow documentation download without login
+		$docs_disabled = true; 
+	}
+	else
+	{
+	}
+
+	// June 3, 2010
+	global $mail_programmer;
+	global $mail_biologist;
+
+	// print header
+	outputMainHeader();
+	
+	?>	
+<!--	<table width="100%" border="0" class="nav">
+		<tr>		
+			<td>
+				<?php
+// 					outputNavBar();
+				?>
+			</td>
+		</tr>
+	</table>
+	
+	<div class="main">-->
+	<center>
+		<table style="text-align:justify; padding:10px" width="100%">
+			<!-- Marina: March 4/08: Create a resizeable border -->
+			<!--<tr>
+				<td rowspan="100%" style="padding-left:0; padding-right:5px;">
+					<div class="resizeable" onMouseOver="resize();"></div>
+				</td>
+			</tr>-->
+
+			<th colspan="3" style="text-align:center; font-weight:bold; color:#0000ff">OpenFreezer Team Leads</th>
+
+			<TR><TD> </td></tr>
+
+			<tr>
+				<td width="135px">Programmer:</td>
+				<td width="180px">Marina Olhovsky</td>
+				<td><a href="mailto:<?php echo $mail_programmer; ?>"><?php echo $mail_programmer; ?></a></td>
+			</tr>
+
+			<tr>
+				<td>Biologist:</td>
+				<td>Karen Colwill</td>
+				<td><a href="mailto:<?php echo $mail_biologist; ?>"><?php echo $mail_biologist; ?></a></td>
+			</tr>
+		</table>
+	</center>
+	<?php
+
+	// footer
+	outputMainFooter();	
+?>
diff --git a/OpenFreezer/copyright.php b/OpenFreezer/copyright.php
new file mode 100755
index 0000000..832db23
--- /dev/null
+++ b/OpenFreezer/copyright.php
@@ -0,0 +1,125 @@
+<?php
+/**
+ * Copyright
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+ * This file is part of OpenFreezer
+ *
+ * OpenFreezer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+
+ * OpenFreezer is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+ *
+*/
+	include "Classes/MemberLogin_Class.php";
+	include "Classes/Member_Class.php";
+	include "Classes/Session_Var_Class.php";
+	include "DatabaseConn.php";
+
+	session_start();
+
+	$loginBlock = new MemberLogin_Class();
+	$loginBlock->loginCheck($_POST);
+
+	header("Cache-control: private"); //IE 6 Fix 
+
+	include "HeaderFunctions.php";
+
+	// Global Session Variables.
+	// FIX IT: Should probably isolate this better
+	$sessionChecker = new Session_Var_Class();
+	$sessionChecker->checkSession_all();
+	unset( $sessionChecker );
+
+	if (!isset($_SESSION["userinfo"]))
+	{
+		# Disallow documentation download without login
+		$docs_disabled = true; 
+	}
+
+	// print header and side menu
+	outputMainHeader();
+	
+	?>
+	<table bgcolor="#FFFFE0" height="100%">
+		<table width="770px" style="font-size:12pt; padding:3px; text-align:justify" cellpadding="2" cellspacing="2">
+			<th style="text-align:center">OpenFreezer Terms and Conditions</th>
+
+			<tr>
+				<td style="font-weight:bold; padding-top:10px;">
+					License
+				</td>
+			</tr>
+	
+			<tr>
+				<td style="padding-top:10px;">
+					OpenFreezer is distributed under the GNU License, Version 3; you may not use this application except in compliance with the License. You may obtain a copy of the License at <a href="www.gnu.org/licenses">www.gnu.org/licenses</a>.
+				</td>
+			</tr>
+
+			<tr>
+				<td style="padding-top:10px; font-weight:bold;">
+					Third Party Links
+				</td>
+			</tr>
+
+			<tr>
+				<td style="padding-top:10px;">
+					This software package may contain third-party owned content or information, and may also include links or references to other web sites maintained by third parties over whom Mount Sinai Hospital has no control. Mount Sinai Hospital does not endorse, sponsor, recommend, warrant, guarantee or otherwise accept any responsibility for such third party content, information or web sites. Access to any third-party owned content or information or web site is at your own risk, and Mount Sinai [...]
+				</td>
+			</tr>
+
+			<tr>
+				<td style="font-weight:bold; padding-top:10px;">
+					Disclaimer of Warranty; Limitation of Liability
+				</td>
+			</tr>
+
+			<tr>
+				<td style="padding-top:10px;">
+					MOUNT SINAI HOSPITAL DISCLAIMS ALL EXPRESS AND IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE PACKAGE, THE INFORMATION, SERVICES AND MATERIALS DESCRIBED OR CONTAINED IN THIS SOFTWARE PACKAGE, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OF MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  YOUR ACCESS TO AND USE OF THIS SOFTWARE PACKAGE ARE AT YOUR OWN RISK. INFORMATION, SERVICES AND MATERIALS CONTAINED HEREIN MAY NOT BE ERROR-FREE. MOUNT SINAI HOSPITAL  [...]
+				</td>
+			</tr>
+
+			<tr>
+				<td style="font-weight:bold; padding-top:10px;">
+					Indemnification
+				</td>
+			</tr>
+
+			<tr>
+				<td style="padding-top:10px;">
+					You agree to indemnify, defend and hold harmless Mount Sinai Hospital, its officers, directors, employees, agents, consultants, suppliers and third party partners from and against all losses, expenses, damages and costs, including reasonable attorneys' fees, resulting from any violation by you of these Terms and Conditions
+				</td>
+			</tr>
+
+			<tr>
+				<td style="font-weight:bold; padding-top:10px;">
+					Applicable Laws
+				</td>
+			</tr>
+
+			<tr>
+				<td style="padding-top:10px;">
+					These Terms and Conditions and the resolution of any dispute related to these Terms and Conditions shall be construed in accordance with the laws of the province of Ontario, Canada, without regard to its conflicts of laws principles. Any legal action or proceeding related to this Software shall be brought exclusively by the federal and provincial courts of the province of Ontario, Canada.
+				</td>
+			</tr>
+		</table>
+	</table>
+	<?php
+
+	outputMainFooter();
+?>
diff --git a/OpenFreezer/dedication.php b/OpenFreezer/dedication.php
new file mode 100755
index 0000000..6472c14
--- /dev/null
+++ b/OpenFreezer/dedication.php
@@ -0,0 +1,60 @@
+<?php
+	include "Classes/MemberLogin_Class.php";
+	include "Classes/Member_Class.php";
+	include "Classes/Session_Var_Class.php";
+	include "DatabaseConn.php";
+
+	session_start();
+
+	$loginBlock = new MemberLogin_Class();
+	$loginBlock->loginCheck($_POST);
+
+	header("Cache-control: private"); //IE 6 Fix 
+
+	include "HeaderFunctions.php";
+
+//	$link = mysql_pconnect($databaseip, $name, $pw) or die("Could not connect: " . mysql_error());
+//	mysql_select_db($databasename) or die("Could not select database");
+
+	// Global Session Variables.
+	// FIX IT: Should probably isolate this better
+	$sessionChecker = new Session_Var_Class();
+	$sessionChecker->checkSession_all();
+	unset( $sessionChecker );
+
+	outputMainHeader();
+
+	?>
+	<P style="margin-top:3px;">
+	<TABLE style="padding-left:10px; padding-right:10px; padding-top:5px; padding-bottom:20px;">
+		<TH style="font-size:14pt; color:black; text-align:center; padding-right:105px;">LARISA OLHOVSKY</TH>
+
+		<TR>
+			<TD style="padding-top:10px; text-align:center; padding-right:105px;">
+				<IMG SRC="pictures/Mom.jpg" width="290" height="360">
+				<BR><P><span style="font-weight:bold;">August 3, 1955 -- March 18, 2006</span>
+			</TD>
+		</TR>
+
+		<TR>
+			<TD style="width:80%; padding-left:1%; padding-right:12px; padding-top:15px; text-align:justify;">
+				Cancer claimed the life of <b>Larisa Olhovsky</b> too fast too soon.  This software is dedicated to her by her daughter, <a href="mailto:olhovsky at lunenfeld.ca">Marina Olhovsky</a>, the programmer of OpenFreezer, as a guiding light for biological researchers on their path towards winning the battle against cancer and other diseases.
+			</TD>
+		</TR>
+
+		<TR>
+			<TD style="padding-top:15px; padding-left:10px; margin-left:10%; text-align:justify; font-weight:bold;">
+				<i>LEST WE FORGET</i>
+			</TD>
+		</TR>
+
+		<TR>
+			<TD style="padding-top:15px; padding-left:10px; text-align:justify; margin-left:10%; font-weight:bold;">
+				<IMG SRC="pictures/roses2.gif" width="" height="">
+			</TD>
+		</TR>
+	</TABLE>
+	<?php
+
+	outputMainFooter();
+?>
\ No newline at end of file
diff --git a/OpenFreezer/docs.php b/OpenFreezer/docs.php
new file mode 100755
index 0000000..e4d1089
--- /dev/null
+++ b/OpenFreezer/docs.php
@@ -0,0 +1,130 @@
+<?php
+/**
+ * Documentation page
+ *
+ * @author Marina Olhovsky <olhovsky at lunenfeld.ca>
+ * @version 3.1
+ *
+ * PHP versions 4 and 5
+ *
+ * @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+ *
+ * This file is part of OpenFreezer (TM)
+ *
+ * OpenFreezer is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * at your option) any later version.
+
+ * OpenFreezer is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+ *
+*/
+	include "Classes/MemberLogin_Class.php";
+	include "Classes/Member_Class.php";
+	include "Classes/Session_Var_Class.php";
+	include "DatabaseConn.php";
+
+	session_start();
+
+	$loginBlock = new MemberLogin_Class();
+	$loginBlock->loginCheck($_POST);
+
+	header("Cache-control: private"); //IE 6 Fix 
+
+	include "HeaderFunctions.php";
+
+//	$link = mysql_pconnect($databaseip, $name, $pw) or die("Could not connect: " . mysql_error());
+//	mysql_select_db($databasename) or die("Could not select database");
+
+	// Global Session Variables.
+	// FIX IT: Should probably isolate this better
+	$sessionChecker = new Session_Var_Class();
+	$sessionChecker->checkSession_all();
+	unset( $sessionChecker );
+
+	if (!isset($_SESSION["userinfo"]))
+	{
+		# Disallow documentation download without login
+		$docs_disabled = true; 
+	}
+	else
+	{
+	}
+
+	outputMainHeader();
+	?>
+<!--	<table width="100%" border="0" class="nav">
+		<tr>		
+			<td>
+				<?php
+// 					outputNavBar();
+				?>
+			</td>
+
+			<td>
+				<?php 
+//					$loginBlock->printLoginInfo( "" );
+				?>
+			</td>
+		</tr>
+	</table>-->
+	
+<!-- 	<div class="main"> -->
+	
+				<form name="docs" method="POST" action="save.php" ENCTYPE="multipart/form-data">
+					<table width="100%">
+						<!-- Marina: March 4/08: Create a resizeable border -->
+						<!--<tr>
+							<td rowspan="100%" style="padding-left:0; padding-right:5px;">
+								<div class="resizeable" onMouseOver="resize();"></div>
+							</td>
+						</tr>-->
+			
+						<TH style="text-align:left;">
+							<BR><BR>Please refer to the OpenFreezer User Manual at <a href="http://openfreezer.org">http://openfreezer.org</a><BR><HR>
+						</TH>
+
+						<TR>
+							<td colspan="3">
+								<a href="copyright.php">Copyright Notice and Disclaimer</a>  							
+									<a href="Docs/Copyright.doc"><IMG SRC="pictures/disk_small.gif" WIDTH="15" HEIGHT="15" BORDER="0" ALT="doc" style="cursor:pointer; vertical-align:bottom"></a>
+								<P>
+							</td>
+						</tr>
+					</table>
+
+					<table width="770px">
+						<tr>
+							<td style="border-top:1px solid black; padding-top:5px;">
+								<P style="text-align:center; font-weight:bold">OpenFreezer Contributors</P>
+
+								<P style="text-decoration:none; font-weight:bold">Design and Implementation Team:</P>
+
+								<a href="mailto:<?php echo $mail_programmer; ?>">Marina Olhovsky</a>, <a href="mailto:<?php echo $mail_biologist; ?>">Karen Colwill</a>, John Paul Lee, <a href="http://linding.eu">Rune Linding</a>, Clark Wells, <a href="http://www.biodesign.asu.edu/research/research-centers/personalized-diagnostics">Jin Gyoon Park</a>, <a href="mailto:pasculescu at lunenfeld.ca">Adrian Pasculescu</a><BR><BR>
+
+								<P style="text-decoration:none; font-weight:bold">Testing Team:</P>
+								<a href="mailto:williton at lunenfeld.ca">Kelly Williton</a>, <a href="mailto:anna at lunenfeld.ca">Anna Yue Dai</a>, <a href="mailto:goudreault at lunenfeld.ca">Marilyn Goudreault</a>, Kadija Hersi<BR><BR>
+
+								<P style="text-decoration:none; font-weight:bold">Technical Support:</P>
+								<a href="mailto:mohammad at lunenfeld.ca">Naveed Mohammad</a><BR><BR>
+
+								<P style="text-decoration:none; font-weight:bold">Principal Investigator:</P>
+								<a href="mailto:PAWSON at lunenfeld.ca">Tony Pawson</a><BR><BR>
+							</td>
+						</tr>
+					</table>
+				</form>
+			</td>
+		</tr>
+	</table>
+	<?php
+
+	outputMainFooter();
+?>
diff --git a/OpenFreezer/exportChemical.php b/OpenFreezer/exportChemical.php
new file mode 100644
index 0000000..acb9d2a
--- /dev/null
+++ b/OpenFreezer/exportChemical.php
@@ -0,0 +1,10 @@
+<?php
+	header("Content-type: application/octet-stream");
+	header("Content-Disposition: attachment; filename=chemicals.tsv");
+	header("Pragma: no-cache");
+	header("Expires: 0");
+	
+ 	//print_r($_REQUEST);
+
+	print $_REQUEST["outputContent"];
+?>
diff --git a/OpenFreezer/functions.php b/OpenFreezer/functions.php
new file mode 100755
index 0000000..966fc72
--- /dev/null
+++ b/OpenFreezer/functions.php
@@ -0,0 +1,334 @@
+<?php
+
+// DO NOT DELETE THIS CLASS - USED IN SEARCH TABLE OUTPUT!!!!!!!!!!!!!!!!!!!!!!!
+
+/**
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Search
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Handles functions to output reagent search results (summary) table
+ *
+ * @author John Paul Lee @version 2005
+ *
+ * @package Search
+ *
+ * @copyright	2005-2011 Mount Sinai Hospital, Toronto, Ontario
+ * @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Include/require statements
+*/
+include "Reagent/Reagent_Function_Class.php";
+
+
+/**
+* @author John Paul Lee @version 2005
+*/
+function setVectorTypeIDs( $tomatch )
+{
+	$vectorTypeID_arr = array();
+
+	//print_r( $tomatch );
+	
+	while( $row = mysql_fetch_row($tomatch) )
+	{
+		//foreach ($row as $col_value) {
+        //echo "\t\t$col_value\n";
+    	//	}	
+		$vectorTypeID_arr[ $row[1] ] = $row[0];
+	}	 
+	
+	//print_r( $vectorTypeID_arr );
+	
+	return $vectorTypeID_arr;
+}
+
+/**
+* Output reagent type selection box on search page
+*
+* @author John Paul Lee @version 2005
+*/
+function reagentChoice()
+{
+	echo "<SELECT NAME=\"ReagentChoice\" SIZE=1>\n";
+	echo "<OPTION>Vector</OPTION>\n";
+	echo "<OPTION>Insert</OPTION>\n";
+	echo "<OPTION>Oligo</OPTION>\n";
+	echo "<OPTION>CellLine</OPTION>\n";
+	echo "</SELECT>";
+}
+
+
+
+function outputarray( $tooutput )
+{
+	
+}
+
+
+/**
+* Generate a map of reagent property IDs => names
+*
+* @author John Paul Lee @version 2005
+*
+* @see setVectorTypeIDs()
+*/
+function getReagentPropID_const()
+{
+	// CONST : Finds all the names of the property and their given property ID's
+	//			propName --> propID
+	//           [DEBUG] : 1
+	global $conn;
+	
+	$reagentPropID_rs = mysql_query( "SELECT propertyID, propertyName FROM `ReagentPropType_tbl` WHERE `status`='ACTIVE'", $conn) 
+								or die("Query to find property names failed!: ".mysql_error() );
+	
+	
+	$reagentPropID_const = setVectorTypeIDs( $reagentPropID_rs );
+	mysql_free_result( $reagentPropID_rs );
+	//echo "<br> ---- reagentPropID_const ---- <br>";
+	//print_r( $reagentPropID_const );
+	return $reagentPropID_const;
+}
+
+
+/**
+* Generate a map of reagent property names => IDs
+*
+* @author John Paul Lee @version 2005
+*
+* @see setVectorTypeIDs()
+*/
+function getReagentPropID_const_rev( )
+{
+	// CONST : Finds all the names of the property and their given property ID's
+	//			propName --> propID
+	//           [1] : DEBUG
+	global $conn;
+	
+	$reagentPropID_rs = mysql_query( "SELECT propertyName, propertyID FROM `ReagentPropType_tbl` WHERE `status`='ACTIVE'", $conn ) 
+						or die("Query to find property names failed!: ".mysql_error() );
+	
+	
+	$reagentPropID_const = setVectorTypeIDs( $reagentPropID_rs );
+	mysql_free_result( $reagentPropID_rs );
+	//echo "<br> ---- reagentPropID_const ---- <br>";
+	//print_r( $reagentPropID_const );
+	return $reagentPropID_const;
+}
+
+
+/**
+* Generate a map of reagent type IDs => names
+*
+* @author John Paul Lee @version 2005
+*
+* @see setVectorTypeIDs()
+*/
+function getReagentTypes_const()
+{
+	// CONST : Finds all vector types available currently in the database
+	// 			reagentType --> reagentTypeID
+	// 			Vector --> 1
+	global $conn;
+	$reagentTypes_rs = mysql_query( "SELECT `reagentTypeID`, `reagentTypeName` FROM `ReagentType_tbl` WHERE `status`='ACTIVE'", $conn ) 
+							or die("Query Failed 1: " .mysql_error() );
+	$reagentTypes_const = setVectorTypeIDs( $reagentTypes_rs );
+	mysql_free_result( $reagentTypes_rs );
+	//echo "<br> ---- reagentTypes_const ---- <br>";
+	//print_r( $reagentTypes_const );
+	return $reagentTypes_const;
+}
+
+
+/**
+* Generate a map of reagent type names => IDs
+*
+* @author John Paul Lee @version 2005
+*
+* @see setVectorTypeIDs()
+*/
+function getReagentTypes_const_rev()
+{
+	// CONST : Finds all vector types available currently in the database
+	// 			reagentType --> reagentTypeID
+	// 			1 --> Vector
+	global $conn;
+	
+	$reagentTypes_rs = mysql_query( "SELECT `reagentTypeName`, `reagentTypeID` FROM `ReagentType_tbl` WHERE `status`='ACTIVE'", $conn) 
+							or die("Query Failed 1: " .mysql_error() );
+	$reagentTypes_const = setVectorTypeIDs( $reagentTypes_rs );
+	mysql_free_result( $reagentTypes_rs );
+	//echo "<br> ---- reagentTypes_const ---- <br>";
+	//print_r( $reagentTypes_const );
+	return $reagentTypes_const;
+}
+
+// CONST : Finds all the vector properties associated with a given vector type.
+/**
+* @author John Paul Lee @version 2005
+*/
+function getReagentPropReq( $reagentToFind, $types )
+{
+	global $conn;
+	
+	$reagentProp_rs = mysql_query( "SELECT `propertyID`,`requirement` FROM `PropertyReq_tbl` WHERE reagentTypeID='" . 
+					$types[$reagentToFind] . "' AND `status`='ACTIVE' ORDER BY `propertyID` ASC;", $conn ) 
+						or die("Query to find reagent property associated failed!: ".mysql_error() );
+	
+	$tempPropReq_ar = array ();
+	
+	while( $row = mysql_fetch_array( $reagentProp_rs, MYSQL_ASSOC ) )
+	{
+		$tempPropReq_ar[$row["propertyID"]]=$row["requirement"];
+	}
+	
+	mysql_free_result( $reagentProp_rs );
+	return $tempPropReq_ar;
+}
+
+/**
+* Fetch a list of required properties for preps of type identified by $reagentTypeID_tofind
+*
+* @author John Paul Lee @version 2005
+*
+* @param INT represents reagent type ID, e.g. 1 => 'Vector'
+*/
+function getReagentPropReq_num( $reagentTypeID_tofind, $types ) 
+{
+	global $conn;
+	$reagentProp_rs = mysql_query( "SELECT `propertyID`,`requirement` FROM `PropertyReq_tbl` WHERE reagentTypeID='" . 
+					$reagentTypeID_tofind . "' AND `status`='ACTIVE' ORDER BY `propertyID` ASC;", $conn  ) 
+						or die("Query to find reagent property associated failed!: ".mysql_error() );
+	
+	$tempPropReq_ar = array ();
+	
+	while( $row = mysql_fetch_array( $reagentProp_rs, MYSQL_ASSOC ) )
+	{
+		$tempPropReq_ar[$row["propertyID"]]=$row["requirement"];
+	}
+	
+	mysql_free_result( $reagentProp_rs );
+	return $tempPropReq_ar;
+}
+
+
+/**
+* @author John Paul Lee @version 2005
+*/
+function cleanArray( $toclean_ar, $constVal, $badvalues )
+{
+	while( list($delkey, $delval) = each( $badvalues ) )
+	{
+		unset( $toclean_ar[$constVal[$delval]] );
+	}
+	
+	return $toclean_ar;
+}
+
+
+/**
+* Fetch the type ID of the given sequence
+*
+* @author John Paul Lee @version 2005
+*
+* @param INT Sequence ID (corresponds to Sequences_tbl.seqID column)
+*/
+function getSeqTypeID( $toFind )
+{
+	global $conn;
+	
+	$type_rs = mysql_query( "SELECT `seqTypeID` FROM `SequenceType_tbl` WHERE `status`='ACTIVE' AND `seqTypeName`='" . $toFind 
+						. "'", $conn );
+	
+	if( $type_ar = mysql_fetch_array( $type_rs, MYSQL_ASSOC ) )
+	{
+		return $type_ar["seqTypeID"];
+	}
+	
+	return -1;
+}
+
+function getNames( $toConvert )
+{
+	
+}
+
+/* outputs the menu options available */
+function menuTemp()
+{
+	echo "<FORM METHOD=POST ACTION=\"index.php\">";
+	//echo "<INPUT TYPE=SUBMIT NAME=\"View Vectors\" VALUE=\"View All Vector Reagents\">";
+	echo "Input Selection:";
+	echo "<SELECT NAME=choice SIZE=1>\n";
+	echo "<OPTION>View all Vector Reagents</OPTION>\n";
+	echo "<OPTION>View all Insert Reagents</OPTION>\n";
+	echo "<OPTION>View all Oligo Reagents</OPTION>\n";
+	echo "<OPTION>View all CellLine Reagents</OPTION>\n";
+	echo "<OPTION>View Packets Available</OPTION>\n";
+	echo "</SELECT> \n";
+	echo "<BR><br>\n";
+	echo "<INPUT TYPE=SUBMIT NAME=\"ChoiceButton\" VALUE=\"Submit Choice\">";
+	echo "</FORM>";
+	
+	//$_SESSION["SearchType"] = "Reagents";
+	
+	?> 
+	<a href="Search/search.php?Advanced=False&View=1">Search</a>
+	<br>
+	<a href="Views/LocationPlate_View.php?Mode=0">View</a>
+	<br>
+	<a href="Insert_Type_seq.xls">Sequence File</a>
+	<?php
+	
+	
+	echo "<HR>";
+}
+
+/* Basic HTML header information */
+function GenerateHTMLHeader( $title )
+{
+	echo "<html>";
+	echo "<head>";
+	echo "<title>" . $title . "</title>";
+	echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">";
+	echo "</head>";
+	echo "<body>";
+}
+
+/* Basic HTML footer information */
+function GenerateHTMLFooter( )
+{
+	echo "</body>";
+	echo "</html>";
+}
+?>
\ No newline at end of file
diff --git a/OpenFreezer/index.php b/OpenFreezer/index.php
new file mode 100755
index 0000000..e0739ed
--- /dev/null
+++ b/OpenFreezer/index.php
@@ -0,0 +1,102 @@
+<?php
+/**
+* Main page
+*
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package All
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Include/require statements
+*/
+	include "DatabaseConn.php";
+
+	include "Classes/MemberLogin_Class.php";
+	include "Classes/Member_Class.php";
+	include "Classes/Session_Var_Class.php";
+
+	session_start();
+
+	$loginBlock = new MemberLogin_Class();
+	$loginBlock->loginCheck($_POST);
+
+	header("Cache-control: private"); //IE 6 Fix 
+
+	include "HeaderFunctions.php";
+	//include "functions.php";
+	include_once "Reagent/Reagent_Function_Class.php";	// July 19, 2010
+	//include "Location/LocationFunct.php";
+
+	// Global Session Variables.
+	// FIX IT: Should probably isolate this better
+	$sessionChecker = new Session_Var_Class();
+	$sessionChecker->checkSession_all();
+	unset( $sessionChecker );
+
+	$rfunc_obj = new Reagent_Function_Class();
+	$rcount = $rfunc_obj->computeTotalReagents();
+
+	outputMainHeader();
+	
+	// June 3, 2010
+	global $mail_biologist;
+	global $mail_programmer;
+
+	?>
+	<TABLE height="99%">
+		<TABLE width="99%" style="text-align:justify; white-space:normal;">
+			<!-- Marina: March 4/08: Create a resizeable border -->
+			<!--<tr>
+				<td rowspan="100%" style="padding-left:0; padding-right:5px;">
+					<div class="resizeable" onMouseOver="resize();"></div>
+				</td>
+			</tr>-->
+
+			<TR>
+				<td colspan="3">
+					<P style="padding-left:10px;">
+						<span style="color:#000000; font-weight:bold">OpenFreezer Laboratory Reagent Tracking and Workflow Management System</span> comprises a variety of software tools designed to provide support to wetlab scientists.  At its core, the system tracks information on all reagents within the laboratory, such as types of reagents, specific properties of each reagent (including sequences), all isolates and preps of a reagent, and where the preps of reagents are stored in the laboratory.<BR><BR [...]
+
+						<SPAN style="padding-top:5px; font-weight:bold; font-size:9pt;">OpenFreezer leaders:</SPAN><BR><BR>
+
+						<SPAN style="padding-left:10px;">Programmer: <a href="mailto:olhovsky at lunenfeld.ca">Marina Olhovsky</a><BR></span>
+						<SPAN style="padding-left:10px;">Biologist: <a href="mailto:colwill at lunenfeld.ca">Karen Colwill</a><BR><BR></span>
+
+						<P style="padding-left:10px;"><SPAN style="border: 1px solid black; width:850px; padding:10px; font-weight:bold; font-size:9pt;">Dedicated in loving memory of <a href="dedication.php">Larisa Olhovsky</a></SPAN><BR><BR>
+						
+						<P style="padding-left:10px; padding-top:5px;">Please report any errors with the source code through the Bug Tracker at <a href="http://openfreezer.org/bugreport.html">http://openfreezer.org/bugreport.html</a>.  All other questions should be reported to the local administrator.
+				</td>
+			</TR>
+		</TABLE>
+	</TABLE>
+	<?php 
+
+	// print footer
+	outputMainFooter();
+?>
diff --git a/OpenFreezer/orderExcel.php b/OpenFreezer/orderExcel.php
new file mode 100755
index 0000000..3fb2b24
--- /dev/null
+++ b/OpenFreezer/orderExcel.php
@@ -0,0 +1,10 @@
+<?php
+	header("Content-type: application/octet-stream");
+	header("Content-Disposition: attachment; filename=cloneOrder.csv");
+	header("Pragma: no-cache");
+	header("Expires: 0");
+	
+// 	print_r($_POST);
+
+	print $_POST["outputContent"];
+?>
\ No newline at end of file
diff --git a/OpenFreezer/overlib/BabelFish.js b/OpenFreezer/overlib/BabelFish.js
new file mode 100755
index 0000000..baa3609
--- /dev/null
+++ b/OpenFreezer/overlib/BabelFish.js
@@ -0,0 +1,58 @@
+/*
+ BabelFish.js - Script for using the AltaVista BabelFish translation service.
+   Adapted by Foteos Macrides for use with the overlibmws code set.
+   See http://www.macridesweb.com/oltest/BabelFish.html for a demonstration.
+   Initial: October 26, 2003 - Last Revised: January 26, 2008 
+*/
+OLtrans_en = new Image();
+OLtrans_en.src = "http://babelfish.altavista.com/static/i/af/trans_en.gif"
+OLtrans_en_off = new Image();
+OLtrans_en_off.src = "http://babelfish.altavista.com/static/i/af/trans_en_off.gif"
+
+var OLbfURL = location.href;
+
+if (location.href.indexOf("babelfish.altavista.com") == -1) {
+var BabelFish =
+'<div class="babelfish">'
++'<p align="center"><strong>Note:</strong> This page can be viewed in a different language by '
++'selecting the corresponding flag below.</p>'
++'<p align="center">'
++'<!--script type="text/javascript" src="http://www.altavista.com/r?entr"></script-->'
++'<Map name="translate_eng">'
++'<AREA COORDS="0,1,129,38" SHAPE="rect" target="translate" '
++'title="Go to Babel Fish home page/" '
++'href="http://babelfish.altavista.com">'
++'<AREA COORDS="5,110,32,126" SHAPE="rect" target="translate" '
++'title="Translate English to Chinese." '
++'href="http://babelfish.altavista.com/babelfish/tr?doit=done&url='+OLbfURL+'&lp=en_zh">'
++'<AREA COORDS="38,110,65,126" SHAPE="rect" target="translate" '
++'title="Translate English to German." '
++'href="http://babelfish.altavista.com/babelfish/tr?doit=done&url='+OLbfURL+'&lp=en_de">'
++'<AREA COORDS="70,110,95,126"  SHAPE="rect" target="translate" '
++'title="Translate English to Japanese." '
++'href="http://babelfish.altavista.com/babelfish/tr?doit=done&url='+OLbfURL+'&lp=en_ja">'
++'<AREA COORDS="99,110,123,126" SHAPE="rect" target="translate" '
++'title="Translate English to Korean." '
++'href="http://babelfish.altavista.com/babelfish/tr?doit=done&url='+OLbfURL+'&lp=en_ko">'
++'<AREA COORDS="8,130,31,146" SHAPE="rect" target="translate" '
++'title="Translate English to French." '
++'href="http://babelfish.altavista.com/babelfish/tr?doit=done&url='+OLbfURL+'&lp=en_fr">'
++'<AREA COORDS="39,130,65,146" SHAPE="rect" target="translate" '
++'title="Translate English to Italian." '
++'href="http://babelfish.altavista.com/babelfish/tr?doit=done&url='+OLbfURL+'&lp=en_it">'
++'<AREA COORDS="70,130,93,146" SHAPE="rect" target="translate" '
++'title="Translate English to Portuguese." '
++'href="http://babelfish.altavista.com/babelfish/tr?doit=done&url='+OLbfURL+'&lp=en_pt">'
++'<AREA COORDS="100,130,125,146" SHAPE="rect" target="translate" '
++'title="Translate English to Spanish." '
++'href="http://babelfish.altavista.com/babelfish/tr?doit=done&url='+OLbfURL+'&lp=en_es">'
++'</Map>'
++'<img src="http://babelfish.altavista.com/static/i/af/trans_en.gif" '
++'width="131" height="156" usemap="#translate_eng" border="0"><br></p>'
++'<p align="center">The translations are done via the AltaVista Babel Fish service.</p></div>';
+}else{
+var BabelFish =
+'<div class="babelfish"><p align="center">'
++'<img src="http://babelfish.altavista.com/static/i/af/trans_en_off.gif" '
++'width="131" height="156" border="0"></p></div>';
+}
diff --git a/OpenFreezer/overlib/Mini/overlib_anchor_mini.js b/OpenFreezer/overlib/Mini/overlib_anchor_mini.js
new file mode 100755
index 0000000..c12a034
--- /dev/null
+++ b/OpenFreezer/overlib/Mini/overlib_anchor_mini.js
@@ -0,0 +1,98 @@
+//\/////
+//\  overLIB Anchor Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.10 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+//\  THIS IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL!
+if(typeof olInfo=='undefined'||typeof olInfo.meets=='undefined'||!olInfo.meets(4.10))alert('overLIB 4.10 or later is required for the Anchor Plugin.');else{registerCommands('anchor,anchorx,anchory,noanchorwarn,anchoralign');
+if(typeof ol_anchor=='undefined')var ol_anchor='';if(typeof ol_anchorx=='undefined')var ol_anchorx=0;if(typeof ol_anchory=='undefined')var ol_anchory=0;if(typeof ol_noanchorwarn=='undefined')var ol_noanchorwarn=1;if(typeof ol_anchoralign=='undefined')var ol_anchoralign='UL';
+var o3_anchor="",o3_anchorx=0,o3_anchory=0,o3_noanchorwarn=1,o3_anchoralign='UL',mrkObj,rmrkPosition;
+function setAnchorVariables(){o3_anchor=ol_anchor;o3_anchorx=ol_anchorx;o3_anchory=ol_anchory;o3_noanchorwarn=ol_noanchorwarn;o3_anchoralign=ol_anchoralign;mrkObj=null;}
+function parseAnchorExtras(pf,i,ar){var v,k=i;
+if(k<ar.length){if(ar[k]==ANCHOR){eval(pf+"anchor='"+escSglQuote(ar[++k])+"'");return k;}
+if(ar[k]==ANCHORX){eval(pf+'anchorx='+ar[++k]);return k;}
+if(ar[k]==ANCHORY){eval(pf+'anchory='+ar[++k]);return k;}
+if(ar[k]==NOANCHORWARN){eval(pf+'noanchorwarn=('+pf+'noanchorwarn==1)?0:1');return k;}
+if(ar[k]==ANCHORALIGN){k=opt_MULTIPLEARGS(++k,ar,(pf+'anchoralign')); return k;}}
+return-1;}
+function checkAnchorObject(){var w=o3_anchor;
+if(w){if(!(mrkObj=getAnchorObjectRef(w))){if(o3_noanchorwarn){alert('WARNING!  Reference mark "'+w+'" not found.');return false;}else w='';}}
+return true;}
+function anchorHorizontal(browserWidth,horizontalScrollAmount,widthFix){var hasAnchor=(typeof o3_anchor!='undefined'&&o3_anchor);if(!hasAnchor)return void(0);
+if(typeof o3_followscroll!='undefined'&&o3_followscroll&&o3_sticky)o3_relx=rmrkPosition[0];
+return rmrkPosition[0];}
+function anchorVertical(browserHeight,verticalScrollAmount){var hasAnchor=(typeof o3_anchor!='undefined'&&o3_anchor);if(!hasAnchor)return void(0);
+if(typeof o3_followscroll!='undefined'&&o3_followscroll&&o3_sticky)o3_rely=rmrkPosition[1];
+return rmrkPosition[1];}
+function anchorPreface(){if(!mrkObj)return;rmrkPosition=getAnchorLocation(mrkObj);}
+function getAnchorObjectRef(aObj){return getRefById(aObj,o3_frame.document)||getRefByName(aObj,o3_frame.document)}
+function getAnchorLocation(objRef){var mkObj,of,offsets,mlyr
+mkObj=mlyr=objRef
+offsets=[o3_anchorx,o3_anchory]
+if(document.layers){if(typeof mlyr.length!='undefined'&& mlyr.length>1){mkObj=mlyr[0]
+offsets[0]+=mlyr[0].x+mlyr[1].pageX
+offsets[1]+=mlyr[0].y+mlyr[1].pageY
+}else{if(mlyr.toString().indexOf('Image')!=-1||mlyr.toString().indexOf('Anchor')!=-1){offsets[0]+=mlyr.x
+offsets[1]+=mlyr.y
+}else{offsets[0]+=mlyr.pageX
+offsets[1]+=mlyr.pageY}}
+}else{offsets[0]+=pageLocation(mlyr,'Left')
+offsets[1]+=pageLocation(mlyr,'Top')}
+of=getAnchorOffsets(mkObj)
+if(typeof o3_dragimg!='undefined'&& o3_dragimg){olImgLeft=offsets[0];olImgTop=offsets[1];}
+offsets[0]+=of[0]
+offsets[1]+=of[1]
+if(typeof o3_dragimg!='undefined'&& o3_dragimg){olImgRight=offsets[0];olImgBottom=offsets[1];return;}
+return offsets;}
+function getAnchorOffsets(mkObj){var fx=fy=0, mp,puc,mkAry,sx=sy=0,w=o3_anchoralign
+var mW=mH=pW=pH=0
+var off=[0,0]
+mkAry=w.split(',');
+if(mkAry.length<3){mp=mkAry[0].toUpperCase();puc=(mkAry.length==1)?mp:mkAry[1].toUpperCase();}else if(mkAry.length==3){if(!isNaN(mkAry[0])){mp=mkAry.slice(0,2);puc=mkAry[2].toUpperCase();}else{mp=mkAry[0].toUpperCase();puc=mkAry.slice(1);}
+}else{mp=mkAry.slice(0,2);puc=mkAry.slice(2);}
+var shdwPresent=typeof o3_shadow!='undefined'&& o3_shadow
+if(shdwPresent){sx=Math.abs(o3_shadowx);sy=Math.abs(o3_shadowy);}
+pW=(shdwPresent?parseInt(o3_width):(olNs4?over.clip.width:over.offsetWidth))
+pH=(shdwPresent?parseInt(o3_aboveheight):(olNs4?over.clip.height:over.offsetHeight))
+if(olOp&& o3_wrap){pW=(shdwPresent?parseInt(o3_width):(olNs4?over.clip.width:over.offsetWidth))
+pH=(shdwPresent?parseInt(o3_aboveheight):(olNs4?over.clip.height:over.offsetHeight))}
+if(!olOp&& mkObj.toString().indexOf('Image')!=-1){mW=mkObj.width
+mH=mkObj.height
+}else if(!olOp&& mkObj.toString().indexOf('Anchor')!=-1){mp='UL'
+}else{mW=(olNs4)?mkObj.clip.width:mkObj.offsetWidth
+mH=(olNs4)?mkObj.clip.height:mkObj.offsetHeight}
+if(!isNaN(mp)||typeof mp=='object'){if(typeof mp=='object'){fx=parseFloat(mp[0]);fy=parseFloat(mp[1]);}else
+fx=fy=parseFloat(mp);off=[Math.round(fx*mW),Math.round(fy*mH)];}else{if(mp=='UR')off=[mW,0]
+else if(mp=='LL')off=[0,mH]
+else if(mp=='LR')off=[mW,mH]}
+if(typeof o3_dragimg!='undefined'&& o3_dragimg)return off;else{if(!isNaN(puc)||typeof puc=='object' ){if(typeof puc=='object'){fx=parseFloat(puc[0]);fy=parseFloat(puc[1]);}else
+fx=fy=parseFloat(puc);off[0]-=Math.round(fx*(pW-sx));off[1]-=Math.round(fy*(pH-sy));}else{if(puc=='UR'){off[0]-=(pW-sx);off[1]-=sy
+}else if(puc=='LL'){off[0]-=sx;off[1]-=(pH-sy)
+}else if(puc=='LR'){off[0]-=(pW-sx);off[1]-=(pH-sy)}}
+return off}}
+function pageLocation(o,t){var x=0
+while(o.offsetParent){x+=o['offset'+t]
+o=o.offsetParent}
+x+=o['offset'+t]
+return x}
+function getRefById(l,d){var r="",j
+d=(d||document)
+if(d.all)return d.all[l]
+else if(d.getElementById)return d.getElementById(l)
+else if(d.layers&& d.layers.length>0){if(d.layers[l])return d.layers[l]
+for(j=0;j<d.layers.length;j++){r=getRefById(l,d.layers[j].document)
+if(r)return r}}
+return false}
+function getRefByName(l,d){var r=null,j
+d=(d||document)
+if(d.images[l])return d.images[l]
+else if(d.anchors[l])return d.anchors[l];else if(d.layers&& d.layers.length>0){for(j=0;j<d.layers.length;j++){r=getRefByName(l,d.layers[j].document)
+if(r&& r.length>0)return r
+else if(r)return [r,d.layers[j]]}}
+return null}
+registerRunTimeFunction(setAnchorVariables);registerCmdLineFunction(parseAnchorExtras);registerPostParseFunction(checkAnchorObject);registerHook("createPopup",anchorPreface,FAFTER);registerHook("horizontalPlacement",anchorHorizontal,FCHAIN);registerHook("verticalPlacement",anchorVertical,FCHAIN);if(olInfo.meets(4.10))registerNoParameterCommands('noanchorwarn');
+}
diff --git a/OpenFreezer/overlib/Mini/overlib_centerpopup_mini.js b/OpenFreezer/overlib/Mini/overlib_centerpopup_mini.js
new file mode 100755
index 0000000..595385f
--- /dev/null
+++ b/OpenFreezer/overlib/Mini/overlib_centerpopup_mini.js
@@ -0,0 +1,28 @@
+//\/////
+//\  overLIB Center Popup Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.10 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2003. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+//\  THIS IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL!
+if(typeof olInfo=='undefined'||typeof olInfo.meets=='undefined'||!olInfo.meets(4.10))alert('overLIB 4.10 or later is required for the Center Popup Plugin.');else{registerCommands('centerpopup,centeroffset');
+if(typeof ol_centerpopup=='undefined')var ol_centerpopup=0;if(typeof ol_centeroffset=='undefined')var ol_centeroffset='0';
+var o3_centerpopup=0,o3_centeroffset='0';
+function setCenterPopupVariables(){o3_centerpopup=ol_centerpopup;o3_centeroffset=ol_centeroffset;}
+function parseCenterPopupExtras(pf,i,ar){var k=i,v;
+if(k<ar.length){if(ar[k]==CENTERPOPUP){eval(pf+'centerpopup=('+pf+'centerpopup==0)?1:0');return k;}
+if(ar[k]==CENTEROFFSET){k=opt_MULTIPLEARGS(++k,ar,(pf+'centeroffset'));return k;}}
+return-1;}
+function centerPopupHorizontal(browserWidth,horizontalScrollAmount,widthFix){if(!o3_centerpopup)return void(0);
+var vdisp=o3_centeroffset.split(','),placeX,iwidth=browserWidth,winoffset=horizontalScrollAmount,pWd=parseInt(o3_width);
+placeX=winoffset+Math.round((iwidth-widthFix-pWd)/2)+parseInt(vdisp[0]);if(typeof o3_followscroll!='undefined'&&o3_followscroll&&o3_sticky)o3_relx=placeX;
+return placeX;}
+function centerPopupVertical(browserHeight,verticalScrollAmount){if(!o3_centerpopup)return void(0);
+var placeY,iheight=browserHeight,scrolloffset=verticalScrollAmount,vdisp=o3_centeroffset.split(','),pHeight=(o3_aboveheight?parseInt(o3_aboveheight):(olNs4?over.clip.height:over.offsetHeight));
+placeY=scrolloffset+Math.round((iheight-pHeight)/2)+(vdisp.length>1?parseInt(vdisp[1]):0);if(typeof o3_followscroll!='undefined'&&o3_followscroll&&o3_sticky)o3_rely=placeY;
+return placeY;}
+registerRunTimeFunction(setCenterPopupVariables);registerCmdLineFunction(parseCenterPopupExtras);registerHook('horizontalPlacement',centerPopupHorizontal,FCHAIN);registerHook('verticalPlacement',centerPopupVertical,FCHAIN);if(olInfo.meets(4.10))registerNoParameterCommands('centerpopup');
+}
diff --git a/OpenFreezer/overlib/Mini/overlib_crossframe_mini.js b/OpenFreezer/overlib/Mini/overlib_crossframe_mini.js
new file mode 100755
index 0000000..b69000e
--- /dev/null
+++ b/OpenFreezer/overlib/Mini/overlib_crossframe_mini.js
@@ -0,0 +1,36 @@
+//\/////
+//\  overLIB Crossframe Support Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.05 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+//\  THIS IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL!
+if(typeof olInfo=='undefined'||typeof olInfo.meets=='undefined'||!olInfo.meets(4.10))alert('overLIB 4.10 or later is required for the Cross Frame Support Plugin.');else{registerCommands('frame');
+function parseFrameExtras(pf,i,ar){var k=i,v;
+if(k<ar.length){if(ar[k]==FRAME){v=ar[++k];if(pf=='ol_')ol_frame=v;else opt_FRAME(v);return k;}}
+return-1;}
+function opt_FRAME(frm){o3_frame=frm;over=createDivContainer('overDiv');return 0;}
+function frmDepth(thisFrame,ofrm){var retVal='';
+for(var i=0;i<thisFrame.length;i++){if(thisFrame[i].length>0){retVal=frmDepth(thisFrame[i],ofrm);if(retVal=='')continue;}else if(thisFrame[i]!=ofrm)continue;retVal='['+i+']'+retVal;break;}
+return retVal;}
+function getFrmRef(srcFrm,tgetFrm){var rtnVal=''
+if(tgetFrm!=srcFrm){var tFrm=frmDepth(top.frames,tgetFrm)
+var sFrm=frmDepth(top.frames,srcFrm)
+if(sFrm.length==tFrm.length){l=tFrm.lastIndexOf('[')
+if(l){while( sFrm.substring(0,l)!=tFrm.substring(0,l) )
+l=tFrm.lastIndexOf('[',l-1)
+tFrm=tFrm.substr(l)
+sFrm=sFrm.substr(l)}}
+var cnt=0,p='',str=tFrm
+while((k=str.lastIndexOf('['))!=-1){cnt++
+str=str.substring(0,k)}
+for(var i=0;i<cnt;i++)p=p+'parent.'
+rtnVal=p+'frames'+sFrm+'.'}
+return rtnVal}
+function chkForFrmRef(){if(o3_frame!=ol_frame)fnRef=getFrmRef(ol_frame,o3_frame)
+return true;}
+registerCmdLineFunction(parseFrameExtras);registerPostParseFunction(chkForFrmRef);
+}
diff --git a/OpenFreezer/overlib/Mini/overlib_csstyle_mini.js b/OpenFreezer/overlib/Mini/overlib_csstyle_mini.js
new file mode 100755
index 0000000..210f038
--- /dev/null
+++ b/OpenFreezer/overlib/Mini/overlib_csstyle_mini.js
@@ -0,0 +1,45 @@
+//\/////
+//\  overLIB CSS Style Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.05 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+//\  THIS IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL!
+if(typeof olInfo=='undefined'||typeof olInfo.meets=='undefined'||!olInfo.meets(4.10))alert('overLIB 4.10 or later is required for the CSS Style Plugin.');else{registerCommands('cssstyle,padunit,heightunit,widthunit,textsizeunit,textdecoration,textstyle,textweight,captionsizeunit,captiondecoration,captionstyle,captionweight,closesizeunit,closedecoration,closestyle,closeweight');
+if(typeof ol_padunit=='undefined')var ol_padunit="px";if(typeof ol_heightunit=='undefined')var ol_heightunit="px";if(typeof ol_widthunit=='undefined')var ol_widthunit="px";if(typeof ol_textsizeunit=='undefined')var ol_textsizeunit="px";if(typeof ol_textdecoration=='undefined')var ol_textdecoration="none";if(typeof ol_textstyle=='undefined')var ol_textstyle="normal";if(typeof ol_textweight=='undefined')var ol_textweight="normal";if(typeof ol_captionsizeunit=='undefined')var ol_captionsize [...]
+var o3_padunit="px",o3_heightunit="px",o3_widthunit="px",o3_textsizeunit="px",o3_textdecoration="",o3_textstyle="",o3_textweight="",o3_captionsizeunit="px",o3_captiondecoration="",o3_captionstyle="",o3_captionweight="",o3_closesizeunit="px",o3_closedecoration="",o3_closestyle="",o3_closeweight="";
+function setCSSStyleVariables(){o3_padunit=ol_padunit;o3_heightunit=ol_heightunit;o3_widthunit=ol_widthunit;o3_textsizeunit=ol_textsizeunit;o3_textdecoration=ol_textdecoration;o3_textstyle=ol_textstyle;o3_textweight=ol_textweight;o3_captionsizeunit=ol_captionsizeunit;o3_captiondecoration=ol_captiondecoration;o3_captionstyle=ol_captionstyle;o3_captionweight=ol_captionweight;o3_closesizeunit=ol_closesizeunit;o3_closedecoration=ol_closedecoration;o3_closestyle=ol_closestyle;o3_closeweight=o [...]
+function parseCSSStyleExtras(pf,i,ar){var k=i;
+if(k<ar.length){if(ar[k]==CSSSTYLE){eval(pf+'css='+ar[k]);return k;}
+if(ar[k]==PADUNIT){eval(pf+'padunit="'+ar[++k]+'"');return k;}
+if(ar[k]==HEIGHTUNIT){eval(pf+'heightunit="'+ar[++k]+'"');return k;}
+if(ar[k]==WIDTHUNIT){eval(pf+'widthunit="'+ar[++k]+'"');return k;}
+if(ar[k]==TEXTSIZEUNIT){eval(pf+'textsizeunit="'+ar[++k]+'"');return k;}
+if(ar[k]==TEXTDECORATION){eval(pf+'textdecoration="'+ar[++k]+'"');return k;}
+if(ar[k]==TEXTSTYLE){eval(pf+'textstyle="'+ar[++k]+'"');return k;}
+if(ar[k]==TEXTWEIGHT){eval(pf+'textweight="'+ar[++k]+'"');return k;}
+if(ar[k]==CAPTIONSIZEUNIT){eval(pf+'captionsizeunit="'+ar[++k]+'"');return k;}
+if(ar[k]==CAPTIONDECORATION){eval(pf+'captiondecoration="'+ar[++k]+'"');return k;}
+if(ar[k]==CAPTIONSTYLE){eval(pf+'captionstyle="'+ar[++k]+'"');return k;}
+if(ar[k]==CAPTIONWEIGHT){eval(pf+'captionweight="'+ar[++k]+'"');return k;}
+if(ar[k]==CLOSESIZEUNIT){eval(pf+'closesizeunit="'+ar[++k]+'"');return k;}
+if(ar[k]==CLOSEDECORATION){eval(pf+'closedecoration="'+ar[++k]+'"');return k;}
+if(ar[k]==CLOSESTYLE){eval(pf+'closestyle="'+ar[++k]+'"');return k;}
+if(ar[k]==CLOSEWEIGHT){eval(pf+'closeweight="'+ar[++k]+'"');return k;}}
+return-1;}
+function ol_content_simple_cssstyle(text){txt='<table width="'+o3_width+'" border="0" cellpadding="'+o3_border+'" cellspacing="0" style="background-color: '+o3_bgcolor+';height: '+o3_height+o3_heightunit+';"><tr><td><table width="100%" border="0" cellpadding="'+o3_cellpad+'" cellspacing="0" style="color: '+o3_fgcolor+';background-color: '+o3_fgcolor+';height: '+o3_height+o3_heightunit+';"><tr><td valign="TOP"><font style="font-family: '+o3_textfont+';color: '+o3_textcolor+';font-size: '+ [...]
+return txt;}
+function ol_content_caption_cssstyle(text,title,close){var nameId;closing="";closeevent="onMouseOver";
+if(o3_closeclick==1)closeevent=(o3_closetitle?"title='"+o3_closetitle+"'":"")+" onClick";
+if(o3_capicon!=""){nameId=' hspace=\"5\"'+' align=\"middle\" alt=\"\"';if(typeof o3_dragimg!='undefined'&&o3_dragimg)nameId=' hspace=\"5\"'+' name=\"'+o3_dragimg+'\" id=\"'+o3_dragimg+'\" align=\"middle\" alt=\"Drag Enabled\" title=\"Drag Enabled\"';o3_capicon='<img src=\"'+o3_capicon+'\"'+nameId+' />';}
+if(close!=""){closing='<td align="RIGHT"><a href="javascript:return '+fnRef+'cClick();" '+closeevent+'="return '+fnRef+'cClick();" style="color: '+o3_closecolor+';font-family: '+o3_closefont+';font-size: '+o3_closesize+o3_closesizeunit+';text-decoration: '+o3_closedecoration+';font-weight: '+o3_closeweight+';font-style:'+o3_closestyle+';">'+close+'</a></td>';}
+txt='<table width="'+o3_width+'" border="0" cellpadding="'+o3_border+'" cellspacing="0" style="background-color: '+o3_bgcolor+';background-image: url('+o3_bgbackground+');height: '+o3_height+o3_heightunit+';"><tr><td><table width="100%" border="0" cellpadding="0" cellspacing="0"><tr><td><font style="font-family: '+o3_captionfont+';color: '+o3_capcolor+';font-size: '+o3_captionsize+o3_captionsizeunit+';font-weight: '+o3_captionweight+';font-style: '+o3_captionstyle+';text-decoration: '+o3 [...]
+return txt;}
+function ol_content_background_cssstyle(text,picture,hasfullhtml){if(hasfullhtml){txt=text;}else{var pU,hU,wU;pU=(o3_padunit=='%'?'%':'');hU=(o3_heightunit=='%'?'%':'');wU=(o3_widthunit=='%'?'%':'');txt='<table width="'+o3_width+wu+'" border="0" cellpadding="0" cellspacing="0" height="'+o3_height+hu+'"><tr><td colspan="3" height="'+o3_padyt+pu+'"></td></tr><tr><td width="'+o3_padxl+pu+'"></td><td valign="TOP" width="'+(o3_width-o3_padxl-o3_padxr)+pu+'"><font style="font-family: '+o3_text [...]
+set_background(picture);
+return txt;}
+registerRunTimeFunction(setCSSStyleVariables);registerCmdLineFunction(parseCSSStyleExtras);registerHook("ol_content_simple",ol_content_simple_cssstyle,FALTERNATE,CSSSTYLE);registerHook("ol_content_caption",ol_content_caption_cssstyle,FALTERNATE,CSSSTYLE);registerHook("ol_content_background",ol_content_background_cssstyle,FALTERNATE,CSSSTYLE);
+}
diff --git a/OpenFreezer/overlib/Mini/overlib_debug_mini.js b/OpenFreezer/overlib/Mini/overlib_debug_mini.js
new file mode 100755
index 0000000..ec88637
--- /dev/null
+++ b/OpenFreezer/overlib/Mini/overlib_debug_mini.js
@@ -0,0 +1,49 @@
+//\/////
+//\  overLIB Debug Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.05 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2003. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+//\  THIS IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL!
+if(typeof olInfo=='undefined'||typeof olInfo.meets=='undefined'||!olInfo.meets(4.10))alert('overLIB 4.10 or later is required for the Debug Plugin.');else{var olZindex;registerCommands('allowdebug');
+function parseDebugExtras(pf,i,ar){var k=i,v;
+if(k<ar.length){if(ar[k]==ALLOWDEBUG){v=ar[k+1];if(typeof v=='string'){v=ar[++k];if(pf!='ol_')setCanShowParm(v);} return k;}}
+return-1;}
+function showProperties(){var args=showProperties.arguments,sho,shoObj,vis,lvl=0,istrt=0,theDiv='showProps',txt='';
+if(args.length==0)return;if(args.length % 2&&typeof args[0]=='string'){istrt=1;theDiv=args[0];}
+sho=createDivContainer(theDiv);
+if(olNs4){shoObj=sho;txt+='<table cellpadding="1" cellspacing="0" border="0" bgcolor="#000000"><tr><td>';}else{with(sho.style){backgroundColor='#ffffcc';padding='5px';border='1px #000000 solid';}
+shoObj=sho.style;}
+lvl=getLayerLevel(theDiv);
+if(typeof sho.position=='undefined'){sho.position=new Pagelocation(10+lvl*20,10,1);if(typeof olZindex=='undefined')olZindex=getDivZindex();shoObj.zIndex=olZindex+1+lvl;}
+txt+='<table cellpadding="5" border="0" cellspacing="0"'+(olNs4?' bgcolor="#ffffcc"':'')+'>';txt+='<tr><td><strong><A HREF="javascript:moveToBack(\''+theDiv+'\');" title="Move to back">'+theDiv+'</A></strong></td><td align="RIGHT"><strong><a href="javascript:closeLayer(\''+theDiv+'\');" TITLE="Close Layer'+(!olNs4?'" style="background-color: #CCCCCC;border:2px #333369 outset;padding: 2px;':'')+'">X</a></strong></td></tr>';txt+='<tr><td style="text-decoration: underline;"><strong>Item</st [...]
+txt+='<tr><td align="right"><strong>'+args[i]+': </strong></td><td>'+args[++i]+'</td></tr>';txt+='</table>'+(olNs4?'</td></tr></table>':'');
+if(olNs4){sho.document.open();sho.document.write(txt);sho.document.close();}else{if(olIe5&&isMac)sho.innerHTML='';sho.innerHTML=txt;}
+showAllVisibleLayers();}
+function getLayerLevel(lyr){var i=0;
+if(typeof document.popups=='undefined'){document.popups=new Array(lyr);}else{var l=document.popups;for(var i=0;i<l.length;i++)if(lyr==l[i])break;if(i==l.length)l[l.length++]=lyr;}
+return i;}
+function getDivZindex(id){var obj;
+if(id==''||id==null)id='overDiv';
+obj=layerReference(id);obj=(olNs4?obj:obj.style);
+return obj.zIndex;}
+function setCanShowParm(debugID){var lyr,pLyr;
+if(typeof debugID!='string')return;
+pLyr=debugID.split(',');for(var i=0;i<pLyr.length;i++){lyr=layerReference(pLyr[i]);if(lyr!=null&&typeof lyr.position!='undefined')lyr.position.canShow=1;}}
+function Pagelocation(x,y,canShow){this.x=x;this.y=y;this.canShow=(canShow==null)?0:canShow;}
+function showAllVisibleLayers(){var lyr,lyrObj,l=document.popups;
+for(var i=0;i<l.length;i++){lyr=layerReference(l[i]);lyrObj=(olNs4?lyr:lyr.style);if(lyr.position.canShow){positionLayer(lyrObj,lyr.position.x,lyr.position.y);lyrObj.visibility='visible';}}}
+function positionLayer(Obj,x,y){Obj.left=x+(olIe4?eval(docRoot+'.scrollLeft'):window.pageXOffset)+(olNs4?0:'px');Obj.top=y+(olIe4?eval(docRoot+'.scrollTop'):window.pageYOffset)+(olNs4?0:'px');}
+function closeLayer(lyrID){var lyr=layerReference(lyrID);
+lyr.position.canShow=0;lyr=(olNs4?lyr:lyr.style);lyr.visibility='hidden';}
+function moveToBack(layer){var l=document.popups,lyr,obj,i,x=10,y=10,dx=20,z=olZindex+1;
+if(l.length==1)return;
+lyr=layerReference(layer);lyr.position.x=x;lyr.position.y=y;obj=(olNs4?lyr:lyr.style);obj.zIndex=z;
+for(i=0;i<l.length;i++){if(layer==l[i])continue;lyr=layerReference(l[i]);if(lyr.position.canShow==0)continue;obj=(olNs4?lyr:lyr.style);obj.zIndex+=1;lyr.position.x+=dx;lyr.position.y=y;}
+showAllVisibleLayers();}
+function rawTxt(txt){if(typeof txt!='string')return;return txt.replace(/</g,"<").replace(/>/g,">").replace(/"/g,""");}
+registerCmdLineFunction(parseDebugExtras);
+}
diff --git a/OpenFreezer/overlib/Mini/overlib_exclusive_mini.js b/OpenFreezer/overlib/Mini/overlib_exclusive_mini.js
new file mode 100755
index 0000000..f51d89d
--- /dev/null
+++ b/OpenFreezer/overlib/Mini/overlib_exclusive_mini.js
@@ -0,0 +1 @@
+}
diff --git a/OpenFreezer/overlib/Mini/overlib_followscroll_mini.js b/OpenFreezer/overlib/Mini/overlib_followscroll_mini.js
new file mode 100755
index 0000000..09e7db8
--- /dev/null
+++ b/OpenFreezer/overlib/Mini/overlib_followscroll_mini.js
@@ -0,0 +1,38 @@
+//\/////
+//\  overLIB Follow Scroll Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.10 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+//\  THIS IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL!
+if(typeof olInfo=='undefined'||typeof olInfo.meets=='undefined'||!olInfo.meets(4.10))alert('overLIB 4.10 or later is required for the Follow Scroll Plugin.');else{registerCommands('followscroll,followscrollrefresh');
+if(typeof ol_followscroll=='undefined')var ol_followscroll=0;if(typeof ol_followscrollrefresh=='undefined')var ol_followscrollrefresh=100;
+var o3_followscroll=0,o3_followscrollrefresh=100;
+function setScrollVariables(){o3_followscroll=ol_followscroll;o3_followscrollrefresh=ol_followscrollrefresh;}
+function parseScrollExtras(pf,i,ar){var k=i,v;if(k<ar.length){if(ar[k]==FOLLOWSCROLL){eval(pf+'followscroll=('+pf+'followscroll==0)?1:0');return k;}
+if(ar[k]==FOLLOWSCROLLREFRESH){eval(pf+'followscrollrefresh='+ar[++k]);return k;}}
+return-1;}
+function scroll_placeLayer(){var placeX,placeY,widthFix=0;
+if(o3_frame.innerWidth){widthFix=Math.ceil(1.2*(o3_frame.outerWidth-o3_frame.innerWidth));widthFix=(widthFix>50)?20:widthFix;iwidth=o3_frame.innerWidth;}else if(eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientWidth=='number'")&&eval('o3_frame.'+docRoot+'.clientWidth'))
+iwidth=eval('o3_frame.'+docRoot+'.clientWidth');
+winoffset=(olIe4)?eval('o3_frame.'+docRoot+'.scrollLeft'):o3_frame.pageXOffset;
+placeX=runHook('horizontalPlacement',FCHAIN,iwidth,winoffset,widthFix);
+if(o3_frame.innerHeight)iheight=o3_frame.innerHeight;else if(eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientHeight=='number'")&&eval('o3_frame.'+docRoot+'.clientHeight'))
+iheight=eval('o3_frame.'+docRoot+'.clientHeight');
+scrolloffset=(olIe4)?eval('o3_frame.'+docRoot+'.scrollTop'):o3_frame.pageYOffset;
+placeY=runHook('verticalPlacement',FCHAIN,iheight,scrolloffset);
+repositionTo(over,placeX,placeY);
+if(o3_followscroll&&o3_sticky&&(o3_relx||o3_rely)&&(typeof o3_draggable=='undefined'||!o3_draggable)){if(typeof over.scroller=='undefined'||over.scroller.canScroll)over.scroller=new Scroller(placeX-winoffset,placeY-scrolloffset,o3_followscrollrefresh);}}
+function Scroller(X,Y,refresh){this.canScroll=0;this.refresh=refresh;this.x=X;this.y=Y;this.timer=setTimeout("repositionOver()",this.refresh);}
+function cancelScroll(){if(!o3_followscroll||typeof over.scroller=='undefined')return;over.scroller.canScroll=1;
+if(over.scroller.timer){clearTimeout(over.scroller.timer);over.scroller.timer=null;}}
+function getPageScrollY(){if(o3_frame.pageYOffset)return o3_frame.pageYOffset;if(eval(docRoot))return eval('o3_frame.'+docRoot+'.scrollTop');return-1;}
+function getPageScrollX(){if(o3_frame.pageXOffset)return o3_frame.pageXOffset;if(eval(docRoot))return eval('o3_frame.'+docRoot+'.scrollLeft');return-1;}
+function getLayerTop(layer){if(layer.pageY)return layer.pageY;if(layer.style.top)return parseInt(layer.style.top);return-1;}
+function getLayerLeft(layer){if(layer.pageX)return layer.pageX;if(layer.style.left)return parseInt(layer.style.left);return-1;}
+function repositionOver(){var X,Y,pgLeft,pgTop;pgTop=getPageScrollY();pgLeft=getPageScrollX();X=getLayerLeft(over)-pgLeft;Y=getLayerTop(over)-pgTop;
+if(X!=over.scroller.x||Y!=over.scroller.y)repositionTo(over,pgLeft+over.scroller.x,pgTop+over.scroller.y);over.scroller.timer=setTimeout("repositionOver()",over.scroller.refresh);}
+registerRunTimeFunction(setScrollVariables);registerCmdLineFunction(parseScrollExtras);registerHook("hideObject",cancelScroll,FAFTER);registerHook("placeLayer",scroll_placeLayer,FREPLACE);if(olInfo.meets(4.10))registerNoParameterCommands('followscroll');}
diff --git a/OpenFreezer/overlib/Mini/overlib_hideform_mini.js b/OpenFreezer/overlib/Mini/overlib_hideform_mini.js
new file mode 100755
index 0000000..4a4ffca
--- /dev/null
+++ b/OpenFreezer/overlib/Mini/overlib_hideform_mini.js
@@ -0,0 +1,33 @@
+//\/////
+//\  overLIB Hide Form Plugin
+//\
+//\  Uses an iframe shim to mask system controls for IE v5.5 or higher as suggested in
+//\  http://dotnetjunkies.com/weblog/jking/posts/488.aspx
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.05 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+//\  THIS IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL!
+if(typeof olInfo=='undefined'||typeof olInfo.meets=='undefined'||!olInfo.meets(4.10))alert('overLIB 4.10 or later is required for the HideForm Plugin.');else{
+function generatePopUp(content){if(!olIe4||olOp||!olIe55||(typeof o3_shadow!='undefined'&&o3_shadow)||(typeof o3_bubble!='undefined'&&o3_bubble))return;
+var wd,ht,txt,zIdx=0;
+wd=parseInt(o3_width);ht=over.offsetHeight;txt=backDropSource(wd,ht,zIdx++);txt+='<div style="position: absolute;top: 0;left: 0;width: '+wd+'px;z-index: '+zIdx+';">'+content+'</div>';layerWrite(txt);}
+function backDropSource(width,height,Z){return '<iframe frameborder="0" scrolling="no" src="javascript:false;" width="'+width+'" height="'+height+'" style="z-index: '+Z+';filter: Beta(Style=0,Opacity=0);"></iframe>';}
+function hideSelectBox(){if(olNs4||olOp||olIe55)return;var px,py,pw,ph,sx,sw,sy,sh,selEl,v;
+if(olIe4)v=0;else{v=navigator.userAgent.match(/Gecko\/(\d{8})/i);if(!v)return;v=parseInt(v[1]);}
+if(v<20030624){px=parseInt(over.style.left);py=parseInt(over.style.top);pw=o3_width;ph=(o3_aboveheight?parseInt(o3_aboveheight):over.offsetHeight);selEl=(olIe4)?o3_frame.document.all.tags("SELECT"):o3_frame.document.getElementsByTagName("SELECT");for(var i=0;i<selEl.length;i++){if(!olIe4&&selEl[i].size<2)continue;sx=pageLocation(selEl[i],'Left');sy=pageLocation(selEl[i],'Top');sw=selEl[i].offsetWidth;sh=selEl[i].offsetHeight;if((px+pw)<sx||px>(sx+sw)||(py+ph)<sy||py>(sy+sh))continue;selE [...]
+function showSelectBox(){if(olNs4||olOp||olIe55)return;var selEl,v;
+if(olIe4)v=0;else{v=navigator.userAgent.match(/Gecko\/(\d{8})/i);if(!v)return;v=parseInt(v[1]);}
+if(v<20030624){selEl=(olIe4)?o3_frame.document.all.tags("SELECT"):o3_frame.document.getElementsByTagName("SELECT");for(var i=0;i<selEl.length;i++){if(typeof selEl[i].isHidden!='undefined'&&selEl[i].isHidden){selEl[i].isHidden=0;selEl[i].style.visibility='visible';}}}}
+function pageLocation(o,t){var x=0
+while(o.offsetParent){x+=o['offset'+t]
+o=o.offsetParent}
+x+=o['offset'+t]
+return x}
+if(!(olNs4||olOp||olIe55||navigator.userAgent.indexOf('Netscape6')!=-1)){var MMStr=olMouseMove.toString();var strRe=/(if\s*\(o3_allowmove\s*==\s*1.*\)\s*)/;var f=MMStr.match(strRe);
+if(f){var ls=MMStr.search(strRe);ls+=f[1].length;var le=MMStr.substring(ls).search(/[;|}]\n/);MMStr=MMStr.substring(0,ls)+' {runHook("placeLayer",FREPLACE);if(olHideForm)hideSelectBox();'+MMStr.substring(ls+(le!=-1?le+3:0));document.writeln('<script type="text/javascript">\n<!--\n'+MMStr+'\n//-->\n</'+'script>');}
+f=capExtent.onmousemove.toString().match(/function[ ]+(\w*)\(/);if(f&&f[1]!='anonymous')capExtent.onmousemove=olMouseMove;}
+registerHook("createPopup",generatePopUp,FAFTER);registerHook("hideObject",showSelectBox,FAFTER);olHideForm=1;}
diff --git a/OpenFreezer/overlib/Mini/overlib_mini.js b/OpenFreezer/overlib/Mini/overlib_mini.js
new file mode 100755
index 0000000..704d123
--- /dev/null
+++ b/OpenFreezer/overlib/Mini/overlib_mini.js
@@ -0,0 +1,322 @@
+//\/////
+//\  overLIB 4.21 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\
+//\  Contributors are listed on the homepage.
+//\  This file might be old, always check for the latest version at:
+//\  http://www.bosrup.com/web/overlib/
+//\
+//\  Please read the license agreement (available through the link above)
+//\  before using overLIB. Direct any licensing questions to erik at bosrup.com.
+//\
+//\  Do not sell this as your own work or remove this copyright notice. 
+//\  For full details on copying or changing this script please read the
+//\  license agreement at the link above. Please give credit on sites that
+//\  use overLIB and submit changes of the script so other people can use
+//\  them as well.
+//\/////
+//\  THIS IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL!
+var olLoaded=0,pmStart=10000000,pmUpper=10001000,pmCount=pmStart+1,pmt='',pms=new Array(),olInfo=new Info('4.21',1),FREPLACE=0,FBEFORE=1,FAFTER=2,FALTERNATE=3,FCHAIN=4,olHideForm=0,olHautoFlag=0,olVautoFlag=0,hookPts=new Array(),postParse=new Array(),cmdLine=new Array(),runTime=new Array();
+registerCommands('donothing,inarray,caparray,sticky,background,noclose,caption,left,right,center,offsetx,offsety,fgcolor,bgcolor,textcolor,capcolor,closecolor,width,border,cellpad,status,autostatus,autostatuscap,height,closetext,snapx,snapy,fixx,fixy,relx,rely,fgbackground,bgbackground,padx,pady,fullhtml,above,below,capicon,textfont,captionfont,closefont,textsize,captionsize,closesize,timeout,function,delay,hauto,vauto,closeclick,wrap,followmouse,mouseoff,closetitle,cssoff,compatmode,css [...]
+if(typeof ol_fgcolor=='undefined')var ol_fgcolor="#CCCCFF";if(typeof ol_bgcolor=='undefined')var ol_bgcolor="#333399";if(typeof ol_textcolor=='undefined')var ol_textcolor="#000000";if(typeof ol_capcolor=='undefined')var ol_capcolor="#FFFFFF";if(typeof ol_closecolor=='undefined')var ol_closecolor="#9999FF";if(typeof ol_textfont=='undefined')var ol_textfont="Verdana,Arial,Helvetica";if(typeof ol_captionfont=='undefined')var ol_captionfont="Verdana,Arial,Helvetica";if(typeof ol_closefont==' [...]
+if(typeof ol_texts=='undefined')var ol_texts=new Array("Text 0","Text 1");if(typeof ol_caps=='undefined')var ol_caps=new Array("Caption 0","Caption 1");
+var o3_text="",o3_cap="",o3_sticky=0,o3_background="",o3_close="Close",o3_hpos=RIGHT,o3_offsetx=2,o3_offsety=2,o3_fgcolor="",o3_bgcolor="",o3_textcolor="",o3_capcolor="",o3_closecolor="",o3_width=100,o3_border=1,o3_cellpad=2,o3_status="",o3_autostatus=0,o3_height=-1,o3_snapx=0,o3_snapy=0,o3_fixx=-1,o3_fixy=-1,o3_relx=null,o3_rely=null,o3_fgbackground="",o3_bgbackground="",o3_padxl=0,o3_padxr=0,o3_padyt=0,o3_padyb=0,o3_fullhtml=0,o3_vpos=BELOW,o3_aboveheight=0,o3_capicon="",o3_textfont="V [...]
+var o3_x=0,o3_y=0,o3_showingsticky=0,o3_removecounter=0;
+var over=null,fnRef,hoveringSwitch=false,olHideDelay;
+var isMac=(navigator.userAgent.indexOf("Mac")!=-1),olOp=(navigator.userAgent.toLowerCase().indexOf('opera')>-1&&document.createTextNode),olNs4=(navigator.appName=='Netscape'&&parseInt(navigator.appVersion)==4),olNs6=(document.getElementById)?true:false,olKq=(olNs6&&/konqueror/i.test(navigator.userAgent)),olIe4=(document.all)?true:false,olIe5=false,olIe55=false,docRoot='document.body';
+if(olNs4){var oW=window.innerWidth;var oH=window.innerHeight;window.onresize=function(){if(oW!=window.innerWidth||oH!=window.innerHeight)location.reload();}}
+if(olIe4){var agent=navigator.userAgent;if(/MSIE/.test(agent)){var versNum=parseFloat(agent.match(/MSIE[ ](\d\.\d+)\.*/i)[1]);if(versNum>=5){olIe5=true;olIe55=(versNum>=5.5&&!olOp)?true:false;if(olNs6)olNs6=false;}}
+if(olNs6)olIe4=false;}
+if(document.compatMode&&document.compatMode=='CSS1Compat'){docRoot=((olIe4&&!olOp)?'document.documentElement':docRoot);}
+if(window.addEventListener)window.addEventListener("load",OLonLoad_handler,false);else if(window.attachEvent)window.attachEvent("onload",OLonLoad_handler);
+var capExtent;
+function overlib(){if(!olLoaded||isExclusive(overlib.arguments))return true;if(olCheckMouseCapture)olMouseCapture();if(over){over=(typeof over.id!='string')?o3_frame.document.all['overDiv']:over;cClick();}
+olHideDelay=0;o3_text=ol_text;o3_cap=ol_cap;o3_sticky=ol_sticky;o3_background=ol_background;o3_close=ol_close;o3_hpos=ol_hpos;o3_offsetx=ol_offsetx;o3_offsety=ol_offsety;o3_fgcolor=ol_fgcolor;o3_bgcolor=ol_bgcolor;o3_textcolor=ol_textcolor;o3_capcolor=ol_capcolor;o3_closecolor=ol_closecolor;o3_width=ol_width;o3_border=ol_border;o3_cellpad=ol_cellpad;o3_status=ol_status;o3_autostatus=ol_autostatus;o3_height=ol_height;o3_snapx=ol_snapx;o3_snapy=ol_snapy;o3_fixx=ol_fixx;o3_fixy=ol_fixy;o3_r [...]
+setRunTimeVariables();
+fnRef='';
+o3_frame=ol_frame;
+if(!(over=createDivContainer()))return false;
+parseTokens('o3_',overlib.arguments);if(!postParseChecks())return false;
+if(o3_delay==0){return runHook("olMain",FREPLACE);}else{o3_delayid=setTimeout("runHook('olMain',FREPLACE)",o3_delay);return false;}}
+function nd(time){if(olLoaded&&!isExclusive()){hideDelay(time);
+if(o3_removecounter>=1){o3_showingsticky=0 };
+if(o3_showingsticky==0){o3_allowmove=0;if(over!=null&&o3_timerid==0)runHook("hideObject",FREPLACE,over);}else{o3_removecounter++;}}
+return true;}
+function cClick(){if(olLoaded){runHook("hideObject",FREPLACE,over);o3_showingsticky=0;}
+return false;}
+function overlib_pagedefaults(){parseTokens('ol_',overlib_pagedefaults.arguments);}
+function olMain(){var layerhtml,styleType;runHook("olMain",FBEFORE);
+if(o3_background!=""||o3_fullhtml){
+layerhtml=runHook('ol_content_background',FALTERNATE,o3_css,o3_text,o3_background,o3_fullhtml);}else{
+styleType=(pms[o3_css-1-pmStart]=="cssoff"||pms[o3_css-1-pmStart]=="cssclass");
+if(o3_fgbackground!="")o3_fgbackground="background=\""+o3_fgbackground+"\"";if(o3_bgbackground!="")o3_bgbackground=(styleType?"background=\""+o3_bgbackground+"\"":o3_bgbackground);
+if(o3_fgcolor!="")o3_fgcolor=(styleType?"bgcolor=\""+o3_fgcolor+"\"":o3_fgcolor);if(o3_bgcolor!="")o3_bgcolor=(styleType?"bgcolor=\""+o3_bgcolor+"\"":o3_bgcolor);
+if(o3_height>0)o3_height=(styleType?"height=\""+o3_height+"\"":o3_height);else o3_height="";
+if(o3_cap==""){
+layerhtml=runHook('ol_content_simple',FALTERNATE,o3_css,o3_text);}else{
+if(o3_sticky){
+layerhtml=runHook('ol_content_caption',FALTERNATE,o3_css,o3_text,o3_cap,o3_close);}else{
+layerhtml=runHook('ol_content_caption',FALTERNATE,o3_css,o3_text,o3_cap,"");}}}
+if(o3_sticky){if(o3_timerid>0){clearTimeout(o3_timerid);o3_timerid=0;}
+o3_showingsticky=1;o3_removecounter=0;}
+if(!runHook("createPopup",FREPLACE,layerhtml))return false;
+if(o3_autostatus>0){o3_status=o3_text;if(o3_autostatus>1)o3_status=o3_cap;}
+o3_allowmove=0;
+if(o3_timeout>0){if(o3_timerid>0)clearTimeout(o3_timerid);o3_timerid=setTimeout("cClick()",o3_timeout);}
+runHook("disp",FREPLACE,o3_status);runHook("olMain",FAFTER);
+return(olOp&&event&&event.type=='mouseover'&&!o3_status)?'':(o3_status!='');}
+function ol_content_simple(text){var cpIsMultiple=/,/.test(o3_cellpad);var txt='<table width="'+o3_width+'" border="0" cellpadding="'+o3_border+'" cellspacing="0" '+(o3_bgclass?'class="'+o3_bgclass+'"':o3_bgcolor+' '+o3_height)+'><tr><td><table width="100%" border="0" '+((olNs4||!cpIsMultiple)?'cellpadding="'+o3_cellpad+'" ':'')+'cellspacing="0" '+(o3_fgclass?'class="'+o3_fgclass+'"':o3_fgcolor+' '+o3_fgbackground+' '+o3_height)+'><tr><td valign="TOP"'+(o3_textfontclass?' class="'+o3_tex [...]
+set_background("");return txt;}
+function ol_content_caption(text,title,close){var nameId,txt,cpIsMultiple=/,/.test(o3_cellpad);var closing,closeevent;
+closing="";closeevent="onmouseover";if(o3_closeclick==1)closeevent=(o3_closetitle?"title='"+o3_closetitle+"'":"")+" onclick";if(o3_capicon!=""){nameId=' hspace=\"5\"'+' align=\"middle\" alt=\"\"';if(typeof o3_dragimg!='undefined'&&o3_dragimg)nameId=' hspace=\"5\"'+' name=\"'+o3_dragimg+'\" id=\"'+o3_dragimg+'\" align=\"middle\" alt=\"Drag Enabled\" title=\"Drag Enabled\"';o3_capicon='<img src=\"'+o3_capicon+'\"'+nameId+' />';}
+if(close!="")
+closing='<td '+(!o3_compatmode&&o3_closefontclass?'class="'+o3_closefontclass:'align="RIGHT')+'"><a href="javascript:return '+fnRef+'cClick();"'+((o3_compatmode&&o3_closefontclass)?' class="'+o3_closefontclass+'" ':' ')+closeevent+'="return '+fnRef+'cClick();">'+(o3_closefontclass?'':wrapStr(0,o3_closesize,'close'))+close+(o3_closefontclass?'':wrapStr(1,o3_closesize,'close'))+'</a></td>';txt='<table width="'+o3_width+'" border="0" cellpadding="'+o3_border+'" cellspacing="0" '+(o3_bgclass [...]
+set_background("");return txt;}
+function ol_content_background(text,picture,hasfullhtml){if(hasfullhtml){txt=text;}else{txt='<table width="'+o3_width+'" border="0" cellpadding="0" cellspacing="0" height="'+o3_height+'"><tr><td colspan="3" height="'+o3_padyt+'"></td></tr><tr><td width="'+o3_padxl+'"></td><td valign="TOP" width="'+(o3_width-o3_padxl-o3_padxr)+(o3_textfontclass?'" class="'+o3_textfontclass:'')+'">'+(o3_textfontclass?'':wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass?'':wrapStr(1,o3_textsize))+'</td> [...]
+set_background(picture);return txt;}
+function set_background(pic){if(pic==""){if(olNs4){over.background.src=null;}else if(over.style){over.style.backgroundImage="none";}
+}else{if(olNs4){over.background.src=pic;}else if(over.style){over.style.width=o3_width+'px';over.style.backgroundImage="url("+pic+")";}}}
+var olShowId=-1;
+function disp(statustext){runHook("disp",FBEFORE);
+if(o3_allowmove==0){runHook("placeLayer",FREPLACE);(olNs6&&olShowId<0)?olShowId=setTimeout("runHook('showObject',FREPLACE,over)",1):runHook("showObject",FREPLACE,over);o3_allowmove=(o3_sticky||o3_followmouse==0)?0:1;}
+runHook("disp",FAFTER);
+if(statustext!="")self.status=statustext;}
+function createPopup(lyrContent){runHook("createPopup",FBEFORE);
+if(o3_wrap){var wd,ww,theObj=(olNs4?over:over.style);theObj.top=theObj.left=((olIe4&&!olOp)?0:-10000)+(!olNs4?'px':0);layerWrite(lyrContent);wd=(olNs4?over.clip.width:over.offsetWidth);if(wd>(ww=windowWidth())){lyrContent=lyrContent.replace(/\ /g,' ');o3_width=ww;o3_wrap=0;}}
+layerWrite(lyrContent);
+if(o3_wrap)o3_width=(olNs4?over.clip.width:over.offsetWidth);
+runHook("createPopup",FAFTER,lyrContent);
+return true;}
+function placeLayer(){var placeX,placeY,widthFix=0;
+if(o3_frame.innerWidth)widthFix=18;iwidth=windowWidth();
+winoffset=(olIe4)?eval('o3_frame.'+docRoot+'.scrollLeft'):o3_frame.pageXOffset;
+placeX=runHook('horizontalPlacement',FCHAIN,iwidth,winoffset,widthFix);
+if(o3_frame.innerHeight){iheight=o3_frame.innerHeight;}else if(eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientHeight=='number'")&&eval('o3_frame.'+docRoot+'.clientHeight')){iheight=eval('o3_frame.'+docRoot+'.clientHeight');}
+scrolloffset=(olIe4)?eval('o3_frame.'+docRoot+'.scrollTop'):o3_frame.pageYOffset;placeY=runHook('verticalPlacement',FCHAIN,iheight,scrolloffset);
+repositionTo(over,placeX,placeY);}
+function olMouseMove(e){var e=(e)?e:event;
+if(e.pageX){o3_x=e.pageX;o3_y=e.pageY;}else if(e.clientX){o3_x=eval('e.clientX+o3_frame.'+docRoot+'.scrollLeft');o3_y=eval('e.clientY+o3_frame.'+docRoot+'.scrollTop');}
+if(o3_allowmove==1)runHook("placeLayer",FREPLACE);
+if(hoveringSwitch&&!olNs4&&runHook("cursorOff",FREPLACE)){(olHideDelay?hideDelay(olHideDelay):cClick());hoveringSwitch=!hoveringSwitch;}}
+function no_overlib(){return ver3fix;}
+function olMouseCapture(){capExtent=document;var fN,str='',l,k,f,wMv,sS,mseHandler=olMouseMove;var re=/function[ ]*(\w*)\(/;
+wMv=(!olIe4&&window.onmousemove);if(document.onmousemove||wMv){if(wMv)capExtent=window;f=capExtent.onmousemove.toString();fN=f.match(re);if(fN==null){str=f+'(e);';}else if(fN[1]=='anonymous'||fN[1]=='olMouseMove'||(wMv&&fN[1]=='onmousemove')){if(!olOp&&wMv){l=f.indexOf('{')+1;k=f.lastIndexOf('}');sS=f.substring(l,k);if((l=sS.indexOf('('))!=-1){sS=sS.substring(0,l).replace(/^\s+/,'').replace(/\s+$/,'');if(eval("typeof "+sS+"=='undefined'"))window.onmousemove=null;else str=sS+'(e);';}}
+if(!str){olCheckMouseCapture=false;return;}
+}else{if(fN[1])str=fN[1]+'(e);';else{l=f.indexOf('{')+1;k=f.lastIndexOf('}');str=f.substring(l,k)+'\n';}}
+str+='olMouseMove(e);';mseHandler=new Function('e',str);}
+capExtent.onmousemove=mseHandler;if(olNs4)capExtent.captureEvents(Event.MOUSEMOVE);}
+function parseTokens(pf,ar){
+var v,i,mode=-1,par=(pf!='ol_'),fnMark=(par&&!ar.length?1:0);
+for(i=0;i<ar.length;i++){if(mode<0){
+if(typeof ar[i]=='number'&&ar[i]>pmStart&&ar[i]<pmUpper){fnMark=(par?1:0);i--;}else{switch(pf){case 'ol_':
+ol_text=ar[i].toString();break;default:
+o3_text=ar[i].toString();}}
+mode=0;}else{
+if(ar[i]>=pmCount||ar[i]==DONOTHING){continue;}
+if(ar[i]==INARRAY){fnMark=0;eval(pf+'text=ol_texts['+ar[++i]+'].toString()');continue;}
+if(ar[i]==CAPARRAY){eval(pf+'cap=ol_caps['+ar[++i]+'].toString()');continue;}
+if(ar[i]==STICKY){if(pf!='ol_')eval(pf+'sticky=1');continue;}
+if(ar[i]==BACKGROUND){eval(pf+'background="'+ar[++i]+'"');continue;}
+if(ar[i]==NOCLOSE){if(pf!='ol_')opt_NOCLOSE();continue;}
+if(ar[i]==CAPTION){eval(pf+"cap='"+escSglQuote(ar[++i])+"'");continue;}
+if(ar[i]==CENTER||ar[i]==LEFT||ar[i]==RIGHT){eval(pf+'hpos='+ar[i]);if(pf!='ol_')olHautoFlag=1;continue;}
+if(ar[i]==OFFSETX){eval(pf+'offsetx='+ar[++i]);continue;}
+if(ar[i]==OFFSETY){eval(pf+'offsety='+ar[++i]);continue;}
+if(ar[i]==FGCOLOR){eval(pf+'fgcolor="'+ar[++i]+'"');continue;}
+if(ar[i]==BGCOLOR){eval(pf+'bgcolor="'+ar[++i]+'"');continue;}
+if(ar[i]==TEXTCOLOR){eval(pf+'textcolor="'+ar[++i]+'"');continue;}
+if(ar[i]==CAPCOLOR){eval(pf+'capcolor="'+ar[++i]+'"');continue;}
+if(ar[i]==CLOSECOLOR){eval(pf+'closecolor="'+ar[++i]+'"');continue;}
+if(ar[i]==WIDTH){eval(pf+'width='+ar[++i]);continue;}
+if(ar[i]==BORDER){eval(pf+'border='+ar[++i]);continue;}
+if(ar[i]==CELLPAD){i=opt_MULTIPLEARGS(++i,ar,(pf+'cellpad'));continue;}
+if(ar[i]==STATUS){eval(pf+"status='"+escSglQuote(ar[++i])+"'");continue;}
+if(ar[i]==AUTOSTATUS){eval(pf+'autostatus=('+pf+'autostatus==1)?0:1');continue;}
+if(ar[i]==AUTOSTATUSCAP){eval(pf+'autostatus=('+pf+'autostatus==2)?0:2');continue;}
+if(ar[i]==HEIGHT){eval(pf+'height='+pf+'aboveheight='+ar[++i]);continue;}
+if(ar[i]==CLOSETEXT){eval(pf+"close='"+escSglQuote(ar[++i])+"'");continue;}
+if(ar[i]==SNAPX){eval(pf+'snapx='+ar[++i]);continue;}
+if(ar[i]==SNAPY){eval(pf+'snapy='+ar[++i]);continue;}
+if(ar[i]==FIXX){eval(pf+'fixx='+ar[++i]);continue;}
+if(ar[i]==FIXY){eval(pf+'fixy='+ar[++i]);continue;}
+if(ar[i]==RELX){eval(pf+'relx='+ar[++i]);continue;}
+if(ar[i]==RELY){eval(pf+'rely='+ar[++i]);continue;}
+if(ar[i]==FGBACKGROUND){eval(pf+'fgbackground="'+ar[++i]+'"');continue;}
+if(ar[i]==BGBACKGROUND){eval(pf+'bgbackground="'+ar[++i]+'"');continue;}
+if(ar[i]==PADX){eval(pf+'padxl='+ar[++i]);eval(pf+'padxr='+ar[++i]);continue;}
+if(ar[i]==PADY){eval(pf+'padyt='+ar[++i]);eval(pf+'padyb='+ar[++i]);continue;}
+if(ar[i]==FULLHTML){if(pf!='ol_')eval(pf+'fullhtml=1');continue;}
+if(ar[i]==BELOW||ar[i]==ABOVE){eval(pf+'vpos='+ar[i]);if(pf!='ol_')olVautoFlag=1;continue;}
+if(ar[i]==CAPICON){eval(pf+'capicon="'+ar[++i]+'"');continue;}
+if(ar[i]==TEXTFONT){eval(pf+"textfont='"+escSglQuote(ar[++i])+"'");continue;}
+if(ar[i]==CAPTIONFONT){eval(pf+"captionfont='"+escSglQuote(ar[++i])+"'");continue;}
+if(ar[i]==CLOSEFONT){eval(pf+"closefont='"+escSglQuote(ar[++i])+"'");continue;}
+if(ar[i]==TEXTSIZE){eval(pf+'textsize="'+ar[++i]+'"');continue;}
+if(ar[i]==CAPTIONSIZE){eval(pf+'captionsize="'+ar[++i]+'"');continue;}
+if(ar[i]==CLOSESIZE){eval(pf+'closesize="'+ar[++i]+'"');continue;}
+if(ar[i]==TIMEOUT){eval(pf+'timeout='+ar[++i]);continue;}
+if(ar[i]==FUNCTION){if(pf=='ol_'){if(typeof ar[i+1]!='number'){v=ar[++i];ol_function=(typeof v=='function'?v:null);}}else{fnMark=0;v=null;if(typeof ar[i+1]!='number')v=ar[++i]; opt_FUNCTION(v);} continue;}
+if(ar[i]==DELAY){eval(pf+'delay='+ar[++i]);continue;}
+if(ar[i]==HAUTO){eval(pf+'hauto=('+pf+'hauto==0)?1:0');continue;}
+if(ar[i]==VAUTO){eval(pf+'vauto=('+pf+'vauto==0)?1:0');continue;}
+if(ar[i]==CLOSECLICK){eval(pf+'closeclick=('+pf+'closeclick==0)?1:0');continue;}
+if(ar[i]==WRAP){eval(pf+'wrap=('+pf+'wrap==0)?1:0');continue;}
+if(ar[i]==FOLLOWMOUSE){eval(pf+'followmouse=('+pf+'followmouse==1)?0:1');continue;}
+if(ar[i]==MOUSEOFF){eval(pf+'mouseoff=('+pf+'mouseoff==0)?1:0');v=ar[i+1];if(pf!='ol_'&&eval(pf+'mouseoff')&&typeof v=='number'&&(v<pmStart||v>pmUpper))olHideDelay=ar[++i];continue;}
+if(ar[i]==CLOSETITLE){eval(pf+"closetitle='"+escSglQuote(ar[++i])+"'");continue;}
+if(ar[i]==CSSOFF||ar[i]==CSSCLASS){eval(pf+'css='+ar[i]);continue;}
+if(ar[i]==COMPATMODE){eval(pf+'compatmode=('+pf+'compatmode==0)?1:0');continue;}
+if(ar[i]==FGCLASS){eval(pf+'fgclass="'+ar[++i]+'"');continue;}
+if(ar[i]==BGCLASS){eval(pf+'bgclass="'+ar[++i]+'"');continue;}
+if(ar[i]==TEXTFONTCLASS){eval(pf+'textfontclass="'+ar[++i]+'"');continue;}
+if(ar[i]==CAPTIONFONTCLASS){eval(pf+'captionfontclass="'+ar[++i]+'"');continue;}
+if(ar[i]==CLOSEFONTCLASS){eval(pf+'closefontclass="'+ar[++i]+'"');continue;}
+i=parseCmdLine(pf,i,ar);}}
+if(fnMark&&o3_function)o3_text=o3_function();
+if((pf=='o3_')&&o3_wrap){o3_width=0;
+var tReg=/<.*\n*>/ig;if(!tReg.test(o3_text))o3_text=o3_text.replace(/[ ]+/g,' ');if(!tReg.test(o3_cap))o3_cap=o3_cap.replace(/[ ]+/g,' ');}
+if((pf=='o3_')&&o3_sticky){if(!o3_close&&(o3_frame!=ol_frame))o3_close=ol_close;if(o3_mouseoff&&(o3_frame==ol_frame))opt_NOCLOSE(' ');}}
+function layerWrite(txt){txt+="\n";if(olNs4){var lyr=o3_frame.document.layers['overDiv'].document
+lyr.write(txt)
+lyr.close()
+}else if(typeof over.innerHTML!='undefined'){if(olIe5&&isMac)over.innerHTML='';over.innerHTML=txt;}else{range=o3_frame.document.createRange();range.setStartAfter(over);domfrag=range.createContextualFragment(txt);
+while(over.hasChildNodes()){over.removeChild(over.lastChild);}
+over.appendChild(domfrag);}}
+function showObject(obj){runHook("showObject",FBEFORE);
+var theObj=(olNs4?obj:obj.style);theObj.visibility='visible';
+runHook("showObject",FAFTER);}
+function hideObject(obj){runHook("hideObject",FBEFORE);
+var theObj=(olNs4?obj:obj.style);if(olNs6&&olShowId>0){clearTimeout(olShowId);olShowId=0;}
+theObj.visibility='hidden';theObj.top=theObj.left=((olIe4&&!olOp)?0:-10000)+(!olNs4?'px':0);
+if(o3_timerid>0)clearTimeout(o3_timerid);if(o3_delayid>0)clearTimeout(o3_delayid);
+o3_timerid=0;o3_delayid=0;self.status="";
+if(obj.onmouseout||obj.onmouseover){if(olNs4)obj.releaseEvents(Event.MOUSEOUT||Event.MOUSEOVER);obj.onmouseout=obj.onmouseover=null;}
+runHook("hideObject",FAFTER);}
+function repositionTo(obj,xL,yL){var theObj=(olNs4?obj:obj.style);theObj.left=xL+(!olNs4?'px':0);theObj.top=yL+(!olNs4?'px':0);}
+function cursorOff(){var left=parseInt(over.style.left);var top=parseInt(over.style.top);var right=left+(over.offsetWidth>=parseInt(o3_width)?over.offsetWidth:parseInt(o3_width));var bottom=top+(over.offsetHeight>=o3_aboveheight?over.offsetHeight:o3_aboveheight);
+if(o3_x<left||o3_x>right||o3_y<top||o3_y>bottom)return true;
+return false;}
+function opt_FUNCTION(callme){o3_text=(callme?(typeof callme=='string'?(/.+\(.*\)/.test(callme)?eval(callme):callme):callme()):(o3_function?o3_function():'No Function'));
+return 0;}
+function opt_NOCLOSE(unused){if(!unused)o3_close="";
+if(olNs4){over.captureEvents(Event.MOUSEOUT||Event.MOUSEOVER);over.onmouseover=function(){if(o3_timerid>0){clearTimeout(o3_timerid);o3_timerid=0;} }
+over.onmouseout=function(e){if(olHideDelay)hideDelay(olHideDelay);else cClick(e);}
+}else{over.onmouseover=function(){hoveringSwitch=true;if(o3_timerid>0){clearTimeout(o3_timerid);o3_timerid=0;} }}
+return 0;}
+function opt_MULTIPLEARGS(i,args,parameter){var k=i,re,pV,str='';
+for(k=i;k<args.length;k++){if(typeof args[k]=='number'&&args[k]>pmStart)break;str+=args[k]+',';}
+if(str)str=str.substring(0,--str.length);
+k--;pV=(olNs4&&/cellpad/i.test(parameter))?str.split(',')[0]:str;eval(parameter+'="'+pV+'"');
+return k;}
+function nbspCleanup(){if(o3_wrap){o3_text=o3_text.replace(/\ /g,' ');o3_cap=o3_cap.replace(/\ /g,' ');}}
+function escSglQuote(str){return str.toString().replace(/'/g,"\\'");}
+function OLonLoad_handler(e){var re=/\w+\(.*\)[;\s]+/g,olre=/overlib\(|nd\(|cClick\(/,fn,l,i;
+if(!olLoaded)olLoaded=1;
+if(window.removeEventListener&&e.eventPhase==3)window.removeEventListener("load",OLonLoad_handler,false);else if(window.detachEvent){window.detachEvent("onload",OLonLoad_handler);var fN=document.body.getAttribute('onload');if(fN){fN=fN.toString().match(re);if(fN&&fN.length){for(i=0;i<fN.length;i++){if(/anonymous/.test(fN[i]))continue;while((l=fN[i].search(/\)[;\s]+/))!=-1){fn=fN[i].substring(0,l+1);fN[i]=fN[i].substring(l+2);if(olre.test(fn))eval(fn);}}}}}}
+function wrapStr(endWrap,fontSizeStr,whichString){var fontStr,fontColor,isClose=((whichString=='close')?1:0),hasDims=/[%\-a-z]+$/.test(fontSizeStr);fontSizeStr=(olNs4)?(!hasDims?fontSizeStr:'1'):fontSizeStr;if(endWrap)return(hasDims&&!olNs4)?(isClose?'</span>':'</div>'):'</font>';else{fontStr='o3_'+whichString+'font';fontColor='o3_'+((whichString=='caption')? 'cap':whichString)+'color';return(hasDims&&!olNs4)?(isClose?'<span style="font-family: '+quoteMultiNameFonts(eval(fontStr))+';colo [...]
+function quoteMultiNameFonts(theFont){var v,pM=theFont.split(',');for(var i=0;i<pM.length;i++){v=pM[i];v=v.replace(/^\s+/,'').replace(/\s+$/,'');if(/\s/.test(v)&&!/['"]/.test(v)){v="\'"+v+"\'";pM[i]=v;}}
+return pM.join();}
+function isExclusive(args){return false;}
+function setCellPadStr(parameter){var Str='',j=0,ary=new Array(),top,bottom,left,right;
+Str+='padding: ';ary=parameter.replace(/\s+/g,'').split(',');
+switch(ary.length){case 2:
+top=bottom=ary[j];left=right=ary[++j];break;case 3:
+top=ary[j];left=right=ary[++j];bottom=ary[++j];break;case 4:
+top=ary[j];right=ary[++j];bottom=ary[++j];left=ary[++j];break;}
+Str+=((ary.length==1)?ary[0]+'px;':top+'px '+right+'px '+bottom+'px '+left+'px;');
+return Str;}
+function hideDelay(time){if(time&&!o3_delay){if(o3_timerid>0)clearTimeout(o3_timerid);
+o3_timerid=setTimeout("cClick()",(o3_timeout=time));}}
+function horizontalPlacement(browserWidth,horizontalScrollAmount,widthFix){var placeX,iwidth=browserWidth,winoffset=horizontalScrollAmount;var parsedWidth=parseInt(o3_width);
+if(o3_fixx>-1||o3_relx!=null){
+placeX=(o3_relx!=null?( o3_relx<0?winoffset+o3_relx+iwidth-parsedWidth-widthFix:winoffset+o3_relx):o3_fixx);}else{
+if(o3_hauto==1){if((o3_x-winoffset)>(iwidth/2)){o3_hpos=LEFT;}else{o3_hpos=RIGHT;}}
+if(o3_hpos==CENTER){placeX=o3_x+o3_offsetx-(parsedWidth/2);
+if(placeX<winoffset)placeX=winoffset;}
+if(o3_hpos==RIGHT){placeX=o3_x+o3_offsetx;
+if((placeX+parsedWidth)>(winoffset+iwidth-widthFix)){placeX=iwidth+winoffset-parsedWidth-widthFix;if(placeX<0)placeX=0;}}
+if(o3_hpos==LEFT){placeX=o3_x-o3_offsetx-parsedWidth;if(placeX<winoffset)placeX=winoffset;}
+if(o3_snapx>1){var snapping=placeX % o3_snapx;
+if(o3_hpos==LEFT){placeX=placeX-(o3_snapx+snapping);}else{
+placeX=placeX+(o3_snapx-snapping);}
+if(placeX<winoffset)placeX=winoffset;}}
+return placeX;}
+function verticalPlacement(browserHeight,verticalScrollAmount){var placeY,iheight=browserHeight,scrolloffset=verticalScrollAmount;var parsedHeight=(o3_aboveheight?parseInt(o3_aboveheight):(olNs4?over.clip.height:over.offsetHeight));
+if(o3_fixy>-1||o3_rely!=null){
+placeY=(o3_rely!=null?(o3_rely<0?scrolloffset+o3_rely+iheight-parsedHeight:scrolloffset+o3_rely):o3_fixy);}else{
+if(o3_vauto==1){if((o3_y-scrolloffset)>(iheight/2)&&o3_vpos==BELOW&&(o3_y+parsedHeight+o3_offsety-(scrolloffset+iheight)>0)){o3_vpos=ABOVE;}else if(o3_vpos==ABOVE&&(o3_y-(parsedHeight+o3_offsety)-scrolloffset<0)){o3_vpos=BELOW;}}
+if(o3_vpos==ABOVE){if(o3_aboveheight==0)o3_aboveheight=parsedHeight;
+placeY=o3_y-(o3_aboveheight+o3_offsety);if(placeY<scrolloffset)placeY=scrolloffset;}else{
+placeY=o3_y+o3_offsety;}
+if(o3_snapy>1){var snapping=placeY % o3_snapy;
+if(o3_aboveheight>0&&o3_vpos==ABOVE){placeY=placeY-(o3_snapy+snapping);}else{placeY=placeY+(o3_snapy-snapping);}
+if(placeY<scrolloffset)placeY=scrolloffset;}}
+return placeY;}
+function checkPositionFlags(){if(olHautoFlag)olHautoFlag=o3_hauto=0;if(olVautoFlag)olVautoFlag=o3_vauto=0;return true;}
+function windowWidth(){var w;if(o3_frame.innerWidth)w=o3_frame.innerWidth;else if(eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientWidth=='number'")&&eval('o3_frame.'+docRoot+'.clientWidth'))
+w=eval('o3_frame.'+docRoot+'.clientWidth');return w;}
+function createDivContainer(id,frm,zValue){id=(id||'overDiv'),frm=(frm||o3_frame),zValue=(zValue||1000);var objRef,divContainer=layerReference(id);
+if(divContainer==null){if(olNs4){divContainer=frm.document.layers[id]=new Layer(window.innerWidth,frm);objRef=divContainer;}else{var body=(olIe4?frm.document.all.tags('BODY')[0]:frm.document.getElementsByTagName("BODY")[0]);if(olIe4&&!document.getElementById){body.insertAdjacentHTML("beforeEnd",'<div id="'+id+'"></div>');divContainer=layerReference(id);}else{divContainer=frm.document.createElement("DIV");divContainer.id=id;body.appendChild(divContainer);}
+objRef=divContainer.style;}
+objRef.position='absolute';objRef.visibility='hidden';objRef.zIndex=zValue;if(olIe4&&!olOp)objRef.left=objRef.top='0px';else objRef.left=objRef.top=-10000+(!olNs4?'px':0);}
+return divContainer;}
+function layerReference(id){return(olNs4?o3_frame.document.layers[id]:(document.all?o3_frame.document.all[id]:o3_frame.document.getElementById(id)));}
+function isFunction(fnRef){var rtn=true;
+if(typeof fnRef=='object'){for(var i=0;i<fnRef.length;i++){if(typeof fnRef[i]=='function')continue;rtn=false;break;}
+}else if(typeof fnRef!='function'){rtn=false;}
+return rtn;}
+function argToString(array,strtInd,argName){var jS=strtInd,aS='',ar=array;argName=(argName?argName:'ar');
+if(ar.length>jS){for(var k=jS;k<ar.length;k++)aS+=argName+'['+k+'], ';aS=aS.substring(0,aS.length-2);}
+return aS;}
+function reOrder(hookPt,fnRef,order){var newPt=new Array(),match,i,j;
+if(!order||typeof order=='undefined'||typeof order=='number')return hookPt;
+if(typeof order=='function'){if(typeof fnRef=='object'){newPt=newPt.concat(fnRef);}else{newPt[newPt.length++]=fnRef;}
+for(i=0;i<hookPt.length;i++){match=false;if(typeof fnRef=='function'&&hookPt[i]==fnRef){continue;}else{for(j=0;j<fnRef.length;j++)if(hookPt[i]==fnRef[j]){match=true;break;}}
+if(!match)newPt[newPt.length++]=hookPt[i];}
+newPt[newPt.length++]=order;
+}else if(typeof order=='object'){if(typeof fnRef=='object'){newPt=newPt.concat(fnRef);}else{newPt[newPt.length++]=fnRef;}
+for(j=0;j<hookPt.length;j++){match=false;if(typeof fnRef=='function'&&hookPt[j]==fnRef){continue;}else{for(i=0;i<fnRef.length;i++)if(hookPt[j]==fnRef[i]){match=true;break;}}
+if(!match)newPt[newPt.length++]=hookPt[j];}
+for(i=0;i<newPt.length;i++)hookPt[i]=newPt[i];newPt.length=0;
+for(j=0;j<hookPt.length;j++){match=false;for(i=0;i<order.length;i++){if(hookPt[j]==order[i]){match=true;break;}}
+if(!match)newPt[newPt.length++]=hookPt[j];}
+newPt=newPt.concat(order);}
+hookPt=newPt;
+return hookPt;}
+function setRunTimeVariables(){if(typeof runTime!='undefined'&&runTime.length){for(var k=0;k<runTime.length;k++){runTime[k]();}}}
+function parseCmdLine(pf,i,args){if(typeof cmdLine!='undefined'&&cmdLine.length){for(var k=0;k<cmdLine.length;k++){var j=cmdLine[k](pf,i,args);if(j >-1){i=j;break;}}}
+return i;}
+function postParseChecks(pf,args){if(typeof postParse!='undefined'&&postParse.length){for(var k=0;k<postParse.length;k++){if(postParse[k](pf,args))continue;return false;}}
+return true;}
+function registerCommands(cmdStr){if(typeof cmdStr!='string')return;
+var pM=cmdStr.split(',');pms=pms.concat(pM);
+for(var i=0;i< pM.length;i++){eval(pM[i].toUpperCase()+'='+pmCount++);}}
+function registerNoParameterCommands(cmdStr){if(!cmdStr&&typeof cmdStr!='string')return;pmt=(!pmt)?cmdStr:pmt+','+cmdStr;}
+function registerHook(fnHookTo,fnRef,hookType,optPm){var hookPt,last=typeof optPm;
+if(fnHookTo=='plgIn'||fnHookTo=='postParse')return;if(typeof hookPts[fnHookTo]=='undefined')hookPts[fnHookTo]=new FunctionReference();
+hookPt=hookPts[fnHookTo];
+if(hookType!=null){if(hookType==FREPLACE){hookPt.ovload=fnRef;if(fnHookTo.indexOf('ol_content_')>-1)hookPt.alt[pms[CSSOFF-1-pmStart]]=fnRef;
+}else if(hookType==FBEFORE||hookType==FAFTER){var hookPt=(hookType==1?hookPt.before:hookPt.after);
+if(typeof fnRef=='object'){hookPt=hookPt.concat(fnRef);}else{hookPt[hookPt.length++]=fnRef;}
+if(optPm)hookPt=reOrder(hookPt,fnRef,optPm);
+}else if(hookType==FALTERNATE){if(last=='number')hookPt.alt[pms[optPm-1-pmStart]]=fnRef;}else if(hookType==FCHAIN){hookPt=hookPt.chain;if(typeof fnRef=='object')hookPt=hookPt.concat(fnRef);else hookPt[hookPt.length++]=fnRef;}
+return;}}
+function registerRunTimeFunction(fn){if(isFunction(fn)){if(typeof fn=='object'){runTime=runTime.concat(fn);}else{runTime[runTime.length++]=fn;}}}
+function registerCmdLineFunction(fn){if(isFunction(fn)){if(typeof fn=='object'){cmdLine=cmdLine.concat(fn);}else{cmdLine[cmdLine.length++]=fn;}}}
+function registerPostParseFunction(fn){if(isFunction(fn)){if(typeof fn=='object'){postParse=postParse.concat(fn);}else{postParse[postParse.length++]=fn;}}}
+function runHook(fnHookTo,hookType){var l=hookPts[fnHookTo],k,rtnVal=null,optPm,arS,ar=runHook.arguments;
+if(hookType==FREPLACE){arS=argToString(ar,2);
+if(typeof l=='undefined'||!(l=l.ovload))rtnVal=eval(fnHookTo+'('+arS+')');else rtnVal=eval('l('+arS+')');
+}else if(hookType==FBEFORE||hookType==FAFTER){if(typeof l!='undefined'){l=(hookType==1?l.before:l.after);
+if(l.length){arS=argToString(ar,2);for(var k=0;k<l.length;k++)eval('l[k]('+arS+')');}}
+}else if(hookType==FALTERNATE){optPm=ar[2];arS=argToString(ar,3);
+if(typeof l=='undefined'||(l=l.alt[pms[optPm-1-pmStart]])=='undefined'){rtnVal=eval(fnHookTo+'('+arS+')');}else{rtnVal=eval('l('+arS+')');}
+}else if(hookType==FCHAIN){arS=argToString(ar,2);l=l.chain;
+for(k=l.length;k>0;k--)if((rtnVal=eval('l[k-1]('+arS+')'))!=void(0))break;}
+return rtnVal;}
+function FunctionReference(){this.ovload=null;this.before=new Array();this.after=new Array();this.alt=new Array();this.chain=new Array();}
+function Info(version,prerelease){this.version=version;this.prerelease=prerelease;
+this.simpleversion=Math.round(this.version*100);this.major=parseInt(this.simpleversion/100);this.minor=parseInt(this.simpleversion/10)-this.major * 10;this.revision=parseInt(this.simpleversion)-this.major * 100-this.minor * 10;this.meets=meets;}
+function meets(reqdVersion){return(!reqdVersion)?false:this.simpleversion>=Math.round(100*parseFloat(reqdVersion));}
+registerHook("ol_content_simple",ol_content_simple,FALTERNATE,CSSOFF);registerHook("ol_content_caption",ol_content_caption,FALTERNATE,CSSOFF);registerHook("ol_content_background",ol_content_background,FALTERNATE,CSSOFF);registerHook("ol_content_simple",ol_content_simple,FALTERNATE,CSSCLASS);registerHook("ol_content_caption",ol_content_caption,FALTERNATE,CSSCLASS);registerHook("ol_content_background",ol_content_background,FALTERNATE,CSSCLASS);registerPostParseFunction(checkPositionFlags); [...]
+var olCheckMouseCapture=true;if((olNs4||olNs6||olIe4)){olMouseCapture();}else{overlib=no_overlib;nd=no_overlib;ver3fix=true;}
diff --git a/OpenFreezer/overlib/Mini/overlib_setonoff_mini.js b/OpenFreezer/overlib/Mini/overlib_setonoff_mini.js
new file mode 100755
index 0000000..95659e8
--- /dev/null
+++ b/OpenFreezer/overlib/Mini/overlib_setonoff_mini.js
@@ -0,0 +1,32 @@
+//\/////
+//\  overLIB Set On/Off Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.10 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2003. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+//\  THIS IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL!
+if(typeof olInfo=='undefined'||typeof olInfo.meets=='undefined'||!olInfo.meets(4.10))alert('overLIB 4.10 or later is required for the Set On/Off Plugin.');else{registerCommands('seton,setoff');var olSetType;
+function setOnOffVariables(){olSetType=0;}
+function parseOnOffExtras(pf,i,ar){var k=i,v;
+if(k<ar.length){if(ar[k]==SETON||ar[k]==SETOFF){olSetType=1;k=opt_MULTICOMMANDS(++k,ar);return k;}}
+return-1;}
+function hasCommand(istrt,args,COMMAND){for(var i=istrt;i<args.length;i++){if(typeof args[i]=='number'&& args[i]==COMMAND)return i;}
+return-1;}
+function scanCommandSet(pf,args){var k=-1,j,je;
+if(olSetType){
+while((k=hasCommand(++k,args,SETON))<args.length&&k>-1){je=opt_MULTICOMMANDS(k+1,args);for(j=k+1;j<(k+je);j++)setNoParamCommand(1,pf,args[j]);k+=(je-1);}
+k=-1;while((k=hasCommand(++k,args,SETOFF))<args.length&&k>-1){je=opt_MULTICOMMANDS(k+1,args);for(j=k+1;j<(k+je);j++)setNoParamCommand(0,pf,args[j]);k+=(je-1);}}
+return true;}
+var olRe;
+function setNoParamCommand(whichType,pf,COMMAND){var v=pms[COMMAND-1-pmStart];
+if(pmt&&!olRe)olRe=eval('/'+pmt.split(',').join('|')+'/');if(pf!='ol_'&& /capturefirst/.test(v))return;if(pf!='ol_'&& /wrap/.test(v)&& eval(pf+'wrap')&&(whichType==0)){nbspCleanup();o3_width=ol_width;}
+if(olRe.test(v))eval(pf+v+'='+((whichType&&COMMAND==AUTOSTATUSCAP)?whichType++:whichType));}
+function opt_MULTICOMMANDS(i,ar){var k=i;
+while(k<ar.length&& typeof ar[k]=='number'&& ar[k]>pmStart){k++;if(ar[k-1]=='SETON'||ar[k-1]=='SETOFF')break;}
+k-=(k<ar.length?2:1);
+return k;}
+registerRunTimeFunction(setOnOffVariables);registerCmdLineFunction(parseOnOffExtras);registerPostParseFunction(scanCommandSet);
+}
diff --git a/OpenFreezer/overlib/Mini/overlib_shadow_mini.js b/OpenFreezer/overlib/Mini/overlib_shadow_mini.js
new file mode 100755
index 0000000..43ac9e6
--- /dev/null
+++ b/OpenFreezer/overlib/Mini/overlib_shadow_mini.js
@@ -0,0 +1,53 @@
+//\/////
+//\  overLIB Shadow Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.05 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2003. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//\/////
+//\  THIS IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL!
+if(typeof olInfo=='undefined'||typeof olInfo.meets=='undefined'||!olInfo.meets(4.10))alert('overLIB 4.10 or later is required for the Shadow Plugin.');else{registerCommands('shadow,shadowcolor,shadowimage,shadowopacity,shadowx,shadowy');
+if(typeof ol_shadowadjust=='undefined')var ol_shadowadjust=2;if(typeof ol_shadow=='undefined')var ol_shadow=0;if(typeof ol_shadowcolor=='undefined')var ol_shadowcolor='#CCCCCC';if(typeof ol_shadowimage=='undefined')var  ol_shadowimage='';if(typeof ol_shadowopacity=='undefined')var  ol_shadowopacity=0;if(typeof ol_shadowx=='undefined')var ol_shadowx=5;if(typeof ol_shadowy=='undefined')var ol_shadowy=5;
+var o3_shadow=0,o3_shadowcolor="#cccccc",o3_shadowimage='',o3_shadowopacity=0,o3_shadowx=5,o3_shadowy=5,bkSet=0;
+function setShadowVariables(){o3_shadow=ol_shadow;o3_shadowcolor=ol_shadowcolor;o3_shadowimage=ol_shadowimage;o3_shadowopacity=ol_shadowopacity;o3_shadowx=ol_shadowx;o3_shadowy=ol_shadowy;}
+function parseShadowExtras(pf,i,ar){var k=i,v;
+if(k<ar.length){if(ar[k]==SHADOW){eval(pf+'shadow=('+pf+'shadow==0)?1:0');return k;}
+if(ar[k]==SHADOWCOLOR){eval(pf+'shadowcolor="'+ar[++k]+'"');return k;}
+if(ar[k]==SHADOWOPACITY){v=ar[++k];eval(pf+'shadowopacity='+(olOp?0:v));return k;}
+if(ar[k]==SHADOWIMAGE){eval(pf+'shadowimage="'+ar[++k]+'"');return k;}
+if(ar[k]==SHADOWX){eval(pf+'shadowx='+ar[++k]);return k;}
+if(ar[k]==SHADOWY){eval(pf+'shadowy='+ar[++k]);return k;}}
+return-1;}
+function shadow_cursorOff(){var left=parseInt(over.style.left);var top=parseInt(over.style.top);var right=left+(o3_shadow?o3_width:over.offsetWidth);var bottom=top+(o3_shadow?o3_aboveheight:over.offsetHeight);
+if(o3_x<left||o3_x>right||o3_y<top||o3_y>bottom)return true;return false;}
+function checkShadowPreHide(){if(o3_shadow&&o3_shadowopacity)cleanUpShadowEffects();if(o3_shadow&&(olIe4&&isMac) )over.style.pixelWidth=over.style.pixelHeight=0;}
+function generateShadow(content){var wd,ht,X=0,Y=0,zIdx=0,txt,dpObj,puObj,bS='',aPos,posStr=new Array();
+if(!o3_shadow||(o3_shadowx==0&&o3_shadowy==0))return;
+X=Math.abs(o3_shadowx);Y=Math.abs(o3_shadowy);wd=parseInt(o3_width);ht=(olNs4)?over.clip.height:over.offsetHeight;
+if(o3_shadowx==0){if(o3_shadowy<0){posStr[0]=' left:0;top: 0';posStr[1]=' left:0;top: '+Y+'px';}else if(o3_shadowy>0){posStr[0]=' left:0;top: '+Y+'px';posStr[1]=' left:0;top:0';}
+}else if(o3_shadowy==0){if(o3_shadowx<0){posStr[0]=' left:0;top: 0';posStr[1]=' left: '+X+'px';}else if(o3_shadowx>0){posStr[0]=' left: '+X+'px;top: 0';posStr[1]=' left:0;top:0';}
+}else if(o3_shadowx>0){if(o3_shadowy>0){posStr[0]=' left:'+X+'px;top:'+Y+'px';posStr[1]=' left:0;top:0';}else if(o3_shadowy<0){posStr[0]=' left:'+X+'px;top:0';posStr[1]=' left:0;top: '+Y+'px';}
+}else if(o3_shadowx<0){if(o3_shadowy>0){posStr[0]=' left:0;top:'+Y+'px';posStr[1]=' left:'+X+'px;top:0';}else if(o3_shadowy<0){posStr[0]=' left:0;top:0';posStr[1]=' left:'+X+'px;top:'+Y+'px';}}
+txt=(olNs4)?'<div id="backdrop"></div>':((olIe55&&olHideForm)?backDropSource(wd+X,ht+Y,zIdx++):'')+'<div id="backdrop" style="position: absolute;'+posStr[0]+';width: '+wd+'px;height: '+ht+'px;z-index: '+(zIdx++)+';';
+if(o3_shadowimage){bS='background-image: url('+o3_shadowimage+');';if(olNs4)bkSet=1;}else{bS='background-color: '+o3_shadowcolor+';';if(olNs4)bkSet=2;}
+if(olNs4){txt+='<div id="PUContent">'+content+'</div>';}else{txt+=bS+'"></div><div id="PUContent" style="position: absolute;'+posStr[1]+';width: '+wd+'px;z-index: '+(zIdx++)+';">'+content+'</div>';}
+layerWrite(txt);
+if(olNs4&&bkSet){dpObj=over.document.layers['backdrop'];if(typeof dpObj=='undefined')return;
+puObj=over.document.layers['PUContent'];wd=puObj.clip.width;ht=puObj.clip.height;aPos=posStr[0].split(';');
+dpObj.clip.width=wd;dpObj.clip.height=ht;dpObj.left=parseInt(aPos[0].split(':')[1]);dpObj.top=parseInt(aPos[1].split(':')[1]);
+dpObj.bgColor=(bkSet==1)?null:o3_shadowcolor;dpObj.background.src=(bkSet==2)?null:o3_shadowimage;dpObj.zIndex=0;
+aPos=posStr[1].split(';');puObj.left=parseInt(aPos[0].split(':')[1]);puObj.top=parseInt(aPos[1].split(':')[1]);puObj.zIndex=1;
+}else{puObj=(olIe4?o3_frame.document.all['PUContent']:o3_frame.document.getElementById('PUContent'));dpObj=(olIe4?o3_frame.document.all['backdrop']:o3_frame.document.getElementById('backdrop'));ht=puObj.offsetHeight;dpObj.style.height=ht+'px';
+if(o3_shadowopacity){var op=o3_shadowopacity;op=(op<=100?op:100);
+setBrowserOpacity(op,dpObj);}}
+o3_width=wd+X;o3_aboveheight=ht+Y;}
+function cleanUpShadowEffects(){if(olNs4||olOp)return;var dpObj=(olIe4?o3_frame.document.all['backdrop']:o3_frame.document.getElementById('backdrop'));cleanUpBrowserOpacity(dpObj);}
+function setBrowserOpacity(op,lyr){if(olNs4||!op)return;lyr=(lyr)?lyr:over;if(olIe4&&typeof lyr.filters!='undefined'){lyr.style.filter='Alpha(Opacity='+op+')';lyr.filters.alpha.enabled=true;}else{var sOp=(typeof(lyr.style.MozOpacity)!='undefined')?'MozOpacity':(typeof(lyr.style.KhtmlOpacity)!='undefined'?'KhtmlOpacity':(typeof(lyr.style.opacity)!='undefined'?'opacity':''));if(sOp)eval('lyr.style.'+sOp+'=op/100');}}
+function cleanUpBrowserOpacity(lyr){if(olNs4)return;lyr=(lyr)?lyr:over;if(olIe4&&(typeof lyr.filters!='undefined'&&lyr.filters.alpha.enabled)){lyr.style.filter='Alpha(Opacity=100)';lyr.filters.alpha.enabled=false;}else{var sOp=(typeof(lyr.style.MozOpacity)!='undefined')?'MozOpacity':(typeof(lyr.style.KhtmlOpacity)!='undefined'?'KhtmlOpacity':(typeof(lyr.style.opacity)!='undefined'?'opacity':''));if(sOp)eval('lyr.style.'+sOp+'=1.0');}}
+function shadowAdjust(){if(!olNs4)return;var fac=ol_shadowadjust;if(olNs4){document.write('<style type="text/css">\n<!--\n');document.write('#backdrop,#PUContent {position: absolute;left: '+fac*o3_shadowx+'px;top: '+fac*o3_shadowy+'px;}\n');document.write('-->\n<'+'\/style>');}}
+var before=(typeof rmrkPreface!='undefined'?rmrkPreface:null);
+registerRunTimeFunction(setShadowVariables);registerCmdLineFunction(parseShadowExtras);registerHook("cursorOff",shadow_cursorOff,FREPLACE);registerHook("hideObject",checkShadowPreHide,FBEFORE);registerHook("createPopup",generateShadow,FAFTER,before);if(olInfo.meets(4.10))registerNoParameterCommands('shadow');
+if(olNs4)shadowAdjust();
+}
diff --git a/OpenFreezer/overlib/ajaxcontentmws.js b/OpenFreezer/overlib/ajaxcontentmws.js
new file mode 100755
index 0000000..9177049
--- /dev/null
+++ b/OpenFreezer/overlib/ajaxcontentmws.js
@@ -0,0 +1,185 @@
+/*
+ ajaxcontentmws.js - Foteos Macrides (author and Copyright holder)
+    Initial: June 22, 2006 - Last Revised: March 24, 2008
+ Wrapper function set for getting and using the responseText and / or
+ responseXML from a GET or POST XMLHttpRequest, which can be used to
+ generate dynamic content for overlib or overlib2 calls, or to modify
+ the content of a displayed STICKY popup dynamically.
+
+ For GET Use:
+       onmouseover="return OLgetAJAX(url, command, delay, css);"
+       onmouseout="OLclearAJAX();"  (if delay > 0)
+ or:
+       onclick="OLgetAJAX(url, command, 0, css); return false;"
+ or:
+       onload="OLgetAJAX(url, command, 0, css);
+ 
+ Where:
+       url (required)
+ is a quoted string, or unquoted string variable name or array entry, with
+ the full, relative, or partial URL for a file or a server-side script (php,
+ asp, or cgi, e.g. perl), and may have a query string appended (e.g.,
+ 'http://my.domain.com/scripts/myScript.php?foo=bar&life=grand').
+ And:
+       command (required)
+ is the function reference (unquoted name without parens) of a function to
+ be called when the server's response has been received (it could instead be
+ an inline function, i.e., defined within the 2nd argument, or a quoted string
+ for a function with parens and any args)
+ And:
+       delay (may be omitted unless css is included)
+ is an unquoted number indicating the number of millisecs to wait before
+ initiating an XMLHttpRequest GET request. It should be 0 when using onclick
+ or onload, but may be a modest value such as 300 for onmouseover to avoid
+ any chatter of requests. When used with onmouseover, include:
+       onmouseout="OLclearAJAX();"
+ to clear the request if the user does not hover for at least that long.  If
+ the popup is not STICKY, include an nd or nd2 call, e.g.,
+       onmouseout="OLclearAJAX(); nd();"
+ And:
+       css (may be omitted)
+ is a quoted string with the CSS class (e.g. 'ovfl510' for
+ .ovfl510 {width:510px; height:145px; overflow:auto; ...} ) for a div to
+ encase the responseText and set the width, height and scrollbars in the
+ main text area of the popup, or the unquoted number 0 if no encasing div
+ is to be used.
+
+ For POST substitute OLpostAJAX(url, qry, command, delay, css);
+ Where
+       qry (required)
+ is the string to be posted, typically a query string (without a lead ?)
+ and the other arguments are as above.
+
+ See http://www.macridesweb.com/oltest/AJAX.html for more information.
+*/
+
+// Initialize our global variables for this function set.
+var OLhttp=false,OLcommandAJAX=null,OLdelayidAJAX=0,OLclassAJAX='',
+OLresponseAJAX='',OLabortAJAX=0,OLdebugAJAX=0;
+
+// Create a series of wrapper functions (e.g. OLcmdT#() for  ones which
+// use OLhttp.responseText via the OLresponseAJAX global, and OLcmdX#()
+// for ones which use OLhttp.responseXML) whose reference (unquoted name
+// without parens) is the 2nd argument in OLgetAJAX(url,command,delay,css)
+// calls.  This one is for the first example in the AJAX.html support
+// document, to use the OLresponseAJAX global as the lead argument for an
+// overlib popup. Put your functions in the head, or in another imported
+// .js file, so that they will not be affected by updates of this .js file.
+//
+function OLcmdExT1() {
+ return overlib(OLresponseAJAX, TEXTPADDING,0, CAPTIONPADDING,4,
+  CAPTION,'Example with AJAX content via <span '
+  +'class="yellow">responseText</span>.  Popup scrolls with the window.',
+  WRAP, BORDER,2, STICKY, CLOSECLICK, SCROLL,
+  MIDX,0, RELY,100,
+  STATUS,'Example with AJAX content via responseText of XMLHttpResponse');
+}
+
+// Alert for old browsers which lack XMLHttpRequest support. 
+function OLsorryAJAX() {
+ alert('Sorry, AJAX is not supported by your browser.');
+ return false;
+}
+
+// Check 2nd arg for function
+function OLchkFuncAJAX(ar){
+ var t=typeof ar;return (((t=='function'))||((t=='string')&&(/.+\(.*\)/.test(ar))));
+}
+
+// Alert for bad 2nd argument
+function OLnotFuncAJAX(m) {
+  if(over)cClick();
+  alert('The 2nd arg of OL'+m+'AJAX is not a function reference, nor an inline function, '
+  +'nor a quoted string with a function indicated.');
+  return OLclearAJAX();
+}
+
+// Alert for indicating an XMLHttpRequest network error.
+function OLerrorAJAX() {
+ if(OLhttp.status&&OLhttp.status!=2147746065)alert('Network error '+OLhttp.status+'. Try again later.');
+ return false;
+}
+
+// Returns a new XMLHttpRequest object, or false for older browsers
+// which did not yet support it.  Called as OLhttp=OLnewXMLHttp() via
+// the OLgetAJAX(url,command,delay,css) wrapper function.
+//
+function OLnewXMLHttp() {
+ var f=false,req=f;
+ if(window.XMLHttpRequest)eval(new Array('try{',
+ 'req=new XMLHttpRequest();','}catch(e){','req=f;','}').join('\n'));
+ /*@cc_on @if(@_jscript_version>=5)if(!req)
+ eval(new Array('try{','req=new ActiveXObject("Msxml2.XMLHTTP");',
+ '}catch(e){','try{','req=new ActiveXObject("Microsoft.XMLHTTP");',
+ '}catch(e){','req=f;','}}').join('\n')); @end @*/
+ return req;
+}
+
+// Handle the OLhttp.responseText string from the XMLHttpRequest object.
+function OLdoAJAX() {
+ if(OLhttp.readyState==4){
+  if(OLdebugAJAX)alert(
+    'OLhttp.status = '+OLhttp.status+'\n'
+   +'OLhttp.statusText = '+OLhttp.statusText+'\n'
+   +'OLhttp.getAllResponseHeaders() = \n'
+   +OLhttp.getAllResponseHeaders()+'\n'
+   +'OLhttp.getResponseHeader("Content-Type") = '
+   +OLhttp.getResponseHeader("Content-Type")+'\n');
+  if(OLhttp.status==200||(OLhttp.status==0&&!OLabortAJAX&&!OLie55)){
+   OLresponseAJAX=OLclassAJAX?'<div class="'+OLclassAJAX+'">':'';
+   OLresponseAJAX += OLhttp.responseText;
+   OLresponseAJAX += OLclassAJAX?'</div>':'';
+   if(OLdebugAJAX)alert('OLresponseAJAX = \n'+OLresponseAJAX);
+   OLclassAJAX=0;
+   return (typeof OLcommandAJAX=='string')?eval(OLcommandAJAX):OLcommandAJAX();
+  }else{
+   OLclassAJAX=0;
+   OLabortAJAX=0;
+   return OLerrorAJAX();
+  }
+ }
+}
+
+// Actually make the request initiated via OLgetAJAX or OLpostAJAX, or
+// invoke a "permission denied" alert if a cross-domain URL was used.
+function OLsetAJAX(url,qry) {
+ if(window.location.protocol.indexOf('http')==0&&
+ (url.indexOf('file:')==0||url.indexOf('ftp:')==0)){
+ alert('[object Error]\n(Cross-domain access not permitted)');return false;}
+ qry=(qry||null);var s='',m=(qry)?'POST':'GET';OLabortAJAX=0;
+ OLdelayidAJAX=0;eval(new Array('try{','OLhttp.open(m,url,true);',
+ '}catch(e){','s=e','OLhttp=false;','}').join('\n'));if(!OLhttp){
+ alert(s+'\n(Cross-domain access not permitted)');return false;}if(qry)
+ OLhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
+ OLhttp.onreadystatechange=OLdoAJAX;
+ OLhttp.send(qry);
+}
+
+// Clear or abort any delayed OLsetAJAX call or pending request. 
+function OLclearAJAX() {
+ if(OLdelayidAJAX){clearTimeout(OLdelayidAJAX);OLdelayidAJAX=0;}
+ if(OLhttp&&!OLdebugAJAX){OLabortAJAX=1;OLhttp.abort();}
+ return false;
+}
+
+// Load a new XMLHttpRequest object into the OLhttp global, load the
+// OLcommandAJAX and OLclassAJAX globals, and initiate a GET request
+// via OLsetAJAX(url) to populate OLhttp.
+function OLgetAJAX(url,command,delay,css) {
+ if(!OLchkFuncAJAX(command))return OLnotFuncAJAX('get');
+ OLclearAJAX();OLhttp=OLnewXMLHttp();if(!OLhttp)return OLsorryAJAX();
+ OLcommandAJAX=command;delay=(delay||0);css=(css||0);OLclassAJAX=css;
+ if(delay)OLdelayidAJAX=setTimeout("OLsetAJAX('"+url+"')",delay);
+ else OLsetAJAX(url);
+}
+
+// Load a new XMLHttpRequest object into the OLhttp global, load the
+// OLcommandAJAX and OLclassAJAX globals, and initiate a POST request
+// via OLsetAJAX(url,qry) to populate OLhttp.
+function OLpostAJAX(url,qry,command,delay,css) {
+ if(!OLchkFuncAJAX(command))return OLnotFuncAJAX('post');
+ OLclearAJAX();OLhttp=OLnewXMLHttp();if(!OLhttp)return OLsorryAJAX();
+ qry=(qry||0);OLcommandAJAX=command;delay=(delay||0);css=(css||0);OLclassAJAX=css;
+ if(delay)OLdelayidAJAX=setTimeout("OLsetAJAX('"+url+"','"+qry+"')",delay);
+ else OLsetAJAX(url,qry);
+}
diff --git a/OpenFreezer/overlib/arrow.gif b/OpenFreezer/overlib/arrow.gif
new file mode 100755
index 0000000..71b08c1
Binary files /dev/null and b/OpenFreezer/overlib/arrow.gif differ
diff --git a/OpenFreezer/overlib/calendarmws.js b/OpenFreezer/overlib/calendarmws.js
new file mode 100755
index 0000000..0bb30d9
--- /dev/null
+++ b/OpenFreezer/overlib/calendarmws.js
@@ -0,0 +1,624 @@
+/*
+ calendarmws.js - Script for generating calender popups and selecting dates for form
+  submissions.  See http://www.macridesweb.com/oltest/calendarmws.html for a demonstration.
+  Initial: November 9, 2003 - Last Revised: June 11, 2008
+
+****
+ Original:  Kedar R. Bhave (softricks at hotmail.com)
+ Web Site:  http://www.softricks.com
+ (uses window popups)
+
+ Modifications and customizations to work with the overLIB v3.50
+ Author:   James B. O'Connor (joconnor at nordenterprises.com)
+ Web Site: http://www.nordenterprises.com
+ Developed for use with http://home-owners-assoc.com
+ Note: while overlib works fine with Netscape 4, this function does not work very
+    well, since portions of the "over" div end up under other fields on the form and
+    cannot be seen.  If you want to use this with NS4,  you'll need to change the
+    positioning in the overlib() call to make sure the "over" div gets positioned
+    away from all other form fields
+ The O'Connor script and many more are available free online at:
+    The JavaScript Source!! http://javascript.internet.com
+
+ Further modifications made by Foteos Macrides (http://www.macridesweb.com/oltest/)
+    and Bill McCormick (wpmccormick at freeshell.org) for overlibmws
+*/
+
+var ggPosX = -1;
+var ggPosY = -1;
+var ggInactive = 0;
+var ggOnChange = null;
+var ggUseOverlib2 = 0;
+
+var ggWinContent = "";
+
+var weekend = [0,6];
+var weekendColor = "#e0e0e0";
+var fontface = "Verdana";
+var fontsize = 8; // in "pt" units; used with "font-size" style element
+
+var gNow = new Date();
+
+Calendar.Months = ["January", "February", "March", "April", "May", "June",
+"July", "August", "September", "October", "November", "December"];
+
+// Non-Leap year Month days..
+Calendar.DOMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+// Leap year Month days..
+Calendar.lDOMonth = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+
+function Calendar(p_item, p_month, p_year, p_format) {
+	if ((p_month == null) && (p_year == null)) return;
+
+	if (p_month == null) {
+		this.gMonthName = null;
+		this.gMonth = null;
+		this.gYearly = true;
+	} else {
+		this.gMonthName = Calendar.get_month(p_month);
+		this.gMonth = new Number(p_month);
+		this.gYearly = false;
+	}
+
+	this.gYear = p_year;
+	this.gFormat = p_format;
+	this.gBGColor = "white";
+	this.gFGColor = "black";
+	this.gTextColor = "black";
+	this.gHeaderColor = "black";
+	this.gReturnItem = p_item;
+}
+
+Calendar.get_month = Calendar_get_month;
+Calendar.get_daysofmonth = Calendar_get_daysofmonth;
+Calendar.calc_month_year = Calendar_calc_month_year;
+
+function Calendar_get_month(monthNo) {
+	return Calendar.Months[monthNo];
+}
+
+function Calendar_get_daysofmonth(monthNo, p_year) {
+	/* 
+	Check for leap year ..
+	1.Years evenly divisible by four are normally leap years, except for... 
+	2.Years also evenly divisible by 100 are not leap years, except for... 
+	3.Years also evenly divisible by 400 are leap years. 
+	*/
+	if ((p_year % 4) == 0) {
+		if ((p_year % 100) == 0 && (p_year % 400) != 0)
+			return Calendar.DOMonth[monthNo];
+	
+		return Calendar.lDOMonth[monthNo];
+	} else
+		return Calendar.DOMonth[monthNo];
+}
+
+function Calendar_calc_month_year(p_Month, p_Year, incr) {
+	/* 
+	Will return an 1-D array with 1st element being the calculated month 
+	and second being the calculated year 
+	after applying the month increment/decrement as specified by 'incr' parameter.
+	'incr' will normally have 1/-1 to navigate thru the months.
+	*/
+	var ret_arr = new Array();
+	
+	if (incr == -1) {
+		// B A C K W A R D
+		if (p_Month == 0) {
+			ret_arr[0] = 11;
+			ret_arr[1] = parseInt(p_Year) - 1;
+		} else {
+			ret_arr[0] = parseInt(p_Month) - 1;
+			ret_arr[1] = parseInt(p_Year);
+		}
+	} else if (incr == 1) {
+		// F O R W A R D
+		if (p_Month == 11) {
+			ret_arr[0] = 0;
+			ret_arr[1] = parseInt(p_Year) + 1;
+		} else {
+			ret_arr[0] = parseInt(p_Month) + 1;
+			ret_arr[1] = parseInt(p_Year);
+		}
+	}
+	return ret_arr;
+}
+
+function Calendar_calc_month_year(p_Month, p_Year, incr) {
+	/* 
+	Will return an 1-D array with 1st element being the calculated month 
+	and second being the calculated year 
+	after applying the month increment/decrement as specified by 'incr' parameter.
+	'incr' will normally have 1/-1 to navigate thru the months.
+	*/
+	var ret_arr = new Array();
+	
+	if (incr == -1) {
+		// B A C K W A R D
+		if (p_Month == 0) {
+			ret_arr[0] = 11;
+			ret_arr[1] = parseInt(p_Year) - 1;
+		} else {
+			ret_arr[0] = parseInt(p_Month) - 1;
+			ret_arr[1] = parseInt(p_Year);
+		}
+	} else if (incr == 1) {
+		// F O R W A R D
+		if (p_Month == 11) {
+			ret_arr[0] = 0;
+			ret_arr[1] = parseInt(p_Year) + 1;
+		} else {
+			ret_arr[0] = parseInt(p_Month) + 1;
+			ret_arr[1] = parseInt(p_Year);
+		}
+	}
+	return ret_arr;
+}
+
+// This is for compatibility with Navigator 3, we have to create and discard one object
+// before the prototype object exists.
+new Calendar();
+
+Calendar.prototype.getMonthlyCalendarCode = function() {
+	var vCode = "";
+	var vHeader_Code = "";
+	var vData_Code = "";
+	
+	// Begin Table Drawing code here..
+	vCode += ('<div align="center"><table border="1" bgcolor="' + this.gBGColor +
+	 "\" style='font-size:" + fontsize + "pt;'>");
+
+	vHeader_Code = this.cal_header();
+	vData_Code = this.cal_data();
+	vCode += (vHeader_Code + vData_Code);
+
+	vCode += '</table></div>';
+
+	return vCode;
+}
+
+Calendar.prototype.show = function() {
+	var vCode = "";
+
+	var vDate = new Date();
+	vDate.setMonth(this.gMonth);
+	vDate.setFullYear(this.gYear);
+	var vNowMonth = gNow.getMonth();
+	var vNowYear = gNow.getFullYear();
+	var yOK=!ggInactive||vNowYear<vDate.getFullYear()?1:0;
+	var mOK=!ggInactive||(yOK||
+        (vNowYear<=vDate.getFullYear()&&vNowMonth<vDate.getMonth()))?1:0;
+
+	// build content into global var ggWinContent
+	ggWinContent += ('<div style="font-family:\'' + fontface + '\';font-weight:bold;'
+		+'font-size:' + fontsize + 'pt;text-align:center;">');
+	ggWinContent += (this.gMonthName + ' ' + this.gYear);
+	ggWinContent += '</div>';
+	
+	// Show navigation buttons
+	var prevMMYYYY = Calendar.calc_month_year(this.gMonth, this.gYear, -1);
+	var prevMM = prevMMYYYY[0];
+	var prevYYYY = prevMMYYYY[1];
+
+	var nextMMYYYY = Calendar.calc_month_year(this.gMonth, this.gYear, 1);
+	var nextMM = nextMMYYYY[0];
+	var nextYYYY = nextMMYYYY[1];
+	
+	ggWinContent += ('<table width="100%" border="1" cellspacing="0" cellpadding="0" '
+		+'bgcolor="#e0e0e0" style="font-size:' + fontsize
+		+'pt;"><tr><td align="center">');
+	ggWinContent += ('['
+		+(yOK?'<a href="javascript:void(0);" '
+		+'title="Go back one year" '
+		+'onmouseover="window.status=\'Go back one year\'; return true;" '
+		+'onmouseout="window.status=\'\'; return true;" '
+		+'onclick="Build(\'' + this.gReturnItem + '\', \'' + this.gMonth + '\', \''
+		+(parseInt(this.gYear)-1) + '\', \'' + this.gFormat + '\');"'
+		+'>':'')
+		+'<<Year'
+		+(yOK?'</a>':'')
+		+']</td><td align="center">');
+	ggWinContent += ('['
+		+(mOK?'<a href="javascript:void(0);" '
+		+'title="Go back one month" '
+		+'onmouseover="window.status=\'Go back one month\'; return true;" '
+		+'onmouseout="window.status=\'\'; return true;" '
+		+'onclick="Build(\'' + this.gReturnItem + '\', \'' + prevMM + '\', \''
+		+prevYYYY + '\', \'' + this.gFormat + '\');"'
+		+'>':'')
+		+'<Mon'
+		+(mOK?'</a>':'')
+		+']</td><td align="center">');
+	ggWinContent += '       </td><td align="center">';
+	ggWinContent += ('[<a href="javascript:void(0);" '
+		+'title="Go forward one month" '
+		+'onmouseover="window.status=\'Go forward one month\'; return true;" '
+		+'onmouseput="window.status=\'\'; return true;" '
+		+'onclick="Build(\'' + this.gReturnItem + '\', \'' + nextMM + '\', \''
+		+nextYYYY + '\', \'' + this.gFormat + '\');"'
+		+'>Mon></a>]</td><td align="center">');
+	ggWinContent += ('[<a href="javascript:void(0);" '
+		+'title="Go forward one year" '
+		+'onmouseover="window.status=\'Go forward one year\'; return true;" '
+		+'onmouseout="window.status=\'\'; return true;" '
+		+'onClick="Build(\'' + this.gReturnItem + '\', \'' + this.gMonth + '\', \''
+		+(parseInt(this.gYear)+1) + '\', \'' + this.gFormat + '\');"'
+		+'>Year>></a>]</td></tr></table><div style="font-size:3px;">'
+		+' </div>');
+
+	// Get the complete calendar code for the month, and add it to the content var
+	vCode = this.getMonthlyCalendarCode();
+	ggWinContent += vCode;
+}
+
+Calendar.prototype.showY = function() {
+	var vCode = "";
+	var i;
+
+	ggWinContent += ('<div style="font-family:\'' + fontface + '\';font-weight:bold;'
+		+'font-size:' + (fontsize+1) +'pt;text-align:center;">' + this.gYear +'</div>');
+
+	var vDate = new Date();
+	vDate.setDate(1);
+	vDate.setFullYear(this.gYear);
+	var vNowYear = gNow.getFullYear();
+	var yOK=!ggInactive||vNowYear<vDate.getFullYear()?1:0;
+
+	// Show navigation buttons
+	var prevYYYY = parseInt(this.gYear) - 1;
+	var nextYYYY = parseInt(this.gYear) + 1;
+	
+	ggWinContent += ('<table width="100%" border="1" cellspacing="0" cellpadding="0" '
+		+'bgcolor="#e0e0e0" style="font-size:' + fontsize + 'pt;"><tr><td '
+		+'align="center">');
+	ggWinContent += ('['
+		+(yOK?'<a href="javascript:void(0);" '
+		+'title="Go back one year" '
+		+'onmouseover="window.status=\'Go back one year\'; return true;" '
+		+'onmouseout="window.status=\'\'; return true;" '
+		+'onclick="Build(\'' + this.gReturnItem + '\', null, \'' + prevYYYY + '\', \''
+		+this.gFormat + '\');">':'')
+		+'<<Year'
+		+(yOK?'<a>':'')
+		+']</td><td align="center">');
+	ggWinContent += '       </td><td align="center">';
+	ggWinContent += ('[<a href="javascript:void(0);" '
+		+'title="Go forward one year" '
+		+'onmouseover="window.status=\'Go forward one year\'; return true;" '
+		+'onmouseout="window.status=\'\'; return true;" '
+		+'onclick="Build(\'' + this.gReturnItem + '\', null, \'' + nextYYYY + '\', \''
+		+this.gFormat + '\');">Year>></a>]</td></tr></table>');
+
+	// Get the complete calendar code for each month.
+	// start a table and first row in the table
+	ggWinContent += ('<table width="100%" border="0" cellspacing="0" cellpadding="2" '
+		+'style="font-size:' + fontsize + 'pt;"><tr>');
+	for (i=0; i<12; i++) {
+		// start the table cell
+		ggWinContent += '<td align="center" valign="top">';
+		this.gMonth = i;
+		this.gMonthName = Calendar.get_month(this.gMonth);
+		vCode = this.getMonthlyCalendarCode();
+		ggWinContent += (this.gMonthName + '/' + this.gYear + '<div '
+			+'style="font-size:2px;"> </div>');
+		ggWinContent += vCode;
+		ggWinContent += '</td>';
+		if (i == 3 || i == 7) ggWinContent += '</tr><tr>';
+	}
+	ggWinContent += '</tr></table>';
+}
+
+Calendar.prototype.cal_header = function() {
+	var vCode = '<tr>';
+	vCode += ('<td width="14%" style="font-family:' + fontface + ';color:'
+		+this.gHeaderColor + ';font-weight:bold;">Sun</td>');
+	vCode += ('<td width="14%" style="font-family:' + fontface + ';color:'
+		+this.gHeaderColor + ';font-weight:bold;">Mon</td>');
+	vCode += ('<td width="14%" style="font-family:' + fontface + ';color:'
+		+this.gHeaderColor + ';font-weight:bold;">Tue</td>');
+	vCode += ('<td width="14%" style="font-family:' + fontface + ';color:'
+		+this.gHeaderColor + ';font-weight:bold;">Wed</td>');
+	vCode += ('<td width="14%" style="font-family:' + fontface + ';color:'
+		+this.gHeaderColor + ';font-weight:bold;">Thu</td>');
+	vCode += ('<td width="14%" style="font-family:' + fontface + ';color:'
+		+this.gHeaderColor + ';font-weight:bold;">Fri</td>');
+	vCode += ('<td width="16%" style="font-family:' + fontface + ';color:'
+		+this.gHeaderColor + ';font-weight:bold;">Sat</td>');
+	vCode += '</tr>';
+	return vCode;
+}
+
+Calendar.prototype.cal_data = function() {
+	var vDate = new Date();
+	vDate.setDate(1);
+	vDate.setMonth(this.gMonth);
+	vDate.setFullYear(this.gYear);
+
+	var vNowDay = gNow.getDate();
+	var vNowMonth = gNow.getMonth();
+	var vNowYear = gNow.getFullYear();
+
+	var yOK=!ggInactive||vNowYear<=vDate.getFullYear()?1:0;
+	var mOK=!ggInactive||vNowYear<vDate.getFullYear()||
+	 (vNowYear==vDate.getFullYear()&&vNowMonth<=vDate.getMonth())?1:0;
+	var ymOK=yOK&&mOK?1:0;
+	var dOK=!ggInactive||vNowYear<vDate.getFullYear()||vNowMonth<vDate.getMonth()?1:0;
+
+	var vFirstDay=vDate.getDay();
+	var vDay=1;
+	var vLastDay=Calendar.get_daysofmonth(this.gMonth, this.gYear);
+	var vOnLastDay=0;
+	var vCode = '<tr>';
+        var i,j,k,m;
+	var orig = eval("document." + this.gReturnItem + ".value").toString();
+	/*
+	Get day for the 1st of the requested month/year..
+	Place as many blank cells before the 1st day of the month as necessary. 
+	*/
+	for (i=0; i<vFirstDay; i++) { vCode +=
+		('<td width="14%"' + this.write_weekend_string(i)
+		+'style="font-family:\'' + fontface + '\';text-align:center;"> </td>');
+	}
+
+	// Write rest of the 1st week
+	for (j=vFirstDay; j<7; j++) { vCode +=
+		('<td width="14%"' + this.write_weekend_string(j) +'style="font-family:\''
+		+ fontface + '\';text-align:center;">'
+		+((ymOK)&&(vDay>=vNowDay||dOK)?'<a href="javascript:void(0);" '
+		+'title="set date to ' + this.format_data(vDay) + '" '
+		+'onmouseover="window.status=\'set date to ' + this.format_data(vDay) + '\'; '
+		+'return true;" '
+		+'onmouseout="window.status=\'\'; return true;" '
+		+'onclick="document.' + this.gReturnItem + '.value=\'' + this.format_data(vDay)
+		+'\';ggPosX= -1;ggPosY= -1;' + OLfnRef + (ggUseOverlib2?'cClick2();':'cClick();')
+		+'if((ggOnChange)&&(document.' + this.gReturnItem + '.value!=\'' + orig
+		+'\'))ggOnChange();">':'')
+		+ this.format_day(vDay)
+		+((ymOK)&&(vDay>=vNowDay||dOK)?'</a>':'')
+		+'</td>');
+		vDay += 1;
+	}
+	vCode += '</tr>';
+
+	// Write the rest of the weeks
+	for (k=2; k<7; k++) {
+		vCode += '<tr>';
+		for (j=0; j<7; j++) { vCode +=
+			('<td width="14%"' + this.write_weekend_string(j)
+			+'style="font-family:\'' + fontface + '\';text-align:center;">'
+			+((ymOK)&&(vDay>=vNowDay||dOK)?'<a '
+			+'href="javascript:void(0);" '
+			+'title="set date to ' + this.format_data(vDay) + '" '
+			+'onmouseover="window.status=\'set date to ' + this.format_data(vDay)
+			+'\'; return true;" '
+			+'onmouseout="window.status=\'\'; return true;" '
+			+'onclick="document.' + this.gReturnItem + '.value=\''
+			+ this.format_data(vDay) + '\';ggPosX= -1;ggPosY= -1;'
+			+ OLfnRef + (ggUseOverlib2?'cClick2();':'cClick();')
+			+'if((ggOnChange)&&(document.' + this.gReturnItem + '.value!=\''
+			+orig + '\'))ggOnChange();">':'')
+			+ this.format_day(vDay)
+			+((ymOK)&&(vDay>=vNowDay||dOK)?'</a>':'')
+			+'</td>');
+			vDay += 1;
+			if (vDay > vLastDay) {
+				vOnLastDay = 1;
+				break;
+			}
+		}
+		if (j == 6) vCode += '</tr>';
+		if (vOnLastDay == 1) break;
+	}
+	
+	// Fill up the rest of last week with proper blanks, so that we get proper square blocks
+	for (m=1; m<(7-j); m++) { vCode +=
+		('<td width="14%"' + this.write_weekend_string(j+m) + 'style="font-family:\''
+		+ fontface + '\';color:gray;text-align:center;"> </td>');
+	}
+	return vCode;
+}
+
+Calendar.prototype.format_day = function(vday) {
+	var vNowDay = gNow.getDate();
+	var vNowMonth = gNow.getMonth();
+	var vNowYear = gNow.getFullYear();
+
+	if (vday == vNowDay && this.gMonth == vNowMonth && this.gYear == vNowYear)
+		return ('<span style="color:red;font-weight:bold;">' + vday + '</span>');
+	else
+		return (vday);
+}
+
+Calendar.prototype.write_weekend_string = function(vday) {
+	var i;
+
+	// Return special formatting for the weekend day.
+	for (i=0; i<weekend.length; i++) {
+		if (vday == weekend[i])
+			return (' bgcolor="' + weekendColor + '"');
+	}
+	
+	return "";
+}
+
+Calendar.prototype.format_data = function(p_day) {
+	var vData;
+	var vMonth = 1 + this.gMonth;
+	vMonth = (vMonth.toString().length < 2) ? "0" + vMonth : vMonth;
+	var vMon = Calendar.get_month(this.gMonth).substr(0,3).toUpperCase();
+	var vFMon = Calendar.get_month(this.gMonth).toUpperCase();
+	var vY4 = new String(this.gYear);
+	var vY2 = new String(this.gYear.substr(2,2));
+	var vDD = (p_day.toString().length < 2) ? "0" + p_day : p_day;
+
+	switch (this.gFormat) {
+		case "MM\/DD\/YYYY" :
+			vData = vMonth + "\/" + vDD + "\/" + vY4;
+			break;
+		case "MM\/DD\/YY" :
+			vData = vMonth + "\/" + vDD + "\/" + vY2;
+			break;
+		case "MM-DD-YYYY" :
+			vData = vMonth + "-" + vDD + "-" + vY4;
+			break;
+		case "YYYY-MM-DD" :
+			vData = vY4 + "-" + vMonth + "-" + vDD;
+			break;
+		case "MM-DD-YY" :
+			vData = vMonth + "-" + vDD + "-" + vY2;
+			break;
+		case "DD\/MON\/YYYY" :
+			vData = vDD + "\/" + vMon + "\/" + vY4;
+			break;
+		case "DD\/MON\/YY" :
+			vData = vDD + "\/" + vMon + "\/" + vY2;
+			break;
+		case "DD-MON-YYYY" :
+			vData = vDD + "-" + vMon + "-" + vY4;
+			break;
+		case "DD-MON-YY" :
+			vData = vDD + "-" + vMon + "-" + vY2;
+			break;
+		case "DD\/MONTH\/YYYY" :
+			vData = vDD + "\/" + vFMon + "\/" + vY4;
+			break;
+		case "DD\/MONTH\/YY" :
+			vData = vDD + "\/" + vFMon + "\/" + vY2;
+			break;
+		case "DD-MONTH-YYYY" :
+			vData = vDD + "-" + vFMon + "-" + vY4;
+			break;
+		case "DD-MONTH-YY" :
+			vData = vDD + "-" + vFMon + "-" + vY2;
+			break;
+		case "DD\/MM\/YYYY" :
+			vData = vDD + "\/" + vMonth + "\/" + vY4;
+			break;
+		case "DD\/MM\/YY" :
+			vData = vDD + "\/" + vMonth + "\/" + vY2;
+			break;
+		case "DD-MM-YYYY" :
+			vData = vDD + "-" + vMonth + "-" + vY4;
+			break;
+		case "DD-MM-YY" :
+			vData = vDD + "-" + vMonth + "-" + vY2;
+			break;
+		case "DD.MM.YYYY" :
+			vData = vDD + "." + vMonth + "." + vY4;
+			break;
+		case "DD.MM.YY" :
+			vData = vDD + "." + vMonth + "." + vY2;
+			break;
+		default :
+			vData = vMonth + "\/" + vDD + "\/" + vY4;
+	}
+
+	return vData;
+}
+
+function Build(p_item, p_month, p_year, p_format) {
+	var gCal = new Calendar(p_item, p_month, p_year, p_format);
+
+	// Customize your Calendar here..
+	gCal.gBGColor="white";
+	gCal.gLinkColor="black";
+	gCal.gTextColor="black";
+	gCal.gHeaderColor="darkgreen";
+
+	// initialize the content string
+	ggWinContent = "";
+
+	// Check for DRAGGABLE support
+	if (typeof ol_draggable == 'undefined') DRAGGABLE = DONOTHING;
+
+	// Choose appropriate show function
+	if (gCal.gYearly) {
+		// Note: you can set ggPosX and ggPosY as part of the onclick javascript
+		// code before you call the show_yearly_calendar function:
+		//	onclick="ggPosX=20;ggPosY=5;show_yearly_calendar(...);"
+                if (OLns6) {
+			if (ggPosX == -1) ggPosX = 20;
+			if (ggPosY == -1) ggPosY = 10;
+		}
+		if (fontsize == 8) fontsize = 6;
+		// generate the calendar
+		gCal.showY();
+	} else {
+		if (fontsize == 6) fontsize = 8;
+		gCal.show();
+	}
+
+	// Clear or force EXCLUSIVE setting
+	o3_exclusive=(ggUseOverlib2)?1:0;
+	var CalendarOv=(ggUseOverlib2)?overlib2:overlib;
+	// If X and Y positions are not specified use MIDX and RELY
+	if (ggPosX == -1 && ggPosY == -1) {
+		CalendarOv(ggWinContent, AUTOSTATUSCAP, STICKY, EXCLUSIVE, DRAGGABLE,
+		 CLOSECLICK, TEXTSIZE,'8pt', CAPTIONSIZE,'8pt', CLOSESIZE,'8pt',
+		 CAPTION,'Select a date', MIDX,0, RELY,10);
+        // Otherwise use FIXX and FIXY
+	} else {
+		// Make sure popup is on screen
+		var X = ((ggPosX < 10)?0:ggPosX - 10), Y = ((ggPosY < 10)?0:ggPosY - 10);
+		window.scroll(X, Y);
+		// Put up the calendar
+		CalendarOv(ggWinContent, AUTOSTATUSCAP, STICKY, EXCLUSIVE, DRAGGABLE,
+		 CLOSECLICK, TEXTSIZE,'8pt', CAPTIONSIZE,'8pt', CLOSESIZE,'8pt',
+		 CAPTION,'Select a date', FIXX,ggPosX, FIXY,ggPosY);
+		// Reset the position variables
+		ggPosX = -1; ggPosY = -1;
+	}
+	ggUseOverlib2=0;
+}
+
+function show_calendar() {
+	var p_item	// Return Item.
+	var p_month	// 0-11 for Jan-Dec; 12 for All Months.
+	var p_year	// 4-digit year
+	var p_format	// Date format (YYYY-MM-DD, DD/MM/YYYY, ...)
+	fontsize = 8;
+
+	p_item = arguments[0];
+	if (arguments[1] == "" || arguments[1] == null || arguments[1] == '12')
+		p_month = new String(gNow.getMonth());
+	else
+		p_month = arguments[1];
+	if (arguments[2] == "" || arguments[2] == null)
+		p_year = new String(gNow.getFullYear().toString());
+	else
+		p_year = arguments[2];
+	if (arguments[3] == "" || arguments[3] == null)
+		p_format = "YYYY-MM-DD";
+	else
+		p_format = arguments[3];
+
+	if (OLns4) return overlib('Sorry, your browser does not support this feature. '
+	 +'Manually enter<br>' + p_format,
+	 FGCOLOR,'#ffffcc', TEXTSIZE,2, STICKY, NOCLOSE, OFFSETX,-10, OFFSETY,-10,
+	 WIDTH,110, BASE,2);
+
+	Build(p_item, p_month, p_year, p_format);
+}
+
+function show_yearly_calendar() {
+	var p_item	// Return Item.
+	var p_year	// 4-digit year
+	var p_format	// Date format (YYYY-MM-DD, DD/MM/YYYY, ...)
+
+	p_item = arguments[0];
+	if (arguments[1] == "" || arguments[1] == null)
+		p_year = new String(gNow.getFullYear().toString());
+	else
+		p_year = arguments[1];
+	if (arguments[2] == "" || arguments[2] == null)
+		p_format = "YYYY-MM-DD";
+	else
+		p_format = arguments[2];
+
+	if (OLns4) return overlib('Sorry, your browser does not support this feature. '
+	 +'Manually enter<br>' + p_format,
+	 FGCOLOR,'#ffffcc', TEXTSIZE,2, STICKY, NOCLOSE, OFFSETX,-10, OFFSETY,-10,
+	 WIDTH,110, BASE,2);
+
+	Build(p_item, null, p_year, p_format);
+}
diff --git a/OpenFreezer/overlib/calendarmws_lang.js b/OpenFreezer/overlib/calendarmws_lang.js
new file mode 100755
index 0000000..06bf959
--- /dev/null
+++ b/OpenFreezer/overlib/calendarmws_lang.js
@@ -0,0 +1,705 @@
+/*
+ calendarmws_lang.js - Script with multi-language support for generating calender popups
+  and selecting dates for form submissions.
+  See http://www.macridesweb.com/oltest/calendarmws_lang.html for a demonstration.
+  Initial (calendarmws.js): November 9, 2003 - Last Revised: June 11, 2008
+
+****
+ Original:  Kedar R. Bhave (softricks at hotmail.com)
+ Web Site:  http://www.softricks.com
+ (uses window popups)
+
+ Modifications and customizations to work with the overLIB v3.50
+ Author:   James B. O'Connor (joconnor at nordenterprises.com)
+ Web Site: http://www.nordenterprises.com
+ Developed for use with http://home-owners-assoc.com
+ Note: while overlib works fine with Netscape 4, this function does not work very
+    well, since portions of the "over" div end up under other fields on the form and
+    cannot be seen.  If you want to use this with NS4,  you'll need to change the
+    positioning in the overlib() call to make sure the "over" div gets positioned
+    away from all other form fields
+ The O'Connor script and many more are available free online at:
+    The JavaScript Source!! http://javascript.internet.com
+
+ Further modifications made by Foteos Macrides (http://www.macridesweb.com/oltest/),
+    Bodo Hantschmann (http://www.hantschmann.org) - multi-language support, and
+    Bill McCormick (wpmccormick at freeshell.org) - draggable support, for overlibmws.
+
+ Requires sprintf.js from the overlibmws distribution.
+*/
+
+var ggPosX = -1;
+var ggPosY = -1;
+var ggInactive = 0;
+var ggOnChange = null;
+var ggLang = 'eng';
+var ggUseOverlib2 = 0;
+
+var ggWinContent = "";
+
+var weekend = [0,6];
+var weekendColor = "#e0e0e0";
+var fontface = "Verdana";
+var fontsize = 8; // in "pt" units; used with "font-size" style element
+
+var calmsg = new Array();
+var datFormat = new Array();
+var CalendarMonths = new Array();
+var CalendarWeekdays = new Array();
+
+/* -----------------------------------------------------------------------------------------
+   Languages (set via the value of the ggLang global)
+   
+   'eng' - English
+   'ger' - German
+   'esp' - Spanish
+   'dut' - Dutch / Netherlands
+   
+   for more languages: 
+      greetings from babelfish ;-)  (Hint: Use always english as base, that gives the best
+      results.
+   ----------------------------------------------------------------------------------------- */
+   
+/* -------------------------------
+   English
+   ------------------------------- */
+calmsg["eng"] = new Array;
+calmsg["eng"][0] = "One year backward";
+calmsg["eng"][1] = "One year forward";
+calmsg["eng"][2] = "One month backward";
+calmsg["eng"][3] = "One month forward";
+calmsg["eng"][4] = "Set date";
+calmsg["eng"][5] = "Select date";
+calmsg["eng"][6] = "Your Browser does NOT support this feature. Update asap, please!<br />";
+calmsg["eng"][7] = "Year";
+calmsg["eng"][8] = "Click to close";
+datFormat["eng"] = "MM/DD/YYYY";
+CalendarMonths["eng"] = new Array("January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December");
+CalendarWeekdays["eng"] = new Array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
+
+/* -------------------------------
+   German
+   ------------------------------- */
+calmsg["ger"] = new Array;
+calmsg["ger"][0] = "Ein Jahr zurück";
+calmsg["ger"][1] = "Ein Jahr vorwärts";
+calmsg["ger"][2] = "Einen Monat zurück";
+calmsg["ger"][3] = "Einen Monat vorwärts";
+calmsg["ger"][4] = "Datum setzen";
+calmsg["ger"][5] = "Datum wählen";
+calmsg["ger"][6] = "Leider unterstützt Ihr Browser dieses Feature nicht. "
+ +"Bitte updaten!<br />";
+calmsg["ger"][7] = "Jahr";
+calmsg["ger"][8] = "Zum schließen klicken";
+datFormat["ger"] = "DD.MM.YYYY";
+CalendarMonths["ger"] = new Array("Januar", "Februar", "März", "April", "Mai", "Juni",
+ "Juli", "August", "September", "Oktober", "November", "Dezember");
+CalendarWeekdays["ger"] = new Array("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa");
+
+/* -------------------------------
+   Spanish
+   ------------------------------- */
+calmsg["esp"] = new Array;
+calmsg["esp"][0] = "Un a�o atras";
+calmsg["esp"][1] = "Un a�o adelante";
+calmsg["esp"][2] = "Un mes atras";
+calmsg["esp"][3] = "Un mes adelante";
+calmsg["esp"][4] = "Fije la fecha";
+calmsg["esp"][5] = "Seleccione la fecha";
+calmsg["esp"][6] = "Su browser no apoya esta caracter�stica. �Actualizaci�n cuanto antes, "
+ +"por favor!<br />";
+calmsg["esp"][7] = "A�o";
+calmsg["esp"][8] = "Tecleo a cerrarse";
+datFormat["esp"] = "DD.MM.YYYY";
+CalendarMonths["esp"] = new Array("Enero", "Febrero", "Marcha", "Abril", "Puede", "Junio",
+ "Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre");
+CalendarWeekdays["esp"] = new Array("Do", "Lu", "Ma", "Mi", "Ju", "Vi", "Sa");
+
+/* -------------------------------
+   Dutch
+   ------------------------------- */
+calmsg["dut"] = new Array;
+calmsg["dut"][0] = "��n jaar achteruit";
+calmsg["dut"][1] = "��n jaar voorwaarts";
+calmsg["dut"][2] = "��n maand achteruit";
+calmsg["dut"][3] = "��n maand voorwaarts";
+calmsg["dut"][4] = "Overname datum";
+calmsg["dut"][5] = "Selecteer datum";
+calmsg["dut"][6] = "Uw Browser steunt deze eigenschap niet. Update zo vlug mogelijk, "
+ +"tevreden!<br />";
+calmsg["dut"][7] = "Jaar";
+calmsg["dut"][8] = "klik aan het sluiten";
+datFormat["dut"] = "DD.MM.YYYY";
+CalendarMonths["dut"] = new Array("Januari", "Februari", "Maart", "April", "Mei", "Juni",
+ "Juli", "Augustus", "September", "Oktober", "November", "December");
+CalendarWeekdays["dut"] = new Array("Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za");
+
+var gNow = new Date();
+
+Calendar.CellWidth = ["14%", "14%", "14%", "14%", "14%", "14%", "16%"];
+
+// Non-Leap year Month days..
+Calendar.DOMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+// Leap year Month days..
+Calendar.lDOMonth = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+
+function Calendar(p_item, p_month, p_year, p_format) {
+	if ((p_month == null) && (p_year == null)) return;
+
+	if (p_month == null) {
+		this.gMonthName = null;
+		this.gMonth = null;
+		this.gYearly = true;
+	} else {
+		this.gMonthName = Calendar.get_month(p_month);
+		this.gMonth = new Number(p_month);
+		this.gYearly = false;
+	}
+
+	this.gYear = p_year;
+	this.gFormat = p_format;
+	this.gBGColor = "white";
+	this.gFGColor = "black";
+	this.gTextColor = "black";
+	this.gHeaderColor = "black";
+	this.gReturnItem = p_item;
+}
+
+Calendar.get_month = Calendar_get_month;
+Calendar.get_daysofmonth = Calendar_get_daysofmonth;
+Calendar.calc_month_year = Calendar_calc_month_year;
+
+function Calendar_get_month(monthNo) {
+	return Calendar.Months[monthNo];
+}
+
+function Calendar_get_daysofmonth(monthNo, p_year) {
+	/* 
+	Check for leap year ..
+	1.Years evenly divisible by four are normally leap years, except for... 
+	2.Years also evenly divisible by 100 are not leap years, except for... 
+	3.Years also evenly divisible by 400 are leap years. 
+	*/
+	if ((p_year % 4) == 0) {
+		if ((p_year % 100) == 0 && (p_year % 400) != 0)
+			return Calendar.DOMonth[monthNo];
+	
+		return Calendar.lDOMonth[monthNo];
+	} else
+		return Calendar.DOMonth[monthNo];
+}
+
+function Calendar_calc_month_year(p_Month, p_Year, incr) {
+	/* 
+	Will return an 1-D array with 1st element being the calculated month 
+	and second being the calculated year 
+	after applying the month increment/decrement as specified by 'incr' parameter.
+	'incr' will normally have 1/-1 to navigate thru the months.
+	*/
+	var ret_arr = new Array();
+	
+	if (incr == -1) {
+		// B A C K W A R D
+		if (p_Month == 0) {
+			ret_arr[0] = 11;
+			ret_arr[1] = parseInt(p_Year) - 1;
+		} else {
+			ret_arr[0] = parseInt(p_Month) - 1;
+			ret_arr[1] = parseInt(p_Year);
+		}
+	} else if (incr == 1) {
+		// F O R W A R D
+		if (p_Month == 11) {
+			ret_arr[0] = 0;
+			ret_arr[1] = parseInt(p_Year) + 1;
+		} else {
+			ret_arr[0] = parseInt(p_Month) + 1;
+			ret_arr[1] = parseInt(p_Year);
+		}
+	}
+	return ret_arr;
+}
+
+function Calendar_calc_month_year(p_Month, p_Year, incr) {
+	/* 
+	Will return an 1-D array with 1st element being the calculated month 
+	and second being the calculated year 
+	after applying the month increment/decrement as specified by 'incr' parameter.
+	'incr' will normally have 1/-1 to navigate thru the months.
+	*/
+	var ret_arr = new Array();
+	
+	if (incr == -1) {
+		// B A C K W A R D
+		if (p_Month == 0) {
+			ret_arr[0] = 11;
+			ret_arr[1] = parseInt(p_Year) - 1;
+		} else {
+			ret_arr[0] = parseInt(p_Month) - 1;
+			ret_arr[1] = parseInt(p_Year);
+		}
+	} else if (incr == 1) {
+		// F O R W A R D
+		if (p_Month == 11) {
+			ret_arr[0] = 0;
+			ret_arr[1] = parseInt(p_Year) + 1;
+		} else {
+			ret_arr[0] = parseInt(p_Month) + 1;
+			ret_arr[1] = parseInt(p_Year);
+		}
+	}
+	return ret_arr;
+}
+
+// This is for compatibility with Navigator 3, we have to create and discard one object
+// before the prototype object exists.
+new Calendar();
+
+Calendar.prototype.getMonthlyCalendarCode = function() {
+	var vCode = "";
+	var vHeader_Code = "";
+	var vData_Code = "";
+	
+	// Begin Table Drawing code here..
+	vCode += ('<div align="center"><table border="1" bgcolor="' + this.gBGColor
+	+'" style="font-size:' + fontsize + 'pt;">');
+
+	vHeader_Code = this.cal_header();
+	vData_Code = this.cal_data();
+	vCode += (vHeader_Code + vData_Code);
+
+	vCode += '</table></div>';
+
+	return vCode;
+}
+
+Calendar.prototype.show = function() {
+	var vCode = "";
+
+	var vDate = new Date();
+	vDate.setMonth(this.gMonth);
+	vDate.setFullYear(this.gYear);
+	var vNowMonth = gNow.getMonth();
+	var vNowYear = gNow.getFullYear();
+	var yOK=!ggInactive||vNowYear<vDate.getFullYear()?1:0;
+	var mOK=!ggInactive||(yOK||
+         (vNowYear<=vDate.getFullYear()&&vNowMonth<vDate.getMonth()))?1:0;
+
+	// build content into global var ggWinContent
+	ggWinContent += sprintf('<div style="font-family:\'%s\';font-weight:bold;'
+		+'font-size:%spt;text-align:center;">%s %s</div>',
+		fontface, fontsize, this.gMonthName, this.gYear);
+	
+	// Show navigation buttons
+	var prevMMYYYY = Calendar.calc_month_year(this.gMonth, this.gYear, -1);
+	var prevMM = prevMMYYYY[0];
+	var prevYYYY = prevMMYYYY[1];
+
+	var nextMMYYYY = Calendar.calc_month_year(this.gMonth, this.gYear, 1);
+	var nextMM = nextMMYYYY[0];
+	var nextYYYY = nextMMYYYY[1];
+	
+	var nav_cell = '<td align="%s"> [<a href="javascript:void(0);" title="%s" '
+		+'onmouseover="window.status=\'%s\'; return true;" '
+		+'onmouseout="window.status=\'\'; return true;" '
+		+'onclick="Build(\'%s\',\'%s\',\'%s\',\'%s\');">%s%s%s<\/a>] </td>';
+	var nav_cell_inactive = '<td align="%s"> [%s%s] </td>'
+
+	ggWinContent += '<table width="100%" border="0" cellspacing="0" cellpadding="0" '
+	+'bgcolor="#e0e0e0" style="font-size:' + fontsize + 'pt;">';
+	ggWinContent += '<tr>';
+	ggWinContent += yOK?sprintf(nav_cell, 
+		'left', calmsg[ggLang][0], calmsg[ggLang][0],
+		this.gReturnItem, this.gMonth, (parseInt(this.gYear)-1), this.gFormat,
+		'<<', (parseInt(this.gYear)-1), ''):
+		sprintf(nav_cell_inactive, 'left', '<<', (parseInt(this.gYear)-1));
+	ggWinContent += sprintf(nav_cell, 
+		'right', calmsg[ggLang][1], calmsg[ggLang][1],
+		this.gReturnItem, this.gMonth, (parseInt(this.gYear)+1), this.gFormat,
+		'', (parseInt(this.gYear)+1), '>>');
+	ggWinContent += '</tr><tr>';
+	ggWinContent += mOK?sprintf(nav_cell, 
+		'left', calmsg[ggLang][2], calmsg[ggLang][2],
+		this.gReturnItem, prevMM, prevYYYY, this.gFormat, '<',
+		Calendar.Months[prevMM], ''):
+		sprintf(nav_cell_inactive, '<', Calendar.Months[prevMM]);
+	ggWinContent += sprintf(nav_cell, 
+		'right', calmsg[ggLang][3], calmsg[ggLang][3],
+		this.gReturnItem, nextMM, nextYYYY, this.gFormat, '',
+		Calendar.Months[nextMM], '>');
+	ggWinContent += '</tr></table><div style="font-size:3px;"> </div>';
+
+	// Get the complete calendar code for the month, and add it to the content var
+	vCode = this.getMonthlyCalendarCode();
+	ggWinContent += vCode;
+}
+
+Calendar.prototype.showY = function() {
+	var vCode = "";
+	var i;
+
+	ggWinContent += sprintf(
+		'<div style="font-family:\'%s\';font-weight:bold;font-size:%spt;'
+		+'text-align:center;">%s</div>', fontface, fontsize+1, this.gYear);
+	// Show navigation buttons
+	var prevYYYY = parseInt(this.gYear) - 1;
+	var nextYYYY = parseInt(this.gYear) + 1;
+	
+	var vDate = new Date();
+	vDate.setFullYear(this.gYear);
+	var vCode = "";
+	var vNowYear = gNow.getFullYear();
+	var yOK=!ggInactive||vNowYear<vDate.getFullYear()?1:0;
+
+	ggWinContent += '<table width="100%" ' + sprintf(
+		'border="1" cellspacing="0" cellpadding="0" bgcolor="%s" '
+		+'style="font-size:%spt;">', '#e0e0e0', fontsize);
+	ggWinContent += '<tr>';
+	ggWinContent += yOK?sprintf(
+		'<td align="center">[<a href="javascript:void(0);" title="%s" '
+		+'onmouseover="window.status=\'%s\'; return true;" '
+		+'onmouseout="window.status=\'\'; return true;" '
+		+'onclick="Build(\'%s\', null, \'%s\', \'%s\');"><<%s</a>]</td>',
+		calmsg[ggLang][0], calmsg[ggLang][0], this.gReturnItem,
+		prevYYYY, this.gFormat, (parseInt(this.gYear)-1)):
+		sprintf('<td align="center">[<<%s]</td>',(parseInt(this.gYear)-1));
+	ggWinContent += '<td align="center">       </td>';
+	ggWinContent += sprintf(
+		'<td align="center">[<a href="javascript:void(0);" title="%s" '
+		+'onmouseover="window.status=\'%s\'; return true;" '
+		+'onmouseout="window.status=\'\'; return true;" '
+		+'onclick="Build(\'%s\', null, \'%s\', \'%s\');">%s>></a>]</td>',
+		calmsg[ggLang][1], calmsg[ggLang][1], this.gReturnItem,
+		nextYYYY, this.gFormat, (parseInt(this.gYear)+1));
+	ggWinContent += '</tr></table>';
+
+	// Get the complete calendar code for each month.
+	// start a table and first row in the table
+	ggWinContent += '<table width="100%" border="0" cellspacing="0" cellpadding="2" '
+	+'style="font-size:' + fontsize + 'pt;"><tr>';
+	for (i=0; i<12; i++) {
+		// start the table cell
+		ggWinContent += '<td align="center" valign="top">';
+		this.gMonth = i;
+		this.gMonthName = Calendar.get_month(this.gMonth);
+		vCode = this.getMonthlyCalendarCode();
+		ggWinContent += (this.gMonthName + '/' + this.gYear+ '<div '
+			+'style="font-size:2px;"> </div>');
+		ggWinContent += vCode;
+		ggWinContent += '</td>';
+		if (i == 3 || i == 7) ggWinContent += '</tr><tr>';
+	}
+	ggWinContent += '</tr></table>';
+}
+
+Calendar.prototype.cal_header = function() {
+	var vCode = '<tr>';
+	for (i=0; i<7; i++) { vCode += sprintf(
+		'<td width="%s" style="font-family:\'%s\';font-weight:bold;color:%s; '
+		+'text-align:center;">%s</td>',
+		Calendar.CellWidth[i], fontface, this.gHeaderColor, Calendar.Weekdays[i]);
+	}
+	return (vCode + '</tr>');
+}
+
+Calendar.prototype.cal_data = function() {
+	var vDate = new Date();
+	vDate.setDate(1);
+	vDate.setMonth(this.gMonth);
+	vDate.setFullYear(this.gYear);
+
+	var vNowDay = gNow.getDate();
+	var vNowMonth = gNow.getMonth();
+	var vNowYear = gNow.getFullYear();
+
+	var yOK=!ggInactive||vNowYear<=vDate.getFullYear()?1:0;
+	var mOK=!ggInactive||vNowYear<vDate.getFullYear()||
+	 (vNowYear==vDate.getFullYear()&&vNowMonth<=vDate.getMonth())?1:0;
+	var ymOK=yOK&&mOK?1:0;
+	var dOK=!ggInactive||vNowYear<vDate.getFullYear()||vNowMonth<vDate.getMonth()?1:0;
+
+	var vFirstDay=vDate.getDay();
+	var vDay=1;
+	var vLastDay=Calendar.get_daysofmonth(this.gMonth, this.gYear);
+	var vOnLastDay=0;
+	var vCode = '<tr>';
+        var i,j,k,m;
+	var orig = eval("document." + this.gReturnItem + ".value").toString();
+	/*
+	Get day for the 1st of the requested month/year..
+	Place as many blank cells before the 1st day of the month as necessary. 
+	*/
+	for (i=0; i<vFirstDay; i++) { vCode += sprintf(
+		'<td width="%s" %s style="font-family:\'%s\';text-align:center;"> </td>',
+		Calendar.CellWidth[0], this.write_weekend_string(i),fontface);
+	}
+	// Write rest of the 1st week
+	for (j=vFirstDay; j<7; j++) { vCode += (ymOK)&&(vDay>=vNowDay||dOK)?sprintf(
+		'<td width="%s" %s style="font-family:\'%s\';text-align:center;"><a '
+		+'href="javascript:void(0);" title="%s: %s" '
+		+'onmouselver="window.status=\'%s: %s\'; return true;" '
+		+'onmouseout="window.status=\'\'; return true;" '
+		+'onclick="document.%s.value=\'%s\';ggPosX= -1;ggPosY= -1;%s'
+                +(ggUseOverlib2?'cClick2();':'cClick();')
+		+'if((ggOnChange)&&(document.%s.value!=\'%s\'))ggOnChange();">%s</a></td>',
+		Calendar.CellWidth[j+1], this.write_weekend_string(j), fontface,
+		calmsg[ggLang][4], this.format_data(vDay), calmsg[ggLang][4],
+		this.format_data(vDay), this.gReturnItem, this.format_data(vDay), OLfnRef,
+		this.gReturnItem, orig, this.format_day(vDay)):
+		sprintf('<td width="%s" %s style="font-family:\'%s\';text-align:center;">'
+		+'%s</td>', Calendar.CellWidth[j+1], this.write_weekend_string(j), fontface,
+		this.format_day(vDay));
+		vDay += 1;
+	}
+	vCode += '</tr>';
+
+	// Write the rest of the weeks
+	for (k=2; k<7; k++) {
+		vCode += '<tr>';
+		for (j=0; j<7; j++) { vCode += (ymOK)&&(vDay>=vNowDay||dOK)?sprintf(
+			'<td width="%s" %s style="font-family:\'%s\';text-align:center;"><a '
+			+'href="javascript:void(0);" title="%s: %s" '
+			+'onmouseover="window.status=\'%s: %s\'; return true;" '
+			+'onmouseout="window.status=\'\'; return true;" '
+			+'onclick="document.%s.value=\'%s\';ggPosX= -1;ggPosY= -1;%s'
+                        +(ggUseOverlib2?'cClick2();':'cClick();')+'if'
+			+'((ggOnChange)&&(document.%s.value!=\'%s\'))ggOnChange();">%s</a></td>',
+			Calendar.CellWidth[j+1], this.write_weekend_string(j), fontface,
+			calmsg[ggLang][4], this.format_data(vDay),calmsg[ggLang][4],
+			this.format_data(vDay), this.gReturnItem, this.format_data(vDay),
+			OLfnRef, this.gReturnItem, orig, this.format_day(vDay)):sprintf(
+			'<td width="%s" %s style="font-family:\'%s\';text-align:center;">'
+			+'%s</td>', Calendar.CellWidth[j+1], this.write_weekend_string(j),
+			fontface, this.format_day(vDay));
+			vDay += 1;
+			if (vDay > vLastDay) {
+				vOnLastDay = 1;
+				break;
+			}
+		}
+		if (j == 6) vCode += '</tr>';
+		if (vOnLastDay == 1) break;
+	}
+	
+	// Fill up the rest of last week with proper blanks, so that we get proper square blocks
+	for (m=1; m<(7-j); m++) { vCode += sprintf(
+		'<td width="%s" %s style="font-family:\'%s\';color:gray;text-align:center;"'
+		+'> </td>',
+		Calendar.CellWidth[m+1], this.write_weekend_string(j+m), fontface);
+	}
+	return vCode;
+}
+
+Calendar.prototype.format_day = function(vday) {
+	var vNowDay = gNow.getDate();
+	var vNowMonth = gNow.getMonth();
+	var vNowYear = gNow.getFullYear();
+
+	if (vday == vNowDay && this.gMonth == vNowMonth && this.gYear == vNowYear)
+		return ('<span style="color:red;font-weight:bold;">' + vday + '</span>');
+	else
+		return (vday);
+}
+
+Calendar.prototype.write_weekend_string = function(vday) {
+	var i;
+
+	// Return special formatting for the weekend day.
+	for (i=0; i<weekend.length; i++) {
+		if (vday == weekend[i])
+			return (' bgcolor="' + weekendColor + '"');
+	}
+	
+	return "";
+}
+
+Calendar.prototype.format_data = function(p_day) {
+	var vData;
+	var vMonth = 1 + this.gMonth;
+	vMonth = (vMonth.toString().length < 2) ? "0" + vMonth : vMonth;
+	var vMon = Calendar.get_month(this.gMonth).substr(0,3).toUpperCase();
+	var vFMon = Calendar.get_month(this.gMonth).toUpperCase();
+	var vY4 = new String(this.gYear);
+	var vY2 = new String(this.gYear.substr(2,2));
+	var vDD = (p_day.toString().length < 2) ? "0" + p_day : p_day;
+
+	switch (this.gFormat) {
+		case "MM\/DD\/YYYY" :
+			vData = vMonth + "\/" + vDD + "\/" + vY4;
+			break;
+		case "MM\/DD\/YY" :
+			vData = vMonth + "\/" + vDD + "\/" + vY2;
+			break;
+		case "MM-DD-YYYY" :
+			vData = vMonth + "-" + vDD + "-" + vY4;
+			break;
+		case "YYYY-MM-DD" :
+			vData = vY4 + "-" + vMonth + "-" + vDD;
+			break;
+		case "MM-DD-YY" :
+			vData = vMonth + "-" + vDD + "-" + vY2;
+			break;
+		case "DD\/MON\/YYYY" :
+			vData = vDD + "\/" + vMon + "\/" + vY4;
+			break;
+		case "DD\/MON\/YY" :
+			vData = vDD + "\/" + vMon + "\/" + vY2;
+			break;
+		case "DD-MON-YYYY" :
+			vData = vDD + "-" + vMon + "-" + vY4;
+			break;
+		case "DD-MON-YY" :
+			vData = vDD + "-" + vMon + "-" + vY2;
+			break;
+		case "DD\/MONTH\/YYYY" :
+			vData = vDD + "\/" + vFMon + "\/" + vY4;
+			break;
+		case "DD\/MONTH\/YY" :
+			vData = vDD + "\/" + vFMon + "\/" + vY2;
+			break;
+		case "DD-MONTH-YYYY" :
+			vData = vDD + "-" + vFMon + "-" + vY4;
+			break;
+		case "DD-MONTH-YY" :
+			vData = vDD + "-" + vFMon + "-" + vY2;
+			break;
+		case "DD\/MM\/YYYY" :
+			vData = vDD + "\/" + vMonth + "\/" + vY4;
+			break;
+		case "DD\/MM\/YY" :
+			vData = vDD + "\/" + vMonth + "\/" + vY2;
+			break;
+		case "DD-MM-YYYY" :
+			vData = vDD + "-" + vMonth + "-" + vY4;
+			break;
+		case "DD-MM-YY" :
+			vData = vDD + "-" + vMonth + "-" + vY2;
+			break;
+		case "DD.MM.YYYY" :
+			vData = vDD + "." + vMonth + "." + vY4;
+			break;
+		case "DD.MM.YY" :
+			vData = vDD + "." + vMonth + "." + vY2;
+			break;
+		default :
+			vData = vMonth + "\/" + vDD + "\/" + vY4;
+	}
+
+	return vData;
+}
+
+function Build(p_item, p_month, p_year, p_format) {
+	var gCal = new Calendar(p_item, p_month, p_year, p_format);
+
+	// Customize your Calendar here..
+	gCal.gBGColor="white";
+	gCal.gLinkColor="black";
+	gCal.gTextColor="black";
+	gCal.gHeaderColor="darkgreen";
+
+	// initialize the content string
+	ggWinContent = "";
+
+	// Check for DRAGGABLE support
+	if (typeof ol_draggable == 'undefined') DRAGGABLE = DONOTHING;
+
+	// Choose appropriate show function
+	if (gCal.gYearly) {
+		// Note: you can set ggPosX and ggPosY as part of the onclick javascript
+		// code before you call the show_yearly_calendar function:
+		//	onclick="ggPosX=20;ggPosY=5;show_yearly_calendar(...);"
+                if (OLns6) {
+			if (ggPosX == -1) ggPosX = 20;
+			if (ggPosY == -1) ggPosY = 10;
+		}
+		if (fontsize == 8) fontsize = 6;
+		// generate the calendar
+		gCal.showY();
+	} else {
+		if (fontsize == 6) fontsize = 8;
+		gCal.show();
+	}
+
+	// Clear or force EXCLUSIVE setting
+	o3_exclusive=(ggUseOverlib2)?1:0;
+	var CalendarOv=(ggUseOverlib2)?overlib2:overlib;
+	// If X and Y positions are not specified use MIDX and RELY
+	if (ggPosX == -1 && ggPosY == -1) {
+		CalendarOv(ggWinContent, AUTOSTATUSCAP, STICKY, EXCLUSIVE, DRAGGABLE,
+		 CLOSECLICK, TEXTSIZE,'8pt', CAPTIONSIZE,'8pt', CLOSESIZE,'8pt',
+		 CAPTION,calmsg[ggLang][5], CLOSETITLE,calmsg[ggLang][8],CLOSETEXT,
+		 '<span style="background:#e0e0e0;color:#000000;text-decoration:none;'
+		 +'font-weight:bold;"> X </span>', MIDX,0, RELY,10);
+        // Otherwise use FIXX and FIXY
+	} else {
+		// Make sure popup is on screen
+		var X = ((ggPosX < 10)?0:ggPosX - 10), Y = ((ggPosY < 10)?0:ggPosY - 10);
+		window.scroll(X, Y);
+		// Put up the calendar
+		CalendarOv(ggWinContent, AUTOSTATUSCAP, STICKY, EXCLUSIVE, DRAGGABLE,
+		 CLOSECLICK, TEXTSIZE,'8pt', CAPTIONSIZE,'8pt', CLOSESIZE,'8pt',
+		 CAPTION,calmsg[ggLang][5], CLOSETITLE,calmsg[ggLang][8],CLOSETEXT,
+		 '<span style="background:#e0e0e0;color:#000000;text-decoration:none;'
+		 +'font-weight:bold;"> X </span>', FIXX,ggPosX, FIXY,ggPosY);
+		// Reset the position variables
+		ggPosX = -1; ggPosY = -1;
+	}
+	ggUseOverlib2=0;
+}
+
+function show_calendar() {
+	var p_item	// Return Item.
+	var p_month	// 0-11 for Jan-Dec; 12 for All Months.
+	var p_year	// 4-digit year
+	var p_format	// Date format (YYYY-MM-DD, DD/MM/YYYY, ...)
+	fontsize = 8;
+
+	Calendar.Months = CalendarMonths[ggLang];
+	Calendar.Weekdays = CalendarWeekdays[ggLang];
+
+	p_item = arguments[0];
+	if (arguments[1] == "" || arguments[1] == null || arguments[1] == '12')
+		p_month = new String(gNow.getMonth());
+	else
+		p_month = arguments[1];
+	if (arguments[2] == "" || arguments[2] == null)
+		p_year = new String(gNow.getFullYear().toString());
+	else
+		p_year = arguments[2];
+	if (arguments[3] == "" || arguments[3] == null)
+		p_format = datFormat[ggLang];
+	else
+		p_format = arguments[3];
+
+	if (OLns4) return overlib(calmsg[ggLang][6]+p_format,
+	 FGCOLOR,'#ffffcc', TEXTSIZE,2, STICKY, NOCLOSE, OFFSETX,-10, OFFSETY,-10,
+	 WIDTH,110, BASE,2);
+
+	Build(p_item, p_month, p_year, p_format);
+}
+
+function show_yearly_calendar() {
+	var p_item	// Return Item.
+	var p_year	// 4-digit year
+	var p_format	// Date format (YYYY-MM-DD, DD/MM/YYYY, ...)
+
+	Calendar.Months = CalendarMonths[ggLang];
+	Calendar.Weekdays = CalendarWeekdays[ggLang];
+
+	p_item = arguments[0];
+	if (arguments[1] == "" || arguments[1] == null)
+		p_year = new String(gNow.getFullYear().toString());
+	else
+		p_year = arguments[1];
+	if (arguments[2] == "" || arguments[2] == null)
+		p_format = datFormat[ggLang];
+	else
+		p_format = arguments[2];
+
+	if (OLns4) return overlib(calmsg[ggLang][6]+p_format,
+	 FGCOLOR,'#ffffcc', TEXTSIZE,2, STICKY, NOCLOSE, OFFSETX,-10, OFFSETY,-10,
+	 WIDTH,110, BASE,2);
+
+	Build(p_item, null, p_year, p_format);
+}
diff --git a/OpenFreezer/overlib/cornerBL.gif b/OpenFreezer/overlib/cornerBL.gif
new file mode 100755
index 0000000..e5af971
Binary files /dev/null and b/OpenFreezer/overlib/cornerBL.gif differ
diff --git a/OpenFreezer/overlib/cornerBR.gif b/OpenFreezer/overlib/cornerBR.gif
new file mode 100755
index 0000000..7f97070
Binary files /dev/null and b/OpenFreezer/overlib/cornerBR.gif differ
diff --git a/OpenFreezer/overlib/cornerTL.gif b/OpenFreezer/overlib/cornerTL.gif
new file mode 100755
index 0000000..242b06f
Binary files /dev/null and b/OpenFreezer/overlib/cornerTL.gif differ
diff --git a/OpenFreezer/overlib/cornerTR.gif b/OpenFreezer/overlib/cornerTR.gif
new file mode 100755
index 0000000..9d7cc78
Binary files /dev/null and b/OpenFreezer/overlib/cornerTR.gif differ
diff --git a/OpenFreezer/overlib/edgeB.gif b/OpenFreezer/overlib/edgeB.gif
new file mode 100755
index 0000000..cef34c0
Binary files /dev/null and b/OpenFreezer/overlib/edgeB.gif differ
diff --git a/OpenFreezer/overlib/edgeL.gif b/OpenFreezer/overlib/edgeL.gif
new file mode 100755
index 0000000..592c1b1
Binary files /dev/null and b/OpenFreezer/overlib/edgeL.gif differ
diff --git a/OpenFreezer/overlib/edgeR.gif b/OpenFreezer/overlib/edgeR.gif
new file mode 100755
index 0000000..d3d6635
Binary files /dev/null and b/OpenFreezer/overlib/edgeR.gif differ
diff --git a/OpenFreezer/overlib/edgeT.gif b/OpenFreezer/overlib/edgeT.gif
new file mode 100755
index 0000000..416a31d
Binary files /dev/null and b/OpenFreezer/overlib/edgeT.gif differ
diff --git a/OpenFreezer/overlib/exit.gif b/OpenFreezer/overlib/exit.gif
new file mode 100755
index 0000000..9f9bc80
Binary files /dev/null and b/OpenFreezer/overlib/exit.gif differ
diff --git a/OpenFreezer/overlib/exit_blue.gif b/OpenFreezer/overlib/exit_blue.gif
new file mode 100755
index 0000000..d04bc54
Binary files /dev/null and b/OpenFreezer/overlib/exit_blue.gif differ
diff --git a/OpenFreezer/overlib/exit_metallic.gif b/OpenFreezer/overlib/exit_metallic.gif
new file mode 100755
index 0000000..e9459af
Binary files /dev/null and b/OpenFreezer/overlib/exit_metallic.gif differ
diff --git a/OpenFreezer/overlib/flower.gif b/OpenFreezer/overlib/flower.gif
new file mode 100755
index 0000000..101275e
Binary files /dev/null and b/OpenFreezer/overlib/flower.gif differ
diff --git a/OpenFreezer/overlib/htmlspecialcharsmws.js b/OpenFreezer/overlib/htmlspecialcharsmws.js
new file mode 100755
index 0000000..b7ccb62
--- /dev/null
+++ b/OpenFreezer/overlib/htmlspecialcharsmws.js
@@ -0,0 +1,68 @@
+/*
+ htmlspecialcharsmws.js - Foteos Macrides (author and Copyright holder)
+    Initial: January 26, 2008 - Last Revised: March 28, 2008
+ Wrapper function set for performing the equivalent of the php
+ htmlspecialchars(sting, quote_style) function on html fragments
+ (see: http://us2.php.net/manual/en/function.htmlspecialchars.php)
+ to display the raw markup via overlibmws STICKY, EXCLUSIVE popups.
+ */
+
+
+/* Optional second argment values (ampersands and angle brackets always converted)
+       none or 0: convert double qoutes but not single quotes
+    ENT_NOQUOTES: don't covert either
+      ENT_QUOTES: convert both
+*/
+var ENT_NOQUOTES=1,ENT_QUOTES=2;
+
+/* Covert an html fragment */
+function OLhtmlspecialchars(str,quo){
+ var s=(str||'').toString().replace(/&/g,"&"),q=(quo||0);
+ if(q!=ENT_NOQUOTES)s=s.replace(/"/g,""");
+ if(q==ENT_QUOTES)s=s.replace(/'/g,"'");
+ return s.replace(/</g,"<").replace(/>/g,">");
+}
+
+/* Convert and show arbitary Markup */
+function OLshowMarkup(str,quo){
+ var so=OLoverHTML,s=(str||'null').toString(),q=(quo||0);
+ overlib(OLhtmlspecialchars(s,q), CAPTION,'<div align="center">Markup</div>', EXCLUSIVEOVERRIDE, STICKY, EXCLUSIVE,
+  BGCLASS,'', BORDER,1, BGCOLOR,'#666666', BASE,0, CGCLASS,'', CAPTIONFONTCLASS,'', CLOSEFONTCLASS,'', CAPTIONPADDING,6,
+  CGCOLOR,'#999999', CAPTIONSIZE,'12px', CAPCOLOR,'#ffffff', CLOSESIZE,'11px', CLOSECOLOR,'#ffffff', FGCLASS,'',
+  TEXTFONTCLASS,'', TEXTPADDING,6, FGCOLOR,'#eeeeee', TEXTSIZE,'12px', TEXTCOLOR,'#000000', MIDX,0, RELY,5, WRAP,
+  (OLfilterPI)?-FILTER:DONOTHING, (OLshadowPI)?-SHADOW:DONOTHING);
+ OLoverHTML=so;
+}
+
+/* Convert and show most recent OLoverHTML */
+function OLoverHTMLshow(quo){
+ var so=OLoverHTML,s=(so||'null').toString(),q=(quo||0);
+ overlib(OLhtmlspecialchars(s,q), CAPTION,'<div align="center">OLoverHTML</div>', EXCLUSIVEOVERRIDE, STICKY, EXCLUSIVE,
+  BGCLASS,'', BORDER,1, BGCOLOR,'#666666', BASE,0, CGCLASS,'', CAPTIONFONTCLASS,'', CLOSEFONTCLASS,'', CAPTIONPADDING,6,
+  CGCOLOR,'#999999', CAPTIONSIZE,'12px', CAPCOLOR,'#ffffff', CLOSESIZE,'11px', CLOSECOLOR,'#ffffff', FGCLASS,'',
+  TEXTFONTCLASS,'', TEXTPADDING,6, FGCOLOR,'#eeeeee', TEXTSIZE,'12px', TEXTCOLOR,'#000000', MIDX,0, RELY,5, WRAP,
+  (OLfilterPI)?-FILTER:DONOTHING, (OLshadowPI)?-SHADOW:DONOTHING);
+ OLoverHTML=so;
+}
+
+/* Convert and show most recent OLover2HTML */
+function OLover2HTMLshow(quo){
+ var so=OLoverHTML,s2=(OLover2HTML||'null').toString(),q=(quo||0);
+ overlib(OLhtmlspecialchars(s2,q), CAPTION,'<div align="center">OLover2HTML</div>', EXCLUSIVEOVERRIDE, STICKY, EXCLUSIVE,
+  BGCLASS,'', BORDER,1, BGCOLOR,'#666666', BASE,0, CGCLASS,'', CAPTIONFONTCLASS,'', CLOSEFONTCLASS,'', CAPTIONPADDING,6,
+  CGCOLOR,'#aaaaaa', CAPTIONSIZE,'12px', CAPCOLOR,'#ffffff', CLOSESIZE,'11px', CLOSECOLOR,'#ffffff', FGCLASS,'',
+  TEXTFONTCLASS,'', TEXTPADDING,6, FGCOLOR,'#eeeeee', TEXTSIZE,'12px', TEXTCOLOR,'#000000', MIDX,0, RELY,5, WRAP,
+  (OLfilterPI)?-FILTER:DONOTHING, (OLshadowPI)?-SHADOW:DONOTHING);
+ OLoverHTML=so;
+}
+
+/* Convert and show most recent OLresponseAJAX */
+function OLresponseAJAXshow(quo){
+ var so=OLoverHTML,s=(OLresponseAJAX||'null').toString(),q=(quo||0);
+ overlib(OLhtmlspecialchars(s,q), CAPTION,'<div align="center">OLresponseAJAX</div>', EXCLUSIVEOVERRIDE, STICKY, EXCLUSIVE,
+  BGCLASS,'', BORDER,1, BGCOLOR,'#666666', BASE,0, CGCLASS,'', CAPTIONFONTCLASS,'', CLOSEFONTCLASS,'', CAPTIONPADDING,6,
+  CGCOLOR,'#999999', CAPTIONSIZE,'12px', CAPCOLOR,'#ffffff', CLOSESIZE,'11px', CLOSECOLOR,'#ffffff', FGCLASS,'',
+  TEXTFONTCLASS,'', TEXTPADDING,6, FGCOLOR,'#eeeeee', TEXTSIZE,'12px', TEXTCOLOR,'#000000', MIDX,0, RELY,5, WRAP,
+  (OLfilterPI)?-FILTER:DONOTHING, (OLshadowPI)?-SHADOW:DONOTHING);
+ OLoverHTML=so;
+}
diff --git a/OpenFreezer/overlib/iframecontentmws.js b/OpenFreezer/overlib/iframecontentmws.js
new file mode 100755
index 0000000..cbad738
--- /dev/null
+++ b/OpenFreezer/overlib/iframecontentmws.js
@@ -0,0 +1,53 @@
+/*
+ iframecontentmws.js - Foteos Macrides (author and copyright holder)
+   Initial: October 10, 2004 - Last Revised: January 26, 2008
+ Scripts for using HTML documents as iframe content in overlibmws popups.
+
+ See http://www.macridesweb.com/oltest/IFRAME.html
+ and http://www.macridesweb.com/oltest/AJAX.html#ajaxex3
+ for more information.
+*/
+
+/*
+ Use as lead argument in overlib or overlb2 calls.  Include WRAP and
+ TEXTPADDING,0 in the call to ensure that the width arg is respected (unless
+ the CAPTION plus CLOSETEXT widths add up to more than the width arg, in which
+ case you should increase the width arg).  The name arg should be a unique
+ string for each popup with iframe content in the document.  The frameborder
+ arg should be 1 (browser default if omitted) or 0.  The scrolling arg should
+ be 'auto' (default if omitted), 'yes' or 'no'.
+*/
+function OLiframeContent(src, width, height, name, frameborder, scrolling) {
+ return ('<iframe src="'+src+'" width="'+width+'" height="'+height+'"'
+ +(name!=null?' name="'+name+'" id="'+name+'"':'')
+ +(frameborder!=null?' frameborder="'+frameborder+'"':'')
+ +' scrolling="'+(scrolling!=null?scrolling:'auto')
+ +'"><div>[iframe not supported]</div></iframe>');
+}
+
+/*
+ Swap the src if we are iframe content.  The name arg should be the same
+ string as in the OLiframeContent function for the popup.  The src arg is
+ a partial, relative, or complete URL for the document to be swapped in.
+*/
+function OLswapIframeSrc(name, src){
+ if(parent==self){
+  alert(src+'\n\n is only for iframe content');
+  return;
+ }
+ var o=parent.OLgetRef(name);
+ if(o)o.src=src;
+ else alert(src+'\n\n is not available');
+}
+
+/*
+ Emulate the Back button if we are iframe content.  Use only in documents
+ which are swapped in by using the OLswapIframeSrc function.
+*/
+function OLiframeBack(){
+ if(parent==self){
+  alert('This feature is only for iframe content');
+  return;
+ }
+ history.back();
+}
diff --git a/OpenFreezer/overlib/inputText.gif b/OpenFreezer/overlib/inputText.gif
new file mode 100755
index 0000000..db7f8df
Binary files /dev/null and b/OpenFreezer/overlib/inputText.gif differ
diff --git a/OpenFreezer/overlib/license.html b/OpenFreezer/overlib/license.html
new file mode 100755
index 0000000..0f4f9e0
--- /dev/null
+++ b/OpenFreezer/overlib/license.html
@@ -0,0 +1,265 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-Type" content="text/html; charset=iso-8859-1">
+<meta name="keywords" content="overlib, overlibmws, DHTML popups, DHTML tooltips, DHTML, popup, tooltip, Macrides Web Services, Macrides">
+<meta name="description" content="Open source license for the overlibmws DHTML popup and tooltip software package.">
+<meta name="author" content="Foteos Macrides">
+<title>overLIB - License for the overlibmws package</title>
+
+<script type="text/javascript">
+<!--
+var OLbubbleImageDir='http://www.macridesweb.com/oltest/';
+var OLbubbleImages='flower';
+//-->
+</script>
+
+<script type="text/javascript"
+ src="http://www.macridesweb.com/oltest/overlibmws.js"></script>
+<script type="text/javascript"
+ src="http://www.macridesweb.com/oltest/overlibmws_filter.js"></script>
+<script type="text/javascript"
+ src="http://www.macridesweb.com/oltest/overlibmws_bubble.js"></script>
+<script type="text/javascript"
+ src="http://www.macridesweb.com/oltest/overlibmws_shadow.js"></script>
+
+<script type="text/javascript">
+<!--
+OLpageDefaults(TEXTPADDING,6,CAPTIONPADDING,6,WRAP,
+ FILTER,FILTERSHADOW,1,FILTERSHADOWCOLOR,'#cf33cf',
+ SHADOW,SHADOWCOLOR,'#cf33cf',SHADOWOPACITY,100);
+
+// Preload backgound images.
+rainbowline=new Image();
+rainbowline.src="http://www.macridesweb.com/image/rainbowline.gif"
+rb=new Image();
+rb.src="http://www.macridesweb.com/image/rb.jpg"
+// -->
+</script>
+
+<style type="text/css">
+<!--
+.oltxt14 {font-family:Verdana;font-size:14px;font-weight:bold;color:#330033;}
+a {color:#338855;font-weight:bold;}
+a:hover {color:#FF00FF}
+.txtb12 {font-family:Verdana,Arial,sans-serif;font-size:12px;font-weight:bold;}
+.text14 {font-family:Verdana,Arial,sans-serif;font-size:14px;}
+.text20 {font-family:Verdana,Arial,sans-serif;font-size:20px;font-weight:bold;}
+.text22 {font-family:Verdana,Arial,sans-serif;font-size:22px;font-weight:bold;}
+.myText {font-family:Verdana,Arial,Helvetica,sans-serif;font-size:13px;color:#000000;}
+.snip {font-family:Verdana,Arial,Helvetica;font-size:10px;}
+.purple14 {font-family:Verdana,Arial,Helvetica,sans-serif;font-size:14px;color:purple;
+ font-weight:bold;}
+.purple22 {font-family:Verdana,Arial,Helvetica,sans-serif;font-size:22px;color:purple;
+ font-weight:bold;font-style:italic;}
+.comic20 {font-family:'Comic Sans MS';font-size:20px;}
+-->
+</style>
+</head>
+
+<body text="#000000" bgcolor="#ddeeff">
+
+<table width="90%" cellpadding="0" cellspacing="0" align="center">
+ <tr>
+  <td align="center" class="text22">
+    Open Source License for the <span class="purple22">overlibmws</span> Package
+  </td>
+ </tr>
+ <tr>
+  <td class="text14">
+   <br>
+   <span class="text20">1. License coverage</span>
+   <br><br>
+   Note that this license only covers the script library (javascript core and plugin modules)
+   and not any supporting material such as the <span class="purple14">overlibmws</span> <a
+     href="http://www.macridesweb.com/oltest/"
+     onmouseover="return overlib('Link to the Download and Test Directory for '
+      +'<span class=\'purple14\'><i>overlibmws</i></span>',
+      TEXTFONTCLASS,'myText', VAUTO, OFFSETY,20, CENTER, FGCOLOR,'#cceeff');"
+     onmouseout="nd();">website</a> or its online documentation and support files. You may not
+   reproduce the website or its online material without explicit written permission from the
+   author, but can freely incorporate scripts and procedures which are demonstrated in that
+   material into your own HTML or XML documents.
+   <br><br>
+   <span class="text20">2. License (Artistic)</span>
+   <ul>
+    <li>
+     <b>Preamble</b><br>
+     The intent of this document is to state the conditions under which a Package may be
+     copied, such that the Copyright Holder maintains some semblance of artistic control over
+     the development of the package, while giving the users of the package the right to use
+     and distribute the Package in a more-or-less customary fashion, plus the right to make
+     reasonable modifications.
+    </li>
+   </ul>
+   <ul>
+    <li>
+     <b>Definitions:</b><br>
+     "Package" refers to the collection of files distributed by the Copyright Holder, and
+     derivatives of that collection of files created through textual modification.
+     <br><br>
+     "Standard Version" refers to such a Package if it has not been modified, or has been
+     modified in accordance with the wishes of the Copyright Holder.
+     <br><br>
+     "Copyright Holder" is whoever is named in the copyright or copyrights for the package.
+     <br><br>
+     "You" is you, if you're thinking about copying or distributing this Package.
+     <br><br>
+     "Reasonable copying fee" is whatever you can justify on the basis of media cost,
+     duplication charges, time of people involved, and so on. (You will not be required to
+     justify it to the Copyright Holder, but only to the computing community at large as a
+     market that must bear the fee.)
+     <br><br>
+     "Freely Available" means that no fee is charged for the item itself, though there may be
+     fees involved in handling the item. It also means that recipients of the item may
+     redistribute it under the same conditions they received it.
+    </li>
+   </ul>
+   <ol>
+    <li>
+     You may make and give away verbatim copies of the source form of the Standard Version
+     of this Package without restriction, provided that you duplicate all of the original
+     copyright notices and associated disclaimers.
+    </li>
+    <li>
+     You may apply bug fixes, portability fixes and other modifications derived from the
+     Public Domain or from the Copyright Holder. A Package modified in such a way shall still
+     be considered the Standard Version.
+    </li>
+    <li>
+     You may otherwise modify your copy of this Package in any way, provided that you insert
+     a prominent notice in each changed file stating how and when you changed that file, and
+     provided that you do at least ONE of the following:
+     <ol>
+      <li>
+       place your modifications in the Public Domain or otherwise make them Freely Available,
+       such as by posting said modifications to Usenet or an equivalent medium, or placing the
+       modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright
+       Holder to include your modifications in the Standard Version of the Package.
+      </li>
+      <li>
+       use the modified Package only within your corporation or organization.
+      </li>
+      <li>
+       rename any non-standard executables so the names do not conflict with standard
+       executables, which must also be provided, and provide a separate manual page for each
+       non-standard executable that clearly documents how it differs from the Standard Version.
+      </li>
+      <li>
+       make other distribution arrangements with the Copyright Holder.
+      </li>
+     </ol>
+    </li>
+    <li>
+     You may distribute the programs of this Package in object code or executable form,
+     provided that you do at least ONE of the following:
+     <ol>
+      <li>
+       distribute a Standard Version of the executables and library files, together with
+       instructions (in the manual page or equivalent) on where to get the Standard Version.
+      </li>
+      <li>
+       accompany the distribution with the machine-readable source of the Package with your
+       modifications.
+      </li>
+      <li>
+       accompany any non-standard executables with their corresponding Standard Version
+       executables, giving the non-standard executables non-standard names, and clearly
+       documenting the differences in manual pages (or equivalent), together with instructions
+       on where to get the Standard Version.
+      </li>
+      <li>
+       make other distribution arrangements with the Copyright Holder.
+      </li>
+     </ol>
+    </li>
+    <li>
+     You may charge a reasonable copying fee for any distribution of this Package. You may
+     charge any fee you choose for support of this Package. You may not charge a fee for this
+     Package itself. However, you may distribute this Package in aggregate with other (possibly
+     commercial) programs as part of a larger (possibly commercial) software distribution
+     provided that you do not advertise this Package as a product of your own.
+    </li>
+    <li>
+     The scripts and library files supplied as input to or produced as output from the programs
+     of this Package do not automatically fall under the copyright of this Package, but belong
+     to whomever generated them, and may be sold commercially, and may be aggregated with this
+     Package.
+    </li>
+    <li>
+     C or perl subroutines supplied by you and linked into this Package shall not be considered
+     part of this Package.
+    </li>
+    <li>
+     The name of the Copyright Holder may not be used to endorse or promote products derived
+     from this software without specific prior written permission.
+    </li>
+    <li>
+     THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+     WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+     PURPOSE.
+    </li>
+   </ol>
+   <br>
+  </td>
+ </tr>
+</table>
+
+<table align="center" cellpadding="0" cellspacing="0" border="0" bgcolor="#ccddff">
+ <tr>
+  <td width="90" align="right" valign="middle" class="myText">
+   <a
+    href="http://www.macridesweb.com/oltest/"
+    onmousemove="if(OLie55)self.status=this.href;"
+    onmouseover="return overlib(
+     'Popups by <span class=\'purple14\'><i>overlibmws</i></span>',
+     REF,'logo',REFX,96,REFY,-4,BORDER,3,BASE,3,TEXTPADDING,4,TEXTFONTCLASS,'oltxt14',
+     FGBACKGROUND,'http://www.macridesweb.com/image/rb.jpg',
+     BGBACKGROUND,'http://www.macridesweb.com/image/rainbowline.gif');"
+    onmouseout="nd();"><img
+    name='logo' id="logo"
+    width="88" height="31" hspace="10" vspace="10" align="right" border="0" alt=""
+    src="http://www.macridesweb.com/image/overlibmwslogo.gif"></a><br>
+  </td>
+  <td valign="middle" class="snip">
+   Copyright Foteos Macrides<br>
+     2002-2010.<br>
+     All rights reserved.<br>
+  </td>
+  <td width="72" align="right" valign="middle" class="myText">
+   <a
+    target="_blank"
+    href="https://www.paypal.com/xclick/business=overlibmws%40macridesweb.com&item_name=Donation+for+overlibmws&no_note=1&tax=0&currency_code=USD"
+    onmousemove="if(OLie55)self.status=this.href;"
+    onmouseover="return overlib(
+     'The <span class=\'purple14\'><i>overlibmws</i></span> library '
+     +'and its support materials at this site are <br>free to download and use, but '
+     +'voluntary donations via PayPal are<br>appreciated (donations via PayPal are fast, '
+     +'simple, and secure).',TEXTPADDING,8,FGCOLOR,'#bbddff',
+     FGBACKGROUND,'http://www.macridesweb.com/image/rb.jpg',
+     REF,'logo',REFC,'UL',REFP,'LL',REFX,-10,REFY,-10,TEXTFONTCLASS,'txtb12',BORDER,6,BASE,6,
+     BGBACKGROUND,'http://www.macridesweb.com/image/rainbowline.gif');"
+    onmouseout="nd();"><img
+    src="http://www.macridesweb.com/image/PayPalDonate.gif"
+    width="62" height="31" border="0"
+    alt=""></a><br>
+  </td>
+  <td width="110" align="right" valign="middle" class="myText">
+   <a
+    onmousemove="if(OLie55)self.status=this.href;"
+    onmouseover="return overlib(' Valid HTML 4.01',BUBBLE,
+     TEXTFONTCLASS,'comic20',REF,'w3c',REFC,'UR',REFP,'LR',REFX,73,REFY,2,
+     FILTERSHADOW,1,FILTERSHADOWCOLOR,'#00B000');"
+    onmouseout="nd();"
+    href="http://validator.w3.org/check?uri=http%3A%2F%2Fwww.macridesweb.com%2Foltest%2Flicense.html"><img
+    name="w3c" id="w3c"
+    border="0" height="31" width="88" alt="" hspace="6"
+    src="http://www.macridesweb.com/image/valid-html401.gif"></a><br>
+  </td>
+ </tr>
+</table>
+<br>
+
+</body>
+</html>
diff --git a/OpenFreezer/overlib/loading.gif b/OpenFreezer/overlib/loading.gif
new file mode 100755
index 0000000..5c8f1ef
Binary files /dev/null and b/OpenFreezer/overlib/loading.gif differ
diff --git a/OpenFreezer/overlib/makemini.pl b/OpenFreezer/overlib/makemini.pl
new file mode 100755
index 0000000..3d29ebb
--- /dev/null
+++ b/OpenFreezer/overlib/makemini.pl
@@ -0,0 +1,95 @@
+#!/usr/bin/perl
+
+my $doPlugin = 0;
+my $x = shift(@ARGV);
+if ($x !~ /^-p/) { unshift(@ARGV, $x); }
+else { $doPlugin=1; }
+my $injs = shift(@ARGV);
+my $outjs = shift(@ARGV);
+
+if ($injs eq '' or $outjs eq '') {
+	print "Please use this script like this: makemini.pl [-p] in.js out.js\n";	
+	exit(0);
+}
+
+
+open(INJS, $injs);
+open(OUTJS, ">$outjs");
+
+my $output = '';
+
+while (<INJS>) {
+	my $line = $_;
+	
+	if ($line =~ /^\/\//) {
+		# Remove lines that aren't important: //\
+		$line = "" if ($line !~ /^\/\/\\/);
+		$line = "\n//\\  THIS IS A VERY MODIFIED VERSION. DO NOT EDIT OR PUBLISH. GET THE ORIGINAL!\n\n" if ($line =~ /\/\/\\mini/);
+	} else {
+		chop $line;
+
+		$line =~ s/, /,/g unless ($line =~ /'\], '/);           # ,{sp} -> ,
+		$line =~ s/; /;/g;           # ;{sp} -> ;
+		$line =~ s/ = /=/g;          # {sp}={sp} -> =
+		$line =~ s/ == /==/g;        # {sp}=={sp} -> ==
+		$line =~ s/ < /</g;          # {sp}<{sp} -> <
+		$line =~ s/ > />/g;          # {sp}>{sp} -> >
+		$line =~ s/ & /&/g;          # {sp}&{sp} -> &
+		$line =~ s/ \| /\|/g;        # {sp}|{sp} -> |
+		$line =~ s/ <= /<=/g;        # {sp}<={sp} -> <=
+		$line =~ s/ >= />=/g;        # {sp}>={sp} -> >=
+		$line =~ s/ \+ /\+/g;        # {sp}+{sp} -> +
+		$line =~ s/ - /-/g;          # {sp}-{sp} -> -
+		$line =~ s/ \/ /\//g;
+		$line =~ s/ \|\| /\|\|/g;    # {sp}||{sp} -> ||
+		$line =~ s/ && /&&/g;        # {sp}&&{sp} -> &&
+		$line =~ s/ \? /\?/g;        # {sp?{sp} -> ?
+		$line =~ s/ \: /\:/g;        # {sp}:{sp} -> :
+		$line =~ s/ != /!=/g;        # {sp}!={sp} -> !=
+		$line =~ s/ += /+=/g;        # {sp}+={sp} -> +=
+		$line =~ s/ -= /-=/g;        # {sp}-={sp} -> -=
+		$line =~ s/ \*= /\*=/g;      # {sp}*={sp} -> *=
+		$line =~ s/ \|= /\|=/g;       # {sp}|={sp} -> |=
+		$line =~ s/ \^= /\^=/g;       # {sp}^={sp} -> ^=
+		$line =~ s/= /=/g;           # ={sp} -> =
+		$line =~ s/ =/=/g;           # {sp}= -> =
+		$line =~ s/\+ /\+/g;
+		$line =~ s/ \+/\+/g;
+		$line =~ s/- /-/g;
+		$line =~ s/ -/-/g;
+
+		$line =~ s/\/\/(.*)$//g if ($line !~ /\/\/-->(.*)$/ && $line !~ /http:\/\/(.*)$/); # remove trailing comments unless its part of a javascript insert or web address
+		$line = '' if $line =~ /^[\n|\/\/]/; # skip blank lines or any line starting with //
+
+		$line =~ s/^\s+//g;
+		$line =~ s/\s+$//g;
+		$line =~ s/(.+)\s+(.+)/$1 $2/g;
+		$line =~ s/\{ (\w)/\{$1/g;
+		$line =~ s/\) (\w)/\)$1/g;
+		$line =~ s/\) var/\)var/g;
+		$line =~ s/[ ]+\(/\(/g;
+		$line =~ s/\) \{/\)\{/g;
+		$line =~ s/\} else/\}else/g;
+		$line =~ s/else \{/else\{/g;
+		if ($line =~ /^\}$/) {
+			if ($output =~ /;$/) {
+				$output .= "}";
+			} else {
+				$output = substr($output,0,length($output)-1) . "}";
+			}
+			$line = '';
+		}
+	}
+
+	$output .= $line if ($line ne '');
+	$output .= "\n" unless ($line =~ /;\n*$/ or $line =~ /{\n*$/);
+}
+
+$output =~ s/\n+/\n/g;
+$output .= "}\n" if ($doPlugin && $output !~ /\}\s+$/);
+# replace multiple ;var xx to ,xx if the line contains var
+ at lines = split(/^/,$output);
+foreach $line (@lines) {
+	$line =~ s/;var /,/g if ($line =~ /^\s*var / && $line !~ /(turn|ment|Capture\(\)|Div'\)|1000\));var /);
+	print OUTJS $line;
+}
diff --git a/OpenFreezer/overlib/objectcontentmws.js b/OpenFreezer/overlib/objectcontentmws.js
new file mode 100755
index 0000000..99f0218
--- /dev/null
+++ b/OpenFreezer/overlib/objectcontentmws.js
@@ -0,0 +1,16 @@
+/*
+ objectcontentmws.js - Foteos Macrides
+   Initial: October 10, 2004 - Last Revised: January 26, 2008
+ Simple script for using an HTML file as object content in overlibmws popups.
+ Include WRAP and TEXTPADDING,0 in the overlib call to ensure that the width
+ argument is respected (unless the CAPTION plus CLOSETEXT widths add up to more
+ than the width argument, in which case you should increase the width argument).
+
+ See http://www.macridesweb.com/oltest/overflow.html for demonstrations.
+*/
+
+function OLobjectContent(data, width, height, name) {
+ return ('<object data="'+data+'" width="'+width+'" height="'+height+'"'
+ +(name?' name="'+name+'" id="'+name+'"':'')+' type="text/html">'
+ +'<div>[object not supported]</div></object>');
+}
diff --git a/OpenFreezer/overlib/oval.gif b/OpenFreezer/overlib/oval.gif
new file mode 100755
index 0000000..7e1af22
Binary files /dev/null and b/OpenFreezer/overlib/oval.gif differ
diff --git a/OpenFreezer/overlib/overlib.js b/OpenFreezer/overlib/overlib.js
new file mode 100755
index 0000000..e900ab4
--- /dev/null
+++ b/OpenFreezer/overlib/overlib.js
@@ -0,0 +1,1491 @@
+//\/////
+//\  overLIB 4.21 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\
+//\  Contributors are listed on the homepage.
+//\  This file might be old, always check for the latest version at:
+//\  http://www.bosrup.com/web/overlib/
+//\
+//\  Please read the license agreement (available through the link above)
+//\  before using overLIB. Direct any licensing questions to erik at bosrup.com.
+//\
+//\  Do not sell this as your own work or remove this copyright notice. 
+//\  For full details on copying or changing this script please read the
+//\  license agreement at the link above. Please give credit on sites that
+//\  use overLIB and submit changes of the script so other people can use
+//\  them as well.
+//   $Revision: 1.119 $                $Date: 2005/07/02 23:41:44 $
+//\/////
+//\mini
+
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+var olLoaded = 0;var pmStart = 10000000; var pmUpper = 10001000; var pmCount = pmStart+1; var pmt=''; var pms = new Array(); var olInfo = new Info('4.21', 1);
+var FREPLACE = 0; var FBEFORE = 1; var FAFTER = 2; var FALTERNATE = 3; var FCHAIN=4;
+var olHideForm=0;  // parameter for hiding SELECT and ActiveX elements in IE5.5+ 
+var olHautoFlag = 0;  // flags for over-riding VAUTO and HAUTO if corresponding
+var olVautoFlag = 0;  // positioning commands are used on the command line
+var hookPts = new Array(), postParse = new Array(), cmdLine = new Array(), runTime = new Array();
+// for plugins
+registerCommands('donothing,inarray,caparray,sticky,background,noclose,caption,left,right,center,offsetx,offsety,fgcolor,bgcolor,textcolor,capcolor,closecolor,width,border,cellpad,status,autostatus,autostatuscap,height,closetext,snapx,snapy,fixx,fixy,relx,rely,fgbackground,bgbackground,padx,pady,fullhtml,above,below,capicon,textfont,captionfont,closefont,textsize,captionsize,closesize,timeout,function,delay,hauto,vauto,closeclick,wrap,followmouse,mouseoff,closetitle,cssoff,compatmode,css [...]
+
+////////
+// DEFAULT CONFIGURATION
+// Settings you want everywhere are set here. All of this can also be
+// changed on your html page or through an overLIB call.
+////////
+if (typeof ol_fgcolor=='undefined') var ol_fgcolor="#CCCCFF";
+if (typeof ol_bgcolor=='undefined') var ol_bgcolor="#333399";
+if (typeof ol_textcolor=='undefined') var ol_textcolor="#000000";
+if (typeof ol_capcolor=='undefined') var ol_capcolor="#FFFFFF";
+if (typeof ol_closecolor=='undefined') var ol_closecolor="#9999FF";
+if (typeof ol_textfont=='undefined') var ol_textfont="Verdana,Arial,Helvetica";
+if (typeof ol_captionfont=='undefined') var ol_captionfont="Verdana,Arial,Helvetica";
+if (typeof ol_closefont=='undefined') var ol_closefont="Verdana,Arial,Helvetica";
+if (typeof ol_textsize=='undefined') var ol_textsize="1";
+if (typeof ol_captionsize=='undefined') var ol_captionsize="1";
+if (typeof ol_closesize=='undefined') var ol_closesize="1";
+if (typeof ol_width=='undefined') var ol_width="200";
+if (typeof ol_border=='undefined') var ol_border="1";
+if (typeof ol_cellpad=='undefined') var ol_cellpad=2;
+if (typeof ol_offsetx=='undefined') var ol_offsetx=10;
+if (typeof ol_offsety=='undefined') var ol_offsety=10;
+if (typeof ol_text=='undefined') var ol_text="Default Text";
+if (typeof ol_cap=='undefined') var ol_cap="";
+if (typeof ol_sticky=='undefined') var ol_sticky=0;
+if (typeof ol_background=='undefined') var ol_background="";
+if (typeof ol_close=='undefined') var ol_close="Close";
+if (typeof ol_hpos=='undefined') var ol_hpos=RIGHT;
+if (typeof ol_status=='undefined') var ol_status="";
+if (typeof ol_autostatus=='undefined') var ol_autostatus=0;
+if (typeof ol_height=='undefined') var ol_height=-1;
+if (typeof ol_snapx=='undefined') var ol_snapx=0;
+if (typeof ol_snapy=='undefined') var ol_snapy=0;
+if (typeof ol_fixx=='undefined') var ol_fixx=-1;
+if (typeof ol_fixy=='undefined') var ol_fixy=-1;
+if (typeof ol_relx=='undefined') var ol_relx=null;
+if (typeof ol_rely=='undefined') var ol_rely=null;
+if (typeof ol_fgbackground=='undefined') var ol_fgbackground="";
+if (typeof ol_bgbackground=='undefined') var ol_bgbackground="";
+if (typeof ol_padxl=='undefined') var ol_padxl=1;
+if (typeof ol_padxr=='undefined') var ol_padxr=1;
+if (typeof ol_padyt=='undefined') var ol_padyt=1;
+if (typeof ol_padyb=='undefined') var ol_padyb=1;
+if (typeof ol_fullhtml=='undefined') var ol_fullhtml=0;
+if (typeof ol_vpos=='undefined') var ol_vpos=BELOW;
+if (typeof ol_aboveheight=='undefined') var ol_aboveheight=0;
+if (typeof ol_capicon=='undefined') var ol_capicon="";
+if (typeof ol_frame=='undefined') var ol_frame=self;
+if (typeof ol_timeout=='undefined') var ol_timeout=0;
+if (typeof ol_function=='undefined') var ol_function=null;
+if (typeof ol_delay=='undefined') var ol_delay=0;
+if (typeof ol_hauto=='undefined') var ol_hauto=0;
+if (typeof ol_vauto=='undefined') var ol_vauto=0;
+if (typeof ol_closeclick=='undefined') var ol_closeclick=0;
+if (typeof ol_wrap=='undefined') var ol_wrap=0;
+if (typeof ol_followmouse=='undefined') var ol_followmouse=1;
+if (typeof ol_mouseoff=='undefined') var ol_mouseoff=0;
+if (typeof ol_closetitle=='undefined') var ol_closetitle='Close';
+if (typeof ol_compatmode=='undefined') var ol_compatmode=0;
+if (typeof ol_css=='undefined') var ol_css=CSSOFF;
+if (typeof ol_fgclass=='undefined') var ol_fgclass="";
+if (typeof ol_bgclass=='undefined') var ol_bgclass="";
+if (typeof ol_textfontclass=='undefined') var ol_textfontclass="";
+if (typeof ol_captionfontclass=='undefined') var ol_captionfontclass="";
+if (typeof ol_closefontclass=='undefined') var ol_closefontclass="";
+
+////////
+// ARRAY CONFIGURATION
+////////
+
+// You can use these arrays to store popup text here instead of in the html.
+if (typeof ol_texts=='undefined') var ol_texts = new Array("Text 0", "Text 1");
+if (typeof ol_caps=='undefined') var ol_caps = new Array("Caption 0", "Caption 1");
+
+////////
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+
+
+
+
+
+////////
+// INIT
+////////
+// Runtime variables init. Don't change for config!
+var o3_text="";
+var o3_cap="";
+var o3_sticky=0;
+var o3_background="";
+var o3_close="Close";
+var o3_hpos=RIGHT;
+var o3_offsetx=2;
+var o3_offsety=2;
+var o3_fgcolor="";
+var o3_bgcolor="";
+var o3_textcolor="";
+var o3_capcolor="";
+var o3_closecolor="";
+var o3_width=100;
+var o3_border=1;
+var o3_cellpad=2;
+var o3_status="";
+var o3_autostatus=0;
+var o3_height=-1;
+var o3_snapx=0;
+var o3_snapy=0;
+var o3_fixx=-1;
+var o3_fixy=-1;
+var o3_relx=null;
+var o3_rely=null;
+var o3_fgbackground="";
+var o3_bgbackground="";
+var o3_padxl=0;
+var o3_padxr=0;
+var o3_padyt=0;
+var o3_padyb=0;
+var o3_fullhtml=0;
+var o3_vpos=BELOW;
+var o3_aboveheight=0;
+var o3_capicon="";
+var o3_textfont="Verdana,Arial,Helvetica";
+var o3_captionfont="Verdana,Arial,Helvetica";
+var o3_closefont="Verdana,Arial,Helvetica";
+var o3_textsize="1";
+var o3_captionsize="1";
+var o3_closesize="1";
+var o3_frame=self;
+var o3_timeout=0;
+var o3_timerid=0;
+var o3_allowmove=0;
+var o3_function=null; 
+var o3_delay=0;
+var o3_delayid=0;
+var o3_hauto=0;
+var o3_vauto=0;
+var o3_closeclick=0;
+var o3_wrap=0;
+var o3_followmouse=1;
+var o3_mouseoff=0;
+var o3_closetitle='';
+var o3_compatmode=0;
+var o3_css=CSSOFF;
+var o3_fgclass="";
+var o3_bgclass="";
+var o3_textfontclass="";
+var o3_captionfontclass="";
+var o3_closefontclass="";
+
+// Display state variables
+var o3_x = 0;
+var o3_y = 0;
+var o3_showingsticky = 0;
+var o3_removecounter = 0;
+
+// Our layer
+var over = null;
+var fnRef, hoveringSwitch = false;
+var olHideDelay;
+
+// Decide browser version
+var isMac = (navigator.userAgent.indexOf("Mac") != -1);
+var olOp = (navigator.userAgent.toLowerCase().indexOf('opera') > -1 && document.createTextNode);  // Opera 7
+var olNs4 = (navigator.appName=='Netscape' && parseInt(navigator.appVersion) == 4);
+var olNs6 = (document.getElementById) ? true : false;
+var olKq = (olNs6 && /konqueror/i.test(navigator.userAgent));
+var olIe4 = (document.all) ? true : false;
+var olIe5 = false; 
+var olIe55 = false; // Added additional variable to identify IE5.5+
+var docRoot = 'document.body';
+
+// Resize fix for NS4.x to keep track of layer
+if (olNs4) {
+	var oW = window.innerWidth;
+	var oH = window.innerHeight;
+	window.onresize = function() { if (oW != window.innerWidth || oH != window.innerHeight) location.reload(); }
+}
+
+// Microsoft Stupidity Check(tm).
+if (olIe4) {
+	var agent = navigator.userAgent;
+	if (/MSIE/.test(agent)) {
+		var versNum = parseFloat(agent.match(/MSIE[ ](\d\.\d+)\.*/i)[1]);
+		if (versNum >= 5){
+			olIe5=true;
+			olIe55=(versNum>=5.5&&!olOp) ? true : false;
+			if (olNs6) olNs6=false;
+		}
+	}
+	if (olNs6) olIe4 = false;
+}
+
+// Check for compatability mode.
+if (document.compatMode && document.compatMode == 'CSS1Compat') {
+	docRoot= ((olIe4 && !olOp) ? 'document.documentElement' : docRoot);
+}
+
+// Add window onload handlers to indicate when all modules have been loaded
+// For Netscape 6+ and Mozilla, uses addEventListener method on the window object
+// For IE it uses the attachEvent method of the window object and for Netscape 4.x
+// it sets the window.onload handler to the OLonload_handler function for Bubbling
+if(window.addEventListener) window.addEventListener("load",OLonLoad_handler,false);
+else if (window.attachEvent) window.attachEvent("onload",OLonLoad_handler);
+
+var capExtent;
+
+////////
+// PUBLIC FUNCTIONS
+////////
+
+// overlib(arg0,...,argN)
+// Loads parameters into global runtime variables.
+function overlib() {
+	if (!olLoaded || isExclusive(overlib.arguments)) return true;
+	if (olCheckMouseCapture) olMouseCapture();
+	if (over) {
+		over = (typeof over.id != 'string') ? o3_frame.document.all['overDiv'] : over;
+		cClick();
+	}
+
+	// Load defaults to runtime.
+  olHideDelay=0;
+	o3_text=ol_text;
+	o3_cap=ol_cap;
+	o3_sticky=ol_sticky;
+	o3_background=ol_background;
+	o3_close=ol_close;
+	o3_hpos=ol_hpos;
+	o3_offsetx=ol_offsetx;
+	o3_offsety=ol_offsety;
+	o3_fgcolor=ol_fgcolor;
+	o3_bgcolor=ol_bgcolor;
+	o3_textcolor=ol_textcolor;
+	o3_capcolor=ol_capcolor;
+	o3_closecolor=ol_closecolor;
+	o3_width=ol_width;
+	o3_border=ol_border;
+	o3_cellpad=ol_cellpad;
+	o3_status=ol_status;
+	o3_autostatus=ol_autostatus;
+	o3_height=ol_height;
+	o3_snapx=ol_snapx;
+	o3_snapy=ol_snapy;
+	o3_fixx=ol_fixx;
+	o3_fixy=ol_fixy;
+	o3_relx=ol_relx;
+	o3_rely=ol_rely;
+	o3_fgbackground=ol_fgbackground;
+	o3_bgbackground=ol_bgbackground;
+	o3_padxl=ol_padxl;
+	o3_padxr=ol_padxr;
+	o3_padyt=ol_padyt;
+	o3_padyb=ol_padyb;
+	o3_fullhtml=ol_fullhtml;
+	o3_vpos=ol_vpos;
+	o3_aboveheight=ol_aboveheight;
+	o3_capicon=ol_capicon;
+	o3_textfont=ol_textfont;
+	o3_captionfont=ol_captionfont;
+	o3_closefont=ol_closefont;
+	o3_textsize=ol_textsize;
+	o3_captionsize=ol_captionsize;
+	o3_closesize=ol_closesize;
+	o3_timeout=ol_timeout;
+	o3_function=ol_function;
+	o3_delay=ol_delay;
+	o3_hauto=ol_hauto;
+	o3_vauto=ol_vauto;
+	o3_closeclick=ol_closeclick;
+	o3_wrap=ol_wrap;	
+	o3_followmouse=ol_followmouse;
+	o3_mouseoff=ol_mouseoff;
+	o3_closetitle=ol_closetitle;
+	o3_css=ol_css;
+	o3_compatmode=ol_compatmode;
+	o3_fgclass=ol_fgclass;
+	o3_bgclass=ol_bgclass;
+	o3_textfontclass=ol_textfontclass;
+	o3_captionfontclass=ol_captionfontclass;
+	o3_closefontclass=ol_closefontclass;
+	
+	setRunTimeVariables();
+	
+	fnRef = '';
+	
+	// Special for frame support, over must be reset...
+	o3_frame = ol_frame;
+	
+	if(!(over=createDivContainer())) return false;
+
+	parseTokens('o3_', overlib.arguments);
+	if (!postParseChecks()) return false;
+
+	if (o3_delay == 0) {
+		return runHook("olMain", FREPLACE);
+ 	} else {
+		o3_delayid = setTimeout("runHook('olMain', FREPLACE)", o3_delay);
+		return false;
+	}
+}
+
+// Clears popups if appropriate
+function nd(time) {
+	if (olLoaded && !isExclusive()) {
+		hideDelay(time);  // delay popup close if time specified
+
+		if (o3_removecounter >= 1) { o3_showingsticky = 0 };
+		
+		if (o3_showingsticky == 0) {
+			o3_allowmove = 0;
+			if (over != null && o3_timerid == 0) runHook("hideObject", FREPLACE, over);
+		} else {
+			o3_removecounter++;
+		}
+	}
+	
+	return true;
+}
+
+// The Close onMouseOver function for stickies
+function cClick() {
+	if (olLoaded) {
+		runHook("hideObject", FREPLACE, over);
+		o3_showingsticky = 0;	
+	}	
+	return false;
+}
+
+// Method for setting page specific defaults.
+function overlib_pagedefaults() {
+	parseTokens('ol_', overlib_pagedefaults.arguments);
+}
+
+
+////////
+// OVERLIB MAIN FUNCTION
+////////
+
+// This function decides what it is we want to display and how we want it done.
+function olMain() {
+	var layerhtml, styleType;
+ 	runHook("olMain", FBEFORE);
+ 	
+	if (o3_background!="" || o3_fullhtml) {
+		// Use background instead of box.
+		layerhtml = runHook('ol_content_background', FALTERNATE, o3_css, o3_text, o3_background, o3_fullhtml);
+	} else {
+		// They want a popup box.
+		styleType = (pms[o3_css-1-pmStart] == "cssoff" || pms[o3_css-1-pmStart] == "cssclass");
+
+		// Prepare popup background
+		if (o3_fgbackground != "") o3_fgbackground = "background=\""+o3_fgbackground+"\"";
+		if (o3_bgbackground != "") o3_bgbackground = (styleType ? "background=\""+o3_bgbackground+"\"" : o3_bgbackground);
+
+		// Prepare popup colors
+		if (o3_fgcolor != "") o3_fgcolor = (styleType ? "bgcolor=\""+o3_fgcolor+"\"" : o3_fgcolor);
+		if (o3_bgcolor != "") o3_bgcolor = (styleType ? "bgcolor=\""+o3_bgcolor+"\"" : o3_bgcolor);
+
+		// Prepare popup height
+		if (o3_height > 0) o3_height = (styleType ? "height=\""+o3_height+"\"" : o3_height);
+		else o3_height = "";
+
+		// Decide which kinda box.
+		if (o3_cap=="") {
+			// Plain
+			layerhtml = runHook('ol_content_simple', FALTERNATE, o3_css, o3_text);
+		} else {
+			// With caption
+			if (o3_sticky) {
+				// Show close text
+				layerhtml = runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, o3_close);
+			} else {
+				// No close text
+				layerhtml = runHook('ol_content_caption', FALTERNATE, o3_css, o3_text, o3_cap, "");
+			}
+		}
+	}	
+
+	// We want it to stick!
+	if (o3_sticky) {
+		if (o3_timerid > 0) {
+			clearTimeout(o3_timerid);
+			o3_timerid = 0;
+		}
+		o3_showingsticky = 1;
+		o3_removecounter = 0;
+	}
+
+	// Created a separate routine to generate the popup to make it easier
+	// to implement a plugin capability
+	if (!runHook("createPopup", FREPLACE, layerhtml)) return false;
+
+	// Prepare status bar
+	if (o3_autostatus > 0) {
+		o3_status = o3_text;
+		if (o3_autostatus > 1) o3_status = o3_cap;
+	}
+
+	// When placing the layer the first time, even stickies may be moved.
+	o3_allowmove = 0;
+
+	// Initiate a timer for timeout
+	if (o3_timeout > 0) {          
+		if (o3_timerid > 0) clearTimeout(o3_timerid);
+		o3_timerid = setTimeout("cClick()", o3_timeout);
+	}
+
+	// Show layer
+	runHook("disp", FREPLACE, o3_status);
+	runHook("olMain", FAFTER);
+
+	return (olOp && event && event.type == 'mouseover' && !o3_status) ? '' : (o3_status != '');
+}
+
+////////
+// LAYER GENERATION FUNCTIONS
+////////
+// These functions just handle popup content with tags that should adhere to the W3C standards specification.
+
+// Makes simple table without caption
+function ol_content_simple(text) {
+	var cpIsMultiple = /,/.test(o3_cellpad);
+	var txt = '<table width="'+o3_width+ '" border="0" cellpadding="'+o3_border+'" cellspacing="0" '+(o3_bgclass ? 'class="'+o3_bgclass+'"' : o3_bgcolor+' '+o3_height)+'><tr><td><table width="100%" border="0" '+((olNs4||!cpIsMultiple) ? 'cellpadding="'+o3_cellpad+'" ' : '')+'cellspacing="0" '+(o3_fgclass ? 'class="'+o3_fgclass+'"' : o3_fgcolor+' '+o3_fgbackground+' '+o3_height)+'><tr><td valign="TOP"'+(o3_textfontclass ? ' class="'+o3_textfontclass+'">' : ((!olNs4&&cpIsMultiple) ? ' style=" [...]
+
+	set_background("");
+	return txt;
+}
+
+// Makes table with caption and optional close link
+function ol_content_caption(text,title,close) {
+	var nameId, txt, cpIsMultiple = /,/.test(o3_cellpad);
+	var closing, closeevent;
+
+	closing = "";
+	closeevent = "onmouseover";
+	if (o3_closeclick == 1) closeevent = (o3_closetitle ? "title='" + o3_closetitle +"'" : "") + " onclick";
+	if (o3_capicon != "") {
+	  nameId = ' hspace = \"5\"'+' align = \"middle\" alt = \"\"';
+	  if (typeof o3_dragimg != 'undefined' && o3_dragimg) nameId =' hspace=\"5\"'+' name=\"'+o3_dragimg+'\" id=\"'+o3_dragimg+'\" align=\"middle\" alt=\"Drag Enabled\" title=\"Drag Enabled\"';
+	  o3_capicon = '<img src=\"'+o3_capicon+'\"'+nameId+' />';
+	}
+
+	if (close != "")
+		closing = '<td '+(!o3_compatmode && o3_closefontclass ? 'class="'+o3_closefontclass : 'align="RIGHT')+'"><a href="javascript:return '+fnRef+'cClick();"'+((o3_compatmode && o3_closefontclass) ? ' class="' + o3_closefontclass + '" ' : ' ')+closeevent+'="return '+fnRef+'cClick();">'+(o3_closefontclass ? '' : wrapStr(0,o3_closesize,'close'))+close+(o3_closefontclass ? '' : wrapStr(1,o3_closesize,'close'))+'</a></td>';
+	txt = '<table width="'+o3_width+ '" border="0" cellpadding="'+o3_border+'" cellspacing="0" '+(o3_bgclass ? 'class="'+o3_bgclass+'"' : o3_bgcolor+' '+o3_bgbackground+' '+o3_height)+'><tr><td><table width="100%" border="0" cellpadding="2" cellspacing="0"><tr><td'+(o3_captionfontclass ? ' class="'+o3_captionfontclass+'">' : '>')+(o3_captionfontclass ? '' : '<b>'+wrapStr(0,o3_captionsize,'caption'))+o3_capicon+title+(o3_captionfontclass ? '' : wrapStr(1,o3_captionsize)+'</b>')+'</td>'+closi [...]
+
+	set_background("");
+	return txt;
+}
+
+// Sets the background picture,padding and lots more. :)
+function ol_content_background(text,picture,hasfullhtml) {
+	if (hasfullhtml) {
+		txt=text;
+	} else {
+		txt='<table width="'+o3_width+'" border="0" cellpadding="0" cellspacing="0" height="'+o3_height+'"><tr><td colspan="3" height="'+o3_padyt+'"></td></tr><tr><td width="'+o3_padxl+'"></td><td valign="TOP" width="'+(o3_width-o3_padxl-o3_padxr)+(o3_textfontclass ? '" class="'+o3_textfontclass : '')+'">'+(o3_textfontclass ? '' : wrapStr(0,o3_textsize,'text'))+text+(o3_textfontclass ? '' : wrapStr(1,o3_textsize))+'</td><td width="'+o3_padxr+'"></td></tr><tr><td colspan="3" height="'+o3_padyb+ [...]
+	}
+
+	set_background(picture);
+	return txt;
+}
+
+// Loads a picture into the div.
+function set_background(pic) {
+	if (pic == "") {
+		if (olNs4) {
+			over.background.src = null; 
+		} else if (over.style) {
+			over.style.backgroundImage = "none";
+		}
+	} else {
+		if (olNs4) {
+			over.background.src = pic;
+		} else if (over.style) {
+			over.style.width=o3_width + 'px';
+			over.style.backgroundImage = "url("+pic+")";
+		}
+	}
+}
+
+////////
+// HANDLING FUNCTIONS
+////////
+var olShowId=-1;
+
+// Displays the popup
+function disp(statustext) {
+	runHook("disp", FBEFORE);
+	
+	if (o3_allowmove == 0) {
+		runHook("placeLayer", FREPLACE);
+		(olNs6&&olShowId<0) ? olShowId=setTimeout("runHook('showObject', FREPLACE, over)", 1) : runHook("showObject", FREPLACE, over);
+		o3_allowmove = (o3_sticky || o3_followmouse==0) ? 0 : 1;
+	}
+	
+	runHook("disp", FAFTER);
+
+	if (statustext != "") self.status = statustext;
+}
+
+// Creates the actual popup structure
+function createPopup(lyrContent){
+	runHook("createPopup", FBEFORE);
+	
+	if (o3_wrap) {
+		var wd,ww,theObj = (olNs4 ? over : over.style);
+		theObj.top = theObj.left = ((olIe4&&!olOp) ? 0 : -10000) + (!olNs4 ? 'px' : 0);
+		layerWrite(lyrContent);
+		wd = (olNs4 ? over.clip.width : over.offsetWidth);
+		if (wd > (ww=windowWidth())) {
+			lyrContent=lyrContent.replace(/\ /g, ' ');
+			o3_width=ww;
+			o3_wrap=0;
+		} 
+	}
+
+	layerWrite(lyrContent);
+	
+	// Have to set o3_width for placeLayer() routine if o3_wrap is turned on
+	if (o3_wrap) o3_width=(olNs4 ? over.clip.width : over.offsetWidth);
+	
+	runHook("createPopup", FAFTER, lyrContent);
+
+	return true;
+}
+
+// Decides where we want the popup.
+function placeLayer() {
+	var placeX, placeY, widthFix = 0;
+	
+	// HORIZONTAL PLACEMENT, re-arranged to work in Safari
+	if (o3_frame.innerWidth) widthFix=18; 
+	iwidth = windowWidth();
+
+	// Horizontal scroll offset
+	winoffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollLeft') : o3_frame.pageXOffset;
+
+	placeX = runHook('horizontalPlacement',FCHAIN,iwidth,winoffset,widthFix);
+
+	// VERTICAL PLACEMENT, re-arranged to work in Safari
+	if (o3_frame.innerHeight) {
+		iheight=o3_frame.innerHeight;
+	} else if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientHeight=='number'")&&eval('o3_frame.'+docRoot+'.clientHeight')) { 
+		iheight=eval('o3_frame.'+docRoot+'.clientHeight');
+	}			
+
+	// Vertical scroll offset
+	scrolloffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollTop') : o3_frame.pageYOffset;
+	placeY = runHook('verticalPlacement',FCHAIN,iheight,scrolloffset);
+
+	// Actually move the object.
+	repositionTo(over, placeX, placeY);
+}
+
+// Moves the layer
+function olMouseMove(e) {
+	var e = (e) ? e : event;
+
+	if (e.pageX) {
+		o3_x = e.pageX;
+		o3_y = e.pageY;
+	} else if (e.clientX) {
+		o3_x = eval('e.clientX+o3_frame.'+docRoot+'.scrollLeft');
+		o3_y = eval('e.clientY+o3_frame.'+docRoot+'.scrollTop');
+	}
+	
+	if (o3_allowmove == 1) runHook("placeLayer", FREPLACE);
+
+	// MouseOut handler
+	if (hoveringSwitch && !olNs4 && runHook("cursorOff", FREPLACE)) {
+		(olHideDelay ? hideDelay(olHideDelay) : cClick());
+		hoveringSwitch = !hoveringSwitch;
+	}
+}
+
+// Fake function for 3.0 users.
+function no_overlib() { return ver3fix; }
+
+// Capture the mouse and chain other scripts.
+function olMouseCapture() {
+	capExtent = document;
+	var fN, str = '', l, k, f, wMv, sS, mseHandler = olMouseMove;
+	var re = /function[ ]*(\w*)\(/;
+	
+	wMv = (!olIe4 && window.onmousemove);
+	if (document.onmousemove || wMv) {
+		if (wMv) capExtent = window;
+		f = capExtent.onmousemove.toString();
+		fN = f.match(re);
+		if (fN == null) {
+			str = f+'(e); ';
+		} else if (fN[1] == 'anonymous' || fN[1] == 'olMouseMove' || (wMv && fN[1] == 'onmousemove')) {
+			if (!olOp && wMv) {
+				l = f.indexOf('{')+1;
+				k = f.lastIndexOf('}');
+				sS = f.substring(l,k);
+				if ((l = sS.indexOf('(')) != -1) {
+					sS = sS.substring(0,l).replace(/^\s+/,'').replace(/\s+$/,'');
+					if (eval("typeof " + sS + " == 'undefined'")) window.onmousemove = null;
+					else str = sS + '(e);';
+				}
+			}
+			if (!str) {
+				olCheckMouseCapture = false;
+				return;
+			}
+		} else {
+			if (fN[1]) str = fN[1]+'(e); ';
+			else {
+				l = f.indexOf('{')+1;
+				k = f.lastIndexOf('}');
+				str = f.substring(l,k) + '\n';
+			}
+		}
+		str += 'olMouseMove(e); ';
+		mseHandler = new Function('e', str);
+	}
+
+	capExtent.onmousemove = mseHandler;
+	if (olNs4) capExtent.captureEvents(Event.MOUSEMOVE);
+}
+
+////////
+// PARSING FUNCTIONS
+////////
+
+// Does the actual command parsing.
+function parseTokens(pf, ar) {
+	// What the next argument is expected to be.
+	var v, i, mode=-1, par = (pf != 'ol_');	
+	var fnMark = (par && !ar.length ? 1 : 0);
+
+	for (i = 0; i < ar.length; i++) {
+		if (mode < 0) {
+			// Arg is maintext,unless its a number between pmStart and pmUpper
+			// then its a command.
+			if (typeof ar[i] == 'number' && ar[i] > pmStart && ar[i] < pmUpper) {
+				fnMark = (par ? 1 : 0);
+				i--;   // backup one so that the next block can parse it
+			} else {
+				switch(pf) {
+					case 'ol_':
+						ol_text = ar[i].toString();
+						break;
+					default:
+						o3_text=ar[i].toString();  
+				}
+			}
+			mode = 0;
+		} else {
+			// Note: NS4 doesn't like switch cases with vars.
+			if (ar[i] >= pmCount || ar[i]==DONOTHING) { continue; }
+			if (ar[i]==INARRAY) { fnMark = 0; eval(pf+'text=ol_texts['+ar[++i]+'].toString()'); continue; }
+			if (ar[i]==CAPARRAY) { eval(pf+'cap=ol_caps['+ar[++i]+'].toString()'); continue; }
+			if (ar[i]==STICKY) { if (pf!='ol_') eval(pf+'sticky=1'); continue; }
+			if (ar[i]==BACKGROUND) { eval(pf+'background="'+ar[++i]+'"'); continue; }
+			if (ar[i]==NOCLOSE) { if (pf!='ol_') opt_NOCLOSE(); continue; }
+			if (ar[i]==CAPTION) { eval(pf+"cap='"+escSglQuote(ar[++i])+"'"); continue; }
+			if (ar[i]==CENTER || ar[i]==LEFT || ar[i]==RIGHT) { eval(pf+'hpos='+ar[i]); if(pf!='ol_') olHautoFlag=1; continue; }
+			if (ar[i]==OFFSETX) { eval(pf+'offsetx='+ar[++i]); continue; }
+			if (ar[i]==OFFSETY) { eval(pf+'offsety='+ar[++i]); continue; }
+			if (ar[i]==FGCOLOR) { eval(pf+'fgcolor="'+ar[++i]+'"'); continue; }
+			if (ar[i]==BGCOLOR) { eval(pf+'bgcolor="'+ar[++i]+'"'); continue; }
+			if (ar[i]==TEXTCOLOR) { eval(pf+'textcolor="'+ar[++i]+'"'); continue; }
+			if (ar[i]==CAPCOLOR) { eval(pf+'capcolor="'+ar[++i]+'"'); continue; }
+			if (ar[i]==CLOSECOLOR) { eval(pf+'closecolor="'+ar[++i]+'"'); continue; }
+			if (ar[i]==WIDTH) { eval(pf+'width='+ar[++i]); continue; }
+			if (ar[i]==BORDER) { eval(pf+'border='+ar[++i]); continue; }
+			if (ar[i]==CELLPAD) { i=opt_MULTIPLEARGS(++i,ar,(pf+'cellpad')); continue; }
+			if (ar[i]==STATUS) { eval(pf+"status='"+escSglQuote(ar[++i])+"'"); continue; }
+			if (ar[i]==AUTOSTATUS) { eval(pf +'autostatus=('+pf+'autostatus == 1) ? 0 : 1'); continue; }
+			if (ar[i]==AUTOSTATUSCAP) { eval(pf +'autostatus=('+pf+'autostatus == 2) ? 0 : 2'); continue; }
+			if (ar[i]==HEIGHT) { eval(pf+'height='+pf+'aboveheight='+ar[++i]); continue; } // Same param again.
+			if (ar[i]==CLOSETEXT) { eval(pf+"close='"+escSglQuote(ar[++i])+"'"); continue; }
+			if (ar[i]==SNAPX) { eval(pf+'snapx='+ar[++i]); continue; }
+			if (ar[i]==SNAPY) { eval(pf+'snapy='+ar[++i]); continue; }
+			if (ar[i]==FIXX) { eval(pf+'fixx='+ar[++i]); continue; }
+			if (ar[i]==FIXY) { eval(pf+'fixy='+ar[++i]); continue; }
+			if (ar[i]==RELX) { eval(pf+'relx='+ar[++i]); continue; }
+			if (ar[i]==RELY) { eval(pf+'rely='+ar[++i]); continue; }
+			if (ar[i]==FGBACKGROUND) { eval(pf+'fgbackground="'+ar[++i]+'"'); continue; }
+			if (ar[i]==BGBACKGROUND) { eval(pf+'bgbackground="'+ar[++i]+'"'); continue; }
+			if (ar[i]==PADX) { eval(pf+'padxl='+ar[++i]); eval(pf+'padxr='+ar[++i]); continue; }
+			if (ar[i]==PADY) { eval(pf+'padyt='+ar[++i]); eval(pf+'padyb='+ar[++i]); continue; }
+			if (ar[i]==FULLHTML) { if (pf!='ol_') eval(pf+'fullhtml=1'); continue; }
+			if (ar[i]==BELOW || ar[i]==ABOVE) { eval(pf+'vpos='+ar[i]); if (pf!='ol_') olVautoFlag=1; continue; }
+			if (ar[i]==CAPICON) { eval(pf+'capicon="'+ar[++i]+'"'); continue; }
+			if (ar[i]==TEXTFONT) { eval(pf+"textfont='"+escSglQuote(ar[++i])+"'"); continue; }
+			if (ar[i]==CAPTIONFONT) { eval(pf+"captionfont='"+escSglQuote(ar[++i])+"'"); continue; }
+			if (ar[i]==CLOSEFONT) { eval(pf+"closefont='"+escSglQuote(ar[++i])+"'"); continue; }
+			if (ar[i]==TEXTSIZE) { eval(pf+'textsize="'+ar[++i]+'"'); continue; }
+			if (ar[i]==CAPTIONSIZE) { eval(pf+'captionsize="'+ar[++i]+'"'); continue; }
+			if (ar[i]==CLOSESIZE) { eval(pf+'closesize="'+ar[++i]+'"'); continue; }
+			if (ar[i]==TIMEOUT) { eval(pf+'timeout='+ar[++i]); continue; }
+			if (ar[i]==FUNCTION) { if (pf=='ol_') { if (typeof ar[i+1]!='number') { v=ar[++i]; ol_function=(typeof v=='function' ? v : null); }} else {fnMark = 0; v = null; if (typeof ar[i+1]!='number') v = ar[++i];  opt_FUNCTION(v); } continue; }
+			if (ar[i]==DELAY) { eval(pf+'delay='+ar[++i]); continue; }
+			if (ar[i]==HAUTO) { eval(pf+'hauto=('+pf+'hauto == 0) ? 1 : 0'); continue; }
+			if (ar[i]==VAUTO) { eval(pf+'vauto=('+pf+'vauto == 0) ? 1 : 0'); continue; }
+			if (ar[i]==CLOSECLICK) { eval(pf +'closeclick=('+pf+'closeclick == 0) ? 1 : 0'); continue; }
+			if (ar[i]==WRAP) { eval(pf +'wrap=('+pf+'wrap == 0) ? 1 : 0'); continue; }
+			if (ar[i]==FOLLOWMOUSE) { eval(pf +'followmouse=('+pf+'followmouse == 1) ? 0 : 1'); continue; }
+			if (ar[i]==MOUSEOFF) { eval(pf +'mouseoff=('+pf+'mouseoff==0) ? 1 : 0'); v=ar[i+1]; if (pf != 'ol_' && eval(pf+'mouseoff') && typeof v == 'number' && (v < pmStart || v > pmUpper)) olHideDelay=ar[++i]; continue; }
+			if (ar[i]==CLOSETITLE) { eval(pf+"closetitle='"+escSglQuote(ar[++i])+"'"); continue; }
+			if (ar[i]==CSSOFF||ar[i]==CSSCLASS) { eval(pf+'css='+ar[i]); continue; }
+			if (ar[i]==COMPATMODE) { eval(pf+'compatmode=('+pf+'compatmode==0) ? 1 : 0'); continue; }
+			if (ar[i]==FGCLASS) { eval(pf+'fgclass="'+ar[++i]+'"'); continue; }
+			if (ar[i]==BGCLASS) { eval(pf+'bgclass="'+ar[++i]+'"'); continue; }
+			if (ar[i]==TEXTFONTCLASS) { eval(pf+'textfontclass="'+ar[++i]+'"'); continue; }
+			if (ar[i]==CAPTIONFONTCLASS) { eval(pf+'captionfontclass="'+ar[++i]+'"'); continue; }
+			if (ar[i]==CLOSEFONTCLASS) { eval(pf+'closefontclass="'+ar[++i]+'"'); continue; }
+			i = parseCmdLine(pf, i, ar);
+		}
+	}
+
+	if (fnMark && o3_function) o3_text = o3_function();
+	
+	if ((pf == 'o3_') && o3_wrap) {
+		o3_width = 0;
+		
+		var tReg=/<.*\n*>/ig;
+		if (!tReg.test(o3_text)) o3_text = o3_text.replace(/[ ]+/g, ' ');
+		if (!tReg.test(o3_cap))o3_cap = o3_cap.replace(/[ ]+/g, ' ');
+	}
+	if ((pf == 'o3_') && o3_sticky) {
+		if (!o3_close && (o3_frame != ol_frame)) o3_close = ol_close;
+		if (o3_mouseoff && (o3_frame == ol_frame)) opt_NOCLOSE(' ');
+	}
+}
+
+
+////////
+// LAYER FUNCTIONS
+////////
+
+// Writes to a layer
+function layerWrite(txt) {
+	txt += "\n";
+	if (olNs4) {
+		var lyr = o3_frame.document.layers['overDiv'].document
+		lyr.write(txt)
+		lyr.close()
+	} else if (typeof over.innerHTML != 'undefined') {
+		if (olIe5 && isMac) over.innerHTML = '';
+		over.innerHTML = txt;
+	} else {
+		range = o3_frame.document.createRange();
+		range.setStartAfter(over);
+		domfrag = range.createContextualFragment(txt);
+		
+		while (over.hasChildNodes()) {
+			over.removeChild(over.lastChild);
+		}
+		
+		over.appendChild(domfrag);
+	}
+}
+
+// Make an object visible
+function showObject(obj) {
+	runHook("showObject", FBEFORE);
+
+	var theObj=(olNs4 ? obj : obj.style);
+	theObj.visibility = 'visible';
+
+	runHook("showObject", FAFTER);
+}
+
+// Hides an object
+function hideObject(obj) {
+	runHook("hideObject", FBEFORE);
+
+	var theObj=(olNs4 ? obj : obj.style);
+	if (olNs6 && olShowId>0) { clearTimeout(olShowId); olShowId=0; }
+	theObj.visibility = 'hidden';
+	theObj.top = theObj.left = ((olIe4&&!olOp) ? 0 : -10000) + (!olNs4 ? 'px' : 0);
+
+	if (o3_timerid > 0) clearTimeout(o3_timerid);
+	if (o3_delayid > 0) clearTimeout(o3_delayid);
+
+	o3_timerid = 0;
+	o3_delayid = 0;
+	self.status = "";
+
+	if (obj.onmouseout||obj.onmouseover) {
+		if (olNs4) obj.releaseEvents(Event.MOUSEOUT || Event.MOUSEOVER);
+		obj.onmouseout = obj.onmouseover = null;
+	}
+
+	runHook("hideObject", FAFTER);
+}
+
+// Move a layer
+function repositionTo(obj, xL, yL) {
+	var theObj=(olNs4 ? obj : obj.style);
+	theObj.left = xL + (!olNs4 ? 'px' : 0);
+	theObj.top = yL + (!olNs4 ? 'px' : 0);
+}
+
+// Check position of cursor relative to overDiv DIVision; mouseOut function
+function cursorOff() {
+	var left = parseInt(over.style.left);
+	var top = parseInt(over.style.top);
+	var right = left + (over.offsetWidth >= parseInt(o3_width) ? over.offsetWidth : parseInt(o3_width));
+	var bottom = top + (over.offsetHeight >= o3_aboveheight ? over.offsetHeight : o3_aboveheight);
+
+	if (o3_x < left || o3_x > right || o3_y < top || o3_y > bottom) return true;
+
+	return false;
+}
+
+
+////////
+// COMMAND FUNCTIONS
+////////
+
+// Calls callme or the default function.
+function opt_FUNCTION(callme) {
+	o3_text = (callme ? (typeof callme=='string' ? (/.+\(.*\)/.test(callme) ? eval(callme) : callme) : callme()) : (o3_function ? o3_function() : 'No Function'));
+
+	return 0;
+}
+
+// Handle hovering
+function opt_NOCLOSE(unused) {
+	if (!unused) o3_close = "";
+
+	if (olNs4) {
+		over.captureEvents(Event.MOUSEOUT || Event.MOUSEOVER);
+		over.onmouseover = function () { if (o3_timerid > 0) { clearTimeout(o3_timerid); o3_timerid = 0; } }
+		over.onmouseout = function (e) { if (olHideDelay) hideDelay(olHideDelay); else cClick(e); }
+	} else {
+		over.onmouseover = function () {hoveringSwitch = true; if (o3_timerid > 0) { clearTimeout(o3_timerid); o3_timerid =0; } }
+	}
+
+	return 0;
+}
+
+// Function to scan command line arguments for multiples
+function opt_MULTIPLEARGS(i, args, parameter) {
+  var k=i, re, pV, str='';
+
+  for(k=i; k<args.length; k++) {
+		if(typeof args[k] == 'number' && args[k]>pmStart) break;
+		str += args[k] + ',';
+	}
+	if (str) str = str.substring(0,--str.length);
+
+	k--;  // reduce by one so the for loop this is in works correctly
+	pV=(olNs4 && /cellpad/i.test(parameter)) ? str.split(',')[0] : str;
+	eval(parameter + '="' + pV + '"');
+
+	return k;
+}
+
+// Remove   in texts when done.
+function nbspCleanup() {
+	if (o3_wrap) {
+		o3_text = o3_text.replace(/\ /g, ' ');
+		o3_cap = o3_cap.replace(/\ /g, ' ');
+	}
+}
+
+// Escape embedded single quotes in text strings
+function escSglQuote(str) {
+  return str.toString().replace(/'/g,"\\'");
+}
+
+// Onload handler for window onload event
+function OLonLoad_handler(e) {
+	var re = /\w+\(.*\)[;\s]+/g, olre = /overlib\(|nd\(|cClick\(/, fn, l, i;
+
+	if(!olLoaded) olLoaded=1;
+
+  // Remove it for Gecko based browsers
+	if(window.removeEventListener && e.eventPhase == 3) window.removeEventListener("load",OLonLoad_handler,false);
+	else if(window.detachEvent) { // and for IE and Opera 4.x but execute calls to overlib, nd, or cClick()
+		window.detachEvent("onload",OLonLoad_handler);
+		var fN = document.body.getAttribute('onload');
+		if (fN) {
+			fN=fN.toString().match(re);
+			if (fN && fN.length) {
+				for (i=0; i<fN.length; i++) {
+					if (/anonymous/.test(fN[i])) continue;
+					while((l=fN[i].search(/\)[;\s]+/)) != -1) {
+						fn=fN[i].substring(0,l+1);
+						fN[i] = fN[i].substring(l+2);
+						if (olre.test(fn)) eval(fn);
+					}
+				}
+			}
+		}
+	}
+}
+
+// Wraps strings in Layer Generation Functions with the correct tags
+//    endWrap true(if end tag) or false if start tag
+//    fontSizeStr - font size string such as '1' or '10px'
+//    whichString is being wrapped -- 'text', 'caption', or 'close'
+function wrapStr(endWrap,fontSizeStr,whichString) {
+	var fontStr, fontColor, isClose=((whichString=='close') ? 1 : 0), hasDims=/[%\-a-z]+$/.test(fontSizeStr);
+	fontSizeStr = (olNs4) ? (!hasDims ? fontSizeStr : '1') : fontSizeStr;
+	if (endWrap) return (hasDims&&!olNs4) ? (isClose ? '</span>' : '</div>') : '</font>';
+	else {
+		fontStr='o3_'+whichString+'font';
+		fontColor='o3_'+((whichString=='caption')? 'cap' : whichString)+'color';
+		return (hasDims&&!olNs4) ? (isClose ? '<span style="font-family: '+quoteMultiNameFonts(eval(fontStr))+'; color: '+eval(fontColor)+'; font-size: '+fontSizeStr+';">' : '<div style="font-family: '+quoteMultiNameFonts(eval(fontStr))+'; color: '+eval(fontColor)+'; font-size: '+fontSizeStr+';">') : '<font face="'+eval(fontStr)+'" color="'+eval(fontColor)+'" size="'+(parseInt(fontSizeStr)>7 ? '7' : fontSizeStr)+'">';
+	}
+}
+
+// Quotes Multi word font names; needed for CSS Standards adherence in font-family
+function quoteMultiNameFonts(theFont) {
+	var v, pM=theFont.split(',');
+	for (var i=0; i<pM.length; i++) {
+		v=pM[i];
+		v=v.replace(/^\s+/,'').replace(/\s+$/,'');
+		if(/\s/.test(v) && !/['"]/.test(v)) {
+			v="\'"+v+"\'";
+			pM[i]=v;
+		}
+	}
+	return pM.join();
+}
+
+// dummy function which will be overridden 
+function isExclusive(args) {
+	return false;
+}
+
+// Sets cellpadding style string value
+function setCellPadStr(parameter) {
+	var Str='', j=0, ary = new Array(), top, bottom, left, right;
+
+	Str+='padding: ';
+	ary=parameter.replace(/\s+/g,'').split(',');
+
+	switch(ary.length) {
+		case 2:
+			top=bottom=ary[j];
+			left=right=ary[++j];
+			break;
+		case 3:
+			top=ary[j];
+			left=right=ary[++j];
+			bottom=ary[++j];
+			break;
+		case 4:
+			top=ary[j];
+			right=ary[++j];
+			bottom=ary[++j];
+			left=ary[++j];
+			break;
+	}
+
+	Str+= ((ary.length==1) ? ary[0] + 'px;' : top + 'px ' + right + 'px ' + bottom + 'px ' + left + 'px;');
+
+	return Str;
+}
+
+// function will delay close by time milliseconds
+function hideDelay(time) {
+	if (time&&!o3_delay) {
+		if (o3_timerid > 0) clearTimeout(o3_timerid);
+
+		o3_timerid=setTimeout("cClick()",(o3_timeout=time));
+	}
+}
+
+// Was originally in the placeLayer() routine; separated out for future ease
+function horizontalPlacement(browserWidth, horizontalScrollAmount, widthFix) {
+	var placeX, iwidth=browserWidth, winoffset=horizontalScrollAmount;
+	var parsedWidth = parseInt(o3_width);
+
+	if (o3_fixx > -1 || o3_relx != null) {
+		// Fixed position
+		placeX=(o3_relx != null ? ( o3_relx < 0 ? winoffset +o3_relx+ iwidth - parsedWidth - widthFix : winoffset+o3_relx) : o3_fixx);
+	} else {  
+		// If HAUTO, decide what to use.
+		if (o3_hauto == 1) {
+			if ((o3_x - winoffset) > (iwidth / 2)) {
+				o3_hpos = LEFT;
+			} else {
+				o3_hpos = RIGHT;
+			}
+		}  		
+
+		// From mouse
+		if (o3_hpos == CENTER) { // Center
+			placeX = o3_x+o3_offsetx-(parsedWidth/2);
+
+			if (placeX < winoffset) placeX = winoffset;
+		}
+
+		if (o3_hpos == RIGHT) { // Right
+			placeX = o3_x+o3_offsetx;
+
+			if ((placeX+parsedWidth) > (winoffset+iwidth - widthFix)) {
+				placeX = iwidth+winoffset - parsedWidth - widthFix;
+				if (placeX < 0) placeX = 0;
+			}
+		}
+		if (o3_hpos == LEFT) { // Left
+			placeX = o3_x-o3_offsetx-parsedWidth;
+			if (placeX < winoffset) placeX = winoffset;
+		}  	
+
+		// Snapping!
+		if (o3_snapx > 1) {
+			var snapping = placeX % o3_snapx;
+
+			if (o3_hpos == LEFT) {
+				placeX = placeX - (o3_snapx+snapping);
+			} else {
+				// CENTER and RIGHT
+				placeX = placeX+(o3_snapx - snapping);
+			}
+
+			if (placeX < winoffset) placeX = winoffset;
+		}
+	}	
+
+	return placeX;
+}
+
+// was originally in the placeLayer() routine; separated out for future ease
+function verticalPlacement(browserHeight,verticalScrollAmount) {
+	var placeY, iheight=browserHeight, scrolloffset=verticalScrollAmount;
+	var parsedHeight=(o3_aboveheight ? parseInt(o3_aboveheight) : (olNs4 ? over.clip.height : over.offsetHeight));
+
+	if (o3_fixy > -1 || o3_rely != null) {
+		// Fixed position
+		placeY=(o3_rely != null ? (o3_rely < 0 ? scrolloffset+o3_rely+iheight - parsedHeight : scrolloffset+o3_rely) : o3_fixy);
+	} else {
+		// If VAUTO, decide what to use.
+		if (o3_vauto == 1) {
+			if ((o3_y - scrolloffset) > (iheight / 2) && o3_vpos == BELOW && (o3_y + parsedHeight + o3_offsety - (scrolloffset + iheight) > 0)) {
+				o3_vpos = ABOVE;
+			} else if (o3_vpos == ABOVE && (o3_y - (parsedHeight + o3_offsety) - scrolloffset < 0)) {
+				o3_vpos = BELOW;
+			}
+		}
+
+		// From mouse
+		if (o3_vpos == ABOVE) {
+			if (o3_aboveheight == 0) o3_aboveheight = parsedHeight; 
+
+			placeY = o3_y - (o3_aboveheight+o3_offsety);
+			if (placeY < scrolloffset) placeY = scrolloffset;
+		} else {
+			// BELOW
+			placeY = o3_y+o3_offsety;
+		} 
+
+		// Snapping!
+		if (o3_snapy > 1) {
+			var snapping = placeY % o3_snapy;  			
+
+			if (o3_aboveheight > 0 && o3_vpos == ABOVE) {
+				placeY = placeY - (o3_snapy+snapping);
+			} else {
+				placeY = placeY+(o3_snapy - snapping);
+			} 			
+
+			if (placeY < scrolloffset) placeY = scrolloffset;
+		}
+	}
+
+	return placeY;
+}
+
+// checks positioning flags
+function checkPositionFlags() {
+	if (olHautoFlag) olHautoFlag = o3_hauto=0;
+	if (olVautoFlag) olVautoFlag = o3_vauto=0;
+	return true;
+}
+
+// get Browser window width
+function windowWidth() {
+	var w;
+	if (o3_frame.innerWidth) w=o3_frame.innerWidth;
+	else if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientWidth=='number'")&&eval('o3_frame.'+docRoot+'.clientWidth')) 
+		w=eval('o3_frame.'+docRoot+'.clientWidth');
+	return w;			
+}
+
+// create the div container for popup content if it doesn't exist
+function createDivContainer(id,frm,zValue) {
+	id = (id || 'overDiv'), frm = (frm || o3_frame), zValue = (zValue || 1000);
+	var objRef, divContainer = layerReference(id);
+
+	if (divContainer == null) {
+		if (olNs4) {
+			divContainer = frm.document.layers[id] = new Layer(window.innerWidth, frm);
+			objRef = divContainer;
+		} else {
+			var body = (olIe4 ? frm.document.all.tags('BODY')[0] : frm.document.getElementsByTagName("BODY")[0]);
+			if (olIe4&&!document.getElementById) {
+				body.insertAdjacentHTML("beforeEnd",'<div id="'+id+'"></div>');
+				divContainer=layerReference(id);
+			} else {
+				divContainer = frm.document.createElement("DIV");
+				divContainer.id = id;
+				body.appendChild(divContainer);
+			}
+			objRef = divContainer.style;
+		}
+
+		objRef.position = 'absolute';
+		objRef.visibility = 'hidden';
+		objRef.zIndex = zValue;
+		if (olIe4&&!olOp) objRef.left = objRef.top = '0px';
+		else objRef.left = objRef.top =  -10000 + (!olNs4 ? 'px' : 0);
+	}
+
+	return divContainer;
+}
+
+// get reference to a layer with ID=id
+function layerReference(id) {
+	return (olNs4 ? o3_frame.document.layers[id] : (document.all ? o3_frame.document.all[id] : o3_frame.document.getElementById(id)));
+}
+////////
+//  UTILITY FUNCTIONS
+////////
+
+// Checks if something is a function.
+function isFunction(fnRef) {
+	var rtn = true;
+
+	if (typeof fnRef == 'object') {
+		for (var i = 0; i < fnRef.length; i++) {
+			if (typeof fnRef[i]=='function') continue;
+			rtn = false;
+			break;
+		}
+	} else if (typeof fnRef != 'function') {
+		rtn = false;
+	}
+	
+	return rtn;
+}
+
+// Converts an array into an argument string for use in eval.
+function argToString(array, strtInd, argName) {
+	var jS = strtInd, aS = '', ar = array;
+	argName=(argName ? argName : 'ar');
+	
+	if (ar.length > jS) {
+		for (var k = jS; k < ar.length; k++) aS += argName+'['+k+'], ';
+		aS = aS.substring(0, aS.length-2);
+	}
+	
+	return aS;
+}
+
+// Places a hook in the correct position in a hook point.
+function reOrder(hookPt, fnRef, order) {
+	var newPt = new Array(), match, i, j;
+
+	if (!order || typeof order == 'undefined' || typeof order == 'number') return hookPt;
+	
+	if (typeof order=='function') {
+		if (typeof fnRef=='object') {
+			newPt = newPt.concat(fnRef);
+		} else {
+			newPt[newPt.length++]=fnRef;
+		}
+		
+		for (i = 0; i < hookPt.length; i++) {
+			match = false;
+			if (typeof fnRef == 'function' && hookPt[i] == fnRef) {
+				continue;
+			} else {
+				for(j = 0; j < fnRef.length; j++) if (hookPt[i] == fnRef[j]) {
+					match = true;
+					break;
+				}
+			}
+			if (!match) newPt[newPt.length++] = hookPt[i];
+		}
+
+		newPt[newPt.length++] = order;
+
+	} else if (typeof order == 'object') {
+		if (typeof fnRef == 'object') {
+			newPt = newPt.concat(fnRef);
+		} else {
+			newPt[newPt.length++] = fnRef;
+		}
+		
+		for (j = 0; j < hookPt.length; j++) {
+			match = false;
+			if (typeof fnRef == 'function' && hookPt[j] == fnRef) {
+				continue;
+			} else {
+				for (i = 0; i < fnRef.length; i++) if (hookPt[j] == fnRef[i]) {
+					match = true;
+					break;
+				}
+			}
+			if (!match) newPt[newPt.length++]=hookPt[j];
+		}
+
+		for (i = 0; i < newPt.length; i++) hookPt[i] = newPt[i];
+		newPt.length = 0;
+		
+		for (j = 0; j < hookPt.length; j++) {
+			match = false;
+			for (i = 0; i < order.length; i++) {
+				if (hookPt[j] == order[i]) {
+					match = true;
+					break;
+				}
+			}
+			if (!match) newPt[newPt.length++] = hookPt[j];
+		}
+		newPt = newPt.concat(order);
+	}
+
+	hookPt = newPt;
+
+	return hookPt;
+}
+
+////////
+//  PLUGIN ACTIVATION FUNCTIONS
+////////
+
+// Runs plugin functions to set runtime variables.
+function setRunTimeVariables(){
+	if (typeof runTime != 'undefined' && runTime.length) {
+		for (var k = 0; k < runTime.length; k++) {
+			runTime[k]();
+		}
+	}
+}
+
+// Runs plugin functions to parse commands.
+function parseCmdLine(pf, i, args) {
+	if (typeof cmdLine != 'undefined' && cmdLine.length) { 
+		for (var k = 0; k < cmdLine.length; k++) { 
+			var j = cmdLine[k](pf, i, args);
+			if (j >- 1) {
+				i = j;
+				break;
+			}
+		}
+	}
+
+	return i;
+}
+
+// Runs plugin functions to do things after parse.
+function postParseChecks(pf,args){
+	if (typeof postParse != 'undefined' && postParse.length) {
+		for (var k = 0; k < postParse.length; k++) {
+			if (postParse[k](pf,args)) continue;
+			return false;  // end now since have an error
+		}
+	}
+	return true;
+}
+
+
+////////
+//  PLUGIN REGISTRATION FUNCTIONS
+////////
+
+// Registers commands and creates constants.
+function registerCommands(cmdStr) {
+	if (typeof cmdStr!='string') return;
+
+	var pM = cmdStr.split(',');
+	pms = pms.concat(pM);
+
+	for (var i = 0; i< pM.length; i++) {
+		eval(pM[i].toUpperCase()+'='+pmCount++);
+	}
+}
+
+// Registers no-parameter commands
+function registerNoParameterCommands(cmdStr) {
+	if (!cmdStr && typeof cmdStr != 'string') return;
+	pmt=(!pmt) ? cmdStr : pmt + ',' + cmdStr;
+}
+
+// Register a function to hook at a certain point.
+function registerHook(fnHookTo, fnRef, hookType, optPm) {
+	var hookPt, last = typeof optPm;
+	
+	if (fnHookTo == 'plgIn'||fnHookTo == 'postParse') return;
+	if (typeof hookPts[fnHookTo] == 'undefined') hookPts[fnHookTo] = new FunctionReference();
+
+	hookPt = hookPts[fnHookTo];
+
+	if (hookType != null) {
+		if (hookType == FREPLACE) {
+			hookPt.ovload = fnRef;  // replace normal overlib routine
+			if (fnHookTo.indexOf('ol_content_') > -1) hookPt.alt[pms[CSSOFF-1-pmStart]]=fnRef; 
+
+		} else if (hookType == FBEFORE || hookType == FAFTER) {
+			var hookPt=(hookType == 1 ? hookPt.before : hookPt.after);
+
+			if (typeof fnRef == 'object') {
+				hookPt = hookPt.concat(fnRef);
+			} else {
+				hookPt[hookPt.length++] = fnRef;
+			}
+
+			if (optPm) hookPt = reOrder(hookPt, fnRef, optPm);
+
+		} else if (hookType == FALTERNATE) {
+			if (last=='number') hookPt.alt[pms[optPm-1-pmStart]] = fnRef;
+		} else if (hookType == FCHAIN) {
+			hookPt = hookPt.chain; 
+			if (typeof fnRef=='object') hookPt=hookPt.concat(fnRef); // add other functions 
+			else hookPt[hookPt.length++]=fnRef;
+		}
+
+		return;
+	}
+}
+
+// Register a function that will set runtime variables.
+function registerRunTimeFunction(fn) {
+	if (isFunction(fn)) {
+		if (typeof fn == 'object') {
+			runTime = runTime.concat(fn);
+		} else {
+			runTime[runTime.length++] = fn;
+		}
+	}
+}
+
+// Register a function that will handle command parsing.
+function registerCmdLineFunction(fn){
+	if (isFunction(fn)) {
+		if (typeof fn == 'object') {
+			cmdLine = cmdLine.concat(fn);
+		} else {
+			cmdLine[cmdLine.length++] = fn;
+		}
+	}
+}
+
+// Register a function that does things after command parsing. 
+function registerPostParseFunction(fn){
+	if (isFunction(fn)) {
+		if (typeof fn == 'object') {
+			postParse = postParse.concat(fn);
+		} else {
+			postParse[postParse.length++] = fn;
+		}
+	}
+}
+
+////////
+//  PLUGIN REGISTRATION FUNCTIONS
+////////
+
+// Runs any hooks registered.
+function runHook(fnHookTo, hookType) {
+	var l = hookPts[fnHookTo], k, rtnVal = null, optPm, arS, ar = runHook.arguments;
+
+	if (hookType == FREPLACE) {
+		arS = argToString(ar, 2);
+
+		if (typeof l == 'undefined' || !(l = l.ovload)) rtnVal = eval(fnHookTo+'('+arS+')');
+		else rtnVal = eval('l('+arS+')');
+
+	} else if (hookType == FBEFORE || hookType == FAFTER) {
+		if (typeof l != 'undefined') {
+			l=(hookType == 1 ? l.before : l.after);
+	
+			if (l.length) {
+				arS = argToString(ar, 2);
+				for (var k = 0; k < l.length; k++) eval('l[k]('+arS+')');
+			}
+		}
+	} else if (hookType == FALTERNATE) {
+		optPm = ar[2];
+		arS = argToString(ar, 3);
+
+		if (typeof l == 'undefined' || (l = l.alt[pms[optPm-1-pmStart]]) == 'undefined') {
+			rtnVal = eval(fnHookTo+'('+arS+')');
+		} else {
+			rtnVal = eval('l('+arS+')');
+		}
+	} else if (hookType == FCHAIN) {
+		arS=argToString(ar,2);
+		l=l.chain;
+
+		for (k=l.length; k > 0; k--) if((rtnVal=eval('l[k-1]('+arS+')'))!=void(0)) break;
+	}
+
+	return rtnVal;
+}
+
+////////
+// OBJECT CONSTRUCTORS
+////////
+
+// Object for handling hooks.
+function FunctionReference() {
+	this.ovload = null;
+	this.before = new Array();
+	this.after = new Array();
+	this.alt = new Array();
+	this.chain = new Array();
+}
+
+// Object for simple access to the overLIB version used.
+// Examples: simpleversion:351 major:3 minor:5 revision:1
+function Info(version, prerelease) {
+	this.version = version;
+	this.prerelease = prerelease;
+
+	this.simpleversion = Math.round(this.version*100);
+	this.major = parseInt(this.simpleversion / 100);
+	this.minor = parseInt(this.simpleversion / 10) - this.major * 10;
+	this.revision = parseInt(this.simpleversion) - this.major * 100 - this.minor * 10;
+	this.meets = meets;
+}
+
+// checks for Core Version required
+function meets(reqdVersion) {
+	return (!reqdVersion) ? false : this.simpleversion >= Math.round(100*parseFloat(reqdVersion));
+}
+
+
+////////
+// STANDARD REGISTRATIONS
+////////
+registerHook("ol_content_simple", ol_content_simple, FALTERNATE, CSSOFF);
+registerHook("ol_content_caption", ol_content_caption, FALTERNATE, CSSOFF);
+registerHook("ol_content_background", ol_content_background, FALTERNATE, CSSOFF);
+registerHook("ol_content_simple", ol_content_simple, FALTERNATE, CSSCLASS);
+registerHook("ol_content_caption", ol_content_caption, FALTERNATE, CSSCLASS);
+registerHook("ol_content_background", ol_content_background, FALTERNATE, CSSCLASS);
+registerPostParseFunction(checkPositionFlags);
+registerHook("hideObject", nbspCleanup, FAFTER);
+registerHook("horizontalPlacement", horizontalPlacement, FCHAIN);
+registerHook("verticalPlacement", verticalPlacement, FCHAIN);
+if (olNs4||(olIe5&&isMac)||olKq) olLoaded=1;
+registerNoParameterCommands('sticky,autostatus,autostatuscap,fullhtml,hauto,vauto,closeclick,wrap,followmouse,mouseoff,compatmode');
+///////
+// ESTABLISH MOUSECAPTURING
+///////
+
+// Capture events, alt. diffuses the overlib function.
+var olCheckMouseCapture=true;
+if ((olNs4 || olNs6 || olIe4)) {
+	olMouseCapture();
+} else {
+	overlib = no_overlib;
+	nd = no_overlib;
+	ver3fix = true;
+}
diff --git a/OpenFreezer/overlib/overlib421.zip b/OpenFreezer/overlib/overlib421.zip
new file mode 100755
index 0000000..f393bb8
Binary files /dev/null and b/OpenFreezer/overlib/overlib421.zip differ
diff --git a/OpenFreezer/overlib/overlibCompat.js b/OpenFreezer/overlib/overlibCompat.js
new file mode 100755
index 0000000..f8fb88d
--- /dev/null
+++ b/OpenFreezer/overlib/overlibCompat.js
@@ -0,0 +1,30 @@
+////////////////////////////////////////////////////////////////////////////////////
+// OVERLIB 2 COMPATABILITY FUNCTIONS
+// Include this if you are upgrading from overlib v2.x.  Otherwise, forget it.
+////////////////////////////////////////////////////////////////////////////////////
+// Converts old 0=left, 1=right and 2=center into constants.
+function vpos_convert(d){if(d==0){d=LEFT;}else{if(d==1){d=RIGHT;}else{d=CENTER;}}return d;}
+// Simple popup
+function dts(d,text){o3_hpos=vpos_convert(d);overlib(text,o3_hpos,CAPTION,"");}
+// Caption popup
+function dtc(d,text,title){o3_hpos=vpos_convert(d);overlib(text,CAPTION,title,o3_hpos);}
+// Sticky
+function stc(d,text,title){o3_hpos=vpos_convert(d);overlib(text,CAPTION,title,o3_hpos,STICKY);}
+// Simple popup right
+function drs(text){dts(1,text);}
+// Caption popup right
+function drc(text,title){dtc(1,text,title);}
+// Sticky caption right
+function src(text,title){stc(1,text,title);}
+// Simple popup left
+function dls(text){dts(0,text);}
+// Caption popup left
+function dlc(text,title){dtc(0,text,title);}
+// Sticky caption left
+function slc(text,title){stc(0,text,title);}
+// Simple popup center
+function dcs(text){dts(2,text);}
+// Caption popup center
+function dcc(text,title){dtc(2,text,title);}
+// Sticky caption center
+function scc(text,title){stc(2,text,title);}
diff --git a/OpenFreezer/overlib/overlibConfig.txt b/OpenFreezer/overlib/overlibConfig.txt
new file mode 100755
index 0000000..4adb2d1
--- /dev/null
+++ b/OpenFreezer/overlib/overlibConfig.txt
@@ -0,0 +1,650 @@
+
+Below are described the configuration variables and arrays associated with the
+overlib commands, and their defaults as set in the
+	overlibmws.js
+core module and the
+	overlibmws_bubble.js, overlibmws_crossframe.js, overlibmws_debug.js,
+ 	overlibmws_draggable.js, overlibmws_exclusive.js, overlib_filter.js,
+ 	overlibmws_function.js, overlibmws_hide.js, overlibmws_modal.js,
+        overlibmws_overtwo.js, overlibmws_print.js, overlibmws_scroll.js and
+        overlibmws_shadow.js
+plugin modules.  The
+	overlibmws_iframe.js and overlib_regCore.js
+plugin modules do not have configuration variables or arrays.
+
+You can change any of the configuration default values for all pages by making
+the modifications in overlibmws.js or the plugin modules, or for individual HTML
+pages by declaring any of these variables with the values you prefer in a SCRIPT
+block or imported js file for those pages.
+
+You instead can change the configuration default values for individual HTML pages by
+calling the OLpageDefaults(arguments) function in a SCRIPT block or imported js file
+with "arguments" consisting of a comma-separated list of uppercase command names and
+their parameters if any, homologously to the arguments for an overlib() call.
+
+The overlibmws_overtwo.js module is used by calling overlib2() and nd2() from within
+an overlib() call that invokes a primary popup, to invoke and close secondary popups.
+Its LABLE2 command and its configuration variable are specific to the secondary popups,
+and are complementary to the core module's LABLEL command and its configuration variable
+for primary popups.
+
+The overlibmws_iframe.js module has no additional commands, and thus no configuration
+variables. It should be imported when a page has system controls (e.g., some form
+elements, flash objects, applets) which obscure overlib popups.  It corrects this
+problem for IE v5.5 or higher.  For versions of IE lower than v5.5 and for other browsers,
+you can use commands in the overlibmws_hide.js plugin module.  See the examples in
+http://www.macridesweb.com/oltest/hide.html and http://www.macridesweb.com/oltest/flash.html
+on how to use those command to hide the system controls when overlib popups are invoked.
+
+The overlibmws_regCore.js module has no overlib() or overlib2() commands, and thus
+no configuration variables.  It should be imported in frames which will not themselves
+import the core module and any plugin modules, but instead will use those in another
+frame.  See its header for more information.  Examples of its use are in
+http://www.macridesweb.com/oltest/testFrame.html
+
+See the overlibmws Command Reference (http://www.macridesweb.com/oltest/commandRef.html)
+for more information about the commands, configuration variables, and plugin modules. 
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION FOR CORE MODULE overlibmws.js
+////////////////////////////////////////////////////////////////////////////////////
+
+// FGCOLOR - Main background color (the large area).
+// Usually a bright color (white, yellow etc).
+var ol_fgcolor = "#CCCCFF";
+
+// BGCOLOR - Border color.
+// Usually a dark color (black, brown etc).
+var ol_bgcolor = "#333399";
+
+// CGCOLOR - Caption background color (typically same as border color).
+// Usually a dark color (black, brown etc).
+var ol_cgcolor = "#333399";
+
+// TEXTCOLOR - Text color.
+// Usually a dark color.
+var ol_textcolor = "#000000";
+
+// CAPCOLOR - Color of the caption text.
+// Usually a bright color
+var ol_capcolor = "#FFFFFF";
+
+// CLOSECOLOR - Color of "Close" when using Sticky.
+// Usually a semi-bright color.
+var ol_closecolor = "#9999FF";
+
+// TEXTFONT - Font face for the main text.
+var ol_textfont = "Verdana,Arial,Helvetica";
+
+// CAPTIONFONT - Font face for the caption.
+var ol_captionfont = "Verdana,Arial,Helvetica";
+
+// CLOSEFONT - Font face for the close text.
+var ol_closefont = "Verdana,Arial,Helvetica";
+
+// TEXTSIZE - Font size for the main text.
+var ol_textsize = "1";
+
+// CAPTIONSIZE - Font size for the caption.
+var ol_captionsize = "1";
+
+// CLOSESIZE - Font size for the close text.
+var ol_closesize = "1";
+
+// FGCLASS - Main background class.
+var ol_fgclass = "";
+
+// BGCLASS - Frame background class.
+var ol_bgclass = "";
+
+// CGCLASS - Caption background class.
+var ol_cgclass = "";
+
+// TEXTPADDING - Padding for main text.
+var ol_textpadding = "2";
+
+// TEXTFONTCLASS - Main font class.
+var ol_textfontclass = "";
+
+// CAPTIONPADDING - Padding for caption (including Close text if present).
+var ol_captionpadding = "2";
+
+// CAPTIONFONTCLASS - Caption font class.
+var ol_captionfontclass = "";
+
+// CLOSEFONTCLASS - Close font class.
+var ol_closefontclass = "";
+
+// CLOSECLICK - If the user has to click to close stickies.
+var ol_closeclick = 0;
+
+// CLOSETEXT - Text for the closing sticky popups. Normal is "Close".
+var ol_close = "Close";
+
+// CLOSETITLE - Text to use as value of TITLE attribute for browser-generated TooTips
+// with the "Close" link in captions of stickies when CLOSECLICK is changed to 1;
+var ol_closetitle = "Click to Close";
+
+// Default text for popups
+// Should you forget to pass something to overLIB this will be displayed.
+var ol_text = "Default Text";
+
+// Default caption
+// You should leave this blank or you will have problems making non caps popups.
+var ol_cap = "";
+
+// CAPBELOW - Whether the caption should appear below the main text area.  Default is
+// off (0) such that the caption appears above.
+var ol_capbelow=0;
+
+// BACKGROUND - Default background image. Better left empty unless you always want one.
+var ol_background = "";
+
+// WIDTH - Default width of the popups in pixels. 100-300 pixels is typical.
+// This value is simply a suggestion to the browser, which may change the
+// actual width depending on the content.
+var ol_width = "200";
+
+// WRAP - Intended to keep the popup no wider than its content plus normal padding, but
+// to wrap the content if it would exceed the window width, or if it would exceed WRAPMAX
+// when that has been set to a value greater than zero.
+// Overrides the o3_width setting. Default is no wrap (0).
+var ol_wrap = 0;
+
+// WRAPMAX - If set to a value greater than 0, sets the maximum width of the popup, up to
+// the window width, before wrapping occurs when the WRAP command is set.
+var ol_wrapmax = 0;
+
+// HEIGHT - Default height for popup. Often best left alone.
+var ol_height = -1;
+
+// BORDER - How thick the ol_border should be in pixels.
+// 1-3 pixels is typical.
+var ol_border = "1";
+
+// BASE - Any additional thickening of the border's base in pixels.
+var ol_base = "0";
+
+// OFFSETX - How many pixels to the right (positive values) or left (negative values)
+// of the cursor to show the popup. Values between 3 and 12 are best.
+var ol_offsetx = 10;
+	
+// OFFSETY - How many pixels below (positive values) or above (negative values) the
+// cursor to show the popup. Values between 3 and 20 are best.
+var ol_offsety = 10;
+
+// STICKY - Decides if sticky popups are default. 0 for non, 1 for stickies.
+var ol_sticky = 0;
+
+// NOFOLLOW - Should non-sticky popups not follow cursor movements (i.e., remain
+// stationary where initially positioned on invocation, like title-based tooltips).
+var ol_nofollow = 0;
+
+// NOCLOSE - Omit Close text in stickies with captions, for all stickies use mouse off
+// after mouse over sticky to close, and cancel any timeout while over sticky.
+var ol_noclose = 0;
+
+// MOUSEOFF - For stickies which do have a caption with a CLOSETEXT, also use mouse off
+// after mouse over sticky to close, and cancel any timeout while over sticky.
+var ol_mouseoff = 0;
+
+// OFFDELAY - Default delay for closing NOCLOSE or MOUSEOFF popups.  If a mouse over the
+// sticky occurs during this delay, the close is cancelled.
+var ol_delay = 300;
+
+// RIGHT - Default vertical alignment for popups.
+// It's best to leave RIGHT here. Other options are LEFT and CENTER.
+var ol_hpos = RIGHT;
+
+// BELOW - Default vertical position of the popups.
+// It's best to leave BELOW here. Other options are ABOVE and VCENTER.
+var ol_vpos = BELOW;
+
+// Default status bar text when a popup is invoked.
+var ol_status = "";
+
+// AUTOSTATUS, AUTOSTATUSCAP - If the status bar automatically should load either
+// text or caption. 0=nothing, 1=text, 2=caption
+var ol_autostatus = 0;
+
+// SNAPX - Horizontal grid spacing that popups will snap to.
+// 0 makes no grid, anything else will cause a snap to that grid spacing.
+var ol_snapx = 0;
+
+// SNAPY - Vertical grid spacing that popups will snap to.
+// 0 makes no grid, anything else will cause a snap to that grid spacing.
+var ol_snapy = 0;
+
+// FIXX - Sets the popup horizontal position to a fixed column.
+// Numbers greater than -1 will cause fixed position.
+var ol_fixx = -1;
+
+// FIXY - Sets the popup vertical position to a fixed row.
+// Numbers greater than -1 will cause fixed position.
+var ol_fixy = -1;
+
+// RELX - Sets the popup horizontal position to a column relative to the window display.
+// Anything numeric (non-null) will cause relative position. Positive and 0 is to
+// the right from left window margin for left margin of popup. Negative is to the
+// left from right window margin for right margin of popup.
+var ol_relx = null;
+
+// RELY - Sets the popup vertical position to a row relative to the window display.
+// Anything numeric (non-null) will cause relative position. Positive and 0 is down
+// from top window margin for top margin of popup. Negaive is up from bottom window
+// margin for bottom margin of popup.
+var ol_rely = null;
+
+// MIDX - Sets the popup horizontal midpoint to a column relative to the window horizontal
+// midpoint. Anything numeric (non-null) will cause midpoint position. Positive and
+// 0 is to the right from the window midpoint. Negative is to the left.
+var ol_midx = null;
+
+// MIDY - Sets the popup vertical midpoint to a row relative to the window vertical midpoint.
+// Anything numeric (non-null) will cause midpoint position. Positive and 0 is down from
+// the window midpoint. Negative is up.
+var ol_midy = null;
+
+// REF - The NAME of an anchor or image, or ID of a layer, to serve as a reference object such
+// that a corner of the popup will be positioned relative to a corner of the object.
+var ol_ref = "";
+
+// REFC - Corner of the reference object for positioning.
+// Value can be: 'UL' (Upper Left), 'UR', 'LR', or 'LL'.
+var ol_refc = 'UL';
+
+// REFP - Corner of the popup for positioning.
+// Value can be: 'UL' (Upper Left), 'UR', 'LR', or 'LL'.
+var ol_refp = 'UL';
+
+// REFX - X displacement from the reference point. Positive to the right,
+// negative left.
+var ol_refx = 0;
+
+// REFY - Y displacement from the reference point. Positive down, negative up.
+var ol_refy = 0;
+
+// FGBACKGROUND - Background image for the popup's inside.
+var ol_fgbackground = "";
+
+// BGBACKGROUND - Background image for the popup's frame (border).
+var ol_bgbackground = "";
+
+// CGBACKGROUND - Background image for the caption.
+var ol_cgbackground = "";
+
+// PADX
+// How much horizontal left padding text should get by default when BACKGROUND is used.
+var ol_padxl = 1;
+// How much horizontal right padding text should get by default when BACKGROUND is used.
+var ol_padxr = 1;
+
+// PADY
+// How much vertical top padding text should get by default when BACKGROUND is used.
+var ol_padyt = 1;
+// How much vertical bottom padding text should get by default when BACKGROUND is used.
+var ol_padyb = 1;
+
+// FULLHTML - If the user by default must supply all html for complete control of popup content.
+// Set to 1 to activate, 0 otherwise.
+var ol_fullhtml = 0;
+
+// CAPICON - Default icon to place next to the popups caption.
+var ol_capicon = "";
+
+// FRAME - Default frame. We default to current frame if there is no frame defined.
+var ol_frame = self;
+
+// TIMEOUT - Default timeout. By default there is no timeout.
+var ol_timeout = 0;
+
+// DELAY - Default delay for onset of popup. By default there is no delay.
+var ol_delay = 0;
+
+// HAUTO - If overLIB should decide the horizontal placement.
+var ol_hauto = 0;
+
+// VAUTO - If overLIB should decide the vertical placement.
+var ol_vauto = 0;
+
+// NOJUSTX - If overLIB should let popups overrun the left or right window margins.
+var ol_nojustx = 0;
+
+// NOJUSTY - If overLIB should let popups overrun the top or bottom window margins.
+var ol_nojusty = 0;
+
+// LABEL - A labeling string for the primary popup while it is displayed (visible).
+var ol_label = "";
+
+// DECODE - If overLIB should automatically decode any URL-encoded characters in
+// lead argument and/or caption.
+var ol_decode = "";
+
+////////////////////////////////////////////////////////////////////////////////////
+// ARRAY CONFIGURATION FOR CORE MODULE overlibmws.js
+////////////////////////////////////////////////////////////////////////////////////
+
+// INARRAY - Array with texts.
+var ol_texts = new Array(
+ "Text 0",
+ "Text 1");
+
+// CAPARRAY - Array with captions.
+var ol_caps = new Array(
+ "Caption 0",
+ "Caption 1");
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION FOR overlibmws.js
+////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION FOR PLUGIN MODULE overlibmws_bubble.js
+////////////////////////////////////////////////////////////////////////////////////
+
+// BUBBLE - Whether to use a bubble type popup. Default is no (0).
+var ol_bubble = 0;
+
+// BUBBLETYPE - Type of bubble image to use. Default is 'flower'.  Other options are
+// 'oval', 'square', 'pushpin', 'quotation', or 'roundedcorners'. Specify directory
+// for images via the last parameter of registerImages() near the top of the plugin
+// module (default value is './').
+var ol_bubbletype = 'flower';
+
+// ADJBUBBLE - Whether to resize the image in relation to the content.
+// Default is no (0). 
+var ol_adjbubble = 0;
+
+// RCBUBBLECOLOR - Color for the textual content of speech bubble popups which have
+// 'roundcorners' as their BUBBLETYPE parameter.  Default value is '#ffffcc'. 
+var ol_rcbubblecolor = '#ffffcc';
+
+// BUBBLECLOSE - Whether to block the normally automatic setting of NOCLOSE for
+// bubble popups that are sticky.
+// Default is no (0). 
+var ol_bubbleclose = 0;
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION FOR overlibmws_bubble.js
+////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION FOR PLUGIN MODULE overlibmws_crossframe.js
+////////////////////////////////////////////////////////////////////////////////////
+
+You must import this plugin module to use the FRAME command, but its configuration
+variable, ol_frame, is set in the core module.
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION FOR overlibmws_crossframe.js
+////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION FOR PLUGIN MODULE overlibmws_debug.js
+////////////////////////////////////////////////////////////////////////////////////
+
+// ALLOWDEBUG - The ID or a comma-separated list of IDs for debug layers which, if
+// invoked following an overlib call and then made hidden via the close link at
+// upper right, should be made visible again whenever that overlib call occurs.
+var ol_allowdebug = "";
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION FOR overlibmws_debug.js
+////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION FOR PLUGIN MODULE overlibmws_draggable.js
+////////////////////////////////////////////////////////////////////////////////////
+
+// DRAGGABLE - If sticky should be draggable.
+var ol_draggable = 0;
+
+// DRAGCAP - Restrict dragging handle to the caption.
+var ol_dragcap = 0;
+
+// DRAGID - The id of a container div with a CSS class that uses overflow:auto
+// for a DRAGGABLE popup that doesn't have iframe content and doesn't use DRAGCAP.
+var ol_dragid = '';
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION FOR overlibmws_draggable.js
+////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION FOR PLUGIN MODULE overlibmws_exclusive.js
+////////////////////////////////////////////////////////////////////////////////////
+
+// EXCLUSIVE - Decides if a sticky primary popup should be exclusive, such that no other
+// primry popup can be invoked and replace it before the sticky is closed by the user or
+// a timeout (secondary popups can still be invoked from within the exclusive primary).
+var ol_exclusive = 0;
+
+// EXCLUSIVESTATUS - Status line string to use for exclusive stickies
+var ol_exclusivestatus = 'Please act on or close the open popup.';
+
+// EXCLUSIVEOVERRIDE = If a displayed exclusive sticky should be overridden by the
+// current overlib call for a popup.
+var ol_exclusiveoverride=0;
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION FOR overlibmws_exclusive.js
+////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION FOR PLUGIN MODULE overlibmws_filter.js
+////////////////////////////////////////////////////////////////////////////////////
+
+// FILTER - Toggles on the filter feature set for IE v5.5+ browsers. Defualt is off.
+var ol_filter=0;
+
+// FADEIN - Filter type for stylinzed fadein. Value can be 0 - 50 for the 51 types,
+// or 51 (default) for random selections of the type across successive occurrences
+// of the popup.
+var ol_fadein=51;
+
+// FADETIME - Duration of fadein (millisec).
+var ol_fadetime=800;
+
+// FILTEROPACITY - Opacity of entire popup.  The higher the number in the range of 1-99,
+// the more more opaque (less transparent) the popup will be.  But 0 is handled as
+// equivalent to 100 (no transparency).  This feature also is implemented for Mozilla
+// and Netscape v6+ browsers.
+var ol_filteropacity=100;
+
+// FILTERSHADOW - Type of filter-based shadow.  Default is off (0).
+// Dropshadow is 1. Shadow (tapers from corners) is 2.
+var ol_filtershadow=0;
+
+// FILTERSHADOWCOLOR - Color of filter-based shadow.
+var ol_filtershadowcolor="#cccccc";
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION FOR overlibmws_filter.js
+////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION FOR PLUGIN MODULE overlibmws_function.js
+////////////////////////////////////////////////////////////////////////////////////
+
+// FUNCTION - Default javascript function. By default there is none.
+var ol_function = null;
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION FOR overlibmws_function.js
+////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION FOR PLUGIN MODULE overlibmws_hide.js
+////////////////////////////////////////////////////////////////////////////////////
+
+// HIDESELECTBOXES - Whether to hide any select boxes which overlap the popup
+// while the popup is being displayed.
+var ol_hideselectboxes=0;
+
+// HIDEBYID - An id or comma-separated list of id's to be hidden while the popup
+// is displayed.  Is intended for form elements and is ignored for any browsers
+// using HIDESELECTBOXES and for Opera v7+.
+var ol_hidebyid='';
+
+// HIDEBYIDALL - An id or comma=separated list of id's to be hidden while the popup
+// is displayed.  Is intended for non-form elements with system controls, e.g.,
+// flash objects and applets.
+var ol_hidebyidall='';
+
+// HIDEBYIDNS4 - An id or comma-separated list of id's for positioned div's to be
+// hidden while the popup is being displayed by Netscape v4.x browsers.
+var ol_hidebyidns4='';
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION FOR overlibmws_hide.js
+////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION FOR PLUGIN MODULE overlibmws_modal.js
+////////////////////////////////////////////////////////////////////////////////////
+
+// MODAL - Whether to make the popup modal (block access to any other items in the
+// document via a shield until the popup is acted upon and closed).
+var ol_modal = 0;
+
+// MODALCOLOR - The color of the modal shield.
+var ol_modalcolor = '#bbbbbb';
+
+// MODALOPACITY - The opacity of the modal shield.
+var ol_modalopacity = 40;
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION FOR overlibmws_overtwo.js
+////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION FOR PLUGIN MODULE overlibmws_overtwo.js
+////////////////////////////////////////////////////////////////////////////////////
+
+// LABEL - A labeling string for the secondary popup while it is displayed (visible).
+var ol_label = "";
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION FOR overlibmws_overtwo.js
+////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION FOR PLUGIN MODULE overlibmws_print.js
+////////////////////////////////////////////////////////////////////////////////////
+
+// PRINT - Whether sticky should include a Print link or button.
+var ol_print = 0;
+
+// PRINTBUTTON - Whether to use button in main text area even if caption area is present.
+var ol_printbutton=0;
+
+// NOAUTOPRINT - Whether to block automatic printing and deletion of temporary printing window.
+var ol_noautoprint=0;
+
+// PRINTCOLOR - Color of "Print" link in caption area of sticky.
+var ol_printcolor="#eeeeff";
+
+// PRINTFONT - Font face for the print text.
+var ol_printfont="Verdana,Arial,Helvetica";
+
+// PRINTSIZE - Font size for the print text.
+var ol_printsize=1;
+
+// PRINTTEXT - Text for the sticky popup print link. Normal is "Print".
+var ol_printtext='Print';
+
+// PRINTBUTTONTEXT - Text for the sticky popup print button. Normal is "Print".
+var ol_printbuttontext='Print';
+
+// PRINTTITLE - Text to use as value of TITLE attribute for browser-generated TooTips
+// with the "Print" link in captions of stickies or "Print" button in main text area.
+var ol_printtitle="Click to Print";
+
+// PRINTFONTCLASS - Print font class.
+var ol_printfontclass="";
+
+// PRINTCSSFILE - URL for .ccs file with CSS rules for styling the popup.
+var ol_printcssfile="";
+
+// PRINTXML - String for (optional) xml tag for temporary printing window.
+var ol_printxml="";
+
+// PRINTDOCTYPE - String for DOCTYPE declaration for temporary printing window.
+var ol_printdoctype=
+ '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" '
++'"http://www.w3.org/TR/html4/loose.dtd">';
+
+// PRINTROOT - String for root tag for temporary printing window.
+var ol_printroot="<html>";
+
+// PRINTTYPE - String for MIME type for temporary printing window.
+var ol_printtype="text/html";
+
+// PRINTCHARSET - String for charset for temporary printing window.
+var ol_printcharset="iso-8859-1";
+
+// PRINTURL - URL for a document to be printed via the temporary printing window.
+var ol_printurl="";
+
+// PRINTJOB - string for an external function to be used for the temporary printing window.
+var ol_printjob="";
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION FOR overlibmws_print.js
+////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION FOR PLUGIN MODULE overlibmws_scroll.js
+////////////////////////////////////////////////////////////////////////////////////
+
+// SCROLL - Whether sticky should scroll with the document when positioned via
+// RELX or MIDX, and RELY or MIDY.
+var ol_scroll = 0;
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION FOR overlibmws_scroll.js
+////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////////
+// DEFAULT CONFIGURATION FOR PLUGIN MODULE overlibmws_shadow.js
+////////////////////////////////////////////////////////////////////////////////////
+
+// SHADOW - Whether to add a dropshadow. Default is no (0).
+var ol_shadow = 0;
+
+// SHADOWX - Horizontal dropshadow displacement in pixels.
+// Positive is to the right and negative is to the left.
+var ol_shadowx = 5;
+
+// SHADOWY - Vertical dropshadow displacement in pixels.
+// Positive is downward and negative is upward.
+var ol_shadowy = 5;
+
+// SHADOWCOLOR - Dropshadow color.
+var ol_shadowcolor = "#666666";
+
+// SHADOWIMAGE - Dropshadow background image. Default is none.
+var ol_shadowimage = "";
+
+// SHADOWOPACITY - Dropshadow opacity (100 is solid; 0 turns off this feature and
+// thus also yields a solid shadow). Default is 60.
+var ol_shadowopacity = 60;
+
+////////////////////////////////////////////////////////////////////////////////////
+// END CONFIGURATION FOR overlibmws_shadow.js
+////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/OpenFreezer/overlib/overlib_anchor.js b/OpenFreezer/overlib/overlib_anchor.js
new file mode 100755
index 0000000..6287c39
--- /dev/null
+++ b/OpenFreezer/overlib/overlib_anchor.js
@@ -0,0 +1,333 @@
+//\/////
+//\  overLIB Anchor Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.10 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//   $Revision: 1.7 $                      $Date: 2004/11/25 21:27:19 $
+//\/////
+//\mini
+
+
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || typeof olInfo.meets == 'undefined' || !olInfo.meets(4.10)) alert('overLIB 4.10 or later is required for the Anchor Plugin.');
+else {
+registerCommands('anchor,anchorx,anchory,noanchorwarn,anchoralign');
+
+
+
+////////
+// DEFAULT CONFIGURATION
+// Settings you want everywhere are set here. All of this can also be
+// changed on your html page or through an overLIB call.
+////////
+if (typeof ol_anchor ==  'undefined') var ol_anchor = '';
+if (typeof ol_anchorx ==  'undefined') var ol_anchorx = 0;
+if (typeof ol_anchory ==  'undefined') var ol_anchory = 0;
+if (typeof ol_noanchorwarn ==  'undefined') var ol_noanchorwarn = 1;
+if (typeof ol_anchoralign ==  'undefined') var ol_anchoralign = 'UL';
+
+////////
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+
+
+
+
+
+////////
+// INIT
+////////
+// Runtime variables init. Don't change for config!
+var o3_anchor = "";
+var o3_anchorx = 0;
+var o3_anchory = 0;
+var o3_noanchorwarn = 1;
+var o3_anchoralign = 'UL';
+var mrkObj, rmrkPosition;  //reference mark object, reference mark position, an array;
+
+
+////////
+// PLUGIN FUNCTIONS
+////////
+function setAnchorVariables() {
+	o3_anchor = ol_anchor;
+	o3_anchorx = ol_anchorx;
+	o3_anchory = ol_anchory;
+	o3_noanchorwarn = ol_noanchorwarn;
+	o3_anchoralign = ol_anchoralign;
+	mrkObj = null;  // initialize this variable
+}
+
+// Parses Reference Mark commands
+function parseAnchorExtras(pf,i,ar) {
+	var v, k=i;
+
+	if (k < ar.length) {
+		if (ar[k] ==  ANCHOR) { eval(pf + "anchor = '" + escSglQuote(ar[++k]) + "'"); return k; }
+		if (ar[k] ==  ANCHORX) { eval(pf + 'anchorx = ' + ar[++k]); return k; }
+		if (ar[k] ==  ANCHORY) { eval(pf + 'anchory = ' + ar[++k]); return k; }
+		if (ar[k] ==  NOANCHORWARN) { eval(pf + 'noanchorwarn = (' + pf + 'noanchorwarn==1) ? 0 : 1'); return k; }
+		if (ar[k] ==  ANCHORALIGN) { k = opt_MULTIPLEARGS(++k, ar, (pf + 'anchoralign'));  return k; }
+	}
+
+	return -1;
+}
+
+
+///////
+//  FUNCTION WHICH CHECKS FOR THE EXISTENCE OF A REFERENCE MARKER
+///////
+function checkAnchorObject() {
+	var w = o3_anchor;
+
+	if (w) {
+		if (!(mrkObj = getAnchorObjectRef(w))) {
+			if (o3_noanchorwarn) {
+				alert('WARNING!  Reference mark "' + w + '" not found.');
+				return false;
+			} else w = '';
+		}
+	}
+
+	return true;
+}
+
+///////
+// EXTERNAL SUPPORT FUNCTIONS TO HANDLE ANCHOR PROPERTIES
+///////
+
+// Horizontal placement routine with anchors
+function anchorHorizontal(browserWidth, horizontalScrollAmount, widthFix) {
+	var hasAnchor = (typeof o3_anchor != 'undefined' && o3_anchor);
+	if (!hasAnchor) return void(0);
+
+	// set o3_relx for follow scroll if defined
+	if (typeof o3_followscroll != 'undefined' && o3_followscroll && o3_sticky) o3_relx = rmrkPosition[0];
+
+	return rmrkPosition[0];
+}
+
+// Vertical placement routine with anchors
+function anchorVertical(browserHeight,verticalScrollAmount) {
+	var hasAnchor = (typeof o3_anchor != 'undefined' && o3_anchor);	
+	if (!hasAnchor) return void(0);
+
+	// set o3_rely for follow scroll if defined
+	if (typeof o3_followscroll != 'undefined' && o3_followscroll && o3_sticky) o3_rely = rmrkPosition[1];
+
+	return rmrkPosition[1];
+}
+
+// Stub function for the runHook routine
+function anchorPreface() {
+	if (!mrkObj) return;
+	rmrkPosition = getAnchorLocation(mrkObj);
+}
+
+// Get Reference Mark object 
+function getAnchorObjectRef(aObj) {
+	return getRefById(aObj, o3_frame.document) || getRefByName(aObj, o3_frame.document)
+}
+
+// Adapted to overlib from jwin by Jason Anderson -- http://www.jwinlib.com
+function getAnchorLocation(objRef){
+	var mkObj, of, offsets, mlyr
+	
+	mkObj = mlyr = objRef
+	offsets = [o3_anchorx, o3_anchory]
+	
+	if (document.layers){
+		if (typeof mlyr.length != 'undefined' &&  mlyr.length > 1) {
+				mkObj = mlyr[0]
+				offsets[0] += mlyr[0].x + mlyr[1].pageX
+				offsets[1] += mlyr[0].y + mlyr[1].pageY
+			} else {
+				if(mlyr.toString().indexOf('Image') != -1 || mlyr.toString().indexOf('Anchor') != -1){
+					offsets[0] += mlyr.x
+					offsets[1] += mlyr.y
+				} else {
+					offsets[0] += mlyr.pageX
+					offsets[1] += mlyr.pageY
+				}
+			}          
+	} else {
+		offsets[0] += pageLocation(mlyr, 'Left')
+		offsets[1] += pageLocation(mlyr, 'Top')
+	}
+	
+	of = getAnchorOffsets(mkObj)
+	
+	if (typeof o3_dragimg != 'undefined' &&  o3_dragimg) {
+		olImgLeft = offsets[0];
+		olImgTop = offsets[1];
+	}
+	
+	offsets[0] += of[0]                    
+	offsets[1] += of[1]
+	
+	if (typeof o3_dragimg != 'undefined' &&  o3_dragimg) {
+		olImgRight = offsets[0]; 
+		olImgBottom = offsets[1];
+		return;
+	}
+	
+	return offsets;
+}
+
+// Adapted to overlib from jwin by Jason Anderson -- http://www.jwinlib.com
+function getAnchorOffsets(mkObj){
+	var fx = fy = 0,  mp, puc, mkAry, sx = sy = 0, w = o3_anchoralign  
+	var mW = mH = pW = pH = 0
+	var off = [0, 0]
+
+	mkAry = w.split(',');
+
+	if (mkAry.length < 3) {
+		mp = mkAry[0].toUpperCase();
+		puc = (mkAry.length == 1) ? mp : mkAry[1].toUpperCase();
+	} else if (mkAry.length == 3) {
+		if (!isNaN(mkAry[0])) {
+			mp = mkAry.slice(0, 2);
+			puc = mkAry[2].toUpperCase();
+		 } else {
+			mp = mkAry[0].toUpperCase();
+			puc = mkAry.slice(1);
+		 }
+	} else {
+		mp = mkAry.slice(0, 2);
+		puc = mkAry.slice(2);
+	}
+
+	var shdwPresent = typeof o3_shadow != 'undefined' &&  o3_shadow
+
+	if (shdwPresent) {
+		sx = Math.abs(o3_shadowx);
+		sy = Math.abs(o3_shadowy);
+	}
+
+	pW = (shdwPresent ? parseInt(o3_width) : (olNs4 ? over.clip.width : over.offsetWidth))
+	pH = (shdwPresent ? parseInt(o3_aboveheight) : (olNs4 ? over.clip.height : over.offsetHeight))
+
+	if (olOp &&  o3_wrap) {
+		pW = (shdwPresent ? parseInt(o3_width) : (olNs4 ? over.clip.width : over.offsetWidth))
+		pH = (shdwPresent ? parseInt(o3_aboveheight) : (olNs4 ? over.clip.height : over.offsetHeight))
+	}
+
+	if (!olOp &&  mkObj.toString().indexOf('Image') != -1){
+		mW = mkObj.width
+		mH = mkObj.height
+	} else if (!olOp &&  mkObj.toString().indexOf('Anchor') != -1) {  // enforced only for NS4
+		mp = 'UL'
+	} else {
+		mW = (olNs4) ? mkObj.clip.width : mkObj.offsetWidth
+		mH = (olNs4) ? mkObj.clip.height : mkObj.offsetHeight
+	}
+
+	if (!isNaN(mp) || typeof mp == 'object') {
+		if (typeof mp == 'object') {
+			fx = parseFloat(mp[0]);
+			fy = parseFloat(mp[1]);
+		} else
+			fx = fy = parseFloat(mp);
+		off = [Math.round(fx*mW), Math.round(fy*mH)];
+	} else {
+		 if (mp == 'UR') off = [mW, 0]
+		 else if (mp == 'LL') off = [0, mH]
+		 else if (mp == 'LR') off = [mW, mH]
+	}
+
+	if (typeof o3_dragimg != 'undefined' &&  o3_dragimg) return off;
+	else {
+		if (!isNaN(puc) || typeof puc == 'object' ) {
+			if (typeof puc == 'object') {
+				fx = parseFloat(puc[0]);
+				fy = parseFloat(puc[1]);
+			} else
+				fx = fy = parseFloat(puc);
+			off[0] -= Math.round(fx*(pW - sx));
+			off[1] -= Math.round(fy*(pH - sy));
+		} else {
+			if (puc == 'UR') {
+				off[0] -= (pW - sx); 
+				off[1] -= sy
+			} else if (puc == 'LL') {
+				off[0] -= sx;
+				off[1] -= (pH - sy)
+			} else if (puc == 'LR') {
+				off[0] -= (pW-sx);
+				off[1] -= (pH - sy)
+			}
+		}
+		return off
+	}
+}
+
+// Adapted to overlib from jwin by Jason Anderson -- http://www.jwinlib.com
+function pageLocation(o, t){
+	var x = 0
+
+	while(o.offsetParent){
+		x += o['offset' + t]
+		o = o.offsetParent
+	}
+	x += o['offset' + t]
+
+	return x
+} 
+
+// Adapted to overlib from jwin by Jason Anderson -- http://www.jwinlib.com
+function getRefById(l, d){
+	var r = "", j
+
+	d = (d || document)
+	if (d.all) return d.all[l]    
+	else if (d.getElementById) return d.getElementById(l)
+	else if (d.layers &&  d.layers.length > 0) {
+		if (d.layers[l]) return d.layers[l]
+		
+		for (j=0; j < d.layers.length; j++) {
+			r = getRefById(l, d.layers[j].document)
+			if(r) return r               
+		}
+	}
+
+	return false
+}
+
+// Adapted to overlib from jwin by Jason Anderson -- http://www.jwinlib.com
+function getRefByName(l, d) {
+	var r = null, j
+
+	d = (d || document)
+
+	if (d.images[l]) return d.images[l]
+	else if (d.anchors[l]) return d.anchors[l];
+	else if (d.layers &&  d.layers.length > 0) {
+		for (j=0; j < d.layers.length; j++) {
+			r = getRefByName(l, d.layers[j].document)
+			if (r &&  r.length > 0) return r
+			else if (r) return [r, d.layers[j]]
+		}
+	}
+
+	return null
+}
+
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerRunTimeFunction(setAnchorVariables);
+registerCmdLineFunction(parseAnchorExtras);
+registerPostParseFunction(checkAnchorObject);
+registerHook("createPopup", anchorPreface, FAFTER);
+registerHook("horizontalPlacement", anchorHorizontal, FCHAIN);
+registerHook("verticalPlacement", anchorVertical, FCHAIN);
+if(olInfo.meets(4.10)) registerNoParameterCommands('noanchorwarn');
+}
\ No newline at end of file
diff --git a/OpenFreezer/overlib/overlib_centerpopup.js b/OpenFreezer/overlib/overlib_centerpopup.js
new file mode 100755
index 0000000..a31de50
--- /dev/null
+++ b/OpenFreezer/overlib/overlib_centerpopup.js
@@ -0,0 +1,89 @@
+//\/////
+//\  overLIB Center Popup Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.10 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2003. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//   $Revision: 1.3 $                $Date: 2004/11/25 21:27:19 $
+//
+//\/////
+//\mini
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || typeof olInfo.meets == 'undefined' || !olInfo.meets(4.10)) alert('overLIB 4.10 or later is required for the Center Popup Plugin.');
+else {
+registerCommands('centerpopup,centeroffset');
+////////
+// DEFAULT CONFIGURATION
+// You don't have to change anything here if you don't want to. All of this can be
+// changed on your html page or through an overLIB call.
+////////
+// Default value for centerpopup is to not center the popup
+if (typeof ol_centerpopup == 'undefined') var ol_centerpopup = 0;
+if (typeof ol_centeroffset == 'undefined') var ol_centeroffset = '0';
+////////
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+////////
+// INIT
+////////
+// Runtime variables init. Don't change for config!
+var o3_centerpopup = 0;
+var o3_centeroffset = '0';
+////////
+// PLUGIN FUNCTIONS
+////////
+function setCenterPopupVariables() {
+	o3_centerpopup = ol_centerpopup;
+	o3_centeroffset = ol_centeroffset;
+}
+// Parses Shadow and Scroll commands
+function parseCenterPopupExtras(pf,i,ar) {
+	var k = i,v;
+
+	if (k < ar.length) {
+		if (ar[k] == CENTERPOPUP) { eval(pf + 'centerpopup = (' + pf + 'centerpopup == 0) ? 1 : 0'); return k; }
+		if (ar[k] == CENTEROFFSET) { k = opt_MULTIPLEARGS(++k,ar,(pf + 'centeroffset')); return k; }
+	}
+
+	return -1;
+}
+// Function which positions popup in Center of screen
+function centerPopupHorizontal(browserWidth, horizontalScrollAmount, widthFix) {
+	if (!o3_centerpopup) return void(0);
+
+	var vdisp = o3_centeroffset.split(',');
+	var placeX, iwidth = browserWidth, winoffset = horizontalScrollAmount;
+  var pWd = parseInt(o3_width);
+
+	placeX = winoffset + Math.round((iwidth - widthFix - pWd)/2) + parseInt(vdisp[0]);
+	if(typeof o3_followscroll != 'undefined' && o3_followscroll && o3_sticky) o3_relx = placeX;
+
+	return placeX;
+}
+function centerPopupVertical(browserHeight,verticalScrollAmount) {
+	if (!o3_centerpopup) return void(0);
+
+	var placeY, iheight = browserHeight, scrolloffset = verticalScrollAmount;
+	var vdisp = o3_centeroffset.split(',');
+	var pHeight = (o3_aboveheight ? parseInt(o3_aboveheight) : (olNs4 ? over.clip.height : over.offsetHeight));
+
+	placeY = scrolloffset + Math.round((iheight - pHeight)/2) + (vdisp.length > 1 ? parseInt(vdisp[1]) : 0);
+	if(typeof o3_followscroll != 'undefined' && o3_followscroll && o3_sticky) o3_rely = placeY;
+
+	return placeY;
+}
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerRunTimeFunction(setCenterPopupVariables);
+registerCmdLineFunction(parseCenterPopupExtras);
+registerHook('horizontalPlacement',centerPopupHorizontal,FCHAIN);
+registerHook('verticalPlacement', centerPopupVertical, FCHAIN);
+if(olInfo.meets(4.10)) registerNoParameterCommands('centerpopup');
+}
\ No newline at end of file
diff --git a/OpenFreezer/overlib/overlib_crossframe.js b/OpenFreezer/overlib/overlib_crossframe.js
new file mode 100755
index 0000000..d58e5a8
--- /dev/null
+++ b/OpenFreezer/overlib/overlib_crossframe.js
@@ -0,0 +1,105 @@
+//\/////
+//\  overLIB Crossframe Support Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.05 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//   $Revision: 1.8 $                $Date: 2004/11/25 21:27:19 $
+//\/////
+//\mini
+
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || typeof olInfo.meets == 'undefined' || !olInfo.meets(4.10)) alert('overLIB 4.10 or later is required for the Cross Frame Support Plugin.');
+else {
+registerCommands('frame');
+
+
+////////
+//  PLUGIN FUNCTIONS
+///////
+
+// Parses FRAME command
+function parseFrameExtras(pf,i,ar) {
+	var k = i,v;
+
+	if (k < ar.length) {
+		if (ar[k] == FRAME) { v = ar[++k]; if(pf == 'ol_') ol_frame = v; else opt_FRAME(v); return k; }
+	}
+
+	return -1;
+}
+
+////////
+// SUPPORT FUNCTIONS
+////////
+
+// Defines which frame we should point to.
+function opt_FRAME(frm) {
+ 	o3_frame = frm; 	
+	over = createDivContainer('overDiv');	
+	return 0;
+}
+
+// Get frame depth of nested frames
+function frmDepth(thisFrame,ofrm) {
+	var retVal = '';
+
+	for (var i = 0; i<thisFrame.length; i++) {
+		if (thisFrame[i].length > 0) { 
+			retVal = frmDepth(thisFrame[i],ofrm);
+			if (retVal ==  '') continue;
+		} else if (thisFrame[i] != ofrm) continue;
+		retVal = '[' + i + ']' + retVal;
+		break;
+	}
+
+	return retVal;
+}
+
+// Gets frame reference value relative to top frame
+function getFrmRef(srcFrm,tgetFrm) {
+	var rtnVal = ''
+
+	if (tgetFrm != srcFrm) {
+		var tFrm = frmDepth(top.frames,tgetFrm)
+		var sFrm = frmDepth(top.frames,srcFrm)
+		if (sFrm.length ==  tFrm.length) {
+			l = tFrm.lastIndexOf('[')
+			
+			if (l) {
+				while ( sFrm.substring(0,l) != tFrm.substring(0,l) )
+				l = tFrm.lastIndexOf('[',l-1)
+				tFrm = tFrm.substr(l)
+				sFrm = sFrm.substr(l)
+			}
+		}
+	
+		var cnt = 0, p = '',str = tFrm
+		while ((k = str.lastIndexOf('[')) != -1) {
+			cnt++ 
+			str = str.substring(0,k)
+		}
+
+		for (var i = 0; i<cnt; i++) p = p + 'parent.'
+		rtnVal = p + 'frames' + sFrm + '.'
+	}
+ 
+	return rtnVal
+}
+
+function chkForFrmRef() {
+	if(o3_frame != ol_frame) fnRef = getFrmRef(ol_frame,o3_frame)
+	return true;
+}
+
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerCmdLineFunction(parseFrameExtras);
+registerPostParseFunction(chkForFrmRef);
+}
\ No newline at end of file
diff --git a/OpenFreezer/overlib/overlib_cssstyle.js b/OpenFreezer/overlib/overlib_cssstyle.js
new file mode 100755
index 0000000..95c725b
--- /dev/null
+++ b/OpenFreezer/overlib/overlib_cssstyle.js
@@ -0,0 +1,182 @@
+//\/////
+//\  overLIB CSS Style Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.05 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//   $Revision: 1.11 $                      $Date: 2004/11/25 21:27:19 $
+//\/////
+//\mini
+
+
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || typeof olInfo.meets == 'undefined' || !olInfo.meets(4.10)) alert('overLIB 4.10 or later is required for the CSS Style Plugin.');
+else {
+registerCommands('cssstyle,padunit,heightunit,widthunit,textsizeunit,textdecoration,textstyle,textweight,captionsizeunit,captiondecoration,captionstyle,captionweight,closesizeunit,closedecoration,closestyle,closeweight');
+
+
+////////
+// DEFAULT CONFIGURATION
+// Settings you want everywhere are set here. All of this can also be
+// changed on your html page or through an overLIB call.
+////////
+if (typeof ol_padunit=='undefined') var ol_padunit="px";
+if (typeof ol_heightunit=='undefined') var ol_heightunit="px";
+if (typeof ol_widthunit=='undefined') var ol_widthunit="px";
+if (typeof ol_textsizeunit=='undefined') var ol_textsizeunit="px";
+if (typeof ol_textdecoration=='undefined') var ol_textdecoration="none";
+if (typeof ol_textstyle=='undefined') var ol_textstyle="normal";
+if (typeof ol_textweight=='undefined') var ol_textweight="normal";
+if (typeof ol_captionsizeunit=='undefined') var ol_captionsizeunit="px";
+if (typeof ol_captiondecoration=='undefined') var ol_captiondecoration="none";
+if (typeof ol_captionstyle=='undefined') var ol_captionstyle="normal";
+if (typeof ol_captionweight=='undefined') var ol_captionweight="bold";
+if (typeof ol_closesizeunit=='undefined') var ol_closesizeunit="px";
+if (typeof ol_closedecoration=='undefined') var ol_closedecoration="none";
+if (typeof ol_closestyle=='undefined') var ol_closestyle="normal";
+if (typeof ol_closeweight=='undefined') var ol_closeweight="normal";
+
+////////
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+
+
+
+////////
+// INIT
+////////
+// Runtime variables init. Don't change for config!
+var o3_padunit="px";
+var o3_heightunit="px";
+var o3_widthunit="px";
+var o3_textsizeunit="px";
+var o3_textdecoration="";
+var o3_textstyle="";
+var o3_textweight="";
+var o3_captionsizeunit="px";
+var o3_captiondecoration="";
+var o3_captionstyle="";
+var o3_captionweight="";
+var o3_closesizeunit="px";
+var o3_closedecoration="";
+var o3_closestyle="";
+var o3_closeweight="";
+
+
+////////
+// PLUGIN FUNCTIONS
+////////
+
+// Function which sets runtime variables to their default values
+function setCSSStyleVariables() {
+	o3_padunit=ol_padunit;
+	o3_heightunit=ol_heightunit;
+	o3_widthunit=ol_widthunit;
+	o3_textsizeunit=ol_textsizeunit;
+	o3_textdecoration=ol_textdecoration;
+	o3_textstyle=ol_textstyle;
+	o3_textweight=ol_textweight;
+	o3_captionsizeunit=ol_captionsizeunit;
+	o3_captiondecoration=ol_captiondecoration;
+	o3_captionstyle=ol_captionstyle;
+	o3_captionweight=ol_captionweight;
+	o3_closesizeunit=ol_closesizeunit;
+	o3_closedecoration=ol_closedecoration;
+	o3_closestyle=ol_closestyle;
+	o3_closeweight=ol_closeweight;
+}
+
+// Parses CSS Style commands.
+function parseCSSStyleExtras(pf, i, ar) {
+	var k = i;
+	
+	if (k < ar.length) {
+		if (ar[k]==CSSSTYLE) { eval(pf+'css='+ar[k]); return k; }
+		if (ar[k]==PADUNIT) { eval(pf+'padunit="'+ar[++k]+'"'); return k; }
+		if (ar[k]==HEIGHTUNIT) { eval(pf+'heightunit="'+ar[++k]+'"'); return k; }
+		if (ar[k]==WIDTHUNIT) { eval(pf+'widthunit="'+ar[++k]+'"'); return k; }
+		if (ar[k]==TEXTSIZEUNIT) { eval(pf+'textsizeunit="'+ar[++k]+'"'); return k; }
+		if (ar[k]==TEXTDECORATION) { eval(pf+'textdecoration="'+ar[++k]+'"'); return k; }
+		if (ar[k]==TEXTSTYLE) { eval(pf+'textstyle="'+ar[++k]+'"'); return k; }
+		if (ar[k]==TEXTWEIGHT) { eval(pf+'textweight="'+ar[++k]+'"'); return k; }
+		if (ar[k]==CAPTIONSIZEUNIT) { eval(pf+'captionsizeunit="'+ar[++k]+'"'); return k; }
+		if (ar[k]==CAPTIONDECORATION) { eval(pf+'captiondecoration="'+ar[++k]+'"'); return k; }
+		if (ar[k]==CAPTIONSTYLE) { eval(pf+'captionstyle="'+ar[++k]+'"'); return k; }
+		if (ar[k]==CAPTIONWEIGHT) { eval(pf+'captionweight="'+ar[++k]+'"'); return k; }
+		if (ar[k]==CLOSESIZEUNIT) { eval(pf+'closesizeunit="'+ar[++k]+'"'); return k; }
+		if (ar[k]==CLOSEDECORATION) { eval(pf+'closedecoration="'+ar[++k]+'"'); return k; }
+		if (ar[k]==CLOSESTYLE) { eval(pf+'closestyle="'+ar[++k]+'"'); return k; }
+		if (ar[k]==CLOSEWEIGHT) { eval(pf+'closeweight="'+ar[++k]+'"'); return k; }
+	}
+	
+	return -1;
+}
+
+////////
+// LAYER GENERATION FUNCTIONS
+////////
+
+// Makes simple table without caption
+function ol_content_simple_cssstyle(text) {
+	txt = '<table width="'+o3_width+ '" border="0" cellpadding="'+o3_border+'" cellspacing="0" style="background-color: '+o3_bgcolor+'; height: '+o3_height+o3_heightunit+';"><tr><td><table width="100%" border="0" cellpadding="' + o3_cellpad + '" cellspacing="0" style="color: '+o3_fgcolor+'; background-color: '+o3_fgcolor+'; height: '+o3_height+o3_heightunit+';"><tr><td valign="TOP"><font style="font-family: '+o3_textfont+'; color: '+o3_textcolor+'; font-size: '+o3_textsize+o3_textsizeunit+' [...]
+	set_background("");
+	
+	return txt;
+}
+
+// Makes table with caption and optional close link
+function ol_content_caption_cssstyle(text, title, close) {
+	var nameId;
+	closing = "";
+	closeevent = "onMouseOver";
+	
+	if (o3_closeclick == 1) closeevent= (o3_closetitle ? "title='" + o3_closetitle +"'" : "") + " onClick";
+
+	if (o3_capicon!="") {
+		nameId=' hspace=\"5\"'+' align=\"middle\" alt=\"\"';
+		if (typeof o3_dragimg != 'undefined' && o3_dragimg) nameId = ' hspace=\"5\"'+' name=\"'+o3_dragimg+'\" id=\"'+o3_dragimg+'\" align=\"middle\" alt=\"Drag Enabled\" title=\"Drag Enabled\"';
+		o3_capicon = '<img src=\"'+o3_capicon+'\"'+nameId+' />';
+	}
+	
+	if (close != "") {
+		closing = '<td align="RIGHT"><a href="javascript:return '+fnRef+'cClick();" '+closeevent+'="return '+fnRef+'cClick();" style="color: '+o3_closecolor+'; font-family: '+o3_closefont+'; font-size: '+o3_closesize+o3_closesizeunit+'; text-decoration: '+o3_closedecoration+'; font-weight: '+o3_closeweight+'; font-style:'+o3_closestyle+';">'+close+'</a></td>';
+	}
+	
+	txt = '<table width="'+o3_width+ '" border="0" cellpadding="'+o3_border+'" cellspacing="0" style="background-color: '+o3_bgcolor+'; background-image: url('+o3_bgbackground+'); height: '+o3_height+o3_heightunit+';"><tr><td><table width="100%" border="0" cellpadding="0" cellspacing="0"><tr><td><font style="font-family: '+o3_captionfont+'; color: '+o3_capcolor+'; font-size: '+o3_captionsize+o3_captionsizeunit+'; font-weight: '+o3_captionweight+'; font-style: '+o3_captionstyle+'; text-decor [...]
+	set_background("");
+
+	return txt;
+}
+
+// Sets the background picture, padding and lots more. :)
+function ol_content_background_cssstyle(text, picture, hasfullhtml) {
+	if (hasfullhtml) {
+		txt = text;
+	} else {
+		var pU, hU, wU;
+		pU = (o3_padunit == '%' ? '%' : '');
+		hU = (o3_heightunit == '%' ? '%' : '');
+		wU = (o3_widthunit == '%' ? '%' : '');
+		txt = '<table width="'+o3_width+wu+'" border="0" cellpadding="0" cellspacing="0" height="'+o3_height+hu+'"><tr><td colspan="3" height="'+o3_padyt+pu+'"></td></tr><tr><td width="'+o3_padxl+pu+'"></td><td valign="TOP" width="'+(o3_width-o3_padxl-o3_padxr)+pu+'"><font style="font-family: '+o3_textfont+'; color: '+o3_textcolor+'; font-size: '+o3_textsize+o3_textsizeunit+';">'+text+'</font></td><td width="'+o3_padxr+pu+'"></td></tr><tr><td colspan="3" height="'+o3_padyb+pu+'"></td></tr></table>';
+	}
+
+	set_background(picture);
+
+	return txt;
+}
+
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerRunTimeFunction(setCSSStyleVariables);
+registerCmdLineFunction(parseCSSStyleExtras);
+registerHook("ol_content_simple", ol_content_simple_cssstyle, FALTERNATE, CSSSTYLE);
+registerHook("ol_content_caption", ol_content_caption_cssstyle, FALTERNATE, CSSSTYLE);
+registerHook("ol_content_background", ol_content_background_cssstyle, FALTERNATE, CSSSTYLE);
+}
\ No newline at end of file
diff --git a/OpenFreezer/overlib/overlib_debug.js b/OpenFreezer/overlib/overlib_debug.js
new file mode 100755
index 0000000..325516e
--- /dev/null
+++ b/OpenFreezer/overlib/overlib_debug.js
@@ -0,0 +1,177 @@
+//\/////
+//\  overLIB Debug Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.05 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2003. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//   $Revision: 1.6 $                $Date: 2005/02/01 22:18:44 $
+//
+//\/////
+//\mini
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || typeof olInfo.meets == 'undefined' || !olInfo.meets(4.10)) alert('overLIB 4.10 or later is required for the Debug Plugin.');
+else {
+var olZindex;
+registerCommands('allowdebug');
+////////
+// PLUGIN FUNCTIONS
+////////
+// Parses Debug Parameters
+function parseDebugExtras(pf, i, ar) {
+	var k =  i, v;
+
+	if (k < ar.length) {
+		if (ar[k] == ALLOWDEBUG) { v = ar[k + 1]; if(typeof v == 'string') {v = ar[++k]; if (pf != 'ol_') setCanShowParm(v);} return k; }
+	}
+
+	return -1;
+}
+// Debug main routine
+function showProperties() {
+	var args = showProperties.arguments, sho, shoObj, vis, lvl = 0, istrt = 0, theDiv = 'showProps', txt = '';
+
+	if (args.length == 0) return;
+	if (args.length % 2 && typeof args[0] == 'string') {
+		istrt = 1;
+		theDiv = args[0];
+	}
+
+	sho = createDivContainer(theDiv);
+
+	if (olNs4) {
+		shoObj = sho;
+		txt += '<table cellpadding="1" cellspacing="0" border="0" bgcolor="#000000"><tr><td>';
+	} else {
+		with(sho.style) {
+			backgroundColor = '#ffffcc';
+			padding = '5px';
+			border = '1px #000000 solid';
+		}
+		shoObj = sho.style;
+	}
+
+	lvl = getLayerLevel(theDiv);
+
+	if(typeof sho.position == 'undefined') {
+		sho.position = new Pagelocation(10 + lvl*20, 10, 1);
+		if(typeof olZindex == 'undefined') olZindex = getDivZindex();
+		shoObj.zIndex = olZindex + 1 + lvl;
+	}
+
+	txt += '<table cellpadding="5" border="0" cellspacing="0"' + (olNs4 ? ' bgcolor="#ffffcc"' : '') + '>';
+	txt += '<tr><td><strong><A HREF="javascript:moveToBack(\'' + theDiv + '\');" title="Move to back">' + theDiv + '</A></strong></td><td align="RIGHT"><strong><a href="javascript:closeLayer(\'' + theDiv + '\');" TITLE="Close Layer' + (!olNs4 ? '" style="background-color: #CCCCCC; border:2px #333369 outset; padding: 2px;' : '') + '">X</a></strong></td></tr>';
+	txt += '<tr><td style="text-decoration: underline;"><strong>Item</strong></td><td style="text-decoration: underline;"><strong>Value</strong></td></tr>';
+	for (var i = istrt; i<args.length-1; i++) 
+		txt += '<tr><td align="right"><strong>' + args[i] + ': </strong></td><td>' + args[++i] + '</td></tr>';
+	txt += '</table>' + (olNs4 ? '</td></tr></table>' : '');
+
+	if (olNs4) {
+		sho.document.open();
+		sho.document.write(txt);
+		sho.document.close();
+	} else {
+		if(olIe5&&isMac) sho.innerHTML = '';
+		sho.innerHTML = txt;
+	}
+
+	showAllVisibleLayers();
+}
+function getLayerLevel(lyr) {
+	var i = 0;
+
+	if (typeof document.popups == 'undefined') {
+		document.popups = new Array(lyr);
+	} else {
+		var l = document.popups;
+		for (var i = 0; i<l.length; i++) if (lyr == l[i]) break;
+		if(i == l.length) l[l.length++] = lyr;
+	}
+
+	return i;
+}
+function getDivZindex(id) {
+	var obj;
+
+	if(id == '' || id == null) id = 'overDiv';
+
+	obj = layerReference(id);
+	obj = (olNs4 ? obj : obj.style);
+
+	return obj.zIndex;
+}
+function setCanShowParm(debugID) {
+	var lyr, pLyr;
+
+	if(typeof debugID != 'string') return;
+
+	pLyr = debugID.split(',');
+	for(var i = 0; i<pLyr.length; i++) {
+		lyr = layerReference(pLyr[i]);
+		if(lyr != null && typeof lyr.position != 'undefined') lyr.position.canShow = 1;
+	}
+}
+function Pagelocation(x, y, canShow) {
+	this.x = x;
+	this.y = y;
+  this.canShow = (canShow == null) ? 0 : canShow;
+}
+function showAllVisibleLayers(){
+	var lyr, lyrObj, l = document.popups;
+
+	for (var i = 0; i<l.length; i++) {
+		lyr = layerReference(l[i]);
+		lyrObj = (olNs4 ? lyr : lyr.style);
+    if(lyr.position.canShow) {
+  		positionLayer(lyrObj, lyr.position.x, lyr.position.y);
+  		lyrObj.visibility = 'visible';
+    }
+	}
+}
+function positionLayer(Obj, x, y) { // Obj is obj.style for IE/NS6+ but obj for NS4
+	Obj.left = x + (olIe4 ? eval(docRoot + '.scrollLeft') : window.pageXOffset) + (olNs4 ? 0 : 'px');
+	Obj.top = y + (olIe4 ? eval(docRoot + '.scrollTop') : window.pageYOffset) + (olNs4 ? 0 : 'px');
+}
+function closeLayer(lyrID) {
+	var lyr = layerReference(lyrID);
+
+  lyr.position.canShow = 0;
+	lyr = (olNs4 ? lyr : lyr.style);
+	lyr.visibility = 'hidden';
+}
+function moveToBack(layer) {
+	var l = document.popups, lyr, obj, i, x = 10, y = 10, dx = 20, z = olZindex + 1;
+
+	if(l.length == 1) return;
+
+	lyr = layerReference(layer);
+	lyr.position.x = x;
+	lyr.position.y = y;
+	obj = (olNs4 ? lyr : lyr.style);
+	obj.zIndex = z;
+
+	for (i = 0; i<l.length; i++) {
+		if (layer == l[i]) continue;
+		lyr = layerReference(l[i]);
+    if(lyr.position.canShow == 0) continue;
+		obj = (olNs4 ? lyr : lyr.style);
+		obj.zIndex += 1;
+		lyr.position.x += dx;
+		lyr.position.y = y;
+	}
+
+	showAllVisibleLayers();
+}
+function rawTxt(txt) {
+	if (typeof txt != 'string') return;
+	return txt.replace(/</g,"<").replace(/>/g,">").replace(/"/g,""");
+}
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerCmdLineFunction(parseDebugExtras);
+}
\ No newline at end of file
diff --git a/OpenFreezer/overlib/overlib_exclusive.js b/OpenFreezer/overlib/overlib_exclusive.js
new file mode 100755
index 0000000..cccce63
--- /dev/null
+++ b/OpenFreezer/overlib/overlib_exclusive.js
@@ -0,0 +1,123 @@
+//\/////
+//\  overLIB Exclusive Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.05 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//   $Revision: 1.7 $                      $Date: 2004/11/25 21:27:19 $
+//\/////
+//\mini
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || typeof olInfo.meets == 'undefined' || !olInfo.meets(4.10)) alert('overLIB 4.10 or later is required for the Debug Plugin.');
+else {
+registerCommands('exclusive,exclusivestatus,exclusiveoverride');
+var olOverrideIsSet;  // variable which tells if override is set
+
+
+////////
+// DEFAULT CONFIGURATION
+// Settings you want everywhere are set here. All of this can also be
+// changed on your html page or through an overLIB call.
+////////
+if (typeof ol_exclusive == 'undefined') var ol_exclusive = 0;
+if (typeof ol_exclusivestatus == 'undefined') var ol_exclusivestatus = 'Please close open popup first.';
+
+////////
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+
+
+////////
+// INIT
+////////
+// Runtime variables init. Don't change for config!
+var o3_exclusive = 0;
+var o3_exclusivestatus = '';
+
+////////
+// PLUGIN FUNCTIONS
+////////
+
+// Set runtime variables
+function setExclusiveVariables() {
+	o3_exclusive = ol_exclusive;
+	o3_exclusivestatus = ol_exclusivestatus;
+}
+
+// Parses Exclusive Parameters
+function parseExclusiveExtras(pf,i,ar) {
+	var k = i,v;
+
+	olOverrideIsSet = false;  // a global variable
+
+	if (k < ar.length) {
+		if (ar[k] == EXCLUSIVEOVERRIDE) { if(pf !=  'ol_') olOverrideIsSet = true; return k; }
+		if (ar[k] == EXCLUSIVE) { eval(pf +  'exclusive = (' +  pf + 'exclusive == 0) ? 1 : 0'); return k; }
+		if (ar[k] == EXCLUSIVESTATUS) { eval(pf + "exclusivestatus = '" + escSglQuote(ar[++k]) + "'"); return k; }
+	}
+
+	return -1;
+}
+
+///////
+//  HELPER FUNCTIONS
+///////
+// set status message and indicate whether popup is exclusive
+function isExclusive(args) {
+	var rtnVal = false;
+
+	if(args != null) rtnVal = hasCommand(args, EXCLUSIVEOVERRIDE);
+
+	if(rtnVal) return false;
+	else {
+		self.status = (o3_exclusive) ? o3_exclusivestatus : '';
+		return o3_exclusive;
+	}
+
+}
+
+// checks overlib argument list to see if it has a COMMAND argument
+function hasCommand(args, COMMAND) {
+	var rtnFlag = false;
+
+	for (var i=0; i<args.length; i++) {
+		if (typeof args[i] == 'number' &&  args[i] == COMMAND) {
+			rtnFlag = true;
+			break;
+		}
+	}
+
+	return rtnFlag;
+}
+
+// makes sure exclusive setting is off
+function clearExclusive() {
+	o3_exclusive = 0;
+}
+
+function setExclusive() {
+	o3_exclusive = (o3_showingsticky &&  o3_exclusive);
+}
+
+function chkForExclusive() {
+	if (olOverrideIsSet) o3_exclusive = 0;  // turn it off in case it's been set.
+
+	return true;
+}
+
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerRunTimeFunction(setExclusiveVariables);
+registerCmdLineFunction(parseExclusiveExtras);
+registerPostParseFunction(chkForExclusive);
+registerHook("createPopup",setExclusive,FBEFORE);
+registerHook("hideObject",clearExclusive,FAFTER);
+if (olInfo.meets(4.10)) registerNoParameterCommands('exclusive');
+}
\ No newline at end of file
diff --git a/OpenFreezer/overlib/overlib_followscroll.js b/OpenFreezer/overlib/overlib_followscroll.js
new file mode 100755
index 0000000..6898fbb
--- /dev/null
+++ b/OpenFreezer/overlib/overlib_followscroll.js
@@ -0,0 +1,175 @@
+//\/////
+//\  overLIB Follow Scroll Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.10 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//   $Revision: 1.12 $                      $Date: 2004/11/25 21:27:19 $
+//\/////
+//\mini
+
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || typeof olInfo.meets == 'undefined' || !olInfo.meets(4.10)) alert('overLIB 4.10 or later is required for the Follow Scroll Plugin.');
+else {
+registerCommands('followscroll,followscrollrefresh');
+
+
+////////
+// DEFAULT CONFIGURATION
+// You don't have to change anything here if you don't want to. All of this can be
+// changed on your html page or through an overLIB call.
+////////
+// Default value for scroll is not to scroll (0)
+if (typeof ol_followscroll=='undefined') var ol_followscroll=0;
+if (typeof ol_followscrollrefresh=='undefined') var ol_followscrollrefresh=100;
+
+////////
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+
+
+
+
+
+
+
+////////
+// INIT
+////////
+// Runtime variables init. Don't change for config!
+var o3_followscroll=0;
+var o3_followscrollrefresh=100;
+
+
+////////
+// PLUGIN FUNCTIONS
+////////
+function setScrollVariables() {
+	o3_followscroll=ol_followscroll;
+	o3_followscrollrefresh=ol_followscrollrefresh;
+}
+
+// Parses Shadow and Scroll commands
+function parseScrollExtras(pf,i,ar) {
+	var k=i,v;
+	if (k < ar.length) {
+		if (ar[k]==FOLLOWSCROLL) { eval(pf +'followscroll=('+pf+'followscroll==0) ? 1 : 0'); return k; }
+		if (ar[k]==FOLLOWSCROLLREFRESH) { eval(pf+'followscrollrefresh='+ar[++k]); return k; }
+	}
+	return -1;
+}
+
+
+
+// Function to support scroll feature (overloads default)
+function scroll_placeLayer() {
+	var placeX, placeY, widthFix = 0;
+	
+	// HORIZONTAL PLACEMENT
+	if (o3_frame.innerWidth) { 
+		widthFix=Math.ceil(1.2*(o3_frame.outerWidth - o3_frame.innerWidth));
+    widthFix = (widthFix > 50) ? 20 : widthFix;
+		iwidth=o3_frame.innerWidth;
+	} else if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientWidth=='number'")&&eval('o3_frame.'+docRoot+'.clientWidth')) 
+		iwidth=eval('o3_frame.'+docRoot+'.clientWidth');			
+
+	// Horizontal scroll offset
+	winoffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollLeft') : o3_frame.pageXOffset;
+
+	placeX = runHook('horizontalPlacement',FCHAIN,iwidth,winoffset,widthFix);
+	
+	// VERTICAL PLACEMENT
+	if (o3_frame.innerHeight) iheight=o3_frame.innerHeight;
+	else if (eval('o3_frame.'+docRoot)&&eval("typeof o3_frame."+docRoot+".clientHeight=='number'")&&eval('o3_frame.'+docRoot+'.clientHeight')) 
+		iheight=eval('o3_frame.'+docRoot+'.clientHeight');			
+
+	// Vertical scroll offset
+	scrolloffset=(olIe4) ? eval('o3_frame.'+docRoot+'.scrollTop') : o3_frame.pageYOffset;
+
+	placeY = runHook('verticalPlacement',FCHAIN,iheight,scrolloffset);
+
+	// Actually move the object.
+	repositionTo(over,placeX,placeY);
+	
+	if (o3_followscroll && o3_sticky && (o3_relx || o3_rely) && (typeof o3_draggable == 'undefined' || !o3_draggable)) {
+		if (typeof over.scroller=='undefined' || over.scroller.canScroll) over.scroller = new Scroller(placeX-winoffset,placeY-scrolloffset,o3_followscrollrefresh);
+	}
+}
+
+
+
+///////
+// SUPPORT ROUTINES FOR SCROLL FEATURE
+///////
+
+// Scroller constructor
+function Scroller(X,Y,refresh) {
+	this.canScroll=0;
+	this.refresh=refresh;
+	this.x=X;
+	this.y=Y;
+	this.timer=setTimeout("repositionOver()",this.refresh);
+}
+
+// Removes the timer to stop replacing the layer.
+function cancelScroll() {
+	if (!o3_followscroll || typeof over.scroller == 'undefined') return;
+	over.scroller.canScroll = 1;
+	
+	if (over.scroller.timer) {
+		clearTimeout(over.scroller.timer);
+		over.scroller.timer=null;
+	}
+}
+
+// Find out how much we've scrolled.
+	function getPageScrollY() {
+	if (o3_frame.pageYOffset) return o3_frame.pageYOffset;
+	if (eval(docRoot)) return eval('o3_frame.' + docRoot + '.scrollTop');
+	return -1;
+}
+function getPageScrollX() {
+	if (o3_frame.pageXOffset) return o3_frame.pageXOffset;
+	if (eval(docRoot)) return eval('o3_frame.'+docRoot+'.scrollLeft');
+	return -1;
+}
+
+// Find out where our layer is
+function getLayerTop(layer) {
+	if (layer.pageY) return layer.pageY;
+	if (layer.style.top) return parseInt(layer.style.top);
+	return -1;
+}
+function getLayerLeft(layer) {
+	if (layer.pageX) return layer.pageX;
+	if (layer.style.left) return parseInt(layer.style.left);
+	return -1;
+}
+
+// Repositions the layer if needed
+function repositionOver() {
+	var X, Y, pgLeft, pgTop;
+	pgTop = getPageScrollY();
+	pgLeft = getPageScrollX();
+	X = getLayerLeft(over)-pgLeft;
+	Y = getLayerTop(over)-pgTop;
+	
+	if (X != over.scroller.x || Y != over.scroller.y) repositionTo(over, pgLeft+over.scroller.x, pgTop+over.scroller.y);
+	over.scroller.timer = setTimeout("repositionOver()", over.scroller.refresh);
+}
+
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerRunTimeFunction(setScrollVariables);
+registerCmdLineFunction(parseScrollExtras);
+registerHook("hideObject",cancelScroll,FAFTER);
+registerHook("placeLayer",scroll_placeLayer,FREPLACE);
+if (olInfo.meets(4.10)) registerNoParameterCommands('followscroll');
+}
diff --git a/OpenFreezer/overlib/overlib_hideform.js b/OpenFreezer/overlib/overlib_hideform.js
new file mode 100755
index 0000000..3b576e0
--- /dev/null
+++ b/OpenFreezer/overlib/overlib_hideform.js
@@ -0,0 +1,135 @@
+//\/////
+//\  overLIB Hide Form Plugin
+//\
+//\  Uses an iframe shim to mask system controls for IE v5.5 or higher as suggested in
+//\  http://dotnetjunkies.com/weblog/jking/posts/488.aspx
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.05 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2004. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//   $Revision: 1.20 $                $Date: 2004/11/25 21:27:19 $
+//\/////
+//\mini
+if (typeof olInfo == 'undefined' || typeof olInfo.meets == 'undefined' || !olInfo.meets(4.10)) alert('overLIB 4.10 or later is required for the HideForm Plugin.');
+else {
+
+// Function which generates the popup with an IFRAME shim
+function generatePopUp(content) {
+	if(!olIe4||olOp||!olIe55||(typeof o3_shadow != 'undefined' && o3_shadow)||(typeof o3_bubble != 'undefined' && o3_bubble)) return;
+
+	var wd,ht,txt, zIdx =  0;
+
+	wd =  parseInt(o3_width);
+	ht =  over.offsetHeight;
+	txt =  backDropSource(wd,ht,zIdx++);
+	txt += '<div style="position: absolute; top: 0; left: 0; width: '+ wd+'px; z-index: ' + zIdx + ';">' + content + '</div>';
+	layerWrite(txt);
+}
+
+// Code for the IFRAME which is used in other places
+function backDropSource(width, height, Z) {
+	return '<iframe frameborder="0" scrolling="no" src="javascript:false;" width="' + width + '" height="' + height + '" style="z-index: ' + Z + '; filter: Beta(Style=0,Opacity=0);"></iframe>';
+}
+
+// Hides SELECT boxes that will be under the popup
+// Checking Gecko version number to try to include other browsers based on the Gecko engine
+function hideSelectBox() {
+	if(olNs4 || olOp || olIe55) return;
+	var px, py, pw, ph, sx, sw, sy, sh, selEl, v;
+
+	if(olIe4) v = 0;
+	else {
+		v = navigator.userAgent.match(/Gecko\/(\d{8})/i);
+		if(!v) return;   // return if no string match
+		v = parseInt(v[1]);
+	}
+
+	if (v < 20030624) {  // versions less than June 24, 2003 were earlier Netscape browsers
+		px = parseInt(over.style.left);
+		py = parseInt(over.style.top);
+		pw = o3_width;
+		ph = (o3_aboveheight ? parseInt(o3_aboveheight) : over.offsetHeight);
+		selEl = (olIe4) ? o3_frame.document.all.tags("SELECT") : o3_frame.document.getElementsByTagName("SELECT");
+		for (var i=0; i<selEl.length; i++) {
+			if(!olIe4 && selEl[i].size < 2) continue;  // Not IE and SELECT size is 1 or not specified
+			sx = pageLocation(selEl[i],'Left');
+			sy = pageLocation(selEl[i],'Top');
+			sw = selEl[i].offsetWidth;
+			sh = selEl[i].offsetHeight;
+			if((px+pw) < sx || px > (sx+sw) || (py+ph) < sy || py > (sy+sh)) continue;
+			selEl[i].isHidden = 1;
+			selEl[i].style.visibility = 'hidden';
+		}
+	}
+}
+
+// Shows previously hidden SELECT Boxes
+function showSelectBox() {
+	if(olNs4 || olOp || olIe55) return;
+	var selEl, v;
+
+	if(olIe4) v = 0;
+	else {
+		v = navigator.userAgent.match(/Gecko\/(\d{8})/i);
+		if(!v) return; 
+		v = parseInt(v[1]);
+	}
+
+	if(v < 20030624) {
+		selEl = (olIe4) ? o3_frame.document.all.tags("SELECT") : o3_frame.document.getElementsByTagName("SELECT");
+		for (var i=0; i<selEl.length; i++) {
+			if(typeof selEl[i].isHidden !=  'undefined' && selEl[i].isHidden) {
+				selEl[i].isHidden = 0;
+				selEl[i].style.visibility = 'visible';
+			}
+		}
+	}
+}
+
+// function gets the total offset properties of an element
+// this same function occurs in overlib_mark.js.
+function pageLocation(o,t){
+	var x = 0
+
+	while(o.offsetParent){
+		x += o['offset'+t]
+		o = o.offsetParent
+	}
+
+	x += o['offset'+t]
+
+	return x
+}
+
+// reset mouse move routine for NS7 but not NS7.1,Opera, or IE5.5+
+// It also bypasses Netscape 6 since the modifications mess up the display of popups
+// and don't work anyways.
+// Modify mouse move routine while loading so that hideSelectBox()
+// can be called from the correct location
+if (!(olNs4 || olOp || olIe55 || navigator.userAgent.indexOf('Netscape6') != -1)) {
+	var MMStr = olMouseMove.toString();
+	var strRe = /(if\s*\(o3_allowmove\s*==\s*1.*\)\s*)/;
+	var f = MMStr.match(strRe);
+
+	if (f) {
+		var ls = MMStr.search(strRe);
+		ls += f[1].length;
+		var le = MMStr.substring(ls).search(/[;|}]\n/);
+		MMStr = MMStr.substring(0,ls) + ' { runHook("placeLayer",FREPLACE); if(olHideForm) hideSelectBox(); ' + MMStr.substring(ls + (le != -1 ? le+3 : 0));
+		document.writeln('<script type="text/javascript">\n<!--\n' + MMStr + '\n//-->\n</' + 'script>');
+	}
+
+	f = capExtent.onmousemove.toString().match(/function[ ]+(\w*)\(/);
+	if (f&&f[1] != 'anonymous') capExtent.onmousemove = olMouseMove;
+}
+
+
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerHook("createPopup",generatePopUp,FAFTER);
+registerHook("hideObject",showSelectBox,FAFTER);
+olHideForm=1;
+}
diff --git a/OpenFreezer/overlib/overlib_setonoff.js b/OpenFreezer/overlib/overlib_setonoff.js
new file mode 100755
index 0000000..c996c14
--- /dev/null
+++ b/OpenFreezer/overlib/overlib_setonoff.js
@@ -0,0 +1,101 @@
+//\/////
+//\  overLIB Set On/Off Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.10 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2003. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//   $Revision: 1.3 $                $Date: 2004/11/25 21:27:19 $
+//
+//\/////
+//\mini
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || typeof olInfo.meets == 'undefined' || !olInfo.meets(4.10)) alert('overLIB 4.10 or later is required for the Set On/Off Plugin.');
+else {
+registerCommands('seton, setoff');
+var olSetType;
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+// PLUGIN FUNCTIONS
+////////
+// Set runtime variables
+function setOnOffVariables() {
+	olSetType = 0;
+}
+// Parses Set On/Off Parameters
+function parseOnOffExtras(pf, i, ar) {
+	var k = i, v;
+
+	if (k < ar.length) {
+		if (ar[k] == SETON||ar[k] == SETOFF) { olSetType = 1; k = opt_MULTICOMMANDS(++k, ar); return k; }
+	}
+
+	return -1;
+}
+///////
+//  HELPER FUNCTIONS
+///////
+// searches arg list for COMMAND; 
+function hasCommand(istrt, args, COMMAND) {
+	for (var i = istrt; i < args.length; i++) {
+		if (typeof args[i] == 'number' &&  args[i] == COMMAND) return i;
+	}
+
+	return -1;
+}
+// scans for toggle like commands to be forced ON/OFF
+function scanCommandSet(pf, args) {
+	var k = -1, j, je;
+
+	if (olSetType) {
+		// search for SETON command
+		while ((k = hasCommand(++k, args, SETON)) < args.length && k > -1) {
+			je = opt_MULTICOMMANDS(k + 1, args);
+			for (j = k + 1; j <  (k + je); j++) setNoParamCommand(1, pf, args[j]);
+			k += (je - 1);
+		}
+		// search for SETOFF command
+		k = -1;
+		while ((k = hasCommand(++k, args, SETOFF)) < args.length && k > -1) {
+			je = opt_MULTICOMMANDS(k + 1, args);
+			for (j = k + 1; j <  (k + je); j++) setNoParamCommand(0, pf, args[j]);
+			k += (je - 1);
+		}		
+	}
+
+	return true;
+}
+var olRe;
+// set command according to whichType (0 or 1)
+function setNoParamCommand(whichType, pf, COMMAND) {
+	var v = pms[COMMAND - 1 - pmStart];
+
+	if(pmt && !olRe) olRe = eval('/' + pmt.split(',').join('|') + '/');
+	if (pf != 'ol_' &&  /capturefirst/.test(v)) return;  // no o3_capturefirst variable
+	if (pf != 'ol_' &&  /wrap/.test(v) &&  eval(pf + 'wrap') &&  (whichType == 0)) {
+		nbspCleanup();   // undo wrap effects since checked after all parsing
+		o3_width = ol_width;
+	}
+
+	if (olRe.test(v))	eval(pf + v + '=' + ((whichType && COMMAND == AUTOSTATUSCAP) ? whichType++ : whichType));
+}
+function opt_MULTICOMMANDS(i, ar) {
+	var k = i;
+
+	while (k < ar.length &&  typeof ar[k] == 'number' &&  ar[k] > pmStart) {k++; if (ar[k - 1] == 'SETON'||ar[k - 1] == 'SETOFF') break;}
+	k -= (k < ar.length ? 2 : 1);
+
+	return k;
+}
+////////
+// PLUGIN REGISTRATIONS
+////////
+registerRunTimeFunction(setOnOffVariables);
+registerCmdLineFunction(parseOnOffExtras);
+registerPostParseFunction(scanCommandSet);
+}
\ No newline at end of file
diff --git a/OpenFreezer/overlib/overlib_shadow.js b/OpenFreezer/overlib/overlib_shadow.js
new file mode 100755
index 0000000..b6b194e
--- /dev/null
+++ b/OpenFreezer/overlib/overlib_shadow.js
@@ -0,0 +1,270 @@
+//\/////
+//\  overLIB Shadow Plugin
+//\  This file requires overLIB 4.10 or later.
+//\
+//\  overLIB 4.05 - You may not remove or change this notice.
+//\  Copyright Erik Bosrup 1998-2003. All rights reserved.
+//\  Contributors are listed on the homepage.
+//\  See http://www.bosrup.com/web/overlib/ for details.
+//   $Revision: 1.15 $                $Date: 2004/11/25 21:27:19 $
+//\/////
+//\mini
+
+////////
+// PRE-INIT
+// Ignore these lines, configuration is below.
+////////
+if (typeof olInfo == 'undefined' || typeof olInfo.meets == 'undefined' || !olInfo.meets(4.10)) alert('overLIB 4.10 or later is required for the Shadow Plugin.');
+else {
+registerCommands('shadow,shadowcolor,shadowimage,shadowopacity,shadowx,shadowy');
+
+
+////////
+// DEFAULT CONFIGURATION
+// You don't have to change anything here if you don't want to. All of this can be
+// changed on your html page or through an overLIB call.
+////////
+if (typeof ol_shadowadjust=='undefined') var ol_shadowadjust=2;  // for Ns4.x only
+if (typeof ol_shadow=='undefined') var ol_shadow=0;
+if (typeof ol_shadowcolor=='undefined') var ol_shadowcolor='#CCCCCC';
+if (typeof ol_shadowimage=='undefined') var  ol_shadowimage='';
+if (typeof ol_shadowopacity=='undefined') var  ol_shadowopacity=0;
+if (typeof ol_shadowx=='undefined') var ol_shadowx=5;
+if (typeof ol_shadowy=='undefined') var ol_shadowy=5;
+
+////////
+// END OF CONFIGURATION
+// Don't change anything below this line, all configuration is above.
+////////
+
+
+
+
+////////
+// INIT
+////////
+// Runtime variables init. Don't change for config!
+var o3_shadow=0;
+var o3_shadowcolor="#cccccc";
+var o3_shadowimage='';
+var o3_shadowopacity=0;
+var o3_shadowx=5;
+var o3_shadowy=5;
+var bkSet=0;  // Needed for this effect in NS4
+
+
+
+// Function which sets runtime variables to their default values
+function setShadowVariables() {
+	o3_shadow=ol_shadow;
+	o3_shadowcolor=ol_shadowcolor;
+	o3_shadowimage=ol_shadowimage;
+	o3_shadowopacity=ol_shadowopacity;
+	o3_shadowx=ol_shadowx;
+	o3_shadowy=ol_shadowy;
+}
+
+
+// Parses shadow commands
+function parseShadowExtras(pf,i,ar) {
+	var k = i, v;
+	
+	if (k < ar.length) {
+		if (ar[k]==SHADOW) { eval(pf +'shadow=('+pf+'shadow==0) ? 1 : 0'); return k; }
+		if (ar[k]==SHADOWCOLOR) { eval(pf+'shadowcolor="'+ar[++k]+'"'); return k; }
+		if (ar[k]==SHADOWOPACITY) {v=ar[++k]; eval(pf+'shadowopacity='+(olOp ? 0 : v)); return k; }
+		if (ar[k]==SHADOWIMAGE) { eval(pf+'shadowimage="'+ar[++k]+'"'); return k; }
+		if (ar[k]==SHADOWX) { eval(pf+'shadowx='+ar[++k]); return k; }
+		if (ar[k]==SHADOWY) { eval(pf+'shadowy='+ar[++k]); return k; }
+	}
+	
+	return -1;
+}
+
+
+// Function for MOUSEOUT/MOUSEOFF feature with shadow
+function shadow_cursorOff() {
+	var left= parseInt(over.style.left);
+	var top=parseInt(over.style.top);
+	var right=left+(o3_shadow ? o3_width : over.offsetWidth);
+	var bottom=top+(o3_shadow ? o3_aboveheight : over.offsetHeight);
+	
+	if (o3_x < left || o3_x > right || o3_y < top || o3_y > bottom) return true;
+	return false;
+}
+
+// Pre-hide processing to clean-up.
+function checkShadowPreHide() {
+	if (o3_shadow && o3_shadowopacity) cleanUpShadowEffects();
+	if (o3_shadow && (olIe4 && isMac) ) over.style.pixelWidth=over.style.pixelHeight = 0;
+}
+
+
+// Funciton that creates the actual shadow
+function generateShadow(content) {
+	var wd, ht, X = 0, Y = 0, zIdx = 0, txt, dpObj, puObj, bS= '', aPos, posStr=new Array();
+
+	if (!o3_shadow || (o3_shadowx == 0 && o3_shadowy == 0)) return;
+
+	X = Math.abs(o3_shadowx);
+	Y = Math.abs(o3_shadowy);
+	wd = parseInt(o3_width);
+	ht = (olNs4) ? over.clip.height : over.offsetHeight;
+
+	if (o3_shadowx == 0) {
+		if (o3_shadowy < 0) {
+		  posStr[0]=' left:0; top: 0';
+		  posStr[1]=' left:0; top: '+Y+'px';
+		} else if (o3_shadowy > 0) {
+		  posStr[0]=' left:0; top: '+Y+'px';
+		  posStr[1]=' left:0; top:0';
+		}
+	} else if (o3_shadowy == 0) {
+		if (o3_shadowx < 0) {
+		  posStr[0]=' left:0; top: 0';
+		  posStr[1]=' left: '+X+'px';
+		} else if (o3_shadowx > 0) {
+		  posStr[0]=' left: '+ X+'px; top: 0';
+		  posStr[1]=' left:0; top:0';
+		}
+	} else if (o3_shadowx > 0) {
+		if (o3_shadowy > 0) {
+		  posStr[0]=' left:'+ X+'px; top:'+Y+'px';
+		  posStr[1]=' left:0; top:0';
+		} else if (o3_shadowy < 0) {
+		  posStr[0]=' left:'+X+'px; top:0';
+		  posStr[1]=' left:0; top: '+Y+'px';
+		}
+	} else if (o3_shadowx < 0) {
+		if (o3_shadowy > 0) {
+		  posStr[0]=' left:0; top:'+Y+'px';
+		  posStr[1]=' left:'+X+'px; top:0';
+		} else if (o3_shadowy < 0) {
+		  posStr[0]=' left:0; top:0';
+		  posStr[1]=' left:'+X+'px; top:'+Y+'px';
+		}
+	}
+	
+	txt = (olNs4) ? '<div id="backdrop"></div>' : ((olIe55&&olHideForm) ? backDropSource(wd+X,ht+Y,zIdx++) : '') + '<div id="backdrop" style="position: absolute;'+posStr[0]+'; width: '+wd+'px; height: '+ht+'px; z-index: ' + (zIdx++) + '; ';
+
+	if (o3_shadowimage) {
+		bS='background-image: url('+o3_shadowimage+');';
+		if (olNs4) bkSet=1;
+	} else { 
+		bS='background-color: '+o3_shadowcolor +';';
+		if (olNs4) bkSet=2;
+	}
+
+	if (olNs4) {
+		txt += '<div id="PUContent">'+content+'</div>';
+	} else {
+		txt += bS+'"></div><div id="PUContent" style="position: absolute;'+posStr[1]+'; width: '+ wd+'px; z-index: '+(zIdx++)+';">'+content+'</div>';
+	}
+	
+	layerWrite(txt);
+
+	if (olNs4 && bkSet) {
+		dpObj = over.document.layers['backdrop'];
+		if (typeof dpObj == 'undefined') return;  // if shadow layer not found, then content layer won't be either
+		
+		puObj = over.document.layers['PUContent'];
+		wd = puObj.clip.width;
+		ht = puObj.clip.height;
+		aPos = posStr[0].split(';');
+		
+		dpObj.clip.width = wd;
+		dpObj.clip.height = ht;
+		dpObj.left = parseInt(aPos[0].split(':')[1]);
+		dpObj.top = parseInt(aPos[1].split(':')[1]);
+    
+    dpObj.bgColor = (bkSet == 1) ? null : o3_shadowcolor;
+		dpObj.background.src = (bkSet==2) ? null : o3_shadowimage;
+		dpObj.zIndex = 0;
+
+		aPos = posStr[1].split(';');
+		puObj.left = parseInt(aPos[0].split(':')[1]);
+		puObj.top = parseInt(aPos[1].split(':')[1]);
+		puObj.zIndex = 1;
+		
+	} else {
+		puObj = (olIe4 ? o3_frame.document.all['PUContent'] : o3_frame.document.getElementById('PUContent'));
+		dpObj = (olIe4 ? o3_frame.document.all['backdrop'] : o3_frame.document.getElementById('backdrop'));
+		ht = puObj.offsetHeight;
+		dpObj.style.height = ht + 'px';
+		
+		if (o3_shadowopacity) {
+			var op = o3_shadowopacity;
+			op = (op <= 100 ? op : 100);
+			
+			setBrowserOpacity(op,dpObj);
+		}
+	} 
+
+	// Set popup's new width and height values here so they are available in placeLayer()
+	o3_width = wd+X;
+	o3_aboveheight = ht+Y;
+}
+
+
+////////
+// SUPPORT FUNCTIONS
+////////
+
+// Cleans up opacity settings if any.
+function cleanUpShadowEffects() {
+	if (olNs4 || olOp) return;
+	var dpObj=(olIe4 ? o3_frame.document.all['backdrop'] : o3_frame.document.getElementById('backdrop'));
+	cleanUpBrowserOpacity(dpObj);
+}
+
+// multi browser opacity support
+function setBrowserOpacity(op,lyr){
+	if (olNs4||!op) return;  // if Ns4.x or opacity not given return;
+	lyr=(lyr) ? lyr : over;
+	if (olIe4&&typeof lyr.filters != 'undefined') {
+		lyr.style.filter='Alpha(Opacity='+op+')';
+		lyr.filters.alpha.enabled=true;
+	} else {
+		var sOp=(typeof(lyr.style.MozOpacity)!='undefined') ? 'MozOpacity' : (typeof(lyr.style.KhtmlOpacity)!='undefined' ? 'KhtmlOpacity' : (typeof(lyr.style.opacity)!='undefined' ? 'opacity' : '')); 
+		if (sOp) eval('lyr.style.'+sOp+'=op/100');
+	}
+}
+
+// multi-browser Opacity cleanup
+function cleanUpBrowserOpacity(lyr) {
+	if (olNs4) return;
+	lyr=(lyr) ? lyr : over;
+	if (olIe4&&(typeof lyr.filters != 'undefined'&&lyr.filters.alpha.enabled)) {
+		lyr.style.filter='Alpha(Opacity=100)';
+		lyr.filters.alpha.enabled=false;
+	} else {
+		var sOp=(typeof(lyr.style.MozOpacity)!='undefined') ? 'MozOpacity' : (typeof(lyr.style.KhtmlOpacity)!='undefined' ? 'KhtmlOpacity' : (typeof(lyr.style.opacity)!='undefined' ? 'opacity' : '')); 
+		if (sOp) eval('lyr.style.'+sOp+'=1.0');
+	}
+}
+
+// This routine is needed only for Ns4.x to allow use of popups with dropshadows and CSSCLASS at the same time on a page
+function shadowAdjust() {
+	if (!olNs4) return;
+	var fac = ol_shadowadjust;
+	if (olNs4) {
+		document.write('<style type="text/css">\n<!--\n');
+		document.write('#backdrop, #PUContent {position: absolute; left: '+fac*o3_shadowx+'px; top: '+fac*o3_shadowy+'px; }\n');
+		document.write('-->\n<' + '\/style>');
+	}
+}
+
+////////
+// PLUGIN REGISTRATIONS
+////////
+var before = (typeof rmrkPreface!='undefined' ? rmrkPreface : null);
+
+registerRunTimeFunction(setShadowVariables);
+registerCmdLineFunction(parseShadowExtras);
+registerHook("cursorOff",shadow_cursorOff,FREPLACE);
+registerHook("hideObject",checkShadowPreHide,FBEFORE);
+registerHook("createPopup",generateShadow,FAFTER,before);
+if (olInfo.meets(4.10)) registerNoParameterCommands('shadow');
+
+if (olNs4) shadowAdjust();  // write style rules for proper support of Ns4.x
+}
\ No newline at end of file
diff --git a/OpenFreezer/overlib/overlibmws.js b/OpenFreezer/overlib/overlibmws.js
new file mode 100755
index 0000000..5f5cdd7
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws.js
@@ -0,0 +1,622 @@
+/*
+ Do not remove or change this notice.
+ overlibmws.js core module - Copyright Foteos Macrides 2002-2010. All rights reserved.
+   Initial: August 18, 2002 - Last Revised: March 2, 2010
+ This module is subject to the same terms of usage as for Erik Bosrup's overLIB,
+ though only a minority of the code and API now correspond with Erik's version.
+ See the overlibmws Change History and Command Reference via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+ Give credit on sites that use overlibmws and submit changes so others can use them as well.
+ You can get Erik's version via: http://www.bosrup.com/web/overlib/
+*/
+
+// PRE-INIT -- Ignore these lines, configuration is below.
+var OLloaded=0,OLbubblePI=0,OLcrossframePI=0,OLdebugPI=0,OLdraggablePI=0,OLexclusivePI=0,OLfilterPI=0,
+OLfunctionPI=0,OLhidePI=0,OLiframePI=0,OLmodalPI=0,OLovertwoPI=0,OLscrollPI=0,OLshadowPI=0,OLprintPI=0,
+pmCnt=1,pMtr=new Array(),OLcmdLine=new Array(),OLrunTime=new Array(),OLv,OLudf,OLrefXY,
+OLpct=new Array("83%","67%","83%","100%","117%","150%","200%","267%");if(typeof OLgateOK=='undefined')var OLgateOK=1;
+var OLp1or2c='inarray,caparray,caption,closetext,right,left,center,autostatuscap,padx,pady,below,above,vcenter,donothing',
+OLp1or2co='nofollow,background,offsetx,offsety,fgcolor,bgcolor,cgcolor,textcolor,capcolor,width,wrap,wrapmax,height,border,'
++'base,status,autostatus,snapx,snapy,fixx,fixy,relx,rely,midx,midy,ref,refc,refp,refx,refy,fgbackground,bgbackground,'
++'cgbackground,fullhtml,capicon,textfont,captionfont,textsize,captionsize,timeout,delay,hauto,vauto,nojustx,nojusty,fgclass,'
++'bgclass,cgclass,capbelow,textpadding,textfontclass,captionpadding,captionfontclass,sticky,noclose,mouseoff,offdelay,'
++'closecolor,closefont,closesize,closeclick,closetitle,closefontclass,decode',OLp1or2o='text,cap,close,hpos,vpos,padxl,'
++'padxr,padyt,padyb',OLp1co='label',OLp1or2=OLp1or2co+','+OLp1or2o,OLp1=OLp1co+','+'frame';
+OLregCmds(OLp1or2c+','+OLp1or2co+','+OLp1co);
+function OLud(v){return eval('typeof ol_'+v+'=="undefined"')?1:0;}
+
+// DEFAULT CONFIGURATION -- See overlibConfig.txt for descriptions
+if(OLud('fgcolor'))var ol_fgcolor="#ccccff";
+if(OLud('bgcolor'))var ol_bgcolor="#333399";
+if(OLud('cgcolor'))var ol_cgcolor="#333399";
+if(OLud('textcolor'))var ol_textcolor="#000000";
+if(OLud('capcolor'))var ol_capcolor="#ffffff";
+if(OLud('closecolor'))var ol_closecolor="#eeeeff";
+if(OLud('textfont'))var ol_textfont="Verdana,Arial,Helvetica";
+if(OLud('captionfont'))var ol_captionfont="Verdana,Arial,Helvetica";
+if(OLud('closefont'))var ol_closefont="Verdana,Arial,Helvetica";
+if(OLud('textsize'))var ol_textsize=1;
+if(OLud('captionsize'))var ol_captionsize=1;
+if(OLud('closesize'))var ol_closesize=1;
+if(OLud('fgclass'))var ol_fgclass="";
+if(OLud('bgclass'))var ol_bgclass="";
+if(OLud('cgclass'))var ol_cgclass="";
+if(OLud('textpadding'))var ol_textpadding=2;
+if(OLud('textfontclass'))var ol_textfontclass="";
+if(OLud('captionpadding'))var ol_captionpadding=2;
+if(OLud('captionfontclass'))var ol_captionfontclass="";
+if(OLud('closefontclass'))var ol_closefontclass="";
+if(OLud('close'))var ol_close="Close";
+if(OLud('closeclick'))var ol_closeclick=0;
+if(OLud('closetitle'))var ol_closetitle="Click to Close";
+if(OLud('text'))var ol_text="Default Text";
+if(OLud('cap'))var ol_cap="";
+if(OLud('capbelow'))var ol_capbelow=0;
+if(OLud('background'))var ol_background="";
+if(OLud('width'))var ol_width=200;
+if(OLud('wrap'))var ol_wrap=0;
+if(OLud('wrapmax'))var ol_wrapmax=0;
+if(OLud('height'))var ol_height= -1;
+if(OLud('border'))var ol_border=1;
+if(OLud('base'))var ol_base=0;
+if(OLud('offsetx'))var ol_offsetx=10;
+if(OLud('offsety'))var ol_offsety=10;
+if(OLud('sticky'))var ol_sticky=0;
+if(OLud('nofollow'))var ol_nofollow=0;
+if(OLud('noclose'))var ol_noclose=0;
+if(OLud('mouseoff'))var ol_mouseoff=0;
+if(OLud('offdelay'))var ol_offdelay=300;
+if(OLud('hpos'))var ol_hpos=RIGHT;
+if(OLud('vpos'))var ol_vpos=BELOW;
+if(OLud('status'))var ol_status="";
+if(OLud('autostatus'))var ol_autostatus=0;
+if(OLud('snapx'))var ol_snapx=0;
+if(OLud('snapy'))var ol_snapy=0;
+if(OLud('fixx'))var ol_fixx= -1;
+if(OLud('fixy'))var ol_fixy= -1;
+if(OLud('relx'))var ol_relx=null;
+if(OLud('rely'))var ol_rely=null;
+if(OLud('midx'))var ol_midx=null;
+if(OLud('midy'))var ol_midy=null;
+if(OLud('ref'))var ol_ref="";
+if(OLud('refc'))var ol_refc='UL';
+if(OLud('refp'))var ol_refp='UL';
+if(OLud('refx'))var ol_refx=0;
+if(OLud('refy'))var ol_refy=0;
+if(OLud('fgbackground'))var ol_fgbackground="";
+if(OLud('bgbackground'))var ol_bgbackground="";
+if(OLud('cgbackground'))var ol_cgbackground="";
+if(OLud('padxl'))var ol_padxl=1;
+if(OLud('padxr'))var ol_padxr=1;
+if(OLud('padyt'))var ol_padyt=1;
+if(OLud('padyb'))var ol_padyb=1;
+if(OLud('fullhtml'))var ol_fullhtml=0;
+if(OLud('capicon'))var ol_capicon="";
+if(OLud('frame'))var ol_frame=self;
+if(OLud('timeout'))var ol_timeout=0;
+if(OLud('delay'))var ol_delay=0;
+if(OLud('hauto'))var ol_hauto=0;
+if(OLud('vauto'))var ol_vauto=0;
+if(OLud('nojustx'))var ol_nojustx=0;
+if(OLud('nojusty'))var ol_nojusty=0;
+if(OLud('label'))var ol_label="";
+if(OLud('decode'))var ol_decode=0;
+// ARRAY CONFIGURATION - See overlibConfig.txt for descriptions.
+if(OLud('texts'))var ol_texts=new Array("Text 0","Text 1");
+if(OLud('caps'))var ol_caps=new Array("Caption 0","Caption 1");
+// END CONFIGURATION -- Don't change anything below, all configuration is above.
+
+// INIT -- Runtime variables.
+var o3_text="",o3_cap="",o3_sticky=0,o3_nofollow=0,o3_background="",o3_noclose=0,o3_mouseoff=0,o3_offdelay=300,o3_hpos=RIGHT,
+o3_offsetx=10,o3_offsety=10,o3_fgcolor="",o3_bgcolor="",o3_cgcolor="",o3_textcolor="",o3_capcolor="",o3_closecolor="",
+o3_width=200,o3_wrap=0,o3_wrapmax=0,o3_height= -1,o3_border=1,o3_base=0,o3_status="",o3_autostatus=0,o3_snapx=0,o3_snapy=0,
+o3_fixx= -1,o3_fixy= -1,o3_relx=null,o3_rely=null,o3_midx=null,o3_midy=null,o3_ref="",o3_refc='UL',o3_refp='UL',o3_refx=0,
+o3_refy=0,o3_fgbackground="",o3_bgbackground="",o3_cgbackground="",o3_padxl=0,o3_padxr=0,o3_padyt=0,o3_padyb=0,o3_fullhtml=0,
+o3_vpos=BELOW,o3_capicon="",o3_textfont="Verdana,Arial,Helvetica",o3_captionfont="",o3_closefont="",o3_textsize=1,OLcC=null,
+o3_captionsize=1,o3_closesize=1,o3_frame=self,o3_timeout=0,o3_delay=0,o3_hauto=0,o3_vauto=0,o3_nojustx=0,o3_nojusty=0,
+o3_close="",o3_closeclick=0,o3_closetitle="",o3_fgclass="",o3_bgclass="",o3_cgclass="",o3_textpadding=2,o3_textfontclass="",
+o3_captionpadding=2,o3_captionfontclass="",o3_closefontclass="",o3_capbelow=0,o3_label="",o3_decode=0,
+CSSOFF=DONOTHING,CSSCLASS=DONOTHING,over=null,OLdelayid=0,OLtimerid=0,OLshowid=0,OLndt=0,OLfnRef="",OLhover=0,OLx=0,OLy=0,
+OLshowingsticky=0,OLallowmove=0,OLoverHTML="",OLover2HTML="",OLifRef="",OLo2Ref="",OLifX=0,OLifY=0,
+OLua=(OLv=navigator.userAgent)?OLv.toLowerCase():'',
+OLns4=(navigator.appName=='Netscape'&&parseInt(navigator.appVersion)==4)?1:0,
+OLns6=(document.getElementById)?1:0,
+OLie4=(document.all)?1:0,
+OLgek=(OLv=OLua.match(/gecko\/(\d{8})/i))?parseInt(OLv[1]):0,
+OLmac=(OLua.indexOf('mac')>=0)?1:0,
+OLsaf=(OLua.indexOf('safari')>=0)?1:0,
+OLkon=(OLua.indexOf('konqueror')>=0)?1:0,
+OLkht=(OLsaf||OLkon)?1:0,
+OLopr=(OLua.indexOf('opera')>=0)?1:0,
+OLop7=(OLopr&&document.createTextNode)?1:0;
+OLop95=(OLop7&&document.getElementsByClassName)?1:0;
+if(OLopr){OLns4=OLns6=OLgek=0;OLie4=(OLop7)?1:0;}
+var OLieM=((OLie4&&OLmac)&&!(OLkht||OLopr))?1:0,
+OLie5=0,OLie55=0,OLie7=0;OLie8=0;if(OLie4&&!OLop7){
+if((OLv=OLua.match(/msie (\d\.\d+)\.*/i))&&(OLv=parseFloat(OLv[1]))>=5.0){
+OLie5=1;OLns6=0;if(OLv>=5.5)OLie55=1;if(OLv>=7.0)OLie7=1;if(OLv>=8.0)OLie8=1;}if(OLns6)OLie4=0;}
+if(OLns4)window.onresize=function(){location.reload();};var OLchkMh=1,OLdw;
+if(OLns4||OLie4||OLns6){OLmh();if(window.addEventListener)window.addEventListener("unload",
+OLulCl,false);}else{overlib=nd=cClick=OLpageDefaults=no_overlib;}
+function OLulCl(){if(over)cClick();window.removeEventListener("unload",OLulCl,false);}
+
+/*
+ PUBLIC FUNCTIONS
+*/
+// Loads defaults then args into runtime variables.
+function overlib(){
+if(!(OLloaded&&OLgateOK))return;if((OLexclusivePI)&&OLisExclusive(arguments))return true;if(OLchkMh)OLmh();if(OLndt&&
+!OLtimerid)OLndt=0;if(over){if(OLfilterPI)o3_filter=0;cClick();}if(parent!=self){new Array('try{','if(parent.OLo2Ref){',
+'parent.OLeval(parent.OLo2Ref);','parent.OLo2Ref="";','}','if(parent.OLifRef){','parent.OLeval(parent.OLifRef);',
+'parent.OLifRef="";','}','}','catch(e){','}').join('\n')};if(OLo2Ref){eval(OLo2Ref);OLo2Ref="";}if(OLifRef){eval(OLifRef);
+OLifRef="";}OLload(OLp1or2);OLload(OLp1);OLfnRef="";OLifX=0;OLifY=0;OLhover=0;if(OLcrossframePI&&parent!=self)OLchkFRAME(
+arguments);OLsetRunTimeVar();OLparseTokens('o3_',arguments);if(!(over=OLmkLyr()))return false;over.onmouseover=
+over.onmouseout=null;if(o3_decode)OLdecode();if(OLprintPI)OLchkPrint();if(OLbubblePI)OLchkForBubbleEffect();if(OLdebugPI)
+OLsetDebugCanShow();if(OLshadowPI)OLinitShadow();if(OLiframePI)OLinitIfs();if(OLfilterPI)OLinitFilterLyr();if(OLexclusivePI
+&&o3_exclusive&&o3_exclusivestatus!="")o3_status=o3_exclusivestatus;else if(o3_autostatus==2&&o3_cap!="")o3_status=o3_cap;
+else if(o3_autostatus==1&&o3_text!="")o3_status=o3_text;if(!o3_delay){return OLmain();}else{OLdelayid=setTimeout("OLmain()",
+o3_delay);if(o3_status!=""){self.status=o3_status;return true;}else if(!(OLop7&&event&&event.type=='mouseover'))
+return false;}
+}
+function OLeval(s){eval(s);}
+
+// Clears popups if appropriate
+function nd(time){
+if(OLloaded&&OLgateOK){if(!((OLexclusivePI)&&OLisExclusive())){if(time&&over&&!o3_delay){if(OLtimerid>0)
+clearTimeout(OLtimerid);OLtimerid=(OLhover&&!OLcursorOff())?0:setTimeout("cClick()",(o3_timeout=OLndt=time));
+}else{if(!OLshowingsticky){OLallowmove=0;if(over)OLhideObject(over);}}}}return false;
+}
+
+// Close function for stickies
+function cClick(){
+if(OLloaded&&OLgateOK){OLhover=0;if(over){if(OLo2Ref){eval(OLo2Ref);OLo2Ref="";}if(OLovertwoPI&&over==over2)cClick2();
+OLhideObject(over);OLshowingsticky=0;OLallowmove=0;}if(OLmodalPI)OLclearModal();}return false;
+}
+
+// Sets page-specific defaults.
+function OLpageDefaults(){
+OLparseTokens('ol_',arguments);
+}
+
+// Gets object referenced by its id or name
+function OLgetRef(l,d){var r=OLgetRefById(l,d);return (r)?r:OLgetRefByName(l,d);}
+
+// For unsupported browsers.
+function no_overlib(){return false;}
+
+/*
+ OVERLIB MAIN FUNCTION SET
+*/
+function OLmain(){
+o3_delay=0;if(parent!=self&&o3_frame==parent&&parent.OLscrollPI&&parent.over)parent.OLclearScroll();if(o3_noclose)
+OLoptMOUSEOFF(0);else if(o3_mouseoff)OLoptMOUSEOFF(1);if(o3_sticky){OLshowingsticky=1;if(OLfnRef&&parent!=self&&
+o3_frame==parent&&parent.overlib)parent.OLifRef=(OLfilterPI?OLfnRef+'o3_filter=0;':'')+OLfnRef+'cClick();';}OLdoLyr();
+OLallowmove=0;if(o3_timeout>0){if(OLtimerid>0)clearTimeout(OLtimerid);OLtimerid=setTimeout("cClick()",o3_timeout);}
+OLchkRef();OLdisp(o3_status);if(OLdraggablePI)OLcheckDrag();if(o3_status!="")return true;else if(!(OLop7&&event&&
+event.type=='mouseover'))return false;
+}
+function OLchkRef(){
+if(o3_ref){OLrefXY=OLgetRefXY(o3_ref);if(OLrefXY[0]==null&&OLcrossframePI)OLchkIfRef();
+if(OLrefXY[0]==null){o3_ref="";o3_midx=0;o3_midy=0;}}
+}
+
+// Loads o3_ variables
+function OLload(c){var i,m=c.split(',');for(i=0;i<m.length;i++)eval('o3_'+m[i]+'=ol_'+m[i]);}
+
+// Chooses LGF 
+function OLdoLGF(){
+return (o3_background!=''||o3_fullhtml)?OLcontentBackground(o3_text,o3_background,o3_fullhtml):(o3_cap=="")?
+OLcontentSimple(o3_text):(o3_sticky)?OLcontentCaption(o3_text,o3_cap,o3_close):OLcontentCaption(o3_text,o3_cap,'');
+}
+
+// Makes Layer
+function OLmkLyr(id,f,z){
+id=(id||'overDiv');f=(f||o3_frame);z=(z||1000);var fd=f.document,d=OLgetRefById(id,fd);if(!d){if(OLns4)d=fd.layers[id]=
+new Layer(1024,f);else if(OLie4&&!OLop7){fd.body.insertAdjacentHTML('AfterBegin','<div id="'+id+'"></div>');d=fd.all[id];}
+else{d=fd.createElement('div');if(d){d.id=id;fd.body.appendChild(d);}}if(!d)return null;if(OLns4)d.zIndex=z;else{var o=
+d.style;o.position='absolute';o.visibility='hidden';o.zIndex=z;}}return d;
+}
+
+// Creates and writes layer content
+function OLdoLyr(){
+if(o3_sticky&&OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}if(o3_background==''&&!o3_fullhtml){
+if(o3_fgbackground!='')o3_fgbackground=' background="'+o3_fgbackground+'"';
+if(o3_bgbackground!='')o3_bgbackground=' background="'+o3_bgbackground+'"';
+if(o3_cgbackground!='')o3_cgbackground=' background="'+o3_cgbackground+'"';
+if(o3_fgcolor!='')o3_fgcolor=' bgcolor="'+o3_fgcolor+'"';if(o3_bgcolor!='')o3_bgcolor=' bgcolor="'+o3_bgcolor+'"';
+if(o3_cgcolor!='')o3_cgcolor=' bgcolor="'+o3_cgcolor+'"';if(o3_height>0)o3_height=(OLns4)?' height="'+o3_height+'"':
+' style="height:'+o3_height+'px;"';else o3_height='';}if(!OLns4)OLrepositionTo(over,(OLns6?20:0),0);var lyrHtml=OLdoLGF();
+if(o3_wrap&&!o3_fullhtml){OLlayerWrite(lyrHtml);o3_width=(OLns4?over.clip.width:over.offsetWidth);if(OLie4&&!OLop95){
+var w=OLfd().clientWidth;if(o3_width>=w){if(OLop7){if(OLovertwoPI&&over==over2){var z=over2.style.zIndex;
+o3_frame.document.body.removeChild(over);over2=OLmkLyr('overDiv2',o3_frame,z);over=over2;}else{
+o3_frame.document.body.removeChild(over);over=OLmkLyr();}}o3_width=w-20;}}
+if(o3_wrapmax<1&&o3_frame.innerWidth)o3_wrapmax=o3_frame.innerWidth-40;
+if(o3_wrapmax>0&&o3_width>o3_wrapmax)o3_width=o3_wrapmax;o3_wrap=0;lyrHtml=OLdoLGF();}OLlayerWrite(lyrHtml);
+o3_width=(OLns4?over.clip.width:over.offsetWidth);if(OLbubblePI)OLgenerateBubble(lyrHtml);
+}
+
+/*
+ LAYER GENERATION FUNCTIONS
+*/
+// Makes simple table without caption
+function OLcontentSimple(txt){
+var t=OLbgLGF()+OLfgLGF(txt)+OLbaseLGF();OLsetBackground('');return t;
+}
+
+// Makes table with caption and optional close link
+function OLcontentCaption(txt,title,close){
+var closing=(OLprintPI?OLprintCapLGF():''),closeevent='onmouseover',caption,t,cC='javascript:return '+OLfnRef
++(OLovertwoPI&&over==over2?'cClick2();':'cClick();');if(o3_closeclick)closeevent=(o3_closetitle?'title="'
++o3_closetitle+'" ':'')+'onclick';if(o3_capicon!=''&&o3_capicon.indexOf('<img')!=0)o3_capicon='<img src="'+o3_capicon
++'" /> ';if(close){closing+='<td align="right"><a href="'+cC+'" '+closeevent+'="'+cC+'"'+(o3_closefontclass?' class="'
++o3_closefontclass+'">':(OLns4?'><':'')+OLlgfUtil(0,1,'','a',o3_closecolor,o3_closefont,o3_closesize))+close+
+(o3_closefontclass?'':(OLns4?OLlgfUtil(1,1,'','a'):''))+'</a></td>';}caption='<table id="overCap'
++(OLovertwoPI&&over==over2?'2':'')+'"'+OLwd(0)+' border="0" cellpadding="'+o3_captionpadding+'" cellspacing="0"'
++(o3_cgclass?' class="'+o3_cgclass+'"':o3_cgcolor+o3_cgbackground)+'><tr><td'+OLwd(0)+(o3_cgclass?' class="'
++o3_cgclass+'">':'>')+(o3_captionfontclass?'<div'+OLhL(1)+' class="'+o3_captionfontclass+'">':OLlgfUtil(0,1,'','div',
+o3_capcolor,o3_captionfont,o3_captionsize))+o3_capicon+title+OLlgfUtil(1,1,'','div')+'</td>'+closing+'</tr></table>';
+t=OLbgLGF()+(o3_capbelow?OLfgLGF(txt)+caption:caption+OLfgLGF(txt))+OLbaseLGF();OLsetBackground('');return t;
+}
+
+// For BACKGROUND and FULLHTML commands
+function OLcontentBackground(txt,image,hasfullhtml){
+var t;if(hasfullhtml){t=txt;}else{t='<table'+OLwd(1)+' border="0" cellpadding="0" '+'cellspacing="0" '+'height="'
++o3_height+'"><tr><td colspan="3" height="'+o3_padyt+'"></td></tr><tr><td width="'+o3_padxl+'"></td><td valign="top"'
++OLwd(2)+'>'+OLlgfUtil(0,0,o3_textfontclass,'div',o3_textcolor,o3_textfont,o3_textsize)+txt+OLlgfUtil(1,0,'','div')
++'</td><td width="'+o3_padxr+'"></td></tr><tr><td colspan="3" height="'+o3_padyb+'"></td></tr></table>';}
+OLsetBackground(image);return t;
+}
+
+// LGF utilities
+function OLbgLGF(){
+return '<table'+OLwd(1)+o3_height+' border="0" cellpadding="'+o3_border+'" cellspacing="0"'+(o3_bgclass?' class="'
++o3_bgclass+'"':o3_bgcolor+o3_bgbackground)+'><tr><td>';
+}
+function OLfgLGF(t){
+return '<table'+OLwd(0)+o3_height+' border="0" cellpadding="'+o3_textpadding+'" cellspacing="0"'+(o3_fgclass?' class="'
++o3_fgclass+'"':o3_fgcolor+o3_fgbackground)+'><tr><td valign="top"'+(o3_fgclass?' class="'+o3_fgclass+'"':'')+'>'
++OLlgfUtil(0,0,o3_textfontclass,'div',o3_textcolor,o3_textfont,o3_textsize)+t+(OLprintPI?OLprintFgLGF():'')
++OLlgfUtil(1,0,'','div')+'</td></tr></table>';
+}
+function OLlgfUtil(end,stg,tfc,ele,col,fac,siz){
+if(end)return('</'+(OLns4?'font'+(stg?'></strong':''):ele)+'>');else return(tfc?'<div'+OLhL(1)+' class="'+tfc+'">':
+((ele=='a'?'':'<')+(OLns4?(stg?'strong><':'')+'font color="'+col+'" face="'+OLquoteMultiNameFonts(fac)+'" size="'
++siz:(ele=='a'?'':ele)+' style="'+((ele=='div')?OLhL(0):'')+'color:'+col+(stg?';font-weight:bold':'')+';font-family:'
++OLquoteMultiNameFonts(fac)+';font-size:'+siz+';'+(ele=='span'?'text-decoration:underline;':''))+'">'));
+}
+function OLquoteMultiNameFonts(f){
+var i,v,pM=f.split(',');for(i=0;i<pM.length;i++){v=pM[i];v=v.replace(/^\s+/,'').replace(/\s+$/,'');
+if(/\s/.test(v) && !/['"]/.test(v)){v="\'"+v+"\'";pM[i]=v;}}return pM.join();
+}
+function OLbaseLGF(){
+return ((o3_base>0&&!o3_wrap)?('<table width="100%" border="0" cellpadding="0" cellspacing="0"'+(o3_bgclass?' class="'
++o3_bgclass+'"':'')+'><tr><td height="'+o3_base+'"></td></tr></table>'):'')+'</td></tr></table>';
+}
+function OLwd(a){return(o3_wrap?'':' width="'+(!a?'100%':(a==1?o3_width:(o3_width-o3_padxl-o3_padxr)))+'"');}
+function OLhL(s){if(!OLie5)return '';return(s?' style="overflow:auto;"':'overflow:auto;');}
+
+// Loads image into the div.
+function OLsetBackground(i){
+if(i==''){if(OLns4)over.background.src=null;else{if(OLns6)over.style.width='';over.style.backgroundImage='none';}}
+else{if(OLns4)over.background.src=i;else{if(OLns6)over.style.width=o3_width+'px';over.style.backgroundImage='url('+i+')';}}
+}
+
+/*
+ HANDLING FUNCTIONS
+*/
+// Displays layer
+function OLdisp(s){
+if(OLmodalPI&&!o3_modalscroll)OLchkModal();if(!OLallowmove){if(OLshadowPI)OLdispShadow();if(OLiframePI)OLdispIfs();
+OLplaceLayer();if(OLmodalPI&&o3_modalscroll)OLchkModal();if(OLndt)OLshowObject(over);else OLshowid=
+setTimeout("OLshowObject(over)",1);OLallowmove=(o3_sticky||o3_nofollow)?0:1;}OLndt=0;if(s!="")self.status=s;
+}
+
+// Decides placement of layer.
+function OLplaceLayer(){
+var snp,X,Y,pgLeft,pgTop,pWd=o3_width,pHt,iWd=100,iHt=100,SB=0,LM=0,CX=0,TM=0,BM=0,CY=0,o=OLfd(),
+nsb=(OLgek>=20010505&&!o3_frame.scrollbars.visible)?1:0;
+if(!OLkht&&!OLop95&&o&&o.clientWidth)iWd=o.clientWidth;
+else if(o3_frame.innerWidth){SB=Math.ceil(1.4*(o3_frame.outerWidth-o3_frame.innerWidth));
+if(SB>20)SB=20;iWd=o3_frame.innerWidth;}
+pgLeft=(OLie4&&!OLop95)?o.scrollLeft:o3_frame.pageXOffset;
+if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow)SB=CX=5;else
+if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowx){SB+=((o3_shadowx>0)?o3_shadowx:0);
+LM=((o3_shadowx<0)?Math.abs(o3_shadowx):0);CX=Math.abs(o3_shadowx);}
+if(o3_ref!=""||o3_fixx> -1||o3_relx!=null||o3_midx!=null){
+if(o3_ref!=""){X=OLrefXY[0];if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow){
+if(o3_refp=='UR'||o3_refp=='LR')X-=5;}
+else if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowx){
+if(o3_shadowx<0&&(o3_refp=='UL'||o3_refp=='LL'))X-=o3_shadowx;else
+if(o3_shadowx>0&&(o3_refp=='UR'||o3_refp=='LR'))X-=o3_shadowx;}
+}else{if(o3_midx!=null){
+X=parseInt(pgLeft+((iWd-pWd-SB-LM)/2)+o3_midx);
+}else{if(o3_relx!=null){
+if(o3_relx>=0)X=pgLeft+o3_relx+LM;else X=pgLeft+o3_relx+iWd-pWd-SB;
+}else{X=o3_fixx+LM;}}}
+}else{
+if(o3_hauto){
+if(o3_hpos==LEFT&&OLx-pgLeft+OLifX<iWd/2&&OLx-pWd-o3_offsetx+OLifX<pgLeft+LM)o3_hpos=RIGHT;else
+if(o3_hpos==RIGHT&&OLx-pgLeft+OLifX>iWd/2&&OLx+pWd+o3_offsetx+OLifX>pgLeft+iWd-SB)o3_hpos=LEFT;}
+X=(o3_hpos==CENTER)?parseInt(OLx-((pWd+CX)/2)+o3_offsetx):
+(o3_hpos==LEFT)?OLx-o3_offsetx-pWd:OLx+o3_offsetx;
+if(o3_snapx>1){
+snp=X % o3_snapx;
+if(o3_hpos==LEFT){X=X-(o3_snapx+snp);}else{X=X+(o3_snapx-snp);}}X+=OLifX;}
+if(!o3_nojustx&&X+pWd>pgLeft+iWd-SB)
+X=iWd+pgLeft-pWd-SB;if(!o3_nojustx&&X-LM<pgLeft)X=pgLeft+LM;
+pgTop=OLie4&&!OLop95?o.scrollTop:o3_frame.pageYOffset;
+if(!OLkht&&!OLop95&&!nsb&&o&&o.clientHeight)iHt=o.clientHeight;
+else if(o3_frame.innerHeight)iHt=o3_frame.innerHeight;
+if(OLbubblePI&&o3_bubble)pHt=OLbubbleHt;else pHt=OLns4?over.clip.height:over.offsetHeight;
+if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowy){TM=(o3_shadowy<0)?Math.abs(o3_shadowy):0;
+if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow)BM=CY=5;else
+BM=(o3_shadowy>0)?o3_shadowy:0;CY=Math.abs(o3_shadowy);}
+if(o3_ref!=""||o3_fixy> -1||o3_rely!=null||o3_midy!=null){
+if(o3_ref!=""){Y=OLrefXY[1];if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow){
+if(o3_refp=='LL'||o3_refp=='LR')Y-=5;}else if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowy){
+if(o3_shadowy<0&&(o3_refp=='UL'||o3_refp=='UR'))Y-=o3_shadowy;else
+if(o3_shadowy>0&&(o3_refp=='LL'||o3_refp=='LR'))Y-=o3_shadowy;}
+}else{if(o3_midy!=null){
+Y=parseInt(pgTop+((iHt-pHt-CY)/2)+o3_midy);
+}else{if(o3_rely!=null){
+if(o3_rely>=0)Y=pgTop+o3_rely+TM;else Y=pgTop+o3_rely+iHt-pHt-BM;}else{
+Y=o3_fixy+TM;}}}
+}else{
+if(o3_vauto){
+if(o3_vpos==ABOVE&&OLy-pgTop+OLifY<iHt/2&&OLy-pHt-o3_offsety+OLifY<pgTop)o3_vpos=BELOW;else
+if(o3_vpos==BELOW&&OLy-pgTop+OLifY>iHt/2&&OLy+pHt+o3_offsety+((OLns4||OLkht)?17:0)+OLifY>pgTop+iHt-BM)
+o3_vpos=ABOVE;}Y=(o3_vpos==VCENTER)?parseInt(OLy-((pHt+CY)/2)+o3_offsety):
+(o3_vpos==ABOVE)?OLy-(pHt+o3_offsety+BM):OLy+o3_offsety+TM;
+if(o3_snapy>1){
+snp=Y % o3_snapy;
+if(pHt>0&&o3_vpos==ABOVE){Y=Y-(o3_snapy+snp);}else{Y=Y+(o3_snapy-snp);}}Y+=OLifY;}
+if(!o3_nojusty&&Y+pHt+BM>pgTop+iHt)Y=pgTop+iHt-pHt-BM;if(!o3_nojusty&&Y-TM<pgTop)Y=pgTop+TM;
+OLrepositionTo(over,X,Y);
+if(OLshadowPI)OLrepositionShadow(X,Y);if(OLiframePI)OLrepositionIfs(X,Y);
+if(OLns6&&o3_frame.innerHeight){iHt=o3_frame.innerHeight;OLrepositionTo(over,X,Y);}
+if(OLscrollPI)OLchkScroll(X-pgLeft,Y-pgTop);
+}
+
+// Chooses body or documentElement
+function OLfd(f){
+var fd=((f)?f:o3_frame).document,fdc=fd.compatMode,fdd=fd.documentElement;
+return (!OLop7&&fdc&&fdc!='BackCompat'&&fdd&&fdd.clientWidth)?fd.documentElement:fd.body;
+}
+
+// Gets location of REFerence object
+function OLgetRefXY(r,d){
+var o=OLgetRef(r,d),ob=o,rXY=[o3_refx,o3_refy],of;if(!o)return [null,null];if(OLns4){
+if(typeof o.length!='undefined'&&o.length>1){ob=o[0];rXY[0]+=o[0].x+o[1].pageX;rXY[1]+=o[0].y+o[1].pageY;}else{
+if((o.toString().indexOf('Image')!= -1)||(o.toString().indexOf('Anchor')!= -1)){rXY[0]+=o.x;rXY[1]+=o.y;}
+else{rXY[0]+=o.pageX;rXY[1]+=o.pageY;}}}else{rXY[0]+=OLpageLoc(o,'Left');rXY[1]+=OLpageLoc(o,'Top');}
+of=OLgetRefOffsets(ob);rXY[0]+=of[0];rXY[1]+=of[1];return rXY;
+}
+
+// Seeks REFerence by id
+function OLgetRefById(l,d){
+l=(l||'overDiv');d=(d||o3_frame.document);var j,r;if(d.getElementById)return d.getElementById(l);
+if(OLie4&&d.all)return d.all[l];if(d.layers&&d.layers.length>0){if(d.layers[l])return d.layers[l];
+for(j=0;j<d.layers.length;j++){r=OLgetRefById(l,d.layers[j].document);if(r)return r;}}return null;
+}
+
+// Seeks REFerence by name
+function OLgetRefByName(l,d){
+d=(d||o3_frame.document);var j,r,v=OLie4?d.all.tags('iframe'):OLns6?d.getElementsByTagName('iframe'):null;
+if(typeof d.images!='undefined'&&d.images[l])return d.images[l];
+if(typeof d.anchors!='undefined'&&d.anchors[l])return d.anchors[l];
+if(v)for(j=0;j<v.length;j++)if(v[j].name==l)return v[j];if(d.layers&&d.layers.length>0)for(j=0;j<d.layers.length;j++){
+r=OLgetRefByName(l,d.layers[j].document);if(r&&r.length>0)return r;else if(r)return [r,d.layers[j]];}return null;
+}
+
+// Gets layer vs REFerence offsets
+function OLgetRefOffsets(o){
+var c=o3_refc.toUpperCase(),p=o3_refp.toUpperCase(),W=0,H=0,pW=0,pH=0,of=[0,0];pW=(OLbubblePI&&o3_bubble)?
+o3_width:OLns4?over.clip.width:over.offsetWidth;pH=(OLbubblePI&&o3_bubble)?OLbubbleHt:OLns4?
+over.clip.height:over.offsetHeight;if((!OLop7)&&o.toString().indexOf('Image')!= -1){W=o.width;H=o.height;}
+else if((!OLop7)&&o.toString().indexOf('Anchor')!= -1){c=o3_refc='UL';}else{W=(OLns4)?o.clip.width:o.offsetWidth;
+H=(OLns4)?o.clip.height:o.offsetHeight;}if((OLns4||(OLns6&&OLgek))&&o.border){W+=2*parseInt(o.border);
+H+=2*parseInt(o.border);}if(c=='UL'){of=(p=='UR')?[-pW,0]:(p=='LL')?[0,-pH]:(p=='LR')?[-pW,-pH]:[0,0];}else if(c=='UR'){
+of=(p=='UR')?[W-pW,0]:(p=='LL')?[W,-pH]:(p=='LR')?[W-pW,-pH]:[W,0];}else if(c=='LL'){of=(p=='UR')?[-pW,H]:(p=='LL')?[0,H-pH]:
+(p=='LR')?[-pW,H-pH]:[0,H];}else if(c=='LR'){of=(p=='UR')?[W-pW,H]:(p=='LL')?[W,H-pH]:(p=='LR')?[W-pW,H-pH]:[W,H];}return of;
+}
+
+// Gets x or y location of object
+function OLpageLoc(o,t){
+var l=0,s=o;while(o.offsetParent&&o.offsetParent.tagName.toLowerCase()!='html'){l+=o['offset'+t];o=o.offsetParent;}
+l+=o['offset'+t];if(!OLop7)while(s=s.parentNode){if((s['scroll'+t]>0)&&s.tagName.toLowerCase()=='div')l-=s['scroll'+t];}
+return l;
+}
+
+// Moves layer
+function OLmouseMove(e){
+var e=(e||event);OLx=(e.pageX||e.clientX+OLfd().scrollLeft);OLy=(e.pageY||e.clientY+OLfd().scrollTop);if((OLallowmove&&
+over)&&(o3_frame==self||over==OLgetRefById()||(OLovertwoPI&&over2==over&&over==OLgetRefById('overDiv2')))){OLplaceLayer();
+if(OLhidePI)OLhideUtil(0,1,1,0,0,0);}
+}
+
+// Capture mouse and chain other scripts.
+function OLmh(){
+var fN,f,j,k,s,mh=OLmouseMove,w=(OLns4&&window.onmousemove),re=/function[ ]*(\w*)\(/;OLdw=document;if(document.onmousemove||
+w){if(w)OLdw=window;f=OLdw.onmousemove.toString();fN=f.match(re);if(!fN||fN[1]=='anonymous'||fN[1]=='OLmouseMove'){OLchkMh=0;
+return;}if(fN[1])s=fN[1]+'(e)';else{j=f.indexOf('{');k=f.lastIndexOf('}')+1;s=f.substring(j,k);}s+=';OLmouseMove(e);';
+mh=new Function('e',s);}OLdw.onmousemove=mh;if(OLns4)OLdw.captureEvents(Event.MOUSEMOVE);
+}
+
+/*
+ PARSING
+*/
+function OLparseTokens(pf,ar){
+var i,v,md= -1,par=(pf!='ol_'),p=OLpar,q=OLparQuo,t=OLtoggle;OLudf=(par&&!ar.length?1:0);
+for(i=0;i<ar.length;i++){if(md<0){if(typeof ar[i]=='number'){OLudf=(par?1:0);i--;}
+else{switch(pf){case 'ol_':ol_text=ar[i];break;default:o3_text=ar[i];}}md=0;}else{
+if(ar[i]==INARRAY){OLudf=0;eval(pf+'text=ol_texts['+ar[(++i)]+']');continue;}
+if(ar[i]==CAPARRAY){eval(pf+'cap=ol_caps['+ar[(++i)]+']');continue;}
+if(ar[i]==CAPTION){q(ar[++i],pf+'cap');continue;}
+if(Math.abs(ar[i])==STICKY){t(ar[i],pf+'sticky');continue;}
+if(Math.abs(ar[i])==NOFOLLOW){t(ar[i],pf+'nofollow');continue;}
+if(ar[i]==BACKGROUND){q(ar[++i],pf+'background');continue;}
+if(Math.abs(ar[i])==NOCLOSE){t(ar[i],pf+'noclose');continue;}
+if(Math.abs(ar[i])==MOUSEOFF){t(ar[i],pf+'mouseoff');continue;}
+if(ar[i]==OFFDELAY){p(ar[++i],pf+'offdelay');continue;}
+if(ar[i]==RIGHT||ar[i]==LEFT||ar[i]==CENTER){p(ar[i],pf+'hpos');continue;}
+if(ar[i]==OFFSETX){p(ar[++i],pf+'offsetx');continue;}
+if(ar[i]==OFFSETY){p(ar[++i],pf+'offsety');continue;}
+if(ar[i]==FGCOLOR){q(ar[++i],pf+'fgcolor');continue;}
+if(ar[i]==BGCOLOR){q(ar[++i],pf+'bgcolor');continue;}
+if(ar[i]==CGCOLOR){q(ar[++i],pf+'cgcolor');continue;}
+if(ar[i]==TEXTCOLOR){q(ar[++i],pf+'textcolor');continue;}
+if(ar[i]==CAPCOLOR){q(ar[++i],pf+'capcolor');continue;}
+if(ar[i]==CLOSECOLOR){q(ar[++i],pf+'closecolor');continue;}
+if(ar[i]==WIDTH){p(ar[++i],pf+'width');continue;}
+if(Math.abs(ar[i])==WRAP){t(ar[i],pf+'wrap');continue;}
+if(ar[i]==WRAPMAX){p(ar[++i],pf+'wrapmax');continue;}
+if(ar[i]==HEIGHT){p(ar[++i],pf+'height');continue;}
+if(ar[i]==BORDER){p(ar[++i],pf+'border');continue;}
+if(ar[i]==BASE){p(ar[++i],pf+'base');continue;}
+if(ar[i]==STATUS){q(ar[++i],pf+'status');continue;}
+if(Math.abs(ar[i])==AUTOSTATUS){v=pf+'autostatus';
+eval(v+'=('+ar[i]+'<0)?('+v+'==2?2:0):('+v+'==1?0:1)');continue;}
+if(Math.abs(ar[i])==AUTOSTATUSCAP){v=pf+'autostatus';
+eval(v+'=('+ar[i]+'<0)?('+v+'==1?1:0):('+v+'==2?0:2)');continue;}
+if(ar[i]==CLOSETEXT){q(ar[++i],pf+'close');continue;}
+if(ar[i]==SNAPX){p(ar[++i],pf+'snapx');continue;}
+if(ar[i]==SNAPY){p(ar[++i],pf+'snapy');continue;}
+if(ar[i]==FIXX){p(ar[++i],pf+'fixx');continue;}
+if(ar[i]==FIXY){p(ar[++i],pf+'fixy');continue;}
+if(ar[i]==RELX){p(ar[++i],pf+'relx');continue;}
+if(ar[i]==RELY){p(ar[++i],pf+'rely');continue;}
+if(ar[i]==MIDX){p(ar[++i],pf+'midx');continue;}
+if(ar[i]==MIDY){p(ar[++i],pf+'midy');continue;}
+if(ar[i]==REF){q(ar[++i],pf+'ref');continue;}
+if(ar[i]==REFC){q(ar[++i],pf+'refc');continue;}
+if(ar[i]==REFP){q(ar[++i],pf+'refp');continue;}
+if(ar[i]==REFX){p(ar[++i],pf+'refx');continue;}
+if(ar[i]==REFY){p(ar[++i],pf+'refy');continue;}
+if(ar[i]==FGBACKGROUND){q(ar[++i],pf+'fgbackground');continue;}
+if(ar[i]==BGBACKGROUND){q(ar[++i],pf+'bgbackground');continue;}
+if(ar[i]==CGBACKGROUND){q(ar[++i],pf+'cgbackground');continue;}
+if(ar[i]==PADX){p(ar[++i],pf+'padxl');p(ar[++i],pf+'padxr');continue;}
+if(ar[i]==PADY){p(ar[++i],pf+'padyt');p(ar[++i],pf+'padyb');continue;}
+if(Math.abs(ar[i])==FULLHTML){t(ar[i],pf+'fullhtml');continue;}
+if(ar[i]==BELOW||ar[i]==ABOVE||ar[i]==VCENTER){p(ar[i],pf+'vpos');continue;}
+if(ar[i]==CAPICON){q(ar[++i],pf+'capicon');continue;}
+if(ar[i]==TEXTFONT){q(ar[++i],pf+'textfont');continue;}
+if(ar[i]==CAPTIONFONT){q(ar[++i],pf+'captionfont');continue;}
+if(ar[i]==CLOSEFONT){q(ar[++i],pf+'closefont');continue;}
+if(ar[i]==TEXTSIZE){q(ar[++i],pf+'textsize');continue;}
+if(ar[i]==CAPTIONSIZE){q(ar[++i],pf+'captionsize');continue;}
+if(ar[i]==CLOSESIZE){q(ar[++i],pf+'closesize');continue;}
+if(ar[i]==TIMEOUT){p(ar[++i],pf+'timeout');continue;}
+if(ar[i]==DELAY){p(ar[++i],pf+'delay');continue;}
+if(Math.abs(ar[i])==HAUTO){t(ar[i],pf+'hauto');continue;}
+if(Math.abs(ar[i])==VAUTO){t(ar[i],pf+'vauto');continue;}
+if(Math.abs(ar[i])==NOJUSTX){t(ar[i],pf+'nojustx');continue;}
+if(Math.abs(ar[i])==NOJUSTY){t(ar[i],pf+'nojusty');continue;}
+if(Math.abs(ar[i])==CLOSECLICK){t(ar[i],pf+'closeclick');continue;}
+if(ar[i]==CLOSETITLE){q(ar[++i],pf+'closetitle');continue;}
+if(ar[i]==FGCLASS){q(ar[++i],pf+'fgclass');continue;}
+if(ar[i]==BGCLASS){q(ar[++i],pf+'bgclass');continue;}
+if(ar[i]==CGCLASS){q(ar[++i],pf+'cgclass');continue;}
+if(ar[i]==TEXTPADDING){p(ar[++i],pf+'textpadding');continue;}
+if(ar[i]==TEXTFONTCLASS){q(ar[++i],pf+'textfontclass');continue;}
+if(ar[i]==CAPTIONPADDING){p(ar[++i],pf+'captionpadding');continue;}
+if(ar[i]==CAPTIONFONTCLASS){q(ar[++i],pf+'captionfontclass');continue;}
+if(ar[i]==CLOSEFONTCLASS){q(ar[++i],pf+'closefontclass');continue;}
+if(Math.abs(ar[i])==CAPBELOW){t(ar[i],pf+'capbelow');continue;}
+if(ar[i]==LABEL){q(ar[++i],pf+'label');continue;}
+if(Math.abs(ar[i])==DECODE){t(ar[i],pf+'decode');continue;}
+if(ar[i]==DONOTHING){continue;}
+i=OLparseCmdLine(pf,i,ar);}}
+if((OLfunctionPI)&&OLudf&&o3_function)o3_text=o3_function();
+if(pf=='o3_')OLfontSize();
+}
+function OLpar(a,v){eval(v+'='+a);}
+function OLparQuo(a,v){eval(v+"='"+OLescSglQt(a)+"'");}
+function OLescSglQt(s){return s.toString().replace(/\\/g,"\\\\").replace(/'/g,"\\'");}
+function OLtoggle(a,v){eval(v+'=('+v+'==0&&'+a+'>=0)?1:0');}
+function OLhasDims(s){return /[%\-a-z]+$/.test(s);}
+function OLfontSize(){
+var i;if(OLhasDims(o3_textsize)){if(OLns4)o3_textsize="2";}else
+if(!OLns4){i=parseInt(o3_textsize);o3_textsize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
+if(OLhasDims(o3_captionsize)){if(OLns4)o3_captionsize="2";}else
+if(!OLns4){i=parseInt(o3_captionsize);o3_captionsize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
+if(OLhasDims(o3_closesize)){if(OLns4)o3_closesize="2";}else
+if(!OLns4){i=parseInt(o3_closesize);o3_closesize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
+if(OLprintPI)OLprintDims();
+}
+function OLdecode(){
+var re=/%[0-9A-Fa-f]{2,}/,t=o3_text,c=o3_cap,u=unescape,d=!OLns4&&(!OLgek||OLgek>=20020826)&&typeof decodeURIComponent?
+decodeURIComponent:u;if(typeof(window.TypeError)=='function'){if(re.test(t)){eval(new Array('try{','o3_text=d(t);',
+'}catch(e){','o3_text=u(t);','}').join('\n'))};if(c&&re.test(c)){eval(new Array('try{','o3_cap=d(c);','}catch(e){',
+'o3_cap=u(c);','}').join('\n'))}}else{if(re.test(t))o3_text=u(t);if(c&&re.test(c))o3_cap=u(c);}
+}
+
+/*
+ LAYER FUNCTIONS
+*/
+// Writes to layer
+function OLlayerWrite(t){
+t+="\n";if(OLns4){over.document.write(t);over.document.close();}else if(typeof over.innerHTML!='undefined'){
+if(OLieM)over.innerHTML='';over.innerHTML=t;}else{var range=o3_frame.document.createRange();range.setStartAfter(over);
+var domfrag=range.createContextualFragment(t);while(over.hasChildNodes()){over.removeChild(over.lastChild);}
+over.appendChild(domfrag);}if(OLovertwoPI&&over==over2)OLover2HTML=t;else OLoverHTML=t;
+if(OLprintPI)over.print=o3_print?t:null;
+}
+
+// Makes object visible
+function OLshowObject(o){
+OLshowid=0;o=(OLns4)?o:o.style;if(((OLfilterPI)&&!OLchkFilter(o))||!OLfilterPI)o.visibility="visible";
+if(OLshadowPI)OLshowShadow();if(OLiframePI)OLshowIfs();if(OLhidePI)OLhideUtil(1,1,0);
+}
+
+// Hides object
+function OLhideObject(o){
+if(OLshowid>0){clearTimeout(OLshowid);OLshowid=0;}if(OLtimerid>0)clearTimeout(OLtimerid);
+if(OLdelayid>0)clearTimeout(OLdelayid);OLtimerid=0;OLdelayid=0;self.status="";o3_label=ol_label;
+if(o3_frame!=self)o=OLgetRefById();if(o){if(o.onmouseover)o.onmouseover=null;if(OLscrollPI&&o==over)OLclearScroll();
+if(OLdraggablePI)OLclearDrag();if(OLfilterPI)OLcleanupFilter(o);if(OLshadowPI)OLhideShadow();var os=(OLns4)?o:o.style;
+if(((OLfilterPI)&&!OLchkFadeOut(os))||!OLfilterPI){os.visibility="hidden";if(!OLie55||(typeof ggOnChange=='undefined'&&
+(!OLfilterPI||!o3_filter||o3_fadeout<0)))o.innerHTML='';}if(OLhidePI&&o==over)OLhideUtil(0,0,1);if(OLiframePI)OLhideIfs(o);}
+}
+
+// Moves layer
+function OLrepositionTo(o,xL,yL){
+o=(OLns4)?o:o.style;o.left=(OLns4?xL:xL+'px');o.top=(OLns4?yL:yL+'px');
+}
+
+// Handle NOCLOSE-MOUSEOFF
+function OLoptMOUSEOFF(c){
+if(!c)o3_close="";over.onmouseover=function(){OLhover=1;if(OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}}
+over.onmouseout=function(){if(OLhover){OLcC=(OLovertwoPI&&over2&&over==over2?cClick2:cClick);if(OLtimerid>0)
+clearTimeout(OLtimerid);OLtimerid=setTimeout("OLcC()",(o3_offdelay<1)?1:o3_offdelay);}}
+}
+function OLcursorOff(){
+var o=(OLns4?over:over.style),pHt=OLns4?over.clip.height:over.offsetHeight,left=parseInt(o.left),top=parseInt(o.top),
+right=left+o3_width,bottom=top+((OLbubblePI&&o3_bubble)?OLbubbleHt:pHt);
+if(OLx<left||OLx>right||OLy<top||OLy>bottom)return true;return false;
+}
+
+/*
+ REGISTRATION
+*/
+function OLsetRunTimeVar(){
+if(OLrunTime.length)for(var k=0;k<OLrunTime.length;k++)OLrunTime[k]();
+}
+function OLparseCmdLine(pf,i,ar){
+if(OLcmdLine.length){for(var k=0;k<OLcmdLine.length;k++){var j=OLcmdLine[k](pf,i,ar);if(j>-1){i=j;break;}}}return i;
+}
+function OLregCmds(c){
+if(typeof c!='string')return;var pM=c.split(',');pMtr=pMtr.concat(pM);
+for(var i=0;i<pM.length;i++)eval(pM[i].toUpperCase()+'='+(pmCnt++));
+}
+function OLregRunTimeFunc(f){
+if(typeof f=='object')OLrunTime=OLrunTime.concat(f);else OLrunTime[OLrunTime.length++]=f;
+}
+function OLregCmdLineFunc(f){
+if(typeof f=='object')OLcmdLine=OLcmdLine.concat(f);else OLcmdLine[OLcmdLine.length++]=f;
+}
+
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws.zip b/OpenFreezer/overlib/overlibmws.zip
new file mode 100755
index 0000000..dac3ba7
Binary files /dev/null and b/OpenFreezer/overlib/overlibmws.zip differ
diff --git a/OpenFreezer/overlib/overlibmws_bubble.js b/OpenFreezer/overlib/overlibmws_bubble.js
new file mode 100755
index 0000000..6909879
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_bubble.js
@@ -0,0 +1,134 @@
+/*
+ overlibmws_bubble.js plug-in module - Copyright Foteos Macrides 2003-2010. All rights reserved.
+   For support of the BUBBLE feature.
+   Initial: July 26, 2003 - Last Revised: July 2, 2009
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+var OLbubbleCmds='bubble,bubbletype,adjbubble,rcbubblecolor,bubbleclose';OLregCmds(OLbubbleCmds);
+
+// DEFAULT CONFIGURATION
+if(OLud('bubble'))var ol_bubble=0;
+if(OLud('bubbletype'))var ol_bubbletype='';
+if(OLud('adjbubble'))var ol_adjbubble=0;
+if(OLud('rcbubblecolor'))var ol_rcbubblecolor='#ffffcc';
+if(OLud('bubbleclose'))var ol_bubbleclose=0;
+// END CONFIGURATION
+
+function OLund(v){return eval('typeof '+v+'=="undefined"')?1:0;}
+if(OLund('OLbubbleImageSet'))var OLbubbleImageSet='flower,oval,square,pushpin,quotation,roundcorners';
+if(OLund('OLbubbleImages'))var OLbubbleImages=OLbubbleImageSet;
+if(OLund('OLbubbleImageDir'))var OLbubbleImageDir='./';
+if(OLund('OLbubbleIMGsuffix'))var OLbubbleIMGsuffix='';
+if(OLund('OLbubbleRCsuffix'))var OLbubbleRCsuffix='';
+if(OLund('OLimgWidth'))var OLimgWidth=[250,330,144,202,200];
+if(OLund('OLimgHeight'))var OLimgHeight=[150,160,190,221,66];
+if(OLund('OLcontentWidth'))var OLcontentWidth=[200,250,130,184,190];
+if(OLund('OLcontentHeight'))var OLcontentHeight=[80,85,150,176,46];
+if(OLund('OLpadLeft'))var OLpadLeft=[30,40,7,9,5];
+if(OLund('OLpadTop'))var OLpadTop=[25,48,10,34,4];
+if(OLund('OLarwTipX'))var OLarwTipX=[180,50,51,9,19];
+if(OLund('OLarwTipY'))var OLarwTipY=[148,5,180,221,64];
+
+var o3_bubble=0,o3_bubbletype='',o3_adjbubble=0,o3_rcbubblecolor='',o3_bubbleclose=0,
+OLbubbleHt=0,OLbI,OLbContentWd=OLcontentWidth;
+OLregisterImages(OLbubbleImageSet,OLbubbleImageDir,OLbubbleIMGsuffix,OLbubbleRCsuffix);
+
+function OLloadBubble(){
+OLload(OLbubbleCmds);OLbubbleHt=0;
+}
+
+function OLparseBubble(pf,i,ar){
+var k=i,t=OLtoggle,q=OLparQuo;if(k<ar.length){
+if(Math.abs(ar[k])==BUBBLE){t(ar[k],pf+'bubble');return k;}
+if(ar[k]==BUBBLETYPE){q(ar[++k],pf+'bubbletype');return k;}
+if(Math.abs(ar[k])==ADJBUBBLE){t(ar[k],pf+'adjbubble');return k;}
+if(ar[k]==RCBUBBLECOLOR){q(ar[++k],pf+'rcbubblecolor');return k;}
+if(Math.abs(ar[k])==BUBBLECLOSE){t(ar[k],pf+'bubbleclose');return k;}}
+return -1;
+}
+
+function OLchkForBubbleEffect(){
+if(o3_bubble){o3_bubbletype=(o3_bubbletype)?o3_bubbletype:'flower';
+for(var i=0;i<OLbTypes.length;i++){if(OLbTypes[i]==o3_bubbletype){OLbI=i;break;}}
+// disable inappropriate parameters
+o3_bgcolor=o3_fgcolor='';o3_border=o3_base=0;o3_fgbackground=o3_bgbackground=o3_cgbackground=o3_background='';
+o3_cap='';if(o3_sticky)o3_noclose=(o3_bubbleclose)?0:1;o3_fullhtml=0;if(OLshadowPI)o3_shadow=0;
+if(o3_bubbletype.indexOf('roundcorners')<0){o3_width=OLbContentWd[OLbI];o3_hpos=RIGHT;o3_vpos=BELOW;o3_vauto=0;
+o3_hauto=0;o3_wrap=0;o3_nojusty=1;}}return true;
+}
+
+function OLregisterImages(imgStr,path,isuffix,rsuffix){
+if(typeof imgStr!='string')return;var p=(path&&typeof path=='string')?path:'.',is=(typeof isuffix=='string')?isuffix:'',
+rs=(typeof rsuffix=='string')?rsuffix:'',bT;if(p.charAt(p.length-1)=='/')p=p.substring(0,p.length-1);
+if(OLund('OLbTypes'))OLbTypes=imgStr.split(',');if(OLund('OLbubbleImg')){OLbubbleImg=new Array();
+for(var i=0;i<OLbTypes.length;i++){bT=OLbTypes[i];if(OLbubbleImages.indexOf(bT)<0)continue;
+if(bT.indexOf('roundcorners')==0){OLbubbleImg[i]=new Array();
+var o=OLbubbleImg[i],su=((bT.length>12)?bT.substring(12):'')+rs;
+o[0]=new Image();o[0].src=p+'/cornerTL'+su+'.gif';o[1]=new Image();o[1].src=p+'/edgeT'+su+'.gif';
+o[2]=new Image();o[2].src=p+'/cornerTR'+su+'.gif';o[3]=new Image();o[3].src=p+'/edgeL'+su+'.gif';
+o[4]=new Image();o[4].src=p+'/edgeR'+su+'.gif';o[5]=new Image();o[5].src=p+'/cornerBL'+su+'.gif';
+o[6]=new Image();o[6].src=p+'/edgeB'+su+'.gif';o[7]=new Image();o[7].src=p+'/cornerBR'+su+'.gif';}
+else{OLbubbleImg[i]=new Image();OLbubbleImg[i].src=p+'/'+bT+is+'.gif';}}}
+}
+
+function OLgenerateBubble(content){
+if(!o3_bubble)return;if(o3_bubbletype.indexOf('roundcorners')==0)return OLdoRoundCorners(content);
+var ar,X,Y,W,fc=1.0,txt,sY,bHtDiff,bPadDiff=0,bLobj,bCobj,bTopPad=OLpadTop,bLeftPad=OLpadLeft,
+bContentHt=OLcontentHeight,bHt=OLimgHeight,bWd=OLimgWidth,bArwTipX=OLarwTipX,bArwTipY=OLarwTipY;
+bHtDiff=fc*bContentHt[OLbI]-(OLns4?over.clip.height:over.offsetHeight);if(o3_adjbubble){
+fc=OLresizeBubble(bHtDiff,0.5,fc);ar=OLgetHeightDiff(fc);bHtDiff=ar[0];content=ar[1];}
+if(bHtDiff>0)bPadDiff=(bHtDiff<2)?0:parseInt(0.5*bHtDiff);
+Y=(bHtDiff<0)?fc*bTopPad[OLbI]:fc*bTopPad[OLbI]+bPadDiff;X=fc*bLeftPad[OLbI];
+Y=Math.ceil(Y);X=Math.ceil(X);o3_width=Math.ceil(fc*bWd[OLbI]);W=Math.ceil(fc*OLbContentWd[OLbI]);
+OLbubbleHt=Math.ceil((bHtDiff<0?fc*bHt[OLbI]-bHtDiff:fc*bHt[OLbI]));
+txt='<img src="'+OLbubbleImg[OLbI].src+'" width="'+o3_width+'" height="'+OLbubbleHt+'" />'
++(OLns4?'<div id="bContent">':'<div id="bContent" style="position:absolute; top:'+Y+'px; left:'
++X+'px; width:'+W+'px; z-index:1;">')+content+'</div>';OLlayerWrite(txt);
+if(OLns4){bCobj=over.document.layers['bContent'];if(typeof bCobj=='undefined')return;
+bCobj.top=Y;bCobj.left=X;bCobj.clip.width=W;bCobj.zIndex=1;}
+if(fc*bArwTipY[OLbI]<0.5*fc*bHt[OLbI])sY=Math.ceil(fc*bArwTipY[OLbI]);else sY= -(OLbubbleHt+20);
+o3_offsetx -=Math.ceil(fc*bArwTipX[OLbI]);o3_offsety +=sY;
+}
+
+function OLdoRoundCorners(content){
+var wd=(OLns4)?over.clip.width:over.offsetWidth,ht=(OLns4)?over.clip.height:over.offsetHeight,
+o=OLbubbleImg[OLbI],ids=' style="display:block;"',wd14='" width="14',ht14='" height="14"',
+t='<table cellpadding="0" cellspacing="0" border="0"><tr><td align="right" valign="bottom"><img src="'
++o[0].src+wd14+ht14+ids+' /></td><td valign="bottom"><img src="'
++o[1].src+'" width="'+wd+ht14+ids+' /></td><td align="left" valign="bottom"><img src="'
++o[2].src+wd14+ht14+ids+' /></td></tr><tr><td align="right"><img src="'
++o[3].src+wd14+ids+'" height="'+ht+'"'+ids+' /></td><td bgcolor="'+o3_rcbubblecolor+'">'
++content+'</td><td align="left"><img src="'
++o[4].src+wd14+ids+'" height="'+ht+'"'+ids+' /></td></tr><tr><td align="right" valign="top"><img src="'
++o[5].src+wd14+ht14+ids+' /></td><td valign="top"><img src="'
++o[6].src+'" width="'+wd+ht14+ids+' /></td><td align="left" valign="top"><img src="'
++o[7].src+wd14+ht14+ids+' /></td></tr></table>';OLlayerWrite(t);o3_width=wd+28;OLbubbleHt=ht+28;
+}
+
+function OLresizeBubble(h1,dF,fold){
+var df,h2,fnew,alpha,cnt=0;while(cnt<2){df= -OLsignOf(h1)*dF;fnew=fold+df;h2=OLgetHeightDiff(fnew)[0];
+if(Math.abs(h2)<11)break;if(OLsignOf(h1)!=OLsignOf(h2)){alpha=Math.abs(h1)/(Math.abs(h1)+Math.abs(h2));
+if(h1<0)fnew=alpha*fnew+(1.0-alpha)*fold;else fnew=(1.0-alpha)*fnew+alpha*fold;}else{
+alpha=Math.abs(h1)/(Math.abs(h2)-Math.abs(h1));if(h1<0)fnew=(1.0+alpha)*fold-alpha*fnew;
+else fnew=(1.0+alpha)*fnew-alpha*fold;}fold=fnew;h1=h2;dF*=0.5;cnt++;}return fnew;
+}
+function OLsignOf(x){return (x<0)? -1:1;}
+
+function OLgetHeightDiff(f){
+var lyrhtml;o3_width=Math.ceil(f*OLcontentWidth[OLbI]);lyrhtml=OLcontentSimple(o3_text);OLlayerWrite(lyrhtml)
+return [f*OLcontentHeight[OLbI]-((OLns4)?over.clip.height:over.offsetHeight),lyrhtml];
+}
+
+OLregRunTimeFunc(OLloadBubble);OLregCmdLineFunc(OLparseBubble);
+
+if(OLns4)
+document.write('<style type="text/css">\n<!--\n#bContent{position:absolute;left:0px;top:0px;width:1024}\n'
++'-->\n<'+'\/style>');
+OLbubblePI=1;
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws_crossframe.js b/OpenFreezer/overlib/overlibmws_crossframe.js
new file mode 100755
index 0000000..e1bbf41
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_crossframe.js
@@ -0,0 +1,58 @@
+/*
+ overlibmws_crossframe.js plug-in module - Copyright Foteos Macrides 2003-2010. All rights reserved.
+   For support of FRAME.
+   Initial: August 3, 2003 - Last Revised: October 25, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+OLregCmds('frame');
+
+function OLparseCrossframe(pf,i,ar){
+var k=i,v;
+if(k<ar.length){
+if(ar[k]==FRAME){v=ar[++k];if(pf=='ol_')ol_frame=v;else OLoptFRAME(v);return k;}}
+return -1;
+}
+
+function OLgetFrameRef(thisFrame,ofrm){
+var i,v,retVal='';for(i=0;i<thisFrame.length;i++){if((((thisFrame[i].length>0)))&&(((OLns4))||
+((OLie4)&&(v=thisFrame[i].document.all.tags('iframe'))!=null&&v.length==0)||
+((OLns6)&&(v=thisFrame[i].document.getElementsByTagName('iframe'))!=null&&v.length==0))){
+retVal=OLgetFrameRef(thisFrame[i],ofrm);if(retVal=='')continue;}
+else if(thisFrame[i]!=ofrm)continue;retVal='['+i+']'+retVal;break;}
+return retVal;
+}
+
+function OLoptFRAME(frm){
+o3_frame=OLmkLyr('overDiv',frm)?frm:self;if(o3_frame!=self){var l,tFrm=OLgetFrameRef(top.frames,o3_frame),
+sFrm=OLgetFrameRef(top.frames,ol_frame);if(sFrm.length==tFrm.length) {l=tFrm.lastIndexOf('[');if(l){
+while(sFrm.substring(0,l)!=tFrm.substring(0,l))l=tFrm.lastIndexOf('[',l-1);tFrm=tFrm.substr(l);sFrm=sFrm.substr(l);}}
+var i,k,cnt=0,p='',str=tFrm;while((k=str.lastIndexOf('['))!= -1){cnt++;str=str.substring(0,k);}if(!sFrm&&o3_frame==parent)
+sFrm=OLgetFrameRef(parent,self);else for(i=0;i<cnt;i++)p=p+'parent.';OLfnRef=p+'frames'+sFrm+'.';var n=window.name,o;
+if((n&&parent!=self&&o3_frame==parent)&&(o=OLgetRef(n,parent.document))){if(OLie4&&!OLop7){
+OLx=event.clientX+OLfd().scrollLeft;OLy=event.clientY+OLfd().scrollTop;}
+OLifX=OLpageLoc(o,'Left')-(OLie4&&!OLop7?OLfd().scrollLeft:self.pageXOffset);
+OLifY=OLpageLoc(o,'Top')-(OLie4&&!OLop7?OLfd().scrollTop:self.pageYOffset);}}
+}
+
+function OLchkIfRef(){
+var n=(parent!=self&&o3_frame==parent)?window.name:'',o=n?OLgetRef(n):null;
+if(o){var oR=OLgetRef(o3_ref,document);if(oR){OLrefXY=OLgetRefXY(o3_ref,document);
+OLrefXY[0]+=(OLpageLoc(o,'Left')-(OLie4&&!OLop7?OLfd(self).scrollLeft:self.pageXOffset));
+OLrefXY[1]+=(OLpageLoc(o,'Top')-(OLie4&&!OLop7?OLfd(self).scrollTop:self.pageYOffset));}}
+}
+
+function OLchkFRAME(args){
+var OLfrmVal=self;for(var i=0;i<args.length;i++){if(typeof args[i]=='number'&&args[i]==FRAME){OLfrmVal=args[i+1];break;}}
+if(OLfrmVal!=self&&OLfrmVal.over&&OLfrmVal.cClick)OLfrmVal.cClick();
+}
+
+OLregCmdLineFunc(OLparseCrossframe);
+
+OLcrossframePI=1;
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws_debug.js b/OpenFreezer/overlib/overlibmws_debug.js
new file mode 100755
index 0000000..47f5d07
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_debug.js
@@ -0,0 +1,120 @@
+/*
+ overlibmws_debug.js plug-in module - Copyright Foteos Macrides 2003-2010. All rights reserved.
+   For support of the OLshowProperties() debugging function.
+   Initial: July 26, 2003 - Last Revised: June 22, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+var OLzIndex;
+OLregCmds('allowdebug');
+
+// DEFAULT CONFIGURATION
+if(OLud('allowdebug'))var ol_allowdebug='';
+// END CONFIGURATION
+
+var o3_allowdebug='';
+
+function OLloadDebug(){
+OLload('allowdebug');
+}
+
+function OLparseDebug(pf,i,ar){
+var k=i;
+if(ar[k]==ALLOWDEBUG){
+if(k<(ar.length-1)&&typeof ar[k+1]=='string')OLparQuo(ar[++k],pf+'allowdebug');return k;}
+return -1;
+}
+
+function OLshowProperties(){
+var ar=arguments,sho,shoS,vis,lvl=0,istrt=0,theDiv='showProps',txt='',
+fac='Verdana,Arial,Helvetica',siz=(OLns4?'1':'67%'),
+fon='><font color="#000000" face="'+fac+'" size="'+siz,
+stl=' style="font-family:'+fac+';font-size:'+siz+';',
+sty=stl+'color:#000000;',clo=(OLns4?'</font>':'');
+if(ar.length==0)return;
+if(ar.length%2&&typeof ar[0]=='string'){istrt=1;theDiv=ar[0];}
+if(!(sho=OLmkLyr(theDiv,self)))return;
+shoS=(OLns4)?sho:sho.style;
+lvl=OLgetLayerLevel(theDiv);
+if(typeof sho.position=='undefined'){
+sho.position=new OLpageLocDebug(10+lvl*20,10,1);
+if(typeof OLzIndex=='undefined')OLzIndex=OLgetDivZindex('overDiv',self);
+shoS.zIndex=OLzIndex+1+lvl;}
+txt='<table cellpadding="1" cellspacing="0" border="0" bgcolor="#000000"><tr><td>'
++'<table cellpadding="5" border="0" cellspacing="0" bgcolor="#ffffcc">'
++'<tr><td><strong><a href="javascript:OLmoveToBack(\''+theDiv+'\');" title="Move to back"'
++(OLns4?fon:stl)+'">'+theDiv+clo
++'</a></strong></td><td align="right"><strong><a href="javascript:OLcloseLayer(\''+theDiv
++'\');" title="Close Layer"'+(OLns4?fon:stl
++'background-color:#cccccc;border:1px #333369 outset;padding:0px;')+'">X'+clo
++'</a></strong></td></tr><tr><td'+(OLns4?fon:sty)+'">'+'<strong><em>Item</em></strong>'
++clo+'</td><td'+(OLns4?fon:sty)+'">'+'<strong><em>Value</em></strong>'+clo+'</td></tr>';
+for(var i=istrt;i<ar.length-1;i++)
+txt+='<tr><td align="right"'+(OLns4?fon:sty)+'">'+'<strong>'+ar[i]+': </strong>'
++clo+'</td><td'+(OLns4?fon:sty)+'">'+ar[++i]+clo+'</td></tr>';
+txt+='</table></td></tr></table>';
+if(OLns4){sho.document.open();sho.document.write(txt);sho.document.close();
+}else{if(OLie4&&OLieM)sho.innerHTML='';sho.innerHTML=txt;}
+OLshowAllVisibleLayers();
+}
+
+function OLgetLayerLevel(lyr){
+var i=0;
+if(typeof document.popups=='undefined'){document.popups=new Array(lyr);
+}else{var l=document.popups;for(i=0;i<l.length;i++)if(lyr==l[i])break;
+if(i==l.length)l[l.length++]=lyr;}
+return i;
+}
+
+function OLgetDivZindex(id,f){
+if(!id)id='overDiv';if(!f)f=o3_frame;
+var o=OLgetRefById(id,f.document);
+if(o){o=OLns4?o:o.style;return o.zIndex;}
+else return 1000;
+}
+
+function OLsetDebugCanShow(){
+if(o3_allowdebug!=''){
+var i,lyr,pLyr=o3_allowdebug.replace(/[ ]/ig,'').split(',');
+for(i=0;i<pLyr.length;i++){lyr=OLgetRefById(pLyr[i],self.document);
+if(lyr&&typeof lyr.position!='undefined')lyr.position.canShow=1;}}
+}
+
+function OLpageLocDebug(x,y,canShow){
+this.x=x;this.y=y;this.canShow=(canShow==null)?0:canShow;
+}
+
+function OLshowAllVisibleLayers(){
+var i,lyr,o,l=document.popups;
+for(i=0;i<l.length;i++){if((lyr=OLgetRefById(l[i],self.document))&&lyr.position.canShow){
+o=OLns4?lyr:lyr.style;OLpositionLayer(o,lyr.position.x,lyr.position.y);o.visibility='visible';}}
+}
+
+function OLpositionLayer(o,x,y){
+o.left=x+(OLie4&&!OLop95?OLfd(self).scrollLeft:self.pageXOffset)+(OLns4?0:'px');
+o.top=y+(OLie4&&!OLop95?OLfd(self).scrollTop:self.pageYOffset)+(OLns4?0:'px');
+}
+
+function OLcloseLayer(id){
+var lyr=OLgetRefById(id,self.document);
+if(lyr){lyr.position.canShow=0;lyr=OLns4?lyr:lyr.style;lyr.visibility='hidden';}
+}
+
+function OLmoveToBack(layer){
+var l=document.popups,lyr,o,i,x=10,dx=20,z=OLzIndex+1;if(l.length==1)return;
+if(lyr=OLgetRefById(layer,self.document)){lyr.position.x=x;o=OLns4?lyr:lyr.style;o.zIndex=z;
+for(i=0;i<l.length;i++){if(layer==l[i])continue;
+if(!(lyr=OLgetRefById(l[i],self.document))||lyr.position.canShow==0)continue;
+o=OLns4?lyr:lyr.style;o.zIndex+=1;lyr.position.x+=dx;}OLshowAllVisibleLayers();}
+}
+
+OLregRunTimeFunc(OLloadDebug);
+OLregCmdLineFunc(OLparseDebug);
+
+OLdebugPI=1;
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws_draggable.js b/OpenFreezer/overlib/overlibmws_draggable.js
new file mode 100755
index 0000000..d2b5eb1
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_draggable.js
@@ -0,0 +1,85 @@
+/*
+ overlibmws_draggable.js plug-in module - Copyright Foteos Macrides 2002-2010. All rights reserved.
+   For support of the DRAGGABLE feature.
+   Initial: August 24, 2002 - Last Revised: January 26, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+var OLdraggableCmds='draggable,dragcap,dragid';
+OLregCmds(OLdraggableCmds);
+
+// DEFAULT CONFIGURATION
+if(OLud('draggable'))var ol_draggable=0;
+if(OLud('dragcap'))var ol_dragcap=0;
+if(OLud('dragid'))var ol_dragid='';
+// END CONFIGURATION
+
+var o3_draggable=0,o3_dragcap=0,o3_dragid='',o3_dragging=0,OLdrg=null,OLmMv,
+OLcX,OLcY,OLcbX,OLcbY;function OLloadDraggable(){OLload(OLdraggableCmds);}
+function OLparseDraggable(pf,i,ar){var t=OLtoggle,k=i;if(k<ar.length){
+if(Math.abs(ar[k])==DRAGGABLE){t(ar[k],pf+'draggable');return k;}
+if(Math.abs(ar[k])==DRAGCAP){t(ar[k],pf+'dragcap');return k;}
+if(ar[k]==DRAGID){OLparQuo(ar[++k],pf+'dragid');return k;}}return -1;
+}
+
+function OLcheckDrag(){
+if(o3_draggable){if(o3_sticky&&(o3_frame==self))OLinitDrag();else o3_draggable=0;}
+}
+function OLinitDrag(){
+OLmMv=OLdw.onmousemove;o3_dragging=0;
+if(OLns4){document.captureEvents(Event.MOUSEDOWN|Event.CLICK);
+document.onmousedown=OLgrabEl;document.onclick=function(e){return routeEvent(e);}}
+else{var dvido=(o3_dragid)?OLgetRef(o3_dragid):null,capid=(OLovertwoPI&&over==over2?
+'overCap2':'overCap');if(dvido)dvido.onscroll=function(){OLdw.onmousemove=OLmMv;
+OLinitDrag();};OLdrg=(o3_cap&&o3_dragcap)?OLgetRef(capid):over;
+if(!OLdrg||!OLdrg.style)OLdrg=over;OLdrg.onmousedown=OLgrabEl;OLsetDrgCur(1);}
+}
+function OLsetDrgCur(d){if(!OLns4&&OLdrg)OLdrg.style.cursor=(d?'move':'auto');}
+
+function OLgrabEl(e){
+var e=(e||event);
+var cKy=(OLns4?e.modifiers&Event.ALT_MASK:(e.altKey||(OLop7&&e.ctrlKey)));o3_dragging=1;
+if(cKy){OLsetDrgCur(0);document.onmouseup=function(){OLsetDrgCur(1);o3_dragging=0;}
+return(OLns4?routeEvent(e):true);}
+OLx=(e.pageX||e.clientX+OLfd().scrollLeft);OLy=(e.pageY||e.clientY+OLfd().scrollTop);
+if(OLie4)over.onselectstart=function(){return false;}
+if(OLns4){OLcX=OLx;OLcY=OLy;document.captureEvents(Event.MOUSEUP)}else{
+OLcX=OLx-(OLns4?over.left:parseInt(over.style.left));
+OLcY=OLy-(OLns4?over.top:parseInt(over.style.top));
+if((OLshadowPI)&&bkdrop&&o3_shadow){OLcbX=OLx-(parseInt(bkdrop.style.left));
+OLcbY=OLy-(parseInt(bkdrop.style.top));}}OLdw.onmousemove=OLmoveEl;
+document.onmouseup=function(){
+if(OLie4)over.onselectstart=null;o3_dragging=0;OLdw.onmousemove=OLmMv;}
+return(OLns4?routeEvent(e):false);
+}
+
+function OLmoveEl(e){
+var e=(e||event);
+OLx=(e.pageX||e.clientX+OLfd().scrollLeft);OLy=(e.pageY||e.clientY+OLfd().scrollTop);
+if(o3_dragging){if(OLns4){over.moveBy(OLx-OLcX,OLy-OLcY);
+if(OLshadowPI&&bkdrop&&o3_shadow)bkdrop.moveBy(OLx-OLcX,OLy-OLcY);}
+else{OLrepositionTo(over,OLx-OLcX,OLy-OLcY);
+if((OLiframePI)&&OLie55&&OLifsP1)OLrepositionTo(OLifsP1,OLx-OLcX,OLy-OLcY);
+if((OLshadowPI)&&bkdrop&&o3_shadow){OLrepositionTo(bkdrop,OLx-OLcbX,OLy-OLcbY);
+if((OLiframePI)&&OLie55&&OLifsSh)OLrepositionTo(OLifsSh,OLx-OLcbX,OLy-OLcbY);}}
+if(OLhidePI)OLhideUtil(0,1,1,0,0,0);}if(OLns4){OLcX=OLx;OLcY=OLy;}
+return false;
+}
+
+function OLclearDrag(){
+if(OLns4){document.releaseEvents(Event.MOUSEDOWN|Event.MOUSEUP|Event.CLICK);
+document.onmousedown=document.onclick=null;}else{
+if(OLdrg)OLdrg.onmousedown=null;over.onmousedown=null;OLsetDrgCur(0);}
+document.onmouseup=null;o3_dragging=0;
+}
+
+OLregRunTimeFunc(OLloadDraggable);
+OLregCmdLineFunc(OLparseDraggable);
+
+OLdraggablePI=1;
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws_exclusive.js b/OpenFreezer/overlib/overlibmws_exclusive.js
new file mode 100755
index 0000000..7659b27
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_exclusive.js
@@ -0,0 +1,58 @@
+/*
+ overlibmws_exclusive.js plug-in module - Copyright Foteos Macrides 2003-2010. All rights reserved.
+   For support of the EXCLUSIVE feature.
+   Initial: November 7, 2003 - Last Revised: June 11, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+var OLexclusiveCmds='exclusive,exclusivestatus,exclusiveoverride';
+OLregCmds(OLexclusiveCmds);
+
+// DEFAULT CONFIGURATION
+if(OLud('exclusive'))var ol_exclusive=0;
+if(OLud('exclusivestatus'))var ol_exclusivestatus='Please act on or close the open popup.';
+if(OLud('exclusiveoverride'))var ol_exclusiveoverride=0;
+// END CONFIGURATION
+
+var o3_exclusive=0,o3_exclusivestatus='',o3_exclusiveoverride=0;
+
+function OLloadExclusive(){
+OLload(OLexclusiveCmds);
+}
+
+function OLparseExclusive(pf,i,ar){
+var k=i,t=OLtoggle;
+if(k<ar.length){
+if(Math.abs(ar[k])==EXCLUSIVE){t(ar[k],pf+'exclusive');return k;}
+if(ar[k]==EXCLUSIVESTATUS){OLparQuo(ar[++k],pf+'exclusivestatus');return k;}
+if(Math.abs(ar[k])==EXCLUSIVEOVERRIDE){t(ar[k],pf+'exclusiveoverride');return k;}}
+return -1;
+}
+
+function OLisExclusive(args){
+if((args!=null)&&OLhasOverRide(args))o3_exclusiveoverride=(ol_exclusiveoverride==0)?1:0;
+else o3_exclusiveoverride=ol_exclusiveoverride;
+var rtnVal=(o3_exclusive&&!o3_exclusiveoverride&&OLshowingsticky&&
+((OLovertwoPI&&OLshowingsticky2)||over==OLgetRefById('overDiv')));
+if(rtnVal)self.status=o3_exclusivestatus;
+return rtnVal;
+}
+
+function OLhasOverRide(args){
+var rtnFlag=0;
+for(var i=0;i<args.length;i++){
+if(typeof args[i]=='number'&&args[i]==EXCLUSIVEOVERRIDE){
+rtnFlag=1;break;}}
+return rtnFlag;
+}
+
+OLregRunTimeFunc(OLloadExclusive);
+OLregCmdLineFunc(OLparseExclusive);
+
+OLexclusivePI=1;
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws_filter.js b/OpenFreezer/overlib/overlibmws_filter.js
new file mode 100755
index 0000000..f27d9f4
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_filter.js
@@ -0,0 +1,156 @@
+/*
+ overlibmws_filter.js plug-in module - Copyright Foteos Macrides 2003-2010. All rights reserved.
+  For support of the FILTER feature.
+  Initial: November 27, 2003 - Last Revised: October 25, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+var OLfilterCmds='filter,fadein,fadeout,fadetime,filteropacity,filtershadow,filtershadowcolor';
+OLregCmds(OLfilterCmds);
+
+// DEFAULT CONFIGURATION
+if(OLud('filter'))var ol_filter=0;
+if(OLud('fadein'))var ol_fadein=52;
+if(OLud('fadeout'))var ol_fadeout=52;
+if(OLud('fadetime'))var ol_fadetime=800;
+if(OLud('filteropacity'))var ol_filteropacity=100;
+if(OLud('filtershadow'))var ol_filtershadow=0;
+if(OLud('filtershadowcolor'))var ol_filtershadowcolor="#cccccc";
+// END CONFIGURATION
+
+var o3_filter=0,o3_fadein=52,o3_fadeout=52,o3_fadetime=800,o3_filteropacity=100,
+o3_filtershadow=0,o3_filtershadowcolor="#cccccc",OLfiIdx= -1,OLfInc=5,OLfTmInc=40,OLfOp=1,
+OLfiId=0,OLfoId=0,OLfOp2=1,OLfiId2=0,OLfoId2=0,OLfInc2=5,OLfTmInc2=40;
+
+function OLloadFilter(){
+OLload(OLfilterCmds);
+}
+
+function OLparseFilter(pf,i,ar){
+var k=i,p=OLpar;
+if(k<ar.length){
+if(Math.abs(ar[k])==FILTER){OLtoggle(ar[k],pf+'filter');return k;}
+if(ar[k]==FADEIN){p(ar[++k],pf+'fadein');return k;}
+if(ar[k]==FADEOUT){p(ar[++k],pf+'fadeout');return k;}
+if(ar[k]==FADETIME){p(ar[++k],pf+'fadetime');return k;}
+if(ar[k]==FILTEROPACITY){p(ar[++k],pf+'filteropacity');return k;}
+if(ar[k]==FILTERSHADOW){p(ar[++k],pf+'filtershadow');return k;}
+if(ar[k]==FILTERSHADOWCOLOR){OLparQuo(ar[++k],pf+'filtershadowcolor');return k;}}
+return -1;
+}
+
+function OLhasOp(){
+var op=0;if(OLns4||OLieM)return op;var os=over.style,u='undefined';if(os)op=(typeof os.opacity!=u||typeof os.MozOpacity!=u||
+typeof os.KhtmlOpacity!=u||OLie4&&!OLopr)?1:0;return(op);
+}
+
+function OLinitFilterLyr(o2){
+if(!OLie55){if(!OLhasOp()){o3_filter=0;return;}var O2=(o2||0);if(parent!=self){if(parent.OLshowingsticky)o3_fadeout=0;
+if(parent.OLfilterPI)parent.OLcleanupFilter(parent.over,O2);}OLcleanupFilter(over,O2);}if(OLie55){o3_fadein-=1;o3_fadeout-=1;
+OLfiIdx= -1;if(over.style.filter&&!OLop95){var p,s,ob=over.filters[28];for(p=28;p<31;p++){over.filters[p].enabled=0;}
+for(s=0;s<28;s++){if(over.filters[s].status)over.filters[s].stop();over.filters[s].enabled=0;}ob.enabled=0;
+ob.opacity=ol_filteropacity;return;}}if(OLie55&&(!o3_filter||(OLshadowPI&&o3_shadow)))return;if(!OLie55){var b=(OLshadowPI)?
+OLgetRef('backdrop2'):null;if(o2){if(OLfiId2)clearTimeout(OLfiId2);if(OLfoId2)clearInterval(OLfoId2);OLfiId2=OLfoId2=0;
+if(b)b.style.visibility='hidden';over2.style.visibility='hidden';OLopOv(ol_filteropacity,2);if(o3_filter&&(o3_fadein||
+o3_fadeout)){OLfInc2=o3_filteropacity/20;OLfOp2=(o3_fadein?1:o3_filteropacity);OLfTmInc2=parseInt(o3_fadetime/20);}}else{
+if(OLfiId)clearTimeout(OLfiId);if(OLfoId)clearInterval(OLfoId);OLfiId=OLfoId=0;if(OLshadowPI&&bkdrop)
+bkdrop.style.visibility='hidden';over.style.visibility='hidden';OLopOv(ol_filteropacity);if(o3_filter&&(o3_fadein||
+o3_fadeout)){OLfInc=o3_filteropacity/20;OLfOp=(o3_fadein?1:o3_filteropacity);OLfTmInc=parseInt(o3_fadetime/20);}}return;}
+var d=" progid:DXImageTransform.Microsoft.";over.style.filter="revealTrans()"
++d+"Fade(Overlap=1.00 enabled=0)"+d+"Inset(enabled=0)"
++d+"Iris(irisstyle=PLUS,motion=in enabled=0)"+d+"Iris(irisstyle=PLUS,motion=out enabled=0)"
++d+"Iris(irisstyle=DIAMOND,motion=in enabled=0)"+d+"Iris(irisstyle=DIAMOND,motion=out enabled=0)"
++d+"Iris(irisstyle=CROSS,motion=in enabled=0)"+d+"Iris(irisstyle=CROSS,motion=out enabled=0)"
++d+"Iris(irisstyle=STAR,motion=in enabled=0)"+d+"Iris(irisstyle=STAR,motion=out enabled=0)"
++d+"RadialWipe(wipestyle=CLOCK enabled=0)"+d+"RadialWipe(wipestyle=WEDGE enabled=0)"
++d+"RadialWipe(wipestyle=RADIAL enabled=0)"+d+"Pixelate(MaxSquare=35,enabled=0)"
++d+"Slide(slidestyle=HIDE,Bands=25 enabled=0)"+d+"Slide(slidestyle=PUSH,Bands=25 enabled=0)"
++d+"Slide(slidestyle=SWAP,Bands=25 enabled=0)"+d+"Spiral(GridSizeX=16,GridSizeY=16 enabled=0)"
++d+"Stretch(stretchstyle=HIDE enabled=0)"+d+"Stretch(stretchstyle=PUSH enabled=0)"
++d+"Stretch(stretchstyle=SPIN enabled=0)"+d+"Wheel(spokes=16 enabled=0)"
++d+"GradientWipe(GradientSize=1.00,wipestyle=0,motion=forward enabled=0)"
++d+"GradientWipe(GradientSize=1.00,wipestyle=0,motion=reverse enabled=0)"
++d+"GradientWipe(GradientSize=1.00,wipestyle=1,motion=forward enabled=0)"
++d+"GradientWipe(GradientSize=1.00,wipestyle=1,motion=reverse enabled=0)"
++d+"Zigzag(GridSizeX=8,GridSizeY=8 enabled=0)"+d+"Alpha(enabled=0)"
++d+"Dropshadow(OffX=5,OffY=5,Positive=true,enabled=0)"
++d+"Shadow(strength=5,direction=135,enabled=0)";
+}
+
+function OLchkFilter(o,o2){
+if(!o3_filter||o!=over.style||(OLie55&&OLshadowPI&&o3_shadow))return false;if(!OLie55){var op=o3_filteropacity;
+if(op>0&&op<100){if(o2)OLopOv(op,2);else OLopOv(op);}if(o3_fadein||o3_fadeout){var p=(o3_fadein)?(o2?OLfOp2:OLfOp):
+o3_filteropacity;if(o2){OLopOv(p,2);if(o3_fadein&&!OLfiId2)OLfadeIn2();}else{OLopOv(p);if(o3_fadein&&!OLfiId)OLfadeIn();}}
+return false;}var fi=o3_fadein,fo=o3_fadeout,fp=1,ft=o3_fadetime/1000;if(fi<0||fi>51){fi=fo;fp=0;}if(fi==51)
+fi=parseInt(Math.random()*50);var at=fi>-1&&fi<24&&ft>0,af=fi>23&&fi<51&&ft>0;OLfiIdx=(af?fi-23:0);var p,s,e,ob,
+t=over.filters[OLfiIdx];for(p=28;p<31;p++){over.filters[p].enabled=0;}for(s=0;s<28;s++){if(over.filters[s].status)
+over.filters[s].stop();over.filters[s].enabled=0;}for(e=1;e<3;e++){if(o3_filtershadowcolor&&o3_filtershadow==e){
+ob=over.filters[28+e];ob.enabled=1;ob.color=o3_filtershadowcolor;}}if(o3_filteropacity>0&&o3_filteropacity<100){
+ob=over.filters[28];ob.enabled=1;ob.opacity=o3_filteropacity;}if(fp&&(at||af)){if(at)over.filters[0].transition=fi;
+t.duration=ft;t.apply();o.visibility='visible';t.play();return true;}return false;
+}
+
+function OLopOv(op,o2){
+var o=(o2?over2:over),os=o.style;if(OLie4&&!OLop95&&typeof os.filter=='string')os.filter='Alpha(opacity='+op+')';
+else if(typeof os.opacity!='undefined')os.opacity=op/100;else if(typeof os.MozOpacity!='undefined')os.MozOpacity=op/100;
+else if(typeof os.KhtmlOpacity!='undefined')os.KhtmlOpacity=op/100;
+}
+
+function OLopOvSh(op,o){
+if(!bkdrop&&!o)return;var os=(o)?o.style:bkdrop.style;if(OLie4&&!OLop95&&typeof os.filter=='string')os.filter=
+'Alpha(opacity='+op+')';else if(typeof os.opacity!='undefined')os.opacity=op/100;else if(typeof os.MozOpacity!='undefined')
+os.MozOpacity=op/100;else if(typeof os.KhtmlOpacity!='undefined')os.KhtmlOpacity=op/100;
+}
+
+function OLcleanupFilter(o,o2){
+if(!o3_filter||!over||o!=over||(OLie55&&OLshadowPI&&o3_shadow))return;if(!OLie55){if(o2){if(OLfiId2)clearTimeout(OLfiId2);
+if(OLfoId2)clearInterval(OLfoId2);OLfiId2=OLfoId2=0;var op=o3_filteropacity;if(op>0&&op<100)OLopOv(ol_filteropacity,2);}
+else{if(OLfiId)clearTimeout(OLfiId);if(OLfoId)clearInterval(OLfoId);OLfiId=OLfoId=0;var op=o3_filteropacity;
+if(op>0&&op<100)OLopOv(ol_filteropacity);}return;}if(typeof over.filters!='object')return;var os=over.style,fi=o3_fadein,
+fo=o3_fadeout;if(fi>=0&&fi<=51&&fo==fi){if(OLfiIdx<0)return;var t=over.filters[OLfiIdx];if(t.status)t.stop();
+os.visibility='visible';t.apply();os.visibility='hidden';t.play();}else{if(fo>=0&&fo<=51){fi=fo;if(fi==51)
+fi=parseInt(Math.random()*50);var ft=o3_fadetime;var at=fi>-1&&fi<24&&ft>0; var af=fi>23&&fi<51&&ft>0;OLfiIdx=(af?fi-23:0);
+t=over.filters[OLfiIdx];if(at||af){if(at)over.filters[0].transition=fi;if(t.status)t.stop();os.visibility='visible';
+t.apply();os.visibility='hidden';t.play();}}}OLfiIdx=-1;if(event&&event.type=='click')event.returnValue=false;
+}
+
+function OLfadeIn(){
+if(OLfOp>=o3_filteropacity){if(OLshadowPI&&o3_shadow&&bkdrop)OLopOvSh(o3_shadowopacity);OLopOv(o3_filteropacity);
+clearTimeout(OLfiId);OLfiId=0;}else{OLopOv(OLfOp);if(!OLfOp&&over.style.visibility=='hidden')over.style.visibility='visible';
+var ops=0.3*OLfOp;if(OLfOp>40&&OLshadowPI&&o3_shadow&&bkdrop&&ops<o3_shadowopacity)OLopOvSh(ops);OLfOp+=OLfInc;
+OLfiId=setTimeout("OLfadeIn()",OLfTmInc);}
+}
+function OLfadeIn2(){
+if(OLfOp2>=o3_filteropacity){if(OLshadowPI&&o3_shadow&&bkdrop)OLopOvSh(o3_shadowopacity);OLopOv(o3_filteropacity,2);
+clearTimeout(OLfiId2);OLfiId2=0;}else{OLopOv(OLfOp2,2);if(!OLfOp2&&over2&&over2.style.visibility=='hidden')
+over2.style.visibility='visible';var ops=0.3*OLfOp2;if(OLfOp2>40&&OLshadowPI&&o3_shadow&&bkdrop&&ops<o3_shadowopacity)
+OLopOvSh(ops);OLfOp2+=OLfInc2;OLfiId2=setTimeout("OLfadeIn2()",OLfTmInc2);}
+}
+
+function OLchkFadeOut(o){
+if(OLie55||!o3_filter||!o3_fadeout||o!=over.style)return false;OLfoId=setInterval('OLfadeOut()',OLfTmInc);return true;
+}
+function OLfadeOut(){
+if(OLfOp<0){clearInterval(OLfoId);OLfoId=0;o3_fadeout=0;if(OLshadowPI&&o3_shadow&&bkdrop){bkdrop.style.visibility="hidden";
+OLcleanUpShadow();}OLhideObject(over);}else{var ops=0.3*OLfOp;
+if(OLfOp>40&&OLshadowPI&&o3_shadow&&bkdrop&&ops<o3_shadowopacity)OLopOvSh(ops);OLopOv(OLfOp);OLfOp-=OLfInc;}
+}
+function OLchkFadeOut2(o){
+if(OLie55||!o3_filter||!o3_fadeout||o!=over.style)return false;OLfoId2=setInterval('OLfadeOut2()',OLfTmInc2);return true;
+}
+function OLfadeOut2(){
+var b=(OLshadowPI)?OLgetRef('backdrop2'):null;if(!b)b=(bkdrop)?bkdrop:null;if(OLfOp2<0){clearInterval(OLfoId2);if(b){
+b.style.visibility="hidden";if(over==over2)OLcleanUpShadow();}OLfoId2=0;OLhideObjectP2(over);over2.style.visibility='hidden';
+}else{var ops=0.3*OLfOp2;if(b){if(OLfOp2>40)OLopOvSh(ops,b);else OLopOvSh(1,b);}OLopOv(OLfOp2,2);OLfOp2-=OLfInc2;}
+}
+
+OLregRunTimeFunc(OLloadFilter);
+OLregCmdLineFunc(OLparseFilter);
+
+OLfilterPI=1;
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws_function.js b/OpenFreezer/overlib/overlibmws_function.js
new file mode 100755
index 0000000..5540b0f
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_function.js
@@ -0,0 +1,44 @@
+/*
+ overlibmws_function.js plug-in module - Copyright Foteos Macrides 2002-2010. All rights reserved.
+   For support of the FUNCTION feature.
+   Initial: August 18, 2002 - Last Revised: January 26, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+OLregCmds('function');
+
+// DEFAULT CONFIGURATION
+if(OLud('function'))var ol_function=null;
+// END CONFIGURATION
+
+var o3_function=null;
+
+function OLloadFunction(){
+OLload('function');
+}
+
+function OLparseFunction(pf,i,ar){
+var k=i,v=null;
+if(k<ar.length){
+if(ar[k]==FUNCTION){if(pf=='ol_'){if(typeof ar[k+1]!='number'){v=ar[++k];
+ol_function=(typeof v=='function'?v:null);}}
+else{OLudf=0;v=null;if(typeof ar[k+1]!='number')v=ar[++k];OLoptFUNCTION(v);}return k;}}
+return -1;
+}
+
+function OLoptFUNCTION(callme){
+o3_text=(callme?(typeof callme=='string'?(/.+\(.*\)/.test(callme)?eval(callme):
+callme):callme()):(o3_function?o3_function():'No Function'));
+return 0;
+}
+
+OLregRunTimeFunc(OLloadFunction);
+OLregCmdLineFunc(OLparseFunction);
+
+OLfunctionPI=1;
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws_hide.js b/OpenFreezer/overlib/overlibmws_hide.js
new file mode 100755
index 0000000..466ae18
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_hide.js
@@ -0,0 +1,81 @@
+/*
+ overlibmws_hide.js plug-in module - Copyright Foteos Macrides 2003-2010. All rights reserved.
+   For hiding elements.
+   Initial: November 13, 2003 - Last Revised: February 10, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+var OLhideCmds='hideselectboxes,hidebyid,hidebyidall,hidebyidns4';
+OLregCmds(OLhideCmds);
+
+// DEFAULT CONFIGURATION
+if(OLud('hideselectboxes'))var ol_hideselectboxes=0;
+if(OLud('hidebyid'))var ol_hidebyid='';
+if(OLud('hidebyidall'))var ol_hidebyidall='';
+if(OLud('hidebyidns4'))var ol_hidebyidns4='';
+// END CONFIGURATION
+
+var o3_hideselectboxes=0,o3_hidebyid='',o3_hidebyidall='',o3_hidebyidns4='',
+OLselectOK=(OLie7||OLop7||OLgek>=20030624||OLsaf)?1:0;
+
+function OLloadHide(){
+OLload(OLhideCmds);
+}
+
+function OLparseHide(pf,i,ar){
+var k=i,q=OLparQuo;
+if(k<ar.length){
+if(Math.abs(ar[k])==HIDESELECTBOXES){OLtoggle(ar[k],pf+'hideselectboxes');return k;}
+if(ar[k]==HIDEBYID){q(ar[++k],pf+'hidebyid');return k;}
+if(ar[k]==HIDEBYIDALL){q(ar[++k],pf+'hidebyidall');return k;}
+if(ar[k]==HIDEBYIDNS4){q(ar[++k],pf+'hidebyidns4');return k;}}
+return -1;
+}
+
+function OLchkHide(hide){
+if(OLiframePI&&OLie55)return;if(OLmodalPI&&o3_modal)o3_hideselectboxes=0;var id,o,i;
+if(o3_hidebyid&&typeof o3_hidebyid=='string'&&!(o3_hideselectboxes&&OLns6)&&!OLop7&&!OLns4){
+id=o3_hidebyid.replace(/[ ]/ig,'').split(',');for(i=0;i<id.length;i++){
+o=(OLie4?o3_frame.document.all[id[i]]:OLns6?o3_frame.document.getElementById(id[i]):null);
+if(o)o.style.visibility=(hide?'hidden':'visible');}}
+if(o3_hidebyidall&&typeof o3_hidebyidall=='string'){
+id=o3_hidebyidall.replace(/[ ]/ig,'').split(',');for(i=0;i<id.length;i++){
+o=OLgetRefById(id[i]);if(o){o=(OLns4)?o:o.style;
+o.visibility=(hide?'hidden':'visible');}}}
+if(o3_hidebyidns4&&OLns4&&typeof o3_hidebyidns4=='string'){
+id=o3_hidebyidns4.replace(/[ ]/ig,'').split(',');for(i=0;i<id.length;i++){
+o=eval('o3_frame.document.'+id[i]);if(o)o.visibility=(hide?'hidden':'visible');}}
+}
+
+function OLselectBoxes(hide,all){
+if((OLiframePI&&OLie55)||OLselectOK||OLns4)return;var sel=OLie4?
+o3_frame.document.all.tags('select'):o3_frame.document.getElementsByTagName('select'),
+px=over.offsetLeft,py=over.offsetTop,pw=over.offsetWidth,ph=over.offsetHeight,bx=px,by=py,
+bw=pw,bh=ph,sx,sy,sw,sh,i,sp,si;if((OLshadowPI)&&bkdrop&&o3_shadow){bx=bkdrop.offsetLeft;
+by=bkdrop.offsetTop;bw=bkdrop.offsetWidth;bh=bkdrop.offsetHeight;}for(i=0;i<sel.length;i++){
+sx=0;sy=0;si=0;if(sel[i].offsetParent){sp=sel[i];while(sp.offsetParent&&
+sp.offsetParent.tagName.toLowerCase()!='body'){if(sp.offsetParent.id=='overDiv'||
+sp.offsetParent.id=='overDiv2')si=1;sp=sp.offsetParent;sx+=sp.offsetLeft;sy+=sp.offsetTop;}
+sx+=sel[i].offsetLeft;sy+=sel[i].offsetTop;sw=sel[i].offsetWidth;sh=sel[i].offsetHeight;
+if(si||(!OLie4&&sel[i].size<2))continue;else if(hide){if((px+pw>sx&&px<sx+sw&&py+ph>sy&&
+py<sy+sh)||(bx+bw>sx&&bx<sx+sw&&by+bh>sy&&by<sy+sh)){if(sel[i].style.visibility!="hidden")
+sel[i].style.visibility="hidden";}}else{if(all||(!(OLovertwoPI&&over==over2)&&(px+pw<sx||
+px>sx+sw||py+ph<sy||py>sy+sh)&&(bx+bw<sx||bx>sx+sw||by+bh<sy||by>sy+sh))){
+if(sel[i].style.visibility!="visible")sel[i].style.visibility="visible";}}}}
+}
+
+function OLhideUtil(a1,a2,a3,a4,a5,a6){
+if(a4==null){OLchkHide(a1);if(o3_hideselectboxes)OLselectBoxes(a2,a3);}else{OLchkHide(a1);
+OLchkHide(a2);if(o3_hideselectboxes){OLselectBoxes(a3,a4);OLselectBoxes(a5,a6);}}
+}
+
+OLregRunTimeFunc(OLloadHide);
+OLregCmdLineFunc(OLparseHide);
+
+OLhidePI=1;
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws_iframe.js b/OpenFreezer/overlib/overlibmws_iframe.js
new file mode 100755
index 0000000..a06bdc5
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_iframe.js
@@ -0,0 +1,93 @@
+/*
+ overlibmws_iframe.js plug-in module - Copyright Foteos Macrides 2003-2010. All rights reserved.
+   Masks system controls to prevent obscuring of popops for IE v5.5 or higher.
+   Initial: October 19, 2003 - Last Revised: January 26, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+
+var OLifsP1=null,OLifsSh=null,OLifsP2=null;
+
+// IFRAME SHIM SUPPORT FUNCTIONS
+function OLinitIfs(){
+if(!OLie55)return;
+if((OLovertwoPI)&&over2&&over==over2){
+var o=o3_frame.document.all['overIframeOvertwo'];
+if(!o||OLifsP2!=o){OLifsP2=null;OLgetIfsP2Ref();}return;}
+o=o3_frame.document.all['overIframe'];
+if(!o||OLifsP1!=o){OLifsP1=null;OLgetIfsRef();}
+if((OLshadowPI)&&o3_shadow){o=o3_frame.document.all['overIframeShadow'];
+if(!o||OLifsSh!=o){OLifsSh=null;OLgetIfsShRef();}}
+}
+
+function OLsetIfsRef(o,i,z){
+o.id=i;o.src='javascript:false;';o.scrolling='no';var os=o.style;os.position='absolute';
+os.top='0px';os.left='0px';os.width='1px';os.height='1px';os.visibility='hidden';
+os.zIndex=over.style.zIndex-z;os.filter='Alpha(style=0,opacity=0)';
+}
+
+function OLgetIfsRef(){
+if(OLifsP1||!OLie55)return;
+OLifsP1=o3_frame.document.createElement('iframe');
+OLsetIfsRef(OLifsP1,'overIframe',2);
+o3_frame.document.body.appendChild(OLifsP1);
+}
+
+function OLgetIfsShRef(){
+if(OLifsSh||!OLie55)return;
+OLifsSh=o3_frame.document.createElement('iframe');
+OLsetIfsRef(OLifsSh,'overIframeShadow',3);
+o3_frame.document.body.appendChild(OLifsSh);
+}
+
+function OLgetIfsP2Ref(){
+if(OLifsP2||!OLie55)return;
+OLifsP2=o3_frame.document.createElement('iframe');
+OLsetIfsRef(OLifsP2,'overIframeOvertwo',1);
+o3_frame.document.body.appendChild(OLifsP2);
+}
+
+function OLsetDispIfs(o,w,h){
+var os=o.style;
+os.width=w+'px';os.height=h+'px';os.clip='rect(0px '+w+'px '+h+'px 0px)';
+o.filters.alpha.enabled=true;
+}
+
+function OLdispIfs(){
+if(!OLie55)return;
+var wd=over.offsetWidth,ht=over.offsetHeight;
+if(OLfilterPI&&o3_filter&&o3_filtershadow){wd+=5;ht+=5;}
+if((OLovertwoPI)&&over2&&over==over2){
+if(!OLifsP2)return;
+OLsetDispIfs(OLifsP2,wd,ht);return;}
+if(!OLifsP1)return;
+OLsetDispIfs(OLifsP1,wd,ht);
+if((!OLshadowPI)||!o3_shadow||!OLifsSh)return;
+OLsetDispIfs(OLifsSh,wd,ht);
+}
+
+function OLshowIfs(){
+if(OLifsP1){OLifsP1.style.visibility="visible";
+if((OLshadowPI)&&o3_shadow&&OLifsSh)OLifsSh.style.visibility="visible";}
+}
+
+function OLhideIfs(o){
+if(!OLie55||o!=over)return;
+if(OLifsP1)OLifsP1.style.visibility="hidden";
+if((OLshadowPI)&&o3_shadow&&OLifsSh)OLifsSh.style.visibility="hidden";
+}
+
+function OLrepositionIfs(X,Y){
+if(OLie55){if((OLovertwoPI)&&over2&&over==over2){
+if(OLifsP2)OLrepositionTo(OLifsP2,X,Y);}
+else{if(OLifsP1){OLrepositionTo(OLifsP1,X,Y);if((OLshadowPI)&&o3_shadow&&OLifsSh)
+OLrepositionTo(OLifsSh,X+o3_shadowx,Y+o3_shadowy);}}}
+}
+
+OLiframePI=1;
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws_modal.js b/OpenFreezer/overlib/overlibmws_modal.js
new file mode 100755
index 0000000..a7a0641
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_modal.js
@@ -0,0 +1,139 @@
+/*
+ overlibmws_modal.js plug-in module - Copyright Foteos Macrides 2006-2010. All rights reserved.
+   For support of the MODAL feature.
+   Initial: November 15, 2006 - Last Revised: June 21, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;var OLmodalCmds='modal,modalcolor,modalopacity,modalscroll';OLregCmds(OLmodalCmds);
+
+// DEFAULT CONFIGURATION
+if(OLud('modal'))var ol_modal=0;
+if(OLud('modalcolor'))var ol_modalcolor="#bbbbbb";
+if(OLud('modalopacity'))var ol_modalopacity=40;
+if(OLud('modalscroll'))var ol_modalscroll=0;
+// END CONFIGURATION
+
+var o3_modal=0,o3_modalcolor="#bbbbbb",o3_modalopacity=40,o3_modalscroll=0;
+
+function OLloadModal(){
+OLload(OLmodalCmds);
+}
+
+function OLparseModal(pf,i,ar){
+var t=OLtoggle,k=i;if(k<ar.length){
+if(Math.abs(ar[k])==MODAL){t(ar[k],pf+'modal');return k;}
+if(ar[k]==MODALCOLOR){OLparQuo(ar[++k],pf+'modalcolor');return k;}
+if(ar[k]==MODALOPACITY){OLpar(ar[++k],pf+'modalopacity');return k;}
+if(Math.abs(ar[k])==MODALSCROLL){t(ar[k],pf+'modalscroll');return k;}}
+return -1;
+}
+
+var OLmMask=null,OLmIframe=null,OLmMaskOn=0,OLmSelectOK=(OLie55||OLop7||OLgek>=20030624)?1:0,OLmRoot='html',OLmGotSc=0,
+OLmScLeft=0,OLmScTop=0,OLmKDH=null,OLmTI=new Array(),OLmTT=new Array("a","button","iframe","input","select","textarea"),
+OLmEdit=0;	
+
+function OLchkModal(){
+if(o3_modal){if(OLsaf&&!o3_modalscroll){o3_modalscroll=1;return;}if(o3_sticky&&!OLns4)OLmInitMask();else o3_modal=0;}
+}
+function OLclearModal(){
+if(OLmMaskOn)OLmHideMask();
+}
+
+function OLsetModalIframe(o,i,z){
+o.id=i;o.src='javascript:false;';o.scrolling='no';var os=o.style;os.position='absolute';os.zIndex=z;
+os.filter='Alpha(style=0,opacity=0)';
+}
+
+function OLmInitMask(){
+OLmRoot=(o3_frame.document.compatMode&&o3_frame.document.compatMode=='BackCompat')?'body':'html';
+var doCss=(!OLgetRef('modalMask'))?1:0,zI=(over)?over.style.zIndex-2:998;OLmMask=OLmkLyr('modalMask',o3_frame);
+OLmMask.style.zIndex=zI;if(OLie55){if(!OLgetRef('modalIframe')){OLmIframe=o3_frame.document.createElement('iframe');
+OLsetModalIframe(OLmIframe,'modalIframe',(zI-1));o3_frame.document.body.appendChild(OLmIframe);}
+else OLmIframe.style.zIndex=(zI-1);}var o=OLmMask.style,op=o3_modalopacity;op=(op<=100&&op>0?op:100);
+o.backgroundColor=o3_modalcolor;if(doCss){o.display='none';o.top='0px';o.left='0px';o.width='100%';o.height='100%';
+o.visibility='visible';if(OLie55){var oi=o3_frame.document.all['modalIframe'].style;oi.display='none';oi.top='0px';
+oi.left='0px';oi.width='100%';oi.height='100%';oi.visibility='visible';}}if(OLie4&&!OLieM&&!OLop95
+&&typeof o.filter=='string'){o.filter='Alpha(opacity='+op+')';if(OLie55)OLmMask.filters.alpha.enabled=1;}else{op=op/100;
+if(typeof o.opacity!='undefined')o.opacity=op;else if(typeof o.MozOpacity!='undefined')o.MozOpacity=op;
+else if(typeof o.KhtmlOpacity!='undefined')o.KhtmlOpacity=op;}OLmAddEv(window,"resize",OLmHandleMask);OLmShowMask();
+}
+function OLmShowMask(){
+OLmMaskOn=1;if(!OLie4||OLop7){OLmKDH=document.onkeypress?document.onkeypress.toString():null;
+document.onkeypress=OLmKeyDownHandler;}else OLmDisableTI();OLmMask.style.display="block";
+if(OLie55)OLmIframe.style.display="block";OLmHandleMask();OLmSetMaskSize();if(!OLmSelectOK)OLmHideSB();
+}
+function OLmHandleMask(){
+if(OLmMaskOn){if(!OLmGotSc){OLmScLeft=parseInt((OLie4&&!OLop95?OLfd(o3_frame).scrollLeft:o3_frame.pageXOffset),10);
+OLmScTop=parseInt((OLie4&&!OLop95?OLfd(o3_frame).scrollTop:o3_frame.pageYOffset),10);OLmGotSc=1;}
+var root=o3_frame.document.getElementsByTagName(OLmRoot)[0];if(!o3_modalscroll&&root.style.overflow!='hidden')
+root.style.overflow='hidden';var o=OLmMask.style,oi=(OLie55&&OLmIframe)?OLmIframe.style:null;o.top=o.left=0+'px';
+o.height=o.width='100%';if(oi){oi.top=oi.left=0+'px';oi.height=oi.width='100%';}OLmSetMaskSize();}
+}
+function OLmSetMaskSize(){
+var root=o3_frame.document.getElementsByTagName(OLmRoot)[0],mHt,fullWd=OLmViewportWd(),fullHt=OLmViewportHt();
+if(fullHt>root.scrollHeight)mHt=fullHt;else mHt=root.scrollHeight;OLmMask.style.height=mHt+'px';
+OLmMask.style.width=root.scrollWidth+'px';if(OLie55&&OLmIframe){OLmIframe.style.height=mHt+'px';
+OLmIframe.style.width=root.scrollWidth+'px';}
+}
+function OLmHideMask(){
+OLmMaskOn=0;var root=o3_frame.document.getElementsByTagName(OLmRoot)[0];root.style.overflow=(OLop7?'auto':'');
+if(!OLie4||OLop7){document.onkeypress=OLmKDH;OLmKDH=null;}else OLmRestoreTI();if(!OLmSelectOK)OLmShowSB();
+OLmRemoveEv(window,"resize",OLmHandleMask);if(o3_frame.scrollTo&&OLmGotSc){o3_frame.scrollTo(OLmScLeft,OLmScTop);OLmGotSc=0;}
+if(OLgetRef('modalMask')&&OLmMask){OLmMask.style.display='none';if(OLie55)OLmIframe.style.display='none';}OLmEdit=0;
+}
+
+function OLmKeyDownHandler(e){
+var ev=(e||event),k=ev.keyCode,c=ev.charCode;
+if(OLmMaskOn&&!OLmEdit&&(k==9||c==32||(OLgek&&k==13)||(k>=32&&k<=40)))return false;
+}
+
+function OLmAddEv(obj,evType,fn){
+if(obj.addEventListener){obj.addEventListener(evType,fn,false);return true;}if(obj.attachEvent){
+var r=obj.attachEvent("on"+evType,fn);return r;}return false;
+}
+function OLmRemoveEv(obj,evType,fn){
+if(obj.removeEventListener){obj.removeEventListener(evType,fn,false);return true;}if(obj.detachEvent){
+var r=obj.detachEvent("on"+evType,fn);return r;}return false;
+}
+
+function OLmViewportWd(){
+if(o3_frame.innerWidth!=o3_frame.undefined)return o3_frame.innerWidth;
+if(o3_frame.document.compatMode=='CSS1Compat')return o3_frame.document.documentElement.clientWidth;
+if(o3_frame.document.body)return o3_frame.document.body.clientWidth;return o3_frame.undefined;
+}
+function OLmViewportHt(){
+if(o3_frame.innerHeight!=o3_frame.undefined)return o3_frame.innerHeight;
+if(o3_frame.document.compatMode=='CSS1Compat')return o3_frame.document.documentElement.clientHeight;
+if(o3_frame.document.body)return o3_frame.document.body.clientHeight;return o3_frame.undefined;
+}
+
+function OLmHideSB(){
+var s=over.innerHTML;over.innerHTML='';
+var sel=OLie4?o3_frame.document.all.tags('select'):o3_frame.document.getElementsByTagName('select');
+for(i=0;i<sel.length;i++)sel[i].style.visibility="hidden";over.innerHTML=s;
+}
+function OLmShowSB(){
+var s=over.innerHTML;over.innerHTML='';
+var sel=OLie4?o3_frame.document.all.tags('select'):o3_frame.document.getElementsByTagName('select');
+for(i=0;i<sel.length;i++)sel[i].style.visibility="visible";over.innerHTML=s;
+}
+
+function OLmDisableTI(){
+if(OLie4&&!OLop7){var i=0;for(var j=0;j<OLmTT.length;j++){var tagE=o3_frame.document.getElementsByTagName(OLmTT[j]);
+for(var k=0;k<tagE.length;k++){OLmTI[i]=tagE[k].tabIndex;tagE[k].tabIndex="-1";i++;}}}
+}
+function OLmRestoreTI(){
+if(OLie4&&!OLop7){var i=0;for(var j=0;j<OLmTT.length;j++){var tagE=o3_frame.document.getElementsByTagName(OLmTT[j]);
+for(var k=0;k<tagE.length;k++){tagE[k].tabIndex=OLmTI[i];tagE[k].tabEnabled=true;i++;}}}
+}
+
+OLregRunTimeFunc(OLloadModal);
+OLregCmdLineFunc(OLparseModal);
+
+OLmodalPI=1;
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws_overtwo.js b/OpenFreezer/overlib/overlibmws_overtwo.js
new file mode 100755
index 0000000..22f77d4
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_overtwo.js
@@ -0,0 +1,117 @@
+/*
+ overlibmws_overtwo.js plug-in module - Copyright Foteos Macrides 2003-2010. All rights reserved.
+   For support of the popups-within-a-popup feature.
+   Initial: July 14, 2003 - Last Revised: March 7, 2010
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+OLregCmds('label2');
+
+// DEFAULT CONFIGURATION
+if(OLud('label2'))var ol_label2="";
+// END CONFIGURATION
+
+var o3_label2="",OLshowingsticky2=0,over2=null,OLp1over=null,bkdrop2=null,OLp1bkdrop=null,OLp1scroll=0,OLp1X=0,OLp1Y=0,
+OLp1If=null,OLp1IfShadow=null,OLp1bubbleHt=0,OLp1exclusive=0,OLp1modal=0,OLp1fiIdx= -1,OLp1Hover=0,OLp2over=null;
+
+function OLloadOvertwo(){
+OLload('label2');
+}
+
+function OLparseOvertwo(pf,i,ar){
+var k=i,q=OLparQuo;
+if(k<ar.length){
+if(ar[k]==LABEL2){q(ar[++k],pf+'label2');return k;}}
+return -1;
+}
+
+// PUBLIC FUNCTIONS
+function overlib2(){
+var ar=arguments;if(over2)cClick2();if(ar.length==0)return false;OLp2over=null;if(!OLshowingsticky||OLpFrame(ar)){if(
+parent!=self&&window.name&&OLeval2('parent.OLshowingsticky')&&OLpFrame(ar)){if(parent.OLshowid){parent.clearTimeout(
+parent.OLshowid);parent.OLshowid=0;}if(parent.OLdelayid){parent.clearTimeout(parent.OLdelayid);parent.OLdelayid=0;}
+if(parent.OLtimerid){parent.clearTimeout(parent.OLtimerid);parent.OLtimerid=0;}if(OLshowingsticky)cClick();OLp2over=over;
+over=parent.over;}else return false;}OLifX=0;OLifY=0;if(OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}if(OLshowid>0){
+clearTimeout(OLshowid);OLshowid=0;}if(OLdelayid>0){clearTimeout(OLdelayid);OLdelayid=0;}if(typeof over.onmouseover!=
+'undefined'&&over.onmouseover!=null){OLp1Hover=1;OLhover=0;over.onmouseover=null;}else OLp1Hover=0;OLp1over=null;
+OLp1scroll=(OLscrollPI&&o3_scroll?1:0);if(OLp1scroll){OLp1X=over.scroll.x;OLp1Y=over.scroll.y;OLclearScroll();o3_scroll=0;}
+if(OLfunctionPI)o3_function=ol_function;if(OLdraggablePI&&o3_draggable)OLclearDrag();OLp1exclusive=(OLexclusivePI&&
+o3_exclusive?1:0);OLp1modal=(OLmodalPI&&o3_modal?1:0);if((OLiframePI)&&OLifsP1){OLp1If=OLifsP1;OLifsP1=null;if(OLifsSh){
+OLp1IfShadow=OLifsSh;OLifsSh=null;}}else{OLp1If=null;OLp1IfSh=null}OLpullP1(OLo2c(1));if(OLbubblePI)OLp1bubbleHt=OLbubbleHt;
+if(OLfilterPI){OLp1fiIdx=OLfiIdx;if(!OLie55&&o3_filter)OLopOv(o3_filteropacity);}OLload(OLo2c(0));o3_label2=ol_label2;
+OLparseTokens('o3_',ar);if((parent!=self&&OLshowingsticky)&&(OLeval2('parent.OLshowingsticky')||OLfnRef||window.name))
+o3_delay=0;OLpushP1(OLp1co);if(OLexclusivePI)o3_exclusive=OLp1exclusive;if(o3_decode)OLdecode();if(!OLshowingsticky)
+parent.OLo2Ref=(OLfnRef)?OLfnRef+'cClick2()':'';if(OLbubblePI)OLchkForBubbleEffect();if(o3_autostatus==2&&o3_cap!="")
+o3_status=o3_cap;else if(o3_autostatus==1&&o3_text!="")o3_status=o3_text;if(o3_delay==0)OLdispP2();else OLdelayid=
+setTimeout("OLdispP2()",o3_delay);if(o3_status!=""){self.status=o3_status;return true;}else if(!(OLop7&&event&&
+event.type=='mouseover'))return false;
+}
+function OLeval2(s){var ret=0;eval(new Array('try{','if(',s,')ret=1;}','catch(e){','ret=0;}').join('\n'));return(ret);}
+
+function nd2(){
+if(OLdelayid>0){clearTimeout(OLdelayid);OLdelayid=0;}if(parent!=self&&OLeval2('over==parent.over')){if(OLp2over||
+OLeval2('parent.OLshowingsticky')){over=null;OLp2over=null;}}if(OLshowingsticky2)return false;return cClick2();
+}
+
+function cClick2(){
+if(!over2||over!=over2)return false;if(OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}if(OLshowid>0){clearTimeout(
+OLshowid);OLshowid=0;}if(OLp1over&&OLp1over!=OLmkLyr()){OLp1over=null;over2=null;return false;}OLhover=0;over.onmouseover=
+null;OLhideObjectP2(over);OLshowingsticky2=0;if(OLp1bkdrop){bkdrop=OLp1bkdrop;OLp1bkdrop=null;}if(OLp1over){over=OLp1over;
+OLp1over=null;}if(parent!=self&&OLeval2('over==parent.over')){if(OLp2over||OLeval2('parent.OLshowingsticky'))over=OLp2over;}
+OLp2over=null;if((OLiframePI)&&OLp1If){OLifsP1=OLp1If;OLp1If=null;if(OLp1IfShadow){OLifsSh=OLp1IfShadow;OLp1IfShadow=null;}}
+OLpushP1(OLo2c(1));if(OLbubblePI){OLbubbleHt=OLp1bubbleHt;OLp1BubbleHt=0;}if(OLfilterPI)OLfiIdx=OLp1fiIdx;
+var o=OLgetRefById();if(o&&o==over){if(OLp1scroll){o3_scroll=1;OLp1scroll=0;OLchkScroll(OLp1X,OLp1Y);}else o3_scroll=0;
+if(OLdraggablePI)OLcheckDrag();if(OLp1exclusive){o3_exclusive=1;OLp1exclusive=0;}if(OLhidePI)OLhideUtil(0,1,1,0,0,0);
+if(o3_autostatus==2&&o3_cap!="")o3_status=o3_cap;else if(o3_autostatus==1&&o3_text!="")o3_status=o3_text;if(OLp1Hover){
+OLoptMOUSEOFF(1);OLp1Hover=0;OLhover=1;if(parent==self&&OLcursorOff())cClick();}if(o3_status!="")self.status=o3_status;}
+if(OLmodalPI&&!OLp1modal)OLclearModal();OLp1modal=0;return false;
+}
+
+// SUPPORT FUNCTIONS
+function OLpullP1(c){var i,m=c.split(',');for(i=0;i<m.length;i++)eval('OLp1'+m[i]+'=o3_'+m[i]);}
+function OLpushP1(c){var i,m=c.split(',');for(i=0;i<m.length;i++)eval('o3_'+m[i]+'=OLp1'+m[i]);}
+function OLo2c(a){return OLp1or2+(a?','+OLp1:'')+(OLbubblePI?','+OLbubbleCmds:'')+(OLdraggablePI?','+OLdraggableCmds:'')
++(OLfilterPI?','+OLfilterCmds:'')+(OLmodalPI?','+OLmodalCmds:'')+(OLprintPI?','+OLprintCmds:'')
++(OLshadowPI?','+OLshadowCmds:'');}
+
+function OLpFrame(ar){
+var r=0;if(OLcrossframePI){for(var i=0;i<ar.length;i++){if(typeof ar[i]=='number'&&ar[i]==FRAME){if(ar[i+1]==parent)r=1;
+break;}}}return r;
+}
+
+function OLdispP2(){
+var o=(OLns4?over:over.style),zI=parseInt(o.zIndex)+2;o3_delay=0;if(!(over2=OLmkLyr('overDiv2',o3_frame,zI)))return;
+OLp1over=over;over=over2;if(OLmodalPI&&!OLp1modal&&!o3_modalscroll)OLchkModal();if(OLbubblePI)OLbubbleHt=0;
+if(o3_noclose)OLoptMOUSEOFF(0);else if(o3_mouseoff)OLoptMOUSEOFF(1);if(o3_sticky)OLshowingsticky2=1;
+OLdoLyr();if(o3_timeout>0){if(OLtimerid>0)clearTimeout(OLtimerid);OLtimerid=setTimeout("cClick2()",o3_timeout);
+o3_timeout=0;}OLchkRef();if(OLshadowPI&&o3_shadow){OLp1bkdrop=bkdrop;bkdrop=bkdrop2;OLinitShadow();}if(OLiframePI){
+OLinitIfs();OLdispIfs();}if(OLfilterPI)OLinitFilterLyr(2);if(OLshadowPI&&o3_shadow)OLdispShadow();OLplaceLayer();
+if(OLmodalPI&&!OLp1modal&&o3_modalscroll)OLchkModal();OLshowid=setTimeout("OLshowObjectP2(over2)",1);
+OLallowmove=(o3_sticky||o3_nofollow)?0:1;
+}
+
+function OLshowObjectP2(o){
+OLshowid=0;if(o)o=(OLns4?o:o.style);if(((OLfilterPI)&&!OLchkFilter(o,2))||!OLfilterPI)o.visibility="visible";
+if(OLshadowPI)OLshowShadow();if(OLiframePI&&OLifsP2)OLifsP2.style.visibility="visible";if(OLhidePI)OLhideUtil(1,1,0);
+if(OLdraggablePI)OLcheckDrag();
+}
+
+function OLhideObjectP2(o){
+if(OLshowid>0){clearTimeout(OLshowid);OLshowid=0;}if(OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}o3_timeout=0;
+if(OLdelayid>0){clearTimeout(OLdelayid);OLdelayid=0;}o3_delay=0;if(o&&o==OLgetRefById('overDiv2')){
+if(OLscrollPI)OLclearScroll();if(OLdraggablePI)OLclearDrag();if(OLfilterPI)OLcleanupFilter(o,2);if(OLshadowPI)OLhideShadow();
+var os=(OLns4)?o:o.style;if(((OLfilterPI)&&!OLchkFadeOut2(os))||!OLfilterPI){os.visibility="hidden";
+if(!OLie55||(typeof ggOnChange=='undefined'&&(!OLfilterPI||!o3_filter||o3_fadeout<0)))o.innerHTML='';}
+if(OLiframePI&&OLifsP2)OLifsP2.style.visibility="hidden";}OLallowmove=o3_nofollow=0;o3_label2=ol_label2;
+}
+
+OLregRunTimeFunc(OLloadOvertwo);
+OLregCmdLineFunc(OLparseOvertwo);
+
+OLovertwoPI=1;
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws_print.js b/OpenFreezer/overlib/overlibmws_print.js
new file mode 100755
index 0000000..fe71edd
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_print.js
@@ -0,0 +1,143 @@
+/*
+ overlibmws_print.js plug-in module - Copyright Foteos Macrides 2002-2010. All rights reserved.
+   For support of the PRINT feature.
+   Initial: April 25, 2005 - Last Revised: October 15, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+var OLprintCmds='print,printbutton,noautoprint,printcolor,printfont,printsize,printtext,'
++'printbuttontext,printtitle,printfontclass,printcssfile,printxml,printdoctype,printroot,'
++'printtype,printcharset,printurl,printjob',OLprJob=null;OLregCmds(OLprintCmds);
+
+// DEFAULT CONFIGURATION
+if(OLud('print'))var ol_print=0;
+if(OLud('printbutton'))var ol_printbutton=0;
+if(OLud('noautoprint'))var ol_noautoprint=0;
+if(OLud('printcolor'))var ol_printcolor="#eeeeff";
+if(OLud('printfont'))var ol_printfont="Verdana,Arial,Helvetica";
+if(OLud('printsize'))var ol_printsize=1;
+if(OLud('printtext'))var ol_printtext='Print';
+if(OLud('printbuttontext'))var ol_printbuttontext='Print';
+if(OLud('printtitle'))var ol_printtitle="Click to Print";
+if(OLud('printfontclass'))var ol_printfontclass="";
+if(OLud('printcssfile'))var ol_printcssfile="";
+if(OLud('printxml'))var ol_printxml="";
+if(OLud('printdoctype'))var ol_printdoctype=
+ '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" '
++'"http://www.w3.org/TR/html4/loose.dtd">';
+if(OLud('printroot'))var ol_printroot="<html>";
+if(OLud('printtype'))var ol_printtype="text/html";
+if(OLud('printcharset'))var ol_printcharset="iso-8859-1";
+if(OLud('printurl'))var ol_printurl="";
+if(OLud('printjob'))var ol_printjob="";
+// END CONFIGURATION
+
+var o3_print=0,o3_printbutton=0,o3_noautoprint,o3_printcolor="",o3_printfont="",o3_printsize=1,
+o3_printtext="",o3_printbuttontext="",o3_printtitle="",o3_printfontclass="",o3_printcssfile="",
+o3_printxml="",o3_printdoctype="",o3_printroot="",o3_printtype="",o3_printcharset="",
+o3_printurl="",o3_printjob="";
+
+function OLloadPrint(){
+OLload(OLprintCmds);
+}
+
+function OLparsePrint(pf,i,ar){
+var k=i,t=OLtoggle,q=OLparQuo;
+if(k<ar.length){
+if(Math.abs(ar[k])==PRINT){t(ar[k],pf+'print');return k;}
+if(Math.abs(ar[k])==PRINTBUTTON){t(ar[k],pf+'printbutton');return k;}
+if(Math.abs(ar[k])==NOAUTOPRINT){t(ar[k],pf+'noautoprint');return k;}
+if(ar[k]==PRINTCOLOR){q(ar[++k],pf+'printcolor');return k;}
+if(ar[k]==PRINTFONT){q(ar[++k],pf+'printfont');return k;}
+if(ar[k]==PRINTSIZE){q(ar[++k],pf+'printsize');return k;}
+if(ar[k]==PRINTTEXT){q(ar[++k],pf+'printtext');return k;}
+if(ar[k]==PRINTBUTTONTEXT){q(ar[++k],pf+'printbuttontext');return k;}
+if(ar[k]==PRINTTITLE){q(ar[++k],pf+'printtitle');return k;}
+if(ar[k]==PRINTFONTCLASS){q(ar[++k],pf+'printfontclass');return k;}
+if(ar[k]==PRINTCSSFILE){q(ar[++k],pf+'printcssfile');return k;}
+if(ar[k]==PRINTXML){q(ar[++k],pf+'printxml');return k;}
+if(ar[k]==PRINTDOCTYPE){q(ar[++k],pf+'printdoctype');return k;}
+if(ar[k]==PRINTROOT){q(ar[++k],pf+'printroot');return k;}
+if(ar[k]==PRINTTYPE){q(ar[++k],pf+'printtype');return k;}
+if(ar[k]==PRINTCHARSET){q(ar[++k],pf+'printcharset');return k;}
+if(ar[k]==PRINTURL){q(ar[++k],pf+'printurl');return k;}
+if(ar[k]==PRINTJOB){q(ar[++k],pf+'printjob');return k;}}
+return -1;
+}
+
+function OLprintDims(){
+if(OLhasDims(o3_printsize)){if(OLns4)o3_printsize="2";}else
+if(!OLns4){var i=parseInt(o3_printsize);o3_printsize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
+}
+
+function OLchkPrint(){if(!o3_sticky)o3_print=0;else over.print=null;}
+
+function OLprintCapLGF(){
+var n=(OLovertwoPI&&over2&&over==over2)?2:1;
+return(o3_print&&!o3_printbutton?'<td align="right"><a href="javascript:'+OLfnRef
++'return OLprint('+n+');" '+(o3_printtitle?'title="'+o3_printtitle+'" ':'')+'onclick="'
++OLfnRef+'return OLprint('+n+');"'+(o3_printfontclass?' class="'+o3_printfontclass+'">':
+(OLns4?'><':'')+OLlgfUtil(0,1,'','a',o3_printcolor,o3_printfont,o3_printsize))+o3_printtext
++(o3_printfontclass?'':(OLns4?OLlgfUtil(1,1,'','a'):''))+'</a></td>':'');
+}
+
+function OLprintFgLGF(){
+var n=(OLovertwoPI&&over2&&over==over2)?2:1;return (o3_print&&(!o3_cap||o3_printbutton)?
+'<div align="center"><form action="javascript:void(0);"><input type="button" '
++(OLns4?'':'style="font-family:Verdana;font-size:11px;color:#000000;" ')+'value="'
++o3_printbuttontext+'" title="'+o3_printtitle+'" '+(OLgek?'autocomplete="off" ':'')
++'onclick="'+OLfnRef+'return OLprint('+n+');" /></form></div>':'');
+}
+
+function OLprint(n){
+if(n!=2&&OLovertwoPI&&over2&&over==over2)cClick2();
+if(!(over&&over.print))return false;if(o3_printjob){eval(o3_printjob);
+if(OLie55&&event&&event.type=='click')event.returnValue=false;return false;}
+if(o3_printurl){if(!window.print||o3_noautoprint)
+alert('Print (Control-P) the OLprint Window when it appears, then close it.');OLprJob=
+window.open(o3_printurl,'OLurlJob','resizable=1,status=1,screenX=0,left=0,screenY=0,top=0');
+OLprJob.focus();if(OLprJob){if(window.print&&!o3_noautoprint){OLprJob.print();
+setTimeout("OLprJob.close();OLprJob=null;",2);}}return false;}
+var sx=(OLshadowPI&&o3_shadow?o3_shadowx:0),sy=(OLshadowPI&&o3_shadow?o3_shadowy:0),
+lm=20+(sx<0?Math.abs(sx):0),rm=20+(sx>0?sx:0),tm=20+(sy<0?Math.abs(sy):0),bm=20+(sy>0?sy:0),
+pWd=o3_width,pHt=(OLns4?over.clip.height:over.offsetHeight),iWd=pWd+lm+rm,iHt=pHt+tm+bm,
+fs=(OLfilterPI&&OLie55&&o3_filter?o3_filtershadow:0),Fn='{return false;}',
+o2=(OLovertwoPI?OLp1or2c+','+OLp1or2co+','+OLp1co+',scroll,function':'');
+t=o3_printxml+o3_printdoctype+o3_printroot+'<head><meta http-equiv="content-Type" content="'
++o3_printtype+'; charset='+o3_printcharset+'" /><title>OLprint Job</title>'
++(o3_printcssfile?'<link rel="stylesheet" type="text/css" href="'+o3_printcssfile+'" />':'')
++'<script type="text/javascript">var OLfnRef="",OLna='+o3_noautoprint+',OLo2="'+o2+'";'
++'function OLprintAndClose(){if(window.print&&!OLna){self.print();setTimeout("self.close()",2);}'
++'else{alert("Print (Control-P) the OLprint Window, then close it.");}}'
++'function OLprint(){if(window.print)self.print();}function cClick(){self.close();}'
++'function nd()'+Fn+'function overlib2()'+Fn+'function nd2()'+Fn+'if(OLo2){'
++'var i,m=OLo2.split(",");for(i=0;i<m.length;i++)eval(m[i].toUpperCase()+"="+0);}</script>'
++'</head><body onLoad="self.focus();OLprintAndClose()">'
++(sx||sy?'<div id="printBackdrop" style="position:absolute;z-index:999;visibility:visible;'
++'width:'+o3_width+(OLns4?';':'px;')+'height:'+pHt+(OLns4?';':'px;')
++(o3_shadowimage?'background-image:url('+o3_shadowimage+');':'background-color:'
++o3_shadowcolor+';')+'left:'+(lm+sx).toString()+(OLns4?';':'px;')+'top:'+(tm+sy).toString()
++(OLns4?';':'px;')+'"></div>':'')
++'<div id="overPrintDiv" style="position:absolute;z-index:1000;visibility:visible;width:'
++o3_width+(OLns4?';':'px;')+(o3_background?'background-image:url('+o3_background+');':'')
++'left:'+lm.toString()+(OLns4?';':'px;')+'top:'+tm.toString()+(OLns4?';':'px;')
++(fs?'filter:progid:DXImageTransform.Microsoft.':'')
++(fs==2?'Shadow(color=\''+o3_filtershadowcolor+'\',direction=135,strength=5);':'')
++(fs==1?'Dropshadow(color=\''+o3_filtershadowcolor+'\');':'')+'">'+over.print
++'</div></body></html>';
+OLprJob=window.open('','OLprintJob','resizable=0,width='+iWd+',height='+iHt
++',status=0,location=0,toolbar=0,menubar=0,scrolling=0,screenX=0,left=0,screenY=0,top=0');
+OLprJob.document.write(t);OLprJob.document.close();if(OLie55&&event&&event.type=='click')
+event.returnValue=false;return false;
+}
+
+OLregRunTimeFunc(OLloadPrint);
+OLregCmdLineFunc(OLparsePrint);
+
+OLprintPI=1;
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws_regCore.js b/OpenFreezer/overlib/overlibmws_regCore.js
new file mode 100755
index 0000000..e97bfaa
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_regCore.js
@@ -0,0 +1,75 @@
+/*
+ overlibmws_regCore.js plug-in module - Copyright Foteos Macrides 2003-2010. All rights reserved.
+   Import this file to declare the core command constants in frame documents which do not
+   import the core module, overlibmws.js, but point to the overlib() and nd() commands in
+   another document of the frameset, e.g. parent.scene.overlib(...) and parent.scene.nd()
+   in a frame document named "scene" which does import the core module.  You can then use
+   this file's OLregisterPlugins() function via a script block to declare pre-existing
+   plugin modules, or it's OLregisterCommands() function for new plugins whose
+   commands are not yet defined as string variables in this file.  The order of
+   entries in those functions should parallel the order of importing the plugins.
+ Initial: August 3, 2003 - Last Revised: October 1, 2009
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+var OLloaded=0,OLpmCnt=1,OLpMtr=new Array();
+OLregisterCommands('inarray,caparray,caption,closetext,right,left,center,autostatuscap,padx,'
++'pady,below,above,vcenter,donothing,nofollow,background,offsetx,offsety,fgcolor,bgcolor,'
++'cgcolor,textcolor,capcolor,width,wrap,wrapmax,height,border,base,status,autostatus,snapx,'
++'snapy,fixx,fixy,relx,rely,midx,midy,ref,refc,refp,refx,refy,fgbackground,bgbackground,'
++'cgbackground,fullhtml,capicon,textfont,captionfont,textsize,captionsize,timeout,delay,hauto,'
++'vauto,nojustx,nojusty,fgclass,bgclass,cgclass,capbelow,textpadding,textfontclass,'
++'captionpadding,captionfontclass,sticky,noclose,mouseoff,offdelay,closecolor,closefont,'
++'closesize,closeclick,closetitle,closefontclass,decode,label');
+
+var CSSOFF=DONOTHING,CSSCLASS=DONOTHING;
+var OLpluginBUBBLE='bubble,bubbletype,adjbubble,rcbubblecolor,bubbleclose';
+var OLpluginCROSSFRAME='frame';
+var OLpluginDEBUG='allowdebug';
+var OLpluginDRAGGABLE='draggable,dragcap,dragid';
+var OLpluginEXCLUSIVE='exclusive,exclusivestatus,exclusiveoverride';
+var OLpluginFILTER='filter,fadein,fadeout,fadetime,filteropacity,filtershadow,filtershadowcolor';
+var OLpluginFUNCTION='function';
+var OLpluginHIDE='hideselectboxes,hidebyid,hidebyidall,hidebyidns4';
+var OLpluginMODAL='modal,modalcolor,modalopacity,modalscroll';
+var OLpluginOVERTWO='label2';
+var OLpluginPRINT='print,printbutton,noautoprint,printcolor,printfont,printsize,printtext,'
++'printbuttontext,printtitle,printfontclass,printcssfile,printxml,printdoctype,printroot,'
++'printtype,printcharset,printurl,printjob';
+var OLpluginSCROLL='scroll';
+var OLpluginSHADOW='shadow,shadowx,shadowy,shadowcolor,shadowimage,shadowopacity';
+
+// PUBLIC FUNCTIONS
+function OLregisterCommands(cmdStr){
+if(typeof cmdStr!='string')return;
+var pM=cmdStr.split(',');
+OLpMtr=OLpMtr.concat(pM);
+for(var i=0;i<pM.length;i++)
+eval(pM[i].toUpperCase()+'='+(OLpmCnt++));
+}
+
+function OLregisterPlugins(){
+var ar=arguments;
+for(var i=0;i<ar.length;i++){
+if(ar[i].toUpperCase()=='BUBBLE'){OLregisterCommands(OLpluginBUBBLE);continue;}
+if(ar[i].toUpperCase()=='CROSSFRAME'){OLregisterCommands(OLpluginCROSSFRAME);continue;}
+if(ar[i].toUpperCase()=='DEBUG'){OLregisterCommands(OLpluginDEBUG);continue;}
+if(ar[i].toUpperCase()=='DRAGGABLE'){OLregisterCommands(OLpluginDRAGGABLE);continue;}
+if(ar[i].toUpperCase()=='EXCLUSIVE'){OLregisterCommands(OLpluginEXCLUSIVE);continue;}
+if(ar[i].toUpperCase()=='FILTER'){OLregisterCommands(OLpluginFILTER);continue;}
+if(ar[i].toUpperCase()=='FUNCTION'){OLregisterCommands(OLpluginFUNCTION);continue;}
+if(ar[i].toUpperCase()=='HIDE'){OLregisterCommands(OLpluginHIDE);continue;}
+if(ar[i].toUpperCase()=='IFRAME')continue;
+if(ar[i].toUpperCase()=='MODAL'){OLregisterCommands(OLpluginMODAL);continue;}
+if(ar[i].toUpperCase()=='OVERTWO'){OLregisterCommands(OLpluginOVERTWO);continue;}
+if(ar[i].toUpperCase()=='PRINT'){OLregisterCommands(OLpluginPRINT);continue;}
+if(ar[i].toUpperCase()=='REGCORE')continue;
+if(ar[i].toUpperCase()=='SCROLL'){OLregisterCommands(OLpluginSCROLL);continue;}
+if(ar[i].toUpperCase()=='SHADOW'){OLregisterCommands(OLpluginSHADOW);continue;}}
+}
+
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws_scroll.js b/OpenFreezer/overlib/overlibmws_scroll.js
new file mode 100755
index 0000000..73bfcf5
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_scroll.js
@@ -0,0 +1,70 @@
+/*
+ overlibmws_scroll.js plug-in module - Copyright Foteos Macrides 2002-2010. All rights reserved.
+  For support of the SCROLL feature.
+  Initial: October 20, 2002 - Last Revised: June 21, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+OLregCmds('scroll');
+
+// DEFAULT CONFIGURATION
+if(OLud('scroll'))var ol_scroll=0;
+// END CONFIGURATION
+
+var o3_scroll=0,OLscrollRefresh=100;
+
+function OLloadScroll(){
+OLload('scroll');
+}
+
+function OLparseScroll(pf,i,ar){
+var k=i;
+if(k<ar.length){if(Math.abs(ar[k])==SCROLL){OLtoggle(ar[k],pf+'scroll');return k;}}
+return -1;
+}
+
+function OLchkScroll(X,Y){
+if(o3_scroll){if(!OLshowingsticky||
+(OLovertwoPI&&over==over2&&!OLshowingsticky2)||
+(OLdraggablePI&&o3_draggable&&o3_frame==self)||
+(o3_relx==null&&o3_midx==null)||(o3_rely==null&&o3_midy==null))o3_scroll=0;
+else if(typeof over.scroll=='undefined'||over.scroll.canScroll)
+over.scroll=new OLsetScroll(X,Y,OLscrollRefresh);}
+}
+
+function OLsetScroll(X,Y,refresh){
+if(o3_scroll){this.canScroll=0;this.refresh=refresh;this.x=X;this.y=Y;
+this.timer=setTimeout("OLscrollReposition()",this.refresh);}
+}
+
+function OLclearScroll(){
+if(o3_scroll){if(typeof over.scroll=='undefined'){o3_scroll=0;return;}
+over.scroll.canScroll=1;if(over.scroll.timer){
+clearTimeout(over.scroll.timer);over.scroll.timer=null;}}
+}
+
+function OLscrollReposition(){
+var o=over,oD=(OLovertwoPI&&over==over2?'overDiv2':'overDiv');
+if(o3_scroll&&o&&o==OLgetRefById(oD)){var X,Y,pgLeft,pgTop;
+pgLeft=(OLie4&&!OLop95)?OLfd().scrollLeft:o3_frame.pageXOffset;
+pgTop=(OLie4&&!OLop95)?OLfd().scrollTop:o3_frame.pageYOffset;
+X=(o.pageX?o.pageX:o.style.left?o.style.left:0)-pgLeft;
+Y=(o.pageY?o.pageY:o.style.top?o.style.top:0)-pgTop;
+if(X!=o.scroll.x||Y!=o.scroll.y){
+OLrepositionTo(o,pgLeft+o.scroll.x,pgTop+o.scroll.y);
+if(OLshadowPI)OLrepositionShadow(pgLeft+o.scroll.x,pgTop+o.scroll.y);
+if(OLiframePI)OLrepositionIfs(pgLeft+o.scroll.x,pgTop+o.scroll.y);
+if(OLhidePI)OLhideUtil(0,1,1,0,0,0);}
+o.scroll.timer=setTimeout("OLscrollReposition()",o.scroll.refresh);}
+}
+
+OLregRunTimeFunc(OLloadScroll);
+OLregCmdLineFunc(OLparseScroll);
+
+OLscrollPI=1;
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmws_shadow.js b/OpenFreezer/overlib/overlibmws_shadow.js
new file mode 100755
index 0000000..e6a8364
--- /dev/null
+++ b/OpenFreezer/overlib/overlibmws_shadow.js
@@ -0,0 +1,113 @@
+/*
+ overlibmws_shadow.js plug-in module - Copyright Foteos Macrides 2003-2010. All rights reserved.
+   For support of the SHADOW feature.
+   Initial: July 14, 2003 - Last Revised: June 21, 2008
+ See the Change History and Command Reference for overlibmws via:
+
+	http://www.macridesweb.com/oltest/
+
+ Published under an open source license: http://www.macridesweb.com/oltest/license.html
+*/
+
+OLloaded=0;
+var OLshadowCmds='shadow,shadowx,shadowy,shadowcolor,shadowimage,shadowopacity';
+OLregCmds(OLshadowCmds);
+
+// DEFAULT CONFIGURATION
+if(OLud('shadow'))var ol_shadow=0;
+if(OLud('shadowx'))var ol_shadowx=5;
+if(OLud('shadowy'))var ol_shadowy=5;
+if(OLud('shadowcolor'))var ol_shadowcolor="#666666";
+if(OLud('shadowimage'))var ol_shadowimage="";
+if(OLud('shadowopacity'))var ol_shadowopacity=60;
+// END CONFIGURATION
+
+var o3_shadow=0,o3_shadowx=5,o3_shadowy=5,o3_shadowcolor="#666666",o3_shadowimage="";
+var o3_shadowopacity=60,bkdrop=null;
+
+function OLloadShadow(){
+OLload(OLshadowCmds);
+}
+
+function OLparseShadow(pf,i,ar){
+var k=i,p=OLpar,q=OLparQuo;
+if(k<ar.length){
+if(Math.abs(ar[k])==SHADOW){OLtoggle(ar[k],pf+'shadow');return k;}
+if(ar[k]==SHADOWX){p(ar[++k],pf+'shadowx');return k;}
+if(ar[k]==SHADOWY){p(ar[++k],pf+'shadowy');return k;}
+if(ar[k]==SHADOWCOLOR){q(ar[++k],pf+'shadowcolor');return k;}
+if(ar[k]==SHADOWIMAGE){q(ar[++k],pf+'shadowimage');return k;}
+if(ar[k]==SHADOWOPACITY){p(ar[++k],pf+'shadowopacity');return k;}}
+return -1;
+}
+
+function OLdispShadow(){
+if(o3_shadow){OLgetShadowLyrRef();if(bkdrop)OLgenerateShadowLyr();}
+}
+
+function OLinitShadow(){
+if(OLie55&&OLfilterPI&&o3_filter){if(o3_shadow){o3_shadow=0;
+if(!o3_filtershadow){o3_filtershadow=2;o3_filtershadowcolor=o3_shadowcolor;}}return;}
+var o;if(!(o=OLmkLyr((OLovertwoPI&&over2&&over==over2?'backdrop2':'backdrop'),
+o3_frame,999))||bkdrop!=o){bkdrop=null;OLgetShadowLyrRef();}
+}
+
+function OLgetShadowLyrRef(){
+if(bkdrop||!o3_shadow)return;
+bkdrop=OLgetRefById((OLovertwoPI&&over2&&over==over2?'backdrop2':'backdrop'));
+if(!bkdrop){o3_shadow=0;bkdrop=null;}
+}
+
+function OLgenerateShadowLyr(){
+var wd=(OLns4?over.clip.width:over.offsetWidth),hgt=(OLns4?over.clip.height:over.offsetHeight);
+if(OLns4){bkdrop.clip.width=wd;bkdrop.clip.height=hgt;
+if(o3_shadowimage)bkdrop.background.src=o3_shadowimage;
+else{bkdrop.bgColor=o3_shadowcolor;bkdrop.zIndex=over.zIndex -1;}
+}else{var o=bkdrop.style;o.width=wd+'px';o.height=hgt+'px';
+if(o3_shadowimage)o.backgroundImage="url("+o3_shadowimage+")";
+else o.backgroundColor=o3_shadowcolor;
+o.clip='rect(0px '+wd+'px '+hgt+'px 0px)';o.zIndex=over.style.zIndex -1;
+if(o3_shadowopacity){var op=o3_shadowopacity;op=(op<=100&&op>0?op:100);
+if(OLie4&&!OLieM&&!OLop95&&typeof o.filter=='string'){
+o.filter='Alpha(opacity='+op+')';if(OLie55&&typeof bkdrop.filters=='object')
+bkdrop.filters.alpha.enabled=1;}else{op=op/100;OLopBk(op);}}}
+}
+
+function OLopBk(op){
+var o=bkdrop.style;
+if(typeof o.opacity!='undefined')o.opacity=op;
+else if(typeof o.MozOpacity!='undefined')o.MozOpacity=op;
+else if(typeof o.KhtmlOpacity!='undefined')o.KhtmlOpacity=op;
+}
+
+function OLcleanUpShadow(){
+if(!bkdrop)return;
+if(OLns4){bkdrop.bgColor=null;bkdrop.background.src=null;}else{
+var o=bkdrop.style;o.backgroundColor='transparent';o.backgroundImage='none';
+if(OLie4&&!OLieM&&typeof o.filter=='string'){
+o.filter='Alpha(opacity=100)';if(OLie55&&typeof bkdrop.filters=='object')
+bkdrop.filters.alpha.enabled=0;}else OLopBk(1.0);
+if(OLns6){o.width=1+'px';o.height=1+'px';
+OLrepositionTo(bkdrop,o3_frame.pageXOffset,o3_frame.pageYOffset);}}
+}
+
+function OLshowShadow(){if(bkdrop&&o3_shadow){var o=(OLns4?bkdrop:bkdrop.style);
+if(!OLns4&&!OLieM&&(OLfilterPI&&o3_filter&&o3_fadein))OLopOvSh(1);o.visibility="visible";}
+}
+
+function OLhideShadow(){
+if(bkdrop&&o3_shadow){var o=OLgetRefById((OLovertwoPI&&over2&&over==over2?
+'backdrop2':'backdrop'));if(o&&o==bkdrop){var os=(OLns4?bkdrop:bkdrop.style);
+if(OLns4||OLieM||!OLfilterPI||((OLfilterPI)&&(!o3_filter||!o3_fadeout||!OLhasOp()))){
+os.visibility="hidden";OLcleanUpShadow();}}}
+}
+
+function OLrepositionShadow(X,Y){
+if(bkdrop&&o3_shadow)OLrepositionTo(bkdrop,X+o3_shadowx,Y+o3_shadowy);
+}
+
+OLregRunTimeFunc(OLloadShadow);
+OLregCmdLineFunc(OLparseShadow);
+
+OLshadowPI=1;
+OLloaded=1;
diff --git a/OpenFreezer/overlib/overlibmwslogo.gif b/OpenFreezer/overlib/overlibmwslogo.gif
new file mode 100755
index 0000000..f7b5508
Binary files /dev/null and b/OpenFreezer/overlib/overlibmwslogo.gif differ
diff --git a/OpenFreezer/overlib/print.gif b/OpenFreezer/overlib/print.gif
new file mode 100755
index 0000000..f1270a2
Binary files /dev/null and b/OpenFreezer/overlib/print.gif differ
diff --git a/OpenFreezer/overlib/pushpin.gif b/OpenFreezer/overlib/pushpin.gif
new file mode 100755
index 0000000..79c0dbd
Binary files /dev/null and b/OpenFreezer/overlib/pushpin.gif differ
diff --git a/OpenFreezer/overlib/quotation.gif b/OpenFreezer/overlib/quotation.gif
new file mode 100755
index 0000000..45a01ed
Binary files /dev/null and b/OpenFreezer/overlib/quotation.gif differ
diff --git a/OpenFreezer/overlib/raised_blue.gif b/OpenFreezer/overlib/raised_blue.gif
new file mode 100755
index 0000000..b54e736
Binary files /dev/null and b/OpenFreezer/overlib/raised_blue.gif differ
diff --git a/OpenFreezer/overlib/raised_metallic.gif b/OpenFreezer/overlib/raised_metallic.gif
new file mode 100755
index 0000000..cb72e4d
Binary files /dev/null and b/OpenFreezer/overlib/raised_metallic.gif differ
diff --git a/OpenFreezer/overlib/semitrans.gif b/OpenFreezer/overlib/semitrans.gif
new file mode 100755
index 0000000..df1bc22
Binary files /dev/null and b/OpenFreezer/overlib/semitrans.gif differ
diff --git a/OpenFreezer/overlib/showCalendar.gif b/OpenFreezer/overlib/showCalendar.gif
new file mode 100755
index 0000000..68d10f1
Binary files /dev/null and b/OpenFreezer/overlib/showCalendar.gif differ
diff --git a/OpenFreezer/overlib/sprintf.js b/OpenFreezer/overlib/sprintf.js
new file mode 100755
index 0000000..f5170ab
--- /dev/null
+++ b/OpenFreezer/overlib/sprintf.js
@@ -0,0 +1,133 @@
+ /* Function printf(format_string,arguments...)
+ * Javascript emulation of the C printf function (modifiers and argument types 
+ *    "p" and "n" are not supported due to language restrictions)
+ *
+ * Copyright 2003 K&L Productions. All rights reserved
+ * http://www.klproductions.com 
+ *
+ * Terms of use: This function can be used free of charge IF this header is not
+ *               modified and remains with the function code.
+ * 
+ * Legal: Use this code at your own risk. K&L Productions assumes NO resposibility
+ *        for anything.
+ ********************************************************************************/
+function sprintf(fstring)
+  { var pad = function(str,ch,len)
+      { var ps='';
+        for(var i=0; i<Math.abs(len); i++) ps+=ch;
+        return len>0?str+ps:ps+str;
+      }
+    var processFlags = function(flags,width,rs,arg)
+      { var pn = function(flags,arg,rs)
+          { if(arg>=0)
+              { if(flags.indexOf(' ')>=0) rs = ' ' + rs;
+                else if(flags.indexOf('+')>=0) rs = '+' + rs;
+              }
+            else
+                rs = '-' + rs;
+            return rs;
+          }
+        var iWidth = parseInt(width,10);
+        if(width.charAt(0) == '0')
+          { var ec=0;
+            if(flags.indexOf(' ')>=0 || flags.indexOf('+')>=0) ec++;
+            if(rs.length<(iWidth-ec)) rs = pad(rs,'0',rs.length-(iWidth-ec));
+            return pn(flags,arg,rs);
+          }
+        rs = pn(flags,arg,rs);
+        if(rs.length<iWidth)
+          { if(flags.indexOf('-')<0) rs = pad(rs,' ',rs.length-iWidth);
+            else rs = pad(rs,' ',iWidth - rs.length);
+          }    
+        return rs;
+      }
+    var converters = new Array();
+    converters['c'] = function(flags,width,precision,arg)
+      { if(typeof(arg) == 'number') return String.fromCharCode(arg);
+        if(typeof(arg) == 'string') return arg.charAt(0);
+        return '';
+      }
+    converters['d'] = function(flags,width,precision,arg)
+      { return converters['i'](flags,width,precision,arg); 
+      }
+    converters['u'] = function(flags,width,precision,arg)
+      { return converters['i'](flags,width,precision,Math.abs(arg)); 
+      }
+    converters['i'] =  function(flags,width,precision,arg)
+      { var iPrecision=parseInt(precision);
+        var rs = ((Math.abs(arg)).toString().split('.'))[0];
+        if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
+        return processFlags(flags,width,rs,arg); 
+      }
+    converters['E'] = function(flags,width,precision,arg) 
+      { return (converters['e'](flags,width,precision,arg)).toUpperCase();
+      }
+    converters['e'] =  function(flags,width,precision,arg)
+      { iPrecision = parseInt(precision);
+        if(isNaN(iPrecision)) iPrecision = 6;
+        rs = (Math.abs(arg)).toExponential(iPrecision);
+        if(rs.indexOf('.')<0 && flags.indexOf('#')>=0) rs = rs.replace(/^(.*)(e.*)$/,'$1.$2');
+        return processFlags(flags,width,rs,arg);        
+      }
+    converters['f'] = function(flags,width,precision,arg)
+      { iPrecision = parseInt(precision);
+        if(isNaN(iPrecision)) iPrecision = 6;
+        rs = (Math.abs(arg)).toFixed(iPrecision);
+        if(rs.indexOf('.')<0 && flags.indexOf('#')>=0) rs = rs + '.';
+        return processFlags(flags,width,rs,arg);
+      }
+    converters['G'] = function(flags,width,precision,arg)
+      { return (converters['g'](flags,width,precision,arg)).toUpperCase();
+      }
+    converters['g'] = function(flags,width,precision,arg)
+      { iPrecision = parseInt(precision);
+        absArg = Math.abs(arg);
+        rse = absArg.toExponential();
+        rsf = absArg.toFixed(6);
+        if(!isNaN(iPrecision))
+          { rsep = absArg.toExponential(iPrecision);
+            rse = rsep.length < rse.length ? rsep : rse;
+            rsfp = absArg.toFixed(iPrecision);
+            rsf = rsfp.length < rsf.length ? rsfp : rsf;
+          }
+        if(rse.indexOf('.')<0 && flags.indexOf('#')>=0) rse = rse.replace(/^(.*)(e.*)$/,'$1.$2');
+        if(rsf.indexOf('.')<0 && flags.indexOf('#')>=0) rsf = rsf + '.';
+        rs = rse.length<rsf.length ? rse : rsf;
+        return processFlags(flags,width,rs,arg);        
+      }  
+    converters['o'] = function(flags,width,precision,arg)
+      { var iPrecision=parseInt(precision);
+        var rs = Math.round(Math.abs(arg)).toString(8);
+        if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
+        if(flags.indexOf('#')>=0) rs='0'+rs;
+        return processFlags(flags,width,rs,arg); 
+      }
+    converters['X'] = function(flags,width,precision,arg)
+      { return (converters['x'](flags,width,precision,arg)).toUpperCase();
+      }
+    converters['x'] = function(flags,width,precision,arg)
+      { var iPrecision=parseInt(precision);
+        arg = Math.abs(arg);
+        var rs = Math.round(arg).toString(16);
+        if(rs.length<iPrecision) rs=pad(rs,' ',iPrecision - rs.length);
+        if(flags.indexOf('#')>=0) rs='0x'+rs;
+        return processFlags(flags,width,rs,arg); 
+      }
+    converters['s'] = function(flags,width,precision,arg)
+      { var iPrecision=parseInt(precision);
+        var rs = arg;
+        if(rs.length > iPrecision) rs = rs.substring(0,iPrecision);
+        return processFlags(flags,width,rs,0);
+      }
+    farr = fstring.split('%');
+    retstr = farr[0];
+    fpRE = /^([-+ #]*)(\d*)\.?(\d*)([cdieEfFgGosuxX])(.*)$/;
+    for(var i=1; i<farr.length; i++)
+      { fps=fpRE.exec(farr[i]);
+        if(!fps) continue;
+        if(arguments[i]!=null) retstr+=converters[fps[4]](fps[1],fps[2],fps[3],arguments[i]);
+        retstr += fps[5];
+      }
+    return retstr;
+  }
+/* Function sprintf() END */  
\ No newline at end of file
diff --git a/OpenFreezer/overlib/square.gif b/OpenFreezer/overlib/square.gif
new file mode 100755
index 0000000..9d43ad7
Binary files /dev/null and b/OpenFreezer/overlib/square.gif differ
diff --git a/OpenFreezer/pictures/1280352360_arrow_collapse.gif b/OpenFreezer/pictures/1280352360_arrow_collapse.gif
new file mode 100755
index 0000000..5152181
Binary files /dev/null and b/OpenFreezer/pictures/1280352360_arrow_collapse.gif differ
diff --git a/OpenFreezer/pictures/1NYK.jpg b/OpenFreezer/pictures/1NYK.jpg
new file mode 100755
index 0000000..8701972
Binary files /dev/null and b/OpenFreezer/pictures/1NYK.jpg differ
diff --git a/OpenFreezer/pictures/1px.gif b/OpenFreezer/pictures/1px.gif
new file mode 100755
index 0000000..c95709f
Binary files /dev/null and b/OpenFreezer/pictures/1px.gif differ
diff --git a/OpenFreezer/pictures/LIM.gif b/OpenFreezer/pictures/LIM.gif
new file mode 100755
index 0000000..eed45f8
Binary files /dev/null and b/OpenFreezer/pictures/LIM.gif differ
diff --git a/OpenFreezer/pictures/Mom.jpg b/OpenFreezer/pictures/Mom.jpg
new file mode 100755
index 0000000..a178e8f
Binary files /dev/null and b/OpenFreezer/pictures/Mom.jpg differ
diff --git a/OpenFreezer/pictures/SH2_domain.gif b/OpenFreezer/pictures/SH2_domain.gif
new file mode 100755
index 0000000..c76294b
Binary files /dev/null and b/OpenFreezer/pictures/SH2_domain.gif differ
diff --git a/OpenFreezer/pictures/V117609_map.svg b/OpenFreezer/pictures/V117609_map.svg
new file mode 100755
index 0000000..0ad126d
--- /dev/null
+++ b/OpenFreezer/pictures/V117609_map.svg
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="1000px" height="1000px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
+<line fill-rule="evenodd" clip-rule="evenodd" fill="#D3D3D3" x1="718.231" y1="281.71" x2="632.231" y2="281.71"/>
+<line fill="none" stroke="#A9A9A9" stroke-width="0.4" stroke-miterlimit="10" x1="745.029" y1="289.016" x2="659.029" y2="289.016"/>
+<rect x="636.231" y="286.11" fill-rule="evenodd" clip-rule="evenodd" fill="#682860" width="10" height="3.2"/>
+<rect x="636.231" y="286.11" fill="none" stroke="#682860" stroke-width="0.4" stroke-miterlimit="10" width="10" height="3.2"/>
+<text transform="matrix(1 0 0 1 647.0313 289.3101)" font-family="'Arial-BoldMT'" font-size="4"> - 5' CLONING SITE</text>
+<rect x="636.231" y="292.11" fill-rule="evenodd" clip-rule="evenodd" fill="#682860" width="10" height="3.2"/>
+<rect x="636.231" y="292.11" fill="none" stroke="#682860" stroke-width="0.4" stroke-miterlimit="10" width="10" height="3.2"/>
+<text transform="matrix(1 0 0 1 647.0313 295.3101)" font-family="'Arial-BoldMT'" font-size="4"> - 3' CLONING SITE</text>
+<rect x="636.231" y="298.11" fill-rule="evenodd" clip-rule="evenodd" fill="#FF00FF" width="10" height="3.2"/>
+<rect x="636.231" y="298.11" fill="none" stroke="#FF00FF" stroke-width="0.4" stroke-miterlimit="10" width="10" height="3.2"/>
+<text transform="matrix(1 0 0 1 647.0313 301.3101)" font-family="'Arial-BoldMT'" font-size="4"> - 5' LINKER</text>
+<rect x="636.231" y="304.11" fill-rule="evenodd" clip-rule="evenodd" fill="#FF00FF" width="10" height="3.2"/>
+<rect x="636.231" y="304.11" fill="none" stroke="#FF00FF" stroke-width="0.4" stroke-miterlimit="10" width="10" height="3.2"/>
+<text transform="matrix(1 0 0 1 647.0313 307.3101)" font-family="'Arial-BoldMT'" font-size="4"> - 3' LINKER</text>
+<rect x="636.231" y="310.11" fill-rule="evenodd" clip-rule="evenodd" fill="#FF0000" width="10" height="3.2"/>
+<rect x="636.231" y="310.11" fill="none" stroke="#FF0000" stroke-width="0.4" stroke-miterlimit="10" width="10" height="3.2"/>
+<text transform="matrix(1 0 0 1 647.0313 313.3101)" font-family="'Arial-BoldMT'" font-size="4"> - CDNA INSERT</text>
+<rect x="636.231" y="316.11" fill-rule="evenodd" clip-rule="evenodd" fill="#FFC0CB" width="10" height="3.2"/>
+<rect x="636.231" y="316.11" fill="none" stroke="#FFC0CB" stroke-width="0.4" stroke-miterlimit="10" width="10" height="3.2"/>
+<text transform="matrix(1 0 0 1 647.0313 319.3101)" font-family="'Arial-BoldMT'" font-size="4"> - CLEAVAGE SITE</text>
+<rect x="636.231" y="322.11" fill-rule="evenodd" clip-rule="evenodd" fill="#66CDAA" width="10" height="3.2"/>
+<rect x="636.231" y="322.11" fill="none" stroke="#66CDAA" stroke-width="0.4" stroke-miterlimit="10" width="10" height="3.2"/>
+<text transform="matrix(1 0 0 1 647.0313 325.3101)" font-family="'Arial-BoldMT'" font-size="4"> - F1</text>
+<rect x="636.231" y="328.11" fill-rule="evenodd" clip-rule="evenodd" fill="#556B2F" width="10" height="3.2"/>
+<rect x="636.231" y="328.11" fill="none" stroke="#556B2F" stroke-width="0.4" stroke-miterlimit="10" width="10" height="3.2"/>
+<text transform="matrix(1 0 0 1 647.0313 331.3101)" font-family="'Arial-BoldMT'" font-size="4"> - F2</text>
+<rect x="636.231" y="334.11" fill-rule="evenodd" clip-rule="evenodd" fill="#F4A460" width="10" height="3.2"/>
+<rect x="636.231" y="334.11" fill="none" stroke="#F4A460" stroke-width="0.4" stroke-miterlimit="10" width="10" height="3.2"/>
+<text transform="matrix(1 0 0 1 647.0313 337.3101)" font-family="'Arial-BoldMT'" font-size="4"> - F3</text>
+<rect x="636.231" y="340.11" fill-rule="evenodd" clip-rule="evenodd" fill="#9932CC" width="10" height="3.2"/>
+<rect x="636.231" y="340.11" fill="none" stroke="#9932CC" stroke-width="0.4" stroke-miterlimit="10" width="10" height="3.2"/>
+<text transform="matrix(1 0 0 1 500.1768 301.3101)" fill="#0000FF" font-family="'Arial-BoldMT'" font-size="12.8">Olfr723</text>
+<text transform="matrix(1 0 0 1 338.2314 317.3101)" fill="#0000FF" font-family="'Arial-BoldMT'" font-size="4">Features shorter than 150 nt:</text>
+<rect x="340.231" y="322.11" fill-rule="evenodd" clip-rule="evenodd" fill="#0000FF" width="6" height="2.4"/>
+<rect x="340.231" y="322.11" fill="none" stroke="#0000FF" stroke-width="0.4" stroke-linejoin="round" stroke-miterlimit="10" width="6" height="2.4"/>
+<text transform="matrix(1 0 0 1 348.2314 324.5098)" font-family="'Arial-BoldMT'" font-size="4">Ampicillin promoter (4070-4166)</text>
+<rect x="340.231" y="328.11" fill-rule="evenodd" clip-rule="evenodd" fill="#0000FF" width="6" height="2.4"/>
+<rect x="340.231" y="328.11" fill="none" stroke="#0000FF" stroke-width="0.4" stroke-linejoin="round" stroke-miterlimit="10" width="6" height="2.4"/>
+<text transform="matrix(1 0 0 1 348.2314 330.5098)" font-family="'Arial-BoldMT'" font-size="4">Ampicillin promoter (2027-2076)</text>
+<rect x="340.231" y="334.11" fill-rule="evenodd" clip-rule="evenodd" fill="#0000FF" width="6" height="2.4"/>
+<rect x="340.231" y="334.11" fill="none" stroke="#0000FF" stroke-width="0.4" stroke-linejoin="round" stroke-miterlimit="10" width="6" height="2.4"/>
+<text transform="matrix(1 0 0 1 348.2314 336.5098)" font-family="'Arial-BoldMT'" font-size="4">T3 promoter (243-262)</text>
+<rect x="340.231" y="340.11" fill-rule="evenodd" clip-rule="evenodd" fill="#0000FF" width="6" height="2.4"/>
+<rect x="340.231" y="340.11" fill="none" stroke="#0000FF" stroke-width="0.4" stroke-linejoin="round" stroke-miterlimit="10" width="6" height="2.4"/>
+<text transform="matrix(1 0 0 1 348.2314 342.5098)" font-family="'Arial-BoldMT'" font-size="4">T7 promoter (1334-1353)</text>
+<rect x="340.231" y="346.11" fill-rule="evenodd" clip-rule="evenodd" fill="#682860" width="6" height="2.4"/>
+<rect x="340.231" y="346.11" fill="none" stroke="#682860" stroke-width="0.4" stroke-linejoin="round" stroke-miterlimit="10" width="6" height="2.4"/>
+<text transform="matrix(1 0 0 1 348.2314 348.5098)" font-family="'Arial-BoldMT'" font-size="4">EcoRI (283-288)</text>
+<rect x="340.231" y="352.11" fill-rule="evenodd" clip-rule="evenodd" fill="#682860" width="6" height="2.4"/>
+<rect x="340.231" y="352.11" fill="none" stroke="#682860" stroke-width="0.4" stroke-linejoin="round" stroke-miterlimit="10" width="6" height="2.4"/>
+<text transform="matrix(1 0 0 1 348.2314 354.5098)" font-family="'Arial-BoldMT'" font-size="4">EcoRI (1307-1312)</text>
+<path fill="none" stroke="#0000FF" stroke-width="0.4" stroke-miterlimit="10" d="M560.632,548.91c0-44.183-35.817-80-80-80
+	c-44.183,0-80,35.817-80,80s35.817,80,80,80C524.814,628.91,560.632,593.093,560.632,548.91"/>
+<polyline fill-rule="evenodd" clip-rule="evenodd" points="480.631,466.11 478.631,463.31 482.631,463.31 480.631,466.11 "/>
+<polyline fill="none" stroke="#000000" stroke-width="0.4" stroke-miterlimit="10" points="480.631,466.11 478.631,463.31 
+	482.631,463.31 480.631,466.11 "/>
+<text transform="matrix(1 0 0 1 478.6313 461.3101)" font-family="'Arial-BoldMT'" font-size="6.4">1</text>
+<text transform="matrix(1 0 0 1 455.0122 534.9102)" fill="#0000FF" font-family="'Arial-BoldMT'" font-size="12.8">V117609</text>
+<text transform="matrix(1 0 0 1 449.3286 544.9102)" fill="#0000FF" font-family="'Arial-BoldMT'" font-size="12.8">nt 1 - 4962</text>
+<path fill="none" stroke="#FF0000" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" d="M509.259,474.207
+	c33.223,12.731,54.045,45.874,51.098,81.331"/>
+<line fill="none" stroke="#000000" stroke-width="0.4" stroke-linejoin="round" stroke-miterlimit="10" x1="509.974" y1="472.34" x2="526.992" y2="460.783"/>
+<text transform="matrix(1 0 0 1 526.9912 460.7827)" fill="#0000FF" font-family="'Arial-BoldMT'" font-size="4.4">cDNA Insert (289-1306)</text>
+<path fill="none" stroke="#FDEE00" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" d="M416.894,597.259
+	c-17.997-23.726-21.327-55.483-8.642-82.426"/>
+<line fill="none" stroke="#000000" stroke-width="0.4" stroke-linejoin="round" stroke-miterlimit="10" x1="415.301" y1="598.468" x2="398.283" y2="610.024"/>
+<text transform="matrix(1 0 0 1 329.0747 610.0244)" fill="#0000FF" font-family="'Arial-BoldMT'" font-size="4.4">Ampicillin resistance (3209-4069)</text>
+<path fill="none" stroke="#FDEE00" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" d="M511.795,622.591
+	c-25.227,10.67-54.158,7.691-76.683-7.893"/>
+<line fill="none" stroke="#000000" stroke-width="0.4" stroke-linejoin="round" stroke-miterlimit="10" x1="512.574" y1="624.433" x2="529.593" y2="635.989"/>
+<text transform="matrix(1 0 0 1 529.5918 635.9902)" fill="#0000FF" font-family="'Arial-BoldMT'" font-size="4.4">Kanamycin resistance (2165-2959)</text>
+<path fill="none" stroke="#C0C0C0" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" d="M413.026,506.136
+	c12.338-19.5,32.495-32.723,55.295-36.273"/>
+<line fill="none" stroke="#000000" stroke-width="0.4" stroke-linejoin="round" stroke-miterlimit="10" x1="411.336" y1="505.067" x2="394.318" y2="493.51"/>
+<text transform="matrix(1 0 0 1 360.0864 493.5098)" fill="#0000FF" font-family="'Arial-BoldMT'" font-size="4.4">pUC (4167-4840)</text>
+<path fill="none" stroke="#0000FF" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" d="M480.834,468.91
+	c7.237,0.019,14.438,1.019,21.407,2.974"/>
+<line fill="none" stroke="#000000" stroke-width="0.4" stroke-linejoin="round" stroke-miterlimit="10" x1="480.839" y1="466.91" x2="497.857" y2="455.353"/>
+<text transform="matrix(1 0 0 1 497.8569 455.3535)" fill="#0000FF" font-family="'Arial-BoldMT'" font-size="4.4">LAC promoter (2-216)</text>
+<path fill="none" stroke="#0000FF" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" d="M408.295,514.741
+	c1.385-2.932,2.947-5.777,4.677-8.52"/>
+<path fill="none" stroke="#0000FF" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" d="M524.13,616.051
+	c-1.389,0.899-2.805,1.756-4.246,2.567"/>
+<path fill="none" stroke="#0000FF" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" d="M504.861,472.667
+	c0.611,0.194,1.22,0.396,1.827,0.605"/>
+<path fill="none" stroke="#0000FF" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" d="M560.071,558.359
+	c-0.076,0.638-0.159,1.273-0.25,1.908"/>
+<path fill="none" stroke="#682860" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" d="M508.69,473.992
+	c0.157,0.059,0.315,0.119,0.474,0.179"/>
+<path fill="none" stroke="#682860" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" d="M560.348,555.639
+	c-0.014,0.168-0.028,0.336-0.044,0.505"/>
+</svg>
diff --git a/OpenFreezer/pictures/WS_FTP.LOG b/OpenFreezer/pictures/WS_FTP.LOG
new file mode 100755
index 0000000..8121ffb
--- /dev/null
+++ b/OpenFreezer/pictures/WS_FTP.LOG
@@ -0,0 +1,22 @@
+105.04.28 07:52 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\clone.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images clone.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\del.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images del.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\excel.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images excel.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\help.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images help.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\minus.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images minus.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\null.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images null.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\plus.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images plus.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\save.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images save.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\save_blue.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images save_blue.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\selcolor.htm --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images selcolor.htm
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\sort_blue_down.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images sort_blue_down.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\sort_blue_left.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images sort_blue_left.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\sort_blue_right.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images sort_blue_right.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\sort_blue_up.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images sort_blue_up.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\sort_down.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images sort_down.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\sort_left.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images sort_left.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\sort_red_down.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images sort_red_down.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\sort_red_up.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images sort_red_up.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\sort_right.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images sort_right.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\sort_up.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images sort_up.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\spotfire.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images spotfire.gif
+105.04.28 07:53 B C:\DOCS\MDSP\ARGUS\Code\2003-08-14\argus_htdocs\images\table_corner.gif --> 192.168.1.109 /BackUpNotebook2/Other/ARGUS/Code/2003-08-14/argus_htdocs/images table_corner.gif
diff --git a/OpenFreezer/pictures/a1.png b/OpenFreezer/pictures/a1.png
new file mode 100755
index 0000000..25e8658
Binary files /dev/null and b/OpenFreezer/pictures/a1.png differ
diff --git a/OpenFreezer/pictures/a2.png b/OpenFreezer/pictures/a2.png
new file mode 100755
index 0000000..2d365e2
Binary files /dev/null and b/OpenFreezer/pictures/a2.png differ
diff --git a/OpenFreezer/pictures/about_hover.png b/OpenFreezer/pictures/about_hover.png
new file mode 100755
index 0000000..e490e46
Binary files /dev/null and b/OpenFreezer/pictures/about_hover.png differ
diff --git a/OpenFreezer/pictures/add_reagent_screenshot.png b/OpenFreezer/pictures/add_reagent_screenshot.png
new file mode 100755
index 0000000..b04f5e6
Binary files /dev/null and b/OpenFreezer/pictures/add_reagent_screenshot.png differ
diff --git a/OpenFreezer/pictures/allgold.png b/OpenFreezer/pictures/allgold.png
new file mode 100755
index 0000000..b744fc7
Binary files /dev/null and b/OpenFreezer/pictures/allgold.png differ
diff --git a/OpenFreezer/pictures/arrow-menu.png b/OpenFreezer/pictures/arrow-menu.png
new file mode 100755
index 0000000..c11b05d
Binary files /dev/null and b/OpenFreezer/pictures/arrow-menu.png differ
diff --git a/OpenFreezer/pictures/arrow-right.png b/OpenFreezer/pictures/arrow-right.png
new file mode 100755
index 0000000..b930726
Binary files /dev/null and b/OpenFreezer/pictures/arrow-right.png differ
diff --git a/OpenFreezer/pictures/arrow.png b/OpenFreezer/pictures/arrow.png
new file mode 100755
index 0000000..bb499d4
Binary files /dev/null and b/OpenFreezer/pictures/arrow.png differ
diff --git a/OpenFreezer/pictures/arrow2.png b/OpenFreezer/pictures/arrow2.png
new file mode 100755
index 0000000..cd5cde6
Binary files /dev/null and b/OpenFreezer/pictures/arrow2.png differ
diff --git a/OpenFreezer/pictures/arrow3.png b/OpenFreezer/pictures/arrow3.png
new file mode 100755
index 0000000..ce69246
Binary files /dev/null and b/OpenFreezer/pictures/arrow3.png differ
diff --git a/OpenFreezer/pictures/arrow4.png b/OpenFreezer/pictures/arrow4.png
new file mode 100755
index 0000000..d1ac6c3
Binary files /dev/null and b/OpenFreezer/pictures/arrow4.png differ
diff --git a/OpenFreezer/pictures/arrow_collapse.gif b/OpenFreezer/pictures/arrow_collapse.gif
new file mode 100755
index 0000000..5442138
Binary files /dev/null and b/OpenFreezer/pictures/arrow_collapse.gif differ
diff --git a/OpenFreezer/pictures/arrow_expand.gif b/OpenFreezer/pictures/arrow_expand.gif
new file mode 100755
index 0000000..f5a1cb5
Binary files /dev/null and b/OpenFreezer/pictures/arrow_expand.gif differ
diff --git a/OpenFreezer/pictures/arrow_more.png b/OpenFreezer/pictures/arrow_more.png
new file mode 100755
index 0000000..bfcbad5
Binary files /dev/null and b/OpenFreezer/pictures/arrow_more.png differ
diff --git a/OpenFreezer/pictures/back_arrow.png b/OpenFreezer/pictures/back_arrow.png
new file mode 100755
index 0000000..5585973
Binary files /dev/null and b/OpenFreezer/pictures/back_arrow.png differ
diff --git a/OpenFreezer/pictures/background-beige.png b/OpenFreezer/pictures/background-beige.png
new file mode 100755
index 0000000..37f2def
Binary files /dev/null and b/OpenFreezer/pictures/background-beige.png differ
diff --git a/OpenFreezer/pictures/background-gray.png b/OpenFreezer/pictures/background-gray.png
new file mode 100755
index 0000000..1afa906
Binary files /dev/null and b/OpenFreezer/pictures/background-gray.png differ
diff --git a/OpenFreezer/pictures/background-texture.png b/OpenFreezer/pictures/background-texture.png
new file mode 100755
index 0000000..e3e12a2
Binary files /dev/null and b/OpenFreezer/pictures/background-texture.png differ
diff --git a/OpenFreezer/pictures/background.jpg b/OpenFreezer/pictures/background.jpg
new file mode 100755
index 0000000..eb2f0ec
Binary files /dev/null and b/OpenFreezer/pictures/background.jpg differ
diff --git a/OpenFreezer/pictures/background.png b/OpenFreezer/pictures/background.png
new file mode 100755
index 0000000..c2cfc43
Binary files /dev/null and b/OpenFreezer/pictures/background.png differ
diff --git a/OpenFreezer/pictures/bah.png b/OpenFreezer/pictures/bah.png
new file mode 100755
index 0000000..c7862bb
Binary files /dev/null and b/OpenFreezer/pictures/bah.png differ
diff --git a/OpenFreezer/pictures/bg.png b/OpenFreezer/pictures/bg.png
new file mode 100755
index 0000000..87d11eb
Binary files /dev/null and b/OpenFreezer/pictures/bg.png differ
diff --git a/OpenFreezer/pictures/bg2.png b/OpenFreezer/pictures/bg2.png
new file mode 100755
index 0000000..6c40829
Binary files /dev/null and b/OpenFreezer/pictures/bg2.png differ
diff --git a/OpenFreezer/pictures/bg3.png b/OpenFreezer/pictures/bg3.png
new file mode 100755
index 0000000..820fb51
Binary files /dev/null and b/OpenFreezer/pictures/bg3.png differ
diff --git a/OpenFreezer/pictures/bg4.png b/OpenFreezer/pictures/bg4.png
new file mode 100755
index 0000000..43baf24
Binary files /dev/null and b/OpenFreezer/pictures/bg4.png differ
diff --git a/OpenFreezer/pictures/bg5.png b/OpenFreezer/pictures/bg5.png
new file mode 100755
index 0000000..7be020e
Binary files /dev/null and b/OpenFreezer/pictures/bg5.png differ
diff --git a/OpenFreezer/pictures/bg6.png b/OpenFreezer/pictures/bg6.png
new file mode 100755
index 0000000..3cacf93
Binary files /dev/null and b/OpenFreezer/pictures/bg6.png differ
diff --git a/OpenFreezer/pictures/bg7.png b/OpenFreezer/pictures/bg7.png
new file mode 100755
index 0000000..b515147
Binary files /dev/null and b/OpenFreezer/pictures/bg7.png differ
diff --git a/OpenFreezer/pictures/bg8.png b/OpenFreezer/pictures/bg8.png
new file mode 100755
index 0000000..8e145c0
Binary files /dev/null and b/OpenFreezer/pictures/bg8.png differ
diff --git a/OpenFreezer/pictures/bg9.png b/OpenFreezer/pictures/bg9.png
new file mode 100755
index 0000000..1897dda
Binary files /dev/null and b/OpenFreezer/pictures/bg9.png differ
diff --git a/OpenFreezer/pictures/bg_active.png b/OpenFreezer/pictures/bg_active.png
new file mode 100755
index 0000000..25f7e91
Binary files /dev/null and b/OpenFreezer/pictures/bg_active.png differ
diff --git a/OpenFreezer/pictures/bgetst.png b/OpenFreezer/pictures/bgetst.png
new file mode 100755
index 0000000..4a1936d
Binary files /dev/null and b/OpenFreezer/pictures/bgetst.png differ
diff --git a/OpenFreezer/pictures/bgtemp.png b/OpenFreezer/pictures/bgtemp.png
new file mode 100755
index 0000000..8ec448f
Binary files /dev/null and b/OpenFreezer/pictures/bgtemp.png differ
diff --git a/OpenFreezer/pictures/bgtmp.png b/OpenFreezer/pictures/bgtmp.png
new file mode 100755
index 0000000..e61145a
Binary files /dev/null and b/OpenFreezer/pictures/bgtmp.png differ
diff --git a/OpenFreezer/pictures/bigbottomgray.png b/OpenFreezer/pictures/bigbottomgray.png
new file mode 100755
index 0000000..112af23
Binary files /dev/null and b/OpenFreezer/pictures/bigbottomgray.png differ
diff --git a/OpenFreezer/pictures/bigtopgray.png b/OpenFreezer/pictures/bigtopgray.png
new file mode 100755
index 0000000..0d96904
Binary files /dev/null and b/OpenFreezer/pictures/bigtopgray.png differ
diff --git a/OpenFreezer/pictures/bio_bullet.gif b/OpenFreezer/pictures/bio_bullet.gif
new file mode 100755
index 0000000..efc2508
Binary files /dev/null and b/OpenFreezer/pictures/bio_bullet.gif differ
diff --git a/OpenFreezer/pictures/black.png b/OpenFreezer/pictures/black.png
new file mode 100755
index 0000000..af5e569
Binary files /dev/null and b/OpenFreezer/pictures/black.png differ
diff --git a/OpenFreezer/pictures/black1px.gif b/OpenFreezer/pictures/black1px.gif
new file mode 100755
index 0000000..90ec85d
Binary files /dev/null and b/OpenFreezer/pictures/black1px.gif differ
diff --git a/OpenFreezer/pictures/bluelines.png b/OpenFreezer/pictures/bluelines.png
new file mode 100755
index 0000000..faac472
Binary files /dev/null and b/OpenFreezer/pictures/bluelines.png differ
diff --git a/OpenFreezer/pictures/border.jpg b/OpenFreezer/pictures/border.jpg
new file mode 100755
index 0000000..bbb24b8
Binary files /dev/null and b/OpenFreezer/pictures/border.jpg differ
diff --git a/OpenFreezer/pictures/border_down.jpg b/OpenFreezer/pictures/border_down.jpg
new file mode 100755
index 0000000..96e8c36
Binary files /dev/null and b/OpenFreezer/pictures/border_down.jpg differ
diff --git a/OpenFreezer/pictures/bottomdarkgray.png b/OpenFreezer/pictures/bottomdarkgray.png
new file mode 100755
index 0000000..d455093
Binary files /dev/null and b/OpenFreezer/pictures/bottomdarkgray.png differ
diff --git a/OpenFreezer/pictures/bottomshadowframe.png b/OpenFreezer/pictures/bottomshadowframe.png
new file mode 100755
index 0000000..580b75e
Binary files /dev/null and b/OpenFreezer/pictures/bottomshadowframe.png differ
diff --git a/OpenFreezer/pictures/bubble.gif b/OpenFreezer/pictures/bubble.gif
new file mode 100755
index 0000000..53c3ceb
Binary files /dev/null and b/OpenFreezer/pictures/bubble.gif differ
diff --git a/OpenFreezer/pictures/bubble_filler.gif b/OpenFreezer/pictures/bubble_filler.gif
new file mode 100755
index 0000000..49c9a6b
Binary files /dev/null and b/OpenFreezer/pictures/bubble_filler.gif differ
diff --git a/OpenFreezer/pictures/bubble_middle.gif b/OpenFreezer/pictures/bubble_middle.gif
new file mode 100755
index 0000000..2e371e9
Binary files /dev/null and b/OpenFreezer/pictures/bubble_middle.gif differ
diff --git a/OpenFreezer/pictures/bug_hover.png b/OpenFreezer/pictures/bug_hover.png
new file mode 100755
index 0000000..07b47ff
Binary files /dev/null and b/OpenFreezer/pictures/bug_hover.png differ
diff --git a/OpenFreezer/pictures/bullet-menu.png b/OpenFreezer/pictures/bullet-menu.png
new file mode 100755
index 0000000..dbef904
Binary files /dev/null and b/OpenFreezer/pictures/bullet-menu.png differ
diff --git a/OpenFreezer/pictures/bullet.gif b/OpenFreezer/pictures/bullet.gif
new file mode 100755
index 0000000..6305bae
Binary files /dev/null and b/OpenFreezer/pictures/bullet.gif differ
diff --git a/OpenFreezer/pictures/bullet.png b/OpenFreezer/pictures/bullet.png
new file mode 100755
index 0000000..c6fb009
Binary files /dev/null and b/OpenFreezer/pictures/bullet.png differ
diff --git a/OpenFreezer/pictures/button.png b/OpenFreezer/pictures/button.png
new file mode 100755
index 0000000..edaf20d
Binary files /dev/null and b/OpenFreezer/pictures/button.png differ
diff --git a/OpenFreezer/pictures/button_bg.png b/OpenFreezer/pictures/button_bg.png
new file mode 100755
index 0000000..9cb3435
Binary files /dev/null and b/OpenFreezer/pictures/button_bg.png differ
diff --git a/OpenFreezer/pictures/button_collapse.png b/OpenFreezer/pictures/button_collapse.png
new file mode 100755
index 0000000..7c1e0b1
Binary files /dev/null and b/OpenFreezer/pictures/button_collapse.png differ
diff --git a/OpenFreezer/pictures/button_collapse2.png b/OpenFreezer/pictures/button_collapse2.png
new file mode 100755
index 0000000..a0b38de
Binary files /dev/null and b/OpenFreezer/pictures/button_collapse2.png differ
diff --git a/OpenFreezer/pictures/button_collapse_blue.png b/OpenFreezer/pictures/button_collapse_blue.png
new file mode 100755
index 0000000..43a2dc2
Binary files /dev/null and b/OpenFreezer/pictures/button_collapse_blue.png differ
diff --git a/OpenFreezer/pictures/button_expand.png b/OpenFreezer/pictures/button_expand.png
new file mode 100755
index 0000000..e9e904b
Binary files /dev/null and b/OpenFreezer/pictures/button_expand.png differ
diff --git a/OpenFreezer/pictures/button_expand2.png b/OpenFreezer/pictures/button_expand2.png
new file mode 100755
index 0000000..101b551
Binary files /dev/null and b/OpenFreezer/pictures/button_expand2.png differ
diff --git a/OpenFreezer/pictures/button_select.gif b/OpenFreezer/pictures/button_select.gif
new file mode 100755
index 0000000..fea394a
Binary files /dev/null and b/OpenFreezer/pictures/button_select.gif differ
diff --git a/OpenFreezer/pictures/buttonbg.png b/OpenFreezer/pictures/buttonbg.png
new file mode 100755
index 0000000..95c5fb0
Binary files /dev/null and b/OpenFreezer/pictures/buttonbg.png differ
diff --git a/OpenFreezer/pictures/buttonsborder.png b/OpenFreezer/pictures/buttonsborder.png
new file mode 100755
index 0000000..a0d872f
Binary files /dev/null and b/OpenFreezer/pictures/buttonsborder.png differ
diff --git a/OpenFreezer/pictures/cell_assoc.gif b/OpenFreezer/pictures/cell_assoc.gif
new file mode 100755
index 0000000..5efac54
Binary files /dev/null and b/OpenFreezer/pictures/cell_assoc.gif differ
diff --git a/OpenFreezer/pictures/cell_assoc.png b/OpenFreezer/pictures/cell_assoc.png
new file mode 100755
index 0000000..5efac54
Binary files /dev/null and b/OpenFreezer/pictures/cell_assoc.png differ
diff --git a/OpenFreezer/pictures/charcoalframe.png b/OpenFreezer/pictures/charcoalframe.png
new file mode 100755
index 0000000..dc52c46
Binary files /dev/null and b/OpenFreezer/pictures/charcoalframe.png differ
diff --git a/OpenFreezer/pictures/clientserverdiagm.png b/OpenFreezer/pictures/clientserverdiagm.png
new file mode 100755
index 0000000..daa9156
Binary files /dev/null and b/OpenFreezer/pictures/clientserverdiagm.png differ
diff --git a/OpenFreezer/pictures/clone.gif b/OpenFreezer/pictures/clone.gif
new file mode 100755
index 0000000..697cf11
Binary files /dev/null and b/OpenFreezer/pictures/clone.gif differ
diff --git a/OpenFreezer/pictures/collapse.png b/OpenFreezer/pictures/collapse.png
new file mode 100755
index 0000000..e4f8f4e
Binary files /dev/null and b/OpenFreezer/pictures/collapse.png differ
diff --git a/OpenFreezer/pictures/complogo.bmp b/OpenFreezer/pictures/complogo.bmp
new file mode 100755
index 0000000..263c3e7
Binary files /dev/null and b/OpenFreezer/pictures/complogo.bmp differ
diff --git a/OpenFreezer/pictures/complogo2.bmp b/OpenFreezer/pictures/complogo2.bmp
new file mode 100755
index 0000000..21f4624
Binary files /dev/null and b/OpenFreezer/pictures/complogo2.bmp differ
diff --git a/OpenFreezer/pictures/computer.jpg b/OpenFreezer/pictures/computer.jpg
new file mode 100755
index 0000000..623a087
Binary files /dev/null and b/OpenFreezer/pictures/computer.jpg differ
diff --git a/OpenFreezer/pictures/contact_hover.png b/OpenFreezer/pictures/contact_hover.png
new file mode 100755
index 0000000..9ce3d19
Binary files /dev/null and b/OpenFreezer/pictures/contact_hover.png differ
diff --git a/OpenFreezer/pictures/contrast.gif b/OpenFreezer/pictures/contrast.gif
new file mode 100755
index 0000000..a91f169
Binary files /dev/null and b/OpenFreezer/pictures/contrast.gif differ
diff --git a/OpenFreezer/pictures/copyright_hover.png b/OpenFreezer/pictures/copyright_hover.png
new file mode 100755
index 0000000..f11d88b
Binary files /dev/null and b/OpenFreezer/pictures/copyright_hover.png differ
diff --git a/OpenFreezer/pictures/creambg.png b/OpenFreezer/pictures/creambg.png
new file mode 100755
index 0000000..e871baf
Binary files /dev/null and b/OpenFreezer/pictures/creambg.png differ
diff --git a/OpenFreezer/pictures/creamline.png b/OpenFreezer/pictures/creamline.png
new file mode 100755
index 0000000..e10dcd5
Binary files /dev/null and b/OpenFreezer/pictures/creamline.png differ
diff --git a/OpenFreezer/pictures/cursor_pointer.gif b/OpenFreezer/pictures/cursor_pointer.gif
new file mode 100755
index 0000000..2043603
Binary files /dev/null and b/OpenFreezer/pictures/cursor_pointer.gif differ
diff --git a/OpenFreezer/pictures/darkbottomgray.png b/OpenFreezer/pictures/darkbottomgray.png
new file mode 100755
index 0000000..566d0f1
Binary files /dev/null and b/OpenFreezer/pictures/darkbottomgray.png differ
diff --git a/OpenFreezer/pictures/darkgrayline.png b/OpenFreezer/pictures/darkgrayline.png
new file mode 100755
index 0000000..11a603b
Binary files /dev/null and b/OpenFreezer/pictures/darkgrayline.png differ
diff --git a/OpenFreezer/pictures/dbdiagm.png b/OpenFreezer/pictures/dbdiagm.png
new file mode 100755
index 0000000..d6cf15a
Binary files /dev/null and b/OpenFreezer/pictures/dbdiagm.png differ
diff --git a/OpenFreezer/pictures/dedication.png b/OpenFreezer/pictures/dedication.png
new file mode 100755
index 0000000..d3ca372
Binary files /dev/null and b/OpenFreezer/pictures/dedication.png differ
diff --git a/OpenFreezer/pictures/dedication_hover.png b/OpenFreezer/pictures/dedication_hover.png
new file mode 100755
index 0000000..c16f6a5
Binary files /dev/null and b/OpenFreezer/pictures/dedication_hover.png differ
diff --git a/OpenFreezer/pictures/del.gif b/OpenFreezer/pictures/del.gif
new file mode 100755
index 0000000..8f3c13e
Binary files /dev/null and b/OpenFreezer/pictures/del.gif differ
diff --git a/OpenFreezer/pictures/delete_icon.jpg b/OpenFreezer/pictures/delete_icon.jpg
new file mode 100755
index 0000000..8c74dcf
Binary files /dev/null and b/OpenFreezer/pictures/delete_icon.jpg differ
diff --git a/OpenFreezer/pictures/disk_small.gif b/OpenFreezer/pictures/disk_small.gif
new file mode 100755
index 0000000..be25e08
Binary files /dev/null and b/OpenFreezer/pictures/disk_small.gif differ
diff --git a/OpenFreezer/pictures/divider.gif b/OpenFreezer/pictures/divider.gif
new file mode 100755
index 0000000..a8fc9b6
Binary files /dev/null and b/OpenFreezer/pictures/divider.gif differ
diff --git a/OpenFreezer/pictures/divider.png b/OpenFreezer/pictures/divider.png
new file mode 100755
index 0000000..2e9c16a
Binary files /dev/null and b/OpenFreezer/pictures/divider.png differ
diff --git a/OpenFreezer/pictures/dna.png b/OpenFreezer/pictures/dna.png
new file mode 100755
index 0000000..86700d0
Binary files /dev/null and b/OpenFreezer/pictures/dna.png differ
diff --git a/OpenFreezer/pictures/docs_focus.png b/OpenFreezer/pictures/docs_focus.png
new file mode 100755
index 0000000..4f7999d
Binary files /dev/null and b/OpenFreezer/pictures/docs_focus.png differ
diff --git a/OpenFreezer/pictures/docs_hover.png b/OpenFreezer/pictures/docs_hover.png
new file mode 100755
index 0000000..2fd3b82
Binary files /dev/null and b/OpenFreezer/pictures/docs_hover.png differ
diff --git a/OpenFreezer/pictures/double.png b/OpenFreezer/pictures/double.png
new file mode 100755
index 0000000..9ea6cf8
Binary files /dev/null and b/OpenFreezer/pictures/double.png differ
diff --git a/OpenFreezer/pictures/down_new.png b/OpenFreezer/pictures/down_new.png
new file mode 100755
index 0000000..21c6dc9
Binary files /dev/null and b/OpenFreezer/pictures/down_new.png differ
diff --git a/OpenFreezer/pictures/download.png b/OpenFreezer/pictures/download.png
new file mode 100755
index 0000000..dd4f3db
Binary files /dev/null and b/OpenFreezer/pictures/download.png differ
diff --git a/OpenFreezer/pictures/download_hover.png b/OpenFreezer/pictures/download_hover.png
new file mode 100755
index 0000000..0e876fa
Binary files /dev/null and b/OpenFreezer/pictures/download_hover.png differ
diff --git a/OpenFreezer/pictures/eighty_percent_map.png b/OpenFreezer/pictures/eighty_percent_map.png
new file mode 100755
index 0000000..0e0ab8e
Binary files /dev/null and b/OpenFreezer/pictures/eighty_percent_map.png differ
diff --git a/OpenFreezer/pictures/eighty_percent_search.png b/OpenFreezer/pictures/eighty_percent_search.png
new file mode 100755
index 0000000..295ecb7
Binary files /dev/null and b/OpenFreezer/pictures/eighty_percent_search.png differ
diff --git a/OpenFreezer/pictures/excel.gif b/OpenFreezer/pictures/excel.gif
new file mode 100755
index 0000000..76e9f10
Binary files /dev/null and b/OpenFreezer/pictures/excel.gif differ
diff --git a/OpenFreezer/pictures/expand.png b/OpenFreezer/pictures/expand.png
new file mode 100755
index 0000000..f071a25
Binary files /dev/null and b/OpenFreezer/pictures/expand.png differ
diff --git a/OpenFreezer/pictures/faq_hover.png b/OpenFreezer/pictures/faq_hover.png
new file mode 100755
index 0000000..3a8f194
Binary files /dev/null and b/OpenFreezer/pictures/faq_hover.png differ
diff --git a/OpenFreezer/pictures/fifty_percent_map.png b/OpenFreezer/pictures/fifty_percent_map.png
new file mode 100755
index 0000000..5873ea5
Binary files /dev/null and b/OpenFreezer/pictures/fifty_percent_map.png differ
diff --git a/OpenFreezer/pictures/firefox_logo.gif b/OpenFreezer/pictures/firefox_logo.gif
new file mode 100755
index 0000000..5f365c8
Binary files /dev/null and b/OpenFreezer/pictures/firefox_logo.gif differ
diff --git a/OpenFreezer/pictures/firefox_logo.jpg b/OpenFreezer/pictures/firefox_logo.jpg
new file mode 100755
index 0000000..8e1fe38
Binary files /dev/null and b/OpenFreezer/pictures/firefox_logo.jpg differ
diff --git a/OpenFreezer/pictures/five_after_three.pdf b/OpenFreezer/pictures/five_after_three.pdf
new file mode 100755
index 0000000..051199c
Binary files /dev/null and b/OpenFreezer/pictures/five_after_three.pdf differ
diff --git a/OpenFreezer/pictures/focus_about.png b/OpenFreezer/pictures/focus_about.png
new file mode 100755
index 0000000..b594021
Binary files /dev/null and b/OpenFreezer/pictures/focus_about.png differ
diff --git a/OpenFreezer/pictures/focus_bug.png b/OpenFreezer/pictures/focus_bug.png
new file mode 100755
index 0000000..d7f1117
Binary files /dev/null and b/OpenFreezer/pictures/focus_bug.png differ
diff --git a/OpenFreezer/pictures/focus_color.png b/OpenFreezer/pictures/focus_color.png
new file mode 100755
index 0000000..d5cf20d
Binary files /dev/null and b/OpenFreezer/pictures/focus_color.png differ
diff --git a/OpenFreezer/pictures/focus_contact.png b/OpenFreezer/pictures/focus_contact.png
new file mode 100755
index 0000000..8ca6f12
Binary files /dev/null and b/OpenFreezer/pictures/focus_contact.png differ
diff --git a/OpenFreezer/pictures/focus_dedication.png b/OpenFreezer/pictures/focus_dedication.png
new file mode 100755
index 0000000..b6b0766
Binary files /dev/null and b/OpenFreezer/pictures/focus_dedication.png differ
diff --git a/OpenFreezer/pictures/focus_download.png b/OpenFreezer/pictures/focus_download.png
new file mode 100755
index 0000000..524067b
Binary files /dev/null and b/OpenFreezer/pictures/focus_download.png differ
diff --git a/OpenFreezer/pictures/focus_faq.png b/OpenFreezer/pictures/focus_faq.png
new file mode 100755
index 0000000..23f14e2
Binary files /dev/null and b/OpenFreezer/pictures/focus_faq.png differ
diff --git a/OpenFreezer/pictures/focus_home.png b/OpenFreezer/pictures/focus_home.png
new file mode 100755
index 0000000..a37e854
Binary files /dev/null and b/OpenFreezer/pictures/focus_home.png differ
diff --git a/OpenFreezer/pictures/focus_news.png b/OpenFreezer/pictures/focus_news.png
new file mode 100755
index 0000000..3419e61
Binary files /dev/null and b/OpenFreezer/pictures/focus_news.png differ
diff --git a/OpenFreezer/pictures/frame.png b/OpenFreezer/pictures/frame.png
new file mode 100755
index 0000000..219c216
Binary files /dev/null and b/OpenFreezer/pictures/frame.png differ
diff --git a/OpenFreezer/pictures/framenew.png b/OpenFreezer/pictures/framenew.png
new file mode 100755
index 0000000..509363a
Binary files /dev/null and b/OpenFreezer/pictures/framenew.png differ
diff --git a/OpenFreezer/pictures/framewblackcorners.png b/OpenFreezer/pictures/framewblackcorners.png
new file mode 100755
index 0000000..2c853cb
Binary files /dev/null and b/OpenFreezer/pictures/framewblackcorners.png differ
diff --git a/OpenFreezer/pictures/freezer.jpg b/OpenFreezer/pictures/freezer.jpg
new file mode 100755
index 0000000..2e8667e
Binary files /dev/null and b/OpenFreezer/pictures/freezer.jpg differ
diff --git a/OpenFreezer/pictures/freezer_w_tubes.jpg b/OpenFreezer/pictures/freezer_w_tubes.jpg
new file mode 100755
index 0000000..3e7c43d
Binary files /dev/null and b/OpenFreezer/pictures/freezer_w_tubes.jpg differ
diff --git a/OpenFreezer/pictures/god.png b/OpenFreezer/pictures/god.png
new file mode 100755
index 0000000..e6c65a9
Binary files /dev/null and b/OpenFreezer/pictures/god.png differ
diff --git a/OpenFreezer/pictures/goldbg.png b/OpenFreezer/pictures/goldbg.png
new file mode 100755
index 0000000..af80981
Binary files /dev/null and b/OpenFreezer/pictures/goldbg.png differ
diff --git a/OpenFreezer/pictures/goldlines.png b/OpenFreezer/pictures/goldlines.png
new file mode 100755
index 0000000..be0db27
Binary files /dev/null and b/OpenFreezer/pictures/goldlines.png differ
diff --git a/OpenFreezer/pictures/goodqualitymap.png b/OpenFreezer/pictures/goodqualitymap.png
new file mode 100755
index 0000000..5fc7414
Binary files /dev/null and b/OpenFreezer/pictures/goodqualitymap.png differ
diff --git a/OpenFreezer/pictures/granite.png b/OpenFreezer/pictures/granite.png
new file mode 100755
index 0000000..4b2514b
Binary files /dev/null and b/OpenFreezer/pictures/granite.png differ
diff --git a/OpenFreezer/pictures/granitegray.png b/OpenFreezer/pictures/granitegray.png
new file mode 100755
index 0000000..1ff3879
Binary files /dev/null and b/OpenFreezer/pictures/granitegray.png differ
diff --git a/OpenFreezer/pictures/gray_line.png b/OpenFreezer/pictures/gray_line.png
new file mode 100755
index 0000000..8b664dc
Binary files /dev/null and b/OpenFreezer/pictures/gray_line.png differ
diff --git a/OpenFreezer/pictures/gray_round_top_left.png b/OpenFreezer/pictures/gray_round_top_left.png
new file mode 100755
index 0000000..dca5bfb
Binary files /dev/null and b/OpenFreezer/pictures/gray_round_top_left.png differ
diff --git a/OpenFreezer/pictures/graybevelbottom.png b/OpenFreezer/pictures/graybevelbottom.png
new file mode 100755
index 0000000..960dce2
Binary files /dev/null and b/OpenFreezer/pictures/graybevelbottom.png differ
diff --git a/OpenFreezer/pictures/graybevelframe.png b/OpenFreezer/pictures/graybevelframe.png
new file mode 100755
index 0000000..48c112f
Binary files /dev/null and b/OpenFreezer/pictures/graybevelframe.png differ
diff --git a/OpenFreezer/pictures/graybevelupsidedown.png b/OpenFreezer/pictures/graybevelupsidedown.png
new file mode 100755
index 0000000..77c38a6
Binary files /dev/null and b/OpenFreezer/pictures/graybevelupsidedown.png differ
diff --git a/OpenFreezer/pictures/graybg.png b/OpenFreezer/pictures/graybg.png
new file mode 100755
index 0000000..62c0a91
Binary files /dev/null and b/OpenFreezer/pictures/graybg.png differ
diff --git a/OpenFreezer/pictures/graybg2.png b/OpenFreezer/pictures/graybg2.png
new file mode 100755
index 0000000..0104e69
Binary files /dev/null and b/OpenFreezer/pictures/graybg2.png differ
diff --git a/OpenFreezer/pictures/graybottom.png b/OpenFreezer/pictures/graybottom.png
new file mode 100755
index 0000000..785a209
Binary files /dev/null and b/OpenFreezer/pictures/graybottom.png differ
diff --git a/OpenFreezer/pictures/graybottomshadowframe.png b/OpenFreezer/pictures/graybottomshadowframe.png
new file mode 100755
index 0000000..56a8d13
Binary files /dev/null and b/OpenFreezer/pictures/graybottomshadowframe.png differ
diff --git a/OpenFreezer/pictures/grayline.png b/OpenFreezer/pictures/grayline.png
new file mode 100755
index 0000000..154072a
Binary files /dev/null and b/OpenFreezer/pictures/grayline.png differ
diff --git a/OpenFreezer/pictures/graylines.png b/OpenFreezer/pictures/graylines.png
new file mode 100755
index 0000000..cf8b994
Binary files /dev/null and b/OpenFreezer/pictures/graylines.png differ
diff --git a/OpenFreezer/pictures/graylinewoutline.png b/OpenFreezer/pictures/graylinewoutline.png
new file mode 100755
index 0000000..ca0e669
Binary files /dev/null and b/OpenFreezer/pictures/graylinewoutline.png differ
diff --git a/OpenFreezer/pictures/grayroundcorners.png b/OpenFreezer/pictures/grayroundcorners.png
new file mode 100755
index 0000000..bb63c0f
Binary files /dev/null and b/OpenFreezer/pictures/grayroundcorners.png differ
diff --git a/OpenFreezer/pictures/graytop.png b/OpenFreezer/pictures/graytop.png
new file mode 100755
index 0000000..221223f
Binary files /dev/null and b/OpenFreezer/pictures/graytop.png differ
diff --git a/OpenFreezer/pictures/graytopshadowframe.png b/OpenFreezer/pictures/graytopshadowframe.png
new file mode 100755
index 0000000..0e0983c
Binary files /dev/null and b/OpenFreezer/pictures/graytopshadowframe.png differ
diff --git a/OpenFreezer/pictures/graywborder.png b/OpenFreezer/pictures/graywborder.png
new file mode 100755
index 0000000..4b89d1e
Binary files /dev/null and b/OpenFreezer/pictures/graywborder.png differ
diff --git a/OpenFreezer/pictures/grb2.jpg b/OpenFreezer/pictures/grb2.jpg
new file mode 100755
index 0000000..e61bddf
Binary files /dev/null and b/OpenFreezer/pictures/grb2.jpg differ
diff --git a/OpenFreezer/pictures/green_bg.jpg b/OpenFreezer/pictures/green_bg.jpg
new file mode 100755
index 0000000..325a15c
Binary files /dev/null and b/OpenFreezer/pictures/green_bg.jpg differ
diff --git a/OpenFreezer/pictures/hdr.png b/OpenFreezer/pictures/hdr.png
new file mode 100755
index 0000000..34e6806
Binary files /dev/null and b/OpenFreezer/pictures/hdr.png differ
diff --git a/OpenFreezer/pictures/hdr10.png b/OpenFreezer/pictures/hdr10.png
new file mode 100755
index 0000000..00be2ad
Binary files /dev/null and b/OpenFreezer/pictures/hdr10.png differ
diff --git a/OpenFreezer/pictures/hdr11.png b/OpenFreezer/pictures/hdr11.png
new file mode 100755
index 0000000..5b603b5
Binary files /dev/null and b/OpenFreezer/pictures/hdr11.png differ
diff --git a/OpenFreezer/pictures/hdr2.png b/OpenFreezer/pictures/hdr2.png
new file mode 100755
index 0000000..8914f11
Binary files /dev/null and b/OpenFreezer/pictures/hdr2.png differ
diff --git a/OpenFreezer/pictures/hdr3.png b/OpenFreezer/pictures/hdr3.png
new file mode 100755
index 0000000..7d7b004
Binary files /dev/null and b/OpenFreezer/pictures/hdr3.png differ
diff --git a/OpenFreezer/pictures/hdr4.png b/OpenFreezer/pictures/hdr4.png
new file mode 100755
index 0000000..b175b4c
Binary files /dev/null and b/OpenFreezer/pictures/hdr4.png differ
diff --git a/OpenFreezer/pictures/hdr5.png b/OpenFreezer/pictures/hdr5.png
new file mode 100755
index 0000000..b175b4c
Binary files /dev/null and b/OpenFreezer/pictures/hdr5.png differ
diff --git a/OpenFreezer/pictures/hdr6.png b/OpenFreezer/pictures/hdr6.png
new file mode 100755
index 0000000..9301a81
Binary files /dev/null and b/OpenFreezer/pictures/hdr6.png differ
diff --git a/OpenFreezer/pictures/hdr7.png b/OpenFreezer/pictures/hdr7.png
new file mode 100755
index 0000000..3bd0099
Binary files /dev/null and b/OpenFreezer/pictures/hdr7.png differ
diff --git a/OpenFreezer/pictures/hdr8.png b/OpenFreezer/pictures/hdr8.png
new file mode 100755
index 0000000..c224f47
Binary files /dev/null and b/OpenFreezer/pictures/hdr8.png differ
diff --git a/OpenFreezer/pictures/hdr9.png b/OpenFreezer/pictures/hdr9.png
new file mode 100755
index 0000000..b6a6419
Binary files /dev/null and b/OpenFreezer/pictures/hdr9.png differ
diff --git a/OpenFreezer/pictures/hdr_larisa.png b/OpenFreezer/pictures/hdr_larisa.png
new file mode 100755
index 0000000..b1a3c6a
Binary files /dev/null and b/OpenFreezer/pictures/hdr_larisa.png differ
diff --git a/OpenFreezer/pictures/hdr_of.png b/OpenFreezer/pictures/hdr_of.png
new file mode 100755
index 0000000..356837a
Binary files /dev/null and b/OpenFreezer/pictures/hdr_of.png differ
diff --git a/OpenFreezer/pictures/hdr_short.png b/OpenFreezer/pictures/hdr_short.png
new file mode 100755
index 0000000..acee33a
Binary files /dev/null and b/OpenFreezer/pictures/hdr_short.png differ
diff --git a/OpenFreezer/pictures/hdr_tux.png b/OpenFreezer/pictures/hdr_tux.png
new file mode 100755
index 0000000..72042c7
Binary files /dev/null and b/OpenFreezer/pictures/hdr_tux.png differ
diff --git a/OpenFreezer/pictures/header.png b/OpenFreezer/pictures/header.png
new file mode 100755
index 0000000..5ac3469
Binary files /dev/null and b/OpenFreezer/pictures/header.png differ
diff --git a/OpenFreezer/pictures/header5.png b/OpenFreezer/pictures/header5.png
new file mode 100755
index 0000000..0fefa7e
Binary files /dev/null and b/OpenFreezer/pictures/header5.png differ
diff --git a/OpenFreezer/pictures/header_new.png b/OpenFreezer/pictures/header_new.png
new file mode 100755
index 0000000..81a8d84
Binary files /dev/null and b/OpenFreezer/pictures/header_new.png differ
diff --git a/OpenFreezer/pictures/header_trans.jpg b/OpenFreezer/pictures/header_trans.jpg
new file mode 100755
index 0000000..b993fe4
Binary files /dev/null and b/OpenFreezer/pictures/header_trans.jpg differ
diff --git a/OpenFreezer/pictures/heading.png b/OpenFreezer/pictures/heading.png
new file mode 100755
index 0000000..d01e1e4
Binary files /dev/null and b/OpenFreezer/pictures/heading.png differ
diff --git a/OpenFreezer/pictures/heading10.png b/OpenFreezer/pictures/heading10.png
new file mode 100755
index 0000000..e29e3c2
Binary files /dev/null and b/OpenFreezer/pictures/heading10.png differ
diff --git a/OpenFreezer/pictures/heading11.png b/OpenFreezer/pictures/heading11.png
new file mode 100755
index 0000000..ed49991
Binary files /dev/null and b/OpenFreezer/pictures/heading11.png differ
diff --git a/OpenFreezer/pictures/heading12.png b/OpenFreezer/pictures/heading12.png
new file mode 100755
index 0000000..5178fd4
Binary files /dev/null and b/OpenFreezer/pictures/heading12.png differ
diff --git a/OpenFreezer/pictures/heading13.png b/OpenFreezer/pictures/heading13.png
new file mode 100755
index 0000000..cbd5e31
Binary files /dev/null and b/OpenFreezer/pictures/heading13.png differ
diff --git a/OpenFreezer/pictures/heading14.png b/OpenFreezer/pictures/heading14.png
new file mode 100755
index 0000000..3570282
Binary files /dev/null and b/OpenFreezer/pictures/heading14.png differ
diff --git a/OpenFreezer/pictures/heading15.png b/OpenFreezer/pictures/heading15.png
new file mode 100755
index 0000000..74d3320
Binary files /dev/null and b/OpenFreezer/pictures/heading15.png differ
diff --git a/OpenFreezer/pictures/heading2.png b/OpenFreezer/pictures/heading2.png
new file mode 100755
index 0000000..1e94933
Binary files /dev/null and b/OpenFreezer/pictures/heading2.png differ
diff --git a/OpenFreezer/pictures/heading3.png b/OpenFreezer/pictures/heading3.png
new file mode 100755
index 0000000..2a4a0ce
Binary files /dev/null and b/OpenFreezer/pictures/heading3.png differ
diff --git a/OpenFreezer/pictures/heading4.png b/OpenFreezer/pictures/heading4.png
new file mode 100755
index 0000000..38853a5
Binary files /dev/null and b/OpenFreezer/pictures/heading4.png differ
diff --git a/OpenFreezer/pictures/heading5.png b/OpenFreezer/pictures/heading5.png
new file mode 100755
index 0000000..81f6813
Binary files /dev/null and b/OpenFreezer/pictures/heading5.png differ
diff --git a/OpenFreezer/pictures/heading6.png b/OpenFreezer/pictures/heading6.png
new file mode 100755
index 0000000..1c327ed
Binary files /dev/null and b/OpenFreezer/pictures/heading6.png differ
diff --git a/OpenFreezer/pictures/heading7.png b/OpenFreezer/pictures/heading7.png
new file mode 100755
index 0000000..022b497
Binary files /dev/null and b/OpenFreezer/pictures/heading7.png differ
diff --git a/OpenFreezer/pictures/heading8.png b/OpenFreezer/pictures/heading8.png
new file mode 100755
index 0000000..dd039c9
Binary files /dev/null and b/OpenFreezer/pictures/heading8.png differ
diff --git a/OpenFreezer/pictures/heading9.png b/OpenFreezer/pictures/heading9.png
new file mode 100755
index 0000000..c35de68
Binary files /dev/null and b/OpenFreezer/pictures/heading9.png differ
diff --git a/OpenFreezer/pictures/heading_larisa.png b/OpenFreezer/pictures/heading_larisa.png
new file mode 100755
index 0000000..b0e75d1
Binary files /dev/null and b/OpenFreezer/pictures/heading_larisa.png differ
diff --git a/OpenFreezer/pictures/heading_new.png b/OpenFreezer/pictures/heading_new.png
new file mode 100755
index 0000000..fb9cca7
Binary files /dev/null and b/OpenFreezer/pictures/heading_new.png differ
diff --git a/OpenFreezer/pictures/help.gif b/OpenFreezer/pictures/help.gif
new file mode 100755
index 0000000..6846bb7
Binary files /dev/null and b/OpenFreezer/pictures/help.gif differ
diff --git a/OpenFreezer/pictures/help_hover.png b/OpenFreezer/pictures/help_hover.png
new file mode 100755
index 0000000..815edd0
Binary files /dev/null and b/OpenFreezer/pictures/help_hover.png differ
diff --git a/OpenFreezer/pictures/help_orange.gif b/OpenFreezer/pictures/help_orange.gif
new file mode 100755
index 0000000..ebfcfab
Binary files /dev/null and b/OpenFreezer/pictures/help_orange.gif differ
diff --git a/OpenFreezer/pictures/hm4.png b/OpenFreezer/pictures/hm4.png
new file mode 100644
index 0000000..c56cb8b
Binary files /dev/null and b/OpenFreezer/pictures/hm4.png differ
diff --git a/OpenFreezer/pictures/hm6.png b/OpenFreezer/pictures/hm6.png
new file mode 100644
index 0000000..6ac75d6
Binary files /dev/null and b/OpenFreezer/pictures/hm6.png differ
diff --git a/OpenFreezer/pictures/home_hover.png b/OpenFreezer/pictures/home_hover.png
new file mode 100755
index 0000000..607c122
Binary files /dev/null and b/OpenFreezer/pictures/home_hover.png differ
diff --git a/OpenFreezer/pictures/hr.png b/OpenFreezer/pictures/hr.png
new file mode 100755
index 0000000..5f302ec
Binary files /dev/null and b/OpenFreezer/pictures/hr.png differ
diff --git a/OpenFreezer/pictures/icebg.jpg b/OpenFreezer/pictures/icebg.jpg
new file mode 100755
index 0000000..ec68dfb
Binary files /dev/null and b/OpenFreezer/pictures/icebg.jpg differ
diff --git a/OpenFreezer/pictures/images.jpg b/OpenFreezer/pictures/images.jpg
new file mode 100644
index 0000000..c690015
Binary files /dev/null and b/OpenFreezer/pictures/images.jpg differ
diff --git a/OpenFreezer/pictures/insert_example.png b/OpenFreezer/pictures/insert_example.png
new file mode 100755
index 0000000..485f969
Binary files /dev/null and b/OpenFreezer/pictures/insert_example.png differ
diff --git a/OpenFreezer/pictures/just_larisa.png b/OpenFreezer/pictures/just_larisa.png
new file mode 100755
index 0000000..c90a30e
Binary files /dev/null and b/OpenFreezer/pictures/just_larisa.png differ
diff --git a/OpenFreezer/pictures/lab.html b/OpenFreezer/pictures/lab.html
new file mode 100755
index 0000000..0082c9e
--- /dev/null
+++ b/OpenFreezer/pictures/lab.html
@@ -0,0 +1,97 @@
+<FORM name="lab_form" method="POST" action="http://openfreezer.org/TEST//cgi/user_request_handler.py">
+			
+					<!-- pass current user as hidden form field -->
+					<INPUT type="hidden" ID="curr_username_hidden" NAME="curr_username"value="Marina Olhovsky">
+					<TABLE width="775px" cellpadding="5px" cellspacing="5px" class="detailedView_tbl">
+						<TR>
+							<TD colspan="6" class="detailedView_heading" style="padding-left:250px">
+								LABORATORY DETAILS PAGE
+								<INPUT TYPE="submit" style="margin-left:50px;" name="modify_lab" value="Change Lab Info"><INPUT TYPE="submit" style="margin-left:2px;" name="delete_lab" value="Delete Lab" onClick="return verifyDeleteLab()">
+							</TD>
+
+						</TR>
+					
+						<TR>
+							<TD class="projectDetailedViewName">
+								Name:
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								Colwill Lab
+								<INPUT TYPE="hidden" name="labName" value="Colwill Lab">
+
+								<!-- lab ID a hidden value -->
+								<INPUT TYPE="hidden" name="labID" value="8">
+							</TD>
+						</TR>
+
+						<TR>
+							<TD class="projectDetailedViewName">
+								Lab head:
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								Dr. Karen Colwill
+								<INPUT TYPE="hidden" name="labHead" value="Dr. Karen Colwill">
+							</TD>
+						</TR>
+						
+						<TR>
+							<TD class="projectDetailedViewName">
+								Description:
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								Dr. Karen Colwill's Research Laboratory
+								<INPUT TYPE="hidden" name="labDescription" value="Dr. Karen Colwill's Research Laboratory">
+							</TD>
+						</TR>
+
+						<TR>
+							<TD class="projectDetailedViewName">
+								Location:
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								Toronto
+								<INPUT TYPE="hidden" name="address" value="Toronto">
+							</TD>
+						</TR>
+						
+						<TR>
+							<TD class="projectDetailedViewName" style="white-space:nowrap">
+								Default access level:
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								Writer
+								<INPUT TYPE="hidden" name="access" value="Writer">
+							</TD>
+						</TR>
+						
+						<!-- Members -->
+						<TR>
+							<TD class="projectDetailedViewName">
+								Members:
+							</TD>
+							
+							<TD class="detailedView_value" style="width:400px">
+								<UL>
+							
+								</UL>
+							</TD>
+						</TR>
+					</TABLE>
+				</FORM>
+				
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				
\ No newline at end of file
diff --git a/OpenFreezer/pictures/largemapwborder.png b/OpenFreezer/pictures/largemapwborder.png
new file mode 100755
index 0000000..0b25be4
Binary files /dev/null and b/OpenFreezer/pictures/largemapwborder.png differ
diff --git a/OpenFreezer/pictures/larisa.png b/OpenFreezer/pictures/larisa.png
new file mode 100755
index 0000000..1087fe4
Binary files /dev/null and b/OpenFreezer/pictures/larisa.png differ
diff --git a/OpenFreezer/pictures/larisa1.png b/OpenFreezer/pictures/larisa1.png
new file mode 100755
index 0000000..f3f80d7
Binary files /dev/null and b/OpenFreezer/pictures/larisa1.png differ
diff --git a/OpenFreezer/pictures/larisa2.png b/OpenFreezer/pictures/larisa2.png
new file mode 100755
index 0000000..1b1c0a9
Binary files /dev/null and b/OpenFreezer/pictures/larisa2.png differ
diff --git a/OpenFreezer/pictures/larisa3.png b/OpenFreezer/pictures/larisa3.png
new file mode 100755
index 0000000..36dea4d
Binary files /dev/null and b/OpenFreezer/pictures/larisa3.png differ
diff --git a/OpenFreezer/pictures/larisa4.png b/OpenFreezer/pictures/larisa4.png
new file mode 100755
index 0000000..223ce14
Binary files /dev/null and b/OpenFreezer/pictures/larisa4.png differ
diff --git a/OpenFreezer/pictures/larisa_all.png b/OpenFreezer/pictures/larisa_all.png
new file mode 100755
index 0000000..126bfb5
Binary files /dev/null and b/OpenFreezer/pictures/larisa_all.png differ
diff --git a/OpenFreezer/pictures/larisa_alone.png b/OpenFreezer/pictures/larisa_alone.png
new file mode 100755
index 0000000..95b745a
Binary files /dev/null and b/OpenFreezer/pictures/larisa_alone.png differ
diff --git a/OpenFreezer/pictures/larisa_blue.png b/OpenFreezer/pictures/larisa_blue.png
new file mode 100755
index 0000000..7a757f7
Binary files /dev/null and b/OpenFreezer/pictures/larisa_blue.png differ
diff --git a/OpenFreezer/pictures/larisa_final.png b/OpenFreezer/pictures/larisa_final.png
new file mode 100755
index 0000000..5bc27af
Binary files /dev/null and b/OpenFreezer/pictures/larisa_final.png differ
diff --git a/OpenFreezer/pictures/larisa_glow.png b/OpenFreezer/pictures/larisa_glow.png
new file mode 100755
index 0000000..c0dcf1d
Binary files /dev/null and b/OpenFreezer/pictures/larisa_glow.png differ
diff --git a/OpenFreezer/pictures/larisa_glow_caps.png b/OpenFreezer/pictures/larisa_glow_caps.png
new file mode 100755
index 0000000..2f83cce
Binary files /dev/null and b/OpenFreezer/pictures/larisa_glow_caps.png differ
diff --git a/OpenFreezer/pictures/larisa_glow_shadow.png b/OpenFreezer/pictures/larisa_glow_shadow.png
new file mode 100755
index 0000000..b2719a2
Binary files /dev/null and b/OpenFreezer/pictures/larisa_glow_shadow.png differ
diff --git a/OpenFreezer/pictures/larisa_hdr.png b/OpenFreezer/pictures/larisa_hdr.png
new file mode 100755
index 0000000..e0d640a
Binary files /dev/null and b/OpenFreezer/pictures/larisa_hdr.png differ
diff --git a/OpenFreezer/pictures/larisa_hdr2.png b/OpenFreezer/pictures/larisa_hdr2.png
new file mode 100755
index 0000000..4a5994d
Binary files /dev/null and b/OpenFreezer/pictures/larisa_hdr2.png differ
diff --git a/OpenFreezer/pictures/larisa_hdr_&.png b/OpenFreezer/pictures/larisa_hdr_&.png
new file mode 100755
index 0000000..65343e5
Binary files /dev/null and b/OpenFreezer/pictures/larisa_hdr_&.png differ
diff --git a/OpenFreezer/pictures/larisa_new.png b/OpenFreezer/pictures/larisa_new.png
new file mode 100755
index 0000000..705383c
Binary files /dev/null and b/OpenFreezer/pictures/larisa_new.png differ
diff --git a/OpenFreezer/pictures/larisa_plain.png b/OpenFreezer/pictures/larisa_plain.png
new file mode 100755
index 0000000..c2ca89c
Binary files /dev/null and b/OpenFreezer/pictures/larisa_plain.png differ
diff --git a/OpenFreezer/pictures/left.png b/OpenFreezer/pictures/left.png
new file mode 100755
index 0000000..f37e07e
Binary files /dev/null and b/OpenFreezer/pictures/left.png differ
diff --git a/OpenFreezer/pictures/leftinnershadowframe.png b/OpenFreezer/pictures/leftinnershadowframe.png
new file mode 100755
index 0000000..f9785dd
Binary files /dev/null and b/OpenFreezer/pictures/leftinnershadowframe.png differ
diff --git a/OpenFreezer/pictures/less_vertical.gif b/OpenFreezer/pictures/less_vertical.gif
new file mode 100755
index 0000000..ac01bf9
Binary files /dev/null and b/OpenFreezer/pictures/less_vertical.gif differ
diff --git a/OpenFreezer/pictures/license_hover.png b/OpenFreezer/pictures/license_hover.png
new file mode 100755
index 0000000..7d68a49
Binary files /dev/null and b/OpenFreezer/pictures/license_hover.png differ
diff --git a/OpenFreezer/pictures/lin.png b/OpenFreezer/pictures/lin.png
new file mode 100755
index 0000000..efcaf2a
Binary files /dev/null and b/OpenFreezer/pictures/lin.png differ
diff --git a/OpenFreezer/pictures/lin2.png b/OpenFreezer/pictures/lin2.png
new file mode 100755
index 0000000..0fab12d
Binary files /dev/null and b/OpenFreezer/pictures/lin2.png differ
diff --git a/OpenFreezer/pictures/lin_vert.png b/OpenFreezer/pictures/lin_vert.png
new file mode 100755
index 0000000..ba39316
Binary files /dev/null and b/OpenFreezer/pictures/lin_vert.png differ
diff --git a/OpenFreezer/pictures/line.png b/OpenFreezer/pictures/line.png
new file mode 100755
index 0000000..7601d72
Binary files /dev/null and b/OpenFreezer/pictures/line.png differ
diff --git a/OpenFreezer/pictures/line3.png b/OpenFreezer/pictures/line3.png
new file mode 100755
index 0000000..cb9067e
Binary files /dev/null and b/OpenFreezer/pictures/line3.png differ
diff --git a/OpenFreezer/pictures/line4.png b/OpenFreezer/pictures/line4.png
new file mode 100755
index 0000000..a0ba180
Binary files /dev/null and b/OpenFreezer/pictures/line4.png differ
diff --git a/OpenFreezer/pictures/lines.png b/OpenFreezer/pictures/lines.png
new file mode 100755
index 0000000..efbdf0c
Binary files /dev/null and b/OpenFreezer/pictures/lines.png differ
diff --git a/OpenFreezer/pictures/lines2.png b/OpenFreezer/pictures/lines2.png
new file mode 100755
index 0000000..b580004
Binary files /dev/null and b/OpenFreezer/pictures/lines2.png differ
diff --git a/OpenFreezer/pictures/link2.png b/OpenFreezer/pictures/link2.png
new file mode 100755
index 0000000..a53f8cc
Binary files /dev/null and b/OpenFreezer/pictures/link2.png differ
diff --git a/OpenFreezer/pictures/link3.png b/OpenFreezer/pictures/link3.png
new file mode 100755
index 0000000..7f10051
Binary files /dev/null and b/OpenFreezer/pictures/link3.png differ
diff --git a/OpenFreezer/pictures/link4.png b/OpenFreezer/pictures/link4.png
new file mode 100755
index 0000000..789f2c7
Binary files /dev/null and b/OpenFreezer/pictures/link4.png differ
diff --git a/OpenFreezer/pictures/link5.png b/OpenFreezer/pictures/link5.png
new file mode 100755
index 0000000..f366eb1
Binary files /dev/null and b/OpenFreezer/pictures/link5.png differ
diff --git a/OpenFreezer/pictures/link6.png b/OpenFreezer/pictures/link6.png
new file mode 100755
index 0000000..d68ebd6
Binary files /dev/null and b/OpenFreezer/pictures/link6.png differ
diff --git a/OpenFreezer/pictures/link7.png b/OpenFreezer/pictures/link7.png
new file mode 100755
index 0000000..f1c6f58
Binary files /dev/null and b/OpenFreezer/pictures/link7.png differ
diff --git a/OpenFreezer/pictures/link_icon.png b/OpenFreezer/pictures/link_icon.png
new file mode 100755
index 0000000..48c4b12
Binary files /dev/null and b/OpenFreezer/pictures/link_icon.png differ
diff --git a/OpenFreezer/pictures/logo.jpg b/OpenFreezer/pictures/logo.jpg
new file mode 100755
index 0000000..3e7c43d
Binary files /dev/null and b/OpenFreezer/pictures/logo.jpg differ
diff --git a/OpenFreezer/pictures/mainbullet.png b/OpenFreezer/pictures/mainbullet.png
new file mode 100755
index 0000000..3b9b11b
Binary files /dev/null and b/OpenFreezer/pictures/mainbullet.png differ
diff --git a/OpenFreezer/pictures/mainbullet2.png b/OpenFreezer/pictures/mainbullet2.png
new file mode 100755
index 0000000..af491a4
Binary files /dev/null and b/OpenFreezer/pictures/mainbullet2.png differ
diff --git a/OpenFreezer/pictures/map.png b/OpenFreezer/pictures/map.png
new file mode 100755
index 0000000..ae4c984
Binary files /dev/null and b/OpenFreezer/pictures/map.png differ
diff --git a/OpenFreezer/pictures/map2.png b/OpenFreezer/pictures/map2.png
new file mode 100755
index 0000000..a4a48dd
Binary files /dev/null and b/OpenFreezer/pictures/map2.png differ
diff --git a/OpenFreezer/pictures/map3.png b/OpenFreezer/pictures/map3.png
new file mode 100755
index 0000000..392c963
Binary files /dev/null and b/OpenFreezer/pictures/map3.png differ
diff --git a/OpenFreezer/pictures/map4.png b/OpenFreezer/pictures/map4.png
new file mode 100755
index 0000000..18a314d
Binary files /dev/null and b/OpenFreezer/pictures/map4.png differ
diff --git a/OpenFreezer/pictures/map_small.png b/OpenFreezer/pictures/map_small.png
new file mode 100755
index 0000000..87177d6
Binary files /dev/null and b/OpenFreezer/pictures/map_small.png differ
diff --git a/OpenFreezer/pictures/mapcontrast.png b/OpenFreezer/pictures/mapcontrast.png
new file mode 100755
index 0000000..b020ecd
Binary files /dev/null and b/OpenFreezer/pictures/mapcontrast.png differ
diff --git a/OpenFreezer/pictures/mapframe.png b/OpenFreezer/pictures/mapframe.png
new file mode 100755
index 0000000..55cab97
Binary files /dev/null and b/OpenFreezer/pictures/mapframe.png differ
diff --git a/OpenFreezer/pictures/mbio3.jpg b/OpenFreezer/pictures/mbio3.jpg
new file mode 100755
index 0000000..66fb2b4
Binary files /dev/null and b/OpenFreezer/pictures/mbio3.jpg differ
diff --git a/OpenFreezer/pictures/menu_bg.png b/OpenFreezer/pictures/menu_bg.png
new file mode 100755
index 0000000..4def703
Binary files /dev/null and b/OpenFreezer/pictures/menu_bg.png differ
diff --git a/OpenFreezer/pictures/menubg.png b/OpenFreezer/pictures/menubg.png
new file mode 100755
index 0000000..e2cc550
Binary files /dev/null and b/OpenFreezer/pictures/menubg.png differ
diff --git a/OpenFreezer/pictures/minus.gif b/OpenFreezer/pictures/minus.gif
new file mode 100755
index 0000000..54634fd
Binary files /dev/null and b/OpenFreezer/pictures/minus.gif differ
diff --git a/OpenFreezer/pictures/minus.png b/OpenFreezer/pictures/minus.png
new file mode 100755
index 0000000..8bc58c6
Binary files /dev/null and b/OpenFreezer/pictures/minus.png differ
diff --git a/OpenFreezer/pictures/mol_bullet.gif b/OpenFreezer/pictures/mol_bullet.gif
new file mode 100755
index 0000000..00ca5bf
Binary files /dev/null and b/OpenFreezer/pictures/mol_bullet.gif differ
diff --git a/OpenFreezer/pictures/more-info.gif b/OpenFreezer/pictures/more-info.gif
new file mode 100755
index 0000000..9362fab
Binary files /dev/null and b/OpenFreezer/pictures/more-info.gif differ
diff --git a/OpenFreezer/pictures/more_vertical.gif b/OpenFreezer/pictures/more_vertical.gif
new file mode 100755
index 0000000..7daff7c
Binary files /dev/null and b/OpenFreezer/pictures/more_vertical.gif differ
diff --git a/OpenFreezer/pictures/new01.gif b/OpenFreezer/pictures/new01.gif
new file mode 100755
index 0000000..fc6f51e
Binary files /dev/null and b/OpenFreezer/pictures/new01.gif differ
diff --git a/OpenFreezer/pictures/new_hdr.png b/OpenFreezer/pictures/new_hdr.png
new file mode 100755
index 0000000..5407abc
Binary files /dev/null and b/OpenFreezer/pictures/new_hdr.png differ
diff --git a/OpenFreezer/pictures/new_header.png b/OpenFreezer/pictures/new_header.png
new file mode 100755
index 0000000..6ba3363
Binary files /dev/null and b/OpenFreezer/pictures/new_header.png differ
diff --git a/OpenFreezer/pictures/newframe.png b/OpenFreezer/pictures/newframe.png
new file mode 100755
index 0000000..0846e61
Binary files /dev/null and b/OpenFreezer/pictures/newframe.png differ
diff --git a/OpenFreezer/pictures/newmap.jpg b/OpenFreezer/pictures/newmap.jpg
new file mode 100755
index 0000000..e978451
Binary files /dev/null and b/OpenFreezer/pictures/newmap.jpg differ
diff --git a/OpenFreezer/pictures/newmap.png b/OpenFreezer/pictures/newmap.png
new file mode 100755
index 0000000..15cf776
Binary files /dev/null and b/OpenFreezer/pictures/newmap.png differ
diff --git a/OpenFreezer/pictures/newof.png b/OpenFreezer/pictures/newof.png
new file mode 100755
index 0000000..03bfde4
Binary files /dev/null and b/OpenFreezer/pictures/newof.png differ
diff --git a/OpenFreezer/pictures/news_hover.png b/OpenFreezer/pictures/news_hover.png
new file mode 100755
index 0000000..8db36ac
Binary files /dev/null and b/OpenFreezer/pictures/news_hover.png differ
diff --git a/OpenFreezer/pictures/newsearch.png b/OpenFreezer/pictures/newsearch.png
new file mode 100755
index 0000000..9111a87
Binary files /dev/null and b/OpenFreezer/pictures/newsearch.png differ
diff --git a/OpenFreezer/pictures/newtitle.png b/OpenFreezer/pictures/newtitle.png
new file mode 100755
index 0000000..7973d67
Binary files /dev/null and b/OpenFreezer/pictures/newtitle.png differ
diff --git a/OpenFreezer/pictures/ninety_percent_map.png b/OpenFreezer/pictures/ninety_percent_map.png
new file mode 100755
index 0000000..59161b2
Binary files /dev/null and b/OpenFreezer/pictures/ninety_percent_map.png differ
diff --git a/OpenFreezer/pictures/nonrecomb_vector.pdf b/OpenFreezer/pictures/nonrecomb_vector.pdf
new file mode 100755
index 0000000..bc3be3c
Binary files /dev/null and b/OpenFreezer/pictures/nonrecomb_vector.pdf differ
diff --git a/OpenFreezer/pictures/null.gif b/OpenFreezer/pictures/null.gif
new file mode 100755
index 0000000..eaf7e65
Binary files /dev/null and b/OpenFreezer/pictures/null.gif differ
diff --git a/OpenFreezer/pictures/objectmodel.png b/OpenFreezer/pictures/objectmodel.png
new file mode 100755
index 0000000..7c3230e
Binary files /dev/null and b/OpenFreezer/pictures/objectmodel.png differ
diff --git a/OpenFreezer/pictures/of_hding.png b/OpenFreezer/pictures/of_hding.png
new file mode 100755
index 0000000..b56b455
Binary files /dev/null and b/OpenFreezer/pictures/of_hding.png differ
diff --git a/OpenFreezer/pictures/of_hding2.png b/OpenFreezer/pictures/of_hding2.png
new file mode 100755
index 0000000..9b11d58
Binary files /dev/null and b/OpenFreezer/pictures/of_hding2.png differ
diff --git a/OpenFreezer/pictures/of_hding3.png b/OpenFreezer/pictures/of_hding3.png
new file mode 100755
index 0000000..bc80798
Binary files /dev/null and b/OpenFreezer/pictures/of_hding3.png differ
diff --git a/OpenFreezer/pictures/of_hding4.png b/OpenFreezer/pictures/of_hding4.png
new file mode 100755
index 0000000..c1e559a
Binary files /dev/null and b/OpenFreezer/pictures/of_hding4.png differ
diff --git a/OpenFreezer/pictures/of_hding5.png b/OpenFreezer/pictures/of_hding5.png
new file mode 100755
index 0000000..1ab9590
Binary files /dev/null and b/OpenFreezer/pictures/of_hding5.png differ
diff --git a/OpenFreezer/pictures/of_hding6.png b/OpenFreezer/pictures/of_hding6.png
new file mode 100755
index 0000000..2a89542
Binary files /dev/null and b/OpenFreezer/pictures/of_hding6.png differ
diff --git a/OpenFreezer/pictures/of_larisa.png b/OpenFreezer/pictures/of_larisa.png
new file mode 100755
index 0000000..dd0a743
Binary files /dev/null and b/OpenFreezer/pictures/of_larisa.png differ
diff --git a/OpenFreezer/pictures/of_lims.PNG b/OpenFreezer/pictures/of_lims.PNG
new file mode 100755
index 0000000..fb0b71b
Binary files /dev/null and b/OpenFreezer/pictures/of_lims.PNG differ
diff --git a/OpenFreezer/pictures/of_logo.png b/OpenFreezer/pictures/of_logo.png
new file mode 100755
index 0000000..5cb540c
Binary files /dev/null and b/OpenFreezer/pictures/of_logo.png differ
diff --git a/OpenFreezer/pictures/of_trans.jpg b/OpenFreezer/pictures/of_trans.jpg
new file mode 100755
index 0000000..cf94de8
Binary files /dev/null and b/OpenFreezer/pictures/of_trans.jpg differ
diff --git a/OpenFreezer/pictures/offinal.png b/OpenFreezer/pictures/offinal.png
new file mode 100755
index 0000000..5a36ffa
Binary files /dev/null and b/OpenFreezer/pictures/offinal.png differ
diff --git a/OpenFreezer/pictures/ofhdr.png b/OpenFreezer/pictures/ofhdr.png
new file mode 100755
index 0000000..28c2d52
Binary files /dev/null and b/OpenFreezer/pictures/ofhdr.png differ
diff --git a/OpenFreezer/pictures/ofnew.png b/OpenFreezer/pictures/ofnew.png
new file mode 100755
index 0000000..5489176
Binary files /dev/null and b/OpenFreezer/pictures/ofnew.png differ
diff --git a/OpenFreezer/pictures/ofsingle.png b/OpenFreezer/pictures/ofsingle.png
new file mode 100755
index 0000000..497ce5d
Binary files /dev/null and b/OpenFreezer/pictures/ofsingle.png differ
diff --git a/OpenFreezer/pictures/oftitlefinal.png b/OpenFreezer/pictures/oftitlefinal.png
new file mode 100755
index 0000000..7167ae3
Binary files /dev/null and b/OpenFreezer/pictures/oftitlefinal.png differ
diff --git a/OpenFreezer/pictures/ok.png b/OpenFreezer/pictures/ok.png
new file mode 100755
index 0000000..8d4bdc6
Binary files /dev/null and b/OpenFreezer/pictures/ok.png differ
diff --git a/OpenFreezer/pictures/ok2.png b/OpenFreezer/pictures/ok2.png
new file mode 100755
index 0000000..7354a81
Binary files /dev/null and b/OpenFreezer/pictures/ok2.png differ
diff --git a/OpenFreezer/pictures/ok3.png b/OpenFreezer/pictures/ok3.png
new file mode 100755
index 0000000..c35ed85
Binary files /dev/null and b/OpenFreezer/pictures/ok3.png differ
diff --git a/OpenFreezer/pictures/openfreezer.jpg b/OpenFreezer/pictures/openfreezer.jpg
new file mode 100755
index 0000000..5fc9bc0
Binary files /dev/null and b/OpenFreezer/pictures/openfreezer.jpg differ
diff --git a/OpenFreezer/pictures/openfreezer.png b/OpenFreezer/pictures/openfreezer.png
new file mode 100755
index 0000000..e0433b2
Binary files /dev/null and b/OpenFreezer/pictures/openfreezer.png differ
diff --git a/OpenFreezer/pictures/page_bg.gif b/OpenFreezer/pictures/page_bg.gif
new file mode 100755
index 0000000..eee9a59
Binary files /dev/null and b/OpenFreezer/pictures/page_bg.gif differ
diff --git a/OpenFreezer/pictures/page_bg_temp.gif b/OpenFreezer/pictures/page_bg_temp.gif
new file mode 100755
index 0000000..91f81f7
Binary files /dev/null and b/OpenFreezer/pictures/page_bg_temp.gif differ
diff --git a/OpenFreezer/pictures/page_bg_temp.jpg b/OpenFreezer/pictures/page_bg_temp.jpg
new file mode 100755
index 0000000..8e41344
Binary files /dev/null and b/OpenFreezer/pictures/page_bg_temp.jpg differ
diff --git a/OpenFreezer/pictures/parchment.png b/OpenFreezer/pictures/parchment.png
new file mode 100755
index 0000000..64ba10a
Binary files /dev/null and b/OpenFreezer/pictures/parchment.png differ
diff --git a/OpenFreezer/pictures/penguin_alone.gif b/OpenFreezer/pictures/penguin_alone.gif
new file mode 100755
index 0000000..b778498
Binary files /dev/null and b/OpenFreezer/pictures/penguin_alone.gif differ
diff --git a/OpenFreezer/pictures/penguin_transparent.gif b/OpenFreezer/pictures/penguin_transparent.gif
new file mode 100755
index 0000000..3325a0a
Binary files /dev/null and b/OpenFreezer/pictures/penguin_transparent.gif differ
diff --git a/OpenFreezer/pictures/ph_sci-microscope.jpg b/OpenFreezer/pictures/ph_sci-microscope.jpg
new file mode 100755
index 0000000..9150461
Binary files /dev/null and b/OpenFreezer/pictures/ph_sci-microscope.jpg differ
diff --git a/OpenFreezer/pictures/pinkline.png b/OpenFreezer/pictures/pinkline.png
new file mode 100755
index 0000000..452b644
Binary files /dev/null and b/OpenFreezer/pictures/pinkline.png differ
diff --git a/OpenFreezer/pictures/plus.gif b/OpenFreezer/pictures/plus.gif
new file mode 100755
index 0000000..90ba30d
Binary files /dev/null and b/OpenFreezer/pictures/plus.gif differ
diff --git a/OpenFreezer/pictures/plus.png b/OpenFreezer/pictures/plus.png
new file mode 100755
index 0000000..73e288b
Binary files /dev/null and b/OpenFreezer/pictures/plus.png differ
diff --git a/OpenFreezer/pictures/plus_bullet.gif b/OpenFreezer/pictures/plus_bullet.gif
new file mode 100755
index 0000000..4e97fe6
Binary files /dev/null and b/OpenFreezer/pictures/plus_bullet.gif differ
diff --git a/OpenFreezer/pictures/project.html b/OpenFreezer/pictures/project.html
new file mode 100755
index 0000000..8d2222c
--- /dev/null
+++ b/OpenFreezer/pictures/project.html
@@ -0,0 +1,110 @@
+<FORM name="project_form" method="POST" action="http://openfreezer.org/TEST//cgi/project_request_handler.py">
+			
+					<!-- pass current user as hidden form field -->
+					<INPUT type="hidden" ID="username_hidden" NAME="username"value="Marina Olhovsky">
+					<TABLE width="775px" cellpadding="5px" cellspacing="5px" class="detailedView_tbl">
+						<TR>
+							<TD colspan="6" class="detailedView_heading" style="padding-left:250px">
+								PROJECT DETAILS PAGE
+								<INPUT TYPE="submit" style="margin-left:60px;" name="modify_project" value="Modify Project"><INPUT TYPE="submit" style="margin-left:2px;" name="delete_project" value="Delete Project" onSubmit="return confirmDeleteProject();">
+							</TD>
+
+						</TR>
+
+						<TR>
+							<TD class="projectDetailedViewName">
+								Project #
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								31
+								
+								<INPUT TYPE="hidden" name="packetID" value="31">
+							</TD>
+
+						</TR>
+
+						<TR>
+							<TD class="projectDetailedViewName">
+								Project Owner:
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								Marina Olhovsky
+								<INPUT TYPE="hidden" name="packetOwner" value="4">
+							</TD>
+						</TR>
+
+						<TR>
+							<TD class="projectDetailedViewName">
+								Project Name:
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								fsadf
+								<INPUT TYPE="hidden" name="packetName" value="fsadf">
+							</TD>
+						</TR>
+
+						<TR>
+							<TD class="projectDetailedViewName">
+								Project Description:
+							</TD>
+
+							<TD class="detailedView_value" style="width:400px">
+								
+								<INPUT TYPE="hidden" name="packetDescription" value="">
+							</TD>
+						</TR>
+						
+						<TR>
+							<TD colspan="6">
+								<HR/>
+							</TD>
+						</TR>
+
+
+						<TR>
+							<TD class="projectDetailedViewName">
+								Project Members:
+							</TD>
+						</TR>
+						
+						<TR>
+							<TD class="detailedView_value" colspan="6">
+								<TABLE>
+									<TR>
+										<TD style="font-weight:bold; padding-left:10px">
+											Readers:
+										</TD>
+
+										<TD style="font-weight:bold; padding-left:10px">
+											Writers:
+										</TD>
+									</TR>
+																		
+									<TR>
+										<TD class="detailedView_value" style="width:250px; vertical-align:top">
+															</TD>
+
+
+										<TD class="detailedView_value" style="width:250px; vertical-align:top">
+											
+										</TD>
+									</TR>
+								</TABLE>
+							</TD>	
+						</TR>
+					</TABLE>
+				</FORM>
+				
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				<blockquote> </blockquote>
+				
\ No newline at end of file
diff --git a/OpenFreezer/pictures/proteins_transparent.gif b/OpenFreezer/pictures/proteins_transparent.gif
new file mode 100755
index 0000000..3523792
Binary files /dev/null and b/OpenFreezer/pictures/proteins_transparent.gif differ
diff --git a/OpenFreezer/pictures/q3.png b/OpenFreezer/pictures/q3.png
new file mode 100755
index 0000000..1464609
Binary files /dev/null and b/OpenFreezer/pictures/q3.png differ
diff --git a/OpenFreezer/pictures/ratti.lg.jpg b/OpenFreezer/pictures/ratti.lg.jpg
new file mode 100755
index 0000000..71d88f2
Binary files /dev/null and b/OpenFreezer/pictures/ratti.lg.jpg differ
diff --git a/OpenFreezer/pictures/ratti.lg_2.jpg b/OpenFreezer/pictures/ratti.lg_2.jpg
new file mode 100755
index 0000000..44e3d59
Binary files /dev/null and b/OpenFreezer/pictures/ratti.lg_2.jpg differ
diff --git a/OpenFreezer/pictures/read_more.png b/OpenFreezer/pictures/read_more.png
new file mode 100755
index 0000000..f3629ed
Binary files /dev/null and b/OpenFreezer/pictures/read_more.png differ
diff --git a/OpenFreezer/pictures/redtop.png b/OpenFreezer/pictures/redtop.png
new file mode 100755
index 0000000..c37c279
Binary files /dev/null and b/OpenFreezer/pictures/redtop.png differ
diff --git a/OpenFreezer/pictures/redtop2.png b/OpenFreezer/pictures/redtop2.png
new file mode 100755
index 0000000..fc44402
Binary files /dev/null and b/OpenFreezer/pictures/redtop2.png differ
diff --git a/OpenFreezer/pictures/redtop3.png b/OpenFreezer/pictures/redtop3.png
new file mode 100755
index 0000000..37ac28a
Binary files /dev/null and b/OpenFreezer/pictures/redtop3.png differ
diff --git a/OpenFreezer/pictures/researcher.jpg b/OpenFreezer/pictures/researcher.jpg
new file mode 100755
index 0000000..3a2dee9
Binary files /dev/null and b/OpenFreezer/pictures/researcher.jpg differ
diff --git a/OpenFreezer/pictures/right.png b/OpenFreezer/pictures/right.png
new file mode 100755
index 0000000..695717c
Binary files /dev/null and b/OpenFreezer/pictures/right.png differ
diff --git a/OpenFreezer/pictures/roses.gif b/OpenFreezer/pictures/roses.gif
new file mode 100755
index 0000000..9b83d15
Binary files /dev/null and b/OpenFreezer/pictures/roses.gif differ
diff --git a/OpenFreezer/pictures/roses2.gif b/OpenFreezer/pictures/roses2.gif
new file mode 100755
index 0000000..8d10622
Binary files /dev/null and b/OpenFreezer/pictures/roses2.gif differ
diff --git a/OpenFreezer/pictures/round.png b/OpenFreezer/pictures/round.png
new file mode 100755
index 0000000..cb38552
Binary files /dev/null and b/OpenFreezer/pictures/round.png differ
diff --git a/OpenFreezer/pictures/round_bl.png b/OpenFreezer/pictures/round_bl.png
new file mode 100755
index 0000000..44c771f
Binary files /dev/null and b/OpenFreezer/pictures/round_bl.png differ
diff --git a/OpenFreezer/pictures/round_br.png b/OpenFreezer/pictures/round_br.png
new file mode 100755
index 0000000..afca6a5
Binary files /dev/null and b/OpenFreezer/pictures/round_br.png differ
diff --git a/OpenFreezer/pictures/round_tl.png b/OpenFreezer/pictures/round_tl.png
new file mode 100755
index 0000000..666b697
Binary files /dev/null and b/OpenFreezer/pictures/round_tl.png differ
diff --git a/OpenFreezer/pictures/round_tr.png b/OpenFreezer/pictures/round_tr.png
new file mode 100755
index 0000000..b8cd5e6
Binary files /dev/null and b/OpenFreezer/pictures/round_tr.png differ
diff --git a/OpenFreezer/pictures/round_up.png b/OpenFreezer/pictures/round_up.png
new file mode 100755
index 0000000..843cb8d
Binary files /dev/null and b/OpenFreezer/pictures/round_up.png differ
diff --git a/OpenFreezer/pictures/rt.png b/OpenFreezer/pictures/rt.png
new file mode 100755
index 0000000..959b9f2
Binary files /dev/null and b/OpenFreezer/pictures/rt.png differ
diff --git a/OpenFreezer/pictures/rt2.png b/OpenFreezer/pictures/rt2.png
new file mode 100755
index 0000000..1d22612
Binary files /dev/null and b/OpenFreezer/pictures/rt2.png differ
diff --git a/OpenFreezer/pictures/rt3.png b/OpenFreezer/pictures/rt3.png
new file mode 100755
index 0000000..4017533
Binary files /dev/null and b/OpenFreezer/pictures/rt3.png differ
diff --git a/OpenFreezer/pictures/rt4.png b/OpenFreezer/pictures/rt4.png
new file mode 100755
index 0000000..67db22f
Binary files /dev/null and b/OpenFreezer/pictures/rt4.png differ
diff --git a/OpenFreezer/pictures/rt5.png b/OpenFreezer/pictures/rt5.png
new file mode 100755
index 0000000..5536b75
Binary files /dev/null and b/OpenFreezer/pictures/rt5.png differ
diff --git a/OpenFreezer/pictures/rt6.png b/OpenFreezer/pictures/rt6.png
new file mode 100755
index 0000000..0900de2
Binary files /dev/null and b/OpenFreezer/pictures/rt6.png differ
diff --git a/OpenFreezer/pictures/rt7.png b/OpenFreezer/pictures/rt7.png
new file mode 100755
index 0000000..f6f02f0
Binary files /dev/null and b/OpenFreezer/pictures/rt7.png differ
diff --git a/OpenFreezer/pictures/rt8.png b/OpenFreezer/pictures/rt8.png
new file mode 100755
index 0000000..714684c
Binary files /dev/null and b/OpenFreezer/pictures/rt8.png differ
diff --git a/OpenFreezer/pictures/rt9.png b/OpenFreezer/pictures/rt9.png
new file mode 100755
index 0000000..5424c16
Binary files /dev/null and b/OpenFreezer/pictures/rt9.png differ
diff --git a/OpenFreezer/pictures/rtplain.png b/OpenFreezer/pictures/rtplain.png
new file mode 100755
index 0000000..b6b1ddf
Binary files /dev/null and b/OpenFreezer/pictures/rtplain.png differ
diff --git a/OpenFreezer/pictures/save.gif b/OpenFreezer/pictures/save.gif
new file mode 100755
index 0000000..864f220
Binary files /dev/null and b/OpenFreezer/pictures/save.gif differ
diff --git a/OpenFreezer/pictures/save_blue.gif b/OpenFreezer/pictures/save_blue.gif
new file mode 100755
index 0000000..a40ce41
Binary files /dev/null and b/OpenFreezer/pictures/save_blue.gif differ
diff --git a/OpenFreezer/pictures/screenshot.jpg b/OpenFreezer/pictures/screenshot.jpg
new file mode 100755
index 0000000..d8501e0
Binary files /dev/null and b/OpenFreezer/pictures/screenshot.jpg differ
diff --git a/OpenFreezer/pictures/screenshot_w_border.jpg b/OpenFreezer/pictures/screenshot_w_border.jpg
new file mode 100755
index 0000000..94c3b8c
Binary files /dev/null and b/OpenFreezer/pictures/screenshot_w_border.jpg differ
diff --git a/OpenFreezer/pictures/search2.png b/OpenFreezer/pictures/search2.png
new file mode 100755
index 0000000..82d26ab
Binary files /dev/null and b/OpenFreezer/pictures/search2.png differ
diff --git a/OpenFreezer/pictures/search3.png b/OpenFreezer/pictures/search3.png
new file mode 100755
index 0000000..57510e1
Binary files /dev/null and b/OpenFreezer/pictures/search3.png differ
diff --git a/OpenFreezer/pictures/search4.png b/OpenFreezer/pictures/search4.png
new file mode 100755
index 0000000..8c39b70
Binary files /dev/null and b/OpenFreezer/pictures/search4.png differ
diff --git a/OpenFreezer/pictures/search_95.png b/OpenFreezer/pictures/search_95.png
new file mode 100755
index 0000000..ee890b7
Binary files /dev/null and b/OpenFreezer/pictures/search_95.png differ
diff --git a/OpenFreezer/pictures/search_compressed.png b/OpenFreezer/pictures/search_compressed.png
new file mode 100755
index 0000000..ea1e4c8
Binary files /dev/null and b/OpenFreezer/pictures/search_compressed.png differ
diff --git a/OpenFreezer/pictures/search_cropped.png b/OpenFreezer/pictures/search_cropped.png
new file mode 100755
index 0000000..ac34e1e
Binary files /dev/null and b/OpenFreezer/pictures/search_cropped.png differ
diff --git a/OpenFreezer/pictures/search_screen.png b/OpenFreezer/pictures/search_screen.png
new file mode 100755
index 0000000..a10b275
Binary files /dev/null and b/OpenFreezer/pictures/search_screen.png differ
diff --git a/OpenFreezer/pictures/selcolor.htm b/OpenFreezer/pictures/selcolor.htm
new file mode 100755
index 0000000..337f4db
--- /dev/null
+++ b/OpenFreezer/pictures/selcolor.htm
@@ -0,0 +1,203 @@
+<HEAD>
+<STYLE type=text/css>BODY {
+	FONT-SIZE: 12px; BACKGROUND: menu; MARGIN-LEFT: 10px; FONT-FAMILY: Verdana
+}
+BUTTON {
+	WIDTH: 5em
+}
+P {
+	TEXT-ALIGN: center
+}
+TABLE {
+	CURSOR: hand
+}
+</STYLE>
+
+<SCRIPT language=JavaScript event=onclick for=ColorTable>
+<!--
+  SelColor.value = event.srcElement.title;
+// -->
+</SCRIPT>
+
+<SCRIPT language=JavaScript event=onmouseover for=ColorTable>
+<!--
+  text = event.srcElement.title;
+  if ( text != event.srcElement.bgColor )
+    text += " (" + event.srcElement.bgColor + ")";
+  RGB.innerText = text;
+// -->
+</SCRIPT>
+
+<SCRIPT language=JavaScript event=onmouseout for=ColorTable>
+<!--
+  RGB.innerText = " ";
+// -->
+</SCRIPT>
+
+<SCRIPT language=JavaScript event=onclick for=Ok>
+<!--
+  window.returnValue = SelColor.value;
+  window.close();
+// -->
+</SCRIPT>
+</HEAD>
+
+<BODY onload=SelColor.focus()>
+<DIV> </DIV>
+<P>
+<TABLE id=ColorTable borderColor=silver cellSpacing=0 borderColorDark=black 
+cellPadding=0 borderColorLight=white border=1>
+  <TBODY>
+  <TR>
+    <TD title=aliceblue bgColor=aliceblue>    
+    <TD title=antiquewhite bgColor=antiquewhite>    
+    <TD title=aqua bgColor=aqua>    
+    <TD title=aquamarine bgColor=aquamarine>    
+    <TD title=azure bgColor=azure>    
+    <TD title=beige bgColor=beige>    
+    <TD title=bisque bgColor=bisque>    
+    <TD title=black bgColor=black>    
+    <TD title=blanchedalmond bgColor=blanchedalmond>    
+    <TD title=blue bgColor=blue>    
+    <TD title=blueviolet bgColor=blueviolet>    
+    <TD title=brown bgColor=brown>    
+    <TD title=burlywood bgColor=burlywood>    
+    <TD title=cadetblue bgColor=cadetblue>    
+    <TD title=chartreuse bgColor=chartreuse>    
+    <TD title=chocolate bgColor=chocolate>    
+  <TR>
+    <TD title=coral bgColor=coral>   
+    <TD title=cornflower bgColor=#c0f0e0>   
+    <TD title=cornsilk bgColor=cornsilk>   
+    <TD title=crimson bgColor=crimson>   
+    <TD title=cyan bgColor=cyan>   
+    <TD title=darkblue bgColor=darkblue>   
+    <TD title=darkcyan bgColor=darkcyan>   
+    <TD title=darkgoldenrod bgColor=darkgoldenrod>   
+    <TD title=darkgray bgColor=darkgray>   
+    <TD title=darkgreen bgColor=darkgreen>   
+    <TD title=darkkhaki bgColor=darkkhaki>   
+    <TD title=darkmagenta bgColor=darkmagenta>   
+    <TD title=darkolivegreen bgColor=darkolivegreen>   
+    <TD title=darkorange bgColor=darkorange>   
+    <TD title=darkorchid bgColor=darkorchid>   
+    <TD title=darkred bgColor=darkred>   
+  <TR>
+    <TD title=darksalmon bgColor=darksalmon>   
+    <TD title=darkseagreen bgColor=darkseagreen>   
+    <TD title=darkslateblue bgColor=darkslateblue>   
+    <TD title=darkslategray bgColor=darkslategray>   
+    <TD title=darkturquoise bgColor=darkturquoise>   
+    <TD title=darkviolet bgColor=darkviolet>   
+    <TD title=deeppink bgColor=deeppink>   
+    <TD title=deepskyblue bgColor=deepskyblue>   
+    <TD title=dimgray bgColor=dimgray>   
+    <TD title=dodgerblue bgColor=dodgerblue>   
+    <TD title=firebrick bgColor=firebrick>   
+    <TD title=floralwhite bgColor=floralwhite>   
+    <TD title=forestgreen bgColor=forestgreen>   
+    <TD title=fuchia bgColor=#f0c00a>   
+    <TD title=gainsboro bgColor=gainsboro>   
+    <TD title=ghostwhite bgColor=ghostwhite>   
+  <TR>
+    <TD title=gold bgColor=gold>   
+    <TD title=goldenrod bgColor=goldenrod>   
+    <TD title=gray bgColor=gray>   
+    <TD title=green bgColor=green>   
+    <TD title=greenyellow bgColor=greenyellow>   
+    <TD title=honeydew bgColor=honeydew>   
+    <TD title=hotpink bgColor=hotpink>   
+    <TD title=indianred bgColor=indianred>   
+    <TD title=indigo bgColor=indigo>   
+    <TD title=ivory bgColor=ivory>   
+    <TD title=khaki bgColor=khaki>   
+    <TD title=lavender bgColor=lavender>   
+    <TD title=lavenderblush bgColor=lavenderblush>   
+    <TD title=lawngreen bgColor=lawngreen>   
+    <TD title=lemonchiffon bgColor=lemonchiffon>   
+    <TD title=lightblue bgColor=lightblue>   
+  <TR>
+    <TD title=lightcoral bgColor=lightcoral>   
+    <TD title=lightcyan bgColor=lightcyan>   
+    <TD title=lightgoldenrodyellow bgColor=lightgoldenrodyellow>   
+    <TD title=lightgreen bgColor=lightgreen>   
+    <TD title=lightgrey bgColor=lightgrey>   
+    <TD title=lightpink bgColor=lightpink>   
+    <TD title=lightsalmon bgColor=lightsalmon>   
+    <TD title=lightseagreen bgColor=lightseagreen>   
+    <TD title=lightskyblue bgColor=lightskyblue>   
+    <TD title=lightslategray bgColor=lightslategray>   
+    <TD title=lightsteelblue bgColor=lightsteelblue>   
+    <TD title=lightyellow bgColor=lightyellow>   
+    <TD title=lime bgColor=lime>   
+    <TD title=limegreen bgColor=limegreen>   
+    <TD title=linen bgColor=linen>   
+    <TD title=magenta bgColor=magenta>   
+  <TR>
+    <TD title=maroon bgColor=maroon>   
+    <TD title=mediumaquamarine bgColor=mediumaquamarine>   
+    <TD title=mediumblue bgColor=mediumblue>   
+    <TD title=mediumorchid bgColor=mediumorchid>   
+    <TD title=mediumpurple bgColor=mediumpurple>   
+    <TD title=mediumseagreen bgColor=mediumseagreen>   
+    <TD title=mediumslateblue bgColor=mediumslateblue>   
+    <TD title=mediumspringgreen bgColor=mediumspringgreen>   
+    <TD title=mediumturquoise bgColor=mediumturquoise>   
+    <TD title=mediumvioletred bgColor=mediumvioletred>   
+    <TD title=midnightblue bgColor=midnightblue>   
+    <TD title=mintcream bgColor=mintcream>   
+    <TD title=mistyrose bgColor=mistyrose>   
+    <TD title=moccasin bgColor=moccasin>   
+    <TD title=navajowhite bgColor=navajowhite>   
+    <TD title=navy bgColor=navy>   
+  <TR>
+    <TD title=oldlace bgColor=oldlace>   
+    <TD title=olive bgColor=olive>   
+    <TD title=olivedrab bgColor=olivedrab>   
+    <TD title=orange bgColor=orange>   
+    <TD title=orangered bgColor=orangered>   
+    <TD title=orchid bgColor=orchid>   
+    <TD title=palegoldenrod bgColor=palegoldenrod>   
+    <TD title=palegreen bgColor=palegreen>   
+    <TD title=paleturquoise bgColor=paleturquoise>   
+    <TD title=palevioletred bgColor=palevioletred>   
+    <TD title=papayawhip bgColor=papayawhip>   
+    <TD title=peachpuff bgColor=peachpuff>   
+    <TD title=peru bgColor=peru>   
+    <TD title=pink bgColor=pink>   
+    <TD title=plum bgColor=plum>   
+    <TD title=powderblue bgColor=powderblue>   
+  <TR>
+    <TD title=purple bgColor=purple>   
+    <TD title=red bgColor=red>   
+    <TD title=rosybrown bgColor=rosybrown>   
+    <TD title=royalblue bgColor=royalblue>   
+    <TD title=saddlebrown bgColor=saddlebrown>   
+    <TD title=salmon bgColor=salmon>   
+    <TD title=sandybrown bgColor=sandybrown>   
+    <TD title=seagreen bgColor=seagreen>   
+    <TD title=seashell bgColor=seashell>   
+    <TD title=sienna bgColor=sienna>   
+    <TD title=silver bgColor=silver>   
+    <TD title=skyblue bgColor=skyblue>   
+    <TD title=slateblue bgColor=slateblue>   
+    <TD title=slategray bgColor=slategray>   
+    <TD title=snow bgColor=snow>   
+    <TD title=springgreen bgColor=springgreen>   
+  <TR>
+    <TD title=steelblue bgColor=steelblue>   
+    <TD title=tan bgColor=tan>   
+    <TD title=teal bgColor=teal>   
+    <TD title=thistle bgColor=thistle>   
+    <TD title=tomato bgColor=tomato>   
+    <TD title=turquoise bgColor=turquoise>   
+    <TD title=violet bgColor=violet>   
+    <TD title=wheat bgColor=wheat>   
+    <TD title=white bgColor=white>   
+    <TD title=whitesmoke bgColor=whitesmoke>   
+    <TD title=yellow bgColor=yellow>   
+    <TD title=yellowgreen bgColor=yellowgreen>   </TR></TBODY></TABLE>
+<P><LABEL for=SelColor>Color:</LABEL> <INPUT id=SelColor> <BR><SPAN 
+id=RGB> </SPAN> 
+<P><BUTTON id=Ok type=submit>OK</BUTTON><BUTTON 
+onclick=window.close();>Cancel</BUTTON> </P></BODY></HTML>
diff --git a/OpenFreezer/pictures/sh2_3d.gif b/OpenFreezer/pictures/sh2_3d.gif
new file mode 100755
index 0000000..589fa32
Binary files /dev/null and b/OpenFreezer/pictures/sh2_3d.gif differ
diff --git a/OpenFreezer/pictures/sh2_domain.jpg b/OpenFreezer/pictures/sh2_domain.jpg
new file mode 100755
index 0000000..d25e73f
Binary files /dev/null and b/OpenFreezer/pictures/sh2_domain.jpg differ
diff --git a/OpenFreezer/pictures/sh3_habil.gif b/OpenFreezer/pictures/sh3_habil.gif
new file mode 100755
index 0000000..7853ffc
Binary files /dev/null and b/OpenFreezer/pictures/sh3_habil.gif differ
diff --git a/OpenFreezer/pictures/shadowframe.png b/OpenFreezer/pictures/shadowframe.png
new file mode 100755
index 0000000..4635b81
Binary files /dev/null and b/OpenFreezer/pictures/shadowframe.png differ
diff --git a/OpenFreezer/pictures/sharp_map.png b/OpenFreezer/pictures/sharp_map.png
new file mode 100755
index 0000000..93ffff8
Binary files /dev/null and b/OpenFreezer/pictures/sharp_map.png differ
diff --git a/OpenFreezer/pictures/side_about.png b/OpenFreezer/pictures/side_about.png
new file mode 100755
index 0000000..35132e3
Binary files /dev/null and b/OpenFreezer/pictures/side_about.png differ
diff --git a/OpenFreezer/pictures/side_copyright.png b/OpenFreezer/pictures/side_copyright.png
new file mode 100755
index 0000000..f3d0817
Binary files /dev/null and b/OpenFreezer/pictures/side_copyright.png differ
diff --git a/OpenFreezer/pictures/side_docs.png b/OpenFreezer/pictures/side_docs.png
new file mode 100755
index 0000000..5258ff3
Binary files /dev/null and b/OpenFreezer/pictures/side_docs.png differ
diff --git a/OpenFreezer/pictures/side_docs_btn_small.png b/OpenFreezer/pictures/side_docs_btn_small.png
new file mode 100755
index 0000000..cd6018e
Binary files /dev/null and b/OpenFreezer/pictures/side_docs_btn_small.png differ
diff --git a/OpenFreezer/pictures/side_download.png b/OpenFreezer/pictures/side_download.png
new file mode 100755
index 0000000..e322800
Binary files /dev/null and b/OpenFreezer/pictures/side_download.png differ
diff --git a/OpenFreezer/pictures/side_help.png b/OpenFreezer/pictures/side_help.png
new file mode 100755
index 0000000..5c087c8
Binary files /dev/null and b/OpenFreezer/pictures/side_help.png differ
diff --git a/OpenFreezer/pictures/side_home.png b/OpenFreezer/pictures/side_home.png
new file mode 100755
index 0000000..9b7a29e
Binary files /dev/null and b/OpenFreezer/pictures/side_home.png differ
diff --git a/OpenFreezer/pictures/side_news.png b/OpenFreezer/pictures/side_news.png
new file mode 100755
index 0000000..33b0404
Binary files /dev/null and b/OpenFreezer/pictures/side_news.png differ
diff --git a/OpenFreezer/pictures/silver_border_all.png b/OpenFreezer/pictures/silver_border_all.png
new file mode 100755
index 0000000..ee54d2a
Binary files /dev/null and b/OpenFreezer/pictures/silver_border_all.png differ
diff --git a/OpenFreezer/pictures/silver_bullet.png b/OpenFreezer/pictures/silver_bullet.png
new file mode 100755
index 0000000..2de0a6e
Binary files /dev/null and b/OpenFreezer/pictures/silver_bullet.png differ
diff --git a/OpenFreezer/pictures/silver_bullet2.png b/OpenFreezer/pictures/silver_bullet2.png
new file mode 100755
index 0000000..444e113
Binary files /dev/null and b/OpenFreezer/pictures/silver_bullet2.png differ
diff --git a/OpenFreezer/pictures/silverbg.png b/OpenFreezer/pictures/silverbg.png
new file mode 100755
index 0000000..72d63d2
Binary files /dev/null and b/OpenFreezer/pictures/silverbg.png differ
diff --git a/OpenFreezer/pictures/silverborder.png b/OpenFreezer/pictures/silverborder.png
new file mode 100755
index 0000000..c2215e7
Binary files /dev/null and b/OpenFreezer/pictures/silverborder.png differ
diff --git a/OpenFreezer/pictures/silverframe.png b/OpenFreezer/pictures/silverframe.png
new file mode 100755
index 0000000..e9d4415
Binary files /dev/null and b/OpenFreezer/pictures/silverframe.png differ
diff --git a/OpenFreezer/pictures/silverframe2.png b/OpenFreezer/pictures/silverframe2.png
new file mode 100755
index 0000000..a440ec3
Binary files /dev/null and b/OpenFreezer/pictures/silverframe2.png differ
diff --git a/OpenFreezer/pictures/silverframe3.png b/OpenFreezer/pictures/silverframe3.png
new file mode 100755
index 0000000..b082d6e
Binary files /dev/null and b/OpenFreezer/pictures/silverframe3.png differ
diff --git a/OpenFreezer/pictures/silvermenubullet.png b/OpenFreezer/pictures/silvermenubullet.png
new file mode 100755
index 0000000..ede09a1
Binary files /dev/null and b/OpenFreezer/pictures/silvermenubullet.png differ
diff --git a/OpenFreezer/pictures/sitebg.jpg b/OpenFreezer/pictures/sitebg.jpg
new file mode 100755
index 0000000..da7816a
Binary files /dev/null and b/OpenFreezer/pictures/sitebg.jpg differ
diff --git a/OpenFreezer/pictures/sitebg.png b/OpenFreezer/pictures/sitebg.png
new file mode 100755
index 0000000..cf5c172
Binary files /dev/null and b/OpenFreezer/pictures/sitebg.png differ
diff --git a/OpenFreezer/pictures/small_bg.png b/OpenFreezer/pictures/small_bg.png
new file mode 100755
index 0000000..2fd2c5c
Binary files /dev/null and b/OpenFreezer/pictures/small_bg.png differ
diff --git a/OpenFreezer/pictures/small_sharp_amp.png b/OpenFreezer/pictures/small_sharp_amp.png
new file mode 100755
index 0000000..3838c58
Binary files /dev/null and b/OpenFreezer/pictures/small_sharp_amp.png differ
diff --git a/OpenFreezer/pictures/smaller_map.png b/OpenFreezer/pictures/smaller_map.png
new file mode 100755
index 0000000..59161b2
Binary files /dev/null and b/OpenFreezer/pictures/smaller_map.png differ
diff --git a/OpenFreezer/pictures/smallergrayframe.png b/OpenFreezer/pictures/smallergrayframe.png
new file mode 100755
index 0000000..8842f15
Binary files /dev/null and b/OpenFreezer/pictures/smallergrayframe.png differ
diff --git a/OpenFreezer/pictures/smallmap.png b/OpenFreezer/pictures/smallmap.png
new file mode 100755
index 0000000..de4deb9
Binary files /dev/null and b/OpenFreezer/pictures/smallmap.png differ
diff --git a/OpenFreezer/pictures/smallmapwborder.png b/OpenFreezer/pictures/smallmapwborder.png
new file mode 100755
index 0000000..a6bd4ad
Binary files /dev/null and b/OpenFreezer/pictures/smallmapwborder.png differ
diff --git a/OpenFreezer/pictures/smallsearch.png b/OpenFreezer/pictures/smallsearch.png
new file mode 100755
index 0000000..35f6fbe
Binary files /dev/null and b/OpenFreezer/pictures/smallsearch.png differ
diff --git a/OpenFreezer/pictures/smtg.png b/OpenFreezer/pictures/smtg.png
new file mode 100755
index 0000000..8b498c0
Binary files /dev/null and b/OpenFreezer/pictures/smtg.png differ
diff --git a/OpenFreezer/pictures/sort/sort_blue_down.gif b/OpenFreezer/pictures/sort/sort_blue_down.gif
new file mode 100755
index 0000000..cd9476f
Binary files /dev/null and b/OpenFreezer/pictures/sort/sort_blue_down.gif differ
diff --git a/OpenFreezer/pictures/sort/sort_blue_left.gif b/OpenFreezer/pictures/sort/sort_blue_left.gif
new file mode 100755
index 0000000..8441a40
Binary files /dev/null and b/OpenFreezer/pictures/sort/sort_blue_left.gif differ
diff --git a/OpenFreezer/pictures/sort/sort_blue_right.gif b/OpenFreezer/pictures/sort/sort_blue_right.gif
new file mode 100755
index 0000000..d7e6b00
Binary files /dev/null and b/OpenFreezer/pictures/sort/sort_blue_right.gif differ
diff --git a/OpenFreezer/pictures/sort/sort_blue_up.gif b/OpenFreezer/pictures/sort/sort_blue_up.gif
new file mode 100755
index 0000000..3af2649
Binary files /dev/null and b/OpenFreezer/pictures/sort/sort_blue_up.gif differ
diff --git a/OpenFreezer/pictures/sort/sort_down.gif b/OpenFreezer/pictures/sort/sort_down.gif
new file mode 100755
index 0000000..2655bcc
Binary files /dev/null and b/OpenFreezer/pictures/sort/sort_down.gif differ
diff --git a/OpenFreezer/pictures/sort/sort_left.gif b/OpenFreezer/pictures/sort/sort_left.gif
new file mode 100755
index 0000000..3677401
Binary files /dev/null and b/OpenFreezer/pictures/sort/sort_left.gif differ
diff --git a/OpenFreezer/pictures/sort/sort_red_down.gif b/OpenFreezer/pictures/sort/sort_red_down.gif
new file mode 100755
index 0000000..9b46043
Binary files /dev/null and b/OpenFreezer/pictures/sort/sort_red_down.gif differ
diff --git a/OpenFreezer/pictures/sort/sort_red_up.gif b/OpenFreezer/pictures/sort/sort_red_up.gif
new file mode 100755
index 0000000..1ddd104
Binary files /dev/null and b/OpenFreezer/pictures/sort/sort_red_up.gif differ
diff --git a/OpenFreezer/pictures/sort/sort_right.gif b/OpenFreezer/pictures/sort/sort_right.gif
new file mode 100755
index 0000000..006964d
Binary files /dev/null and b/OpenFreezer/pictures/sort/sort_right.gif differ
diff --git a/OpenFreezer/pictures/sort/sort_up.gif b/OpenFreezer/pictures/sort/sort_up.gif
new file mode 100755
index 0000000..ff2bd95
Binary files /dev/null and b/OpenFreezer/pictures/sort/sort_up.gif differ
diff --git a/OpenFreezer/pictures/sort_blue_down.gif b/OpenFreezer/pictures/sort_blue_down.gif
new file mode 100755
index 0000000..eaf7e65
Binary files /dev/null and b/OpenFreezer/pictures/sort_blue_down.gif differ
diff --git a/OpenFreezer/pictures/sort_blue_left.gif b/OpenFreezer/pictures/sort_blue_left.gif
new file mode 100755
index 0000000..eaf7e65
Binary files /dev/null and b/OpenFreezer/pictures/sort_blue_left.gif differ
diff --git a/OpenFreezer/pictures/sort_blue_right.gif b/OpenFreezer/pictures/sort_blue_right.gif
new file mode 100755
index 0000000..eaf7e65
Binary files /dev/null and b/OpenFreezer/pictures/sort_blue_right.gif differ
diff --git a/OpenFreezer/pictures/sort_blue_up.gif b/OpenFreezer/pictures/sort_blue_up.gif
new file mode 100755
index 0000000..eaf7e65
Binary files /dev/null and b/OpenFreezer/pictures/sort_blue_up.gif differ
diff --git a/OpenFreezer/pictures/sort_down.gif b/OpenFreezer/pictures/sort_down.gif
new file mode 100755
index 0000000..eaf7e65
Binary files /dev/null and b/OpenFreezer/pictures/sort_down.gif differ
diff --git a/OpenFreezer/pictures/sort_left.gif b/OpenFreezer/pictures/sort_left.gif
new file mode 100755
index 0000000..eaf7e65
Binary files /dev/null and b/OpenFreezer/pictures/sort_left.gif differ
diff --git a/OpenFreezer/pictures/sort_right.gif b/OpenFreezer/pictures/sort_right.gif
new file mode 100755
index 0000000..eaf7e65
Binary files /dev/null and b/OpenFreezer/pictures/sort_right.gif differ
diff --git a/OpenFreezer/pictures/sort_up.gif b/OpenFreezer/pictures/sort_up.gif
new file mode 100755
index 0000000..eaf7e65
Binary files /dev/null and b/OpenFreezer/pictures/sort_up.gif differ
diff --git a/OpenFreezer/pictures/sphere_bullet.jpeg b/OpenFreezer/pictures/sphere_bullet.jpeg
new file mode 100755
index 0000000..efc59d1
Binary files /dev/null and b/OpenFreezer/pictures/sphere_bullet.jpeg differ
diff --git a/OpenFreezer/pictures/spotfire.gif b/OpenFreezer/pictures/spotfire.gif
new file mode 100755
index 0000000..411ad0c
Binary files /dev/null and b/OpenFreezer/pictures/spotfire.gif differ
diff --git a/OpenFreezer/pictures/star_bullet.gif b/OpenFreezer/pictures/star_bullet.gif
new file mode 100755
index 0000000..38c1b41
Binary files /dev/null and b/OpenFreezer/pictures/star_bullet.gif differ
diff --git a/OpenFreezer/pictures/submenu_bg.png b/OpenFreezer/pictures/submenu_bg.png
new file mode 100755
index 0000000..4f83acb
Binary files /dev/null and b/OpenFreezer/pictures/submenu_bg.png differ
diff --git a/OpenFreezer/pictures/tab2.png b/OpenFreezer/pictures/tab2.png
new file mode 100755
index 0000000..5dedeb0
Binary files /dev/null and b/OpenFreezer/pictures/tab2.png differ
diff --git a/OpenFreezer/pictures/tabhelp.png b/OpenFreezer/pictures/tabhelp.png
new file mode 100755
index 0000000..10b5c30
Binary files /dev/null and b/OpenFreezer/pictures/tabhelp.png differ
diff --git a/OpenFreezer/pictures/table_corner.gif b/OpenFreezer/pictures/table_corner.gif
new file mode 100755
index 0000000..3e59cf3
Binary files /dev/null and b/OpenFreezer/pictures/table_corner.gif differ
diff --git a/OpenFreezer/pictures/tblborder.png b/OpenFreezer/pictures/tblborder.png
new file mode 100755
index 0000000..2acca90
Binary files /dev/null and b/OpenFreezer/pictures/tblborder.png differ
diff --git a/OpenFreezer/pictures/test.png b/OpenFreezer/pictures/test.png
new file mode 100755
index 0000000..739ecf8
Binary files /dev/null and b/OpenFreezer/pictures/test.png differ
diff --git a/OpenFreezer/pictures/test2.png b/OpenFreezer/pictures/test2.png
new file mode 100755
index 0000000..53ffceb
Binary files /dev/null and b/OpenFreezer/pictures/test2.png differ
diff --git a/OpenFreezer/pictures/test_of.png b/OpenFreezer/pictures/test_of.png
new file mode 100755
index 0000000..74b0dcf
Binary files /dev/null and b/OpenFreezer/pictures/test_of.png differ
diff --git a/OpenFreezer/pictures/test_tubes.jpg b/OpenFreezer/pictures/test_tubes.jpg
new file mode 100755
index 0000000..d6d7074
Binary files /dev/null and b/OpenFreezer/pictures/test_tubes.jpg differ
diff --git a/OpenFreezer/pictures/testbg.png b/OpenFreezer/pictures/testbg.png
new file mode 100755
index 0000000..9f5a40b
Binary files /dev/null and b/OpenFreezer/pictures/testbg.png differ
diff --git a/OpenFreezer/pictures/testbg2.png b/OpenFreezer/pictures/testbg2.png
new file mode 100755
index 0000000..f9f7b0e
Binary files /dev/null and b/OpenFreezer/pictures/testbg2.png differ
diff --git a/OpenFreezer/pictures/testframe.png b/OpenFreezer/pictures/testframe.png
new file mode 100755
index 0000000..6332fbb
Binary files /dev/null and b/OpenFreezer/pictures/testframe.png differ
diff --git a/OpenFreezer/pictures/testgray.png b/OpenFreezer/pictures/testgray.png
new file mode 100755
index 0000000..ca20f33
Binary files /dev/null and b/OpenFreezer/pictures/testgray.png differ
diff --git a/OpenFreezer/pictures/testmenu.png b/OpenFreezer/pictures/testmenu.png
new file mode 100755
index 0000000..fdf1254
Binary files /dev/null and b/OpenFreezer/pictures/testmenu.png differ
diff --git a/OpenFreezer/pictures/text_final.png b/OpenFreezer/pictures/text_final.png
new file mode 100755
index 0000000..e9253ac
Binary files /dev/null and b/OpenFreezer/pictures/text_final.png differ
diff --git a/OpenFreezer/pictures/textoutline.png b/OpenFreezer/pictures/textoutline.png
new file mode 100755
index 0000000..3ecb6d7
Binary files /dev/null and b/OpenFreezer/pictures/textoutline.png differ
diff --git a/OpenFreezer/pictures/tm_trans.jpg b/OpenFreezer/pictures/tm_trans.jpg
new file mode 100755
index 0000000..4d1f317
Binary files /dev/null and b/OpenFreezer/pictures/tm_trans.jpg differ
diff --git a/OpenFreezer/pictures/tmpof.png b/OpenFreezer/pictures/tmpof.png
new file mode 100755
index 0000000..2e7850f
Binary files /dev/null and b/OpenFreezer/pictures/tmpof.png differ
diff --git a/OpenFreezer/pictures/top.png b/OpenFreezer/pictures/top.png
new file mode 100755
index 0000000..ea994a9
Binary files /dev/null and b/OpenFreezer/pictures/top.png differ
diff --git a/OpenFreezer/pictures/top_about.png b/OpenFreezer/pictures/top_about.png
new file mode 100755
index 0000000..4496470
Binary files /dev/null and b/OpenFreezer/pictures/top_about.png differ
diff --git a/OpenFreezer/pictures/top_bug.png b/OpenFreezer/pictures/top_bug.png
new file mode 100755
index 0000000..60b7287
Binary files /dev/null and b/OpenFreezer/pictures/top_bug.png differ
diff --git a/OpenFreezer/pictures/top_contact.png b/OpenFreezer/pictures/top_contact.png
new file mode 100755
index 0000000..6d29dc4
Binary files /dev/null and b/OpenFreezer/pictures/top_contact.png differ
diff --git a/OpenFreezer/pictures/top_copyright.png b/OpenFreezer/pictures/top_copyright.png
new file mode 100755
index 0000000..3a6494d
Binary files /dev/null and b/OpenFreezer/pictures/top_copyright.png differ
diff --git a/OpenFreezer/pictures/top_docs.png b/OpenFreezer/pictures/top_docs.png
new file mode 100755
index 0000000..fee23bf
Binary files /dev/null and b/OpenFreezer/pictures/top_docs.png differ
diff --git a/OpenFreezer/pictures/top_download.png b/OpenFreezer/pictures/top_download.png
new file mode 100755
index 0000000..13c6220
Binary files /dev/null and b/OpenFreezer/pictures/top_download.png differ
diff --git a/OpenFreezer/pictures/top_faq.png b/OpenFreezer/pictures/top_faq.png
new file mode 100755
index 0000000..ecc823e
Binary files /dev/null and b/OpenFreezer/pictures/top_faq.png differ
diff --git a/OpenFreezer/pictures/top_help.png b/OpenFreezer/pictures/top_help.png
new file mode 100755
index 0000000..4cfa695
Binary files /dev/null and b/OpenFreezer/pictures/top_help.png differ
diff --git a/OpenFreezer/pictures/top_home.png b/OpenFreezer/pictures/top_home.png
new file mode 100755
index 0000000..67bcdcc
Binary files /dev/null and b/OpenFreezer/pictures/top_home.png differ
diff --git a/OpenFreezer/pictures/top_license.png b/OpenFreezer/pictures/top_license.png
new file mode 100755
index 0000000..2557c1f
Binary files /dev/null and b/OpenFreezer/pictures/top_license.png differ
diff --git a/OpenFreezer/pictures/top_news.png b/OpenFreezer/pictures/top_news.png
new file mode 100755
index 0000000..25ce648
Binary files /dev/null and b/OpenFreezer/pictures/top_news.png differ
diff --git a/OpenFreezer/pictures/topdarkgray.png b/OpenFreezer/pictures/topdarkgray.png
new file mode 100755
index 0000000..5653b29
Binary files /dev/null and b/OpenFreezer/pictures/topdarkgray.png differ
diff --git a/OpenFreezer/pictures/topleftround.png b/OpenFreezer/pictures/topleftround.png
new file mode 100755
index 0000000..381120e
Binary files /dev/null and b/OpenFreezer/pictures/topleftround.png differ
diff --git a/OpenFreezer/pictures/topline.png b/OpenFreezer/pictures/topline.png
new file mode 100755
index 0000000..320769b
Binary files /dev/null and b/OpenFreezer/pictures/topline.png differ
diff --git a/OpenFreezer/pictures/topshadowframe.png b/OpenFreezer/pictures/topshadowframe.png
new file mode 100755
index 0000000..6854a95
Binary files /dev/null and b/OpenFreezer/pictures/topshadowframe.png differ
diff --git a/OpenFreezer/pictures/tux.PNG b/OpenFreezer/pictures/tux.PNG
new file mode 100755
index 0000000..94aa026
Binary files /dev/null and b/OpenFreezer/pictures/tux.PNG differ
diff --git a/OpenFreezer/pictures/tuxsicle.jpg b/OpenFreezer/pictures/tuxsicle.jpg
new file mode 100755
index 0000000..8e946b8
Binary files /dev/null and b/OpenFreezer/pictures/tuxsicle.jpg differ
diff --git a/OpenFreezer/pictures/up_arrow.png b/OpenFreezer/pictures/up_arrow.png
new file mode 100755
index 0000000..f398acf
Binary files /dev/null and b/OpenFreezer/pictures/up_arrow.png differ
diff --git a/OpenFreezer/pictures/up_new.png b/OpenFreezer/pictures/up_new.png
new file mode 100755
index 0000000..0d76873
Binary files /dev/null and b/OpenFreezer/pictures/up_new.png differ
diff --git a/OpenFreezer/pictures/vector_assoc.gif b/OpenFreezer/pictures/vector_assoc.gif
new file mode 100755
index 0000000..779ff11
Binary files /dev/null and b/OpenFreezer/pictures/vector_assoc.gif differ
diff --git a/OpenFreezer/pictures/vector_assoc.png b/OpenFreezer/pictures/vector_assoc.png
new file mode 100755
index 0000000..779ff11
Binary files /dev/null and b/OpenFreezer/pictures/vector_assoc.png differ
diff --git a/OpenFreezer/pictures/vector_diagm.pdf b/OpenFreezer/pictures/vector_diagm.pdf
new file mode 100755
index 0000000..73f1e8a
Binary files /dev/null and b/OpenFreezer/pictures/vector_diagm.pdf differ
diff --git a/OpenFreezer/pictures/version_trans.jpg b/OpenFreezer/pictures/version_trans.jpg
new file mode 100755
index 0000000..d85081a
Binary files /dev/null and b/OpenFreezer/pictures/version_trans.jpg differ
diff --git a/OpenFreezer/pictures/vert.png b/OpenFreezer/pictures/vert.png
new file mode 100755
index 0000000..6cecf9f
Binary files /dev/null and b/OpenFreezer/pictures/vert.png differ
diff --git a/OpenFreezer/pictures/verysmallmap.png b/OpenFreezer/pictures/verysmallmap.png
new file mode 100755
index 0000000..8da8057
Binary files /dev/null and b/OpenFreezer/pictures/verysmallmap.png differ
diff --git a/OpenFreezer/pictures/white-bullet.png b/OpenFreezer/pictures/white-bullet.png
new file mode 100755
index 0000000..be7bcf3
Binary files /dev/null and b/OpenFreezer/pictures/white-bullet.png differ
diff --git a/OpenFreezer/pictures/whitegetfirefox80x15.gif b/OpenFreezer/pictures/whitegetfirefox80x15.gif
new file mode 100755
index 0000000..6c4d528
Binary files /dev/null and b/OpenFreezer/pictures/whitegetfirefox80x15.gif differ
diff --git a/OpenFreezer/pictures/whmis/biohazard.jpg b/OpenFreezer/pictures/whmis/biohazard.jpg
new file mode 100644
index 0000000..f59624f
Binary files /dev/null and b/OpenFreezer/pictures/whmis/biohazard.jpg differ
diff --git a/OpenFreezer/pictures/whmis/classificiation_system.pdf b/OpenFreezer/pictures/whmis/classificiation_system.pdf
new file mode 100644
index 0000000..aecc54f
Binary files /dev/null and b/OpenFreezer/pictures/whmis/classificiation_system.pdf differ
diff --git a/OpenFreezer/pictures/whmis/compressed_gas.jpg b/OpenFreezer/pictures/whmis/compressed_gas.jpg
new file mode 100644
index 0000000..b36c3a0
Binary files /dev/null and b/OpenFreezer/pictures/whmis/compressed_gas.jpg differ
diff --git a/OpenFreezer/pictures/whmis/corrosive.jpg b/OpenFreezer/pictures/whmis/corrosive.jpg
new file mode 100644
index 0000000..6b09dad
Binary files /dev/null and b/OpenFreezer/pictures/whmis/corrosive.jpg differ
diff --git a/OpenFreezer/pictures/whmis/flammable.jpg b/OpenFreezer/pictures/whmis/flammable.jpg
new file mode 100644
index 0000000..0e0c43e
Binary files /dev/null and b/OpenFreezer/pictures/whmis/flammable.jpg differ
diff --git a/OpenFreezer/pictures/whmis/new_images/biohazard.jpg b/OpenFreezer/pictures/whmis/new_images/biohazard.jpg
new file mode 100644
index 0000000..abbdce4
Binary files /dev/null and b/OpenFreezer/pictures/whmis/new_images/biohazard.jpg differ
diff --git a/OpenFreezer/pictures/whmis/new_images/compressed_gas.jpg b/OpenFreezer/pictures/whmis/new_images/compressed_gas.jpg
new file mode 100644
index 0000000..756275b
Binary files /dev/null and b/OpenFreezer/pictures/whmis/new_images/compressed_gas.jpg differ
diff --git a/OpenFreezer/pictures/whmis/new_images/corrosive.jpg b/OpenFreezer/pictures/whmis/new_images/corrosive.jpg
new file mode 100644
index 0000000..4231740
Binary files /dev/null and b/OpenFreezer/pictures/whmis/new_images/corrosive.jpg differ
diff --git a/OpenFreezer/pictures/whmis/new_images/flammable.jpg b/OpenFreezer/pictures/whmis/new_images/flammable.jpg
new file mode 100644
index 0000000..6fbe11e
Binary files /dev/null and b/OpenFreezer/pictures/whmis/new_images/flammable.jpg differ
diff --git a/OpenFreezer/pictures/whmis/new_images/oxidizing.jpg b/OpenFreezer/pictures/whmis/new_images/oxidizing.jpg
new file mode 100644
index 0000000..65e1792
Binary files /dev/null and b/OpenFreezer/pictures/whmis/new_images/oxidizing.jpg differ
diff --git a/OpenFreezer/pictures/whmis/new_images/poisonous.jpg b/OpenFreezer/pictures/whmis/new_images/poisonous.jpg
new file mode 100644
index 0000000..1fcd81c
Binary files /dev/null and b/OpenFreezer/pictures/whmis/new_images/poisonous.jpg differ
diff --git a/OpenFreezer/pictures/whmis/new_images/reactive.jpg b/OpenFreezer/pictures/whmis/new_images/reactive.jpg
new file mode 100644
index 0000000..bc04868
Binary files /dev/null and b/OpenFreezer/pictures/whmis/new_images/reactive.jpg differ
diff --git a/OpenFreezer/pictures/whmis/new_images/toxic.jpg b/OpenFreezer/pictures/whmis/new_images/toxic.jpg
new file mode 100644
index 0000000..ad903d9
Binary files /dev/null and b/OpenFreezer/pictures/whmis/new_images/toxic.jpg differ
diff --git a/OpenFreezer/pictures/whmis/oxidizer.jpg b/OpenFreezer/pictures/whmis/oxidizer.jpg
new file mode 100644
index 0000000..70bdda7
Binary files /dev/null and b/OpenFreezer/pictures/whmis/oxidizer.jpg differ
diff --git a/OpenFreezer/pictures/whmis/poisonous.jpg b/OpenFreezer/pictures/whmis/poisonous.jpg
new file mode 100644
index 0000000..ca80428
Binary files /dev/null and b/OpenFreezer/pictures/whmis/poisonous.jpg differ
diff --git a/OpenFreezer/pictures/whmis/reactive.jpg b/OpenFreezer/pictures/whmis/reactive.jpg
new file mode 100644
index 0000000..38ab879
Binary files /dev/null and b/OpenFreezer/pictures/whmis/reactive.jpg differ
diff --git a/OpenFreezer/pictures/whmis/toxic.jpg b/OpenFreezer/pictures/whmis/toxic.jpg
new file mode 100644
index 0000000..101dac8
Binary files /dev/null and b/OpenFreezer/pictures/whmis/toxic.jpg differ
diff --git a/OpenFreezer/pictures/yellow_bg.jpg b/OpenFreezer/pictures/yellow_bg.jpg
new file mode 100755
index 0000000..0932fed
Binary files /dev/null and b/OpenFreezer/pictures/yellow_bg.jpg differ
diff --git a/OpenFreezer/scripts/menu.js b/OpenFreezer/scripts/menu.js
new file mode 100755
index 0000000..b8ec7b2
--- /dev/null
+++ b/OpenFreezer/scripts/menu.js
@@ -0,0 +1,21066 @@
+//CHANGE THIS TO YOUR OPENFREEZER URL (NOTE THE TRAILING SLASH)
+var hostName = "Your OpenFreezer URL, e.g. http://www.my_openfreezer.org/";
+
+var cgiPath = hostName + "cgi/";
+var parentsValid = true;
+var currReagentType;
+var wellResult = true;
+var parentResult = true;
+var addElementError = false;	// May 26, 2010
+var goback = false;
+
+// June 3/08
+function redirect(url)
+{
+	window.location = url;
+}
+
+function openPage(menuOpt)
+{
+	if (document.getElementById("curr_user_hidden"))
+	{
+		userID = document.getElementById("curr_user_hidden").value;
+
+		// remember to trim, have extra whitespace for padding!
+		if (trimAll(menuOpt.text) == 'Personal page')
+			redirectToCurrentUserDetailedView(userID);
+		else
+		{
+			if (menuOpt.value != "")
+			{
+				redirect(menuOpt.value);
+			}
+		}
+	}
+	else
+	{
+		if (menuOpt.value != "")
+		{
+			redirect(menuOpt.value);
+		}
+	}
+}
+
+
+function cancelReagentCreation()
+{
+	url = window.location.toString();
+
+	curr_username = document.getElementById('curr_username_hidden');
+	
+	// get reagent type from URL - cancellation should be done for Vectors and Inserts, later maybe for other types too, but because input name reagent_type_hidden is used in many places throughout the code, cannot assign an ID to it
+	rid_index = url.indexOf('&rID=')+5;
+	rID = url.substring(rid_index, url.indexOf('&', rid_index));
+
+	url = cgiPath + "create.py";
+
+	xmlhttp = createXML();
+	xmlhttp.open("POST", url, false);
+	xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+
+	xmlhttp.send('cancel_creation=1&reagent_id_hidden=' + rID + '&curr_username=' + curr_username);
+
+	xmlhttp.onreadystatechange = function(){};
+}
+
+
+// Reagent functions
+function showMorphology()
+{
+	var list_id = "morphology_list";
+	var text_id = "morphology_txt";	
+	var listElement = document.getElementById(list_id);
+	var txtElem = document.getElementById(text_id);
+	var selectedInd = listElement.selectedIndex;
+	var selectedValue = listElement[selectedInd].value;
+
+	if (selectedValue.toLowerCase() == 'other')
+	{
+		// Show the textbox
+		txtElem.style.display = "inline";
+
+		// Set the focus to the new textbox (place cursor inside)
+		txtElem.focus();
+	}
+	else
+	{
+		// Hide the textbox
+		txtElem.style.display="none";
+	}
+}
+
+function showTissueType()
+{
+	var list_id = "tissue_type_list";
+	var text_id = "tissue_type_txt";	
+	var listElement = document.getElementById(list_id);
+	var txtElem = document.getElementById(text_id);
+	var selectedInd = listElement.selectedIndex;
+	var selectedValue = listElement[selectedInd].value;
+
+	if (selectedValue.toLowerCase() == 'other')
+	{
+		// Show the textbox
+		txtElem.style.display = "inline";
+
+		// Set the focus to the new textbox (place cursor inside)
+		txtElem.focus();
+	}
+	else
+	{
+		// Hide the textbox
+		txtElem.style.display="none";
+	}
+}
+
+function showSpeciesBox()
+{
+	var list_id = "species_list";
+	var text_id = "species_txt";	
+	var listElement = document.getElementById(list_id);
+	var txtElem = document.getElementById(text_id);
+	var selectedInd = listElement.selectedIndex;
+	var selectedValue = listElement[selectedInd].value;
+
+	if (selectedValue.toLowerCase() == 'other')
+	{
+		// Show the textbox
+		txtElem.style.display = "inline";
+
+		// Set the focus to the new textbox (place cursor inside)
+		txtElem.focus();
+	}
+	else
+	{
+		// Hide the textbox
+		txtElem.style.display="none";
+	}
+}
+
+function showDevStage()
+{
+	var list_id = "dev_stage_list";
+	var text_id = "dev_stage_txt";	
+	var listElement = document.getElementById(list_id);
+	var txtElem = document.getElementById(text_id);
+	var selectedInd = listElement.selectedIndex;
+	var selectedValue = listElement[selectedInd].value;
+
+	if (selectedValue.toLowerCase() == 'other')
+	{
+		// Show the textbox
+		txtElem.style.display = "inline";
+
+		// Set the focus to the new textbox (place cursor inside)
+		txtElem.focus();
+	}
+	else
+	{
+		// Hide the textbox
+		txtElem.style.display="none";
+	}
+}
+
+function showProtocolBox()
+{
+	var list_id = "protocol_list";
+	var text_id = "protocol_txt";	
+	var listElement = document.getElementById(list_id);
+	var txtElem = document.getElementById(text_id);
+	var selectedInd = listElement.selectedIndex;
+	var selectedValue = listElement[selectedInd].value;
+
+	if (selectedValue.toLowerCase() == 'other')
+	{
+		// Show the textbox
+		txtElem.style.display="inline";
+
+		// Set the focus to the new textbox (place cursor inside)
+		txtElem.focus();
+	}
+	else
+	{
+		// Hide the textbox
+		txtElem.style.display="none";
+	}
+}
+
+// March 3/08: Changing function signature - passing list and text IDs as arguments
+function showTagTypeBox(list_id, text_id)
+{
+	var listElement = document.getElementById(list_id);
+	var txtElem = document.getElementById(text_id);
+	
+	var selectedInd = listElement.selectedIndex;
+	
+	var selectedValue = listElement[selectedInd].value;
+	
+	if (selectedValue.toLowerCase() == 'other')
+	{
+		// Show the textbox
+		txtElem.style.display="inline";
+
+		// Set the focus to the new textbox (place cursor inside)
+		txtElem.focus();
+	}
+	else
+	{
+		// Hide the textbox
+		txtElem.style.display="none";
+	}
+}
+
+// April 23, 2010
+// Taken from http://www.webtoolkit.info/javascript-url-decode-encode.html
+function utf8_decode(utftext)
+{
+	var string = "";
+	var i = 0;
+	var c = c1 = c2 = 0;
+ 
+	while (i < utftext.length)
+	{
+// alert(utftext.charAt(i));
+
+		c = utftext.charCodeAt(i);
+
+		if (c < 128)
+		{
+// alert(c + " < 128");
+			string += String.fromCharCode(c);
+			i++;
+		}
+		else if((c > 191) && (c < 224))
+		{
+// alert(c + " > 191 and < 224");
+
+			c2 = utftext.charCodeAt(i+1);
+			string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
+			i += 2;
+		}
+		else
+		{
+// alert(c + " > 224");
+			c2 = utftext.charCodeAt(i+1);
+			c3 = utftext.charCodeAt(i+2);
+			string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+			i += 3;
+		}
+	}
+
+	return string;
+}
+
+
+
+// April 6/07, Marina: Same rationale for Checkbox properties: to differentiate between Insert and Cell Line Alternate ID properties, call the show() function with specific name parameter
+function showSpecificOtherCheckbox(checkTextboxID)
+{
+	var checkTextbox = document.getElementById(checkTextboxID);
+
+	if (checkTextbox.style.display == "none")
+	{
+		checkTextbox.style.display = "inline";
+		checkTextbox.focus();
+	}
+	else
+	{
+		checkTextbox.style.display = "none";
+	}
+}
+
+// Added April 6/07, Marina: Since the new layout may contain multiple expandable dropdown lists for different reagent types, wrote this function, which takes as input specific IDs that contain the reagent type embedded in them; then there's no confusion
+function showSpecificOtherTextbox(listID, textID)
+{
+// alert(textID + " before");
+
+	textID = unescape(textID);
+
+// alert(textID + " after");
+	var listElement = document.getElementById(listID);
+// alert(listID);
+	var txtElem = document.getElementById(textID);
+// 	alert(textID);
+	var selectedInd = listElement.selectedIndex;
+// alert(selectedInd);
+	var selectedValue = listElement[selectedInd].value;
+// alert(selectedValue);
+	
+	if (selectedValue.toLowerCase() == 'other')
+	{
+		// Show the textbox
+		txtElem.style.display="inline";
+
+		// Set the focus to the new textbox (place cursor inside)
+		txtElem.focus();
+	}
+	else
+	{
+		// Hide the textbox
+		if (txtElem)
+			txtElem.style.display="none";
+	}
+}
+
+function showExprSystBox()
+{
+	var list_id = "expr_syst_list";
+	var text_id = "expr_syst_list_txt";	
+	var listElement = document.getElementById(list_id);
+	var txtElem = document.getElementById(text_id);
+	var selectedInd = listElement.selectedIndex;
+	var selectedValue = listElement[selectedInd].value;
+
+	if (selectedValue.toLowerCase() == 'other')
+	{
+		// Show the textbox
+		txtElem.style.display="inline";
+
+		// Set the focus to the new textbox (place cursor inside)
+		txtElem.focus();
+	}
+	else
+	{
+		// Hide the textbox
+		txtElem.style.display="none";
+	}
+}
+
+function showPromoText()
+{
+	var list_id = "promoter_list";
+	var text_id = "promo_txt";	
+	var listElement = document.getElementById(list_id);
+
+	// Check to see if the textbox exists and create it ONLY if it doesn't
+	var txtElem = document.getElementById(text_id);
+	var selectedInd = listElement.selectedIndex;
+	var selectedValue = listElement[selectedInd].value;
+
+	if (selectedValue.toLowerCase() == 'other')
+	{
+		// Show the textbox
+		txtElem.style.display="inline";
+
+		// Set the focus to the new textbox (place cursor inside)
+		txtElem.focus();
+	}
+	else
+	{
+		// Hide the textbox
+		txtElem.style.display="none";
+	}
+}
+
+function showCMText()
+{
+	var list_id = "cm_list";
+	var text_id = "cm_txt";	
+	var listElement = document.getElementById(list_id);
+
+	// Check to see if the textbox exists and create it ONLY if it doesn't
+	var txtElem = document.getElementById(text_id);
+	var selectedInd = listElement.selectedIndex;
+	var selectedValue = listElement[selectedInd].value;
+
+	if (selectedValue.toLowerCase() == 'other')
+	{
+		// Show the textbox
+		txtElem.style.display="inline";
+
+		// Set the focus to the new textbox (place cursor inside)
+		txtElem.focus();
+	}
+	else
+	{
+		// Hide the textbox
+		txtElem.style.display="none";
+	}
+}
+
+// Oct. 15/07: Show/hide restriction enzyme textbox if 'Other' is selected from the dropdown list
+// Last modified Feb. 11/08
+function showHideFivePrimeOther(subtype)
+{
+	var fpList = document.getElementById("fpcs_list_1");
+
+	// different ID for Novel Vectors and Inserts (no subtype postfix)
+	if (!fpList)
+	{
+		var fpList = document.getElementById("fpcs_list");
+		var fpText = document.getElementById("fpcs_txt");
+	}
+	else
+		var fpText = document.getElementById("fpcs_txt_" + subtype);
+
+	var selectedInd = fpList.selectedIndex;
+	var selectedValue = fpList[selectedInd].value;
+
+	if (selectedValue.toLowerCase() == 'other')
+	{
+		// Show the textbox
+		fpText.style.display="inline";
+
+		// Set the focus to the new textbox (place cursor inside)
+		fpText.focus();
+	}
+	else
+	{
+		fpText.style.display="none";
+	}
+}
+
+
+// Oct. 15/07: Show/hide restriction enzyme textbox if 'Other' is selected from the dropdown list
+function showHideThreePrimeOther(subtype)
+{
+//	var allSelect = document.getElementsByTagName("SELECT");
+
+//	for (a in allSelect)
+//	{
+//		tmpList = allSelect[a];
+
+//		if (tmpList.id == "tpcs_list_1")
+//		{
+ 			var tpList = document.getElementById("tpcs_list_1");
+			var tpText = document.getElementById("tpcs_txt_" + subtype);
+		
+			var selectedInd = tpList.selectedIndex;
+			var selectedValue = tpList[selectedInd].value;
+		
+			if (selectedValue.toLowerCase() == 'other')
+			{
+				// Show the textbox
+				tpText.style.display="inline";
+		
+				// Set the focus to the new textbox (place cursor inside)
+				tpText.focus();
+			}
+ 			else
+ 			{
+				// Hide the textbox
+ 				tpText.style.display="none";
+ 			}
+//		}
+//	}
+}
+
+function cancelModify(rID)
+{
+	window.location.href = hostName + "Reagent.php?View=6&rid=" + rID;
+}
+
+// May 13/08
+// Invoked at step 2 of reagent creation, where sequence is entered
+// Validation varies according to reagent type
+function verifyReagentSequenceCreation(rType, subtype)
+{
+	if (document.getElementById("cancel_set"))
+	{
+		var cancelSet = document.getElementById("cancel_set").value;
+	}
+	else
+	{
+		var cancelSet = 0;
+	}
+
+	if (cancelSet != 1)
+	{
+		if (rType == 'Insert')
+		{
+			return verifyInsertCreation();
+		}
+		else if (rType == 'Vector')
+		{
+// Nov. 6/08 - verification needed for all vector types, not just novel - code is the same
+// 			if (subtype.toLowerCase() == 'novel')
+// 			{
+				return verifyNovelVectorSequence();
+// 			}
+		}
+	}
+}
+
+
+// Feb. 7/08: Called at Insert creation to make sure sequence is filled in
+function verifyInsertCreation()
+{
+	var dna_sequence = document.getElementById("dna_sequence_Insert");
+	var sequence_warning = document.getElementById("sequence_warning");
+	var seq = trimAll(dna_sequence.value);
+
+	if (seq == "")
+	{
+		alert("Please provide an Insert sequence");
+		dna_sequence.focus();
+		sequence_warning.style.display = "inline";
+
+		return false;
+	}
+	else
+		sequence_warning.style.display = "none";
+
+	for (i = 0; i < seq.length; i++)
+	{
+		aChar = seq.charAt(i).toLowerCase();
+
+		if ( (aChar != 'a') && (aChar != 'c') && (aChar != 'g') && (aChar != 't') && (aChar != 'n'))
+		{
+			var answer = confirm("Insert sequence contains characters other than A, C, G, T or N.  Saving will remove these extra characters.  Are you sure you wish to proceed?");
+
+			if (answer == 0)
+			{
+				dna_sequence.focus();
+				return false;
+			}
+			else
+			{
+				// Filter unwanted chars first, then save
+				new_sequence = filterDNASeq(seq);
+				dna_sequence.value = new_sequence;
+				break;
+			}
+		}
+	}
+
+//	if (!verifyCDNA(true))
+//		return false;
+
+	return verifyCloningSites("insert");
+}
+
+
+function verifySitesAtCreation()
+{
+	return verifyHybridSites('fpcs', 'fpcs_list') && verifyHybridSites('tpcs', 'fpcs_list');
+}
+
+/*
+// April 30/08: Validate proper format of HYBRID sites
+function verifyHybridSites(inputID, enzListID)
+{
+// alert(enzListID);
+	// May 29/08
+	var gatewayLoxPNoneSites = ['attB1', 'attB2', 'attP1', 'attP2', 'attL1', 'attL2', 'attR1', 'attR2', 'LoxP', 'None'];
+	var enzymeList = document.getElementById(enzListID);
+
+	var siteField = document.getElementById(inputID);
+	var site = siteField.value;	// always a text field
+
+	var digits = "0123456789";
+
+	if (!inArray(site, gatewayLoxPNoneSites))
+	{
+		for (d in digits)
+		{
+			if (site.indexOf(d) >= 0)
+			{
+				alert("Site names may contain Roman numerals only.  Please verify your input.");
+				siteField.focus();
+				return false;
+			}
+	
+			if (site.indexOf('/') >= 0)
+			{
+				alert("Hybrid site names must be hyphen-delimited. Please verify your input");
+				siteField.focus();
+				return false;
+			}
+	
+			// Make sure the hybrid restriction site provided is of the form EnzI-EnzII, where EnzI and EnzII both match a REBASE enzyme value and are separated by hyphen, no spaces
+			var hyphenIndex = site.indexOf('-');
+	
+	// Removed April 30/08 - both sites don't need to be hybrid at creation, one can contain a single enzyme name
+	// 
+	// 		if (hyphenIndex < 0)
+	// 		{
+	// 			alert("Hybrid restriction site must be of the form 'SiteI-SiteII', where SiteI and SiteII both match REBASE enzyme names and are separated by a hyphen.  Please verify your input.");
+	// 			siteField.focus();
+	// 			return false;
+	// 		}
+	
+			if (hyphenIndex > 0)
+			{
+				var h1 = trimAll(site.substring(0, hyphenIndex));
+				var h2 = trimAll(site.substring(hyphenIndex+1));
+
+				var h1_matches = 0;
+				var h2_matches = 0;
+			
+				for (i = 0; i < enzymeList.options.length; i++)
+				{
+					enz = enzymeList.options[i].value;
+			
+					if (enz == h1)
+					{
+						h1_matches++;
+						break;
+					}
+				}
+			
+				for (i = 0; i < enzymeList.options.length; i++)
+				{
+					enz = enzymeList.options[i].value;
+			
+					if (enz == h2)
+					{
+						h2_matches++;
+						break;
+					}
+				}
+			
+				if ((h1_matches > 0) && (h2_matches > 0))
+				{
+					break;		// feb. 7/08
+				}
+				else
+				{
+					alert("Hybrid restriction site names are CASE-SENSITIVE, of the form 'SiteI-SiteII', where SiteI and SiteII both match REBASE enzyme names, SEPARATED BY A HYPHEN.  Please verify your input.");
+					siteField.focus();
+					return false;
+				}
+			}
+		}
+	}
+
+	return true;
+}*/
+
+
+function verifySites(sitesWarningsArray)
+{
+// Array('pv_fpcs_list':'pv_fpcs_warning', 'pv_tpcs_list':'pv_tpcs_warning', 'insert_fpcs_list':'insert_fpcs_warning', 'insert_tpcs_list':'insert_tpcs_warning')
+	radios = document.getElementsByName("warning_change_input");
+
+	for (i = 0; i < radios.length; i++)
+	{
+		if (radios[i].checked)
+		{
+			if ((radios[i].value == "restart") || (radios[i].value == "change_parents_warning_option"))
+				return true;
+
+			else if (radios[i].value == "make_hybrid_option")
+			{
+				for (listID in sitesWarningsArray)
+				{
+			// 		alert(listID);
+			// 		alert(sitesWarningsArray[listID]);
+			
+					if (document.getElementById(listID))
+					{
+						aList = document.getElementById(listID);
+						aSelVal = aList[aList.selectedIndex].value;
+			
+						if ((aSelVal.toLowerCase() == 'other') || (aSelVal == ''))
+						{
+							alert("Please fill in the values for all cloning sites");
+							aList.focus();
+			
+							aWarnID = sitesWarningsArray[listID];
+							aWarning = document.getElementById(aWarnID);
+			
+							if (aWarning)
+							{
+								aWarning.style.display = "inline";
+			
+								// hide the rest
+								allSpans = document.getElementsByTagName("SPAN");
+			
+								for (i=0; i < allSpans.length; i++)
+								{
+			aSpan = allSpans[i];
+			
+			// alert(aSpan);
+			// alert(aSpan.id);
+									if (aSpan && aSpan.id && (aSpan.id != aWarning.id))
+									{
+										aSpan.style.display = "none";
+									}
+								}
+							}
+			
+							return false;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return true;
+
+
+// 	fpcsListID = "fpcs_list_" + rType;
+// 	tpcsListID = "tpcs_list_" + rType;
+// 
+// 	fp_warn_name = "fpcs_warning_" + rType;
+// 	tp_warn_name = "tpcs_warning_" + rType;
+// 
+// 	fp_warning = document.getElementById(fp_warn_name);
+// 	tp_warning = document.getElementById(tp_warn_name);
+// 
+// 	radios = document.getElementsByName("warning_change_input");
+// 
+// 	for (i = 0; i < radios.length; i++)
+// 	{
+// 		if (radios[i].checked)
+// 		{
+// 			if (radios[i].value == "restart")
+// 				return true;
+// 		}
+// 	}
+// 
+// 	if (document.getElementById(fpcsListID))
+// 	{
+// 		fpcsList = document.getElementById(fpcsListID);
+// 
+// 		fpSelected = fpcsList[fpcsList.selectedIndex].value;
+// 
+// 		if ((fpSelected.toLowerCase() == 'other') || (fpSelected == ''))
+// 		{
+// 			alert("Please provide a specific value for the 5' cloning site.");
+// 			fpcsList.focus();
+// 
+// 			if (tp_warning)
+// 				tp_warning.style.display = "none";
+// 
+// 			if (fp_warning)
+// 				fp_warning.style.display = "inline";
+// 
+// 			return false;
+// 		}
+// 	}
+// 
+// 	if (document.getElementById(tpcsListID))
+// 	{
+// 		tpcsList = document.getElementById(tpcsListID);
+// 		tpSelected = tpcsList[tpcsList.selectedIndex].value;
+// 
+// 		if ((tpSelected.toLowerCase() == 'other') || (tpSelected == ''))
+// 		{
+// 			if (fp_warning)
+// 				fp_warning.style.display = "none";
+// 
+// 			if (tp_warning)
+// 				tp_warning.style.display = "inline";
+// 
+// 			alert("Please provide a specific value for the 3' cloning site.");
+// 			return false;
+// 		}
+// 	}
+// 
+// 	return true;
+}
+
+// Oct. 15/07: Verify restriction enzyme input format - make sure it contains no digits or slashes
+function verifyCloningSites(subtype)
+{
+	if (isNumeric(subtype))
+	{
+		var selectedFivePrime = document.getElementById("fpcs_list_" + subtype);
+		var selectedThreePrime = document.getElementById("tpcs_list_" + subtype);
+	}
+	else
+	{
+		var selectedFivePrime = document.getElementById("fpcs_list_1");
+		var selectedThreePrime = document.getElementById("tpcs_list_1");
+	}
+
+	// Aug. 14/09: last attempt
+	if (!selectedFivePrime)
+		var selectedFivePrime = document.getElementById("fpcs_list");
+
+	if (!selectedThreePrime)
+		var selectedThreePrime = document.getElementById("tpcs_list");
+
+	// Nov. 13/08
+	if (!selectedFivePrime)
+	{
+		alert("Please indicate 5' cloning site, including start and stop positions, or select 'None' if not known.");
+		return false;
+	}
+	
+	if (!selectedThreePrime)
+	{
+		alert("Please indicate 3' cloning site, including start and stop positions, or select 'None' if not known.");
+		return false;
+	}
+
+	var fpSelInd = selectedFivePrime.selectedIndex;
+	var fpSelVal = selectedFivePrime[fpSelInd].value;
+
+	// Feb. 5/08
+	var tpSelInd = selectedThreePrime.selectedIndex;
+	var tpSelVal = selectedThreePrime[tpSelInd].value;
+
+	var digits = "0123456789";
+
+	// feb 5/08 - hide name warning	
+	var tp_warning = document.getElementById("tp_warning");
+	var fp_warning = document.getElementById("fp_warning");
+
+	var name_warning = document.getElementById("insert_name_warning");
+
+	if (name_warning)
+		name_warning.style.display = "none";
+
+	var sequence_warning = document.getElementById("sequence_warning");
+
+	if (sequence_warning)
+		sequence_warning.style.display = "none";
+
+	if (subtype == "insert")
+	{
+ 		var oc_warning = document.getElementById("oc_warning");
+ 		var it_warning = document.getElementById("it_warning");
+
+		if (oc_warning)
+			oc_warning.style.display = "none";
+
+		if (it_warning)
+			it_warning.style.display = "none";
+	}
+
+	// Feb. 5/08: Make sure cloning sites are never left blank
+	if (fpSelVal == "")
+	{
+		// hide other warnings if shown
+		if (tp_warning)
+			tp_warning.style.display = "none";
+
+		alert("Please provide a value for the 5' restriction site (select option 'None' from the list if you do not wish to provide a cloning site at this moment)");
+
+		if (fp_warning)
+			fp_warning.style.display = "inline";
+
+		selectedFivePrime.focus();
+		return false;
+	}
+	else
+	{
+		// hide warnings
+		if (fp_warning)
+			fp_warning.style.display = "none";
+
+// 		document.getElementById("tp_warning").style.display = "none";
+	}
+
+	if (tpSelVal == "")
+	{
+		// hide 5' warning
+		if (fp_warning)
+			fp_warning.style.display = "none";
+
+		alert("Please provide a value for the 3' restriction site (select option 'None' from the list if you do not wish to provide a cloning site at this moment)");
+
+		if (tp_warning) 
+			tp_warning.style.display = "inline";
+
+		selectedThreePrime.focus();
+
+		return false;
+	}
+	else
+	{
+		// hide warnings
+// 		document.getElementById("fp_warning").style.display = "none";
+// 		document.getElementById("tp_warning").style.display = "none";
+
+		if (tp_warning) 
+			tp_warning.style.display = "none";
+	}
+
+	// DO THE CHECK IFFFFFFFFFFFF THERE'S A HYBRID INPUT - i.e. 'Other' value selected from the list and the textbox is visible
+	if (fpSelVal.toLowerCase() == 'other')
+	{
+		// hide empty sites warnings
+		document.getElementById("fp_warning").style.display = "none";
+		document.getElementById("tp_warning").style.display = "none";
+
+		// moved here Feb. 11/08
+		var fpTxt = document.getElementById("fpcs_txt_" + subtype);	
+		var fpSite = fpTxt.value;
+
+		// 5' site
+		for (d in digits)
+		{
+			if (fpSite.indexOf(d) >= 0)
+			{
+				alert("Site names may contain Roman numerals only.  Please verify your input.");
+				fpTxt.focus();
+				return false;
+			}
+	
+			if (fpSite.indexOf('/') >= 0)
+			{
+				alert("Hybrid site names must be hyphen-delimited. Please verify your input");
+				fpTxt.focus();
+				return false;
+			}
+	
+			// Make sure the hybrid restriction site provided is of the form EnzI-EnzII, where EnzI and EnzII both match a REBASE enzyme value and are separated by hyphen, no spaces
+			var hyphenIndex = fpSite.indexOf('-');
+	
+			if (hyphenIndex < 0)
+			{
+				alert("Hybrid restriction site must be of the form 'SiteI-SiteII', where SiteI and SiteII both match REBASE enzyme names and are separated by a hyphen.  Please verify your input for the 5' hybrid restriction site.");
+				fpTxt.focus();
+				return false;
+			}
+	
+			var fp_h1 = trimAll(fpSite.substring(0, hyphenIndex));
+			var fp_h2 = trimAll(fpSite.substring(hyphenIndex+1));
+		
+			var h1_matches = 0;
+			var h2_matches = 0;
+		
+			for (i = 0; i < selectedFivePrime.options.length; i++)
+			{
+				enz = selectedFivePrime.options[i].value;
+		
+				if (enz == fp_h1)
+				{
+					h1_matches++;
+					break;
+				}
+			}
+		
+			for (i = 0; i < selectedFivePrime.options.length; i++)
+			{
+				enz = selectedFivePrime.options[i].value;
+		
+				if (enz == fp_h2)
+				{
+					h2_matches++;
+					break;
+				}
+			}
+		
+			if ((h1_matches > 0) && (h2_matches > 0))
+			{
+// feb 7/08			return true;	//  NO!!! won't go to 3' check if returns
+				break;		// feb. 7/08
+			}
+			else
+			{
+				alert("Hybrid restriction site must be of the form 'SiteI-SiteII', where SiteI and SiteII both match REBASE enzyme names and are separated by a hyphen.  Please verify your input for the 5' hybrid restriction site.");
+				fpTxt.focus();
+				return false;
+			}
+		}
+	}
+
+	// 3' site
+	var tpTxt = document.getElementById("tpcs_txt_" + subtype);	// moved here feb. 11/08
+
+	if (tpTxt)
+		var tpSite = tpTxt.value;
+
+	if (tpSelVal.toLowerCase() == 'other')
+	{
+		for (d in digits)
+		{
+			if (tpSite.indexOf(d) >= 0)
+			{
+				alert("Site names may contain Roman numerals only.  Please verify your input.");
+				tpTxt.focus();
+				return false;
+			}
+	
+			if (tpSite.indexOf('/') >= 0)
+			{
+				alert("Hybrid sites must be hyphen-delimited. Please verify your input");
+				tpTxt.focus();
+				return false;
+			}
+	
+			// Make sure the hybrid restriction site provided is of the form EnzI-EnzII, where EnzI and EnzII both match a REBASE enzyme value and are separated by hyphen, no spaces
+			var hyphenIndex = tpSite.indexOf('-');
+	
+			if (hyphenIndex < 0)
+			{
+				alert("Hybrid restriction site must be of the form 'SiteI-SiteII', where SiteI and SiteII both match REBASE enzyme names and are separated by a hyphen.  Please verify your input for the 3' hybrid restriction site.");
+				tpTxt.focus();
+				return false;
+			}
+	
+			var tp_h1 = trimAll(tpSite.substring(0, hyphenIndex));
+			var tp_h2 = trimAll(tpSite.substring(hyphenIndex+1));
+		
+			var h1_matches = 0;
+			var h2_matches = 0;
+		
+			for (i = 0; i < selectedThreePrime.options.length; i++)
+			{
+				enz = selectedThreePrime.options[i].value;
+		
+				if (enz == tp_h1)
+				{
+					h1_matches++;
+					break;
+				}
+			}
+		
+			for (i = 0; i < selectedThreePrime.options.length; i++)
+			{
+				enz = selectedThreePrime.options[i].value;
+		
+				if (enz == tp_h2)
+				{
+					h2_matches++;
+					break;
+				}
+			}
+		
+			if ((h1_matches > 0) && (h2_matches > 0))
+			{
+// 				return true;	// NO!!
+				break;		// feb. 7/08
+			}
+			else
+			{
+				alert("Hybrid restriction site must be of the form 'SiteI-SiteII', where SiteI and SiteII both match REBASE enzyme names and are separated by a hyphen.  Please verify your input for the 3' hybrid restriction site.");
+				tpTxt.focus();
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
+
+// April 19/07, last updated June 3/08
+// On Vector creation warning page: if user decides to change input parent values, enable the appropriate textbox
+function enableOrDisableParents(rType, subtype)
+{
+	switch (rType)
+	{
+		case 'Vector':
+			var pvID;
+			var secondParent;
+
+			if ((subtype == 'nonrecomb') || (subtype == 'gateway_entry'))
+			{
+				pvID = document.getElementById("nr_pv_id");
+				secondParent = document.getElementById("insert");
+			}
+
+			else if ((subtype == 'recomb') || (subtype == 'gateway_expression'))
+			{
+				pvID = document.getElementById("rec_pv_id");
+				secondParent = document.getElementById("ipv_id");
+			}
+
+			var radio = document.getElementById("change_parents_warning_option");
+
+			if (radio.checked == true)
+			{
+				pvID.readOnly = false;
+				secondParent.readOnly = false;
+
+				pvID.style.color = "#FF0000";
+				secondParent.style.color = "#FF0000";
+
+				// May 14/08: Color cell white
+				pvID.style.backgroundColor = "#FFFFFF";
+				secondParent.style.backgroundColor = "#FFFFFF";
+
+				pvID.focus();	// No, removed April 30/08 - what if it's the Insert that needs changing?
+			}
+			else
+			{
+				pvID.readOnly = true;
+				secondParent.readOnly = true;
+
+				pvID.style.color = "brown";
+				secondParent.style.color = "brown";
+
+				// May 14/08: Color cell gray to emphasize that it's disabled
+				pvID.style.backgroundColor = "#E8E8E8";
+				secondParent.style.backgroundColor = "#E8E8E8";
+			}
+
+		break;
+		
+		case 'Insert':
+			var pvID = document.getElementById("piv_id");
+			var senseID = document.getElementById("sense_id");
+			var antisenseID = document.getElementById("antisense_id");
+
+			var radio = document.getElementById("change_parents_warning_option");
+
+			if (radio.checked == true)
+			{
+				pvID.readOnly = false;
+				senseID.readOnly = false;
+				antisenseID.readOnly = false;
+
+				pvID.style.color = "#FF0000";
+				senseID.style.color = "#FF0000";
+				antisenseID.style.color = "#FF0000";
+
+				// May 14/08: Color cell white
+				pvID.style.backgroundColor = "#FFFFFF";
+				senseID.style.backgroundColor = "#FFFFFF";
+				antisenseID.style.backgroundColor = "#FFFFFF";
+
+				pvID.focus();
+			}
+			else
+			{
+				pvID.readOnly = true;
+				senseID.readOnly = true;
+				antisenseID.readOnly = true;
+
+				pvID.style.color = "brown";
+				senseID.style.color = "brown";
+				antisenseID.style.color = "brown";
+
+				// May 14/08: Color cell gray to emphasize that it's disabled
+				pvID.style.backgroundColor = "#E8E8E8";
+				senseID.style.backgroundColor = "#E8E8E8";
+				antisenseID.style.backgroundColor = "#E8E8E8";
+			}
+
+		break;
+
+		case 'CellLine':
+			var pvID = document.getElementById("clpv_id");
+			var pclID = document.getElementById("pcl_id");
+
+			var radio = document.getElementById("change_parents_warning_option");
+
+			if (radio.checked == true)
+			{
+				pvID.readOnly = false;
+				pclID.readOnly = false;
+
+				pvID.style.color = "#FF0000";
+				pclID.style.color = "#FF0000";
+
+				// May 14/08: Color cell white
+				pvID.style.backgroundColor = "#FFFFFF";
+				pclID.style.backgroundColor = "#FFFFFF";
+
+				pvID.focus();
+			}
+			else
+			{
+				pvID.readOnly = true;
+				pclID.readOnly = true;
+
+				pvID.style.color = "brown";
+				pclID.style.color = "brown";
+
+				// May 14/08: Color cell gray to emphasize that it's disabled
+				pvID.style.backgroundColor = "#E8E8E8";
+				pclID.style.backgroundColor = "#E8E8E8";
+			}
+
+		break;
+	}
+}
+
+// August 22/07: Same as above but for recombination vector creation
+function enableOrDisableRecombParents()
+{
+	var pvID = document.getElementById("rec_pv_id");
+	var insertID = document.getElementById("ipv_id");
+	var radio = document.getElementById("change_parents_warning_option");
+
+	if (radio.checked == true)
+	{
+		pvID.readOnly = false;
+		insertID.readOnly = false;
+
+		pvID.style.color = "#FF0000";
+		insertID.style.color = "#FF0000";
+
+		// May 14/08: Color cell white
+		pvID.style.backgroundColor = "#FFFFFF";
+		insertID.style.backgroundColor = "#FFFFFF";
+
+		pvID.focus();
+	}
+	else
+	{
+		pvID.readOnly = true;
+		insertID.readOnly = true;
+
+		pvID.style.color = "brown";
+		insertID.style.color = "brown";
+
+		// May 14/08: Color cell gray to emphasize that it's disabled
+		pvID.style.backgroundColor = "#E8E8E8";
+		insertID.style.backgroundColor = "#E8E8E8";
+	}
+}
+
+// August 23/07: Same thing for cell lines
+function enableOrDisableCellLineParents()
+{
+	var pvID = document.getElementById("cl_pv_id");
+	var clID = document.getElementById("parent_cell_line_id");
+	var radio = document.getElementById("change_parents_warning_option");
+
+	if (radio.checked == true)
+	{
+		pvID.readOnly = false;
+		clID.readOnly = false;
+
+		pvID.style.color = "#FF0000";
+		clID.style.color = "#FF0000";
+
+		// May 14/08: Color cell white
+		pvID.style.backgroundColor = "#FFFFFF";
+		clID.style.backgroundColor = "#FFFFFF";
+
+		pvID.focus();
+	}
+	else
+	{
+		pvID.readOnly = true;
+		clID.readOnly = true;
+
+		pvID.style.color = "brown";
+		clID.style.color = "brown";
+
+		// May 14/08: Color cell gray to emphasize that it's disabled
+		pvID.style.backgroundColor = "#E8E8E8";
+		clID.style.backgroundColor = "#E8E8E8";
+	}
+}
+
+// Update Feb. 25/09: added 'reverseInsertCheckbox'
+function showHideCustomSites()
+{
+	var chkbox = document.getElementById("customSitesCheckbox");
+	var sitesTbl = document.getElementById("customCloningSites");
+
+	var reverseComplementCheckbox = document.getElementById("reverseComplementCheckbox");
+	var reverseInsertCheckbox = document.getElementById("reverseInserttCheckbox");
+
+	if (chkbox)
+	{
+		if (chkbox.checked)
+		{
+			sitesTbl.style.display = "block";
+		}
+		else
+		{
+			sitesTbl.style.display = "none";
+		}
+	}
+	else if (reverseComplementCheckbox)
+	{
+		if (reverseComplementCheckbox.checked)
+		{
+			sitesTbl.style.display = "block";
+		}
+		else
+		{
+			sitesTbl.style.display = "none";
+		}
+	}
+	else if (reverseInsertCheckbox)
+	{
+		if (reverseComplementCheckbox.checked)
+		{
+			sitesTbl.style.display = "block";
+		}
+		else
+		{
+			sitesTbl.style.display = "none";
+		}
+	}
+	else
+	{
+		var radio = document.getElementById("make_hybrid_option");
+
+		if (radio.checked == true)
+		{
+			sitesTbl.style.display = "block";
+		}
+		else
+		{
+			sitesTbl.style.display = "none";
+		}
+	}
+}
+
+function enableOrDisableSites()
+{
+// 	var sitesTbl = document.getElementById("cloning_sites");
+// 
+// 	if (sitesTbl && (sitesTbl.style.display == "none"))
+// 	{
+// 		sitesTbl.style.display = "inline";
+// 	}
+
+	var radio = document.getElementById("make_hybrid_option");
+	
+// 	var fpcs = document.getElementById("fpcs");
+// 	var tpcs = document.getElementById("tpcs");
+
+	var insert_fpcs = document.getElementById("fpcs_list");
+	var insert_tpcs = document.getElementById("tpcs_list");
+
+	var pv_fpcs = document.getElementById("fpcs_list_1");
+	var pv_tpcs = document.getElementById("tpcs_list_1");
+
+// 	var fpcs_comm = document.getElementById("fpcs_comment");
+// 	var tpcs_comm = document.getElementById("tpcs_comment");
+
+// 	var main_fpcs_captn = document.getElementById("main_5_site_caption");
+// 	var main_tpcs_captn = document.getElementById("main_3_site_caption");
+		
+// 	var alt_fpcs_captn = document.getElementById("alt_5_site_caption");
+// 	var alt_tpcs_captn = document.getElementById("alt_3_site_caption");
+
+	if (radio.checked == true)
+	{
+		pv_fpcs.disabled = false;
+		pv_tpcs.disabled = false;
+
+		insert_fpcs.disabled = false;
+		insert_tpcs.disabled = false;
+
+// 		fpcs.style.color = "#FF0000";
+// 		tpcs.style.color = "#FF0000";
+
+// 		fpcs_comm.style.display = "table-row";
+// 		tpcs_comm.style.display = "table-row";
+
+// 		main_fpcs_captn.style.display = "none";
+// 		main_tpcs_captn.style.display = "none";
+
+// 		alt_fpcs_captn.style.display = "table-row";
+// 		alt_tpcs_captn.style.display = "table-row";
+
+		// May 14/08: Color cell white
+// 		fpcs.style.backgroundColor = "#FFFFFF";
+// 		tpcs.style.backgroundColor = "#FFFFFF";
+		
+// 		fpcs.focus();
+	}
+	else
+	{
+		pv_fpcs.disabled = true;
+		pv_tpcs.disabled = true;
+
+		insert_fpcs.disabled = true;
+		insert_tpcs.disabled = true;
+
+// 		fpcs.style.color = "brown";
+// 		tpcs.style.color = "brown";
+
+// 		fpcs_comm.style.display = "none";
+// 		tpcs_comm.style.display = "none";
+		
+// 		main_fpcs_captn.style.display = "table-row";
+// 		main_tpcs_captn.style.display = "table-row";
+
+// 		alt_fpcs_captn.style.display = "none";
+// 		alt_tpcs_captn.style.display = "none";
+
+		// May 14/08: Color cell gray to emphasize that it's disabled
+// 		fpcs.style.backgroundColor = "#E8E8E8";
+// 		tpcs.style.backgroundColor = "#E8E8E8";
+	}
+}
+
+
+function getReagentType()
+{
+	var reagentSelectionBox = document.getElementById("reagentTypes");
+
+ 	if (reagentSelectionBox)
+ 	{
+		var rTypeSelectedInd = reagentSelectionBox.selectedIndex;
+		var reagentType = reagentSelectionBox[rTypeSelectedInd].value;
+
+		return reagentType;
+ 	}
+
+ 	return null;
+}
+
+
+
+// On Reagent creation, show appropriate subtype selection box depending on the main reagent type selected
+// Written March 27/07 by Marina
+function showReagentSubtype()
+{
+	reagentType = getReagentType();
+	subtype = getReagentSubtype(reagentType);
+
+	// Subtype lists
+	var vectorSubtypeBox = document.getElementById("vectorSubtypes");
+	var cellLineSubtypeBox = document.getElementById("cellLineSubtypes");
+
+	// April 11/07: Show association diagrams too
+	var vectorDiagm = document.getElementById("vector_types_diagram");
+	var cellLineDiagm = document.getElementById("cell_line_types_diagram");
+
+// 	var addReagentTypeTable = document.getElementById("addReagentTypeTable");
+
+	// and hide them initially
+	if (vectorDiagm)
+		vectorDiagm.style.display = "none";
+
+	if (cellLineDiagm)
+		cellLineDiagm.style.display = "none";
+
+	// Reset all subtype lists
+	if (vectorSubtypeBox)
+		vectorSubtypeBox.selectedIndex = 0;
+
+	if (cellLineSubtypeBox)
+		cellLineSubtypeBox.selectedIndex = 0;
+	
+	// Hide parents input form
+	var nonRecombParents = document.getElementById("nonrec_parents");
+	var recombParents = document.getElementById("recomb_parents");	
+	var cellLineParents = document.getElementById("stable_cell_line_parents");
+	
+	if (nonRecombParents)
+		nonRecombParents.style.display = "none";
+
+	if (recombParents)
+		recombParents.style.display = "none";
+
+	if (cellLineParents)
+		cellLineParents.style.display = "none";
+
+	// Hide Next button
+// 	var preload = document.getElementById("preload");
+// 	preload.style.display = "none";
+	
+	// General properties forms
+	var insertGeneralProps = document.getElementById("insert_general_props");
+// 	var oligoGeneralProps = document.getElementById("oligo_general_props");
+
+	var vectorGeneralProps = document.getElementById("vector_general_props");
+// 	var vectorBackgroundProps = document.getElementById("vector_backgroundProperty_table");
+
+	var cellLineGeneralProps = document.getElementById("cell_line_general_props");
+
+	// April 22/09
+	var vector_heading = document.getElementById("vector_heading");
+	var cell_line_heading = document.getElementById("cell_line_heading");
+
+	var reagentTypeCreateOther = document.getElementsByName("reagentTypeCreateOther");
+
+// 	alert(reagentType);
+
+	switch (reagentType)
+	{
+		case 'Vector':
+			if (cellLineGeneralProps)
+			{
+				cellLineGeneralProps.style.display = "none";
+			}
+
+			if (cellLineSubtypeBox)
+			{
+				cellLineSubtypeBox.style.display = "none";
+			}
+
+			vectorSubtypeBox.style.display = "table-row";
+			vectorDiagm.style.display = "table-row";
+			insertGeneralProps.style.display = "none";
+// 			oligoGeneralProps.style.display = "none";
+// 			addReagentTypeTable.style.display = "none";
+			vector_heading.style.display = "inline";
+			cell_line_heading.style.display = "none";
+
+			for (i=0; i < reagentTypeCreateOther.length; i++)
+			{
+				reagentTypeCreateOther[i].style.display="none";
+			}
+		break;
+		
+		case 'CellLine':
+			if (insertGeneralProps)
+			{
+				insertGeneralProps.style.display = "none";
+			}
+
+			if (vectorSubtypeBox)
+			{
+				vectorSubtypeBox.style.display = "none";
+			}
+
+			if (cellLineSubtypeBox)
+			{
+				cellLineSubtypeBox.style.display = "table-row";
+			}
+
+			if (cellLineDiagm)
+			{
+				cellLineDiagm.style.display = "table-row";
+			}
+
+			if (vectorGeneralProps)
+			{
+				vectorGeneralProps.style.display = "none";			
+			}
+			
+			if (vector_heading)
+			{
+				vector_heading.style.display = "none";
+			}
+
+			if (cell_line_heading)
+			{
+				cell_line_heading.style.display = "inline";
+			}
+
+			for (i=0; i < reagentTypeCreateOther.length; i++)
+			{
+				reagentTypeCreateOther[i].style.display="none";
+			}
+		break;
+		
+		case 'Insert':
+			if (cellLineGeneralProps)
+				cellLineGeneralProps.style.display = "none";
+
+			if (vectorSubtypeBox)
+				vectorSubtypeBox.style.display = "none";
+
+			if (cellLineSubtypeBox)
+				cellLineSubtypeBox.style.display = "none";
+
+			if (insertGeneralProps)
+				insertGeneralProps.style.display = "inline";
+// 			oligoGeneralProps.style.display = "none";
+
+			if (vectorGeneralProps)
+				vectorGeneralProps.style.display = "none";
+// 			vectorBackgroundProps.style.display = "none";
+
+			if (cellLineDiagm)
+				cellLineDiagm.style.display = "none";
+
+			if (vectorDiagm)
+				vectorDiagm.style.display = "none";
+
+// 			if (addReagentTypeTable)
+// 				addReagentTypeTable.style.display = "none";
+
+			if (vector_heading)
+			vector_heading.style.display = "none";
+
+			if (cell_line_heading)
+				cell_line_heading.style.display = "none";
+
+			for (i=0; i < reagentTypeCreateOther.length; i++)
+			{
+				reagentTypeCreateOther[i].style.display="none";
+			}
+		break;
+		
+// 		case 'Oligo':
+// 			vectorSubtypeBox.style.display = "none";
+// 			cellLineGeneralProps.style.display = "none";
+// 			cellLineSubtypeBox.style.display = "none";
+// 			oligoGeneralProps.style.display = "table-row";
+// 			insertGeneralProps.style.display = "none";
+// 			vectorGeneralProps.style.display = "none";
+// // 			vectorBackgroundProps.style.display = "none";
+// 			cellLineDiagm.style.display = "none";
+// 			vectorDiagm.style.display = "none";
+// 			addReagentTypeTable.style.display = "none";
+// 
+// 			vector_heading.style.display = "none";
+// 			cell_line_heading.style.display = "none";
+// 
+// 			for (i=0; i < reagentTypeCreateOther.length; i++)
+// 			{
+// 				reagentTypeCreateOther[i].style.display="none";
+// 			}
+// 		break;
+	
+		case 'Other':
+// alert("1");
+			// New reagent type addition
+			vectorSubtypeBox.style.display = "none";
+			cellLineSubtypeBox.style.display = "none";
+			cellLineGeneralProps.style.display = "none";
+			vectorGeneralProps.style.display = "none";
+// 			vectorBackgroundProps.style.display = "none";
+			cellLineDiagm.style.display = "none";
+			vectorDiagm.style.display = "none";
+// 			oligoGeneralProps.style.display = "none";
+			insertGeneralProps.style.display = "none";
+
+			vector_heading.style.display = "none";
+			cell_line_heading.style.display = "none";
+
+			for (i=0; i < reagentTypeCreateOther.length; i++)
+			{
+				reagentTypeCreateOther[i].style.display="none";
+			}
+
+// 			addReagentTypeTable.style.display = "inline";
+
+			if (document.getElementById("customizeReagentPropsTbl"))
+				document.getElementById("customizeReagentPropsTbl").style.display = "inline";
+
+			if (document.getElementById("propsSummaryTbl"))
+				document.getElementById("propsSummaryTbl").style.display = "inline";
+
+			document.getElementById("reagent_type_name").focus();
+		break;
+
+		default:
+			if (vectorSubtypeBox)
+				vectorSubtypeBox.style.display = "none";
+
+			if (cellLineGeneralProps)
+				cellLineGeneralProps.style.display = "none";
+
+			if (cellLineSubtypeBox)
+				cellLineSubtypeBox.style.display = "none";
+
+// 			if (oligoGeneralProps)
+// 				oligoGeneralProps.style.display = "none";
+
+			if (insertGeneralProps)
+				insertGeneralProps.style.display = "none";
+
+			if (vectorGeneralProps)
+				vectorGeneralProps.style.display = "none";
+
+			if (cellLineDiagm)
+				cellLineDiagm.style.display = "none";
+
+			if (vectorDiagm)
+				vectorDiagm.style.display = "none";
+
+// 			if (addReagentTypeTable)
+// 				addReagentTypeTable.style.display = "none";
+
+			if (vector_heading)
+				vector_heading.style.display = "none";
+
+			if (cell_line_heading)
+				cell_line_heading.style.display = "none";
+
+			for (i=0; i < reagentTypeCreateOther.length; i++)
+			{
+				var newTypeTbl = reagentTypeCreateOther[i];
+
+				if (newTypeTbl.id != "createReagentTbl_" + reagentType)
+					newTypeTbl.style.display="none";
+				else
+					newTypeTbl.style.display="inline";
+			}
+		break;
+	}
+}
+
+
+// June 9/09: Prevent form submission when user hits 'Enter'
+// Source: http://www.arraystudio.com/as-workshop/disable-form-submit-on-enter-keypress.html
+function disableEnterKey(e)
+{
+     var key;
+
+     if(window.event)
+          key = window.event.keyCode;     //IE
+     else
+          key = e.which;     //firefox
+
+     if(key == 13)
+          return false;
+     else
+          return true;
+}
+
+// If the type of reagent being created requires parent values to be filled in, show form to fill the apropriate parent values based on the reagent type selected
+// Only applies to Vectors and Cell Lines
+// Updated June 8/08: Print different headings
+// Updated Feb. 11/09: Show reverse complement and customize sites options for non-recombination vectors only
+function showParents(listID)
+{
+	var currSelected = document.getElementById(listID);
+	
+	var subtypeSelectedInd = currSelected.selectedIndex;
+	var subtypeSelected = currSelected[subtypeSelectedInd].value;
+
+	var nonRecombParents = document.getElementById("nonrec_parents");
+	var recombParents = document.getElementById("recomb_parents");	
+	var cellLineParents = document.getElementById("stable_cell_line_parents");
+	
+	// June 8/08
+	var creatorTitle = document.getElementById("creator_title");
+	var gwExpressionTitle = document.getElementById("gw_expression_title");
+
+	// Sept. 8/08
+	var recombHdr = document.getElementById("recomb_hdr");
+	var gwExprHdr = document.getElementById("gw_expr_hdr");
+
+	// Sept. 9/08
+	var nonrecHdr = document.getElementById("nonrecomb_hdr");
+	var gwEntryHdr = document.getElementById("gw_entry_hdr");
+
+	// Sept. 9/08
+	var nonrecTitle = document.getElementById("nonrec_title");
+
+	var gwEntryTitle = document.getElementById("gw_entry_title");
+
+	var nonrecVectorDiagm = document.getElementById("custom_sites_diagm");
+
+	// Sept. 9/08
+	var nonrecPV = document.getElementById("nonrec_pv");
+	var gwParentDonor = document.getElementById("gw_pv");
+
+	var creatorPV = document.getElementById("creator_acceptor_pv");
+	var gwExpressionDestinationPV = document.getElementById("destination_pv");
+
+	var creatorDonorIPV = document.getElementById("creator_donor_ipv");
+	var gwDonorIPV = document.getElementById("gateway_donor_ipv");
+
+	// Vector general properties form
+	var vectorGeneralProps = document.getElementById("vector_general_props");
+	
+	// Cell Line general properties form
+	var cellLineGeneralProps = document.getElementById("cell_line_general_props");
+
+	// Feb, 11/09: Show reverse checkbox and custom sites for non-recombination vectors only
+	var reverseComplementCheckbox = document.getElementById("reverseComplementCheckbox");
+	var customSitesCheckbox = document.getElementById("customSitesCheckbox");
+	var customize_sites_text = document.getElementById("customize_sites_text");
+	var rc_text = document.getElementById("rc_text");
+	var rc_caption = document.getElementById("rc_caption");
+
+	/*
+		Rules for showing parent types:
+		
+		- Non-Recombination Vector: Parent Vector ID, Insert ID
+		- Recombination Vector: Parent Vector ID, Insert Parent Vector ID
+		
+		- Gateway ENTRY Vector: SAME AS NON-RECOMBINATION: Parent Vector ID, Insert ID
+		- Gateway EXPRESSION Vector: SAME AS RECOMBINATION: Parent Vector ID, Insert Parent Vector ID
+		
+		- Stable Cell Line: Parent Vector ID, Parent Cell Line ID
+	*/
+	switch (subtypeSelected)
+	{
+		case 'nonrecomb':
+			if (nonRecombParents)
+			{
+				nonRecombParents.style.display = "table-row";
+			}
+
+			if (recombParents)
+			{
+				recombParents.style.display = "none";
+			}
+
+			if (cellLineParents)
+			{
+				cellLineParents.style.display = "none";
+			}
+
+// 			preload.style.display = "table-row";
+
+			if (vectorGeneralProps)
+			{
+				vectorGeneralProps.style.display = "none";
+			}
+
+// 			vectorBackgroundProps.style.display = "none";
+			
+			if (cellLineGeneralProps)
+			{
+				cellLineGeneralProps.style.display = "none";
+			}
+
+			// Sept. 9/08
+			if (nonrecHdr)
+			{
+				nonrecHdr.style.display = "inline";
+			}
+
+			if (gwEntryHdr)
+			{
+				gwEntryHdr.style.display = "none";
+			}
+
+			// Sept. 9/08
+			if (nonrecTitle)
+			{
+				nonrecTitle.style.display = "inline";	
+			}
+
+			if (gwEntryTitle)
+			{
+				gwEntryTitle.style.display = "none";
+			}
+
+			// Sept. 9/08
+			if (nonrecPV)
+			{
+				nonrecPV.style.display = "inline";	
+			}
+
+			if (gwParentDonor)
+			{
+				gwParentDonor.style.display = "none";
+			}
+
+			// June 8/08
+			if (creatorTitle)
+			{
+				creatorTitle.style.display = "none";
+			}
+
+			if (gwExpressionTitle)
+			{
+				gwExpressionTitle.style.display = "none";
+			}
+
+			if (creatorPV)
+			{
+				creatorPV.style.display = "none";
+			}
+
+			if (gwExpressionDestinationPV)
+			{
+				gwExpressionDestinationPV.style.display = "none";
+			}
+
+			if (creatorDonorIPV)
+			{
+				creatorDonorIPV.style.display = "none";	
+			}
+
+			if (gwDonorIPV)
+			{
+				gwDonorIPV.style.display = "none";
+			}
+
+			// Feb. 11/09
+			if (reverseComplementCheckbox)
+				reverseComplementCheckbox.style.display = "inline";
+
+			if (customSitesCheckbox)
+				customSitesCheckbox.style.display = "inline";
+
+			if (customize_sites_text)
+				customize_sites_text.style.display = "inline";
+
+			if (rc_text)
+				rc_text.style.display = "inline";
+
+			if (rc_caption)
+				rc_caption.style.display = "inline";
+
+			// and hide them initially
+			if (nonrecVectorDiagm)
+				nonrecVectorDiagm.style.display = "inline";
+		break;
+		
+		case 'recomb':
+			nonRecombParents.style.display = "none";
+			recombParents.style.display = "table-row";
+			cellLineParents.style.display = "none";
+// 			preload.style.display = "table-row";
+			vectorGeneralProps.style.display = "none";
+// 			vectorBackgroundProps.style.display = "none";
+			cellLineGeneralProps.style.display = "none";
+			
+			// Sept. 8/08
+			recombHdr.style.display = "inline";
+			gwExprHdr.style.display = "none";
+
+			// June 8/08
+			creatorTitle.style.display = "inline";
+			gwExpressionTitle.style.display = "none";
+
+			creatorPV.style.display = "inline";
+			gwExpressionDestinationPV.style.display = "none";
+			
+			creatorDonorIPV.style.display = "inline";
+			gwDonorIPV.style.display = "none";
+
+			// Feb. 11/09: Hide custom sites and reverse complement options
+			if (reverseComplementCheckbox)
+				reverseComplementCheckbox.style.display = "none";
+
+			if (customSitesCheckbox)
+				customSitesCheckbox.style.display = "none";
+
+			if (customize_sites_text)
+				customize_sites_text.style.display = "none";
+
+			if (rc_text)
+				rc_text.style.display = "none";
+
+			if (rc_caption)
+				rc_caption.style.display = "none";
+
+			// hide non-recomb vector diagm
+			if (nonrecVectorDiagm)
+				nonrecVectorDiagm.style.display = "none";
+		break;
+		
+		case 'gateway_entry':
+
+			if (nonRecombParents)
+			{
+				nonRecombParents.style.display = "table-row";	
+			}
+
+			if (recombParents)
+			{
+				recombParents.style.display = "none";
+			}
+
+			if (cellLineParents)
+			{
+				cellLineParents.style.display = "none";
+			}
+
+// 			preload.style.display = "table-row";
+
+			if (vectorGeneralProps)
+			{
+				vectorGeneralProps.style.display = "none";
+			}
+
+// 			vectorBackgroundProps.style.display = "none";
+
+			if (cellLineGeneralProps)
+			{
+				cellLineGeneralProps.style.display = "none";
+			}
+
+			// Sept. 9/08
+			if (nonrecHdr)
+			{
+				nonrecHdr.style.display = "none";
+			}
+
+			if (gwEntryHdr)
+			{
+				gwEntryHdr.style.display = "inline";
+			}
+
+			// Sept. 9/08
+			if (nonrecTitle)
+			{
+				nonrecTitle.style.display = "none";
+			}
+
+			if (gwEntryTitle)
+			{
+				gwEntryTitle.style.display = "inline";
+			}
+
+			// Sept. 9/08
+			if (nonrecPV)
+			{
+				nonrecPV.style.display = "none";
+			}
+
+			if (gwParentDonor)
+			{
+				gwParentDonor.style.display = "inline";
+			}
+
+			// June 8/08
+			if (creatorTitle)
+			{
+				creatorTitle.style.display = "none";
+			}
+
+			if (gwExpressionTitle)
+			{
+				gwExpressionTitle.style.display = "none";
+			}
+
+			if (creatorPV)
+			{
+				creatorPV.style.display = "none";
+			}
+
+			if (gwExpressionDestinationPV)
+			{
+				gwExpressionDestinationPV.style.display = "none";
+			}
+
+			if (creatorDonorIPV)
+			{
+				creatorDonorIPV.style.display = "none";
+			}
+
+			if (gwDonorIPV)
+			{
+				gwDonorIPV.style.display = "none";
+			}
+
+			// Feb. 11/09: Hide custom sites and reverse complement options
+			if (reverseComplementCheckbox)
+				reverseComplementCheckbox.style.display = "none";
+
+			if (customSitesCheckbox)
+				customSitesCheckbox.style.display = "none";
+
+			if (customize_sites_text)
+				customize_sites_text.style.display = "none";
+
+			if (rc_text)
+				rc_text.style.display = "none";
+
+			if (rc_caption)
+				rc_caption.style.display = "none";
+
+			if (nonrecVectorDiagm)
+				nonrecVectorDiagm.style.display = "none";
+		break;
+		
+		case 'gateway_expression':
+			nonRecombParents.style.display = "none";
+			recombParents.style.display = "table-row";
+			cellLineParents.style.display = "none";
+// 			preload.style.display = "table-row";
+			vectorGeneralProps.style.display = "none";
+// 			vectorBackgroundProps.style.display = "none";
+			cellLineGeneralProps.style.display = "none";
+			
+			// June 8/08
+			creatorTitle.style.display = "none";
+			gwExpressionTitle.style.display = "inline";
+			
+			// Sept. 8/08
+			recombHdr.style.display = "none";
+			gwExprHdr.style.display = "inline";
+
+			creatorPV.style.display = "none";
+			gwExpressionDestinationPV.style.display = "inline";
+			
+			creatorDonorIPV.style.display = "none";
+			gwDonorIPV.style.display = "inline";
+
+			// Feb. 11/09: Hide custom sites and reverse complement options
+			if (reverseComplementCheckbox)
+				reverseComplementCheckbox.style.display = "none";
+
+			if (customSitesCheckbox)
+				customSitesCheckbox.style.display = "none";
+
+			if (customize_sites_text)
+				customize_sites_text.style.display = "none";
+
+			if (rc_text)
+				rc_text.style.display = "none";
+
+			if (rc_caption)
+				rc_caption.style.display = "none";
+
+			if (nonrecVectorDiagm)
+				nonrecVectorDiagm.style.display = "none";
+		break;
+		
+		case 'novel':
+			// For Novel Vector, the procedure is the same as for Inserts and Oligos: Just show general properties form, no parents:
+			nonRecombParents.style.display = "none";
+			recombParents.style.display = "none";
+			cellLineParents.style.display = "none";
+			vectorGeneralProps.style.display = "table-row";
+// 			vectorBackgroundProps.style.display = "table-row";
+// 			preload.style.display = "none";
+			cellLineGeneralProps.style.display = "none";
+
+			// June 8/08
+			creatorTitle.style.display = "none";
+			gwExpressionTitle.style.display = "none";
+			
+			creatorPV.style.display = "none";
+			gwExpressionDestinationPV.style.display = "none";
+			
+			creatorDonorIPV.style.display = "none";
+			gwDonorIPV.style.display = "none";
+
+			// Feb. 11/09: Hide custom sites and reverse complement options
+			if (reverseComplementCheckbox)
+				reverseComplementCheckbox.style.display = "none";
+
+			if (customSitesCheckbox)
+				customSitesCheckbox.style.display = "none";
+
+			if (customize_sites_text)
+				customize_sites_text.style.display = "none";
+
+			if (rc_text)
+				rc_text.style.display = "none";
+
+			if (rc_caption)
+				rc_caption.style.display = "none";
+		break;
+		
+		case 'stable_cell_line':
+			cellLineParents.style.display = "table-row";
+			nonRecombParents.style.display = "none";
+			recombParents.style.display = "none";
+// 			preload.style.display = "table-row";
+			vectorGeneralProps.style.display = "none";
+// 			vectorBackgroundProps.style.display = "none";
+			cellLineGeneralProps.style.display = "none";
+
+			// June 8/08
+			creatorTitle.style.display = "none";
+			gwExpressionTitle.style.display = "none";
+			
+			creatorPV.style.display = "none";
+			gwExpressionDestinationPV.style.display = "none";
+			
+			creatorDonorIPV.style.display = "none";
+			gwDonorIPV.style.display = "none";
+
+		break;
+
+		case 'parent_cell_line':
+			cellLineGeneralProps.style.display = "table-row";
+			nonRecombParents.style.display = "none";
+			recombParents.style.display = "none";
+			cellLineParents.style.display = "none";
+			vectorGeneralProps.style.display = "none";
+// 			vectorBackgroundProps.style.display = "none";
+
+			// June 8/08
+			creatorTitle.style.display = "none";
+			gwExpressionTitle.style.display = "none";
+			
+			creatorPV.style.display = "none";
+			gwExpressionDestinationPV.style.display = "none";
+			
+			creatorDonorIPV.style.display = "none";
+			gwDonorIPV.style.display = "none";
+
+			// Feb. 11/09: Hide custom sites and reverse complement options
+			if (reverseComplementCheckbox)
+				reverseComplementCheckbox.style.display = "none";
+
+			if (customSitesCheckbox)
+				customSitesCheckbox.style.display = "none";
+
+			if (customize_sites_text)
+				customize_sites_text.style.display = "none";
+
+			if (rc_text)
+				rc_text.style.display = "none";
+
+			if (rc_caption)
+				rc_caption.style.display = "none";
+		break;
+		
+		default:
+			nonRecombParents.style.display = "none";
+			recombParents.style.display = "none";
+			cellLineParents.style.display = "none";
+			cellLineGeneralProps.style.display = "none";
+			vectorGeneralProps.style.display = "none";
+// 			vectorBackgroundProps.style.display = "none";
+
+			// June 8/08
+			creatorTitle.style.display = "none";
+			gwExpressionTitle.style.display = "none";
+			
+			creatorPV.style.display = "none";
+			gwExpressionDestinationPV.style.display = "none";
+			
+			creatorDonorIPV.style.display = "none";
+			gwDonorIPV.style.display = "none";
+
+			// Feb. 11/09: Hide custom sites and reverse complement options
+			if (reverseComplementCheckbox)
+				reverseComplementCheckbox.style.display = "none";
+
+			if (customSitesCheckbox)
+				customSitesCheckbox.style.display = "none";
+
+			if (customize_sites_text)
+				customize_sites_text.style.display = "none";
+
+			if (rc_text)
+				rc_text.style.display = "none";
+
+			if (rc_caption)
+				rc_caption.style.display = "none";
+		break;
+	}
+}
+
+
+function getReagentSubtype(reagentType)
+{
+	var subtypeSelectedInd = "";
+	var subtype = "";
+	
+	switch (reagentType)
+	{
+		case 'Vector':
+			
+			var vectorSubtypeBox = document.getElementById("vectorSubtypes");
+
+			if (vectorSubtypeBox)
+			{
+				subtypeSelectedInd = vectorSubtypeBox.selectedIndex;
+				subtype = vectorSubtypeBox[subtypeSelectedInd].value;
+	
+				return subtype;
+			}
+		break;
+		
+		case 'Insert':
+			return "";
+		break;
+		
+		case 'Oligo':
+			return "";
+		break;
+		
+		case 'CellLine':
+			var cellLineSubtypeBox = document.getElementById("cellLineSubtypes");
+
+			if (cellLineSubtypeBox)
+			{
+				subtypeSelectedInd = cellLineSubtypeBox.selectedIndex;
+				subtype = cellLineSubtypeBox[subtypeSelectedInd].value;
+			}
+			
+			return subtype;
+		break;
+		
+		default:
+			return "";
+		break;
+	}
+}
+
+// Written May 11/08
+function verifyReagentIntroCreation(rType, subtype)
+{
+	if (document.getElementById("cancel_set"))
+	{
+		var cancelSet = document.getElementById("cancel_set").value;
+	}
+	else
+	{
+		var cancelSet = 0;
+	}
+
+	if (cancelSet != 1)
+	{
+		if (rType == 'Insert')
+		{
+			subtype = "";
+	
+			// Type of Insert can never be empty
+// 			var itype_list = document.getElementById("itype_list");
+			var itype_list = document.getElementById("Insert_Type of insert_prop");
+			var itype_selectedInd = itype_list.selectedIndex;
+		
+// 			var oc_list = document.getElementById("oc_list");
+			var oc_list = document.getElementById("Insert_Open/Closed_prop");
+			var oc_selectedInd = oc_list.selectedIndex;
+		
+// 			var oc_warning = document.getElementById("oc_warning");
+			var oc_warning = document.getElementById("Insert_Open/Closed_warning");
+// 			var it_warning = document.getElementById("it_warning");
+			var it_warning = document.getElementById("Insert_Type of insert_warning");
+			
+			if (verifyReagentName(rType, subtype) && verifyStatus(rType) && verifyPacket(rType))
+			{
+				// No Insert Type selected
+				if ((itype_selectedInd == 0) && (itype_list[itype_selectedInd].value == ""))
+				{
+					alert("You must select a Type of Insert to continue");
+					itype_list.focus();
+					it_warning.style.display = "inline";
+					oc_warning.style.display = "none";
+		
+					return false;
+				}
+				else
+				{
+					it_warning.style.display = "none";
+		
+					// If insert type is filled in, check open/closed
+					var itype_selectedValue = itype_list[itype_selectedInd].value;
+		
+					if ((itype_selectedValue != "cDNA with UTRs") && (itype_selectedValue != "DNA Fragment") && (itype_selectedValue != "None"))
+					{
+						// must have an open/closed value
+						oc_sel_val = oc_list[oc_selectedInd].value;
+		
+						if (oc_sel_val == "")
+						{
+							alert("You must select an Open/Closed value to continue");
+							oc_list.focus();
+							oc_warning.style.display = "inline";
+							return false;
+						}
+					}
+					else 	// added May 28/07 to hide warning if showing from previous error
+					{
+						if (oc_warning.style.display == "inline")
+						{
+							oc_warning.style.display = "none";
+						}
+					}
+		
+					return checkMandatoryProps(rType);
+				}
+			}
+	
+			return false;
+		}
+
+		return (verifyReagentName(rType, subtype) && verifyStatus(rType) && verifyPacket(rType) && checkMandatoryProps(rType));
+	}
+}
+
+
+// Verifies Parent input fields are filled in properly on Vector creation
+// e.g. both are non-empty, Vector ID not given where Insert ID is expected & v.v., etc.
+function verifyParents(rType, subtype)
+{
+	var rType = ((rType == null) || (rType == '')) ? getReagentType() : rType;
+	var subtype = ((subtype == null) || (subtype == '')) ? getReagentSubtype(rType) : subtype;
+	
+	if (document.getElementById("process_error_restart") && document.getElementById("process_error_restart").checked)
+	{
+		return true;
+	}
+
+	switch (subtype)
+	{
+		case 'nonrecomb':
+
+			// parent vector and insert
+			parentVector = trimAll(document.getElementById("nr_pv_id").value);
+			insertID = trimAll(document.getElementById("insert").value);
+			
+			// verify that parent Vector ID starts with V and that the group ID is a valid numerical index
+			if (parentVector.length == 0)
+			{
+				alert("Please enter a Parent Vector OpenFreezer ID, or select the \"Novel Vector\" option to create a Vector without pre-existing parents");
+				document.getElementById("nr_pv_id").focus();
+				return false;	
+			}
+			else if (insertID.length == 0)
+			{
+				alert("Please enter an Insert OpenFreezer ID, or select the \"Novel Vector\" option to create a Vector without pre-existing parents");
+				document.getElementById("insert").focus();
+				return false;
+			}
+			else if (parentVector.substring(0,1).toLowerCase() != 'v')
+			{
+				alert("Incorrect prefix for OpenFreezer Parent Vector ID (must be \"V\" or \"v\")")
+				document.getElementById("nr_pv_id").focus();
+				return false;
+			}
+			else if (insertID.substring(0,1).toLowerCase() != 'i')
+			{
+				alert("Incorrect prefix for OpenFreezer Insert ID, must be \"I\" or \"i\"")
+				document.getElementById("insert").focus();
+				return false;
+			}
+			else if (!isNumeric(parentVector.substring(1)))
+			{
+				alert("The identifier portion of the OpenFreezer Parent Vector ID must be a non-zero number, please verify your input")
+				document.getElementById("nr_pv_id").focus();
+				return false;
+			}
+			else if (!isNumeric(insertID.substring(1)))
+			{
+				alert("The identifier portion of the OpenFreezer Insert ID must be a non-zero number, please verify your input")
+				document.getElementById("insert").focus();
+				return false;
+			}
+			// July 4/08: Since function "isNumeric" includes a decimal point in the set of allowed characters, add a separate check for it
+			else if (parentVector.substring(1).indexOf(".") >= 0)
+			{
+				alert("The identifier portion of the OpenFreezer Parent Vector ID must be a non-zero number, please verify your input")
+				document.getElementById("nr_pv_id").focus();
+				return false;
+			}
+			// July 4/08: Separate error check for the decimal point
+			else if (insertID.substring(1).indexOf(".") >= 0)
+			{
+				alert("The identifier portion of the OpenFreezer Insert ID must be a non-zero number, please verify your input")
+				document.getElementById("insert").focus();
+				return false;
+			}
+		break;
+		
+		case 'recomb':
+
+			// parent vector and insert parent vector
+			parentVector = trimAll(document.getElementById("rec_pv_id").value);
+// May 30/08		insertParentVector = trimAll(document.getElementById("insert_parent_vector_id").value);
+
+			if (document.getElementById("ipv_id"))
+				insertParentVector = trimAll(document.getElementById("ipv_id").value);		// May 30/08
+			else
+				insertParentVector = trimAll(document.getElementById("insert_parent_vector_id").value);
+			
+			if (parentVector.length == 0)
+			{
+				alert("Please enter a Parent Vector OpenFreezer ID, or select the \"Novel Vector\" option to create a Vector without pre-existing parents");
+				document.getElementById("rec_pv_id").focus();
+				return false;	
+			}
+			else if (insertParentVector.length == 0)
+			{
+				alert("Please enter an Insert Parent Vector OpenFreezer ID, or select the \"Novel Vector\" option to create a Vector without pre-existing parents");
+				document.getElementById("insert_parent_vector_id").focus();
+				return false;
+			}
+			else if (parentVector.substring(0,1).toLowerCase() != 'v')
+			{
+				alert("Incorrect prefix for OpenFreezer Parent Vector ID (must be \"V\" or \"v\")")
+				document.getElementById("rec_pv_id").focus();
+				return false;
+			}
+			else if (insertParentVector.substring(0,1).toLowerCase() != 'v')
+			{
+				alert("Incorrect prefix for OpenFreezer Insert Parent Vector ID, must be \"V\" or \"v\"")
+				document.getElementById("insert_parent_vector_id").focus();
+				return false;
+			}
+			else if (!isNumeric(parentVector.substring(1)))
+			{
+				alert("The identifier portion of the OpenFreezer Parent Vector ID must be a non-zero number, please verify your input")
+				document.getElementById("rec_pv_id").focus();
+				return false;
+			}
+			else if (!isNumeric(insertParentVector.substring(1)))
+			{
+				alert("The identifier portion of the OpenFreezer Insert Parent Vector ID must be a non-zero number, please verify your input")
+				document.getElementById("insert_parent_vector_id").focus();
+				return false;
+			}
+			// July 4/08: Separate error check for the decimal point
+			else if (parentVector.substring(1).indexOf(".") >= 0)
+			{
+				alert("The identifier portion of the OpenFreezer Parent Vector ID must be a non-zero number, please verify your input")
+				document.getElementById("rec_pv_id").focus();
+				return false;
+			}
+			// July 4/08: Separate error check for the decimal point
+			else if (insertParentVector.substring(1).indexOf(".") >= 0)
+			{
+				alert("The identifier portion of the OpenFreezer Insert Parent Vector ID must be a non-zero number, please verify your input")
+				document.getElementById("insert_parent_vector_id").focus();
+				return false;
+			}
+		break;
+		
+		case 'gateway_entry':
+		
+			// parent vector and insert - SAME AS NON-RECOMB
+			parentVector = trimAll(document.getElementById("nr_pv_id").value);
+			insertID = trimAll(document.getElementById("insert").value);
+			
+			// verify that parent Vector ID starts with V and that the group ID is a valid numerical index
+			if (parentVector.length == 0)
+			{
+				alert("Please enter a Parent Vector OpenFreezer ID, or select the \"Novel Vector\" option to create a Vector without pre-existing parents");
+				document.getElementById("nr_pv_id").focus();
+				return false;	
+			}
+			else if (insertID.length == 0)
+			{
+				alert("Please enter an Insert OpenFreezer ID, or select the \"Novel Vector\" option to create a Vector without pre-existing parents");
+				document.getElementById("insert").focus();
+				return false;
+			}
+			else if (parentVector.substring(0,1).toLowerCase() != 'v')
+			{
+				alert("Incorrect prefix for OpenFreezer Parent Vector ID (must be \"V\" or \"v\")")
+				document.getElementById("nr_pv_id").focus();
+				return false;
+			}
+			else if (insertID.substring(0,1).toLowerCase() != 'i')
+			{
+				alert("Incorrect prefix for OpenFreezer Insert ID, must be \"I\" or \"i\"")
+				document.getElementById("insert").focus();
+				return false;
+			}
+			else if (!isNumeric(parentVector.substring(1)))
+			{
+				alert("The identifier portion of the OpenFreezer Parent Vector ID must be a non-zero number, please verify your input")
+				document.getElementById("nr_pv_id").focus();
+				return false;
+			}
+			else if (!isNumeric(insertID.substring(1)))
+			{
+				alert("The identifier portion of the OpenFreezer Insert ID must be a non-zero number, please verify your input")
+				document.getElementById("insert").focus();
+				return false;
+			}
+			// July 4/08: Since function "isNumeric" includes a decimal point in the set of allowed characters, add a separate check for it
+			else if (parentVector.substring(1).indexOf(".") >= 0)
+			{
+				alert("The identifier portion of the OpenFreezer Parent Vector ID must be a non-zero number, please verify your input")
+				document.getElementById("nr_pv_id").focus();
+				return false;
+			}
+			// July 4/08: Separate error check for the decimal point
+			else if (insertID.substring(1).indexOf(".") >= 0)
+			{
+				alert("The identifier portion of the OpenFreezer Insert ID must be a non-zero number, please verify your input")
+				document.getElementById("insert").focus();
+				return false;
+			}
+		break;
+		
+		case 'gateway_expression':
+		
+			// parent vector and insert parent vector - SAME AS RECOMB
+			parentVector = trimAll(document.getElementById("rec_pv_id").value);
+			insertParentVector = trimAll(document.getElementById("insert_parent_vector_id").value);
+			
+			if (parentVector.length == 0)
+			{
+				alert("Please enter a Parent Vector OpenFreezer ID, or select the \"Novel Vector\" option to create a Vector without pre-existing parents");
+				document.getElementById("rec_pv_id").focus();
+				return false;	
+			}
+			else if (insertParentVector.length == 0)
+			{
+				alert("Please enter an Insert Parent Vector OpenFreezer ID, or select the \"Novel Vector\" option to create a Vector without pre-existing parents");
+				document.getElementById("insert_parent_vector_id").focus();
+				return false;
+			}
+			else if (parentVector.substring(0,1).toLowerCase() != 'v')
+			{
+				alert("Incorrect prefix for OpenFreezer Parent Vector ID (must be \"V\" or \"v\")")
+				document.getElementById("rec_pv_id").focus();
+				return false;
+			}
+			else if (insertParentVector.substring(0,1).toLowerCase() != 'v')
+			{
+				alert("Incorrect prefix for OpenFreezer Insert Parent Vector ID, must be \"V\" or \"v\"")
+				document.getElementById("insert_parent_vector_id").focus();
+				return false;
+			}
+			else if (!isNumeric(parentVector.substring(1)))
+			{
+				alert("The identifier portion of the OpenFreezer Parent Vector ID must be a non-zero number, please verify your input")
+				document.getElementById("rec_pv_id").focus();
+				return false;
+			}
+			else if (!isNumeric(insertParentVector.substring(1)))
+			{
+				alert("The identifier portion of the OpenFreezer Insert Parent Vector ID must be a non-zero number, please verify your input")
+				document.getElementById("insert_parent_vector_id").focus();
+				return false;
+			}
+			// July 4/08: Separate error check for the decimal point
+			else if (parentVector.substring(1).indexOf(".") >= 0)
+			{
+				alert("The identifier portion of the OpenFreezer Parent Vector ID must be a non-zero number, please verify your input")
+				document.getElementById("rec_pv_id").focus();
+				return false;
+			}
+			// July 4/08: Separate error check for the decimal point
+			else if (insertParentVector.substring(1).indexOf(".") >= 0)
+			{
+				alert("The identifier portion of the OpenFreezer Insert Parent Vector ID must be a non-zero number, please verify your input")
+				document.getElementById("insert_parent_vector_id").focus();
+				return false;
+			}
+		break;
+		
+		case 'stable_cell_line':
+		
+			// parent vector and parent cell line
+			parentVector = trimAll(document.getElementById("cl_pv_id").value);
+			parentCellLine = trimAll(document.getElementById("parent_cell_line_id").value);
+			
+			if (parentVector.length == 0)
+			{
+				alert("Please enter a Parent Vector OpenFreezer ID, or select the \"Parent Cell Line\" option to create a Cell Line without pre-existing parents");
+				document.getElementById("cl_pv_id").focus();
+				return false;	
+			}
+			else if (parentCellLine.length == 0)
+			{
+				alert("Please enter a Parent Cell Line OpenFreezer ID, or select the \"Parent Cell Line\" option to create a Cell Line without pre-existing parents");
+				document.getElementById("parent_cell_line_id").focus();
+				return false;
+			}
+			else if (parentVector.substring(0,1).toLowerCase() != 'v')
+			{
+				alert("Incorrect prefix for OpenFreezer Parent Vector ID (must be \"V\" or \"v\")")
+				document.getElementById("cl_pv_id").focus();
+				return false;
+			}
+			else if (parentCellLine.substring(0,1).toLowerCase() != 'c')
+			{
+				alert("Incorrect prefix for OpenFreezer Parent Cell Line ID, must be \"C\" or \"c\"")
+				document.getElementById("parent_cell_line_id").focus();
+				return false;
+			}
+			else if (!isNumeric(parentVector.substring(1)))
+			{
+				alert("The identifier portion of the OpenFreezer Parent Vector ID must be a non-zero number, please verify your input")
+				document.getElementById("cl_pv_id").focus();
+				return false;
+			}
+			else if (!isNumeric(parentCellLine.substring(1)))
+			{
+				alert("The identifier portion of the OpenFreezer Parent Cell Line ID must be a non-zero number, please verify your input")
+				document.getElementById("parent_cell_line_id").focus();
+				return false;
+			}
+		break;
+		
+		default:
+			// no subtype, look at type
+			if (rType == 'Insert')
+			{
+				senseOligo = trimAll(document.getElementById("insertSenseOligo").value);
+				antisenseOligo = trimAll(document.getElementById("insertAntisenseOligo").value);
+				insertParentVector = trimAll(document.getElementById("insertParentVector").value);
+
+				// can be empty, but check correct prefixes and numerical group IDs
+				if (senseOligo.length > 0)
+				{
+					if (senseOligo.substring(0,1).toLowerCase() != 'o')
+					{
+						alert("Incorrect prefix for OpenFreezer Sense Oligo ID, must be \"O\" or \"o\"");
+						document.getElementById("insertSenseOligo").focus();
+						return false;
+					}
+					
+					if (!isNumeric(senseOligo.substring(1)))
+					{
+						alert("The identifier portion of OpenFreezer Sense Oligo ID must be a non-zero number, please verify your input");
+						document.getElementById("insertSenseOligo").focus();
+						return false;
+					}
+				}
+
+				if (antisenseOligo.length > 0)
+				{
+					if (antisenseOligo.substring(0,1).toLowerCase() != 'o')
+					{
+						alert("Incorrect prefix for OpenFreezer Antisense Oligo ID, must be \"O\" or \"o\"");
+						document.getElementById("insertAntisenseOligo").focus();
+						return false;
+					}
+					
+					if (!isNumeric(antisenseOligo.substring(1)))
+					{
+						alert("The identifier portion of OpenFreezer Antiesnse Oligo ID must be a non-zero number, please verify your input");
+						document.getElementById("insertAntisenseOligo").focus();
+						return false;
+					}
+				}
+
+				if (insertParentVector.length > 0)
+				{
+					if (insertParentVector.substring(0,1).toLowerCase() != 'v')
+					{
+						alert("Incorrect prefix for OpenFreezer Insert Parent Vector ID, must be \"V\" or \"v\"")
+						document.getElementById("insertParentVector").focus();
+						return false;
+					}					
+					
+					if (!isNumeric(insertParentVector.substring(1)))
+					{
+						alert("The identifier portion of the OpenFreezer Insert Parent Vector ID must be a non-zero number, please verify your input")
+						document.getElementById("insertParentVector").focus();
+						return false;
+					}
+				}
+			}
+		break;
+	}
+}
+
+function printSitesWarning()
+{
+	return confirm("If you have modified the restriction sites, the sequence will be recomputed during saving and CLEARED IF IT CANNOT BE RECONSTITUTED WITH THE CHOSEN CLONING SITES.  Are you sure you wish to proceed?");
+}
+
+function verifyOligoSequence()
+{
+	var dna_sequence = document.getElementById("oligo_dna_sequence");
+
+	var sequence_warning = document.getElementById("oligo_sequence_warning");
+	var seq = trimAll(dna_sequence.value);
+
+	if (seq == "")
+	{
+		alert("Please provide a sequence for the Oligo");
+		dna_sequence.focus();
+		sequence_warning.style.display = "inline";
+
+		return false;
+	}
+	else
+		sequence_warning.style.display = "none";
+
+	for (i = 0; i < seq.length; i++)
+	{
+		aChar = seq.charAt(i).toLowerCase();
+
+		if ( (aChar != 'a') && (aChar != 'c') && (aChar != 'g') && (aChar != 't') && (aChar != 'n'))
+		{
+			var answer = confirm("Oligo sequence contains characters other than A, C, G, T or N.  Saving will remove these extra characters.  Are you sure you wish to proceed?");
+
+			if (answer == 0)
+			{
+				dna_sequence.focus();
+				return false;
+			}
+			else
+			{
+				// Filter unwanted chars first, then save
+				new_sequence = filterDNASeq(seq);
+				dna_sequence.value = new_sequence;
+				break;
+			}
+		}
+	}
+
+	return true;
+}
+
+/* Function defined twice!!  removed Oct. 19/09
+function inArray(myChar, myArray)
+{
+    for (var i = 0; i < myArray.length; i++)
+    {
+        //alert(myArray[i]);
+        //alert(myChar == myArray[i]);
+
+        if (myChar == myArray[i])
+            return true;
+    }
+
+    return false;
+}*/
+
+
+
+function verifySequence(rTypeName, seqType)
+{
+	var seq_container = document.getElementById(seqType + "_sequence_" + rTypeName);
+
+	if (!seq_container)
+		seq_container = document.getElementById(seqType + "_sequence");
+
+	switch (seqType)
+	{
+		case 'dna':
+			var nucleotides = Array("A", "a", "C", "c", "G", "g", "T", "t", "N", "n");
+			var conf = "Your DNA sequence contains characters other than A, C, G, T or N.  Saving will remove these extra characters.  Are you sure you wish to proceed?";
+		break;
+
+		case 'rna':
+			var nucleotides = Array("A", "a", "C", "c", "G", "g", "U", "u", "N", "n");
+			var conf = "Your RNA sequence contains characters other than A, C, G, U or N.  Saving will remove these extra characters.  Are you sure you wish to proceed?";
+		break;
+
+		case 'protein':		// Aug. 24/09: include ambiguous AAs
+			var nucleotides = Array("A", "a", "B", "b", "C", "c", "D", "d", "E", "e", "F", "f", "G", "g", "H", "h", "I", "i", "K", "k", "L", "l", "M", "m", "N", "n", "P", "p", "Q", "q", "R", "r", "S", "s", "T", "t", "V", "v", "W", "w", "X", "x", "Y", "y", "Z", "z", "*");
+			var conf = "Your Protein sequence contains characters other than A, B, C, D, E, F, G, H, I, K, L, M, N, P, Q, R, S, T, V, W, X, Y, Z or *.  Saving will remove these extra characters.  Are you sure you wish to proceed?";
+		break;
+	}
+
+	// keep 'dna_sequence' variable name for consistency
+	if (seq_container)
+		var dna_sequence = filterSpace(seq_container.value);
+	else
+		var dna_sequence = "";
+
+	if (document.pressed == 'Create')
+	{
+		// Only execute code on EXIT FROM CREATE VIEW
+
+		// August 13/09: Different sequence container IDs for different reagent types
+		if (!seqType || seqType == "")
+		{
+			// assume DNA
+			seqType = "dna";
+		}
+
+		for (var i = 0; i < dna_sequence.length; i++)
+		{
+			var ch = dna_sequence.charAt(i);
+			
+			if (!inArray(ch, nucleotides))
+			{
+				var answer = confirm(conf);
+	
+				if (answer == 0)
+				{
+					seq_container.focus();
+					return false;
+				}
+				else
+				{
+					// Filter unwanted chars first, then save
+					switch (seqType)
+					{
+						case 'dna':
+							new_sequence = filterDNASeq(dna_sequence);
+						break;
+	
+						case 'rna':
+							new_sequence = filterRNASeq(dna_sequence);
+						break;
+	
+						case 'protein':
+							new_sequence = filterProteinSeq(dna_sequence);
+						break;
+					}
+	
+					seq_container.value = new_sequence;
+					return true;
+				}
+			}
+		}
+    	}
+	else if(document.pressed == 'Save')
+	{
+		for (var i = 0; i < dna_sequence.length; i++)
+		{
+			var ch = dna_sequence.charAt(i);
+
+			if (!inArray(ch, nucleotides))
+			{
+				if (!confirm(conf))
+				{
+					seq_container.focus();
+					return false;
+				}
+				else
+				{
+					// Filter unwanted chars first, then save
+					switch (seqType)
+					{
+						case 'dna':
+							new_sequence = filterDNASeq(dna_sequence);
+						break;
+	
+						case 'rna':
+							new_sequence = filterRNASeq(dna_sequence);
+						break;
+	
+						case 'protein':
+							new_sequence = filterProteinSeq(dna_sequence);
+						break;
+					}
+
+					seq_container.value = new_sequence;
+					return true;
+				}
+			}
+		}
+	}
+
+	return true;
+}
+
+// August 23/07, Marina: Remember the new parent value for later processing by Python
+// clonMeth is identical to ATypeID field value in the database, e.g. '1'->'Insert' for non-recombination vectors, '2'->'LOXP' for recombination vectors, etc.
+function changeParentValues(clonMeth)
+{
+//	alert('setting parents');
+	switch (clonMeth)
+	{
+		case '1':
+			// Non-recombination vector
+			srcPV = document.getElementById("parent_vector_id_txt");
+//			alert(srcPV.value);
+			srcInsert = document.getElementById("insert_id_txt");
+//			alert(srcInsert.value);
+			targetPV = document.getElementById("pv_id_hidden");
+			targetInsert = document.getElementById("insert_id_hidden");
+			
+			targetPV.value = srcPV.value;
+			targetInsert.value = srcInsert.value;
+		break;
+
+		case '2':
+			// Recombination vector
+			srcPV = document.getElementById("parent_vector_id_txt");
+			srcIPV = document.getElementById("ipv_id_txt");
+
+			targetPV = document.getElementById("pv_id_hidden");
+			targetIPV = document.getElementById("ipv_id_hidden");
+
+			targetPV.value = srcPV.value;
+			targetIPV.value = srcIPV.value;
+		break;
+
+		case '4':
+	
+			// Insert - check Oligos and Parent Insert Vector
+			srcSense = document.getElementById("sense_oligo_id_txt");
+			srcAntisense = document.getElementById("antisense_id_txt");
+			srcPIV = document.getElementById("ipv_id_txt");
+
+			targetSense = document.getElementById("sense_id_hidden");
+			targetAntisense = document.getElementById("antisense_id_hidden");
+			targetPIV = document.getElementById("piv_id_hidden");
+
+			targetSense.value = srcSense.value;
+			targetAntisense.value = srcAntisense.value;
+			targetPIV.value = srcPIV.value;
+
+		case '5':
+			srcPV = document.getElementById("pv_id_txt");
+			srcCL = document.getElementById("cl_id_txt");
+
+			targetPV = document.getElementById("clpv_id_hidden");
+			targetCL = document.getElementById("cl_id_hidden");
+
+			targetPV.value = srcPV.value;
+			targetCL.value = srcCL.value;
+
+// 			srcChange_PV_Flag = document.getElementById("assoc_pv_change");
+// 			targetChange_PV_Flag = document.getElementById("change_pv");
+// 
+// 			targetChange_PV_Flag.value = srcChange_PV_Flag.value;
+// 
+// 			srcChange_CL_Flag = document.getElementById("assoc_cl_change");
+// 			targetChange_CL_Flag = document.getElementById("change_cl");
+// 
+// 			targetChange_CL_Flag.value = srcChange_CL_Flag.value;
+	}
+}
+
+
+function verifyParentFormat(subtype)
+{
+	switch (subtype)
+	{
+		case '1':
+			
+			// parent vector and insert
+			pvField = document.getElementById("parent_vector_id_txt");
+			parentVector = trimAll(pvField.value);
+
+			insertField = document.getElementById("insert_id_txt");
+			insertID = trimAll(insertField.value);
+			
+			// verify that parent Vector ID starts with V and that the group ID is a valid numerical index
+			if (parentVector.length > 0)
+			{
+				if (parentVector.substring(0,1).toLowerCase() != 'v')
+				{
+					alert("Incorrect prefix for OpenFreezer Parent Vector ID (must be \"V\" or \"v\")")
+					pvField.focus();
+					return false;
+				}
+				else if (!isNumeric(parentVector.substring(1)))
+				{
+					alert("The identifier portion of the OpenFreezer Parent Vector ID must be a non-zero number, please verify your input")
+					pvField.focus();
+					return false;
+				}
+				// July 4/08: Since function "isNumeric" includes a decimal point in the set of allowed characters, add a separate check for it
+				else if (parentVector.substring(1).indexOf(".") >= 0)
+				{
+					alert("The identifier portion of the OpenFreezer Parent Vector ID must be a non-zero number, please verify your input")
+					pvField.focus();
+					return false;
+				}
+			}
+
+			if (insertID.length > 0)
+			{
+				if (insertID.substring(0,1).toLowerCase() != 'i')
+				{
+					alert("Incorrect prefix for OpenFreezer Insert ID, must be \"I\" or \"i\"")
+					insertField.focus();
+					return false;
+				}
+				else if (!isNumeric(insertID.substring(1)))
+				{
+					alert("The identifier portion of the OpenFreezer Insert ID must be a non-zero number, please verify your input")
+					insertField.focus();
+					return false;
+				}
+				// July 4/08: Separate error check for the decimal point
+				else if (insertID.substring(1).indexOf(".") >= 0)
+				{
+					alert("The identifier portion of the OpenFreezer Insert ID must be a non-zero number, please verify your input")
+					insertField.focus();
+					return false;
+				}
+			}
+		break;
+		
+		case '2':
+		
+			// parent vector and insert parent vector
+			pvField = document.getElementById("parent_vector_id_txt");
+			parentVector = trimAll(pvField.value);
+
+			ipvField = document.getElementById("ipv_id_txt");
+			insertParentVector = trimAll(ipvField.value);
+			
+			if (parentVector.length > 0)
+			{
+				if (parentVector.substring(0,1).toLowerCase() != 'v')
+				{
+					alert("Incorrect prefix for OpenFreezer Parent Vector ID (must be \"V\" or \"v\")")
+					pvField.focus();
+					return false;
+				}
+				else if (!isNumeric(parentVector.substring(1)))
+				{
+					alert("The identifier portion of the OpenFreezer Parent Vector ID must be a non-zero number, please verify your input")
+					pvField.focus();
+					return false;
+				}
+				// July 4/08: Separate error check for the decimal point
+				else if (parentVector.substring(1).indexOf(".") >= 0)
+				{
+					alert("The identifier portion of the OpenFreezer Parent Vector ID must be a non-zero number, please verify your input")
+					pvField.focus();
+					return false;
+				}
+			}
+
+			if (insertParentVector.length > 0)
+			{
+				if (insertParentVector.substring(0,1).toLowerCase() != 'v')
+				{
+					alert("Incorrect prefix for OpenFreezer Insert Parent Vector ID, must be \"V\" or \"v\"")
+					ipvField.focus();
+					return false;
+				}
+				else if (!isNumeric(insertParentVector.substring(1)))
+				{
+					alert("The identifier portion of the OpenFreezer Insert Parent Vector ID must be a non-zero number, please verify your input")
+					ipvField.focus();
+					return false;
+				}
+				// July 4/08: Separate error check for the decimal point
+				else if (insertParentVector.substring(1).indexOf(".") >= 0)
+				{
+					alert("The identifier portion of the OpenFreezer Insert Parent Vector ID must be a non-zero number, please verify your input")
+					ipvField.focus();
+					return false;
+				}
+			}
+		break;
+	}
+
+	return true;
+}
+
+// updated April 18/08
+function checkSave(scriptPath)
+{
+//	alert('in checksave');
+	var vType = document.getElementById("vector_cloning_method").value;
+// alert(vType);
+	if (vType != '3')
+	{
+		if (verifyVectorParents(vType) && verifyCloningSites(vType))
+		{
+			changeParentValues(vType);
+			verifySequenceAndRestrictionSites(scriptPath, vType);
+		}
+		else
+		{
+	//		alert ('verification failed');
+		}
+	}
+// Removed April 21/08
+// 	else	// Nov. 27/11 - novel vectors, no parents
+// 	{
+// 		document.getElementById("change_state_id").value = "Save";
+// 		document.vectorDetailForm.submit();
+// 	}
+}
+
+function verifyVectorParents(vType)
+{
+// 	alert('in verify parents');
+
+	if (document.pressed == 'Save')
+	{
+//		var vType = document.getElementById("vector_cloning_method").value;
+
+		if (verifyParentFormat(vType))
+		{
+			var vpChange = document.getElementById("change_pv").value;
+			var pvOld = document.getElementById("parent_vector_old_id").value;
+			var pvNew = document.getElementById("parent_vector_id_txt").value;
+
+			if ((pvNew != "") && (pvNew != pvOld) && (vpChange != 1) )
+			{
+				alert("Vector " + pvNew + " could not be saved without preloading its properties.  Press the \"Change\" button to load the properties before saving.");
+				
+				document.getElementById("parent_vector_id_txt").focus();
+
+				return false;
+			}
+			else
+				return true;
+		}
+	}
+	
+//	return true;
+}
+
+// September 12/07, Marina: When Vector parents are changed, its sequence is recomputed anew.  Get user's confirmation that they want to proceed with the changes
+function confirmSequenceChange()
+{
+	// Determine if parents were changed (i.e. old value != new value)
+	var pvOld = document.getElementById("parent_vector_old_id").value;
+	//alert("pvOld " + pvOld);
+
+	if (document.getElementById("parent_vector_id_txt"))
+	{
+		var pvNew = document.getElementById("parent_vector_id_txt").value;
+	}
+// 	alert("pvNew " + pvNew);
+	var secondParentChange = false;
+
+	// Insert or IPV?
+	if (document.getElementById("insert_id_txt"))
+	{
+		var iOld = document.getElementById("insert_old_id").value;
+		var iNew = document.getElementById("insert_id_txt").value;
+		secondParentChange = (iOld != iNew) ? true : false;
+	}
+	else if (document.getElementById("ipv_id_txt"))
+	{
+		var ipvOld = document.getElementById("ipv_old_id").value;
+		var ipvNew = document.getElementById("ipv_id_txt").value;
+		secondParentChange = (ipvOld != ipvNew) ? true : false;
+	}
+
+	if (document.pressed == 'Save')
+	{
+		if ( pvNew && ((pvOld != pvNew) || secondParentChange))
+			return confirm("You are changing parent values.  Sequence is going to be modified upon saving.  Are you sure you want to proceed?");
+	}
+
+	return true;
+}
+
+
+function verifyCellLineParents()
+{
+	if (document.pressed == 'Save')
+	{
+		var pvChange = document.getElementById("change_pv").value;
+		var clChange = document.getElementById("change_cl").value;
+		
+		var pvOld = document.getElementById("parent_vector_old_id").value;
+		var clOld = document.getElementById("parent_cellline_old_id").value;
+	
+		var pvNew = document.getElementById("pv_id_txt").value;
+		var clNew = document.getElementById("cl_id_txt").value;
+
+		if (((pvNew == "") && (pvOld != "")) || ((pvNew != "") && (pvOld == "")) || ((pvNew != "") && (pvOld != "") && (pvNew != pvOld) && (pvChange != 1)))
+		{
+			alert("Please press 'Change' before saving for Parent Vector modification to take effect");
+			return false;
+		}
+
+		
+// 		if ( (pvNew != "") && (pvNew != pvOld) && (pvChange != 1) )
+// 		{
+// 			alert("Vector " + pvNew + " could not be saved without preloading its properties.  Press the \"Change\" button to load the properties before saving.");
+// 
+// 			document.getElementById("pv_id_txt").focus();
+// 	
+// 			return false;
+// 		}
+
+		if (((clNew == "") && (clOld != "")) || ((clNew != "") && (clOld == "")) || ((clNew != "") && (clOld != "") && (clNew != clOld) && (clChange != 1)))
+		{
+			alert("Please press 'Change' before saving for Parent Cell Line modification to take effect");
+			return false;
+		}
+
+		
+
+// 		if ( (clNew != "") && (clNew != clOld) && (clChange != 1))
+// 		{
+// 			alert("Cell Line " + clNew + " could not be saved without preloading its properties.  Press the \"Change\" button to load the properties before saving.");
+// 
+// 			document.getElementById("cl_id_txt").focus();
+// 	
+// 			return false;
+// 		}
+	}
+	
+	return true;
+}
+
+function showOtherTextBox()
+{
+        var chkbx_id = "other_chkbx";
+        var text_id = "ar_chkbx_txt";
+
+        // May 24/06, Marina - Now that we have two groups of checkboxes, which could appear on the view simultaneously for some reagent types (e.g. cell lines), have to differentiate between the alternate ID checkbox group and antibiotic resistance/resistance marker group
+        var alt_chkbx_id = "other_Alt_ID_chkbx";
+        var alt_txt_id= "alternate_id_txt";
+
+        var chkbxElement = document.getElementById(chkbx_id);
+        var txtElem = document.getElementById(text_id);
+
+        // May 24/06
+        var alt_id_chkbxElement = document.getElementById(alt_chkbx_id);
+        var alt_id_txtElem = document.getElementById(alt_txt_id);
+
+        if (chkbxElement)
+        {
+                if (chkbxElement.checked)
+                {
+                        // Show the textbox and set it in focus
+                        txtElem.style.display="inline";
+                        txtElem.focus();
+                }
+                else
+                {
+                        // Hide the textbox
+                        txtElem.style.display="none";
+                }
+        }
+
+        if (alt_id_chkbxElement)
+        {
+                // May 24/06
+                if (alt_id_chkbxElement.checked)
+                {
+                        // Show the textbox and set it in focus
+                        alt_id_txtElem.style.display="inline";
+                        alt_id_txtElem.focus();
+                }
+                else
+                {
+                        // Hide the textbox
+                        alt_id_txtElem.style.display="none";
+                }
+        }
+}
+
+// Feb. 8/08
+function showAlternateIDText()
+{
+	var altIDList = document.getElementById("alternate_id_list");
+	var altSelInd = altIDList.selectedIndex;
+	var selAltID = altIDList[altSelInd].value;
+// 	alert(selAltID + "_alternate_id_textbox");
+
+	var altIDRow = document.getElementById("alt_id_row_" + selAltID);
+	altIDRow.style.display = "table-row";
+
+	// Feb. 19/08: Set focus in corresponding textbox
+	var altID_txt = document.getElementById(selAltID + "_alternate_id_textbox");
+// 	altID_txt.style.display = "inline";
+
+	// feb. 11/08
+	var hiddenList = document.getElementById("alternate_ids_hidden");
+	hiddenList.options[altSelInd-1].selected = true;
+
+	altID_txt.focus();	// feb. 19/08
+// 	alert(getSelectedElements("alternate_ids_hidden"));
+}
+
+// Written May 23/06 by Marina
+function showAltIDTextBox(chkbx_id, text_id)
+{
+        var chkbxElement = document.getElementById(chkbx_id);
+	var txtElem = document.getElementById(text_id);
+
+        if (chkbxElement.checked)
+        {
+                // Show the textbox and set it in focus
+                txtElem.style.display="inline";
+                txtElem.focus();
+        }
+        else
+        {
+                // Hide the textbox
+                txtElem.style.display="none";
+        }
+}
+ 
+ 
+function verifyAlternateID()
+{
+    alt_id_prop_set = document.getElementsByName("reagent_detailedview_alternate_id_prop[]");
+    var prefix = "alternate_id_";
+    var postfix = "_textbox";
+
+    for (i = 0; i < alt_id_prop_set.length; i++)
+    {
+        nextElem = alt_id_prop_set[i];
+        alt_id = nextElem.value;
+
+        if (nextElem.value.toLowerCase() != 'other')
+            textBoxElem = document.getElementById(prefix + alt_id + postfix);
+        else
+            textBoxElem = document.getElementById("alternate_id_txt");
+
+        if (nextElem.checked)
+        {
+            if (textBoxElem.value == "")
+            {
+                alert("Please fill in the value of '" + alt_id + "' Alternate ID field");
+
+                textBoxElem.style.display = "inline";   // in case it's hidden
+                textBoxElem.focus();
+
+                return false;
+            }
+        }
+        else
+        {
+            // Clear out the value in the corresponding textbox
+            textBoxElem.value = "";
+        }
+    }
+
+    return true;
+}
+
+function verifyProperties(rTypeID)
+{
+    if (document.pressed == 'Save')
+    {
+        // There is a list of properties to verify for each reagent type
+        switch (rTypeID)
+        {
+            case 2:     // Insert
+
+                // Properties that must always be filled in for Inserts
+                mandatoryProps = [];
+
+                // Dropdown lists where properties may be added - Make sure that if 'Other' option is selected, the new property value is also filled in
+                propElemList = new Array();
+                propNameList = new Array();
+
+                propElemList["tag_list"] = "tag_txt";
+                propElemList["cm_list"] = "cm_txt";
+                propElemList["species_list"] = "species_txt";
+
+                propNameList["tag_list"] = "Tag";
+                propNameList["cm_list"] = "Cloning Method";
+                propNameList["species_list"] = "Species";
+
+
+                return (verifySequence() && verifyAlternateID() && verifyOther(propElemList, propNameList) && verifyMandatory(mandatoryProps));
+
+            break;
+        }
+    }
+
+    return true;
+}
+
+
+// May 28/07, Marina: Making 'Packet ID' a mandatory field on reagent creation pages
+function verifyPacket(rType)
+{
+	// Nov. 13/08 - hack for cell lines, needs rewriting
+	if (rType == 'cell_line')
+		rType = 'CellLine';
+	
+	// Nov. 17/08 - same as above
+	else if (rType == 'oligo')
+		rType = 'Oligo';
+
+	if (document.getElementById("cancel_set"))
+	{
+		var cancelSet = document.getElementById("cancel_set").value;
+	}
+	else
+	{
+		var cancelSet = 0;
+	}
+
+	if (cancelSet != 1)
+	{
+// alert(rType);
+		var temp_id = "packetList_" + rType;
+// alert(temp_id);
+		var packetList = document.getElementById(temp_id);
+
+		if (packetList)		// could just be another creation step, OK
+			var packet_selectedInd = packetList.selectedIndex;
+		
+		// Warning div depends on type and sometimes subtype of reagent
+		var type_tmp = "packet_warning_" + rType;
+		var packet_warning = document.getElementById(type_tmp);
+		
+		// Common to all
+		if ( (packet_selectedInd == 0) && (packetList[packet_selectedInd].value == 0))
+		{
+			alert ("You must select a Project ID to continue");
+			packetList.focus();
+			packet_warning.style.display = "inline";
+			
+			return false;
+		}
+		else 
+		{
+			// If everything is OK this time but warning was shown previously, hide it
+			if (packet_warning.style.display == "inline")
+			{
+				packet_warning.style.display = "none";
+			}
+		}
+	}
+	
+	return true;
+}
+
+
+// Feb. 5/08: Make sure reagent name is filled in
+function verifyReagentName(rType, subtype)
+{
+// 	alert("Verify name; subtype: " + subtype);
+// 	alert("Show field reagent_name_prop_" + subtype);
+// 	alert("Show warning " + subtype + "_name_warning");
+
+	if (document.getElementById("cancel_set"))
+	{
+		var cancelSet = document.getElementById("cancel_set").value;
+	}
+	else
+	{
+		var cancelSet = 0;
+	}
+
+	if (cancelSet != 1)
+	{
+// 		var nameField = document.getElementById("reagent_name_prop_" + subtype);
+		var nameField = document.getElementById(rType + "_Name_prop");
+// 		var name_warning = document.getElementById(subtype + "_name_warning");
+		var name_warning = document.getElementById(rType + "_Name_warning");
+	
+		if (nameField.value == "")
+		{
+			// hide all other warnings - Different for each reagent type, so check first if exists
+// 			if (document.getElementById("fp_warning"))
+			if (document.getElementById(rType + "_5' Cloning Site_warning"))
+// 				document.getElementById("fp_warning").style.display = "none";
+				document.getElementById(rType + "_5' Cloning Site_warning").style.display = "none";
+	
+// 			if (document.getElementById("tp_warning"))
+// 				document.getElementById("tp_warning").style.display = "none";
+	
+			if (document.getElementById(rType + "_3' Cloning Site_warning"))
+// 				document.getElementById("fp_warning").style.display = "none";
+				document.getElementById(rType + "_3' Cloning Site_warning").style.display = "none";
+/*
+			if (document.getElementById("oc_warning"))
+				document.getElementById("oc_warning").style.display = "none";*/
+
+			if (document.getElementById(rType + "_Open/Closed_warning"))
+				document.getElementById(rType + "_Open/Closed_warning").style.display = "none";
+		
+// 			if (document.getElementById("it_warning"))
+// 				document.getElementById("it_warning").style.display = "none";
+	
+			if (document.getElementById(rType + "_Type of Insert_warning"))
+				document.getElementById(rType + "_Type of Insert_warning").style.display = "none";
+		
+			alert("Please provide a name for the new " + rType);
+			name_warning.style.display = "inline";
+			nameField.focus();
+	
+			return false;
+		}
+	
+		// hide warning
+		name_warning.style.display = "none";
+	}
+
+	return true;
+}
+
+// Feb. 12/08: Make Status mandatory
+function verifyStatus(rType)
+{
+	if (document.getElementById("cancel_set"))
+	{
+		var cancelSet = document.getElementById("cancel_set").value;
+	}
+	else
+	{
+		var cancelSet = 0;
+	}
+
+	if (cancelSet != 1)
+	{
+		var statusList = document.getElementById(rType + "_Status_prop");
+	
+		if (statusList)		// not present on all views, e.g. absent from Insert from Primer
+		{
+			var status_selectedInd = statusList.selectedIndex;
+			var status_warning = document.getElementById(rType + "_Status_warning");
+	
+			if ( (status_selectedInd == 0) && (statusList[status_selectedInd].value == 0))
+			{
+				alert ("Please indicate the status of the new " + rType);
+				statusList.focus();
+				status_warning.style.display = "inline";
+				
+				return false;
+			}
+			else 
+			{
+				// If everything is OK this time but warning was shown previously, hide it
+				if (status_warning.style.display == "inline")
+				{
+					status_warning.style.display = "none";
+				}
+			}
+		}
+	}
+
+	return true;
+}
+
+
+// May 11/08 - Added isLinear parameter to differentiate between circular and linear sequences - in the first case feature endPos may be < startPos (feature still cannot exceed the length of the sequence)
+function verifyCDNA(isLinear)
+{
+	var cdnaStart = document.getElementById("cdna_insert_start");
+	var cdnaEnd =  document.getElementById("cdna_insert_end");
+// 	var cdnaWarning = document.getElementById("cdna_warning");	// removed May 11/08
+	var cdnaUnknown = document.getElementById("cdna_unknown");
+
+// 	var dna_sequence = document.getElementById("dna_sequence").value;
+	
+	// Check start and end filled in - May 14/08: Make mandatory for Insert, optional for Vectors
+	if (isLinear)
+	{
+		if (!cdnaUnknown)	// Nov. 13/08
+		{
+			alert("Please indicate cDNA start and stop positions, or check 'N/A' if unknown");
+			return false;
+		}
+
+		if (!cdnaUnknown.checked)
+		{
+			if ((trimAll(cdnaStart.value) == "") || parseInt(cdnaStart.value) == 0)
+			{
+				alert("Please indicate both cDNA start and end positions, or select \"N/A\" if the sequence does not contain a cDNA.");
+				cdnaStart.focus();
+	// 			cdnaWarning.style.display = "table-row";
+		
+				return false;
+			}
+			
+		
+			if ((trimAll(cdnaEnd.value) == "") || parseInt(cdnaEnd.value) == 0)
+			{
+				alert("Please indicate both cDNA start and end positions, or select \"N/A\" if the sequence does not contain a cDNA.");
+				cdnaEnd.focus();
+	// 			cdnaWarning.style.display = "table-row";
+		
+				return false;
+			}
+	
+			// Check start <= end
+			if (parseInt(cdnaStart.value) >= parseInt(cdnaEnd.value))
+			{
+				alert("cDNA end index must be greater than the start index.  Please verify your input.");
+				cdnaStart.focus();
+				return false;
+			}
+		}
+	}
+	
+	// May 21/08: Not showing cDNA for Novel vectors - so check if the field exists
+if (cdnaStart && cdnaEnd)
+{
+
+	// Check start and end numeric
+	if (parseInt(trimAll(cdnaStart.value)) < 0)
+	{
+		alert("cDNA start position must be an integer value greater than or equal to 0.  Please verify your input.");
+		cdnaStart.focus();
+		return false;
+	}
+
+	if (parseInt(trimAll(cdnaEnd.value)) < 0)
+	{
+		alert("cDNA end position must be an integer value greater than or equal to 0.  Please verify your input.");
+		cdnaEnd.focus();
+		return false;
+	}
+
+/*
+	// REDUNDANT!!! (a minus sign would be captured by above check)
+	// 	// Check start and end > 0
+	// 	if (parseInt(cdnaStart.value) < 0)
+	// 	{
+	// 		alert("cDNA start value must be an integer value greater than or equal to 0.  Please verify your input.");
+	// 		cdnaStart.focus();
+	// 		return false;
+	// 	}
+	// 
+	// 	if (parseInt(cdnaEnd.value) < 0)
+	// 	{
+	// 		alert("cDNA end value must be an integer value greater than or equal to 0.  Please verify your input.");
+	// 		cdnaEnd.focus();
+	// 		return false;
+	// 	}
+*/
+	// Check start and end <= sequence length
+/*
+	if (parseInt(cdnaEnd.value) > parseInt(dna_sequence.length))
+	{
+		alert("cDNA end value cannot exceed the length of the DNA sequence.  Please verify your input.");
+		cdnaEnd.focus();
+		return false;
+	}
+
+	if (parseInt(cdnaStart.value) > parseInt(dna_sequence.length))
+	{
+		alert("cDNA start value cannot exceed the length of the DNA sequence.  Please verify your input.");
+		cdnaStart.focus();
+		return false;
+	}
+*/
+}
+// 	cdnaWarning.style.display = "none";
+	return true;
+
+/*
+	// Removed April 11/08
+	// 	// cDNA positions MAY be left at 0, but it's a good idea to remind the user that they can be changed
+	// 	var response = true;
+	// 
+	// 	if ( (parseInt(trimAll(cdnaStart.value)) == 0) && (parseInt(trimAll(cdnaEnd.value)) == 0) )
+	// 	{
+	// 		response = confirm("cDNA start and end positions are set to 0.  Save anyway?");
+	// 	
+	// 		// the response here would be the opposite of the function's return value; an affirmative response means the user does not want to save but wants to change cDNA values, in which case the function should return 'false', and vice versa
+	// 		if (!response)
+	// 			cdnaStart.focus();
+	// 	}
+	// 
+	// 	return response;
+*/
+}
+
+// March 18/08: Check property positions
+// May 14/08: Added isLinear argument - circular Vector sequences may have end > start; also cDNA positions must be filled in for Inserts
+function verifyPositions(isLinear)
+{
+	if (document.getElementById("cancel_set"))
+	{
+		var cancelSet = document.getElementById("cancel_set").value;
+	}
+	else
+	{
+		var cancelSet = 0;
+	}
+
+	if (cancelSet != 1)
+	{
+		// Verify positions for all feature names in the 'features' dropdown selection list, plus cloning sites
+		var featureNamesList = document.getElementById("sequence_property_names");
+	
+		var propPrefix = "reagent_detailedview_";
+		var propPostfix = "_prop";
+	
+		var startPrefix = "_startpos";
+		var endPrefix = "_endpos";
+	
+		var tmpID;
+		var tmpAttr;
+		var tmpOptn;
+	
+		var allFields = document.getElementsByTagName("INPUT");
+// 		var dna_sequence = filterSeq(document.getElementById("dna_sequence").value).toLowerCase();
+	
+		var tmpStart;
+		var tmpStartInput;
+	
+		var tmpEnd;
+		var tmpEndField;
+	
+		var i, j, k, l, ch, nt;
+	
+		var numbers = "0123456789";
+		var nucleotides = "AaCcGgTt";
+	
+		var startInd;
+		var endInd;
+	
+	// 	alert(allFields.length);
+	
+		for (i = 0; i < allFields.length; i++)
+		{
+// 			alert(i);
+	
+			tmpInput = allFields[i];
+	
+			if (tmpInput.type == "hidden")
+			{
+				tmpID = tmpInput.id;
+// 				alert(tmpID);
+			
+				startInd = tmpID.indexOf(startPrefix + propPostfix);
+				endInd = tmpID.indexOf(endPrefix + propPostfix);
+	
+				if (startInd > 0)
+				{
+	// 				alert(tmpID);
+					propName = tmpID.substring(0, startInd);
+// 					alert("Prop " + propName);
+	
+					tmpStart = tmpInput.value;
+// 					alert("Start " + tmpStart);
+	
+					tmpStartID = propPrefix + propName + startPrefix + propPostfix;
+	// 				alert(tmpStartID);
+	
+					// Get numerical index to distinguish b/w multiple feature values
+					propCount = tmpID.substr(startInd+((startPrefix + propPostfix).length), tmpID.length);
+	// 				alert(propCount);
+	
+					tmpStartInput = document.getElementById(propName + propCount + startPrefix + "_id");
+	
+					if (trimAll(propCount).length > 0)
+					{
+						// Try to find end input
+						tmpEndID = propName + endPrefix + propPostfix + propCount;
+		// 				alert(tmpEndID);
+		
+						tmpEndInput = document.getElementById(tmpEndID);
+						tmpEnd = tmpEndInput.value;
+	// 					alert("End " + tmpEnd);
+	
+						tmpEndField = document.getElementById(propName + propCount + endPrefix + "_id");
+	// 					alert(propName + propCount + endPrefix + "_id");
+					}
+					else
+					{
+						// do anything??
+					}
+	
+					// Check start numeric
+					for (k = 0; k < trimAll(tmpStart).length; k++)
+					{
+						ch = trimAll(tmpStart).charAt(k);
+	
+						if (!inArray(ch, numbers))
+						{
+							alert("Feature start positions may only contain digits.  Please verify your input.");
+							tmpStartInput.focus();
+							return false;
+						}
+					}
+	
+					// Check end numeric
+					for (k = 0; k < trimAll(tmpEnd).length; k++)
+					{
+						ch = trimAll(tmpEnd).charAt(k);
+	
+						if (!inArray(ch, numbers))
+						{
+							alert("Feature end positions may only contain digits.  Please verify your input.");
+							tmpEndField.focus();
+							return false;
+						}
+					}
+			
+	// 				alert("DNA length " + parseInt(dna_sequence.length));
+	
+					// Check start and end <= sequence length
+/*
+					if (parseInt(tmpEnd) > parseInt(dna_sequence.length))
+					{
+						alert("Feature end value cannot exceed the length of the DNA sequence.  Please verify your input.");
+						tmpEndField.focus();
+						return false;
+					}
+				
+					if (parseInt(tmpStart) > parseInt(dna_sequence.length))
+					{
+						alert("Feature start value cannot exceed the length of the DNA sequence.  Please verify your input.");
+						tmpStartInput.focus();
+						return false;
+					}
+*/
+			
+					// Check start < end
+					if (!isLinear && (parseInt(tmpStart) > parseInt(tmpEnd)))
+					{
+						alert("Feature start index cannot be greater than the end index.  Please verify your input.");
+						tmpStartInput.focus();
+						return false;
+					}
+				}
+			}
+			else if (tmpInput.type.toLowerCase() == "text")
+			{
+				// Single-value features don't have a numeric identifier
+// 				alert(tmpInput.id);
+	// 			alert(tmpInput.name);
+	
+				tmpID = tmpInput.id;
+	//			alert(tmpID);
+	//			alert(startPrefix + propPostfix);
+	
+				startInd = tmpID.indexOf(startPrefix + propPostfix);
+				endInd = tmpID.indexOf(endPrefix + propPostfix);
+	
+				if (startInd > 0)
+				{
+					propName = tmpID.substring(0, startInd);
+// 					alert("CURRENT FEATURE: " + propName);
+			
+					tmpStart = tmpInput.value;
+	
+// 					alert("Start " + tmpStart);
+			
+					tmpStartInput = tmpInput;
+	
+					// Try to find end input
+					tmpEndID = propName + endPrefix + propPostfix
+	// 				alert(tmpEndID);
+	
+					tmpEndInput = document.getElementById(tmpEndID);
+	
+					if (tmpEndInput)	// might not exist if this is not a feature
+					{
+						tmpEnd = tmpEndInput.value;
+	// 					alert("End " + tmpEnd);
+	
+						// Check start & end numeric
+						for (k = 0; k < trimAll(tmpStart).length; k++)
+						{
+							ch = trimAll(tmpStart).charAt(k);
+		
+							if (!inArray(ch, numbers))
+							{
+								alert("Feature start positions may only contain digits.  Please verify your input.");
+								tmpStartInput.focus();
+								return false;
+							}
+						}
+	
+						for (k = 0; k < trimAll(tmpEnd).length; k++)
+						{
+							ch = trimAll(tmpEnd).charAt(k);
+		
+							if (!inArray(ch, numbers))
+							{
+								alert("Feature end positions may only contain digits.  Please verify your input.");
+								tmpEndInput.focus();
+								return false;
+							}
+						}
+			
+	// 					alert("DNA length " + parseInt(dna_sequence.length));
+	
+						// Check start and end <= sequence length
+/*
+						if (parseInt(tmpStart) > parseInt(dna_sequence.length))
+						{
+							alert("Feature start value cannot exceed the length of the DNA sequence.  Please verify your input.");
+							tmpStartInput.focus();
+							return false;
+						}
+		
+						if (parseInt(tmpEnd) > parseInt(dna_sequence.length))
+						{
+							alert("Feature end value cannot exceed the length of the DNA sequence.  Please verify your input.");
+							tmpEndInput.focus();
+							return false;
+						}
+*/				
+			
+						// Check start < end
+						if (!isLinear && (parseInt(tmpStart) > parseInt(tmpEnd)))
+						{
+							alert("Feature start index cannot be greater than the end index.  Please verify your input.");
+							tmpStartInput.focus();
+							return false;
+						}
+		
+						// For Linkers, check that the positions entered correspond to the linker input value length
+						fpl_input = document.getElementById("fp_linker_prop");
+						tpl_input = document.getElementById("tp_linker_prop");
+		
+						if (fpl_input)
+							five_linker = fpl_input.value.toLowerCase();
+						else
+							five_linker = "";
+	
+						if (tpl_input)
+							three_linker = tpl_input.value.toLowerCase();
+						else
+							three_linker = "";
+		
+						fpl_length = five_linker.length;
+						tpl_length = three_linker.length;
+		
+						fpl_start_in = document.getElementById("5_prime_linker_startpos" + propPostfix);
+						tpl_start_in = document.getElementById("3_prime_linker_startpos" + propPostfix);
+		
+						if (fpl_start_in)
+							fpl_start = trimAll(fpl_start_in.value);
+						else
+							fpl_start = 0;
+	
+						if (tpl_start_in)
+							tpl_start = trimAll(tpl_start_in.value);
+						else
+							tpl_start = 0;
+		
+						fpl_end_in = document.getElementById("5_prime_linker_endpos" + propPostfix);
+						tpl_end_in = document.getElementById("3_prime_linker_endpos" + propPostfix);
+		
+						if (fpl_end_in)
+							fpl_end = trimAll(fpl_end_in.value);
+						else
+							fpl_end = 0;
+	
+						if (tpl_end_in)
+							tpl_end = trimAll(tpl_end_in.value);
+						else
+							tpl_end = 0;
+		
+						if ( (fpl_length > 0) && (parseInt(fpl_start) > 0) && (parseInt(fpl_end) > 0) && ((fpl_end - fpl_start + 1) != fpl_length) )
+						{
+							alert("The length of the 5' linker does not match the start and end indices provided for it.  Please verify your input");
+							fpl_input.focus();
+							return false;
+						}
+		
+						if ( (tpl_length > 0) && (parseInt(tpl_start) > 0) && (parseInt(tpl_end) > 0) && ((tpl_end - tpl_start + 1) != tpl_length) )
+						{
+							alert("The length of the 3' linker does not match the start and end indices provided for it.  Please verify your input");
+							tpl_input.focus();
+							return false;
+						}
+		
+						// At least one of linker, start or end is blank (but not all) - DISALLOW THIS, causes database inconsistencies.  Force the user to make corrections
+		
+						// For simplicity now, though, only check actual property value not empty if its positions are filled in
+		
+						// linker empty, positions filled in
+						if ((fpl_length == 0) && (parseInt(fpl_start) > 0) && (parseInt(fpl_end) > 0))
+						{
+							alert("You have provided start and end positions for the 5' linker but not the actual linker value.  Please verify your input.");
+							fpl_input.focus();
+							return false;
+						}
+	
+	// 				// Only linker filled in, positions empty -- OK, ALLOW
+	// 				else if ( (fpl_length > 0) && (parseInt(fpl_start) == 0) && (parseInt(fpl_end) == 0) )
+	// 				{
+	// 					return confirm("Position values for the 5' linker value are not filled in.  Are you sure you want to continue (linker will be saved without start/stop values)");
+	// 				}
+	
+	// 				// Only start filled in
+	// 				else if ( (fpl_length == 0) && (parseInt(fpl_start) > 0) && (parseInt(fpl_end) == 0) )
+	// 				{
+	// 					alert("You have provided the start position for the 5' linker but not the actual linker value or its end position.  Please verify your input.");
+	// 					fpl_input.focus();
+	// 					return false;
+	// 				}
+	// 
+	// 				// Only end filled in
+	// 				else if ( (fpl_length == 0) && (parseInt(fpl_end) > 0) && ( (parseInt(fpl_start) == 0) || trimAll(fpl_start).length == 0) )
+	// 				{
+	// 					alert("You have provided the end position for the 5' linker but not the actual linker value or its start position.  Please verify your input.");
+	// 					fpl_input.focus();
+	// 					return false;
+	// 				}
+	// 
+	// 				// start empty, linker and end filled in
+	// 				else if ( (fpl_length > 0) && (parseInt(fpl_start) == 0) && (parseInt(fpl_end) > 0) )
+	// 				{
+	// 					alert("You have not provided the 5' linker start position.  Please verify your input.");
+	// 					fpl_input.focus();
+	// 					return false;
+	// 				}
+	// 
+	// 				// end empty, linker and end filled in
+	// 				else if ( (fpl_length > 0) && (parseInt(fpl_start) > 0) && (parseInt(fpl_end) == 0) )
+	// 				{
+	// 					alert("You have not provided the 5' linker end position.  Please verify your input.");
+	// 					fpl_input.focus();
+	// 					return false;
+	// 				}
+	
+						// Ditto for 3' linker
+						// linker empty, positions filled in
+						if ((tpl_length == 0) && (parseInt(tpl_start) > 0) && (parseInt(tpl_end) > 0))
+						{
+							alert("You have provided start and end positions for the 3' linker but not the actual linker value.  Please verify your input.");
+							tpl_input.focus();
+							return false;
+						}
+	
+	// 				// Only linker filled in, positions empty -- OK, ALLOW
+	// 				else if ( (fpl_length > 0) && (parseInt(fpl_start) == 0) && (parseInt(fpl_end) == 0) )
+	// 				{
+	// 					return confirm("Position values for the 5' linker value are not filled in.  Are you sure you want to continue (linker will be saved without start/stop values)");
+	// 				}
+	
+	// 				// Only start filled in
+	// 				else if ( (tpl_length == 0) && (parseInt(tpl_start) > 0) && (parseInt(tpl_end) == 0) )
+	// 				{
+	// 					alert("You have provided the start position for the 3' linker but not the actual linker value or its end position.  Please verify your input.");
+	// 					tpl_input.focus();
+	// 					return false;
+	// 				}
+	// 
+	// 				// Only end filled in
+	// 				else if ( (tpl_length == 0) && (parseInt(tpl_start) == 0) && (parseInt(tpl_end) > 0) )
+	// 				{
+	// 					alert("You have provided the end position for the 3' linker but not the actual linker value or its start position.  Please verify your input.");
+	// 					tpl_input.focus();
+	// 					return false;
+	// 				}
+	// 
+	// 				// start empty, linker and end filled in
+	// 				else if ( (tpl_length > 0) && (parseInt(tpl_start) == 0) && (parseInt(tpl_end) > 0) )
+	// 				{
+	// 					alert("You have not provided the 3' linker start position.  Please verify your input.");
+	// 					tpl_input.focus();
+	// 					return false;
+	// 				}
+	// 
+	// 				// end empty, linker and end filled in
+	// 				else if ( (tpl_length > 0) && (parseInt(tpl_start) > 0) && (parseInt(tpl_end) == 0) )
+	// 				{
+	// 					alert("You have not provided the 3' linker end position.  Please verify your input.");
+	// 					tpl_input.focus();
+	// 					return false;
+	// 				}
+	
+						// Check that linkers only contain ACGT (not a position validation but still)
+						for (l = 0; l < fpl_length; l++)
+						{
+							nt = five_linker[l];
+		
+							if (!inArray(nt, nucleotides))
+							{
+								alert("5' linker value may not contain characters other than A,C,G,T.  Please verify your input.");
+								fpl_input.focus();
+								return false;
+							}
+						}
+		
+						for (l = 0; l < tpl_length; l++)
+						{
+							nt = three_linker[l];
+		
+							if (!inArray(nt, nucleotides))
+							{
+								alert("3' linker value may not contain characters other than A,C,G,T.  Please verify your input.");
+								tpl_input.focus();
+								return false;
+							}
+						}
+		
+						// Last but not least, check that the linker value provided is found on the actual sequence where indicated
+/*
+						if ((parseInt(fpl_start) != 0) && (parseInt(fpl_end) != 0) && (dna_sequence.substring(parseInt(fpl_start)-1, fpl_end) != five_linker) )
+						{
+							alert("5' linker could not be found on sequence at the specified positions.  Please verify your input.");
+							fpl_input.focus();
+							return false;
+						}
+		
+						if ( (parseInt(tpl_start) != 0) && (parseInt(tpl_end) != 0) && (dna_sequence.substring(parseInt(tpl_start)-1, tpl_end) != three_linker) )
+						{
+							alert("3' linker could not be found on sequence at the specified positions.  Please verify your input.");
+							tpl_input.focus();
+							return false;
+						}
+*/
+					}
+				}
+			}
+		}
+	
+		// May 14/08: Make Insert cDNA positions mandatory UNLESS it's non-coding or DNA fragment
+		// For Vectors, if not Novel, cDNA positions will automatically be pre-filled from sequence reconstitution; not mandatory for Novel
+		if (isLinear)
+			return verifyCDNA(isLinear) && verifyCloningSites("insert");
+	}
+
+	return true;	// keep!
+}
+
+// Last modified Feb. 12/08
+function validateInsert()
+{
+	// Type of Insert can never be empty
+	var itype_list = document.getElementById("itype_list");
+	var itype_selectedInd = itype_list.selectedIndex;
+
+	var oc_list = document.getElementById("oc_list");
+	var oc_selectedInd = oc_list.selectedIndex;
+
+	var oc_warning = document.getElementById("oc_warning");
+	var it_warning = document.getElementById("it_warning");
+
+	// Feb. 5/08: Make Name a mandatory field
+	// Feb. 12/08: Make Status mandatory too
+	if (verifyPacket("Insert") && verifyStatus("Insert") && verifyReagentName("Insert", "insert") && verifyCloningSites("insert") && verifySequence("Insert") && verifyPositions() && verifyCDNA(true))
+	{
+		// No Insert Type selected
+		if ((itype_selectedInd == 0) && (itype_list[itype_selectedInd].value == ""))
+		{	
+			alert("You must select a Type of Insert to continue");
+			itype_list.focus();
+			it_warning.style.display = "inline";
+			oc_warning.style.display = "none";
+
+			return false;
+		}
+		else
+		{
+			it_warning.style.display = "none";
+
+			// If insert type is filled in, check open/closed
+			var itype_selectedValue = itype_list[itype_selectedInd].value;
+
+			if ((itype_selectedValue != "cDNA with UTRs") && (itype_selectedValue != "DNA Fragment") && (itype_selectedValue != "None"))
+			{
+				// must have an open/closed value
+				oc_sel_val = oc_list[oc_selectedInd].value;
+
+				if (oc_sel_val == "")
+				{
+					alert("You must select an Open/Closed value to continue");
+					oc_list.focus();
+					oc_warning.style.display = "inline";
+					return false;
+				}
+			}
+			else 	// added May 28/07 to hide warning if showing from previous error
+			{
+				if (oc_warning.style.display == "inline")
+				{
+					oc_warning.style.display = "none";
+				}
+			}
+
+			return true;
+		}
+	}
+	else
+	{
+		// Hide all other warnings
+		it_warning.style.display = "none";
+		oc_warning.style.display = "none";
+	}
+	
+	return false;
+}
+
+
+// Feb. 29/08
+function verifyInsertSaveSequence()
+{
+	// Type of Insert can never be empty
+	var itype_list = document.getElementById("itype_list");
+	var itype_selectedInd = itype_list.selectedIndex;
+
+	var oc_list = document.getElementById("oc_list");
+	var oc_selectedInd = oc_list.selectedIndex;
+
+	var oc_warning = document.getElementById("oc_warning");
+	var it_warning = document.getElementById("it_warning");
+
+	// Feb. 5/08: Make Name a mandatory field
+	// Feb. 12/08: Make Status mandatory too
+// 	if (verifySequence() && verifyCDNA())		// April 18/08: Don't verify cDNA here, get error on sequence deletion
+	if (verifySequence())
+	{
+		// No Insert Type selected
+		if ((itype_selectedInd == 0) && (itype_list[itype_selectedInd].value == ""))
+		{
+			alert("You must select a Type of Insert to continue");
+			itype_list.focus();
+			it_warning.style.display = "inline";
+			oc_warning.style.display = "none";
+
+			return false;
+		}
+		else
+		{
+			it_warning.style.display = "none";
+
+			// If insert type is filled in, check open/closed
+			var itype_selectedValue = itype_list[itype_selectedInd].value;
+
+			if ((itype_selectedValue != "cDNA with UTRs") && (itype_selectedValue != "DNA Fragment") && (itype_selectedValue != "None"))
+			{
+				// must have an open/closed value
+				oc_sel_val = oc_list[oc_selectedInd].value;
+
+				if (oc_sel_val == "")
+				{
+					alert("You must select an Open/Closed value to continue");
+					oc_list.focus();
+					oc_warning.style.display = "inline";
+					return false;
+				}
+			}
+			else 	// added May 28/07 to hide warning if showing from previous error
+			{
+				if (oc_warning.style.display == "inline")
+				{
+					oc_warning.style.display = "none";
+				}
+			}
+
+			return true;
+		}
+	}
+	else
+	{
+		// Hide all other warnings
+		it_warning.style.display = "none";
+		oc_warning.style.display = "none";
+	}
+
+	return false;
+}
+
+// This function verifies, for dropdown lists where properties may be added, that if option 'Other' is selected, the new property value is filled in (essentially make sure that 'Other' textboxes are not left blank)
+function verifyOther(propList, propNameList)
+{
+    var prop;
+    var propName;
+    var propVal;
+    var pName;
+
+    for (var propID in propList)
+    {
+        prop = document.getElementById(propID);
+
+        var sel_ind = prop.selectedIndex;
+	var sel_val = prop[sel_ind].value;
+
+        if (sel_val.toLowerCase() == 'other')
+        {
+            propName = propList[propID];
+            textElem = document.getElementById(propName);
+            propVal = textElem.value;
+
+            if (propVal == "")
+            {
+                pName = propNameList[propID];
+
+                alert("Please fill in the value of 'Other' for '" + pName + "' property");
+                textElem.style.display = "inline";
+                textElem.focus();
+
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+
+
+//	Various utility functions used in various sections of the website
+
+// April 3/07, Marina: Check whether the input string is numeric
+// Taken from CodeToad: http://www.codetoad.com/javascript/isnumeric.asp
+// CAUTION: DO NOT USE 'char' as a variable name - It is a reserved keyword and will NOT work on Mac OS-X
+function isNumeric(sText)
+{
+	var validChars = "0123456789.";
+	var isNumber=true;
+	var aChar;
+ 
+	// remove whitespace if there is any
+	sText = trimAll(sText);
+
+ 	if (sText.length == 0) 
+		return false;
+	
+ 	if (sText.substring(0,1) == '0')
+		return false;
+	
+	for (i = 0; i < sText.length && isNumber == true; i++) 
+      	{ 
+		aChar = sText.charAt(i); 
+		
+		if (validChars.indexOf(aChar) == -1) 
+         	{
+			isNumber = false;
+         	}
+      	}
+
+	return isNumber;
+}
+
+// Trim leading and trailing whitespace from a string
+// Taken from http://www.aspdev.org/articles/javascript-trim
+// April 8/07, Marina, last updated Nov. 15/07
+function trimAll(sString)
+{
+	while ((sString.substring(0,1) == ' ') || (sString.substring(0,1) == '\t')  || (sString.substring(0,1) == '\n')  || (sString.substring(0,1) == '\r'))
+	{
+		sString = sString.substring(1, sString.length);
+	}
+	
+	while ((sString.substring(sString.length-1, sString.length) == ' ')  || (sString.substring(sString.length-1, sString.length) == '\t')  || (sString.substring(sString.length-1, sString.length) == '\n') || (sString.substring(sString.length-1, sString.length) == '\r'))
+	{
+		sString = sString.substring(0,sString.length-1);
+	}
+
+	// Added August 13, 2010; was not properly trimming HTML  
+	sString = sString.replace(/^\s*/, '').replace(/\s*$/, ''); 
+
+	return sString;
+}
+
+
+// 	Location functions
+
+// Added May 22/07, Marina
+// On Plate view: Sort table columns at the click of a mouse
+function sortByColumn(colName)
+{
+	sortBy = document.getElementById("sortByCol_hidden");
+	sortBy.value = colName;
+	
+	searchForm = document.printContainersOfOneTypeForm;
+	searchForm.submit();
+}
+
+// Feb. 15/08
+function groupByContainer()
+{
+	var locationOutputMode = document.getElementById("location_output_mode");
+	locationOutputMode.value = "2";
+	document.viewLocation.submit();
+}
+
+// Feb. 15/08
+function groupByIsolate()
+{
+	var locationOutputMode = document.getElementById("location_output_mode");
+	locationOutputMode.value = "1";
+	document.viewLocation.submit();
+}
+
+// Aug. 28/08
+function showPlates()
+{
+	var contTypeList = document.getElementById("cont_name_selection");
+	var contType = contTypeList[contTypeList.selectedIndex].value;
+
+	document.printPlatesForContainerForm.submit();
+}
+
+// 	Sequence functions
+
+function filterSpace(txt)
+{
+        var txt_ar = txt.split(' ');
+        var sel = "";
+
+        for (i = 0; i < txt_ar.length; i++)
+        {
+                sel += txt_ar[i];
+        }
+
+        return sel;
+}
+
+
+function filterRNASeq(seq)
+{
+    // Filter out characters other than A,C,G,T from DNA sequence
+    var nucleotides = "AaCcGgUuNn";
+    var newSeq = "";
+
+    for (var i = 0; i < seq.length; i++)
+    {
+        var myChar = seq.charAt(i);
+
+        if (inArray(myChar, nucleotides))
+            newSeq += myChar;
+    }
+
+    return newSeq;
+}
+
+
+function filterProteinSeq(seq)
+{
+// alert("yow");
+    seq = seq.toUpperCase();
+
+    // Filter out characters other than amino acids from Protein sequence
+    // Update Aug. 24/09: include ambiguous amino acids - B, J, X, Z
+    var nucleotides = "AaBbCcDdEeFfGgHhIiKkLlMmNnPpQqRrSsTtVvWwXxYyZz*";
+    var newSeq = "";
+
+    for (var i = 0; i < seq.length; i++)
+    {
+        var myChar = seq.charAt(i);
+
+        if (inArray(myChar, nucleotides))
+            newSeq += myChar;
+    }
+
+    return newSeq;
+}
+
+function filterDNASeq(seq)
+{
+    // Filter out characters other than A,C,G,T from DNA sequence
+    var nucleotides = "AaCcGgTtNn";
+    var newSeq = "";
+
+    for (var i = 0; i < seq.length; i++)
+    {
+        var myChar = seq.charAt(i);
+
+        if (inArray(myChar, nucleotides))
+            newSeq += myChar;
+    }
+
+    return newSeq;
+}
+
+
+function showHideChildren(linkID, contentElemID)
+{
+	// Extract show/hide portion of linkID
+	var ind1 = linkID.indexOf('_');
+	var linkType = linkID.substring(0, ind1);	// show or hide
+	var listType = linkID.substring(ind1+1);	// vector or cell_line
+	
+    	var currLink = document.getElementById(linkID);
+    	var contentElem = document.getElementById(contentElemID);
+
+	var showLink = document.getElementById("show_" + listType);
+    	var hideLink = document.getElementById("hide_" + listType);
+
+	// Show/hide contents - July 6/09: Changed 'inline' to 'table-row' - in new function children are contained within a <tr> element
+	contentElem.style.display = (linkType == "show") ? "table-row" : "none";	// do not use 'inline'!
+	
+	// Switch between show/hide link (if currently have 'show', hide it and inhide 'hide', & v.v.)
+	showLink.style.display = (linkType == "show") ? "none" : "inline";	// keep 'inline' here!
+	hideLink.style.display = (linkType == "show") ? "inline" : "none";
+}
+
+
+// April 16, 2010: Just invoke a Python script to execute a command-line cp command
+function copyTmpFile(srcFileName, toFileName)
+{
+	url = cgiPath + "commands.py";
+
+	xmlhttp = createXML();
+	xmlhttp.open("POST", url, false);
+	xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+
+	args = "cmd=cp&srcFile=" + srcFileName + "&toFile=" + toFileName;
+	xmlhttp.send(args);
+
+	xmlhttp.onreadystatechange = openFile(xmlhttp);
+}
+
+function openFile(xmlhttp)
+{
+	if (xmlhttp.readyState == 4)
+	{
+		if (xmlhttp.status == 200)
+		{
+// 			prompt("", xmlhttp.responseText);
+		}
+	}
+}
+
+// March 23/09: Output Vector information in GenBank format
+function exportToGenbank(rID, limsID)
+{
+	url = cgiPath + "genbank.py";
+	xmlhttp = createXML();
+	xmlhttp.open("POST", url, false);
+	xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+
+	seqParams = "rID=" + rID;
+
+	xmlhttp.send(seqParams);
+
+	xmlhttp.onreadystatechange = outputGenBankInfo(xmlhttp);
+}
+
+function outputGenBankInfo(xmlhttp)
+{
+	if (xmlhttp.readyState == 4)
+	{
+		if (xmlhttp.status == 200)
+		{
+			fName = hostName + "Reagent/genbank/" + limsID + ".gbk";
+// 			return popup(fName, limsID, 1200, 1200, 'yes');
+		}
+	}
+// 	else
+// 	{
+// 		alert(xmlhttp.readyState);
+// 	}
+}
+
+// June 5/07, Marina: Export sequence to FASTA file
+function exportDNASeqToFasta(fastaCont)
+{
+	var fastaContent = document.getElementById("dna_fasta_content");
+	var seqExportForm = document.getElementById("export_dna_sequence_form");
+
+	fastaContent.value = fastaCont;
+	seqExportForm.submit();
+}
+
+
+// June 5/07, Marina: Export sequence to FASTA file
+function exportProteinSeqToFasta(fasCont)
+{
+	var fastaContent = document.getElementById("protein_fasta_content");
+	var seqExportForm = document.getElementById("export_protein_sequence_form");
+	
+	fastaContent.value = fasCont;
+	seqExportForm.submit();
+}
+
+// Oct. 23/09
+function exportRNASeqToFasta(fastaCont)
+{
+	var fastaContent = document.getElementById("rna_fasta_content");
+	var seqExportForm = document.getElementById("export_rna_sequence_form");
+	
+	fastaContent.value = fastaCont;
+	seqExportForm.submit();
+}
+
+// Initialization - June 15, 2007, Marina
+function initAll()
+{
+// 	document.getElementById('header_table').style.width = screen.width-40;
+// 	document.getElementById('warning_div').style.width = screen.width-40;
+	
+	//if ((window.location.href.indexOf("Location.php?View=") >= 0) && (window.location.href.indexOf("&Mod=") >= 0))
+	//{
+		// make sure we're on the plate's detailed view
+		if (document.getElementById("changeAttributeSelect"))
+		{
+			document.getElementById("changeAttributeSelect").selectedIndex = 0;
+			clearAllWells(window.location.href.substr((hostName+"Location.php?View=").length+"&Mod=".length+1, window.location.href.length));
+		}
+	//}
+
+	initSearch();
+	prepareVectorMap(cgiPath);
+	prepareOligoMap(cgiPath);
+}
+
+
+// function setSessionVariables()
+// {
+// 	enableCheckboxes();
+// 	document.addReagentTypeForm.submit();
+// 
+// 	if (verifyNewReagentTypeName() && verifyNewReagentTypePrefix())
+// 	{
+// 		document.addReagentTypeForm.action = cgiPath + "reagent_type_request_handler.py";
+// 		document.addReagentTypeForm.submit();	
+// 	}
+// }
+
+// Jan. 3, 2010
+function deleteContainer(contID)
+{
+	if (confirm('Are you sure you wish to delete container?  Deletion cannot be undone.'))
+	{
+		document.deleteContainerForm.submit();
+	}
+}
+
+
+function initSearch()
+{
+	var searchField = document.getElementById("search_term_id");
+	
+	if (searchField != null)		// won't show up on any view other than Search
+		searchField.focus();
+}
+
+
+// Fetch all lists of lab members 
+function getLabMembersLists()
+{
+	var labMemLists = document.getElementsByTagName("SELECT");
+	var constMemListName = "labSourceMembers_";
+
+	var tmpList;
+	var resultList = Array();
+
+	for (i = 0; i < labMemLists.length; i++)
+	{
+		tmpList = labMemLists[i];
+
+		if ((tmpList.name.substring(0, tmpList.name.length-1) == constMemListName))
+			resultList.push(tmpList);
+	}
+	
+	return resultList;
+}
+
+
+// 	Menu functions
+// 	April 2007, Marina
+
+function expandAll()
+{
+	var list = document.getElementsByTagName('ul');
+
+	for (var i=0; i < list.length; i++)
+	{
+		if (list[i].className == 'submenu')
+		{
+			list[i].style.display = "block";
+		}
+	}
+}
+
+function expandCollapse(listID)
+{
+	var topElem = document.getElementById(listID);
+
+	// Extract the numeric portion of the name
+	var ind1 = listID.indexOf('_');
+	var menuName = listID.substring(0, ind1);
+	var level = parseInt(listID.substring(ind1+1));
+
+	// Find corresponding submenu
+	var nextLevel = level + 1;
+	var subID = menuName + '_' + nextLevel;
+	var subElem = document.getElementById(subID);
+
+	// Switch between expand/collapse icon on top menu
+	var menuExpandImg = document.getElementById(menuName + "_expand_img");
+	var menuCollapseImg = document.getElementById(menuName + "_collapse_img");
+
+	if (menuExpandImg.style.display == "inline")
+	{
+		menuExpandImg.style.display = "none";
+		menuCollapseImg.style.display = "inline";
+	}
+	else
+	{
+		menuCollapseImg.style.display = "none";
+		menuExpandImg.style.display = "inline";
+	}
+
+	// Show the appropriate submenu
+	subElem.style.display = (subElem.style.display=="block")?"none":"block";	
+}
+
+
+
+// 	Project functions
+// 	June 2007, Marina
+
+function getSelectedLab()
+{
+	var labList = document.getElementById("labList");
+	var labSelInd = labList.selectedIndex;
+	
+	return labList.options[labSelInd].id;
+}
+
+
+function showLabMembersList()
+{
+	var labID = getSelectedLab();
+	var currLabMemListName = "lab_source_list_" + labID;
+	
+	var labMemList = document.getElementById(currLabMemListName);
+	var constMemListName = "labSourceMembers_";
+
+	// does not appear on all views
+	if (labMemList)
+		labMemList.style.display = "inline";		// use "" for browser compatibility??
+
+	// June 29/07: Added functionality for Delete view
+	var membersRow = document.getElementById("deleteMembersRow");
+	
+	if (membersRow) 
+	{
+		if (labID == 0)
+			membersRow.style.display = "none";
+		else
+			membersRow.style.display = "table-row";
+	}
+	
+	// Hide all other lists
+	var otherLabMemLists = document.getElementsByTagName("SELECT");
+	var currList;
+
+	for (i = 0; i < otherLabMemLists.length; i++)
+	{
+		tmpList = otherLabMemLists[i];
+		ind1 = tmpList.name.indexOf("_")+1;
+
+		if ( (tmpList.name.substring(0, ind1) == constMemListName) && (tmpList != labMemList))
+		{
+			tmpList.style.display = "none";
+		}
+	}
+}
+
+// Return an array of selected items in a list
+// Resulting array is a list of OPTION elements
+function getSelectedOptions(myList)
+{
+// 	myList = myList.replace("'", "\\'");	// NO!!!!!!!
+	myList = unescape(myList);
+
+	var fromList = document.getElementById(myList);
+	var selOpts = new Array();
+	
+	for (i = 0; i < fromList.options.length; i++)
+	{
+		currOptn = fromList.options[i];
+		
+		if (currOptn.selected)
+		{
+			selOpts.push(currOptn);
+		}
+	}
+	
+	return selOpts;
+}
+
+
+// Identify which 'access level' (step 2) radio button is currently selected
+function getSelectedRole(step)
+{
+	var inputList = document.getElementsByTagName("INPUT");
+	var inputTmp;
+	var radioTmp;
+	
+	for (i = 0; i < inputList.length; i++)
+	{
+		inputTmp = inputList[i];
+		
+		if (inputTmp.type == 'radio')
+		{
+			rTempName = inputTmp.name;
+		
+			if (rTempName == "access_levels")
+			{
+				if (inputTmp.checked)
+				{
+					return inputTmp.value;
+				}
+			}
+		}
+	}
+}
+
+
+// Called at step 1 to move members from source list to readers, writers or admin list, depending on access level selected
+function addMembers(srcListID, role)
+{
+	var targetListID;
+	
+	switch (role)
+	{
+		case 'read':
+			targetListID = "readers_target_list";
+		break;
+		
+		case 'write':
+			targetListID = "writers_target_list";
+		break;
+		
+		default:
+			// move back to original list
+			targetListID = "lab_source_list_" + getSelectedLab();
+		break;
+	}
+	
+	moveListElements(srcListID, targetListID, false);
+}
+
+
+// Called at step 3 to move members from readers/writers list back to the original members list
+// Modified June 28/07 - move a member back to his/her own lab, which is not necessarily the lab currently selected 
+function removeProjectMembers()
+{
+	// Move selected members from ALL target lists
+	var readersListID = "readers_target_list";
+	var writersListID = "writers_target_list";
+
+	var readersList = document.getElementById(readersListID);
+	var writersList = document.getElementById(writersListID);
+
+	var targetListID = "";
+	var targetLabListIDPrefix = "lab_source_list_";
+	
+	var selReaders = getSelectedOptions(readersListID);
+	var selWriters = getSelectedOptions(writersListID);
+	
+	// Move readers first, then writers
+	for (r = 0; r < selReaders.length; r++)
+	{
+		rdrOpt = selReaders[r];
+		rdrOptID = rdrOpt.id;
+
+		// extract the lab ID from the option ID - the character after "_lab_" (using ID, since 'name' is not an attribute of the OPTION tag)
+		str1 = "_lab_";
+		ind1 = rdrOptID.indexOf(str1) + str1.length;
+		labID = rdrOptID.substring(ind1);
+		targetListID = targetLabListIDPrefix + labID;
+		targetList = document.getElementById(targetListID);
+		
+		// Not using moveListElements, since it incorrectly moves ALL values in the source list to the same target list
+		if (targetList.options.length == 0)
+		{
+			targetList.options.add(rdrOpt);
+			removeElement(readersList, rdrOpt);
+			
+		}
+		else
+		{
+			addElement(targetList, targetList.options.length, rdrOpt);
+			removeElement(readersList, rdrOpt);
+		}
+		
+		clearAllElements(targetListID);
+	}
+
+	// writers
+	for (w = 0; w < selWriters.length; w++)
+	{
+		wrtrOpt = selWriters[w];
+		wrtrOptID = wrtrOpt.id;
+
+		// extract the lab ID from the option ID - the character after "_lab_" (using ID, since 'name' is not an attribute of the OPTION tag)
+		str1 = "_lab_";
+		ind1 = wrtrOptID.indexOf(str1) + str1.length;
+		labID = wrtrOptID.substring(ind1);
+		targetListID = targetLabListIDPrefix + labID;
+		targetList = document.getElementById(targetListID);
+
+		// Not using moveListElements, since it incorrectly moves ALL values in the source list to the same target list
+		if (targetList.options.length == 0)
+		{
+			targetList.options.add(wrtrOpt);
+			removeElement(writersList, wrtrOpt);
+		}
+		else
+		{
+			addElement(targetList, targetList.options.length, wrtrOpt);
+			removeElement(writersList, wrtrOpt);
+		}
+		
+		clearAllElements(targetListID);
+	}
+	
+	clearCheckboxes(readersListID, targetListID);	
+	clearCheckboxes(writersListID, targetListID);
+}
+
+function removeElement(myList, optn)
+{
+	var tmpOpt;
+	
+	for (i = 0; i < myList.options.length; i++)
+	{
+		tmpOpt = myList.options[i];
+		
+		if (tmpOpt.text == optn.text)
+			myList.options[i] = null;
+	}
+}
+
+function addElementToListFromInput(inputID, listID)
+{
+	// ATTENTION: PHP escapes quotation marks!  The actual field name contains a slash before a quote.  Must, therefore, append a slash here, for the input name to be recognized1
+
+// 	inputID = inputID.replace("'", "\\'");	// maybe need replaceAll??
+	inputID = unescape(inputID);
+// 	listID = listID.replace("'", "\\'");	// maybe need replaceAll??
+	listID = unescape(listID);
+
+	var fIn = document.getElementById(inputID);
+	var toList = document.getElementById(listID);
+	var tmpVal = fIn.value;
+
+	newOptn = document.createElement("OPTION");
+	newOptn.text = tmpVal;
+	newOptn.value = tmpVal;
+
+	// June 15, 2010
+	if (trimAll(tmpVal).toLowerCase() == 'other')
+	{
+		alert("This value is not allowed.  Please verify your input.");
+		return false;
+	}
+	
+	if (trimAll(tmpVal) == '')
+	{
+		return false;
+	}
+
+
+	// Now insert it at the appropriate position in the target list to maintain alphabetical ordering!
+	if (toList.options.length == 0)
+	{
+		toList.options.add(newOptn);
+	}
+	else
+	{
+		addElement(toList, toList.options.length, newOptn, true);
+	}
+
+	if (!addElementError)
+	{
+		// clear option value
+		fIn.value = "";
+	}
+
+	fIn.focus();		// June 15/09
+}
+
+function removePropertyListValue(pAlias)
+{
+	// ATTENTION: PHP escapes quotation marks!  The actual field name contains a slash before a quote.  Must, therefore, append a slash here, for the input name to be recognized1
+// 	pAlias = pAlias.replace("'", "\\'");	// KEEP!!! maybe need replaceAll??
+	pAlias = unescape(pAlias);
+
+	var pList = document.getElementById("propertyValuesInputList_" + pAlias);
+	var pVal;
+	var listLen = pList.options.length;
+// 	alert(listLen);
+
+	for (i = listLen-1; i >= 0; i--)
+	{
+		if (pList.options[i].selected == true)
+		{
+// 			alert(pList.options[i].value);
+
+// 			pVal = pList[pList.selectedIndex].value;
+			pVal = pList.options[i].value;
+// 			alert(i);
+// 			alert(pVal);
+			removeListElement(pList, pVal);
+
+			// # options has decreased by 1 - update!!
+			listLen = pList.options.length;
+			i = listLen;
+// 			alert(listLen);
+		}
+	}
+
+// 	removeListElement(pList, pVal);
+}
+
+// myList: object (e.g. SELECT)
+// myElem: value (text, numeric)
+function removeListElement(myList, myElem)
+{
+	var counter = 0;
+	var tempList = myList;
+	var tempElem;
+
+	while (counter < tempList.options.length)
+	{
+		tempElem = tempList.options[counter].value;
+
+		if (tempElem == myElem)
+		{
+			// remove element from original list
+			myList.options[counter] = null;
+			
+			// recompute list length and reset counter
+			tempList = myList;
+			counter = 0;
+		}
+		else
+		{
+			counter++;
+		}
+	}
+}
+
+// Oct. 8, 2010: Check if a value exists in a dropdown list
+// Not checking numeric or case-sensitivity here; see if needed along the way
+function existsListElement(targetListID, optValue)
+{
+	var tList = document.getElementById(targetListID);
+// alert(optValue);
+	var result = false;
+
+	for (i=0; i < tList.options.length; i++)
+	{
+		tmpOptn = tList.options[i];
+// alert(tmpOptn.value);
+		if (tmpOptn.value == optValue)
+			return true;
+	}
+
+	return false;
+}
+
+
+// Used on Project, User and Lab Views to add/remove members to/from projects/labs, or modify member project lists
+function moveListElements(fromListID, targetListID, numeric, check_case)
+{
+// alert("in moveListElements");
+// 	fromListID = fromListID.replace("'", "\\'");	// maybe need replaceAll??
+	fromListID = unescape(fromListID);
+// 	targetListID = targetListID.replace("'", "\\'");	// maybe need replaceAll??
+	targetListID = unescape(targetListID);
+// alert(targetListID);
+	var toList = document.getElementById(targetListID);
+// 	var labID = getSelectedLab();
+	var fromList = document.getElementById(fromListID);
+	var selOpts = getSelectedOptions(fromListID);
+	
+	var currOptn;
+	var newOptn;
+
+	for (m = 0; m < selOpts.length; m++)
+	{
+		currOptn = selOpts[m];
+
+// 	alert(currOptn.value);
+
+		// Oct. 8, 2010: move IFF doesn't exist
+		if (!existsListElement(targetListID, currOptn.value))
+		{
+			newOptn = document.createElement("OPTION");
+			newOptn.text = currOptn.text;
+			newOptn.value = currOptn.value;
+			newOptn.id = currOptn.id;
+	
+			// Now insert it at the appropriate position in the target list to maintain alphabetical ordering!
+			if (toList.options.length == 0)
+			{
+				toList.options.add(newOptn);
+			}
+			else
+			{
+				// traverse list recursively to find insert position
+				// With projects, however, the index comparison should be numeric
+				if (numeric == true)
+				{
+					addNumElement(toList, toList.options.length, newOptn);
+				}
+				else
+				{
+					addElement(toList, toList.options.length, newOptn, check_case);
+				}
+			}
+		}
+	}
+		
+	
+	// Remove this element from original list
+	var totalOpts = fromList.options.length;
+	
+	if (!addElementError)
+	{
+		for (j in selOpts)
+		{
+			optRmv = selOpts[j];
+			
+			for (i = 0; i < totalOpts; i++)
+			{
+				origOptn = fromList.options[i];
+				
+				if (origOptn.value == optRmv.value)
+				{
+					fromList.options[i] = null;
+				}
+		
+				// RECOMPUTE LIST LENGTH!!!
+				totalOpts = fromList.options.length;
+			}
+		}
+	}
+	else
+	{
+		// still, deselect this option
+		clearAllElements(fromListID);
+	}
+	
+	clearCheckboxes(fromListID, targetListID);
+}
+
+// May 27, 2010
+// Very specific function - at reagent type creation, take the newly entered reagent type name and append to list of parent types if requested
+function addReagentTypeNameToParentsList()
+{
+	var rTypeName = document.getElementById("reagent_type_name").value;
+	var includeParent = document.getElementById("includeParent");
+
+	if (includeParent.checked)
+	{
+		var parents = document.getElementById("add_reagent_type_parents");
+		var newOptn = document.createElement("OPTION");
+
+		newOptn.value = rTypeName;
+		newOptn.selected = true;
+		parents.options.add(newOptn);
+	}
+}
+
+
+function addFormElements(aForm, aList)
+{
+	lElems = aList.options;
+
+	for (i = 0; i < lElems.length; i++)
+	{
+		newElem = lElems[i].value;
+		aForm.appendChild(newElem);
+	}
+}
+
+function clearCheckboxes(fromListID, targetListID)
+{
+	var fromList = document.getElementById(fromListID);
+	var toList = document.getElementById(targetListID);
+	
+	var chkbxFrom;
+	var chkbxTo;
+	
+	var chkbxSource = document.getElementById("add_all_chkbx");
+	var chkbxRead = document.getElementById("select_all_reader_chkbx");
+	var chkbxWrite = document.getElementById("select_all_writer_chkbx");
+	var chkbxAdmin = document.getElementById("select_all_admin_chkbx");
+	
+	var totalSelectedTo = getTotalItemsSelected(toList);
+
+	// Checkboxes are not present on some views, in which case this function produces an error
+	if (chkbxSource || chkbxRead || chkbxWrite || chkbxAdmin)
+	{
+		switch (targetListID)
+		{
+			case 'readers_target_list':
+				chkbxTo = chkbxRead;
+			break;	
+
+			case 'writers_target_list':
+				chkbxTo = chkbxWrite;
+			break;
+
+			case 'user_projects_write':
+				chkbxTo = chkbxWrite;
+			break;
+			
+			case 'user_projects_readonly':
+				chkbxTo = chkbxRead;
+			break;
+
+			default:
+				chkbxTo = chkbxSource;
+			break;
+		}
+
+		switch (fromListID)
+		{
+			case 'readers_target_list':
+				chkbxFrom = chkbxRead;
+			break;
+
+			case 'writers_target_list':
+				chkbxFrom = chkbxWrite;
+			break;			
+			
+			case 'user_projects_readonly':
+				chkbxFrom = chkbxRead;
+			break;
+
+			case 'user_projects_write':
+				chkbxFrom = chkbxWrite;
+			break;
+			
+			default:
+				chkbxFrom = chkbxSource;
+			break;
+		}
+		
+		// Check if no elements remain in the source list, AND no elements are selected in the target list - then clear checkboxes
+		if (totalSelectedTo != toList.options.length)
+		{
+			chkbxTo.checked = false;
+		}
+
+		if (fromList.options.length == 0)
+		{
+			chkbxFrom.checked = false;
+		}
+	}
+}
+
+
+function getTotalItemsSelected(toList)
+{
+	var totalSelected = 0;
+	
+	for (i = 0; i < toList.options.length; i++)
+	{
+		var tempOptn = 	toList.options[i];
+		
+		if (tempOptn.selected)
+			totalSelected++;
+	}
+
+	return totalSelected;
+}
+
+
+// June 3, 2010: as the name implies
+function addProjectOwnerToWritersList()
+{
+	var ownersList = document.getElementById('projectOwnersList');
+	var selInd = ownersList.selectedIndex;
+	var pOwnerID = ownersList[selInd].value;
+	var pOwner = ownersList[selInd].text;
+
+	var newOptn = document.createElement('OPTION');
+	newOptn.text = pOwner;
+	newOptn.value = pOwnerID;
+
+	var writersList = document.getElementById('writers_target_list');
+
+	// make sure it doesn't exist - do duplicats check here
+	writersArray = new Array();
+
+	for (i=0; i < writersList.options.length; i++)
+	{
+		tmpOpt = writersList.options[i];
+
+		if (tmpOpt)
+		{
+			writersArray.push(tmpOpt.value);
+		}
+	}
+
+	if (!hasArrayElement(writersArray, pOwnerID))
+	{
+		if (writersList.options.length == 0)
+			addElement(writersList, 1, newOptn, true);
+		else
+			addElement(writersList, writersList.options.length, newOptn, true);
+	}
+}
+
+
+// June 3, 2010: At automated password reminder page, check that EITHER username or full name is filled, don't leave empty text fields
+function checkPasswordReminder()
+{
+	var username = document.getElementById('uname_remind');
+	var fullName = document.getElementById('udesc_remind');
+
+	// first, check username
+	if (trimAll(username.value) == '')
+	{
+		// if username is not filled, check description
+		if (trimAll(fullName.value) == '')
+		{
+			alert("Please provide either your user name or your full name as recorded in OpenFreezer.\n\nIf you have not yet obtained a user account, please contact the Administrator.");
+
+			return false;
+		}
+	}
+
+	return true;
+}
+
+// Recursive method to insert an element to maintain alphabetical ordering
+// mylist - array of list elements
+// position - initial start position @ start of recursion
+function addElement(mylist, listSize, myOptn, check_case)
+{
+// 	alert("List size " + listSize);
+	
+	myPos = listSize - 1;
+
+	// alert(check_case);
+	addElementError = false;	// reset globally
+
+// alert(check_case);
+
+	// May 26, 2010: Disallow duplicate values
+	if (check_case)
+	{
+// 	alert("checking case");
+// 	alert(myPos);
+// 	alert(">>>" + mylist.options[myPos].text + "<<<");
+// 	alert(">>>" + myOptn.text + "<<<");
+
+		if (mylist.options[myPos])	// added June 3
+		{
+			if (trimAll(mylist.options[myPos].text).toLowerCase() == trimAll(myOptn.text).toLowerCase())
+			{
+				alert("This value already exists in the list.  Please verify your input.");
+				addElementError = true;
+				return;
+			}
+		}
+	}
+
+	if (listSize == 1)
+	{
+		var newOptn = document.createElement("OPTION");
+
+		newOptn.text = myOptn.text;
+		newOptn.value = myOptn.value;
+		newOptn.id = myOptn.id;		// june 28/07
+
+		// Sept. 25/08: Try to use case-insensitive comparison
+// 		if (mylist.options[myPos].text < myOptn.text)
+		if (mylist.options[myPos] && (mylist.options[myPos].text.toLowerCase() < myOptn.text.toLowerCase()))
+		{
+			//alert(mylist.options[myPos].value + " comes BEFORE " + myOptn.value);
+			mylist.options.add(newOptn, myPos+1);		
+		}
+		else
+		{
+			//alert(mylist.options[myPos].value + " comes AFTER " + myOptn.value);
+			mylist.options.add(newOptn, 0);
+		}
+	}	
+	else
+	{
+		// Sept. 25/08: Try to use case-insensitive comparison
+// 		if (mylist.options[myPos].text < myOptn.text)
+		if (mylist.options[myPos].text.toLowerCase() < myOptn.text.toLowerCase())
+		{
+			//alert(mylist.options[myPos].value + " comes BEFORE " + myOptn.value);
+			
+			var newOptn = document.createElement("OPTION");
+
+			newOptn.text = myOptn.text;
+			newOptn.value = myOptn.value;
+			newOptn.id = myOptn.id;		// june 28/07
+			
+			mylist.options.add(newOptn, myPos+1);
+		}
+		else
+		{
+			//alert(mylist.options[myPos].value + " comes AFTER " + myOptn.value);
+			addElement(mylist, listSize-1, myOptn, check_case);
+		}
+	}
+}
+
+
+// Same, only compare NUMERIC indices
+function addNumElement(mylist, listSize, myOptn)
+{
+	myPos = listSize - 1;
+	
+	if (listSize == 1)
+	{
+		var newOptn = document.createElement("OPTION");
+
+		newOptn.text = myOptn.text;
+		newOptn.value = myOptn.value;
+		newOptn.id = myOptn.id;		// june 28/07
+
+		if (parseInt(mylist.options[myPos].value) < parseInt(myOptn.value))
+		{
+			//alert(mylist.options[myPos].value + " comes BEFORE " + myOptn.value);
+			mylist.options.add(newOptn, myPos+1);		
+		}
+		else
+		{
+			//alert(mylist.options[myPos].value + " comes AFTER " + myOptn.value);
+			mylist.options.add(newOptn, 0);
+		}
+	}	
+	else 
+	{
+		if (parseInt(mylist.options[myPos].value) < parseInt(myOptn.value))
+		{
+			//alert(mylist.options[myPos].value + " comes BEFORE " + myOptn.value);
+			
+			var newOptn = document.createElement("OPTION");
+
+			newOptn.text = myOptn.text;
+			newOptn.value = myOptn.value;
+			newOptn.id = myOptn.id;		// june 28/07
+			
+			mylist.options.add(newOptn, myPos+1);
+		}
+		else
+		{
+			//alert(mylist.options[myPos].value + " comes AFTER " + myOptn.value);
+			addNumElement(mylist, listSize-1, myOptn);
+		}
+	}
+}
+
+
+// Added Oct. 5, 2010
+function showLabProjects(labListID)
+{
+// alert(labListID);
+	var labsList = document.getElementById(labListID);
+// 	alert(labsList.selectedIndex);
+	var labSelInd = labsList.selectedIndex;
+	var selLabID = labsList[labSelInd].value;
+// 	alert(selLab);
+
+	var labProjectList = document.getElementById("lab_projects_" + selLabID);
+
+	var allSelects = document.getElementsByTagName("SELECT");
+
+	var allSpans = document.getElementsByTagName("SPAN");
+
+	var noLabProjects = document.getElementById("no_projects_" + selLabID);
+
+	for (a=0; a < allSelects.length; a++)
+	{
+		tmpSel = allSelects[a];
+
+		if ((tmpSel.id.indexOf("lab_projects_") == 0) && (tmpSel.id != "lab_projects_" + selLabID))
+			tmpSel.style.display = "none";
+	}
+
+	for (b=0; b < allSpans.length; b++)
+	{
+		tmpSpan = allSpans[b];
+
+		if ((tmpSpan.id.indexOf("no_projects_") == 0) && (tmpSpan.id != "no_projects_" + selLabID))
+			tmpSpan.style.display = "none";
+	}
+
+	if (labProjectList)
+	{
+		document.getElementById("addReadProjects").onclick = function(){addProjects("lab_projects_" + selLabID, 'readonly')};
+		labProjectList.style.display = "";
+	}
+
+	if (noLabProjects)
+		noLabProjects.style.display = "inline";
+
+	// show current checkbox and hide the rest
+	var allDivs = document.getElementsByTagName("DIV");
+
+	for (c=0; c < allDivs.length; c++)
+	{
+		tmpDiv = allDivs[c];
+
+		if ((tmpDiv.id.indexOf("selectAllCaption_") == 0) && (tmpDiv.id != "selectAllCaption_" + selLabID))
+			tmpDiv.style.display = "none";
+	}
+
+	document.getElementById("project_read_checkbox").style.display = "";
+
+	// no 'select all' box for empty lab project lists
+	if (document.getElementById("selectAllCaption_" + selLabID))
+		document.getElementById("selectAllCaption_" + selLabID).style.display = "";
+
+	document.getElementById("projectCaption").style.display = "";
+}
+
+function hideLabProjects()
+{
+	// get the selected labID and hide the corresponding project list
+	var labsList = document.getElementById("projectLabID");
+// 	alert(labsList.selectedIndex);
+	var labSelInd = labsList.selectedIndex;
+	var selLabID = labsList[labSelInd].value;
+// alert(selLabID);
+
+	var labProjectList = document.getElementById("lab_projects_" + selLabID);
+
+	// no lab project list might be shown at this point
+	if (labProjectList)
+		labProjectList.style.display = "none";
+	
+	document.getElementById("project_read_checkbox").style.display = "none";
+	document.getElementById("projectCaption").style.display = "none";
+}
+
+// Select all options in a list; takes as arguments a list name and a checkbox name - checkbox needs to be cleared when function returns
+// April 3/09: Renamed function from selectAllUsers to selectAll - code used in many cases, not just users
+function selectAll(cbID, uListName, includeDisabled)
+{
+	var checkBox = document.getElementById(cbID);
+	
+	if (checkBox.checked)
+	{
+		// select all
+		selectAllElements(uListName, includeDisabled);
+	}
+	else
+	{
+		// clear all
+		clearAllElements(uListName);
+	}
+}
+
+
+function selectAllContainerProperties(cbID, uListName)
+{
+	var checkBox = document.getElementById(cbID);
+	
+	if (checkBox.checked)
+	{
+		// select all
+		selectAllElements(uListName);
+	}
+	else
+	{
+		// clear all
+		clearAllElements(uListName);
+	}
+}
+
+
+// Select all elements in a list 
+// mainly needed for passing form data to CGI, but there are other applications
+function selectAllElements(listName, includeDisabled)
+{
+	listName = unescape(listName);
+
+	var myList = document.getElementById(listName);
+	var i;
+
+	for (i = 0; i < myList.options.length; i++)
+	{
+		// Dec. 11/09, exclude disabled options if requested
+// alert(includeDisabled);
+		if (!includeDisabled)
+		{
+			if (myList.options[i].disabled != true)
+				myList.options[i].selected = true;
+		}
+		else
+			myList.options[i].selected = true;
+	}
+}
+
+
+// Similar to getSelectedOptions but returns a list of actual element VALUES
+function getSelectedElements(myList)
+{
+	var fromList = document.getElementById(myList);
+	var selOpts = new Array();
+	
+	for (i = 0; i < fromList.options.length; i++)
+	{
+		currOptn = fromList.options[i];
+		
+		if (currOptn.selected)
+		{
+			selOpts.push(currOptn.value);
+		}
+	}
+	
+	return selOpts;
+}
+
+
+function clearAllElements(listName)
+{
+	listName = unescape(listName);
+
+	var myList = document.getElementById(listName);
+	
+	for (i = 0; i < myList.options.length; i++)
+	{
+		myList.options[i].selected = false;
+	}
+}
+
+// Removed August 24/07 - think it's deprecated
+// Returns true if a value has been selected from the list identified by projectListID; returns false otherwise
+// function verifyProject()
+// {
+// 	var projectList = document.getElementById("packetList");
+// 	var packet_selectedInd = projectList.selectedIndex;
+// 	var projectWarning = document.getElementById("project_warning");
+// 	
+// 	if (packet_selectedInd <= 0)
+// 	{
+// 		alert ("Please select a Project ID to view");
+// 		projectList.focus();
+// 		projectWarning.style.display = "inline";
+// 
+// 		return false;
+// 	}
+// 	
+// 	return true;	
+// }
+
+
+// June 1/07, Marina: Make sure a project ID has been selected from a dropdown list
+// Essentially performs the same action as verifyProject and verifyPacket, except this time the function is being invoked on Project deletion 
+// It takes as arguments the ID of the Project dropdown list, not reagent type
+// Returns true if a value has been selected from the list identified by projectListID; returns false otherwise
+function verifyProjectDeletion(projectListID, submitID)
+{
+	var projectList = document.getElementById(projectListID);
+	var packet_selectedInd = projectList.selectedIndex;
+	var projectWarning = document.getElementById("project_warning");
+	
+	var submitBtn = document.getElementById(submitID);
+	
+	if (packet_selectedInd <= 0)
+	{
+		submitBtn.disabled = true;	
+		return false;
+	}
+	else 
+	{
+		// If everything is OK this time but warning was shown previously, hide it
+		if (projectWarning)
+		{
+			if (projectWarning.style.display == "inline")
+			{
+				projectWarning.style.display = "none";
+			}
+		}
+		
+		submitBtn.disabled = false;
+	}
+	
+	return true;	
+}
+
+// Get the number of selected elements in a list
+// aList: List object (not name!)
+function getNumSelected(aList)
+{
+	var numSel = 0;
+	
+	for (i = 0; i < aList.options.length; i++)
+	{
+		if (aList.options[i].selected)
+			numSel++;
+	}
+	
+	return numSel;
+}
+
+// Used in project creation or in adding members to a project: Make sure the resulting list of members is not empty
+// Updated June 20/07 by Marina
+function verifyMembers(memListID)
+{
+	var membersList = document.getElementById(memListID);
+//	var numSel = 0;
+	var numSel = getNumSelected(membersList);	// june 29/27
+	var proceed = true;
+	
+	
+// 	for (i = 0; i < membersList.options.length; i++)
+// 	{
+// 		if (membersList.options[i].selected)
+// 			numSel++;
+// 	}
+	
+	var message;
+	
+	switch (memListID)
+	{
+		case 'readers_target_list':
+			message = "The list of members who have read-only access to this project is empty.  Are you sure you wish to proceed?";
+		break;
+		
+		case 'writers_target_list':
+			message = "The list of members who have write access to this project is empty.  Are you sure you wish to proceed?";
+		break;
+		
+		default:
+
+		break;
+	}
+	
+	if (numSel == 0)
+		proceed = confirm(message);
+
+	return proceed;
+}
+
+function verifyProjectName(pNameID)
+{
+	var packetNameField = document.getElementById(pNameID);
+	var projectOwnerWarning = document.getElementById("projectOwnerWarning");
+	var projectNameWarning = document.getElementById("projectNameWarning");
+	var projectDescrWarning = document.getElementById("projectDescrWarning");
+
+	// Hide owner warning if shown
+	projectOwnerWarning.style.display="none";
+	projectDescrWarning.style.display="none";
+
+	if (trimAll(packetNameField.value).length == 0)
+	{
+		alert("Please specify a name for your project.");
+		packetNameField.focus();
+		projectNameWarning.style.display = "inline";
+
+		return false;
+	}
+
+	return true;
+}
+
+
+// June  3, 2010
+function verifyProjectDescr(pDescrID)
+{
+	var packetDescrField = document.getElementById(pDescrID);
+
+	var projectOwnerWarning = document.getElementById("projectOwnerWarning");
+	var projectNameWarning = document.getElementById("projectNameWarning");
+	var projectDescrWarning = document.getElementById("projectDescrWarning");
+
+	// Hide owner warning if shown
+	projectOwnerWarning.style.display="none";
+	projectNameWarning.style.display="none";
+
+	if (trimAll(packetDescrField.value).length == 0)
+	{
+		alert("Please provide a project description.");
+		packetDescrField.focus();
+		projectDescrWarning.style.display = "inline";
+
+		return false;
+	}
+
+	return true;
+}
+
+// Added July 25/08
+function verifyProjectOwner(ownersList)
+{
+	var projectOwnersList = document.getElementById(ownersList);
+	var projectOwnerWarning = document.getElementById("projectOwnerWarning");
+	var projectNameWarning = document.getElementById("projectNameWarning");
+	var projectDescrWarning = document.getElementById("projectDescrWarning");
+
+	projectNameWarning.style.display = "none";
+	projectDescrWarning.style.display = "none";
+
+	if (projectOwnersList.selectedIndex == 0)
+	{
+		alert("Please select a project owner.");
+		projectOwnersList.focus();
+		projectOwnerWarning.style.display="inline";
+
+		return false;0
+	}
+
+	return true;
+}
+
+function showProject0Details()
+{
+	var projectList = document.getElementById("packetList");
+	var projectSelInd = projectList.selectedIndex;
+	var projectDetails = document.getElementById("project_details");
+	
+	var projectSelValue = projectList[projectSelInd].text;
+	var projectName_array = projectSelValue.split(":");		// Will always have 3 elements: project ID, owner, project name
+	
+	var packetName = document.getElementById("packet_name");
+	var submitBtn = document.getElementById("submit_project_modify");
+	
+	if (projectSelInd == 0)
+	{
+		projectDetails.style.display = "none";
+	}
+	else
+	{
+		projectDetails.style.display = "inline";
+		packetName.value = trimAll(projectName_array[2]);	// again, project name is the last element of projectName_array
+	}
+}
+//	User Management functions
+//	June 28, 2007, Marina
+
+
+// Called at step 1 to move members from source list to readers, writers or admin list, depending on access level selected
+function addProjects(srcListID, role)
+{
+// alert(srcListID);
+	var targetListID;
+	
+	switch (role)
+	{
+		case 'read':
+			targetListID = "user_projects_readonly";
+		break;
+		
+		case 'write':
+			targetListID = "user_projects_write";
+		break;
+
+		// Added Sept. 9/07: This is the case where the user is a Reader, and there is no write project list for him - only one source and one target list
+		case 'readonly':
+			targetListID = "user_projects_read";
+		break;
+
+		case 'rmv_read':
+			targetListID = "packetListRead";
+		break;
+
+		case 'rmv_write':
+			targetListID = "packetListWrite";
+		break;
+
+		default:
+			// move back to original list
+			targetListID = "packetList";
+		break;
+	}
+	
+	moveListElements(srcListID, targetListID, true);
+}
+
+// Oct. 7, 2010: remove user projects and return to appropriate lab projects list
+function moveProjectToLabListSpecific(fromListID)
+{
+	var fromList = document.getElementById(fromListID);
+
+	var selElems = getSelectedOptions(fromListID);
+	var i;
+
+	for (i = 0; i < selElems.length; i++)
+	{
+		tmpOptn = selElems[i];
+
+		optID = tmpOptn.id;
+
+		if (optID.indexOf("lab_") == 0)
+		{
+			projInd = optID.indexOf("_project_");
+			labID = optID.substring("lab_".length, projInd);
+			labListID = "lab_projects_" + labID;
+
+			labList = document.getElementById(labListID);
+	
+			if (labList.options.length == 0)
+			{
+				labList.options.add(tmpOptn);
+				removeElement(fromList, tmpOptn);
+			}
+			else
+			{
+				addNumElement(labList, labList.options.length, tmpOptn);
+				removeElement(fromList, tmpOptn);
+			}
+
+			clearAllElements(labListID);
+		}
+	}
+}
+
+// Oct. 8, 2010
+function moveProjectToUserListSpecific(fromListID)
+{
+	var fromList = document.getElementById(fromListID);
+// 	var userSearchList = document.getElementById("searchByMembers");
+// 	var selUser = userSearchList[userSearchList.selectedIndex].value;
+// 	var uProjList = document.getElementById("userPackets_" + selUser);
+
+	var selElems = getSelectedOptions(fromListID);
+	var i;
+
+	for (i = 0; i < selElems.length; i++)
+	{
+		tmpOptn = selElems[i];
+
+		optID = tmpOptn.id;
+// alert(optID);
+		if (optID.indexOf("_user_projects_") > 0)
+		{
+			userInd = optID.indexOf("_user_projects_");
+			userID = optID.substring(0, userInd);
+			userListID = "userPackets_" + userID;
+
+			userList = document.getElementById(userListID);
+	
+			if (userList.options.length == 0)
+			{
+				userList.options.add(tmpOptn);
+				removeElement(fromList, tmpOptn);
+			}
+			else
+			{
+				addNumElement(userList, userList.options.length, tmpOptn);
+				removeElement(fromList, tmpOptn);
+			}
+
+			clearAllElements(userListID);
+		}
+		else if (optID.indexOf("lab_") == 0)
+		{
+			moveProjectToLabListSpecific(fromListID);
+/*
+			projectInd = optID.indexOf("_project_");
+			labID = optID.substring("lab_".length, projectInd);
+			labListID = "lab_projects_" + labID;
+
+			labList = document.getElementById(labListID);
+
+			if (labList.options.length == 0)
+			{
+				labList.options.add(tmpOptn);
+				removeElement(fromList, tmpOptn);
+			}
+			else
+			{
+				addNumElement(labList, labList.options.length, tmpOptn);
+				removeElement(fromList, tmpOptn);
+			}
+			clearAllElements(labListID);*/
+		}
+	}
+}
+
+
+// Oct. 8, 2010
+function showUserProjects(userID)
+{
+// 	alert(userID);
+
+	packetDivID = userID + "_projects";
+	uPackets = document.getElementById(packetDivID);
+
+	if (uPackets)
+		uPackets.style.display="table-row";
+
+	userProjectCaption = document.getElementById("userProjectCaption_" + userID);
+
+	if (userProjectCaption)
+		userProjectCaption.style.display="inline";
+
+	// hide the rest of user packet TRs
+	allRows = document.getElementsByTagName("TR");
+
+	for (i=0; i < allRows.length; i++)
+	{
+		aRow = allRows[i];
+
+		if (aRow.id && (aRow.id.indexOf("_projects") > 0) && (aRow != uPackets))
+		{
+			aRow.style.display = "none";
+		}
+	}
+
+	document.getElementById("addReadProjectsUser").onclick = function(){addProjects("userPackets_" + userID, 'readonly')};
+}
+
+
+function showProjectKeywordSearch()
+{
+	document.getElementById("projectKeywdSearch").style.display="table-row";
+}
+
+function hideKeywd()
+{
+	document.getElementById("projectKeywdSearch").style.display="none";
+	document.getElementById("project_search_results").style.display="none";
+}
+
+
+function searchProjectByKeyword()
+{
+	xmlhttp = createXML();
+
+	var keywd = document.getElementById("project_keywd").value;
+
+	url = cgiPath + "project_request_handler.py?keyword=" + keywd + "&search_project_by_keyword";
+
+	xmlhttp.open("GET", url, false);
+
+	xmlhttp.send('');
+
+ 	xmlhttp.onreadystatechange = printProjectSearchResults(xmlhttp);
+}
+
+function printProjectSearchResults(xmlhttp)
+{
+	var projectSearchResults = document.getElementById("project_search_results");
+	projectSearchResults.style.display = "table-row";
+
+	var keywdProjectMatchList = document.getElementById("keywdProjectMatchList");
+
+	if (xmlhttp.readyState == 4)
+	{
+		if (xmlhttp.status == 200)
+		{
+			response = trimAll(xmlhttp.responseText);	// comma-delimited
+
+			respAr = response.split(", ");
+
+			respAr.sort();
+
+			for (i=0; i < respAr.length; i++)
+			{
+				pText = respAr[i];
+
+				pNum = pText.substring(0, pText.indexOf(":"));
+
+				tmpOptn = document.createElement("OPTION");
+
+				tmpOptn.value = pNum;
+				tmpOptn.text = pText;
+				keywdProjectMatchList.options[i] = tmpOptn;
+			}
+		}
+	}
+}
+
+function showAllProjects()
+{
+	document.getElementById("viewAllProjects").style.display="table-row";
+}
+
+function hideAllProjects()
+{
+	document.getElementById("viewAllProjects").style.display="none";
+}
+
+
+function hideUserProjects()
+{
+	// get the selected labID and hide the corresponding project list
+	var usersList = document.getElementById("searchByMembers");
+// 	alert(labsList.selectedIndex);
+	var userSelInd = usersList.selectedIndex;
+	var selUserID = usersList[userSelInd].value;
+// alert(selLabID);
+
+	var userProjectList = document.getElementById(selUserID+ "_projects");
+
+	// no lab project list might be shown at this point
+	if (userProjectList)
+		userProjectList.style.display = "none";
+	
+// 	document.getElementById("project_read_checkbox").style.display = "none";
+// 	document.getElementById("projectCaption").style.display = "none";
+}
+
+
+function removeProjects(srcListID)
+{
+	var srcList = document.getElementById(srcListID);
+	var selElems = getSelectedOptions(srcListID);
+	
+	for (i = 0; i < selElems.length; i++)
+	{
+		rmvOptn = selElems[i].value;
+		removeListElement(srcList, rmvOptn);
+	}
+	
+}
+
+function showHidePrivileges()
+{
+	var radioBtns = document.getElementsByTagName("INPUT");
+	var accessLevels = document.getElementById("user_access");
+	var projectAccess = document.getElementById("project_access");
+
+	for (r=0; r < radioBtns.length; r++)
+	{
+		tmpInput = radioBtns[r];
+		//alert(tmpInput.type);
+		//alert(tmpInput.name);
+		//alert(tmpInput.value);
+		
+		if ((tmpInput.type == 'radio') && (tmpInput.name == 'privChoiceRadio') && (tmpInput.value == 'override') && (tmpInput.checked))
+		{
+			accessLevels.style.display = "table-row";
+			break;
+		}
+		else
+		{
+			accessLevels.style.display = "none";
+
+			// also hide project access level section
+			// Change of heart Aug 12/07 - show project list at all times, regardless of access level
+//			projectAccess.style.display = "none";
+		}
+	}
+}
+
+function showHideWriteProjectAccess()
+{
+	var projectWriteAccessTable = document.getElementById("write_project_access");
+	var projectReadAccessTable = document.getElementById("read_project_access");
+	var readNote = document.getElementById("read_note");
+	var radioBtns = document.getElementsByTagName("INPUT");
+	
+	for (r=0; r < radioBtns.length; r++)
+	{
+		tmpInput = radioBtns[r];
+		
+// 		alert("Type " + tmpInput.type);
+// 		alert("Name " + tmpInput.name);
+// 		alert("Value " + tmpInput.value);
+		
+		if ((tmpInput.type == 'radio') && (tmpInput.name == 'system_access_level') && (tmpInput.checked) && (tmpInput.value != 'Reader'))
+		{
+			projectReadAccessTable.style.display = "none";
+			projectWriteAccessTable.style.display = "table-row";
+			readNote.style.display = "none";
+			break;		// found what we're looking for, no need to go on
+		}
+		else
+		{
+			projectReadAccessTable.style.display = "table-row";
+			projectWriteAccessTable.style.display = "none";
+
+			// BUT here, DON'T put 'break', b/c we haven't found what we need, keep looking!!!
+		}
+	}	
+}
+
+function verifyAddUser()
+{
+	return verifyLabSelected() && verifyUsername() && verifyPassword() && verifyFirstname() && verifyLastname() && verifyPosition();
+}
+
+function verifyLabSelected()
+{
+	var labList = document.getElementById("labList");
+	var labSelInd = labList.selectedIndex;
+	var labWarning = document.getElementById("lab_warning");
+	
+	if (labSelInd <= 0)
+	{
+		alert("You must select a Laboratory to continue");
+		labWarning.focus();
+		labWarning.style.display = "inline";
+		return false;
+	}
+	else
+	{
+		labWarning.style.display = "none";
+		return true;
+	}
+}
+
+function verifyUsername()
+{
+	var username = document.getElementById("user_name");
+
+	if (username.value.length == 0)
+	{
+		alert ("Please provide a username.");
+		username.focus();
+		return false;
+	}
+	
+	return true;
+}
+
+
+// Jan. 14, 2010: Check mandatory properties at container **type** creation/mopdification
+function verifyContainerType()
+{
+	return verifyContainerTypeName() && verifyContainerTypeCode();
+}
+
+
+function verifyContainerTypeName()
+{
+	var contTypeName = document.getElementById("containerTypeName");
+
+	if (contTypeName)
+	{
+		if (contTypeName.value.length == 0)
+		{
+			alert("Plese provide a name for the new container type.");
+			contTypeName.focus();
+			return false;
+		}
+	}
+
+	return true;
+}
+
+
+function verifyContainerTypeCode()
+{
+	var contCode = document.getElementById("containerCode");
+	var alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+	
+
+	if (contCode)
+	{
+		if (contCode.value.length == 0)
+		{
+			alert("Plese provide a two-letter unique identifier for new container type.");
+			contCode.focus();
+			return false;
+		}
+		else if (contCode.value.length != 2)
+		{
+			alert("Container type codes must be 2 characters in length.  Plese verify your input.");
+			contCode.focus();
+			return false;
+		}
+		else
+		{
+			for (i=0; i < contCode.value.length; i++)
+			{
+				var ch = contCode.value.charAt(i).toUpperCase();
+	
+				if (alpha.indexOf(ch) < 0)
+				{
+					alert("Container type identifiers must be Latin alphabetic characters only, other characters and numbers are not allowed.");
+					contCode.focus();
+					return false;
+				}
+			}
+		}
+	}
+
+	return true;
+}
+
+
+// Dec. 21/09, update Jan. 13, 2010 - verify mandatory properties when adding/modifying a **container**
+function confirmMandatoryLocation()
+{
+	return verifyContainerName() && verifyContainerType() && verifyContainerSize() && /*&& verifyContainerCode()*/ verifyStorageType() && verifyStorageName();
+}
+
+
+// Jan. 13, 2010
+function checkLocationNumeric()
+{
+	// shelf, rack, row, column
+	var shelfInput = document.getElementById("contShelf");
+	var rackInput = document.getElementById("contRack");
+	var rowInput = document.getElementById("contRow");
+	var colInput = document.getElementById("contCol");
+
+	var shelf = shelfInput.value;
+	var rack = rackInput.value;
+	var row = rowInput.value;
+	var col = colInput.value;
+
+	var numbers = "0123456789";
+	var numbers_nozero = "123456789";
+
+	if (shelf.length == 1)
+	{
+		if (numbers_nozero.indexOf(shelf) < 0)
+		{
+			alert("Shelf indices must be non-zero numeric values.  Please verify your input.");
+			shelfInput.focus();
+			return false;
+		}
+	}
+	else
+	{
+		for (i=0; i < shelf.length; i++)
+		{
+			ch = shelf.charAt(i);
+
+			if (numbers.indexOf(ch) < 0)
+			{
+				alert("Shelf indices must be non-zero numeric values.  Please verify your input.");
+				shelfInput.focus();
+				return false;
+			}
+		}
+	}
+
+	if (rack.length == 1)
+	{
+		if (numbers_nozero.indexOf(rack) < 0)
+		{
+			alert("Rack indices must be non-zero numeric values.  Please verify your input.");
+			rackInput.focus();
+			return false;
+		}
+	}
+	else
+	{
+		for (i=0; i < rack.length; i++)
+		{
+			ch = rack.charAt(i);
+
+			if (numbers.indexOf(ch) < 0)
+			{
+				alert("Rack indices must be non-zero numeric values.  Please verify your input.");
+				rackInput.focus();
+				return false;
+			}
+		}
+	}
+
+	if (col.length == 1)
+	{
+		if (numbers_nozero.indexOf(col) < 0)
+		{
+			alert("Column indices must be non-zero numeric values.  Please verify your input.");
+			colInput.focus();
+			return false;
+		}
+	}
+	else
+	{
+		for (i=0; i < col.length; i++)
+		{
+			ch = col.charAt(i);
+
+			if (numbers.indexOf(ch) < 0)
+			{
+				alert("Column indices must be non-zero numeric values.  Please verify your input.");
+				colInput.focus();
+				return false;
+			}
+		}
+	}
+
+	if (row.length == 1)
+	{
+		if (numbers_nozero.indexOf(row) < 0)
+		{
+			alert("Row indices must be non-zero numeric values.  Please verify your input.");
+			rowInput.focus();
+			return false;
+		}
+	}
+	else
+	{
+		for (i=0; i < row.length; i++)
+		{
+			ch = row.charAt(i);
+
+			if (numbers.indexOf(ch) < 0)
+			{
+				alert("Row indices must be non-zero numeric values.  Please verify your input.");
+				rowInput.focus();
+				return false;
+			}
+		}
+	}
+}
+
+
+function verifyContainerName()
+{
+	var contName = document.getElementById("containerName");
+
+	if (contName)
+	{
+		if (contName.value.length == 0)
+		{
+			alert("Plese provide a name for the new container");
+			contName.focus();
+			return false;
+		}
+	}
+
+	return true;
+}
+
+
+// Dec. 21/09
+function verifyContainerCode()
+{
+	var contCode = document.getElementById("containerCode");
+
+	if (contCode)
+	{
+		if (contCode.value.length == 0)
+		{
+			alert("Plese provide a two-letter unique identifier for new container");
+			contCode.focus();
+			return false;
+		}
+	}
+
+	return true;
+}
+
+
+// Jan. 13, 2010
+function verifyStorageType()
+{
+	var storageType = document.getElementById("location_types");
+
+	if (storageType)
+	{
+		if (storageType.selectedIndex == 0)
+		{
+			alert("Please select a storage type for the new container.");
+
+			storageType.style.color = "#FF0000";
+			storageType.focus();
+			return false;
+		}
+	}
+
+	storageType.style.color = "#000000";
+	return true;
+}
+
+// Dec. 1, 2010
+function verifyContainerType()
+{
+	var containerType = document.getElementById("contGroupBox");
+
+	if (containerType)
+	{
+		if (containerType.selectedIndex == 0)
+		{
+			alert("Please select a container type from the list.\n\n  If the sought container type is not in the list, create it using the 'Add Container Type' menu option or contact an administrator if this option is not available.");
+
+			containerType.style.color = "#FF0000";
+			containerType.focus();
+			return false;
+		}
+	}
+
+	containerType.style.color = "#000000";
+	return true;
+}
+
+
+// Dec. 1, 2010
+function verifyContainerSize()
+{
+	var containerSizes = document.getElementById("contSizeList");
+
+	if (containerSizes)
+	{
+		if (containerSizes.selectedIndex == 0)
+		{
+			alert("Please select a container size from the list.\n\n  If the sought container size is not in the list, create it using the 'Add Container Size' menu option or contact an administrator if this option is not available.");
+
+			containerSizes.style.color = "#FF0000";
+			containerSizes.focus();
+			return false;
+		}
+	}
+
+	containerSizes.style.color = "#000000";
+	return true;
+}
+
+
+function verifyStorageName()
+{
+	var storageName = document.getElementById('locationName');
+
+	if (storageName)
+	{
+		if (storageName.value.length == 0)
+		{
+			alert("Please provide a storage name for the new container.");
+			storageName.focus();
+			return false;
+		}
+	
+	}
+	return true;
+}
+
+function verifyPassword()
+{
+	var passwd = document.getElementById("passwd");
+	
+	if (passwd.value.length == 0)
+	{
+		alert("Plese enter a valid password for the new user");
+		passwd.focus();
+		return false;
+	}
+	
+	return true;
+}
+
+function checkLab()
+{
+	var labName = document.getElementById("lab_name").value;
+
+	if (labName.length == 0)
+	{
+		alert("Please provide a name for the laboratory.");
+		document.getElementById("lab_name").focus();
+		return false;
+	}
+
+	var labCodeField = document.getElementById("lab_id");
+	var labCode = labCodeField.value;
+
+	if (labCode.length == 0)
+	{
+		alert("Please provide a 2-character laboratory identifier.");
+		document.getElementById("lab_id").focus();
+		return false;
+	}
+
+	var alpha = "abcdefghijklmnopqrstuvwxyz";
+
+	if (labCode.length > 2)
+	{
+		alert("Lab code must be exactly 2 characters in length.");
+		labCodeField.focus();
+		return false;
+	}
+	else
+	{
+		var count1 = 0;
+		var count2 = 0;
+
+		for (i = 0; i < alpha.length; i++)
+		{
+			aChar = alpha[i];
+
+			if (labCode.toLowerCase().charAt(0) == aChar)
+				count1++;
+
+			if (labCode.toLowerCase().charAt(1) == aChar)
+				count2++;
+		}
+
+		if ( (count1 == 0) || (count2 == 0) )
+		{
+			alert("Lab code must contain alpha characters only.");
+			labCodeField.focus();
+			return false;
+		}
+	}
+
+	
+	var titles = document.getElementById("titlesList");
+
+	if (titles)
+	{
+		var titleIndex = titles.selectedIndex;
+		var selTitle = titles[titleIndex].value;
+	}
+
+	var labHead = document.getElementById("lab_head").value;
+
+	if (labHead.length == 0)
+	{
+		alert("Please enter the name of the laboratory owner or PI.");
+		document.getElementById("lab_head").focus();
+		return false;
+	}
+
+
+	var labDescr = document.getElementById("lab_descr").value;
+	var labAddress = document.getElementById("lab_location").value;
+
+	var allInputs = document.getElementsByTagName("INPUT");
+	var labAccess;
+
+	for (a in allInputs)
+	{
+		tmpInput = allInputs[a];
+
+		if ( (tmpInput.type == 'radio') && (tmpInput.name == 'system_access_level') && (tmpInput.checked) )
+		{
+			labAccess = tmpInput.value;
+			break;
+		}
+	}
+}
+
+function verifyPosition()
+{
+	var position = document.getElementById("positions_list"); 
+	var posSelInd = position.selectedIndex;
+	var posWarn = document.getElementById("position_warning");
+	
+	if (posSelInd <= 0)
+	{
+		alert("Please select a Position/Department to continue");
+		posWarn.focus();
+		posWarn.style.display = "inline";
+		return false;
+	}
+	
+	return true;
+}
+
+function enableSubmit(myListID, submitID)
+{
+	var myList = document.getElementById(myListID);
+	var submitBtn = document.getElementById(submitID);
+	
+	//var numSel = getNumSelected(myList);
+	
+//	if ((numSel > 0) && (myList.options.length > 0))
+	if (myList.options.length > 0)
+	{
+		submitBtn.disabled = false;
+	}
+	else
+	{
+		submitBtn.disabled = true;
+	}
+}
+
+function enableParents(pListID)
+{
+	var parentList = document.getElementById(pListID);
+
+	if (parentList)
+	{
+		for (p=0; p < parentList.options.length; p++)
+		{
+			tmpOpt = parentList.options[p];
+			tmpOpt.disabled=false;
+		}
+	}
+}
+
+// Jan. 13, 2010
+function enableText()
+{
+	var allInputs = document.getElementsByTagName("INPUT");
+	var i, j;
+	var tmpInput;
+
+	for (i=0; i < allInputs.length; i++)
+	{
+		tmpInput = allInputs[i];
+	
+		if (tmpInput.type.toLowerCase() == 'text')
+		{
+			tmpInput.disabled = false;	// Jan. 7, 2010
+		}
+	}
+}
+
+
+// Jan. 29, 2010
+function enableRadio()
+{
+	var allInputs = document.getElementsByTagName("INPUT");
+	var i, j;
+	var tmpInput;
+
+	for (i=0; i < allInputs.length; i++)
+	{
+		tmpInput = allInputs[i];
+	
+		if (tmpInput.type.toLowerCase() == 'radio')
+		{
+			tmpInput.disabled = false;	// Jan. 7, 2010
+		}
+	}
+}
+
+
+function enableSelect()
+{
+	var allSelects = document.getElementsByTagName("SELECT");
+	var i, j;
+	var tmpSelect;
+
+	for (i=0; i < allSelects.length; i++)
+	{
+		tmpSelect = allSelects[i];
+
+// alert(tmpSelect.multiple);
+
+		// April 19, 2010: Execute ONLY for MULTIPLE selection lists (at reagent type creation/modification).  Causes problems with normal lists!!!
+
+		// May 25, 2010 - need to enable single lists too though; remove the 'if' temporarily and check
+// 		if (tmpSelect.multiple)
+// 		{
+			tmpSelect.disabled = false;	// Jan. 7, 2010
+	
+			for (j = 0; j < tmpSelect.options.length; j++)
+			{
+				tmpOptn = tmpSelect.options[j];
+				tmpOptn.disabled = false;
+			}
+// 		}
+	}
+}
+
+function checkSelectUser(fromList, toList, actn)
+{
+	var srcList = document.getElementById(fromList);
+	var targetList = document.getElementById(toList);
+	var addDelBtn = document.getElementById(actn);
+	
+	var numSel = getNumSelected(srcList);
+	
+	if (numSel == 0)
+	{
+		alert("Please select at least one member from the dropdown list");
+		return false;
+	}
+	else
+	{
+		moveListElements(fromList, toList, false);
+		
+		// if candidates list becomes empty, disable Submit button
+		//if (fromList == 'deletion_candidates_list')
+		//{
+			enableSubmit('deletion_candidates_list', 'deleteUserBtn');
+		//}
+		
+		return true;
+	}
+}
+
+function verifyFirstname()
+{
+	var fName = document.getElementById("first_name");
+
+	if (fName.value.length == 0)
+	{
+		alert ("Please specify the user's first name.");
+		fName.focus();
+		return false;
+	}
+	
+	return true;
+}
+
+function verifyLastname()
+{
+	var lName = document.getElementById("last_name");
+
+	if (lName.value.length == 0)
+	{
+		alert ("Please specify the user's last name.");
+		lName.focus();
+		return false;
+	}
+	
+	return true;
+}
+
+function verifyDeleteUser()
+{
+	return confirm("Are you sure you want to delete this user?");
+}
+
+
+function verifyDeleteLab()
+{
+	return confirm("Are you sure you want to delete this laboratory?");
+}
+
+function confirmDeleteProject()
+{
+	return confirm("Are you sure you want to delete this project?");
+}
+
+// June 3/09
+function confirmDeleteReagentType()
+{
+	return confirm("Are you sure you want to delete this reagent type?");
+}
+
+// Redirect to CURRENT user Detailed View through menu link
+function redirectToCurrentUserDetailedView(userID)
+{
+	document.curr_user_form.submit();
+}
+
+
+// Redirect to User Detailed View from Lab Detailed View
+function redirectToUserDetailedView(userID)
+{
+	var userInput = document.getElementById("view_user_hidden");
+
+	if (userInput)
+		userInput.value = userID;
+
+	if (document.lab_form)
+		document.lab_form.submit();
+
+	else if (document.user_form)
+		document.user_form.submit();
+}
+
+
+// Redirect to Lab Detailed View from User Detailed View
+function redirectToLabView(labID)
+{
+	var labInput = document.getElementById("view_lab_hidden");
+	labInput.value = labID;
+	document.user_form.submit();
+}
+
+
+// Redirect to Project Detailed View from User Detailed View
+function redirectToProjectDetailedView(packetID)
+{
+	var projectForm = document.getElementById("viewProjectForm");
+	var projectInput = document.getElementById("view_packet_hidden");
+	projectInput.value = packetID;
+	projectForm.submit();
+}
+
+
+// Redirect to User Detailed View from Project Detailed View
+function redirectToUserFromProject(userID)
+{
+	var userForm = document.getElementById("viewUserForm");
+	var userInput = document.getElementById("view_user_hidden");
+	userInput.value = userID;
+	userForm.submit();
+}
+
+// Redirect to Lab view from Project Details page
+function goToLabViewFromProject(labID)
+{
+	var labForm = document.getElementById("viewLabForm");
+	var labInput = document.getElementById("view_lab_hidden");
+	
+	labInput.value = labID;
+	labForm.submit();
+}
+
+function removeLabMembers(labListName)
+{
+	var labList = document.getElementById(labListName);
+	var selMembers = getSelectedElements(labListName);	// list of actual member ID VALUES
+	
+	for (i = 0; i < selMembers.length; i++)
+	{
+		tmpMember = selMembers[i];
+		removeListElement(labList, tmpMember);
+	}
+}
+
+// March 23, 2010
+// function showMultiple(cbID, listID, textID, btnID)
+function showMultiple(cbID, tblID, listID)
+{
+// alert(cbID);
+// alert(tblID);
+// alert(listID);
+
+// 	checkMult = document.getElementById(cbID);
+	propList = document.getElementById(listID);
+
+	mult_cbLabel = document.getElementById("mult_" + cbID + "_label");
+// alert(mult_cbLabel );
+	one_cbLabel = document.getElementById("one_" + cbID + "_label");
+
+	attrID = cbID.substring(cbID.lastIndexOf("_")+1, cbID.length);
+// alert(attrID);
+	otherTxt = document.getElementById("other_text_" + attrID);
+
+	showMoreImg = document.getElementById("expand_" + cbID);
+	showLessImg = document.getElementById("collapse_" + cbID);
+
+	// May 11, 2010
+	mult_tbl = document.getElementById(tblID);
+
+// 	if (checkMult.checked)
+	if (mult_tbl.style.display == "none")
+	{
+		propList.style.display = "none";
+		mult_tbl.style.display = "inline";
+
+// 		cbLabel.innerHTML = "Remove Multiple";
+		mult_cbLabel.style.display = "none";
+		one_cbLabel.style.display = "inline";
+
+// 		checkMult.checked = false;
+		showMoreImg.style.display = "none";
+		showLessImg.style.display = "inline";
+
+		otherTxt.style.display = "none";
+	}
+	else
+	{
+		propList.style.display = "inline";
+		mult_tbl.style.display = "none";
+
+// 		cbLabel.innerHTML = "Select Multiple";
+		mult_cbLabel.style.display = "inline";
+		one_cbLabel.style.display = "none";
+
+// 		checkMult.checked = false;
+		showMoreImg.style.display = "inline";
+		showLessImg.style.display = "none";
+
+// 		if (otherTxt.innerHTML == "")
+// 			otherTxt.style.display = "none";
+// 		else
+// 			otherTxt.style.display = "inline";
+	}
+}
+
+// May 13/09
+function searchMultipleReagentTypes()
+{
+	checkMult = document.getElementById("searchMultipleReagentTypesCheckbox");
+	rTypesList = document.getElementById("reagentTypesFilterList");
+	
+	// For the search reagents view only
+// 	rTypesList.name = "filter[]";
+	
+	if (checkMult.checked)
+		rTypesList.multiple="multiple";
+	else
+		rTypesList.multiple="";
+}
+
+function searchMultipleProjects()
+{
+	checkMult = document.getElementById("searchMultiple");
+	packetList = document.getElementById("packetList");
+	
+	// For the search reagents view only
+	packetList.name = "packets[]";
+	
+	if (checkMult.checked)
+		packetList.multiple="multiple";
+	else
+		packetList.multiple="";
+}
+
+
+// On Change Password page: make sure all 3 fields (old password, new password, confirm new) have been filled in
+function checkNonEmptyPassword()
+{
+	var oldPasswd = document.getElementById("old_passwd");
+	var newPasswd = document.getElementById("new_passwd");
+	var newPasswdConfirm = document.getElementById("new_passwd_confirm");
+	
+	if ( (oldPasswd.value != "") && (newPasswd.value != "") && (newPasswdConfirm.value != "") )
+	{
+		return true;
+	}
+	else
+	{
+		alert("Please fill in all form fields");
+		return false;
+	}
+}
+
+
+// The following functions are required for User Search
+function showLabList()
+{
+	var labList = document.getElementById("labList");
+	
+	if (labList.style.display == "none")
+		labList.style.display = "table-row";
+	else
+		labList.style.display = "none";
+}
+
+function showPosition()
+{
+	var positions = document.getElementById("positions");
+	
+	if (positions.style.display == "none")
+	{
+		positions.style.display = "table-row";
+	}
+	else
+	{
+		positions.style.display = "none";
+	}
+}
+
+function showFirstName()
+{
+	var firstNameField = document.getElementById("firstNameField");
+	var fName = document.getElementById("fName");
+
+	if (firstNameField.style.display == "none")
+	{
+		firstNameField.style.display = "table-row";
+		fName.focus();
+	}
+	else
+	{
+		firstNameField.style.display = "none";
+	}
+}
+
+function showLastName()
+{
+	var lastNameField = document.getElementById("lastNameField");
+	var lName = document.getElementById("lName");
+
+	if (lastNameField.style.display == "none")
+	{
+		lastNameField.style.display = "table-row";
+		lName.focus();
+	}
+	else
+	{
+		lastNameField.style.display = "none";
+	}
+}
+
+
+// Invoked in User Modify view, to remove projects from the user's read/write project list and return to the project pool
+function removeUserProjects()
+{
+	var readProjListID = "user_projects_readonly";
+	var writeProjListID = "user_projects_write";
+
+	var readProjList = document.getElementById(readProjListID);
+	var writeProjList = document.getElementById(writeProjListID);
+
+	var targetListID = "packetList";
+	var targetList = document.getElementById(targetListID);
+	
+	var selReadProj = getSelectedOptions(readProjListID);
+	
+	if (writeProjList)
+		var selWriteProj = getSelectedOptions(writeProjListID);
+	
+	// Move read-only projects first, then move writeable projects
+	for (r = 0; r < selReadProj.length; r++)
+	{
+		rdrOpt = selReadProj[r];
+		rdrOptID = rdrOpt.id;
+		
+		// Not using moveListElements, since it incorrectly moves ALL values in the source list to the same target list
+		if (targetList.options.length == 0)
+		{
+			targetList.options.add(rdrOpt);
+			removeElement(readProjList, rdrOpt);
+			
+		}
+		else
+		{
+			addNumElement(targetList, targetList.options.length, rdrOpt);
+			removeElement(readProjList, rdrOpt);
+		}
+		
+		clearAllElements(targetListID);
+	}
+
+	// writeable projects - IFF they exist (may be absent for readers)
+	if (writeProjList)
+	{
+		for (w = 0; w < selWriteProj.length; w++)
+		{
+			wrtrOpt = selWriteProj[w];
+			wrtrOptID = wrtrOpt.id;
+
+			if (targetList.options.length == 0)
+			{
+				targetList.options.add(wrtrOpt);
+				removeElement(writeProjList, wrtrOpt);
+			}
+			else
+			{
+				addNumElement(targetList, targetList.options.length, wrtrOpt);
+				removeElement(writeProjList, wrtrOpt);
+			}
+			
+			clearAllElements(targetListID);
+		}
+	}
+
+	clearCheckboxes(readProjListID, targetListID);	
+	
+	if (writeProjList)
+		clearCheckboxes(writeProjListID, targetListID);
+}
+
+
+// Called upon exit from User modification view, to check that if a user's access level is set to Reader, there are no Write projects assigned to him/her
+function verifyWriteProjects()
+{
+	var userCategoriesList = document.getElementById("user_category");
+	var selectedInd = userCategoriesList.selectedIndex;
+	var selectedValue = userCategoriesList[selectedInd].value;
+	var writeProjList = document.getElementById("user_projects_write");
+ 
+	// value 1 represents 'Reader' - corresponds to actual db value
+	if ( (selectedValue == '4') && writeProjList && (writeProjList.options.length > 0))
+	{
+		alert("You may not make this user a Reader while s/he has Write access to projects.  Please clear the user's Write Project list before changing the access level.");
+		return false;
+	}
+
+	return true;
+}
+
+
+// Mass Spectrometry module functions
+// September 2007, Marina
+
+// In 'Input Samples and Results' view: Show/hide the appropriate dropdown list depending on the radio button selected
+function showHideSamplesResultsOptions(optionID)
+{
+	// radio button option for 'Input Samples and Results'
+	var radOptn = document.getElementById(optionID).value;
+
+	// Corresponding dropdown lists for each option
+	var dd_1 = document.getElementById("input_bio_samples_select");
+	var dd_2 = document.getElementById("process_ms_results_select");
+	var dd_3 = document.getElementById("input_for_quant_analysis_select");
+
+	switch (radOptn)
+	{
+		case '1':
+			dd_1.style.display = "inline";
+			dd_2.style.display = "none";
+			dd_3.style.display = "none";
+		break;
+
+		case '2':
+			dd_1.style.display = "none";
+			dd_2.style.display = "inline";
+			dd_3.style.display = "none";
+		break;
+
+		case '3':
+			dd_1.style.display = "none";
+			dd_2.style.display = "none";
+			dd_3.style.display = "inline";
+		break;
+
+		case '4':
+			dd_1.style.display = "none";
+			dd_2.style.display = "none";
+			dd_3.style.display = "none";
+		break;
+	}
+}
+
+function verifyWellsSelected()
+{
+	var allInput = document.getElementsByTagName("INPUT");
+	var numChecked = 0;
+
+	for (i = 0; i < allInput.length; i++)
+	{
+		tmpInput = allInput[i];
+
+		if ( (tmpInput.type == "checkbox") && (tmpInput.name == "wells_checkbox[]") && tmpInput.checked )
+		{
+			numChecked++;
+		}
+	}
+
+	if (numChecked == 0)
+	{
+		alert("Please select at least one well in order to proceed");
+
+		// June 7, 2011: Reset the attributes dropdown
+		var changeAttributeSelect = document.getElementById('changeAttributeSelect');
+
+		if (changeAttributeSelect)
+		{
+			changeAttributeSelect.selectedIndex = 0;
+		}
+
+		return false;
+	}
+
+	return true;
+}
+
+
+// Oct. 3/07: Create XMLHttpRequest object for AJAX
+function createXML()
+{
+	var xmlhttp = false;
+
+	if (!xmlhttp && typeof XMLHttpRequest!='undefined') 
+	{
+		try 
+		{
+			xmlhttp = new XMLHttpRequest();
+		}
+		catch (e) 
+		{
+			xmlhttp=false;
+		}
+	}
+	if (!xmlhttp && window.createRequest) 
+	{
+		try
+		{
+			xmlhttp = window.createRequest();
+		} 
+		catch (e)
+		{
+			xmlhttp=false;
+		}
+	}
+
+	return xmlhttp;
+}
+
+
+function searchProt()
+{
+	xmlhttp = createXML();
+
+	// get form arguments to pass to Perl script
+	var keywd = document.getElementById("search_keyword").value;
+	var artif = document.getElementById("noArtifacts").value;
+	var minProb = document.getElementById("minProb").value;
+	var minScore = document.getElementById("minScore").value;
+	var maxFreq = document.getElementById("maxFreq").value;
+
+	var currUserID = document.getElementById("curr_user_hidden").value;
+
+      	xmlhttp.open("GET", url, false);
+
+      	xmlhttp.send('');
+
+// 	xmlhttp.send(null);
+ 	xmlhttp.onreadystatechange = printSearchResults(xmlhttp);
+}
+
+
+function printSearchResults(xmlhttp)
+{
+	var resultRow = document.getElementById("result_row");
+	var resultDiv = document.getElementById("prot_search_result_hidden");
+
+// 	alert(xmlhttp.responseText);
+
+	if (xmlhttp.readyState == 4)
+	{
+		resultRow.style.display = "table-row";
+		resultDiv.innerHTML = xmlhttp.responseText;
+	}
+}
+
+// October 17/07: Use BioPython to get a list of REBASE enzymes
+// Updated Nov. 12/07: As there are distinct OpenFreezer versions (devel, test, live), specify the complete path
+function getEnzymes(scriptPath)
+{
+	xmlhttp = createXML();
+	url = scriptPath + "restriction_sites.py";
+// 	xmlhttp.open("GET", url, false);
+// 	xmlhttp.send('');
+
+	xmlhttp.open("POST", url, false);
+	xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+	params = ''
+	xmlhttp.send(params);
+
+	xmlhttp.onreadystatechange = printEnzymeList(xmlhttp);
+}
+
+
+function verifyHybridSites(inputID, enzListID)
+{
+	var gatewayLoxPNoneSites = ['attB1', 'attB2', 'attP1', 'attP2', 'attL1', 'attL2', 'attR1', 'attR2', 'LoxP', 'None'];
+
+	enzList = document.getElementById(enzListID);
+// 	enzList = ['AscI','PacI', 'EcoRI', 'BamHI', 'BglII'];	// debugging
+// alert(enzList.id);
+// return false;
+		
+	var siteField = document.getElementById(inputID);
+	var site = siteField.value;	// always a text field
+	
+	var digits = "0123456789";
+
+	if (!inArray(site, gatewayLoxPNoneSites))
+	{
+		for (d in digits)
+		{
+			if (site.indexOf(d) >= 0)
+			{
+				alert("Site names may contain Roman numerals only.  Please verify your input.");
+				siteField.focus();
+				return false;
+			}
+	
+			if (site.indexOf('/') >= 0)
+			{
+				alert("Hybrid site names must be hyphen-delimited. Please verify your input");
+				siteField.focus();
+				return false;
+			}
+		}
+	}
+	else
+	{
+		alert("You may not use Gateway or LoxP sites to create a hybrid");
+		return false;
+	}
+
+	// Make sure the hybrid restriction site provided is of the form EnzI-EnzII, where EnzI and EnzII both match a REBASE enzyme value and are separated by hyphen, no spaces
+	var hyphenIndex = site.indexOf('-');
+
+	if (hyphenIndex > 0)
+	{
+		var h1 = trimAll(site.substring(0, hyphenIndex));
+		var h2 = trimAll(site.substring(hyphenIndex+1));
+
+		var h1_matches = 0;
+		var h2_matches = 0;
+	
+		for (i = 0; i < enzList.options.length; i++)
+		{
+			enz = enzList.options[i].value;
+	
+			if (enz == h1)
+			{
+				h1_matches++;
+				break;
+			}
+		}
+	
+		for (i = 0; i < enzList.options.length; i++)
+		{
+			enz = enzList.options[i].value;
+	
+			if (enz == h2)
+			{
+				h2_matches++;
+				break;
+			}
+		}
+	
+		if ((h1_matches > 0) && (h2_matches > 0))
+		{
+			return true;
+		}
+		else
+		{
+			alert("Hybrid restriction site names are CASE-SENSITIVE, of the form 'SiteI-SiteII', where SiteI and SiteII both match REBASE enzyme names, SEPARATED BY A HYPHEN.  Please verify your input.");
+			siteField.focus();
+			return false;
+		}
+	}
+}
+
+function printEnzymeList(xmlhttp)
+{
+	var allSelects = document.getElementsByTagName("SELECT");
+
+	var enzymes;
+	var enzList = new Array();
+	var enzOpt;
+
+	var selectedFivePrime = document.getElementById("fpcs_val");
+	var selectedThreePrime = document.getElementById("tpcs_val");
+
+	// Nov. 19/08: Add another field to store Insert sites
+	var selectedFivePrime_Insert = document.getElementById("fpcs_val_insert");
+	var selectedThreePrime_Insert = document.getElementById("tpcs_val_insert");
+
+// Dec. 9/09: ?????
+// 	var selectedRestrictionSite = document.getElementById("restriction_sites");
+
+	// oct 28/08
+	var prefix = "reagent_detailedview_";
+	var postfix = "_prop";
+
+	if (xmlhttp.readyState == 4)
+	{
+		enzymes = xmlhttp.responseText;
+		enzList = enzymes.split(' ');
+
+		for (a in allSelects)
+		{
+			if (allSelects[a])
+			{
+				if (allSelects[a].id)
+				{
+					// 5' site
+					if ( (allSelects[a].id == "fpcs_list") || (allSelects[a].id == "fpcs_list_1") || (allSelects[a].id == "fpcs_list_2") || (allSelects[a].id == "fpcs_list_3"))
+					{
+						var fivePrimeSelect = allSelects[a];
+			
+						for (i=0; i < enzList.length; i++)
+						{
+							var tmpEnz = trimAll(enzList[i]);
+				
+							enzOpt = document.createElement("OPTION");
+							enzOpt.text = tmpEnz;
+							enzOpt.value = tmpEnz;
+		
+							fivePrimeSelect.options[i] = enzOpt;
+						}
+		
+						// Add recombination and gateway sites - attB, attL, attP, LoxP
+		
+						// attB1
+						attB_1_optn = document.createElement("OPTION");
+						attB_1_optn.value = "attB1";
+						attB_1_optn.text = "attB1";
+						addElement(fivePrimeSelect, fivePrimeSelect.options.length-1, attB_1_optn);
+		
+		// 				// attB2
+		// 				attB_2_optn = document.createElement("OPTION");
+		// 				attB_2_optn.value = "attB2";
+		// 				attB_2_optn.text = "attB2";
+		// 				addElement(fivePrimeSelect, fivePrimeSelect.options.length-1, attB_2_optn);
+		
+						// attL1
+						attL_1_optn = document.createElement("OPTION");
+						attL_1_optn.value = "attL1";
+						attL_1_optn.text = "attL1";
+						addElement(fivePrimeSelect, fivePrimeSelect.options.length-1, attL_1_optn);
+		
+		// 				// attL2
+		// 				attL_2_optn = document.createElement("OPTION");
+		// 				attL_2_optn.value = "attL2";
+		// 				attL_2_optn.text = "attL2";
+		// 				addElement(fivePrimeSelect, fivePrimeSelect.options.length-1, attL_2_optn);
+		
+						// attP1
+						attP_1_optn = document.createElement("OPTION");
+						attP_1_optn.value = "attP1";
+						attP_1_optn.text = "attP1";
+						addElement(fivePrimeSelect, fivePrimeSelect.options.length-1, attP_1_optn);
+		
+		// 				// attP2
+		// 				attP_2_optn = document.createElement("OPTION");
+		// 				attP_2_optn.value = "attP2";
+		// 				attP_2_optn.text = "attP2";
+		// 				addElement(fivePrimeSelect, fivePrimeSelect.options.length-1, attP_2_optn);
+		
+						// attR1
+						attR_1_optn = document.createElement("OPTION");
+						attR_1_optn.value = "attR1";
+						attR_1_optn.text = "attR1";
+						addElement(fivePrimeSelect, fivePrimeSelect.options.length-1, attR_1_optn);
+		
+		// 				// attR2
+		// 				attR_2_optn = document.createElement("OPTION");
+		// 				attR_2_optn.value = "attR2";
+		// 				attR_2_optn.text = "attR2";
+		// 				addElement(fivePrimeSelect, fivePrimeSelect.options.length-1, attR_2_optn);
+		
+						// LoxP
+						loxp_optn = document.createElement("OPTION");
+						loxp_optn.value = 'LoxP';
+						loxp_optn.text = 'LoxP';
+						addElement(fivePrimeSelect, fivePrimeSelect.options.length-1, loxp_optn);
+		
+						// Feb. 5/08: Add option "None"
+						noneOpt = document.createElement("OPTION");
+						noneOpt.text = 'None';
+						noneOpt.value = 'None';
+						addElement(fivePrimeSelect, fivePrimeSelect.options.length-1, noneOpt);
+		
+						var fpInList = false;
+		
+						// Finally, select the current cloning site
+						for (j = 0; j < fivePrimeSelect.options.length; j++)
+						{
+							aOptn = fivePrimeSelect.options[j].value;
+		
+							// Updated Nov. 19/08
+							if (selectedFivePrime_Insert && fivePrimeSelect.id == "fpcs_list")
+							{
+								if (selectedFivePrime_Insert.value == aOptn)
+								{
+									fpInList = true;
+									fivePrimeSelect.selectedIndex = j;
+								}
+							}
+		
+							else if (selectedFivePrime)
+							{
+								if (selectedFivePrime.value == aOptn)
+								{
+									fpInList = true;
+									fivePrimeSelect.selectedIndex = j;
+								}
+							}
+						}
+		
+						if (!fpInList)
+						{
+							// select 'Other' and show textbox
+		
+							// add option 'Other' first - Moved here Dec. 1/08
+							otherOpt = document.createElement("OPTION");
+							otherOpt.text = 'Other';
+							otherOpt.value = 'Other';
+							addElement(fivePrimeSelect, fivePrimeSelect.options.length-1, otherOpt);
+		
+							for (k = 0; k < fivePrimeSelect.options.length; k++)
+							{
+								if (fivePrimeSelect.options[k].value.toLowerCase() == 'other')
+								{
+									fivePrimeSelect.selectedIndex = k;
+		
+									allText = document.getElementsByTagName("INPUT");
+		
+									for (at in allText)
+									{
+										if (allText[at].name == "5_prime_cloning_site_name_txt")
+										{
+											allText[at].style.display = "inline";
+										}
+									}
+								}
+							}
+						}
+					}
+		
+					// Sept. 19/08: added Restriction Sites list
+					// Change Nov. 9/09: Only fill lists with REBASE enzymes for Vectors and Inserts
+		// 			else if ((allSelects[a].id == "Vector_restriction_site_:_list") || (allSelects[a].id == "Insert_restriction_site_:_list"))
+					else if ((allSelects[a].id == "restriction_site_:_list") || (allSelects[a].id.indexOf("restriction_site_:_list") >= 0))
+					{
+						var restrSiteSelect = allSelects[a];
+						
+						// Oct. 28/08: Use the same strategy as with other feature lists - fetch the selected value from the field name
+						var rsSelectName = allSelects[a].name;
+						var selectedRestrictionSite = rsSelectName.substring(prefix.length+"restriction_site_:_".length, rsSelectName.indexOf("_start_"));
+			
+						for (i=0; i < enzList.length; i++)
+						{
+							var tmpEnz = trimAll(enzList[i]);
+				
+							enzOpt = document.createElement("OPTION");
+							enzOpt.text = tmpEnz;
+							enzOpt.value = tmpEnz;
+		
+							restrSiteSelect.options[i] = enzOpt;
+						}
+		
+						// Add recombination and gateway sites - attB, attL, attP, LoxP
+		
+						// attB1
+						attB_1_optn = document.createElement("OPTION");
+						attB_1_optn.value = 'attB1';
+						attB_1_optn.text = 'attB1';
+						addElement(restrSiteSelect, restrSiteSelect.options.length-1, attB_1_optn);
+		
+						// attB2
+						attB_2_optn = document.createElement("OPTION");
+						attB_2_optn.value = 'attB2';
+						attB_2_optn.text = 'attB2';
+						addElement(restrSiteSelect, restrSiteSelect.options.length-1, attB_2_optn);
+		
+						// attL1
+						attL_1_optn = document.createElement("OPTION");
+						attL_1_optn.value = 'attL1';
+						attL_1_optn.text = 'attL1';
+						addElement(restrSiteSelect, restrSiteSelect.options.length-1, attL_1_optn);
+		
+						// attL2
+						attL_2_optn = document.createElement("OPTION");
+						attL_2_optn.value = 'attL2';
+						attL_2_optn.text = 'attL2';
+						addElement(restrSiteSelect, restrSiteSelect.options.length-1, attL_2_optn);
+		
+						// attP1
+						attP_1_optn = document.createElement("OPTION");
+						attP_1_optn.value = 'attP1';
+						attP_1_optn.text = 'attP1';
+						addElement(restrSiteSelect, restrSiteSelect.options.length-1, attP_1_optn);
+		
+						// attP2
+						attP_2_optn = document.createElement("OPTION");
+						attP_2_optn.value = 'attP2';
+						attP_2_optn.text = 'attP2';
+						addElement(restrSiteSelect, restrSiteSelect.options.length-1, attP_2_optn);
+		
+						// attR1
+						attR_1_optn = document.createElement("OPTION");
+						attR_1_optn.value = 'attR1';
+						attR_1_optn.text = 'attR1';
+						addElement(restrSiteSelect, restrSiteSelect.options.length-1, attR_1_optn);
+		
+						// attR2
+						attR_2_optn = document.createElement("OPTION");
+						attR_2_optn.value = 'attR2';
+						attR_2_optn.text = 'attR2';
+						addElement(restrSiteSelect, restrSiteSelect.options.length-1, attR_2_optn);
+						
+						// LoxP
+						loxp_optn = document.createElement("OPTION");
+						loxp_optn.value = 'LoxP';
+						loxp_optn.text = 'LoxP';
+						addElement(restrSiteSelect, restrSiteSelect.options.length-1, loxp_optn);
+		
+						// March 18/09: Topo
+						topo_optn = document.createElement("OPTION");
+						topo_optn.value = 'TOPO';
+						topo_optn.text = 'TOPO';
+						addElement(restrSiteSelect, restrSiteSelect.options.length-1, topo_optn);
+		
+						// Feb. 5/08: Add option "None"
+						noneOpt = document.createElement("OPTION");
+						noneOpt.text = 'None';
+						noneOpt.value = 'None';
+						addElement(restrSiteSelect, restrSiteSelect.options.length-1, noneOpt);
+		
+						// Finally, select the current cloning site
+						var rsInList = false;
+		
+						for (j = 0; j < restrSiteSelect.options.length; j++)
+						{
+							aOptn = restrSiteSelect.options[j].value;
+		
+							// Oct. 28/08: Use the same strategy as with other feature lists - fetch the selected value from the field name
+							if (selectedRestrictionSite)
+							{
+		// oct 28/08					if (selectedRestrictionSite.value == aOptn)
+								if (selectedRestrictionSite.toLowerCase() == aOptn.toLowerCase())
+								{
+									restrSiteSelect.selectedIndex = j;
+									rsInList = true;
+								}
+							}
+						}
+		// Removed Jan. 16/08 b/c was interfering with 3' Cloning Site list. Should not have 'other' restriction sites for now, see if problems arise. 
+		// 				if (!rsInList)
+		// 				{
+		// 					// Enzyme not found (prob. hybrid); select 'Other' and show textbox
+		// 
+		// 					// add option 'Other' first - moved here Dec. 1/08
+		// 					otherOpt = document.createElement("OPTION");
+		// 					otherOpt.text = 'Other';
+		// 					otherOpt.value = 'Other';
+		// 					addElement(restrSiteSelect, restrSiteSelect.options.length-1, otherOpt);
+		// 					otherIndex = restrSiteSelect.options.length-1;
+		// 	
+		// 					for (k = 0; k < restrSiteSelect.options.length; k++)
+		// 					{
+		// 						if (restrSiteSelect.options[k].value == 'Other')
+		// 						{
+		// 							restrSiteSelect.selectedIndex = k;
+		// 
+		// 							allText = document.getElementsByTagName("INPUT");
+		// 
+		// 							for (at in allText)
+		// 							{
+		// 								if (allText[at].name == "3_prime_cloning_site_name_txt")
+		// 								{
+		// 									allText[at].style.display = "inline";
+		// 								}
+		// 							}
+		// 						}
+		// 					}
+		// 				}
+					}
+					
+					// 3' site
+					if ( (allSelects[a].id == "tpcs_list") || (allSelects[a].id == "tpcs_list_1") || (allSelects[a].id == "tpcs_list_2") || (allSelects[a].id == "tpcs_list_3"))
+					{
+						var threePrimeSelect = allSelects[a];
+			
+						for (i=0; i < enzList.length; i++)
+						{
+							var tmpEnz = trimAll(enzList[i]);
+				
+							enzOpt = document.createElement("OPTION");
+							enzOpt.text = tmpEnz;
+							enzOpt.value = tmpEnz;
+		
+							threePrimeSelect.options[i] = enzOpt;
+						}
+		
+						// Add recombination and gateway sites - attB, attL, attP, LoxP
+		
+		// 				// attB1
+		// 				attB_1_optn = document.createElement("OPTION");
+		// 				attB_1_optn.value = 'attB1';
+		// 				attB_1_optn.text = 'attB1';
+		// 				addElement(threePrimeSelect, threePrimeSelect.options.length-1, attB_1_optn);
+		
+						// attB2
+						attB_2_optn = document.createElement("OPTION");
+						attB_2_optn.value = 'attB2';
+						attB_2_optn.text = 'attB2';
+						addElement(threePrimeSelect, threePrimeSelect.options.length-1, attB_2_optn);
+		
+		// 				// attL1
+		// 				attL_1_optn = document.createElement("OPTION");
+		// 				attL_1_optn.value = 'attL1';
+		// 				attL_1_optn.text = 'attL1';
+		// 				addElement(threePrimeSelect, threePrimeSelect.options.length-1, attL_1_optn);
+		
+						// attL2
+						attL_2_optn = document.createElement("OPTION");
+						attL_2_optn.value = 'attL2';
+						attL_2_optn.text = 'attL2';
+						addElement(threePrimeSelect, threePrimeSelect.options.length-1, attL_2_optn);
+		
+		// 				// attP1
+		// 				attP_1_optn = document.createElement("OPTION");
+		// 				attP_1_optn.value = 'attP1';
+		// 				attP_1_optn.text = 'attP1';
+		// 				addElement(threePrimeSelect, threePrimeSelect.options.length-1, attP_1_optn);
+		
+						// attP2
+						attP_2_optn = document.createElement("OPTION");
+						attP_2_optn.value = 'attP2';
+						attP_2_optn.text = 'attP2';
+						addElement(threePrimeSelect, threePrimeSelect.options.length-1, attP_2_optn);
+		
+		// 				// attR1
+		// 				attR_1_optn = document.createElement("OPTION");
+		// 				attR_1_optn.value = 'attR1';
+		// 				attR_1_optn.text = 'attR1';
+		// 				addElement(threePrimeSelect, threePrimeSelect.options.length-1, attR_1_optn);
+		
+						// attR2
+						attR_2_optn = document.createElement("OPTION");
+						attR_2_optn.value = 'attR2';
+						attR_2_optn.text = 'attR2';
+						addElement(threePrimeSelect, threePrimeSelect.options.length-1, attR_2_optn);
+						
+						// LoxP
+						loxp_optn = document.createElement("OPTION");
+						loxp_optn.value = 'LoxP';
+						loxp_optn.text = 'LoxP';
+						addElement(threePrimeSelect, threePrimeSelect.options.length-1, loxp_optn);
+		
+						// Feb. 5/08: Add option "None"
+						noneOpt = document.createElement("OPTION");
+						noneOpt.text = 'None';
+						noneOpt.value = 'None';
+						addElement(threePrimeSelect, threePrimeSelect.options.length-1, noneOpt);
+		
+						// Finally, select the current cloning site
+						var tpInList = false;
+		
+						for (j = 0; j < threePrimeSelect.options.length; j++)
+						{
+							aOptn = threePrimeSelect.options[j].value;
+		
+							// Updated Nov. 19/08
+							if (selectedThreePrime_Insert && threePrimeSelect.id == "tpcs_list")
+							{
+								if (selectedThreePrime_Insert.value == aOptn)
+								{
+									tpInList = true;
+									threePrimeSelect.selectedIndex = j;
+								}
+							}
+		
+							else if (selectedThreePrime)
+							{
+								if (selectedThreePrime.value == aOptn)
+								{
+									threePrimeSelect.selectedIndex = j;
+									tpInList = true;
+								}
+							}
+						}
+		
+						if (!tpInList)
+						{
+							// Enzyme not found (prob. hybrid); select 'Other' and show textbox
+			
+							// add option 'Other' first - Dec. 1/08
+							otherOpt = document.createElement("OPTION");
+							otherOpt.text = 'Other';
+							otherOpt.value = 'Other';
+							addElement(threePrimeSelect, threePrimeSelect.options.length-1, otherOpt);
+							otherIndex = threePrimeSelect.options.length-1;
+		
+							for (k = 0; k < threePrimeSelect.options.length; k++)
+							{
+								if (threePrimeSelect.options[k].value.toLowerCase() == 'other')
+								{
+									threePrimeSelect.selectedIndex = k;
+		
+									allText = document.getElementsByTagName("INPUT");
+		
+									for (at in allText)
+									{
+										if (allText[at].name == "3_prime_cloning_site_name_txt")
+										{
+											allText[at].style.display = "inline";
+										}
+									}
+								}
+							}
+						}
+					}
+				}	// end if (allSelects[a].id)
+			}	// end if (allSelects[a])
+		}
+	}
+}
+
+
+function cancelVectorModification(scriptPath)
+{
+	document.getElementById("change_state_id").value = "Cancel";
+	document.vectorDetailForm.submit();
+}
+
+function modifyVector(scriptPath)
+{
+	document.getElementById("change_state_id").value = "Modify";
+	document.vectorDetailForm.submit();
+}
+
+// On Save, if restriction sites were modified, verify that they could be used to construct sequence
+// Updated April 18/08: added vType parameter
+function verifySequenceAndRestrictionSites(scriptPath, vType)
+{
+	document.getElementById("saveBtn").style.cursor = 'wait';
+
+	var fpList = document.getElementById("fpcs_list_" + vType);
+	var tpList = document.getElementById("tpcs_list_" + vType);
+
+	var fpSelInd = fpList.selectedIndex;
+	var tpSelInd = tpList.selectedIndex;
+
+	var fpcs = fpList[fpSelInd].value;
+	var tpcs = tpList[tpSelInd].value;
+
+	var fpcs_orig = document.getElementById("fpcs_original").value;
+	var tpcs_orig = document.getElementById("tpcs_original").value;
+
+	var params = "";
+
+	var vType = document.getElementById("vector_cloning_method").value;
+
+	var parentVectorField = document.getElementById("parent_vector_id_txt");
+	var srcPV = parentVectorField.value;
+
+	var uName = document.getElementById("curr_uname").value;
+
+	// feb 5/08: hide name warning
+	if (document.getElementById(vType + "_name_warning"))
+		document.getElementById(vType + "_name_warning").style.display = "none";
+
+// 	document.getElementById("oc_warning").style.display = "none";
+// 	document.getElementById("it_warning").style.display = "none";
+
+// 	document.getElementById("change_state_id").value = "Save";
+
+//	if ((fpcs != fpcs_orig) || (tpcs != tpcs_orig))
+//	{
+		url = scriptPath + "vector_sequence.py";
+		xmlhttp1 = createXML();
+		xmlhttp1.open("POST", url, false);
+		xmlhttp1.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+	
+		switch (vType)
+		{
+			case '1':
+				srcInsert = document.getElementById("insert_id_txt").value;
+				seqParams = "PV=" + srcPV + "&I=" + srcInsert + "&fpcs=" + fpcs + "&tpcs=" + tpcs + "&curr_username=" + uName + "&cloning_method=" + vType + "&change_state=Save";
+
+				xmlhttp1.send(seqParams);
+				xmlhttp1.onreadystatechange = preloadSequence(xmlhttp1, scriptPath);
+			break;
+
+			case '2':
+				srcIPV = document.getElementById("ipv_id_txt").value;
+				seqParams = "PV=" + srcPV + "&IPV=" + srcIPV + "&fpcs=" + fpcs + "&tpcs=" + tpcs + "&curr_username=" + uName + "&cloning_method=" + vType + "&change_state=Save";
+		
+				xmlhttp1.send(seqParams);
+				xmlhttp1.onreadystatechange = preloadSequence(xmlhttp1, scriptPath);	
+			break;
+
+			default:
+			break;
+		}
+//	}
+
+	document.getElementById("saveBtn").style.cursor = 'auto';
+}
+
+
+// Preload properties when parent values are changed
+function previewVector(scriptPath)
+{
+	document.getElementById("changeParentsBtn").style.cursor = 'wait';
+
+	var vType = document.getElementById("vector_cloning_method").value;
+	
+	if (verifyParentFormat(vType))
+	{
+	
+		var fpList = document.getElementById("fpcs_list");
+		var tpList = document.getElementById("tpcs_list");
+
+		var fpSelInd = fpList.selectedIndex;
+		var tpSelInd = tpList.selectedIndex;
+
+		var fpcs = fpList[fpSelInd].value;
+		var tpcs = tpList[tpSelInd].value;
+
+		var uName = document.getElementById("curr_uname").value;
+
+		var params = "";
+		
+		var srcPV, srcInsert, srcIPV;
+
+		changeParentValues(vType);
+
+		// Sequence
+		// First, check if parents are filled in
+		var parentVectorField = document.getElementById("parent_vector_id_txt");
+		var parentVector = parentVectorField.value;
+
+		srcPV = document.getElementById("parent_vector_id_txt").value;
+
+		// remember PV
+		document.getElementById("parent_vector_old_id").value = parentVector;
+
+		var seqField = document.getElementById("dna_sequence");
+
+		if (parentVector == "")
+		{
+			var proceed = confirm("Your Parent Vector value is empty.  Are you sure you wish to proceed?");
+
+			if (proceed)
+			{
+				seqField.value = "";
+				return true;
+			}
+			else
+			{
+				parentVectorField.focus();
+			}
+		}
+		else
+		{
+			// Sequence
+			url = scriptPath + "vector_sequence.py";
+			xmlhttp1 = createXML();
+			xmlhttp1.open("POST", url, false);
+			xmlhttp1.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+		
+			switch (vType)
+			{
+				case '1':
+				
+					// Non-recombination vector
+					srcInsert = document.getElementById("insert_id_txt").value;
+		
+					// Insert empty??
+					if (srcInsert == "")
+					{
+						var proceed = confirm("Your Insert value is empty.  Are you sure you wish to proceed?");
+
+						if (proceed)
+						{
+							document.getElementById("dna_sequence").value = "";
+							return true;
+						}
+						else
+						{
+							// different parameters for different properties
+							seqParams = "PV=" + srcPV + "&I=" + srcInsert + "&fpcs=" + fpcs + "&tpcs=" + tpcs + "&curr_username=" + uName + "&cloning_method=" + vType + "&change_state=Save";
+							
+							xmlhttp1.send(seqParams);
+							xmlhttp1.onreadystatechange = preloadSequence(xmlhttp1, scriptPath);
+						}
+					}
+					else
+					{
+						// different parameters for different properties
+						seqParams = "PV=" + srcPV + "&I=" + srcInsert + "&fpcs=" + fpcs + "&tpcs=" + tpcs + "&curr_username=" + uName + "&cloning_method=" + vType + "&change_state=Save";
+						
+						xmlhttp1.send(seqParams);
+						xmlhttp1.onreadystatechange = preloadSequence(xmlhttp1, scriptPath);
+					}
+				break;
+		
+				case '2':
+					
+					// Recombination vector
+					srcIPV = document.getElementById("ipv_id_txt").value;
+		
+					if (srcIPV == "")
+					{
+						var proceed = confirm("Your Insert value is empty.  Are you sure you wish to proceed?");
+
+						if (proceed)
+						{
+							document.getElementById("dna_sequence").value = "";
+							return true;
+						}
+						else
+						{
+							// different parameters for different properties
+							seqParams = "PV=" + srcPV + "&IPV=" + srcIPV + "&fpcs=" + fpcs + "&tpcs=" + tpcs + "&curr_username=" + uName + "&cloning_method=" + vType + "&change_state=Save";
+					
+							xmlhttp1.send(seqParams);
+							xmlhttp1.onreadystatechange = preloadSequence(xmlhttp1, scriptPath);
+						}
+					}
+					else
+					{
+						// different parameters for different properties
+						seqParams = "PV=" + srcPV + "&IPV=" + srcIPV + "&fpcs=" + fpcs + "&tpcs=" + tpcs + "&curr_username=" + uName + "&cloning_method=" + vType + "&change_state=Save";
+				
+						xmlhttp1.send(seqParams);
+						xmlhttp1.onreadystatechange = preloadSequence(xmlhttp1, scriptPath);
+					}
+				break;
+			}
+		}
+
+		// Cloning sites - Keep latest values
+		// 	fpList.options[fpSelInd].selected = true;
+		// 	tpList.options[tpSelInd].selected = true;
+
+	}
+	
+	document.getElementById("changeParentsBtn").style.cursor = 'auto';
+}
+
+function preloadSequence(xmlhttp, scriptPath)
+{
+//	alert("Loading sequence");
+//	alert(xmlhttp.readyState);
+
+	var fpList = document.getElementById("fpcs_list");
+	var tpList = document.getElementById("tpcs_list");
+
+	if (xmlhttp.readyState == 4)
+	{
+//		alert(xmlhttp.status);
+//		alert(xmlhttp.responseText);
+	
+		if (xmlhttp.status == 200)
+		{
+			response = trimAll(xmlhttp.responseText);	// tab-separated
+//			alert(response);
+			if (response == 1)
+			{
+				alert("Unable to generate sequence: Unknown sites on Insert. Please verify your input values before saving.")
+
+				// reset parent values
+				document.getElementById("parent_vector_id_txt").value = document.getElementById("pv_original").value;
+				document.getElementById("parent_vector_id_txt").style.color = "#FF0000";
+
+				if (document.getElementById("insert_id_txt"))
+				{
+					document.getElementById("insert_id_txt").style.color = "#FF0000";
+					document.getElementById("insert_id_txt").value = document.getElementById("insert_original").value;
+				}
+
+				else if (document.getElementById("ipv_id_txt"))
+				{
+					document.getElementById("ipv_id_txt").style.color = "#FF0000";
+					document.getElementById("ipv_id_txt").value = document.getElementById("ipv_original").value;
+				}
+
+				fpcs_orig = document.getElementById("fpcs_original").value;
+				tpcs_orig = document.getElementById("tpcs_original").value;
+			
+				fpList.style.color = "#FF0000";
+				tpList.style.color = "#FF0000";
+
+				matchListOption(fpList.id, fpcs_orig);
+				matchListOption(tpList.id, tpcs_orig);
+
+				// reset sequence
+				seq_orig = document.getElementById("seq_original").value;
+				seq_curr = document.getElementById("dna_sequence").value;
+
+				if (filterSpace(seq_curr) != seq_orig)
+				{
+					document.getElementById("dna_sequence").value = seq_orig;
+				}
+			}
+			else if (response == 2)
+			{
+				alert("Unable to generate sequence: Restriction sites could not be found on parent vector sequence. Please verify your input values before saving.")
+
+				// reset parent values
+				document.getElementById("parent_vector_id_txt").value = document.getElementById("pv_original").value;
+				document.getElementById("parent_vector_id_txt").style.color = "#FF0000";
+
+				if (document.getElementById("insert_id_txt"))
+				{
+					document.getElementById("insert_id_txt").style.color = "#FF0000";
+					document.getElementById("insert_id_txt").value = document.getElementById("insert_original").value;
+				}
+
+				else if (document.getElementById("ipv_id_txt"))
+				{
+					document.getElementById("ipv_id_txt").style.color = "#FF0000";
+					document.getElementById("ipv_id_txt").value = document.getElementById("ipv_original").value;
+				}
+
+				fpcs_orig = document.getElementById("fpcs_original").value;
+				tpcs_orig = document.getElementById("tpcs_original").value;
+			
+				fpList.style.color = "#FF0000";
+				tpList.style.color = "#FF0000";
+			
+				matchListOption(fpList.id, fpcs_orig);
+				matchListOption(tpList.id, tpcs_orig);
+
+				// reset sequence
+				seq_orig = document.getElementById("seq_original").value;
+				seq_curr = document.getElementById("dna_sequence").value;
+
+				if (filterSpace(seq_curr) != seq_orig)
+				{
+					document.getElementById("dna_sequence").value = seq_orig;
+				}
+			}
+			else if (response == 3)
+			{
+				alert("Unable to generate sequence: Restriction sites occur more than once on parent vector sequence. Please verify your input values before saving.")
+
+				// reset parent values
+				document.getElementById("parent_vector_id_txt").value = document.getElementById("pv_original").value;
+
+				document.getElementById("parent_vector_id_txt").style.color = "#FF0000";
+
+				if (document.getElementById("insert_id_txt"))
+				{
+					document.getElementById("insert_id_txt").style.color = "#FF0000";
+					document.getElementById("insert_id_txt").value = document.getElementById("insert_original").value;
+				}
+
+				else if (document.getElementById("ipv_id_txt"))
+				{
+					document.getElementById("ipv_id_txt").style.color = "#FF0000";
+					document.getElementById("ipv_id_txt").value = document.getElementById("ipv_original").value;
+				}
+
+				fpcs_orig = document.getElementById("fpcs_original").value;
+				tpcs_orig = document.getElementById("tpcs_original").value;
+			
+				fpList.style.color = "#FF0000";
+				tpList.style.color = "#FF0000";
+			
+				matchListOption(fpList.id, fpcs_orig);
+				matchListOption(tpList.id, tpcs_orig);
+			
+				// reset sequence
+				seq_orig = document.getElementById("seq_original").value;
+				seq_curr = document.getElementById("dna_sequence").value;
+
+				if (filterSpace(seq_curr) != seq_orig)
+				{
+					document.getElementById("dna_sequence").value = seq_orig;
+				}
+			}
+			else if (response == 4)
+			{
+				alert("Unable to generate sequence: Restriction sites cannot be hybridized. Please verify your input values before saving.")
+
+				// reset parent values
+				document.getElementById("parent_vector_id_txt").value = document.getElementById("pv_original").value;
+				document.getElementById("parent_vector_id_txt").style.color = "#FF0000";
+
+				if (document.getElementById("insert_id_txt"))
+				{
+					document.getElementById("insert_id_txt").style.color = "#FF0000";
+					document.getElementById("insert_id_txt").value = document.getElementById("insert_original").value;
+				}
+
+				else if (document.getElementById("ipv_id_txt"))
+				{
+					document.getElementById("ipv_id_txt").style.color = "#FF0000";
+					document.getElementById("ipv_id_txt").value = document.getElementById("ipv_original").value;
+				}
+
+				fpcs_orig = document.getElementById("fpcs_original").value;
+				tpcs_orig = document.getElementById("tpcs_original").value;
+			
+				fpList.style.color = "#FF0000";
+				tpList.style.color = "#FF0000";
+			
+				matchListOption(fpList.id, fpcs_orig);
+				matchListOption(tpList.id, tpcs_orig);
+			
+				// reset sequence
+				seq_orig = document.getElementById("seq_original").value;
+				seq_curr = document.getElementById("dna_sequence").value;
+
+				if (filterSpace(seq_curr) != seq_orig)
+				{
+					document.getElementById("dna_sequence").value = seq_orig;
+				}
+			}
+			else if (response == 5)
+			{
+				alert("Unable to generate sequence: 5' site occurs after 3' site on parent vector sequence. Please verify your input values before saving.");
+
+				// reset parent values
+				document.getElementById("parent_vector_id_txt").value = document.getElementById("pv_original").value;
+				document.getElementById("parent_vector_id_txt").style.color = "#FF0000";
+
+				if (document.getElementById("insert_id_txt"))
+				{
+					document.getElementById("insert_id_txt").style.color = "#FF0000";
+					document.getElementById("insert_id_txt").value = document.getElementById("insert_original").value;
+				}
+
+				else if (document.getElementById("ipv_id_txt"))
+				{
+					document.getElementById("ipv_id_txt").style.color = "#FF0000";
+					document.getElementById("ipv_id_txt").value = document.getElementById("ipv_original").value;
+				}
+
+				fpcs_orig = document.getElementById("fpcs_original").value;
+				tpcs_orig = document.getElementById("tpcs_original").value;
+			
+				fpList.style.color = "#FF0000";
+				tpList.style.color = "#FF0000";
+			
+				matchListOption(fpList.id, fpcs_orig);
+				matchListOption(tpList.id, tpcs_orig);
+				
+				// reset sequence
+				seq_orig = document.getElementById("seq_original").value;
+				seq_curr = document.getElementById("dna_sequence").value;
+
+				if (filterSpace(seq_curr) != seq_orig)
+				{
+					document.getElementById("dna_sequence").value = seq_orig;
+				}
+			}
+			else if (response == 5)
+			{
+				alert("Unknown parent values.  Please verify your input values before saving.")
+
+				// reset parent values
+				document.getElementById("parent_vector_id_txt").value = document.getElementById("pv_original").value;
+				document.getElementById("parent_vector_id_txt").style.color = "#FF0000";
+
+				if (document.getElementById("insert_id_txt"))
+				{
+					document.getElementById("insert_id_txt").style.color = "#FF0000";
+					document.getElementById("insert_id_txt").value = document.getElementById("insert_original").value;
+				}
+
+				else if (document.getElementById("ipv_id_txt"))
+				{
+					document.getElementById("ipv_id_txt").style.color = "#FF0000";
+					document.getElementById("ipv_id_txt").value = document.getElementById("ipv_original").value;
+				}
+
+				fpcs_orig = document.getElementById("fpcs_original").value;
+				tpcs_orig = document.getElementById("tpcs_original").value;
+			
+				fpList.style.color = "#FF0000";
+				tpList.style.color = "#FF0000";
+			
+				matchListOption(fpList.id, fpcs_orig);
+				matchListOption(tpList.id, tpcs_orig);
+				
+				// reset sequence
+				seq_orig = document.getElementById("seq_original").value;
+				seq_curr = document.getElementById("dna_sequence").value;
+
+				if (filterSpace(seq_curr) != seq_orig)
+				{
+					document.getElementById("dna_sequence").value = seq_orig;
+				}
+			}
+			else if (response == 10)
+			{
+				alert("You are not authorized to use this Parent Vector, since you do not have at least Read access to its project. Please verify your input values before saving.")
+
+				// reset parent values
+				document.getElementById("parent_vector_id_txt").value = document.getElementById("pv_original").value;
+				document.getElementById("parent_vector_id_txt").style.color = "#FF0000";
+				document.getElementById("parent_vector_id_txt").focus();
+
+				fpcs_orig = document.getElementById("fpcs_original").value;
+				tpcs_orig = document.getElementById("tpcs_original").value;
+			
+				fpList.style.color = "#FF0000";
+				tpList.style.color = "#FF0000";
+			
+				matchListOption(fpList.id, fpcs_orig);
+				matchListOption(tpList.id, tpcs_orig);
+				
+				// reset sequence
+				seq_orig = document.getElementById("seq_original").value;
+				seq_curr = document.getElementById("dna_sequence").value;
+
+				if (filterSpace(seq_curr) != seq_orig)
+				{
+					document.getElementById("dna_sequence").value = seq_orig;
+				}
+			}
+			else if (response == 11)
+			{
+				alert("You are not authorized to use this Insert Parent Vector, since you do not have at least Read access to its project. Please verify your input values before saving.");
+
+				// reset parent values
+				document.getElementById("ipv_id_txt").value = document.getElementById("ipv_original").value;
+				document.getElementById("ipv_id_txt").style.color = "#FF0000";
+				document.getElementById("ipv_id_txt").focus();
+
+				fpcs_orig = document.getElementById("fpcs_original").value;
+				tpcs_orig = document.getElementById("tpcs_original").value;
+			
+				fpList.style.color = "#FF0000";
+				tpList.style.color = "#FF0000";
+			
+				matchListOption(fpList.id, fpcs_orig);
+				matchListOption(tpList.id, tpcs_orig);
+				
+				// reset sequence
+				seq_orig = document.getElementById("seq_original").value;
+				seq_curr = document.getElementById("dna_sequence").value;
+
+				if (filterSpace(seq_curr) != seq_orig)
+				{
+					document.getElementById("dna_sequence").value = seq_orig;
+				}
+			}
+			else if (response == 12)
+			{
+				alert("Unable to generate sequence: Unknown Parent Vector ID. Please verify your input values before saving.");
+
+				// reset parent values
+				document.getElementById("parent_vector_id_txt").value = document.getElementById("pv_original").value;
+				document.getElementById("parent_vector_id_txt").style.color = "#FF0000";
+				document.getElementById("parent_vector_id_txt").focus();
+
+				fpcs_orig = document.getElementById("fpcs_original").value;
+				tpcs_orig = document.getElementById("tpcs_original").value;
+			
+				fpList.style.color = "#FF0000";
+				tpList.style.color = "#FF0000";
+			
+				matchListOption(fpList.id, fpcs_orig);
+				matchListOption(tpList.id, tpcs_orig);
+				
+				// reset sequence
+				seq_orig = document.getElementById("seq_original").value;
+				seq_curr = document.getElementById("dna_sequence").value;
+
+				if (filterSpace(seq_curr) != seq_orig)
+				{
+					document.getElementById("dna_sequence").value = seq_orig;
+				}
+			}
+			else if (response == 16)
+			{
+				alert("Unable to generate sequence: Unknown Insert ID. Please verify your input values before saving.");
+
+				document.getElementById("insert_id_txt").value = document.getElementById("insert_old_id").value;
+				document.getElementById("insert_id_txt").style.color = "#FF0000";
+				document.getElementById("insert_id_txt").focus();
+
+				fpcs_orig = document.getElementById("fpcs_original").value;
+				tpcs_orig = document.getElementById("tpcs_original").value;
+			
+				fpList.style.color = "#FF0000";
+				tpList.style.color = "#FF0000";
+			
+				matchListOption(fpList.id, fpcs_orig);
+				matchListOption(tpList.id, tpcs_orig);
+				
+				// reset sequence
+				seq_orig = document.getElementById("seq_original").value;
+				seq_curr = document.getElementById("dna_sequence").value;
+
+				if (filterSpace(seq_curr) != seq_orig)
+				{
+					document.getElementById("dna_sequence").value = seq_orig;
+				}
+			}
+			else if (response == 17)
+			{
+				alert("Unable to generate sequence: Unknown Parent Insert Vector ID. Please verify your input values before saving.");
+
+				document.getElementById("ipv_id_txt").style.color = "#FF0000";
+				document.getElementById("ipv_id_txt").value = document.getElementById("ipv_original").value;
+				document.getElementById("ipv_id_txt").focus();
+
+				fpcs_orig = document.getElementById("fpcs_original").value;
+				tpcs_orig = document.getElementById("tpcs_original").value;
+			
+				fpList.style.color = "#FF0000";
+				tpList.style.color = "#FF0000";
+			
+				matchListOption(fpList.id, fpcs_orig);
+				matchListOption(tpList.id, tpcs_orig);
+
+				// reset sequence
+				seq_orig = document.getElementById("seq_original").value;
+				seq_curr = document.getElementById("dna_sequence").value;
+
+				if (filterSpace(seq_curr) != seq_orig)
+				{
+					document.getElementById("dna_sequence").value = seq_orig;
+				}
+			}
+			else if (response == 18)
+			{
+				alert("Unable to generate sequence: One or both parent sequences are invalid. Please verify your input values before saving.");
+
+				document.getElementById("parent_vector_id_txt").value = document.getElementById("pv_original").value;
+				document.getElementById("parent_vector_id_txt").style.color = "#FF0000";
+
+				if (document.getElementById("insert_id_txt"))
+				{
+					document.getElementById("insert_id_txt").style.color = "#FF0000";
+					document.getElementById("insert_id_txt").value = document.getElementById("insert_original").value;
+				}
+
+				else if (document.getElementById("ipv_id_txt"))
+				{
+					document.getElementById("ipv_id_txt").style.color = "#FF0000";
+					document.getElementById("ipv_id_txt").value = document.getElementById("ipv_original").value;
+				}
+
+				fpcs_orig = document.getElementById("fpcs_original").value;
+				tpcs_orig = document.getElementById("tpcs_original").value;
+			
+				fpList.style.color = "#FF0000";
+				tpList.style.color = "#FF0000";
+			
+				matchListOption(fpList.id, fpcs_orig);
+				matchListOption(tpList.id, tpcs_orig);
+
+				// reset sequence
+				seq_orig = document.getElementById("seq_original").value;
+				seq_curr = document.getElementById("dna_sequence").value;
+
+				if (filterSpace(seq_curr) != seq_orig)
+				{
+					document.getElementById("dna_sequence").value = seq_orig;
+				}
+			}
+			else
+			{
+				// Status OK - show new sequence, REGARDLESS of whether it's identical to original
+				document.getElementById("dna_sequence").value = response;
+
+//				// NOW preload simple properties from PV IFF in preview mode
+//				srcPV = document.getElementById("parent_vector_id_txt").value;
+//
+//				// prepare xmlhttprequest
+//				url = scriptPath + "preview.py";
+//				xmlhttp = createXML();
+//				xmlhttp.open("POST", url, false);
+//				xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+//			
+				if (document.pressed == 'Change')
+				{
+					// NOW preload simple properties from PV -- IFF in preview mode
+					url = scriptPath + "preview.py";
+					xmlhttp = createXML();
+				
+					// Colour properties blue:
+
+					// Sequence
+					document.getElementById("dna_sequence").style.color = "#0000FF";
+
+					// Restriction sites
+					fpList.style.color = "#0000FF";
+					tpList.style.color = "#0000FF";
+
+					// PV
+					srcPV = document.getElementById("parent_vector_id_txt").value;
+					document.getElementById("parent_vector_id_txt").style.color = "#0000FF";
+					
+					// Insert or IPV
+					if (document.getElementById("insert_id_txt"))
+					{
+						document.getElementById("insert_id_txt").style.color = "#0000FF";
+					}
+					else if (document.getElementById("ipv_id_txt"))
+					{
+						document.getElementById("ipv_id_txt").style.color = "#0000FF";
+					}
+
+					// Name
+					document.getElementById("reagent_name_prop").style.color = "#0000FF";
+				
+					// Vector Type
+					document.getElementById("vector_type_list").style.color = "#0000FF";
+
+					// Preload Tag Type
+					xmlhttp.open("POST", url, false);
+					xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+					xmlhttp.send("PV=" + srcPV + "&propAlias=tag");
+					xmlhttp.onreadystatechange = preloadTagType(xmlhttp);
+					
+					// Tag Position
+					xmlhttp.open("POST", url, false);
+					xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+					xmlhttp.send("PV=" + srcPV + "&propAlias=tag_position");
+					xmlhttp.onreadystatechange = preloadTagPosition(xmlhttp);
+					
+					// Expression System
+					xmlhttp.open("POST", url, false);
+					xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+					xmlhttp.send("PV=" + srcPV + "&propAlias=expression_system");
+					xmlhttp.onreadystatechange = preloadExpressionSystem(xmlhttp);
+				
+					// Promoter
+					xmlhttp.open("POST", url, false);
+					xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+					xmlhttp.send("PV=" + srcPV + "&propAlias=promoter");
+					xmlhttp.onreadystatechange = preloadPromoter(xmlhttp);
+				}
+				else if ( (document.pressed == 'Save') || (document.pressed == 'Cancel') )
+				{
+					xmlhttp.open("POST", url, false);
+					xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+					document.vectorDetailForm.submit();
+				}
+			}
+		}
+	}
+}
+
+function preloadTagType(xmlhttp)
+{
+// 	alert("Tag type");
+	if (xmlhttp.readyState == 4)
+	{
+//		alert(xmlhttp.status);
+		if (xmlhttp.status == 200)
+		{
+			response = trimAll(xmlhttp.responseText);	// tab-separated, MUST BE TRIMMED (has extraneous carriage return)
+// 			alert(response);
+	
+			if (document.pressed == 'Change')
+				document.getElementById("tag_list").style.color = "#0000FF";
+			
+			matchListOption("tag_list", response);
+		}
+	}
+}
+
+function preloadTagPosition(xmlhttp)
+{
+// 	alert("Tag position");
+	if (xmlhttp.readyState == 4)
+	{
+		if (xmlhttp.status == 200)
+		{
+			response = trimAll(xmlhttp.responseText);	// tab-separated
+// 			alert(response);
+
+			if (document.pressed == 'Change')
+				document.getElementById("tag_position_list").style.color = "#0000FF";
+	
+			matchListOption("tag_position_list", response);
+		}
+	}
+}
+
+
+function preloadExpressionSystem(xmlhttp)
+{
+// 	alert("Exp sys");
+	if (xmlhttp.readyState == 4)
+	{
+// 		alert(xmlhttp.status);
+// 		alert(xmlhttp.responseText);
+	
+		if (xmlhttp.status == 200)
+		{
+			response = trimAll(xmlhttp.responseText);	// tab-separated
+// 			alert(response);
+			
+			if (document.pressed == 'Change')
+				document.getElementById("expr_syst_list").style.color = "#0000FF";
+			
+			matchListOption("expr_syst_list", response);
+		}
+	}
+}
+
+
+function preloadPromoter(xmlhttp)
+{
+// 	alert("Promoter");
+	if (xmlhttp.readyState == 4)
+	{
+		if (xmlhttp.status == 200)
+		{
+			response = trimAll(xmlhttp.responseText);	// tab-separated
+// 			alert(response);
+
+			if (document.pressed == 'Change')
+				document.getElementById("promoter_list").style.color = "#0000FF";
+	
+			matchListOption("promoter_list", response);
+		}
+	}
+}
+
+
+// Nov. 15/07: In a dropdown list, show the option whose value corresponds to 'optionValue'
+function matchListOption(listName, optionValue)
+{
+	var myList = document.getElementById(listName);
+
+	for (i = 0; i < myList.options.length; i++)
+	{
+		tmpOpt = myList.options[i];
+	
+		if (trimAll(tmpOpt.value.toLowerCase()) == trimAll(optionValue.toLowerCase()))
+		{
+			tmpOpt.selected = true;
+			break;
+		}
+	}
+}
+
+
+// Jan. 23/08: Assign argument values to hidden form input fields
+function addToOrder(reagentID, isolateNumber, containerID, row, col)
+{
+	document.getElementById("order_rid").value = reagentID;
+	document.getElementById("order_iso_num").value = isolateNumber;
+	document.getElementById("order_cont_id").value = containerID;
+	document.getElementById("order_row").value = row;
+	document.getElementById("order_col").value = col;
+
+	document.getElementById("order_placed").value = "1";
+	var currMode = document.getElementById("location_output_mode").value;
+	
+	document.viewLocation.action = "Location.php?View=1&rid=" + reagentID + "&mode=" + currMode;
+	document.viewLocation.submit();
+}
+
+function changeFormAction(form_name, new_action)
+{
+	docForms = document.forms;
+
+	for (i = 0; i < docForms.length; i++)
+	{
+		aForm = docForms[i];
+
+		if (aForm.name == form_name)
+		{
+			aForm.action = new_action;
+			aForm.submit();
+		}
+	}
+}
+
+
+// Feb. 19/08: Move to DNA sequence tab on Reagent Detailed View
+function showDNASequence()
+{
+	var dnaSeqTab = document.getElementById("dnaSequenceTab");
+	var viewDnaTab = document.getElementById("viewDnaTab");
+
+	dnaSeqTab.style.display = "inline";
+
+	// Make tab active
+	viewDnaTab.style.paddingBottom = "9px";
+	viewDnaTab.style.backgroundColor = "#FFF8DC";
+	viewDnaTab.style.color = "#00008B";
+
+	// hide all other sequence view tabs (options: protein or map - coming soon)
+	var protSeqTab = document.getElementById("proteinSequenceTab");
+	var viewProtTab = document.getElementById("viewProteinTab");
+
+	if (protSeqTab && (protSeqTab.style.display != "none"))
+	{
+		protSeqTab.style.display = "none";
+		
+		// make protein tab active
+		viewProtTab.className = "tabLinkInactive";
+
+		viewProtTab.style.paddingBottom = "6px";
+		viewProtTab.style.backgroundColor = "#FFF8DC";
+		viewProtTab.style.color = "#36648B";
+
+		// Enable buttons
+		// Edit btn - Hard-code: only DNA and RNA can have protein translation tabs
+		if (document.getElementById("edit_reagent_sequence_properties") && document.getElementById("save_reagent_sequence_properties") && document.getElementById("cancel_save_sequence_properties"))
+		{
+			var editBtn = document.getElementById("edit_reagent_sequence_properties");
+			var saveBtn = document.getElementById("save_reagent_sequence_properties");
+			var cancelBtn = document.getElementById("cancel_save_sequence_properties");
+		}
+		else if (document.getElementById("edit_reagent_rna_sequence") && document.getElementById("save_reagent_rna_sequence") && document.getElementById("cancel_save_rna_sequence"))
+		{
+			var editBtn = document.getElementById("edit_reagent_rna_sequence");
+			var saveBtn = document.getElementById("save_reagent_rna_sequence");
+			var cancelBtn = document.getElementById("cancel_save_rna_sequence");
+		}
+
+		if (editBtn.style.display != "none")
+			editBtn.disabled = false;
+
+		if (saveBtn.style.display != "none")
+			saveBtn.disabled = false;
+
+		if (cancelBtn.style.display != "none")
+			cancelBtn.disabled = false;
+	}
+}
+
+// Feb. 19/08: Move to DNA sequence tab on Reagent Detailed View
+function showProteinSequence(reagentType)
+{
+	var protSeqTab = document.getElementById("proteinSequenceTab");
+	var viewProtTab = document.getElementById("viewProteinTab");
+	
+	protSeqTab.style.display = "inline";
+
+	viewProtTab.style.paddingBottom = "9px";
+	viewProtTab.style.backgroundColor = "#FFF8DC";
+	viewProtTab.style.color = "#00008B";
+
+	// hide all other sequence view tabs (options: DNA or map - coming soon)
+	var dnaSeqTab = document.getElementById("dnaSequenceTab");
+	var viewDnaTab = document.getElementById("viewDnaTab");
+
+	if (dnaSeqTab && (dnaSeqTab.style.display != "none"))
+	{
+		dnaSeqTab.style.display = "none";
+
+		viewDnaTab.style.paddingBottom = "6px";
+		viewDnaTab.style.backgroundColor = "#FFF8DC";
+		viewDnaTab.style.color = "#36648B";
+
+		// Disable buttons!!
+
+		// Hard-code: only DNA and RNA can have protein translation tabs
+		if (document.getElementById("edit_reagent_sequence_properties") && document.getElementById("save_reagent_sequence_properties") && document.getElementById("cancel_save_sequence_properties"))
+		{
+			var editBtn = document.getElementById("edit_reagent_sequence_properties");
+			var saveBtn = document.getElementById("save_reagent_sequence_properties");
+			var cancelBtn = document.getElementById("cancel_save_sequence_properties");
+		}
+		else if (document.getElementById("edit_reagent_rna_sequence") && document.getElementById("save_reagent_rna_sequence") && document.getElementById("cancel_save_rna_sequence"))
+		{
+			var editBtn = document.getElementById("edit_reagent_rna_sequence");
+			var saveBtn = document.getElementById("save_reagent_rna_sequence");
+			var cancelBtn = document.getElementById("cancel_save_rna_sequence");
+		}
+
+		if (editBtn.style.display != "none")
+			editBtn.disabled = true;
+
+		if (saveBtn.style.display != "none")
+			saveBtn.disabled = true;
+
+		if (cancelBtn.style.display != "none")
+			cancelBtn.disabled = true;
+	}
+}
+
+// Taken from http://javascript.about.com/library/bladdslash.htm
+// Nov. 4/08
+function stripslashes(str)
+{
+	str=str.replace(/\\'/g,'\'');
+	str=str.replace(/\\"/g,'"');
+	str=str.replace(/\\\\/g,'\\');
+	str=str.replace(/\\0/g,'\0');
+	return str;
+}
+
+// Taken from http://javascript.about.com/library/bladdslash.htm
+// Nov. 4/08
+function addslashes(str)
+{
+	str=str.replace(/\'/g,'\\\'');
+	str=str.replace(/\"/g,'\\"');
+	str=str.replace(/\\/g,'\\\\');
+	str=str.replace(/\0/g,'\\0');
+	return str;
+}
+
+function deleteTableRow(tableID, rowID)
+{
+// alert(tableID);
+	var aTable = document.getElementById(tableID);
+// alert(rowID);
+
+	// updated Oct. 27/08
+// 	var tmpRow = document.getElementById(rowID);
+// 	var tmpRow = document.getElementById(rowID.replace("\'", "'"));	// miscellaneous 5' and 3' PCMV LTR values
+
+// alert(aTable.rows.length);
+	// change Feb. 12/10
+	for (i=0; i < aTable.rows.length; i++)
+	{
+		tmpRow = aTable.rows[i];
+
+		if (tmpRow.id == rowID)
+		{
+			var rIndex = tmpRow.rowIndex;
+// alert(rIndex);
+			aTable.deleteRow(rIndex);
+			return;
+		}
+	}
+
+// 	var tmpRow = document.getElementById(stripslashes(rowID));
+// // alert(tmpRow);
+// 	if (tmpRow)
+// 	{
+// 		var rIndex = tmpRow.rowIndex;
+// // 		alert(rIndex);
+// 
+// // if (aTable.rows.length > 1)
+// // 		aTable.deleteRow(rIndex-1);
+// // else
+// 		aTable.deleteRow(rIndex);
+// 	}
+}
+
+
+function getBounds(mode, rID)
+{
+	var start = -1;
+	var stop = -1;
+
+	var constProtSeq = document.getElementById("const_protSeq_" + rID).value;
+	var constDNASeq = document.getElementById("const_dnaSeq_" + rID).value;
+
+	var protStart = document.getElementById("aa_start_txt_" + rID);
+	var protStop = document.getElementById("aa_end_txt_" + rID);
+
+	// Updated May 30/08
+	var cdnaStart = parseInt(document.getElementById("cdna_start").value);
+	var cdnaStop = parseInt(document.getElementById("cdna_stop").value);
+
+	// Sept. 11/08
+	var translStart = parseInt(document.getElementById("prot_start").value);
+	var translStop = parseInt(document.getElementById("prot_stop").value);
+
+	var protOut = document.getElementById("sel_prot_div_" + rID);
+	var dnaOut = document.getElementById("sel_dna_div_" + rID);
+
+	var submitBtn = document.getElementById("get_primers_btn");	// added Sept 14/06
+	var linkersTbl = document.getElementById("linkers_tbl");	// Sept 8/06
+
+	var protSeqOut = '';
+	var dnaSeqOut = '';
+
+	//var indexWarning = document.getElementById("index_warning");	// different error-handling method, check with Karen what her preference is
+
+	if (mode == 'protein')
+	{
+		start = protStart.value;
+		stop = protStop.value;
+
+		// Check that start/stop values are non-empty
+		if (start.length == 0)
+		{
+			alert("Please provide a protein start value");
+			protStart.focus();
+
+			return false;
+		}
+
+		if (stop.length == 0)
+		{
+			alert("Please provide a protein stop value");
+			protStop.focus();
+
+			return false;
+		}
+
+		// First, check if the start/stop values entered are integers
+		// Since parseInt could still return an int even if the value contained alpha chars but began with a digit (it would simply discard the rest), adding my own validation code:
+
+		// check start
+		for (i = 0; i < start.length; i++)
+		{
+			var c = start.charAt(i);
+
+			if (c < "0" || c > "9")
+			{
+				alert("Protein start value must be a non-negative integer; please verify your input");
+
+				protStop.style.color = "000000";
+				protStop.style.fontWeight = "normal";
+
+				protStart.style.color = "FF0000";
+				protStart.style.fontWeight = "bold";
+
+				protStart.focus();
+
+				return false;
+			}
+		}
+
+		// check stop
+		for (i = 0; i < stop.length; i++)
+		{
+			var c = stop.charAt(i);
+
+			if (c < "0" || c > "9")
+			{
+				alert("Protein stop value must be a non-negative integer; please verify your input");
+
+				protStart.style.color = "000000";
+				protStart.style.fontWeight = "normal";
+
+				protStop.style.color = "FF0000";
+				protStop.style.fontWeight = "bold";
+
+				protStop.focus();
+
+				return false;
+			}
+		}
+
+		// Once we know the user has entered integers for start and stop, can convert and do numeric comparison
+		// (Put parseFloat in here due to a bug in Javascript parseInt, where "012" is interpreted as "10" and not as "12")
+		// (See http://www.go4expert.com/forums/showthread.php?t=857)
+		start = parseInt(parseFloat(protStart.value));
+		stop = parseInt(parseFloat(protStop.value));
+
+		// Check that both are non-zero
+		if (start == 0)
+		{
+			alert("Protein start value must be greater than 0; please verify your input");
+
+			protStop.style.color = "000000";
+			protStop.style.fontWeight = "normal";
+
+			protStart.style.color = "FF0000";
+			protStart.style.fontWeight = "bold";
+
+			protStart.focus();
+
+			return false;
+		}
+		else if  (stop == 0)
+		{
+			alert("Protein stop value must be greater than 0; please verify your input");
+
+			protStart.style.color = "000000";
+			protStart.style.fontWeight = "normal";
+
+			protStop.style.color = "FF0000";
+			protStop.style.fontWeight = "bold";
+
+			// focus anyway
+			protStop.focus();
+
+			return false;
+		}
+		// Verify that start < stop
+		else if (start > stop)
+		{
+			// Either:
+			//indexWarning.style.display = "inline";
+
+			// Or:
+			alert("Start position cannot be greater than end position, please verify your input values");
+
+			protStart.style.color = "FF0000";
+			protStart.style.fontWeight = "bold";
+
+			protStop.style.color = "FF0000";
+			protStop.style.fontWeight = "bold";
+
+			protStart.focus();
+
+			return false;
+		}
+		// Not showing an error if stop exceeds sequence size - it's completely irrelevant for the program and less annoying to the user
+		else
+		{
+			// Reset default format in case error message was displayed earlier
+
+			// Either:
+			//indexWarning.style.display = "none";
+
+			// Or:
+			protStart.style.color = "000000";
+			protStart.style.fontWeight = "normal";
+
+			protStop.style.color = "000000";
+			protStop.style.fontWeight = "normal";
+
+			protSeqOut = constProtSeq.substring(start-1, stop);	
+
+			// June 5/08
+			protLen = stop - start + 1;
+
+			// changed June 5/08
+			dnaSeqOut = constDNASeq.substring((start-1)*3, stop*3);
+			//dnaSeqOut = constDNASeq.substring(dnaStartPos, dnaEndPos);
+
+			// changed Sept. 11/08
+			dnaStartPos = translStart - 1 + (start-1)*3;
+			dnaEndPos = dnaStartPos + protLen*3;
+
+			protOut.style.display = "inline";
+
+			protOut.innerHTML = "<P><font size=2px face=Helvetica><b>Selected protein sequence to be cloned:\n</b></font><P>" + spaceAA(protSeqOut);
+
+			dnaOut.innerHTML = "<font size=2px face=Helvetica><b>Corresponding DNA sequence:</b>  (" + (dnaStartPos+1) + " - " + dnaEndPos + ")\n</font><P>" + spaceNT(dnaSeqOut);
+		}
+	}
+	else if (mode == 'nt')
+	{
+	}
+
+	submitBtn.style.display="inline";	// Sept 14/06
+	resetLinkers();				// Nov. 7/06
+	linkersTbl.style.display="inline";	// Sept 8/06
+
+	return true;
+}
+
+
+function spaceAA(seq)
+{
+	var outSeq = '';
+	var chunk = '';
+
+	if (seq.length > 100)
+	{
+		for (i = 0; i < seq.length; i += 10)
+		{
+			chunk += seq.substring(i, i+10) + ' ';
+
+			if (chunk.length == 110)
+			{
+				chunk += '\n';
+				outSeq += chunk;
+				chunk = '';
+			}
+
+		}
+
+		outSeq += chunk;
+	}
+	else
+	{
+		for (i = 0; i < seq.length; i += 10)
+		{
+			outSeq += seq.substring(i, i+10) + ' ';
+		}
+
+		outSeq += seq.substring(i);
+	}
+
+
+	return outSeq;
+}
+
+
+function filterSpace(txt)
+{
+	var txt_ar = txt.split(' ');
+	var sel = "";
+
+	for (i = 0; i < txt_ar.length; i++)
+	{
+		sel += txt_ar[i];
+	}
+
+	return sel;
+}
+
+
+function spaceNT(seq)
+{
+	var outSeq = '';
+	var chunk = '';
+
+	for (i = 0; i < seq.length; i += 3)
+	{
+		chunk += seq.substring(i, i+3) + ' ';
+
+		if (chunk.length == 108)
+		{
+			chunk += '\n';
+			outSeq += chunk;
+			chunk = '';
+		}
+	}
+
+	outSeq += chunk;
+
+	return outSeq;
+}
+
+
+// Sept 8/06 - Show linkers
+function showHideLinkers()
+{
+	linkerSelector = document.getElementById("linker_selector");
+	linkers_row = document.getElementById("linkers_row");
+
+	for (i = 0; i < linkerSelector.options.length; i++)
+	{
+		currOpt = linkerSelector.options[i];
+
+		if (currOpt.selected)
+		{
+			if (currOpt.value == 'Yes')
+			{
+				linkers_row.style.display="table-row";
+				selectLinkers();			// added Nov. 7/06 - if values are cleared, they need to be refilled
+			}
+			else
+			{
+				linkers_row.style.display="none";
+
+				// Added Nov. 7/06: reset linker values too
+				resetLinkerFields();
+			}
+		}
+	}
+}
+
+// This function ONLY clears out the 
+function resetLinkerFields()
+{
+	fwdLinker = document.getElementById("fp_linker");
+	revLinker = document.getElementById("tp_linker");
+
+	fwdLinker.value = "";
+	revLinker.value = "";
+}
+
+// Added Nov. 7/06 by Marina
+// The difference between this function and resetLinkerValues() is that this function resets ALL fields dealing with linkers - i.e. the 'yes/no add linkers' dropdown menu, the linker selection lists and the linker value text fields; resetLinkerFields(), on the other hand, ONLY clears out the values of the linker text fields
+// This function is called on page reload, when ALL linker values need to be reset
+function resetLinkers()
+{
+	linkerSelector = document.getElementById("linker_selector");
+
+	fwdLinkerSelector = document.getElementById("fwd_linker_types_selector");
+	revLinkerSelector = document.getElementById("rev_linker_types_selector");
+
+	fwdLinker = document.getElementById("fp_linker");
+	revLinker = document.getElementById("tp_linker");
+
+	linkerSelector.options[0].selected = 1;
+	fwdLinkerSelector.options[0].selected = 1;
+	revLinkerSelector.options[0].selected = 1;
+
+	fwdLinker.value = "";
+	revLinker.value = "";
+}
+
+// Sept 11/06 - Prefill linker values based on option selected
+function selectLinkers()
+{
+	fwdLinkerSelector = document.getElementById("fwd_linker_types_selector");
+	revLinkerSelector = document.getElementById("rev_linker_types_selector");
+
+	fwdLinker = document.getElementById("fp_linker");
+	revLinker = document.getElementById("tp_linker");
+
+	var fwdLinkersDict = new Object;
+	var revLinkersDict = new Object;
+
+	fwdLinkersDict['gw_atg'] = "gggg aca act ttg tac aaa aaa gtt ggc acc atg";
+	fwdLinkersDict['gw_no_atg'] = "gggg aca act ttg tac aaa aaa gtt ggc acc";
+	fwdLinkersDict['creator_v7_fusion_atg'] = "t acg aag tta tgg cgc gcc atg";
+	fwdLinkersDict['creator_v7_fusion_no_atg'] = "t acg aag tta tgg cgc gcc";
+	fwdLinkersDict['creator_v37_fusion_atg'] = "t ttt ccc cag ggg cgc gcc atg";
+	fwdLinkersDict['creator_v37_fusion_no_atg'] = "t ttt ccc cag ggg cgc gcc";
+	fwdLinkersDict['his_vector_atg'] = "ag gga tcc ggg cgc gcc atg";
+	fwdLinkersDict['his_vector_no_atg'] = "ag gga tcc ggg cgc gcc";
+
+	// April 22, 2009: T7/SP6 Promoters w/ Kozak for Nick and Jerry
+	fwdLinkersDict['t7_promoter'] = "ggcgcgcc taatacgactcactataggg aacag ccacc";
+	fwdLinkersDict['sp6_promoter'] = "ggcgcgcc tatttaggtgacactatag aacag accacc";
+
+	revLinkersDict['gw_stop'] = "gggg ac aac ttt gta caa gaa agt tgg gta cta";
+	revLinkersDict['gw_no_stop'] = "gggg ac aac ttt gta caa gaa agt tgg gta";
+	revLinkersDict['creator_fusion_stop'] = "cta gga act tac ctg gtt aat taa cta";
+	revLinkersDict['creator_fusion_no_stop'] = "cta gga act tac ctg gtt aat taa";
+	revLinkersDict['his_vector_stop'] = "gtg ctc gag tca tca gaa ttc gtt aat taa cta";
+	revLinkersDict['his_vector_no_stop'] = "gtg ctc gag tca tca gaa ttc gtt aat taa";
+
+	// April 22, 2009: Flag-Tag for Nick and Jerry
+	revLinkersDict['flag_tag'] = "tta cttgtcatcgtcatccttgtaatc gccgcctccgccgcc";
+
+	// 5' Linkers
+	for (i = 0; i < fwdLinkerSelector.options.length; i++)
+	{
+		currOpt = fwdLinkerSelector.options[i];
+
+		if (currOpt.selected)
+		{
+// 			alert(currOpt.value);
+
+			if (fwdLinkersDict[currOpt.value])
+				fwdLinker.value = fwdLinkersDict[currOpt.value];
+
+			else if (currOpt.value.toLowerCase() != 'other')	// updated Nov. 20/08 - added ' if (currOpt.value != 'other')'; otherwise lose value entered for 'Other' when the other linker list changes
+				fwdLinker.value = "";		// Fix Dec. 15/08: had 'revLinker' instead of 'fwdLinker'
+		}
+	}
+
+
+	// 3' Linkers
+	for (i = 0; i < revLinkerSelector.options.length; i++)
+	{
+		currOpt = revLinkerSelector.options[i];
+
+		if (currOpt.selected)
+		{
+			if (revLinkersDict[currOpt.value])
+				revLinker.value = revLinkersDict[currOpt.value];
+
+			else if (currOpt.value.toLowerCase() != 'other')	// updated Nov. 20/08 - added ' if (currOpt.value != 'other')'; otherwise lose value entered for 'Other' when the other linker list changes
+				revLinker.value = "";
+		}
+	}
+}
+
+// Added Nov. 7/06 by Marina - Make sure Tm > 0 and length >= linker size + 10
+function verifyTmAndLength()
+{
+	/*const MIN_PRIMER_LENGTH = 10;
+
+	// length form input fields
+	var fwdLengthFormField = document.getElementById("fwd_length_id");
+	var revLengthFormField = document.getElementById("rev_length_id");
+
+	// length input values
+	var fwdLength = fwdLengthFormField.value;
+	var revLength = revLengthFormField.value;*/
+
+	// Tm form input fields
+	var fwdTmFormField = document.getElementById("fwd_tm_id");
+	var revTmFormField = document.getElementById("rev_tm_id");
+
+	// Tm input values
+	var fwdTm = fwdTmFormField.value;
+	var revTm = revTmFormField.value;
+
+	/*// linker values
+	var fwdLinker = document.getElementById("fp_linker").value;
+	var revLinker = document.getElementById("tp_linker").value;
+
+	var numbers = "0123456789";
+
+	// If 5' linker is added, check fwd_length >= fwd_linker + 10
+	if (fwdLinker)
+	{
+		var minLength = fwdLinker.length + MIN_PRIMER_LENGTH;
+
+		// CHECK THE LENGTH IS AN INTEGER!!!!
+		if (fwdLength)
+		{
+			for (var x = 0; x < fwdLength.length; x++)
+			{
+				if (!inArray(fwdLength.charAt(x), numbers))
+				{
+					alert("Length of the 5' primer must be an integer value greater than 0.  Please verify your input.");
+
+					revLengthFormField.style.color = "000000";
+					revLengthFormField.style.fontWeight = "normal";
+
+					fwdLengthFormField.style.color = "FF0000";
+					fwdLengthFormField.style.fontWeight = "bold";
+
+					fwdLengthFormField.focus();
+
+					return false;
+				}
+			}
+
+			if (fwdLength < minLength)
+			{
+				alert("Invalid input: length of the 5' primer must be at least 10 bp greater than the size of the 5' linker");
+
+				revLengthFormField.style.color = "000000";
+				revLengthFormField.style.fontWeight = "normal";
+
+				fwdLengthFormField.style.color = "FF0000";
+				fwdLengthFormField.style.fontWeight = "bold";
+
+				fwdLengthFormField.focus();
+
+				return false;
+			}
+		}
+	}
+	else
+	{
+		// Linker is not added; in that case, just verify that length > 10
+		if (fwdLength)
+		{
+			// just check it's an integer first
+			for (var x = 0; x < fwdLength.length; x++)
+			{
+				if (!inArray(fwdLength.charAt(x), numbers))
+				{
+					alert("Length of the 5' primer must be an integer value greater than 0.  Please verify your input.");
+
+					revLengthFormField.style.color = "000000";
+					revLengthFormField.style.fontWeight = "normal";
+
+					fwdLengthFormField.style.color = "FF0000";
+					fwdLengthFormField.style.fontWeight = "bold";
+
+					fwdLengthFormField.focus();
+					return false;
+				}
+			}
+
+			if (fwdLength < MIN_PRIMER_LENGTH)
+			{
+				alert("Invalid input: length of the 5' primer must be at least 10 bp");
+
+				revLengthFormField.style.color = "000000";
+				revLengthFormField.style.fontWeight = "normal";
+
+				fwdLengthFormField.style.color = "FF0000";
+				fwdLengthFormField.style.fontWeight = "bold";
+
+				fwdLengthFormField.focus();
+
+				return false;
+			}
+		}
+	}
+
+	// Same for reverse length
+	if (revLinker)
+	{
+		var minLength = revLinker.length + MIN_PRIMER_LENGTH;
+
+		if (revLength)
+		{
+			// check it's an integer
+			for (var x = 0; x < revLength.length; x++)
+			{
+				if (!inArray(revLength.charAt(x), numbers))
+				{
+					alert("Length of the 3' primer must be an integer value greater than 0.  Please verify your input.");
+
+					fwdLengthFormField.style.color = "000000";
+					fwdLengthFormField.style.fontWeight = "normal";
+
+					revLengthFormField.style.color = "FF0000";
+					revLengthFormField.style.fontWeight = "bold";
+
+					revLengthFormField.focus();
+
+					return false;
+				}
+			}
+
+			if (revLength < minLength)
+			{
+				alert("Invalid input: length of the 3' primer must be at least 10 bp greater than the size of the 3' linker");
+
+				fwdLengthFormField.style.color = "000000";
+				fwdLengthFormField.style.fontWeight = "normal";
+
+				revLengthFormField.style.color = "FF0000";
+				revLengthFormField.style.fontWeight = "bold";
+
+				revLengthFormField.focus();
+
+				return false;
+			}
+		}
+	}
+	else
+	{
+		// Linker is not added; in that case, just verify that length > 10
+		if (revLength)
+		{
+			// check it's an integer
+			for (var x = 0; x < revLength.length; x++)
+			{
+				if (!inArray(revLength.charAt(x), numbers))
+				{
+					alert("Length of the 3' primer must be an integer value greater than 0.  Please verify your input.");
+
+					fwdLengthFormField.style.color = "000000";
+					fwdLengthFormField.style.fontWeight = "normal";
+
+					revLengthFormField.style.color = "FF0000";
+					revLengthFormField.style.fontWeight = "bold";
+
+
+					revLengthFormField.focus();
+
+					return false;
+				}
+			}
+
+			if (revLength < MIN_PRIMER_LENGTH)
+			{
+				alert("Invalid input: length of the 3' primer must be at least 10 bp");
+
+				fwdLengthFormField.style.color = "000000";
+				fwdLengthFormField.style.fontWeight = "normal";
+
+				revLengthFormField.style.color = "FF0000";
+				revLengthFormField.style.fontWeight = "bold";
+
+				revLengthFormField.focus();
+
+				return false;
+			}
+		}
+	}*/
+
+	// Now check Tm
+	// First, verify that the values are non-empty
+	if (fwdTm.length == 0)
+	{
+		alert("Please provide a 5' primer Tm value");
+
+		fwdTmFormField.style.color = "000000";
+		fwdTmFormField.style.fontWeight = "normal";
+		fwdTmFormField.focus();
+
+		return false;
+	}
+
+	if (revTm.length == 0)
+	{
+		alert("Please provide a 3' primer Tm value");
+
+		revTmFormField.style.color = "000000";
+		revTmFormField.style.fontWeight = "normal";	
+		revTmFormField.focus();
+
+		return false;
+	}		
+
+	// check valid integer input
+	for (i = 0; i < fwdTm.length; i++)
+	{   
+		var x = fwdTm.charAt(i);
+
+		if (x < "0" || x > "9")
+		{
+			alert("Tm for the 5' primer must be a non-negative integer; please verify your input");
+
+			fwdTmFormField.style.color = "FF0000";
+			fwdTmFormField.style.fontWeight = "bold";
+			fwdTmFormField.focus();
+
+			return false;
+		}
+	}
+
+	for (i = 0; i < revTm.length; i++)
+	{   
+		var x = revTm.charAt(i);
+
+		if (x < "0" || x > "9")
+		{
+			alert("Tm for the 3' primer must be a non-negative integer; please verify your input");
+
+			revTmFormField.style.color = "FF0000";
+			revTmFormField.style.fontWeight = "bold";					
+			revTmFormField.focus();
+
+			return false;
+		}
+	}
+
+	// and verify that Tm > 0
+	if (fwdTm <= 0)
+	{
+		alert("Tm for the 5' primer must be greater than 0 degrees Celsius");
+
+		if (fwdTm)
+		{
+			fwdTmFormField.style.color = "FF0000";
+			fwdTmFormField.style.fontWeight = "bold";
+		}
+		else
+		{
+			fwdTmFormField.style.color = "000000";
+			fwdTmFormField.style.fontWeight = "normal";
+		}
+
+		fwdTmFormField.focus();
+
+		return false;
+	}
+
+	if (revTm <= 0)
+	{
+		alert("Tm for the 3' primer must be greater than 0 degrees Celsius");
+
+		if (revTm)
+		{
+			revTmFormField.style.color = "FF0000";
+			revTmFormField.style.fontWeight = "bold";
+		}
+		else
+		{
+			revTmFormField.style.color = "000000";
+			revTmFormField.style.fontWeight = "normal";					
+		}
+
+		revTmFormField.focus();
+
+		return false;
+	}
+
+	return true;
+}
+
+function inArray(myChar, myArray)
+{
+	for (var i = 0; i < myArray.length; i++)
+	{
+		//alert(myArray[i]);
+		//alert(myChar == myArray[i]);
+
+		if (myChar == myArray[i])
+		return true;
+	}
+
+	return false;
+}
+
+function removeFormElements(aForm, elemList)
+{
+	var propsTbl = document.getElementById("modifyReagentPropsTbl");
+
+	for (i = 0; i < elemList.length; i++)
+	{
+// 		alert("Removing " + elemList[i].id);
+		aForm.removeChild(elemList[i]);
+	}
+
+// alert(propsTbl.rows.length);
+}
+
+// March 28/08: Identical to removeFormElements, except the parameters are not objects but IDs
+function deleteElements(formID, elemIDList)
+{
+	var aForm = document.getElementById(formID);
+// 	alert(aForm);
+
+	for (i = 0; i < elemIDList.length; i++)
+	{
+		tmpElID = elemIDList[i];
+// 		alert(tmpElID);
+		tmpElem = document.getElementById(tmpElID);
+// 		alert(tmpElem.value);
+
+		aForm.removeChild(tmpElem);
+	}
+}
+
+
+function popup(mylink, windowname, a_width, a_height, scrollbars)
+{
+	if (!window.focus)
+		return true;
+
+	var a_href;
+
+	if (typeof(mylink) == 'string')
+		a_href=mylink;
+	else
+		a_href=mylink.href;
+
+// 	alert(href);
+
+	window.open(a_href, windowname, "width=" + a_width + ", height=" + a_height + ", scrollbars=" + scrollbars);
+	return false;
+}
+
+function showPropertyValues(listID, tblID)
+{
+	var propNamesList = document.getElementById(listID);
+	var selectedInd = propNamesList.selectedIndex;
+	var propName = propNamesList[selectedInd].value;
+
+	var propList = document.getElementById("addlPropsListRow");
+	
+	// Modified March 3/08
+
+	if (!tblID)
+		tblID = "modifyReagentPropsTbl";
+
+// 	var propsTbl = document.getElementById("modifyReagentPropsTbl");
+	var propsTbl = document.getElementById(tblID);
+
+	var prefix = "reagent_detailedview_";
+	var postfix = "_prop";
+
+	// March 3/08: Since there could be multiple property values (e.g. tag type or expression system), instead of unhiding the corresponding row, append another row to the table and make it identical to the hidden row (so the hidden row serves as a template)
+
+//  	alert(propName);
+
+	switch (propName)
+	{
+		case 'tag':
+			var propRow = propsTbl.insertRow(propList.rowIndex - 1);
+		
+			// Need a few cells in the row
+			var propNameCell = propRow.insertCell(0);
+			var propValueCell = propRow.insertCell(1);
+
+			// Set cell content and formatting as required by template
+			propNameCell.className = "detailedView_colName";
+			propNameCell.innerHTML = "Tag";
+		
+			propValueCell.className = "detailedView_value";
+			propValueCell.colSpan = 5;
+			propValueCell.setAttribute("white-space", "nowrap");
+			propValueCell.style.fontSize = "9pt";
+
+			propValueCell.style.paddingLeft = "5px";
+
+			propValueCell.colSpan = 5;
+			
+			// Generate the list on the fly
+			var tmpTagTypeList = document.getElementById("tag_list");
+
+// removed March 20/08 - needed??
+// 			var tagTypeSelectedInd = tmpTagTypeList.selectedIndex;
+// 			var tagTypeSelectedValue = tmpTagTypeList[tagTypeSelectedInd].value;
+
+			var newTagTypeList = document.createElement("SELECT");
+			var newTagTypeTxt =  document.createElement("INPUT");
+
+			newTagTypeList.setAttribute('name', prefix + propName + postfix);
+			newTagTypeList.setAttribute('id', propName + "_proplist_" + propRow.rowIndex);
+
+			propRow.setAttribute('id', "tag_row_" + propRow.rowIndex + "_id");
+
+			newTagTypeTxt.type = "TEXT";
+			newTagTypeTxt.id = "tag_txt_" + (propList.rowIndex - 1);
+			newTagTypeTxt.style.display = "none";
+
+			for (i = 0; i < tmpTagTypeList.options.length; i++)
+			{
+				tmpOptn = tmpTagTypeList.options[i];
+				newOptn = document.createElement("OPTION");
+
+				newOptn.value = tmpOptn.value;
+				newOptn.name = tmpOptn.name;
+				newOptn.text = tmpOptn.text;
+
+				if (newTagTypeList.options.length == 0)
+					newTagTypeList.options.add(newOptn);
+				else
+					addElement(newTagTypeList, newTagTypeList.options.length, newOptn);
+			}
+
+// 			newTagTypeList.onchange = function() {showTagTypeBox(newTagTypeList.id, newTagTypeTxt.id);}
+// {showTagTypeBox(newTagTypeList.id, newTagTypeTxt.id)};
+
+			propValueCell.appendChild(newTagTypeList);
+			propValueCell.appendChild(newTagTypeTxt);
+
+			// Adjust border height to stretch to bottom of page
+// 			mainBorder = document.getElementById("mainBorder");
+// 			mainBorder.height = document.height;
+// 			mainBorder.rowSpan = propsTbl.rows.length;
+		
+			// For each tag type, show tag position
+			// Modified March 17/08: Instead of showing a hidden row, create a new element and append to form (as done for all other elements; won't save otherwise)
+			var newTagPosRow = propsTbl.insertRow(propRow.rowIndex+1);
+
+			newTagPosRow.setAttribute('id', "tag_position_row_" + propRow.rowIndex + "_id");
+
+			// Need a few cells in the row
+			var newTagPosNameCell = newTagPosRow.insertCell(0);
+			var newTagPosValueCell = newTagPosRow.insertCell(1);
+
+			newTagPosValueCell.className = "detailedView_value";
+			newTagPosValueCell.colSpan = 5;
+
+			newTagPosValueCell.style.paddingLeft = "5px";
+
+			newTagPosNameCell.className = "detailedView_colName";
+			newTagPosNameCell.innerHTML = "Tag Position";
+
+			// March 17/08: Generate Tag Position option list
+			var oldTagPosList = document.getElementById("tag_position_list");
+			var newTagPosList = document.createElement("SELECT");
+
+			newTagPosList.setAttribute('id', "tag_position_proplist_" + propRow.rowIndex);
+
+			for (i = 0; i < oldTagPosList.options.length; i++)
+			{
+				tmpOptn = oldTagPosList.options[i];
+				newOptn = document.createElement("OPTION");
+
+				newOptn.value = tmpOptn.value;
+				newOptn.name = tmpOptn.name;
+				newOptn.text = tmpOptn.text;
+
+				if (newTagPosList.options.length == 0)
+					newTagPosList.options.add(newOptn);
+				else
+					addElement(newTagPosList, newTagPosList.options.length, newOptn);
+			}
+
+			newTagPosValueCell.setAttribute("font-size", "9pt");
+			newTagPosValueCell.setAttribute("white-space", "nowrap");
+			newTagPosValueCell.colSpan = 5;
+
+			newTagPosValueCell.appendChild(newTagPosList);
+
+			// April 2/08: Karen asked to show positions and orientation on a new line for ALL features
+			var tmpTagPosRow = propsTbl.insertRow(newTagPosRow.rowIndex+1);
+			tmpTagPosRow.setAttribute('id', "tag_pos_row" + tmpTagPosRow.rowIndex + "_id");
+			var tmpTagPosRowID = tmpTagPosRow.id;
+
+			var c1 = tmpTagPosRow.insertCell(0);
+			var tagPosCell = tmpTagPosRow.insertCell(1);
+
+			tagPosCell.className = "detailedView_value";
+			tagPosCell.style.paddingLeft = "5px";
+			tagPosCell.setAttribute("white-space", "nowrap");
+			tagPosCell.colSpan = 5;
+
+			tagPosCell.innerHTML = "Start: ";
+
+			var newTagTypeStart = document.createElement("INPUT");
+			newTagTypeStart.setAttribute("type", 'TEXT');
+			newTagTypeStart.setAttribute("size", 5);
+			newTagTypeStart.setAttribute("id", propName + "_" + propRow.rowIndex + "_startpos_id");
+
+			tagPosCell.appendChild(newTagTypeStart);
+
+			tagPosCell.innerHTML += "  End: ";
+			
+			var newTagTypeEnd = document.createElement("INPUT");
+			newTagTypeEnd.setAttribute("type", 'TEXT');
+			newTagTypeEnd.setAttribute("size", 5);
+			newTagTypeEnd.setAttribute("id", propName + "_" + propRow.rowIndex + "_endpos_id");
+
+			tagPosCell.appendChild(newTagTypeEnd);
+
+			// Orientation
+			tagPosCell.innerHTML += "<SPAN style=\"margin-left:10px;\"></span>";
+
+			var fwdDir = document.createElement("INPUT");
+			fwdDir.setAttribute("type", "radio");
+			fwdDir.setAttribute("id", propName + "_" + propRow.rowIndex + "_fwd_dir");
+			fwdDir.setAttribute("name", propName + "_orientation_radio_" + propRow.rowIndex);
+			fwdDir.setAttribute("checked", true);
+
+			tagPosCell.appendChild(fwdDir);
+			tagPosCell.innerHTML += "Forward ";
+ 
+			var revDir = document.createElement("INPUT");
+			revDir.setAttribute("type", "radio");
+			revDir.setAttribute("id", propName + "_" + propRow.rowIndex + "_rev_dir");
+			revDir.setAttribute("name", propName + "_orientation_radio_" + propRow.rowIndex);
+
+			tagPosCell.appendChild(revDir);
+			tagPosCell.innerHTML += "Reverse";
+
+			// Add 'Remove' link
+			var removeLink = document.createElement("SPAN");
+			removeLink.className = "linkShow";
+			removeLink.style.fontSize = "9pt";
+			removeLink.style.fontWeight = "normal";
+			removeLink.style.marginLeft = "10px";
+			removeLink.innerHTML = "Remove";
+
+			tagPosCell.appendChild(removeLink);
+
+			// Add a separator row
+			var divRow = propsTbl.insertRow(tmpTagPosRow.rowIndex + 1);
+			var divCell = divRow.insertCell(0);
+
+			divRow.setAttribute('id', "div_row" + divRow.rowIndex + "_id");
+			divCell.colSpan = 6;
+			divCell.innerHTML = "<HR>";
+
+			// Gather the IDs of all elements in the row to pass to 'deleteRow' function
+// 			var tblID = "modifyReagentPropsTbl";
+			var tagTypeRowID = propRow.id;
+			var tagPosRowID = newTagPosRow.id;
+			var divRowID = divRow.id;
+		
+			// Add list to form
+			var myForm = document.reagentDetailForm;
+
+			var hiddenTagType = document.createElement("INPUT");
+			hiddenTagType.setAttribute("type", "hidden");
+			hiddenTagType.setAttribute("id", "tag_type_prop" + propRow.rowIndex);
+			myForm.appendChild(hiddenTagType);
+
+			var hiddenTagTypeStart = document.createElement("INPUT");
+			hiddenTagTypeStart.setAttribute("type", "hidden");
+			hiddenTagTypeStart.setAttribute("id", "tag_startpos_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenTagTypeStart);
+
+			var hiddenTagTypeEnd = document.createElement("INPUT");
+			hiddenTagTypeEnd.setAttribute("type", "hidden");
+			hiddenTagTypeEnd.setAttribute("id", "tag_endpos_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenTagTypeEnd);
+
+			// Tag position
+			var hiddenTagPosField = document.createElement("INPUT");
+			hiddenTagPosField.setAttribute('type', 'hidden');
+			hiddenTagPosField.setAttribute("id", "tag_position_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenTagPosField);
+
+			// Orientation
+			var hiddenTagTypeDir = document.createElement("INPUT");
+			hiddenTagTypeDir.setAttribute('type', 'hidden');
+			hiddenTagTypeDir.setAttribute("id", "tag_orientation_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenTagTypeDir);
+
+			var elemList = new Array();
+			elemList.push(hiddenTagType);
+			elemList.push(hiddenTagTypeStart);
+			elemList.push(hiddenTagTypeEnd);
+			elemList.push(hiddenTagTypeDir);
+
+			removeLink.onclick = function(){deleteTableRow(tblID, tagTypeRowID); deleteTableRow(tblID, tagPosRowID); deleteTableRow(tblID, tmpTagPosRowID); deleteTableRow(tblID, divRowID); removeFormElements(myForm, elemList)};
+		break;
+
+		case 'promoter':
+			var propRow = propsTbl.insertRow(propList.rowIndex - 1);
+		
+			// Need a few cells in the row
+			var propNameCell = propRow.insertCell(0);
+			var propValueCell = propRow.insertCell(1);
+
+			// Set cell content and formatting as required by template
+			propNameCell.className = "detailedView_colName";
+			propNameCell.innerHTML = "Promoter";
+		
+			propValueCell.className = "detailedView_value";
+			propValueCell.setAttribute("white-space", "nowrap");
+			propValueCell.style.fontSize = "9pt";
+// 			propValueCell.style.fontWeight = "normal";
+			propValueCell.colSpan = 5;
+			
+			propValueCell.style.paddingLeft = "5px";
+
+			// Generate the list on the fly
+			var tmpPromoterList = document.getElementById("promoter_list");
+			var newPromoterList = document.createElement("SELECT");
+			var newPromoterTxt =  document.createElement("INPUT");
+
+			newPromoterList.setAttribute('id', propName + "_proplist_" + propRow.rowIndex);
+// 			newPromoterList.setAttribute('name', "reagent_detailedview_" + propName + "_prop");
+
+			propRow.setAttribute('id', "promoter_row_" + propRow.rowIndex + "_id");
+
+			newPromoterTxt.type = "TEXT";
+			newPromoterTxt.id = "promo_txt_" + (propList.rowIndex - 1);
+			newPromoterTxt.style.display = "none";
+
+			for (i = 0; i < tmpPromoterList.options.length; i++)
+			{
+				tmpOptn = tmpPromoterList.options[i];
+				newOptn = document.createElement("OPTION");
+
+				newOptn.value = tmpOptn.value;
+				newOptn.name = tmpOptn.name;
+				newOptn.text = tmpOptn.text;
+
+				if (newPromoterList.options.length == 0)
+					newPromoterList.options.add(newOptn);
+				else
+					addElement(newPromoterList, newPromoterList.options.length, newOptn);
+			}
+
+			propValueCell.appendChild(newPromoterList);
+			propValueCell.appendChild(newPromoterTxt);
+
+			// Adjust border height to stretch to bottom of page
+// 			mainBorder = document.getElementById("mainBorder");
+// 			mainBorder.height = document.height;
+// 			mainBorder.rowSpan = propsTbl.rows.length;
+		
+			// Show expression system too
+			var newExpSysRow = propsTbl.insertRow(propRow.rowIndex+1);
+
+			newExpSysRow.setAttribute('id', "expression_system_row_" + propRow.rowIndex + "_id");
+
+			// Need a few cells in the row
+			var newExpSysNameCell = newExpSysRow.insertCell(0);
+			var newExpSysValueCell = newExpSysRow.insertCell(1);
+
+			newExpSysNameCell.className = "detailedView_colName";
+			newExpSysValueCell.style.paddingLeft = "5px";
+			
+			var oldExpSystList = document.getElementById("expression_system_list");
+			var newExpSystList = document.createElement("SELECT");
+
+			newExpSystList.setAttribute('id', "expression_system_prop_list_" + propRow.rowIndex);
+
+			for (i = 0; i < oldExpSystList.options.length; i++)
+			{
+				tmpOptn = oldExpSystList.options[i];
+				newOptn = document.createElement("OPTION");
+
+				newOptn.value = tmpOptn.value;
+				newOptn.name = tmpOptn.name;
+				newOptn.text = tmpOptn.text;
+
+				if (newExpSystList.options.length == 0)
+					newExpSystList.options.add(newOptn);
+				else
+					addElement(newExpSystList, newExpSystList.options.length, newOptn);
+			}
+
+			newExpSysNameCell.innerHTML = "Expression System";
+
+			newExpSysValueCell.setAttribute("font-size", "9pt");
+			newExpSysValueCell.setAttribute("font-weight", "normal");
+			newExpSysValueCell.setAttribute("white-space", "nowrap");
+			newExpSysValueCell.colSpan = 5;
+
+			newExpSysValueCell.appendChild(newExpSystList);
+
+			// April 2/08: Karen asked to show positions and orientation on a new line for ALL features
+			var tmpPromPosRow = propsTbl.insertRow(newExpSysRow.rowIndex+1);
+			tmpPromPosRow.setAttribute('id', "promoter_pos_row" + tmpPromPosRow.rowIndex + "_id");
+			var tmpPromPosRowID = tmpPromPosRow.id;
+
+			var c1 = tmpPromPosRow.insertCell(0);
+			var promPosCell = tmpPromPosRow.insertCell(1);
+
+			promPosCell.className = "detailedView_value";
+			promPosCell.style.paddingLeft = "5px";
+			promPosCell.setAttribute("white-space", "nowrap");
+			promPosCell.colSpan = 5;
+
+			promPosCell.innerHTML = "Start: ";
+
+// 			propValueCell.innerHTML += "<SPAN style=\"margin-left:32px;\"></span>Start: ";
+
+			var newPromStart = document.createElement("INPUT");
+			newPromStart.setAttribute("type", 'TEXT');
+			newPromStart.setAttribute("size", 5);
+			newPromStart.setAttribute("id", propName + "_" + propRow.rowIndex + "_startpos_id");
+
+			promPosCell.appendChild(newPromStart);
+
+			promPosCell.innerHTML += "  End: ";
+			
+			var newPromEnd = document.createElement("INPUT");
+			newPromEnd.setAttribute("type", 'TEXT');
+			newPromEnd.setAttribute("size", 5);
+			newPromEnd.setAttribute("id", propName + "_" + propRow.rowIndex + "_endpos_id");
+
+			promPosCell.appendChild(newPromEnd);
+
+			newPromoterList.onchange = function()
+			{
+// 				showPromoterBox(newPromoterList.id, newPromoterTxt.id);
+			};
+
+			// Orientation - March 14/08: Make 'forward' checked by default
+			promPosCell.innerHTML += "<SPAN style=\"margin-left:10px;\"></span>";
+
+			var fwdDir = document.createElement("INPUT");
+			fwdDir.setAttribute("type", "radio");
+			fwdDir.setAttribute("id", propName + "_" + propRow.rowIndex + "_fwd_dir");
+			fwdDir.setAttribute("name", propName + "_orientation_radio_" + propRow.rowIndex);
+			fwdDir.setAttribute("checked", true);
+
+			promPosCell.appendChild(fwdDir);
+			promPosCell.innerHTML += "Forward ";
+ 
+			var revDir = document.createElement("INPUT");
+			revDir.setAttribute("type", "radio");
+			revDir.setAttribute("id", propName + "_" + propRow.rowIndex + "_rev_dir");
+			revDir.setAttribute("name", propName + "_orientation_radio_" + propRow.rowIndex);
+
+			promPosCell.appendChild(revDir);
+			promPosCell.innerHTML += "Reverse";
+
+			// Add 'Remove' link
+			var removeLink = document.createElement("SPAN");
+			removeLink.className = "linkShow";
+			removeLink.style.fontSize = "9pt";
+			removeLink.style.fontWeight = "normal";
+			removeLink.style.marginLeft = "10px";
+			removeLink.innerHTML = "Remove";
+		
+			promPosCell.appendChild(removeLink);
+
+			// Add a separator row
+			var divRow = propsTbl.insertRow(tmpPromPosRow.rowIndex + 1);
+			var divCell = divRow.insertCell(0);
+
+			divRow.setAttribute('id', "div_row" + divRow.rowIndex + "_id");
+			divCell.colSpan = 6;
+			divCell.innerHTML = "<HR>";
+
+			// Gather the IDs of all elements in the row to pass to 'deleteRow' function
+// 			var tblID = "modifyReagentPropsTbl";
+			var promRowID = propRow.id;
+			var expRowID = newExpSysRow.id;
+			var divRowID = divRow.id;
+		
+			// Add list to form
+			var myForm = document.reagentDetailForm;
+
+			var hiddenPromoter = document.createElement("INPUT");
+			hiddenPromoter.setAttribute("type", "hidden");
+			myForm.appendChild(hiddenPromoter);
+
+			var hiddenPromStart = document.createElement("INPUT");
+			hiddenPromStart.setAttribute("type", "hidden");
+			hiddenPromStart.setAttribute("id", "promoter_startpos_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenPromStart);
+
+			var hiddenPromEnd = document.createElement("INPUT");
+			hiddenPromEnd.setAttribute("type", "hidden");
+			hiddenPromEnd.setAttribute("id", "promoter_endpos_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenPromEnd);
+
+			var hiddenExprSyst = document.createElement("INPUT");
+			hiddenExprSyst.setAttribute("type", "hidden");
+			hiddenExprSyst.setAttribute("id", "expression_system_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenExprSyst);
+
+			// Orientation
+			var hiddenPromoDir = document.createElement("INPUT");
+			hiddenPromoDir.setAttribute('type', 'hidden');
+			hiddenPromoDir.setAttribute("id", "promoter_orientation_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenPromoDir);
+
+			var elemList = new Array();
+			elemList.push(hiddenPromoter);
+			elemList.push(hiddenPromStart);
+			elemList.push(hiddenPromEnd);
+			elemList.push(hiddenExprSyst);
+			elemList.push(hiddenPromoDir);
+
+			removeLink.onclick = function(){deleteTableRow(tblID, promRowID); deleteTableRow(tblID, expRowID); deleteTableRow(tblID, tmpPromPosRowID); deleteTableRow(tblID, divRowID); removeFormElements(myForm, elemList)};
+		break;
+ 
+		case 'selectable_marker':
+			var propRow = propsTbl.insertRow(propList.rowIndex - 1);
+		
+			// Need a few cells in the row
+			var propNameCell = propRow.insertCell(0);
+			var propValueCell = propRow.insertCell(1);
+
+			// Set cell content and formatting as required by template
+			propNameCell.className = "detailedView_colName";
+			propNameCell.innerHTML = "Selectable Marker";
+		
+			propValueCell.className = "detailedView_value";
+			propValueCell.setAttribute("white-space", "nowrap");
+			propValueCell.style.fontSize = "9pt";
+			propValueCell.colSpan = 5;
+
+			propValueCell.style.paddingLeft = "5px";
+
+			// Generate the list on the fly
+			var tmpMarkerList = document.getElementById("selectable_marker_list");
+			var markerSelectedInd = tmpMarkerList.selectedIndex;
+			var markerSelectedValue = tmpMarkerList[markerSelectedInd].value;
+
+			var newMarkerList = document.createElement("SELECT");
+			var newMarkerTxt =  document.createElement("INPUT");
+
+			newMarkerList.setAttribute("name", prefix + propName + postfix);
+			newMarkerList.setAttribute("id", propName + "_proplist_" + propRow.rowIndex);
+
+			propRow.setAttribute('id', "selectabler_marker_row_" + propRow.rowIndex + "_id");
+
+			newMarkerTxt.type = "TEXT";
+			newMarkerTxt.id = "selectable_marker_txt_" + (propList.rowIndex - 1);
+			newMarkerTxt.style.display = "none";
+
+			for (i = 0; i < tmpMarkerList.options.length; i++)
+			{
+				tmpOptn = tmpMarkerList.options[i];
+				newOptn = document.createElement("OPTION");
+
+				newOptn.value = tmpOptn.value;
+				newOptn.name = tmpOptn.name;
+				newOptn.text = tmpOptn.text;
+
+				if (newMarkerList.options.length == 0)
+					newMarkerList.options.add(newOptn);
+				else
+					addElement(newMarkerList, newMarkerList.options.length, newOptn);
+			}
+
+			propValueCell.appendChild(newMarkerList);
+			propValueCell.appendChild(newMarkerTxt);
+
+			// Start & stop positions
+			// April 1, 2008: Show in a new row
+			var smPosRow = propsTbl.insertRow(propRow.rowIndex+1);
+			smPosRow.setAttribute('id', "sm_pos_row" + smPosRow.rowIndex + "_id");
+			var smPosRowID = smPosRow.id;
+
+			var c1 = smPosRow.insertCell(0);
+			var smPosCell = smPosRow.insertCell(1);
+
+			smPosCell.style.paddingLeft = "5px";
+
+			smPosCell.innerHTML = "Start: ";
+			smPosCell.className = "detailedView_value";
+			
+			var newMarkerStart = document.createElement("INPUT");
+			newMarkerStart.setAttribute("type", 'TEXT');
+			newMarkerStart.setAttribute("size", 5);
+			newMarkerStart.setAttribute("id", propName + "_" + propRow.rowIndex + "_startpos_id");
+
+			smPosCell.appendChild(newMarkerStart);
+			smPosCell.innerHTML += "  End: ";
+			
+			var newMarkerEnd = document.createElement("INPUT");
+			newMarkerEnd.setAttribute("type", 'TEXT');
+			newMarkerEnd.setAttribute("size", 5);
+			newMarkerEnd.setAttribute("id", propName + "_" + propRow.rowIndex + "_endpos_id");
+
+			smPosCell.appendChild(newMarkerEnd);
+			smPosCell.colSpan=5;
+			smPosCell.setAttribute("white-space", "nowrap");
+
+			newMarkerList.onchange = function()
+			{
+// 				showTagTypeBox(newTagTypeList.id, newTagTypeTxt.id);
+			};
+
+			// Orientation - March 14/08: Make 'forward' checked by default
+			smPosCell.innerHTML += "<SPAN style=\"margin-left:10px;\"></span>";
+
+			var fwdDir = document.createElement("INPUT");
+			fwdDir.setAttribute("type", "radio");
+			fwdDir.setAttribute("id", propName + "_" + propRow.rowIndex + "_fwd_dir");
+			fwdDir.setAttribute("name", propName + "_orientation_radio_" + propRow.rowIndex);
+			fwdDir.setAttribute("checked", true);
+
+			smPosCell.appendChild(fwdDir);
+			smPosCell.innerHTML += "Forward ";
+ 
+			var revDir = document.createElement("INPUT");
+			revDir.setAttribute("type", "radio");
+			revDir.setAttribute("id", propName + "_" + propRow.rowIndex + "_rev_dir");
+			revDir.setAttribute("name", propName + "_orientation_radio_" + propRow.rowIndex);
+			smPosCell.appendChild(revDir);
+			smPosCell.innerHTML += "Reverse";
+
+			// Add 'Remove' link
+			var removeLink = document.createElement("SPAN");
+			removeLink.className = "linkShow";
+			removeLink.style.fontSize = "9pt";
+			removeLink.style.fontWeight = "normal";
+			removeLink.style.marginLeft = "10px";
+			removeLink.innerHTML = "Remove";
+		
+			smPosCell.appendChild(removeLink);
+
+			// Adjust border height to stretch to bottom of page
+// 			mainBorder = document.getElementById("mainBorder");
+// 			mainBorder.height = document.height;
+// 			mainBorder.rowSpan = propsTbl.rows.length;
+		
+			// Add a separator row
+			var divRow = propsTbl.insertRow(smPosRow.rowIndex + 1);
+			var divCell = divRow.insertCell(0);
+
+			divRow.setAttribute('id', "div_row" + divRow.rowIndex + "_id");
+			divCell.colSpan = 6;
+			divCell.innerHTML = "<HR>";
+
+			// 'Remove' link
+// 			var tblID = "modifyReagentPropsTbl";
+			var markerRowID = propRow.id;
+			var divRowID = divRow.id;
+		
+			// Add list to form
+			var myForm = document.reagentDetailForm;
+
+			var hiddenMarker = document.createElement("INPUT");
+			hiddenMarker.setAttribute("type", "hidden");
+// 			hiddenMarker.setAttribute("name", newMarkerList.name);
+			myForm.appendChild(hiddenMarker);
+
+			var hiddenMarkerStart = document.createElement("INPUT");
+			hiddenMarkerStart.setAttribute("type", "hidden");
+			hiddenMarkerStart.setAttribute("id", "selectable_marker_startpos_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenMarkerStart);
+
+			var hiddenMarkerEnd = document.createElement("INPUT");
+			hiddenMarkerEnd.setAttribute("type", "hidden");
+			hiddenMarkerEnd.setAttribute("id", "selectable_marker_endpos_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenMarkerEnd);
+
+			// Orientation
+			var hiddenMarkerDir = document.createElement("INPUT");
+			hiddenMarkerDir.setAttribute('type', 'hidden');
+			hiddenMarkerDir.setAttribute("id", "selectable_marker_orientation_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenMarkerDir);
+
+			var elemList = new Array();
+			elemList.push(hiddenMarker);
+			elemList.push(hiddenMarkerStart);
+			elemList.push(hiddenMarkerEnd);
+			elemList.push(hiddenMarkerDir);
+
+			removeLink.onclick = function(){deleteTableRow(tblID, markerRowID); deleteTableRow(tblID, smPosRowID); deleteTableRow(tblID, divRowID); removeFormElements(myForm, elemList)};
+		break;
+
+		case 'polya':
+		case 'polyA':
+			propName = "polyA";
+			var propRow = propsTbl.insertRow(propList.rowIndex - 1);
+		
+			// Need a few cells in the row
+			var propNameCell = propRow.insertCell(0);
+			var propValueCell = propRow.insertCell(1);
+
+			// Set cell content and formatting as required by template
+			propNameCell.className = "detailedView_colName";
+			propNameCell.innerHTML = "PolyA Tail";
+		
+			propValueCell.className = "detailedView_value";
+			propValueCell.setAttribute("white-space", "nowrap");
+			propValueCell.style.fontSize = "9pt";
+			propValueCell.colSpan = 5;
+			propValueCell.style.paddingLeft = "5px";
+			
+			// Generate the list on the fly
+			var tmpPolyAList = document.getElementById("polyA_list");
+			var polyASelectedInd = tmpPolyAList.selectedIndex;
+			var polyASelectedValue = tmpPolyAList[polyASelectedInd].value;
+
+			var newPolyAList = document.createElement("SELECT");
+			var newPolyATxt =  document.createElement("INPUT");
+
+			newPolyAList.setAttribute("name", prefix + propName + postfix);
+			newPolyAList.setAttribute("id", propName + "_proplist_" + propRow.rowIndex);
+
+			propRow.setAttribute('id', "polyA_row_" + propRow.rowIndex + "_id");
+
+			newPolyATxt.type = "TEXT";
+			newPolyATxt.id = "polyA_txt_" + (propList.rowIndex - 1);
+			newPolyATxt.style.display = "none";
+
+			for (i = 0; i < tmpPolyAList.options.length; i++)
+			{
+				tmpOptn = tmpPolyAList.options[i];
+				newOptn = document.createElement("OPTION");
+
+				newOptn.value = tmpOptn.value;
+				newOptn.name = tmpOptn.name;
+				newOptn.text = tmpOptn.text;
+
+				if (newPolyAList.options.length == 0)
+					newPolyAList.options.add(newOptn);
+				else
+					addElement(newPolyAList, newPolyAList.options.length, newOptn);
+			}
+
+			propValueCell.appendChild(newPolyAList);
+			propValueCell.appendChild(newPolyATxt);
+
+			// Start & stop positions
+			// April 2/08: Karen asked to show positions and orientation on a new line for ALL features
+			var tmpPolyPosRow = propsTbl.insertRow(propRow.rowIndex+1);
+			tmpPolyPosRow.setAttribute('id', "polyA_pos_row" + tmpPolyPosRow.rowIndex + "_id");
+			var tmpPolyPosRowID = tmpPolyPosRow.id;
+
+			var c1 = tmpPolyPosRow.insertCell(0);
+			var polyPosCell = tmpPolyPosRow.insertCell(1);
+
+			polyPosCell.className = "detailedView_value";
+			polyPosCell.style.paddingLeft = "5px";
+			polyPosCell.colSpan=5;
+			polyPosCell.setAttribute("white-space", "nowrap");
+
+			polyPosCell.innerHTML += "Start: ";
+			
+			var newPolyAStart = document.createElement("INPUT");
+			newPolyAStart.setAttribute("type", 'TEXT');
+			newPolyAStart.setAttribute("size", 5);
+			newPolyAStart.setAttribute("id", propName + "_" + propRow.rowIndex + "_startpos_id");
+
+			polyPosCell.appendChild(newPolyAStart);
+
+			polyPosCell.innerHTML += "  End: ";
+			
+			var newPolyAEnd = document.createElement("INPUT");
+			newPolyAEnd.setAttribute("type", 'TEXT');
+			newPolyAEnd.setAttribute("size", 5);
+			newPolyAEnd.setAttribute("id", propName + "_" + propRow.rowIndex + "_endpos_id");
+
+			polyPosCell.appendChild(newPolyAEnd);
+
+			newPolyAList.onchange = function()
+			{
+// 				showTagTypeBox(newTagTypeList.id, newTagTypeTxt.id);
+			};
+
+			// Orientation - March 14/08: Make 'forward' checked by default
+			polyPosCell.innerHTML += "<SPAN style=\"margin-left:10px;\"></span>";
+
+			var fwdDir = document.createElement("INPUT");
+			fwdDir.setAttribute("type", "radio");
+			fwdDir.setAttribute("id", propName + "_" + propRow.rowIndex + "_fwd_dir");
+			fwdDir.setAttribute("name", propName + "_orientation_radio_" + propRow.rowIndex);
+			fwdDir.setAttribute("checked", true);
+
+			polyPosCell.appendChild(fwdDir);
+			polyPosCell.innerHTML += "Forward ";
+ 
+			var revDir = document.createElement("INPUT");
+			revDir.setAttribute("type", "radio");
+			revDir.setAttribute("id", propName + "_" + propRow.rowIndex + "_rev_dir");
+			revDir.setAttribute("name", propName + "_orientation_radio_" + propRow.rowIndex);
+
+			polyPosCell.appendChild(revDir);
+			polyPosCell.innerHTML += "Reverse";
+
+			// Add 'Remove' link
+			var removeLink = document.createElement("SPAN");
+			removeLink.className = "linkShow";
+			removeLink.style.fontSize = "9pt";
+			removeLink.style.fontWeight = "normal";
+			removeLink.style.marginLeft = "10px";
+			removeLink.innerHTML = "Remove";
+		
+			polyPosCell.appendChild(removeLink);
+
+			// Adjust border height to stretch to bottom of page
+// 			mainBorder = document.getElementById("mainBorder");
+// 			mainBorder.height = document.height;
+// 			mainBorder.rowSpan = propsTbl.rows.length;
+		
+			// Add a separator row
+			var divRow = propsTbl.insertRow(tmpPolyPosRow.rowIndex + 1);
+			var divCell = divRow.insertCell(0);
+
+			divRow.setAttribute('id', "div_row" + divRow.rowIndex + "_id");
+			divCell.colSpan = 6;
+			divCell.innerHTML = "<HR>";
+
+			// Gather the IDs of all elements in the row to pass to 'deleteRow' function
+// 			var tblID = "modifyReagentPropsTbl";
+			var polyARowID = propRow.id;
+			var divRowID = divRow.id;
+		
+			// Add list to form
+			var myForm = document.reagentDetailForm;
+
+			var hiddenPolyA = document.createElement("INPUT");
+			hiddenPolyA.setAttribute("type", "hidden");
+			myForm.appendChild(hiddenPolyA);
+
+			var hiddenPolyAStart = document.createElement("INPUT");
+			hiddenPolyAStart.setAttribute("type", "hidden");
+			hiddenPolyAStart.setAttribute("id", "polyA_startpos_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenPolyAStart);
+
+			var hiddenPolyAEnd = document.createElement("INPUT");
+			hiddenPolyAEnd.setAttribute("type", "hidden");
+			hiddenPolyAEnd.setAttribute("id", "polyA_endpos_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenPolyAEnd);
+
+			// Orientation
+			var hiddenPolyADir = document.createElement("INPUT");
+			hiddenPolyADir.setAttribute('type', 'hidden');
+			hiddenPolyADir.setAttribute("id", "polyA_orientation_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenPolyADir);
+
+			var elemList = new Array();
+			elemList.push(hiddenPolyA);
+			elemList.push(hiddenPolyAStart);
+			elemList.push(hiddenPolyAEnd);
+			elemList.push(hiddenPolyADir);
+
+			removeLink.onclick = function(){deleteTableRow(tblID, polyARowID); deleteTableRow(tblID, tmpPolyPosRowID); deleteTableRow(tblID, divRowID); removeFormElements(myForm, elemList)};
+		break;
+	
+		case 'origin_of_replication':
+			var propRow = propsTbl.insertRow(propList.rowIndex - 1);
+		
+			// Need a few cells in the row
+			var propNameCell = propRow.insertCell(0);
+			var propValueCell = propRow.insertCell(1);
+
+			// Set cell content and formatting as required by template
+			propNameCell.className = "detailedView_colName";
+			propNameCell.innerHTML = "Origin of Replication";
+		
+			propValueCell.className = "detailedView_value";
+			propValueCell.setAttribute("white-space", "nowrap");
+			propValueCell.style.fontSize = "9pt";
+			propValueCell.colSpan = 5;
+			propValueCell.style.paddingLeft = "5px";
+			
+			// Generate the list on the fly
+			var tmpOriginList = document.getElementById("origin_of_replication_list");
+			var originSelectedInd = tmpOriginList.selectedIndex;
+			var originSelectedValue = tmpOriginList[originSelectedInd].value;
+
+			var newOriginList = document.createElement("SELECT");
+			var newOriginTxt =  document.createElement("INPUT");
+
+// 			newOriginList.setAttribute("name", prefix + propName + postfix);
+			newOriginList.setAttribute("id", propName + "_proplist_" + propRow.rowIndex);
+
+			propRow.setAttribute('id', "origin_of_replication_row_" + propRow.rowIndex + "_id");
+
+			newOriginTxt.type = "TEXT";
+			newOriginTxt.id = "origin_of_replication_txt_" + (propList.rowIndex - 1);
+			newOriginTxt.style.display = "none";
+
+			for (i = 0; i < tmpOriginList.options.length; i++)
+			{
+				tmpOptn = tmpOriginList.options[i];
+				newOptn = document.createElement("OPTION");
+
+				newOptn.value = tmpOptn.value;
+				newOptn.name = tmpOptn.name;
+				newOptn.text = tmpOptn.text;
+
+				if (newOriginList.options.length == 0)
+					newOriginList.options.add(newOptn);
+				else
+					addElement(newOriginList, newOriginList.options.length, newOptn);
+			}
+
+			propValueCell.appendChild(newOriginList);
+			propValueCell.appendChild(newOriginTxt);
+
+			// Start & stop positions
+			// April 2/08: Karen asked to show positions and orientation on a new line for ALL features
+			var tmpOriginPosRow = propsTbl.insertRow(propRow.rowIndex+1);
+			tmpOriginPosRow.setAttribute('id', "origin_of_replication_pos_row" + tmpOriginPosRow.rowIndex + "_id");
+			var tmpOriginPosRowID = tmpOriginPosRow.id;
+
+			var c1 = tmpOriginPosRow.insertCell(0);
+			var originPosCell = tmpOriginPosRow.insertCell(1);
+
+			originPosCell.className = "detailedView_value";
+			originPosCell.style.paddingLeft = "5px";
+			originPosCell.setAttribute("white-space", "nowrap");
+			originPosCell.colSpan = 5;
+
+			originPosCell.innerHTML += "Start: ";
+
+// 			propValueCell.innerHTML += "<SPAN style=\"margin-left:8px;\"></span>Start: ";
+			
+			var newOriginStart = document.createElement("INPUT");
+			newOriginStart.setAttribute("type", 'TEXT');
+			newOriginStart.setAttribute("size", 5);
+			newOriginStart.setAttribute("id", propName + "_" + propRow.rowIndex + "_startpos_id");
+
+			originPosCell.appendChild(newOriginStart);
+
+			originPosCell.innerHTML += "  End: ";
+			
+			var newOriginEnd = document.createElement("INPUT");
+			newOriginEnd.setAttribute("type", 'TEXT');
+			newOriginEnd.setAttribute("size", 5);
+			newOriginEnd.setAttribute("id", propName + "_" + propRow.rowIndex + "_endpos_id");
+
+			originPosCell.appendChild(newOriginEnd);
+
+			newOriginList.onchange = function()
+			{
+// 				showTagTypeBox(newTagTypeList.id, newTagTypeTxt.id);
+			};
+
+			// Orientation - March 14/08: Make 'forward' checked by default
+			originPosCell.innerHTML += "<SPAN style=\"margin-left:10px;\"></span>";
+
+			var fwdDir = document.createElement("INPUT");
+			fwdDir.setAttribute("type", "radio");
+			fwdDir.setAttribute("id", propName + "_" + propRow.rowIndex + "_fwd_dir");
+			fwdDir.setAttribute("name", propName + "_orientation_radio_" + propRow.rowIndex);
+			fwdDir.setAttribute("checked", true);
+
+			originPosCell.appendChild(fwdDir);
+			originPosCell.innerHTML += "Forward ";
+ 
+			var revDir = document.createElement("INPUT");
+			revDir.setAttribute("type", "radio");
+			revDir.setAttribute("id", propName + "_" + propRow.rowIndex + "_rev_dir");
+			revDir.setAttribute("name", propName + "_orientation_radio_" + propRow.rowIndex);
+
+			originPosCell.appendChild(revDir);
+			originPosCell.innerHTML += "Reverse";
+
+			// Add 'Remove' link
+			var removeLink = document.createElement("SPAN");
+			removeLink.className = "linkShow";
+			removeLink.style.fontSize = "9pt";
+			removeLink.style.fontWeight = "normal";
+			removeLink.style.marginLeft = "10px";
+			removeLink.innerHTML = "Remove";
+		
+			originPosCell.appendChild(removeLink);
+
+			// Adjust border height to stretch to bottom of page
+// 			mainBorder = document.getElementById("mainBorder");
+// 			mainBorder.height = document.height;
+// 			mainBorder.rowSpan = propsTbl.rows.length;
+		
+			// Add a separator row
+			var divRow = propsTbl.insertRow(tmpOriginPosRow.rowIndex + 1);
+			var divCell = divRow.insertCell(0);
+
+			divRow.setAttribute('id', "div_row" + divRow.rowIndex + "_id");
+			divCell.colSpan = 6;
+			divCell.innerHTML = "<HR>";
+
+			// 'Remove' link
+// 			var tblID = "modifyReagentPropsTbl";
+			var originRowID = propRow.id;
+			var divRowID = divRow.id;
+		
+			// Add list to form
+			var myForm = document.reagentDetailForm;
+
+			var hiddenOrigin = document.createElement("INPUT");
+			hiddenOrigin.setAttribute("type", "hidden");
+			myForm.appendChild(hiddenOrigin);
+
+			var hiddenOriginStart = document.createElement("INPUT");
+			hiddenOriginStart.setAttribute("type", "hidden");
+			hiddenOriginStart.setAttribute("id", "origin_of_replication_startpos_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenOriginStart);
+
+			var hiddenOriginEnd = document.createElement("INPUT");
+			hiddenOriginEnd.setAttribute("type", "hidden");
+			hiddenOriginEnd.setAttribute("id", "origin_of_replication_endpos_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenOriginEnd);
+
+			// Orientation
+			var hiddenOriginDir = document.createElement("INPUT");
+			hiddenOriginDir.setAttribute('type', 'hidden');
+			hiddenOriginDir.setAttribute("id", "origin_of_replication_orientation_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenOriginDir);
+
+			var elemList = new Array();
+			elemList.push(hiddenOrigin);
+			elemList.push(hiddenOriginStart);
+			elemList.push(hiddenOriginEnd);
+			elemList.push(hiddenOriginDir);
+
+			removeLink.onclick = function(){deleteTableRow(tblID, originRowID); deleteTableRow(tblID, tmpOriginPosRowID); deleteTableRow(tblID, divRowID); removeFormElements(myForm, elemList)};
+		break;
+
+		case 'miscellaneous':
+			var propRow = propsTbl.insertRow(propList.rowIndex - 1);
+		
+			// Need a few cells in the row
+			var propNameCell = propRow.insertCell(0);
+			var propValueCell = propRow.insertCell(1);
+
+			// Set cell content and formatting as required by template
+			propNameCell.className = "detailedView_colName";
+			propNameCell.innerHTML = "Miscellaneous";
+		
+			propValueCell.className = "detailedView_value";
+			propValueCell.setAttribute("white-space", "nowrap");
+			propValueCell.style.fontSize = "9pt";
+			propValueCell.colSpan = 5;
+			propValueCell.style.paddingLeft = "5px";
+			
+			// Generate the list on the fly
+			var tmpMiscList = document.getElementById("miscellaneous_list");
+			var miscSelectedInd = tmpMiscList.selectedIndex;
+			var miscSelectedValue = tmpMiscList[miscSelectedInd].value;
+
+			var newMiscList = document.createElement("SELECT");
+			var newMiscTxt =  document.createElement("INPUT");
+
+			newMiscList.setAttribute("name", prefix + propName + postfix);
+			newMiscList.setAttribute("id", propName + "_proplist_" + propRow.rowIndex);
+
+			propRow.setAttribute('id', "miscellaneous_row_" + propRow.rowIndex + "_id");
+
+			newMiscTxt.type = "TEXT";
+			newMiscTxt.id = "miscellaneous_txt_" + (propList.rowIndex - 1);
+			newMiscTxt.style.display = "none";
+
+			for (i = 0; i < tmpMiscList.options.length; i++)
+			{
+				tmpOptn = tmpMiscList.options[i];
+				newOptn = document.createElement("OPTION");
+
+				newOptn.value = tmpOptn.value;
+				newOptn.name = tmpOptn.name;
+				newOptn.text = tmpOptn.text;
+
+				if (newMiscList.options.length == 0)
+					newMiscList.options.add(newOptn);
+				else
+					addElement(newMiscList, newMiscList.options.length, newOptn);
+			}
+
+			propValueCell.appendChild(newMiscList);
+			propValueCell.appendChild(newMiscTxt);
+
+			// Start & stop positions
+			// April 1, 2008: Show in a new row
+			var miscPosRow = propsTbl.insertRow(propRow.rowIndex+1);
+			miscPosRow.setAttribute('id', "miscellaneous_pos_row" + miscPosRow.rowIndex + "_id");
+			var miscPosRowID = miscPosRow.id;
+
+			var c1 = miscPosRow.insertCell(0);
+			var miscPosCell = miscPosRow.insertCell(1);
+
+			miscPosCell.className = "detailedView_value";
+			miscPosCell.style.paddingLeft = "5px";
+			miscPosCell.colSpan = 5;
+			miscPosCell.setAttribute("white-space", "nowrap");
+
+			miscPosCell.innerHTML = "Start: ";
+
+			var newMiscStart = document.createElement("INPUT");
+			newMiscStart.setAttribute("type", 'TEXT');
+			newMiscStart.setAttribute("size", 5);
+			newMiscStart.setAttribute("id", propName + "_" + propRow.rowIndex + "_startpos_id");
+
+			miscPosCell.appendChild(newMiscStart);
+
+			miscPosCell.innerHTML += "  End: ";
+			
+			var newMiscEnd = document.createElement("INPUT");
+			newMiscEnd.setAttribute("type", 'TEXT');
+			newMiscEnd.setAttribute("size", 5);
+			newMiscEnd.setAttribute("id", propName + "_" + propRow.rowIndex + "_endpos_id");
+
+			miscPosCell.appendChild(newMiscEnd);
+/*
+			newMiscList.onchange = function()
+			{
+// 				showTagTypeBox(newTagTypeList.id, newTagTypeTxt.id);
+			};*/
+
+			// Orientation - March 14/08: Make 'forward' checked by default
+			miscPosCell.innerHTML += "<SPAN style=\"margin-left:10px;\"></span>";
+
+			var fwdDir = document.createElement("INPUT");
+			fwdDir.setAttribute("type", "radio");
+			fwdDir.setAttribute("id", propName + "_" + propRow.rowIndex + "_fwd_dir");
+			fwdDir.setAttribute("name", propName + "_orientation_radio_" + propRow.rowIndex);
+			fwdDir.setAttribute("checked", true);
+
+			miscPosCell.appendChild(fwdDir);
+			miscPosCell.innerHTML += "Forward ";
+ 
+			var revDir = document.createElement("INPUT");
+			revDir.setAttribute("type", "radio");
+			revDir.setAttribute("id", propName + "_" + propRow.rowIndex + "_rev_dir");
+			revDir.setAttribute("name", propName + "_orientation_radio_" + propRow.rowIndex);
+			miscPosCell.appendChild(revDir);
+			miscPosCell.innerHTML += "Reverse";
+
+			// Add 'Remove' link
+			var removeLink = document.createElement("SPAN");
+			removeLink.className = "linkShow";
+			removeLink.style.fontSize = "9pt";
+			removeLink.style.fontWeight = "normal";
+			removeLink.style.marginLeft = "10px";
+			removeLink.innerHTML = "Remove";
+		
+			miscPosCell.appendChild(removeLink);
+
+			// Adjust border height to stretch to bottom of page
+// 			mainBorder = document.getElementById("mainBorder");
+// 			mainBorder.height = document.height;
+// 			mainBorder.rowSpan = propsTbl.rows.length;
+		
+			// Add a separator row
+			var divRow = propsTbl.insertRow(miscPosRow.rowIndex + 1);
+			var divCell = divRow.insertCell(0);
+
+			divRow.setAttribute('id', "div_row" + divRow.rowIndex + "_id");
+			divCell.colSpan = 6;
+			divCell.innerHTML = "<HR>";
+
+			// 'Remove' link
+// 			var tblID = "modifyReagentPropsTbl";
+			var miscRowID = propRow.id;
+			var divRowID = divRow.id;
+		
+			// Add list to form
+			var myForm = document.reagentDetailForm;
+
+			var hiddenMisc = document.createElement("INPUT");
+			hiddenMisc.setAttribute("type", "hidden");
+			myForm.appendChild(hiddenMisc);
+
+			var hiddenMiscStart = document.createElement("INPUT");
+			hiddenMiscStart.setAttribute("type", "hidden");
+			hiddenMiscStart.setAttribute("id", "miscellaneous_startpos_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenMiscStart);
+
+			var hiddenMiscEnd = document.createElement("INPUT");
+			hiddenMiscEnd.setAttribute("type", "hidden");
+			hiddenMiscEnd.setAttribute("id", "miscellaneous_endpos_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenMiscEnd);
+
+			// Orientation
+			var hiddenMiscDir = document.createElement("INPUT");
+			hiddenMiscDir.setAttribute('type', 'hidden');
+			hiddenMiscDir.setAttribute("id", "miscellaneous_orientation_prop_" + propRow.rowIndex);
+			myForm.appendChild(hiddenMiscDir);
+
+			var elemList = new Array();
+			elemList.push(hiddenMisc);
+			elemList.push(hiddenMiscStart);
+			elemList.push(hiddenMiscEnd);
+			elemList.push(hiddenMiscDir);
+
+			removeLink.onclick = function(){deleteTableRow(tblID, miscRowID); deleteTableRow(tblID, miscPosRowID); deleteTableRow(tblID, divRowID); removeFormElements(myForm, elemList)};
+		break;
+
+		default:
+			var propVals = document.getElementById(propName + "_attribute");
+
+			if (propVals.style.display == "none")
+			{
+				propVals.style.display = "table-row";
+
+				// Add a separator row
+				var divRow = propsTbl.insertRow(propVals.rowIndex + 1);
+				var divCell = divRow.insertCell(0);
+	
+				divCell.colSpan = 6;
+				divCell.innerHTML = "<HR>";
+			}
+		break;
+	}
+
+	propNamesList.selectedIndex = 0;
+}
+
+// March 19/09: Capitalize the first letter of each word in a string
+function titleCase(str)
+{
+	var toks = str.split(" ");
+	
+	var strout = "";
+
+	for (i = 0; i < toks.length; i++)
+	{
+		strout += toks[i].substr(0,1).toUpperCase() + toks[i].substr(1) + " ";
+	}
+
+	return trimAll(strout);
+}
+
+// when adding new reagent type
+function previewReagentTypePropFormat()
+{
+	var plainTextProps = ["5' linker", "3' linker", "accession number", "comments", "concentration", "description", "ensembl gene id", "ensembl peptide id", "entrez gene id", "official gene symbol", "image id", "length", "molecular weight", "name", "protein sequence", "reagent source", "sequence", "melting temperature", "verification comments"];
+
+	var dropdownProps = ["5' cloning site", "3' cloning site", "antibiotic resistance", "cell line type", "developmentatl stage", "expression system", "frame", "cloning method", "intron", "miscellaneous", "morphology", "open/closed", "origin of replication", "project id", "polya", "promoter", "protocol", "restriction site", "selectable marker", "species", "status", "tag position", "tag", "tissue type", "transcription terminator", "type of insert", "vector type", "verification"];
+
+	var checkboxProps = ["alternate id", "resistance marker"];
+
+	var radioProps = ["restrictions on use"];
+
+	var myForm = document.addReagentTypeForm;
+
+	var propNamesList = document.getElementById("src_props_list");
+
+	for (j = 0; j < propNamesList.options.length; j++)
+	{
+		var aOpt = propNamesList.options[j];
+
+		if (aOpt.selected)
+		{
+// 			var selectedInd = i;
+// 			var selectedInd = propNamesList.selectedIndex;
+// 			var propName = propNamesList[selectedInd].value;
+
+			var propName = aOpt.value;
+		
+			var propsTbl = document.getElementById("propInputFormatTable");
+			
+			var prefix = "reagent_detailedview_";
+			var postfix = "_prop";
+		
+			var propRow = propsTbl.insertRow(propsTbl.rows.length);
+			var propNameCell = propRow.insertCell(0);
+			var propInputFormatCell = propRow.insertCell(1);
+		// 	var propInputValuesCell = propRow.insertCell(2);
+			var rmvCell = propRow.insertCell(2);
+			
+			// Format cells
+			propNameCell.style.paddingLeft = "7px";
+			propNameCell.style.fontSize = "9pt";
+		
+			rmvCell.style.textAlign = "left";
+		
+			// Set cell content and formatting as required by template
+// 			propNameCell.innerHTML = titleCase(propName);
+			propNameCell.innerHTML = aOpt.text;
+		
+			// Replicate template input values list and add to second cell
+			var templateInputFormatList = document.getElementById("propInputFormat");
+		
+			var tmpInputFormatList = document.createElement("SELECT");
+			tmpInputFormatList.style.fontSize = "9pt";
+		
+			for (i = 0; i < templateInputFormatList.options.length; i++)
+			{
+				tmpOptn = templateInputFormatList.options[i];
+				newOptn = document.createElement("OPTION");
+		
+				newOptn.value = tmpOptn.value;
+				newOptn.text = tmpOptn.text;
+		
+				if (tmpInputFormatList.options.length == 0)
+					tmpInputFormatList.options.add(newOptn);
+				else
+					addElement(tmpInputFormatList, tmpInputFormatList.options.length, newOptn);
+			}
+		
+			// Have to do this in a separate loop!
+			for (i = 0; i < templateInputFormatList.options.length; i++)
+			{
+				tmpOptn = tmpInputFormatList.options[i];
+			
+				if ((tmpOptn.value == "plain_text") && inArray(propName.toLowerCase(), plainTextProps))
+				{
+					tmpOptn.selected = true;
+				}
+				else if ((tmpOptn.value == "dropdown") && inArray(propName.toLowerCase(), dropdownProps))
+				{
+					tmpOptn.selected = true;
+				}
+				else if ((tmpOptn.value == "radio_btn") && inArray(propName.toLowerCase(), radioProps))
+				{
+					tmpOptn.selected = true;
+				}
+				else if ((tmpOptn.value == "checkboxes") && inArray(propName.toLowerCase(), checkboxProps))
+				{
+					tmpOptn.selected = true;
+				}
+			}
+
+			propInputFormatCell.appendChild(tmpInputFormatList);
+		}
+	}
+}
+
+
+function addFeatures(listID, form_name, featuresRowID, propsTableID)
+{
+	var hasDescriptor = false;
+	var descriptor = "";
+	var descrAlias = "";
+	var descrListID = "";
+
+	var propNamesList = document.getElementById(listID);
+	var selectedInd = propNamesList.selectedIndex;
+	var propName = propNamesList[selectedInd].value;
+
+	switch (propName)
+	{
+		// don't do anything if 'default' is selected
+		case 'default':
+			return;
+		break;
+
+		case 'tag':
+			hasDescriptor = true;
+			descriptor = "Tag Position";
+			descrAlias = "tag_position";
+			descrListID = "tag_position_list";
+		break;
+
+		case 'promoter':
+			hasDescriptor = true;
+			descriptor = "Expression System";
+			descrAlias = "expression_system";
+			descrListID = "expression_system_list";
+		break;
+	}
+
+	var myForm;
+
+	// Add list to form
+	if (form_name == "")
+		myForm = document.reagentDetailForm;
+	else
+	{
+		docForms = document.forms;
+	
+		for (i = 0; i < docForms.length; i++)
+		{
+			aForm = docForms[i];
+
+			if (aForm.name == form_name)
+			{
+				myForm = aForm;
+				break;
+			}
+		}
+	}
+
+	var propList = document.getElementById(featuresRowID);
+
+	// Modified March 3/08
+	var propsTbl = document.getElementById(propsTableID);
+	var propRow = propsTbl.insertRow(propsTbl.rows.length);
+
+	// Need a few cells in the row
+	var propNameCell = propRow.insertCell(0);
+	var propValueCell = propRow.insertCell(1);
+	var propDescrCell = propRow.insertCell(2);
+	var propStartCell = propRow.insertCell(3);
+	var propEndCell = propRow.insertCell(4);
+	var propDirCell = propRow.insertCell(5);
+	var rmvCell = propRow.insertCell(6);
+
+	// Format cells	
+	propNameCell.style.paddingLeft = "7px";
+	propNameCell.style.backgroundColor = "#F5F5DC";
+	propNameCell.style.fontSize = "7pt";		// nov. 12/08
+	propNameCell.style.whiteSpace = "nowrap";
+
+	propValueCell.style.paddingLeft = "7px";
+	propValueCell.style.paddingRight = "5px";
+	propValueCell.style.paddingTop = "1px";
+	propValueCell.style.paddingBottom = "1px";
+	propValueCell.style.backgroundColor = "#F5F5DC";
+
+	propDescrCell.style.paddingLeft = "7px";
+	propDescrCell.style.backgroundColor = "#F5F5DC";
+
+	propStartCell.style.textAlign = "left";
+	propStartCell.style.paddingLeft = "7px";
+	propStartCell.style.paddingRight = "2px";
+	propStartCell.style.backgroundColor = "#F5F5DC";
+
+	propEndCell.style.textAlign = "left";
+	propEndCell.style.backgroundColor = "#F5F5DC";
+	propEndCell.style.paddingLeft = "7px";
+	propEndCell.style.paddingRight = "2px";
+
+	propDirCell.style.textAlign = "left";
+	propDirCell.style.paddingLeft = "5px";
+	propDirCell.style.paddingRight = "5px";
+	propDirCell.style.backgroundColor = "#F5F5DC";
+
+	rmvCell.style.textAlign = "left";
+
+	// Set cell content and formatting as required by template
+	propNameCell.innerHTML = propNamesList[selectedInd].text;
+
+	propValueCell.setAttribute("white-space", "nowrap");
+	
+	// Generate the list on the fly - KEEPING 'tag type' IN VARIABLE NAMES FOR ERROR SAKE (code copy-pasted, keeping variable names to avoid errors renaming)
+	var tmpTagTypeList = document.getElementById(propName + "_list");
+
+	var newTagTypeList = document.createElement("SELECT");
+	var newTagTypeTxt =  document.createElement("INPUT");
+
+	newTagTypeList.style.fontSize = "7pt";		// Nov. 12/08
+
+	var rowIndex;
+
+	if (!document.getElementById(propName + "_row_" + propRow.rowIndex + "_id"))
+	{
+		propRow.setAttribute('id', propName + "_row_" + propRow.rowIndex + "_id");
+		rowIndex = propRow.rowIndex;
+	}
+	else
+	{
+		for (i = 0; i < propsTbl.rows.length; i++)
+		{
+			if (!document.getElementById(propName + "_row_" + i + "_id"))
+			{
+				propRow.setAttribute('id', propName + "_row_" + i + "_id");
+				break;
+			}
+		}
+
+		propRow.setAttribute('id', propName + "_row_" + i + "_id");
+		rowIndex = i;
+	}
+
+	newTagTypeList.setAttribute('id', propName + "_proplist_" + rowIndex);
+
+	newTagTypeTxt.type = "TEXT";
+	newTagTypeTxt.id = propName + "_txt_" + rowIndex;
+
+	newTagTypeTxt.style.display = "none";
+	newTagTypeTxt.style.fontSize = "9pt";
+
+	for (i = 0; i < tmpTagTypeList.options.length; i++)
+	{
+		tmpOptn = tmpTagTypeList.options[i];
+		newOptn = document.createElement("OPTION");
+
+		newOptn.value = tmpOptn.value;
+		newOptn.name = tmpOptn.name;
+		newOptn.text = tmpOptn.text;
+
+		if (newTagTypeList.options.length == 0)
+			newTagTypeList.options.add(newOptn);
+		else
+			addElement(newTagTypeList, newTagTypeList.options.length, newOptn);
+	}
+
+	newTagTypeList.onchange = function(){this.setAttribute('name', propName + "_" + this[this.selectedIndex].value + "_" + rowIndex); showTagTypeBox(newTagTypeList.id, newTagTypeTxt.id);};
+
+	propValueCell.appendChild(newTagTypeList);
+	propValueCell.appendChild(newTagTypeTxt);
+
+	// Generate descriptor lists if applicable
+	if (hasDescriptor)
+	{
+// alert(descrListID);
+		var oldTagPosList = document.getElementById(descrListID);
+		var newDescriptorList = document.createElement("SELECT");
+	
+		newDescriptorList.setAttribute('id', descrAlias + "_proplist_" + rowIndex);
+	
+		newDescriptorList.style.fontSize = "7pt";		// Nov. 12/08
+	
+		for (i = 0; i < oldTagPosList.options.length; i++)
+		{
+			tmpOptn = oldTagPosList.options[i];
+			newOptn = document.createElement("OPTION");
+	
+			newOptn.value = tmpOptn.value;
+			newOptn.name = tmpOptn.name;
+			newOptn.text = tmpOptn.text;
+	
+			if (newDescriptorList.options.length == 0)
+				newDescriptorList.options.add(newOptn);
+			else
+				addElement(newDescriptorList, newDescriptorList.options.length, newOptn);
+		}
+	
+		propDescrCell.appendChild(newDescriptorList);
+	}
+
+	var newTagTypeStart = document.createElement("INPUT");
+	newTagTypeStart.setAttribute("type", 'TEXT');
+	newTagTypeStart.setAttribute("size", 5);
+	newTagTypeStart.setAttribute("id", propName + "_" + rowIndex + "_startpos_id");
+	newTagTypeStart.style.fontSize = "7pt";		// Nov. 12/08
+
+	propStartCell.appendChild(newTagTypeStart);
+
+	var newTagTypeEnd = document.createElement("INPUT");
+	newTagTypeEnd.setAttribute("type", 'TEXT');
+	newTagTypeEnd.setAttribute("size", 5);
+	newTagTypeEnd.setAttribute("id", propName + "_" + rowIndex + "_endpos_id");
+	newTagTypeEnd.style.fontSize = "7pt";		// Nov. 12/08
+
+	propEndCell.appendChild(newTagTypeEnd);
+
+	// Orientation
+	propDirCell.style.fontSize = "7pt";		// Nov. 12/08
+	propDirCell.style.whiteSpace = "nowrap";
+	
+	var fwdDir = document.createElement("INPUT");
+	fwdDir.setAttribute("type", "radio");
+	fwdDir.setAttribute("id", propName + "_" + rowIndex + "_fwd_dir");
+	fwdDir.setAttribute("name", propName + "_orientation_prop_" + rowIndex);
+
+	fwdDir.setAttribute("checked", true);
+
+	propDirCell.appendChild(fwdDir);
+	propDirCell.innerHTML += "Forward ";
+
+	var revDir = document.createElement("INPUT");
+	revDir.setAttribute("type", "radio");
+	revDir.setAttribute("id", propName + "_" + rowIndex + "_rev_dir");
+	revDir.setAttribute("name", propName + "_orientation_prop_" + rowIndex);
+
+	propDirCell.appendChild(revDir);
+	propDirCell.innerHTML += "Reverse";
+
+	// Add 'Remove' link
+	var removeLink = document.createElement("SPAN");
+	removeLink.className = "linkShow";
+	removeLink.style.fontSize = "7pt";
+	removeLink.style.fontWeight = "normal";
+	removeLink.style.marginLeft = "5px";
+	removeLink.innerHTML = "Remove";
+
+	rmvCell.appendChild(removeLink);
+
+	// Gather the IDs of all elements in the row to pass to 'deleteRow' function
+	var tagTypeRowID = propRow.id;
+
+	var hiddenTagType = document.createElement("INPUT");
+	hiddenTagType.setAttribute("type", "hidden");
+	hiddenTagType.setAttribute("id", propName + "_prop" + rowIndex);
+	myForm.appendChild(hiddenTagType);
+
+	var hiddenTagTypeStart = document.createElement("INPUT");
+	hiddenTagTypeStart.setAttribute("type", "hidden");
+	hiddenTagTypeStart.setAttribute("id", propName + "_startpos_prop_" + rowIndex);
+	myForm.appendChild(hiddenTagTypeStart);
+
+	var hiddenTagTypeEnd = document.createElement("INPUT");
+	hiddenTagTypeEnd.setAttribute("type", "hidden");
+	hiddenTagTypeEnd.setAttribute("id", propName + "_endpos_prop_" + rowIndex);
+	myForm.appendChild(hiddenTagTypeEnd);
+
+	// Tag position
+	var hiddenDescriptorField = document.createElement("INPUT");
+	hiddenDescriptorField.setAttribute('type', 'hidden');
+	hiddenDescriptorField.setAttribute("id", descrAlias + "_prop_" + rowIndex);
+	myForm.appendChild(hiddenDescriptorField);
+
+	// Orientation
+	var hiddenTagTypeDir = document.createElement("INPUT");
+	hiddenTagTypeDir.setAttribute('type', 'hidden');
+	hiddenTagTypeDir.setAttribute("id", propName + "_orientation_prop_" + rowIndex);
+	myForm.appendChild(hiddenTagTypeDir);
+
+	var elemList = new Array();
+	elemList.push(hiddenTagType);
+	elemList.push(hiddenTagTypeStart);
+	elemList.push(hiddenTagTypeEnd);
+	elemList.push(hiddenTagTypeDir);
+
+	removeLink.onclick = function(){deleteTableRow(propsTableID, tagTypeRowID); removeFormElements(myForm, elemList)};
+
+	propNamesList.selectedIndex = 0;
+}
+
+
+// August 5/08: Identical to showPropertyValues, only used at reagent creation (different format)
+function showPropertyValues2(listID, form_name, tblID, rType, createNew)
+{
+	var myForm;
+
+	// Add list to form
+	if (form_name == "")
+		myForm = document.reagentDetailForm;
+	else
+	{
+		docForms = document.forms;
+	
+		for (i = 0; i < docForms.length; i++)
+		{
+			aForm = docForms[i];
+
+			if (aForm.name == form_name)
+			{
+				myForm = aForm;
+				break;
+			}
+		}
+	}
+
+// 	alert(myForm);
+
+	if (!tblID)
+		tblID = "modifyReagentPropsTbl";
+
+	var propNamesList = document.getElementById(listID);
+	var selectedInd = propNamesList.selectedIndex;
+	var propName = propNamesList[selectedInd].value;
+// alert(propName);
+
+// alert(tblID);
+
+	var propList = document.getElementById("addlPropsListRow_" + rType);
+	
+	// Modified March 3/08
+// 	var propsTbl = document.getElementById("modifyReagentPropsTbl");
+	var propsTbl = document.getElementById(tblID);
+
+// alert(propList.rowIndex);
+	
+	var prefix = "reagent_detailedview_";
+	var postfix = "_prop";
+
+	// March 3/08: Since there could be multiple property values (e.g. tag type or expression system), instead of unhiding the corresponding property row, append another row to the table and make it identical to the hidden row (so the hidden row serves as a template)
+	switch (propName)
+	{
+// 		case 'tag_type':
+// 			var propRow = propsTbl.insertRow(propList.rowIndex - 2);
+// 
+// 			// Need a few cells in the row
+// 			var propNameCell = propRow.insertCell(0);
+// 			var propValueCell = propRow.insertCell(1);
+// 			var propDescrCell = propRow.insertCell(2);
+// 			var propStartCell = propRow.insertCell(3);
+// 			var propEndCell = propRow.insertCell(4);
+// 			var propDirCell = propRow.insertCell(5);
+// 			var rmvCell = propRow.insertCell(6);
+// 		
+// 			// Format cells	
+// 			propNameCell.style.paddingLeft = "7px";
+// 			propNameCell.style.backgroundColor = "#F5F5DC";
+// 			propNameCell.style.fontSize = "7pt";		// nov. 12/08
+// 		
+// 			propValueCell.style.paddingLeft = "7px";
+// 			propValueCell.style.paddingRight = "5px";
+// 			propValueCell.style.paddingTop = "1px";
+// 			propValueCell.style.paddingBottom = "1px";
+// 			propValueCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propDescrCell.style.paddingLeft = "7px";
+// 			propDescrCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propStartCell.style.textAlign = "left";
+// 			propStartCell.style.paddingLeft = "7px";
+// 			propStartCell.style.paddingRight = "2px";
+// 			propStartCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propEndCell.style.textAlign = "left";
+// 			propEndCell.style.backgroundColor = "#F5F5DC";
+// 			propEndCell.style.paddingLeft = "7px";
+// 			propEndCell.style.paddingRight = "2px";
+// 
+// 			propDirCell.style.textAlign = "left";
+// 			propDirCell.style.paddingLeft = "5px";
+// 			propDirCell.style.paddingRight = "5px";
+// 			propDirCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			rmvCell.style.textAlign = "left";
+// 
+// 			// Set cell content and formatting as required by template	
+// 			propNameCell.innerHTML = "Tag";
+// 			propValueCell.setAttribute("white-space", "nowrap");
+// 			
+// 			// Generate the list on the fly
+// 			if (createNew == "true")
+// 				propNamePrefix = rType + "_"
+// 			else
+// 				propNamePrefix = ""
+// 
+// 			var tmpTagTypeList = document.getElementById(propNamePrefix + "tag_type_list");
+// 
+// 			var newTagTypeList = document.createElement("SELECT");
+// 			var newTagTypeTxt =  document.createElement("INPUT");
+// 
+// 			newTagTypeList.style.fontSize = "7pt";		// Nov. 12/08
+// 
+// 			var rowIndex;
+// 
+// 			if (!document.getElementById(propNamePrefix + "tag_type_row_" + propRow.rowIndex + "_id"))
+// 			{
+// 				propRow.setAttribute('id', propNamePrefix + "tag_type_row_" + propRow.rowIndex + "_id");
+// 				rowIndex = propRow.rowIndex;
+// 			}
+// 			else
+// 			{
+// 				for (i = 0; i < propsTbl.rows.length; i++)
+// 				{
+// 					if (!document.getElementById(propNamePrefix + "tag_type_row_" + i + "_id"))
+// 					{
+// 						propRow.setAttribute('id', propNamePrefix + "tag_type_row_" + i + "_id");
+// 						break;
+// 					}
+// 				}
+// 
+// 				propRow.setAttribute('id', propNamePrefix + "tag_type_row_" + i + "_id");
+// 				rowIndex = i;
+// 			}
+// 
+// // 			newTagTypeList.setAttribute('name', prefix + propName + postfix);
+// 			newTagTypeList.setAttribute('id', propNamePrefix + propName + "_proplist_" + rowIndex);
+// 
+// 			newTagTypeTxt.type = "TEXT";
+// 			newTagTypeTxt.id = propNamePrefix + "tag_type_txt_" + rowIndex;
+// 
+// 			newTagTypeTxt.style.display = "none";
+// 			newTagTypeTxt.style.fontSize = "9pt";
+// 
+// 			for (i = 0; i < tmpTagTypeList.options.length; i++)
+// 			{
+// 				tmpOptn = tmpTagTypeList.options[i];
+// 				newOptn = document.createElement("OPTION");
+// 
+// 				newOptn.value = tmpOptn.value;
+// 				newOptn.name = tmpOptn.name;
+// 				newOptn.text = tmpOptn.text;
+// 
+// 				if (newTagTypeList.options.length == 0)
+// 					newTagTypeList.options.add(newOptn);
+// 				else
+// 					addElement(newTagTypeList, newTagTypeList.options.length, newOptn);
+// 			}
+// 
+// // 			newTagTypeList.onchange = showTagTypeBox;
+// 
+// 			newTagTypeList.onchange = function(){this.setAttribute('name', propNamePrefix + propName + "_" + this[this.selectedIndex].value + "_" + rowIndex); showTagTypeBox(newTagTypeList.id, newTagTypeTxt.id);};
+// 
+// 			propValueCell.appendChild(newTagTypeList);
+// 			propValueCell.appendChild(newTagTypeTxt);
+// 
+// 			// March 17/08: Generate Tag Position option list
+// 			var oldTagPosList = document.getElementById(propNamePrefix + "tag_position_list");
+// // alert(oldTagPosList);
+// 			if (oldTagPosList)
+// 			{
+// 				var newTagPosList = document.createElement("SELECT");
+// 	
+// 				newTagPosList.setAttribute('id', propNamePrefix + "tag_position_proplist_" + rowIndex);
+// // 	alert(newTagPosList.id);
+// 				newTagPosList.style.fontSize = "7pt";		// Nov. 12/08
+// 	
+// 				for (i = 0; i < oldTagPosList.options.length; i++)
+// 				{
+// 					tmpOptn = oldTagPosList.options[i];
+// 					newOptn = document.createElement("OPTION");
+// 	
+// 					newOptn.value = tmpOptn.value;
+// 					newOptn.name = tmpOptn.name;
+// 					newOptn.text = tmpOptn.text;
+// 	
+// 					if (newTagPosList.options.length == 0)
+// 						newTagPosList.options.add(newOptn);
+// 					else
+// 						addElement(newTagPosList, newTagPosList.options.length, newOptn);
+// 				}
+// 	
+// 				propDescrCell.appendChild(newTagPosList);
+// 			}
+// 
+// 			var newTagTypeStart = document.createElement("INPUT");
+// 			newTagTypeStart.setAttribute("type", 'TEXT');
+// 			newTagTypeStart.setAttribute("size", 5);
+// 			newTagTypeStart.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_startpos_id");
+// 			newTagTypeStart.style.fontSize = "7pt";		// Nov. 12/08
+// 
+// 			propStartCell.appendChild(newTagTypeStart);
+// 
+// 			var newTagTypeEnd = document.createElement("INPUT");
+// 			newTagTypeEnd.setAttribute("type", 'TEXT');
+// 			newTagTypeEnd.setAttribute("size", 5);
+// 			newTagTypeEnd.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_endpos_id");
+// 			newTagTypeEnd.style.fontSize = "7pt";		// Nov. 12/08
+// 
+// 			propEndCell.appendChild(newTagTypeEnd);
+// 
+// 			// Orientation
+// 			propDirCell.style.fontSize = "7pt";		// Nov. 12/08
+// 			propDirCell.style.whiteSpace = "nowrap";
+// 			
+// 			var fwdDir = document.createElement("INPUT");
+// 			fwdDir.setAttribute("type", "radio");
+// 			fwdDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_fwd_dir");
+// //  			fwdDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			fwdDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 
+// 			fwdDir.setAttribute("checked", true);
+// 
+// 			propDirCell.appendChild(fwdDir);
+// 			propDirCell.innerHTML += "Forward ";
+// 
+// 			var revDir = document.createElement("INPUT");
+// 			revDir.setAttribute("type", "radio");
+// 			revDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_rev_dir");
+// // 			revDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+//  			revDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 
+// 			propDirCell.appendChild(revDir);
+// 			propDirCell.innerHTML += "Reverse";
+// 
+// 			// Add 'Remove' link
+// 			var removeLink = document.createElement("SPAN");
+// 			removeLink.className = "linkShow";
+// 			removeLink.style.fontSize = "7pt";
+// 			removeLink.style.fontWeight = "normal";
+// 			removeLink.style.marginLeft = "5px";
+// 			removeLink.innerHTML = "Remove";
+// 
+// 			rmvCell.appendChild(removeLink);
+// 
+// 			// Gather the IDs of all elements in the row to pass to 'deleteRow' function
+// // 			var tblID = "modifyReagentPropsTbl";
+// 			var tagTypeRowID = propRow.id;
+// 
+// 			var hiddenTagType = document.createElement("INPUT");
+// 			hiddenTagType.setAttribute("type", "hidden");
+// 			hiddenTagType.setAttribute("id", propNamePrefix + "tag_type_prop" + rowIndex);
+// 			myForm.appendChild(hiddenTagType);
+// 
+// 			var hiddenTagTypeStart = document.createElement("INPUT");
+// 			hiddenTagTypeStart.setAttribute("type", "hidden");
+// 			hiddenTagTypeStart.setAttribute("id", propNamePrefix + "tag_type_startpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenTagTypeStart);
+// 
+// 			var hiddenTagTypeEnd = document.createElement("INPUT");
+// 			hiddenTagTypeEnd.setAttribute("type", "hidden");
+// 			hiddenTagTypeEnd.setAttribute("id", propNamePrefix + "tag_type_endpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenTagTypeEnd);
+// 
+// 			// Tag position
+// 			var hiddenTagPosField = document.createElement("INPUT");
+// 			hiddenTagPosField.setAttribute('type', 'hidden');
+// 			hiddenTagPosField.setAttribute("id", propNamePrefix + "tag_position_prop_" + rowIndex);
+// // alert(hiddenTagPosField.id);
+// 			myForm.appendChild(hiddenTagPosField);
+// 
+// 			// Orientation
+// 			var hiddenTagTypeDir = document.createElement("INPUT");
+// 			hiddenTagTypeDir.setAttribute('type', 'hidden');
+// 			hiddenTagTypeDir.setAttribute("id", propNamePrefix + "tag_type_orientation_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenTagTypeDir);
+// 
+// 			var elemList = new Array();
+// 			elemList.push(hiddenTagType);
+// 			elemList.push(hiddenTagTypeStart);
+// 			elemList.push(hiddenTagTypeEnd);
+// 			elemList.push(hiddenTagTypeDir);
+// 
+// 			removeLink.onclick = function(){deleteTableRow(tblID, tagTypeRowID); removeFormElements(myForm, elemList)};
+// 
+// 		break;
+// 
+// 		case 'promoter':
+// 			var propRow = propsTbl.insertRow(propList.rowIndex - 2);
+// 		
+// 			// Need a few cells in the row
+// 			var propNameCell = propRow.insertCell(0);
+// 			var propValueCell = propRow.insertCell(1);
+// 			var propDescrCell = propRow.insertCell(2);
+// 			var propStartCell = propRow.insertCell(3);
+// 			var propEndCell = propRow.insertCell(4);
+// 			var propDirCell = propRow.insertCell(5);
+// 			var rmvCell = propRow.insertCell(6);
+// 		
+// 			// Format cells
+// 			propNameCell.style.paddingLeft = "7px";
+// 			propNameCell.style.backgroundColor = "#F5F5DC";
+// 			propNameCell.style.fontSize = "7pt";		// nov. 12/08
+// 		
+// 			propValueCell.style.paddingLeft = "7px";
+// 			propValueCell.style.paddingRight = "5px";
+// 			propValueCell.style.paddingTop = "1px";
+// 			propValueCell.style.paddingBottom = "1px";
+// 			propValueCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propDescrCell.style.paddingLeft = "7px";
+// 			propDescrCell.style.backgroundColor = "#F5F5DC";
+// 			propDescrCell.style.fontSize = "7pt";
+// 		
+// 			propStartCell.style.textAlign = "left";
+// 
+// 			propStartCell.style.paddingLeft = "7px";
+// 			propStartCell.style.paddingRight = "2px";
+// 
+// 			propStartCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propEndCell.style.textAlign = "left";
+// 
+// 			propEndCell.style.paddingLeft = "7px";
+// 			propEndCell.style.paddingRight = "2px";
+// 
+// 			propEndCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propDirCell.style.textAlign = "left";
+// 
+// 			propDirCell.style.paddingLeft = "5px";
+// 			propDirCell.style.paddingRight = "5px";
+// 
+// 			propDirCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			rmvCell.style.textAlign = "left";
+// 			propNameCell.innerHTML = "Promoter";
+// 
+// 			// Generate the list on the fly
+// 			if (createNew == "true")
+// 				propNamePrefix = rType + "_"
+// 			else
+// 				propNamePrefix = ""
+// 
+// 			var tmpPromoterList = document.getElementById(propNamePrefix + "promoter_list");
+// 			var newPromoterList = document.createElement("SELECT");
+// 			var newPromoterTxt =  document.createElement("INPUT");
+// 			var newExpSysTxt =  document.createElement("INPUT");
+// 
+// 			var rowIndex;
+// 
+// 			if (!document.getElementById(propNamePrefix + "promoter_row_" + propRow.rowIndex + "_id"))
+// 			{
+// 				propRow.setAttribute('id', propNamePrefix + "promoter_row_" + propRow.rowIndex + "_id");
+// 				rowIndex = propRow.rowIndex;
+// 			}
+// 			else
+// 			{
+// 				for (i = 0; i < propsTbl.rows.length; i++)
+// 				{
+// 					if (!document.getElementById(propNamePrefix + "promoter_row_" + i + "_id"))
+// 					{
+// 						propRow.setAttribute('id', propNamePrefix + "promoter_row_" + i + "_id");
+// 						break;
+// 					}
+// 				}
+// 
+// 				propRow.setAttribute('id', propNamePrefix + "promoter_row_" + i + "_id");
+// 				rowIndex = i;
+// 			}
+// 
+// 			newPromoterList.setAttribute('id', propNamePrefix + propName + "_proplist_" + rowIndex);
+// 			newPromoterList.style.fontSize = "7pt";		// Nov. 12/08
+// 
+// 			newPromoterTxt.type = "TEXT";
+// 			newPromoterTxt.id = propNamePrefix + "promoter_txt_" + rowIndex;
+// 			newPromoterTxt.style.display = "none";
+// 
+// 			newExpSysTxt.type = "TEXT";
+// 			newExpSysTxt.id = propNamePrefix + "expression_system_txt_" + rowIndex;
+// 			newExpSysTxt.style.display = "none";
+// 
+// 			for (i = 0; i < tmpPromoterList.options.length; i++)
+// 			{
+// 				tmpOptn = tmpPromoterList.options[i];
+// 				newOptn = document.createElement("OPTION");
+// 
+// 				newOptn.value = tmpOptn.value;
+// 				newOptn.name = tmpOptn.name;
+// 				newOptn.text = tmpOptn.text;
+// 
+// 				if (newPromoterList.options.length == 0)
+// 					newPromoterList.options.add(newOptn);
+// 				else
+// 					addElement(newPromoterList, newPromoterList.options.length, newOptn);
+// 			}
+// 
+// 			propValueCell.appendChild(newPromoterList);
+// 			propValueCell.appendChild(newPromoterTxt);
+// 
+// 			var oldExpSystList = document.getElementById(propNamePrefix + "expression_system_list");
+// 			var newExpSystList = document.createElement("SELECT");
+// 
+// 			newExpSystList.setAttribute('id', propNamePrefix + "expression_system_prop_list_" + rowIndex);
+// 			newExpSystList.style.fontSize = "7pt";		// Nov. 12/08
+// 
+// 			for (i = 0; i < oldExpSystList.options.length; i++)
+// 			{
+// 				tmpOptn = oldExpSystList.options[i];
+// 				newOptn = document.createElement("OPTION");
+// 
+// 				newOptn.value = tmpOptn.value;
+// 				newOptn.name = tmpOptn.name;
+// 				newOptn.text = tmpOptn.text;
+// 
+// 				if (newExpSystList.options.length == 0)
+// 					newExpSystList.options.add(newOptn);
+// 				else
+// 					addElement(newExpSystList, newExpSystList.options.length, newOptn);
+// 			}
+// 
+// 			propDescrCell.appendChild(newExpSystList);
+// 			propDescrCell.appendChild(newExpSysTxt);
+// 
+// 			var newPromStart = document.createElement("INPUT");
+// 			newPromStart.setAttribute("type", 'TEXT');
+// 			newPromStart.setAttribute("size", 5);
+// 			newPromStart.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_startpos_id");
+// 			newPromStart.style.fontSize = "7pt";		// Nov. 12/08
+// 
+// 			propStartCell.appendChild(newPromStart);
+// 			
+// 			var newPromEnd = document.createElement("INPUT");
+// 			newPromEnd.setAttribute("type", 'TEXT');
+// 			newPromEnd.setAttribute("size", 5);
+// 			newPromEnd.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_endpos_id");
+// 			newPromEnd.style.fontSize = "7pt";		// Nov. 12/08
+// 
+// 			propEndCell.appendChild(newPromEnd);
+// 
+// 			newPromoterList.onchange = function(){this.setAttribute('name', propNamePrefix + propName + "_" + this[this.selectedIndex].value + "_" + rowIndex); showSpecificOtherTextbox(newPromoterList.id, newPromoterTxt.id);};
+// 
+// 			newExpSystList.onchange = function(){showSpecificOtherTextbox(newExpSystList.id, newExpSysTxt.id);};
+// 
+// 			// Orientation - March 14/08: Make 'forward' checked by default
+// 			var fwdDir = document.createElement("INPUT");
+// 			fwdDir.setAttribute("type", "radio");
+// 			fwdDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_fwd_dir");
+// // 			fwdDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			fwdDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 			fwdDir.setAttribute("checked", true);
+// 
+// 			propDirCell.appendChild(fwdDir);
+// 			propDirCell.innerHTML += "Forward ";
+// 			propDirCell.style.fontSize = "7pt";		// Nov. 12/08
+// 			propDirCell.style.whiteSpace = "nowrap";
+// 
+// 			var revDir = document.createElement("INPUT");
+// 			revDir.setAttribute("type", "radio");
+// 			revDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_rev_dir");
+// // 			revDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			revDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 
+// 			propDirCell.appendChild(revDir);
+// 			propDirCell.innerHTML += "Reverse";
+// 
+// 			// Add 'Remove' link
+// 			var removeLink = document.createElement("SPAN");
+// 			removeLink.className = "linkShow";
+// 			removeLink.style.fontSize = "7pt";
+// 			removeLink.style.fontWeight = "normal";
+// 			removeLink.style.marginLeft = "5px";
+// 			removeLink.innerHTML = "Remove";
+// 		
+// 			rmvCell.appendChild(removeLink);
+// 
+// 			// Gather the IDs of all elements in the row to pass to 'deleteRow' function
+// // 			var tblID = "modifyReagentPropsTbl";
+// 			var promRowID = propRow.id;
+// 		
+// // 			// Add list to form
+// // 			if (form_name == "")
+// // 				var myForm = document.reagentDetailForm;
+// // 			else
+// // 			{
+// // 				var myForm;
+// // 			
+// // 				docForms = document.forms;
+// // 			
+// // 				for (i = 0; i < docForms.length; i++)
+// // 				{
+// // 					aForm = docForms[i];
+// // 			
+// // 					if (aForm.name == form_name)
+// // 					{
+// // 						myForm = aForm;
+// // 						break;
+// // 					}
+// // 				}
+// // 			}
+// 
+// 			var hiddenPromoter = document.createElement("INPUT");
+// 			hiddenPromoter.setAttribute("type", "hidden");
+// 			myForm.appendChild(hiddenPromoter);
+// 
+// 			var hiddenPromStart = document.createElement("INPUT");
+// 			hiddenPromStart.setAttribute("type", "hidden");
+// 			hiddenPromStart.setAttribute("id", propNamePrefix + "promoter_startpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenPromStart);
+// 
+// 			var hiddenPromEnd = document.createElement("INPUT");
+// 			hiddenPromEnd.setAttribute("type", "hidden");
+// 			hiddenPromEnd.setAttribute("id", propNamePrefix + "promoter_endpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenPromEnd);
+// 
+// 			var hiddenExprSyst = document.createElement("INPUT");
+// 			hiddenExprSyst.setAttribute("type", "hidden");
+// 			hiddenExprSyst.setAttribute("id", propNamePrefix + "expression_system_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenExprSyst);
+// 
+// 			// Orientation
+// 			var hiddenPromoDir = document.createElement("INPUT");
+// 			hiddenPromoDir.setAttribute('type', 'hidden');
+// 			hiddenPromoDir.setAttribute("id", propNamePrefix + "promoter_orientation_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenPromoDir);
+// 
+// 			var elemList = new Array();
+// 			elemList.push(hiddenPromoter);
+// 			elemList.push(hiddenPromStart);
+// 			elemList.push(hiddenPromEnd);
+// 			elemList.push(hiddenExprSyst);
+// 			elemList.push(hiddenPromoDir);
+// 
+// 			removeLink.onclick = function(){deleteTableRow(tblID, promRowID); removeFormElements(myForm, elemList)};
+// 
+// 		break;
+//  
+// 		case 'selectable_marker':
+// 			var propRow = propsTbl.insertRow(propList.rowIndex - 2);
+// 		
+// 			// Need a few cells in the row
+// 			var propNameCell = propRow.insertCell(0);
+// 			var propValueCell = propRow.insertCell(1);
+// 			var propDescrCell = propRow.insertCell(2);
+// 			var propStartCell = propRow.insertCell(3);
+// 			var propEndCell = propRow.insertCell(4);
+// 			var propDirCell = propRow.insertCell(5);
+// 			var rmvCell = propRow.insertCell(6);
+// 		
+// 			// Format cells	
+// 			propNameCell.style.paddingLeft = "7px";
+// 			propNameCell.style.backgroundColor = "#F5F5DC";
+// 			propNameCell.style.fontSize = "7pt";
+// 		
+// 			propValueCell.style.paddingLeft = "7px";
+// 			propValueCell.style.paddingRight = "5px";
+// 			propValueCell.style.paddingTop = "1px";
+// 			propValueCell.style.paddingBottom = "1px";
+// 			propValueCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propDescrCell.style.paddingLeft = "7px";
+// 			propDescrCell.style.backgroundColor = "#F5F5DC";
+// 			propDescrCell.style.fontSize = "7pt";
+// 		
+// 			propStartCell.style.textAlign = "left";
+// 			propStartCell.style.backgroundColor = "#F5F5DC";
+// 
+// 			propStartCell.style.paddingLeft = "7px";
+// 			propStartCell.style.paddingRight = "2px";
+// 		
+// 			propEndCell.style.textAlign = "left";
+// 
+// 			propEndCell.style.paddingLeft = "7px";
+// 			propEndCell.style.paddingRight = "2px";
+// 
+// 			propEndCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propDirCell.style.textAlign = "left";
+// 			propDirCell.style.backgroundColor = "#F5F5DC";
+// 
+// 			propDirCell.style.paddingLeft = "5px";
+// 			propDirCell.style.paddingRight = "5px";
+// 		
+// 			rmvCell.style.textAlign = "left";
+// 			propNameCell.innerHTML = "Selectable Marker";
+// 
+// 			// Generate the list on the fly
+// 			if (createNew == "true")
+// 				propNamePrefix = rType + "_"
+// 			else
+// 				propNamePrefix = ""
+// 
+// // alert(createNew);
+// // alert(propNamePrefix);
+// // alert(propNamePrefix + "selectable_marker_list")
+// 
+// 			var tmpMarkerList = document.getElementById(propNamePrefix + "selectable_marker_list");
+// 			var markerSelectedInd = tmpMarkerList.selectedIndex;
+// 			var markerSelectedValue = tmpMarkerList[markerSelectedInd].value;
+// 
+// 			var newMarkerList = document.createElement("SELECT");
+// 			var newMarkerTxt =  document.createElement("INPUT");
+// 
+// 			newMarkerList.style.fontSize = "7pt";
+// 
+// // oct 27/08		newMarkerList.setAttribute("name", prefix + propName + postfix);
+// 
+// 			var rowIndex;
+// 
+// 			if (!document.getElementById(propNamePrefix + "selectable_marker_row_" + propRow.rowIndex + "_id"))
+// 			{
+// 				propRow.setAttribute('id', propNamePrefix + "selectable_marker_row_" + propRow.rowIndex + "_id");
+// 				rowIndex = propRow.rowIndex;
+// 			}
+// 			else
+// 			{
+// 				for (i = 0; i < propsTbl.rows.length; i++)
+// 				{
+// 					if (!document.getElementById(propNamePrefix + "selectable_marker_row_" + i + "_id"))
+// 					{
+// 						propRow.setAttribute('id', propNamePrefix + "selectable_marker_row_" + i + "_id");
+// 						break;
+// 					}
+// 				}
+// 
+// 				propRow.setAttribute('id', propNamePrefix + "selectable_marker_row_" + i + "_id");
+// 				rowIndex = i;
+// 			}
+// 
+// 			newMarkerList.setAttribute("id", propNamePrefix + propName + "_proplist_" + rowIndex);
+// 
+// 			newMarkerTxt.type = "TEXT";
+// 			newMarkerTxt.id = propNamePrefix + "selectable_marker_txt_" + rowIndex;
+// 			newMarkerTxt.style.display = "none";
+// 
+// 			newMarkerList.onchange = function(){this.setAttribute('name', propNamePrefix + propName + "_" + this[this.selectedIndex].value + "_" + rowIndex); showSpecificOtherTextbox(newMarkerList.id, newMarkerTxt.id);};	// oct 27/08
+// 
+// 			for (i = 0; i < tmpMarkerList.options.length; i++)
+// 			{
+// 				tmpOptn = tmpMarkerList.options[i];
+// 				newOptn = document.createElement("OPTION");
+// 
+// 				newOptn.value = tmpOptn.value;
+// 				newOptn.name = tmpOptn.name;
+// 				newOptn.text = tmpOptn.text;
+// 
+// 				if (newMarkerList.options.length == 0)
+// 					newMarkerList.options.add(newOptn);
+// 				else
+// 					addElement(newMarkerList, newMarkerList.options.length, newOptn);
+// 			}
+// 
+// 			propValueCell.appendChild(newMarkerList);
+// 			propValueCell.appendChild(newMarkerTxt);
+// 
+// 			var newMarkerStart = document.createElement("INPUT");
+// 			newMarkerStart.setAttribute("type", 'TEXT');
+// 			newMarkerStart.setAttribute("size", 5);
+// 			newMarkerStart.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_startpos_id");
+// 
+// 			newMarkerStart.style.fontSize = "7pt";
+// 			propStartCell.appendChild(newMarkerStart);
+// 			
+// 			var newMarkerEnd = document.createElement("INPUT");
+// 			newMarkerEnd.setAttribute("type", 'TEXT');
+// 			newMarkerEnd.setAttribute("size", 5);
+// 			newMarkerEnd.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_endpos_id");
+// 			newMarkerEnd.style.fontSize = "7pt";
+// 			propEndCell.appendChild(newMarkerEnd);
+// 
+// // 			newMarkerList.onchange = function()
+// // 			{
+// // 				showTagTypeBox(newTagTypeList.id, newTagTypeTxt.id);
+// // 			};
+// 
+// 			// Orientation - March 14/08: Make 'forward' checked by default
+// 			var fwdDir = document.createElement("INPUT");
+// 			fwdDir.setAttribute("type", "radio");
+// 			fwdDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_fwd_dir");
+// // 			fwdDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			fwdDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 			fwdDir.setAttribute("checked", true);
+// 
+// 			propDirCell.appendChild(fwdDir);
+// 			propDirCell.innerHTML += "Forward ";
+// 			propDirCell.style.fontSize = "7pt";
+// 			propDirCell.style.whiteSpace = "nowrap";
+// 
+// 			var revDir = document.createElement("INPUT");
+// 			revDir.setAttribute("type", "radio");
+// 			revDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_rev_dir");
+// // 			revDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			revDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 
+// 			propDirCell.appendChild(revDir);
+// 			propDirCell.innerHTML += "Reverse";
+// 
+// 			// Add 'Remove' link
+// 			var removeLink = document.createElement("SPAN");
+// 			removeLink.className = "linkShow";
+// 			removeLink.style.fontSize = "7pt";
+// 			removeLink.style.fontWeight = "normal";
+// 			removeLink.style.marginLeft = "5px";
+// 			removeLink.innerHTML = "Remove";
+// 		
+// 			rmvCell.appendChild(removeLink);
+// 		
+// // 			// Add list to form
+// // 			if (form_name == "")
+// // 				var myForm = document.reagentDetailForm;
+// // 			else
+// // 			{
+// // 				var myForm;
+// // 			
+// // 				docForms = document.forms;
+// // 			
+// // 				for (i = 0; i < docForms.length; i++)
+// // 				{
+// // 					aForm = docForms[i];
+// // 			
+// // 					if (aForm.name == form_name)
+// // 					{
+// // 						myForm = aForm;
+// // 						break;
+// // 					}
+// // 				}
+// // 			}
+// 
+// // 			var tblID = "modifyReagentPropsTbl";
+// 			var markerRowID = propRow.id;
+// 
+// 			var hiddenMarker = document.createElement("INPUT");
+// 			hiddenMarker.setAttribute("type", "hidden");
+// 			myForm.appendChild(hiddenMarker);
+// 
+// 			var hiddenMarkerStart = document.createElement("INPUT");
+// 			hiddenMarkerStart.setAttribute("type", "hidden");
+// 			hiddenMarkerStart.setAttribute("id", propNamePrefix + "selectable_marker_startpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMarkerStart);
+// 
+// 			var hiddenMarkerEnd = document.createElement("INPUT");
+// 			hiddenMarkerEnd.setAttribute("type", "hidden");
+// 			hiddenMarkerEnd.setAttribute("id", propNamePrefix + "selectable_marker_endpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMarkerEnd);
+// 
+// 			// Orientation
+// 			var hiddenMarkerDir = document.createElement("INPUT");
+// 			hiddenMarkerDir.setAttribute('type', 'hidden');
+// 			hiddenMarkerDir.setAttribute("id", propNamePrefix + "selectable_marker_orientation_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMarkerDir);
+// 
+// 			var elemList = new Array();
+// 			elemList.push(hiddenMarker);
+// 			elemList.push(hiddenMarkerStart);
+// 			elemList.push(hiddenMarkerEnd);
+// 			elemList.push(hiddenMarkerDir);
+// 
+// 			removeLink.onclick = function(){deleteTableRow(tblID, markerRowID); removeFormElements(myForm, elemList)};
+// 		break;
+// 
+// 		case 'polya':
+// 		case 'polyA':
+// 			var propRow = propsTbl.insertRow(propList.rowIndex - 2);
+// 		
+// 			// Need a few cells in the row
+// 			var propNameCell = propRow.insertCell(0);
+// 			var propValueCell = propRow.insertCell(1);
+// 			var propDescrCell = propRow.insertCell(2);
+// 			var propStartCell = propRow.insertCell(3);
+// 			var propEndCell = propRow.insertCell(4);
+// 			var propDirCell = propRow.insertCell(5);
+// 			var rmvCell = propRow.insertCell(6);
+// 		
+// 			// Format cells	
+// 			propNameCell.style.paddingLeft = "7px";
+// 			propNameCell.style.backgroundColor = "#F5F5DC";
+// 			propNameCell.style.fontSize = "7pt";
+// 		
+// 			propValueCell.style.paddingLeft = "7px";
+// 			propValueCell.style.paddingRight = "5px";
+// 			propValueCell.style.paddingTop = "1px";
+// 			propValueCell.style.paddingBottom = "1px";
+// 			propValueCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propDescrCell.style.paddingLeft = "7px";
+// 			propDescrCell.style.backgroundColor = "#F5F5DC";
+// 			propDescrCell.style.fontSize = "7pt";
+// 		
+// 			propStartCell.style.textAlign = "left";
+// 			propStartCell.style.backgroundColor = "#F5F5DC";
+// 
+// 			propStartCell.style.paddingLeft = "7px";
+// 			propStartCell.style.paddingRight = "2px";
+// 		
+// 			propEndCell.style.textAlign = "left";
+// 			propEndCell.style.backgroundColor = "#F5F5DC";
+// 
+// 			propEndCell.style.paddingLeft = "7px";
+// 			propEndCell.style.paddingRight = "2px";
+// 		
+// 			propDirCell.style.textAlign = "left";
+// 			propDirCell.style.backgroundColor = "#F5F5DC";
+// 
+// 			propDirCell.style.paddingLeft = "5px";
+// 			propDirCell.style.paddingRight = "5px";
+// 		
+// 			rmvCell.style.textAlign = "left";
+// 			propName = "polyA";
+// 
+// 			// Set cell content and formatting as required by template
+// 			propNameCell.innerHTML = "PolyA Tail";
+// 			
+// 			// Generate the list on the fly
+// 			if (createNew == "true")
+// 				propNamePrefix = rType + "_"
+// 			else
+// 				propNamePrefix = ""
+// 
+// 			var tmpPolyAList = document.getElementById(propNamePrefix + "polyA_list");
+// 			var polyASelectedInd = tmpPolyAList.selectedIndex;
+// 			var polyASelectedValue = tmpPolyAList[polyASelectedInd].value;
+// 
+// 			var newPolyAList = document.createElement("SELECT");
+// 			var newPolyATxt =  document.createElement("INPUT");
+// 
+// 			newPolyAList.style.fontSize = "7pt";
+// // 			newPolyAList.setAttribute("name", prefix + propName + postfix);
+// 
+// 			var rowIndex;
+// 
+// 			if (!document.getElementById(propNamePrefix + "polyA_row_" + propRow.rowIndex + "_id"))
+// 			{
+// 				propRow.setAttribute('id', propNamePrefix + "polyA_row_" + propRow.rowIndex + "_id");
+// 				rowIndex = propRow.rowIndex;
+// 			}
+// 			else
+// 			{
+// 				for (i = 0; i < propsTbl.rows.length; i++)
+// 				{
+// 					if (!document.getElementById(propNamePrefix + "polyA_row_" + i + "_id"))
+// 					{
+// 						propRow.setAttribute('id', propNamePrefix + "polyA_row_" + i + "_id");
+// 						break;
+// 					}
+// 				}
+// 
+// 				propRow.setAttribute('id', propNamePrefix + "polyA_row_" + i + "_id");
+// 				rowIndex = i;
+// 			}
+// 
+// 			newPolyAList.setAttribute("id", propNamePrefix + propName + "_proplist_" + rowIndex);
+// 
+// 			newPolyATxt.type = "TEXT";
+// 			newPolyATxt.id = propNamePrefix + "polyA_txt_" + rowIndex;
+// 			newPolyATxt.style.display = "none";
+// 
+// 			for (i = 0; i < tmpPolyAList.options.length; i++)
+// 			{
+// 				tmpOptn = tmpPolyAList.options[i];
+// 				newOptn = document.createElement("OPTION");
+// 
+// 				newOptn.value = tmpOptn.value;
+// 				newOptn.name = tmpOptn.name;
+// 				newOptn.text = tmpOptn.text;
+// 
+// 				if (newPolyAList.options.length == 0)
+// 					newPolyAList.options.add(newOptn);
+// 				else
+// 					addElement(newPolyAList, newPolyAList.options.length, newOptn);
+// 			}
+// 
+// 			propValueCell.appendChild(newPolyAList);
+// 			propValueCell.appendChild(newPolyATxt);
+// 
+// 			// Start & stop positions
+// 			var newPolyAStart = document.createElement("INPUT");
+// 			newPolyAStart.setAttribute("type", 'TEXT');
+// 			newPolyAStart.setAttribute("size", 5);
+// 			newPolyAStart.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_startpos_id");
+// 			newPolyAStart.style.fontSize = "7pt";
+// 
+// 			propStartCell.appendChild(newPolyAStart);
+// 
+// 			var newPolyAEnd = document.createElement("INPUT");
+// 			newPolyAEnd.setAttribute("type", 'TEXT');
+// 			newPolyAEnd.setAttribute("size", 5);
+// 			newPolyAEnd.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_endpos_id");
+// 			newPolyAEnd.style.fontSize = "7pt";
+// 
+// 			propEndCell.appendChild(newPolyAEnd);
+// 
+// 			newPolyAList.onchange = function(){this.setAttribute('name', propNamePrefix + propName + "_" + this[this.selectedIndex].value + "_" + rowIndex); showSpecificOtherTextbox(newPolyAList.id, newPolyATxt.id);};
+// 
+// 			// Orientation
+// 			var fwdDir = document.createElement("INPUT");
+// 			fwdDir.setAttribute("type", "radio");
+// 			fwdDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_fwd_dir");
+// // 			fwdDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			fwdDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 
+// 			fwdDir.setAttribute("checked", true);
+// 
+// 			propDirCell.appendChild(fwdDir);
+// 			propDirCell.innerHTML += "Forward ";
+// 			propDirCell.style.fontSize = "7pt";
+// 
+// 			var revDir = document.createElement("INPUT");
+// 			revDir.setAttribute("type", "radio");
+// 			revDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_rev_dir");
+// // 			revDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			revDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 
+// 			propDirCell.appendChild(revDir);
+// 			propDirCell.innerHTML += "Reverse";
+// 			propDirCell.style.fontSize = "7pt";
+// 			propDirCell.style.whiteSpace = "nowrap";
+// 
+// 			// Add 'Remove' link
+// 			var removeLink = document.createElement("SPAN");
+// 			removeLink.className = "linkShow";
+// 			removeLink.style.fontSize = "7pt";
+// 			removeLink.style.fontWeight = "normal";
+// 			removeLink.style.marginLeft = "5px";
+// 			removeLink.innerHTML = "Remove";
+// 			rmvCell.appendChild(removeLink);
+// 
+// 			// Adjust border height to stretch to bottom of page
+// // 			mainBorder = document.getElementById("mainBorder");
+// // 			mainBorder.height = document.height;
+// // 			mainBorder.rowSpan = propsTbl.rows.length;
+// 		
+// 			// Add a separator row
+// // 			var divRow = propsTbl.insertRow(tmpPolyPosRow.rowIndex + 1);
+// // 			var divCell = divRow.insertCell(0);
+// // 
+// // 			divRow.setAttribute('id', "div_row" + divRow.rowIndex + "_id");
+// // 			divCell.colSpan = 6;
+// // 			divCell.innerHTML = "<HR>";
+// 
+// 			// Gather the IDs of all elements in the row to pass to 'deleteRow' function
+// // 			var tblID = "modifyReagentPropsTbl";
+// 			var polyARowID = propRow.id;
+// // 			var divRowID = divRow.id;
+// 		
+// // 			// Add list to form
+// // 			if (form_name == "")
+// // 				var myForm = document.reagentDetailForm;
+// // 			else
+// // 			{
+// // 				var myForm;
+// // 			
+// // 				docForms = document.forms;
+// // 			
+// // 				for (i = 0; i < docForms.length; i++)
+// // 				{
+// // 					aForm = docForms[i];
+// // 			
+// // 					if (aForm.name == form_name)
+// // 					{
+// // 						myForm = aForm;
+// // 						break;
+// // 					}
+// // 				}
+// // 			}
+// 
+// 			var hiddenPolyA = document.createElement("INPUT");
+// 			hiddenPolyA.setAttribute("type", "hidden");
+// 			myForm.appendChild(hiddenPolyA);
+// 
+// 			var hiddenPolyAStart = document.createElement("INPUT");
+// 			hiddenPolyAStart.setAttribute("type", "hidden");
+// 			hiddenPolyAStart.setAttribute("id", propNamePrefix + "polyA_startpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenPolyAStart);
+// 
+// 			var hiddenPolyAEnd = document.createElement("INPUT");
+// 			hiddenPolyAEnd.setAttribute("type", "hidden");
+// 			hiddenPolyAEnd.setAttribute("id", propNamePrefix + "polyA_endpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenPolyAEnd);
+// 
+// 			// Orientation
+// 			var hiddenPolyADir = document.createElement("INPUT");
+// 			hiddenPolyADir.setAttribute('type', 'hidden');
+// 			hiddenPolyADir.setAttribute("id", propNamePrefix + "polyA_orientation_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenPolyADir);
+// 
+// 			var elemList = new Array();
+// 			elemList.push(hiddenPolyA);
+// 			elemList.push(hiddenPolyAStart);
+// 			elemList.push(hiddenPolyAEnd);
+// 			elemList.push(hiddenPolyADir);
+// 
+// // 			removeLink.onclick = function(){deleteRow(tblID, polyARowID); deleteRow(tblID, tmpPolyPosRowID); deleteRow(tblID, divRowID); removeFormElements(myForm, elemList)};
+// 
+// 			removeLink.onclick = function(){deleteTableRow(tblID, polyARowID); removeFormElements(myForm, elemList)};
+// 		break;
+// 	
+// 		case 'origin_of_replication':
+// 			var propRow = propsTbl.insertRow(propList.rowIndex - 2);
+// 		
+// 			// Need a few cells in the row
+// 			var propNameCell = propRow.insertCell(0);
+// 			var propValueCell = propRow.insertCell(1);
+// 			var propDescrCell = propRow.insertCell(2);
+// 			var propStartCell = propRow.insertCell(3);
+// 			var propEndCell = propRow.insertCell(4);
+// 			var propDirCell = propRow.insertCell(5);
+// 			var rmvCell = propRow.insertCell(6);
+// 		
+// 			// Format cells	
+// 			propNameCell.style.paddingLeft = "7px";
+// 			propNameCell.style.backgroundColor = "#F5F5DC";
+// 			propNameCell.style.fontSize = "7pt";
+// 
+// 			propValueCell.style.paddingLeft = "7px";
+// 			propValueCell.style.paddingRight = "5px";
+// 			propValueCell.style.paddingTop = "1px";
+// 			propValueCell.style.paddingBottom = "1px";
+// 			propValueCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propDescrCell.style.paddingLeft = "7px";
+// 			propDescrCell.style.backgroundColor = "#F5F5DC";
+// 			propDescrCell.style.fontSize = "7pt";
+// 		
+// 			propStartCell.style.textAlign = "left";
+// 
+// 			propStartCell.style.paddingLeft = "7px";
+// 			propStartCell.style.paddingRight = "2px";
+// 
+// 			propStartCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propEndCell.style.textAlign = "left";
+// 
+// 			propEndCell.style.paddingLeft = "7px";
+// 			propEndCell.style.paddingRight = "2px";
+// 
+// 			propEndCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propDirCell.style.textAlign = "left";
+// 
+// 			propDirCell.style.paddingLeft = "5px";
+// 			propDirCell.style.paddingRight = "5px";
+// 
+// 			propDirCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			rmvCell.style.textAlign = "left";
+// // 			var propRow = propsTbl.insertRow(propList.rowIndex - 1);
+// 		
+// 			// Need a few cells in the row
+// // 			var propNameCell = propRow.insertCell(0);
+// // 			var propValueCell = propRow.insertCell(1);
+// 
+// 			// Set cell content and formatting as required by template
+// // 			propNameCell.className = "detailedView_colName";
+// 			propNameCell.innerHTML = "Origin of Replication";
+// 		
+// // 			propValueCell.className = "detailedView_value";
+// // 			propValueCell.setAttribute("white-space", "nowrap");
+// // 			propValueCell.style.fontSize = "9pt";
+// // 			propValueCell.colSpan = 5;
+// // 			propValueCell.style.paddingLeft = "5px";
+// 			
+// 			// Generate the list on the fly
+// 			if (createNew == "true")
+// 				propNamePrefix = rType + "_"
+// 			else
+// 				propNamePrefix = ""
+// 
+// 			var tmpOriginList = document.getElementById(propNamePrefix + "origin_of_replication_list");
+// 			var originSelectedInd = tmpOriginList.selectedIndex;
+// 			var originSelectedValue = tmpOriginList[originSelectedInd].value;
+// 
+// 			var newOriginList = document.createElement("SELECT");
+// 			var newOriginTxt =  document.createElement("INPUT");
+// 			newOriginList.style.fontSize = "7pt";
+// 
+// // 			newOriginList.setAttribute("name", prefix + propName + postfix);
+// 
+// 			var rowIndex;
+// 
+// 			if (!document.getElementById(propNamePrefix + "origin_of_replication_row_" + propRow.rowIndex + "_id"))
+// 			{
+// 				propRow.setAttribute('id', propNamePrefix + "origin_of_replication_row_" + propRow.rowIndex + "_id");
+// 				rowIndex = propRow.rowIndex;
+// 			}
+// 			else
+// 			{
+// 				for (i = 0; i < propsTbl.rows.length; i++)
+// 				{
+// 					if (!document.getElementById(propNamePrefix + "origin_of_replication_row_" + i + "_id"))
+// 					{
+// 						propRow.setAttribute('id', propNamePrefix + "origin_of_replication_row_" + i + "_id");
+// 						break;
+// 					}
+// 				}
+// 
+// 				propRow.setAttribute('id', propNamePrefix + "origin_of_replication_row_" + i + "_id");
+// 				rowIndex = i;
+// 			}
+// 
+// 			newOriginList.setAttribute("id", propNamePrefix + propName + "_proplist_" + rowIndex);
+// 
+// // 			propRow.setAttribute('id', "origin_row_" + propRow.rowIndex + "_id");
+// 
+// 			newOriginTxt.type = "TEXT";
+// 			newOriginTxt.id = propNamePrefix + "origin_of_replication_txt_" + rowIndex;
+// 			newOriginTxt.style.display = "none";
+// 
+// 			for (i = 0; i < tmpOriginList.options.length; i++)
+// 			{
+// 				tmpOptn = tmpOriginList.options[i];
+// 				newOptn = document.createElement("OPTION");
+// 
+// 				newOptn.value = tmpOptn.value;
+// 				newOptn.name = tmpOptn.name;
+// 				newOptn.text = tmpOptn.text;
+// 
+// 				if (newOriginList.options.length == 0)
+// 					newOriginList.options.add(newOptn);
+// 				else
+// 					addElement(newOriginList, newOriginList.options.length, newOptn);
+// 			}
+// 
+// 			propValueCell.appendChild(newOriginList);
+// 			propValueCell.appendChild(newOriginTxt);
+// 
+// 			// Start & stop positions
+// 			// April 2/08: Karen asked to show positions and orientation on a new line for ALL features
+// // 			var tmpOriginPosRow = propsTbl.insertRow(propRow.rowIndex+1);
+// // 			tmpOriginPosRow.setAttribute('id', "origin_pos_row" + tmpOriginPosRow.rowIndex + "_id");
+// // 			var tmpOriginPosRowID = tmpOriginPosRow.id;
+// // 
+// // 			var c1 = tmpOriginPosRow.insertCell(0);
+// // 			var originPosCell = tmpOriginPosRow.insertCell(1);
+// // 
+// // 			originPosCell.className = "detailedView_value";
+// // 			originPosCell.style.paddingLeft = "5px";
+// // 			originPosCell.setAttribute("white-space", "nowrap");
+// // 			originPosCell.colSpan = 5;
+// // 
+// // 			originPosCell.innerHTML += "Start: ";
+// 
+// // 			propValueCell.innerHTML += "<SPAN style=\"margin-left:8px;\"></span>Start: ";
+// 			
+// 			var newOriginStart = document.createElement("INPUT");
+// 			newOriginStart.setAttribute("type", 'TEXT');
+// 			newOriginStart.setAttribute("size", 5);
+// 			newOriginStart.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_startpos_id");
+// 			newOriginStart.style.fontSize = "7pt";
+// // 			originPosCell.appendChild(newOriginStart);
+// 			propStartCell.appendChild(newOriginStart);
+// 
+// // 			originPosCell.innerHTML += "  End: ";
+// 			
+// 			var newOriginEnd = document.createElement("INPUT");
+// 			newOriginEnd.setAttribute("type", 'TEXT');
+// 			newOriginEnd.setAttribute("size", 5);
+// 			newOriginEnd.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_endpos_id");
+// 			newOriginEnd.style.fontSize = "7pt";
+// // 			originPosCell.appendChild(newOriginEnd);
+// 			propEndCell.appendChild(newOriginEnd);
+// 
+// 			newOriginList.onchange = function(){this.setAttribute('name', propNamePrefix + propName + "_" + this[this.selectedIndex].value + "_" + rowIndex); showSpecificOtherTextbox(newOriginList.id, newOriginTxt.id);};
+// 			{
+// // 				showTagTypeBox(newTagTypeList.id, newTagTypeTxt.id);
+// 			};
+// 
+// 			// Orientation - March 14/08: Make 'forward' checked by default
+// // 			originPosCell.innerHTML += "<SPAN style=\"margin-left:10px;\"></span>";
+// 
+// 			var fwdDir = document.createElement("INPUT");
+// 			fwdDir.setAttribute("type", "radio");
+// 			fwdDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_fwd_dir");
+// 			fwdDir.setAttribute("name", propNamePrefix + propName + "_orientation_radio_" + rowIndex);
+// 			fwdDir.setAttribute("checked", true);
+// 
+// // 			originPosCell.appendChild(fwdDir);
+// // 			originPosCell.innerHTML += "Forward ";
+// 			propDirCell.appendChild(fwdDir);
+// 			propDirCell.innerHTML += "Forward ";
+// 			propDirCell.style.fontSize = "7pt";
+// 			propDirCell.style.whiteSpace = "nowrap";
+// 
+// 			var revDir = document.createElement("INPUT");
+// 			revDir.setAttribute("type", "radio");
+// 			revDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_rev_dir");
+// 			revDir.setAttribute("name", propNamePrefix + propName + "_orientation_radio_" + rowIndex);
+// 
+// // 			originPosCell.appendChild(revDir);
+// // 			originPosCell.innerHTML += "Reverse";
+// 			propDirCell.appendChild(revDir);
+// 			propDirCell.innerHTML += "Reverse";
+// 
+// 			// Add 'Remove' link
+// 			var removeLink = document.createElement("SPAN");
+// 			removeLink.className = "linkShow";
+// 			removeLink.style.fontSize = "7pt";
+// 			removeLink.style.fontWeight = "normal";
+// 			removeLink.style.marginLeft = "5px";
+// 			removeLink.innerHTML = "Remove";
+// 		
+// // 			originPosCell.appendChild(removeLink);
+// 			rmvCell.appendChild(removeLink);
+// 
+// 			// Adjust border height to stretch to bottom of page
+// // 			mainBorder = document.getElementById("mainBorder");
+// // 			mainBorder.height = document.height;
+// // 			mainBorder.rowSpan = propsTbl.rows.length;
+// 		
+// 			// Add a separator row
+// // 			var divRow = propsTbl.insertRow(tmpOriginPosRow.rowIndex + 1);
+// // 			var divCell = divRow.insertCell(0);
+// 
+// // 			divRow.setAttribute('id', "div_row" + divRow.rowIndex + "_id");
+// // 			divCell.colSpan = 6;
+// // 			divCell.innerHTML = "<HR>";
+// 
+// 			// 'Remove' link
+// // 			var tblID = "modifyReagentPropsTbl";
+// 			var originRowID = propRow.id;
+// // 			var divRowID = divRow.id;
+// 		
+// // 			// Add list to form
+// // 			if (form_name == "")
+// // 				var myForm = document.reagentDetailForm;
+// // 			else
+// // 			{
+// // 				var myForm;
+// // 			
+// // 				docForms = document.forms;
+// // 			
+// // 				for (i = 0; i < docForms.length; i++)
+// // 				{
+// // 					aForm = docForms[i];
+// // 			
+// // 					if (aForm.name == form_name)
+// // 					{
+// // 						myForm = aForm;
+// // 						break;
+// // 					}
+// // 				}
+// // 			}
+// 
+// 			var hiddenOrigin = document.createElement("INPUT");
+// 			hiddenOrigin.setAttribute("type", "hidden");
+// 			myForm.appendChild(hiddenOrigin);
+// 
+// 			var hiddenOriginStart = document.createElement("INPUT");
+// 			hiddenOriginStart.setAttribute("type", "hidden");
+// 			hiddenOriginStart.setAttribute("id", propNamePrefix + "origin_of_replication_startpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenOriginStart);
+// 
+// 			var hiddenOriginEnd = document.createElement("INPUT");
+// 			hiddenOriginEnd.setAttribute("type", "hidden");
+// 			hiddenOriginEnd.setAttribute("id", propNamePrefix + "origin_of_replication_endpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenOriginEnd);
+// 
+// 			// Orientation
+// 			var hiddenOriginDir = document.createElement("INPUT");
+// 			hiddenOriginDir.setAttribute('type', 'hidden');
+// 			hiddenOriginDir.setAttribute("id", propNamePrefix + "origin_of_replication_orientation_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenOriginDir);
+// 
+// 			var elemList = new Array();
+// 			elemList.push(hiddenOrigin);
+// 			elemList.push(hiddenOriginStart);
+// 			elemList.push(hiddenOriginEnd);
+// 			elemList.push(hiddenOriginDir);
+// 
+// // 			removeLink.onclick = function(){deleteRow(tblID, originRowID); deleteRow(tblID, tmpOriginPosRowID); deleteRow(tblID, divRowID); removeFormElements(myForm, elemList)};
+// 
+// 			removeLink.onclick = function(){deleteTableRow(tblID, originRowID); removeFormElements(myForm, elemList)};
+// 		break;
+// 
+// 		case 'miscellaneous':
+// 			var propRow = propsTbl.insertRow(propList.rowIndex - 2);
+// 		
+// 			var propNameCell = propRow.insertCell(0);
+// 			var propValueCell = propRow.insertCell(1);
+// 			var propDescrCell = propRow.insertCell(2);
+// 			var propStartCell = propRow.insertCell(3);
+// 			var propEndCell = propRow.insertCell(4);
+// 			var propDirCell = propRow.insertCell(5);
+// 			var rmvCell = propRow.insertCell(6);
+// 		
+// 			// Format cells
+// 			propNameCell.style.paddingLeft = "7px";
+// 			propNameCell.style.backgroundColor = "#F5F5DC";
+// 			propNameCell.style.fontSize = "7pt";
+// 
+// 			propValueCell.style.paddingLeft = "7px";
+// 			propValueCell.style.paddingRight = "5px";
+// 			propValueCell.style.paddingTop = "1px";
+// 			propValueCell.style.paddingBottom = "1px";
+// 			propValueCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propDescrCell.style.paddingLeft = "7px";
+// 			propDescrCell.style.backgroundColor = "#F5F5DC";
+// 			propDescrCell.style.fontSize = "7pt";
+// 		
+// 			propStartCell.style.textAlign = "left";
+// 
+// 			propStartCell.style.paddingLeft = "7px";
+// 			propStartCell.style.paddingRight = "2px";
+// 
+// 			propStartCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propEndCell.style.textAlign = "left";
+// 			propEndCell.style.backgroundColor = "#F5F5DC";
+// 
+// 			propEndCell.style.paddingLeft = "7px";
+// 			propEndCell.style.paddingRight = "2px";
+// 		
+// 			propDirCell.style.textAlign = "left";
+// 
+// 			propDirCell.style.paddingLeft = "5px";
+// 			propDirCell.style.paddingRight = "5px";
+// 
+// 			propDirCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			rmvCell.style.textAlign = "left";
+// 
+// 			propNameCell.innerHTML = "Miscellaneous";
+// 
+// 			// Generate the list on the fly
+// 			if (createNew == "true")
+// 				propNamePrefix = rType + "_"
+// 			else
+// 				propNamePrefix = ""
+// 
+// 			var tmpMiscList = document.getElementById(propNamePrefix + "miscellaneous_list");
+// 			var miscSelectedInd = tmpMiscList.selectedIndex;
+// 			var miscSelectedValue = tmpMiscList[miscSelectedInd].value;
+// 
+// 			var newMiscList = document.createElement("SELECT");
+// 			var newMiscTxt =  document.createElement("INPUT");
+// 
+// 			var rowIndex;
+// 
+// 			if (!document.getElementById(propNamePrefix+ "miscellaneous_row_" + propRow.rowIndex + "_id"))
+// 			{
+// 				propRow.setAttribute('id', propNamePrefix + "miscellaneous_row_" + propRow.rowIndex + "_id");
+// 				rowIndex = propRow.rowIndex;
+// 			}
+// 			else
+// 			{
+// 				for (i = 0; i < propsTbl.rows.length; i++)
+// 				{
+// 					if (!document.getElementById(propNamePrefix + "miscellaneous_row_" + i + "_id"))
+// 					{
+// 						propRow.setAttribute('id', propNamePrefix + "miscellaneous_row_" + i + "_id");
+// 						break;
+// 					}
+// 				}
+// 
+// 				propRow.setAttribute('id', propNamePrefix + "miscellaneous_row_" + i + "_id");
+// 				rowIndex = i;
+// 			}
+// 
+// 			newMiscList.setAttribute("id", propNamePrefix + propName + "_proplist_" + rowIndex);
+// 			newMiscList.style.fontSize = "7pt";
+// 
+// 			newMiscTxt.type = "TEXT";
+// 			newMiscTxt.id = propNamePrefix + "miscellaneous_txt_" + rowIndex;
+// 			newMiscTxt.style.display = "none";
+// 
+// 			for (i = 0; i < tmpMiscList.options.length; i++)
+// 			{
+// 				tmpOptn = tmpMiscList.options[i];
+// 				newOptn = document.createElement("OPTION");
+// 
+// 				newOptn.value = tmpOptn.value;
+// 				newOptn.name = tmpOptn.name;
+// 				newOptn.text = tmpOptn.text;
+// 
+// 				if (newMiscList.options.length == 0)
+// 					newMiscList.options.add(newOptn);
+// 				else
+// 					addElement(newMiscList, newMiscList.options.length, newOptn);
+// 			}
+// 
+// 			propValueCell.appendChild(newMiscList);
+// 			propValueCell.appendChild(newMiscTxt);
+// 
+// 			var newMiscStart = document.createElement("INPUT");
+// 			newMiscStart.setAttribute("type", 'TEXT');
+// 			newMiscStart.setAttribute("size", 5);
+// 			newMiscStart.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_startpos_id");
+// 			newMiscStart.style.fontSize = "7pt";
+// 			propStartCell.appendChild(newMiscStart);
+// 			
+// 			var newMiscEnd = document.createElement("INPUT");
+// 			newMiscEnd.setAttribute("type", 'TEXT');
+// 			newMiscEnd.setAttribute("size", 5);
+// 			newMiscEnd.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_endpos_id");
+// 			newMiscEnd.style.fontSize = "7pt";
+// 			propEndCell.appendChild(newMiscEnd);
+// 
+// 			newMiscList.onchange = function(){this.setAttribute('name', propNamePrefix + propName + "_" + this[this.selectedIndex].value + "_" + rowIndex); showSpecificOtherTextbox(newMiscList.id, newMiscTxt.id);};
+// 
+// 			// Orientation
+// 			var fwdDir = document.createElement("INPUT");
+// 			fwdDir.setAttribute("type", "radio");
+// 			fwdDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_fwd_dir");
+// // 			fwdDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			fwdDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 			fwdDir.setAttribute("checked", true);
+// 
+// // 			miscPosCell.appendChild(fwdDir);
+// 			propDirCell.appendChild(fwdDir);
+// // 			miscPosCell.innerHTML += "Forward ";
+// 			propDirCell.innerHTML += "Forward ";
+// 
+// 			var revDir = document.createElement("INPUT");
+// 			revDir.setAttribute("type", "radio");
+// 			revDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_rev_dir");
+// // 			revDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			revDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 
+// // 			miscPosCell.appendChild(revDir);
+// // 			miscPosCell.innerHTML += "Reverse";
+// 			propDirCell.appendChild(revDir);
+// 			propDirCell.innerHTML += "Reverse";
+// 			propDirCell.style.fontSize = "7pt";
+// 			propDirCell.style.whiteSpace = "nowrap";
+// 
+// 			// Add 'Remove' link
+// 			var removeLink = document.createElement("SPAN");
+// 			removeLink.className = "linkShow";
+// 			removeLink.style.fontSize = "7pt";
+// 			removeLink.style.fontWeight = "normal";
+// 			removeLink.style.marginLeft = "5px";
+// 			removeLink.innerHTML = "Remove";
+// 		
+// // 			miscPosCell.appendChild(removeLink);
+// 			rmvCell.appendChild(removeLink);
+// 
+// 			// Adjust border height to stretch to bottom of page
+// // 			mainBorder = document.getElementById("mainBorder");
+// // 			mainBorder.height = document.height;
+// // 			mainBorder.rowSpan = propsTbl.rows.length;
+// 		
+// 			// Add a separator row
+// // 			var divRow = propsTbl.insertRow(rowIndex + 1);
+// // 			var divCell = divRow.insertCell(0);
+// 
+// // 			divRow.setAttribute('id', "div_row" + divRow.rowIndex + "_id");
+// // 			divCell.colSpan = 6;
+// // 			divCell.innerHTML = "<HR>";
+// 
+// 			// 'Remove' link
+// // 			var tblID = "modifyReagentPropsTbl";
+// 			var miscRowID = propRow.id;
+// // 			var divRowID = divRow.id;
+// 		
+// // 			// Add list to form
+// // 			if (form_name == "")
+// // 				var myForm = document.reagentDetailForm;
+// // 			else
+// // 			{
+// // 				var myForm;
+// // 			
+// // 				docForms = document.forms;
+// // 			
+// // 				for (i = 0; i < docForms.length; i++)
+// // 				{
+// // 					aForm = docForms[i];
+// // 			
+// // 					if (aForm.name == form_name)
+// // 					{
+// // 						myForm = aForm;
+// // 						break;
+// // 					}
+// // 				}
+// // 			}
+// 
+// 			var hiddenMisc = document.createElement("INPUT");
+// 			hiddenMisc.setAttribute("type", "hidden");
+// 			myForm.appendChild(hiddenMisc);
+// 
+// 			var hiddenMiscStart = document.createElement("INPUT");
+// 			hiddenMiscStart.setAttribute("type", "hidden");
+// 			hiddenMiscStart.setAttribute("id", propNamePrefix + "miscellaneous_startpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMiscStart);
+// 
+// 			var hiddenMiscEnd = document.createElement("INPUT");
+// 			hiddenMiscEnd.setAttribute("type", "hidden");
+// 			hiddenMiscEnd.setAttribute("id", propNamePrefix + "miscellaneous_endpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMiscEnd);
+// 
+// 			// Orientation
+// 			var hiddenMiscDir = document.createElement("INPUT");
+// 			hiddenMiscDir.setAttribute('type', 'hidden');
+// 			hiddenMiscDir.setAttribute("id", propNamePrefix + "miscellaneous_orientation_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMiscDir);
+// 
+// 			var elemList = new Array();
+// 			elemList.push(hiddenMisc);
+// 			elemList.push(hiddenMiscStart);
+// 			elemList.push(hiddenMiscEnd);
+// 			elemList.push(hiddenMiscDir);
+// 
+// // 			removeLink.onclick = function(){deleteRow(tblID, miscRowID); deleteRow(tblID, miscPosRowID); deleteRow(tblID, divRowID); removeFormElements(myForm, elemList)};
+// 			removeLink.onclick = function(){deleteTableRow(tblID, miscRowID); removeFormElements(myForm, elemList)};
+// 
+// 		break;
+// 
+// 		case 'cleavage_site':
+// 			var propRow = propsTbl.insertRow(propList.rowIndex - 2);
+// 		
+// // 			// Need a few cells in the row
+// // 			var propNameCell = propRow.insertCell(0);
+// // 			var propValueCell = propRow.insertCell(1);
+// // 
+// // 			// Set cell content and formatting as required by template
+// // 			propNameCell.className = "detailedView_colName";
+// 
+// 			var propNameCell = propRow.insertCell(0);
+// 			var propValueCell = propRow.insertCell(1);
+// 			var propDescrCell = propRow.insertCell(2);
+// 			var propStartCell = propRow.insertCell(3);
+// 			var propEndCell = propRow.insertCell(4);
+// 			var propDirCell = propRow.insertCell(5);
+// 			var rmvCell = propRow.insertCell(6);
+// 		
+// 			// Format cells	
+// 			propNameCell.style.paddingLeft = "7px";
+// 			propNameCell.style.backgroundColor = "#F5F5DC";
+// 			propNameCell.style.fontSize = "7pt";
+// 
+// 			propValueCell.style.paddingLeft = "7px";
+// 			propValueCell.style.paddingRight = "5px";
+// 			propValueCell.style.paddingTop = "1px";
+// 			propValueCell.style.paddingBottom = "1px";
+// 			propValueCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propDescrCell.style.paddingLeft = "7px";
+// 			propDescrCell.style.backgroundColor = "#F5F5DC";
+// 			propDescrCell.style.fontSize = "7pt";
+// 			propStartCell.style.textAlign = "left";
+// 
+// 			propStartCell.style.paddingLeft = "7px";
+// 			propStartCell.style.paddingRight = "2px";
+// 
+// 			propStartCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propEndCell.style.textAlign = "left";
+// 			propEndCell.style.backgroundColor = "#F5F5DC";
+// 
+// 			propEndCell.style.paddingLeft = "7px";
+// 			propEndCell.style.paddingRight = "2px";
+// 		
+// 			propDirCell.style.textAlign = "left";
+// 
+// 			propDirCell.style.paddingLeft = "5px";
+// 			propDirCell.style.paddingRight = "5px";
+// 
+// 			propDirCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			rmvCell.style.textAlign = "left";
+// 
+// 			propNameCell.innerHTML = "Cleavage Site";
+// // 		
+// // 			propValueCell.className = "detailedView_value";
+// // 			propValueCell.setAttribute("white-space", "nowrap");
+// // 			propValueCell.style.fontSize = "9pt";
+// // 			propValueCell.colSpan = 5;
+// // 			propValueCell.style.paddingLeft = "5px";
+// 			
+// 			// Generate the list on the fly
+// 			if (createNew == "true")
+// 				propNamePrefix = rType + "_"
+// 			else
+// 				propNamePrefix = ""
+// 
+// 			var tmpMiscList = document.getElementById(propNamePrefix + "cleavage_site_list");
+// 			var miscSelectedInd = tmpMiscList.selectedIndex;
+// 			var miscSelectedValue = tmpMiscList[miscSelectedInd].value;
+// 
+// 			var newMiscList = document.createElement("SELECT");
+// 			var newMiscTxt =  document.createElement("INPUT");
+// 			
+// // 			newMiscList.setAttribute("name", prefix + propName + postfix);
+// 
+// 			var rowIndex;
+// 
+// 			if (!document.getElementById(propNamePrefix + "cleavage_site_row_" + propRow.rowIndex + "_id"))
+// 			{
+// 				propRow.setAttribute('id', propNamePrefix + "cleavage_site_row_" + propRow.rowIndex + "_id");
+// 				rowIndex = propRow.rowIndex;
+// 			}
+// 			else
+// 			{
+// 				for (i = 0; i < propsTbl.rows.length; i++)
+// 				{
+// 					if (!document.getElementById(propNamePrefix + "cleavage_site_row_" + i + "_id"))
+// 					{
+// 						propRow.setAttribute('id', propNamePrefix + "cleavage_site_row_" + i + "_id");
+// 						break;
+// 					}
+// 				}
+// 
+// 				propRow.setAttribute('id', "cleavage_site_row_" + i + "_id");
+// 				rowIndex = i;
+// 			}
+// 
+// 			newMiscList.setAttribute("id", propNamePrefix + propName + "_proplist_" + rowIndex);
+// 			newMiscList.style.fontSize = "7pt";
+// 
+// // 			propRow.setAttribute('id', "miscellaneous_row_" + propRow.rowIndex + "_id");
+// 
+// 			newMiscTxt.type = "TEXT";
+// 			newMiscTxt.id = propNamePrefix + "cleavage_site_txt_" + (rowIndex - 1);
+// 			newMiscTxt.style.display = "none";
+// 
+// 			for (i = 0; i < tmpMiscList.options.length; i++)
+// 			{
+// 				tmpOptn = tmpMiscList.options[i];
+// 				newOptn = document.createElement("OPTION");
+// 
+// 				newOptn.value = tmpOptn.value;
+// 				newOptn.name = tmpOptn.name;
+// 				newOptn.text = tmpOptn.text;
+// 
+// 				if (newMiscList.options.length == 0)
+// 					newMiscList.options.add(newOptn);
+// 				else
+// 					addElement(newMiscList, newMiscList.options.length, newOptn);
+// 			}
+// 
+// 			propValueCell.appendChild(newMiscList);
+// 			propValueCell.appendChild(newMiscTxt);
+// 
+// 			// Start & stop positions
+// 			// April 1, 2008: Show in a new row
+// // 			var miscPosRow = propsTbl.insertRow(rowIndex+1);
+// // 			miscPosRow.setAttribute('id', "miscellaneous_pos_row" + rowIndex + "_id");
+// // 			var miscPosRowID = miscPosRow.id;
+// // 
+// // 			var c1 = miscPosRow.insertCell(0);
+// // 			var miscPosCell = miscPosRow.insertCell(1);
+// // 
+// // 			miscPosCell.className = "detailedView_value";
+// // 			miscPosCell.style.paddingLeft = "5px";
+// // 			miscPosCell.colSpan = 5;
+// // 			miscPosCell.setAttribute("white-space", "nowrap");
+// 
+// // 			miscPosCell.innerHTML = "Start: ";
+// 
+// 			var newMiscStart = document.createElement("INPUT");
+// 			newMiscStart.setAttribute("type", 'TEXT');
+// 			newMiscStart.setAttribute("size", 5);
+// 			newMiscStart.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_startpos_id");
+// 			newMiscStart.style.fontSize = "7pt";
+// 
+// // 			miscPosCell.appendChild(newMiscStart);
+// 			propStartCell.appendChild(newMiscStart);
+// 
+// // 			miscPosCell.innerHTML += "  End: ";
+// 			
+// 			var newMiscEnd = document.createElement("INPUT");
+// 			newMiscEnd.setAttribute("type", 'TEXT');
+// 			newMiscEnd.setAttribute("size", 5);
+// 			newMiscEnd.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_endpos_id");
+// 			newMiscEnd.style.fontSize = "7pt";
+// 
+// // 			miscPosCell.appendChild(newMiscEnd);
+// 			propEndCell.appendChild(newMiscEnd);
+// 
+// // 			newMiscList.onchange = function()
+// // 			{
+// // // 				showTagTypeBox(newTagTypeList.id, newTagTypeTxt.id);
+// // 			};
+// 			newMiscList.onchange = function(){this.setAttribute('name', propNamePrefix + propName + "_" + this[this.selectedIndex].value + "_" + rowIndex);};
+// 
+// 			// Orientation - March 14/08: Make 'forward' checked by default
+// // 			miscPosCell.innerHTML += "<SPAN style=\"margin-left:10px;\"></span>";
+// 
+// 			var fwdDir = document.createElement("INPUT");
+// 			fwdDir.setAttribute("type", "radio");
+// 			fwdDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_fwd_dir");
+// // 			fwdDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			fwdDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 			fwdDir.setAttribute("checked", true);
+// 
+// // 			miscPosCell.appendChild(fwdDir);
+// 			propDirCell.appendChild(fwdDir);
+// // 			miscPosCell.innerHTML += "Forward ";
+// 			propDirCell.innerHTML += "Forward ";
+// 
+// 			var revDir = document.createElement("INPUT");
+// 			revDir.setAttribute("type", "radio");
+// 			revDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_rev_dir");
+// // 			revDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			revDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 
+// // 			miscPosCell.appendChild(revDir);
+// // 			miscPosCell.innerHTML += "Reverse";
+// 			propDirCell.appendChild(revDir);
+// 			propDirCell.innerHTML += "Reverse";
+// 			propDirCell.style.fontSize = "7pt";
+// 			propDirCell.style.whiteSpace = "nowrap";
+// 
+// 			// Add 'Remove' link
+// 			var removeLink = document.createElement("SPAN");
+// 			removeLink.className = "linkShow";
+// 			removeLink.style.fontSize = "7pt";
+// 			removeLink.style.fontWeight = "normal";
+// 			removeLink.style.marginLeft = "5px";
+// 			removeLink.innerHTML = "Remove";
+// 		
+// // 			miscPosCell.appendChild(removeLink);
+// 			rmvCell.appendChild(removeLink);
+// 
+// 			// Adjust border height to stretch to bottom of page
+// // 			mainBorder = document.getElementById("mainBorder");
+// // 			mainBorder.height = document.height;
+// // 			mainBorder.rowSpan = propsTbl.rows.length;
+// 		
+// 			// Add a separator row
+// // 			var divRow = propsTbl.insertRow(rowIndex + 1);
+// // 			var divCell = divRow.insertCell(0);
+// 
+// // 			divRow.setAttribute('id', "div_row" + divRow.rowIndex + "_id");
+// // 			divCell.colSpan = 6;
+// // 			divCell.innerHTML = "<HR>";
+// 
+// 			// 'Remove' link
+// // 			var tblID = "modifyReagentPropsTbl";
+// 			var miscRowID = propRow.id;
+// // 			var divRowID = divRow.id;
+// 		
+// // 			// Add list to form
+// // 			if (form_name == "")
+// // 				var myForm = document.reagentDetailForm;
+// // 			else
+// // 			{
+// // 				var myForm;
+// // 			
+// // 				docForms = document.forms;
+// // 			
+// // 				for (i = 0; i < docForms.length; i++)
+// // 				{
+// // 					aForm = docForms[i];
+// // 			
+// // 					if (aForm.name == form_name)
+// // 					{
+// // 						myForm = aForm;
+// // 						break;
+// // 					}
+// // 				}
+// // 			}
+// 
+// 			var hiddenMisc = document.createElement("INPUT");
+// 			hiddenMisc.setAttribute("type", "hidden");
+// 			myForm.appendChild(hiddenMisc);
+// 
+// 			var hiddenMiscStart = document.createElement("INPUT");
+// 			hiddenMiscStart.setAttribute("type", "hidden");
+// 			hiddenMiscStart.setAttribute("id", propNamePrefix + "cleavage_site_startpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMiscStart);
+// 
+// 			var hiddenMiscEnd = document.createElement("INPUT");
+// 			hiddenMiscEnd.setAttribute("type", "hidden");
+// 			hiddenMiscEnd.setAttribute("id", propNamePrefix + "cleavage_site_endpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMiscEnd);
+// 
+// 			// Orientation
+// 			var hiddenMiscDir = document.createElement("INPUT");
+// 			hiddenMiscDir.setAttribute('type', 'hidden');
+// 			hiddenMiscDir.setAttribute("id", propNamePrefix + "cleavage_site_orientation_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMiscDir);
+// 
+// 			var elemList = new Array();
+// 			elemList.push(hiddenMisc);
+// 			elemList.push(hiddenMiscStart);
+// 			elemList.push(hiddenMiscEnd);
+// 			elemList.push(hiddenMiscDir);
+// 
+// // 			removeLink.onclick = function(){deleteRow(tblID, miscRowID); deleteRow(tblID, miscPosRowID); deleteRow(tblID, divRowID); removeFormElements(myForm, elemList)};
+// 
+// 			removeLink.onclick = function(){deleteTableRow(tblID, miscRowID); removeFormElements(myForm, elemList)};
+// 		break;
+// 
+// 		case 'transcription_terminator':
+// 			var propRow = propsTbl.insertRow(propList.rowIndex - 2);
+// 		
+// // 			// Need a few cells in the row
+// // 			var propNameCell = propRow.insertCell(0);
+// // 			var propValueCell = propRow.insertCell(1);
+// // 
+// // 			// Set cell content and formatting as required by template
+// // 			propNameCell.className = "detailedView_colName";
+// 
+// 			var propNameCell = propRow.insertCell(0);
+// 			var propValueCell = propRow.insertCell(1);
+// 			var propDescrCell = propRow.insertCell(2);
+// 			var propStartCell = propRow.insertCell(3);
+// 			var propEndCell = propRow.insertCell(4);
+// 			var propDirCell = propRow.insertCell(5);
+// 			var rmvCell = propRow.insertCell(6);
+// 		
+// 			// Format cells	
+// 			propNameCell.style.paddingLeft = "7px";
+// 			propNameCell.style.backgroundColor = "#F5F5DC";
+// 			propNameCell.style.fontSize = "7pt";
+// 		
+// 			propValueCell.style.paddingLeft = "7px";
+// 			propValueCell.style.paddingRight = "5px";
+// 			propValueCell.style.paddingTop = "1px";
+// 			propValueCell.style.paddingBottom = "1px";
+// 			propValueCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propDescrCell.style.paddingLeft = "7px";
+// 			propDescrCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propStartCell.style.textAlign = "left";
+// 
+// 			propStartCell.style.paddingLeft = "7px";
+// 			propStartCell.style.paddingRight = "2px";
+// 
+// 			propStartCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propEndCell.style.textAlign = "left";
+// 			propEndCell.style.backgroundColor = "#F5F5DC";
+// 
+// 			propEndCell.style.paddingLeft = "7px";
+// 			propEndCell.style.paddingRight = "2px";
+// 		
+// 			propDirCell.style.textAlign = "left";
+// 
+// 			propDirCell.style.paddingLeft = "5px";
+// 			propDirCell.style.paddingRight = "5px";
+// 
+// 			propDirCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			rmvCell.style.textAlign = "left";
+// 
+// 			propNameCell.innerHTML = "Transcription Terminator";
+// // 		
+// // 			propValueCell.className = "detailedView_value";
+// // 			propValueCell.setAttribute("white-space", "nowrap");
+// // 			propValueCell.style.fontSize = "9pt";
+// // 			propValueCell.colSpan = 5;
+// // 			propValueCell.style.paddingLeft = "5px";
+// 			
+// 			// Generate the list on the fly
+// 			if (createNew == "true")
+// 				propNamePrefix = rType + "_"
+// 			else
+// 				propNamePrefix = ""
+// 
+// 			var tmpMiscList = document.getElementById(propNamePrefix + "transcription_terminator_list");
+// 			var miscSelectedInd = tmpMiscList.selectedIndex;
+// 			var miscSelectedValue = tmpMiscList[miscSelectedInd].value;
+// 
+// 			var newMiscList = document.createElement("SELECT");
+// 			var newMiscTxt =  document.createElement("INPUT");
+// 
+// 			newMiscList.style.fontSize = "7pt";
+// 
+// // 			newMiscList.setAttribute("name", prefix + propName + postfix);
+// 
+// 			var rowIndex;
+// 
+// 			if (!document.getElementById(propNamePrefix + "transcription_terminator_row_" + propRow.rowIndex + "_id"))
+// 			{
+// 				propRow.setAttribute('id', propNamePrefix + "transcription_terminator_row_" + propRow.rowIndex + "_id");
+// 				rowIndex = propRow.rowIndex;
+// 			}
+// 			else
+// 			{
+// 				for (i = 0; i < propsTbl.rows.length; i++)
+// 				{
+// 					if (!document.getElementById(propNamePrefix + "transcription_terminator_row_" + i + "_id"))
+// 					{
+// 						propRow.setAttribute('id', propNamePrefix + "transcription_terminator_row_" + i + "_id");
+// 						break;
+// 					}
+// 				}
+// 
+// 				propRow.setAttribute('id', propNamePrefix + "transcription_terminator_row_" + i + "_id");
+// 				rowIndex = i;
+// 			}
+// 
+// 			newMiscList.setAttribute("id", propNamePrefix + propName + "_proplist_" + rowIndex);
+// 
+// // 			propRow.setAttribute('id', "miscellaneous_row_" + propRow.rowIndex + "_id");
+// 
+// 			newMiscTxt.type = "TEXT";
+// 			newMiscTxt.id = propNamePrefix + "transcription_terminator_txt_" + (rowIndex - 1);
+// 			newMiscTxt.style.display = "none";
+// 
+// 			for (i = 0; i < tmpMiscList.options.length; i++)
+// 			{
+// 				tmpOptn = tmpMiscList.options[i];
+// 				newOptn = document.createElement("OPTION");
+// 
+// 				newOptn.value = tmpOptn.value;
+// 				newOptn.name = tmpOptn.name;
+// 				newOptn.text = tmpOptn.text;
+// 
+// 				if (newMiscList.options.length == 0)
+// 					newMiscList.options.add(newOptn);
+// 				else
+// 					addElement(newMiscList, newMiscList.options.length, newOptn);
+// 			}
+// 
+// 			propValueCell.appendChild(newMiscList);
+// 			propValueCell.appendChild(newMiscTxt);
+// 
+// 			// Start & stop positions
+// 			// April 1, 2008: Show in a new row
+// // 			var miscPosRow = propsTbl.insertRow(rowIndex+1);
+// // 			miscPosRow.setAttribute('id', "miscellaneous_pos_row" + rowIndex + "_id");
+// // 			var miscPosRowID = miscPosRow.id;
+// // 
+// // 			var c1 = miscPosRow.insertCell(0);
+// // 			var miscPosCell = miscPosRow.insertCell(1);
+// // 
+// // 			miscPosCell.className = "detailedView_value";
+// // 			miscPosCell.style.paddingLeft = "5px";
+// // 			miscPosCell.colSpan = 5;
+// // 			miscPosCell.setAttribute("white-space", "nowrap");
+// 
+// // 			miscPosCell.innerHTML = "Start: ";
+// 
+// 			var newMiscStart = document.createElement("INPUT");
+// 			newMiscStart.setAttribute("type", 'TEXT');
+// 			newMiscStart.setAttribute("size", 5);
+// 			newMiscStart.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_startpos_id");
+// 			newMiscStart.style.fontSize = "7pt";
+// 
+// // 			miscPosCell.appendChild(newMiscStart);
+// 			propStartCell.appendChild(newMiscStart);
+// 
+// // 			miscPosCell.innerHTML += "  End: ";
+// 			
+// 			var newMiscEnd = document.createElement("INPUT");
+// 			newMiscEnd.setAttribute("type", 'TEXT');
+// 			newMiscEnd.setAttribute("size", 5);
+// 			newMiscEnd.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_endpos_id");
+// 			newMiscEnd.style.fontSize = "7pt";
+// 
+// // 			miscPosCell.appendChild(newMiscEnd);
+// 			propEndCell.appendChild(newMiscEnd);
+// 
+// // 			newMiscList.onchange = function()
+// // 			{
+// // // 				showTagTypeBox(newTagTypeList.id, newTagTypeTxt.id);
+// // 			};
+// 			newMiscList.onchange = function(){this.setAttribute('name', propNamePrefix + propName + "_" + this[this.selectedIndex].value + "_" + rowIndex);};
+// 
+// 			// Orientation - March 14/08: Make 'forward' checked by default
+// // 			miscPosCell.innerHTML += "<SPAN style=\"margin-left:10px;\"></span>";
+// 
+// 			var fwdDir = document.createElement("INPUT");
+// 			fwdDir.setAttribute("type", "radio");
+// 			fwdDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_fwd_dir");
+// // 			fwdDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			fwdDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 
+// 			fwdDir.setAttribute("checked", true);
+// 
+// // 			miscPosCell.appendChild(fwdDir);
+// 			propDirCell.appendChild(fwdDir);
+// // 			miscPosCell.innerHTML += "Forward ";
+// 			propDirCell.innerHTML += "Forward ";
+// 
+// 			var revDir = document.createElement("INPUT");
+// 			revDir.setAttribute("type", "radio");
+// 			revDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_rev_dir");
+// // 			revDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			revDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 
+// // 			miscPosCell.appendChild(revDir);
+// // 			miscPosCell.innerHTML += "Reverse";
+// 			propDirCell.appendChild(revDir);
+// 			propDirCell.innerHTML += "Reverse";
+// 			propDirCell.style.fontSize = "7pt";
+// 			propDirCell.style.whiteSpace = "nowrap";
+// 
+// 			// Add 'Remove' link
+// 			var removeLink = document.createElement("SPAN");
+// 			removeLink.className = "linkShow";
+// 			removeLink.style.fontSize = "7pt";
+// 			removeLink.style.fontWeight = "normal";
+// 			removeLink.style.marginLeft = "5px";
+// 			removeLink.innerHTML = "Remove";
+// 		
+// // 			miscPosCell.appendChild(removeLink);
+// 			rmvCell.appendChild(removeLink);
+// 
+// 			// Adjust border height to stretch to bottom of page
+// // 			mainBorder = document.getElementById("mainBorder");
+// // 			mainBorder.height = document.height;
+// // 			mainBorder.rowSpan = propsTbl.rows.length;
+// 		
+// 			// Add a separator row
+// // 			var divRow = propsTbl.insertRow(rowIndex + 1);
+// // 			var divCell = divRow.insertCell(0);
+// 
+// // 			divRow.setAttribute('id', "div_row" + divRow.rowIndex + "_id");
+// // 			divCell.colSpan = 6;
+// // 			divCell.innerHTML = "<HR>";
+// 
+// 			// 'Remove' link
+// // 			var tblID = "modifyReagentPropsTbl";
+// 			var miscRowID = propRow.id;
+// // 			var divRowID = divRow.id;
+// 		
+// // 			// Add list to form
+// // 			if (form_name == "")
+// // 				var myForm = document.reagentDetailForm;
+// // 			else
+// // 			{
+// // 				var myForm;
+// // 			
+// // 				docForms = document.forms;
+// // 			
+// // 				for (i = 0; i < docForms.length; i++)
+// // 				{
+// // 					aForm = docForms[i];
+// // 			
+// // 					if (aForm.name == form_name)
+// // 					{
+// // 						myForm = aForm;
+// // 						break;
+// // 					}
+// // 				}
+// // 			}
+// 
+// 			var hiddenMisc = document.createElement("INPUT");
+// 			hiddenMisc.setAttribute("type", "hidden");
+// 			myForm.appendChild(hiddenMisc);
+// 
+// 			var hiddenMiscStart = document.createElement("INPUT");
+// 			hiddenMiscStart.setAttribute("type", "hidden");
+// 			hiddenMiscStart.setAttribute("id", propNamePrefix + "transcription_terminator_startpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMiscStart);
+// 
+// 			var hiddenMiscEnd = document.createElement("INPUT");
+// 			hiddenMiscEnd.setAttribute("type", "hidden");
+// 			hiddenMiscEnd.setAttribute("id", propNamePrefix + "transcription_terminator_endpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMiscEnd);
+// 
+// 			// Orientation
+// 			var hiddenMiscDir = document.createElement("INPUT");
+// 			hiddenMiscDir.setAttribute('type', 'hidden');
+// 			hiddenMiscDir.setAttribute("id", propNamePrefix + "transcription_terminator_orientation_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMiscDir);
+// 
+// 			var elemList = new Array();
+// 			elemList.push(hiddenMisc);
+// 			elemList.push(hiddenMiscStart);
+// 			elemList.push(hiddenMiscEnd);
+// 			elemList.push(hiddenMiscDir);
+// 
+// // 			removeLink.onclick = function(){deleteRow(tblID, miscRowID); deleteRow(tblID, miscPosRowID); deleteRow(tblID, divRowID); removeFormElements(myForm, elemList)};
+// 
+// 			removeLink.onclick = function(){deleteTableRow(tblID, miscRowID); removeFormElements(myForm, elemList)};
+// 		break;
+// 
+// 		case 'restriction_site':
+// 
+// 			var propRow = propsTbl.insertRow(propList.rowIndex - 2);
+// 		
+// 			var propNameCell = propRow.insertCell(0);
+// 			var propValueCell = propRow.insertCell(1);
+// 			var propDescrCell = propRow.insertCell(2);
+// 			var propStartCell = propRow.insertCell(3);
+// 			var propEndCell = propRow.insertCell(4);
+// 			var propDirCell = propRow.insertCell(5);
+// 			var rmvCell = propRow.insertCell(6);
+// 		
+// 			// Format cells	
+// 			propNameCell.style.paddingLeft = "7px";
+// 			propNameCell.style.backgroundColor = "#F5F5DC";
+// 			propNameCell.style.fontSize = "7pt";
+// 
+// 			propValueCell.style.paddingLeft = "7px";
+// 			propValueCell.style.paddingRight = "5px";
+// 			propValueCell.style.paddingTop = "1px";
+// 			propValueCell.style.paddingBottom = "1px";
+// 			propValueCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propDescrCell.style.paddingLeft = "7px";
+// 			propDescrCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propStartCell.style.textAlign = "left";
+// 
+// 			propStartCell.style.paddingLeft = "7px";
+// 			propStartCell.style.paddingRight = "2px";
+// 
+// 			propStartCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propEndCell.style.textAlign = "left";
+// 			propEndCell.style.backgroundColor = "#F5F5DC";
+// 
+// 			propEndCell.style.paddingLeft = "7px";
+// 			propEndCell.style.paddingRight = "2px";
+// 		
+// 			propDirCell.style.textAlign = "left";
+// 
+// 			propDirCell.style.paddingLeft = "5px";
+// 			propDirCell.style.paddingRight = "5px";
+// 
+// 			propDirCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			rmvCell.style.textAlign = "left";
+// 
+// 			propNameCell.innerHTML = "Restriction Site";
+// // 		
+// // 			propValueCell.className = "detailedView_value";
+// // 			propValueCell.setAttribute("white-space", "nowrap");
+// // 			propValueCell.style.fontSize = "9pt";
+// // 			propValueCell.colSpan = 5;
+// // 			propValueCell.style.paddingLeft = "5px";
+// 			
+// 			// Generate the list on the fly
+// 			if (createNew == "true")
+// 				propNamePrefix = rType + "_"
+// 			else
+// 				propNamePrefix = ""
+// 			
+// 			var tmpMiscList = document.getElementById(propNamePrefix + "restriction_site_list");
+// 			var miscSelectedInd = tmpMiscList.selectedIndex;
+// 			var miscSelectedValue = tmpMiscList[miscSelectedInd].value;
+// 
+// 			var newMiscList = document.createElement("SELECT");
+// 			var newMiscTxt =  document.createElement("INPUT");
+// 
+// // 			newMiscList.setAttribute("name", prefix + propName + postfix);
+// 
+// 			var rowIndex;
+// 
+// 			if (!document.getElementById(propNamePrefix + "restriction_site_row_" + propRow.rowIndex + "_id"))
+// 			{
+// 				propRow.setAttribute('id', propNamePrefix + "restriction_site_row_" + propRow.rowIndex + "_id");
+// 				rowIndex = propRow.rowIndex;
+// 			}
+// 			else
+// 			{
+// 				for (i = 0; i < propsTbl.rows.length; i++)
+// 				{
+// 					if (!document.getElementById(propNamePrefix + "restriction_site_row_" + i + "_id"))
+// 					{
+// 						propRow.setAttribute('id', propNamePrefix + "restriction_site_row_" + i + "_id");
+// 						break;
+// 					}
+// 				}
+// 
+// 				propRow.setAttribute('id', propNamePrefix + "restriction_site_row_" + i + "_id");
+// 				rowIndex = i;
+// 			}
+// 
+// 			newMiscList.setAttribute("id", propNamePrefix + propName + "_proplist_" + rowIndex);
+// 			newMiscList.style.fontSize = "7pt";
+// 
+// // 			propRow.setAttribute('id', "miscellaneous_row_" + propRow.rowIndex + "_id");
+// 
+// 			newMiscTxt.type = "TEXT";
+// 			newMiscTxt.id = propNamePrefix + "restriction_site_txt_" + (rowIndex - 1);
+// 			newMiscTxt.style.display = "none";
+// 
+// 			for (i = 0; i < tmpMiscList.options.length; i++)
+// 			{
+// 				tmpOptn = tmpMiscList.options[i];
+// 				newOptn = document.createElement("OPTION");
+// 
+// 				newOptn.value = tmpOptn.value;
+// 				newOptn.name = tmpOptn.name;
+// 				newOptn.text = tmpOptn.text;
+// 
+// 				if (newMiscList.options.length == 0)
+// 					newMiscList.options.add(newOptn);
+// 				else
+// 					addElement(newMiscList, newMiscList.options.length, newOptn);
+// 			}
+// 
+// 			propValueCell.appendChild(newMiscList);
+// 			propValueCell.appendChild(newMiscTxt);
+// 
+// 			// Start & stop positions
+// 			// April 1, 2008: Show in a new row
+// // 			var miscPosRow = propsTbl.insertRow(rowIndex+1);
+// // 			miscPosRow.setAttribute('id', "miscellaneous_pos_row" + rowIndex + "_id");
+// // 			var miscPosRowID = miscPosRow.id;
+// // 
+// // 			var c1 = miscPosRow.insertCell(0);
+// // 			var miscPosCell = miscPosRow.insertCell(1);
+// // 
+// // 			miscPosCell.className = "detailedView_value";
+// // 			miscPosCell.style.paddingLeft = "5px";
+// // 			miscPosCell.colSpan = 5;
+// // 			miscPosCell.setAttribute("white-space", "nowrap");
+// 
+// // 			miscPosCell.innerHTML = "Start: ";
+// 
+// 			var newMiscStart = document.createElement("INPUT");
+// 			newMiscStart.setAttribute("type", 'TEXT');
+// 			newMiscStart.setAttribute("size", 5);
+// 			newMiscStart.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_startpos_id");
+// 			newMiscStart.style.fontSize = "7pt";
+// 
+// // 			miscPosCell.appendChild(newMiscStart);
+// 			propStartCell.appendChild(newMiscStart);
+// 
+// // 			miscPosCell.innerHTML += "  End: ";
+// 			
+// 			var newMiscEnd = document.createElement("INPUT");
+// 			newMiscEnd.setAttribute("type", 'TEXT');
+// 			newMiscEnd.setAttribute("size", 5);
+// 			newMiscEnd.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_endpos_id");
+// 			newMiscEnd.style.fontSize = "7pt";
+// 
+// // 			miscPosCell.appendChild(newMiscEnd);
+// 			propEndCell.appendChild(newMiscEnd);
+// 
+// // 			newMiscList.onchange = function()
+// // 			{
+// // // 				showTagTypeBox(newTagTypeList.id, newTagTypeTxt.id);
+// // 			};
+// 			newMiscList.onchange = function(){this.setAttribute('name', propNamePrefix + propName + "_" + this[this.selectedIndex].value + "_" + rowIndex);};
+// 
+// 			// Orientation - March 14/08: Make 'forward' checked by default
+// // 			miscPosCell.innerHTML += "<SPAN style=\"margin-left:10px;\"></span>";
+// 
+// 			var fwdDir = document.createElement("INPUT");
+// 			fwdDir.setAttribute("type", "radio");
+// 			fwdDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_fwd_dir");
+// // 			fwdDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			fwdDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 			fwdDir.setAttribute("checked", true);
+// 
+// // 			miscPosCell.appendChild(fwdDir);
+// 			propDirCell.appendChild(fwdDir);
+// // 			miscPosCell.innerHTML += "Forward ";
+// 			propDirCell.innerHTML += "Forward ";
+// 
+// 			var revDir = document.createElement("INPUT");
+// 			revDir.setAttribute("type", "radio");
+// 			revDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_rev_dir");
+// // 			revDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			revDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 
+// // 			miscPosCell.appendChild(revDir);
+// // 			miscPosCell.innerHTML += "Reverse";
+// 			propDirCell.appendChild(revDir);
+// 			propDirCell.innerHTML += "Reverse";
+// 
+// 			propDirCell.style.fontSize = "7pt";
+// 			propDirCell.style.whiteSpace = "nowrap";
+// 
+// 			// Add 'Remove' link
+// 			var removeLink = document.createElement("SPAN");
+// 			removeLink.className = "linkShow";
+// 			removeLink.style.fontSize = "7pt";
+// 			removeLink.style.fontWeight = "normal";
+// 			removeLink.style.marginLeft = "5px";
+// 			removeLink.innerHTML = "Remove";
+// 		
+// // 			miscPosCell.appendChild(removeLink);
+// 			rmvCell.appendChild(removeLink);
+// 
+// 			// Adjust border height to stretch to bottom of page
+// // 			mainBorder = document.getElementById("mainBorder");
+// // 			mainBorder.height = document.height;
+// // 			mainBorder.rowSpan = propsTbl.rows.length;
+// 		
+// 			// Add a separator row
+// // 			var divRow = propsTbl.insertRow(rowIndex + 1);
+// // 			var divCell = divRow.insertCell(0);
+// 
+// // 			divRow.setAttribute('id', "div_row" + divRow.rowIndex + "_id");
+// // 			divCell.colSpan = 6;
+// // 			divCell.innerHTML = "<HR>";
+// 
+// 			// 'Remove' link
+// // 			var tblID = "modifyReagentPropsTbl";
+// 			var miscRowID = propRow.id;
+// // 			var divRowID = divRow.id;
+// 		
+// // 			// Add list to form
+// // 			if (form_name == "")
+// // 				var myForm = document.reagentDetailForm;
+// // 			else
+// // 			{
+// // 				var myForm;
+// // 			
+// // 				docForms = document.forms;
+// // 			
+// // 				for (i = 0; i < docForms.length; i++)
+// // 				{
+// // 					aForm = docForms[i];
+// // 			
+// // 					if (aForm.name == form_name)
+// // 					{
+// // 						myForm = aForm;
+// // 						break;
+// // 					}
+// // 				}
+// // 			}
+// 
+// 			var hiddenMisc = document.createElement("INPUT");
+// 			hiddenMisc.setAttribute("type", "hidden");
+// 			myForm.appendChild(hiddenMisc);
+// 
+// 			var hiddenMiscStart = document.createElement("INPUT");
+// 			hiddenMiscStart.setAttribute("type", "hidden");
+// 			hiddenMiscStart.setAttribute("id", propNamePrefix + "restriction_site_startpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMiscStart);
+// 
+// 			var hiddenMiscEnd = document.createElement("INPUT");
+// 			hiddenMiscEnd.setAttribute("type", "hidden");
+// 			hiddenMiscEnd.setAttribute("id", propNamePrefix + "restriction_site_endpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMiscEnd);
+// 
+// 			// Orientation
+// 			var hiddenMiscDir = document.createElement("INPUT");
+// 			hiddenMiscDir.setAttribute('type', 'hidden');
+// 			hiddenMiscDir.setAttribute("id", propNamePrefix + "restriction_site_orientation_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenMiscDir);
+// 
+// 			var elemList = new Array();
+// 			elemList.push(hiddenMisc);
+// 			elemList.push(hiddenMiscStart);
+// 			elemList.push(hiddenMiscEnd);
+// 			elemList.push(hiddenMiscDir);
+// 
+// // 			removeLink.onclick = function(){deleteRow(tblID, miscRowID); deleteRow(tblID, miscPosRowID); deleteRow(tblID, divRowID); removeFormElements(myForm, elemList)};
+// 
+// 			removeLink.onclick = function(){deleteTableRow(tblID, miscRowID); removeFormElements(myForm, elemList)};
+// 		break;
+// 
+// 		case 'intron':
+// 			var propRow = propsTbl.insertRow(propList.rowIndex - 2);
+// 		
+// 			// Need a few cells in the row
+// 			var propNameCell = propRow.insertCell(0);
+// 			var propValueCell = propRow.insertCell(1);
+// 			var propDescrCell = propRow.insertCell(2);
+// 			var propStartCell = propRow.insertCell(3);
+// 			var propEndCell = propRow.insertCell(4);
+// 			var propDirCell = propRow.insertCell(5);
+// 			var rmvCell = propRow.insertCell(6);
+// 		
+// 			// Format cells	
+// 			propNameCell.style.paddingLeft = "7px";
+// 			propNameCell.style.backgroundColor = "#F5F5DC";
+// 			propNameCell.style.fontSize = "7pt";		// nov. 12/08
+// 		
+// 			propValueCell.style.paddingLeft = "7px";
+// 			propValueCell.style.paddingRight = "5px";
+// 			propValueCell.style.paddingTop = "1px";
+// 			propValueCell.style.paddingBottom = "1px";
+// 			propValueCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propDescrCell.style.paddingLeft = "7px";
+// 			propDescrCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propStartCell.style.textAlign = "left";
+// 			propStartCell.style.paddingLeft = "7px";
+// 			propStartCell.style.paddingRight = "2px";
+// 			propStartCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			propEndCell.style.textAlign = "left";
+// 			propEndCell.style.backgroundColor = "#F5F5DC";
+// 			propEndCell.style.paddingLeft = "7px";
+// 			propEndCell.style.paddingRight = "2px";
+// 
+// 			propDirCell.style.textAlign = "left";
+// 			propDirCell.style.paddingLeft = "5px";
+// 			propDirCell.style.paddingRight = "5px";
+// 			propDirCell.style.backgroundColor = "#F5F5DC";
+// 		
+// 			rmvCell.style.textAlign = "left";
+// 
+// 			// Set cell content and formatting as required by template	
+// 			propNameCell.innerHTML = "Intron";
+// 			propValueCell.setAttribute("white-space", "nowrap");
+// 			
+// 			// Generate the list on the fly
+// 			if (createNew == "true")
+// 				propNamePrefix = rType + "_"
+// 			else
+// 				propNamePrefix = ""
+// 
+// 			var tmpTagTypeList = document.getElementById(propNamePrefix + "intron_list");
+// 
+// 			var newTagTypeList = document.createElement("SELECT");
+// 			var newTagTypeTxt =  document.createElement("INPUT");
+// 
+// 			newTagTypeList.style.fontSize = "7pt";		// Nov. 12/08
+// 
+// 			var rowIndex;
+// 
+// 			if (!document.getElementById(propNamePrefix + "intron_row_" + propRow.rowIndex + "_id"))
+// 			{
+// 				propRow.setAttribute('id', propNamePrefix + "intron_row_" + propRow.rowIndex + "_id");
+// 				rowIndex = propRow.rowIndex;
+// 			}
+// 			else
+// 			{
+// 				for (i = 0; i < propsTbl.rows.length; i++)
+// 				{
+// 					if (!document.getElementById(propNamePrefix + "intron_row_" + i + "_id"))
+// 					{
+// 						propRow.setAttribute('id', propNamePrefix + "intron_row_" + i + "_id");
+// 						break;
+// 					}
+// 				}
+// 
+// 				propRow.setAttribute('id', propNamePrefix + "intron_row_" + i + "_id");
+// 				rowIndex = i;
+// 			}
+// 
+// // 			newTagTypeList.setAttribute('name', prefix + propName + postfix);
+// 			newTagTypeList.setAttribute('id', propNamePrefix + propName + "_proplist_" + rowIndex);
+// 
+// 			newTagTypeTxt.type = "TEXT";
+// 			newTagTypeTxt.id = propNamePrefix + "intron_txt_" + rowIndex;
+// 
+// 			newTagTypeTxt.style.display = "none";
+// 			newTagTypeTxt.style.fontSize = "9pt";
+// 
+// 			for (i = 0; i < tmpTagTypeList.options.length; i++)
+// 			{
+// 				tmpOptn = tmpTagTypeList.options[i];
+// 				newOptn = document.createElement("OPTION");
+// 
+// 				newOptn.value = tmpOptn.value;
+// 				newOptn.name = tmpOptn.name;
+// 				newOptn.text = tmpOptn.text;
+// 
+// 				if (newTagTypeList.options.length == 0)
+// 					newTagTypeList.options.add(newOptn);
+// 				else
+// 					addElement(newTagTypeList, newTagTypeList.options.length, newOptn);
+// 			}
+// 
+// // 			newTagTypeList.onchange = showTagTypeBox;
+// 
+// 			newTagTypeList.onchange = function(){this.setAttribute('name', propNamePrefix + propName + "_" + this[this.selectedIndex].value + "_" + rowIndex); showTagTypeBox(newTagTypeList.id, newTagTypeTxt.id);};
+// 
+// 			propValueCell.appendChild(newTagTypeList);
+// 			propValueCell.appendChild(newTagTypeTxt);
+// 
+// 			var newTagTypeStart = document.createElement("INPUT");
+// 			newTagTypeStart.setAttribute("type", 'TEXT');
+// 			newTagTypeStart.setAttribute("size", 5);
+// 			newTagTypeStart.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_startpos_id");
+// 			newTagTypeStart.style.fontSize = "7pt";		// Nov. 12/08
+// 
+// 			propStartCell.appendChild(newTagTypeStart);
+// 
+// 			var newTagTypeEnd = document.createElement("INPUT");
+// 			newTagTypeEnd.setAttribute("type", 'TEXT');
+// 			newTagTypeEnd.setAttribute("size", 5);
+// 			newTagTypeEnd.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_endpos_id");
+// 			newTagTypeEnd.style.fontSize = "7pt";		// Nov. 12/08
+// 
+// 			propEndCell.appendChild(newTagTypeEnd);
+// 
+// 			// Orientation
+// 			propDirCell.style.fontSize = "7pt";		// Nov. 12/08
+// 			propDirCell.style.whiteSpace = "nowrap";
+// 			
+// 			var fwdDir = document.createElement("INPUT");
+// 			fwdDir.setAttribute("type", "radio");
+// 			fwdDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_fwd_dir");
+// //  			fwdDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+// 			fwdDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 
+// 			fwdDir.setAttribute("checked", true);
+// 
+// 			propDirCell.appendChild(fwdDir);
+// 			propDirCell.innerHTML += "Forward ";
+// 
+// 			var revDir = document.createElement("INPUT");
+// 			revDir.setAttribute("type", "radio");
+// 			revDir.setAttribute("id", propNamePrefix + propName + "_" + rowIndex + "_rev_dir");
+// // 			revDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+//  			revDir.setAttribute("name", propNamePrefix + propName + "_orientation_prop_" + rowIndex);
+// 
+// 			propDirCell.appendChild(revDir);
+// 			propDirCell.innerHTML += "Reverse";
+// 
+// 			// Add 'Remove' link
+// 			var removeLink = document.createElement("SPAN");
+// 			removeLink.className = "linkShow";
+// 			removeLink.style.fontSize = "7pt";
+// 			removeLink.style.fontWeight = "normal";
+// 			removeLink.style.marginLeft = "5px";
+// 			removeLink.innerHTML = "Remove";
+// 
+// 			rmvCell.appendChild(removeLink);
+// 
+// 			// Gather the IDs of all elements in the row to pass to 'deleteRow' function
+// // 			var tblID = "modifyReagentPropsTbl";
+// 			var tagTypeRowID = propRow.id;
+// 
+// 			var hiddenTagType = document.createElement("INPUT");
+// 			hiddenTagType.setAttribute("type", "hidden");
+// 			hiddenTagType.setAttribute("id", propNamePrefix + "intron_prop" + rowIndex);
+// 			myForm.appendChild(hiddenTagType);
+// 
+// 			var hiddenTagTypeStart = document.createElement("INPUT");
+// 			hiddenTagTypeStart.setAttribute("type", "hidden");
+// 			hiddenTagTypeStart.setAttribute("id", propNamePrefix + "intron_startpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenTagTypeStart);
+// 
+// 			var hiddenTagTypeEnd = document.createElement("INPUT");
+// 			hiddenTagTypeEnd.setAttribute("type", "hidden");
+// 			hiddenTagTypeEnd.setAttribute("id", propNamePrefix + "intron_endpos_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenTagTypeEnd);
+// 
+// 			// Orientation
+// 			var hiddenTagTypeDir = document.createElement("INPUT");
+// 			hiddenTagTypeDir.setAttribute('type', 'hidden');
+// 			hiddenTagTypeDir.setAttribute("id", propNamePrefix + "intron_orientation_prop_" + rowIndex);
+// 			myForm.appendChild(hiddenTagTypeDir);
+// 
+// 			var elemList = new Array();
+// 			elemList.push(hiddenTagType);
+// 			elemList.push(hiddenTagTypeStart);
+// 			elemList.push(hiddenTagTypeEnd);
+// 			elemList.push(hiddenTagTypeDir);
+// 
+// 			removeLink.onclick = function(){deleteTableRow(tblID, tagTypeRowID); removeFormElements(myForm, elemList)};
+// 		break;
+
+		case '':
+		break;
+
+		default:
+// alert(rType);
+			var propRow = propsTbl.insertRow(propList.rowIndex - 2);
+		
+			// Need a few cells in the row
+			var propNameCell = propRow.insertCell(0);
+			var propValueCell = propRow.insertCell(1);
+			var propDescrCell = propRow.insertCell(2);
+			var propStartCell = propRow.insertCell(3);
+			var propEndCell = propRow.insertCell(4);
+			var propDirCell = propRow.insertCell(5);
+			var rmvCell = propRow.insertCell(6);
+		
+			// Format cells	
+			propNameCell.style.paddingLeft = "7px";
+			propNameCell.style.backgroundColor = "#F5F5DC";
+			propNameCell.style.fontSize = "7pt";		// nov. 12/08
+			propNameCell.style.whiteSpace = "nowrap";
+		
+			propValueCell.style.paddingLeft = "7px";
+			propValueCell.style.paddingRight = "5px";
+			propValueCell.style.paddingTop = "1px";
+			propValueCell.style.paddingBottom = "1px";
+			propValueCell.style.backgroundColor = "#F5F5DC";
+		
+			propDescrCell.style.paddingLeft = "7px";
+			propDescrCell.style.backgroundColor = "#F5F5DC";
+		
+			propStartCell.style.textAlign = "left";
+			propStartCell.style.paddingLeft = "7px";
+			propStartCell.style.paddingRight = "2px";
+			propStartCell.style.backgroundColor = "#F5F5DC";
+		
+			propEndCell.style.textAlign = "left";
+			propEndCell.style.backgroundColor = "#F5F5DC";
+			propEndCell.style.paddingLeft = "7px";
+			propEndCell.style.paddingRight = "2px";
+
+			propDirCell.style.textAlign = "left";
+			propDirCell.style.paddingLeft = "5px";
+			propDirCell.style.paddingRight = "5px";
+			propDirCell.style.backgroundColor = "#F5F5DC";
+		
+			rmvCell.style.textAlign = "left";
+
+			// Set cell content and formatting as required by template
+			propDescrInput = document.getElementById(rType + "_" + propName + "_descr");
+			
+			if (propDescrInput)
+				propDescr = propDescrInput.value;
+			else
+				propDescr = propName;
+
+// 			propNameCell.innerHTML = propName;
+			propNameCell.innerHTML = propDescr;
+
+			propValueCell.setAttribute("white-space", "nowrap");
+			
+			// Generate the list on the fly
+// 			if ((createNew == "true") || (rType != ""))
+			if (createNew == "true")
+				propNamePrefix = rType + "_"
+			else
+				propNamePrefix = ""
+
+// alert(propNamePrefix + propName + "_:_list");
+
+			var tmpTagTypeList = document.getElementById(propNamePrefix + propName + "_:_list");
+
+			var newTagTypeList = document.createElement("SELECT");
+			var newTagTypeTxt =  document.createElement("INPUT");
+
+			newTagTypeList.style.fontSize = "7pt";		// Nov. 12/08
+
+			var rowIndex;
+
+			if (!document.getElementById(propNamePrefix + propName + "_:_row_" + propRow.rowIndex + "_id"))
+			{
+				propRow.setAttribute('id', propNamePrefix + propName + "_:_row_" + propRow.rowIndex + "_id");
+				rowIndex = propRow.rowIndex;
+			}
+			else
+			{
+				for (i = 0; i < propsTbl.rows.length; i++)
+				{
+					if (!document.getElementById(propNamePrefix + propName + "_:_row_" + i + "_id"))
+					{
+						propRow.setAttribute('id', propNamePrefix + propName + "_:_row_" + i + "_id");
+						break;
+					}
+				}
+
+				propRow.setAttribute('id', propNamePrefix + propName + "_row_" + i + "_id");
+				rowIndex = i;
+			}
+
+// 			newTagTypeList.setAttribute('name', prefix + propName + postfix);
+			newTagTypeList.setAttribute('id', propNamePrefix + propName + "_:_proplist_" + rowIndex);
+
+// alert(propNamePrefix);
+			newTagTypeTxt.type = "TEXT";
+			newTagTypeTxt.id = propNamePrefix + propName + "_txt_" + rowIndex;
+
+			newTagTypeTxt.onKeyPress = function(){return disableEnterKey(event);};
+
+// alert(newTagTypeTxt.id);
+
+			newTagTypeTxt.style.display = "none";
+			newTagTypeTxt.style.fontSize = "9pt";
+
+			for (i = 0; i < tmpTagTypeList.options.length; i++)
+			{
+				tmpOptn = tmpTagTypeList.options[i];
+				newOptn = document.createElement("OPTION");
+
+				newOptn.value = tmpOptn.value;
+				newOptn.name = tmpOptn.name;
+				newOptn.text = tmpOptn.text;
+
+				if (newTagTypeList.options.length == 0)
+					newTagTypeList.options.add(newOptn);
+				else
+					addElement(newTagTypeList, newTagTypeList.options.length, newOptn);
+			}
+
+// 			newTagTypeList.onchange = showTagTypeBox;
+
+			newTagTypeList.onchange = function(){this.setAttribute('name', propNamePrefix + propName + "_:_" + this[this.selectedIndex].value + "_" + rowIndex); showSpecificOtherTextbox(newTagTypeList.id, newTagTypeTxt.id);};
+
+			propValueCell.appendChild(newTagTypeList);
+			propValueCell.appendChild(newTagTypeTxt);
+
+			// Descriptor - for selected features
+			if ((propName == 'tag') || (propName == 'promoter'))
+			{
+				if (propName == "tag")
+					propDescrAlias = "tag_position";
+				else if (propName == "promoter")
+					propDescrAlias = "expression_system";
+	
+				var oldTagPosList = document.getElementById(propNamePrefix + propDescrAlias + "_:_list");
+// 	alert(oldTagPosList.id);
+				if (oldTagPosList)
+				{
+					var newTagPosList = document.createElement("SELECT");
+					var newTagPosTxt =  document.createElement("INPUT");
+
+					newTagPosTxt.type = "TEXT";
+					newTagPosTxt.id = propNamePrefix + propDescrAlias + "_txt_" + rowIndex;
+					newTagPosTxt.onKeyPress = function(){return disableEnterKey(event);};
+		
+					newTagPosTxt.style.display = "none";
+					newTagPosTxt.style.fontSize = "9pt";
+
+					newTagPosList.setAttribute('id', propNamePrefix + propDescrAlias + "_:_proplist_" + rowIndex);
+// 		alert(newTagPosList.id);
+					newTagPosList.style.fontSize = "7pt";		// Nov. 12/08
+		
+					for (i = 0; i < oldTagPosList.options.length; i++)
+					{
+						tmpOptn = oldTagPosList.options[i];
+						newOptn = document.createElement("OPTION");
+		
+						newOptn.value = tmpOptn.value;
+						newOptn.name = tmpOptn.name;
+						newOptn.text = tmpOptn.text;
+		
+						if (newTagPosList.options.length == 0)
+							newTagPosList.options.add(newOptn);
+						else
+							addElement(newTagPosList, newTagPosList.options.length, newOptn);
+					}
+
+					newTagPosList.onchange = function(){this.setAttribute('name', propNamePrefix + propDescrAlias + "_:_" + this[this.selectedIndex].value + "_" + rowIndex); showSpecificOtherTextbox(newTagPosList.id, newTagPosTxt.id);};
+
+					propDescrCell.appendChild(newTagPosList);
+					propDescrCell.appendChild(newTagPosTxt);
+				}
+
+				// Tag position
+				var hiddenTagPosField = document.createElement("INPUT");
+				hiddenTagPosField.setAttribute('type', 'hidden');
+				hiddenTagPosField.setAttribute("id", propNamePrefix + propDescrAlias  + "_:_prop_" + rowIndex);
+// 	alert(hiddenTagPosField.id);
+				myForm.appendChild(hiddenTagPosField);
+			}
+
+			var newTagTypeStart = document.createElement("INPUT");
+			newTagTypeStart.setAttribute("type", 'TEXT');
+			newTagTypeStart.setAttribute("size", 5);
+			newTagTypeStart.setAttribute("id", propNamePrefix + propName + "_:_" + rowIndex + "_startpos_id");
+			newTagTypeStart.style.fontSize = "7pt";		// Nov. 12/08
+			newTagTypeStart.onKeyPress = function(){return disableEnterKey(event);};
+
+			propStartCell.appendChild(newTagTypeStart);
+
+			var newTagTypeEnd = document.createElement("INPUT");
+			newTagTypeEnd.setAttribute("type", 'TEXT');
+			newTagTypeEnd.setAttribute("size", 5);
+			newTagTypeEnd.setAttribute("id", propNamePrefix + propName + "_:_" + rowIndex + "_endpos_id");
+			newTagTypeEnd.style.fontSize = "7pt";		// Nov. 12/08
+			newTagTypeEnd.onKeyPress = function(){return disableEnterKey(event);};
+
+			propEndCell.appendChild(newTagTypeEnd);
+
+			// Orientation
+			propDirCell.style.fontSize = "7pt";		// Nov. 12/08
+			propDirCell.style.whiteSpace = "nowrap";
+			
+			var fwdDir = document.createElement("INPUT");
+			fwdDir.setAttribute("type", "radio");
+			fwdDir.setAttribute("id", propNamePrefix + propName + "_:_" + rowIndex + "_fwd_dir");
+//  			fwdDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+			fwdDir.setAttribute("name", propNamePrefix + propName + "_:_orientation_prop_" + rowIndex);
+
+			fwdDir.setAttribute("checked", true);
+
+			propDirCell.appendChild(fwdDir);
+			propDirCell.innerHTML += "Forward ";
+
+			var revDir = document.createElement("INPUT");
+			revDir.setAttribute("type", "radio");
+			revDir.setAttribute("id", propNamePrefix + propName + "_:_" + rowIndex + "_rev_dir");
+// 			revDir.setAttribute("name", propName + "_orientation_radio_" + rowIndex);
+ 			revDir.setAttribute("name", propNamePrefix + propName + "_:_orientation_prop_" + rowIndex);
+
+			propDirCell.appendChild(revDir);
+			propDirCell.innerHTML += "Reverse";
+
+			// Add 'Remove' link
+			var removeLink = document.createElement("SPAN");
+			removeLink.className = "linkShow";
+			removeLink.style.fontSize = "7pt";
+			removeLink.style.fontWeight = "normal";
+			removeLink.style.marginLeft = "5px";
+			removeLink.innerHTML = "Remove";
+
+			rmvCell.appendChild(removeLink);
+
+			// Gather the IDs of all elements in the row to pass to 'deleteRow' function
+// 			var tblID = "modifyReagentPropsTbl";
+			var tagTypeRowID = propRow.id;
+
+			var hiddenTagType = document.createElement("INPUT");
+			hiddenTagType.setAttribute("type", "hidden");
+			hiddenTagType.setAttribute("id", propNamePrefix + propName + "_:_prop" + rowIndex);
+			myForm.appendChild(hiddenTagType);
+
+			var hiddenTagTypeStart = document.createElement("INPUT");
+			hiddenTagTypeStart.setAttribute("type", "hidden");
+			hiddenTagTypeStart.setAttribute("id", propNamePrefix + propName + "_:_startpos_prop_" + rowIndex);
+			myForm.appendChild(hiddenTagTypeStart);
+
+			var hiddenTagTypeEnd = document.createElement("INPUT");
+			hiddenTagTypeEnd.setAttribute("type", "hidden");
+			hiddenTagTypeEnd.setAttribute("id", propNamePrefix + propName + "_:_endpos_prop_" + rowIndex);
+			myForm.appendChild(hiddenTagTypeEnd);
+
+			// Orientation
+			var hiddenTagTypeDir = document.createElement("INPUT");
+			hiddenTagTypeDir.setAttribute('type', 'hidden');
+			hiddenTagTypeDir.setAttribute("id", propNamePrefix + propName + "_:_orientation_prop_" + rowIndex);
+			myForm.appendChild(hiddenTagTypeDir);
+
+			var elemList = new Array();
+			elemList.push(hiddenTagType);
+			elemList.push(hiddenTagTypeStart);
+			elemList.push(hiddenTagTypeEnd);
+			elemList.push(hiddenTagTypeDir);
+
+			removeLink.onclick = function(){deleteTableRow(tblID, tagTypeRowID); removeFormElements(myForm, elemList)};
+		break;
+	}
+
+// alert(propsTbl.rows.length);
+
+// for (i=0; i < myForm.elements.length; i++)
+// {
+// tmpEl = myForm.elements[i];
+// alert(tmpEl.id);
+// alert(tmpEl.name);
+// alert(tmpEl.value);
+// }
+
+	propNamesList.selectedIndex = 0;
+}
+
+
+// May 6/09: multiple accessions on Insert modification view
+function addAccessionRow(annosTblID, inputName, rowCount, colCount)
+{
+	var annosTbl = document.getElementById(annosTblID);
+// 	var accRow = annosTbl.insertRow(1);	// insert after the first row in annotations table - accessions
+	var accRow = annosTbl.insertRow(rowCount);
+	var firstPlaceholderCell = accRow.insertCell(0);
+// 	var accCell = accRow.insertCell(1);
+	var accCell = accRow.insertCell(colCount);
+
+	accCell.colspan = 5;
+	accCell.className ="detailedView_value";
+	accCell.style.paddingLeft = "3px";
+
+	accCell.innerHTML = "<INPUT type=text value=\"\" name=\"" + inputName + "\"><BR>";
+}
+
+function hasArrayElement(my_array, my_elem)
+{
+	var i;
+
+	for (i = 0; i < my_array.length; i++)
+	{
+		tmpEl = my_array[i];
+
+		if (tmpEl == my_elem)
+			return true;
+	}
+
+	return false;
+}
+
+// Oct. 22/08, updated May 25/09
+function changeFieldNames(form_name, tblID, rType)
+{
+// alert("In changeFieldNames");
+
+	if (tblID)
+		var propTbl = document.getElementById(tblID);
+	else
+		var propTbl = document.getElementById("modifyReagentPropsTbl");
+
+// alert(propTbl);
+// alert(rType);
+	var i, j, k, z;
+
+	var prefix = "reagent_detailedview_";
+	var postfix = "_prop";
+
+	// Modified May 26/09: Cannot assume pre-defined features anymore
+	if (rType)
+		var featuresList = document.getElementById("sequence_property_names_" + rType);
+	else
+		var featuresList = document.getElementById("sequence_property_names");
+
+// 	alert(featuresList);
+
+	var reagentFeaturesList = new Array();
+
+	if (featuresList)
+	{
+		for (a=0; a < featuresList.options.length; a++)
+		{
+			fAliasTmp = featuresList.options[a].value;
+	// 		alert(fAliasTmp);
+			reagentFeaturesList.push(fAliasTmp);
+		}
+	}
+// 	// debug
+// 	for (x=0; x < reagentFeaturesList.length; x++)
+// 		alert(reagentFeaturesList[x]);
+
+// 	removed May 26/09
+// 	var reagentFeaturesList = ["tag_type", "promoter", "selectable_marker", "origin", "polyA", "polya", "miscellaneous", "cleavage_site", "transcription_terminator", "intron", "restriction_site"];
+	
+	var reagentFeatureDescriptors = {"tag":"tag_position", "promoter":"expression_system"}
+	
+	var oldPropValue, newPropValue, oldStartPos, oldEndPos, pStartList, pEndList, pDirList, newDirName, descriptor;
+
+	docForms = document.forms;
+
+	if (propTbl)
+	{
+		for (b=1; b <= propTbl.rows.length; b++)
+		{
+			var aRow = propTbl.rows[b];
+	
+			if (aRow)
+			{
+// 				alert("Row " + aRow.id);
+				aRowID = aRow.id;
+// 				propName = aRowID.substring(0, aRowID.indexOf("_row"));
+				propName = aRowID.substring(0, aRowID.indexOf("_:_"));
+// alert(propName);
+
+				if (hasArrayElement(reagentFeaturesList, propName))
+				{
+// 					alert("Prop name " + propName);
+// 					alert(aRowID);
+					oldPropValue = aRowID.substring((propName+"_:_row_").length, aRowID.indexOf("_start_"));
+// 					alert("Old value " + oldPropValue);
+
+					oldStartPos = aRowID.substring(aRowID.indexOf("_start_")+"_start_".length, aRowID.indexOf("_end_"));
+// 					alert("Old start " + oldStartPos);
+	
+					oldEndPos = aRowID.substring(aRowID.indexOf("_end_")+"_end_".length);
+// 					alert("Old end " + oldEndPos);
+	
+// alert(prefix + propName + "_:_" + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + "_startpos" + postfix);
+
+					pStartList = document.getElementsByName(prefix + propName + "_:_" + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + "_startpos" + postfix);
+	
+// 					alert(pStartList.length);
+	
+					if (pStartList && pStartList.length > 0)
+					{
+						newStart = pStartList[0].value;
+// 						alert("New start " + newStart);
+					}
+					else
+						continue;
+	
+					pEndList = document.getElementsByName(prefix + propName + "_:_" + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + "_endpos" + postfix);
+	
+					if (pEndList && pEndList.length > 0)
+					{
+						newEnd = pEndList[0].value;
+// 						alert("New end " + newEnd);
+					}
+					else
+						continue;
+	
+				//	alert(pEndList.length);
+					
+					if (newStart && newEnd)
+					{
+// alert("New end " + newEnd);
+// alert("New start " + newStart);
+						oldDirName = prefix + propName + "_:_" + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + "_orientation" + postfix;
+						pDirList = document.getElementsByName(oldDirName);	// fwd and rev
+	
+						fwd_dir = pDirList[0];
+						rev_dir = pDirList[1];
+	
+						fieldName = prefix + propName + "_:_" + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + postfix;
+// alert(fieldName);
+						propField = document.getElementsByName(fieldName)[0];
+	
+						newPropValue = propField[propField.selectedIndex].value;
+// 						alert(newPropValue);
+
+						if (newPropValue.toLowerCase() == 'other')
+						{
+// alert("HERE");
+							if (rType && (rType != ""))
+							{
+								if (document.getElementById(prefix + rType + "_" + propName + "_:_" + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + "_txt"))
+									newPropValue = document.getElementById(prefix + rType + "_" + propName + "_:_" + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + "_txt").value;
+
+								// June 8, 2010
+								else if (document.getElementById(prefix + propName + "_:_" + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + "_txt"))
+									newPropValue = document.getElementById(prefix + propName + "_:_" + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + "_txt").value;
+
+								else
+									newPropValue = document.getElementById(rType + "_" + propName + "_:_" + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + "_txt").value;
+// alert(newPropValue);
+							}
+							else
+							{
+								// if-else statements added March 29, 2010
+								if (document.getElementById(prefix + propName + "_:_" + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + "_txt"))
+									newPropValue = document.getElementById(prefix + propName + "_:_" + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + "_txt").value;
+								else
+									newPropValue = document.getElementById(propName + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + "_txt").value;
+							}
+
+// 							alert(newPropValue);
+						}
+
+						newStartName = prefix + propName + "_:_" + newPropValue + "_start_" + newStart + "_end_" + newEnd + "_startpos" + postfix;
+	
+						newEndName = prefix + propName + "_:_" + newPropValue + "_start_" + newStart + "_end_" + newEnd + "_endpos" + postfix;
+	
+						pStartList[0].setAttribute("name", newStartName);
+						pEndList[0].setAttribute("name", newEndName);
+	
+						propField.setAttribute("name", prefix + propName + "_:_" + newPropValue + "_start_" + newStart + "_end_" + newEnd + postfix);
+	
+						newDirName = prefix + propName + "_:_" + newPropValue + "_start_" + newStart + "_end_" + newEnd + "_orientation" + postfix;
+						
+						fwd_dir.setAttribute("name", newDirName);
+						rev_dir.setAttribute("name", newDirName);
+	
+						// description
+						descriptor = reagentFeatureDescriptors[propName];
+						
+						if (descriptor)
+						{
+							oldDescrName = prefix + descriptor + "_:_" + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + postfix;
+// 							alert(oldDescrName);
+							descrField = document.getElementsByName(oldDescrName)[0];
+// descrField = document.getElementById(oldDescrName);
+	
+							if (descrField)
+							{
+// 								alert(oldDescrName);
+// 								alert(descrField.value);
+
+								newDescrName = prefix + descriptor + "_:_" + newPropValue + "_start_" + newStart + "_end_" + newEnd + postfix;
+// 								alert("Setting descriptor name: " + newDescrName);
+
+								descrField.setAttribute("name", newDescrName);
+								
+								if (descrField.value.toLowerCase() == 'other')
+								{
+									txtID = prefix + descriptor + "_:_" + oldPropValue + "_start_" + oldStartPos + "_end_" + oldEndPos + "_txt";
+// 									alert("text field ID " + txtID);
+
+									textField = document.getElementById(txtID);
+
+									if (textField)
+									{
+										newTxtName = prefix + descriptor + "_:_" + newPropValue + "_start_" + newStart + "_end_" + newEnd + "_name_txt";
+// alert("Setting text field name " + newTxtName);
+										textField.setAttribute("name", newTxtName);
+
+										// alert("well, why not??");
+										newDescr = document.getElementById(txtID).value;
+										
+// 										alert("new descr " + newDescrName);
+										descrField.setAttribute("value", newDescr);
+									}
+								}
+							}
+						}
+						
+					}
+					else
+						continue;
+				}
+			}
+		}
+	}
+
+	return;
+}
+
+
+// fieldName - current name to be changed
+function setFieldName(aField, fieldName, propName, descriptor)
+{
+	var reagentFeatureDescriptors = {"tag":"tag_position", "promoter":"expression_system"}
+
+	aField.setAttribute("name", fieldName);
+}
+
+
+// Note: rType is actually an ID, and rTypeID is the name of a reagent type!
+function addParent(rType, rTypeID, assocAlias, assocName, assocID, rIndex)
+{
+// alert(rType);
+// alert(rTypeID);
+
+	var tableID = "category_assoc_section_" + rType;
+// alert(tableID);
+// 	alert("category_assoc_section_" + rTypeID);
+
+	var rowID = rType + "_" + assocAlias + "_assoc_row_" + assocID + "_" + rIndex;
+// alert(rowID);
+	var parentTable = document.getElementById(tableID);
+	var assocRow = document.getElementById(rowID);
+// alert(assocRow);
+// 	var newRow = parentTable.insertRow(assocRow.rowIndex+1);
+	var newRow = parentTable.insertRow(parentTable.rows.length);
+
+	// just generate the next integer in sequence to assign distinct row IDs
+// 	newRow.id = rowID + "_" + parentTable.rowCount+1;
+	var rCount = parentTable.rows.length-1;
+// alert(newRow.rowIndex);
+// alert(parentTable.rows.length-1);
+
+	newRow.id = rType + "_" + assocAlias + "_assoc_row_" + assocID + "_" + rCount;
+
+	var newInput = document.createElement("INPUT");
+
+	newInput.type = "text";
+// 	newInput.setAttribute("name", "assoc_" + assocAlias + "_prop");		// NO!!!!!!!!!!!!!!
+
+	// replaced Feb. 12/10
+	newInput.setAttribute("name", rTypeID + "_assoc_" + assocID + "_prop");
+// alert(newInput.name);
+
+	newInput.onKeyPress=function(){return disableEnterKey(event)};
+
+	// Update Feb. 17/10 - replaced rTypeID with rType
+	newInput.id = rTypeID + "_assoc_" + assocAlias + "_input";
+
+	var cell_1 = newRow.insertCell(0);
+	var cell_2 = newRow.insertCell(1);
+
+
+	// Different formatting for creation and modification views
+	if (document.getElementById("createReagentForm" + rType))
+	{
+		newRow.style.backgroundColor = "#F5F5DC;";
+	
+		cell_1.style.paddingLeft = "15px";
+		cell_1.style.fontSize = "8pt";
+		cell_1.style.fontWeight = "bold";
+
+		cell_2.style.paddingLeft="10px";
+	}
+	else
+	{
+		cell_1.style.paddingLeft = "40px";
+		cell_2.style.paddingLeft="5px";	
+	}
+
+	cell_1.innerHTML = assocName;
+	cell_2.appendChild(newInput);
+
+	// 'Add' and 'Remove' links
+	var removeLink = document.createElement("SPAN");
+
+	removeLink.className = "linkExportSequence";
+	removeLink.style.fontWeight = "normal";
+	removeLink.style.marginLeft = "18px";
+	removeLink.innerHTML = "Remove";
+
+	removeLink.onclick = function(){deleteTableRow(tableID, newRow.id)};
+
+	cell_2.appendChild(removeLink);
+	newInput.focus();
+
+	// Don't put an 'Add' link here - absolutely no point
+}
+
+
+function setFeaturePositions(rType)
+{
+// alert(rType);
+
+// debugging (VERY long)
+// 	var myForm = document.reagentDetailForm;
+// 
+// 	for (i = 0; i < myForm.elements.length; i++)
+// 	{
+// 		alert(myForm.elements[i].name);
+// 		alert(myForm.elements[i].value);
+// 	}
+
+// 	alert("In setFeaturePositions");
+
+	var allFields = document.getElementsByTagName("INPUT");
+	var tmpInput;
+
+	var prefix = "reagent_detailedview_";
+	var postfix = "_prop";
+
+	var propName = "";
+
+	for (i = 0; i < allFields.length; i++)
+	{
+		tmpInput = allFields[i];
+
+// 		alert(tmpInput.name);
+
+		tmpStart = "";
+		tmpEnd = "";
+
+		if (tmpInput.type == "hidden")
+		{
+			tmpID = tmpInput.id;
+// 			alert("Set positions " + tmpID);
+
+			startInd = tmpID.indexOf("_:_startpos_prop");
+			endInd = tmpID.indexOf("_:_endpos_prop");
+
+			if (startInd > 0)
+			{
+// 				alert(tmpID);
+				propName = tmpID.substring(0, startInd);
+// 				alert("Prop name " + propName);
+
+				// Oct. 28/09
+				if (rType != "")
+				{
+					if (propName.indexOf(rType + "_") == 0)
+					{
+						rType_str = rType + "_";
+						propName = tmpID.substring(rType_str.length, propName.length);
+					}
+				}
+
+				propCount = tmpID.substr(startInd+("_:_startpos_prop_".length), tmpID.length);
+// 				alert(propCount);
+
+				if (rType && (rType != ""))
+				{
+					tmpList = document.getElementById(rType + "_" + propName + "_:_proplist_" + propCount);
+				}
+				else
+				{
+					// get the selected value from the corresponding list
+					tmpList = document.getElementById(propName + "_:_proplist_" + propCount);
+				}
+
+// 				alert(tmpList.name);
+
+				if (tmpList)
+					tmpPropVal = tmpList[tmpList.selectedIndex].value;
+				else
+					tmpPropVal = "";
+// 				alert(tmpPropVal);
+	
+				if (tmpPropVal.toLowerCase() == 'other')	// this is ok
+				{
+					if (rType && (rType != ""))
+					{
+						tmpPropVal = document.getElementById(rType + "_" + propName + "_txt_" + propCount).value;
+					}
+					else
+					{
+						tmpPropVal = document.getElementById(propName + "_txt_" + propCount).value;
+					}
+
+					// come back to this with 'Other'
+// 					tmpPropVal = document.getElementById(propName + "_txt_" + propCount).value;
+// 					alert(tmpPropVal);
+				}
+
+				if (rType && (rType != ""))
+				{
+					var tmpPropStart = document.getElementById(rType + "_" + propName + "_:_" + propCount + "_startpos_id").value;
+				}
+				else
+				{
+					var tmpPropStart = document.getElementById(propName + "_:_" + propCount + "_startpos_id").value;
+				}
+
+// 				alert("Start " + tmpPropStart);
+
+				if (rType && (rType != ""))
+				{
+					var hiddenStart = document.getElementById(rType + "_" + propName + "_:_startpos_prop_" + propCount);
+				}
+				else
+				{
+					var hiddenStart = document.getElementById(propName + "_:_startpos_prop_" + propCount);
+				}
+
+				if (rType && (rType != ""))
+				{
+					var tmpPropEnd = document.getElementById(rType + "_" + propName + "_:_" + propCount + "_endpos_id").value;	// added Nov. 7/08
+				}
+				else
+				{
+					var tmpPropEnd = document.getElementById(propName + "_:_" + propCount + "_endpos_id").value;	// added Nov. 7/08
+				}
+
+				// Changed Nov. 7/08 - did not work on modification
+// rmvd Nov. 7/08		var hiddenEnd = document.getElementById(propName + "_endpos_prop_" + propCount);
+// rmvd Nov. 7/08		var tmpEnd = hiddenEnd.value;
+// rmvd Nov. 7/08		hiddenStart.setAttribute("name", prefix + propName + "_" + tmpPropVal + "_start_" + tmpPropStart + "_end_" + tmpEnd + "_startpos_prop");
+
+				if (rType && (rType != ""))
+				{
+					hiddenStart.setAttribute("name", prefix + rType + "_" + propName + "_:_" + tmpPropVal + "_start_" + tmpPropStart + "_end_" + tmpPropEnd + "_startpos_prop");		// added Nov. 7/08
+				}
+				else
+				{
+					hiddenStart.setAttribute("name", prefix + propName + "_:_" + tmpPropVal + "_start_" + tmpPropStart + "_end_" + tmpPropEnd + "_startpos_prop");		// added Nov. 7/08
+				}
+
+// 				alert("Hidden start field: " + hiddenStart.name);
+
+				hiddenStart.setAttribute("value", tmpPropStart);
+			}
+
+			if (endInd > 0)
+			{
+// 				alert(tmpID);
+				propName = tmpID.substring(0, endInd);
+// 				alert(propName);
+
+				// Oct. 28/09
+				if (rType && (rType != ""))
+				{
+                                	if (propName.indexOf(rType + "_") == 0)
+					{
+						rType_str = rType + "_";
+                                        	propName = tmpID.substring(rType_str.length, propName.length);
+					}
+				}
+
+				propCount = tmpID.substr(endInd+("_:_endpos_prop_".length), tmpID.length);
+
+// 				alert(propCount);
+
+				// get the selected value from the corresponding list
+				if (rType && (rType != ""))
+				{
+					tmpList = document.getElementById(rType + "_" + propName + "_:_proplist_" + propCount);
+				}
+				else
+				{
+					tmpList = document.getElementById(propName + "_:_proplist_" + propCount);
+				}
+
+				tmpPropVal = tmpList[tmpList.selectedIndex].value;
+// 				alert("VAlue " + tmpPropVal);
+
+				if (tmpPropVal.toLowerCase() == 'other')
+				{
+					if (rType && (rType != ""))
+					{
+						tmpPropVal = document.getElementById(rType + "_" + propName + "_txt_" + propCount).value;
+					}
+					else
+					{
+						tmpPropVal = document.getElementById(propName + "_txt_" + propCount).value;
+					}
+
+// 					alert(tmpPropVal);
+				}
+
+
+				if (rType && (rType != ""))
+				{
+					var tmpPropEnd = document.getElementById(rType + "_" + propName + "_:_" + propCount + "_endpos_id").value;
+				}
+				else
+				{
+					var tmpPropEnd = document.getElementById(propName + "_:_" + propCount + "_endpos_id").value;
+				}
+
+// 				alert("End " + tmpPropEnd);
+
+				if (rType && (rType != ""))
+				{
+					var hiddenEnd = document.getElementById(rType + "_" + propName + "_:_endpos_prop_" + propCount);
+				}
+				else
+				{
+					var hiddenEnd = document.getElementById(propName + "_:_endpos_prop_" + propCount);
+				}
+
+// 				alert("Hidden end field " + hiddenEnd.name);
+
+				if (rType && (rType != ""))
+				{
+					var hiddenStart = document.getElementById(rType + "_" + propName + "_:_startpos_prop_" + propCount);
+				}
+				else
+				{
+					var hiddenStart = document.getElementById(propName + "_:_startpos_prop_" + propCount);
+				}
+
+				var tmpStart = hiddenStart.value;
+
+				if (rType && (rType != ""))
+				{
+					hiddenEnd.setAttribute("name", prefix + rType + "_" + propName + "_:_" + tmpPropVal + "_start_" + tmpStart + "_end_" + tmpPropEnd + "_endpos_prop");
+				}
+				else
+				{
+					hiddenEnd.setAttribute("name", prefix + propName + "_:_" + tmpPropVal + "_start_" + tmpStart + "_end_" + tmpPropEnd + "_endpos_prop");
+				}
+
+				hiddenEnd.setAttribute("value", tmpPropEnd);
+
+				// Special cases: Descriptors - Tag Type property comes in conjunction with Tag Position; Promoter - with Expression System
+				if (propName == "tag")
+				{
+					if (rType && (rType != ""))
+					{
+						var hiddenTagPosition = document.getElementById(rType + "_" + "tag_position_:_prop_" + propCount);
+					}
+					else
+					{
+						// set the hidden form field's value to the selected value of the visible list
+						var hiddenTagPosition = document.getElementById("tag_position_:_prop_" + propCount);
+					}
+
+// alert("Old tag position name: " + hiddenTagPosition.name);
+
+					if (rType && (rType != ""))
+					{
+						var origTagPosList = document.getElementById(rType + "_" + "tag_position_:_proplist_" + propCount);
+					}
+					else
+					{
+						var origTagPosList = document.getElementById("tag_position_:_proplist_" + propCount);
+					}
+	
+					if (hiddenTagPosition)
+					{
+						if (rType && (rType != ""))
+						{
+							hiddenTagPosition.setAttribute("name", prefix + rType + "_tag_position_:_" + tmpPropVal + "_start_" + tmpPropStart + "_end_" + tmpPropEnd + postfix);
+						}
+						else
+						{
+							hiddenTagPosition.setAttribute("name", prefix + "tag_position_:_" + tmpPropVal + "_start_" + tmpPropStart + "_end_" + tmpPropEnd + postfix);
+						}
+					}
+
+// alert("New tag position name: " + hiddenTagPosition.name);
+
+					if (origTagPosList)
+					{
+						if (origTagPosList[origTagPosList.selectedIndex].value.toLowerCase() == 'other')
+						{
+							// grab the value in the textbox
+							if (rType && (rType != ""))
+							{
+								var tagPosTxt = document.getElementById(rType + "_" + "tag_position" + "_txt_" + propCount);
+							}
+							else
+							{
+								var tagPosTxt = document.getElementById("tag_position" + "_txt_" + propCount);
+							}
+						
+							hiddenTagPosition.setAttribute("value", tagPosTxt.value);
+						}
+						else
+							hiddenTagPosition.setAttribute("value", origTagPosList[origTagPosList.selectedIndex].value);
+					}
+
+// alert("New tag position value: " + hiddenTagPosition.value);
+				}
+				else if (propName == "promoter")
+				{
+					if (rType && (rType != ""))
+					{
+						var hiddenExprSyst = document.getElementById(rType + "_" + "expression_system_:_prop_" + propCount);
+					}
+					else
+					{
+						var hiddenExprSyst = document.getElementById("expression_system_:_prop_" + propCount);
+					}
+
+					if (rType && (rType != ""))
+					{
+						var origExprSystList = document.getElementById(rType + "_" + "expression_system_:_proplist_" + propCount);
+					}
+					else
+					{
+						var origExprSystList = document.getElementById("expression_system_:_proplist_" + propCount);
+					}
+
+					if (hiddenExprSyst)
+					{
+						if (rType && (rType != ""))
+						{
+							hiddenExprSyst.setAttribute("name", prefix + rType + "_expression_system_:_" + tmpPropVal + "_start_" + tmpPropStart + "_end_" + tmpPropEnd + postfix);
+						}
+						else
+						{
+							hiddenExprSyst.setAttribute("name", prefix + "expression_system_:_" + tmpPropVal + "_start_" + tmpPropStart + "_end_" + tmpPropEnd + postfix);
+						}
+					}
+// alert(hiddenExprSyst.name);
+	
+					if (origExprSystList)
+					{
+						if (origExprSystList[origExprSystList.selectedIndex].value.toLowerCase() == 'other')
+						{
+							// grab the value in the textbox
+							if (rType && (rType != ""))
+							{
+								var expSystTxt = document.getElementById(rType + "_" + "expression_system" + "_txt_" + propCount);
+							}
+							else
+							{
+								var expSystTxt = document.getElementById("expression_system" + "_txt_" + propCount);
+							}
+						
+							hiddenExprSyst.setAttribute("value", expSystTxt.value);
+						}
+						else
+							hiddenExprSyst.setAttribute("value", origExprSystList[origExprSystList.selectedIndex].value);
+					}
+				}
+			}
+
+			// March 17/08: Orientation:
+// alert(tmpID);
+			orientInd = tmpID.indexOf("_:_orientation_prop_");
+
+			if (orientInd > 0)
+			{
+				if (rType && (rType != ""))
+					propName = tmpID.substring((rType + "_").length, orientInd);
+				else
+				{
+// alert(tmpID);
+					propName = tmpID.substring(0, orientInd);
+				}
+// alert(propName);
+				propCount = tmpID.substr(orientInd+("_:_orientation_prop_".length), tmpID.length);
+
+				if (rType && (rType != ""))
+				{
+					var tmpFwd = document.getElementById(rType + "_" + propName + "_:_" + propCount + "_fwd_dir");
+					var tmpRev = document.getElementById(rType + "_" + propName + "_:_" + propCount + "_rev_dir");
+				}
+				else
+				{
+					var tmpFwd = document.getElementById(propName + "_:_" + propCount + "_fwd_dir");
+					var tmpRev = document.getElementById(propName + "_:_" + propCount + "_rev_dir");
+				}
+
+				if (tmpFwd.checked)		// orientation <= forward - FAILS ON REMOVAL???
+				{
+					// get the selected value from the corresponding list
+					if (rType && (rType != ""))
+						tmpList = document.getElementById(rType + "_" + propName + "_:_proplist_" + propCount);
+					else
+						tmpList = document.getElementById(propName + "_:_proplist_" + propCount);
+
+					tmpPropVal = tmpList[tmpList.selectedIndex].value;
+// alert(tmpPropVal);
+					if (tmpPropVal.toLowerCase() == 'other')
+					{
+						if (rType && (rType != ""))
+						{
+							tmpPropVal = document.getElementById(rType + "_" + propName + "_txt_" + propCount).value;
+						}
+						else
+						{
+							tmpPropVal = document.getElementById(propName + "_txt_" + propCount).value;
+						}
+
+// 						alert(tmpPropVal);
+					}
+
+// oct 21/08				tmpInput.setAttribute("name", prefix + propName + "_" + tmpPropVal + "_orientation_prop");
+
+					if (rType && (rType != ""))
+						tmpInput.setAttribute("name", prefix + rType + "_" + propName + "_:_" + tmpPropVal + "_start_" + tmpPropStart + "_end_" + tmpPropEnd + "_orientation_prop");
+					else
+						tmpInput.setAttribute("name", prefix + propName + "_:_" + tmpPropVal + "_start_" + tmpPropStart + "_end_" + tmpPropEnd + "_orientation_prop");	// oct 21/08
+
+					tmpInput.setAttribute("value", "forward");
+				}
+				else if (tmpRev.checked)	// orientation <= reverse
+				{
+					// get the selected value from the corresponding list
+					if (rType && (rType != ""))
+						tmpList = document.getElementById(rType + "_" + propName + "_:_proplist_" + propCount);
+					else
+						tmpList = document.getElementById(propName + "_:_proplist_" + propCount);
+
+					tmpPropVal = tmpList[tmpList.selectedIndex].value;
+					
+					if (tmpPropVal.toLowerCase() == 'other')
+					{
+						if (rType && (rType != ""))
+						{
+							tmpPropVal = document.getElementById(rType + "_" + propName + "_txt_" + propCount).value;
+						}
+						else
+						{
+							tmpPropVal = document.getElementById(propName + "_txt_" + propCount).value;
+						}
+
+// 						alert(tmpPropVal);
+					}
+
+// oct 24/08				tmpInput.setAttribute("name", prefix + propName + "_" + tmpPropVal + "_orientation_prop");
+					if (rType && (rType != ""))
+						tmpInput.setAttribute("name", prefix + rType + "_" + propName + "_:_" + tmpPropVal + "_start_" + tmpPropStart + "_end_" + tmpPropEnd + "_orientation_prop");
+					
+					else
+						tmpInput.setAttribute("name", prefix + propName + "_:_" + tmpPropVal + "_start_" + tmpPropStart + "_end_" + tmpPropEnd + "_orientation_prop");	// oct 21/08
+
+					tmpInput.setAttribute("value", "reverse");
+				}
+			}/*
+			else
+			{
+				orientationInd = tmpID.indexOf("_orientation_radio_");
+			}*/
+		}
+	}
+}
+
+// Aug. 11/08: 'Select' elements don't have a 'readonly' attribute, but 'disabled' prevents the element from being submitted with the form.  Need to enable this element when form is submitted - concerns cloning sites.
+function enableSites()
+{
+	//var fpcs;
+	//var tpcs;
+
+	fpcsList = document.getElementById("fpcs_list");
+	tpcsList = document.getElementById("tpcs_list");
+
+	if (fpcsList)
+	{
+		fpcsList.disabled = false;
+		//fpcs = fpcsList[fpcsList.selectedIndex].value;
+	}
+
+	if (tpcsList)
+	{
+		tpcsList.disabled = false;
+		//tpcs = tpcsList[tpcsList.selectedIndex].value;
+	}
+
+	// Different list IDs for Vector and Insert
+	fpcsList_1 = document.getElementById("fpcs_list_1");
+	tpcsList_1 = document.getElementById("tpcs_list_1");
+
+	if (fpcsList_1)
+	{
+		fpcsList_1.disabled = false;
+	//	fpcs = fpcsList[fpcsList.selectedIndex].value;
+	}
+
+	if (tpcsList_1)
+	{
+		tpcsList_1.disabled = false;
+	//	tpcs = tpcsList[tpcsList.selectedIndex].value;
+	}
+
+	/*
+	var fpcs_value = document.getElementById("fpcs_val");
+	var tpcs_value = document.getElementById("tpcs_val");
+	
+	if (fpcs_value)
+	{
+		fpcs_value.value = fpcs;
+	}
+	
+	if (tpcs_value)
+	{
+		tpcs_value.value = tpcs;
+	}*/
+
+}
+
+// July 20/09: try to make common to all reagent types
+function toggleReagentEditModify(actn, categoryAlias, rType)
+{
+// alert(rType);
+// alert(categoryAlias);
+
+// 	var actnBtn = document.getElementById("update_reagent_" + categoryAlias);
+// 	var actn = actnBtn.value;
+
+	var viewSection = document.getElementById(categoryAlias + "_tbl_view");
+	var modifySection = document.getElementById(categoryAlias + "_tbl_modify");
+
+	if (actn == 'edit')
+	{
+		// just show Modify section
+		modifySection.style.display = "inline";
+		viewSection.style.display = "none";
+
+		if ((categoryAlias == "sequence_properties") || (categoryAlias == "protein_sequence_properties") || (categoryAlias == "rna_sequence_properties"))
+		{
+			var editSeqBtn = document.getElementById("edit_reagent_" + categoryAlias);
+			editSeqBtn.style.display = "none";
+
+			var seqBtnDiv = document.getElementById("sequenceButtons");
+			seqBtnDiv.style.display = "inline";
+	
+			// type of insert and open/closed
+			if (document.getElementById("itype_modify"))
+			{
+				var typeOfInsertModify = document.getElementById("itype_modify");
+				typeOfInsertModify.style.display = "table-row";
+			}
+
+			if (document.getElementById("modifyOpenClosed"))
+			{
+				var openClosedModify = document.getElementById("modifyOpenClosed");
+				openClosedModify.style.display = "table-row";
+			}
+
+			if (document.getElementById("rna_tm_view") && document.getElementById("rna_tm_modify"))
+			{
+				var rna_tm_view_div = document.getElementById("rna_tm_view");
+				var rna_tm_edit_div = document.getElementById("rna_tm_modify");
+
+				rna_tm_view_div.style.display = "none";
+				rna_tm_edit_div.style.display = "inline";
+			}
+		}
+
+		// disable the rest of Edit buttons!
+		var inputs = document.getElementsByTagName("INPUT");
+
+		for (i=0; i < inputs.length; i++)
+		{
+			var tmpInput = inputs[i];
+
+			if ((tmpInput.type == "button") && (tmpInput.id != "save_reagent_" + categoryAlias) && (tmpInput.id != "cancel_save_" + categoryAlias) && (tmpInput.id != "update_reagent_" + categoryAlias) && (tmpInput.name != "addBtn[]") && (tmpInput.name != "rmvBtn[]"))
+				tmpInput.disabled = true;
+		}
+	}
+	else if (actn == 'save')
+	{
+//		alert(categoryAlias);
+
+		// Need to add start/stop validation here
+		if ((categoryAlias == "dna_sequence_features") || (categoryAlias == "protein_sequence_features") || (categoryAlias == "rna_sequence_features"))
+		{
+			isLinear = document.getElementById("is_linear").value;
+
+			if (verifyPositions(isLinear))
+			{
+				// July 20/09: document.reagentDetailForm.submit() does NOT work for some reason; use getElementById instead
+				var myForm = document.getElementById("editReagentForm_" + categoryAlias);
+		
+				var tmpAction = document.createElement("INPUT");
+				tmpAction.type = "hidden";
+				tmpAction.name = "change_state";
+				tmpAction.value='Save';
+				myForm.appendChild(tmpAction);
+			
+				var sectionToSave = document.createElement("INPUT");
+				sectionToSave.type = "hidden";
+				sectionToSave.name = "save_section";
+				sectionToSave.value = categoryAlias;
+				myForm.appendChild(sectionToSave);
+
+				enableSites();
+				changeFieldNames(myForm, "modifyReagentPropsTbl_" + categoryAlias, rType);
+				setFeaturePositions();
+
+				myForm.submit();
+			}
+		}
+		else if ((categoryAlias == "sequence_properties") || (categoryAlias == "protein_sequence_properties") || (categoryAlias == "rna_sequence_properties"))
+		{
+			switch(categoryAlias)
+			{
+				case 'sequence_properties':
+					seqType = "dna";
+				break;
+
+				case 'protein_sequence_properties':
+					seqType = "protein";
+				break;
+
+				case 'rna_sequence_properties':
+					seqType = "rna";
+				break;
+			}
+
+// 			switch (rType)
+// 			{
+// 				case 'Vector':
+// 					switchVectorSequenceModify();
+// 				break;
+// 				
+// 				case 'Insert':
+// 					var viewInsertSeq = document.getElementById("insert_seq_div_view");
+// 					var modifyInsertSeq = document.getElementById("insert_seq_div_modify");
+// 					var typeOfInsertModify = document.getElementById("itype_modify");
+// 					var openClosedModify = document.getElementById("modifyOpenClosed");
+// 				
+// 					viewInsertSeq.style.display = "none";
+// 					modifyInsertSeq.style.display = "table-row";
+// 					typeOfInsertModify.style.display = "table-row";
+// 					openClosedModify.style.display = "table-row";
+// 				
+// 				break;
+// 
+// 				default:
+// 				break;
+
+				if (verifySequence(rType, seqType))
+				{
+					// July 20/09: document.reagentDetailForm.submit() does NOT work for some reason; use getElementById instead
+					var myForm = document.getElementById("editReagentForm_" + categoryAlias);
+					
+					/*
+					alert(myForm.name);
+					
+		for (i=0; i < myForm.elements.length; i++)
+		{
+			alert(myForm.elements[i].name);
+			alert(myForm.elements[i].value);
+		}*/
+					var tmpAction = document.createElement("INPUT");
+					tmpAction.type = "hidden";
+					tmpAction.name = "change_state";
+					tmpAction.value='Save';
+					myForm.appendChild(tmpAction);
+				
+					var sectionToSave = document.createElement("INPUT");
+					sectionToSave.type = "hidden";
+					sectionToSave.name = "save_section";
+					sectionToSave.value = categoryAlias;
+					myForm.appendChild(sectionToSave);
+		
+		
+		/*for (i=0; i < myForm.elements.length; i++)
+		{
+			alert(myForm.elements[i].name);
+			alert(myForm.elements[i].value);
+		}*/
+					myForm.submit();
+				}
+// 			}
+		}
+		else
+		{
+			// July 20/09: document.reagentDetailForm.submit() does NOT work for some reason; use getElementById instead
+			var myForm = document.getElementById("editReagentForm_" + categoryAlias);
+	
+			var tmpAction = document.createElement("INPUT");
+			tmpAction.type = "hidden";
+			tmpAction.name = "change_state";
+			tmpAction.value='Save';
+			myForm.appendChild(tmpAction);
+		
+			var sectionToSave = document.createElement("INPUT");
+			sectionToSave.type = "hidden";
+			sectionToSave.name = "save_section";
+			sectionToSave.value = categoryAlias;
+			myForm.appendChild(sectionToSave);
+
+			// May 10, 2010: Allowing multiple values - select list elements!
+			allLists = document.getElementsByTagName("SELECT");
+			
+			for (a = 0; a < allLists.length; a++)
+			{
+				if ((allLists[a].id.indexOf("targetList_") == 0) && (allLists[a].style.display != "none"))
+					selectAllElements(allLists[a].id);
+			}
+
+			myForm.submit();
+		}
+	}
+	else
+	{
+		// July 20/09: document.reagentDetailForm.submit() does NOT work for some reason; use getElementById instead
+		var myForm = document.getElementById("editReagentForm_" + categoryAlias);
+
+		var tmpAction = document.createElement("INPUT");
+		tmpAction.type = "hidden";
+		tmpAction.name = "change_state";
+		tmpAction.value='Cancel';
+		myForm.appendChild(tmpAction);
+	
+		var sectionToSave = document.createElement("INPUT");
+		sectionToSave.type = "hidden";
+		sectionToSave.name = "save_section";
+		sectionToSave.value = categoryAlias;
+		myForm.appendChild(sectionToSave);
+
+		myForm.submit();
+	}
+}
+
+// May 7/09 - Edit procedure for reagent types other than VICO
+function switchOtherIntroModify()
+{
+	var viewOtherReagentIntro = document.getElementById("other_reagent_intro_tbl_view");
+	var modifyOtherReagentIntro = document.getElementById("other_reagent_intro_tbl_modify");
+
+	// June 8/08: Disable Edit buttons for other sections
+	var seqEditBtn = document.getElementById("editOtherReagentSequence");
+	var featuresEditBtn = document.getElementById("editOtherReagentFeatures");
+	var editAnnosBtn = document.getElementById("editOtherReagentExternalIDs");	// formerly 'annotations' - renamed to 'External Identifiers'
+	var editClassifiersBtn = document.getElementById("editOtherReagentClassifiers");
+	var editParentsBtn = document.getElementById("editInsertParents");
+
+	if (seqEditBtn)
+		seqEditBtn.disabled = true;
+
+	if (featuresEditBtn)	// Jan. 8/09
+		featuresEditBtn.disabled = true;
+
+	if (editAnnosBtn)	// Jan. 8/09
+		editAnnosBtn.disabled = true;
+
+	if (editClassifiersBtn)	// Jan. 8/09
+		editClassifiersBtn.disabled = true;
+
+	if (editParentsBtn)	// Jan. 8/09
+		editParentsBtn.disabled = true;
+	
+	viewOtherReagentIntro.style.display = "none";
+	modifyOtherReagentIntro.style.display = "table-row";
+
+	// May 25/09: Custom categories
+	var customCategories = document.getElementsByName("save_other_property_category");
+	var tmpCatAlias;
+	var tmpCatEditBtn;
+
+	for (i = 0; i < customCategories.length; i++)
+	{
+		tmpCatAlias = customCategories[i].value;
+// 		alert(tmpCatAlias);
+		tmpCatEditBtn = document.getElementById("editOtherReagent_" + tmpCatAlias + "_btn");
+
+		if (tmpCatEditBtn)
+			tmpCatEditBtn.disabled = true;
+	}
+
+	document.getElementById("changeStateIntro").value = "Modify";	// must set for Python
+}
+
+
+// May 7/09
+function saveOtherReagentGeneralProps()
+{
+	document.getElementById("changeStateIntro").value = "Save";	// remember to set this for Python
+	document.otherReagentIntroForm.submit();
+}
+
+
+// Feb. 28/08: Hide Insert View Intro section and make Modify Intro section visible
+function switchInsertIntroModify()
+{
+	var viewInsertIntro = document.getElementById("insert_intro_tbl_view");
+	var modifyInsertIntro = document.getElementById("insert_intro_tbl_modify");
+
+	// June 8/08: Disable Edit buttons for other sections
+	var seqEditBtn = document.getElementById("editInsertSeq");
+	var featuresEditBtn = document.getElementById("editInsertSeqFeatures");
+	var editAnnosBtn = document.getElementById("editInsertAnnotations");
+	var editClassifiersBtn = document.getElementById("editInsertClassifiers");
+	var editParentsBtn = document.getElementById("editInsertParents");
+
+	if (seqEditBtn)
+		seqEditBtn.disabled = true;
+
+	if (featuresEditBtn)	// Jan. 8/09
+		featuresEditBtn.disabled = true;
+
+	if (editAnnosBtn)	// Jan. 8/09
+		editAnnosBtn.disabled = true;
+
+	if (editClassifiersBtn)	// Jan. 8/09
+		editClassifiersBtn.disabled = true;
+
+	if (editParentsBtn)	// Jan. 8/09
+		editParentsBtn.disabled = true;
+	
+	viewInsertIntro.style.display = "none";
+	modifyInsertIntro.style.display = "table-row";
+
+	document.getElementById("changeStateIntro").value = "Modify";	// must set for Python
+}
+
+function switchVectorIntroModify()
+{
+	var viewVectorIntro = document.getElementById("vector_intro_tbl_view");
+	var modifyVectorIntro = document.getElementById("vector_intro_tbl_modify");
+
+	// June 8/08: Disable Edit buttons for other sections
+	var seqEditBtn = document.getElementById("editVectorSeq");
+	var featuresEditBtn = document.getElementById("editVectorFeatures");
+	var editParentsBtn = document.getElementById("editVectorParents");
+	
+	// added check Jan. 8/09
+	if (seqEditBtn)
+		seqEditBtn.disabled = true;
+
+	// added check Jan. 8/09
+	if (featuresEditBtn)
+		featuresEditBtn.disabled = true;
+
+	if (editParentsBtn)	// Jan. 8/09 - if this button doesn't exist on the view, as is the case with Novel Vectors, e.g. V4492, won't enter Edit mode
+		editParentsBtn.disabled = true;
+
+	viewVectorIntro.style.display = "none";
+	modifyVectorIntro.style.display = "table-row";
+
+	document.getElementById("changeStateVectorIntro").value = "Modify";	// must set for Python
+}
+
+
+// Feb. 28/08: JUST SUBMIT THE FORM!!!!!!!!!!!!!!!!!!!!  DO ***NOT*** CHANGE DISPLAY - Python will redirect back to Detailed view, which would take care of visibility
+function saveGeneralInsertDetails()
+{
+// NO!!!!!!
+// 	var viewInsertIntro = document.getElementById("insert_intro_tbl_view");
+// 	var modifyInsertIntro = document.getElementById("insert_intro_tbl_modify");
+
+// 	var editBtn = document.getElementById("editInsertIntro");
+// 	var saveBtn = document.getElementById("saveInsertIntro");
+
+// 	viewInsertIntro.style.display = "inline";
+// 	modifyInsertIntro.style.display = "none";
+// 
+// 	editBtn.style.display = "inline";
+// 	saveBtn.style.display = "none";
+
+	document.getElementById("changeStateIntro").value = "Save";	// remember to set this for Python
+	document.insertIntroForm.submit();
+}
+
+function saveGeneralVectorDetails()
+{
+	document.getElementById("changeStateVectorIntro").value = "Save";	// remember to set this for Python
+	document.vectorIntroForm.submit();
+}
+
+function cancelReagentParentsModification()
+{
+	document.getElementById("changeStateParents").value = "Cancel";		// remember to set this for Python
+	document.reagentParentsForm.submit();
+}
+
+
+function cancelInsertIntroModification()
+{
+// Changed again April 10/08 - refreshing the page is not always a good idea; sometimes get a 'POSTDATA' warning
+// 	window.location.reload();	// april 2/08
+
+	// April 10/08 - FINAL, optimal solution
+	document.getElementById("changeStateIntro").value = "Cancel";	// remember to set this for Python
+	document.insertIntroForm.submit();
+}
+
+function cancelGeneralVectorModification()
+{
+	document.getElementById("changeStateVectorIntro").value = "Cancel";	// remember to set this for Python
+	document.vectorIntroForm.submit();
+}
+
+function cancelOtherReagentIntroModification()
+{
+	document.getElementById("changeStateIntro").value = "Cancel";	// remember to set this for Python
+	document.otherReagentIntroForm.submit();
+}
+
+
+function switchOtherReagentSequenceModify(rType)
+{
+	switch (rType)
+	{
+		case 'Vector':
+			switchVectorSequenceModify();
+		break;
+		
+		case 'Insert':
+			switchInsertSequenceModify();
+		break;
+
+	}
+
+// 	var viewSequence = document.getElementById("insert_seq_div_view");
+}
+
+// Feb. 28/08: Insert Sequence modification - show in modify mode
+function switchInsertSequenceModify()
+{
+	var viewInsertSeq = document.getElementById("insert_seq_div_view");
+	var modifyInsertSeq = document.getElementById("insert_seq_div_modify");
+
+	var typeOfInsertView = document.getElementById("type_of_insert");
+	var typeOfInsertModify = document.getElementById("itype_modify");
+
+	var openClosedView = document.getElementById("viewOpenClosed");
+	var openClosedModify = document.getElementById("modifyOpenClosed");
+
+	var dnaLengthView = document.getElementById("dnaLengthView");
+	var cDNALengthView = document.getElementById("cDNALengthView");
+
+	var dnaLengthModify = document.getElementById("dnaLengthModify");
+	var cDNALengthModify = document.getElementById("cDNALengthModify");
+
+	var editBtn = document.getElementById("editInsertSeq");
+	var saveBtn = document.getElementById("saveInsertSeq");
+	var cancelBtn = document.getElementById("cancelChangeInsertSeq");
+
+	// Show cDNA start/stop input fields
+// 	cdnaModify.style.display = "table-row";
+
+	// Hide feature descriptions and show form fields
+	viewInsertSeq.style.display = "none";
+	modifyInsertSeq.style.display = "table-row";
+
+	if (typeOfInsertView)
+		typeOfInsertView.style.display = "none";
+
+	typeOfInsertModify.style.display = "table-row";
+
+	if (openClosedView)
+		openClosedView.style.display = "none";
+
+	openClosedModify.style.display = "table-row";
+
+	// Hide length fields??
+	if (dnaLengthView)
+		dnaLengthView.style.display = "none";
+
+	if (cDNALengthView)
+		cDNALengthView.style.display = "none";
+
+	if (dnaLengthModify)
+		dnaLengthModify.style.display = "inline";
+
+	if (cDNALengthModify)
+		cDNALengthModify.style.display = "table-row";
+
+// 	exportFasta.style.display = "none";
+// 	viewRestrMap.style.display = "none";
+
+	editBtn.style.display = "none";
+	saveBtn.style.display = "inline";
+	cancelBtn.style.display = "inline";
+
+	// June 8/08: Disable Edit buttons for other sections
+	var introEditBtn = document.getElementById("editInsertIntro");
+	var featuresEditBtn = document.getElementById("editInsertSeqFeatures");
+	var editAnnosBtn = document.getElementById("editInsertAnnotations");
+	var editClassifiersBtn = document.getElementById("editInsertClassifiers");
+	var editParentsBtn = document.getElementById("editInsertParents");
+
+	introEditBtn.disabled = true;
+
+	// added check Jan. 8/09
+	if (featuresEditBtn)
+		featuresEditBtn.disabled = true;
+
+	// added check Jan. 8/09
+	if (editAnnosBtn)
+		editAnnosBtn.disabled = true;
+
+	// added check Jan. 8/09
+	if (editClassifiersBtn)
+		editClassifiersBtn.disabled = true;
+
+	// Most important: Insert may have no parents; if so, clicking 'Edit' would produce an error (Jan. 8/09)
+	if (editParentsBtn)
+		editParentsBtn.disabled = true;
+
+	document.getElementById("changeStateSeq").value = "Modify";	// must set for Python
+}
+
+
+function switchVectorSequenceModify()
+{
+	var viewVectorSeq = document.getElementById("vector_seq_div_view");
+	var modifyVectorSeq = document.getElementById("vector_seq_div_modify");
+
+	var editBtn = document.getElementById("editVectorSeq");
+	var saveBtn = document.getElementById("saveVectorSeq");
+	var cancelBtn = document.getElementById("cancelChangeVectorSeq");
+
+	viewVectorSeq.style.display = "none";
+	modifyVectorSeq.style.display = "table-row";
+	
+	editBtn.style.display = "none";
+	saveBtn.style.display = "inline";
+	cancelBtn.style.display = "inline";
+
+	var introEditBtn = document.getElementById("editVectorIntro");
+	var featuresEditBtn = document.getElementById("editVectorFeatures");
+	var editParentsBtn = document.getElementById("editVectorParents");
+
+	introEditBtn.disabled = true;
+
+	if (featuresEditBtn)	// Jan. 8/09
+		featuresEditBtn.disabled = true;
+
+	if (editParentsBtn)	// Jan. 8/09
+		editParentsBtn.disabled = true;
+
+	document.getElementById("changeStateSeq").value = "Modify";	// must set for Python
+}
+
+// Feb. 28/08: JUST SUBMIT THE FORM!!!!!!!!!!!!!!!!!!!!  DO ***NOT*** CHANGE DISPLAY - Python will redirect back to Detailed view, which would take care of visibility
+function saveInsertSequence()
+{
+// 	var exportLinks = document.getElementById("exportLinks");
+
+	if (verifyInsertSaveSequence())
+	{
+		// NO!!!!!!
+		// 	var viewInsertIntro = document.getElementById("insert_intro_tbl_view");
+		// 	var modifyInsertIntro = document.getElementById("insert_intro_tbl_modify");
+		
+		// 	var editBtn = document.getElementById("editInsertIntro");
+		// 	var saveBtn = document.getElementById("saveInsertIntro");
+		
+		// 	viewInsertIntro.style.display = "inline";
+		// 	modifyInsertIntro.style.display = "none";
+		// 
+		// 	editBtn.style.display = "inline";
+		// 	saveBtn.style.display = "none";
+
+		result = confirm("Please note:\n\nAll sequence feature positions will be adjusted upon saving.  You can edit them manually later using the 'Edit Features' function.\n\nAny features directly affected by the change in sequence will be automatically deleted.\n\nAre you sure you wish to proceed?");
+
+// 		exportLinks.style.display = "table-row";
+
+		if (result)
+		{
+			document.getElementById("changeStateSeq").value = "Save";	// remember to set this for Python
+			document.insertSequenceForm.submit();
+		}
+	}
+}
+
+
+function showHidePropertyInputValues(cellID)
+{
+	var inputFormatSelect = document.getElementById("propInputFormat");
+	var inputFormatSelectedIndex = inputFormatSelect.selectedIndex;
+	var inputFormat = inputFormatSelect[inputFormatSelectedIndex].value;
+
+	var propValsCell = document.getElementById(cellID);
+	var newEl;
+
+	switch (inputFormat)
+	{
+		case "plain_text":
+// 			newEl = document.createElement("INPUT");
+// 			newEl.setAttribute("type", "text");
+		break;
+
+		case "dropdown":
+
+		break;
+
+		case "radio_btn":
+
+		break;
+
+		case "checkboxes":
+
+		break;
+	}
+
+	propValsCell.appendChild(newEl);
+}
+
+
+// May 20/08: Make sure Novel vector sequence is filled in and does not contain characters other than ACGT
+function verifyNovelVectorSequence()
+{
+	var dna_sequence = document.getElementById("dna_sequence_");
+	var sequence_warning = document.getElementById("vector_sequence_warning");
+	var seq = trimAll(dna_sequence.value);
+
+// Removed Dec. 15/08 at Karen's request - do not make Novel vector sequence mandatory
+// 	if (seq == "")
+// 	{
+// 		alert("Please provide a sequence for the Novel Vector");
+// 		dna_sequence.focus();
+// 		sequence_warning.style.display = "inline";
+// 
+// 		return false;
+// 	}
+// 	else
+// 		sequence_warning.style.display = "none";
+
+	for (i = 0; i < seq.length; i++)
+	{
+		aChar = seq.charAt(i).toLowerCase();
+
+		if ( (aChar != 'a') && (aChar != 'c') && (aChar != 'g') && (aChar != 't') && (aChar != 'n'))
+		{
+			var answer = confirm("Vector sequence contains characters other than A, C, G, T or N.  Saving will remove these extra characters.  Are you sure you wish to proceed?");
+
+			if (answer == 0)
+			{
+				dna_sequence.focus();
+				return false;
+			}
+			else
+			{
+				// Filter unwanted chars first, then save
+				new_sequence = filterDNASeq(seq);
+				dna_sequence.value = new_sequence;
+				break;
+			}
+		}
+	}
+	
+	return true;
+}
+
+function saveVectorSequence()
+{
+	if (verifySequence())
+	{
+		result = confirm("Please note:\n\nAll sequence feature positions will be adjusted upon saving.  You can edit them manually later using the 'Edit Features' function.\n\nAny features directly affected by the change in sequence will be automatically deleted.\n\nAre you sure you wish to proceed?");
+
+		if (result)
+		{
+			document.getElementById("changeStateSeq").value = "Save";	// remember to set this for Python
+			document.vectorSequenceForm.submit();
+		}
+	}
+}
+
+function cancelInsertSequenceModification()
+{
+// Changed again April 10/08 - refreshing the page is not always a good idea; sometimes get a 'POSTDATA' warning
+// 	window.location.reload();	// april 2/08
+
+// 	var viewInsertSeq = document.getElementById("insert_seq_div_view");
+// 	var modifyInsertSeq = document.getElementById("insert_seq_div_modify");
+// 
+// 	var typeOfInsertView = document.getElementById("type_of_insert");
+// 	var typeOfInsertModify = document.getElementById("itype_modify");
+// 
+// 	var openClosedView = document.getElementById("viewOpenClosed");
+// 	var openClosedModify = document.getElementById("modifyOpenClosed");
+// 
+// 	var cdnaModify = document.getElementById("cdnaModify");
+// 
+// 	var dnaLength = document.getElementById("dnaLength");
+// 	var cDNALength = document.getElementById("cDNALength");
+// 
+// 	var editBtn = document.getElementById("editInsertSeq");
+// 	var saveBtn = document.getElementById("saveInsertSeq");
+// 	var cancelBtn = document.getElementById("cancelChangeInsertSeq");
+// 
+// 	viewInsertSeq.style.display = "table-row";
+// 	modifyInsertSeq.style.display = "none";
+// 
+// 	cdnaModify.style.display = "none";
+// 
+// 	dnaLength.style.display = "table-row";
+// 	cDNALength.style.display = "table-row";
+// 
+// 	typeOfInsertView.style.display = "inline";
+// 	typeOfInsertModify.style.display = "none";
+// 
+// 	if (openClosedView)
+// 		openClosedView.style.display = "table-row";
+// 
+// 	openClosedModify.style.display = "none";
+// 
+// 	editBtn.style.display = "inline";
+// 	saveBtn.style.display = "none";
+// 	cancelBtn.style.display = "none";
+
+	// April 10/08: Final, optimal solution
+	document.getElementById("changeStateFeatures").value = "Cancel";	// must set for Python
+	document.reagentDetailForm.submit();
+}
+
+
+function saveOtherReagentFeatures()
+{
+	enableSites();
+	changeFieldNames('reagentDetailForm', 'featuresTableModify');
+	setFeaturePositions();
+	verifyPositions();
+
+	document.getElementById("changeStateFeatures").value = "Save";	// remember to set this for Python
+	document.otherReagentFeaturesForm.submit();
+}
+
+function cancelOtherReagentFeaturesModification()
+{
+	document.getElementById("changeStateFeatures").value = "Cancel";	// remember to set this for Python
+	document.otherReagentFeaturesForm.submit();
+}
+
+
+function cancelOtherReagentClassifiersModification()
+{
+	document.getElementById("changeStateClassifiers").value = "Cancel";	// remember to set this for Python
+	document.otherReagentClassifiersForm.submit();
+}
+
+// External IDs - formerly 'annotations'
+function switchOtherReagentExternalIDsModify()
+{
+	var viewExternalIDs = document.getElementById("other_reagent_external_ids_tbl_view");
+	var modifyExternalIDs = document.getElementById("other_reagent_external_ids_tbl_modify");
+
+	var editBtn = document.getElementById("editOtherReagentExternalIDs");
+	var saveBtn = document.getElementById("saveOtherReagentExternalIDsBtn");
+	var cancelBtn = document.getElementById("cancelChangeOtherReagentExternalIDs");
+
+	var seqEditBtn = document.getElementById("editOtherReagentSequence");
+	var introEditBtn = document.getElementById("editOtherReagentIntro");
+	var featuresEditBtn = document.getElementById("editOtherReagentFeatures");
+	var classifiersEditBtn = document.getElementById("editOtherReagentClassifiers");
+	var editParentsBtn = document.getElementById("editOtherReagentParents");
+
+	viewExternalIDs.style.display = "none";
+	modifyExternalIDs.style.display = "table-row";
+
+	editBtn.style.display = "none";
+	saveBtn.style.display = "inline";
+	cancelBtn.style.display = "inline";
+
+	if (introEditBtn)	// Jan. 8/09
+		introEditBtn.disabled = true;
+
+	if (seqEditBtn)	// Jan. 8/09
+		seqEditBtn.disabled = true;
+
+	if (featuresEditBtn)	// Jan. 8/09
+		featuresEditBtn.disabled = true;
+
+	if (classifiersEditBtn)	// Jan. 8/09
+		classifiersEditBtn.disabled = true;
+
+	if (editParentsBtn)	// Jan. 8/09
+		editParentsBtn.disabled = true;
+
+	// May 25/09: Custom categories
+	var customCategories = document.getElementsByName("save_other_property_category");
+	var tmpCatAlias;
+	var tmpCatEditBtn;
+
+	for (i = 0; i < customCategories.length; i++)
+	{
+		tmpCatAlias = customCategories[i].value;
+// 		alert(tmpCatAlias);
+		tmpCatEditBtn = document.getElementById("editOtherReagent_" + tmpCatAlias + "_btn");
+
+		if (tmpCatEditBtn)
+			tmpCatEditBtn.disabled = true;
+	}
+
+	document.getElementById("changeStateExternalIDs").value = "Modify";	// must set for Python
+}
+
+
+function cancelOtherReagentModification(propCategoryAlias)
+{
+	// Find the appropriate form
+	var form_name = "otherReagentProps_" + propCategoryAlias + "_form";
+
+	docForms = document.forms;
+
+	for (i = 0; i < docForms.length; i++)
+	{
+		aForm = docForms[i];
+
+		if (aForm.name == form_name)
+		{
+			document.getElementById('changeState_' + propCategoryAlias).value='Cancel';
+			aForm.submit();
+		}
+	}
+}
+
+
+// May 22/09 - On novel reagent types, edit custom categories
+function switchOtherReagentPropsModify(propCategoryAlias)
+{
+	var viewTblID = "other_reagent_" + propCategoryAlias + "_tbl_view";
+	var modifyTblID = "other_reagent_" + propCategoryAlias + "_tbl_modify";
+
+	var viewTable = document.getElementById(viewTblID);
+	var modifyTable = document.getElementById(modifyTblID);
+
+	var editBtn = document.getElementById("editOtherReagent_" + propCategoryAlias + "_btn");
+	var saveBtn = document.getElementById("saveOtherReagent_" + propCategoryAlias + "_btn");
+	var cancelBtn = document.getElementById("cancelChangeOtherReagent_" + propCategoryAlias + "_btn");
+
+	viewTable.style.display = "none";
+	modifyTable.style.display = "table-row";
+
+	editBtn.style.display = "none";
+	saveBtn.style.display = "inline";
+	cancelBtn.style.display = "inline";
+
+	// June 8/08: Disable Edit buttons for other sections
+	var introEditBtn = document.getElementById("editOtherReagentIntro");
+	var seqEditBtn = document.getElementById("editOtherReagentSequence");
+	var editFeaturesBtn = document.getElementById("editOtherReagentFeatures");
+	var editAnnosBtn = document.getElementById("editOtherReagentAnnotations");
+	var editClassifiersBtn = document.getElementById("editOtherReagentClassifiers");
+	var editParentsBtn = document.getElementById("editOtherReagentParents");
+	var externalIDsEditBtn = document.getElementById("editOtherReagentExternalIDs");
+	
+	// Need to disable other custom properties 'edit' sections too! think about this next week
+
+	introEditBtn.disabled = true;
+
+	if (seqEditBtn)
+		seqEditBtn.disabled = true;
+
+	if (editFeaturesBtn)
+		editFeaturesBtn.disabled = true;
+
+	if (externalIDsEditBtn)
+		externalIDsEditBtn.disabled = true;
+
+	if (editAnnosBtn)
+		editAnnosBtn.disabled = true;
+
+	if (editClassifiersBtn)
+		editClassifiersBtn.disabled = true;
+
+	if (editParentsBtn)
+		editParentsBtn.disabled = true;
+
+	// May 25/09: Other custom categories (except the one currently being edited)
+	var customCategories = document.getElementsByName("save_other_property_category");
+	var tmpCatAlias;
+	var tmpCatEditBtn;
+
+	for (i = 0; i < customCategories.length; i++)
+	{
+		tmpCatAlias = customCategories[i].value;
+// 		alert(tmpCatAlias);
+
+		if (tmpCatAlias != propCategoryAlias)
+		{
+			tmpCatEditBtn = document.getElementById("editOtherReagent_" + tmpCatAlias + "_btn");
+	
+			if (tmpCatEditBtn)
+				tmpCatEditBtn.disabled = true;
+		}
+	}
+
+	document.getElementById("changeState_" + propCategoryAlias).value = "Modify";
+}
+
+
+function switchOtherReagentFeaturesModify()
+{
+	var viewFeatures = document.getElementById("other_reagent_features_tbl_view");
+	var modifyFeatures = document.getElementById("other_reagent_features_tbl_modify");
+
+	var editBtn = document.getElementById("editOtherReagentFeatures");
+	var saveBtn = document.getElementById("saveOtherReagentFeaturesBtn");
+	var cancelBtn = document.getElementById("cancelChangeOtherReagentFeatures");
+
+	// Hide feature descriptions and show form fields
+	viewFeatures.style.display = "none";
+	modifyFeatures.style.display = "table-row";
+
+	editBtn.style.display = "none";
+	saveBtn.style.display = "inline";
+	cancelBtn.style.display = "inline";
+
+	// June 8/08: Disable Edit buttons for other sections
+	var introEditBtn = document.getElementById("editOtherReagentIntro");
+	var seqEditBtn = document.getElementById("editOtherReagentSequence");
+	var editAnnosBtn = document.getElementById("editOtherReagentAnnotations");
+	var editClassifiersBtn = document.getElementById("editOtherReagentClassifiers");
+	var editParentsBtn = document.getElementById("editOtherReagentParents");
+	var externalIDsEditBtn = document.getElementById("editOtherReagentExternalIDs");
+	
+	introEditBtn.disabled = true;
+
+	if (seqEditBtn)
+		seqEditBtn.disabled = true;
+
+	if (externalIDsEditBtn)
+		externalIDsEditBtn.disabled = true;
+
+	if (editAnnosBtn)	// Jan. 8/09
+		editAnnosBtn.disabled = true;
+
+	if (editClassifiersBtn)	// Jan. 8/09
+		editClassifiersBtn.disabled = true;
+
+	if (editParentsBtn)	// Jan. 8/09
+		editParentsBtn.disabled = true;
+
+	// May 25/09: Custom categories
+	var customCategories = document.getElementsByName("save_other_property_category");
+	var tmpCatAlias;
+	var tmpCatEditBtn;
+
+	for (i = 0; i < customCategories.length; i++)
+	{
+		tmpCatAlias = customCategories[i].value;
+// 		alert(tmpCatAlias);
+		tmpCatEditBtn = document.getElementById("editOtherReagent_" + tmpCatAlias + "_btn");
+
+		if (tmpCatEditBtn)
+			tmpCatEditBtn.disabled = true;
+	}
+
+	document.getElementById("changeStateFeatures").value = "Modify";	// must set for Python
+}
+
+// Feb. 28/08: Sequence Features modification - show in modify mode
+function switchInsertSequenceFeaturesModify()
+{
+	var viewInsertSeqFeatures = document.getElementById("insert_features_view");
+//	var modifyInsertSeqFeatures = document.getElementById("modifyReagentPropsTbl");
+	var modifyInsertSeqFeatures = document.getElementById("editFeaturesTbl");
+
+	var editBtn = document.getElementById("editInsertSeqFeatures");
+	var saveBtn = document.getElementById("saveInsertSeqFeatures");
+	var cancelBtn = document.getElementById("cancelChangeInsertSeqFeatures");
+
+	// Hide feature descriptions and show form fields
+	viewInsertSeqFeatures.style.display = "none";
+	modifyInsertSeqFeatures.style.display = "table-row";
+
+	editBtn.style.display = "none";
+	saveBtn.style.display = "inline";
+	cancelBtn.style.display = "inline";
+
+	// June 8/08: Disable Edit buttons for other sections
+	var introEditBtn = document.getElementById("editInsertIntro");
+	var seqEditBtn = document.getElementById("editInsertSeq");
+	var editAnnosBtn = document.getElementById("editInsertAnnotations");
+	var editClassifiersBtn = document.getElementById("editInsertClassifiers");
+	var editParentsBtn = document.getElementById("editInsertParents");
+
+	introEditBtn.disabled = true;
+
+	if (seqEditBtn)
+		seqEditBtn.disabled = true;
+
+	if (editAnnosBtn)	// Jan. 8/09
+		editAnnosBtn.disabled = true;
+
+	if (editClassifiersBtn)	// Jan. 8/09
+		editClassifiersBtn.disabled = true;
+
+	if (editParentsBtn)	// Jan. 8/09
+		editParentsBtn.disabled = true;
+
+	document.getElementById("changeStateFeatures").value = "Modify";	// must set for Python
+}
+
+
+// May 25/09: Save custom properties for novel reagent types.
+// Since there are infinite possibilities for the new properties, code differentiates between them by property alias, which is the function argument
+function saveOtherReagentProps(propAlias)
+{
+	// Find the appropriate form
+	var form_name = "otherReagentProps_" + propAlias + "_form";
+
+	docForms = document.forms;
+
+	for (i = 0; i < docForms.length; i++)
+	{
+		aForm = docForms[i];
+
+		if (aForm.name == form_name)
+		{
+			document.getElementById('changeState_' + propAlias).value='Save';
+			aForm.submit();
+		}
+	}
+}
+
+
+function saveInsertSequenceFeatures(form_name)
+{
+	var myForm = document.reagentDetailForm;
+
+	// Need to add start/stop validation here
+	if (verifyPositions(true))
+	{
+		setFeaturePositions();
+		changeFieldNames(form_name);
+
+		// Nov. 18/08 - Enable 'sites' textboxes
+		fpcs = document.getElementById("fpcs_txt_");
+		tpcs = document.getElementById("tpcs_txt_");
+	
+		fpcs.readonly = false;
+		tpcs.readonly = false;
+
+		document.getElementById('changeStateFeatures').value='Save';
+		document.reagentDetailForm.submit();
+	}
+}
+
+function cancelInsertSequenceFeaturesModification()
+{
+	document.getElementById("changeStateFeatures").value = "Cancel";	// remember to set this for Python
+	document.reagentDetailForm.submit();
+}
+
+
+// May 15/09 - edit 'Classifiers' section for custom reagent types
+function switchOtherReagentClassifiersModify()
+{
+	// Show all classifiers EXCEPT type of insert
+	var viewClassifiers = document.getElementById("other_reagent_classifiers_view");
+	var modifyClassifiers = document.getElementById("other_reagent_classifiers_modify");
+
+	var editBtn = document.getElementById("editOtherReagentClassifiers");
+	var saveBtn = document.getElementById("saveOtherReagentClassifiersBtn");
+	var cancelBtn = document.getElementById("cancelChangeOtherReagentClassifiers");
+
+	// Hide feature descriptions and show form fields
+	viewClassifiers.style.display = "none";
+	modifyClassifiers.style.display = "table-row";
+
+	editBtn.style.display = "none";
+	saveBtn.style.display = "inline";
+	cancelBtn.style.display = "inline";
+
+	// June 8/08: Disable Edit buttons for other sections
+	var introEditBtn = document.getElementById("editOtherReagentIntro");
+	var seqEditBtn = document.getElementById("editOtherReagentSequence");
+	var featuresEditBtn = document.getElementById("editOtherReagentFeatures");
+	var editAnnosBtn = document.getElementById("editOtherReagentExternalIDs");	// formerly 'annotations' - renamed to 'External Identifiers'
+	var editParentsBtn = document.getElementById("editInsertParents");
+
+	if (seqEditBtn)
+		seqEditBtn.disabled = true;
+
+	if (introEditBtn)
+		introEditBtn.disabled = true;
+
+	if (editAnnosBtn)
+		editAnnosBtn.disabled = true;
+
+	if (featuresEditBtn)
+		featuresEditBtn.disabled = true;
+
+	if (editParentsBtn)	// Jan. 8/09
+		editParentsBtn.disabled = true;
+
+	// May 25/09: Custom categories
+	var customCategories = document.getElementsByName("save_other_property_category");
+	var tmpCatAlias;
+	var tmpCatEditBtn;
+
+	for (i = 0; i < customCategories.length; i++)
+	{
+		tmpCatAlias = customCategories[i].value;
+// 		alert(tmpCatAlias);
+		tmpCatEditBtn = document.getElementById("editOtherReagent_" + tmpCatAlias + "_btn");
+
+		if (tmpCatEditBtn)
+			tmpCatEditBtn.disabled = true;
+	}
+
+	document.getElementById("changeStateClassifiers").value = "Modify";	// must set for Python
+}
+
+function switchInsertClassifiersModify()
+{
+	// Show all classifiers EXCEPT type of insert
+	var viewInsertClassifiers = document.getElementById("insert_classifiers_view");
+	var modifyInsertClassifiers = document.getElementById("insert_classifiers_modify");
+
+	var editBtn = document.getElementById("editInsertClassifiers");
+	var saveBtn = document.getElementById("saveInsertClassifiers");
+	var cancelBtn = document.getElementById("cancelChangeInsertClassifiers");
+
+	// Hide feature descriptions and show form fields
+	viewInsertClassifiers.style.display = "none";
+	modifyInsertClassifiers.style.display = "inline";
+
+	editBtn.style.display = "none";
+	saveBtn.style.display = "inline";
+	cancelBtn.style.display = "inline";
+
+	// Show form - it was hidden initially to save space
+	document.insertClassifiersForm.style.display = "inline";
+
+	// June 8/08: Disable Edit buttons for other sections
+	var introEditBtn = document.getElementById("editInsertIntro");
+	var seqEditBtn = document.getElementById("editInsertSeq");
+	var editAnnosBtn = document.getElementById("editInsertAnnotations");
+	var editFeaturesBtn = document.getElementById("editInsertSeqFeatures");
+	var editParentsBtn = document.getElementById("editInsertParents");
+
+	introEditBtn.disabled = true;
+
+	if (seqEditBtn)
+		seqEditBtn.disabled = true;
+
+	if (editAnnosBtn)	// Jan. 8/09
+		editAnnosBtn.disabled = true;
+
+	if (editFeaturesBtn)	// Jan. 8/09
+		editFeaturesBtn.disabled = true;
+
+	if (editParentsBtn)	// Jan. 8/09
+		editParentsBtn.disabled = true;
+
+	document.getElementById("changeStateClassifiers").value = "Modify";	// must set for Python
+}
+
+
+function saveInsertClassifiers()
+{
+	if (verifyInsertClassifiers())
+	{
+		document.getElementById("changeStateClassifiers").value = "Save";	// remember to set this for Python
+		document.insertClassifiersForm.submit();
+	}
+}
+
+function saveOtherReagentExternalIDs()
+{
+	document.getElementById("changeStateExternalIDs").value = "Save";	// remember to set this for Python
+	document.otherReagentExternalIDsForm.submit();
+}
+
+
+function saveOtherReagentClassifiers()
+{
+	document.getElementById("changeStateClassifiers").value = "Save";	// remember to set this for Python
+	document.otherReagentClassifiersForm.submit();
+}
+
+// March 10/08: At the moment only includes a type of insert - open/closed check; maybe add more afterwards
+function verifyInsertClassifiers()
+{
+	// Type of Insert can never be empty
+	var itype_list = document.getElementById("itype_list_class");
+	var itype_selectedInd = itype_list.selectedIndex;
+
+	var oc_list = document.getElementById("oc_list_class");
+	var oc_selectedInd = oc_list.selectedIndex;
+
+	var oc_warning = document.getElementById("oc_warning_class");
+	var it_warning = document.getElementById("it_warning_class");
+
+	// No Insert Type selected
+	if ((itype_selectedInd == 0) && (itype_list[itype_selectedInd].value == ""))
+	{
+		alert("You must select a Type of Insert to continue");
+		itype_list.focus();
+		it_warning.style.display = "inline";
+		oc_warning.style.display = "none";
+
+		return false;
+	}
+	else
+	{
+		it_warning.style.display = "none";
+
+		// If insert type is filled in, check open/closed
+		var itype_selectedValue = itype_list[itype_selectedInd].value;
+
+		if ((itype_selectedValue != "cDNA with UTRs") && (itype_selectedValue != "DNA Fragment") && (itype_selectedValue != "None"))
+		{
+			// must have an open/closed value
+			oc_sel_val = oc_list[oc_selectedInd].value;
+
+			if (oc_sel_val == "")
+			{
+				alert("You must select an Open/Closed value to continue");
+				oc_list.focus();
+				oc_warning.style.display = "inline";
+				return false;
+			}
+		}
+		else 	// added May 28/07 to hide warning if showing from previous error
+		{
+			if (oc_warning.style.display == "inline")
+			{
+				oc_warning.style.display = "none";
+			}
+		}
+
+		return true;
+	}
+
+
+	return false;
+}
+
+
+function cancelOtherReagentExternalIDsModification()
+{
+	// April 10/08: Final, optimal solution
+	document.getElementById("changeStateExternalIDs").value = "Cancel";	// must set for Python
+	document.otherReagentExternalIDsForm.submit();
+}
+
+
+function cancelInsertClassifiersModification()
+{
+	// April 10/08: Final, optimal solution
+	document.getElementById("changeStateClassifiers").value = "Cancel";	// must set for Python
+	document.insertClassifiersForm.submit();	
+}
+
+
+// Annotations
+function switchInsertAnnotationsModify()
+{
+	// Show all classifiers EXCEPT type of insert
+	var viewInsertAnnotations = document.getElementById("insert_annotations_view");
+	var modifyInsertAnnotations = document.getElementById("insert_annotations_modify");
+
+	var editBtn = document.getElementById("editInsertAnnotations");
+	var saveBtn = document.getElementById("saveInsertAnnotations");
+	var cancelBtn = document.getElementById("cancelChangeInsertAnnotations");
+
+	// Hide feature descriptions and show form fields
+	viewInsertAnnotations.style.display = "none";
+	modifyInsertAnnotations.style.display = "inline";
+
+	editBtn.style.display = "none";
+	saveBtn.style.display = "inline";
+	cancelBtn.style.display = "inline";
+
+	// Show form - it was hidden initially to save space
+	document.insertAnnotationsForm.style.display = "inline";
+
+	// June 8/08: Disable Edit buttons for other sections
+	var introEditBtn = document.getElementById("editInsertIntro");
+	var seqEditBtn = document.getElementById("editInsertSeq");
+	var editClassifiersBtn = document.getElementById("editInsertClassifiers");
+	var editFeaturesBtn = document.getElementById("editInsertSeqFeatures");
+	var editParentsBtn = document.getElementById("editInsertParents");
+
+	introEditBtn.disabled = true;
+
+	if (seqEditBtn)
+		seqEditBtn.disabled = true;
+
+	if (editClassifiersBtn)	// Jan. 8/09
+		editClassifiersBtn.disabled = true;
+
+	if (editFeaturesBtn)	// Jan. 8/09
+		editFeaturesBtn.disabled = true;
+
+	if (editParentsBtn)	// Jan. 8/09
+		editParentsBtn.disabled = true;
+
+	document.getElementById("changeStateAnnotations").value = "Modify";	// must set for Python
+}
+
+
+function saveInsertAnnotations()
+{
+	if (verifyInsertAnnotations())
+	{
+		document.getElementById("changeStateAnnotations").value = "Save";	// remember to set this for Python
+		document.insertAnnotationsForm.submit();
+	}
+}
+
+
+function verifyInsertAnnotations()
+{
+	return true;
+}
+
+
+
+function cancelInsertAnnotationsModification()
+{
+	document.getElementById("changeStateAnnotations").value = "Cancel";
+	document.insertAnnotationsForm.submit();
+}
+
+// July 3/08
+function switchVectorParentsModify()
+{
+	var viewVectorParents = document.getElementById("showVectorAssoc");
+	var modifyVectorParents = document.getElementById("editVectorAssoc");
+
+	var editBtn = document.getElementById("editReagentParentsBtn");
+	var saveBtn = document.getElementById("saveReagentParentsBtn");
+	var cancelBtn = document.getElementById("cancelChangeReagentParents");
+
+	viewVectorParents.style.display = "none";
+	modifyVectorParents.style.display = "inline";
+
+	editBtn.style.display = "none";
+	saveBtn.style.display = "inline";
+	cancelBtn.style.display = "inline";
+
+	// Disable Edit buttons for other sections
+// 	var introEditBtn = document.getElementById("editVectorIntro");
+// 	var seqEditBtn = document.getElementById("editVectorSeq");
+// 	var editFeaturesBtn = document.getElementById("editVectorFeatures");
+// 
+// 	introEditBtn.disabled = true;
+// 
+// 	if (seqEditBtn)
+// 		seqEditBtn.disabled = true;
+// 
+// 	editFeaturesBtn.disabled = true;
+
+	// disable the rest of Edit buttons!
+	var inputs = document.getElementsByTagName("INPUT");
+
+	for (i=0; i < inputs.length; i++)
+	{
+		var tmpInput = inputs[i];
+
+		if ((tmpInput.type == "button") && (tmpInput.id != "saveReagentParentsBtn") && (tmpInput.id != "cancelChangeReagentParents") && (tmpInput.id != "editReagentParentsBtn"))
+			tmpInput.disabled = true;
+	}
+
+	document.getElementById("changeStateParents").value = "Modify";		// must set for Python
+}
+
+
+function switchCellLineParentsModify()
+{
+	var viewCLParents = document.getElementById("showCellLineAssoc");
+	var modifyCLParents = document.getElementById("editCellLineAssoc");
+
+	var editBtn = document.getElementById("editReagentParentsBtn");
+// 	var saveBtn = document.getElementById("saveReagentParentsBtn");
+	var cancelBtn = document.getElementById("cancelChangeReagentParents");
+
+	viewCLParents.style.display = "none";
+	modifyCLParents.style.display = "inline";
+
+	editBtn.style.display = "none";
+// 	saveBtn.style.display = "inline";
+	cancelBtn.style.display = "inline";
+
+	// Disable Edit buttons for other sections
+// 	var introEditBtn = document.getElementById("editVectorIntro");
+// 	var seqEditBtn = document.getElementById("editVectorSeq");
+// 	var editFeaturesBtn = document.getElementById("editVectorFeatures");
+// 
+// 	introEditBtn.disabled = true;
+// 
+// 	if (seqEditBtn)
+// 		seqEditBtn.disabled = true;
+// 
+// 	editFeaturesBtn.disabled = true;
+
+	// disable the rest of Edit buttons!
+	var inputs = document.getElementsByTagName("INPUT");
+
+	for (i=0; i < inputs.length; i++)
+	{
+		var tmpInput = inputs[i];
+
+		if ((tmpInput.type == "button") && (tmpInput.id != "saveReagentParentsBtn") && (tmpInput.id != "cancelChangeReagentParents") && (tmpInput.id != "editReagentParentsBtn"))
+			tmpInput.disabled = true;
+	}
+
+	document.getElementById("changeStateParents").value = "Modify";		// must set for Python
+}
+
+
+// Jan. 30/09: Several verification cases when user selects the 'custom sites' option during creation or modification
+function verifyCustomSites()
+{
+	// 1. Check to ensure custom cloning sites are selected when the user chooses to reverse complement the Insert
+	var reverse_checkbox = document.getElementById("reverseComplementCheckbox");
+	var customSitesOptn = document.getElementById("customSitesCheckbox");
+
+	var insert_fpcs_list =  document.getElementById("fpcs_list");
+	var insert_tpcs_list =  document.getElementById("tpcs_list");
+
+	var pv_fpcs_list = document.getElementById("fpcs_list_1");
+	var pv_tpcs_list = document.getElementById("tpcs_list_1");
+
+	if (insert_fpcs_list)
+	{
+		var insert_fpcs_list_sel_ind = insert_fpcs_list.selectedIndex;
+		var insert_fpcs = insert_fpcs_list[insert_fpcs_list_sel_ind].value;
+	}
+	else
+	{
+		return true;
+	}
+	
+	if (insert_tpcs_list)
+	{
+		var insert_tpcs_list_sel_ind = insert_tpcs_list.selectedIndex;
+		var insert_tpcs = insert_tpcs_list[insert_tpcs_list_sel_ind].value;
+	}
+	else
+		return true;
+
+	if (pv_fpcs_list)
+	{
+		var pv_fpcs_list_sel_ind = pv_fpcs_list.selectedIndex;
+		var pv_fpcs = pv_fpcs_list[pv_fpcs_list_sel_ind].value;
+	}
+	else
+	{
+		return true;
+	}
+
+	if (pv_tpcs_list)
+	{
+		var pv_tpcs_list_sel_ind = pv_tpcs_list.selectedIndex;
+		var pv_tpcs = pv_tpcs_list[pv_tpcs_list_sel_ind].value;
+	}
+	else
+	{
+		return true;
+	}
+
+	if (reverse_checkbox)
+	{
+		if (reverse_checkbox.checked)
+		{
+			if (customSitesOptn)
+			{
+				if (!customSitesOptn.checked)
+				{
+					// confirm text with Karen on Monday
+					alert("Please customize the cloning sites if you wish to reverse complement the Insert");
+					return false;
+				}
+				else
+				{
+					if (insert_fpcs.toLowerCase() == 'other')
+					{
+						alert("Please specify the 5' Insert cloning site.");
+						return false;
+					}
+	
+					if (insert_tpcs.toLowerCase() == 'other')
+					{
+						alert("Please specify the 3' Insert cloning site.");
+						return false;
+					}
+
+					if (pv_fpcs.toLowerCase() == 'other')
+					{
+						alert("Please specify the 5' Parent Vector cloning site.");
+						return false;
+					}
+	
+					if (pv_tpcs.toLowerCase() == 'other')
+					{
+						alert("Please specify the 3' Parent Vector cloning site.");
+						return false;
+					}
+				}
+			}
+		}
+	}
+	else if (customSitesOptn)
+	{
+		if (insert_fpcs.toLowerCase() == 'other')
+		{
+			alert("Please specify the 5' Insert cloning site.");
+			return false;
+		}
+
+		if (insert_tpcs.toLowerCase() == 'other')
+		{
+			alert("Please specify the 3' Insert cloning site.");
+			return false;
+		}
+
+		if (pv_fpcs.toLowerCase() == 'other')
+		{
+			alert("Please specify the 5' Parent Vector cloning site.");
+			return false;
+		}
+	
+		if (pv_tpcs.toLowerCase() == 'other')
+		{
+			alert("Please specify the 3' Parent Vector cloning site.");
+			return false;
+		}
+	}
+
+	return true;
+}
+
+// Feb. 2/09: On Err=5 during NR Vector creation, if user wishes to RC Insert, s/he needs to also provide custom sites - this function sets their values to pass to CGI
+function setCustomSites()
+{
+	var pv_fpcs_list = document.getElementById('fpcs_list_1');
+	var pv_fpcs = document.getElementById('fpcs_val');
+
+	if (!pv_fpcs_list.disabled)
+	{
+		var pv_fpcs_list_sel_ind = pv_fpcs_list.selectedIndex;
+		var pv_fpcs_list_sel_val = pv_fpcs_list[pv_fpcs_list_sel_ind].value;
+
+		pv_fpcs.value = pv_fpcs_list_sel_val;
+	}
+
+
+	var pv_tpcs_list = document.getElementById('tpcs_list_1');
+	var pv_tpcs = document.getElementById('tpcs_val');
+
+	if (!pv_tpcs_list.disabled)
+	{
+		var pv_tpcs_list_sel_ind = pv_tpcs_list.selectedIndex;
+		var pv_tpcs_list_sel_val = pv_tpcs_list[pv_tpcs_list_sel_ind].value;
+
+		pv_tpcs.value = pv_tpcs_list_sel_val;
+	}
+}
+
+function changeVectorParents(scriptPath)
+{
+// alert("Changing parents, reverse insert " + reverseInsert);
+
+	var rID = document.getElementById("rID_hidden").value;
+
+	var vType = document.getElementById("vector_cloning_method").value;
+
+	xmlhttp1 = createXML();
+	url = scriptPath + "update.py";
+	xmlhttp1.open("POST", url, false);
+	xmlhttp1.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+
+	var url = hostName + "Reagent.php?View=6&rid=" + rID;
+
+	// Jan. 19/09: Add ability to customize sites (mainly for hybrids)
+	var customSitesBox = document.getElementById("customSitesCheckbox");
+
+	var customSites;
+
+	if (customSitesBox)
+	{
+		if (customSitesBox.checked)
+		{
+			customSites = true;
+	
+			insert_custom_five_prime = document.getElementsByName("insert_custom_five_prime")[0].value;
+			insert_custom_three_prime = document.getElementsByName("insert_custom_three_prime")[0].value;
+	
+			pv_custom_five_prime = document.getElementById("fpcs_list_1").value;
+			pv_custom_three_prime = document.getElementById("tpcs_list_1").value;
+	
+		}
+		else
+		{
+			customSites = false;
+	
+			insert_custom_five_prime = "";
+			insert_custom_three_prime = "";
+	
+			pv_custom_five_prime = "";
+			pv_custom_three_prime = "";
+		}
+	}
+	else
+	{
+		customSites = false;
+
+		insert_custom_five_prime = "";
+		insert_custom_three_prime = "";
+
+		pv_custom_five_prime = "";
+		pv_custom_three_prime = "";
+	}
+
+	// Jan. 20/09: Add ability to reverse complement the Insert before constructing a sequence
+	reverseInsert = false;
+
+	var reverseInsertBox = document.getElementById("reverseInsertCheckbox");
+
+	if (reverseInsertBox)
+	{
+		if (reverseInsertBox.checked)
+			reverseInsert = true;
+	}
+
+	if (verifyParentFormat(vType))
+	{
+		// July 8/08: general info
+		var newName = document.getElementById("new_vector_name").value;
+	
+		var newVectorTypesList = document.getElementById("new_vector_type");
+		var newVectorTypeIndex = newVectorTypesList.selectedIndex;
+		var newVectorType = newVectorTypesList[newVectorTypeIndex].value;
+	
+		var newProjectList = document.getElementById("new_packet_id");
+		var newProjectIndex = newProjectList.selectedIndex;
+		var newProjectID = newProjectList[newProjectIndex].value;
+	
+		var newDescription = document.getElementById("new_description").value;
+	
+		var newVerificationList = document.getElementById("new_verification");
+		var newVerIndex = newVerificationList.selectedIndex;
+		var newVerification = newVerificationList[newVerIndex].value;
+	
+		if (newName.length == 0)
+		{
+			alert("Please specify a Vector name.");
+			document.getElementById("new_vector_name").focus();
+
+			// show warning
+
+			return false;
+		}
+	
+		if ((newProjectIndex == 0) && (newProjectList[newProjectIndex].value == 0))
+		{
+			alert("Please select a project ID from the list to continue.");
+			return false;
+		}
+
+		document.getElementById("saveReagentParentsBtn").style.cursor = 'wait';
+
+		var uName = document.getElementById("curr_uname").value;
+
+		var params = "";
+		
+		var srcPV, srcInsert, srcIPV;
+
+		changeParentValues(vType);
+
+		// Check if parents are filled in
+		var parentVectorField = document.getElementById("parent_vector_id_txt");
+		var parentVector = parentVectorField.value;
+
+		srcPV = document.getElementById("parent_vector_id_txt").value;
+
+		// remember PV
+		document.getElementById("parent_vector_old_id").value = parentVector;
+
+		if (parentVector == "")
+		{
+			var proceed = confirm("Your Parent Vector value is empty.  Are you sure you wish to proceed?");
+
+			if (proceed)
+				return true;
+			else
+				parentVectorField.focus();
+		}
+		else
+		{
+			switch (vType)
+			{
+				case '1':
+				
+					// Non-recombination vector
+					srcInsert = document.getElementById("insert_id_txt").value;
+		
+					// Insert empty??
+					if (srcInsert == "")
+					{
+						var proceed = confirm("Your Insert value is empty.  Are you sure you wish to proceed?");
+
+						if (proceed)
+							return true;
+						else
+						{
+							// different parameters for different properties
+							seqParams = "reagent_id_hidden=" + rID + "&reagent_typeid_hidden=1&PV=" + srcPV + "&I=" + srcInsert + "&curr_username=" + uName + "&cloning_method_hidden=" + vType + "&change_state=Save&save_parents=1&newVectorName=" + newName + "&newVectorType=" + newVectorType + "&newProjectID=" + newProjectID + "&newDescription=" + newDescription + "&newVerification=" + newVerification;
+							
+							xmlhttp1.send(seqParams);
+							xmlhttp1.onreadystatechange = confirmChangeVectorParents(xmlhttp1, url);
+						}
+					}
+					else
+					{
+						// different parameters for different properties
+						seqParams = "reagent_id_hidden=" + rID + "&reagent_typeid_hidden=1&PV=" + srcPV + "&I=" + srcInsert + "&curr_username=" + uName + "&cloning_method_hidden=" + vType + "&change_state=Save&save_parents=1&newVectorName=" + newName + "&newVectorType=" + newVectorType + "&newProjectID=" + newProjectID + "&newDescription=" + newDescription + "&newVerification=" + newVerification + "&custom_sites=" + customSites + "&insert_custom_five_prime=" + insert_custom_five_prime + "&insert_custom_th [...]
+
+// 						prompt("", seqParams);
+						
+						xmlhttp1.send(seqParams);
+						xmlhttp1.onreadystatechange = confirmChangeVectorParents(xmlhttp1, url);
+					}
+				break;
+		
+				case '2':
+					
+					// Recombination vector
+					srcIPV = document.getElementById("ipv_id_txt").value;
+		
+					if (srcIPV == "")
+					{
+						var proceed = confirm("Your Insert Parent Vector value is empty.  Are you sure you wish to proceed?");
+
+						if (proceed)
+							return true;
+						else
+						{
+							// different parameters for different properties
+							seqParams = "reagent_id_hidden=" + rID + "&reagent_typeid_hidden=1&PV=" + srcPV + "&IPV=" + srcIPV + "&curr_username=" + uName + "&cloning_method_hidden=" + vType + "&change_state=Save&save_parents=1&newVectorName=" + newName + "&newVectorType=" + newVectorType + "&newProjectID=" + newProjectID + "&newDescription=" + newDescription + "&newVerification=" + newVerification;
+					
+							xmlhttp1.send(seqParams);
+							xmlhttp1.onreadystatechange = confirmChangeVectorParents(xmlhttp1, url);
+						}
+					}
+					else
+					{
+						// different parameters for different properties
+						seqParams = "reagent_id_hidden=" + rID + "&reagent_typeid_hidden=1&PV=" + srcPV + "&IPV=" + srcIPV + "&curr_username=" + uName + "&cloning_method_hidden=" + vType + "&change_state=Save&save_parents=1&newVectorName=" + newName + "&newVectorType=" + newVectorType + "&newProjectID=" + newProjectID + "&newDescription=" + newDescription + "&newVerification=" + newVerification;
+				
+						xmlhttp1.send(seqParams);
+						xmlhttp1.onreadystatechange = confirmChangeVectorParents(xmlhttp1, url);
+					}
+				break;
+			}
+		}
+	}
+	
+	document.getElementById("saveReagentParentsBtn").style.cursor = 'auto';
+	return true;
+}
+
+function confirmChangeVectorParents(xmlhttp, url)
+{
+	if (xmlhttp.readyState == 4)
+	{
+// 		alert(xmlhttp.status);
+// 		alert(xmlhttp.responseText);
+
+		if (xmlhttp.status == 200)
+		{
+			result = xmlhttp.responseText;
+
+// 			prompt("", xmlhttp.responseText);
+// 			toks = xmlhttp.responseText.split("&");
+
+// 			resTok = "Result=";
+// 			ind1 = toks[1].indexOf(resTok)+resTok.length;
+// 			result = toks[1].substring(ind1);
+
+// 			alert(result);
+
+			switch (parseInt(result))
+			{
+				case 0:
+					if (confirm("Vector sequence and features will change permanently upon saving.\nPlease note: You must select the 'Reverse Complement' option if you want the Insert to appear in reverse orientation in the new Vector sequence.  Otherwise, the default forward orientation will be used.\nAre you sure you wish to proceed?"))
+					{
+						redirect(url);
+					}
+				break;
+
+				case 1:
+					alert("Error: Cannot generate Vector sequence using the parent values provided: Unknown sites on Insert.  Please verify your input.")
+				break;
+
+				case 2:
+					alert("Error: Cannot generate Vector sequence using the parent values provided: Insert sites are not found in the parent vector sequence.")
+				break;
+
+				case 3:
+					alert("Error: Cannot generate Vector sequence using the parent values provided: Insert sites occur more than once in the parent vector sequence.  Please verify your input.")
+				break;
+
+				case 4:
+					alert("Error: Cannot generate Vector sequence using the parent values provided: Cloning sites cannot be hybridized.  Please verify your input.")
+				break;
+
+				case 5:
+					alert("Error: Cannot generate Vector sequence using the parent values provided: 5' cloning site occurs after the 3' site on parent sequence.  Please verify your input.")
+				break;
+
+				case 6:
+					alert("Error: Invalid reagent ID.\n\nOne or both of the parent IDs provided cannot be found in the database.  Please verify your input.")
+				break;
+
+				case 10:
+					// Get exact ID from Python - do it later
+					alert("Error: You do not have Write access to the project of the Parent Vector provided.  Please contact the project owner to obtain permission.")
+
+					// focus on the field
+				break;
+
+				case 11:
+					// Get exact ID from Python - do it later
+					alert("Error: You do not have Write access to the project of the Insert provided.  Please contact the project owner to obtain permission.")
+
+					// focus on the field
+				break;
+
+				case 12:
+					// Get exact ID from Python - do it later
+					alert("Error: You do not have Write access to the project of the Parent Insert Vector provided.  Please contact the project owner to obtain permission.")
+
+					// focus on the field
+				break;
+
+				// Updated Feb. 12/09: this is the wrong error; code 13 corresponds to sites not found in Insert; added err code 23 for empty sites (see below)
+				case 13:
+					// Get exact ID from Python - do it later
+					alert("Error: Cannot generate Vector sequence using the parent values provided.\n\nInsert sequence does not contain the restricton sites provided.\n\nPlease verify your input before proceeding.")
+
+					// focus on the field
+				break;
+
+				case 14:
+					// Get exact ID from Python - do it later
+					alert("Error: Cannot generate Vector sequence using the parent values provided.\n\nRestricton sites do not match Insert sequence at the specified positions.\n\nPlease verify your input before proceeding.")
+
+					// focus on the field
+				break;
+
+				case 15:
+					// Get exact ID from Python - do it later
+					alert("Error: Cannot generate Vector sequence using the parent values provided: Donor Vector sequence does not contain LoxP sites.  Please verify your input.")
+
+					// focus on the field
+				break;
+
+				case 16:
+					// Get exact ID from Python - do it later
+					alert("Error: Cannot generate Vector sequence using the parent values provided: Donor Vector sequence only contains one occurrence of LoxP site.  Please verify your input.")
+
+					// focus on the field
+				break;
+
+				case 17:
+					// Get exact ID from Python - do it later
+					alert("Error: Cannot generate Vector sequence using the parent values provided: Donor Vector sequence contains MORE than two occurrences of LoxP sites.  Please verify your input.")
+
+					// focus on the field
+				break;
+
+				case 19:
+					// Get exact ID from Python - do it later
+					alert("Error: Cannot generate Vector sequence using the parent values provided: Invalid type of reagent selected as parent.  Please verify your input.")
+
+					// focus on the field
+				break;
+
+				// Added Feb. 12/09
+				case 23:
+					alert("Error: Cannot generate Vector sequence using the parent values provided.\n\nInsert restricton site values are empty.\n\nPlease verify your input before proceeding.")
+				break;
+
+				default:
+					alert(result);
+				break;
+			}
+		}
+
+// 		return true;
+	}
+
+// 	return false;
+}
+
+function redirect(url)
+{
+	// Redirect back to detailed view
+	window.location.href = url
+}
+
+
+function switchReagentParentsModify(rTypeID)
+{
+	switch(rTypeID)
+	{
+		case 'Vector':
+			switchVectorParentsModify();
+		break;
+
+// 		case 'Insert':
+// 			switchInsertParentsModify();
+// 		break;
+
+		case 'CellLine':
+			// Update Feb. 3/10: show full form after clicking 'Change', not when enetering 'Edit parents' mode
+// 			rID = document.getElementById("rID_hidden").value;
+// 			window.location.href= hostName + "Reagent.php?View=6&rid=" + rID + "&mode=Modify";
+			switchCellLineParentsModify();
+		break;
+
+		default:
+
+			var viewParentsTbl = document.getElementById("viewReagentParents");
+			var editParentsTbl = document.getElementById("category_assoc_section_" + rTypeID);
+		
+			var editBtn = document.getElementById("editReagentParentsBtn");
+			var saveBtn = document.getElementById("saveReagentParentsBtn");
+			var cancelBtn = document.getElementById("cancelChangeReagentParents");
+		
+			viewParentsTbl.style.display = "none";
+			editParentsTbl.style.display = "inline";
+		
+			editBtn.style.display = "none";
+			saveBtn.style.display = "inline";
+			cancelBtn.style.display = "inline";
+		
+			// disable the rest of Edit buttons!
+			var inputs = document.getElementsByTagName("INPUT");
+		
+			for (i=0; i < inputs.length; i++)
+			{
+				var tmpInput = inputs[i];
+		
+				if ((tmpInput.type == "button") && (tmpInput.id != "saveReagentParentsBtn") && (tmpInput.id != "cancelChangeReagentParents") && (tmpInput.id != "editReagentParentsBtn"))
+					tmpInput.disabled = true;
+			}
+		
+			document.getElementById("changeStateParents").value = "Modify";		// must set for Python	
+
+		break;
+	}
+}
+
+
+function switchInsertParentsModify()
+{
+	// Show parents
+// 	var viewInsertParents = document.getElementById("insert_parents_view");
+	var viewInsertParents = document.getElementById("viewReagentParents");		// update 11/09/09 - common output function
+// 	var modifyInsertParents = document.getElementById("insert_parents_modify");
+	var modifyInsertParents = document.getElementById("category_assoc_section_Insert");	// update 11/09/09
+
+// 	var editBtn = document.getElementById("editInsertParents");
+	var editBtn = document.getElementById("editReagentParentsBtn");
+// 	var saveBtn = document.getElementById("saveInsertParentsBtn");
+	var saveBtn = document.getElementById("saveReagentParentsBtn");
+// 	var cancelBtn = document.getElementById("cancelChangeInsertParents");
+	var cancelBtn = document.getElementById("cancelChangeReagentParents");
+
+	// Hide view parents form and show modification form
+	viewInsertParents.style.display = "none";
+	modifyInsertParents.style.display = "inline";
+
+	editBtn.style.display = "none";
+	saveBtn.style.display = "inline";
+	cancelBtn.style.display = "inline";
+
+	// Show form - it was hidden initially to save space
+// 	document.insertParentsForm.style.display = "inline";
+	document.reagentParentsForm.style.display = "inline";
+
+	// June 8/08: Disable Edit buttons for other sections
+	var introEditBtn = document.getElementById("editInsertIntro");
+	var seqEditBtn = document.getElementById("editInsertSeq");
+	var editClassifiersBtn = document.getElementById("editInsertClassifiers");
+	var editFeaturesBtn = document.getElementById("editInsertSeqFeatures");
+	var editAnnosBtn = document.getElementById("editInsertAnnotations");
+
+	introEditBtn.disabled = true;
+
+	if (seqEditBtn)
+		seqEditBtn.disabled = true;
+
+	editClassifiersBtn.disabled = true;
+	editFeaturesBtn.disabled = true;
+	editAnnosBtn.disabled = true;
+
+	document.getElementById("changeStateParents").value = "Modify";	// must set for Python
+}
+
+
+function saveReagentParents(rType)
+{
+// alert(rType);
+// alert(parentsValid);
+
+	if (parentsValid)
+	{
+		switch (rType)
+		{
+			case 'Vector':
+				changeVectorParents(cgiPath);
+			break;
+	
+	// 		case 'Insert':
+	// 			saveInsertParents();
+	// 		break;
+	
+			case 'CellLine':
+				if (verifyCellLineParents())
+				{
+					changeParentValues(5);
+					document.reagentParentsForm.submit();
+				}
+			break;
+	
+			default:
+			// 	if (verifyReagentParents())
+			// 	{
+					document.getElementById("changeStateParents").value = "Save";	// remember to set this for Python
+					document.reagentParentsForm.submit();
+			// 	}
+			break;
+		}
+	}
+	else
+	{
+		return false;
+	}
+}
+
+function saveInsertParents()
+{
+	if (verifyInsertParents())
+	{
+		document.getElementById("changeStateParents").value = "Save";	// remember to set this for Python
+		document.insertParentsForm.submit();
+	}
+}
+
+// maybe update later
+function verifyInsertParents()
+{
+	return true;
+}
+
+
+function cancelInsertParentsModification()
+{
+	// As before, set change_state to 'Cancel' and submit form
+	document.getElementById("changeStateParents").value = "Cancel";
+	document.insertParentsForm.submit();
+}
+
+function cancelVectorParentsModification()
+{
+	// As before, set change_state to 'Cancel' and submit form
+	document.getElementById("changeStateParents").value = "Cancel";
+	document.vectorParentsForm.submit();
+}
+
+function cancelVectorSequenceModification()
+{
+	document.getElementById("changeStateSeq").value = "Cancel";
+	document.vectorSequenceForm.submit();
+}
+
+function cancelVectorFeaturesModification()
+{
+	document.getElementById("changeStateFeatures").value = "Cancel";
+	document.reagentDetailForm.submit();
+}
+
+// JUST UNHIDE THE HIDDEN EDIT SECTION, **NO** SERVER-SIDE PROCESSING!!!
+function switchVectorFeaturesModify()
+{
+	viewPropsTbl = document.getElementById("viewReagentPropsTbl");
+// 	modifyPropsTbl = document.getElementById("modifyReagentPropsTbl");
+	modifyPropsTbl = document.getElementById("editFeaturesTbl");
+
+	saveBtn = document.getElementById("saveVectorFeatures");
+	editBtn = document.getElementById("editVectorFeatures");
+	cancelBtn = document.getElementById("cancelChangeVectorFeatures");
+
+	viewPropsTbl.style.display = "none";
+	modifyPropsTbl.style.display = "inline";
+
+	editBtn.style.display = "none";
+	saveBtn.style.display = "inline";
+	cancelBtn.style.display = "inline";
+
+	// June 3/08: To ensure only one section is edited at a time, disable all other buttons until 'features' section is saved
+	editIntroBtn = document.getElementById("editVectorIntro");
+	editSeqBtn = document.getElementById("editVectorSeq");
+	editParentsBtn = document.getElementById("editVectorParents");
+
+	editIntroBtn.disabled = true;
+	editSeqBtn.disabled = true;
+
+	if (editParentsBtn)	// Jan. 8/09
+		editParentsBtn.disabled = true;
+}
+
+function saveVectorSeqFeatures(form_name)
+{
+// 	var myForm = document.reagentDetailForm;
+
+	// Need to add start/stop validation here
+	if (verifyPositions(false))
+	{
+		enableSites();
+		setFeaturePositions();
+		changeFieldNames(form_name);
+
+		// Nov. 18/08 - Enable 'sites' textboxes
+		reagentType = getReagentType();
+		subtype = getReagentSubtype(reagentType);
+
+		fpcs = document.getElementById("fpcs_txt_"+subtype);
+		tpcs = document.getElementById("tpcs_txt_"+subtype);
+
+		fpcs.readonly = false;
+		tpcs.readonly = false;
+
+		fpcs.style.backgroundColor = "#FFFFFF";
+		tpcs.style.backgroundColor = "#FFFFFF";
+
+		document.getElementById("changeStateFeatures").value = "Save";
+
+		docForms = document.forms;
+	
+		for (i = 0; i < docForms.length; i++)
+		{
+			aForm = docForms[i];
+	
+			if (aForm.name == form_name)
+			{
+				aForm.submit();
+			}
+		}
+	}
+}
+
+// add mandatory fields check - name, status, etc. filled in, maybe more
+function validateVector()
+{
+	document.reagentDetailForm.submit();
+}
+
+// Updated July 14/08
+// This would generate a PDF file
+function prepareVectorMap(scriptPath)
+{
+// 	return popup("/tmp/vector_maps/V3863_map.pdf", "V3863_map.pdf", 1200, 1200, 'yes');	// test
+
+	reagentID = document.getElementById("hidden_vector_id");
+
+	if (reagentID)
+	{
+		rID = reagentID.value;
+// 		alert(rID);
+
+		url = scriptPath + "vector_map.py";
+		xmlhttp1 = createXML();
+		xmlhttp1.open("POST", url, false);
+		xmlhttp1.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+	
+		seqParams = "rID=" + rID;
+	
+		xmlhttp1.send(seqParams);
+		xmlhttp1.onreadystatechange = showVectorMap(xmlhttp1, scriptPath);
+	}
+
+// 	document.show_vector_map_form.submit();		// NO
+}
+
+function showVectorMap(xmlhttp, scriptPath)
+{
+	limsID = document.getElementById("lims_id").value;
+
+	if (xmlhttp.readyState == 4)
+	{
+// 		alert(xmlhttp.status);
+// 		alert(xmlhttp.responseText);
+
+		mapTab = document.getElementById("vector_map_tab");
+	
+		if (xmlhttp.status == 200)
+		{
+			fName = trimAll(xmlhttp.responseText);
+// 			mapTab.innerHTML = "<IMG SRC=\"" + fName + "\">";
+// 			popup(fName, limsID, 1200, 1200, 'yes');
+// 			return;
+		}
+	}
+}
+
+function prepareOligoMap(scriptPath)
+{
+	reagentID = document.getElementById("hidden_vector_id");
+
+	if (reagentID)
+	{
+		rID = reagentID.value;
+// 		alert(rID);
+
+		url = scriptPath + "oligos_vector_map.py";
+		xmlhttp1 = createXML();
+		xmlhttp1.open("POST", url, false);
+		xmlhttp1.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+	
+		seqParams = "rID=" + rID;
+	
+		xmlhttp1.send(seqParams);
+		xmlhttp1.onreadystatechange = showOligoMap(xmlhttp1, scriptPath);
+	}
+}
+
+function showOligoMap(xmlhttp, scriptPath)
+{
+	limsID = document.getElementById("lims_id").value;
+
+	if (xmlhttp.readyState == 4)
+	{
+// 		alert(xmlhttp.status);
+// 		alert(xmlhttp.responseText);
+
+		mapTab = document.getElementById("vector_map_tab");
+	
+		if (xmlhttp.status == 200)
+		{
+			fName = trimAll(xmlhttp.responseText);
+// 			mapTab.innerHTML = "<IMG SRC=\"" + fName + "\">";
+// 			popup(fName, limsID, 1200, 1200, 'yes');
+// 			return;
+		}
+	}
+}
+
+function showMapMenu(oligoMap, limsID, url)
+{
+
+	mapMenu = document.getElementById("mapMenu");
+
+	if (mapMenu)
+	{
+		currOptn = mapMenu[mapMenu.selectedIndex];
+
+		switch (currOptn.id)
+		{
+			case 'viewOligoMap':
+				mapMenu.selectedIndex = 0;
+				mapMenu[mapMenu.selectedIndex].selected = true;
+				return popup(oligoMap, limsID, 1200, 1200, 'yes');
+			break;
+
+			case 'viewVectorMap':
+				mapMenu.selectedIndex = 0;
+				mapMenu[mapMenu.selectedIndex].selected = true;
+ 				return popup(url, limsID, 1200, 1200, 'yes');
+			break;
+		}
+	}
+}
+
+function hideMenu()
+{
+	var menuDiv = document.getElementById("mainMenu");
+
+	if (menuDiv.style.display == "none")
+		menuDiv.style.display = "inline";
+	else
+		menuDiv.style.display = "none";
+}
+
+
+function resize()
+{
+	document.onmouseup = function()
+	{
+		var mainDiv = document.getElementById("mainDiv");
+		var menuDiv = document.getElementById("mainMenu");
+		var bodyWidth = document.body.offsetWidth;
+		var menuWidth;
+
+		var e = arguments[0] || event;
+		// alert('X: ' + e.clientX + '\nY: ' + e.clientY);
+
+		// resize menu
+		menuDiv.style.width = e.clientX;
+
+		// resize main div
+		menuWidth = menuDiv.offsetWidth;
+		mainDiv.style.width = bodyWidth - menuWidth;
+	}
+}
+
+
+// Dec. 22, 2010
+function showHideAddLocation()
+{
+	var chemLocsList = document.getElementById("chemical_locations");
+	var newChemLocDiv = document.getElementById("add_chem_loc");
+	var createLocation = document.getElementById("addLocName");
+	var addLocTypeList = document.getElementById("chem_loc_type_list");
+
+	if (chemLocsList[chemLocsList.selectedIndex].value == "addChemLoc")
+	{
+		newChemLocDiv.style.display = "inline";
+		createLocation.value = "1";
+		addLocTypeList.disabled = '';
+	}
+	else
+	{
+		newChemLocDiv.style.display = "none";
+		createLocation.value = "0";
+		addLocTypeList.disabled = 'disabled';
+	}
+}
+
+// Dec. 22, 2010
+function showHideAddLocType()
+{
+	var chemLocTypeList = document.getElementById("chem_loc_type_list");
+	var newChemLocTypeDiv = document.getElementById("add_chem_loc_type");
+	var createLocationType = document.getElementById("addLocType");
+
+	if (chemLocTypeList[chemLocTypeList.selectedIndex].value == "addChemLocType")
+	{
+		newChemLocTypeDiv.style.display = "inline";
+		createLocationType.value = "1";
+	}
+	else
+	{
+		newChemLocTypeDiv.style.display = "none";
+		createLocationType.value = "0";
+	}
+}
+
+
+// Dec. 20, 2010
+function checkChemicalCreation()
+{
+	// Mandatory fields: chemical name, location, location type
+	var chemName = document.getElementById("chemical_name");
+	var chemLocsList = document.getElementById("chemical_locations");
+	var newChemLocType = document.getElementById("new_chem_loc_type");
+	var newChemLocName = document.getElementById("new_chem_loc_name");
+	var chemLocTypesList = document.getElementById("chem_loc_type_list");
+
+	var addLocName = document.getElementById("addLocName").value;
+	var addLocType = document.getElementById("addLocType").value;
+
+	// jan. 22, 2011
+	var existingLocationNamesList = document.getElementById("existingLocationNamesList");
+
+	if (chemName)
+	{
+		if (trimAll(chemName.value).length == 0)
+		{
+			alert("Please provide a chemical name.");
+			chemName.focus();
+			return false;
+		}
+	}
+
+	if ((addLocType == '1') && newChemLocType)
+	{
+		if (trimAll(newChemLocType.value).length == 0)
+		{
+			alert("Please provide a location type.");
+			newChemLocType.focus();
+			return false;
+		}
+	}
+
+	if ((addLocName == '1') && newChemLocName)
+	{
+		//alert(existingLocationNamesList.selectedIndex);
+
+		if ( (existingLocationNamesList.selectedIndex == 0) && (trimAll(newChemLocName.value).length == 0) )
+		{
+			alert("Please provide a storage name or room number.");
+			newChemLocName.focus();
+			return false;
+		}
+	}
+
+
+	if (chemLocsList)
+	{
+		if (chemLocsList.selectedIndex == 0)
+		{
+			alert("Please select a location from the list.");
+			chemLocsList.focus();
+			return false;
+		}
+	}
+
+	if (chemLocTypesList)
+	{
+		if (!chemLocTypesList.disabled)
+		{
+			if (chemLocTypesList.selectedIndex == 0)
+			{
+				alert("Please select a location type from the list.");
+				chemLocTypesList.focus();
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
+
+function showChemicalLocationList()
+{
+	var searchCriteriaList = document.getElementById("search_criteria_list");
+	var chemLocsList = document.getElementById("chemical_locations");
+	var searchTerm = document.getElementById("chem_search_keyword");
+
+	var i = searchCriteriaList.selectedIndex;
+	var selElement = searchCriteriaList[i].text;
+
+	var chem_search_caption = document.getElementById("chem_search_caption");
+
+	if (selElement == "Location")
+	{
+		searchTerm.style.display = "none";
+		chemLocsList.style.display = "inline";
+
+		chem_search_caption.innerHTML = "Select a Location from the list:";
+	}
+	else
+	{
+		// hide locations
+		searchTerm.style.display = "inline";
+		chemLocsList.style.display = "none";
+	
+		chem_search_caption.innerHTML = "Enter search keyword:";
+	}
+}
+
+
+/**
+	April-June 2009: Functions for adding new reagent types
+*/
+
+// August 4/09: Disallow submitting a form whose action depends on a selected dropdown list value if the value is 'default'
+function checkSelected(listID)
+{
+	var dropdown = document.getElementById(listID);
+
+	if ((dropdown.selectedIndex == 0) || (dropdown[dropdown.selectedIndex].value == "default"))
+		return false;
+
+	return true;
+}
+
+
+// Aug. 5/09: Delete property at step 2 reagent type creation
+function deleteReagentTypeAttribute(rowID, formID)
+{
+	catAlias = rowID.substr(0, rowID.indexOf("_:_"));
+// alert(catAlias);
+	str_1 = catAlias + "_:_";
+// alert(str_1.length);
+// alert(rowID.indexOf("_prop_row"));
+	propAlias = rowID.substr(str_1.length, rowID.indexOf("_prop_row")-(str_1.length));
+// alert(propAlias);
+// alert(rowID);
+	rowID = unescape(rowID);
+// 	rowID = replaceAll(rowID, "'", "\\'");		// keep this!! - No, removed Nov. 6/09
+// alert(rowID);
+// alert(formID);
+	categoryList = document.getElementsByName(catAlias + "[]");
+// alert(categoryList);
+
+	var cond;
+
+// 	if (rowID.indexOf("tag_position") >= 0)
+	if ((propAlias == "tag_position") || (propAlias == "expression_system"))
+	{
+// alert("removing tag pos");
+		cond = true;
+	}
+	else
+		cond = confirm("Are you sure you want to remove this attribute?");
+
+	if (cond)
+	{
+		var myForm = document.getElementById(formID);
+		var propRow = document.getElementById(rowID);
+// alert(propRow);
+		var propTable = propRow.parentNode;
+// alert(propTable);
+		var rIndex = propRow.rowIndex;
+// alert("Row index before: " + rIndex);
+
+		// remove form elements
+		tmp_val = replaceAll((catAlias + "_:_" + propAlias), "'", "\\'");	// keep this
+// 		alert(tmp_val);
+
+		var textInputFormatRadio = document.getElementById("input_format_radio_list_" + tmp_val);
+		var listInputFormatRadio = document.getElementById("input_format_radio_text_" + tmp_val);
+		var dropdownList = document.getElementById("propertyValues_" + tmp_val);
+		var propInput = document.getElementById(tmp_val + "_input");
+
+		// Sept. 4/09: Actually, DON'T delete this element from the form, BUT set flag that it's deleted for Python to process
+		// Nov. 6/09: Do the replacement here!!!!!		
+// 		if (toRemove)
+// 			toRemove.value = "1";
+// 		else
+// {
+// alert("Row index after: " + rIndex);
+
+// 			alert("????????");
+// }
+// 		alert(rIndex);
+		propTable.deleteRow(rIndex);
+
+		// Dec. 9/09: With DNA Sequence, remove the rest of its attributes
+		if ((propAlias == "sequence") || (propAlias == "protein_sequence") || (propAlias == "rna_sequence"))
+		{
+			i = 0;
+
+			while (i >= 0)
+			{
+// alert(i);
+				propTable.deleteRow(i);
+				i = propTable.rows.length - 1;
+			}
+		}
+
+		// Ditto if Tag Type or Promoter are removed - remove their descriptors as well
+		else if (propAlias == "tag")
+		{
+// alert("removing tag");
+			deleteReagentTypeAttribute(rowID.replace("tag", "tag_position"), formID);
+		}
+		else if (propAlias == "promoter")
+		{
+			deleteReagentTypeAttribute(rowID.replace("promoter", "expression_system"), formID);
+		}
+
+		// Feb. 1/10: generate the flag on the fly and append to form -- Feb 8/10: might not need this after all
+		var toRemove = document.createElement("INPUT");
+		toRemove.setAttribute("type", "hidden");
+		toRemove.setAttribute("name", "remove_" + catAlias + "_:_" + propAlias + "_prop");
+		toRemove.setAttribute("value", "1");
+		// alert("remove_" + catAlias + "_:_" + propAlias + "_prop");
+		myForm.appendChild(toRemove);
+	}
+}
+
+
+function removeArrayElement(myArray, myEl)
+{
+	var i;
+	var tmp_ar = new Array();
+
+	for (i = 0; i < myArray.length; i++)
+	{
+		if (myArray[i] != myEl)
+		{
+			tmp_ar.push(myArray[i]);
+		}
+	}
+
+	return tmp_ar;
+}
+
+
+// Feb. 11/10: changed function name from checkExistingReagent to checkExistingPrepID - makes more sense for Location side
+function checkExistingPrepID()
+{
+	// do AJAX here
+	url = cgiPath + "location_request_handler.py";
+	xmlhttp1 = createXML();
+	xmlhttp1.open("POST", url, false);
+	xmlhttp1.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+
+	var allInputs = document.getElementsByTagName("INPUT");
+	var seqParams = "validate_reagent_id";
+	var tmpInput;
+
+	var c = 0;
+	var inputs_ar = new Array();
+
+	for (i=0; i < allInputs.length; i++)
+	{
+		tmpEl = allInputs[i];
+
+		if ((allInputs[i].type == "text") && (allInputs[i].name == "well_LIMSID_field[]"))
+		{
+			tmp_lims_id = allInputs[i].value;
+			tmp_input = allInputs[i];
+
+			inputs_ar[tmp_lims_id] = tmp_input;
+
+			// Empty wells are allowed
+			if (tmp_lims_id.length > 0)
+			{
+				seqParams += "&rID=" + tmp_lims_id;
+			}
+		}
+	}
+
+	xmlhttp1.send(seqParams);
+	xmlhttp1.onreadystatechange = checkReagentID(xmlhttp1, inputs_ar);
+
+	return wellResult;
+}
+
+function checkReagentID(xmlhttp, inputs_ar)
+{
+// alert("in checkParents");
+// 	alert(xmlhttp1.readyState);
+// 	prompt("", xmlhttp.responseText);
+	var result;
+
+	if (xmlhttp.readyState == 4)
+	{
+// alert("ready " + xmlhttp1.readyState);
+// alert("status " + xmlhttp.status);
+// alert("response " + xmlhttp.responseText);
+
+		if (xmlhttp.status == 200)
+		{
+// alert("status " + xmlhttp.status);
+			if (xmlhttp.responseText.indexOf("ErrCode") == 0)
+			{
+// 				tmp_ar = xmlhttp.responseText.split("&");
+// 
+// 				for (i=0; i < tmp_ar.length; i++)
+// 				{
+					tmp_set = xmlhttp.responseText.split("=");
+// alert(tmp_set);
+// 					if (tmp_set[0] == 'ErrCode')
+// 					{
+// alert("Setting parents to false");
+						rID = trimAll(tmp_set[tmp_set.length-1]);
+						rInput = inputs_ar[rID];
+						alert("Reagent " + rID + " does not exist in the database.  Please verify your input.");
+						
+						// Tip gotten from http://geekswithblogs.net/shahedul/archive/2006/08/14/87910.aspx
+						// Turn autocomplete off before calling focus(); otherwise get the following error:
+						// [Exception... "'Permission denied to set property XULElement.selectedIndex' when calling method: [nsIAutoCompletePopup::selectedIndex]" nsresult: "0x8057001e (NS_ERROR_XPC_JS_THREW_STRING)
+						rInput.setAttribute('autocomplete','off');
+						rInput.focus();
+						
+						wellResult = false;
+// 						break;
+// 					}
+// 				}
+			}
+			else
+			{
+// alert("Setting parents to true");
+				wellResult = true;
+			}
+		}
+	}
+}
+
+function checkPrepType()
+{
+	var allInputs = document.getElementsByTagName("INPUT");
+	var i;
+	var all_LIMS_IDs = new Array();
+	var allowed_prefixes = new Array();
+	var all_prefixes = new Array();
+	var lims_id_inputs = new Array();
+	var prefix;
+
+	var reg = /\w+\d+/;
+	var reg_alpha = /\w+/;
+	var reg_num = /\d+/;
+
+	// find all prefixes
+	for (i = 0; i < allInputs.length; i++)
+	{
+/*		if ((allInputs[i].type == "text") && (allInputs[i].name == "well_LIMSID_field[]"))
+		{
+			all_LIMS_IDs.push(allInputs[i].value);
+		}
+		else */
+		if ((allInputs[i].type == "hidden") && (allInputs[i].name == "allowed_prep_prefixes[]"))
+		{
+// alert("allowed " + allInputs[i].value);
+			allowed_prefixes.push(allInputs[i].value);
+		}
+		else if ((allInputs[i].type == "hidden") && (allInputs[i].name == "all_prefixes[]"))
+		{
+// alert("ALL " + allInputs[i].value);
+			all_prefixes.push(allInputs[i].value);
+		}
+	}
+
+
+	for (i = 0; i < allInputs.length; i++)
+	{
+		if ((allInputs[i].type == "text") && (allInputs[i].name == "well_LIMSID_field[]"))
+		{
+			// Empty wells are allowed
+			if (allInputs[i].value.length > 0)
+			{
+// alert(allInputs[i].value.search(reg));
+
+				if (allInputs[i].value.search(reg) < 0)
+				{
+					alert("\"" + allInputs[i].value + "\" is not the correct input format for prep ID.  Please verify your input.");
+					allInputs[i].focus();
+					return false;
+				}
+				else
+				{
+	// alert(allInputs[i].value);
+					alpha_prefix = allInputs[i].value.search(reg_alpha);
+					num_prefix = allInputs[i].value.search(reg_num);
+	
+					prefix = allInputs[i].value.substr(0, num_prefix);
+// 	alert(prefix);
+// alert(all_prefixes);
+// 	return false;
+					// if no prefixes have been defined anything is allowed!
+					if (allowed_prefixes.length > 0)
+					{
+						// don't let lettercase get in the way!
+						if (inArray(prefix, all_prefixes) || inArray(prefix.toUpperCase(), all_prefixes) || inArray(prefix.toLowerCase(), all_prefixes))
+						{
+							if (!inArray(prefix, allowed_prefixes) && !inArray(prefix.toUpperCase(), allowed_prefixes) && !inArray(prefix.toLowerCase(), allowed_prefixes))
+							{
+								alert("This container does not support reagents of type \"" + prefix + "\".  Please refer to the list of allowed reagent types and their prefixes at the bottom of the table.");
+								allInputs[i].focus();
+								return false;
+							}
+						}
+						else
+						{
+							alert("Unrecognized reagent type prefix: \"" + prefix + "\".  Please verify your input.");
+							allInputs[i].focus();
+							return false;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return true;
+}
+
+// May 30, 2011
+function highlightWell(cbID, wellID)
+{
+	var checkbox = document.getElementById(cbID);
+	var wellTD = document.getElementById(wellID);
+	
+	if (checkbox.checked)
+		wellTD.style.backgroundColor='yellow';
+	else
+		wellTD.style.backgroundColor='white';
+}
+
+// May 30, 2011: Response to NM review - mimic Excel; instead of having 'select all/deselect all' buttons click on the top left corner cell
+function selectOrDeselectAllWells(plateID, numWells)
+{
+	var allInput = document.getElementsByTagName("INPUT");
+	var	numChecked = 0;
+
+	var restrictedWells = document.getElementsByName("plate_" + plateID + "_wells_restricted[]");
+	var numRestr = restrictedWells.length;
+
+	for (i=0; i < allInput.length; i++)
+	{
+		tmpInput = allInput[i];		
+
+		if ((tmpInput.type == "checkbox") && (tmpInput.id.indexOf("plate_" + plateID) == 0))
+		{
+			if (tmpInput.checked)
+				numChecked++;
+
+			 if (tmpInput.disabled)
+				 numRestr++;
+		}
+	}
+
+	var numFree = numWells - numRestr;
+
+	if (numChecked < numFree)
+		selectAllWells(plateID);
+	else
+		clearAllWells(plateID);
+}
+
+function selectAllWells(plateID)
+{
+	wellsForm = document.wells_form;
+	formElem = wellsForm.elements
+
+	for (i = 0; i <= formElem.length; i++)
+	{
+		element = formElem[i]
+
+		if (element)
+		{
+			if ((element.name == "wells_checkbox[]") && (!element.disabled))
+			{
+				element.checked = true;
+				parentElement = element.parentNode;
+
+				if (parentElement.tagName == "TD")
+				{
+					parentTD = parentElement;
+
+					if (parentTD.id.indexOf("well_plate_" + plateID) == 0)
+					{
+						parentTD.style.backgroundColor = "yellow";
+					}
+				}
+				else if (parentElement.tagName == "DIV")
+				{					
+					// go one more level up
+					divParent = parentElement;
+					parentTD = divParent.parentNode;
+		
+					if (parentTD.id.indexOf("well_plate_" + plateID) == 0)
+					{
+						parentTD.style.backgroundColor = "yellow";
+					}
+				}
+			}
+		}
+	}
+/*
+	// May 30, 2011: Colour well yellow
+	var allTDs = document.getElementsByTagName("TD");
+
+	for (n = 0; n < allTDs.length; n++)
+	{
+		tmpTD = allTDs[n];
+
+		if (tmpTD.id.indexOf("well_plate_" + plateID) == 0)
+		{
+			tmpTD.style.backgroundColor = "yellow";
+		}
+	}
+	*/
+}
+
+function clearAllWells(plateID)
+{
+	wellsForm = document.wells_form;
+	formElem = wellsForm.elements;
+
+	for (i = 0; i <= formElem.length; i++)
+	{
+		element = formElem[i];
+
+		if (element)
+		{
+			if ((element.name == "wells_checkbox[]") && (!element.disabled))
+			{
+				element.checked = false;
+				parentElement= element.parentNode;
+
+				if (parentElement.tagName == "TD")
+				{
+					parentTD = parentElement;
+								
+					if (parentTD.id.indexOf("well_plate_" + plateID) == 0)
+					{
+						parentTD.style.backgroundColor = "white";
+					}
+				}
+				else if (parentElement.tagName == "DIV")
+				{
+					// go one more level up
+					divParent = parentElement;
+					parentTD = divParent.parentNode;
+					
+					if (parentTD.id.indexOf("well_plate_" + plateID) == 0)
+					{
+						parentTD.style.backgroundColor = "white";
+					}
+				}
+			}
+		}
+	}
+
+/*
+	// May 30, 2011: As we're colouring selected wells now, uncolour them
+	var allTDs = document.getElementsByTagName("TD");
+
+	for (n = 0; n < allTDs.length; n++)
+	{
+		tmpTD = allTDs[n];
+
+		if (tmpTD.style.backgroundColor == "yellow")
+		{
+			tmpTD.style.backgroundColor = "#FFFFFF";
+		}
+	}
+	*/
+}
+
+// Aug. 5/09: Disallow submitting empty dropdowns at reagent type creation
+function checkEmptyDropdowns(formID)
+{
+	var myForm = document.getElementById(formID);
+	var formChildren = myForm.elements;
+	var i;
+	var error = false;
+
+	if (document.pressed != "Cancel")
+	{
+		for (i = 0; i < formChildren.length; i++)
+		{
+			tmpChild = formChildren[i];
+	
+			if ((tmpChild.type == "select") || (tmpChild.type == "select-multiple"))
+			{
+				if (tmpChild.name.indexOf("propertyValues_") == 0)
+				{
+					tmpName = tmpChild.name.substr(tmpChild.name.indexOf("propertyValues_") + ("propertyValues_".length), tmpChild.name.length);
+					tmpRadio = document.getElementById("input_format_radio_list_" + tmpName);
+		
+					var customizable = document.getElementById("customize_cb_" + tmpName);
+// alert("mult_cb_" + tmpName);
+					// DON'T use 'inline' here!!!!!!!!!!
+					if (!tmpRadio || (tmpRadio && tmpRadio.checked && tmpChild.style.display != "none"))
+					{
+						if (tmpName.indexOf("packet_id") < 0)
+						{
+							// alert(customizable.checked);
+							
+							if (!customizable || (customizable && (!customizable.checked)))
+							{
+								if (tmpChild.options.length == 0)
+								{
+		// alert(tmpName);
+									error = true;
+									break;
+								}
+								else if ((tmpChild.options.length == 1) && (tmpChild.options[0].value == "default"))
+								{
+									error = true;
+									break;
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	
+		if (error)
+		{
+			for (i = 0; i < formChildren.length; i++)
+			{
+				tmpElem = formChildren[i];
+	
+				if (tmpElem.type == "select-multiple")
+					clearAllElements(tmpElem.id);
+			}
+	
+	// 		allSpans = document.getElementsByTagName("SPAN");
+	
+			alert("Please provide a set of values for all empty dropdown lists, or select 'Free Text' as input format, if applicable.");
+			tmpWarn = document.getElementById(tmpName + "_warning");
+			tmpWarn.style.display = "inline";
+	
+			expandAllCategories();
+	
+	// 		for (j = 0; j < allSpans.length; j++)
+	// 		{
+	// 			tmpSpan = allSpans[j];
+	// 
+	// 			// hide rest of warnings
+	// 			if ((tmpSpan.id.substr("_warning") > 0) && (tmpSpan != tmpWarn))
+	// 				tmpSpan.style.display = "none";
+	// 		}
+	
+			tmpTxt = document.getElementById("addPropertyValue_" + tmpName + "_txt");
+			tmpTxt.focus();
+	
+			return false;
+		}
+	}
+
+	return true;
+}
+
+
+function expandAllCategories()
+{
+	var categories = document.getElementsByName("categoryID[]");
+
+	for (i = 0; i < categories.length; i++)
+	{
+		categoryID = categories[i].value;
+// 		alert(categoryID);
+
+		expandImg = document.getElementById(categoryID + "_expand_img");
+		collapseImg = document.getElementById(categoryID + "_collapse_img");
+		section = document.getElementById("category_" + categoryID + "_section");
+
+		if (expandImg)
+			expandImg.style.display = "inline";
+
+		if (collapseImg)
+			collapseImg.style.display = "none";
+
+		if (section)
+			section.style.display = "";
+	}
+}
+
+
+
+// Disallow duplicates within one category.  Disallow entering the same property name in different case
+function verifyAddNewProperty(newCBVal, checkboxListID, textInput)
+{
+	var usedProps = getAllUsed(checkboxListID);
+
+	if (document.getElementById("reagent_type_modify"))
+	{
+		var a = document.getElementsByName(checkboxListID + "[]");
+
+		// add newly added (dynamic) checkboxes
+		var b = document.getElementsByName("createReagentType_" + checkboxListID + "[]");
+
+		var t = new Array();
+		var checkboxList;
+
+		for (i=0; i < a.length; i++)
+		{
+			tmp_cb = a[i];
+// 			alert(tmp_cb.value);
+			t.push(tmp_cb);
+		}
+
+		for (i=0; i < b.length; i++)
+		{
+			tmp_cb = b[i];
+// 			alert(tmp_cb.value);
+			t.push(tmp_cb);
+
+			if (tmp_cb.checked)
+			{
+// alert(tmp_cb.value + " is used");
+// alert(tmp_cb.id);
+				// tmp_cb.value is an alias.  Get the description
+				propDescrField = document.getElementById(checkboxListID + "_:_" + tmp_cb.value + "_checkbox_desc_hidden");
+// 	alert(propDescrFields);
+// 	alert(tmp_cb.id);
+	
+				if (propDescrField)
+				{
+// alert(propDescrField.value);
+					propDescr = propDescrField.value;
+
+					usedProps.push(propDescr);
+
+				}
+}		
+		}
+
+		checkboxList = t;
+
+// alert(checkboxList);
+
+	}
+	else
+	{
+		var checkboxList = document.getElementsByName("createReagentType_" + checkboxListID + "[]");
+// 		var checkDescrList = document.getElementsByName("propCheckboxes[]");
+	}
+
+	var rType = document.getElementById("reagent_type_name");
+	var rTypeName = rType.value;
+
+	var rTypePrefixInput = document.getElementById("reagent_type_prefix");
+	var rTypePrefix = rTypePrefixInput.value;
+
+	var reagentTypeNames = document.getElementsByName("reagent_type_names[]");
+	var rTypeNames = new Array();
+
+	for (k=0; k < reagentTypeNames.length; k++)
+	{
+		var tmpName = reagentTypeNames[k].value.toLowerCase();
+		rTypeNames.push(tmpName);
+	}
+
+	var reagentTypePrefixes = document.getElementsByName("reagent_type_prefixes[]");
+	var rTypePrefixes = new Array();
+
+	for (l = 0; l < reagentTypePrefixes.length; l++)
+	{
+		var tmpPrefix = reagentTypePrefixes[l];
+		rTypePrefixes.push(tmpPrefix);
+	}
+
+	if ( (inArray(newCBVal.toLowerCase(), rTypeNames)) || (inArray(newCBVal.toLowerCase(), rTypePrefixes)))
+	{
+		alert("Property names may not be the same as reagent type names or prefixes.  Please verify your input.");
+		textInput.focus();
+		return false;
+	}
+
+	// Now: The words 'DNA Sequence', 'Protein Sequence', 'RNA Sequence' are allowed in the appropriate categories.  BUT 'DNA', 'RNA', 'Protein', or 'Sequence' are not allowed anywhere!!
+	else if ((newCBVal.toLowerCase() == "sequence") || (newCBVal.toLowerCase() == "dna sequence") || (newCBVal.toLowerCase() == "protein sequence") || (newCBVal.toLowerCase() == "rna sequence") || (newCBVal.toLowerCase() == "dna") || (newCBVal.toLowerCase() == "rna") || (newCBVal.toLowerCase() == "protein"))
+	{
+		alert("You may not use 'Sequence', 'DNA Sequence', 'RNA Sequence', 'Protein Sequence',  'Protein', 'DNA' or 'RNA' as reagent type attribute names.   Please verify your input.");
+		textInput.focus();
+		return false;
+	}
+
+	// test 'packet id'
+	var reservedPropNames = ["project id", "alternate id"];
+	var reservedPropCatAlias = {"project id":"general_properties", "alternate id":"externalIDs"};
+	var reservedPropCats = {"project id":"General Properties", "alternate id":"External Identifiers"};
+	
+	var isInUseNewCBVal = false;
+
+	for (n=0; n < usedProps.length; n++)
+	{
+		tmpUsed = usedProps[n];
+
+		if (tmpUsed.toLowerCase() == newCBVal.toLowerCase())
+		{
+			isInUseNewCBVal = true;
+			break;
+		}
+	}
+
+// alert(usedProps);
+// alert(checkboxList.length);
+
+	// June 14, 2010: Newly added categories
+	if (checkboxList.length == 0)
+	{
+		// just give an error msg for reserved props here
+		if (inArray(newCBVal.toLowerCase(), reservedPropNames))
+		{
+			alert("\"" + newCBVal + "\" is a reserved property name and may only appear once in category " + reservedPropCats[newCBVal.toLowerCase()] + " .  Please verify your input.");
+			textInput.focus();
+			return false;
+		}
+	}
+
+	for (i=0; i < checkboxList.length; i++)
+	{
+// alert("Category " + checkboxListID);
+
+		tmpElem = checkboxList[i];
+
+		// Dec. 3/09
+// 		tmpAlias = tmpElem.value.toLowerCase();
+		tmpAlias = tmpElem.value;
+
+// alert(tmpAlias);
+// alert(newCBVal.toLowerCase());
+
+// alert(checkboxListID + "_:_" + tmpAlias + "_checkbox_desc_hidden");
+
+		// Get the actual description next to the checkbox
+		var tmpDescHidden = document.getElementById(checkboxListID + "_:_" + tmpAlias + "_checkbox_desc_hidden");
+
+// 		alert(tmpDescHidden);
+// alert(inArray(usedProps, newCBVal));
+
+		if (tmpDescHidden)
+		{
+// 			alert(tmpDescHidden.value);
+
+			if (inArray(newCBVal.toLowerCase(), reservedPropNames))
+			{
+// alert(checkboxListID);
+// alert(reservedPropCatAlias[newCBVal.toLowerCase()]);
+// alert(checkboxListID == reservedPropCatAlias[newCBVal.toLowerCase()]);
+
+				// For reserved props, check 2 things: whether it's a duplicate and whether it's in the correct category.  Basically, addition of these properties is prohibited, the logic here is just to issue the correct error message.
+
+				// Duplicate in own category??  Project ID is mandatory, but alternate id is not - may be unchecked
+				if (checkboxListID == reservedPropCatAlias[newCBVal.toLowerCase()])
+				{
+					// this is its own category.  Check if it's already been checked
+					if ((tmpElem.checked) && (tmpDescHidden.value.toLowerCase() == newCBVal.toLowerCase()))
+					{
+						alert("You may not add '" + newCBVal + "', since a property with the same name already exists in this category.  Names entered in different LeTtErCaSe are NOT considered distinct.  If you wish to modify a recent entry, uncheck its checkbox first.\n\nPlease note that properties which already exist in OpenFreezer will not be updated.");
+						textInput.focus();
+						return false;
+					}
+
+					// otherwise let it through, why not
+				}
+				else
+				{
+					// If this is a different category, disallow adding this property, period
+					alert("\"" + newCBVal + "\" is a reserved property name and may only appear once in category " + reservedPropCats[newCBVal.toLowerCase()] + " .  Please verify your input.");
+					textInput.focus();
+					return false;
+				}
+			}
+			else
+			{
+				// This is not a reserved property.  Do a regular duplicate check.
+				if ((tmpElem.checked) && (tmpDescHidden.value.toLowerCase() == newCBVal.toLowerCase()))
+				{
+					alert("You may not add '" + newCBVal + "', since a property named '" + tmpDescHidden.value + "' already exists in this category.  Names entered in different LeTtErCaSe are NOT considered distinct.  If you wish to modify a recent entry, uncheck its checkbox first.\n\nPlease note that properties which already exist in OpenFreezer will not be updated.");
+					textInput.focus();
+					return false;
+				}
+			}
+		}
+		// modification view
+		else
+		{
+			if (isInUseNewCBVal)
+			{
+// alert("??");
+				if (inArray(newCBVal.toLowerCase(), reservedPropNames))
+				{
+					if (checkboxListID != reservedPropCatAlias[newCBVal.toLowerCase()])
+					{
+						alert("\"" + newCBVal + "\" is a reserved property name and may only appear once in category " + reservedPropCats[newCBVal.toLowerCase()] + ".  Please verify your input.");
+						textInput.focus();
+						return false;
+					}
+					else
+					{
+						alert("You may not add '" + newCBVal + "', since a property with the same name already exists in this category.  Names entered in different LeTtErCaSe are NOT considered distinct.  If you wish to modify a recent entry, uncheck its checkbox first.\n\nPlease note that properties which already exist in OpenFreezer will not be updated.");
+						textInput.focus();
+						return false;
+					}
+				}
+				else
+				{
+					alert("You may not add '" + newCBVal + "', since a property with the same name already exists in this category.  Names entered in different LeTtErCaSe are NOT considered distinct.  If you wish to modify a recent entry, uncheck its checkbox first.\n\nPlease note that properties which already exist in OpenFreezer will not be updated.");
+					textInput.focus();
+					return false;
+				}
+			}
+			else
+			{
+// alert(newCBVal);
+				// reserved property, e.g. Alternate ID
+				if (inArray(newCBVal.toLowerCase(), reservedPropNames))
+				{
+					// should not go into a foreign category, period
+					if (checkboxListID != reservedPropCatAlias[newCBVal.toLowerCase()])
+					{
+						alert("\"" + newCBVal + "\" is a reserved property name and may only appear once in category " + reservedPropCats[newCBVal.toLowerCase()] + ".  Please verify your input.");
+						textInput.focus();
+						return false;
+					}
+					else
+					{
+						// Check if there is a checked property with the same name in the category
+						// it is not in use obviously, so again have to iterate through all the checkboxes in this category, comparing each to the new value; if a duplicate is found and it's checked issue error msg
+						var tmp_cbName_ar = newCBVal.split(" ");
+						var tmp_cbID = tmp_cbName_ar.join("_");
+
+// alert(checkboxList.length);
+
+						// first, check all EXISTING checkboxes in this category
+						for (i=0; i < checkboxList.length; i++)
+						{
+							tmpElem = checkboxList[i];
+							tmpAlias = tmpElem.value;
+// 					alert(tmpElem.name);
+// 					alert(tmpElem.id);
+							// Get the actual description next to the checkbox
+							var tmpDescHidden = document.getElementById(checkboxListID + "_:_" + tmpAlias + "_desc_hidden");
+						
+							// alert(tmpDescHidden);
+							// alert(inArray(usedProps, newCBVal));
+					
+							if (tmpDescHidden)
+							{
+// 								alert(tmpElem.id);
+// 	 							alert(tmpDescHidden.innerHTML);
+
+								if ((tmpElem.checked) && (tmpDescHidden.innerHTML.toLowerCase() == newCBVal.toLowerCase()))
+								{
+									alert("You may not add '" + newCBVal + "', since a property named '" + tmpDescHidden.value + "' already exists in this category.  Names entered in different LeTtErCaSe are NOT considered distinct.  If you wish to modify a recent entry, uncheck its checkbox first.\n\nPlease note that properties which already exist in OpenFreezer will not be updated.");
+									textInput.focus();
+									return false;
+								}
+							}
+						}
+
+						// NOW check newly added ones
+						if (document.getElementById(checkboxListID + "_:_" + tmp_cbID + "_checkbox_desc_hidden"))
+						{
+							new_cb = document.getElementById("createReagentType_" + checkboxListID + "_:_" + tmp_cbID + "_checkbox_id");
+
+							newDescr = document.getElementById(checkboxListID + "_:_" + tmp_cbID + "_checkbox_desc_hidden").value;
+
+							if (new_cb && newDescr && new_cb.checked)
+							{
+// 								alert("Duplicate " + newDescr);
+								alert("You may not add '" + newCBVal + "', since a property named '" + newDescr + "' already exists in this category.  Names entered in different LeTtErCaSe are NOT considered distinct.  If you wish to modify a recent entry, uncheck its checkbox first.\n\nPlease note that properties which already exist in OpenFreezer will not be updated.");
+								textInput.focus();
+								return false;
+							}
+						}
+					}
+				}
+				else
+				{
+					// Check if there is a checked property with the same name in the category
+					// it is not in use obviously, so again have to iterate through all the checkboxes in this category, comparing each to the new value; if a duplicate is found and it's checked issue error msg
+					var tmp_cbName_ar = newCBVal.split(" ");
+					var tmp_cbID = tmp_cbName_ar.join("_");
+
+					// first, check all EXISTING checkboxes in this category
+					for (i=0; i < checkboxList.length; i++)
+					{
+						tmpElem = checkboxList[i];
+						tmpAlias = tmpElem.value;
+				
+						// Get the actual description next to the checkbox
+						var tmpDescHidden = document.getElementById(checkboxListID + "_:_" + tmpAlias + "_desc_hidden");
+					
+						// alert(tmpDescHidden);
+						// alert(inArray(usedProps, newCBVal));
+				
+						if (tmpDescHidden)
+						{
+							// alert(tmpElem.id);
+							// alert(tmpDescHidden.innerHTML);
+
+							if ((tmpElem.checked) && (tmpDescHidden.innerHTML.toLowerCase() == newCBVal.toLowerCase()))
+							{
+								alert("You may not add '" + newCBVal + "', since a property named '" + tmpDescHidden.value + "' already exists in this category.  Names entered in different LeTtErCaSe are NOT considered distinct.  If you wish to modify a recent entry, uncheck its checkbox first.\n\nPlease note that properties which already exist in OpenFreezer will not be updated.");
+								textInput.focus();
+								return false;
+							}
+						}
+					}
+
+					// NOW check newly added ones
+					if (document.getElementById(checkboxListID + "_:_" + tmp_cbID + "_checkbox_desc_hidden"))
+					{
+						new_cb = document.getElementById("createReagentType_" + checkboxListID + "_:_" + tmp_cbID + "_checkbox_id");
+
+						newDescr = document.getElementById(checkboxListID + "_:_" + tmp_cbID + "_checkbox_desc_hidden").value;
+
+						if (new_cb && newDescr && new_cb.checked)
+						{
+							// alert("Duplicate " + newDescr);
+							alert("You may not add '" + newCBVal + "', since a property named '" + newDescr + "' already exists in this category.  Names entered in different LeTtErCaSe are NOT considered distinct.  If you wish to modify a recent entry, uncheck its checkbox first.\n\nPlease note that properties which already exist in OpenFreezer will not be updated.");
+							textInput.focus();
+							return false;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return true;
+}
+
+
+// June 10, 2010: Same idea as in checkAllExclude, only don't physically check the checkboxes.  This is needed for duplicate property names check at modification
+function getAllUsed(categoryAlias)
+{
+	categoryAlias = unescape(categoryAlias);
+// alert(categoryAlias);
+	var checkBoxList = document.getElementsByName(categoryAlias + "[]");
+// alert(categoryAlias + "[]");
+// for (c=0; c < checkBoxList.length; c++)
+// 	alert(checkBoxList[c].value);
+// alert(checkBoxList.length);
+
+	var toExclude = document.getElementsByName(categoryAlias + "_exclude[]");	// hidden inputs
+// alert(categoryAlias + "_exclude[]");
+// alert(toExclude);
+// alert(toExclude.length);
+
+	var exclList = Array();
+	var i, j;
+
+	// get names of all unused properties (those that should not be checked)
+	for (i=0; i < toExclude.length; i++)
+	{
+		tmpPropAlias = toExclude[i].value;
+// alert(tmpPropAlias);
+		excl_cb = categoryAlias + "_:_" + tmpPropAlias;
+
+		if (document.getElementById(excl_cb))
+		{
+// alert("Excluding " + categoryAlias + "_:_" + tmpPropAlias);
+			exclList.push(excl_cb);
+		}
+	}
+
+	var usedList = Array();
+
+	// now iterate through checboxes and check those that should not be excluded
+	for (j=0; j < checkBoxList.length; j++)
+	{
+		tmpCB = checkBoxList[j];
+// alert(tmpCB);
+		// not checking isDisabled here, b/c this would MOST LIKELY be used to select all assigned properties for ORDERING - hence, need the disabled properties too
+		if (!inArray(tmpCB.id, exclList))
+		{
+			propAlias = tmpCB.id.substring(tmpCB.id.indexOf("_:_")+3);
+			propDescrField = document.getElementById(categoryAlias + "_:_" + propAlias + "_desc_hidden");
+// alert(propDescrField);
+// alert(categoryAlias + "_:_" + propAlias + "_desc_hidden");
+
+			if (propDescrField)
+			{
+// alert(categoryAlias + "_:_" + propAlias + "_desc_hidden");
+				propDescr = propDescrField.innerHTML;
+// alert(propDescr);
+// alert(tmpCB.id + " is used");
+// 			tmpCB.checked = true;
+				usedList.push(propDescr);
+			}
+		}
+	}
+
+	return usedList;
+}
+
+// March 30/09: For addition of new reagent types - add values from text input to checkbox groups
+// checkboxListID == categoryAlias
+// Update June 18/09: Don't convert to title case
+function updateCheckboxListFromInput(inputID, checkboxListID, tableID, formID)
+{
+	inputID = unescape(inputID);
+	checkboxListID = unescape(checkboxListID);
+
+	// Groups of checkbox values contain [] in their name
+	var checkboxList = document.getElementsByName("createReagentType_" + checkboxListID + "[]");
+
+	var textInput = document.getElementById(inputID);
+	var propsTable = document.getElementById(tableID);
+
+	var newCBVal = trimAll(textInput.value);
+	var tmp_cb_ar = newCBVal.toLowerCase().split(" ");
+	var newCBAlias = tmp_cb_ar.join("_");
+
+// 	var myForm = document.getElementById(formID);
+
+	// Oct. 6/09: Hidden description field
+	var tmpDescrHidden = document.createElement("INPUT");
+	tmpDescrHidden.setAttribute("type", "hidden");
+// 	tmpDescrHidden.setAttribute("name", "propCheckboxes[]");
+
+	if (newCBVal.indexOf(checkboxListID + "_:_") == 0)
+	{
+		newCBVal = newCBVal.substring((checkboxListID + "_:_").length, newCBVal.length);
+		newCBAlias = newCBAlias.substring((checkboxListID + "_:_").length, newCBAlias.length);
+	}
+
+	tmpDescrHidden.setAttribute("id", checkboxListID + "_:_" + newCBAlias + "_checkbox_desc_hidden");
+	tmpDescrHidden.setAttribute("value", newCBVal);
+
+	var newCBVal_ar = newCBVal.toLowerCase().split(" ");
+	var tmpCBVal = newCBVal_ar.join("_");
+
+	// Dec. 3/09: Do the same only not in lowercase
+	var tmp_cbName_ar = newCBVal.split(" ");
+	var tmp_cbID = tmp_cbName_ar.join("_");
+	
+	// Oct. 29/09: set flag 'new'
+	var tmp_flag = document.createElement("INPUT");
+	tmp_flag.setAttribute("type", "hidden");
+// 	tmp_flag.setAttribute("name", "is_new_" + checkboxListID + "_:_" + tmpCBVal);
+	tmp_flag.setAttribute("name", "is_new_" + checkboxListID + "_:_" + tmp_cbID);
+
+// 	tmp_flag.setAttribute("id", "isNew_" + checkboxListID + "_:_" + tmpCBVal);
+	tmp_flag.setAttribute("id", "isNew_" + checkboxListID + "_:_" + tmp_cbID);
+
+	tmp_flag.setAttribute("value", true);
+	document.body.appendChild(tmp_flag);
+
+	var newCB = document.createElement("INPUT");
+	newCB.type = "checkbox";
+	
+	var myForm = document.getElementById(formID);
+
+	if (verifyAddNewProperty(newCBVal, checkboxListID, textInput))
+	{
+		newCB.setAttribute("name", "createReagentType_" + checkboxListID + "[]");
+		
+		// Dec. 3/09: NO, don't use lowercase alias, confuses 'PROMOTER' and 'Promoter'
+// 		newCB.setAttribute("id", "createReagentType_" + checkboxListID + "_:_" + tmpCBVal + "_checkbox_id");
+		newCB.setAttribute("id", "createReagentType_" + checkboxListID + "_:_" + tmp_cbID + "_checkbox_id");
+// alert("createReagentType_" + checkboxListID + "_:_" + tmp_cbID + "_checkbox_id");
+// 		newCB.value = tmpCBVal;
+		newCB.value = tmp_cbID;
+
+		newCB.setAttribute("checked", "true");
+
+		if (tableID.indexOf("addReagentType") == 0)
+			var tRows = propsTable.rows.length;		// last row is the 'add' button
+		else
+			var tRows = propsTable.rows.length-1;		// last row is the 'add' button
+	
+		if (checkboxList.length%4 == 0)
+		{
+			var lastRow = propsTable.insertRow(tRows);
+			var tmpCell = lastRow.insertCell(0);
+		}
+		else
+		{
+			// try-catch block added Aug. 11/09: For dynamically generated categories it's the last table row
+			try
+			{
+				var lastRow = propsTable.rows[tRows-1];
+			}
+			catch(e)	// for dynamically generated categories it's the last table row
+			{
+				var lastRow = propsTable.rows[tRows];
+			}
+		
+			var tmpCell = lastRow.insertCell(lastRow.cells.length);
+		}
+	
+		tmpCell.setAttribute("white-space", "nowrap");
+		tmpCell.setAttribute("padding-left", "25px");
+		tmpCell.setAttribute("padding-right", "10px");
+	
+		if (tableID.indexOf("category_") == 0)
+			tmpCell.innerHTML += "    ";	// July 31/09: only way to fix alignment right now, keep!!
+
+		tmpCell.appendChild(newCB);
+
+		// June 18/09: Don't convert to title case
+		tmpCell.innerHTML += newCBVal;
+
+		// Dec. 3/09: try to avoid using lowercase
+// 		tmpDescrHidden.setAttribute("id", checkboxListID + "_:_" + tmpCBVal + "_checkbox_desc_hidden");
+		tmpDescrHidden.setAttribute("id", checkboxListID + "_:_" + tmp_cbID + "_checkbox_desc_hidden");
+// alert(checkboxListID + "_:_" + tmp_cbID + "_checkbox_desc_hidden");
+// 		tmpDescrHidden.setAttribute("name", "createReagentType_" + checkboxListID + "_:_" + tmpCBVal);
+		tmpDescrHidden.setAttribute("name", "createReagentType_" + checkboxListID + "_:_" + tmp_cbID);
+
+		document.body.appendChild(tmpDescrHidden);
+
+		textInput.value = "";	
+		textInput.focus();
+	}
+}
+
+
+function collectReagentTypeProperties(formID)
+{
+	var myForm = document.getElementById(formID);
+	var props = document.getElementsByTagName("INPUT");
+
+	var i, j;
+	var categoryAlias;
+	var pDescrHidden;
+	var propAlias;
+
+	for (j=0; j < props.length; j++)
+	{
+		var tmpProp = props[j];		// a checkbox
+
+		if (tmpProp.type == "checkbox")
+		{
+			if (tmpProp.checked == true)
+			{
+// alert("Checkbox name " + tmpProp.id);
+				tmpName = tmpProp.id;	// e.g. "createReagentType_general_properties_:_notes_checkbox_id"
+// 		alert(tmpName);
+				// Extract the category
+				categoryAlias = tmpName.substring("createReagentType_".length, tmpName.indexOf("_:_"));
+	
+				propAlias = tmpName.substring(("createReagentType_" + categoryAlias + "_:_").length, tmpName.indexOf("_checkbox_id"));
+// 		alert(propAlias);
+				// grab the description
+				// Dec. 3/09: DON'T use getElementById - properties that are unchecked and re-entered in different lettercase both receive the same ID (their name is converted to lowercase to generate the alias, e.g. 'promoter' and 'Promoter') - and then get the problem Karen described with 'larger' and 'LARGER' - IDs are assigned at checkbox creation, so when these properties are entered one at a time (one is unchecked and the second entered), their identical IDs remain, one of them is passed to Py [...]
+				tmpDescr = document.getElementById(categoryAlias + "_:_" + propAlias + "_checkbox_desc_hidden");
+
+// 				tmpDescr = document.getElementsByName("createReagentType_" + categoryAlias + "_:_" + propAlias)
+
+				/*
+				for (i=0; i < tmpDescrs.length; i++)
+				{
+					tmpDescr = tmpDescrs[i];*/
+
+					if (tmpDescr)
+					{
+						if (tmpDescr.value != "")
+						{
+// 	alert("Saving property " + tmpDescr.value);
+							myForm.appendChild(tmpDescr);
+	
+							// 'isNew' flag
+							tmp_flag = document.getElementById("isNew_" + categoryAlias + "_:_" + propAlias);
+							myForm.appendChild(tmp_flag);
+	
+							// DO **NOT**, UNDER ANY CIRCUMSTANCES, DO THIS!!!!!!!  IT WILL RESULT IN THE VERY LAST CHECKBOX NOT BEING SAVED ISSUE!!!!!!!!!
+	// NO!!!!!!!					myForm.appendChild(tmpProp);
+						}
+					}
+// 				}
+			}
+		}
+	}
+}
+
+// June 17/09 - At new reagent type creation, give option to exclude sequence
+function hideSequenceSections()
+{
+	var dnaHeadingRow = document.getElementById("dna_sequence_heading_row");
+	var proteinHeadingRow = document.getElementById("protein_sequence_heading_row");
+	var rnaHeadingRow = document.getElementById("rna_sequence_heading_row");
+
+	var dnaPropsRow = document.getElementById("dna_sequence_props_row");
+	var proteinPropsRow = document.getElementById("protein_sequence_props_row");
+	var rnaPropsRow = document.getElementById("rna_sequence_props_row");
+
+	var dnaAddNewPropsRow = document.getElementById("dna_sequence_add_new_props_row");
+	var proteinAddNewPropsRow = document.getElementById("protein_sequence_add_new_props_row");
+	var rnaAddNewPropsRow = document.getElementById("rna_sequence_add_new_props_row");
+
+	var dnaFeaturesHeadingRow = document.getElementById("dna_sequence_features_heading_row");
+	var dnaFeaturesRow = document.getElementById("dna_sequence_features_row");
+	var dnaAddNewFeaturesRow = document.getElementById("dna_sequence_add_new_features_row");
+
+	var proteinFeaturesHeadingRow = document.getElementById("protein_sequence_features_heading_row");
+	var proteinFeaturesRow = document.getElementById("protein_sequence_features_row");
+	var proteinAddNewFeaturesRow = document.getElementById("protein_sequence_add_new_features_row");
+
+	var rnaFeaturesHeadingRow = document.getElementById("rna_sequence_features_heading_row");
+	var rnaFeaturesRow = document.getElementById("rna_sequence_features_row");
+	var rnaAddNewFeaturesRow = document.getElementById("rna_sequence_add_new_features_row");
+
+	// hide all
+	dnaHeadingRow.style.display = "none";
+	dnaPropsRow.style.display = "none";
+	dnaAddNewPropsRow.style.display = "none";
+	dnaFeaturesHeadingRow.style.display = "none";
+	dnaFeaturesRow.style.display = "none";
+	dnaAddNewFeaturesRow.style.display = "none";
+
+	proteinHeadingRow.style.display = "none";
+	proteinPropsRow.style.display = "none";
+	proteinAddNewPropsRow.style.display = "none";
+
+	proteinFeaturesHeadingRow.style.display = "none";
+	proteinFeaturesRow.style.display = "none";
+	proteinAddNewFeaturesRow.style.display = "none";
+
+	rnaHeadingRow.style.display = "none";
+	rnaPropsRow.style.display = "none";
+	rnaAddNewPropsRow.style.display = "none";
+
+	rnaFeaturesHeadingRow.style.display = "none";
+	rnaFeaturesRow.style.display = "none";
+	rnaAddNewFeaturesRow.style.display = "none";
+}
+
+
+// June 10/09: Different sections for each of the 3 sequence types - DNA, RNA, Protein
+function showDNASequenceSection()
+{
+	var dnaHeadingRow = document.getElementById("dna_sequence_heading_row");
+	var proteinHeadingRow = document.getElementById("protein_sequence_heading_row");
+	var rnaHeadingRow = document.getElementById("rna_sequence_heading_row");
+
+	var dnaPropsRow = document.getElementById("dna_sequence_props_row");
+	var proteinPropsRow = document.getElementById("protein_sequence_props_row");
+	var rnaPropsRow = document.getElementById("rna_sequence_props_row");
+
+	var dnaAddNewPropsRow = document.getElementById("dna_sequence_add_new_props_row");
+	var proteinAddNewPropsRow = document.getElementById("protein_sequence_add_new_props_row");
+	var rnaAddNewPropsRow = document.getElementById("rna_sequence_add_new_props_row");
+
+	var dnaFeaturesHeadingRow = document.getElementById("dna_sequence_features_heading_row");
+	var dnaFeaturesRow = document.getElementById("dna_sequence_features_row");
+	var dnaAddNewFeaturesRow = document.getElementById("dna_sequence_add_new_features_row");
+
+	var proteinFeaturesHeadingRow = document.getElementById("protein_sequence_features_heading_row");
+	var proteinFeaturesRow = document.getElementById("protein_sequence_features_row");
+	var proteinAddNewFeaturesRow = document.getElementById("protein_sequence_add_new_features_row");
+
+	var rnaFeaturesHeadingRow = document.getElementById("rna_sequence_features_heading_row");
+	var rnaFeaturesRow = document.getElementById("rna_sequence_features_row");
+	var rnaAddNewFeaturesRow = document.getElementById("rna_sequence_add_new_features_row");
+
+	document.getElementById("addReagentTypeSequenceProperties").style.display = "table-row";
+	document.getElementById("addReagentTypeProteinSequenceProperties").style.display = "none";
+	document.getElementById("addReagentTypeRNASequenceProperties").style.display = "none";
+	
+	document.getElementById("addReagentTypeFeatures").style.display = "table-row";
+	document.getElementById("addReagentTypeProteinFeatures").style.display = "none";
+	document.getElementById("addReagentTypeRNAFeatures").style.display = "none";
+
+	// show DNA and hide the rest
+	dnaHeadingRow.style.display = "table-row";
+	dnaPropsRow.style.display = "table-row";
+	dnaAddNewPropsRow.style.display = "table-row";
+	dnaFeaturesHeadingRow.style.display = "table-row";
+	dnaFeaturesRow.style.display = "table-row";
+	dnaAddNewFeaturesRow.style.display = "table-row";
+
+	proteinHeadingRow.style.display = "none";
+	proteinPropsRow.style.display = "none";
+	proteinAddNewPropsRow.style.display = "none";
+
+	proteinFeaturesHeadingRow.style.display = "none";
+	proteinFeaturesRow.style.display = "none";
+	proteinAddNewFeaturesRow.style.display = "none";
+
+	rnaHeadingRow.style.display = "none";
+	rnaPropsRow.style.display = "none";
+	rnaAddNewPropsRow.style.display = "none";
+
+	rnaFeaturesHeadingRow.style.display = "none";
+	rnaFeaturesRow.style.display = "none";
+	rnaAddNewFeaturesRow.style.display = "none";
+}
+
+
+function showHideCategory(categoryID, rTypeID)
+{
+	if (rTypeID && (rTypeID != ""))
+	{
+		expandImg = document.getElementById(categoryID + "_expand_img_" + rTypeID);
+		collapseImg = document.getElementById(categoryID + "_collapse_img_" + rTypeID);
+		section = document.getElementById("category_" + categoryID + "_section_" + rTypeID);
+	}
+	else
+	{
+		expandImg = document.getElementById(categoryID + "_expand_img");
+		collapseImg = document.getElementById(categoryID + "_collapse_img");
+		section = document.getElementById("category_" + categoryID + "_section");	
+	}
+
+	if (expandImg.style.display == "inline")	// want to collapse section
+	{
+		expandImg.style.display = "none";
+		collapseImg.style.display = "inline";
+		section.style.display = "none";
+
+		if (categoryID == "sequence")
+		{
+			hideDNASequenceSection();
+			hideRNASequenceSection();
+			hideProteinSequenceSection();
+		}
+	}
+	else
+	{
+		expandImg.style.display = "inline";
+		collapseImg.style.display = "none";
+		section.style.display = "";
+
+		if (categoryID == "sequence")
+		{
+			// show the proper sequence section
+			noneRadio = document.getElementById("sequenceRadioNone");
+			dnaRadio = document.getElementById("sequenceRadioDNA");
+			rnaRadio = document.getElementById("sequenceRadioRNA");
+			proteinRadio = document.getElementById("sequenceRadioProtein");
+
+			if (dnaRadio.checked)
+				showDNASequenceSection();
+			
+			if (proteinRadio.checked)
+				showProteinSequenceSection();
+			
+			if (rnaRadio.checked)
+				showRNASequenceSection();
+		}
+	}
+}
+
+function hideDNASequenceSection()
+{
+	document.getElementById("dna_sequence_props_row").style.display = "none";
+	document.getElementById("dna_sequence_heading_row").style.display = "none";
+	document.getElementById("addReagentTypeSequenceProperties").style.display = "none";
+	document.getElementById("dna_sequence_add_new_props_row").style.display = "none";
+	document.getElementById("dna_sequence_features_heading_row").style.display = "none";
+	document.getElementById("addReagentTypeFeatures").style.display = "none";
+	document.getElementById("dna_sequence_add_new_features_row").style.display = "none";
+}
+
+
+function hideRNASequenceSection()
+{
+	document.getElementById("rna_sequence_props_row").style.display = "none";
+	document.getElementById("rna_sequence_heading_row").style.display = "none";
+	document.getElementById("addReagentTypeRNASequenceProperties").style.display = "none";
+	document.getElementById("rna_sequence_add_new_props_row").style.display = "none";
+	document.getElementById("rna_sequence_features_heading_row").style.display = "none";
+	document.getElementById("addReagentTypeRNAFeatures").style.display = "none";
+	document.getElementById("rna_sequence_add_new_features_row").style.display = "none";
+}
+
+
+function hideProteinSequenceSection()
+{	
+	document.getElementById("protein_sequence_props_row").style.display = "none";
+	document.getElementById("protein_sequence_heading_row").style.display = "none";
+	document.getElementById("addReagentTypeProteinSequenceProperties").style.display = "none";
+	document.getElementById("protein_sequence_add_new_props_row").style.display = "none";
+	document.getElementById("protein_sequence_features_heading_row").style.display = "none";
+	document.getElementById("addReagentTypeProteinFeatures").style.display = "none";
+	document.getElementById("protein_sequence_add_new_features_row").style.display = "none";
+}
+
+// June 12/09
+function cgiFileUpload(formID, fileID, fInputID)
+{
+	var myForm = document.getElementById(formID);
+	var fileName = document.getElementById(fileID);
+	var fileInput = document.getElementById(fInputID);
+
+	if (fileName)
+	{
+		var fName = fileName.value;
+
+		if (fileInput)
+		{
+			fileInput.value = fName;
+
+			if (myForm)
+			{
+				myForm.submit();
+			}
+		}
+	}
+}
+
+
+// June 10/09: Different sections for each of the 3 sequence types - DNA, RNA, Protein
+function showProteinSequenceSection()
+{
+	var dnaHeadingRow = document.getElementById("dna_sequence_heading_row");
+	var proteinHeadingRow = document.getElementById("protein_sequence_heading_row");
+	var rnaHeadingRow = document.getElementById("rna_sequence_heading_row");
+
+	var dnaPropsRow = document.getElementById("dna_sequence_props_row");
+	var proteinPropsRow = document.getElementById("protein_sequence_props_row");
+	var rnaPropsRow = document.getElementById("rna_sequence_props_row");
+
+	var dnaAddNewPropsRow = document.getElementById("dna_sequence_add_new_props_row");
+	var proteinAddNewPropsRow = document.getElementById("protein_sequence_add_new_props_row");
+	var rnaAddNewPropsRow = document.getElementById("rna_sequence_add_new_props_row");
+
+	var dnaFeaturesHeadingRow = document.getElementById("dna_sequence_features_heading_row");
+	var dnaFeaturesRow = document.getElementById("dna_sequence_features_row");
+	var dnaAddNewFeaturesRow = document.getElementById("dna_sequence_add_new_features_row");
+
+	var proteinFeaturesHeadingRow = document.getElementById("protein_sequence_features_heading_row");
+	var proteinFeaturesRow = document.getElementById("protein_sequence_features_row");
+	var proteinAddNewFeaturesRow = document.getElementById("protein_sequence_add_new_features_row");
+
+	var rnaFeaturesHeadingRow = document.getElementById("rna_sequence_features_heading_row");
+	var rnaFeaturesRow = document.getElementById("rna_sequence_features_row");
+	var rnaAddNewFeaturesRow = document.getElementById("rna_sequence_add_new_features_row");
+
+	document.getElementById("addReagentTypeSequenceProperties").style.display = "none";
+	document.getElementById("addReagentTypeProteinSequenceProperties").style.display = "table-row";
+	document.getElementById("addReagentTypeRNASequenceProperties").style.display = "none";
+	
+	document.getElementById("addReagentTypeFeatures").style.display = "none";
+	document.getElementById("addReagentTypeProteinFeatures").style.display = "table-row";
+	document.getElementById("addReagentTypeRNAFeatures").style.display = "none";
+
+	// show Protein and hide the rest
+	proteinHeadingRow.style.display = "table-row";
+	proteinPropsRow.style.display = "table-row";
+	proteinAddNewPropsRow.style.display = "table-row";
+
+	proteinFeaturesHeadingRow.style.display = "table-row";
+	proteinFeaturesRow.style.display = "table-row";
+	proteinAddNewFeaturesRow.style.display = "table-row";
+
+	dnaHeadingRow.style.display = "none";
+	dnaPropsRow.style.display = "none";
+	dnaAddNewPropsRow.style.display = "none";
+
+	dnaFeaturesHeadingRow.style.display = "none";
+	dnaFeaturesRow.style.display = "none";
+	dnaAddNewFeaturesRow.style.display = "none";
+
+	rnaHeadingRow.style.display = "none";
+	rnaPropsRow.style.display = "none";
+	rnaAddNewPropsRow.style.display = "none";
+
+	rnaFeaturesHeadingRow.style.display = "none";
+	rnaFeaturesRow.style.display = "none";
+	rnaAddNewFeaturesRow.style.display = "none";
+
+}
+
+
+// June 10/09: Different sections for each of the 3 sequence types - DNA, RNA, Protein
+function showRNASequenceSection()
+{
+	var dnaHeadingRow = document.getElementById("dna_sequence_heading_row");
+	var proteinHeadingRow = document.getElementById("protein_sequence_heading_row");
+	var rnaHeadingRow = document.getElementById("rna_sequence_heading_row");
+
+	var dnaPropsRow = document.getElementById("dna_sequence_props_row");
+	var proteinPropsRow = document.getElementById("protein_sequence_props_row");
+	var rnaPropsRow = document.getElementById("rna_sequence_props_row");
+
+	var dnaAddNewPropsRow = document.getElementById("dna_sequence_add_new_props_row");
+	var proteinAddNewPropsRow = document.getElementById("protein_sequence_add_new_props_row");
+	var rnaAddNewPropsRow = document.getElementById("rna_sequence_add_new_props_row");
+
+	var dnaFeaturesHeadingRow = document.getElementById("dna_sequence_features_heading_row");
+	var dnaFeaturesRow = document.getElementById("dna_sequence_features_row");
+	var dnaAddNewFeaturesRow = document.getElementById("dna_sequence_add_new_features_row");
+
+	var proteinFeaturesHeadingRow = document.getElementById("protein_sequence_features_heading_row");
+	var proteinFeaturesRow = document.getElementById("protein_sequence_features_row");
+	var proteinAddNewFeaturesRow = document.getElementById("protein_sequence_add_new_features_row");
+
+	var rnaFeaturesHeadingRow = document.getElementById("rna_sequence_features_heading_row");
+	var rnaFeaturesRow = document.getElementById("rna_sequence_features_row");
+	var rnaAddNewFeaturesRow = document.getElementById("rna_sequence_add_new_features_row");
+
+	document.getElementById("addReagentTypeSequenceProperties").style.display = "none";
+	document.getElementById("addReagentTypeProteinSequenceProperties").style.display = "none";
+	document.getElementById("addReagentTypeRNASequenceProperties").style.display = "table-row";
+	
+	document.getElementById("addReagentTypeFeatures").style.display = "none";
+	document.getElementById("addReagentTypeProteinFeatures").style.display = "none";
+	document.getElementById("addReagentTypeRNAFeatures").style.display = "table-row";
+
+	// show Protein and hide the rest
+	proteinHeadingRow.style.display = "none";
+	proteinPropsRow.style.display = "none";
+	proteinAddNewPropsRow.style.display = "none";
+
+	proteinFeaturesHeadingRow.style.display = "none";
+	proteinFeaturesRow.style.display = "none";
+	proteinAddNewFeaturesRow.style.display = "none";
+
+	dnaHeadingRow.style.display = "none";
+	dnaPropsRow.style.display = "none";
+	dnaAddNewPropsRow.style.display = "none";
+	dnaFeaturesHeadingRow.style.display = "none";
+	dnaFeaturesRow.style.display = "none";
+	dnaAddNewFeaturesRow.style.display = "none";
+
+	rnaHeadingRow.style.display = "table-row";
+	rnaPropsRow.style.display = "table-row";
+	rnaAddNewPropsRow.style.display = "table-row";
+
+	rnaFeaturesHeadingRow.style.display = "table-row";
+	rnaFeaturesRow.style.display = "table-row";
+	rnaAddNewFeaturesRow.style.display = "table-row";
+}
+
+
+function verifyAddNewCategory(newCategory)
+{
+	return true;
+}
+
+
+function addPropertiesCategory(inputID, tableID, rowID, formID)
+{
+	var textInput = document.getElementById(inputID);
+	var propsTable = document.getElementById(tableID);
+	var propsRow = document.getElementById(rowID);
+
+// 	alert(propsRow);
+
+	var newCategoryRow = propsTable.insertRow(propsRow.rowIndex);
+	var newCategory = textInput.value;
+
+// 	if (formID == "")
+// 		var myForm = document.addReagentTypeForm;
+// 		var myForm = document.getElementById("add_reagent_type_form");
+// 	else
+		var myForm = document.getElementById(formID);
+
+	var rTypeID = document.getElementById("reagent_type_name");
+
+	// Add warning if this category exists
+
+	if (verifyAddNewCategory(newCategory))
+	{
+		// watch out for names consijoin them with a '_'
+		var tmpStr_ar = newCategory.split(' ');
+		var tmpCatName = "";
+	
+		if (tmpStr_ar.length > 1)
+			tmpCatName = tmpStr_ar.join('_');
+		else
+			tmpCatName = newCategory;
+	
+		var newCollapseImg = document.createElement("IMG");		// down-facing arrow, section collapses when clicked
+		var newExpandImg = document.createElement("IMG");	// right arrow, section expands when clicked
+
+		if (rTypeID && (rTypeID != ""))
+		{
+			newCollapseImg.setAttribute("id", newCategory + "_collapse_img_" + rTypeID);
+			newExpandImg.setAttribute("id", newCategory + "_expand_img_" + rTypeID);
+		}
+		else
+		{
+			newCollapseImg.setAttribute("id", newCategory + "_collapse_img");
+			newExpandImg.setAttribute("id", newCategory + "_expand_img");
+		}
+
+		// expanded arrow image attributes
+		newCollapseImg.setAttribute("src", hostName + "pictures/arrow_collapse.gif");
+		newCollapseImg.setAttribute("width", "20");
+		newCollapseImg.setAttribute("height", "15");
+		newCollapseImg.setAttribute("border", "0");
+		newCollapseImg.setAttribute("alt", "bullet");
+		newCollapseImg.style.paddingRight = "8px";
+		newCollapseImg.style.verticalAlign = "middle";
+		newCollapseImg.style.paddingBottom = "2px";
+		newCollapseImg.onclick = function(){showHideCategory(tmpCatName);};
+
+		// ditto collapsed image
+		newExpandImg.setAttribute("src", hostName + "pictures/arrow_expand.gif");
+		newExpandImg.setAttribute("width", "20");
+		newExpandImg.setAttribute("height", "15");
+		newExpandImg.setAttribute("border", "0");
+		newExpandImg.setAttribute("alt", "bullet");
+		newExpandImg.style.paddingRight = "8px";
+		newExpandImg.style.verticalAlign = "middle";
+		newExpandImg.style.paddingBottom = "2px";
+		newExpandImg.style.display = "none";
+		newExpandImg.onclick = function(){showHideCategory(tmpCatName);};
+	
+		var tmpCell = newCategoryRow.insertCell(0);
+		tmpCell.style.paddingLeft = "5px";
+		tmpCell.style.paddingTop = "10px";
+		tmpCell.style.fontWeight = "bold";
+		tmpCell.style.fontSize = "10pt";
+		tmpCell.style.color = "#0000D2";
+	
+		tmpCell.innerHTML = "<BR>";
+		tmpCell.appendChild(newCollapseImg);
+		tmpCell.appendChild(newExpandImg);
+		tmpCell.innerHTML += /*titleCase(*/newCategory/*)*/;	// no, don't change case here
+	
+		var newCatCB_row = propsTable.insertRow(propsRow.rowIndex);
+		var newCatCB_cell = newCatCB_row.insertCell(0);
+		newCatCB_cell.style.paddingLeft = "36px";
+		var tmpNewCatCB_tbl = document.createElement("TABLE");
+		tmpNewCatCB_tbl.style.cellSpacing = "2";
+	
+		// Add 'check all' and 'clear all' links
+		var checkLink = document.createElement("SPAN");
+		checkLink.setAttribute('id', "checkAll");
+		checkLink.className = "linkShow";
+		checkLink.innerHTML = "Check All";
+		checkLink.style.marginLeft = "10px";
+		checkLink.style.fontSize = "8pt";
+		checkLink.style.fontWeight = "normal";
+		checkLink.onclick = function(){checkAll(tmpCatName);};
+		tmpCell.appendChild(checkLink);
+	
+		// Add 'check all' and 'clear all' links
+		var uncheckLink = document.createElement("SPAN");
+		uncheckLink.setAttribute('id', "uncheckAll");
+		uncheckLink.className = "linkShow";
+		uncheckLink.innerHTML = "Uncheck All";
+		uncheckLink.style.marginLeft = "10px";
+		uncheckLink.style.fontSize = "8pt";
+		uncheckLink.style.fontWeight = "normal";
+		uncheckLink.onclick = function(){uncheckAll(tmpCatName);};
+		tmpCell.appendChild(uncheckLink);
+	
+		var tmpNewCatCB_tbl_id = "addReagentType" + tmpCatName;
+		tmpNewCatCB_tbl.setAttribute("id", tmpNewCatCB_tbl_id);
+		newCatCB_cell.appendChild(tmpNewCatCB_tbl);
+	
+		var tmpAddOtherTxt = document.createElement("INPUT");
+	// 	tmpAddOtherTxt.type = "text";
+	
+		var tmpCatID = tmpCatName.toLowerCase() + "_other";
+		tmpAddOtherTxt.setAttribute("id", tmpCatID);
+	
+	// 	tmpAddOtherTxt.onKeyPress = function(){disableEnterKey("keypress")};
+	
+		var tmpAddOtherBtn = document.createElement("INPUT");
+		tmpAddOtherBtn.type = "button";
+		tmpAddOtherBtn.value = "Add";
+	
+		var addOtherRow = propsTable.insertRow(propsRow.rowIndex);
+		var addOtherCell = addOtherRow.insertCell(0);
+	
+		addOtherCell.style.paddingLeft = "36px";
+		addOtherCell.style.fontWeight = "bold";
+		addOtherCell.setAttribute("padding-left", "36px");
+	
+		addOtherCell.innerHTML = "Add new " + newCategory + " value: ";
+		addOtherCell.appendChild(tmpAddOtherTxt);
+	
+		addOtherCell.innerHTML += " ";
+		addOtherCell.appendChild(tmpAddOtherBtn);
+	
+		var newCatNameInputHidden = document.createElement("INPUT");
+		newCatNameInputHidden.setAttribute("type", "hidden");
+	
+		// April 6/09 - don't think so, see if causes problems later
+	// 	newCatNameInputHidden.setAttribute("name", tmpCatName);
+		newCatNameInputHidden.setAttribute("name", "category[]");
+		newCatNameInputHidden.setAttribute("value", tmpCatName);
+		myForm.appendChild(newCatNameInputHidden);
+	
+		// New April 15/09: Add category descriptor as hidden input
+		var newCatDescrInputHidden = document.createElement("INPUT");
+		newCatDescrInputHidden.setAttribute("type", "hidden");
+	
+		newCatDescrInputHidden.setAttribute("name", "category_descriptor_" + tmpCatName);
+		newCatDescrInputHidden.setAttribute("value", newCategory);
+		myForm.appendChild(newCatDescrInputHidden);
+	
+	// 	tmpAddOtherTxt.onKeyDown = function(){disableEnterKey(new Event())};
+	// 	myForm.appendChild(tmpAddOtherTxt);
+	
+		tmpAddOtherBtn.onclick = function(){updateCheckboxListFromInput(tmpCatID, tmpCatName, tmpNewCatCB_tbl_id, formID)}
+		textInput.value = "";
+	
+		document.getElementById(tmpCatID).focus();
+	}
+}
+
+
+// function checkParentFormat(rType, assocID, assocAlias)
+function checkParentFormat(rType)
+{
+// 	alert("in checkParentFormat " + rType);
+
+	// call AJAX script
+	url = cgiPath + "validate_parents.py";
+	xmlhttp1 = createXML();
+	xmlhttp1.open("POST", url, false);
+	xmlhttp1.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+
+	// alert(rType);
+	// alert(rType + "_assoc_" + assocID + "_prop");
+
+	var allInputs = document.getElementsByTagName("INPUT");
+	var i;
+	var seqParams;
+	var inputs_ar = new Array();
+
+	curr_username = document.getElementById("curr_username_hidden").value;
+
+	seqParams = "rType=" + rType + "&curr_username=" + curr_username;
+
+	switch(rType)
+	{
+		case 'Vector':
+			parent_vector_id_txt = document.getElementById("parent_vector_id_txt");
+			parent_vector_id = parent_vector_id_txt.value;
+
+			pv_assocID = document.getElementById("Vector_assoc_parent_vector_input").value;
+			
+			if (parent_vector_id.length > 0)
+			{
+				inputs_ar[parent_vector_id] = parent_vector_id_txt;
+				seqParams += "&assocID=" + pv_assocID + "&parent_vector=" + parent_vector_id;
+			}
+
+			insert_id_txt = document.getElementById("insert_id_txt");
+			ipv_id_txt = document.getElementById("ipv_id_txt");
+
+			if (insert_id_txt)
+			{
+				insert_id = insert_id_txt.value;
+				insert_assocID = document.getElementById("Vector_assoc_insert_id_input").value;
+
+				if (insert_id.length > 0)
+				{
+					inputs_ar[insert_id] = insert_id_txt;
+					seqParams += "&assocID=" + insert_assocID + "&insert_id=" + insert_id;
+				}
+			}
+			else
+			{
+				ipv_id = ipv_id_txt.value;
+				ipv_assocID = document.getElementById("Vector_assoc_parent_insert_vector_input").value;
+// alert(ipv_assocID);
+				if (ipv_id.length > 0)
+				{
+					inputs_ar[ipv_id] = ipv_id_txt;
+					seqParams += "&assocID=" + ipv_assocID + "&parent_insert_vector=" + ipv_id;
+				}
+			}
+
+		break;
+
+// 		case 'Insert':
+// 		break;
+
+// 		case 'Oligo':
+// 		break;
+
+		case 'CellLine':
+			parent_cell_line_txt = document.getElementById("cl_id_txt");
+			parent_cell_line_id = parent_cell_line_txt.value;
+
+			parent_vector_txt = document.getElementById("pv_id_txt");
+			parent_vector_id = parent_vector_txt.value;
+
+			pcl_assocID = document.getElementById("CellLine_assoc_parent_cell_line_input").value;
+			pv_assocID = document.getElementById("CellLine_assoc_cell_line_parent_vector_input").value;
+
+			if (parent_cell_line_id.length > 0)
+			{
+				inputs_ar[parent_cell_line_id] = parent_cell_line_txt;
+			}
+
+			if (parent_vector_id.length > 0)
+			{
+				inputs_ar[parent_vector_id] = parent_vector_txt;
+			}
+
+			seqParams += "&assocID=" + pcl_assocID + "&parent_cell_line=" + parent_cell_line_id;
+			seqParams += "&assocID=" + pv_assocID + "&cell_line_parent_vector=" + parent_vector_id;
+		break;
+
+		default:
+
+			for (i=0; i < allInputs.length; i++)
+			{
+				tmpEl = allInputs[i];
+				// alert(tmpEl.type);
+		
+				if (tmpEl.type.toLowerCase() == "text")
+				{
+					// debug
+		// 			if (tmpEl.name.indexOf("assoc") >= 0)
+		// 				alert(tmpEl.name);
+		
+					if ((tmpEl.name.indexOf(rType + "_assoc_") == 0) && (tmpEl.name.indexOf("_prop") == tmpEl.name.length-"_prop".length))
+					{
+// 		alert(tmpEl.id);
+						assocID = tmpEl.name.substring((rType + "_assoc_").length, tmpEl.name.indexOf("_prop"));
+// 		alert(assocID);
+						assocAlias = tmpEl.id.substring((rType + "_assoc_").length, tmpEl.id.indexOf("_input"))
+// 		alert(assocAlias);
+						tmpParent = tmpEl.value;
+// 		alert(tmpParent);
+		
+						if (tmpParent.length > 0)
+						{
+							inputs_ar[tmpParent] = allInputs[i];
+							seqParams += "&assocID=" + assocID + "&" + assocAlias + "=" + tmpParent;
+						}
+					}
+				}
+			}
+
+		break;
+	}
+
+// alert(seqParams);
+
+	xmlhttp1.send(seqParams);
+	xmlhttp1.onreadystatechange = checkParents(xmlhttp1, rType, inputs_ar);
+
+	return parentsValid;
+}
+
+function checkParents(xmlhttp, rType, inputs_ar)
+{
+	if (xmlhttp.readyState == 4)
+	{
+// 		alert("ready " + xmlhttp1.readyState);
+
+		if (xmlhttp.status == 200)
+		{
+// 			alert("status " + xmlhttp.status);
+// 			prompt("", xmlhttp.responseText);
+
+			if (xmlhttp.responseText.indexOf("ErrCode") == 0)
+			{
+				tmp_ar = xmlhttp.responseText.split("&");
+
+				tmp_errcode_ar = tmp_ar[0].split("=");
+
+				if (tmp_errcode_ar[0] == 'ErrCode')
+				{
+					err_code = tmp_errcode_ar[1];
+
+					switch (err_code)
+					{
+						case '1':
+							// non-existing prefix, not found in database (e.g. 'D' when the only available prefixes are 'V', 'I', 'C', 'O')
+
+							parent_type_id_err_set = tmp_ar[1];
+							parent_type_id_err_ar = parent_type_id_err_set.split("=");
+							parentID = trimAll(parent_type_id_err_ar[1]);
+
+							alert(parentID + " does not match an existing reagent ID in OpenFreezer.  Please verify your input.");
+							
+							fName = inputs_ar[parentID];
+							fName.setAttribute('autocomplete','off');
+							fName.focus();
+
+							parentsValid = false;
+
+						break;
+// 						
+						case '2':
+							// reagent ID exists but the association is wrong, e.g. user entered an Insert ID where a Vector was expected
+
+							// Error format: "ErrCode=2&&assoc=" + assocName + "&rID=" + parent_id
+
+							assoc_err_set = tmp_ar[1];
+							assoc_err_ar = assoc_err_set.split("=");
+							assocName = assoc_err_ar[1];
+// alert(assocName);
+							parent_type_id_err_set = tmp_ar[2];
+							parent_type_id_err_ar = parent_type_id_err_set.split("=");
+// alert(parent_type_id_err_ar[1]);
+							parentID = trimAll(parent_type_id_err_ar[1]);
+
+							alert(parentID + " is not a valid " + assocName + ".  Please verify your input.");
+							
+							fName = inputs_ar[parentID];
+							fName.setAttribute('autocomplete','off');
+							fName.focus();
+
+							parentsValid = false;
+
+						break;
+						
+						case '3':
+							// user doesn't have read access to parent project
+// print "ErrCode=2&assoc=" + assocName + "&rID=" + parent_id
+							assoc_err_set = tmp_ar[1];
+							assoc_err_ar = assoc_err_set.split("=");
+							assocName = assoc_err_ar[1];
+// alert(assocName);
+							parent_type_id_err_set = tmp_ar[2];
+							parent_type_id_err_ar = parent_type_id_err_set.split("=");
+// alert(parent_type_id_err_ar[1]);
+							parentID = trimAll(parent_type_id_err_ar[1]);
+
+							alert("You may not use " + parentID + " as your " + assocName + ", since you do not have Read access to its project.  Please contact the project owner to obtain access.");
+							
+							fName = inputs_ar[parentID];
+							fName.setAttribute('autocomplete','off');
+							fName.focus();
+
+							parentsValid = false;
+							return
+						
+						break;
+					}
+				}
+
+// 				for (i=0; i < tmp_ar.length; i++)
+// 				{
+// 					tmp_set = tmp_ar[i].split("=");
+// // alert(tmp_set);
+// 
+// 					if (tmp_set[0] == 'ErrCode')
+// 					{
+// // alert("Setting parents to false");
+// // alert(xmlhttp.responseText);
+// 						err_code = tmp_set[1];
+// 
+// 						switch (err_code)
+// 						{
+// 							case '1':
+// 								// non-existing reagent ID (prefix was found in table but numeric portion does not match an existing ID in database)
+// 
+// 								// Error format: ErrCode=1&assoc=" + assocName + "&assocAlias=" + assocAlias + "&" + `assocID` + "=" + parent_id
+// 							break;
+// 							
+// 							case '2':
+// 								// reagent ID exists but the association is wrong, e.g. user entered an Insert ID where a Vector was expected
+// 
+// 								// Error format: ErrCode=2&prefix=" + parent_prefix + "&assoc=" + assocName + "&assocAlias=" + assocAlias
+// 
+// 							break;
+// 							
+// 							case '3':
+// 								// non-existing prefix, not found in database (e.g. 'D' when the only available prefixes are 'V', 'I', 'C', 'O')
+// 
+// 								// Error format: ErrCode=3&parent=" + parent_id
+// 							break;
+// 						}
+// 
+// 						parent_alias = trimAll(tmp_set[0]);
+// 						parent_id = trimAll(tmp_set[1]);
+// 
+// 						alert("Parent " + parent_id + " does not exist in the database.  Please verify your input.");
+// 
+// 						parentInput = document.getElementById(currReagentType +  "_assoc_" + parent_alias + "_input");
+// 
+// 						// Tip gotten from http://geekswithblogs.net/shahedul/archive/2006/08/14/87910.aspx
+// 						// Turn autocomplete off before calling focus(); otherwise get the following error:
+// 						// [Exception... "'Permission denied to set property XULElement.selectedIndex' when calling method: [nsIAutoCompletePopup::selectedIndex]" nsresult: "0x8057001e (NS_ERROR_XPC_JS_THREW_STRING)
+// 						parentInput.setAttribute('autocomplete','off');
+// 
+// 						parentInput.focus();
+// 	
+// 						parentsValid = false;
+// 						break;
+// 					}
+// 				}
+			}
+			else
+			{
+// alert("Setting parents to true");
+				parentsValid = true;
+			}
+		}
+	}
+
+// 	alert(parentsValid);
+}
+
+
+/**
+	Oct. 6/09, Marina: Property name verification at creation of new reagent type:
+
+	A property name CANNOT:
+
+		- be the same as its containing category name (e.g. CANNOT have 'miscellaneous' property under 'miscellaneous' category; OK across different categories - i.e. CAN have 'miscellaneous' sequence feature, a 'Miscellaneous' category and a 'miscellaneous' classifier)
+
+		- be the same as a reagent type name (current or other existing type) - i.e. cannot have a property or category called 'Vector'
+
+		- be the same as a reagent type prefix (current or other existing prefix)
+
+		- be called 'sequence', 'dna', 'protein', 'rna', 'DNA sequence', 'protein sequence', 'rna sequence' (even though these words may be **contained within** the property's name - e.g. 'DNA Sequence Features')
+
+	Some of the above restrictions also apply to category names (if indicated).
+
+// REMOVED COMPLETELY DEC. 2/09: MOVED CHECK TO verifyAddNewProperty()
+function verifyPropertyAndCategoryNames()
+{
+	var rType = document.getElementById("reagent_type_name");
+	var rTypeName = rType.value;
+
+	var rTypePrefixInput = document.getElementById("reagent_type_prefix");
+	var rTypePrefix = rTypePrefixInput.value;
+
+	var reagentTypeNames = document.getElementsByName("reagent_type_names[]");
+	var rTypeNames = new Array();
+
+	for (k=0; k < reagentTypeNames.length; k++)
+	{
+		var tmpName = reagentTypeNames[k].value.toLowerCase();
+		rTypeNames.push(tmpName);
+	}
+
+	var reagentTypePrefixes = document.getElementsByName("reagent_type_prefixes[]");
+	var rTypePrefixes = new Array();
+
+	for (l = 0; l < reagentTypePrefixes.length; l++)
+	{
+		var tmpPrefix = reagentTypePrefixes[l];
+		rTypePrefixes.push(tmpPrefix);
+	}
+
+	// traverse over properties and check each, do sequence separately
+	var allInputs = document.getElementsByTagName("INPUT");
+
+	for (i=0; i < allInputs.length; i++)
+	{
+		var tmpInput = allInputs[i];
+
+		if (tmpInput.type.toLowerCase() == "checkbox")
+		{
+			if (tmpInput.checked == true)
+			{
+				tmpName = tmpInput.id;	// e.g. "createReagentType_general_properties_:_notes_checkbox_id"
+		
+				// Extract the category
+				categoryAlias = tmpName.substring("createReagentType_".length, tmpName.indexOf("_:_"));
+	
+				propAlias = tmpName.substring(("createReagentType_" + categoryAlias + "_:_").length, tmpName.indexOf("_checkbox_id"));
+		
+				// grab the description
+				tmpDescr = document.getElementById(categoryAlias + "_:_" + propAlias + "_checkbox_desc_hidden");
+				
+				if (tmpDescr)
+				{
+					if (tmpDescr.value != "")
+					{
+// 						alert(tmpDescr.value);
+// 						alert(tmpDescr.name);
+
+						if ( (inArray(tmpDescr.value.toLowerCase(), rTypeNames)) || (inArray(tmpDescr.value.toLowerCase(), rTypePrefixes)))
+						{
+							alert("Property names may not be the same as reagent type names or prefixes.  Please verify your input.");
+							tmpDescr.focus();
+							return false;
+						}
+
+						// Now: The words 'DNA Sequence', 'Protein Sequence', 'RNA Sequence' are allowed in the appropriate categories.  BUT 'DNA', 'RNA', 'Protein', or 'Sequence' are not allowed anywhere!!
+						else if ((categoryAlias == "sequence_properties") || (categoryAlias == "protein_sequence_properties") || (categoryAlias == "rna_sequence_properties"))
+						{
+							// Allow 'DNA Sequence', 'RNA Sequence', 'Protein Sequence', disallow the rest
+							if ((tmpDescr.value.toLowerCase() == "dna") || (tmpDescr.value.toLowerCase() == "rna") || (tmpDescr.value.toLowerCase() == "protein") || (tmpDescr.value.toLowerCase() == "sequence"))
+							{
+								alert("'Sequence', 'Protein', 'DNA' or 'RNA' may not be used as reagent type attribute names.  Please verify your input.");
+								tmpDescr.focus();
+								return false;
+							}
+						}
+						else
+						{
+							// Disallow 'DNA Sequence', 'RNA Sequence', 'Protein Sequence', 'DNA', 'RNA', 'Protein', 'Sequence'
+							if ((tmpDescr.value.toLowerCase() == "sequence") || (tmpDescr.value.toLowerCase() == "dna sequence") || (tmpDescr.value.toLowerCase() == "protein sequence") || (tmpDescr.value.toLowerCase() == "rna sequence") || (tmpDescr.value.toLowerCase() == "dna") || (tmpDescr.value.toLowerCase() == "rna") || (tmpDescr.value.toLowerCase() == "protein"))
+							{
+								alert("'Sequence', 'DNA Sequence', 'RNA Sequence', 'Protein Sequence',  'Protein', 'DNA' or 'RNA' may not be used as reagent type attribute names.   Please verify your input.");
+								tmpDescr.focus();
+								return false;
+							}
+						}
+						
+					}
+				}
+			}
+		}
+	}	
+}
+*/
+
+function verifyUniqueReagentTypeName()
+{
+	var allInputs = document.getElementsByTagName("INPUT");
+
+	var rType = document.getElementById("reagent_type_name");
+	var rTypeName = rType.value;
+
+	var uniqueWarning = document.getElementById("reagent_type_name_warning");
+
+	if (rTypeName.length <= 3)
+	{
+		alert("Reagent type names must be over 3 characters in length.  Please verify your input.");
+		rType.focus();
+		uniqueWarning.style.display = "inline";
+		return false;
+	}
+
+	if ( (rTypeName.toLowerCase() == 'sequence') || (rTypeName.toLowerCase() == 'dna sequence') || (rTypeName.toLowerCase() == 'rna sequence') || (rTypeName.toLowerCase() == 'protein sequence'))
+	{
+		alert("You may NOT use 'sequence', 'DNA sequence', 'RNA sequence', 'Protein sequence' as the reagent type name.  Please select a different name for the new reagent type.");
+		rType.focus();
+		uniqueWarning.style.display = "inline";
+		return false;
+	}
+
+	for (i=0; i < allInputs.length; i++)
+	{
+		var tmpInput = allInputs[i];
+
+		if (tmpInput.name == "reagent_type_names[]")
+		{
+			if (rTypeName.toLowerCase() == tmpInput.value.toLowerCase())
+			{
+				alert("The name provided for the new reagent type already exists.  Please choose a unique name for the new reagent type.");
+				rType.focus();
+				uniqueWarning.style.display = "inline";
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
+
+function verifyReagentTypePrefix()
+{
+	var allInputs = document.getElementsByTagName("INPUT");
+
+	var rTypePrefixInput = document.getElementById("reagent_type_prefix");
+	var rTypePrefix = rTypePrefixInput.value;
+
+	var reagentTypeNameInput = document.getElementById("reagent_type_name");
+	var reagentTypeName = reagentTypeNameInput.value;
+
+	var prefixWarning = document.getElementById("reagent_type_prefix_warning");
+
+	for (i=0; i < allInputs.length; i++)
+	{
+		var tmpInput = allInputs[i];
+
+		if (tmpInput.name == "reagent_type_prefixes[]")
+		{
+			if (rTypePrefix.toLowerCase() == tmpInput.value.toLowerCase())
+			{
+				alert("The prefix provided for the new reagent type already exists.  Please choose a unique prefix for the new reagent type.");
+				rTypePrefixInput.focus();
+				prefixWarning.style.display = "inline";
+				return false;
+			}
+		}
+	}
+
+	// prefixes must be under 3 characters in length
+	if (rTypePrefix.length > 3)
+	{
+		alert("Prefixes must be 3 characters in length or less and may not be the same as the reagent type name.  Please verify your input.");
+		rTypePrefixInput.focus();
+		prefixWarning.style.display = "inline";
+		return false;
+	}
+
+	// name may not be the same as prefix (lowercase to make comparison case-insensitive)
+	if (reagentTypeName.toLowerCase() == rTypePrefix.toLowerCase())
+	{
+		alert("Prefixes may not be the same as the reagent type name.  Please verify your input.");
+		rTypePrefixInput.focus();
+		prefixWarning.style.display = "inline";
+		return false;
+	}
+
+	// disallow numbers in prefixes
+	numstr = "0123456789";
+
+	for (i=0; i < rTypePrefix.length; i++)
+	{
+		ch = rTypePrefix.charAt(i);
+
+		if (numstr.indexOf(ch) >= 0)
+		{
+			alert("Prefixes may not contain digits.  Please verify your input.");
+			rTypePrefixInput.focus();
+			prefixWarning.style.display = "inline";
+			return false;
+		}
+	}
+
+	return true;
+}
+
+
+// April 3/09
+function verifyNewReagentTypeName()
+{
+	var rTypeName = document.getElementById("reagent_type_name");
+	var rTypeNameWarning = document.getElementById("reagent_type_name_warning");
+
+	if (rTypeName.value.length == 0)
+	{
+		alert("Please provide a name for the new reagent type");
+		rTypeNameWarning.style.display = "inline";
+		rTypeName.focus();
+		return false;
+	}
+	else
+	{
+		rTypeNameWarning.style.display = "none";
+		return true;
+	}
+}
+
+
+// April 3/09
+function verifyNewReagentTypePrefix()
+{
+	var rTypePrefix = document.getElementById("reagent_type_prefix");
+	var rTypePrefixWarning = document.getElementById("reagent_type_prefix_warning");
+
+	if (rTypePrefix.value.length == 0)
+	{
+		alert("Please specify a unique prefix for the new reagent type");
+		rTypePrefixWarning.style.display = "inline";
+		rTypePrefix.focus();
+		return false;
+	}
+	else
+	{
+		rTypePrefixWarning.style.display = "none";
+		return true;
+	}
+}
+
+// April 3/09 - Check all checkboxes at the click of a button
+function checkAll(cbID)
+{
+	cbID = unescape(cbID);
+
+	var checkBoxList = document.getElementsByName(cbID+"[]");
+	var tmpCB;
+
+	for (i = 0; i < checkBoxList.length; i++)
+	{
+		tmpCB = checkBoxList[i];
+
+		if (!tmpCB.disabled)
+			tmpCB.checked = true;
+	}
+}
+
+// June 7, 2010: check all except <arg>.  Used in reagent type modification, when want to check only all properties assigned to the reagent type, e.g. for ordering
+function checkAllExclude(categoryAlias)
+{
+	categoryAlias = unescape(categoryAlias);
+// alert(categoryAlias);
+	var checkBoxList = document.getElementsByName(categoryAlias + "[]");
+// alert(categoryAlias + "[]");
+// alert(checkBoxList);
+// alert(checkBoxList.length);
+
+	var toExclude = document.getElementsByName(categoryAlias + "_exclude[]");	// hidden inputs
+// alert(categoryAlias + "_exclude[]");
+// alert(toExclude);
+// alert(toExclude.length);
+
+	var exclList = Array();
+	var i, j;
+
+	// get names of all unused properties (those that should not be checked)
+	for (i=0; i < toExclude.length; i++)
+	{
+		tmpPropAlias = toExclude[i].value;
+// alert(tmpPropAlias);
+		excl_cb = categoryAlias + "_:_" + tmpPropAlias;
+
+		if (document.getElementById(excl_cb))
+		{
+// alert("Excluding " + categoryAlias + "_:_" + tmpPropAlias);
+			exclList.push(excl_cb);
+		}
+	}
+
+	// now iterate through checboxes and check those that should not be excluded
+	for (j=0; j < checkBoxList.length; j++)
+	{
+		tmpCB = checkBoxList[j];
+// alert(tmpCB);
+		// not checking isDisabled here, b/c this would MOST LIKELY be used to select all assigned properties for ORDERING - hence, need the disabled properties too
+		if (!inArray(tmpCB.id, exclList))
+		{
+// alert("not in use");
+			tmpCB.checked = true;
+		}
+	}
+}
+
+function enableCheckboxes()
+{
+// alert("here");
+	var checkBoxList = document.getElementsByTagName("INPUT");
+
+	for (i = 0; i < checkBoxList.length; i++)
+	{
+		tmpCB = checkBoxList[i];
+
+		if ((tmpCB.type == "checkbox") && (tmpCB.disabled == true))
+		{
+// alert(tmpCB.value);
+			tmpCB.disabled = false;
+		}
+	}
+}
+
+
+// June 9/09: 'Delete' button on detailed view
+function deleteReagentFromDetailedView(rID)
+{
+	if (confirm("Are you sure you wish to delete this reagent?"))
+	{
+		// call AJAX script
+		url = cgiPath + "delete.py";
+		xmlhttp1 = createXML();
+		xmlhttp1.open("POST", url, false);
+		xmlhttp1.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+	
+		seqParams = "rID=" + rID;
+		
+		xmlhttp1.send(seqParams);
+		// alert(xmlhttp1.readyState);
+// 		alert(xmlhttp1.responseText);
+// 		xmlhttp1.onreadystatechange = deleteReagent(xmlhttp1);
+
+		str_rid = "rID=";
+		str_status = "&Status=";
+
+		limsID = xmlhttp1.responseText.substring(str_rid.length, xmlhttp1.responseText.indexOf(str_status));
+
+		result = xmlhttp1.responseText.substring(xmlhttp1.responseText.indexOf(str_status)+str_status.length);
+
+		if (result == 1)
+		{
+			document.body.className = "cursor_auto";
+
+			alert("Deletion completed.");
+			window.location.href = hostName + "search.php?View=1";
+		}
+		else
+		{
+			document.body.className = "cursor_auto";
+			alert("You may not delete " + limsID + ", since there are preps associated with it.");
+		}
+	}
+}
+
+
+// June 5/09
+function deleteReagentsFromSearch(rSetName)
+{
+// alert(rSetName);
+	var xmlhttp1;
+	var url;
+
+	// Make sure at least one checkbox is checked before prompting - user could click the Delete button w/o selecting anything!
+	var actn = false;
+	var checkBoxList = document.getElementsByName(rSetName + "[]");
+
+	for (i = 0; i < checkBoxList.length; i++)
+	{
+		if (checkBoxList[i].checked)
+		{
+			actn = true;
+			break;
+		}
+	}
+
+	var err = false;
+
+	if (actn)
+	{
+		if (confirm("Are you sure you wish to delete selected reagents?"))
+		{
+			document.body.className = "cursor_wait";
+
+			var checkBoxList = document.getElementsByName(rSetName + "[]");
+		
+	// 		alert(checkBoxList.length);
+	
+			for (i = 0; i < checkBoxList.length; i++)
+			{
+				xmlhttp1 = createXML();
+				url = cgiPath + "delete.py";
+			// 	xmlhttp1 = createXML();
+				xmlhttp1.open("POST", url, false);
+	
+				if (checkBoxList[i].checked)
+				{
+					rID = checkBoxList[i].value;
+	// 	alert(rID);
+					if (document.getElementById("has_children_" + rID))
+					{
+						tmp_rid = document.getElementById("has_children_" + rID).value;
+	
+						alert("You may not delete " + tmp_rid + ", since it is a parent of other reagents.  You should delete these children first before attempting to delete " + tmp_rid);
+	
+						return false;
+					}
+					else if (document.getElementById("write_access_" + rID))
+					{
+						tmp_rid = document.getElementById("write_access_" + rID).value;
+		
+						alert("You may not delete " + tmp_rid + ", since you do not have Write access to its project.  Please contact the project owner to obtain permission to delete.");
+		
+						return false;
+					}
+
+					// call AJAX script
+					xmlhttp1.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+					seqParams = "rID=" + rID;
+					xmlhttp1.send(seqParams);
+
+					// alert(xmlhttp1.readyState);
+					// alert(xmlhttp1.responseText);
+
+					// process AJAX response
+					str_rid = "rID=";
+					str_status = "&Status=";
+
+					rID = xmlhttp1.responseText.substring(str_rid.length, xmlhttp1.responseText.indexOf(str_status));
+
+					result = xmlhttp1.responseText.substring(xmlhttp1.responseText.indexOf(str_status)+str_status.length);
+
+					if (result != 1)
+					{
+						document.body.className = "cursor_auto";
+						alert("You may not delete " + rID + ", since there are preps associated with it.");
+						err = true;
+					}
+					else
+					{
+						err = false;
+					}
+				}
+			}
+
+			if (!err)
+			{
+				document.body.className = "cursor_auto";
+				alert("Deletion completed.");
+				window.location.href = hostName + "search.php?View=1";
+			}
+		}
+	}
+}
+
+// function deleteReagent(xmlhttp1)
+// {
+// 	if (xmlhttp1.readyState == 4)
+// 	{
+// 		if (xmlhttp1.status == 200)
+// 		{
+// 			str_rid = "rID=";
+// 			str_status = "&Status=";
+// 
+// 			rID = xmlhttp1.responseText.substring(str_rid.length, xmlhttp1.responseText.indexOf(str_status));
+// // 			alert(rID);
+// 
+// 			result = xmlhttp1.responseText.substring(xmlhttp1.responseText.indexOf(str_status)+str_status.length);
+// // 			alert(result);
+// 
+// 			document.getElementById("del_status_rid_" + rID).setAttribute("value", result);
+// 		}
+// 	}
+// }
+
+
+// July 1, 2010: for bug report page
+function checkModule()
+{
+	var modules = document.getElementById("modules_list");
+
+	if ((modules.selectedIndex == 0) || (modules[modules.selectedIndex].value == 'default'))
+	{
+		alert("Please select a module from the list.");
+		modules.focus();
+		modules.style.color = "red";
+		return false;
+	}
+
+	return true;
+}
+
+
+// July 1, 2010: for bug report page
+function checkIssue()
+{
+	var bugDescr = document.getElementById("bugDescription");
+	var modules = document.getElementById("modules_list");
+
+	if (trimAll(bugDescr.value) == "")
+	{
+		alert("Please describe in detail your issue or feature request.");
+		bugDescr.focus();
+		modules.style.color = "black";
+		return false;
+	}
+
+	return true;
+}
+
+
+// Modified May 20, 2010: passing ATTRIBUTE IDs, not property names
+function checkMandatoryProps(rType, categoryAlias)
+{
+	var mandatoryProps = document.getElementsByName(rType + "_mandatoryProps[]");
+
+//alert(categoryAlias);
+
+//alert(rType + "_mandatoryProps[]");
+	var allWarnings = document.getElementsByName("warnings[]");
+
+	if ((document.pressed == 'Save') || (document.pressed == 'Create'))
+	{
+		for (i=0; i < mandatoryProps.length; i++)
+		{
+			attrID = mandatoryProps[i].value;
+		
+	//alert("Mandatory: values_" + attrID);
+
+			propField = document.getElementById("values_" + attrID);
+
+			if (propField)
+			{
+				//alert(propField.id);
+
+				pfName = propField.name;
+
+				// May 11, 2011: Differentiate between creation and modification views!!!!
+
+				url = window.location.href;
+				url_pre = hostName + "/Reagent.php?View=";
+
+				view_number = url.substr(url_pre.length-1, 1);
+
+				if ((view_number != '6') || document.getElementById('preload_cell_line'))
+				{
+					// Extract prop alias and category alias from field name
+					//alert(pfName);
+
+					p1 = pfName.substr(("reagent_detailedview_" + rType + "_").length, pfName.length);
+					catAlias = p1.substr(0, p1.indexOf("_:_"));
+					//alert(catAlias);
+
+					prefix = "reagent_detailedview_" + rType + "_" + catAlias + "_:_";
+					//alert(prefix);
+
+					// alert(pfName);
+					// alert(pfName.length);
+
+					p2 = pfName.substr(prefix.length, pfName.lastIndexOf("_prop"));
+					pAlias = p2.substr(0, p2.length-"_prop".length);
+
+		// 			alert(pAlias);
+
+					if (propField.type == "text")
+					{
+						if (trimAll(propField.value).length == 0)
+						{
+							alert("Please provide values for all mandatory properties.");
+							propField.focus();
+
+							// show err msg box
+							errMsg = document.getElementById("warn_" + attrID);
+
+							if (errMsg)
+							{
+								errMsg.style.display = "inline";
+
+								// hide the rest of the error msgs
+								for (i=0; i < allWarnings.length; i++)
+								{
+									if (allWarnings[i].id != "warn_" + attrID)
+										allWarnings[i].style.display = "none";
+								}
+
+								propField.focus();
+							}
+
+							return false;
+						}
+					}
+					else if ((propField.type == "select-one") || (propField.type == "select-multiple"))
+					{
+						// April 15, 2011: prevent error on empty project lists
+						if ((pAlias == "packet_id") && (propField.options.length == 0))
+						{
+							alert("Project list is empty.  Please obtain write access to at least one project before creating reagents.");
+							return false;
+						}
+
+						if (propField.selectedIndex == 0)
+						{			
+							// For empty open/closed, check type of insert, and return true if type of insert is 'cDNA w/ UTRs' or 'DNA Fragment'
+							if (pAlias == "open_closed")
+							{
+								var iTypeAttrID = document.getElementById("type_of_insert_attr_id_hidden").value;
+			 //alert(iTypeAttrID);
+								var itype_list = document.getElementById("values_" + iTypeAttrID);
+			 //alert(itype_list);
+								
+								// if open/closed is empty, check type of insert
+								if ((itype_list[itype_list.selectedIndex].value.toLowerCase() != 'cdna with utrs') && (itype_list[itype_list.selectedIndex].value.toLowerCase() != 'dna fragment'))
+								{
+									alert("Please provide values for all mandatory properties.");
+									propField.focus();
+
+									// show err msg box
+									//errMsg = document.getElementById("warn_" + attrID);
+									for (i=0; i < allWarnings.length; i++)
+									{
+										if (allWarnings[i].id != "warn_" + attrID)
+											allWarnings[i].style.display = "none";
+										else
+											allWarnings[i].style.display = "inline";
+									}
+
+									return false;
+								}
+							}
+							else
+							{
+								alert("Please provide values for all mandatory properties.");
+								propField.focus();
+
+								// show err msg box
+								//errMsg = document.getElementById("warn_" + attrID);
+								for (i=0; i < allWarnings.length; i++)
+								{
+									if (allWarnings[i].id != "warn_" + attrID)
+										allWarnings[i].style.display = "none";
+									else
+										allWarnings[i].style.display = "inline";
+								}
+
+								return false;
+							}
+						}
+					}
+				}
+				else
+				{					
+					// find out which category we're editing!  e.g. for Inserts mandatory props are in different categories, general name, status, project, and classifier/sequence type of insert and open/closed
+					// ALSO for Inserts: open/closed and type of insert are under Classifiers AND Sequence!!!!!!!!!!!!!!!!
+
+					p1 = pfName.substr("reagent_detailedview_".length, pfName.length);
+//					alert(p1);
+
+					prefix = "reagent_detailedview_";
+					//alert(prefix);
+					postfix = "_prop";
+
+					// alert(pfName);
+					// alert(pfName.length);
+
+					pAlias_prop = pfName.substr(prefix.length, pfName.lastIndexOf(postfix)-1);
+					pAlias = pAlias_prop.substr(0, pAlias_prop.lastIndexOf(postfix));
+					//alert(pAlias);
+			//	}
+
+					// In case mandatory properties are in different categories
+					var currTable = document.getElementById(categoryAlias + "_tbl_modify");
+
+	//alert("current category " + categoryAlias);
+	//alert(propField.parentNode.parentNode.id);
+	//alert(pAlias);
+					if ((propField.parentNode.parentNode.id == categoryAlias) && (currTable.style.display != "none"))
+					{					
+						if (currTable.style.display != "none")
+						{
+							if (propField.type == "text")
+							{
+								if (trimAll(propField.value).length == 0)
+								{
+									alert("Please provide values for all mandatory properties.");
+									propField.focus();
+
+									// show err msg box
+									errMsg = document.getElementById("warn_" + attrID);
+
+									if (errMsg)
+									{
+										errMsg.style.display = "inline";
+
+										// hide the rest of the error msgs
+										for (i=0; i < allWarnings.length; i++)
+										{
+											if (allWarnings[i].id != "warn_" + attrID)
+												allWarnings[i].style.display = "none";
+										}
+
+										propField.focus();
+									}
+
+									return false;
+								}
+							}
+							else if ((propField.type == "select-one") || (propField.type == "select-multiple"))
+							{
+								// April 15, 2011: prevent error on empty project lists
+								if ((pAlias == "packet_id") && (propField.options.length == 0))
+								{
+									alert("Project list is empty.  Please obtain write access to at least one project before creating reagents.");
+									return false;
+								}
+
+								if (propField.selectedIndex == 0)
+								{			
+									// For empty open/closed, check type of insert, and return true if type of insert is 'cDNA w/ UTRs' or 'DNA Fragment'
+									if (pAlias == "open_closed")
+									{
+										var iTypeAttrID = document.getElementById("type_of_insert_attr_id_hidden").value;
+					 //alert(iTypeAttrID);
+										var itype_list = document.getElementById("values_" + iTypeAttrID);
+					 //alert(itype_list);
+										
+										// if open/closed is empty, check type of insert
+										if ((itype_list[itype_list.selectedIndex].value.toLowerCase() != 'cdna with utrs') && (itype_list[itype_list.selectedIndex].value.toLowerCase() != 'dna fragment'))
+										{
+											alert("Please provide values for all mandatory properties.");
+											propField.focus();
+
+											// show err msg box
+											//errMsg = document.getElementById("warn_" + attrID);
+											for (i=0; i < allWarnings.length; i++)
+											{
+												if (allWarnings[i].id != "warn_" + attrID)
+													allWarnings[i].style.display = "none";
+												else
+													allWarnings[i].style.display = "inline";
+											}
+
+											return false;
+										}
+									}
+									else
+									{
+										alert("Please provide values for all mandatory properties.");
+										propField.focus();
+
+										// show err msg box
+										//errMsg = document.getElementById("warn_" + attrID);
+										for (i=0; i < allWarnings.length; i++)
+										{
+											if (allWarnings[i].id != "warn_" + attrID)
+												allWarnings[i].style.display = "none";
+											else
+												allWarnings[i].style.display = "inline";
+										}
+
+										return false;
+									}
+								}
+							}
+						}
+					}
+				}
+
+				/*
+					// grab all the properties under this specific category!!!!!!!!!!
+					
+					allWarnings = document.getElementsByName("warnings[]");
+
+					if (propField.type == "text")
+					{
+						if (trimAll(propField.value).length == 0)
+						{
+							alert("Please provide values for all mandatory properties.");
+							propField.focus();
+
+							// show err msg box
+							errMsg = document.getElementById("warn_" + attrID);
+
+							if (errMsg)
+							{
+								errMsg.style.display = "inline";
+
+								// hide the rest of the error msgs
+								for (i=0; i < allWarnings.length; i++)
+								{
+									if (allWarnings[i].id != "warn_" + attrID)
+										allWarnings[i].style.display = "none";
+								}
+
+								propField.focus();
+							}
+
+							return false;
+						}
+					}
+					else if ((propField.type == "select-one") || (propField.type == "select-multiple"))
+					{				
+						// April 15, 2011: prevent error on empty project lists
+						if ((pAlias == "packet_id") && (propField.options.length == 0))
+						{
+							alert("Project list is empty.  Please obtain write access to at least one project before creating reagents.");
+							return false;
+						}
+
+						//alert(pAlias);
+
+						// Update June 23, 2010: allow a blank open/closed value for certain types of insert (change code)
+						if ((propField[propField.selectedIndex].value == 'default') || (propField[propField.selectedIndex].value == '') || (propField[propField.selectedIndex].value.indexOf("-- Select ") == 0))
+						//if (propField.selectedIndex == 0)
+						{
+							//alert(propField.id);
+							//alert(pAlias);
+							//alert(categoryAlias);
+							//alert(thisCategory);
+
+							if (propField.id == categoryAlias + "_open_closed")
+							{
+								// check insert type - can leave open/closed empty for certain types of insert
+								if (document.getElementById("type_of_insert_attr_id_hidden"))
+								{
+	//		  alert("type of insert");
+									var iTypeAttrID = document.getElementById("type_of_insert_attr_id_hidden").value;
+	//		 alert(iTypeAttrID);
+									var itype_list = document.getElementById("values_" + iTypeAttrID);
+	//		 alert(itype_list);
+			
+									if ((itype_list[itype_list.selectedIndex].value != "cDNA with UTRs") && (itype_list[itype_list.selectedIndex].value != "DNA Fragment") && (itype_list[itype_list.selectedIndex].value != "None"))
+									{
+										alert("Please provide values for all mandatory properties.");
+										propField.focus();
+			// show err msg box
+									
+										// hide the rest of the error msgs
+										for (i=0; i < allWarnings.length; i++)
+										{
+											if (allWarnings[i].id != "warn_" + attrID)
+												allWarnings[i].style.display = "none";
+											else
+												allWarnings[i].style.display = "inline";
+										}
+										
+										return false;
+									}
+									else
+										return true;
+								}
+							}
+							// YEAH, BUT CANNOT change type of insert if we're editing a different category!!!!
+							else
+							{
+								alert(propField.id);
+								alert(propField[propField.selectedIndex].value);
+
+								alert("Please provide values for all mandatory properties.");
+								propField.focus();
+
+								// show err msg box
+								//errMsg = document.getElementById("warn_" + attrID);
+								for (i=0; i < allWarnings.length; i++)
+								{
+									if (allWarnings[i].id != "warn_" + attrID)
+										allWarnings[i].style.display = "none";
+									else
+										allWarnings[i].style.display = "inline";
+								}
+
+								return false;
+							}
+						}
+						else if ((pAlias == "packet_id") && (propField.selectedIndex == 0))
+						{
+							alert("Please provide values for all mandatory properties.");
+							propField.focus();
+
+							errMsg = document.getElementById("warn_" + attrID);
+				
+							if (errMsg)
+							{
+								errMsg.style.display = "inline";
+
+								// hide the rest of the error msgs
+								for (i=0; i < allWarnings.length; i++)
+								{
+									if (allWarnings[i].id != "warn_" + attrID)
+										allWarnings[i].style.display = "none";
+								}
+
+								propField.focus();
+							}
+
+							return false;
+						}
+					}
+					*/
+			}
+			else
+			{
+				propField = document.getElementById("targetList_" + attrID);
+
+				if (propField)
+				{
+					//alert(propField.id);
+
+					pfName = propField.name;
+
+					// May 11, 2011: Differentiate between creation and modification views!!!!
+
+					url = window.location.href;
+					url_pre = hostName + "/Reagent.php?View=";
+
+					view_number = url.substr(url_pre.length-1, 1);
+
+					if ((view_number != '6') || document.getElementById('preload_cell_line'))
+					{
+						// Extract prop alias and category alias from field name
+						//alert(pfName);
+
+						p1 = pfName.substr(("reagent_detailedview_" + rType + "_").length, pfName.length);
+						catAlias = p1.substr(0, p1.indexOf("_:_"));
+						//alert(catAlias);
+
+						prefix = "reagent_detailedview_" + rType + "_" + catAlias + "_:_";
+						//alert(prefix);
+
+						// alert(pfName);
+						// alert(pfName.length);
+
+						p2 = pfName.substr(prefix.length, pfName.lastIndexOf("_prop"));
+						pAlias = p2.substr(0, p2.length-"_prop".length);
+
+						if (propField.options.length == 0)
+						{
+							alert("Please provide values for all mandatory properties.");
+							propField.focus();
+
+							// show err msg box
+							//errMsg = document.getElementById("warn_" + attrID);
+							for (i=0; i < allWarnings.length; i++)
+							{
+								if (allWarnings[i].id != "warn_" + attrID)
+									allWarnings[i].style.display = "none";
+								else
+									allWarnings[i].style.display = "inline";
+							}
+
+							return false;	
+						}
+					}
+					else
+					{
+						// find out which category we're editing!  e.g. for Inserts mandatory props are in different categories, general name, status, project, and classifier/sequence type of insert and open/closed
+						// ALSO for Inserts: open/closed and type of insert are under Classifiers AND Sequence!!!!!!!!!!!!!!!!
+
+						p1 = pfName.substr("reagent_detailedview_".length, pfName.length);
+	//					alert(p1);
+
+						prefix = "reagent_detailedview_";
+						//alert(prefix);
+						postfix = "_prop";
+
+						// alert(pfName);
+						// alert(pfName.length);
+
+						pAlias_prop = pfName.substr(prefix.length, pfName.lastIndexOf(postfix)-1);
+						pAlias = pAlias_prop.substr(0, pAlias_prop.lastIndexOf(postfix));
+						//alert(pAlias);
+				//	}
+
+						// In case mandatory properties are in different categories
+						var currTable = document.getElementById(categoryAlias + "_tbl_modify");
+
+		//alert("current category " + categoryAlias);
+		//alert(propField.parentNode.parentNode.id);
+		//alert(pAlias);
+						if ((propField.parentNode.parentNode.id == categoryAlias) && (currTable.style.display != "none"))
+						{					
+							if (currTable.style.display != "none")
+							{
+								if (propField.options.length == 0)
+								{
+									alert("Please provide values for all mandatory properties.");
+									propField.focus();
+
+									// show err msg box
+									//errMsg = document.getElementById("warn_" + attrID);
+									for (i=0; i < allWarnings.length; i++)
+									{
+										if (allWarnings[i].id != "warn_" + attrID)
+											allWarnings[i].style.display = "none";
+										else
+											allWarnings[i].style.display = "inline";
+									}
+
+									return false;	
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+	enableSelect();
+	return true;
+}
+
+
+// April 3/09 - Uncheck all checkboxes at the click of a button
+// Update June 1/09: Some properties are mandatory - added 'exclude' parameter so these boxes are never unchecked
+function uncheckAll(cbID, exclude)
+{
+	cbID = unescape(cbID);
+
+	var checkBoxList = document.getElementsByName(cbID+"[]");
+	var tmpCB;
+
+// 	alert(exclude);
+
+	for (i = 0; i < checkBoxList.length; i++)
+	{
+		tmpCB = checkBoxList[i];
+// alert(tmpCB.value);
+		if (/*(exclude.length > 0) && */!inArray(tmpCB.value, exclude))
+			tmpCB.checked = false;
+	}
+}
+
+// April 3/09: Dynamically substitute new reagent type name in different sections on creation page
+function fillReagentTypeNames()
+{
+	var rTypeName = document.getElementById("reagent_type_name").value;
+	var rTypeNames = document.getElementsByName('newReagentType');
+	var tmpTypeName;
+
+	for (i = 0; i < rTypeNames.length; i++)
+	{
+		tmpTypeName = rTypeNames[i];
+		tmpTypeName.value = rTypeName;
+		tmpTypeName.innerHTML = rTypeName;
+	}
+}
+
+
+// Oct. 20/09
+function replaceAll(str, lookFor, replaceWith)
+{
+	var i;
+	var newString = "";
+
+	for (i=0; i < str.length; i++)
+	{
+		if (i == 0)
+		{
+			if(str.charAt(i) == "'")
+			{
+				newString += "\\" + str.charAt(i);
+			}
+			else
+			{
+				newString += str.charAt(i);
+			}
+		}
+		else
+		{
+			if ((str.charAt(i) == "'") && (str.charAt(i-1) != "\\"))
+			{
+				newString += "\\" + str.charAt(i);
+			}
+			else
+			{
+				newString += str.charAt(i);
+			}
+		}
+
+	}
+
+	return newString;
+}
+
+
+function formatInput(formID)
+{
+	var myForm = document.getElementById(formID);
+	var elems = myForm.elements;
+	var elemLength = elems.length;
+	var i;
+
+	for (i=0; i < elemLength; i++)
+	{
+		var tmpElem = elems[i];
+
+		if (tmpElem.value.indexOf('%') >= 0)
+		{
+			alert("Before: " + tmpElem.value);
+// 			tmpElem.value = tmpElem.value.replace(/%/g,'%25')
+// 			tmpElem.value = escape(tmpElem.value);
+tmpElem.value = tmpElem.value.replace('%', '%25');
+			alert("After: " + tmpElem.value);
+		}
+	}
+}
+// April 6/09: Show/hide property values input table when defining list of property values for a new reagent type
+function showHideAddPropertyValuesInput(propAlias)
+{
+// alert(propAlias);
+
+	// ATTENTION: PHP escapes quotation marks!  The actual field name contains a slash before a quote.  Must, therefore, append a slash here, for the input name to be recognized1
+// 	propAlias = replaceAll(propAlias, "'", "\\'");		// KEEP replaceAll - DON'T use addslashes, won't work!!!!!!
+	propAlias = unescape(propAlias);
+
+	var inputDiv = document.getElementById("propertyValuesInputDiv_" + propAlias);
+	var hyperlinkDiv = document.getElementById("make_hl_" + propAlias);
+	var multipleDiv = document.getElementById("make_mult_" + propAlias);
+
+	// May 11, 2010
+	var otherDiv = document.getElementById("allow_other_" + propAlias);
+
+	var noHL = document.getElementById("no_hl_" + propAlias);
+	var noMult = document.getElementById("no_mult_" + propAlias);
+
+// 	var propsList = document.getElementById("propertyValuesInputList_" + propAlias);
+
+// alert(inputDiv);
+// alert("input_format_radio_list_" + propAlias);
+
+	var inputTypeRadioList = document.getElementById("input_format_radio_list_" + propAlias);
+	var inputTypeRadioText = document.getElementById("input_format_radio_text_" + propAlias);
+
+	if (inputTypeRadioList.checked == true)
+	{
+		inputDiv.style.display = "inline";
+
+// 		if (hyperlinkDiv && (hyperlinkDiv.style.display == "inline"))
+
+		if (hyperlinkDiv)
+			hyperlinkDiv.style.display = "none";
+
+// 		if (multipleDiv && (multipleDiv.style.display == "none"))
+
+		if (multipleDiv)
+		{
+			if (!noMult)
+				multipleDiv.style.display = "inline";
+			else
+				multipleDiv.style.display = "none";
+		}
+
+		// May 11, 2010
+		if (otherDiv)
+			otherDiv.style.display = "inline";
+	}
+	else
+	{
+		inputDiv.style.display = "none";
+
+		if (hyperlinkDiv)
+		{
+			if (!noHL)
+				hyperlinkDiv.style.display = "inline";
+			else
+				hyperlinkDiv.style.display = "none";
+		}
+
+		if (multipleDiv)
+			multipleDiv.style.display = "none";
+
+		if (otherDiv)
+			otherDiv.style.display = "none";
+	}
+}
+
+
+// Aug. 4/09
+function clearAllPropertyValues()
+{
+	var selectLists = document.getElementsByTagName("SELECT");
+
+	for (i = 0; i < selectLists.length; i++)
+	{
+		tmpInput = selectLists[i];
+
+		if (tmpInput.style.display != "none")
+		{
+			clearAllElements(tmpInput.id);
+		}
+	}
+}
+
+
+function verifyCellLineCreation()
+{
+	return verifyBlankTextInput('CellLine_Name_prop', "Please provide a Name for the new Cell Line") && verifyDropdown('CellLine_Status_prop', "Please select a Status value from the dropdown list") && verifyDropdown('4_Project ID_prop', "Please select a Project ID from the dropdown list");
+}
+
+
+// Dec. 22/09: can I use a one-function-fits-all approach instead of 20 functions w/ different names that do the same thing??
+function verifyDropdown(listID, errorMsg)
+{
+	var ddList = document.getElementById(listID);
+
+	if (ddList.selectedIndex == 0)
+	{
+		alert(errorMsg);
+		ddList.focus();
+		return false;
+	}
+	else if ((ddList[ddList.selectedIndex].value == "") || (ddList[ddList.selectedIndex].value.toLowerCase() == 'default'))
+	{
+		alert(errorMsg);
+		ddList.focus();
+		return false;
+	}
+	else
+	{
+		return true;
+	}
+}
+
+
+function verifyBlankTextInput(textID, errorMsg)
+{
+	var textField = document.getElementById(textID);
+
+	if (!textField.value)
+	{
+		alert(errorMsg);
+		textField.focus();
+		return false;
+	}
+	else if (textField.value.length == 0)
+	{
+		alert(errorMsg);
+		textField.focus();
+		return false;
+	}
+	else
+	{
+		return true;
+	}
+}
+
+
+function selectAllPropertyValues(includeDisabled)
+{
+// 	var newPropNames = document.getElementsByName("newPropName");
+	var selectLists = document.getElementsByTagName("SELECT");
+
+// alert(selectLists.length);
+
+// // debug
+// for (t=0; t < selectLists.length; t++)
+// {
+// 	alert(selectLists[t].name);
+// 	alert(selectLists[t].id);
+// }
+
+	var i;
+
+	for (i = 0; i < selectLists.length; i++)
+	{
+		tmpInput = selectLists[i];
+
+	if (tmpInput)
+	{
+		if (tmpInput.style.display != "none")
+		{
+// 		tmpPropAlias = newPropNames[i].value;
+// 		tmpListID = "propertyValuesInputList_" + tmpPropAlias;
+// 		tmpList = document.getElementById(tmpListID);
+
+// 		alert(tmpInput.name);
+
+		// April 19, 2010: think this is also for select-multiples only
+		if (tmpInput.multiple)
+		{
+			for (ind=0; ind < tmpInput.options.length; ind++)
+			{
+				tmpInput.options[ind].selected = true;
+			}
+		}
+// 		if (tmpList && (tmpList.style.display != "none"))
+// 			selectAllElements(tmpListID);
+// 			selectAllElements(tmpInput.id, includeDisabled);
+		}
+	}
+	}
+}
+
+function showTooltip(ttID)
+{
+	document.getElementById(ttID).style.display='block';
+}
+
+function hideTooltip(ttID)
+{
+	document.getElementById(ttID).style.display='none';
+}
+
+// Sept. 9, 2010: moved here from searchFunctions.php
+function checkOutputType()
+{
+	searchBoxElem = document.getElementById("search_by");
+	showSearchElem = document.getElementById("show_search");
+	showProteinElem = document.getElementById("show_protein");
+	showDNAElem = document.getElementById("show_dna");
+	searchTermElem = document.getElementById("search_term_id");
+
+	var myindex  = searchBoxElem.selectedIndex
+	var selValue = searchBoxElem.options[myindex].value
+
+	if (selValue == "protein sequence")
+	{
+		showProteinElem.style.display="inline";
+		showSearchElem.style.display="none";
+		showDNAElem.style.display="none";
+	}
+	else if (selValue == "sequence")
+	{
+		showDNAElem.style.display="inline";
+		showSearchElem.style.display="none";
+		showProteinElem.style.display="none";
+	}
+	else
+	{
+		showSearchElem.style.display="inline";
+		showProteinElem.style.display="none";
+		showDNAElem.style.display="none";
+	}
+
+	searchTermElem.focus();
+}
+
+
+// May 27, 2011: Enable selection of entire rows/columns on a plate (written to address Nature Methods reviewers' comments)
+function selectPlateColumn(plateID, colNum)
+{
+	var allInput = document.getElementsByTagName("INPUT");
+	var	allCBs = Array();
+
+	for (i=0; i < allInput.length; i++)
+	{
+		tmpInput = allInput[i];		
+
+		if (tmpInput.type == "checkbox")
+		{
+			allCBs.push(tmpInput);
+		}
+	}
+
+	var colCBs = Array();
+
+	for (j=0; j < allCBs.length; j++)
+	{
+		tmpCB = allCBs[j];
+
+		if ((tmpCB.id.indexOf("plate_" + plateID) == 0) && (tmpCB.id.lastIndexOf("_Col_" + colNum) + ("_Col_" + colNum).length == tmpCB.id.length) && (!tmpCB.disabled))
+		{
+			colCBs.push(tmpCB);
+		}
+	}
+
+	// Now: It may be that some cells are already checked, and user wants to either check or uncheck by clicking column heading - the key is to do the action on ALL column cells
+	var numChecked = 0;
+	var numUnchecked = 0;
+
+	for (k=0; k < colCBs.length; k++)
+	{
+		if (colCBs[k].checked)
+			numChecked++;
+		else
+			numUnchecked++;
+	}
+
+	// Deselect all IFF all are checked; select all otherwise
+	var uncheckAll = false;
+	var checkAll = false;
+
+	if (numChecked == colCBs.length)
+	{
+		// all cells are checked, uncheck
+		uncheckAll = true;
+
+		for (k=0; k < colCBs.length; k++)
+		{
+			colCBs[k].checked = false;
+					
+			// Now: For empty wells, parent element is TD; BUT for occupied ones the parent is DIV
+			parentElement = colCBs[k].parentNode;
+
+			if (parentElement.tagName == "TD")
+			{
+				tdParent = parentElement;
+
+				if ((tdParent.id.indexOf("well_plate_" + plateID) == 0) && tdParent.id.lastIndexOf("_Col_" + colNum) + ("_Col_" + colNum).length == tdParent.id.length)
+					tdParent.style.backgroundColor = "white";
+			}
+			else if (parentElement.tagName == "DIV")
+			{
+				// go one more level up
+				divParent = parentElement;
+				tdParent = divParent.parentNode;
+	
+				if ((tdParent.id.indexOf("well_plate_" + plateID) == 0) && tdParent.id.lastIndexOf("_Col_" + colNum) + ("_Col_" + colNum).length == tdParent.id.length)
+					tdParent.style.backgroundColor = "white";
+			}
+		}
+	}
+	else
+	{
+		// some are unchecked; therefore, check entire column
+		checkAll = true;
+
+		for (k=0; k < colCBs.length; k++)
+		{
+			colCBs[k].checked = true;
+
+			// colour well			
+			parentElement = colCBs[k].parentNode;
+
+			if (parentElement.tagName == "TD")
+			{
+				tdParent = parentElement;
+
+				if ((tdParent.id.indexOf("well_plate_" + plateID) == 0) && tdParent.id.lastIndexOf("_Col_" + colNum) + ("_Col_" + colNum).length == tdParent.id.length)
+					tdParent.style.backgroundColor = "yellow";
+			}
+			else if (parentElement.tagName == "DIV")
+			{
+				// go one more level up
+				divParent = parentElement;
+				tdParent = divParent.parentNode;
+			
+				if ((tdParent.id.indexOf("well_plate_" + plateID) == 0) && tdParent.id.lastIndexOf("_Col_" + colNum) + ("_Col_" + colNum).length == tdParent.id.length)
+					tdParent.style.backgroundColor = "yellow";
+			}
+		}
+	}
+/*
+	// Colour the entire well
+	var allTDs = document.getElementsByTagName("TD");
+
+	for (n = 0; n < allTDs.length; n++)
+	{
+		tmpTD = allTDs[n];
+
+		if ((tmpTD.id.indexOf("well_plate_" + plateID) == 0) && tmpTD.id.lastIndexOf("_Col_" + colNum) + ("_Col_" + colNum).length == tmpTD.id.length)
+		{
+			if (checkAll)
+			{
+				tmpTD.style.backgroundColor = "yellow";
+			}
+
+			else 
+				tmpTD.style.backgroundColor = "#FFFFFF";
+		}
+	}
+	*/
+}
+
+function selectPlateRow(plateID, rowNum)
+{
+	//alert(rowNum);
+
+	var allInput = document.getElementsByTagName("INPUT");
+	var	allCBs = Array();
+	
+	for (i=0; i < allInput.length; i++)
+	{
+		tmpInput = allInput[i];		
+
+		if (tmpInput.type == "checkbox")
+		{
+			allCBs.push(tmpInput);
+		}
+	}
+
+	var rowCBs = Array();
+
+	for (j=0; j < allCBs.length; j++)
+	{
+		tmpCB = allCBs[j];
+		
+	//	alert(tmpCB.id);
+
+		if ((tmpCB.id.indexOf("plate_" + plateID) == 0) && (tmpCB.id.indexOf("_Row_" + rowNum + "_Col_") > 0) && (!tmpCB.disabled))
+		{
+			rowCBs.push(tmpCB);
+		}
+	}
+
+	// Now: It may be that some cells are already checked, and user wants to either check or uncheck by clicking row heading - the key is to do the action on ALL row cells
+	var numChecked = 0;
+	var numUnchecked = 0;
+
+	for (k=0; k < rowCBs.length; k++)
+	{
+		if (rowCBs[k].checked)
+		{
+			numChecked++;
+		}
+		else
+			numUnchecked++;
+	}
+	
+	// Deselect all IFF all are checked; select all otherwise
+	var uncheckAll = false;
+	var checkAll = false;
+
+	if (numChecked == rowCBs.length)
+	{
+		// all cells are checked, uncheck
+		uncheckAll = true;
+
+		for (k=0; k < rowCBs.length; k++)
+		{
+			rowCBs[k].checked = false;
+						
+			// Now: For empty wells, parent element is TD; BUT for occupied ones the parent is DIV
+			parentElement = rowCBs[k].parentNode;
+
+			if (parentElement.tagName == "TD")
+			{
+				tdParent = parentElement;
+
+				if ((tdParent.id.indexOf("well_plate_" + plateID) == 0) && (tdParent.id.indexOf("_Row_" + rowNum) == ("well_plate_" + plateID).length))
+					tdParent.style.backgroundColor = "white";
+			}
+			else if (parentElement.tagName == "DIV")
+			{
+				// go one more level up
+				divParent = parentElement;
+				tdParent = divParent.parentNode;
+	
+				if ((tdParent.id.indexOf("well_plate_" + plateID) == 0) && (tdParent.id.indexOf("_Row_" + rowNum) == ("well_plate_" + plateID).length))
+					tdParent.style.backgroundColor = "white";			
+			}
+		}
+	}
+	else
+	{
+		// some are unchecked; therefore, check entire row
+		checkAll = true;
+
+		for (k=0; k < rowCBs.length; k++)
+		{
+			rowCBs[k].checked = true;
+			
+			// Now: For empty wells, parent element is TD; BUT for occupied ones the parent is DIV
+			parentElement = rowCBs[k].parentNode;
+
+			if (parentElement.tagName == "TD")
+			{
+				tdParent = parentElement;
+
+				if ((tdParent.id.indexOf("well_plate_" + plateID) == 0) && (tdParent.id.indexOf("_Row_" + rowNum) == ("well_plate_" + plateID).length))
+					tdParent.style.backgroundColor = "yellow";				
+			}
+			else if (parentElement.tagName == "DIV")
+			{
+				// go one more level up
+				divParent = parentElement;
+				tdParent = divParent.parentNode;
+				
+				if ((tdParent.id.indexOf("well_plate_" + plateID) == 0) && (tdParent.id.indexOf("_Row_" + rowNum) == ("well_plate_" + plateID).length))
+					tdParent.style.backgroundColor = "yellow";
+			}
+		}
+	}
+
+/*
+	// Colour the entire well
+	var allTDs = document.getElementsByTagName("TD");
+
+	for (n = 0; n < allTDs.length; n++)
+	{
+		tmpTD = allTDs[n];
+
+		if ((tmpTD.id.indexOf("well_plate_" + plateID) == 0) && (tmpTD.id.indexOf("_Row_" + rowNum) == ("well_plate_" + plateID).length))
+		{
+			if (checkAll)
+				tmpTD.style.backgroundColor = "yellow";
+
+			else 
+			{
+				tmpTD.style.backgroundColor = "#FFFFFF";
+			}
+		}
+	}
+	*/
+}
+
+/*
+function selectColumn(pname)
+{
+	aCol = document.getElementsByName(pname + "_td[]");
+
+	for (a=0; a < aCol.length; a++)
+	{
+		aTD = aCol[a];
+		aTD.style.backgroundColor = "yellow";
+	}
+}*/
+
+
+// June 3, 2011: VERY IMPORTANT - batch update an attribute column value for all selected wells
+function popupWellAttrUpdateForm(propName)
+{
+	if (propName == 'OpenFreezer ID')
+		var tdnodes = document.getElementsByName("limsID_td[]");
+
+	else if (propName == 'Isolate Number')
+		var tdnodes = document.getElementsByName("isoNum_td[]");
+	
+	else
+		var tdnodes = document.getElementsByName(propName + "_td[]");
+
+	if (tdnodes && (tdnodes.length > 0))
+	{
+		var attrVal = prompt(propName + ": ", "");
+
+		for (i = 0; i < tdnodes.length; i++)
+		{
+			tdnode = tdnodes[i];
+
+			txtfield = tdnode.children[0];
+
+			// In FF4, pressing 'Cancel' returns null
+			if (attrVal != null)
+			{
+				txtfield.value = attrVal;
+			}
+		}	
+		
+	}
+}
+
+
+function updateWellAttribute(propName, contID)
+{
+	//alert(propName);
+	//alert(propID);
+	//alert(contID);
+
+	if (propName != "default")
+	{
+		var attrVal = prompt(propName + ": ", "");
+		
+		if (attrVal != null)
+		{
+			// let's try AJAX
+			var allWellsCB = document.getElementsByName("wells_checkbox[]");
+			var checkedWells = new Array();
+
+			for (i=0; i < allWellsCB.length; i++)
+			{		
+				if (allWellsCB[i].checked)
+				{
+					checkedWells.push(allWellsCB[i].value);
+				}
+			}
+
+			wells = checkedWells.join(",");
+
+			url = cgiPath + "location_request_handler.py";
+
+			xmlhttp = createXML();
+			xmlhttp.open("POST", url, false);
+			xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
+
+			xmlhttp.send('update_attribute=1&contID=' + contID + "&propName=" + propName + "&propVal=" + attrVal + "&wells=" + wells);
+
+			xmlhttp.onreadystatechange = printUpdatedPlate(xmlhttp, contID);			
+		}
+	}
+}
+
+function printUpdatedPlate(xmlhttp, contID)
+{
+	//alert(xmlhttp.readyState);
+
+	if (xmlhttp.readyState == 4)
+	{
+		if (xmlhttp.status == 200)
+		{
+ 			//prompt("", xmlhttp.responseText);
+			document.getElementById("changeAttributeSelect").selectedIndex = 0;
+			window.location.href = hostName + "Location.php?View=2&Mod=" + contID;
+		}
+	}
+}
+
+
+function checkUncheckAllIsolates()
+{
+	var allInput = document.getElementsByTagName("INPUT");
+	var	allCBs = Array();
+	var numChecked = 0;
+	
+	for (i=0; i < allInput.length; i++)
+	{
+		tmpInput = allInput[i];		
+
+		if (tmpInput.type == "checkbox")
+		{
+			// on modification the name is well_mod_beingUsed<key>_checkbox; on creation it is simply well_beingUsed_checkbox
+			if ((tmpInput.name.indexOf("beingUsed") > 0) && (tmpInput.name.lastIndexOf("_checkbox") + "_checkbox".length == tmpInput.name.length))
+			{
+				allCBs.push(tmpInput);
+
+				if (tmpInput.checked)
+				{
+					numChecked++;
+				}
+			}
+		}
+	}
+
+	if (numChecked == allCBs.length)
+	{
+		// all checked, uncheck
+		for (i=0; i < allCBs.length; i++)
+		{
+			allCBs[i].checked = false;
+		}
+	}
+	else
+	{
+		// some are not checked, check all
+		for (i=0; i < allCBs.length; i++)
+		{
+			allCBs[i].checked = true;
+		}	
+	}
+}
+
+
+function checkUncheckAllFlags()
+{
+	var allInput = document.getElementsByTagName("INPUT");
+	var	allCBs = Array();
+	var numChecked = 0;
+	
+	for (i=0; i < allInput.length; i++)
+	{
+		tmpInput = allInput[i];		
+
+		if (tmpInput.type == "checkbox")
+		{
+			// on modification the name is well_mod_flag<key>_checkbox; on creation it is simply well_flag_checkbox
+			if ((tmpInput.name.indexOf("flag") > 0) && (tmpInput.name.lastIndexOf("_checkbox") + "_checkbox".length == tmpInput.name.length))
+			{
+				allCBs.push(tmpInput);
+
+				if (tmpInput.checked)
+				{
+					numChecked++;
+				}
+			}
+		}
+	}
+
+	if (numChecked == allCBs.length)
+	{
+		// all checked, uncheck
+		for (i=0; i < allCBs.length; i++)
+		{
+			allCBs[i].checked = false;
+		}
+	}
+	else
+	{
+		// some are not checked, check all
+		for (i=0; i < allCBs.length; i++)
+		{
+			allCBs[i].checked = true;
+		}	
+	}
+}
+
+
+function showSafetySearchForm()
+{
+	var chemSearchList = document.getElementById("search_criteria_list");
+	var selInd = chemSearchList.selectedIndex;
+	var chemSearchCriterion = chemSearchList[selInd];
+	var chem_search_caption = document.getElementById("chem_search_caption");
+
+	if (chemSearchCriterion.text == "Safety")
+	{
+		document.getElementById("safety_search").style.display = "inline";
+		document.getElementById("chemical_locations").style.display = "none";
+		document.getElementById("chem_search_keyword").style.display = "none";
+		
+		chem_search_caption.innerHTML = "Safety:";
+	}
+	else
+	{
+		document.getElementById("safety_search").style.display = "none";
+	}
+}
diff --git a/OpenFreezer/search.php b/OpenFreezer/search.php
new file mode 100755
index 0000000..8d52b85
--- /dev/null
+++ b/OpenFreezer/search.php
@@ -0,0 +1,244 @@
+<?php
+/**
+* Search page
+*
+* PHP versions 4 and 5
+*
+* Copyright (c) 2005-2011 Mount Sinai Hospital, Toronto, Ontario
+*
+* LICENSE:
+*
+* OpenFreezer is free software; you can redistribute it
+* and/or modify it under the terms of the GNU General
+* Public License as published by the Free Software Foundation;
+* either version 3 of the License, or (at your option) any
+* later version.
+*
+* OpenFreezer is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* General Public License for more details.
+*
+* You should have received a copy of the GNU General Public
+* License along with OpenFreezer.  If not, see <http://www.gnu.org/licenses/>.
+*
+* @author John Paul Lee @version 2005
+*
+* @author     Marina Olhovsky <olhosvky at lunenfeld.ca>
+* @version    3.1
+* @package Search
+*
+* @copyright  2005-2011 Mount Sinai Hospital, Toronto, Ontario
+* @license    http://www.opensource.org/licenses/gpl-3.0.html GNU GPLv3
+*/
+
+/**
+* Include/require statements
+*/
+	include "Classes/MemberLogin_Class.php";
+	include "Classes/Member_Class.php";
+	include "Classes/Session_Var_Class.php";
+	include "Classes/generalFunc_Class.php";
+	include "DatabaseConn.php";
+	
+	session_start();
+	
+	$loginBlock = new MemberLogin_Class( );  
+	$loginBlock->loginCheck( $_POST );
+	
+	header("Cache-control: private"); //IE 6 Fix 
+
+	include "HeaderFunctions.php";
+	include "Project/ProjectFunctions.php";		# july 16/07 - needs to be declared before searchFunctions b/c it's used there
+	
+	include "Search/searchFunctions.php";
+	include "Search/searchOutput_reagent.php";
+	
+	include "Classes/StopWatch.php";
+	include "Classes/ColFunctOutputer.php";
+	
+	include "Reagent/Reagent_Function_Class.php";
+	include "Reagent/Reagent_Background_Class.php";
+
+	include "Location/Location_Output_Class.php";	// Feb. 16/10 - want to be able to check preps and disable Delete checkbox
+	include "Location/Location_Funct_Class.php";    // April 27, 2011 
+
+	outputMainHeader();
+	
+	global $Const_Table_Width;
+
+	?>
+	<!--<table width=<?php /*echo $Const_Table_Width; */?> border=0 class=nav>
+		<tr>	
+			<td>
+				<?php
+// 					outputNavBar();
+			
+				?>
+			</td>
+		</tr>
+	</table>-->
+
+	<table height="100%">
+		<table border="0" width="750px">
+		<?php
+		
+		if (isset($_SESSION["userinfo"]))
+		{
+			if ($loginBlock->verifyPermissions( basename( $_SERVER['PHP_SELF'] ), $_SESSION['userinfo']->getUserID( ) ) ) 
+			{
+				$sessionChecker = new Session_Var_Class();
+				$sessionChecker->checkSession_all();
+				unset( $sessionChecker );
+				?>	
+				<tr>
+					<?php
+					if( isset( $_GET["View"]  ) )
+					{
+						outputSubMenu($_GET["View"]);	// common to all, default
+					}
+					?>
+				</tr>
+
+				<tr>
+					<td>
+					<?php
+						if ($_GET["View"] == "1")
+						{
+							if (isset($_POST["SearchArea"]) && isset($_POST["Keyword"]))
+							{
+								$searchCategory = $_POST["SearchArea"];
+								$keyword = trim($_POST["Keyword"]);
+								$_SESSION["modifying_view"] = "False";
+								
+								$clockers = new StopWatch;
+								$clockers->startStopWatch();
+
+								$numHits = searchOutputResults($searchCategory, $keyword);	// update June 5/09
+
+								$clockers->stopStopWatch();
+								$clockers->printStopWatch_verbose();
+								unset( $clockers );
+	
+// print "category " . $_SESSION["userinfo"]->getCategory();
+								// moved here March 19/10 from searchOutput_reagent.php
+								echo "<BR><P>Number of hits: " . $numHits . "<BR>";
+
+								// June 5/09
+								if ($numHits > 0)
+								{
+									$currUserName = $_SESSION["userinfo"]->getDescription();
+									
+									if ($_SESSION["userinfo"]->getCategory() != $_SESSION["userCategoryNames"]['Reader'])
+									{
+										?><P><INPUT TYPE="BUTTON" onClick="deleteReagentsFromSearch('ReagentCheckBox');" VALUE="Delete Selected Reagents"><BR><?php
+									}
+// 									else
+// 									{
+										?>
+<!-- <P><INPUT TYPE="BUTTON" DISABLED VALUE="Delete Selected Reagents"><BR> -->
+<?php
+// 									}
+								}
+							}
+							else if (isset($_GET["SearchArea"]) && isset($_GET["Keyword"]))
+							{
+								// Added April 11/07: Allowing to link to search results from outside LIMS (particularly from MS Map)
+								// Can only be done through GET method - incorporating here at Adrian's request
+								// Requires exact search term match
+								$searchCategory = trim($_GET["SearchArea"]);
+								$keyword = trim($_GET["Keyword"]);
+
+								$_SESSION["modifying_view"] = "False";
+							
+								$clockers = new StopWatch;
+								$clockers->startStopWatch();
+// 11/04/07							searchOutputResults();		// in searchOutput_reagent.php
+								$numHits = searchOutputResults($searchCategory, $keyword);	// update June 5/09
+								$clockers->stopStopWatch();
+								$clockers->printStopWatch_verbose();
+								unset( $clockers );
+
+								// June 5/09
+								if ($numHits > 0)
+								{
+									$currUserName = $_SESSION["userinfo"]->getDescription();
+								
+									if ($currUserName == 'Administrator')
+									{
+										?><P><INPUT TYPE="BUTTON" onClick="deleteReagentsFromSearch('ReagentCheckBox');" VALUE="Delete Selected Reagents"><BR><?php
+									}
+								}
+							}
+						}
+						elseif( $_GET["View"] == "2" )
+						{
+							if( !isset( $_SESSION["modifying_view"] ) )
+							{
+								$_SESSION["modifying_view"] = "False";
+							}
+							
+							if( isset( $_POST["change_state"] ) )
+							{
+								if( $_POST["change_state"] == "Modify" )
+								{
+									$_SESSION["modifying_view"] = "True";
+								}
+								elseif( $_POST["change_state"] == "Save" )
+								{
+									$_SESSION["modifying_view"] = "False";
+
+									if (isset($_POST["reagentChanges"]) && isset($_SESSION["oldvalues_view"]))
+									{
+										submit_changes( $_POST["reagentChanges"], $_SESSION["oldvalues_view"], $_GET["rid"] );
+									}	
+								}
+							}
+	
+							$clockers = new StopWatch;
+							$clockers->startStopWatch();
+							outputDetailedView_main( $_GET["rid"] );
+							$clockers->stopStopWatch();
+							$clockers->printStopWatch_verbose();
+							
+							unset( $clockers );
+						}
+						?>
+					</td>
+				</tr>
+			</table>
+			<?php
+		
+// 			outputMainFooter();
+		}
+		else
+		{
+			/* May 30/07, Marina
+			echo "<tr><td>";
+			echo "Restricted Access! Please log in!";
+			echo "</td></tr>";
+			*/
+			
+			// May 30/07, Marina
+			echo "<tr><td class=\"warning\">";
+			echo "You are not authorized to view this page.  Please contact the site administrator.";
+			echo "</td></tr>";
+
+			?></table><?php
+// 			outputMainFooter();
+		}
+	}
+	else
+	{
+		echo "<tr><td class=\"warning\">";
+		echo "Please log in to access this page.";
+		echo "</td></tr>";
+		?></TABLE><?php
+		mysql_close($conn);
+	}
+	?>
+		</table>
+	</table>
+<?php
+	outputMainFooter();
+?>
diff --git a/OpenFreezer/styles/Header_styles.css b/OpenFreezer/styles/Header_styles.css
new file mode 100755
index 0000000..0fff086
--- /dev/null
+++ b/OpenFreezer/styles/Header_styles.css
@@ -0,0 +1,785 @@
+	html,body
+	{
+/* Apr. 8/09 - don't know if this is needed		height:100%; */
+	}
+
+	body.cursor_wait
+	{
+		cursor:wait;
+	}
+
+	body.cursor_auto
+	{
+		cursor:auto;
+	}
+
+	.title, h2, h1 	{ font: 16px Arial; font-weight: bold }
+	.sidebar {
+	font-family: Georgia, "Times New Roman", Times, serif;
+	font-size: 14px;
+	font-weight:bolder;
+	line-height: 18px;
+	padding: 3px;
+	background-color: #FFFF99;
+	}
+	table.navHeader { color: #FFFFFF; font: 10px Verdana; font-weight: bold; text-decoration: none  }
+	
+	td.navHeader { color: #FFFFFF; font: 10px Verdana; font-weight: bold; text-decoration: none }
+
+	td.nav 	{ color: #FFFFFF; font: 9px Verdana; font-weight: bold; text-decoration: none }
+
+	/* April 3/07, Marina => Removed June 10/08, replaced by 2 divs below */
+	div.header
+	{
+		font-weight:bold;
+		text-align: left;
+		font-variant:small-caps;
+		font-family: Helvetica, sans-serif;
+		font-size:12pt;
+/* 		width: 986px; */
+		width: 100%;
+
+		/* Replaced March 12/09 */
+		height: 85px;
+	}
+
+	table.detailedView_tbl
+	{
+		background-color: #FFFFE5;
+	}
+	
+	table.header
+	{
+		width: 100%;
+		/*background-color: black;*/
+		/*background: url("../pictures/background.png") repeat;*/
+		/*border-bottom: 2px solid black;*/
+	}
+	
+	option.menu_subcat_default
+	{
+/* 		background-image:url('../pictures/goldbg.png'); */	/* no, works only in FF and even then not 100% */
+/* 		background-position:relative; */
+
+		background-color:#FFF8DC;
+		padding-left:7px;
+		font-weight:bold;
+		color:#555;
+		font-size:8pt;
+	
+		border-top:1px solid gold;
+		border-bottom:1px solid gold;
+
+		text-decoration:none;
+	
+		margin-left:2px;
+		padding-top:3px;
+		padding-bottom:3px;
+	}
+	
+/*	option.menu_subcat_default:hover
+	{
+		background:url('');
+	}*/
+	
+	option.menu_sub_default
+	{
+		background-color:#EFEFEF;
+
+		border-top: 1px solid silver;
+		border-bottom: 1px solid silver;
+
+		padding-left:10px;
+		font-weight:bold;
+		color:#555;
+		padding-top:2px;
+		padding-bottom:2px;
+		font-size:8pt;
+/* 		background:url('../pictures/graybg.png'); */	/* no, works only in FF and even then not 100% */
+		margin-top:3px;
+		margin-bottom:3px;
+		margin-left:3px;
+	}
+	
+/*	option.menu_sub_default:hover
+	{
+		background:url('');
+	}*/
+
+	td.header
+	{
+		font-family: Helvetica, sans-serif;
+		font-variant: small-caps;
+		font-size:x-large;
+		width: 100%;
+		height: 40px;
+		vertical-align: bottom;
+		background: url("../pictures/background.png");
+	}
+	
+	td.logo
+	{
+		padding-left:12px;
+		text-align:left;
+		width: 80px;
+	}
+
+	div.caption
+	{
+		font-size:7pt;
+		padding-top: 2px;
+		white-space: nowrap;
+		font-family: Helvetica, sans-serif;
+	}
+	
+	div.subtitle
+	{
+		font-size: large;
+		text-align: center;
+	}
+
+	sup.title
+	{
+		font-size:x-small;
+	}
+
+	div.notice
+	{
+		font-size: 10pt;
+		font-family: Helvetica, sans-serif;
+/* 		text-align: center; */
+		background-color:#EEDFA1;
+		font-weight:bold;
+		padding-top:2px;
+		padding-bottom: 2px;
+		vertical-align: middle;
+		margin-top:0.5em;
+		width:100%;
+
+		/*margin-left: 10px;
+		margin-right: 10px;*/
+	}
+
+	div.footer_container
+	{
+		padding-bottom:6px;
+/* 		width:986px; */
+		width:100%;
+	}
+
+	div.footer
+	{
+		margin-top:0.3cm;
+/* 		position:absolute; */		/* NO!!!!!  This does not stretch bottom to the entire page width */
+		padding-top:0.5em;		/* update Sept. 10, 2010 */
+		padding-bottom:0.3em;	/* update Sept. 10, 2010, changed 0.5 to 0.3 */
+		text-transform: uppercase;
+		font-family: Helvetica, sans-serif;
+		font-size:8pt;	/* update Sept. 10, 2010 */
+		clear:none;
+		text-align: center;
+		font-weight: bold;
+		background-color: #FCE074;
+
+		/* line-height:125%;*/   /* keep, determines footer stripe width */
+	}
+
+	p.notice
+	{
+		font-size:8pt;
+		font-family: Helvetica;
+		font-weight:normal;
+		color: #FF0000;
+	}
+	
+	div.warning
+	{
+		font-size:8pt;
+		font-family: Helvetica;
+		font-weight:normal;
+		color: #FF0000;
+		display: none;
+	}
+	
+
+	a.header
+	{
+		color: #0000FF;
+		text-decoration: underline;
+	}
+	
+	a.header:hover
+	{
+		color: #00AE00;
+	}
+	
+	a.footer
+	{
+		font-weight: normal;
+		font-size: 8pt;
+		text-transform: none;
+		color: #0000FF;
+		text-decoration: underline;
+	}
+	
+	a.footer:hover
+	{
+		color: #00AE00;
+	}
+
+	a.menu
+	{
+		font-size:9pt;
+	}
+
+	/* July 19, 2010 */
+	ul.menu
+	{
+		margin: 0;
+		padding: 0;
+		list-style: none;
+		white-space:nowrap;
+		width: 150px;
+		z-index:2;
+	}
+
+	ul.menu li
+	{
+		position: relative;
+		margin-left:0;
+		padding-left:0;
+		list-style: none;
+		white-space:nowrap;
+		width: 150px;
+		z-index:3;
+	}
+
+	ul.menu li ul
+	{
+		list-style: none;
+		position: relative;
+		left:0;
+		z-index:1;
+		width: 150px;
+		padding:0;
+		padding-bottom:5px;
+		white-space:nowrap;
+		top: 0;
+		display: none;
+		z-index:4;
+	}
+
+	a.top_title
+	{
+		white-space:nowrap;
+		display: block;	/* keep this, don't change to 'inline'!! */
+		text-decoration: none;
+		color: #777;
+		background:url('../pictures/background-gray.png');
+		padding: 5px;
+		border: 1px solid #ccc;
+		font-size:9pt;
+		z-index:5;
+	}
+
+	table.top_2
+	{
+		white-space:nowrap;
+		background-color:white;
+		z-index:6;
+	}
+
+	li.top:hover ul
+	{
+		white-space:nowrap;
+		display: inline;
+		z-index:7;
+	}
+
+	li.top_1:hover ul
+	{
+		white-space:nowrap;
+		display: inline;
+		padding-top:5px;
+		z-index:8;
+	}
+
+	/* Sept. 10, 2010: Try for a tabbed layout - will be of use */
+	div.topmenu
+	{
+ 		position:relative;
+/* 		padding-top:10px; */
+	}
+
+	td.topmenulink:hover
+	{
+		cursor:pointer;
+	}
+
+	
+	td.topmenulink_docs:hover
+	{
+		cursor:pointer;
+	}
+
+	div.sidemenu
+	{
+ 		position:absolute;
+		text-align: left;
+		min-height:500mm;
+		height:100%;
+		width:auto;
+		padding-bottom:18px;
+	}
+	
+	div.menu-content
+	{
+/* 	 	border: 2px groove #EEDFA1; */
+
+		min-height:500mm;
+		height:100%; 
+
+		/* the following 2 statements are for the border */
+/* 		margin-top:5px; */
+/* 		padding-right:10px; */
+
+		/* move footer down */
+		padding-bottom:4px;
+
+		position:relative;
+		float:left;
+		margin-left: 2px;
+/* 		margin-right: 0.5em; */
+		vertical-align:top;
+  	}
+	
+	div.login
+	{
+		height:auto;
+		margin-left: 0.1em;
+		margin-right: 0.5em;
+		color:black;
+		margin-top:10px;
+		padding-top: 3px;
+  	}
+
+	div.main
+	{
+		margin-top:8px;
+		margin-left:2px;
+		width:100%;
+/* 		padding-top:3px; */
+
+		/* April 8/09: This is the only way to prevent content-footer overlap.  Keep min-height and nothing else!!!!!!!!!!!!!!!! */
+		min-height:500mm;
+
+
+/* Removed April 8/09 */
+/* 		height:100%; */
+/* 		height:500mm; */
+/* 		height:auto; */		/* don't EVER use this!!!!!!!!  This prevents the menu border line from stretching down to the entire page height */
+/* 		min-height:100%; */	/* don't use this either!!!!!!!! This does not place the footer at the bottom of the page */
+	}
+
+	div.main_content
+	{
+		background:white;
+		position:relative;
+
+		/* April 8/09: This is the only way to prevent content-footer overlap.  Keep min-height and nothing else!!!!!!!!!!!!!!!! */
+		min-height:500mm;
+		width:auto;	/* keep! */
+
+/* Removed April 8/09 */
+/* 		height:100%; */
+/* 		height:auto; */		/* don't EVER use this!!!!!!!! This prevents the menu border line from stretching down to the entire page height */
+/* 		min-height:100%; */	/* don't use this either!!!!!!!!  This does not place the footer at the bottom of the page */
+/* 		min-height:auto; */	/* can use this if needed */
+
+		margin-bottom:0.5em;
+		margin-left:178px;	/* keep this, looks good on laptop */
+
+		border-left:2px groove black;
+		padding-left:15px;
+		vertical-align:top;
+		cursor:auto;	/* keep for later, when div resizeable is added, to override its cursor resize */
+	}
+
+
+	td.submenu
+	{
+	    padding-left:10px;
+	    white-space:nowrap;
+	}
+	
+	a.submenu
+	{
+	    width: auto;
+	    color: #0000FF;
+	    font-variant: normal;
+	    font-weight:normal;
+	    text-decoration:underline;
+	    font-size:9pt;
+	}
+
+	a.submenu:hover
+	{
+	    color:#002053;
+	    font-weight:normal;
+	    white-space: normal;
+	}
+
+	ul.menulist     /* good!! keep */
+	{
+	    list-style: none;
+	    padding-left: 0;
+	}
+
+	
+	li.menulist
+	{
+		padding-bottom: 5px;
+		padding-left:0px;
+		margin-top:3px;
+	    	margin-bottom: 3px;
+		font-size:10pt;
+	}
+
+	img.menu-expanded
+	{
+		vertical-align: middle;
+	}
+
+	img.menu-expanded:hover
+	{
+		cursor:pointer;
+	}
+
+	/* initially start with all menus expanded */
+	img.menu-collapsed
+	{
+		margin-right:-21px;
+		vertical-align: top;
+	}
+
+	img.menu-collapsed:hover
+	{
+		cursor:pointer;
+	}
+
+	ul.submenu
+	{
+		padding-left: 0;
+		padding-top: 2px;
+		list-style: none;
+		display: none;
+	}
+
+	li.submenu
+	{
+		padding-left: 20px;
+		padding-top: 3px;
+		background-repeat: no-repeat;
+		background-position: center left;
+	}
+
+	img.menutop
+	{
+		padding-right: 12px;
+		padding-left: 2px;
+	}
+
+	img.menu-leaf
+	{
+		padding-right: 4px;
+		vertical-align: middle;
+	}
+
+	li.menutop
+	{
+		padding-left: 0px;
+		padding-top: 3px;
+		margin-top:3px;
+		margin-bottom:3px;
+		white-space: nowrap;
+	}
+	
+	
+	span.login
+	{
+		text-align:left; 
+		font-size:9pt; 
+		color:navy;
+/* 		font-weight:bold; */
+	}
+
+
+	/*
+		Feb. 16/08: Location tabbed pane representation - option to view locations grouped by container or by isolate
+	*/
+	td.currentView
+	{
+		padding-top:5px;
+		padding-bottom:5px;
+	}
+
+	td.switchTo
+	{
+		padding-top:5px;
+		padding-bottom:5px;
+	}
+	
+	table.locationContent
+	{
+		width:100%;
+		border:1px solid black;
+	}
+
+	td.locationContent
+	{
+		border:1px solid black;
+		padding-top:10px;
+		padding-left:15px;
+		padding-bottom:15px;
+		background-color:#FFFFF0;
+	}
+
+	span.tabLinkActive
+	{
+		padding-top:5px;
+		padding-bottom:10px;	/* or make identical to tabLinkInactive */
+		padding-left:25px;
+		padding-right:25px;
+		border-top:1px solid black;
+		border-left:1px solid black;
+		border-right:1px solid black;
+		background-color:/*#FFFACD*/#FFFFF0;
+		color:#8B6508;
+		font-weight:bold;
+		cursor:pointer;
+		text-decoration:none;
+		font-size:9pt;
+	}
+
+	span.tabLinkInactive
+	{
+		padding-top:5px;
+		padding-bottom:6px;
+		padding-left:25px;
+		padding-right:25px;
+		border-top:1px solid #000000;
+		border-left:1px solid #000000;
+		border-right:1px solid #000000;
+		cursor:pointer;
+		background-color:#FFFACD;
+		color:#8B6508;
+		text-decoration:none;
+		font-size:9pt;
+		font-weight:bold;
+	}
+
+	span.tabLinkInactive:hover
+	{
+		padding-bottom:6px;
+		color:#000000;
+	}
+
+	span.tabLinkActive:hover
+	{
+		color:#000000;
+	}
+
+
+	/*
+		Feb. 19/08: Sequence tabbed pane representation - very similar to location
+	*/
+	td.sequenceContent
+	{
+/* 		border:1px solid black; */
+		border-top: 1px inset #F08080;
+		border-right: 1px outset #F08080;
+		border-bottom: 1px outset #F08080;
+		border-left:1px inset #F08080;
+ 
+		padding-top:6px;
+		padding-left:6px;
+		padding-right:5px;
+		padding-bottom:15px;
+/* 		background-color:#FFFFF0; */
+		background-color:#FFF8DC; 
+/* padding:6px; */
+	}
+
+	span.seqTabLinkActive
+	{
+		padding-top:5px;
+		padding-bottom:9px;
+		padding-left:25px;
+		padding-right:25px;
+		border-top:1px inset #F08080;
+		border-left:1px inset #F08080;
+		border-right:1px outset #F08080;
+		background-color:#FFF8DC;
+		color:#00008B;
+		font-weight:bold;
+		cursor:pointer;
+		text-decoration:none;
+		font-size:9pt;
+	}
+
+
+	span.seqTabLinkInactive
+	{
+		padding-top:5px;
+		padding-bottom:6px;
+		padding-left:25px;
+		padding-right:25px;
+		border-top:1px inset #F08080;
+		border-left:1px outset #F08080;
+		border-right:1px outset #F08080;
+		cursor:pointer;
+		background-color:#FFF8DC;
+		color:#36648B;
+		text-decoration:none;
+		font-size:9pt;
+		font-weight:bold;
+	}
+
+	span.seqTabLinkInactive:hover
+	{
+/* 		color:#00008B; */
+	}
+
+	div.tabSequence
+	{
+		width:670px;
+		padding-left:10px;
+		padding-right:10px;
+		height:185px;
+		overflow:auto;
+		background-color:#C1FEC1/*#FFFFE2*/;
+		border-top:1px solid #708090;
+		border-left:1px solid #708090;
+	}
+
+	/* Added Jan. 8/09 */
+	div.vectorSequence
+	{
+		width:680px;
+		padding-left:10px;
+		padding-right:10px;
+		height:185px;
+		overflow:auto;
+		background-color:#C1FEC1/*#FFFFE2*/;
+		border-top:1px solid #708090;
+		border-left:1px solid #708090;
+	}
+
+	/* March 4/08, Marina: Added to make sections resizeable */
+	div.resizeableRight
+	{
+		position:absolute;
+		
+		left:16em;
+		height:58em;
+
+		width:2px;
+		margin-top:1.2em;
+		cursor:col-resize;
+/* 		border-right:3px groove black; */
+	}
+
+	td.creation_readonly
+	{
+		background-color:#D1D1D1;
+		white-space:nowrap;
+		padding-right:25px;
+	}
+
+	td.creation_normal
+	{
+		white-space:nowrap;
+		padding-right:25px;
+	}
+
+	input.input_disabled
+	{
+		background-color:#E8E8E8;
+	}
+
+	input.input_normal
+	{
+		background-color:#FFFFFF;
+	}
+
+	/* Tooltip styles - Dec. 21/09 - adapted from http://psacake.com/web/jl.asp */
+	a.tooltip
+	{
+		position:relative; /*this is the key*/
+		z-index:24;
+		color:#0000FF;
+		font-size:10pt;
+		text-decoration:none;
+	}
+
+	span.tt_show
+	{
+		padding: 30px 8px 0;
+		font-weight:bold;
+		font-family:Helvetica;
+		font-size:9pt;
+		text-align:left;
+		padding-left:15px;
+		padding-bottom:18px;
+		padding-top:24px;
+		width:220px;
+		height:85px;
+		position: absolute;
+		right:0;
+		left:0;
+		background: url('../pictures/bubble.gif') no-repeat;
+	}
+
+	/**
+		May 27, 2011: The following four classes were added to enable selection of entire rows/columns on a plate (written to address Nature Methods reviewers' comments)
+	*/
+	td.plateColumn_hdr
+	{
+		text-align:center; 
+		background-color:#0000CD;
+		color:#FFFFFF;
+		font-weight:bold;
+		font-size:11pt;
+		border-left:2px outset lightgrey;
+		border-right:2px outset lightgrey;
+		border-top:1px solid grey;
+		border-bottom:3px outset lightgrey;
+	}
+
+	td.plateColumn_hdr:hover
+	{
+		cursor:pointer;
+	}
+
+	td.plateRow_hdr
+	{
+		text-align:center; 
+		background-color:#0000CD;
+		color:#FFFFFF;
+		font-weight:bold;
+		font-size:11pt;
+		border:1px solid gray;
+		vertical-align:middle;
+		padding-left:4px;
+		padding-right:4px;
+	}
+	
+	td.plateRow_hdr:hover
+	{
+		cursor:pointer;
+	}
+
+	input.locationText
+	{
+		font-size:7.5pt;
+	}
\ No newline at end of file
diff --git a/OpenFreezer/styles/SearchStyle.css b/OpenFreezer/styles/SearchStyle.css
new file mode 100755
index 0000000..53db16a
--- /dev/null
+++ b/OpenFreezer/styles/SearchStyle.css
@@ -0,0 +1,372 @@
+ 	body
+	{
+		font: 13px Arial;
+		/*background: #FFFFFF url("../pictures/page_bg_temp.jpg") repeat-x fixed bottom;*/
+		
+/* 		width:1075px; */
+		width:98%;
+		height: 82%;
+	} 
+	
+	table, td { font: 13px Arial; color: #000000 }
+	div { text-align: justify }
+	
+	body.gradient { font: 13px Arial; background: #FFFFFF url("../pictures/page_bg_temp.jpg") repeat-x fixed bottom }
+	
+	table.preview 
+	{ 
+		font: 8pt Arial; 
+		color: #000000;
+	}
+	
+	table.tableView { font: 8px Arial; }
+	
+	th.searchHeader
+	{
+		font: 10px Helvetica; 
+		text-align:center;
+		font-variant: small-caps;
+		font-weight: bold;
+		white-space: nowrap;
+		background-color: #F5F5DC;
+	}
+	
+	th.searchHeader:hover
+	{
+		cursor:pointer;
+	}
+	
+	
+	a.search
+	{
+		font: 8pt Helvetica; 
+		text-align: left;
+		white-space: nowrap;
+	}
+	
+	td.searchCheckbox
+	{
+		font: 10px Helvetica; 
+		text-align:center;
+		font-variant: small-caps;
+		font-weight: bold;
+		white-space: nowrap;
+		background-color: #F5F5DC;
+	}
+	
+	td.preview 
+	{ 
+		font: 10px Arial; 
+		color: #000000; 
+		text-align:left;
+		background-color:#8CC07A;
+	}
+	
+	
+	th.title
+	{
+		color: #0000FF;
+		font-size: 10pt;
+	}
+
+	td.detailedView { font: 10px Arial; color:#000000; text-align:left; background-color: #8CC07A; border-color:#FFFFFF; border-style:groove; border-width:1px }
+
+	td.navHeader { color: #FFFFFF; font: 10px Verdana; font-weight: bold; text-decoration: none; }
+	td.warning { color:#FF0000; font-family: "Times New Roman", Times, serif; font-weight:bolder;}
+	
+	td.detailedView_colName 
+	{ 
+		font: 11px Arial, Helvetica, sans-serif; 
+		font-weight:bold; 
+		color:#000000; 
+		padding-left:5px; 
+		padding-right:3px; 
+		text-align:left; 
+		border: 1px groove #698B69;
+		background-color:#C1FFC1;
+		white-space:nowrap;
+		width:180px;		/* restored April 28/09 */
+	}
+
+	td.projectDetailedViewName
+	{ 
+		font: 11px Arial, Helvetica, sans-serif; 
+		font-weight:bold; 
+		color:#000000; 
+		padding-left:5px; 
+		padding-right:3px; 
+		text-align:left; 
+		border: 1px groove #698B69;
+		background-color:#C1FFC1;
+		width:100px;
+	}
+
+	th.detailedView_heading
+	{
+		padding:8px;
+		color:#0000CD;
+		vertical-align:middle;
+		font-size:10pt;
+		font-weight:bold; 
+		text-align:center;
+	}
+	
+	td.detailedView_heading
+	{
+		padding:8px;
+		vertical-align:middle;
+		font-size:10pt;
+		font-weight:bold; 
+		text-align:center;
+	}
+
+	td.detailedView_BlankTitle { width:90px; font-weight:bolder; }
+	th.detailedView_BlankTitle { width:90px; font-weight:bolder; color:#0000CD; text-align:left;}
+
+	table.detailedView_buttons
+	{
+		vertical-align: middle;
+		border-style:dashed;
+		border-color: black;
+		text-align: center;
+	}
+
+	td.sequenceView_value 
+	{ 
+		font: 11px Arial, Helvetica, sans-serif; 
+		font-weight:bold; 
+		color:#000000; 
+		text-align:left; 
+		background-color:#98FB98;
+		border-color:#FFFFFF; 
+		border-width:1px; 
+		border-style:inset; 
+		overflow:auto; 
+		vertical-align:middle;
+	}
+
+	td.detailedView_value
+	{
+		font: 11px Arial, Helvetica, sans-serif; 
+		color:#000000; 
+		text-align:left; 
+		font-weight:bold;
+		white-space:nowrap; 
+/* 		width:auto; */
+	}
+	
+	/* Dec. 23/09, Marina: for preloading properties at cell line parent update */
+	td.detailedView_value_load select
+	{
+		color:#0000FF;
+	}
+
+	/* Dec. 23/09, Marina: for preloading properties at cell line parent update */
+	td.detailedView_value_load input
+	{
+		color:#0000FF;
+	}
+
+	table.detailedView_parents
+	{
+		width:600px;
+		padding:5px;
+	}
+
+	table.searchOutput {border-bottom-color:#33FF33; border-style:solid; float:left; }
+
+	.largest 	{ font: 22px Geneva, Arial; font-weight:bold; }
+   	.larger  	{ font: 17px Geneva, Arial; font-weight:bold; }
+   	.large  	{ font: 15px Geneva, Arial; font-weight:bold; }
+   	.normal 	{ font: 13px Geneva,Arial; }
+  	.small  	{ font: 10px Geneva,Arial; }
+  	.small2, .BoldRed 	{ font: 10px Verdana, MS Sans Serif; }
+
+        a   	{ color: rgb(0,0,255); text-decoration: underline; }
+        a:hover { color: #333; }
+
+        a.footer { color: #fff; font: 10px Verdana; font-weight: bold; text-decoration: none; }
+        a.footer:hover	{ color: #fff; text-decoration: underline; }
+
+        a.nav, .nav 	{ color: #FFFFFF; font: 10px Verdana; font-weight: bold; text-decoration: none; }
+        a.nav:hover 	{ color: #EEBB00; text-decoration: underline; }
+
+        a.nav-active 	{ color: #333333; font: 10px Verdana; font-weight: bold; text-decoration: none; }
+        a.nav-active:hover	{ color: #666666; text-decoration: underline; }
+
+        a.invert:hover 	{ color: #FFF; text-decoration: none; }
+
+        .title, h2, h1 	{ font: 16px Arial; font-weight: bold; width:90px; white-space:nowrap;}
+
+
+        /* Added Feb. 2/07 by Marina */
+	div.sequence
+        {
+            	width:770px;
+            	height:180px;
+            	overflow:auto;
+		background-color:#C1FFC1;
+	}
+
+        /* Feb. 12/08, Marina */
+	div.sequence_edit
+        {
+            	width:770px;
+            	height:180px;
+            	overflow:auto;
+		background-color:#FFFFFF;
+	}
+
+        span.linkShow
+        {
+            color:blue;
+            cursor:pointer;
+            text-decoration:underline;
+            display: inline;
+        }
+
+        span.linkHide
+        {
+            color:blue;
+            cursor:pointer;
+            text-decoration:underline;
+            display: none;
+        }
+
+        table.children
+        {
+            padding:5px;
+            text-align: justify;
+        }
+
+
+        tr.children
+        {
+            display: none;
+        }
+
+
+        td.children
+        {
+            display: none;
+        }
+
+        div.children
+        {
+            	width:690px;
+            	height:180px;
+            	overflow:auto;
+            	padding:3px;
+/*          	background: #FFFFFF url("../pictures/yellow_bg.jpg") repeat;*/
+		background-color: #C1FFC1;
+		border-color:#E6E6FA; 
+		border-width:1px; 
+		border-style:inset;
+        }
+
+	/* Container styles */
+	td.locationHeading
+	{
+		text-align:center;
+		color: #0000FF;
+		font-size: 9pt;
+		text-decoration: underline;
+		white-space: nowrap;
+		padding: 5px;
+	}
+
+
+	td.locationHeading:hover
+	{
+		cursor:pointer;
+	}
+
+	td.locationHeadingNonLink
+	{
+		/* For columns that are not sorted by clicking*/
+		text-align:center;
+		color: #0000F9;
+		font-size: 9pt;
+		text-decoration: none;
+		white-space: nowrap;
+		padding-bottom: 4px;
+		vertical-align: bottom;
+	}
+
+	td.plateNameValue
+	{
+		/* Used only for 'Name' column.  Don't wrap and use left alignment */
+		
+		font-size:9pt;
+		white-space: nowrap;
+		padding-left: 3px;
+	}
+
+
+	td.descriptionValue
+	{
+		/* Used for 'Description' column only.  Allow wrapping to avoid infinite column stretch */
+		
+		font-size:9pt;
+		padding-left: 3px;
+	}
+
+
+	td.locationOtherValue
+	{
+		/* All other columns in container list view */
+		
+		text-align:center;
+		font-size:9pt;
+		white-space: nowrap;
+		padding: 3px;
+	}
+
+	td.adminDisabled
+	{
+		/* For 'Admin' cols, such as 'View' or 'Modify' */
+		text-align:center;
+		font-size:9pt;
+		white-space: nowrap;
+		padding: 3px;
+		color: #6C7B8B;
+		text-decoration: underline;
+	}
+	
+	/* May 28/07, Marina */
+	td.createViewColName
+	{
+		width: 100px;
+	}
+	
+	td.createViewColValue
+	{
+		font-weight: bold;
+	}
+
+
+        span.linkExportSequence
+        {
+            	color: blue;
+            	cursor: pointer;
+            	text-decoration: underline;
+            	display: inline;
+		font-size: 8pt;
+        }
+
+	/* mimic a disabled link */
+	span.linkDisabled
+	{
+		color: #6C7B8B;
+            	text-decoration: underline;
+		font-size:10pt;
+	}
+
+
+	/* Jan. 23/08: Mark clones that are ordered */
+	span.linkOrdered
+	{
+		color: #FF0000;
+            	text-decoration: none;
+		font-size:10pt;
+	}
\ No newline at end of file
diff --git a/OpenFreezer/styles/SearchStyle_old.css b/OpenFreezer/styles/SearchStyle_old.css
new file mode 100755
index 0000000..7f6bad3
--- /dev/null
+++ b/OpenFreezer/styles/SearchStyle_old.css
@@ -0,0 +1,102 @@
+<style type="text/css">
+<!--
+	body		{ font: 13px Geneva,Arial; background: #000000 url(../pictures/page_bg.gif) repeat-x fixed bottom; }
+	table, td	{ font: 13px Geneva,Arial; color: #000000 }
+	div			{ text-align: justify; }
+	
+	table.preview { font: 10px Geneva,Arial; color: #000}
+	td.preview { font: 10px Geneva,Arial; color: #000; text-align:left;  background-color:#8CC07A }
+	
+	td.navHeader { color: #FFFFFF; font: 10px Verdana; font-weight: bold; text-decoration: none }
+	
+	table.searchOutput {border-bottom-color:#33FF33; border-style:solid; float:left; }
+
+	.largest 	{ font: 22px Geneva, Arial; font-weight:bold }
+   	.larger  	{ font: 17px Geneva, Arial; font-weight:bold }
+   	.large  	{ font: 15px Geneva, Arial; font-weight:bold }
+   	.normal 	{ font: 13px Geneva,Arial; }
+  	.small  	{ font: 10px Geneva,Arial }
+  	.small2, .BoldRed 	{ font: 10px Verdana, MS Sans Serif }
+
+        a   	{ color: #004891 }
+        a:hover { color: #333 }
+
+        a.footer 		{ color: #fff; font: 10px Verdana; font-weight: bold; text-decoration: none }
+        a.footer:hover	{ color: #fff; text-decoration: underline }
+
+        a.nav, .nav 	{ color: #FFFFFF; font: 10px Verdana; font-weight: bold; text-decoration: none }
+        a.nav:hover 	{ color: #EEBB00; text-decoration: underline }
+
+        a.nav-active 	{ color: #333333; font: 10px Verdana; font-weight: bold; text-decoration: none }
+        a.nav-active:hover	{ color: #666666; text-decoration: underline }
+
+        a.invert:hover 	{ color: #FFF; text-decoration: none }
+
+        a.comments  	{ color: #ff0000; font: 10px Verdana; font-weight: plain; text-decoration: none }
+
+        .title, h2, h1 	{ font: 16px Arial; font-weight: bold }
+        .toc_title                      { font: 20px Arial; font-weight: bold }
+        .subTitle  		{ font: 12px Verdana; font-weight: bold; color: #fff }
+        .invert                         { color: #fff }
+        .yellowdiv                      { color: #F9CE00; font: 13px Verdana; font-weight: bold }
+        .radio                          { background-color: #F7F7F6; }
+        .error                          { color: #C00 }
+        .BoldRed                        { color: #C00; font-weight: bold; }
+        .radioPoll,.searchCheckbox      { background-color: #F7F7F8; }
+        input                           { font-family: monospace }
+        .ilink                          { border-color: #000 }
+        .glink                          { border-color: #FFCC00 }
+
+        .media-thumbnail                { border-color: #265FA4 }
+        .media-caption-link             { color: #AAAAAA; font: 10px Verdana; font-weight: bold; text-decoration: none }
+        .media-caption-link:hover       { color: #265FA4; }
+
+        .media-caption                  { color: #FFFFFF; font: 12px Verdana; font-weight: bold; text-decoration: none }   
+
+        .ticker-headline                { font: 13px arial; color: #FFFFFF; text-decoration: none; }
+        .ticker-headline:hover          { font: 13px arial; color: #CCCCFF; }
+        .ticker-link                    { font: 12px arial; font-weight: bold; color: #CCAA00; }
+        .ticker-link:hover              { font: 12px arial; font-weight: bold; color: #FFCC00; }
+
+	.news-link			{ font: 11px Geneva,Arial; text-decoration: none }
+	.news-link:hover		{ font: 11px Geneva,Arial; text-decoration: underline; color: #34A1DE }
+
+a.td.thumbnail, a.td.thumbnail:link, a.td.thumbnail:visited, a.td.thumbnail:active {
+        border: rgb(0, 0, 0) 1px solid;
+        margin-bottom: -45px;
+        padding-top: 5px;
+        width: 172px;
+        display: block;
+        background: rgb(35, 35, 35);
+        height: 197px;
+        filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=60);
+}
+a.td.thumbnail:hover            {
+        border: rgb(95, 121, 216) 1px solid;
+        margin-bottom: -45px;
+        padding-top: 5px;
+        width: 172px;
+        display: block;
+        background: rgb(32, 32, 32);
+        height: 197px;
+        filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
+}
+
+.gn_T5 			{ 	color: #FFFFFF; }
+.gn_pkTitle		{	font : 10px Verdana, Geneva, Arial, Helvetica, sans-serif;	}
+.gn_pkRank		{	font : 10px Verdana, Geneva, Arial, Helvetica, sans-serif;	}
+.gn_pkPlatform	{	font : 10px Verdana, Geneva, Arial, Helvetica, sans-serif;	}
+.gn_tbl			{		}
+
+
+        .sponsor-highlight       { color: #0088AF; font: 16px Arial; font-weight: bold; text-decoration: none; }
+        .sponsor-highlight:hover { color: #66AAFF; text-decoration: underline }
+
+        .sponsor-link            { color: #0088AF; font: 12px Arial; font-weight: bold; text-decoration: none; }
+        .sponsor-link:hover { color: #66AAFF; text-decoration: underline }
+
+        .sponsor-teaser          { color: #666666; font: 12px Arial; }
+
+
+-->
+</style>
diff --git a/OpenFreezer/styles/SequenceStyle.css b/OpenFreezer/styles/SequenceStyle.css
new file mode 100755
index 0000000..fb3c2d8
--- /dev/null
+++ b/OpenFreezer/styles/SequenceStyle.css
@@ -0,0 +1,7 @@
+<style type="text/css">
+<!--
+	.protein {  color:#FF0000 }
+	.cdna { font-family:monospace; font-weight:bold; };
+
+-->
+</style>
diff --git a/OpenFreezer/styles/WebsiteBasic.css b/OpenFreezer/styles/WebsiteBasic.css
new file mode 100755
index 0000000..4165e19
--- /dev/null
+++ b/OpenFreezer/styles/WebsiteBasic.css
@@ -0,0 +1,135 @@
+body {
+	background-color: #FFFFCC;
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 12px;
+	line-height: 24px;
+	color: #333333;
+}
+
+td, th {
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 12px;
+	line-height: 24px;
+	color: #330000;
+}
+
+a {
+	color: #330000;
+}
+
+form {
+	background-color: #CCCC99;
+}
+
+.title {
+	font-family: Georgia, "Times New Roman", Times, serif;
+	font-size: 18px;
+	line-height: 30px;
+  background-color: #990000; color: #FFFF66;
+}
+
+.subtitle {
+	font-family: Georgia, "Times New Roman", Times, serif;
+	font-size: 16px;
+	line-height: 20px;
+	font-weight: bold;
+  color: #660000; font-style: oblique;
+}
+
+.header {
+	font-family: Georgia, "Times New Roman", Times, serif;
+	font-size: 24px;
+	background-color: #990000;
+  color: #FFFF66;
+}
+
+.nav {
+	font-family: Georgia, "Times New Roman", Times, serif;
+	font-size: 12px;
+	font-weight: bold;
+	background-color: #CCCC66;
+}
+
+.navLink {
+	font-family: Arial, Helvetica, sans-serif;
+	font-size: 14px;
+	font-weight: bold;
+	background-color: #DEDECA;
+}
+a:hover {
+	color: #DEDECA;
+	background-color: #330000;
+}
+
+.sidebar {
+	font-family: Georgia, "Times New Roman", Times, serif;
+	font-size: 12px;
+	line-height: 18px;
+	padding: 3px;
+	background-color: #FFFF99;
+}
+
+.sidebarHeader {
+	font-family: Georgia, "Times New Roman", Times, serif;
+	font-size: 14px;
+	line-height: 18px;
+	color: #FFFF99;
+	background-color: #999933;
+ font-weight: bold;
+}
+
+.sidebarFooter {
+	font-family: Georgia, "Times New Roman", Times, serif;
+	font-size: 12px;
+	line-height: 18px;
+	background-color: #FFFF99;
+ color: #990000;
+}
+
+.footer {
+  font-family: Georgia, "Times New Roman", Times, serif;
+	font-size: 12px;
+	font-weight: bold;
+	line-height: 22px;
+	color: #333333;
+	background-color: #FFFF99;
+}
+
+.legal {
+	font-family: Georgia, "Times New Roman", Times, serif;
+	font-size: 12pt;
+	color: #333333;
+}
+
+.box1 {
+	border-width: 2px;
+	border-color: #CCCCCC #333333 #333333 #CCCCCC;
+  border-style: dotted;
+	}
+
+.promo {
+	font-family: "Times New Roman", Times, serif;
+	color: #000033;
+}
+
+.titlebar {
+	font-family: "Times New Roman", Times, serif;
+	font-size: 9px;
+	color: #FFFFFF;
+	background-color: #336699;
+}
+
+.dingbat {
+	font-family: Georgia, "Times New Roman", Times, serif;
+	background-color: #CCCC99;
+ color: #660000; font-weight: bolder; font-size: medium;
+}
+
+input.big {
+	width: 100px;
+}
+
+input.small {
+	width: 50px;
+}
+
diff --git a/OpenFreezer/styles/generic.css b/OpenFreezer/styles/generic.css
new file mode 100755
index 0000000..04aeb2f
--- /dev/null
+++ b/OpenFreezer/styles/generic.css
@@ -0,0 +1,238 @@
+			td.corner  	{background-color : #00BB55;
+					 border-right 	:  1px solid  #FFFFFF; 
+					 border-bottom 	: 1px solid #FFFFFF; 
+					 border-top 	: 1px solid #FFFFFF; 
+					 border-left 	: 1px solid #FFFFFF; 
+					 font-family : arial;
+					 font-size : 8pt;
+					 text-align : left;}
+
+			td.cornerBlue  	{background-color : #00BB55;
+					 border-right 	:  1px solid #FFFFFF; 
+					 border-bottom 	: 1px solid #FFFFFF; 
+					 border-top 	: 1px solid #FFFFFF; 
+					 border-left 	: 1px solid #FFFFFF; 
+					 font-family : arial;
+					 font-size : 8pt;
+					 text-align : left;
+					 vertical-align : bottom
+					}
+
+			td.value_i_marked
+			{
+					border-right:  3px solid #FF0000; 
+					 border-bottom 	: 1px solid #FF0000; 
+					 border-top 	: 1px solid #FF0000; 
+					 border-left 	: 1px solid #FF0000; 
+					 font-family : arial;
+					 font-size : 8pt;
+					 text-align : right;
+					 background-color:  #FFFF00
+					}
+			tr.v_marked		{background-color : #EEEE00;}
+			tr.v_marked_Incl	{color : #00CE00;}
+			tr.v_marked_Excl	{color : #EE0000;}
+			tr.v_marked_InclExcl	{color : #804000;}
+			td.smallFont	{
+					 font-family : arial;
+					 font-size : 6pt;
+					}
+
+
+
+			td.colrMgmt_Fg	{border-style: solid; border-width: 1; 
+					 background-color : #FFFFFF; 
+					 color: #000000;
+					 font-family : verdana ;
+					 font-size : 8pt;
+					 font-weight: bold;
+					 }
+			td.colrMgmt_Bg	{border-style: solid; border-width: 1; 
+					 background-color : #AAAAAA; 
+					 color: #FFFFFF;
+					 font-family : verdana ;
+					 font-size : 8pt;
+					 font-weight: bold;
+					 }
+			td.colrMgmt_Undo{border-style: solid; border-width: 1; 
+					 background-color : #FFFFFF; 
+					 color: #000000;
+					 font-family : verdana ;
+					 font-size : 8pt;
+					 }
+
+			table.inline		{background-color : #CCCCCC;}
+			td.inlineMinus	{background-color : #DDDDDD;}
+
+			table.v		{background-color : #FFFFFF;}
+			tr.v_1		{background-color : #EEEEEE;}
+			tr.v_0		{background-color : #DDDDDD;}
+			textarea.v_1	{background-color : #EEEEEE;
+					 border-bottom 	: 0px; 
+					 border-top 	: 0px; 
+					 border-left 	: 0px; 
+					 border-right 	: 0px; 
+					 font-family : arial;
+					 font-size : 8pt;}
+			textarea.v_0	{background-color : #DDDDDD;
+					 border-bottom 	: 0px; 
+					 border-top 	: 0px; 
+					 border-left 	: 0px; 
+					 border-right 	: 0px; 
+					 font-family : arial;
+					 font-size : 8pt;}
+			
+			tr.v_header	{background-color : #00B3F9;}
+			tr.v_header_sorter	{background-color : #4FCAFF;}
+			td.non_header 	{border-bottom : 1px solid #FFFFFF; 
+					 border-right :  1px solid #FFFFFF; 
+					 border-top 	: 1px solid #FFFFFF; 
+					 border-left 	: 1px solid #FFFFFF; 
+					 font-family : arial;
+					 font-size : 8pt;
+					 }
+					 
+			td.header 	{background-color : #00B3F9; border-bottom : 0 solid #FFFFFF;}
+			th.header 	{background-color : #00B3F9;
+					 border-right :  1px solid #FFFFFF; 
+					 border-bottom : 0px solid #FFFFFF; 
+					 color :#FFFFFF; 
+					 font-family : verdana ; 
+					 font-size : 7pt;}
+			th.header_sorter {border-right :  1px solid #FFFFFF; 
+					 border-bottom : 0px solid #FFFFFF; 
+					 color :#FFFFFF; 
+					 font-family : verdana ; 
+					 font-size : 7pt;
+					 }
+			td.header_sorter {border-right :  1px solid #FFFFFF; 
+					 border-bottom : 0px solid #FFFFFF; 
+					 color :#FFFFFF; 
+					 font-family : verdana ; 
+					 font-size : 7pt;
+					 }
+
+
+			tr.spacer	{background-color : #006399}
+			td.spacer 	{background-color : #006399; border-bottom: 1px solid #FFFFFF;}
+			th.column 	{border-right :  1px solid #FFFFFF; 
+					 border-bottom : 1px solid #FFFFFF;}
+
+
+			td.value_i  	{border-right 	:  1px solid #FFFFFF; 
+					 border-bottom 	: 1px solid #FFFFFF; 
+					 border-top 	: 1px solid #FFFFFF; 
+					 border-left 	: 1px solid #FFFFFF; 
+					 font-family : arial;
+					 font-size : 8pt;
+					 text-align : right;}
+
+
+					 
+			td.value_n  	{border-right :  1px solid #FFFFFF; 
+					 border-bottom : 1px solid #FFFFFF; 
+					 border-top 	: 1px solid #FFFFFF; 
+					 border-left 	: 1px solid #FFFFFF; 
+					 font-family : arial;
+					 font-size : 8pt;
+					 text-align : right;}
+					 
+			td.value_d  	{border-right :  1px solid #FFFFFF; 
+					 border-bottom : 1px solid #FFFFFF; 
+					 border-top 	: 1px solid #FFFFFF; 
+					 border-left 	: 1px solid #FFFFFF; 
+					 font-family : arial;
+					 font-size : 8pt;
+					 text-align : center;}
+					 
+			td.value_c  	{border-right :  1px solid #FFFFFF; 
+					 border-bottom : 1px solid #FFFFFF; 
+					 border-top 	: 1px solid #FFFFFF; 
+					 border-left 	: 1px solid #FFFFFF; 
+					 font-family : arial;
+					 font-size : 8pt;
+					 }
+
+
+			td.index	{border-right :  1px solid #FFFFFF; 
+					 border-bottom : 1px solid #FFFFFF; 
+					 border-top 	: 1px solid #FFFFFF; 
+					 border-left 	: 1px solid #FFFFFF; 
+					 font-family : arial;
+					 font-size : 7pt;}		               
+					 
+			img		{cursor : pointer; border-width: 0}
+			
+			span.col_number	{font-family : verdana ; 
+					 font-size : 5pt;}
+
+		       div.tooltip 	{font-family : Verdana; 
+		                          font-size : 11px; 
+		                          color : #0000FF; 
+		                          position : absolute; 
+		                          visibility : hidden; 
+		                          background : #FFFFCC; 
+		                          border-style : solid; 
+		                          border-color : #000000; 
+		                          border-width : 1px;
+		                          z-index: 999}
+
+			span.step_number {font-family : verdana ;
+					  font-size : 11px; 
+					  cursor : pointer;
+					 }
+
+			
+			a.cellValue:link {
+				color: #000000;
+				text-decoration: none;
+			}
+
+			/* This style is how your link will look when the visitor has already been to that page. 
+			/ Here, dark grey text. This must be placed ahead of the mouseover style in your style sheet to work properly.*/
+			
+			a.cellValue:visited {
+				color: #111111;
+				text-decoration: none;
+			}
+
+			/*This is how the mouseover will look. Here I have specified no underline, 
+			 with a light grey background. When the visitor moves their mouse over the link, only the background and underline will change.*/
+			
+			a.cellValue:hover {
+				text-decoration: underline;
+				background-color: #CCCCCC;
+			}
+
+			/*This is mostly useless, as it is what the visitor sees when they are actually clicking the link.*/
+
+			a.cellValue:active {
+				text-decoration: none;
+			}
+			
+
+			td.headerList 	{background-color : #009933; border-bottom : 0px solid #FFFFFF;}
+			th.headerList 	{background-color : #009933;
+					 border-right :  1px solid #FFFFFF; 
+					 border-bottom : 0px solid #FFFFFF; 
+					 color :#FFFFFF; 
+					 font-family : verdana ; 
+					 font-size : 7pt;}
+			input.smallFont	{
+					 font-family : arial;
+					 font-size : 10pt;
+					}
+			span.smallDetails{
+					 font-family : arial;
+					 font-size : 8pt;
+					}
+			span.theName {
+					 font-family : tahoma;
+					 font-weight: bold;
+					}
+			a.theName:link	{
+					text-decoration: none;
+					}
+			a.theName:visited	{
+					text-decoration: none;
+					}
diff --git a/UNIX_install_instructions.pdf b/UNIX_install_instructions.pdf
new file mode 100644
index 0000000..e95bf4b
Binary files /dev/null and b/UNIX_install_instructions.pdf differ
diff --git a/openfreezer.sql b/openfreezer.sql
new file mode 100644
index 0000000..43a499b
--- /dev/null
+++ b/openfreezer.sql
@@ -0,0 +1,1481 @@
+-- MySQL dump 10.11
+--
+-- Host: localhost    Database: marina
+-- ------------------------------------------------------
+-- Server version	5.0.77
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Table structure for table `AssocProp_tbl`
+--
+
+DROP TABLE IF EXISTS `AssocProp_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `AssocProp_tbl` (
+  `propListID` int(11) NOT NULL auto_increment,
+  `assID` int(11) NOT NULL default '0',
+  `APropertyID` int(11) NOT NULL default '0',
+  `propertyValue` varchar(27) NOT NULL default '',
+  `labID` int(11) NOT NULL default '1',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`propListID`),
+  KEY `propListID` (`propListID`),
+  KEY `assID` (`assID`),
+  KEY `APropertyID` (`APropertyID`),
+  KEY `propValue_index` (`propertyValue`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `AssocProp_tbl`
+--
+
+LOCK TABLES `AssocProp_tbl` WRITE;
+/*!40000 ALTER TABLE `AssocProp_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `AssocProp_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `AssocType_tbl`
+--
+
+DROP TABLE IF EXISTS `AssocType_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `AssocType_tbl` (
+  `ATypeID` int(11) NOT NULL auto_increment,
+  `association` varchar(27) default NULL,
+  `description` tinytext,
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`ATypeID`),
+  KEY `ATypeID` (`ATypeID`)
+) ENGINE=MyISAM AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `AssocType_tbl`
+--
+
+LOCK TABLES `AssocType_tbl` WRITE;
+/*!40000 ALTER TABLE `AssocType_tbl` DISABLE KEYS */;
+INSERT INTO `AssocType_tbl` VALUES (1,'INSERT','','ACTIVE'),(2,'LOXP','','ACTIVE'),(3,'BASIC','','ACTIVE'),(4,'Insert Oligos','','ACTIVE'),(5,'CellLine Stable','','ACTIVE'),(6,'Insert Parent Vector','','ACTIVE');
+/*!40000 ALTER TABLE `AssocType_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Assoc_Prop_Type_tbl`
+--
+
+DROP TABLE IF EXISTS `Assoc_Prop_Type_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Assoc_Prop_Type_tbl` (
+  `APropertyID` int(11) NOT NULL auto_increment,
+  `reagentTypeID` int(11) NOT NULL default '0',
+  `APropName` varchar(117) NOT NULL default '',
+  `hierarchy` enum('PARENT','SIBLING','CHILD') NOT NULL default 'PARENT',
+  `alias` tinytext,
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  `description` varchar(250) default NULL,
+  `assocTypeID` int(11) NOT NULL,
+  PRIMARY KEY  (`APropertyID`),
+  KEY `assocTypeID` (`assocTypeID`)
+) ENGINE=MyISAM AUTO_INCREMENT=10 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Assoc_Prop_Type_tbl`
+--
+
+LOCK TABLES `Assoc_Prop_Type_tbl` WRITE;
+/*!40000 ALTER TABLE `Assoc_Prop_Type_tbl` DISABLE KEYS */;
+INSERT INTO `Assoc_Prop_Type_tbl` VALUES (1,1,'insert id','PARENT','insert_id','ACTIVE','Insert ID',2),(2,1,'vector parent id','PARENT','parent_vector','ACTIVE','Parent Vector ID',1),(4,2,'insert parent vector id','PARENT','insert_parent_vector','ACTIVE','Insert Parent Vector ID',1),(5,2,'sense oligo','PARENT','sense_oligo','ACTIVE','Sense Oligo',3),(6,2,'antisense oligo','PARENT','antisense_oligo','ACTIVE','Antisense Oligo',3),(7,1,'parent insert vector','PARENT','parent_insert_vector', [...]
+/*!40000 ALTER TABLE `Assoc_Prop_Type_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Association_tbl`
+--
+
+DROP TABLE IF EXISTS `Association_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Association_tbl` (
+  `assID` int(11) NOT NULL auto_increment,
+  `reagentID` int(11) NOT NULL default '0',
+  `ATypeID` int(11) NOT NULL default '0',
+  `labID` int(11) NOT NULL default '1',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`assID`),
+  KEY `assID` (`assID`),
+  KEY `reagentID` (`reagentID`),
+  KEY `ATypeID` (`ATypeID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Association_tbl`
+--
+
+LOCK TABLES `Association_tbl` WRITE;
+/*!40000 ALTER TABLE `Association_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `Association_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `BugReport_tbl`
+--
+
+DROP TABLE IF EXISTS `BugReport_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `BugReport_tbl` (
+  `bug_type` enum('Bug','Feature') NOT NULL default 'Bug',
+  `bug_descr` text,
+  `status` enum('ACTIVE','DEP') default 'ACTIVE',
+  `is_closed` enum('YES','NO') default 'NO',
+  `module` text,
+  `bugID` int(11) NOT NULL auto_increment,
+  `requested_by` int(11) default NULL,
+  PRIMARY KEY  (`bugID`),
+  KEY `requested_by` (`requested_by`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `BugReport_tbl`
+--
+
+LOCK TABLES `BugReport_tbl` WRITE;
+/*!40000 ALTER TABLE `BugReport_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `BugReport_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ChemicalLocationNames_tbl`
+--
+
+DROP TABLE IF EXISTS `ChemicalLocationNames_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ChemicalLocationNames_tbl` (
+  `chemLocNameID` int(11) NOT NULL auto_increment,
+  `chemicalLocationName` varchar(250) NOT NULL,
+  `chemicalLocationDescr` varchar(250) NOT NULL,
+  `status` enum('ACTIVE','DEP') default 'ACTIVE',
+  PRIMARY KEY  (`chemLocNameID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ChemicalLocationNames_tbl`
+--
+
+LOCK TABLES `ChemicalLocationNames_tbl` WRITE;
+/*!40000 ALTER TABLE `ChemicalLocationNames_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ChemicalLocationNames_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ChemicalLocationTypes_tbl`
+--
+
+DROP TABLE IF EXISTS `ChemicalLocationTypes_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ChemicalLocationTypes_tbl` (
+  `chemLocTypeID` int(11) NOT NULL auto_increment,
+  `chemLocTypeName` varchar(250) NOT NULL default '',
+  `status` enum('ACTIVE','DEP') default 'ACTIVE',
+  PRIMARY KEY  (`chemLocTypeID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ChemicalLocationTypes_tbl`
+--
+
+LOCK TABLES `ChemicalLocationTypes_tbl` WRITE;
+/*!40000 ALTER TABLE `ChemicalLocationTypes_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ChemicalLocationTypes_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ChemicalLocations_tbl`
+--
+
+DROP TABLE IF EXISTS `ChemicalLocations_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ChemicalLocations_tbl` (
+  `chemLocID` int(11) NOT NULL auto_increment,
+  `chemLocName` int(11) NOT NULL,
+  `chemLocType` int(11) NOT NULL,
+  `chemLocComments` int(11) default NULL,
+  `status` enum('ACTIVE','DEP') default 'ACTIVE',
+  PRIMARY KEY  (`chemLocID`),
+  KEY `chemLocName` (`chemLocName`),
+  KEY `chemLocType` (`chemLocType`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ChemicalLocations_tbl`
+--
+
+LOCK TABLES `ChemicalLocations_tbl` WRITE;
+/*!40000 ALTER TABLE `ChemicalLocations_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ChemicalLocations_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ChemicalNames_tbl`
+--
+
+DROP TABLE IF EXISTS `ChemicalNames_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ChemicalNames_tbl` (
+  `chemicalID` int(11) NOT NULL auto_increment,
+  `chemicalName` varchar(250) NOT NULL,
+  `CAS_No` varchar(250) NOT NULL,
+  `status` enum('ACTIVE','DEP') default 'ACTIVE',
+  PRIMARY KEY  (`chemicalID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ChemicalNames_tbl`
+--
+
+LOCK TABLES `ChemicalNames_tbl` WRITE;
+/*!40000 ALTER TABLE `ChemicalNames_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ChemicalNames_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Chemicals_tbl`
+--
+
+DROP TABLE IF EXISTS `Chemicals_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Chemicals_tbl` (
+  `chemicalID` int(11) NOT NULL default '0',
+  `chemicalLocation` int(11) NOT NULL default '0',
+  `Comments` int(11) default NULL,
+  `Quantity` varchar(50) default NULL,
+  `Supplier` int(11) default NULL,
+  `Safety` set('A - Compressed Gas','B1 - Flammable Gas','B2 - Flammable Liquid','B3 - Combustible Liquid','B4 - Flammable Solid','B5 - Flammable Aerosol','B6 - Reactive Flammable','C - Oxidizing','D1A - Immediate Very Toxic','D1B - Immediate Toxic','D2A - Other Very Toxic','D2B - Other Toxic','E - Corrosive','F - Dangerously Reactive','Non-Controlled') default NULL,
+  `status` enum('ACTIVE','DEP') default 'ACTIVE',
+  `chemListID` int(11) NOT NULL auto_increment,
+  `MSDS` text,
+  PRIMARY KEY  (`chemListID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Chemicals_tbl`
+--
+
+LOCK TABLES `Chemicals_tbl` WRITE;
+/*!40000 ALTER TABLE `Chemicals_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `Chemicals_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `CommentLink_tbl`
+--
+
+DROP TABLE IF EXISTS `CommentLink_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `CommentLink_tbl` (
+  `commentLinkID` int(11) NOT NULL auto_increment,
+  `link` varchar(27) NOT NULL default '',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`commentLinkID`),
+  KEY `commentLinkID` (`commentLinkID`)
+) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `CommentLink_tbl`
+--
+
+LOCK TABLES `CommentLink_tbl` WRITE;
+/*!40000 ALTER TABLE `CommentLink_tbl` DISABLE KEYS */;
+INSERT INTO `CommentLink_tbl` VALUES (1,'Reagent','ACTIVE'),(2,'Container','ACTIVE'),(3,'Packet','ACTIVE'),(4,'Experiment','ACTIVE'),(5,'Chemical','ACTIVE');
+/*!40000 ALTER TABLE `CommentLink_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ContainerGroup_tbl`
+--
+
+DROP TABLE IF EXISTS `ContainerGroup_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ContainerGroup_tbl` (
+  `contGroupID` int(11) NOT NULL auto_increment,
+  `contGroupName` varchar(27) NOT NULL default '',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  `isolate_active` enum('YES','NO') default 'NO',
+  `contGroupCode` char(2) default NULL,
+  PRIMARY KEY  (`contGroupID`),
+  KEY `contGroupID` (`contGroupID`)
+) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ContainerGroup_tbl`
+--
+
+LOCK TABLES `ContainerGroup_tbl` WRITE;
+/*!40000 ALTER TABLE `ContainerGroup_tbl` DISABLE KEYS */;
+INSERT INTO `ContainerGroup_tbl` VALUES (1,'Glycerol Stocks','ACTIVE','YES','GS');
+/*!40000 ALTER TABLE `ContainerGroup_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ContainerReagentTypes_tbl`
+--
+
+DROP TABLE IF EXISTS `ContainerReagentTypes_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ContainerReagentTypes_tbl` (
+  `contReagentTypeID` int(11) NOT NULL auto_increment,
+  `contTypeID` int(11) NOT NULL,
+  `reagentTypeID` int(11) NOT NULL,
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`contReagentTypeID`),
+  KEY `contTypeID` (`contTypeID`),
+  KEY `reagentTypeID` (`reagentTypeID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ContainerReagentTypes_tbl`
+--
+
+LOCK TABLES `ContainerReagentTypes_tbl` WRITE;
+/*!40000 ALTER TABLE `ContainerReagentTypes_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ContainerReagentTypes_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ContainerTypeAttributes_tbl`
+--
+
+DROP TABLE IF EXISTS `ContainerTypeAttributes_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ContainerTypeAttributes_tbl` (
+  `contTypePropID` int(11) NOT NULL auto_increment,
+  `containerTypeID` int(11) NOT NULL,
+  `containerTypeAttributeID` int(11) NOT NULL,
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`contTypePropID`),
+  KEY `containerTypeID` (`containerTypeID`),
+  KEY `containerTypeAttributeID` (`containerTypeAttributeID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ContainerTypeAttributes_tbl`
+--
+
+LOCK TABLES `ContainerTypeAttributes_tbl` WRITE;
+/*!40000 ALTER TABLE `ContainerTypeAttributes_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ContainerTypeAttributes_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ContainerTypeID_tbl`
+--
+
+DROP TABLE IF EXISTS `ContainerTypeID_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ContainerTypeID_tbl` (
+  `contTypeID` int(11) NOT NULL auto_increment,
+  `containerName` varchar(27) NOT NULL default '',
+  `maxCol` int(11) NOT NULL default '0',
+  `maxRow` int(11) NOT NULL default '0',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`contTypeID`),
+  KEY `contTypeID` (`contTypeID`)
+) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ContainerTypeID_tbl`
+--
+
+LOCK TABLES `ContainerTypeID_tbl` WRITE;
+/*!40000 ALTER TABLE `ContainerTypeID_tbl` DISABLE KEYS */;
+INSERT INTO `ContainerTypeID_tbl` VALUES (1,'96-well plate',12,8,'ACTIVE');
+/*!40000 ALTER TABLE `ContainerTypeID_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Container_tbl`
+--
+
+DROP TABLE IF EXISTS `Container_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Container_tbl` (
+  `containerID` int(11) NOT NULL auto_increment,
+  `contGroupID` int(11) NOT NULL default '0',
+  `contTypeID` int(11) NOT NULL default '0',
+  `contGroupCount` int(11) NOT NULL default '0',
+  `name` tinytext,
+  `container_desc` tinytext,
+  `labID` int(11) NOT NULL default '1',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  `barcode` varchar(250) default NULL,
+  `isolate_active` enum('YES','NO') NOT NULL default 'YES',
+  `shelf` int(11) default NULL,
+  `rack` int(11) default NULL,
+  `location` int(11) NOT NULL,
+  `row_number` int(11) default NULL,
+  `col_number` int(11) default NULL,
+  `locationName` varchar(250) default NULL,
+  `address` varchar(250) default NULL,
+  PRIMARY KEY  (`containerID`),
+  KEY `containerID` (`containerID`),
+  KEY `contGroupID` (`contGroupID`),
+  KEY `contTypeID` (`contTypeID`),
+  KEY `contGroupCount` (`contGroupCount`),
+  KEY `labID` (`labID`),
+  KEY `location` (`location`)
+) ENGINE=MyISAM AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Container_tbl`
+--
+
+LOCK TABLES `Container_tbl` WRITE;
+/*!40000 ALTER TABLE `Container_tbl` DISABLE KEYS */;
+INSERT INTO `Container_tbl` VALUES (1,1,1,1,'First container in OpenFreezer','Feel free to change/remove this',1,'DEP','96GS1','YES',0,0,3,0,0,'Change this',''),(2,2,1,1,'Oligo Box 1','description added now',2,'ACTIVE','CL96OL1','YES',1,2,2,4,3,'Freezer 1',''),(3,2,2,2,'Oligo Box 3','Third oligo box in Colwill lab',2,'DEP','CL100OL1','YES',4,1,2,3,2,'Colwill Freezer3','room 984 '),(4,3,2,1,'Antibody Box 1','Antibodys A-C',2,'ACTIVE','CL100AB1','YES',3,4,1,5,5,'Colwill Fridge 1','room 970 [...]
+/*!40000 ALTER TABLE `Container_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Experiment_tbl`
+--
+
+DROP TABLE IF EXISTS `Experiment_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Experiment_tbl` (
+  `expID` int(11) NOT NULL auto_increment,
+  `reagentID` int(11) default NULL,
+  `oldID` varchar(17) default NULL,
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`expID`),
+  KEY `expID` (`expID`),
+  KEY `reagentID` (`reagentID`),
+  KEY `oldID` (`oldID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Experiment_tbl`
+--
+
+LOCK TABLES `Experiment_tbl` WRITE;
+/*!40000 ALTER TABLE `Experiment_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `Experiment_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `GeneralComments_tbl`
+--
+
+DROP TABLE IF EXISTS `GeneralComments_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `GeneralComments_tbl` (
+  `commentID` int(11) NOT NULL auto_increment,
+  `commentLinkID` int(250) default NULL,
+  `comment` text,
+  `labID` int(11) NOT NULL default '1',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`commentID`),
+  KEY `commentID` (`commentID`),
+  KEY `commentLinkID` (`commentLinkID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `GeneralComments_tbl`
+--
+
+LOCK TABLES `GeneralComments_tbl` WRITE;
+/*!40000 ALTER TABLE `GeneralComments_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `GeneralComments_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Isolate_tbl`
+--
+
+DROP TABLE IF EXISTS `Isolate_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Isolate_tbl` (
+  `isolate_pk` int(11) NOT NULL auto_increment,
+  `expID` int(11) NOT NULL default '0',
+  `isolateNumber` int(11) NOT NULL default '0',
+  `isolateName` varchar(117) default 'NONE',
+  `description` tinytext,
+  `isolate_active` enum('YES','NO') NOT NULL default 'NO',
+  `beingUsed` enum('YES','NO') NOT NULL default 'NO',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`isolate_pk`),
+  KEY `isolate_pk` (`isolate_pk`),
+  KEY `expID` (`expID`),
+  KEY `isolateNumber` (`isolateNumber`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Isolate_tbl`
+--
+
+LOCK TABLES `Isolate_tbl` WRITE;
+/*!40000 ALTER TABLE `Isolate_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `Isolate_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `LabInfo_tbl`
+--
+
+DROP TABLE IF EXISTS `LabInfo_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `LabInfo_tbl` (
+  `labID` int(11) NOT NULL auto_increment,
+  `lab_name` varchar(27) default NULL,
+  `description` tinytext,
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  `default_access_level` int(11) NOT NULL default '4',
+  `location` text,
+  `lab_head` varchar(150) default NULL,
+  `labCode` char(2) default NULL,
+  PRIMARY KEY  (`labID`)
+) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `LabInfo_tbl`
+--
+
+LOCK TABLES `LabInfo_tbl` WRITE;
+/*!40000 ALTER TABLE `LabInfo_tbl` DISABLE KEYS */;
+INSERT INTO `LabInfo_tbl` VALUES (1,'Admin','','ACTIVE',1,'','Admin','AD');
+/*!40000 ALTER TABLE `LabInfo_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `LocationTypes_tbl`
+--
+
+DROP TABLE IF EXISTS `LocationTypes_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `LocationTypes_tbl` (
+  `locationTypeID` int(11) NOT NULL auto_increment,
+  `locationTypeName` varchar(250) default NULL,
+  `status` enum('ACTIVE','DEP') default 'ACTIVE',
+  PRIMARY KEY  (`locationTypeID`)
+) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `LocationTypes_tbl`
+--
+
+LOCK TABLES `LocationTypes_tbl` WRITE;
+/*!40000 ALTER TABLE `LocationTypes_tbl` DISABLE KEYS */;
+INSERT INTO `LocationTypes_tbl` VALUES (1,'Fridge','ACTIVE'),(2,'Freezer','ACTIVE'),(3,'To change, update LocationTypes_tbl in the database','ACTIVE');
+/*!40000 ALTER TABLE `LocationTypes_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `LoginRecord_tbl`
+--
+
+DROP TABLE IF EXISTS `LoginRecord_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `LoginRecord_tbl` (
+  `crec_id` int(11) NOT NULL auto_increment,
+  `userID` int(11) NOT NULL default '0',
+  `timestamp` datetime default NULL,
+  `user_ip` varchar(27) NOT NULL default '',
+  `user_host` varchar(27) NOT NULL default '',
+  `cookieID` varchar(27) default NULL,
+  `sessionID` varchar(27) default NULL,
+  `persistent` enum('T','F') NOT NULL default 'F',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`crec_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `LoginRecord_tbl`
+--
+
+LOCK TABLES `LoginRecord_tbl` WRITE;
+/*!40000 ALTER TABLE `LoginRecord_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `LoginRecord_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Method_tbl`
+--
+
+DROP TABLE IF EXISTS `Method_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Method_tbl` (
+  `methodID` int(11) NOT NULL auto_increment,
+  `oldID` int(11) default NULL,
+  `method` text NOT NULL,
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`methodID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Method_tbl`
+--
+
+LOCK TABLES `Method_tbl` WRITE;
+/*!40000 ALTER TABLE `Method_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `Method_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `PacketOwners_tbl`
+--
+
+DROP TABLE IF EXISTS `PacketOwners_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `PacketOwners_tbl` (
+  `packetID` int(11) NOT NULL auto_increment,
+  `firstName` varchar(27) NOT NULL default '',
+  `lastName` varchar(27) NOT NULL default '',
+  `packetName` varchar(27) NOT NULL default '',
+  `description` int(11) default NULL,
+  `labID` int(11) NOT NULL default '1',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  `dateSubmitted` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
+  PRIMARY KEY  (`packetID`),
+  KEY `packetID` (`packetID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `PacketOwners_tbl`
+--
+
+LOCK TABLES `PacketOwners_tbl` WRITE;
+/*!40000 ALTER TABLE `PacketOwners_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `PacketOwners_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Packets_tbl`
+--
+
+DROP TABLE IF EXISTS `Packets_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Packets_tbl` (
+  `packetID` int(11) NOT NULL auto_increment,
+  `ownerID` int(11) NOT NULL default '3',
+  `packetName` varchar(250) NOT NULL default '',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  `packetDescription` int(11) default NULL,
+  `is_private` enum('TRUE','FALSE') default 'FALSE',
+  PRIMARY KEY  (`packetID`),
+  KEY `ownerID` (`ownerID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Packets_tbl`
+--
+
+LOCK TABLES `Packets_tbl` WRITE;
+/*!40000 ALTER TABLE `Packets_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `Packets_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `PrepElemTypes_tbl`
+--
+
+DROP TABLE IF EXISTS `PrepElemTypes_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `PrepElemTypes_tbl` (
+  `elementTypeID` int(11) NOT NULL auto_increment,
+  `propertyName` varchar(100) NOT NULL default '',
+  `PrepElementDesc` tinytext,
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`elementTypeID`),
+  KEY `elementTypeID` (`elementTypeID`),
+  KEY `propertyName` (`propertyName`)
+) ENGINE=MyISAM AUTO_INCREMENT=51 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `PrepElemTypes_tbl`
+--
+
+LOCK TABLES `PrepElemTypes_tbl` WRITE;
+/*!40000 ALTER TABLE `PrepElemTypes_tbl` DISABLE KEYS */;
+INSERT INTO `PrepElemTypes_tbl` VALUES (1,'OriginalID','The Original ID Contained In Well','ACTIVE'),(2,'Method ID','Method ID','ACTIVE'),(3,'Bacteria Strain','Bacteria Strain','ACTIVE'),(4,'Concentration','Concentration','ACTIVE'),(5,'Reagent Source','Reagent Source','ACTIVE'),(6,'Cell Line Name','Cell Line Name','ACTIVE'),(7,'Isolate Name','Isolate Name','ACTIVE'),(8,'Plates/Vial','Plates/Vial','ACTIVE'),(9,'Date','Date','ACTIVE'),(10,'Person','Person','ACTIVE'),(11,'Passage','Passage' [...]
+/*!40000 ALTER TABLE `PrepElemTypes_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `PrepElementProp_tbl`
+--
+
+DROP TABLE IF EXISTS `PrepElementProp_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `PrepElementProp_tbl` (
+  `prepPropID` int(11) NOT NULL auto_increment,
+  `prepID` int(11) NOT NULL default '0',
+  `elementTypeID` int(11) NOT NULL default '0',
+  `value` varchar(27) NOT NULL default '',
+  `labID` int(11) NOT NULL default '1',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`prepPropID`),
+  KEY `prepID` (`prepID`),
+  KEY `elementTypeID` (`elementTypeID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `PrepElementProp_tbl`
+--
+
+LOCK TABLES `PrepElementProp_tbl` WRITE;
+/*!40000 ALTER TABLE `PrepElementProp_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `PrepElementProp_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Prep_Req_tbl`
+--
+
+DROP TABLE IF EXISTS `Prep_Req_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Prep_Req_tbl` (
+  `prepReqID` int(11) NOT NULL auto_increment,
+  `prepElementTypeID` int(11) NOT NULL default '0',
+  `containerID` int(11) NOT NULL default '0',
+  `requirement` enum('REQ','OPT') NOT NULL default 'OPT',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`prepReqID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Prep_Req_tbl`
+--
+
+LOCK TABLES `Prep_Req_tbl` WRITE;
+/*!40000 ALTER TABLE `Prep_Req_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `Prep_Req_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Prep_tbl`
+--
+
+DROP TABLE IF EXISTS `Prep_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Prep_tbl` (
+  `prepID` int(11) NOT NULL auto_increment,
+  `isolate_pk` int(11) NOT NULL default '0',
+  `refAvailID` varchar(77) default NULL,
+  `wellID` int(11) default NULL,
+  `flag` enum('YES','NO') NOT NULL default 'NO',
+  `comments` tinytext,
+  `labID` int(11) NOT NULL default '1',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`prepID`),
+  KEY `prepID` (`prepID`),
+  KEY `isolate_pk` (`isolate_pk`),
+  KEY `refAvailID` (`refAvailID`),
+  KEY `wellID` (`wellID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Prep_tbl`
+--
+
+LOCK TABLES `Prep_tbl` WRITE;
+/*!40000 ALTER TABLE `Prep_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `Prep_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ProjectMembers_tbl`
+--
+
+DROP TABLE IF EXISTS `ProjectMembers_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ProjectMembers_tbl` (
+  `pmID` int(11) NOT NULL auto_increment,
+  `packetID` int(11) NOT NULL default '0',
+  `memberID` int(11) NOT NULL default '0',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  `role` enum('Reader','Writer') NOT NULL default 'Reader',
+  PRIMARY KEY  (`pmID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ProjectMembers_tbl`
+--
+
+LOCK TABLES `ProjectMembers_tbl` WRITE;
+/*!40000 ALTER TABLE `ProjectMembers_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ProjectMembers_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `PropertyReq_tbl`
+--
+
+DROP TABLE IF EXISTS `PropertyReq_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `PropertyReq_tbl` (
+  `propertyID` int(11) NOT NULL default '0',
+  `reagentTypeID` int(11) NOT NULL default '0',
+  `requirement` enum('REQ','OPT') NOT NULL default 'OPT',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`propertyID`,`reagentTypeID`),
+  KEY `reagentTypeID` (`reagentTypeID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `PropertyReq_tbl`
+--
+
+LOCK TABLES `PropertyReq_tbl` WRITE;
+/*!40000 ALTER TABLE `PropertyReq_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `PropertyReq_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ReagentPropList_tbl`
+--
+
+DROP TABLE IF EXISTS `ReagentPropList_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ReagentPropList_tbl` (
+  `propListID` int(11) NOT NULL auto_increment,
+  `reagentID` int(11) NOT NULL default '0',
+  `propertyID` int(11) NOT NULL default '0',
+  `propertyValue` text,
+  `labID` int(11) NOT NULL default '1',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  `startPos` int(11) default '0',
+  `endPos` int(11) default '0',
+  `direction` enum('forward','reverse') default 'forward',
+  `descriptor` text,
+  PRIMARY KEY  (`propListID`),
+  KEY `reagentID` (`reagentID`),
+  KEY `propertyID` (`propertyID`),
+  KEY `status` (`status`),
+  KEY `propListID` (`propListID`),
+  FULLTEXT KEY `propertyValue` (`propertyValue`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ReagentPropList_tbl`
+--
+
+LOCK TABLES `ReagentPropList_tbl` WRITE;
+/*!40000 ALTER TABLE `ReagentPropList_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `ReagentPropList_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ReagentPropTypeCategories_tbl`
+--
+
+DROP TABLE IF EXISTS `ReagentPropTypeCategories_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ReagentPropTypeCategories_tbl` (
+  `propertyCategoryID` int(11) NOT NULL auto_increment,
+  `propertyCategoryName` varchar(250) default NULL,
+  `status` enum('ACTIVE','DEP') default 'ACTIVE',
+  `propertyCategoryAlias` varchar(250) default NULL,
+  `ordering` int(11) NOT NULL default '2147483647',
+  PRIMARY KEY  (`propertyCategoryID`),
+  KEY `propertyCategoryName` (`propertyCategoryName`),
+  KEY `status` (`status`),
+  KEY `propertyCategoryAlias` (`propertyCategoryAlias`),
+  KEY `ordering` (`ordering`)
+) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ReagentPropTypeCategories_tbl`
+--
+
+LOCK TABLES `ReagentPropTypeCategories_tbl` WRITE;
+/*!40000 ALTER TABLE `ReagentPropTypeCategories_tbl` DISABLE KEYS */;
+INSERT INTO `ReagentPropTypeCategories_tbl` VALUES (1,'General Properties','ACTIVE','general_properties',1),(2,'DNA Sequence','ACTIVE','sequence_properties',2),(4,'External Identifiers','ACTIVE','externalIDs',4),(5,'Classifiers','ACTIVE','classifiers',5),(3,'DNA Sequence Features','ACTIVE','dna_sequence_features',3),(8,'RNA Sequence','ACTIVE','rna_sequence_properties',8),(6,'Protein Sequence','ACTIVE','protein_sequence_properties',6),(7,'Protein Sequence Features','ACTIVE','protein_seque [...]
+/*!40000 ALTER TABLE `ReagentPropTypeCategories_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ReagentPropType_tbl`
+--
+
+DROP TABLE IF EXISTS `ReagentPropType_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ReagentPropType_tbl` (
+  `propertyID` int(11) NOT NULL auto_increment,
+  `propertyName` varchar(250) NOT NULL default '',
+  `propertyAlias` varchar(250) default NULL,
+  `propertyDesc` tinytext,
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  `propertyColor` varchar(250) default NULL,
+  `ordering` int(11) default '2147483647',
+  PRIMARY KEY  (`propertyID`),
+  KEY `propertyName` (`propertyName`),
+  KEY `propertyType` (`propertyAlias`),
+  KEY `status` (`status`),
+  KEY `propertyID` (`propertyID`),
+  KEY `propertyAlias` (`propertyAlias`)
+) ENGINE=MyISAM AUTO_INCREMENT=73 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ReagentPropType_tbl`
+--
+
+LOCK TABLES `ReagentPropType_tbl` WRITE;
+/*!40000 ALTER TABLE `ReagentPropType_tbl` DISABLE KEYS */;
+INSERT INTO `ReagentPropType_tbl` VALUES (1,'5\' linker','5_prime_linker','5\' Linker','ACTIVE','#FF00FF',4),(2,'3\' linker','3_prime_linker','3\' Linker','ACTIVE','#FF00FF',5),(3,'status','status','Status','ACTIVE',NULL,2),(4,'verification','verification','Verification','ACTIVE',NULL,5),(5,'name','name','Name','ACTIVE',NULL,1),(6,'packet id','packet_id','Project ID','ACTIVE',NULL,3),(7,'tag','tag','Tag','ACTIVE','#008000',6),(8,'tag position','tag_position','Tag Position','ACTIVE',NULL, [...]
+/*!40000 ALTER TABLE `ReagentPropType_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ReagentPropertyCategories_tbl`
+--
+
+DROP TABLE IF EXISTS `ReagentPropertyCategories_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ReagentPropertyCategories_tbl` (
+  `propCatID` int(11) NOT NULL auto_increment,
+  `propID` int(11) NOT NULL,
+  `categoryID` int(11) NOT NULL,
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`propCatID`),
+  KEY `propID` (`propID`),
+  KEY `categoryID` (`categoryID`),
+  KEY `propCatID` (`propCatID`),
+  KEY `status` (`status`)
+) ENGINE=MyISAM AUTO_INCREMENT=2296 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ReagentPropertyCategories_tbl`
+--
+
+LOCK TABLES `ReagentPropertyCategories_tbl` WRITE;
+/*!40000 ALTER TABLE `ReagentPropertyCategories_tbl` DISABLE KEYS */;
+INSERT INTO `ReagentPropertyCategories_tbl` VALUES (2186,1,3,'ACTIVE'),(2187,2,3,'ACTIVE'),(2188,3,1,'ACTIVE'),(2189,4,1,'ACTIVE'),(2190,5,1,'ACTIVE'),(2191,6,1,'ACTIVE'),(2192,7,3,'ACTIVE'),(2193,8,3,'ACTIVE'),(2194,9,4,'ACTIVE'),(2195,12,1,'ACTIVE'),(2196,13,1,'ACTIVE'),(2197,14,3,'ACTIVE'),(2198,15,3,'ACTIVE'),(2199,17,1,'ACTIVE'),(2200,18,1,'ACTIVE'),(2201,19,3,'ACTIVE'),(2202,20,3,'ACTIVE'),(2203,21,5,'ACTIVE'),(2204,22,5,'ACTIVE'),(2205,23,2,'ACTIVE'),(2206,25,2,'ACTIVE'),(2207,26, [...]
+/*!40000 ALTER TABLE `ReagentPropertyCategories_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ReagentTypeAttribute_Set_tbl`
+--
+
+DROP TABLE IF EXISTS `ReagentTypeAttribute_Set_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ReagentTypeAttribute_Set_tbl` (
+  `ssetID` int(11) NOT NULL default '0',
+  `reagentTypeAttributeID` int(11) NOT NULL,
+  `status` enum('ACTIVE','DEP') default 'ACTIVE',
+  `reagentTypeAttributeSetID` int(11) NOT NULL auto_increment,
+  PRIMARY KEY  (`reagentTypeAttributeSetID`),
+  KEY `reagentTypeAttributeID` (`reagentTypeAttributeID`)
+) ENGINE=MyISAM AUTO_INCREMENT=3550 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ReagentTypeAttribute_Set_tbl`
+--
+
+LOCK TABLES `ReagentTypeAttribute_Set_tbl` WRITE;
+/*!40000 ALTER TABLE `ReagentTypeAttribute_Set_tbl` DISABLE KEYS */;
+INSERT INTO `ReagentTypeAttribute_Set_tbl` VALUES (1,4707,'ACTIVE',2523),(7,4707,'ACTIVE',2524),(4,4707,'ACTIVE',2525),(2,4707,'ACTIVE',2526),(5,4707,'ACTIVE',2527),(6,4707,'ACTIVE',2528),(3,4707,'ACTIVE',2529),(141,4775,'ACTIVE',2530),(142,4775,'ACTIVE',2531),(12,4776,'ACTIVE',2532),(722,4776,'ACTIVE',2533),(10,4776,'ACTIVE',2534),(8,4776,'ACTIVE',2535),(723,4776,'ACTIVE',2536),(724,4776,'ACTIVE',2537),(685,4781,'ACTIVE',2538),(686,4781,'ACTIVE',2539),(364,4808,'ACTIVE',2542),(367,4808, [...]
+/*!40000 ALTER TABLE `ReagentTypeAttribute_Set_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ReagentTypeAttributes_tbl`
+--
+
+DROP TABLE IF EXISTS `ReagentTypeAttributes_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ReagentTypeAttributes_tbl` (
+  `reagentTypePropertyID` int(11) NOT NULL auto_increment,
+  `reagentTypeID` int(11) NOT NULL,
+  `propertyTypeID` int(11) NOT NULL,
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  `ordering` int(11) NOT NULL default '1',
+  `is_multiple` enum('YES','NO') default 'NO',
+  `is_hyperlink` enum('YES','NO') NOT NULL default 'NO',
+  `is_customizeable` enum('YES','NO') NOT NULL default 'NO',
+  PRIMARY KEY  (`reagentTypePropertyID`),
+  KEY `reagentTypeID` (`reagentTypeID`),
+  KEY `status` (`status`),
+  KEY `propertyTypeID` (`propertyTypeID`),
+  KEY `reagentTypePropertyID` (`reagentTypePropertyID`)
+) ENGINE=MyISAM AUTO_INCREMENT=4941 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ReagentTypeAttributes_tbl`
+--
+
+LOCK TABLES `ReagentTypeAttributes_tbl` WRITE;
+/*!40000 ALTER TABLE `ReagentTypeAttributes_tbl` DISABLE KEYS */;
+INSERT INTO `ReagentTypeAttributes_tbl` VALUES (4700,1,2190,'ACTIVE',1,'NO','NO','NO'),(4701,1,2188,'ACTIVE',2,'NO','NO','NO'),(4702,1,2191,'ACTIVE',3,'NO','NO','NO'),(4703,2,2190,'ACTIVE',1,'NO','NO','NO'),(4704,3,2190,'ACTIVE',1,'NO','NO','NO'),(4705,4,2190,'ACTIVE',1,'NO','NO','NO'),(4706,2,2188,'ACTIVE',2,'NO','NO','NO'),(4707,3,2188,'ACTIVE',2,'NO','NO','NO'),(4708,4,2188,'ACTIVE',2,'NO','NO','NO'),(4709,2,2191,'ACTIVE',3,'NO','NO','NO'),(4710,3,2191,'ACTIVE',3,'NO','NO','NO'),(4711 [...]
+/*!40000 ALTER TABLE `ReagentTypeAttributes_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `ReagentType_tbl`
+--
+
+DROP TABLE IF EXISTS `ReagentType_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `ReagentType_tbl` (
+  `reagentTypeID` int(11) NOT NULL auto_increment,
+  `reagentTypeName` varchar(27) NOT NULL default '',
+  `reagent_prefix` varchar(27) NOT NULL default '',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`reagentTypeID`),
+  KEY `reagentTypeName` (`reagentTypeName`),
+  KEY `status` (`status`),
+  KEY `reagentTypeID` (`reagentTypeID`)
+) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `ReagentType_tbl`
+--
+
+LOCK TABLES `ReagentType_tbl` WRITE;
+/*!40000 ALTER TABLE `ReagentType_tbl` DISABLE KEYS */;
+INSERT INTO `ReagentType_tbl` VALUES (1,'Vector','V','ACTIVE'),(2,'Insert','I','ACTIVE'),(3,'Oligo','O','ACTIVE'),(4,'CellLine','C','ACTIVE');
+/*!40000 ALTER TABLE `ReagentType_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Reagent_SubType_tbl`
+--
+
+DROP TABLE IF EXISTS `Reagent_SubType_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Reagent_SubType_tbl` (
+  `reagent_SubTypeID` int(11) NOT NULL auto_increment,
+  `reagent_typeID` int(11) NOT NULL default '0',
+  `name` varchar(47) NOT NULL default '',
+  `alias` varchar(27) default NULL,
+  `affix` varchar(17) default NULL,
+  `labID` int(11) NOT NULL default '1',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`reagent_SubTypeID`)
+) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Reagent_SubType_tbl`
+--
+
+LOCK TABLES `Reagent_SubType_tbl` WRITE;
+/*!40000 ALTER TABLE `Reagent_SubType_tbl` DISABLE KEYS */;
+INSERT INTO `Reagent_SubType_tbl` VALUES (1,1,'Non-Recombination Vector','nonrecomb',NULL,1,'ACTIVE'),(2,1,'Creator Expression Vector via Recombination','recomb',NULL,1,'ACTIVE'),(3,1,'Novel Vector','novel',NULL,1,'ACTIVE'),(4,1,'Gateway Entry Vector','gateway_entry',NULL,1,'ACTIVE'),(5,1,'Gateway Expression Vector','gateway_expression',NULL,1,'ACTIVE'),(6,4,'Parent Cell Line','parent_cell_line',NULL,1,'ACTIVE'),(7,4,'Stable Cell Line','stable_cell_line',NULL,1,'ACTIVE');
+/*!40000 ALTER TABLE `Reagent_SubType_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Reagents_tbl`
+--
+
+DROP TABLE IF EXISTS `Reagents_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Reagents_tbl` (
+  `reagentID` int(11) NOT NULL auto_increment,
+  `reagentTypeID` int(11) NOT NULL default '0',
+  `reagent_SubTypeID` int(11) NOT NULL default '1',
+  `3rd_typing_id` int(11) NOT NULL default '0',
+  `groupID` int(11) NOT NULL default '0',
+  `creatorID` smallint(6) NOT NULL default '1',
+  `labID` int(11) NOT NULL default '1',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`reagentID`),
+  KEY `reagentID` (`reagentID`),
+  KEY `reagentTypeID` (`reagentTypeID`),
+  KEY `groupID` (`groupID`),
+  KEY `status` (`status`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Reagents_tbl`
+--
+
+LOCK TABLES `Reagents_tbl` WRITE;
+/*!40000 ALTER TABLE `Reagents_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `Reagents_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `SecuredPages_tbl`
+--
+
+DROP TABLE IF EXISTS `SecuredPages_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `SecuredPages_tbl` (
+  `pageID` int(11) NOT NULL auto_increment,
+  `section` varchar(150) NOT NULL default '',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  `baseURL` varchar(250) NOT NULL default '',
+  PRIMARY KEY  (`pageID`)
+) ENGINE=MyISAM AUTO_INCREMENT=47 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `SecuredPages_tbl`
+--
+
+LOCK TABLES `SecuredPages_tbl` WRITE;
+/*!40000 ALTER TABLE `SecuredPages_tbl` DISABLE KEYS */;
+INSERT INTO `SecuredPages_tbl` VALUES (1,'Home','ACTIVE','index.php'),(2,'Reagent Tracker','ACTIVE','Reagent.php'),(3,'Location Tracker','ACTIVE','Location.php'),(5,'Project Management','ACTIVE','Project.php'),(6,'User Management','ACTIVE','User.php'),(7,'Documentation','ACTIVE','Docs.php'),(8,'Terms and Conditions','ACTIVE','copyright.php'),(9,'Contact Us','ACTIVE','contacts.php'),(10,'Reagent Tracker','ACTIVE','search.php'),(12,'Lab Management','ACTIVE','User.php'),(13,'Search projects [...]
+/*!40000 ALTER TABLE `SecuredPages_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `SequenceType_tbl`
+--
+
+DROP TABLE IF EXISTS `SequenceType_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `SequenceType_tbl` (
+  `seqTypeID` int(11) NOT NULL auto_increment,
+  `seqTypeName` varchar(17) NOT NULL default '',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`seqTypeID`)
+) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `SequenceType_tbl`
+--
+
+LOCK TABLES `SequenceType_tbl` WRITE;
+/*!40000 ALTER TABLE `SequenceType_tbl` DISABLE KEYS */;
+INSERT INTO `SequenceType_tbl` VALUES (1,'DNA','ACTIVE'),(2,'Protein','ACTIVE'),(4,'RNA','ACTIVE');
+/*!40000 ALTER TABLE `SequenceType_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Sequences_tbl`
+--
+
+DROP TABLE IF EXISTS `Sequences_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Sequences_tbl` (
+  `seqID` int(11) NOT NULL auto_increment,
+  `seqTypeID` int(11) NOT NULL default '0',
+  `sequence` text NOT NULL,
+  `frame` smallint(6) NOT NULL default '0',
+  `length` int(11) default NULL,
+  `labID` int(11) NOT NULL default '1',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  `start` int(11) default NULL,
+  `end` int(11) default NULL,
+  `mw` double(65,2) default NULL,
+  PRIMARY KEY  (`seqID`),
+  KEY `seqID` (`seqID`),
+  FULLTEXT KEY `sequence` (`sequence`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Sequences_tbl`
+--
+
+LOCK TABLES `Sequences_tbl` WRITE;
+/*!40000 ALTER TABLE `Sequences_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `Sequences_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `System_Set_Groups_tbl`
+--
+
+DROP TABLE IF EXISTS `System_Set_Groups_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `System_Set_Groups_tbl` (
+  `ssetGroupID` int(11) NOT NULL auto_increment,
+  `groupDesc` tinytext,
+  `propertyIDLink` int(11) default NULL,
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`ssetGroupID`)
+) ENGINE=MyISAM AUTO_INCREMENT=75 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `System_Set_Groups_tbl`
+--
+
+LOCK TABLES `System_Set_Groups_tbl` WRITE;
+/*!40000 ALTER TABLE `System_Set_Groups_tbl` DISABLE KEYS */;
+INSERT INTO `System_Set_Groups_tbl` VALUES (1,'General Properties Status',2188,'ACTIVE'),(2,'General Properties Verification',2189,'ACTIVE'),(4,'DNA Sequence Features Expression System',2201,'ACTIVE'),(5,'DNA Sequence Features Promoter',2202,'ACTIVE'),(6,'DNA Sequence Features Tag',2192,'ACTIVE'),(7,'DNA Sequence Features Tag Position',2193,'ACTIVE'),(8,'General Properties Vector type',2219,'ACTIVE'),(9,'Classifiers Type of Insert',2220,'ACTIVE'),(10,'General Properties Cell Line Type',2 [...]
+/*!40000 ALTER TABLE `System_Set_Groups_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `System_Set_tbl`
+--
+
+DROP TABLE IF EXISTS `System_Set_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `System_Set_tbl` (
+  `ssetID` int(11) NOT NULL auto_increment,
+  `ssetGroupID` int(11) NOT NULL default '0',
+  `entityName` text NOT NULL,
+  `entityDesc` text,
+  `ordering` int(11) default NULL,
+  `labID` int(11) NOT NULL default '1',
+  `restriction` enum('YES','NO') NOT NULL default 'NO',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`ssetID`),
+  KEY `labID` (`labID`),
+  KEY `status` (`status`),
+  KEY `ssetGroupID` (`ssetGroupID`)
+) ENGINE=MyISAM AUTO_INCREMENT=1418 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `System_Set_tbl`
+--
+
+LOCK TABLES `System_Set_tbl` WRITE;
+/*!40000 ALTER TABLE `System_Set_tbl` DISABLE KEYS */;
+INSERT INTO `System_Set_tbl` VALUES (1,1,'Completed','Completed',1,1,'NO','ACTIVE'),(2,1,'In Progress','In Progress',1,1,'NO','ACTIVE'),(3,1,'Planning','Planning',1,1,'NO','ACTIVE'),(4,1,'Failed','Failed',1,1,'NO','ACTIVE'),(5,1,'Not Available','Not Available',1,1,'NO','ACTIVE'),(6,1,'Not Required','Not Required',1,1,'NO','ACTIVE'),(7,1,'Do Not Use','Do Not Use',1,1,'NO','ACTIVE'),(8,2,'Unverified','Unverified',1,1,'NO','ACTIVE'),(9,2,'RE Verified','RE Verified',1,1,'NO','ACTIVE'),(10,2, [...]
+/*!40000 ALTER TABLE `System_Set_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `UserCategories_tbl`
+--
+
+DROP TABLE IF EXISTS `UserCategories_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `UserCategories_tbl` (
+  `categoryID` int(11) NOT NULL auto_increment,
+  `category` varchar(250) NOT NULL default '',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`categoryID`)
+) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `UserCategories_tbl`
+--
+
+LOCK TABLES `UserCategories_tbl` WRITE;
+/*!40000 ALTER TABLE `UserCategories_tbl` DISABLE KEYS */;
+INSERT INTO `UserCategories_tbl` VALUES (1,'Admin','ACTIVE'),(2,'Creator','ACTIVE'),(3,'Writer','ACTIVE'),(4,'Reader','ACTIVE');
+/*!40000 ALTER TABLE `UserCategories_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `UserPermission_tbl`
+--
+
+DROP TABLE IF EXISTS `UserPermission_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `UserPermission_tbl` (
+  `userPermID` int(11) NOT NULL auto_increment,
+  `pageID` int(11) NOT NULL default '0',
+  `categoryID` int(11) NOT NULL default '0',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`userPermID`),
+  KEY `pageID` (`pageID`),
+  KEY `categoryID` (`categoryID`)
+) ENGINE=MyISAM AUTO_INCREMENT=47 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `UserPermission_tbl`
+--
+
+LOCK TABLES `UserPermission_tbl` WRITE;
+/*!40000 ALTER TABLE `UserPermission_tbl` DISABLE KEYS */;
+INSERT INTO `UserPermission_tbl` VALUES (1,1,4,'ACTIVE'),(2,2,4,'ACTIVE'),(3,3,4,'ACTIVE'),(5,5,3,'ACTIVE'),(6,6,4,'ACTIVE'),(7,7,4,'ACTIVE'),(8,8,4,'ACTIVE'),(9,9,4,'ACTIVE'),(10,10,4,'ACTIVE'),(12,12,1,'ACTIVE'),(13,13,3,'ACTIVE'),(14,14,3,'ACTIVE'),(15,15,4,'ACTIVE'),(16,16,2,'ACTIVE'),(17,17,3,'ACTIVE'),(18,18,4,'ACTIVE'),(21,21,2,'ACTIVE'),(22,22,2,'ACTIVE'),(23,23,1,'ACTIVE'),(24,24,1,'ACTIVE'),(25,25,1,'ACTIVE'),(26,26,1,'ACTIVE'),(27,27,4,'ACTIVE'),(30,30,4,'ACTIVE'),(34,34,4,'AC [...]
+/*!40000 ALTER TABLE `UserPermission_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Users_tbl`
+--
+
+DROP TABLE IF EXISTS `Users_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Users_tbl` (
+  `userID` int(11) NOT NULL auto_increment,
+  `username` varchar(27) NOT NULL default '',
+  `password` tinytext NOT NULL,
+  `email` tinytext,
+  `labID` int(11) NOT NULL default '1',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  `firstname` varchar(250) NOT NULL default '',
+  `lastname` varchar(250) NOT NULL default '',
+  `category` int(11) NOT NULL default '4',
+  `description` varchar(25) NOT NULL default '',
+  `position` enum('Student','Postdoc','Technical','RA','MS','Administrative','IT','PI','Other') default NULL,
+  PRIMARY KEY  (`userID`),
+  KEY `labID` (`labID`)
+) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Users_tbl`
+--
+
+LOCK TABLES `Users_tbl` WRITE;
+/*!40000 ALTER TABLE `Users_tbl` DISABLE KEYS */;
+INSERT INTO `Users_tbl` VALUES (1,'admin','21232f297a57a5a743894a0e4a801fc3','openfreezer.admin at lunenfeld.ca',1,'ACTIVE','','',1,'Administrator',NULL);
+/*!40000 ALTER TABLE `Users_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `WebTracker_tbl`
+--
+
+DROP TABLE IF EXISTS `WebTracker_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `WebTracker_tbl` (
+  `trackerID` int(11) NOT NULL auto_increment,
+  `timestamp` datetime default NULL,
+  `userIP` varchar(27) default NULL,
+  `userhost` varchar(27) default NULL,
+  `url` tinytext,
+  PRIMARY KEY  (`trackerID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `WebTracker_tbl`
+--
+
+LOCK TABLES `WebTracker_tbl` WRITE;
+/*!40000 ALTER TABLE `WebTracker_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `WebTracker_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `Wells_tbl`
+--
+
+DROP TABLE IF EXISTS `Wells_tbl`;
+SET @saved_cs_client     = @@character_set_client;
+SET character_set_client = utf8;
+CREATE TABLE `Wells_tbl` (
+  `wellID` int(11) NOT NULL auto_increment,
+  `containerID` int(11) NOT NULL default '0',
+  `wellCol` int(11) NOT NULL default '0',
+  `wellRow` int(11) NOT NULL default '0',
+  `do_not_use` enum('TRUE','FALSE') NOT NULL default 'FALSE',
+  `reserved` enum('TRUE','FALSE') NOT NULL default 'TRUE',
+  `creatorID` smallint(6) default '1',
+  `status` enum('ACTIVE','DEP') NOT NULL default 'ACTIVE',
+  PRIMARY KEY  (`wellID`),
+  KEY `wellID` (`wellID`),
+  KEY `containerID` (`containerID`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+SET character_set_client = @saved_cs_client;
+
+--
+-- Dumping data for table `Wells_tbl`
+--
+
+LOCK TABLES `Wells_tbl` WRITE;
+/*!40000 ALTER TABLE `Wells_tbl` DISABLE KEYS */;
+/*!40000 ALTER TABLE `Wells_tbl` ENABLE KEYS */;
+UNLOCK TABLES;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2012-01-13  0:04:21

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/openfreezer.git



More information about the debian-med-commit mailing list