diff --git a/ajax.php b/ajax.php
index 0786b41a43691fa1667212753c01d48d2fde05ad..57b6274ccee12f4292f97aa7df5b4f9c9cd938ce 100644
--- a/ajax.php
+++ b/ajax.php
@@ -34,6 +34,9 @@ $dispatcher = patterns('',
         url_post('^(?P<id>\d+)/attach$', 'uploadInlineImageClient'),
         url_get('^(?P<namespace>[\w.]+)$', 'getDraftClient'),
         url_post('^(?P<namespace>[\w.]+)$', 'createDraftClient')
+    )),
+    url('^/form/', patterns('ajax.forms.php:DynamicFormsAjaxAPI',
+        url_get('^help-topic/(?P<id>\d+)$', 'getClientFormsForHelpTopic')
     ))
 );
 print $dispatcher->resolve($ost->get_path_info());
diff --git a/assets/default/css/theme.css b/assets/default/css/theme.css
index 4a1af12ac59e2fab9b7179b1c4ba250ee50badd7..bacbd67a060e81c7888561e4fa396da1849c7e06 100644
--- a/assets/default/css/theme.css
+++ b/assets/default/css/theme.css
@@ -532,9 +532,11 @@ body {
   width: 140px;
   float: left;
 }
+label.required {
+  font-weight: bold;
+}
 #ticketForm div label.required,
 #clientLogin div label.required {
-  font-weight: bold;
   text-align: left;
 }
 #ticketForm div input,
diff --git a/bootstrap.php b/bootstrap.php
index b2540b15936cfc82778b024fb9a0b42a1d7ad31b..ac25ecf3142858bd636486b1685c6fdc7c43696f 100644
--- a/bootstrap.php
+++ b/bootstrap.php
@@ -65,6 +65,8 @@ class Bootstrap {
         define('FILE_CHUNK_TABLE',$prefix.'file_chunk');
 
         define('ATTACHMENT_TABLE',$prefix.'attachment');
+        define('USER_TABLE',$prefix.'user');
+        define('USER_EMAIL_TABLE',$prefix.'user_email');
 
         define('STAFF_TABLE',$prefix.'staff');
         define('TEAM_TABLE',$prefix.'team');
@@ -87,6 +89,15 @@ class Bootstrap {
         define('TICKET_PRIORITY_TABLE',$prefix.'ticket_priority');
         define('PRIORITY_TABLE',TICKET_PRIORITY_TABLE);
 
+        define('FORM_SEC_TABLE',$prefix.'form');
+        define('FORM_FIELD_TABLE',$prefix.'form_field');
+
+        define('LIST_TABLE',$prefix.'list');
+        define('LIST_ITEM_TABLE',$prefix.'list_items');
+
+        define('FORM_ENTRY_TABLE',$prefix.'form_entry');
+        define('FORM_ANSWER_TABLE',$prefix.'form_entry_values');
+
         define('TOPIC_TABLE',$prefix.'help_topic');
         define('SLA_TABLE', $prefix.'sla');
 
@@ -153,6 +164,27 @@ class Bootstrap {
             self::croak($ferror);
     }
 
+    function loadCode() {
+        #include required files
+        require(INCLUDE_DIR.'class.ostsession.php');
+        require(INCLUDE_DIR.'class.usersession.php');
+        require(INCLUDE_DIR.'class.pagenate.php'); //Pagenate helper!
+        require(INCLUDE_DIR.'class.log.php');
+        require(INCLUDE_DIR.'class.crypto.php');
+        require(INCLUDE_DIR.'class.timezone.php');
+        require(INCLUDE_DIR.'class.http.php');
+        require(INCLUDE_DIR.'class.signal.php');
+        require(INCLUDE_DIR.'class.nav.php');
+        require(INCLUDE_DIR.'class.page.php');
+        require_once(INCLUDE_DIR.'class.format.php'); //format helpers
+        require_once(INCLUDE_DIR.'class.validator.php'); //Class to help with basic form input validation...please help improve it.
+        require(INCLUDE_DIR.'class.mailer.php');
+        if (extension_loaded('mysqli'))
+            require_once INCLUDE_DIR.'mysqli.php';
+        else
+            require(INCLUDE_DIR.'mysql.php');
+    }
+
     function croak($message) {
         $msg = $message."\n\n".THISPAGE;
         Mailer::sendmail(ADMIN_EMAIL, 'osTicket Fatal Error', $msg,
@@ -174,7 +206,7 @@ define('I18N_DIR', INCLUDE_DIR.'i18n/');
 /*############## Do NOT monkey with anything else beyond this point UNLESS you really know what you are doing ##############*/
 
 #Current version && schema signature (Changes from version to version)
-define('THIS_VERSION','1.8.0-devel'); //Shown on admin panel
+define('THIS_VERSION','1.8-git'); //Shown on admin panel
 //Path separator
 if(!defined('PATH_SEPARATOR')){
     if(strpos($_ENV['OS'],'Win')!==false || !strcasecmp(substr(PHP_OS, 0, 3),'WIN'))
@@ -187,6 +219,7 @@ if(!defined('PATH_SEPARATOR')){
 ini_set('include_path', './'.PATH_SEPARATOR.INCLUDE_DIR.PATH_SEPARATOR.PEAR_DIR);
 
 require(INCLUDE_DIR.'class.osticket.php');
+require(INCLUDE_DIR.'class.misc.php');
 
 // Determine the path in the URI used as the base of the osTicket
 // installation
@@ -195,26 +228,6 @@ if (!defined('ROOT_PATH') && ($rp = osTicket::get_root_path(dirname(__file__))))
 
 Bootstrap::init();
 
-#include required files
-require(INCLUDE_DIR.'class.ostsession.php');
-require(INCLUDE_DIR.'class.usersession.php');
-require(INCLUDE_DIR.'class.pagenate.php'); //Pagenate helper!
-require(INCLUDE_DIR.'class.log.php');
-require(INCLUDE_DIR.'class.crypto.php');
-require(INCLUDE_DIR.'class.misc.php');
-require(INCLUDE_DIR.'class.timezone.php');
-require(INCLUDE_DIR.'class.http.php');
-require(INCLUDE_DIR.'class.signal.php');
-require(INCLUDE_DIR.'class.nav.php');
-require(INCLUDE_DIR.'class.page.php');
-require(INCLUDE_DIR.'class.format.php'); //format helpers
-require(INCLUDE_DIR.'class.validator.php'); //Class to help with basic form input validation...please help improve it.
-require(INCLUDE_DIR.'class.mailer.php');
-if (extension_loaded('mysqli'))
-    require_once INCLUDE_DIR.'mysqli.php';
-else
-    require(INCLUDE_DIR.'mysql.php');
-
 #CURRENT EXECUTING SCRIPT.
 define('THISPAGE', Misc::currentURL());
 define('THISURI', $_SERVER['REQUEST_URI']);
diff --git a/css/osticket.css b/css/osticket.css
index 87e6c6aed4b382095e42199f41a00f35bea32621..8b986fef422772ae58c24cbaed324763e8171c03 100644
--- a/css/osticket.css
+++ b/css/osticket.css
@@ -43,3 +43,10 @@
     display: block;
     opacity: 0.3;
 }
+
+div.section-break {
+    margin-top: 1em;
+    margin-bottom: 0.5em;
+    padding-top: 0.8em !important;
+    border-top: 1px solid #ccc;
+}
diff --git a/include/ajax.config.php b/include/ajax.config.php
index 7f2be0617f3d37f7df7484c5b4e2e5d44f98b407..bf4174fe8e6ff53150f8fe77fff541010b4f0e37 100644
--- a/include/ajax.config.php
+++ b/include/ajax.config.php
@@ -35,7 +35,7 @@ class ConfigAjaxAPI extends AjaxController {
         global $cfg;
 
         $config=array(
-            'allow_attachments' => (bool) $cfg->allowOnlineAttachments,
+            'allow_attachments' => (bool) $cfg->allowOnlineAttachments(),
             'file_types'      => $cfg->getAllowedFileTypes(),
             'max_file_size'   => (int) $cfg->getMaxFileSize(),
             'max_file_uploads'=> (int) $cfg->getClientMaxFileUploads(),
diff --git a/include/ajax.content.php b/include/ajax.content.php
index 197d75ffe50c622296ca0bb22335874773fb499b..2451880ac8da4494fa44e690d07daa2926a4d7a8 100644
--- a/include/ajax.content.php
+++ b/include/ajax.content.php
@@ -49,7 +49,8 @@ class ContentAjaxAPI extends AjaxController {
                     <tr><td width="130">%{ticket.id}</td><td>Ticket ID (internal ID)</td></tr>
                     <tr><td>%{ticket.number}</td><td>Ticket number (external ID)</td></tr>
                     <tr><td>%{ticket.email}</td><td>Email address</td></tr>
-                    <tr><td>%{ticket.name}</td><td>Full name</td></tr>
+                    <tr><td>%{ticket.name}</td><td>Full name &mdash;
+                        <em>see name expansion</em></td></tr>
                     <tr><td>%{ticket.subject}</td><td>Subject</td></tr>
                     <tr><td>%{ticket.phone}</td><td>Phone number | ext</td></tr>
                     <tr><td>%{ticket.status}</td><td>Status</td></tr>
@@ -80,6 +81,18 @@ class ContentAjaxAPI extends AjaxController {
                     <tr><td>%{reset_link}</td>
                         <td>Reset link used by the password reset feature</td></tr>
                 </table>
+                <table width="100%" border="0" cellspacing=1 cellpadding=1>
+                    <tr><td colspan="2"><b>Name Expansion</b></td></tr>
+                    <tr><td>.first</td><td>First Name</td></tr>
+                    <tr><td>.middle</td><td>Middle Name(s)</td></tr>
+                    <tr><td>.last</td><td>Last Name</td></tr>
+                    <tr><td>.full</td><td>First Last</td></tr>
+                    <tr><td>.legal</td><td>First M. Last</td></tr>
+                    <tr><td>.short</td><td>First L.</td></tr>
+                    <tr><td>.formal</td><td>Mr. Last</td></tr>
+                    <tr><td>.shortformal</td><td>F. Last</td></tr>
+                    <tr><td>.lastfirst</td><td>Last, First</td></tr>
+                </table>
             </td>
         </tr>
     </table>
diff --git a/include/ajax.forms.php b/include/ajax.forms.php
new file mode 100644
index 0000000000000000000000000000000000000000..a04c327a0f9153135cc57dfdc7099d6b6b3da0fd
--- /dev/null
+++ b/include/ajax.forms.php
@@ -0,0 +1,95 @@
+<?php
+
+require_once(INCLUDE_DIR . 'class.topic.php');
+require_once(INCLUDE_DIR . 'class.dynamic_forms.php');
+
+class DynamicFormsAjaxAPI extends AjaxController {
+    function getForm($form_id) {
+        $form = DynamicForm::lookup($form_id);
+        if (!$form) return;
+
+        foreach ($form->getFields() as $field) {
+            $field->render();
+        }
+    }
+
+    function getFormsForHelpTopic($topic_id, $client=false) {
+        $topic = Topic::lookup($topic_id);
+        if ($topic->ht['form_id']
+                && ($form = DynamicForm::lookup($topic->ht['form_id'])))
+            $form->render(!$client);
+    }
+
+    function getClientFormsForHelpTopic($topic_id) {
+        return $this->getFormsForHelpTopic($topic_id, true);
+    }
+
+    function getFieldConfiguration($field_id) {
+        $field = DynamicFormField::lookup($field_id);
+        include(STAFFINC_DIR . 'templates/dynamic-field-config.tmpl.php');
+    }
+
+    function saveFieldConfiguration($field_id) {
+        $field = DynamicFormField::lookup($field_id);
+        if (!$field->setConfiguration())
+            include(STAFFINC_DIR . 'templates/dynamic-field-config.tmpl.php');
+        else
+            $field->save();
+    }
+
+    function getUserInfo($user_id) {
+        $user = User::lookup($user_id);
+
+        $data = $user->ht;
+        $data['email'] = $user->default_email->address;
+
+        $custom = array();
+        foreach ($user->getDynamicData() as $cd) {
+            $cd->addMissingFields();
+            foreach ($cd->getFields() as $f) {
+                if ($f->get('name') == 'name')
+                    $f->value = $user->getFullName();
+                elseif ($f->get('name') == 'email')
+                    $f->value = $user->getEmail();
+            }
+            $custom[] = $cd->getForm();
+        }
+
+        include(STAFFINC_DIR . 'templates/user-info.tmpl.php');
+    }
+
+    function saveUserInfo($user_id) {
+        $user = User::lookup($user_id);
+
+        $custom_data = $user->getDynamicData();
+        $custom = array();
+        $valid = true;
+        foreach ($custom_data as $cd) {
+            $cd->addMissingFields();
+            $cf = $custom[] = $cd->getForm();
+            $valid &= $cd->isValid();
+        }
+
+        if (!$valid) {
+            include(STAFFINC_DIR . 'templates/user-info.tmpl.php');
+            return;
+        }
+
+        // Save custom data
+        foreach ($custom_data as $cd) {
+            foreach ($cd->getFields() as $f) {
+                if ($f->get('name') == 'name') {
+                    $user->name = $f->getClean();
+                    $user->save();
+                }
+                elseif ($f->get('name') == 'email') {
+                    $user->default_email->address = $f->getClean();
+                    $user->default_email->save();
+                }
+            }
+            $cd->save();
+        }
+    }
+}
+
+?>
diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php
index 34c46325ed84d304c7a8c031bb8a5b686ea337a1..0f373efd613e3ac9cd90c792de1aee0b1f16582e 100644
--- a/include/ajax.tickets.php
+++ b/include/ajax.tickets.php
@@ -17,6 +17,7 @@
 if(!defined('INCLUDE_DIR')) die('403');
 
 include_once(INCLUDE_DIR.'class.ticket.php');
+require_once(INCLUDE_DIR.'class.ajax.php');
 
 class TicketsAjaxAPI extends AjaxController {
 
@@ -30,8 +31,10 @@ class TicketsAjaxAPI extends AjaxController {
         $limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25;
         $tickets=array();
 
-        $sql='SELECT DISTINCT ticketID, email'
-            .' FROM '.TICKET_TABLE
+        $sql='SELECT DISTINCT ticketID, email.address AS email'
+            .' FROM '.TICKET_TABLE.' ticket'
+            .' LEFT JOIN '.USER_TABLE.' user ON user.id = ticket.user_id'
+            .' LEFT JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id'
             .' WHERE ticketID LIKE \''.db_input($_REQUEST['q'], false).'%\'';
 
         $sql.=' AND ( staff_id='.db_input($thisstaff->getId());
@@ -43,12 +46,17 @@ class TicketsAjaxAPI extends AjaxController {
             $sql.=' OR dept_id IN ('.implode(',', db_input($depts)).')';
 
         $sql.=' )  '
-            .' ORDER BY created  LIMIT '.$limit;
+            .' ORDER BY ticket.created LIMIT '.$limit;
 
         if(($res=db_query($sql)) && db_num_rows($res)) {
-            while(list($id, $email)=db_fetch_row($res))
-                $tickets[] = array('id'=>$id, 'email'=>$email, 'value'=>$id, 'info'=>"$id - $email");
+            while(list($id, $email)=db_fetch_row($res)) {
+                $info = "$id - $email";
+                $tickets[] = array('id'=>$id, 'email'=>$email, 'value'=>$id,
+                    'info'=>$info, 'matches'=>$_REQUEST['q']);
+            }
         }
+        if (!$tickets)
+            return self::lookupByEmail();
 
         return $this->json_encode($tickets);
     }
@@ -60,9 +68,15 @@ class TicketsAjaxAPI extends AjaxController {
         $limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25;
         $tickets=array();
 
-        $sql='SELECT email, count(ticket_id) as tickets '
-            .' FROM '.TICKET_TABLE
-            .' WHERE email LIKE \'%'.db_input(strtolower($_REQUEST['q']), false).'%\' ';
+        $sql='SELECT email.address AS email, count(ticket.ticket_id) as tickets '
+            .' FROM '.TICKET_TABLE.' ticket'
+            .' JOIN '.USER_TABLE.' user ON user.id = ticket.user_id'
+            .' JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id'
+            .' LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON (entry.object_id = user.id
+                AND entry.object_type=\'U\')
+               LEFT JOIN '.FORM_ANSWER_TABLE.' data ON (data.entry_id = entry.id)'
+            .' WHERE (email.address LIKE \'%'.db_input(strtolower($_REQUEST['q']), false).'%\'
+                OR data.value LIKE \'%'.db_input($_REQUEST['q'], false).'%\')';
 
         $sql.=' AND ( staff_id='.db_input($thisstaff->getId());
 
@@ -73,22 +87,23 @@ class TicketsAjaxAPI extends AjaxController {
             $sql.=' OR dept_id IN ('.implode(',', db_input($depts)).')';
 
         $sql.=' ) '
-            .' GROUP BY email '
-            .' ORDER BY created  LIMIT '.$limit;
+            .' GROUP BY email.address '
+            .' ORDER BY ticket.created  LIMIT '.$limit;
 
         if(($res=db_query($sql)) && db_num_rows($res)) {
             while(list($email, $count)=db_fetch_row($res))
-                $tickets[] = array('email'=>$email, 'value'=>$email, 'info'=>"$email ($count)");
+                $tickets[] = array('email'=>$email, 'value'=>$email,
+                    'info'=>"$email ($count)", 'matches'=>$_REQUEST['q']);
         }
 
         return $this->json_encode($tickets);
     }
 
-    function search() {
+    function _search($req) {
         global $thisstaff, $cfg;
 
         $result=array();
-        $select = 'SELECT count( DISTINCT ticket.ticket_id) as tickets ';
+        $select = 'SELECT DISTINCT ticket.ticket_id';
         $from = ' FROM '.TICKET_TABLE.' ticket ';
         $where = ' WHERE 1 ';
 
@@ -104,15 +119,15 @@ class TicketsAjaxAPI extends AjaxController {
         $where.=' ) ';
 
         //Department
-        if($_REQUEST['deptId'])
-            $where.=' AND ticket.dept_id='.db_input($_REQUEST['deptId']);
+        if($req['deptId'])
+            $where.=' AND ticket.dept_id='.db_input($req['deptId']);
 
         //Help topic
-        if($_REQUEST['topicId'])
-            $where.=' AND ticket.topic_id='.db_input($_REQUEST['topicId']);
+        if($req['topicId'])
+            $where.=' AND ticket.topic_id='.db_input($req['topicId']);
 
         //Status
-        switch(strtolower($_REQUEST['status'])) {
+        switch(strtolower($req['status'])) {
             case 'open':
                 $where.=' AND ticket.status="open" ';
                 break;
@@ -128,9 +143,9 @@ class TicketsAjaxAPI extends AjaxController {
         }
 
         //Assignee
-        if(isset($_REQUEST['assignee']) && strcasecmp($_REQUEST['status'], 'closed'))  {
-            $id=preg_replace("/[^0-9]/", "", $_REQUEST['assignee']);
-            $assignee = $_REQUEST['assignee'];
+        if(isset($req['assignee']) && strcasecmp($req['status'], 'closed'))  {
+            $id=preg_replace("/[^0-9]/", "", $req['assignee']);
+            $assignee = $req['assignee'];
             $where.= ' AND ( ( ticket.status="open" ';
             if($assignee[0]=='t')
                 $where.=' AND ticket.team_id='.db_input($id);
@@ -141,19 +156,19 @@ class TicketsAjaxAPI extends AjaxController {
 
             $where.=')';
 
-            if($_REQUEST['staffId'] && !$_REQUEST['status']) //Assigned TO + Closed By
-                $where.= ' OR (ticket.staff_id='.db_input($_REQUEST['staffId']). ' AND ticket.status="closed") ';
-            elseif(isset($_REQUEST['staffId'])) // closed by any
+            if($req['staffId'] && !$req['status']) //Assigned TO + Closed By
+                $where.= ' OR (ticket.staff_id='.db_input($req['staffId']). ' AND ticket.status="closed") ';
+            elseif(isset($req['staffId'])) // closed by any
                 $where.= ' OR ticket.status="closed" ';
 
             $where.= ' ) ';
-        } elseif($_REQUEST['staffId']) {
-            $where.=' AND (ticket.staff_id='.db_input($_REQUEST['staffId']).' AND ticket.status="closed") ';
+        } elseif($req['staffId']) {
+            $where.=' AND (ticket.staff_id='.db_input($req['staffId']).' AND ticket.status="closed") ';
         }
 
         //dates
-        $startTime  =($_REQUEST['startDate'] && (strlen($_REQUEST['startDate'])>=8))?strtotime($_REQUEST['startDate']):0;
-        $endTime    =($_REQUEST['endDate'] && (strlen($_REQUEST['endDate'])>=8))?strtotime($_REQUEST['endDate']):0;
+        $startTime  =($req['startDate'] && (strlen($req['startDate'])>=8))?strtotime($req['startDate']):0;
+        $endTime    =($req['endDate'] && (strlen($req['endDate'])>=8))?strtotime($req['endDate']):0;
         if( ($startTime && $startTime>time()) or ($startTime>$endTime && $endTime>0))
             $startTime=$endTime=0;
 
@@ -164,23 +179,65 @@ class TicketsAjaxAPI extends AjaxController {
             $where.=' AND ticket.created<=FROM_UNIXTIME('.$endTime.')';
 
         //Query
-        if($_REQUEST['query']) {
-            $queryterm=db_real_escape($_REQUEST['query'], false);
-
-            $from.=' LEFT JOIN '.TICKET_THREAD_TABLE.' thread ON (ticket.ticket_id=thread.ticket_id )';
-            $where.=" AND (  ticket.email LIKE '%$queryterm%'"
-                       ." OR ticket.name LIKE '%$queryterm%'"
-                       ." OR ticket.subject LIKE '%$queryterm%'"
+        if($req['query']) {
+            $queryterm=db_real_escape($req['query'], false);
+
+            $from.=' LEFT JOIN '.TICKET_THREAD_TABLE.' thread ON (ticket.ticket_id=thread.ticket_id )'
+                .' LEFT JOIN '.FORM_ENTRY_TABLE.' tentry ON (tentry.object_id = ticket.ticket_id
+                   AND tentry.object_type="T")
+                   LEFT JOIN '.FORM_ANSWER_TABLE.' tans ON (tans.entry_id = tentry.id
+                   AND tans.value_id IS NULL)
+                   LEFT JOIN '.FORM_ENTRY_TABLE.' uentry ON (uentry.object_id = ticket.user_id
+                   AND uentry.object_type="U")
+                   LEFT JOIN '.FORM_ANSWER_TABLE.' uans ON (uans.entry_id = uentry.id
+                   AND uans.value_id IS NULL)
+                   LEFT JOIN '.USER_TABLE.' user ON (ticket.user_id = user.id)
+                   LEFT JOIN '.USER_EMAIL_TABLE.' uemail ON (user.id = uemail.user_id)';
+
+            $where.=" AND (  uemail.address LIKE '%$queryterm%'"
+                       ." OR user.name LIKE '%$queryterm%'"
+                       ." OR tans.value LIKE '%$queryterm%'"
+                       ." OR uans.value LIKE '%$queryterm%'"
                        ." OR thread.title LIKE '%$queryterm%'"
                        ." OR thread.body LIKE '%$queryterm%'"
                        .' )';
         }
 
+        // Dynamic fields
+        $dynfields='(SELECT entry.object_id, value, value_id FROM '.FORM_ANSWER_TABLE.' ans '.
+             'LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON entry.id=ans.entry_id '.
+             'LEFT JOIN '.FORM_FIELD_TABLE.' field ON field.id=ans.field_id '.
+             'WHERE field.name = %1$s AND entry.object_type="T")';
+        foreach (TicketForm::getInstance()->getFields() as $f) {
+            if ($f->get('name') && isset($req[$f->getFormName()])
+                    && ($val = $req[$f->getFormName()])) {
+                $name = 'dyn_'.$f->get('id');
+                $from .= ' LEFT JOIN '.sprintf($dynfields, db_input($f->get('name')))
+                    ." $name ON ($name.object_id = ticket.ticket_id)";
+                $where .= " AND ($name.value_id = ".db_input($val)
+                    . " OR $name.value LIKE '%".db_real_escape($val)."%')";
+            }
+        }
+
         $sql="$select $from $where";
-        if(($tickets=db_result(db_query($sql)))) {
-            $result['success'] =sprintf("Search criteria matched %s - <a href='tickets.php?%s'>view</a>",
-                                        ($tickets>1?"$tickets tickets":"$tickets ticket"),
-                                        str_replace(array('&amp;', '&'), array('&', '&amp;'), $_SERVER['QUERY_STRING']));
+        $res = db_query($sql);
+        while (list($tickets[]) = db_fetch_row($res));
+        $tickets = array_filter($tickets);
+
+        return $tickets;
+    }
+
+    function search() {
+        $tickets = self::_search($_REQUEST);
+
+        if (count($tickets)) {
+            $uid = md5($_SERVER['QUERY_STRING']);
+            $_SESSION["adv_$uid"] = $tickets;
+            $result['success'] =sprintf(
+                "Search criteria matched %d %s - <a href='tickets.php?%s'>view</a>",
+                count($tickets), (count($tickets)>1?"tickets":"ticket"),
+                'advsid='.$uid
+            );
         } else {
             $result['fail']='No tickets found matching your search criteria.';
         }
diff --git a/include/ajax.users.php b/include/ajax.users.php
index d18f3c3323b889b3e155575b608f2e75fea61dd8..a075ff42176d219726c7d3323a20093c673a6f86 100644
--- a/include/ajax.users.php
+++ b/include/ajax.users.php
@@ -31,9 +31,10 @@ class UsersAjaxAPI extends AjaxController {
         $limit = isset($_REQUEST['limit']) ? (int) $_REQUEST['limit']:25;
         $users=array();
 
-        $sql='SELECT DISTINCT email, name '
-            .' FROM '.TICKET_TABLE
-            .' WHERE email LIKE \'%'.db_input(strtolower($_REQUEST['q']), false).'%\' '
+        $sql='SELECT DISTINCT email.address, name '
+            .' FROM '.USER_TABLE.' user '
+            .' JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id '
+            .' WHERE email.address LIKE \'%'.db_input(strtolower($_REQUEST['q']), false).'%\' '
             .' ORDER BY created '
             .' LIMIT '.$limit;
            
diff --git a/include/api.tickets.php b/include/api.tickets.php
index f49680ce7f60c62b9e61cfe5d6fdbd8e21f7ab44..81dac7a927134e11e090cc1e356b42e82064b915 100644
--- a/include/api.tickets.php
+++ b/include/api.tickets.php
@@ -8,15 +8,25 @@ class TicketApiController extends ApiController {
     # Supported arguments -- anything else is an error. These items will be
     # inspected _after_ the fixup() method of the ApiXxxDataParser classes
     # so that all supported input formats should be supported
-    function getRequestStructure($format) {
+    function getRequestStructure($format, $data=null) {
         $supported = array(
             "alert", "autorespond", "source", "topicId",
-            "name", "email", "subject", "phone", "phone_ext",
             "attachments" => array("*" =>
                 array("name", "type", "data", "encoding")
             ),
             "message", "ip", "priorityId"
         );
+        # Fetch dynamic form field names for the given help topic and add
+        # the names to the supported request structure
+        if (isset($data['topicId'])) {
+            $topic=Topic::lookup($data['topicId']);
+            $form=DynamicForm::lookup($topic->ht['form_id']);
+            foreach ($form->getDynamicFields() as $field)
+                $supported[] = $field->get('name');
+        }
+        $form = TicketForm::lookup()->instanciate();
+        foreach ($form->getDynamicFields() as $field)
+            $supported[] = $field->get('name');
 
         if(!strcasecmp($format, 'email')) {
             $supported = array_merge($supported, array('header', 'mid',
@@ -90,6 +100,15 @@ class TicketApiController extends ApiController {
 
         # Create the ticket with the data (attempt to anyway)
         $errors = array();
+
+        if ($topic=Topic::lookup($data['topicId'])) {
+            if ($form=DynamicForm::lookup($topic->ht['form_id'])) {
+                $form = $form->instanciate();
+                if (!$form->isValid())
+                    $errors += $form->errors();
+            }
+        }
+
         $ticket = Ticket::create($data, $errors, $data['source'], $autorespond, $alert);
         # Return errors (?)
         if (count($errors)) {
@@ -105,6 +124,12 @@ class TicketApiController extends ApiController {
             return $this->exerr(500, "Unable to create new ticket: unknown error");
         }
 
+        # Save dynamic form
+        if (isset($form)) {
+            $form->setTicketId($ticket->getId());
+            $form->save();
+        }
+
         return $ticket;
     }
 
diff --git a/include/class.api.php b/include/class.api.php
index 019d3fba39e46286e98cbe6664e229645e88adfc..418b8da76824c3574b89a508bd298bcccfa1476f 100644
--- a/include/class.api.php
+++ b/include/class.api.php
@@ -235,7 +235,7 @@ class ApiController {
      * Structure to validate the request against -- must be overridden to be
      * useful
      */
-    function getRequestStructure($format) { return array(); }
+    function getRequestStructure($format, $data=null) { return array(); }
     /**
      * Simple validation that makes sure the keys of a parsed request are
      * expected. It is assumed that the functions actually implementing the
@@ -266,7 +266,7 @@ class ApiController {
     function validate(&$data, $format) {
         return $this->validateRequestStructure(
                 $data,
-                $this->getRequestStructure($format)
+                $this->getRequestStructure($format, $data)
                 );
     }
 
diff --git a/include/class.client.php b/include/class.client.php
index 5ff5911c26297cea963bf37b50e66ee955ba9b1f..3ee32c8f73f331ee5979fafebcc508a728066040 100644
--- a/include/class.client.php
+++ b/include/class.client.php
@@ -24,6 +24,8 @@ class Client {
     var $username;
     var $email;
 
+    var $_answers;
+
     var $ticket_id;
     var $ticketID;
 
@@ -40,11 +42,14 @@ class Client {
         if(!$id && !($id=$this->getId()))
             return false;
 
-        $sql='SELECT ticket_id, ticketID, name, email, phone, phone_ext '
-            .' FROM '.TICKET_TABLE
+        $sql='SELECT ticket.ticket_id, ticketID, email.address as email '
+            .' FROM '.TICKET_TABLE.' ticket '
+            .' LEFT JOIN '.USER_TABLE.' user ON user.id = ticket.user_id'
+            .' LEFT JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id'
             .' WHERE ticketID='.db_input($id);
+
         if($email)
-            $sql.=' AND email='.db_input($email);
+            $sql.=' AND email.address = '.db_input($email);
 
         if(!($res=db_query($sql)) || !db_num_rows($res))
             return NULL;
@@ -53,15 +58,26 @@ class Client {
         $this->id         = $this->ht['ticketID']; //placeholder
         $this->ticket_id  = $this->ht['ticket_id'];
         $this->ticketID   = $this->ht['ticketID'];
-        $this->fullname   = ucfirst($this->ht['name']);
+
+        $user = User::lookup(array('emails__address'=>$this->ht['email']));
+        $this->fullname   = $user->getFullName();
+
         $this->username   = $this->ht['email'];
         $this->email      = $this->ht['email'];
 
         $this->stats = array();
-      
+
         return($this->id);
     }
 
+    function loadDynamicData() {
+        $this->_answers = array();
+        foreach (DynamicFormEntry::forClient($this->getId()) as $form)
+            foreach ($form->getAnswers() as $answer)
+                $this->_answers[$answer->getField()->get('name')] =
+                    $answer->getValue();
+    }
+
     function reload() {
         return $this->load();
     }
@@ -87,13 +103,9 @@ class Client {
     }
 
     function getPhone() {
-        return $this->ht['phone'];
+        return $this->_answers['phone'];
     }
 
-    function getPhoneExt() {
-        return $this->ht['phone_ext'];
-    }
-    
     function getTicketID() {
         return $this->ticketID;
     }
@@ -120,9 +132,11 @@ class Client {
 
     /* ------------- Static ---------------*/
     function getLastTicketIdByEmail($email) {
-        $sql='SELECT ticketID FROM '.TICKET_TABLE
-            .' WHERE email='.db_input($email)
-            .' ORDER BY created '
+        $sql='SELECT ticket.ticketID '.TICKET_TABLE.' ticket '
+            .' LEFT JOIN '.USER_TABLE.' user ON user.id = ticket.user_id'
+            .' LEFT JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id'
+            .' WHERE email.address = '.db_input($email)
+            .' ORDER BY ticket.created '
             .' LIMIT 1';
         if(($res=db_query($sql)) && db_num_rows($res))
             list($tid) = db_fetch_row($res);
@@ -175,12 +189,12 @@ class Client {
         //See if we can fetch local ticket id associated with the ID given
         if(($ticket=Ticket::lookupByExtId($ticketID, $email)) && $ticket->getId()) {
             //At this point we know the ticket ID is valid.
-            //TODO: 1) Check how old the ticket is...3 months max?? 2) Must be the latest 5 tickets?? 
+            //TODO: 1) Check how old the ticket is...3 months max?? 2) Must be the latest 5 tickets??
             //Check the email given.
 
             # Require auth token for automatic logins (GET METHOD).
             if (!strcasecmp($ticket->getEmail(), $email) && (!$auto_login || $auth === $ticket->getAuthToken())) {
-                    
+
                 //valid match...create session goodies for the client.
                 $user = new ClientSession($email,$ticket->getExtId());
                 $_SESSION['_client'] = array(); //clear.
@@ -193,7 +207,7 @@ class Client {
                 //Log login info...
                 $msg=sprintf('%s/%s logged in [%s]', $ticket->getEmail(), $ticket->getExtId(), $_SERVER['REMOTE_ADDR']);
                 $ost->logDebug('User login', $msg);
-        
+
                 //Regenerate session ID.
                 $sid=session_id(); //Current session id.
                 session_regenerate_id(TRUE); //get new ID.
@@ -202,7 +216,7 @@ class Client {
 
                 return $user;
 
-            } 
+            }
         }
 
         //If we get to this point we know the login failed.
diff --git a/include/class.config.php b/include/class.config.php
index 5d0c8160fda9113de06af83bcf58482d0ad996e8..acd72ca3066f160618fad11970a93d7aa17f1372 100644
--- a/include/class.config.php
+++ b/include/class.config.php
@@ -146,6 +146,7 @@ class OsticketConfig extends Config {
         'allow_email_attachments' => true,
         'allow_online_attachments' => true,
         'allow_online_attachments_onlogin' => false,
+        'name_format' =>        'full', # First Last
     );
 
     function OsticketConfig($section=null) {
@@ -326,6 +327,10 @@ class OsticketConfig extends Config {
         return $this->get('autolock_minutes');
     }
 
+    function getDefaultNameFormat() {
+        return $this->get('name_format');
+    }
+
     function getDefaultDeptId() {
         return $this->get('default_dept_id');
     }
@@ -519,11 +524,6 @@ class OsticketConfig extends Config {
         return ($this->get('enable_mail_polling'));
     }
 
-    function allowPriorityChange() {
-        return ($this->get('allow_priority_change'));
-    }
-
-
     function useEmailPriority() {
         return ($this->get('use_email_priority'));
     }
@@ -768,7 +768,6 @@ class OsticketConfig extends Config {
         $f['helpdesk_url']=array('type'=>'string',   'required'=>1, 'error'=>'Helpdesk URl required');
         $f['helpdesk_title']=array('type'=>'string',   'required'=>1, 'error'=>'Helpdesk title required');
         $f['default_dept_id']=array('type'=>'int',   'required'=>1, 'error'=>'Default Dept. required');
-        $f['default_template_id']=array('type'=>'int',   'required'=>1, 'error'=>'You must select template.');
         $f['staff_session_timeout']=array('type'=>'int',   'required'=>1, 'error'=>'Enter idle time in minutes');
         $f['client_session_timeout']=array('type'=>'int',   'required'=>1, 'error'=>'Enter idle time in minutes');
         //Date & Time Options
@@ -789,10 +788,10 @@ class OsticketConfig extends Config {
             'helpdesk_title'=>$vars['helpdesk_title'],
             'helpdesk_url'=>$vars['helpdesk_url'],
             'default_dept_id'=>$vars['default_dept_id'],
-            'default_template_id'=>$vars['default_template_id'],
             'max_page_size'=>$vars['max_page_size'],
             'log_level'=>$vars['log_level'],
             'log_graceperiod'=>$vars['log_graceperiod'],
+            'name_format'=>$vars['name_format'],
             'passwd_reset_period'=>$vars['passwd_reset_period'],
             'staff_max_logins'=>$vars['staff_max_logins'],
             'staff_login_timeout'=>$vars['staff_login_timeout'],
@@ -861,7 +860,6 @@ class OsticketConfig extends Config {
             'default_sla_id'=>$vars['default_sla_id'],
             'max_open_tickets'=>$vars['max_open_tickets'],
             'autolock_minutes'=>$vars['autolock_minutes'],
-            'allow_priority_change'=>isset($vars['allow_priority_change'])?1:0,
             'use_email_priority'=>isset($vars['use_email_priority'])?1:0,
             'enable_captcha'=>isset($vars['enable_captcha'])?1:0,
             'log_ticket_activity'=>isset($vars['log_ticket_activity'])?1:0,
@@ -889,6 +887,7 @@ class OsticketConfig extends Config {
     function updateEmailsSettings($vars, &$errors) {
 
         $f=array();
+        $f['default_template_id']=array('type'=>'int',   'required'=>1, 'error'=>'You must select template.');
         $f['default_email_id']=array('type'=>'int',   'required'=>1, 'error'=>'Default email required');
         $f['alert_email_id']=array('type'=>'int',   'required'=>1, 'error'=>'Selection required');
         $f['admin_email']=array('type'=>'email',   'required'=>1, 'error'=>'System admin email required');
@@ -903,6 +902,7 @@ class OsticketConfig extends Config {
             return false;
 
         return $this->updateAll(array(
+            'default_template_id'=>$vars['default_template_id'],
             'default_email_id'=>$vars['default_email_id'],
             'alert_email_id'=>$vars['alert_email_id'],
             'default_smtp_id'=>$vars['default_smtp_id'],
diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php
new file mode 100644
index 0000000000000000000000000000000000000000..92863db2fd331d0b5cbb5b239e6b9a8555ea219d
--- /dev/null
+++ b/include/class.dynamic_forms.php
@@ -0,0 +1,817 @@
+<?php
+/*********************************************************************
+    class.dynamic_forms.php
+
+    Forms models built on the VerySimpleModel paradigm. Allows for arbitrary
+    data to be associated with tickets. Eventually this model can be
+    extended to associate arbitrary data with registered clients and thread
+    entries.
+
+    Jared Hancock <jared@osticket.com>
+    Copyright (c)  2006-2013 osTicket
+    http://www.osticket.com
+
+    Released under the GNU General Public License WITHOUT ANY WARRANTY.
+    See LICENSE.TXT for details.
+
+    vim: expandtab sw=4 ts=4 sts=4:
+**********************************************************************/
+require_once(INCLUDE_DIR . 'class.orm.php');
+require_once(INCLUDE_DIR . 'class.forms.php');
+
+/**
+ * Form template, used for designing the custom form and for entering custom
+ * data for a ticket
+ */
+class DynamicForm extends VerySimpleModel {
+
+    static $meta = array(
+        'table' => FORM_SEC_TABLE,
+        'ordering' => array('title'),
+        'pk' => array('id'),
+    );
+
+    // Registered form types
+    static $types = array(
+        'T' => 'Ticket Information',
+        'U' => 'User Information',
+    );
+
+    var $_form;
+    var $_fields;
+    var $_dfields;
+
+    function getFields() {
+        if (!isset($this->_fields)) {
+            $this->_fields = array();
+            foreach ($this->getDynamicFields() as $f)
+                // TODO: Index by field name or id
+                $this->_fields[$f->get('id')] = $f->getImpl($f);
+        }
+        return $this->_fields;
+    }
+
+    function getDynamicFields() {
+        if (!isset($this->_dfields))
+            $this->_dfields = DynamicFormField::objects()
+                ->filter(array('form_id'=>$this->id))
+                ->all();
+        return $this->_dfields;
+    }
+
+    // Multiple inheritance -- delegate to Form
+    function __call($what, $args) {
+        $delegate = array($this->getForm(), $what);
+        if (!is_callable($delegate))
+            throw new Exception($what.': Call to non-existing function');
+        return call_user_func_array($delegate, $args);
+    }
+
+    function hasField($name) {
+        foreach ($this->getDynamicFields() as $f)
+            if ($f->get('name') == $name)
+                return true;
+    }
+
+    function getTitle() { return $this->get('title'); }
+    function getInstructions() { return $this->get('instructions'); }
+
+    function getForm() {
+        if (!$this->_form) {
+            $fields = $this->getFields();
+            $this->_form = new Form($fields, false, array(
+                'title'=>$this->title, 'instructions'=>$this->instructions));
+        }
+        return $this->_form;
+    }
+
+    function isDeletable() {
+        return $this->get('deletable');
+    }
+
+    function instanciate($sort=1) {
+        return DynamicFormEntry::create(array(
+            'form_id'=>$this->get('id'), 'sort'=>$sort));
+    }
+
+    function data($data) {
+        if ($data instanceof DynamicFormEntry) {
+            $this->_fields = $data->getFields();
+        }
+    }
+
+    function save($refetch=false) {
+        if (count($this->dirty))
+            $this->set('updated', new SqlFunction('NOW'));
+        if (isset($this->dirty['notes']))
+            $this->notes = Format::sanitize($this->notes);
+        return parent::save($refetch);
+    }
+
+    function delete() {
+        if (!$this->isDeletable())
+            return false;
+        else
+            return parent::delete();
+    }
+
+    static function create($ht=false) {
+        $inst = parent::create($ht);
+        $inst->set('created', new SqlFunction('NOW'));
+        if (isset($ht['fields'])) {
+            $inst->save();
+            foreach ($ht['fields'] as $f) {
+                $f = DynamicFormField::create($f);
+                $f->form_id = $inst->id;
+                $f->save();
+            }
+        }
+        return $inst;
+    }
+}
+
+class UserForm extends DynamicForm {
+    static $instance;
+
+    static function objects() {
+        $os = parent::objects();
+        return $os->filter(array('type'=>'U'));
+    }
+
+    function getFields() {
+        $fields = parent::getFields();
+        foreach ($fields as $f) {
+            if ($f->get('name') == 'email') {
+                $f->getConfiguration();
+                $f->_config['classes'] = 'auto email typeahead';
+                $f->_config['autocomplete'] = false;
+            }
+            elseif ($f->get('name') == 'name') {
+                $f->getConfiguration();
+                $f->_config['classes'] = 'auto name';
+            }
+        }
+        return $fields;
+    }
+
+    static function getInstance() {
+        if (!isset(static::$instance)) {
+            $o = static::objects();
+            static::$instance = $o[0]->instanciate();
+        }
+        return static::$instance;
+    }
+}
+
+class TicketForm extends DynamicForm {
+    static $instance;
+
+    static function objects() {
+        $os = parent::objects();
+        return $os->filter(array('type'=>'T'));
+    }
+
+    static function getInstance() {
+        if (!isset(static::$instance)) {
+            $o = static::objects();
+            static::$instance = $o[0]->instanciate();
+        }
+        return static::$instance;
+    }
+}
+// Add fields from the standard ticket form to the ticket filterable fields
+Filter::addSupportedMatches('Custom Fields', function() {
+    $matches = array();
+    foreach (TicketForm::getInstance()->getFields() as $f) {
+        if (!$f->hasData())
+            continue;
+        $matches['field.'.$f->get('id')] = $f->getLabel();
+    }
+    return $matches;
+});
+
+require_once(INCLUDE_DIR . "class.json.php");
+
+class DynamicFormField extends VerySimpleModel {
+
+    static $meta = array(
+        'table' => FORM_FIELD_TABLE,
+        'ordering' => array('sort'),
+        'pk' => array('id'),
+        'joins' => array(
+            'form' => array(
+                'null' => true,
+                'constraint' => array('form_id' => 'DynamicForm.id'),
+            ),
+        ),
+    );
+
+    var $_field;
+
+    // Multiple inheritance -- delegate to FormField
+    function __call($what, $args) {
+        return call_user_func_array(
+            array($this->getField(), $what), $args);
+    }
+
+    function getField() {
+        if (!isset($this->_field))
+            $this->_field = new FormField($this->ht);
+        return $this->_field;
+    }
+
+    function getAnswer() { return $this->answer; }
+
+    /**
+     * setConfiguration
+     *
+     * Used in the POST request of the configuration process. The
+     * ::getConfigurationForm() method should be used to retrieve a
+     * configuration form for this field. That form should be submitted via
+     * a POST request, and this method should be called in that request. The
+     * data from the POST request will be interpreted and will adjust the
+     * configuration of this field
+     *
+     * Parameters:
+     * errors - (OUT array) receives validation errors of the parsed
+     *      configuration form
+     *
+     * Returns:
+     * (bool) true if the configuration was updated, false if there were
+     * errors. If false, the errors were written into the received errors
+     * array.
+     */
+    function setConfiguration(&$errors=array()) {
+        $config = array();
+        foreach ($this->getConfigurationForm() as $name=>$field) {
+            $config[$name] = $field->getClean();
+            $errors = array_merge($errors, $field->errors());
+        }
+        if (count($errors) === 0)
+            $this->set('configuration', JsonDataEncoder::encode($config));
+        $this->set('hint', $_POST['hint']);
+        return count($errors) === 0;
+    }
+
+    function isDeletable() {
+        return ($this->get('edit_mask') & 1) == 0;
+    }
+    function isNameForced() {
+        return $this->get('edit_mask') & 2;
+    }
+    function isPrivacyForced() {
+        return $this->get('edit_mask') & 4;
+    }
+    function isRequirementForced() {
+        return $this->get('edit_mask') & 8;
+    }
+
+    function delete() {
+        // Don't really delete form fields as that will screw up the data
+        // model. Instead, just drop the association with the form which
+        // will give the appearance of deletion. Not deleting means that
+        // the field will continue to exist on form entries it may already
+        // have answers on, but since it isn't associated with the form, it
+        // won't be available for new form submittals.
+        $this->set('form_id', 0);
+        $this->save();
+    }
+
+    function save() {
+        if (count($this->dirty))
+            $this->set('updated', new SqlFunction('NOW'));
+        return parent::save();
+    }
+
+    static function create($ht=false) {
+        $inst = parent::create($ht);
+        $inst->set('created', new SqlFunction('NOW'));
+        if (isset($ht['configuration']))
+            $inst->configuration = JsonDataEncoder::encode($ht['configuration']);
+        return $inst;
+    }
+}
+
+/**
+ * Represents an entry to a dynamic form. Used to render the completed form
+ * in reference to the attached ticket, etc. A form is used to represent the
+ * template of enterable data. This represents the data entered into an
+ * instance of that template.
+ *
+ * The data of the entry is called 'answers' in this model. This model
+ * represents an instance of a form entry. The data / answers to that entry
+ * are represented individually in the DynamicFormEntryAnswer model.
+ */
+class DynamicFormEntry extends VerySimpleModel {
+
+    static $meta = array(
+        'table' => FORM_ENTRY_TABLE,
+        'ordering' => array('sort'),
+        'pk' => array('id'),
+        'joins' => array(
+            'form' => array(
+                'null' => true,
+                'constraint' => array('form_id' => 'DynamicForm.id'),
+            ),
+        ),
+    );
+
+    var $_values;
+    var $_fields;
+    var $_form;
+    var $_errors = false;
+    var $_clean = false;
+
+    function getAnswers() {
+        if (!isset($this->_values)) {
+            $this->_values = DynamicFormEntryAnswer::objects()
+                ->filter(array('entry_id'=>$this->get('id')))
+                ->all();
+            foreach ($this->_values as $v)
+                $v->entry = $this;
+        }
+        return $this->_values;
+    }
+
+    function getAnswer($name) {
+        foreach ($this->getAnswers() as $ans)
+            if ($ans->getField()->get('name') == $name)
+                return $ans->getValue();
+        return null;
+    }
+    function setAnswer($name, $value, $id=false) {
+        foreach ($this->getAnswers() as $ans) {
+            if ($ans->getField()->get('name') == $name) {
+                $ans->set('value', $value);
+                if ($id !== false)
+                    $ans->set('value_id', $id);
+                break;
+            }
+        }
+    }
+
+    function errors() {
+        return $this->_errors;
+    }
+
+    function getTitle() { return $this->getForm()->getTitle(); }
+    function getInstructions() { return $this->getForm()->getInstructions(); }
+
+    function getForm() {
+        if (!isset($this->_form)) {
+            $this->_form = DynamicForm::lookup($this->get('form_id'));
+            if ($this->id)
+                $this->_form->data($this);
+        }
+        return $this->_form;
+    }
+
+    function getFields() {
+        if (!isset($this->_fields)) {
+            $this->_fields = array();
+            foreach ($this->getAnswers() as $a)
+                $this->_fields[] = $a->getField();
+        }
+        return $this->_fields;
+    }
+
+    function isValid() {
+        if (!is_array($this->_errors)) {
+            $this->_errors = array();
+            $this->getClean();
+            foreach ($this->getFields() as $field)
+                if ($field->errors())
+                    $this->_errors[$field->get('id')] = $field->errors();
+        }
+        return !$this->_errors;
+    }
+
+    function getClean() {
+        if (!$this->_clean) {
+            $this->_clean = array();
+            foreach ($this->getFields() as $field)
+                $this->_clean[$field->get('id')]
+                    = $this->_clean[$field->get('name')] = $field->getClean();
+        }
+        return $this->_clean;
+    }
+
+    function forTicket($ticket_id, $force=false) {
+        static $entries = array();
+        if (!isset($entries[$ticket_id]) || $force)
+            $entries[$ticket_id] = DynamicFormEntry::objects()
+                ->filter(array('object_id'=>$ticket_id, 'object_type'=>'T'));
+        return $entries[$ticket_id];
+    }
+    function setTicketId($ticket_id) {
+        $this->object_type = 'T';
+        $this->object_id = $ticket_id;
+    }
+
+    function forClient($user_id) {
+        return DynamicFormEntry::objects()
+            ->filter(array('object_id'=>$user_id, 'object_type'=>'U'));
+    }
+    function setClientId($user_id) {
+        $this->object_type = 'U';
+        $this->object_id = $user_id;
+    }
+
+    function render($staff=true) {
+        return $this->getForm()->render($staff);
+    }
+
+    /**
+     * addMissingFields
+     *
+     * Adds fields that have been added to the linked form (field set) since
+     * this entry was originally created. If fields are added to the form,
+     * the method will automatically add the fields and null answers to the
+     * entry.
+     */
+    function addMissingFields() {
+        foreach ($this->getForm()->getDynamicFields() as $field) {
+            $found = false;
+            foreach ($this->getAnswers() as $answer) {
+                if ($answer->get('field_id') == $field->get('id')) {
+                    $found = true; break;
+                }
+            }
+            if (!$found && ($field = $field->getImpl($field))
+                    && !$field->isPresentationOnly()) {
+                $a = DynamicFormEntryAnswer::create(
+                    array('field_id'=>$field->get('id'), 'entry_id'=>$this->id));
+                $a->field = $field;
+                $a->entry = $this;
+                // Add to list of answers
+                $this->_values[] = $a;
+                $this->_fields[] = $field;
+                // Omit fields without data
+                // For user entries, the name and email fields should not be
+                // saved with the rest of the data
+                if (!($this->object_type == 'U'
+                        && in_array($field->get('name'), array('name','email')))
+                        && $field->hasData())
+                    $a->save();
+                $this->_form = null;
+            }
+            // Sort the form the way it is declared to be sorted
+            if ($this->_fields)
+                usort($this->_fields, function($a, $b) {
+                    return $a->get('sort') - $b->get('sort');
+                });
+        }
+    }
+
+    function save() {
+        if (count($this->dirty))
+            $this->set('updated', new SqlFunction('NOW'));
+        parent::save();
+        foreach ($this->getAnswers() as $a) {
+            $field = $a->getField();
+            if ($this->object_type == 'U'
+                    && in_array($field->get('name'), array('name','email')))
+                continue;
+            $val = $field->to_database($field->getClean());
+            if (is_array($val)) {
+                $a->set('value', $val[0]);
+                $a->set('value_id', $val[1]);
+            }
+            else
+                $a->set('value', $val);
+            $a->set('entry_id', $this->get('id'));
+            // Don't save answers for presentation-only fields
+            if ($field->hasData() && !$field->isPresentationOnly())
+                $a->save();
+        }
+        $this->_values = array();
+    }
+
+    function delete() {
+        foreach ($this->getAnswers() as $a)
+            $a->delete();
+        return parent::delete();
+    }
+
+    static function create($ht=false) {
+        $inst = parent::create($ht);
+        $inst->set('created', new SqlFunction('NOW'));
+        foreach ($inst->getForm()->getFields() as $f) {
+            if (!$f->hasData()) continue;
+            $a = DynamicFormEntryAnswer::create(
+                array('field_id'=>$f->get('id')));
+            $a->field = $f;
+            $inst->_values[] = $a;
+        }
+        return $inst;
+    }
+}
+
+/**
+ * Represents a single answer to a single field on a dynamic form. The
+ * data / answer to the field is linked back to the form and field which was
+ * originally used for the submission.
+ */
+class DynamicFormEntryAnswer extends VerySimpleModel {
+
+    static $meta = array(
+        'table' => FORM_ANSWER_TABLE,
+        'ordering' => array('field__sort'),
+        'pk' => array('entry_id', 'field_id'),
+        'joins' => array(
+            'field' => array(
+                'constraint' => array('field_id' => 'DynamicFormField.id'),
+            ),
+            'entry' => array(
+                'constraint' => array('entry_id' => 'DynamicFormEntry.id'),
+            ),
+        ),
+    );
+
+    var $field;
+    var $form;
+    var $entry;
+    var $_value;
+
+    function getEntry() {
+        return $this->entry;
+    }
+
+    function getForm() {
+        if (!$this->form)
+            $this->form = $this->getEntry()->getForm();
+        return $this->form;
+    }
+
+    function getField() {
+        if (!isset($this->field)) {
+            $f = DynamicFormField::lookup($this->get('field_id'));
+            $this->field = $f->getImpl($f);
+            $this->field->answer = $this;
+        }
+        return $this->field;
+    }
+
+    function getValue() {
+        if (!$this->_value)
+            $this->_value = $this->getField()->to_php(
+                $this->get('value'), $this->get('value_id'));
+        return $this->_value;
+    }
+
+    function getIdValue() {
+        return $this->get('value_id');
+    }
+
+    function toString() {
+        return $this->getField()->toString($this->getValue());
+    }
+
+    function __toString() {
+        return $this->toString();
+    }
+}
+
+/**
+ * Dynamic lists are used to represent list of arbitrary data that can be
+ * used as dropdown or typeahead selections in dynamic forms. This model
+ * defines a list. The individual items are stored in the DynamicListItem
+ * model.
+ */
+class DynamicList extends VerySimpleModel {
+
+    static $meta = array(
+        'table' => LIST_TABLE,
+        'ordering' => array('name'),
+        'pk' => array('id'),
+    );
+
+    var $_items;
+
+    function getSortModes() {
+        return array(
+            'Alpha'     => 'Alphabetical',
+            '-Alpha'    => 'Alphabetical (Reversed)',
+            'SortCol'   => 'Manually Sorted'
+        );
+    }
+
+    function getListOrderBy() {
+        switch ($this->sort_mode) {
+            case 'Alpha':   return 'value';
+            case '-Alpha':  return '-value';
+            case 'SortCol': return 'sort';
+        }
+    }
+
+    function getPluralName() {
+        if ($name = $this->get('name_plural'))
+            return $name;
+        else
+            return $this->get('name') . 's';
+    }
+
+    function getItems($limit=false, $offset=false) {
+        if (!$this->_items) {
+            $this->_items = DynamicListItem::objects()->filter(
+                    array('list_id'=>$this->get('id')))
+                ->order_by($this->getListOrderBy());
+            if ($limit)
+                $this->_items->limit($limit);
+            if ($offset)
+                $this->_items->offset($offset);
+        }
+        return $this->_items;
+    }
+
+    function getItemCount() {
+        return DynamicListItem::objects()->filter(array('list_id'=>$this->id))
+            ->count();
+    }
+
+    function save($refetch=false) {
+        if (count($this->dirty))
+            $this->set('updated', new SqlFunction('NOW'));
+        if (isset($this->dirty['notes']))
+            $this->notes = Format::sanitize($this->notes);
+        return parent::save($refetch);
+    }
+
+    function delete() {
+        $fields = DynamicFormField::objects()->filter(array(
+            'type'=>'list-'.$this->id))->count();
+        if ($fields == 0)
+            return parent::delete();
+        else
+            // Refuse to delete lists that are in use by fields
+            return false;
+    }
+
+    static function create($ht=false) {
+        $inst = parent::create($ht);
+        $inst->set('created', new SqlFunction('NOW'));
+        return $inst;
+    }
+
+    static function getSelections() {
+        $selections = array();
+        foreach (DynamicList::objects() as $list) {
+            $selections['list-'.$list->id] =
+                array($list->getPluralName(),
+                    SelectionField, $list->get('id'));
+        }
+        return $selections;
+    }
+}
+FormField::addFieldTypes('Custom Lists', array(DynamicList, 'getSelections'));
+
+/**
+ * Represents a single item in a dynamic list
+ *
+ * Fields:
+ * value - (char * 255) Actual list item content
+ * extra - (char * 255) Other values that represent the same item in the
+ *      list, such as an abbreviation. In practice, should be a
+ *      space-separated list of tokens which should hit this list item in a
+ *      search
+ * sort - (int) If sorting by this field, represents the numeric sort order
+ *      that this item should come in the dropdown list
+ */
+class DynamicListItem extends VerySimpleModel {
+
+    static $meta = array(
+        'table' => LIST_ITEM_TABLE,
+        'pk' => array('id'),
+        'joins' => array(
+            'list' => array(
+                'null' => true,
+                'constraint' => array('list_id' => 'DynamicList.id'),
+            ),
+        ),
+    );
+
+    function toString() {
+        return $this->get('value');
+    }
+
+    function delete() {
+        # Don't really delete, just unset the list_id to un-associate it with
+        # the list
+        $this->set('list_id', null);
+        return $this->save();
+    }
+}
+
+class SelectionField extends FormField {
+    function getListId() {
+        list(,$list_id) = explode('-', $this->get('type'));
+        return $list_id;
+    }
+
+    function getList() {
+        if (!$this->_list)
+            $this->_list = DynamicList::lookup($this->getListId());
+        return $this->_list;
+    }
+
+    function getWidget() {
+        return new SelectionWidget($this);
+    }
+
+    function parse($value) {
+        return $this->to_php($value);
+    }
+
+    function to_php($value, $id=false) {
+        $item = DynamicListItem::lookup($id ? $id : $value);
+        # Attempt item lookup by name too
+        if (!$item) {
+            $item = DynamicListItem::lookup(array(
+                'value'=>$value,
+                'list_id'=>$this->getListId()));
+        }
+        return ($item) ? $item : $id;
+    }
+
+    function to_database($item) {
+        if ($item instanceof DynamicListItem)
+            return array($item->value, $item->id);
+        return null;
+    }
+
+    function toString($item) {
+        return ($item instanceof DynamicListItem) ? $item->toString() : $item;
+    }
+
+    function validateEntry($item) {
+        parent::validateEntry($item);
+        if ($item && !$item instanceof DynamicListItem)
+            $this->_errors[] = 'Select a value from the list';
+    }
+
+    function getConfigurationOptions() {
+        return array(
+            'typeahead' => new ChoiceField(array(
+                'id'=>1, 'label'=>'Widget', 'required'=>false,
+                'default'=>false,
+                'choices'=>array(false=>'Drop Down', true=>'Typeahead'),
+                'hint'=>'Typeahead will work better for large lists')),
+        );
+    }
+
+    function getChoices() {
+        if (!$this->_choices) {
+            $this->_choices = array();
+            foreach ($this->getList()->getItems() as $i)
+                $this->_choices[$i->get('id')] = $i->get('value');
+        }
+        return $this->_choices;
+    }
+}
+
+class SelectionWidget extends ChoicesWidget {
+    function render() {
+        $config = $this->field->getConfiguration();
+        $value = false;
+        if ($this->value instanceof DynamicListItem) {
+            // Loaded from database
+            $value = $this->value->get('id');
+            $name = $this->value->get('value');
+        } elseif ($this->value) {
+            // Loaded from POST
+            $value = $this->value;
+            $name = DynamicListItem::lookup($value);
+            $name = ($name) ? $name->get('value') : $value;
+        }
+
+        if (!$config['typeahead']) {
+            $this->value = $value;
+            return parent::render();
+        }
+
+        $source = array();
+        foreach ($this->field->getList()->getItems() as $i)
+            $source[] = array(
+                'value' => $i->get('value'),
+                'info' => $i->get('value')." -- ".$i->get('extra'),
+            );
+        ?>
+        <span style="display:inline-block">
+        <input type="text" size="30" name="<?php echo $this->name; ?>"
+            value="<?php echo $name; ?>" autocomplete="off" />
+        <script type="text/javascript">
+        $(function() {
+            $('input[name=<?php echo $this->name; ?>]').typeahead({
+                source: <?php echo JsonDataEncoder::encode($source); ?>,
+                property: 'info',
+                onselect: function(item) {
+                    $('input[name="<?php echo $this->name; ?>"]').val(item['value'])
+                }
+            });
+        });
+        </script>
+        </span>
+        <?php
+    }
+}
+?>
diff --git a/include/class.filter.php b/include/class.filter.php
index 1f94120793d338ddb57be5979eb31a500d9c1ada..81c6a39fe17a86e8e5981385a0dd417d6e47955f 100644
--- a/include/class.filter.php
+++ b/include/class.filter.php
@@ -18,6 +18,17 @@ class Filter {
     var $id;
     var $ht;
 
+    static $match_types = array(
+        'Basic Fields' => array(
+            'name'      => 'Name',
+            'email'     => 'Email',
+            'subject'   => 'Subject',
+            'body'      => 'Body/Text',
+            'reply-to'  => 'Reply-To Email',
+            'reply-to-name' => 'Reply-To Name',
+        ),
+    );
+
     function Filter($id) {
         $this->id=0;
         $this->load($id);
@@ -165,7 +176,7 @@ class Filter {
 
     function addRule($what, $how, $val,$extra=array()) {
 
-        $rule= array_merge($extra,array('w'=>$what, 'h'=>$how, 'v'=>$val));
+        $rule= array_merge($extra,array('what'=>$what, 'how'=>$how, 'val'=>$val));
         $rule['filter_id']=$this->getId();
 
         return FilterRule::create($rule,$errors);               # nolint
@@ -299,13 +310,28 @@ class Filter {
             $ticket['cannedResponseId'] = $this->getCannedResponse();
     }
     /* static */ function getSupportedMatches() {
-        return array(
-            'name'=>    'Name',
-            'email'=>   'Email',
-            'subject'=> 'Subject',
-            'body'=>    'Body/Text'
-        );
+        foreach (static::$match_types as $k=>&$v) {
+            if (is_callable($v))
+                $v = $v();
+        }
+        unset($v);
+        return static::$match_types;
+    }
+
+    static function addSupportedMatches($group, $callable) {
+        static::$match_types[$group] = $callable;
     }
+
+    static function getSupportedMatchFields() {
+        $keys = array();
+        foreach (static::getSupportedMatches() as $group=>$matches) {
+            foreach ($matches as $key=>$label) {
+                $keys[] = $key;
+            }
+        }
+        return $keys;
+    }
+
     /* static */ function getSupportedMatchTypes() {
         return array(
             'equal'=>       'Equal',
@@ -370,7 +396,7 @@ class Filter {
 
     function save_rules($id,$vars,&$errors) {
 
-        $matches = array_keys(self::getSupportedMatches());
+        $matches = array_keys(self::getSupportedMatchFields());
         $types = array_keys(self::getSupportedMatchTypes());
 
         $rules=array();
@@ -382,7 +408,9 @@ class Filter {
                     $errors["rule_$i"]='Invalid match type selection';
                 elseif(!$vars["rule_v$i"])
                     $errors["rule_$i"]='Value required';
-                elseif($vars["rule_w$i"]=='email' && $vars["rule_h$i"]=='equal' && !Validator::is_email($vars["rule_v$i"]))
+                elseif($vars["rule_w$i"]=='email'
+                        && $vars["rule_h$i"]=='equal'
+                        && !Validator::is_email($vars["rule_v$i"]))
                     $errors["rule_$i"]='Valid email required for the match type';
                 else //for everything-else...we assume it's valid.
                     $rules[]=array('what'=>$vars["rule_w$i"],
@@ -640,22 +668,18 @@ class TicketFilter {
      *  deal with the data in the incoming ticket (based on $vars) will be considered.
      *  @see ::quickList() for more information.
      */
-    function TicketFilter($origin, $vars=null) {
+    function TicketFilter($origin, $vars=array()) {
 
         //Normalize the target based on ticket's origin.
         $this->target = self::origin2target($origin);
 
         //Extract the vars we care about (fields we filter by!).
-         $this->vars = array_filter(array_map('trim',
-                 array(
-                     'email'     => $vars['email'],
-                     'subject'   => $vars['subject'],
-                     'name'      => $vars['name'],
-                     'body'      => $vars['message'],
-                     'emailId'   => $vars['emailId'],
-                     'reply-to'  => @$vars['reply-to'],
-                     'reply-to-name' => @$vars['reply-to-name'],
-                 )));
+        $this->vars = array('body'=>$vars['message']);
+        $interest = Filter::getSupportedMatchFields();
+        foreach ($vars as $k=>$v) {
+            if (in_array($k, $interest))
+                $this->vars[$k] = trim($v);
+        }
 
          //Init filters.
         $this->build();
diff --git a/include/class.forms.php b/include/class.forms.php
new file mode 100644
index 0000000000000000000000000000000000000000..adb525e8078c931340123f6b9e5d85e8c36b10cc
--- /dev/null
+++ b/include/class.forms.php
@@ -0,0 +1,991 @@
+<?php
+/*********************************************************************
+    class.forms.php
+
+    osTicket forms framework
+
+    Jared Hancock <jared@osticket.com>
+    Copyright (c)  2006-2013 osTicket
+    http://www.osticket.com
+
+    Released under the GNU General Public License WITHOUT ANY WARRANTY.
+    See LICENSE.TXT for details.
+
+    vim: expandtab sw=4 ts=4 sts=4:
+**********************************************************************/
+
+/**
+ * Form template, used for designing the custom form and for entering custom
+ * data for a ticket
+ */
+class Form {
+    var $fields = array();
+    var $title = 'Unnamed';
+    var $instructions = '';
+
+    var $_errors;
+    var $_source = false;
+
+    function Form() {
+        call_user_func_array(array($this, '__construct'), func_get_args());
+    }
+    function __construct($fields=array(), $source=null, $options=array()) {
+        $this->fields = $fields;
+        foreach ($fields as $f)
+            $f->setForm($this);
+        if (isset($options['title']))
+            $this->title = $options['title'];
+        if (isset($options['instructions']))
+            $this->instructions = $options['instructions'];
+        // Use POST data if source was not specified
+        $this->_source = ($source) ? $source : $_POST;
+    }
+    function data($source) {
+        foreach ($this->fields as $name=>$f)
+            if (isset($source[$name]))
+                $f->value = $source[$name];
+    }
+
+    function getFields() {
+        return $this->fields;
+    }
+    function getTitle() { return $this->title; }
+    function getInstructions() { return $this->instructions; }
+    function getSource() { return $this->_source; }
+
+    function isValid() {
+        if (!is_array($this->_errors)) {
+            $this->_errors = array();
+            $this->getClean();
+            foreach ($this->getFields() as $field)
+                if ($field->errors())
+                    $this->_errors[$field->get('id')] = $field->errors();
+        }
+        return !$this->_errors;
+    }
+
+    function getClean() {
+        if (!$this->_clean) {
+            $this->_clean = array();
+            foreach ($this->getFields() as $key=>$field) {
+                $this->_clean[$key] = $this->_clean[$field->get('name')]
+                    = $field->getClean();
+            }
+        }
+        return $this->_clean;
+    }
+
+    function errors() {
+        return $this->_errors;
+    }
+
+    function render($staff=true, $title=false, $instructions=false) {
+        if ($title)
+            $this->title = $title;
+        if ($instructions)
+            $this->instructions = $instructions;
+        $form = $this;
+        if ($staff)
+            include(STAFFINC_DIR . 'templates/dynamic-form.tmpl.php');
+        else
+            include(CLIENTINC_DIR . 'templates/dynamic-form.tmpl.php');
+    }
+}
+
+require_once(INCLUDE_DIR . "class.json.php");
+
+class FormField {
+    static $widget = false;
+
+    var $ht = array(
+        'label' => 'Unlabeled',
+        'required' => false,
+        'default' => false,
+        'configuration' => array(),
+    );
+
+    var $_form;
+    var $_cform;
+    var $_clean;
+    var $_errors = array();
+    var $_widget;
+    var $parent;
+    var $presentation_only = false;
+
+    static $types = array(
+        'Basic Fields' => array(
+            'text'  => array('Short Answer', TextboxField),
+            'memo' => array('Long Answer', TextareaField),
+            'thread' => array('Thread Entry', ThreadEntryField, false),
+            'datetime' => array('Date and Time', DatetimeField),
+            'phone' => array('Phone Number', PhoneField),
+            'bool' => array('Checkbox', BooleanField),
+            'choices' => array('Choices', ChoiceField),
+            'break' => array('Section Break', SectionBreakField),
+        ),
+    );
+    static $more_types = array();
+
+    function __construct($options=array()) {
+        static $uid = 100;
+        $this->ht = array_merge($this->ht, $options);
+        if (!isset($this->ht['id']))
+            $this->ht['id'] = $uid++;
+    }
+
+    static function addFieldTypes($group, $callable) {
+        static::$more_types[$group] = $callable;
+    }
+
+    static function allTypes() {
+        if (static::$more_types) {
+            foreach (static::$more_types as $group=>$c)
+                static::$types[$group] = call_user_func($c);
+            static::$more_types = array();
+        }
+        return static::$types;
+    }
+
+    static function getFieldType($type) {
+        foreach (static::allTypes() as $group=>$types)
+            if (isset($types[$type]))
+                return $types[$type];
+    }
+
+    function get($what) {
+        return $this->ht[$what];
+    }
+
+    /**
+     * getClean
+     *
+     * Validates and cleans inputs from POST request. This is performed on a
+     * field instance, after a DynamicFormSet / DynamicFormSection is
+     * submitted via POST, in order to kick off parsing and validation of
+     * user-entered data.
+     */
+    function getClean() {
+        if (!isset($this->_clean)) {
+            $value = $this->getWidget()->value;
+            $this->_clean = $this->parse($value);
+            $this->validateEntry($this->_clean);
+        }
+        return $this->_clean;
+    }
+
+    function errors() {
+        return $this->_errors;
+    }
+
+    function isValidEntry() {
+        $this->validateEntry();
+        return count($this->_errors) == 0;
+    }
+
+    /**
+     * validateEntry
+     *
+     * Validates user entry on an instance of the field on a dynamic form.
+     * This is called when an instance of this field (like a TextboxField)
+     * receives data from the user and that value should be validated.
+     *
+     * Parameters:
+     * $value - (string) input from the user
+     */
+    function validateEntry($value) {
+        if (!$value && count($this->_errors))
+            return;
+
+        # Validates a user-input into an instance of this field on a dynamic
+        # form
+        if ($this->get('required') && !$value && $this->hasData())
+            $this->_errors[] = sprintf('%s is a required field', $this->getLabel());
+    }
+
+    /**
+     * parse
+     *
+     * Used to transform user-submitted data to a PHP value. This value is
+     * not yet considered valid. The ::validateEntry() method will be called
+     * on the value to determine if the entry is valid. Therefore, if the
+     * data is clearly invalid, return something like NULL that can easily
+     * be deemed invalid in ::validateEntry(), however, can still produce a
+     * useful error message indicating what is wrong with the input.
+     */
+    function parse($value) {
+        return trim($value);
+    }
+
+    /**
+     * to_php
+     *
+     * Transforms the data from the value stored in the database to a PHP
+     * value. The ::to_database() method is used to produce the database
+     * valse, so this method is the compliment to ::to_database().
+     *
+     * Parameters:
+     * $value - (string or null) database representation of the field's
+     *      content
+     */
+    function to_php($value) {
+        return $value;
+    }
+
+    /**
+     * to_database
+     *
+     * Determines the value to be stored in the database. The database
+     * backend for all fields is a text field, so this method should return
+     * a text value or NULL to represent the value of the field. The
+     * ::to_php() method will convert this value back to PHP.
+     *
+     * Paremeters:
+     * $value - PHP value of the field's content
+     */
+    function to_database($value) {
+        return $value;
+    }
+
+    /**
+     * toString
+     *
+     * Converts the PHP value created in ::parse() or ::to_php() to a
+     * pretty-printed value to show to the user. This is especially useful
+     * for something like dates which are stored considerably different in
+     * the database from their respective human-friendly versions.
+     * Furthermore, this method allows for internationalization and
+     * localization.
+     *
+     * Parametes:
+     * $value - PHP value of the field's content
+     */
+    function toString($value) {
+        return $value;
+    }
+
+    function getLabel() { return $this->get('label'); }
+
+    /**
+     * getImpl
+     *
+     * Magic method that will return an implementation instance of this
+     * field based on the simple text value of the 'type' value of this
+     * field instance. The list of registered fields is determined by the
+     * global get_dynamic_field_types() function. The data from this model
+     * will be used to initialize the returned instance.
+     *
+     * For instance, if the value of this field is 'text', a TextField
+     * instance will be returned.
+     */
+    function getImpl($parent=null) {
+        // Allow registration with ::addFieldTypes and delayed calling
+        $type = static::getFieldType($this->get('type'));
+        $clazz = $type[1];
+        $inst = new $clazz($this->ht);
+        $inst->parent = $parent;
+        $inst->setForm($this->_form);
+        return $inst;
+    }
+
+    function __call($what, $args) {
+        // XXX: Throw exception if $this->parent is not set
+        if (!$this->parent)
+            throw new Exception($what.': Call to undefined function');
+        // BEWARE: DynamicFormField has a __call() which will create a new
+        //      FormField instance and invoke __call() on it or bounce
+        //      immediately back
+        return call_user_func_array(
+            array($this->parent, $what), $args);
+    }
+
+    function getAnswer() { return $this->answer; }
+
+    function getFormName() {
+        if (is_numeric($this->get('id')))
+            return '-field-id-'.$this->get('id');
+        else
+            return $this->get('id');
+    }
+
+    function setForm($form) {
+        $this->_form = $form;
+    }
+    function getForm() {
+        return $this->_form;
+    }
+    /**
+     * Returns the data source for this field. If created from a form, the
+     * data source from the form is returned. Otherwise, if the request is a
+     * POST, then _POST is returned.
+     */
+    function getSource() {
+        if ($this->_form)
+            return $this->_form->getSource();
+        elseif ($_SERVER['REQUEST_METHOD'] == 'POST')
+            return $_POST;
+        else
+            return array();
+    }
+
+    function render($mode=null) {
+        $this->getWidget()->render($mode);
+    }
+
+    function renderExtras($mode=null) {
+        return;
+    }
+
+    function getConfigurationOptions() {
+        return array();
+    }
+
+    /**
+     * getConfiguration
+     *
+     * Loads configuration information from database into hashtable format.
+     * Also, the defaults from ::getConfigurationOptions() are integrated
+     * into the database-backed options, so that if options have not yet
+     * been set or a new option has been added and not saved for this field,
+     * the default value will be reflected in the returned configuration.
+     */
+    function getConfiguration() {
+        if (!$this->_config) {
+            $this->_config = $this->get('configuration');
+            if (is_string($this->_config))
+                $this->_config = JsonDataParser::parse($this->_config);
+            elseif (!$this->_config)
+                $this->_config = array();
+            foreach ($this->getConfigurationOptions() as $name=>$field)
+                if (!isset($this->_config[$name]))
+                    $this->_config[$name] = $field->get('default');
+        }
+        return $this->_config;
+    }
+
+    /**
+     * If the [Config] button should be shown to allow for the configuration
+     * of this field
+     */
+    function isConfigurable() {
+        return true;
+    }
+
+    /**
+     * Field type is changeable in the admin interface
+     */
+    function isChangeable() {
+        return true;
+    }
+
+    /**
+     * Field does not contain data that should be saved to the database. Ie.
+     * non data fields like section headers
+     */
+    function hasData() {
+        return true;
+    }
+
+    /**
+     * Returns true if the field/widget should be rendered as an entire
+     * block in the target form.
+     */
+    function isBlockLevel() {
+        return false;
+    }
+
+    /**
+     * Fields should not be saved with the dynamic data. It is assumed that
+     * some static processing will store the data elsewhere.
+     */
+    function isPresentationOnly() {
+        return $this->presentation_only;
+    }
+
+    function getConfigurationForm() {
+        if (!$this->_cform) {
+            $type = static::getFieldType($this->get('type'));
+            $clazz = $type[1];
+            $T = new $clazz();
+            $this->_cform = $T->getConfigurationOptions();
+        }
+        return $this->_cform;
+    }
+
+    function getWidget() {
+        if (!static::$widget)
+            throw new Exception('Widget not defined for this field');
+        if (!isset($this->_widget)) {
+            $this->_widget = new static::$widget($this);
+            $this->_widget->parseValue();
+        }
+        return $this->_widget;
+    }
+}
+
+class TextboxField extends FormField {
+    static $widget = 'TextboxWidget';
+
+    function getConfigurationOptions() {
+        return array(
+            'size'  =>  new TextboxField(array(
+                'id'=>1, 'label'=>'Size', 'required'=>false, 'default'=>16,
+                    'validator' => 'number')),
+            'length' => new TextboxField(array(
+                'id'=>2, 'label'=>'Max Length', 'required'=>false, 'default'=>30,
+                    'validator' => 'number')),
+            'validator' => new ChoiceField(array(
+                'id'=>3, 'label'=>'Validator', 'required'=>false, 'default'=>'',
+                'choices' => array('phone'=>'Phone Number','email'=>'Email Address',
+                    'ip'=>'IP Address', 'number'=>'Number', ''=>'None'))),
+            'validator-error' => new TextboxField(array(
+                'id'=>4, 'label'=>'Validation Error', 'default'=>'',
+                'configuration'=>array('size'=>40),
+                'hint'=>'Message shown to user if the input does not match the validator')),
+        );
+    }
+
+    function validateEntry($value) {
+        parent::validateEntry($value);
+        $validators = array(
+            '' =>       null,
+            'email' =>  array(array('Validator', 'is_email'),
+                'Enter a valid email address'),
+            'phone' =>  array(array('Validator', 'is_phone'),
+                'Enter a valid phone number'),
+            'ip' =>     array(array('Validator', 'is_ip'),
+                'Enter a valid IP address'),
+            'number' => array('is_numeric', 'Enter a number')
+        );
+        // Support configuration forms, as well as GUI-based form fields
+        $valid = $this->get('validator');
+        if (!$valid) {
+            $config = $this->getConfiguration();
+            $valid = $config['validator'];
+        }
+        if (!$value || !isset($validators[$valid]))
+            return;
+        $func = $validators[$valid];
+        if (is_array($func) && is_callable($func[0]))
+            if (!call_user_func($func[0], $value))
+                $this->_errors[] = $func[1];
+    }
+}
+
+class TextareaField extends FormField {
+    static $widget = 'TextareaWidget';
+
+    function getConfigurationOptions() {
+        return array(
+            'cols'  =>  new TextboxField(array(
+                'id'=>1, 'label'=>'Width (chars)', 'required'=>true, 'default'=>40)),
+            'rows'  =>  new TextboxField(array(
+                'id'=>2, 'label'=>'Height (rows)', 'required'=>false, 'default'=>4)),
+            'length' => new TextboxField(array(
+                'id'=>3, 'label'=>'Max Length', 'required'=>false, 'default'=>30)),
+            'html' => new BooleanField(array(
+                'id'=>4, 'label'=>'HTML', 'required'=>false, 'default'=>true,
+                'configuration'=>array('desc'=>'Allow HTML input in this box'))),
+        );
+    }
+}
+
+class PhoneField extends FormField {
+    static $widget = 'PhoneNumberWidget';
+
+    function validateEntry($value) {
+        parent::validateEntry($value);
+        # Run validator against $this->value for email type
+        list($phone, $ext) = explode("X", $value, 2);
+        if ($phone && !Validator::is_phone($phone))
+            $this->_errors[] = "Enter a valid phone number";
+        if ($ext) {
+            if (!is_numeric($ext))
+                $this->_errors[] = "Enter a valide phone extension";
+            elseif (!$phone)
+                $this->_errors[] = "Enter a phone number for the extension";
+        }
+    }
+
+    function toString($value) {
+        list($phone, $ext) = explode("X", $value, 2);
+        $phone=Format::phone($phone);
+        if ($ext)
+            $phone.=" x$ext";
+        return $phone;
+    }
+}
+
+class BooleanField extends FormField {
+    static $widget = 'CheckboxWidget';
+
+    function getConfigurationOptions() {
+        return array(
+            'desc' => new TextareaField(array(
+                'id'=>1, 'label'=>'Description', 'required'=>false, 'default'=>'',
+                'hint'=>'Text shown inline with the widget',
+                'configuration'=>array('rows'=>2)))
+        );
+    }
+
+    function to_database($value) {
+        return ($value) ? '1' : '0';
+    }
+
+    function parse($value) {
+        return $this->to_php($value);
+    }
+    function to_php($value) {
+        return $value ? true : false;
+    }
+
+    function toString($value) {
+        return ($value) ? 'Yes' : 'No';
+    }
+}
+
+class ChoiceField extends FormField {
+    static $widget = 'ChoicesWidget';
+
+    function getConfigurationOptions() {
+        return array(
+            'choices'  =>  new TextareaField(array(
+                'id'=>1, 'label'=>'Choices', 'required'=>false, 'default'=>'')),
+        );
+    }
+
+    function toString($value) {
+        $choices = $this->getChoices();
+        if (isset($choices[$value]))
+            return $choices[$value];
+        else
+            return $choices[$this->get('default')];
+    }
+
+    function getChoices() {
+        if ($this->_choices === null) {
+            // Allow choices to be set in this->ht (for configurationOptions)
+            $this->_choices = $this->get('choices');
+            if (!$this->_choices) {
+                $this->_choices = array();
+                $config = $this->getConfiguration();
+                $choices = explode("\n", $config['choices']);
+                foreach ($choices as $choice) {
+                    // Allow choices to be key: value
+                    list($key, $val) = explode(':', $choice);
+                    if ($val == null)
+                        $val = $key;
+                    $this->_choices[trim($key)] = trim($val);
+                }
+            }
+        }
+        return $this->_choices;
+     }
+}
+
+class DatetimeField extends FormField {
+    static $widget = 'DatetimePickerWidget';
+
+    function to_database($value) {
+        // Store time in gmt time, unix epoch format
+        return (string) $value;
+    }
+
+    function to_php($value) {
+        if (!$value)
+            return $value;
+        else
+            return (int) $value;
+    }
+
+    function parse($value) {
+        if (!$value) return null;
+        $config = $this->getConfiguration();
+        return ($config['gmt']) ? Misc::db2gmtime($value) : strtotime($value);
+    }
+
+    function toString($value) {
+        global $cfg;
+        $config = $this->getConfiguration();
+        $format = ($config['time'])
+            ? $cfg->getDateTimeFormat() : $cfg->getDateFormat();
+        if ($config['gmt'])
+            // Return time local to user's timezone
+            return Format::userdate($format, $value);
+        else
+            return Format::date($format, $value);
+    }
+
+    function getConfigurationOptions() {
+        return array(
+            'time' => new BooleanField(array(
+                'id'=>1, 'label'=>'Time', 'required'=>false, 'default'=>false,
+                'configuration'=>array(
+                    'desc'=>'Show time selection with date picker'))),
+            'gmt' => new BooleanField(array(
+                'id'=>2, 'label'=>'Timezone Aware', 'required'=>false,
+                'configuration'=>array(
+                    'desc'=>"Show date/time relative to user's timezone"))),
+            'min' => new DatetimeField(array(
+                'id'=>3, 'label'=>'Earliest', 'required'=>false,
+                'hint'=>'Earliest date selectable')),
+            'max' => new DatetimeField(array(
+                'id'=>4, 'label'=>'Latest', 'required'=>false,
+                'default'=>null)),
+            'future' => new BooleanField(array(
+                'id'=>5, 'label'=>'Allow Future Dates', 'required'=>false,
+                'default'=>true, 'configuration'=>array(
+                    'desc'=>'Allow entries into the future'))),
+        );
+    }
+
+    function validateEntry($value) {
+        $config = $this->getConfiguration();
+        parent::validateEntry($value);
+        if (!$value) return;
+        if ($config['min'] and $value < $config['min'])
+            $this->_errors[] = 'Selected date is earlier than permitted';
+        elseif ($config['max'] and $value > $config['max'])
+            $this->_errors[] = 'Selected date is later than permitted';
+        // strtotime returns -1 on error for PHP < 5.1.0 and false thereafter
+        elseif ($value === -1 or $value === false)
+            $this->_errors[] = 'Enter a valid date';
+    }
+}
+
+/**
+ * This is kind-of a special field that doesn't have any data. It's used as
+ * a field to provide a horizontal section break in the display of a form
+ */
+class SectionBreakField extends FormField {
+    static $widget = 'SectionBreakWidget';
+
+    function hasData() {
+        return false;
+    }
+
+    function isBlockLevel() {
+        return true;
+    }
+}
+
+class ThreadEntryField extends FormField {
+    static $widget = 'ThreadEntryWidget';
+
+    function isChangeable() {
+        return false;
+    }
+    function isBlockLevel() {
+        return true;
+    }
+    function isPresentationOnly() {
+        return true;
+    }
+    function renderExtras($mode=null) {
+        if ($mode == 'client')
+            $this->getWidget()->showAttachments();
+    }
+}
+
+class PriorityField extends ChoiceField {
+    function getWidget() {
+        $widget = parent::getWidget();
+        if ($widget->value instanceof Priority)
+            $widget->value = $widget->value->getId();
+        return $widget;
+    }
+
+    function getChoices() {
+        $this->ht['default'] = 0;
+
+        $sql = 'SELECT priority_id, priority_desc FROM '.PRIORITY_TABLE
+              .' ORDER BY priority_urgency DESC';
+        $choices = array(0 => '&mdash; Default &mdash;');
+        if (!($res = db_query($sql)))
+            return $choices;
+
+        while ($row = db_fetch_row($res))
+            $choices[$row[0]] = $row[1];
+        return $choices;
+    }
+
+    function parse($id) {
+        return $this->to_php(null, $id);
+    }
+
+    function to_php($value, $id) {
+        return Priority::lookup($id);
+    }
+
+    function to_database($prio) {
+        return ($prio instanceof Priority)
+            ? array($prio->getDesc(), $prio->getId())
+            : $prio;
+    }
+
+    function toString($value) {
+        return ($value instanceof Priority) ? $value->getDesc() : $value;
+    }
+
+    function getConfigurationOptions() {
+        return array();
+    }
+}
+FormField::addFieldTypes('Built-in Lists', function() {
+    return array(
+        'priority' => array('Priority Level', PriorityField),
+    );
+});
+
+class Widget {
+
+    function __construct($field) {
+        $this->field = $field;
+        $this->name = $field->getFormName();
+    }
+
+    function parseValue() {
+        $this->value = $this->getValue();
+        if (!isset($this->value) && is_object($this->field->getAnswer()))
+            $this->value = $this->field->getAnswer()->getValue();
+        if (!isset($this->value) && $this->field->value)
+            $this->value = $this->field->value;
+    }
+
+    function getValue() {
+        $data = $this->field->getSource();
+        if (!isset($data[$this->name]))
+            return null;
+        return $data[$this->name];
+    }
+}
+
+class TextboxWidget extends Widget {
+    function render() {
+        $config = $this->field->getConfiguration();
+        if (isset($config['size']))
+            $size = "size=\"{$config['size']}\"";
+        if (isset($config['length']))
+            $maxlength = "maxlength=\"{$config['length']}\"";
+        if (isset($config['classes']))
+            $classes = 'class="'.$config['classes'].'"';
+        if (isset($config['autocomplete']))
+            $autocomplete = 'autocomplete="'.($config['autocomplete']?'on':'off').'"';
+        ?>
+        <span style="display:inline-block">
+        <input type="text" id="<?php echo $this->name; ?>"
+            <?php echo $size . " " . $maxlength; ?>
+            <?php echo $classes.' '.$autocomplete; ?>
+            name="<?php echo $this->name; ?>"
+            value="<?php echo Format::htmlchars($this->value); ?>"/>
+        </span>
+        <?php
+    }
+}
+
+class TextareaWidget extends Widget {
+    function render() {
+        $config = $this->field->getConfiguration();
+        $class = "";
+        if (isset($config['rows']))
+            $rows = "rows=\"{$config['rows']}\"";
+        if (isset($config['cols']))
+            $cols = "cols=\"{$config['cols']}\"";
+        if (isset($config['length']))
+            $maxlength = "maxlength=\"{$config['length']}\"";
+        if (isset($config['html']) && $config['html'])
+            $class = 'class="richtext no-bar small"';
+        ?>
+        <span style="display:inline-block;width:100%">
+        <textarea <?php echo $rows." ".$cols." ".$length." ".$class; ?>
+            name="<?php echo $this->name; ?>"><?php
+                echo Format::htmlchars($this->value);
+            ?></textarea>
+        </span>
+        <?php
+    }
+}
+
+class PhoneNumberWidget extends Widget {
+    function render() {
+        list($phone, $ext) = explode("X", $this->value);
+        ?>
+        <input type="text" name="<?php echo $this->name; ?>" value="<?php
+            echo $phone; ?>"/> Ext: <input type="text" name="<?php
+            echo $this->name; ?>-ext" value="<?php echo $ext; ?>" size="5"/>
+        <?php
+    }
+
+    function getValue() {
+        $data = $this->field->getSource();
+        $base = parent::getValue();
+        if ($base === null)
+            return $base;
+        $ext = $data["{$this->name}-ext"];
+        if ($ext) $ext = 'X'.$ext;
+        return $base . $ext;
+    }
+}
+
+class ChoicesWidget extends Widget {
+    function render() {
+        $config = $this->field->getConfiguration();
+        // Determine the value for the default (the one listed if nothing is
+        // selected)
+        $def_key = $this->field->get('default');
+        $choices = $this->field->getChoices();
+        $have_def = isset($choices[$def_key]);
+        if (!$have_def)
+            $def_val = 'Select '.$this->field->get('label');
+        else
+            $def_val = $choices[$def_key];
+        ?> <span style="display:inline-block">
+        <select name="<?php echo $this->name; ?>">
+            <?php if (!$have_def) { ?>
+            <option value="<?php echo $def_key; ?>">&mdash; <?php
+                echo $def_val; ?> &mdash;</option>
+            <?php }
+            foreach ($choices as $key=>$name) {
+                if (!$have_def && $key == $def_key)
+                    continue; ?>
+                <option value="<?php echo $key; ?>" <?php
+                    if ($this->value == $key) echo 'selected="selected"';
+                ?>><?php echo $name; ?></option>
+            <?php } ?>
+        </select>
+        </span>
+        <?php
+    }
+}
+
+class CheckboxWidget extends Widget {
+    function __construct($field) {
+        parent::__construct($field);
+        $this->name = '_field-checkboxes';
+    }
+
+    function render() {
+        $config = $this->field->getConfiguration();
+        ?>
+        <input type="checkbox" name="<?php echo $this->name; ?>[]" <?php
+            if ($this->value) echo 'checked="checked"'; ?> value="<?php
+            echo $this->field->get('id'); ?>"/>
+        <?php
+        if ($config['desc']) { ?>
+            <em style="display:inline-block"><?php
+                echo Format::htmlchars($config['desc']); ?></em>
+        <?php }
+    }
+
+    function getValue() {
+        $data = $this->field->getSource();
+        if (count($data))
+            return @in_array($this->field->get('id'), $data[$this->name]);
+        return parent::getValue();
+    }
+}
+
+class DatetimePickerWidget extends Widget {
+    function render() {
+        $config = $this->field->getConfiguration();
+        if ($this->value) {
+            $this->value = (is_int($this->value) ? $this->value :
+                    strtotime($this->value));
+            if ($config['gmt'])
+                $this->value += 3600 *
+                    $_SESSION['TZ_OFFSET']+($_SESSION['TZ_DST']?date('I',$time):0);
+
+            list($hr, $min) = explode(':', date('H:i', $this->value));
+            $this->value = date('m/d/Y', $this->value);
+        }
+        ?>
+        <input type="text" name="<?php echo $this->name; ?>"
+            value="<?php echo Format::htmlchars($this->value); ?>" size="12"
+            autocomplete="off" />
+        <script type="text/javascript">
+            $(function() {
+                $('input[name="<?php echo $this->name; ?>"]').datepicker({
+                    <?php
+                    if ($config['min'])
+                        echo "minDate: new Date({$config['min']}000),";
+                    if ($config['max'])
+                        echo "maxDate: new Date({$config['max']}000),";
+                    elseif (!$config['future'])
+                        echo "maxDate: new Date().getTime(),";
+                    ?>
+                    numberOfMonths: 2,
+                    showButtonPanel: true,
+                    buttonImage: './images/cal.png',
+                    showOn:'both'
+                });
+            });
+        </script>
+        <?php
+        if ($config['time'])
+            // TODO: Add time picker -- requires time picker or selection with
+            //       Misc::timeDropdown
+            echo '&nbsp;' . Misc::timeDropdown($hr, $min, $this->name . ':time');
+    }
+
+    /**
+     * Function: getValue
+     * Combines the datepicker date value and the time dropdown selected
+     * time value into a single date and time string value.
+     */
+    function getValue() {
+        $data = $this->field->getSource();
+        $datetime = parent::getValue();
+        if ($datetime && isset($data[$this->name . ':time']))
+            $datetime .= ' ' . $data[$this->name . ':time'];
+        return $datetime;
+    }
+}
+
+class SectionBreakWidget extends Widget {
+    function render() {
+        ?><div class="form-header section-break"><h3><?php
+        echo Format::htmlchars($this->field->get('label'));
+        ?></h3><em><?php echo Format::htmlchars($this->field->get('hint'));
+        ?></em></div>
+        <?php
+    }
+}
+
+class ThreadEntryWidget extends Widget {
+    function render($client=null) {
+        global $cfg;
+
+        ?><div style="margin-bottom:0.5em;margin-top:0.5em"><strong><?php
+        echo Format::htmlchars($this->field->get('label'));
+        ?></strong>:</div>
+        <textarea name="<?php echo $this->field->get('name'); ?>"
+            placeholder="<?php echo Format::htmlchars($this->field->get('hint')); ?>"
+            <?php if (!$client) { ?>
+                data-draft-namespace="ticket.staff"
+            <?php } else { ?>
+                data-draft-namespace="ticket.client"
+                data-draft-object-id="<?php echo substr(session_id(), -12); ?>"
+            <?php } ?>
+            class="richtext draft draft-delete ifhtml"
+            cols="21" rows="8" style="width:80%;"><?php echo
+            $this->value; ?></textarea>
+    <?php
+    }
+
+    function showAttachments() {
+        global $cfg, $thisclient;
+
+        if(($cfg->allowOnlineAttachments()
+            && !$cfg->allowAttachmentsOnlogin())
+            || ($cfg->allowAttachmentsOnlogin()
+                && ($thisclient && $thisclient->isValid()))) { ?>
+        <hr/>
+        <div><strong>Attachments:</strong></div>
+        <div class="uploads"></div><br>
+        <input type="file" class="multifile" name="attachments[]" id="attachments" size="30" value="" />
+        <font class="error">&nbsp;<?php echo $errors['attachments']; ?></font>
+        <?php
+        }
+    }
+}
+
+?>
diff --git a/include/class.i18n.php b/include/class.i18n.php
index 0f8bc844301d1dcc42db87f1e92b98d51e89a622..7891d7ef937ecacf2bc148ae4a4e441801a8e003 100644
--- a/include/class.i18n.php
+++ b/include/class.i18n.php
@@ -41,17 +41,20 @@ class Internationalization {
      * system language and reload the data.
      */
     function loadDefaultData() {
+        # notrans -- do not translate the contents of this array
         $models = array(
-            'email_template_group.yaml' => 'EmailTemplateGroup', # notrans
-            'department.yaml' =>    'Dept', # notrans
-            'sla.yaml' =>           'SLA', # notrans
-            // Note that department and sla are required for help_topic
-            'help_topic.yaml' =>    'Topic', # notrans
-            'filter.yaml' =>        'Filter', # notrans
-            'team.yaml' =>          'Team', # notrans
+            'email_template_group.yaml' => 'EmailTemplateGroup',
+            'department.yaml' =>    'Dept',
+            'sla.yaml' =>           'SLA',
+            'form.yaml' =>          'DynamicForm',
+            // Note that department, sla, and forms are required for
+            // help_topic
+            'help_topic.yaml' =>    'Topic',
+            'filter.yaml' =>        'Filter',
+            'team.yaml' =>          'Team',
             // Note that group requires department
-            'group.yaml' =>         'Group', # notrans
-            'file.yaml' =>          'AttachmentFile', # notrans
+            'group.yaml' =>         'Group',
+            'file.yaml' =>          'AttachmentFile',
         );
 
         $errors = array();
diff --git a/include/class.json.php b/include/class.json.php
index b5a589cfac122e008acc207f3bd2942931f31fe7..f3dfd282cdf565522c45b4f7f173da45e7e40bfa 100644
--- a/include/class.json.php
+++ b/include/class.json.php
@@ -22,10 +22,12 @@ include_once "JSON.php";
 
 class JsonDataParser {
     function parse($stream) {
-        $contents = '';
-        while (!feof($stream)) {
-            $contents .= fread($stream, 8192);
-        }
+        if (is_resource($stream)) {
+            $contents = '';
+            while (!feof($stream))
+                $contents .= fread($stream, 8192);
+        } else
+            $contents = $stream;
         return self::decode($contents);
     }
 
diff --git a/include/class.nav.php b/include/class.nav.php
index a92a5629ec149579cd3d7883be2aa8ff2ef661fc..89f47ed75e1cd46ef75a95016e5ab019cea024a5 100644
--- a/include/class.nav.php
+++ b/include/class.nav.php
@@ -207,7 +207,9 @@ class AdminNav extends StaffNav{
                                         'title'=>'Ticket&nbsp;Filters','iconclass'=>'ticketFilters');
                     $subnav[]=array('desc'=>'SLA&nbsp;Plans','href'=>'slas.php','iconclass'=>'sla');
                     $subnav[]=array('desc'=>'API&nbsp;Keys','href'=>'apikeys.php','iconclass'=>'api');
-                    $subnav[]=array('desc'=>'Site&nbsp;Pages', 'href'=>'pages.php','title'=>'Pages','iconclass'=>'pages');
+                    $subnav[]=array('desc'=>'Pages', 'href'=>'pages.php','title'=>'Pages','iconclass'=>'pages');
+                    $subnav[]=array('desc'=>'Forms','href'=>'forms.php','iconclass'=>'forms');
+                    $subnav[]=array('desc'=>'Lists','href'=>'lists.php','iconclass'=>'lists');
                     break;
                 case 'emails':
                     $subnav[]=array('desc'=>'Emails','href'=>'emails.php', 'title'=>'Email Addresses', 'iconclass'=>'emailSettings');
diff --git a/include/class.orm.php b/include/class.orm.php
new file mode 100644
index 0000000000000000000000000000000000000000..8aa8e5d39fe0e57ee715d334411ddfb49790d47b
--- /dev/null
+++ b/include/class.orm.php
@@ -0,0 +1,979 @@
+<?php
+/*********************************************************************
+    class.orm.php
+
+    Simple ORM (Object Relational Mapper) for PHP5 based on Django's ORM,
+    except that complex filter operations are not supported. The ORM simply
+    supports ANDed filter operations without any GROUP BY support.
+
+    Jared Hancock <jared@osticket.com>
+    Copyright (c)  2006-2013 osTicket
+    http://www.osticket.com
+
+    Released under the GNU General Public License WITHOUT ANY WARRANTY.
+    See LICENSE.TXT for details.
+
+    vim: expandtab sw=4 ts=4 sts=4:
+**********************************************************************/
+
+class VerySimpleModel {
+    static $meta = array(
+        'table' => false,
+        'ordering' => false,
+        'pk' => false
+    );
+
+    var $ht;
+    var $dirty;
+    var $__new__ = false;
+
+    function __construct($row) {
+        $this->ht = $row;
+        $this->__setupForeignLists();
+        $this->dirty = array();
+    }
+
+    function get($field) {
+        return $this->ht[$field];
+    }
+    function __get($field) {
+        if (array_key_exists($field, $this->ht))
+            return $this->ht[$field];
+        elseif (isset(static::$meta['joins'][$field])) {
+            // TODO: Support instrumented lists and such
+            $j = static::$meta['joins'][$field];
+            $class = $j['fkey'][0];
+            $v = $this->ht[$field] = $class::lookup($this->ht[$j['local']]);
+            return $v;
+        }
+    }
+
+    function set($field, $value) {
+        // Update of foreign-key by assignment to model instance
+        if (isset(static::$meta['joins'][$field])) {
+            $j = static::$meta['joins'][$field];
+            // XXX: Ensure $value instanceof $j['fkey'][0]
+            if ($value->__new__)
+                $value->save();
+            // Capture the object under the object's field name
+            $this->ht[$field] = $value;
+            // Capture the foreign key id value
+            $field = $j['local'];
+            $value = $value->{$j['fkey'][1]};
+            // Fall through to the standard logic below
+        }
+        // XXX: Fully support or die if updating pk
+        // XXX: The contents of $this->dirty should be the value after the
+        // previous fetch or save. For instance, if the value is changed more
+        // than once, the original value should be preserved in the dirty list
+        // on the second edit.
+        $old = isset($this->ht[$field]) ? $this->ht[$field] : null;
+        if ($old != $value) {
+            $this->dirty[$field] = $old;
+            $this->ht[$field] = $value;
+        }
+    }
+    function __set($field, $value) {
+        return $this->set($field, $value);
+    }
+
+    function setAll($props) {
+        foreach ($props as $field=>$value)
+            $this->set($field, $value);
+    }
+
+    function __setupForeignLists() {
+        // Construct related lists
+        if (isset(static::$meta['joins'])) {
+            foreach (static::$meta['joins'] as $name => $j) {
+                if (isset($j['list']) && $j['list']) {
+                    $fkey = $j['fkey'];
+                    $this->{$name} = new InstrumentedList(
+                        // Send Model, Foriegn-Field, Local-Id
+                        array($fkey[0], $fkey[1], $this->{$j['local']})
+                    );
+                }
+            }
+        }
+    }
+
+    static function _inspect() {
+        if (!static::$meta['table'])
+            throw new OrmConfigurationError(
+                'Model does not define meta.table', get_called_class());
+
+        // Break down foreign-key metadata
+        foreach (static::$meta['joins'] as $field => &$j) {
+            if (isset($j['reverse'])) {
+                list($model, $key) = explode('.', $j['reverse']);
+                $info = $model::$meta['joins'][$key];
+                $constraint = array();
+                foreach ($info['constraint'] as $foreign => $local) {
+                    list(,$field) = explode('.', $local);
+                    $constraint[$field] = "$model.$foreign";
+                }
+                $j['constraint'] = $constraint;
+                $j['list'] = true;
+            }
+            // XXX: Make this better (ie. composite keys)
+            $keys = array_keys($j['constraint']);
+            $foreign = $j['constraint'][$keys[0]];
+            $j['fkey'] = explode('.', $foreign);
+            $j['local'] = $keys[0];
+        }
+    }
+
+    static function objects() {
+        return new QuerySet(get_called_class());
+    }
+
+    static function lookup($criteria) {
+        if (!is_array($criteria))
+            // Model::lookup(1), where >1< is the pk value
+            $criteria = array(static::$meta['pk'][0] => $criteria);
+        $list = static::objects()->filter($criteria)->limit(1);
+        // TODO: Throw error if more than one result from database
+        return $list[0];
+    }
+
+    function delete($pk=false) {
+        $table = static::$meta['table'];
+        $sql = 'DELETE FROM '.$table;
+
+        if (!$pk) $pk = static::$meta['pk'];
+        if (!is_array($pk)) $pk=array($pk);
+
+        foreach ($pk as $p)
+            $filter[] = $p.' = '.db_input($this->get($p));
+        $sql .= ' WHERE '.implode(' AND ', $filter).' LIMIT 1';
+        return db_affected_rows(db_query($sql)) == 1;
+    }
+
+    function save($refetch=false) {
+        $pk = static::$meta['pk'];
+        if (!is_array($pk)) $pk=array($pk);
+        if ($this->__new__)
+            $sql = 'INSERT INTO '.static::$meta['table'];
+        else
+            $sql = 'UPDATE '.static::$meta['table'];
+        $filter = $fields = array();
+        if (count($this->dirty) === 0)
+            return;
+        foreach ($this->dirty as $field=>$old)
+            if ($this->__new__ or !in_array($field, $pk))
+                if (@get_class($this->get($field)) == 'SqlFunction')
+                    $fields[] = $field.' = '.$this->get($field)->toSql();
+                else
+                    $fields[] = $field.' = '.db_input($this->get($field));
+        foreach ($pk as $p)
+            $filter[] = $p.' = '.db_input($this->get($p));
+        $sql .= ' SET '.implode(', ', $fields);
+        if (!$this->__new__) {
+            $sql .= ' WHERE '.implode(' AND ', $filter);
+            $sql .= ' LIMIT 1';
+        }
+        if (db_affected_rows(db_query($sql)) != 1) {
+            throw new Exception(db_error());
+            return false;
+        }
+        if ($this->__new__) {
+            if (count($pk) == 1)
+                $this->ht[$pk[0]] = db_insert_id();
+            $this->__new__ = false;
+            // Setup lists again
+            $this->__setupForeignLists();
+        }
+        # Refetch row from database
+        # XXX: Too much voodoo
+        if ($refetch) {
+            # XXX: Support composite PK
+            $criteria = array($pk[0] => $this->get($pk[0]));
+            $self = static::lookup($criteria);
+            $this->ht = $self->ht;
+        }
+        $this->dirty = array();
+        return $this->get($pk[0]);
+    }
+
+    static function create($ht=false) {
+        if (!$ht) $ht=array();
+        $class = get_called_class();
+        $i = new $class(array());
+        $i->__new__ = true;
+        foreach ($ht as $field=>$value)
+            if (!is_array($value))
+                $i->set($field, $value);
+        return $i;
+    }
+
+    /**
+     * isValid
+     *
+     * Validates the contents of $this->ht before the model should be
+     * committed to the database. This is the validation for the field
+     * template -- edited in the admin panel for a form section.
+     */
+    function isValid() {
+        return true;
+    }
+}
+
+class SqlFunction {
+    function SqlFunction($name) {
+        $this->func = $name;
+        $this->args = array_slice(func_get_args(), 1);
+    }
+
+    function toSql() {
+        $args = (count($this->args)) ? implode(',', db_input($this->args)) : "";
+        return sprintf('%s(%s)', $this->func, $args);
+    }
+}
+
+class QuerySet implements IteratorAggregate, ArrayAccess {
+    var $model;
+
+    var $constraints = array();
+    var $exclusions = array();
+    var $ordering = array();
+    var $limit = false;
+    var $offset = 0;
+    var $related = array();
+    var $values = array();
+
+    var $compiler = 'MySqlCompiler';
+    var $iterator = 'ModelInstanceIterator';
+
+    var $params;
+    var $query;
+
+    function __construct($model) {
+        $this->model = $model;
+    }
+
+    function filter() {
+        // Multiple arrays passes means OR
+        $this->constraints[] = func_get_args();
+        return $this;
+    }
+
+    function exclude() {
+        $this->exclusions[] = func_get_args();
+        return $this;
+    }
+
+    function order_by() {
+        $this->ordering = array_merge($this->ordering, func_get_args());
+        return $this;
+    }
+
+    function limit($count) {
+        $this->limit = $count;
+        return $this;
+    }
+
+    function offset($at) {
+        $this->offset = $at;
+        return $this;
+    }
+
+    function select_related() {
+        $this->related = array_merge($this->related, func_get_args());
+        return $this;
+    }
+
+    function values() {
+        $this->values = func_get_args();
+        $this->iterator = 'HashArrayIterator';
+        return $this;
+    }
+
+    function values_flat() {
+        $this->values = func_get_args();
+        $this->iterator = 'FlatArrayIterator';
+        return $this;
+    }
+
+    function all() {
+        return $this->getIterator()->asArray();
+    }
+
+    function count() {
+        $compiler = new $this->compiler();
+        return $compiler->compileCount($this);
+    }
+
+    function exists() {
+        return $this->count() > 0;
+    }
+
+    // IteratorAggregate interface
+    function getIterator() {
+        if (!isset($this->_iterator))
+            $this->_iterator = new $this->iterator($this);
+        return $this->_iterator;
+    }
+
+    // ArrayAccess interface
+    function offsetExists($offset) {
+        return $this->getIterator()->offsetExists($offset);
+    }
+    function offsetGet($offset) {
+        return $this->getIterator()->offsetGet($offset);
+    }
+    function offsetUnset($a) {
+        throw new Exception('QuerySet is read-only');
+    }
+    function offsetSet($a, $b) {
+        throw new Exception('QuerySet is read-only');
+    }
+
+    function __toString() {
+        return (string)$this->getQuery();
+    }
+
+    function getQuery($options=array()) {
+        if (isset($this->query))
+            return $this->query;
+
+        // Load defaults from model
+        $model = $this->model;
+        if (!$this->ordering && isset($model::$meta['ordering']))
+            $this->ordering = $model::$meta['ordering'];
+
+        $compiler = new $this->compiler($options);
+        $this->query = $compiler->compileSelect($this);
+
+        return $this->query;
+    }
+}
+
+class ModelInstanceIterator implements Iterator, ArrayAccess {
+    var $model;
+    var $resource;
+    var $cache = array();
+    var $position = 0;
+    var $queryset;
+
+    function __construct($queryset=false) {
+        if ($queryset) {
+            $this->model = $queryset->model;
+            $this->resource = $queryset->getQuery();
+        }
+    }
+
+    function buildModel($row) {
+        // TODO: Traverse to foreign keys
+        return new $this->model($row);
+    }
+
+    function fillTo($index) {
+        while ($this->resource && $index >= count($this->cache)) {
+            if ($row = $this->resource->getArray()) {
+                $this->cache[] = $this->buildModel($row);
+            } else {
+                $this->resource->close();
+                $this->resource = null;
+                break;
+            }
+        }
+    }
+
+    function asArray() {
+        $this->fillTo(PHP_INT_MAX);
+        return $this->cache;
+    }
+
+    // Iterator interface
+    function rewind() {
+        $this->position = 0;
+    }
+    function current() {
+        $this->fillTo($this->position);
+        return $this->cache[$this->position];
+    }
+    function key() {
+        return $this->position;
+    }
+    function next() {
+        $this->position++;
+    }
+    function valid() {
+        $this->fillTo($this->position);
+        return count($this->cache) > $this->position;
+    }
+
+    // ArrayAccess interface
+    function offsetExists($offset) {
+        $this->fillTo($offset);
+        return $this->position >= $offset;
+    }
+    function offsetGet($offset) {
+        $this->fillTo($offset);
+        return $this->cache[$offset];
+    }
+    function offsetUnset($a) {
+        throw new Exception(sprintf('%s is read-only', get_class($this)));
+    }
+    function offsetSet($a, $b) {
+        throw new Exception(sprintf('%s is read-only', get_class($this)));
+    }
+}
+
+class FlatArrayIterator extends ModelInstanceIterator {
+    function __construct($queryset) {
+        $this->resource = $queryset->getQuery();
+    }
+    function fillTo($index) {
+        while ($this->resource && $index >= count($this->cache)) {
+            if ($row = $this->resource->getRow()) {
+                $this->cache += $row;
+            } else {
+                $this->resource->close();
+                $this->resource = null;
+                break;
+            }
+        }
+    }
+}
+
+class InstrumentedList extends ModelInstanceIterator {
+    var $key;
+    var $id;
+
+    function __construct($fkey, $queryset=false) {
+        list($model, $this->key, $this->id) = $fkey;
+        if (!$queryset)
+            $queryset = $model::objects()->filter(array($this->key=>$this->id));
+        parent::__construct($queryset);
+        if (!$this->id)
+            $this->resource = null;
+    }
+
+    function add($object) {
+        $object->{$this->key} = $this->id;
+        $object->save();
+        $this->list[] = $object;
+    }
+    function remove($object) {
+        $object->delete();
+    }
+
+    function offsetUnset($a) {
+        $this->fillTo($a);
+        $this->cache[$a]->delete();
+    }
+    function offsetSet($a, $b) {
+        $this->fillTo($a);
+        $this->cache[$a]->delete();
+        $this->add($b);
+    }
+}
+
+class SqlCompiler {
+    var $options = array();
+    var $params = array();
+    var $joins = array();
+    var $aliases = array();
+    var $alias_num = 1;
+
+    static $operators = array(
+        'exact' => '%$1s = %$2s'
+    );
+
+    function __construct($options=false) {
+        if ($options)
+            $this->options = array_merge($this->options, $options);
+    }
+
+    /**
+     * Handles breaking down a field or model search descriptor into the
+     * model search path, field, and operator parts. When used in a queryset
+     * filter, an expression such as
+     *
+     * user__email__hostname__contains => 'foobar'
+     *
+     * would be broken down to search from the root model (passed in,
+     * perhaps a ticket) to the user and email models by inspecting the
+     * model metadata 'joins' property. The 'constraint' value found there
+     * will be used to build the JOIN sql clauses.
+     *
+     * The 'hostname' will be the field on 'email' model that should be
+     * compared in the WHERE clause. The comparison should be made using a
+     * 'contains' function, which in MySQL, might be implemented using
+     * something like "<lhs> LIKE '%foobar%'"
+     *
+     * This function will rely heavily on the pushJoin() function which will
+     * handle keeping track of joins made previously in the query and
+     * therefore prevent multiple joins to the same table for the same
+     * reason. (Self joins are still supported).
+     *
+     * Comparison functions supported by this function are defined for each
+     * respective SqlCompiler subclass; however at least these functions
+     * should be defined:
+     *
+     *      function    a__function => b
+     *      ----------+------------------------------------------------
+     *      exact     | a is exactly equal to b
+     *      gt        | a is greater than b
+     *      lte       | b is greater than a
+     *      lt        | a is less than b
+     *      gte       | b is less than a
+     *      ----------+------------------------------------------------
+     *      contains  | (string) b is contained within a
+     *      statswith | (string) first len(b) chars of a are exactly b
+     *      endswith  | (string) last len(b) chars of a are exactly b
+     *      like      | (string) a matches pattern b
+     *      ----------+------------------------------------------------
+     *      in        | a is in the list or the nested queryset b
+     *      ----------+------------------------------------------------
+     *      isnull    | a is null (if b) else a is not null
+     *
+     * If no comparison function is declared in the field descriptor,
+     * 'exact' is assumed.
+     */
+    function getField($field, $model, $options=array()) {
+        $joins = array();
+
+        // Break apart the field descriptor by __ (double-underbars). The
+        // first part is assumed to be the root field in the given model.
+        // The parts after each of the __ pieces are links to other tables.
+        // The last item (after the last __) is allowed to be an operator
+        // specifiction.
+        $parts = explode('__', $field);
+        $operator = static::$operators['exact'];
+        if (!isset($options['table'])) {
+            $field = array_pop($parts);
+            if (array_key_exists($field, static::$operators)) {
+                $operator = static::$operators[$field];
+                $field = array_pop($parts);
+            }
+        }
+
+        $path = array();
+        $crumb = '';
+        $alias = $this->quote($model::$meta['table']);
+
+        // Traverse through the parts and establish joins between the tables
+        // if the field is joined to a foreign model
+        if (count($parts) && isset($model::$meta['joins'][$parts[0]])) {
+            // Call pushJoin for each segment in the join path. A new
+            // JOIN fragment will need to be emitted and/or cached
+            foreach ($parts as $p) {
+                $path[] = $p;
+                $tip = implode('__', $path);
+                $info = $model::$meta['joins'][$p];
+                $alias = $this->pushJoin($crumb, $tip, $model, $info);
+                // Roll to foreign model
+                foreach ($info['constraint'] as $local => $foreign) {
+                    list($model, $f) = explode('.', $foreign);
+                    if (class_exists($model))
+                        break;
+                }
+                $crumb = $tip;
+            }
+        }
+        if (isset($options['table']) && $options['table'])
+            $field = $alias;
+        elseif ($alias)
+            $field = $alias.'.'.$this->quote($field);
+        else
+            $field = $this->quote($field);
+        return array($field, $operator);
+    }
+
+    /**
+     * Uses the compiler-specific `compileJoin` function to compile the join
+     * statement fragment, and caches the result in the local $joins list. A
+     * new alias is acquired using the `nextAlias` function which will be
+     * associated with the join. If the same path is requested again, the
+     * algorithm is short-circuited and the originally-assigned table alias
+     * is returned immediately.
+     */
+    function pushJoin($tip, $path, $model, $info) {
+        // TODO: Build the join statement fragment and return the table
+        // alias. The table alias will be useful where the join is used in
+        // the WHERE and ORDER BY clauses
+
+        // If the join already exists for the statement-being-compiled, just
+        // return the alias being used.
+        if (isset($this->joins[$path]))
+            return $this->joins[$path]['alias'];
+
+        // TODO: Support only using aliases if necessary. Use actual table
+        // names for everything except oddities like self-joins
+
+        $alias = $this->nextAlias();
+        // Keep an association between the table alias and the model. This
+        // will make model construction much easier when we have the data
+        // and the table alias from the database.
+        $this->aliases[$alias] = $model;
+
+        // TODO: Stash joins and join constraints into local ->joins array.
+        // This will be useful metadata in the executor to construct the
+        // final models for fetching
+        // TODO: Always use a table alias. This will further help with
+        // coordination between the data returned from the database (where
+        // table alias is available) and the corresponding data.
+        $this->joins[$path] = array(
+            'alias' => $alias,
+            'sql'=> $this->compileJoin($tip, $model, $alias, $info),
+        );
+        return $alias;
+    }
+
+    function compileWhere($where, $model) {
+        $constrints = array();
+        foreach ($where as $constraint) {
+            $filter = array();
+            foreach ($constraint as $field=>$value) {
+                list($field, $op) = $this->getField($field, $model);
+                // Allow operators to be callable rather than sprintf
+                // strings
+                if ($value === null)
+                    $filter[] = sprintf('%s IS NULL', $field);
+                elseif (is_callable($op))
+                    $filter[] = call_user_func($op, $field, $value);
+                else
+                    $filter[] = sprintf($op, $field, $this->input($value));
+            }
+            // Multiple constraints here are ANDed together
+            $constraints[] = implode(' AND ', $filter);
+        }
+        // Multiple constrains here are ORed together
+        $filter = implode(' OR ', $constraints);
+        if (count($constraints) > 1)
+            $filter = '(' . $filter . ')';
+        return $filter;
+    }
+
+    function getParams() {
+        return $this->params;
+    }
+
+    function getJoins() {
+        $sql = '';
+        foreach ($this->joins as $j)
+            $sql .= $j['sql'];
+        return $sql;
+    }
+
+    function nextAlias() {
+        // Use alias A1-A9,B1-B9,...
+        $alias = chr(65 + (int)($this->alias_num / 9)) . $this->alias_num % 9;
+        $this->alias_num++;
+        return $alias;
+    }
+}
+
+class DbEngine {
+
+    function __construct($info) {
+    }
+
+    function connect() {
+    }
+
+    // Gets a compiler compatible with this database engine that can compile
+    // and execute a queryset or DML request.
+    function getCompiler() {
+    }
+}
+
+class MySqlCompiler extends SqlCompiler {
+
+    static $operators = array(
+        'exact' => '%1$s = %2$s',
+        'contains' => array('self', '__contains'),
+        'gt' => '%1$s > %2$s',
+        'lt' => '%1$s < %2$s',
+        'isnull' => '%1$s IS NULL',
+        'like' => '%1$s LIKE %2$s',
+        'in' => array('self', '__in'),
+    );
+
+    function __contains($a, $b) {
+        # {%a} like %{$b}%
+        return sprintf('%s LIKE %s', $a, $this->input("%$b%"));
+    }
+
+    function __in($a, $b) {
+        if (is_array($b)) {
+            $vals = array_map(array($this, 'input'), $b);
+            $b = implode(', ', $vals);
+        }
+        else {
+            $b = $this->input($b);
+        }
+        return sprintf('%s IN (%s)', $a, $b);
+    }
+
+    function compileJoin($tip, $model, $alias, $info) {
+        $constraints = array();
+        $join = ' JOIN ';
+        if (isset($info['null']) && $info['null'])
+            $join = ' LEFT'.$join;
+        if (isset($this->joins[$tip]))
+            $table = $this->joins[$tip]['alias'];
+        else
+            $table = $this->quote($model::$meta['table']);
+        foreach ($info['constraint'] as $local => $foreign) {
+            list($rmodel, $right) = explode('.', $foreign);
+            // TODO: Support a constant constraint
+            $constraints[] = sprintf("%s.%s = %s.%s",
+                $table, $this->quote($local), $alias,
+                $this->quote($right)
+            );
+        }
+        return $join.$this->quote($rmodel::$meta['table'])
+            .' '.$alias.' ON ('.implode(' AND ', $constraints).')';
+    }
+
+    function input($what) {
+        if ($what instanceof QuerySet) {
+            $q = $what->getQuery(array('nosort'=>true));
+            $this->params += $q->params;
+            return (string)$q;
+        }
+        else {
+            $this->params[] = $what;
+            return '?';
+        }
+    }
+
+    function quote($what) {
+        return "`$what`";
+    }
+
+    function compileCount($queryset) {
+        $model = $queryset->model;
+        $table = $model::$meta['table'];
+        $where_pos = array();
+        $where_neg = array();
+        $joins = array();
+        foreach ($queryset->constraints as $where) {
+            $where_pos[] = $this->compileWhere($where, $model);
+        }
+        foreach ($queryset->exclusions as $where) {
+            $where_neg[] = $this->compileWhere($where, $model);
+        }
+
+        $where = '';
+        if ($where_pos || $where_neg) {
+            $where = ' WHERE '.implode(' AND ', $where_pos)
+                .implode(' AND NOT ', $where_neg);
+        }
+        $joins = $this->getJoins();
+        $sql = 'SELECT COUNT(*) AS count FROM '.$this->quote($table).$joins.$where;
+        $exec = new MysqlExecutor($sql, $this->params);
+        $row = $exec->getArray();
+        return $row['count'];
+    }
+
+    function compileSelect($queryset) {
+        $model = $queryset->model;
+        $where_pos = array();
+        $where_neg = array();
+        $joins = array();
+        foreach ($queryset->constraints as $where) {
+            $where_pos[] = $this->compileWhere($where, $model);
+        }
+        foreach ($queryset->exclusions as $where) {
+            $where_neg[] = $this->compileWhere($where, $model);
+        }
+
+        $where = '';
+        if ($where_pos || $where_neg) {
+            $where = ' WHERE '.implode(' AND ', $where_pos)
+                .implode(' AND NOT ', $where_neg);
+        }
+
+        $sort = '';
+        if ($queryset->ordering && !isset($this->options['nosort'])) {
+            $orders = array();
+            foreach ($queryset->ordering as $sort) {
+                $dir = 'ASC';
+                if (substr($sort, 0, 1) == '-') {
+                    $dir = 'DESC';
+                    $sort = substr($sort, 1);
+                }
+                list($field) = $this->getField($sort, $model);
+                $orders[] = $field.' '.$dir;
+            }
+            $sort = ' ORDER BY '.implode(', ', $orders);
+        }
+
+        // Include related tables
+        $fields = array();
+        $table = $model::$meta['table'];
+        if ($queryset->related) {
+            $fields = array($this->quote($table).'.*');
+            foreach ($queryset->related as $rel) {
+                // XXX: This is ugly
+                list($t) = $this->getField($rel, $model,
+                    array('table'=>true));
+                $fields[] = $t.'.*';
+            }
+        // Support only retrieving a list of values rather than a model
+        } elseif ($queryset->values) {
+            foreach ($queryset->values as $v) {
+                list($fields[]) = $this->getField($v, $model);
+            }
+        } else {
+            $fields[] = $this->quote($table).'.*';
+        }
+
+        $joins = $this->getJoins();
+        $sql = 'SELECT '.implode(', ', $fields).' FROM '
+            .$this->quote($table).$joins.$where.$sort;
+        if ($queryset->limit)
+            $sql .= ' LIMIT '.$queryset->limit;
+        if ($queryset->offset)
+            $sql .= ' OFFSET '.$queryset->offset;
+
+        return new MysqlExecutor($sql, $this->params);
+    }
+
+    function compileUpdate() {
+    }
+
+    function compileInsert() {
+    }
+
+    function compileDelete() {
+    }
+
+    // Returns meta data about the table used to build queries
+    function inspectTable($table) {
+    }
+}
+
+class MysqlExecutor {
+
+    var $stmt;
+    var $fields = array();
+
+    var $sql;
+    var $params;
+
+    function __construct($sql, $params) {
+        $this->sql = $sql;
+        $this->params = $params;
+    }
+
+    function _prepare() {
+        if (!($this->stmt = db_prepare($this->sql)))
+            throw new Exception('Unable to prepare query: '.db_error()
+                .' '.$this->sql);
+        if (count($this->params))
+            $this->_bind($this->params);
+        $this->stmt->execute();
+        $this->_setup_output();
+        $this->stmt->store_result();
+    }
+
+    function _bind($params) {
+        if (count($params) != $this->stmt->param_count)
+            throw new Exception('Parameter count does not match query');
+
+        $types = '';
+        $ps = array();
+        foreach ($params as &$p) {
+            if (is_int($p))
+                $types .= 'i';
+            elseif (is_string($p))
+                $types .= 's';
+            // TODO: Emit error if param is null
+            $ps[] = &$p;
+        }
+        unset($p);
+        array_unshift($ps, $types);
+        call_user_func_array(array($this->stmt,'bind_param'), $ps);
+    }
+
+    function _setup_output() {
+        $meta = $this->stmt->result_metadata();
+        while ($f = $meta->fetch_field())
+            $this->fields[] = $f;
+    }
+
+    // Iterator interface
+    function rewind() {
+        if (!isset($this->stmt))
+            $this->_prepare();
+        $this->stmt->data_seek(0);
+    }
+
+    function next() {
+        $status = $this->stmt->fetch();
+        if ($status === false)
+            throw new Exception($this->stmt->error_list . db_error());
+        elseif ($status === null) {
+            $this->close();
+            return false;
+        }
+        return true;
+    }
+
+    function getArray() {
+        $output = array();
+        $variables = array();
+
+        if (!isset($this->stmt))
+            $this->_prepare();
+
+        foreach ($this->fields as $f)
+            $variables[] = &$output[$f->name]; // pass by reference
+
+        call_user_func_array(array($this->stmt, 'bind_result'), $variables);
+        if (!$this->next())
+            return false;
+        return $output;
+    }
+
+    function getRow() {
+        $output = array();
+        $variables = array();
+
+        if (!isset($this->stmt))
+            $this->_prepare();
+
+        foreach ($this->fields as $f)
+            $variables[] = &$output[]; // pass by reference
+
+        call_user_func_array(array($this->stmt, 'bind_result'), $variables);
+        if (!$this->next())
+            return false;
+        return $output;
+    }
+
+    function getStruct() {
+        $output = array();
+        $variables = array();
+
+        if (!isset($this->stmt))
+            $this->_prepare();
+
+        foreach ($this->fields as $f)
+            $variables[] = &$output[$f->table][$f->name]; // pass by reference
+
+        // TODO: Figure out what the table alias for the root model will be
+        call_user_func_array(array($this->stmt, 'bind_result'), $variables);
+        if (!$this->next())
+            return false;
+        return $output;
+    }
+
+    function close() {
+        if (!$this->stmt)
+            return;
+
+        $this->stmt->close();
+        $this->stmt = null;
+    }
+
+    function __toString() {
+        return $this->sql;
+    }
+}
+?>
diff --git a/include/class.pdf.php b/include/class.pdf.php
index ea658378685c04f8345a5e3e73d7042499b1eeb1..b20eaf7ac53df9290a0532fafcb7ac62d466e491 100644
--- a/include/class.pdf.php
+++ b/include/class.pdf.php
@@ -109,7 +109,7 @@ class Ticket2PDF extends FPDF
     function WriteText($w, $text, $border) {
 
         $this->SetFont('Times','',11);
-        $this->MultiCell($w, 5, $text, $border, 'L');
+        $this->MultiCell($w, 7, $text, $border, 'L');
 
     }
 
@@ -187,7 +187,7 @@ class Ticket2PDF extends FPDF
         if($ticket->getIP())
             $source.='  ('.$ticket->getIP().')';
         $this->Cell($c, 7, $source, 1, 0, 'L', true);
-        $this->Ln(15);
+        $this->Ln(12);
 
         $this->SetFont('Arial', 'B', 11);
         if($ticket->isOpen()) {
@@ -233,7 +233,30 @@ class Ticket2PDF extends FPDF
         $this->Cell($l, 7, 'Last Message', 1, 0, 'L', true);
         $this->SetFont('');
         $this->Cell($c, 7, Format::db_datetime($ticket->getLastMsgDate()), 1, 1, 'L', true);
-        $this->Ln(5);
+
+        $this->SetFillColor(255, 255, 255);
+        foreach (DynamicFormEntry::forTicket($ticket->getId()) as $form) {
+            $idx = 0;
+            foreach ($form->getAnswers() as $a) {
+                if (in_array($a->getField()->get('name'),
+                            array('email','name','subject','phone')))
+                    continue;
+                $this->SetFont('Arial', 'B', 11);
+                if ($idx++ === 0) {
+                    $this->Ln(5);
+                    $this->SetFillColor(244, 250, 255);
+                    $this->Cell(($l+$c)*2, 7, $a->getForm()->get('title'),
+                        1, 0, 'L', true);
+                    $this->Ln(7);
+                    $this->SetFillColor(255, 255, 255);
+                }
+                $this->Cell($l*2, 7, $a->getField()->get('label'), 1, 0, 'L', true);
+                $this->SetFont('');
+                $this->WriteText($c*2, $a->toString(), 1);
+            }
+        }
+        $this->SetFillColor(244, 250, 255);
+        $this->Ln(10);
 
         $this->SetFont('Arial', 'B', 11);
         $this->cMargin = 0;
diff --git a/include/class.staff.php b/include/class.staff.php
index a1fe8e7c821576632df1e2e6062a26e19e123409..93708bc0cccfbd71120f321f22e722f7af98834e 100644
--- a/include/class.staff.php
+++ b/include/class.staff.php
@@ -19,6 +19,7 @@ include_once(INCLUDE_DIR.'class.error.php');
 include_once(INCLUDE_DIR.'class.team.php');
 include_once(INCLUDE_DIR.'class.group.php');
 include_once(INCLUDE_DIR.'class.passwd.php');
+include_once(INCLUDE_DIR.'class.user.php');
 
 class Staff {
 
@@ -165,7 +166,7 @@ class Staff {
     }
 
     function getName() {
-        return ucfirst($this->ht['firstname'].' '.$this->ht['lastname']);
+        return new PersonsName($this->ht['firstname'].' '.$this->ht['lastname']);
     }
 
     function getFirstName() {
diff --git a/include/class.ticket.php b/include/class.ticket.php
index 2ab7ba1e683c0bfe84c8185b6626ad205a9fda99..596254830eb8b4536bcee86df05d25d975643897 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -30,6 +30,8 @@ include_once(INCLUDE_DIR.'class.variable.php');
 include_once(INCLUDE_DIR.'class.priority.php');
 include_once(INCLUDE_DIR.'class.sla.php');
 include_once(INCLUDE_DIR.'class.canned.php');
+require_once(INCLUDE_DIR.'class.dynamic_forms.php');
+require_once(INCLUDE_DIR.'class.user.php');
 
 class Ticket {
 
@@ -60,14 +62,12 @@ class Ticket {
         if(!$id && !($id=$this->getId()))
             return false;
 
-        $sql='SELECT  ticket.*, lock_id, dept_name, priority_desc '
+        $sql='SELECT  ticket.*, lock_id, dept_name '
             .' ,IF(sla.id IS NULL, NULL, DATE_ADD(ticket.created, INTERVAL sla.grace_period HOUR)) as sla_duedate '
             .' ,count(attach.attach_id) as attachments '
             .' FROM '.TICKET_TABLE.' ticket '
             .' LEFT JOIN '.DEPT_TABLE.' dept ON (ticket.dept_id=dept.dept_id) '
             .' LEFT JOIN '.SLA_TABLE.' sla ON (ticket.sla_id=sla.id AND sla.isactive=1) '
-            .' LEFT JOIN '.TICKET_PRIORITY_TABLE.' pri ON ('
-                .'ticket.priority_id=pri.priority_id) '
             .' LEFT JOIN '.TICKET_LOCK_TABLE.' tlock ON ('
                 .'ticket.ticket_id=tlock.ticket_id AND tlock.expire>NOW()) '
             .' LEFT JOIN '.TICKET_ATTACHMENT_TABLE.' attach ON ('
@@ -84,6 +84,9 @@ class Ticket {
 
         $this->id       = $this->ht['ticket_id'];
         $this->number   = $this->ht['ticketID'];
+        $this->_answers = array();
+
+        $this->loadDynamicData();
 
         //Reset the sub classes (initiated ondemand)...good for reloads.
         $this->staff = null;
@@ -102,6 +105,15 @@ class Ticket {
         return true;
     }
 
+    function loadDynamicData() {
+        if (!$this->_answers) {
+            foreach (DynamicFormEntry::forTicket($this->getId(), true) as $form)
+                foreach ($form->getAnswers() as $answer)
+                    $this->_answers[$answer->getField()->get('name')]
+                        = $answer;
+        }
+    }
+
     function reload() {
         return $this->load();
     }
@@ -170,8 +182,31 @@ class Ticket {
         return $this->number;
     }
 
-    function getEmail() {
-        return $this->ht['email'];
+    function getOwnerId() {
+        return $this->ht['user_id'];
+    }
+
+    function getOwner() {
+        if (!isset($this->user))
+            $this->user = User::lookup($this->getOwnerId());
+        return $this->user;
+    }
+
+    function getEmail(){
+        if ($o = $this->getOwner())
+            return $o->getEmail();
+        return null;
+    }
+
+    function getReplyToEmail() {
+        if ($this->ht['user_email_id']) {
+            if (!isset($this->reply_email))
+                $this->reply_email = UserEmail::lookup($this->ht['user_email_id']);
+            return $this->reply_email->address;
+        }
+        else {
+            return $this->getEmail();
+        }
     }
 
     function getAuthToken() {
@@ -179,12 +214,14 @@ class Ticket {
         return md5($this->getId() . $this->getEmail() . SECRET_SALT);
     }
 
-    function getName() {
-        return $this->ht['name'];
+    function getName(){
+        if ($o = $this->getOwner())
+            return $o->getName();
+        return null;
     }
 
     function getSubject() {
-        return $this->ht['subject'];
+        return $this->_answers['subject'];
     }
 
     /* Help topic title  - NOT object -> $topic */
@@ -251,27 +288,31 @@ class Ticket {
     }
 
     function getPriorityId() {
-        return $this->ht['priority_id'];
+        global $cfg;
+
+        if ($a = $this->_answers['priority']->getValue())
+            return $a->getId();
+        return $cfg->getDefaultPriorityId();
     }
 
-    function getPriority() { //TODO: Make it an obj.
-        return  $this->ht['priority_desc'];
+    function getPriority() {
+        if ($a = $this->_answers['priority']->getValue())
+            return $a->getDesc();
+        return '...ummm...';
     }
 
     function getPhone() {
-        return $this->ht['phone'];
+        list($phone, $ext) = explode(" ", $this->_answers['phone'], 2);
+        return $phone;
     }
 
     function getPhoneExt() {
-        return $this->ht['phone_ext'];
+        list($phone, $ext) = explode(" ", $this->_answers['phone'], 2);
+        return $ext;
     }
 
     function getPhoneNumber() {
-        $phone=Format::phone($this->getPhone());
-        if(($ext=$this->getPhoneExt()))
-            $phone.=" $ext";
-
-        return $phone;
+        return $this->_answers['phone'];
     }
 
     function getSource() {
@@ -288,11 +329,8 @@ class Ticket {
 
     function getUpdateInfo() {
 
-        $info=array('name'  =>  $this->getName(),
-                    'email' =>  $this->getEmail(),
-                    'phone' =>  $this->getPhone(),
+        $info=array('phone' =>  $this->getPhone(),
                     'phone_ext' =>  $this->getPhoneExt(),
-                    'subject'   =>  $this->getSubject(),
                     'source'    =>  $this->getSource(),
                     'topicId'   =>  $this->getTopicId(),
                     'priorityId'    =>  $this->getPriorityId(),
@@ -533,20 +571,6 @@ class Ticket {
         return $this->lastMsgId=$msgid;
     }
 
-    function setPriority($priorityId) {
-
-        //XXX: what happens to SLA priority???
-
-        if(!$priorityId || $priorityId==$this->getPriorityId())
-            return ($priorityId);
-
-        $sql='UPDATE '.TICKET_TABLE.' SET updated=NOW() '
-            .', priority_id='.db_input($priorityId)
-            .' WHERE ticket_id='.db_input($this->getId());
-
-        return (($res=db_query($sql)) && db_affected_rows($res));
-    }
-
     //DeptId can NOT be 0. No orphans please!
     function setDeptId($deptId) {
 
@@ -1069,6 +1093,12 @@ class Ticket {
 
                 return $closedate;
                 break;
+            default:
+                if (isset($this->_answers[$tag]))
+                    // The answer object is retrieved here which will
+                    // automatically invoke the toString() method when the
+                    // answer is coerced into text
+                    return $this->_answers[$tag];
         }
 
         return false;
@@ -1614,6 +1644,9 @@ class Ticket {
         //delete just orphaned ticket thread & associated attachments.
         $this->getThread()->delete();
 
+        foreach (DynamicFormEntry::forTicket($this->getId()) as $form)
+            $form->delete();
+
         return true;
     }
 
@@ -1625,13 +1658,8 @@ class Ticket {
             return false;
 
         $fields=array();
-        $fields['name']     = array('type'=>'string',   'required'=>1, 'error'=>'Name required');
-        $fields['email']    = array('type'=>'email',    'required'=>1, 'error'=>'Valid email required');
-        $fields['subject']  = array('type'=>'string',   'required'=>1, 'error'=>'Subject required');
         $fields['topicId']  = array('type'=>'int',      'required'=>1, 'error'=>'Help topic required');
-        $fields['priorityId'] = array('type'=>'int',    'required'=>1, 'error'=>'Priority required');
         $fields['slaId']    = array('type'=>'int',      'required'=>0, 'error'=>'Select SLA');
-        $fields['phone']    = array('type'=>'phone',    'required'=>0, 'error'=>'Valid phone # required');
         $fields['duedate']  = array('type'=>'date',     'required'=>0, 'error'=>'Invalid date - must be MM/DD/YY');
 
         $fields['note']     = array('type'=>'text',     'required'=>1, 'error'=>'Reason for the update required');
@@ -1650,23 +1678,9 @@ class Ticket {
                 $errors['duedate']='Due date must be in the future';
         }
 
-        //Make sure phone extension is valid
-        if($vars['phone_ext'] ) {
-            if(!is_numeric($vars['phone_ext']) && !$errors['phone'])
-                $errors['phone']='Invalid phone ext.';
-            elseif(!$vars['phone']) //make sure they just didn't enter ext without phone #
-                $errors['phone']='Phone number required';
-        }
-
         if($errors) return false;
 
         $sql='UPDATE '.TICKET_TABLE.' SET updated=NOW() '
-            .' ,email='.db_input($vars['email'])
-            .' ,name='.db_input(Format::striptags($vars['name']))
-            .' ,subject='.db_input(Format::striptags($vars['subject']))
-            .' ,phone="'.db_input($vars['phone'],false).'"'
-            .' ,phone_ext='.db_input($vars['phone_ext']?$vars['phone_ext']:NULL)
-            .' ,priority_id='.db_input($vars['priorityId'])
             .' ,topic_id='.db_input($vars['topicId'])
             .' ,sla_id='.db_input($vars['slaId'])
             .' ,duedate='.($vars['duedate']?db_input(date('Y-m-d G:i',Misc::dbtime($vars['duedate'].' '.$vars['time']))):'NULL');
@@ -1708,11 +1722,13 @@ class Ticket {
         if(!$extId || !is_numeric($extId))
             return 0;
 
-        $sql ='SELECT  ticket_id FROM '.TICKET_TABLE.' ticket '
-             .' WHERE ticketID='.db_input($extId);
+        $sql ='SELECT ticket.ticket_id FROM '.TICKET_TABLE.' ticket '
+             .' LEFT JOIN '.USER_TABLE.' user ON user.id = ticket.user_id'
+             .' LEFT JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id'
+             .' WHERE ticket.ticketID='.db_input($extId);
 
         if($email)
-            $sql.=' AND email='.db_input($email);
+            $sql .= ' AND email.address = '.db_input($email);
 
         if(($res=db_query($sql)) && db_num_rows($res))
             list($id)=db_fetch_row($res);
@@ -1763,15 +1779,6 @@ class Ticket {
         return $id;
     }
 
-    function getOpenTicketsByEmail($email) {
-
-        $sql='SELECT count(*) as open FROM '.TICKET_TABLE.' WHERE status='.db_input('open').' AND email='.db_input($email);
-        if(($res=db_query($sql)) && db_num_rows($res))
-            list($num)=db_fetch_row($res);
-
-        return $num;
-    }
-
     /* Quick staff's tickets stats */
     function getStaffStats($staff) {
         global $cfg;
@@ -1828,6 +1835,8 @@ class Ticket {
 
         if(!$email || !Validator::is_email($email))
             return null;
+        if (!$user = User::lookup(array('emails__address'=>$email)))
+            return null;
 
         $sql='SELECT count(open.ticket_id) as open, count(closed.ticket_id) as closed '
             .' FROM '.TICKET_TABLE.' ticket '
@@ -1835,7 +1844,7 @@ class Ticket {
                 ON (open.ticket_id=ticket.ticket_id AND open.status=\'open\') '
             .' LEFT JOIN '.TICKET_TABLE.' closed
                 ON (closed.ticket_id=ticket.ticket_id AND closed.status=\'closed\')'
-            .' WHERE ticket.email='.db_input($email);
+            .' WHERE ticket.user_id = '.db_input($user->getId());
 
         return db_fetch_array(db_query($sql));
     }
@@ -1848,10 +1857,12 @@ class Ticket {
     function create($vars, &$errors, $origin, $autorespond=true, $alertstaff=true) {
         global $ost, $cfg, $thisclient, $_FILES;
 
-        // Drop extra whitespace
-        foreach (array('email', 'phone', 'subject', 'name') as $f)
-            if (isset($vars[$f]))
-                $vars[$f] = trim($vars[$f]);
+        // Identify the user creating the ticket and unpack user information
+        // fields into local scope for filtering and banning purposes
+        $user_form = UserForm::getInstance();
+        $user_info = $user_form->getClean();
+        if ($user_form->isValid())
+            $vars += $user_info;
 
         //Check for 403
         if ($vars['email']  && Validator::is_email($vars['email'])) {
@@ -1879,6 +1890,23 @@ class Ticket {
             }
         }
 
+        // Create and verify the dynamic form entry for the new ticket
+        $form = TicketForm::getInstance();
+        // If submitting via email, ensure we have a subject and such
+        foreach ($form->getFields() as $field) {
+            $fname = $field->get('name');
+            if ($fname && isset($vars[$fname]) && !$field->value)
+                $field->value = $vars[$fname];
+        }
+
+        // Don't enforce form validation for email
+        if (!$form->isValid() && strtolower($origin) != 'email')
+            $errors += $form->errors();
+
+        // Unpack dynamic variables into $vars for filter application
+        foreach ($form->getFields() as $f)
+            $vars['field.'.$f->get('id')] = $f->toString($f->getClean());
+
         //Init ticket filters...
         $ticket_filter = new TicketFilter($origin, $vars);
         // Make sure email contents should not be rejected
@@ -1895,9 +1923,6 @@ class Ticket {
 
         $id=0;
         $fields=array();
-        $fields['name']     = array('type'=>'string',   'required'=>1, 'error'=>'Name required');
-        $fields['email']    = array('type'=>'email',    'required'=>1, 'error'=>'Valid email required');
-        $fields['subject']  = array('type'=>'string',   'required'=>1, 'error'=>'Subject required');
         $fields['message']  = array('type'=>'text',     'required'=>1, 'error'=>'Message required');
         switch (strtolower($origin)) {
             case 'web':
@@ -1917,20 +1942,10 @@ class Ticket {
                 # TODO: Return error message
                 $errors['err']=$errors['origin'] = 'Invalid origin given';
         }
-        $fields['priorityId']   = array('type'=>'int',      'required'=>0, 'error'=>'Invalid Priority');
-        $fields['phone']        = array('type'=>'phone',    'required'=>0, 'error'=>'Valid phone # required');
 
         if(!Validator::process($fields, $vars, $errors) && !$errors['err'])
             $errors['err'] ='Missing or invalid data - check the errors and try again';
 
-        //Make sure phone extension is valid
-        if($vars['phone_ext'] ) {
-            if(!is_numeric($vars['phone_ext']) && !$errors['phone'])
-                $errors['phone']='Invalid phone ext.';
-            elseif(!$vars['phone']) //make sure they just didn't enter ext without phone # XXX: reconsider allowing!
-                $errors['phone']='Phone number required';
-        }
-
         //Make sure the due date is valid
         if($vars['duedate']) {
             if(!$vars['time'] || strpos($vars['time'],':')===false)
@@ -1941,9 +1956,21 @@ class Ticket {
                 $errors['duedate']='Due date must be in the future';
         }
 
+        // Data is slightly different between HTTP posts and emails
+        if ((isset($vars['emailId']) && $vars['emailId'])
+                || !isset($user_info['email']) || !$user_info['email']) {
+            $user_info = $vars;
+        }
+        elseif (!$user_form->isValid()) {
+            $errors['user'] = 'Incomplete client information';
+        }
+
         //Any error above is fatal.
         if($errors)  return 0;
 
+        $user = User::fromForm($user_info);
+        $user_email = UserEmail::ensure($user_info['email']);
+
         # Perform ticket filter actions on the new ticket arguments
         if ($ticket_filter) $ticket_filter->apply($vars);
 
@@ -1953,13 +1980,13 @@ class Ticket {
 
         // OK...just do it.
         $deptId=$vars['deptId']; //pre-selected Dept if any.
-        $priorityId=$vars['priorityId'];
         $source=ucfirst($vars['source']);
         $topic=NULL;
         // Intenal mapping magic...see if we need to override anything
         if(isset($vars['topicId']) && ($topic=Topic::lookup($vars['topicId']))) { //Ticket created via web by user/or staff
             $deptId=$deptId?$deptId:$topic->getDeptId();
-            $priorityId=$priorityId?$priorityId:$topic->getPriorityId();
+            if (!$form->getAnswer('priority'))
+                $form->setAnswer('priority', null, $topic->getPriorityId());
             if($autorespond) $autorespond=$topic->autoRespond();
             $source=$vars['source']?$vars['source']:'Web';
 
@@ -1977,13 +2004,15 @@ class Ticket {
 
         }elseif($vars['emailId'] && !$vars['deptId'] && ($email=Email::lookup($vars['emailId']))) { //Emailed Tickets
             $deptId=$email->getDeptId();
-            $priorityId=$priorityId?$priorityId:$email->getPriorityId();
+            if (!$form->getAnswer('priority'))
+                $form->setAnswer('priority', null, $email->getPriorityId());
             if($autorespond) $autorespond=$email->autoRespond();
             $email=null;
             $source='Email';
         }
         //Last minute checks
-        $priorityId=$priorityId?$priorityId:$cfg->getDefaultPriorityId();
+        if (!$form->getAnswer('priority'))
+            $form->setAnswer('priority', null, $cfg->getDefaultPriorityId());
         $deptId=$deptId?$deptId:$cfg->getDefaultDeptId();
         $topicId=$vars['topicId']?$vars['topicId']:0;
         $ipaddress=$vars['ip']?$vars['ip']:$_SERVER['REMOTE_ADDR'];
@@ -1992,15 +2021,11 @@ class Ticket {
         $extId=Ticket::genExtRandID();
         $sql='INSERT INTO '.TICKET_TABLE.' SET created=NOW() '
             .' ,lastmessage= NOW()'
+            .' ,user_id='.db_input($user->id)
+            .' ,user_email_id='.db_input($user_email->id)
             .' ,ticketID='.db_input($extId)
             .' ,dept_id='.db_input($deptId)
             .' ,topic_id='.db_input($topicId)
-            .' ,priority_id='.db_input($priorityId)
-            .' ,email='.db_input($vars['email'])
-            .' ,name='.db_input(Format::striptags($vars['name']))
-            .' ,subject='.db_input(Format::striptags($vars['subject']))
-            .' ,phone="'.db_input($vars['phone'],false).'"'
-            .' ,phone_ext='.db_input($vars['phone_ext']?$vars['phone_ext']:'')
             .' ,ip_address='.db_input($ipaddress)
             .' ,source='.db_input($source);
 
@@ -2021,6 +2046,10 @@ class Ticket {
             //TODO: RETHING what happens if this fails?? [At the moment on failure random ID is used...making stuff usable]
         }
 
+        // Save the (common) dynamic form
+        $form->setTicketId($id);
+        $form->save();
+
         $dept = $ticket->getDept();
 
         //post the message.
@@ -2092,11 +2121,6 @@ class Ticket {
         if($vars['source'] && !in_array(strtolower($vars['source']),array('email','phone','other')))
             $errors['source']='Invalid source - '.Format::htmlchars($vars['source']);
 
-        if(!$vars['issue'])
-            $errors['issue']='Summary of the issue required';
-        else
-            $vars['message']=$vars['issue'];
-
         if(!($ticket=Ticket::create($vars, $errors, 'staff', false, (!$vars['assignId']))))
             return false;
 
diff --git a/include/class.topic.php b/include/class.topic.php
index 801e6e684a0b9cc08f480d7ee80ecf7abaf0b66d..688cb7aaa2715d8e68b6ebfc03f2dc5148175ea6 100644
--- a/include/class.topic.php
+++ b/include/class.topic.php
@@ -223,10 +223,11 @@ class Topic {
             .',dept_id='.db_input($vars['dept_id'])
             .',priority_id='.db_input($vars['priority_id'])
             .',sla_id='.db_input($vars['sla_id'])
+            .',form_id='.db_input($vars['form_id'])
             .',page_id='.db_input($vars['page_id'])
             .',isactive='.db_input($vars['isactive'])
             .',ispublic='.db_input($vars['ispublic'])
-            .',noautoresp='.db_input(isset($vars['noautoresp'])?1:0)
+            .',noautoresp='.db_input(isset($vars['noautoresp']) && $vars['noautoresp']?1:0)
             .',notes='.db_input(Format::sanitize($vars['notes']));
 
         //Auto assign ID is overloaded...
diff --git a/include/class.user.php b/include/class.user.php
new file mode 100644
index 0000000000000000000000000000000000000000..b38ec252886395ecdba9580990fe648fb03e4149
--- /dev/null
+++ b/include/class.user.php
@@ -0,0 +1,305 @@
+<?php
+/*********************************************************************
+    class.user.php
+
+    External end-user identification for osTicket
+
+    Peter Rotich <peter@osticket.com>
+    Jared Hancock <jared@osticket.com>
+    Copyright (c)  2006-2013 osTicket
+    http://www.osticket.com
+
+    Released under the GNU General Public License WITHOUT ANY WARRANTY.
+    See LICENSE.TXT for details.
+
+    vim: expandtab sw=4 ts=4 sts=4:
+**********************************************************************/
+require_once(INCLUDE_DIR . 'class.orm.php');
+
+class UserEmailModel extends VerySimpleModel {
+    static $meta = array(
+        'table' => USER_EMAIL_TABLE,
+        'pk' => array('id'),
+        'joins' => array(
+            'user' => array(
+                'constraint' => array('user_id' => 'UserModel.id')
+            )
+        )
+    );
+}
+
+class UserModel extends VerySimpleModel {
+    static $meta = array(
+        'table' => USER_TABLE,
+        'pk' => array('id'),
+        'joins' => array(
+            'emails' => array(
+                'reverse' => 'UserEmailModel.user',
+            ),
+            'default_email' => array(
+                'null' => true,
+                'constraint' => array('default_email_id' => 'UserEmailModel.id')
+            ),
+        )
+    );
+
+    var $emails;
+
+    static function objects() {
+        $qs = parent::objects();
+        #$qs->select_related('default_email');
+        return $qs;
+    }
+
+    function getId() {
+        return $this->id;
+    }
+
+    function getDefaultEmailAddress() {
+        return $this->getDefaultEmail()->address;
+    }
+
+    function getDefaultEmail() {
+        return $this->default_email;
+    }
+}
+
+class User extends UserModel {
+
+    function __construct($ht) {
+        parent::__construct($ht);
+        // TODO: Make this automatic with select_related()
+        if (isset($ht['default_email_id']))
+            $this->default_email = UserEmail::lookup($ht['default_email_id']);
+    }
+
+    static function fromForm($data=false) {
+        // Try and lookup by email address
+        $user = User::lookup(array('emails__address'=>$data['email']));
+        if (!$user) {
+            $user = User::create(array('name'=>$data['name'],
+                'default_email'=>
+                    UserEmail::create(array('address'=>$data['email']))
+            ));
+            $user->save();
+            $user->emails->add($user->default_email);
+
+            // Attach initial custom fields
+            $uf = UserForm::getInstance();
+            foreach ($uf->getFields() as $f)
+                if (isset($data[$f->get('name')]))
+                    $uf->setAnswer($f->get('name'), $data[$f->get('name')]);
+            $uf->save();
+        }
+
+        return $user;
+    }
+
+    function getEmail() {
+        return $this->default_email->address;
+    }
+
+    function getFullName() {
+        return $this->name;
+    }
+
+    function getName() {
+        return new PersonsName($this->name);
+    }
+
+    function getDynamicData() {
+        $data = DynamicFormEntry::forClient($this->id);
+        if (!$data[0]) {
+            $data = array();
+            $g = UserForm::getInstance();
+            $g->setClientId($this->id);
+            $data[] = $g;
+        }
+        return $data;
+    }
+
+    function save($refetch=false) {
+        // Drop commas and reorganize the name without them
+        $parts = array_map('trim', explode(',', $this->name));
+        switch (count($parts)) {
+            case 2:
+                // Assume last, first --or-- last suff., first
+                $this->name = $parts[1].' '.$parts[0];
+                // XXX: Consider last, first suff.
+                break;
+            case 3:
+                // Assume last, first, suffix, write 'first last suffix'
+                $this->name = $parts[1].' '.$parts[0].' '.$parts[2];
+                break;
+        }
+        return parent::save($refetch);
+    }
+}
+User::_inspect();
+
+class PersonsName {
+    var $parts;
+    var $name;
+
+    static $formats = array(
+        'first' => array("First", 'getFirst'),
+        'last' => array("Last", 'getLast'),
+        'full' => array("First Last", 'getFull'),
+        'legal' => array("First M. Last", 'getLegal'),
+        'lastfirst' => array("Last, First", 'getLastFirst'),
+        'formal' => array("Mr. Last", 'getFormal'),
+        'short' => array("First L.", 'getShort'),
+        'shortformal' => array("F. Last", 'getShortFormal'),
+        'complete' => array("Mr. First M. Last Sr.", 'getComplete'),
+    );
+
+    function __construct($name) {
+        $this->parts = static::splitName($name);
+        $this->name = $name;
+    }
+
+    function getFirst() {
+        return $this->parts['first'];
+    }
+
+    function getLast() {
+        return $this->parts['last'];
+    }
+
+    function getMiddle() {
+        return $this->parts['middle'];
+    }
+
+    function getMiddleInitial() {
+        return mb_substr($this->parts['middle'],0,1).'.';
+    }
+
+    function getFormal() {
+        return trim($this->parts['salutation'].' '.$this->parts['last']);
+    }
+
+    function getFull() {
+        return trim($this->parts['first'].' '.$this->parts['last']);
+    }
+
+    function getLegal() {
+        $parts = array(
+            $this->parts['first'],
+            mb_substr($this->parts['middle'],0,1),
+            $this->parts['last'],
+        );
+        if ($parts[1]) $parts[1] .= '.';
+        return implode(' ', array_filter($parts));
+    }
+
+    function getComplete() {
+        $parts = array(
+            $this->parts['salutation'],
+            $this->parts['first'],
+            mb_substr($this->parts['middle'],0,1),
+            $this->parts['last'],
+            $this->parts['suffix']
+        );
+        if ($parts[2]) $parts[2] .= '.';
+        return implode(' ', array_filter($parts));
+    }
+
+    function getLastFirst() {
+        $name = $this->parts['last'].', '.$this->parts['first'];
+        if ($this->parts['suffix'])
+            $name .= ', '.$this->parts['suffix'];
+        return $name;
+    }
+
+    function getShort() {
+        return $this->parts['first'].' '.mb_substr($this->parts['last'],0,1).'.';
+    }
+
+    function getShortFormal() {
+        return mb_substr($this->parts['first'],0,1).'. '.$this->parts['last'];
+    }
+
+    function getOriginal() {
+        return $this->name;
+    }
+
+    function asVar() {
+        return $this->__toString();
+    }
+
+    function __toString() {
+        global $cfg;
+        $format = $cfg->getDefaultNameFormat();
+        list(,$func) = static::$formats[$format];
+        if (!$func) $func = 'getFull';
+        return call_user_func(array($this, $func));
+    }
+
+    static function allFormats() {
+        return static::$formats;
+    }
+
+    /**
+     * Thanks, http://stackoverflow.com/a/14420217
+     */
+    static function splitName($name) {
+        $results = array();
+
+        $r = explode(' ', $name);
+        $size = count($r);
+
+        //check first for period, assume salutation if so
+        if (mb_strpos($r[0], '.') === false)
+        {
+            $results['salutation'] = '';
+            $results['first'] = $r[0];
+        }
+        else
+        {
+            $results['salutation'] = $r[0];
+            $results['first'] = $r[1];
+        }
+
+        //check last for period, assume suffix if so
+        if (mb_strpos($r[$size - 1], '.') === false)
+        {
+            $results['suffix'] = '';
+        }
+        else
+        {
+            $results['suffix'] = $r[$size - 1];
+        }
+
+        //combine remains into last
+        $start = ($results['salutation']) ? 2 : 1;
+        $end = ($results['suffix']) ? $size - 2 : $size - 1;
+
+        $middle = array();
+        for ($i = $start; $i <= $end; $i++)
+        {
+            $middle[] = $r[$i];
+        }
+        if (count($middle) > 1) {
+            $results['last'] = array_pop($middle);
+            $results['middle'] = implode(' ', $middle);
+        }
+        else {
+            $results['last'] = $middle[0];
+            $results['middle'] = '';
+        }
+
+        return $results;
+    }
+
+}
+
+class UserEmail extends UserEmailModel {
+    static function ensure($address) {
+        $email = static::lookup(array('address'=>$address));
+        if (!$email) {
+            $email = static::create(array('address'=>$address));
+            $email->save();
+        }
+        return $email;
+    }
+}
diff --git a/include/client/header.inc.php b/include/client/header.inc.php
index 2849ccbe3221aafd203cc8dcaf2bf6c28d39fd51..e03f36cbb1aa29b762fc8f4e5eaadba7a51aa489 100644
--- a/include/client/header.inc.php
+++ b/include/client/header.inc.php
@@ -13,7 +13,10 @@ header("Content-Type: text/html; charset=UTF-8\r\n");
     <link rel="stylesheet" href="<?php echo ROOT_PATH; ?>css/osticket.css" media="screen">
     <link rel="stylesheet" href="<?php echo ASSETS_PATH; ?>css/theme.css" media="screen">
     <link rel="stylesheet" href="<?php echo ASSETS_PATH; ?>css/print.css" media="print">
-    <link type="text/css" href="<?php echo ROOT_PATH; ?>css/ui-lightness/jquery-ui-1.10.3.custom.min.css" rel="stylesheet" />
+    <link rel="stylesheet" href="<?php echo ROOT_PATH; ?>scp/css/typeahead.css"
+         media="screen" />
+    <link type="text/css" href="<?php echo ROOT_PATH; ?>css/ui-lightness/jquery-ui-1.10.3.custom.min.css"
+        rel="stylesheet" media="screen" />
     <link rel="stylesheet" href="<?php echo ROOT_PATH; ?>css/thread.css" media="screen">
     <link rel="stylesheet" href="<?php echo ROOT_PATH; ?>css/redactor.css" media="screen">
     <link type="text/css" rel="stylesheet" href="<?php echo ROOT_PATH; ?>css/font-awesome.min.css">
@@ -21,6 +24,7 @@ header("Content-Type: text/html; charset=UTF-8\r\n");
     <script type="text/javascript" src="<?php echo ROOT_PATH; ?>js/jquery-ui-1.10.3.custom.min.js"></script>
     <script src="<?php echo ROOT_PATH; ?>js/jquery.multifile.js"></script>
     <script src="<?php echo ROOT_PATH; ?>js/osticket.js"></script>
+    <script src="<?php echo ROOT_PATH; ?>scp/js/bootstrap-typeahead.js"></script>
     <script type="text/javascript" src="<?php echo ROOT_PATH; ?>js/redactor.min.js"></script>
     <script type="text/javascript" src="<?php echo ROOT_PATH; ?>js/redactor-osticket.js"></script>
     <?php
diff --git a/include/client/open.inc.php b/include/client/open.inc.php
index a0a97b7a3aa711a7446236f249cff0cb084fec8b..b9ba42e2421ed3b35dff180016427ce484c3648e 100644
--- a/include/client/open.inc.php
+++ b/include/client/open.inc.php
@@ -4,8 +4,7 @@ $info=array();
 if($thisclient && $thisclient->isValid()) {
     $info=array('name'=>$thisclient->getName(),
                 'email'=>$thisclient->getEmail(),
-                'phone'=>$thisclient->getPhone(),
-                'phone_ext'=>$thisclient->getPhoneExt());
+                'phone'=>$thisclient->getPhone());
 }
 
 $info=($_POST && $errors)?Format::htmlchars($_POST):$info;
@@ -16,47 +15,14 @@ $info=($_POST && $errors)?Format::htmlchars($_POST):$info;
   <?php csrf_token(); ?>
   <input type="hidden" name="a" value="open">
   <table width="800" cellpadding="1" cellspacing="0" border="0">
-    <tr>
-        <th class="required" width="160">Full Name:</th>
-        <td>
-            <?php
-            if($thisclient && $thisclient->isValid()) {
-                echo $thisclient->getName();
-            } else { ?>
-                <input id="name" type="text" name="name" size="30" value="<?php echo $info['name']; ?>">
-                <font class="error">*&nbsp;<?php echo $errors['name']; ?></font>
-            <?php
-            } ?>
-        </td>
-    </tr>
-    <tr>
-        <th class="required" width="160">Email Address:</th>
-        <td>
-            <?php
-            if($thisclient && $thisclient->isValid()) {
-                echo $thisclient->getEmail();
-            } else { ?>
-                <input id="email" type="text" name="email" size="30" value="<?php echo $info['email']; ?>">
-                <font class="error">*&nbsp;<?php echo $errors['email']; ?></font>
-            <?php
-            } ?>
-        </td>
-    </tr>
-    <tr>
-        <th>Telephone:</th>
-        <td>
-
-            <input id="phone" type="text" name="phone" size="17" value="<?php echo $info['phone']; ?>">
-            <label for="ext" class="inline">Ext.:</label>
-            <input id="ext" type="text" name="phone_ext" size="3" value="<?php echo $info['phone_ext']; ?>">
-            <font class="error">&nbsp;<?php echo $errors['phone']; ?>&nbsp;&nbsp;<?php echo $errors['phone_ext']; ?></font>
-        </td>
-    </tr>
-    <tr><td colspan=2>&nbsp;</td></tr>
+    <tbody>
     <tr>
         <td class="required">Help Topic:</td>
         <td>
-            <select id="topicId" name="topicId">
+            <select id="topicId" name="topicId" onchange="javascript:
+                    $('#dynamic-form').load(
+                        'ajax.php/form/help-topic/' + this.value);
+                    ">
                 <option value="" selected="selected">&mdash; Select a Help Topic &mdash;</option>
                 <?php
                 if($topics=Topic::getPublicHelpTopics()) {
@@ -72,60 +38,23 @@ $info=($_POST && $errors)?Format::htmlchars($_POST):$info;
             <font class="error">*&nbsp;<?php echo $errors['topicId']; ?></font>
         </td>
     </tr>
-    <tr>
-        <td class="required">Subject:</td>
-        <td>
-            <input id="subject" type="text" name="subject" size="40" value="<?php echo $info['subject']; ?>">
-            <font class="error">*&nbsp;<?php echo $errors['subject']; ?></font>
-        </td>
-    </tr>
-    <tr>
-        <td class="required">Message:</td>
-        <td>
-            <div style="margin-bottom:0.5em;"><em>Please provide as much detail as possible so we can best assist you.</em> <font class="error">*&nbsp;<?php echo $errors['message']; ?></font>
-                </div>
-            <textarea id="message" cols="60" rows="8" name="message"
-                class="richtext ifhtml draft"
-                data-draft-namespace="ticket.client"
-                data-draft-object-id="<?php echo substr(session_id(), -12); ?>"
-                ><?php echo $info['message']; ?></textarea>
-        </td>
-    </tr>
-
-    <?php if(($cfg->allowOnlineAttachments() && !$cfg->allowAttachmentsOnlogin())
-            || ($cfg->allowAttachmentsOnlogin() && ($thisclient && $thisclient->isValid()))) { ?>
-    <tr>
-        <td>Attachments:</td>
-        <td>
-            <div class="uploads"></div><br>
-            <input type="file" class="multifile" name="attachments[]" id="attachments" size="30" value="" />
-            <font class="error">&nbsp;<?php echo $errors['attachments']; ?></font>
-        </td>
-    </tr>
-    <tr><td colspan=2>&nbsp;</td></tr>
-    <?php } ?>
-    <?php
-    if($cfg->allowPriorityChange() && ($priorities=Priority::getPriorities())) { ?>
-    <tr>
-        <td>Ticket Priority:</td>
-        <td>
-            <select id="priority" name="priorityId">
-                <?php
-                    if(!$info['priorityId'])
-                        $info['priorityId'] = $cfg->getDefaultPriorityId(); //System default.
-                    foreach($priorities as $id =>$name) {
-                        echo sprintf('<option value="%d" %s>%s</option>',
-                                        $id, ($info['priorityId']==$id)?'selected="selected"':'', $name);
-
-                    }
-                ?>
-            </select>
-            <font class="error">&nbsp;<?php echo $errors['priorityId']; ?></font>
-        </td>
-    </tr>
-    <?php
-    }
-    ?>
+<?php
+        if (!$thisclient) {
+            UserForm::getInstance()->render(false, 'Your Information');
+        }
+        else { ?>
+            <tr><td colspan="2"><hr /></td></tr>
+        <tr><td>Email:</td><td><?php echo $thisclient->getEmail(); ?></td></tr>
+        <tr><td>Client:</td><td><?php echo $thisclient->getName(); ?></td></tr>
+        <?php }
+        TicketForm::getInstance()->render(false); ?>
+    </tbody>
+    <tbody id="dynamic-form">
+        <?php if ($form) {
+            include(CLIENTINC_DIR . 'templates/dynamic-form.tmpl.php');
+        } ?>
+    </tbody>
+    <tbody>
     <?php
     if($cfg && $cfg->isCaptchaEnabled() && (!$thisclient || !$thisclient->isValid())) {
         if($_POST && $errors && !$errors['captcha'])
@@ -144,6 +73,7 @@ $info=($_POST && $errors)?Format::htmlchars($_POST):$info;
     <?php
     } ?>
     <tr><td colspan=2>&nbsp;</td></tr>
+    </tbody>
   </table>
   <p style="padding-left:150px;">
         <input type="submit" value="Create Ticket">
diff --git a/include/client/templates/dynamic-form.tmpl.php b/include/client/templates/dynamic-form.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..5eac1d38a00826a471d88dba0fde260b53c7798a
--- /dev/null
+++ b/include/client/templates/dynamic-form.tmpl.php
@@ -0,0 +1,51 @@
+<?php
+    // Form headline and deck with a horizontal divider above and an extra
+    // space below.
+    // XXX: Would be nice to handle the decoration with a CSS class
+    ?>
+    <tr><td colspan="2"><hr />
+    <div class="form-header" style="margin-bottom:0.5em">
+    <h3><?php echo Format::htmlchars($form->getTitle()); ?></h3>
+    <em><?php echo Format::htmlchars($form->getInstructions()); ?></em>
+    </div>
+    </td></tr>
+    <?php
+    // Form fields, each with corresponding errors follows. Fields marked
+    // 'private' are not included in the output for clients
+    global $thisclient;
+    foreach ($form->getFields() as $field) {
+        if ($field->get('private'))
+            continue;
+        ?>
+        <tr>
+            <?php if ($field->isBlockLevel()) { ?>
+                <td colspan="2">
+            <?php
+            }
+            else { ?>
+                <td><label for="<?php echo $field->getFormname(); ?>" class="<?php
+                    if ($field->get('required')) echo 'required'; ?>">
+                <?php echo Format::htmlchars($field->get('label')); ?>:</label></td><td>
+            <?php
+            }
+            $field->render('client'); ?>
+            <?php if ($field->get('required')) { ?>
+                <font class="error">*</font>
+            <?php
+            }
+            if ($field->get('hint') && !$field->isBlockLevel()) { ?>
+                <br /><em style="color:gray;display:inline-block"><?php
+                    echo Format::htmlchars($field->get('hint')); ?></em>
+            <?php
+            }
+            foreach ($field->errors() as $e) { ?>
+                <br />
+                <font class="error"><?php echo $e; ?></font>
+            <?php }
+            $field->renderExtras('client');
+            ?>
+            </td>
+        </tr>
+        <?php
+    }
+?>
diff --git a/include/client/tickets.inc.php b/include/client/tickets.inc.php
index 8eda7eca323e9cf5a9cc8b142575acd9a72d59de..7c2c6e56436e5fcf454caf8c6dca5d117f4f6e72 100644
--- a/include/client/tickets.inc.php
+++ b/include/client/tickets.inc.php
@@ -18,8 +18,8 @@ if(isset($_REQUEST['status'])) { //Query string status has nothing to do with th
     $status='open'; //Defaulting to open
 }
 
-$sortOptions=array('id'=>'ticketID', 'name'=>'ticket.name', 'subject'=>'ticket.subject',
-                    'email'=>'ticket.email', 'status'=>'ticket.status', 'dept'=>'dept_name','date'=>'ticket.created');
+$sortOptions=array('id'=>'ticketID', 'name'=>'user.name', 'subject'=>'subject.value',
+                    'email'=>'email.address', 'status'=>'ticket.status', 'dept'=>'dept_name','date'=>'ticket.created');
 $orderWays=array('DESC'=>'DESC','ASC'=>'ASC');
 //Sorting options...
 $order_by=$order=null;
@@ -38,13 +38,24 @@ if($order_by && strpos($order_by,','))
 $x=$sort.'_sort';
 $$x=' class="'.strtolower($order).'" ';
 
-$qselect='SELECT ticket.ticket_id,ticket.ticketID,ticket.dept_id,isanswered, dept.ispublic, ticket.subject, ticket.name, ticket.email '.
-           ',dept_name,ticket. status, ticket.source, ticket.created ';
+$qselect='SELECT ticket.ticket_id,ticket.ticketID,ticket.dept_id,isanswered, '
+    .'dept.ispublic, subject.value as subject, '
+    .'user.name, email.address as email, '
+    .'dept_name,ticket. status, ticket.source, ticket.created ';
+
+$dynfields='(SELECT entry.object_id, value FROM '.FORM_ANSWER_TABLE.' ans '.
+         'LEFT JOIN '.FORM_ENTRY_TABLE.' entry ON entry.id=ans.entry_id '.
+         'LEFT JOIN '.FORM_FIELD_TABLE.' field ON field.id=ans.field_id '.
+         'WHERE field.name = "%1$s" AND entry.object_type="T")';
+$subject_sql = sprintf($dynfields, 'subject');
 
 $qfrom='FROM '.TICKET_TABLE.' ticket '
-      .' LEFT JOIN '.DEPT_TABLE.' dept ON (ticket.dept_id=dept.dept_id) ';
+      .' LEFT JOIN '.DEPT_TABLE.' dept ON (ticket.dept_id=dept.dept_id) '
+      .' LEFT JOIN '.USER_TABLE.' user ON user.id = ticket.user_id'
+      .' LEFT JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id'
+      .' LEFT JOIN '.$subject_sql.' subject ON ticket.ticket_id = subject.object_id ';
 
-$qwhere =' WHERE ticket.email='.db_input($thisclient->getEmail());
+$qwhere =' WHERE email.address='.db_input($thisclient->getEmail());
 
 if($status){
     $qwhere.=' AND ticket.status='.db_input($status);
@@ -58,7 +69,7 @@ if($search) {
     } else {//Deep search!
         $queryterm=db_real_escape($_REQUEST['q'],false); //escape the term ONLY...no quotes.
         $qwhere.=' AND ( '
-                ." ticket.subject LIKE '%$queryterm%'"
+                ." subject.value LIKE '%$queryterm%'"
                 ." OR thread.body LIKE '%$queryterm%'"
                 .' ) ';
         $deep_search=true;
diff --git a/include/client/view.inc.php b/include/client/view.inc.php
index f85cff8daeeb59620f5d188978b7aa2ba1a0ba51..0ec5b9941224397b5f5e99239454bc05b35be33e 100644
--- a/include/client/view.inc.php
+++ b/include/client/view.inc.php
@@ -52,6 +52,30 @@ if(!$dept || !$dept->isPublic())
             </table>
        </td>
     </tr>
+    <tr>
+<?php
+foreach (DynamicFormEntry::forTicket($ticket->getId()) as $idx=>$form) {
+    $answers = $form->getAnswers();
+    if ($idx > 0 and $idx % 2 == 0) { ?>
+        </tr><tr>
+    <?php } ?>
+    <td width="50%">
+        <table class="infoTable" cellspacing="1" cellpadding="3" width="100%" border="0">
+    <?php foreach ($answers as $answer) {
+        if (in_array($answer->getField()->get('name'), array('name', 'email', 'subject')))
+            continue;
+        elseif ($answer->getField()->get('private'))
+            continue;
+        ?>
+        <tr>
+        <th width="100"><?php echo $answer->getField()->get('label');
+            ?>:</th>
+        <td><?php echo $answer->toString(); ?></td>
+        </tr>
+    <?php } ?>
+    </table></td>
+<?php } ?>
+</tr>
 </table>
 <br>
 <h2>Subject:<?php echo Format::htmlchars($ticket->getSubject()); ?></h2>
diff --git a/include/i18n/en_US/form.yaml b/include/i18n/en_US/form.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..69b3ae30b0d0af5afd2df0dd0f25a2a0c1ba4482
--- /dev/null
+++ b/include/i18n/en_US/form.yaml
@@ -0,0 +1,105 @@
+#
+# Default (dynamic) form configuration. This data is used as the initial,
+# minimal data for dynamic forms that ships with the system.
+#
+# Fields:
+# id:       Used only if associated with a help topic
+# title:    Bold section title of the form
+# instructions: Title deck, detailed instructions on entering form data
+# notes:    Notes for the form, shown under the fields
+# deletable: True if the form can be removed from the system
+# fields:   List of fields for the form
+#   type:       Field type (short name) (eg. 'text', 'memo', 'phone', ...)
+#   label:      Field label shown to the user
+#   name:       Name used with the data internally. This is especially
+#               useful for page and email templates, where %{ ticket.<name> }
+#               will be used to retrieve the data from the field.
+#   hint:       Help text shown with the field
+#   edit_mask:  Mask out edits to the field (1=>delete, 2=>change name,
+#                   4=>privacy setting, 8=>requirement setting)
+#   private:    True if the field should be hidden from the client
+#   required:   True if entry for the field is required
+#   configuration: Field-specific configuration
+#     size:     (text) width of the field
+#     length:   (text) maximum size of the data in the field
+#     cols:     (memo) width of the textarea
+#     rows:     (memo) height of the textarea
+#
+---
+- id: 1
+  type: U # notrans
+  title: Contact Information
+  deletable: false
+  fields:
+    - type: text # notrans
+      name: email # notrans
+      label: Email Address
+      required: true
+      sort: 1
+      edit_mask: 15
+      configuration:
+        size: 40
+        length: 64
+        validator: email # notrans
+
+    - type: text # notrans
+      name: name # notrans
+      label: Full Name
+      required: true
+      sort: 2
+      edit_mask: 15
+      configuration:
+        size: 40
+        length: 64
+
+    - type: phone # notrans
+      name: phone # notrans
+      label: Phone Number
+      required: false
+      sort: 3
+
+    - type: memo # notrans
+      name: notes
+      label: Internal Notes
+      required: false
+      private: true
+      sort: 4
+      configuration:
+        rows: 4
+        cols: 40
+
+- id: 2
+  type: T # notrans
+  title: Ticket Details
+  instructions: Please Describe Your Issue
+  notes: |
+      This form will be attached to every ticket, regardless of its source.
+      You can add any fields to this form and they will be available to all
+      tickets, and will be searchable with advanced search and filterable.
+  deletable: false
+  fields:
+    - type: text # notrans
+      name: subject # notrans
+      label: Issue Summary
+      required: true
+      edit_mask: 15
+      sort: 1
+      configuration:
+        size: 40
+        length: 50
+
+    - type: thread # notrans
+      name: message # notrans
+      label: Issue Details
+      hint: Details on the reason(s) for opening the ticket.
+      required: true
+      edit_mask: 15
+      sort: 2
+
+    - type: priority # notrans
+      name: priority # notrans
+      label: Priority Level
+      required: false
+      private: true
+      edit_mask: 3
+      sort: 3
diff --git a/include/i18n/en_US/help_topic.yaml b/include/i18n/en_US/help_topic.yaml
index 11d7e819ccdaf3b5469e622bc4a974536130192d..fe5294319fa36118dd756a53b7bb5d6bc2ded8a8 100644
--- a/include/i18n/en_US/help_topic.yaml
+++ b/include/i18n/en_US/help_topic.yaml
@@ -23,6 +23,7 @@
   dept_id: 1
   sla_id: 1
   priority_id: 2
+  form_id: 0
   topic: Support
   notes: |
     Tickets that primarily concern the support deparment
@@ -32,6 +33,7 @@
   dept_id: 1
   sla_id: 0
   priority_id: 2
+  form_id: 0
   topic: Billing
   notes: |
     Tickets that primarily concern the sales and billing deparments
diff --git a/include/i18n/en_US/templates/premade.yaml b/include/i18n/en_US/templates/premade.yaml
index 8483de8b9ce7a05dd2a510b64cf1833d509af2ba..fa73ee8f9f87c79e212ddf42e8fbda7f899f6643 100644
--- a/include/i18n/en_US/templates/premade.yaml
+++ b/include/i18n/en_US/templates/premade.yaml
@@ -17,7 +17,7 @@
 
 - title: Sample (with variables)
   response: |
-    %{ticket.name},
+    Hi %{ticket.name.first},
 
     Your ticket #%{ticket.number} created on %{ticket.create_date} is in
     %{ticket.dept.name} department.
diff --git a/include/mysqli.php b/include/mysqli.php
index ad545a5dbfd8a9fae8206c0e6e14189809e1105b..13ce86ec5ffa293cf91a23de4bfe2dc8e5fe4044 100644
--- a/include/mysqli.php
+++ b/include/mysqli.php
@@ -225,6 +225,11 @@ function db_field_type($res, $col=0) {
     return $res->fetch_field_direct($col); # nolint
 }
 
+function db_prepare($stmt) {
+    global $__db;
+    return $__db->prepare($stmt);
+}
+
 function db_connect_error() {
     global $__db;
     return $__db->connect_error;
diff --git a/include/staff/dynamic-form.inc.php b/include/staff/dynamic-form.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..b5f18b1411284bf260901077a9e2a987c7cde636
--- /dev/null
+++ b/include/staff/dynamic-form.inc.php
@@ -0,0 +1,208 @@
+<?php
+
+$info=array();
+if($form && $_REQUEST['a']!='add') {
+    $title = 'Update custom form section';
+    $action = 'update';
+    $submit_text='Save Changes';
+    $info = $form->ht;
+    $newcount=2;
+} else {
+    $title = 'Add new custom form section';
+    $action = 'add';
+    $submit_text='Add Form';
+    $newcount=4;
+}
+$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
+
+?>
+<form action="?id=<?php echo urlencode($_REQUEST['id']); ?>" method="post" id="save">
+    <?php csrf_token(); ?>
+    <input type="hidden" name="do" value="<?php echo $action; ?>">
+    <input type="hidden" name="id" value="<?php echo $info['id']; ?>">
+    <h2>Custom Form</h2>
+    <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2">
+    <thead>
+        <tr>
+            <th colspan="2">
+                <h4><?php echo $title; ?></h4>
+                <em>Custom forms are used to allow custom data to be
+                associated with tickets</em>
+            </th>
+        </tr>
+    </thead>
+    <tbody>
+        <tr>
+            <td width="180" class="required">Title:</td>
+            <td><input type="text" name="title" size="40" value="<?php
+                echo $info['title']; ?>"/></td>
+        </tr>
+        <tr>
+            <td width="180">Instructions:</td>
+            <td><textarea name="instructions" rows="3" cols="40"><?php
+                echo $info['instructions']; ?></textarea>
+            </td>
+        </tr>
+    </tbody>
+    </table>
+    <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2">
+    <?php if ($form && $form->get('type') == 'T') { ?>
+    <thead>
+        <tr>
+            <th colspan="7">
+                <em><strong>User Information Fields</strong> more information here</em>
+            </th>
+        </tr>
+        <tr>
+            <th></th>
+            <th>Label</th>
+            <th>Type</th>
+            <th>Internal</th>
+            <th>Required</th>
+            <th>Name</th>
+            <th>Delete</th>
+        </tr>
+    </thead>
+    <tbody>
+    <?php
+        $uform = UserForm::objects()->all();
+        $ftypes = FormField::allTypes();
+        foreach ($uform[0]->getFields() as $f) {
+            if ($f->get('private')) continue;
+        ?>
+        <tr>
+            <td></td>
+            <td><?php echo $f->get('label'); ?></td>
+            <td><?php $t=FormField::getFieldType($f->get('type')); echo $t[0]; ?></td>
+            <td><input type="checkbox" disabled="disabled"/></td>
+            <td><input type="checkbox" disabled="disabled"
+                <?php echo $f->get('required') ? 'checked="checked"' : ''; ?>/></td>
+            <td><?php echo $f->get('name'); ?></td>
+            <td><input type="checkbox" disabled="disabled"/></td></tr>
+
+        <?php } ?>
+    </tbody>
+    <?php } # form->type == 'T' ?>
+    <thead>
+        <tr>
+            <th colspan="7">
+                <em><strong>Form Fields</strong> fields available for ticket information</em>
+            </th>
+        </tr>
+        <tr>
+            <th>Sort</th>
+            <th>Label</th>
+            <th>Type</th>
+            <th>Internal</th>
+            <th>Required</th>
+            <th>Name</th>
+            <th>Delete</th>
+        </tr>
+    </thead>
+    <tbody class="sortable-rows" data-sort="sort-">
+    <?php if ($form) foreach ($form->getFields() as $f) {
+        $id = $f->get('id');
+        $deletable = !$f->isDeletable() ? 'disabled="disabled"' : '';
+        $force_name = $f->isNameForced() ? 'disabled="disabled"' : '';
+        $force_privacy = $f->isPrivacyForced() ? 'disabled="disabled"' : '';
+        $force_required = $f->isRequirementForced() ? 'disabled="disabled"' : '';
+        $errors = $f->errors(); ?>
+        <tr>
+            <td><i class="icon-sort"></i></td>
+            <td><input type="text" size="32" name="label-<?php echo $id; ?>"
+                value="<?php echo $f->get('label'); ?>"/></td>
+            <td><select name="type-<?php echo $id; ?>" <?php
+                if (!$f->isChangeable()) echo 'disabled="disabled"'; ?>>
+                <?php foreach (FormField::allTypes() as $group=>$types) {
+                        ?><optgroup label="<?php echo Format::htmlchars($group); ?>"><?php
+                        foreach ($types as $type=>$nfo) {
+                            if ($f->get('type') != $type
+                                    && isset($nfo[2]) && !$nfo[2]) continue; ?>
+                <option value="<?php echo $type; ?>" <?php
+                    if ($f->get('type') == $type) echo 'selected="selected"'; ?>>
+                    <?php echo $nfo[0]; ?></option>
+                    <?php } ?>
+                </optgroup>
+                <?php } ?>
+            </select>
+            <?php if ($f->isConfigurable()) { ?>
+                <a class="action-button" style="float:none;overflow:inherit"
+                    href="ajax.php/form/field-config/<?php
+                        echo $f->get('id'); ?>"
+                    onclick="javascript:
+                        $('#overlay').show();
+                        $('#field-config .body').load(this.href);
+                        $('#field-config').show();
+                        return false;
+                    "><i class="icon-edit"></i> Config</a>
+            <?php } ?></td>
+            <td><input type="checkbox" name="private-<?php echo $id; ?>"
+                <?php if ($f->get('private')) echo 'checked="checked"'; ?>
+                <?php echo $force_privacy ?>/></td>
+            <td><input type="checkbox" name="required-<?php echo $id; ?>"
+                <?php if ($f->get('required')) echo 'checked="checked"'; ?>
+                <?php echo $force_required ?>/>
+            </td>
+            <td>
+                <input type="text" size="20" name="name-<?php echo $id; ?>"
+                    value="<?php echo $f->get('name'); ?>" <?php echo $force_name ?>/>
+                <font class="error"><?php
+                    if ($errors['name']) echo '<br/>'; echo $errors['name'];
+                ?></font>
+                </td>
+            <td><input type="checkbox" name="delete-<?php echo $id; ?>"
+                    <?php echo $deletable; ?>/>
+                <input type="hidden" name="sort-<?php echo $id; ?>"
+                    value="<?php echo $f->get('sort'); ?>"/>
+                </td>
+        </tr>
+    <?php
+    }
+    for ($i=0; $i<$newcount; $i++) { ?>
+            <td><em>+</em>
+                <input type="hidden" name="sort-new-<?php echo $i; ?>"/></td>
+            <td><input type="text" size="32" name="label-new-<?php echo $i; ?>"/></td>
+            <td><select name="type-new-<?php echo $i; ?>">
+                <?php foreach (FormField::allTypes() as $group=>$types) {
+                    ?><optgroup label="<?php echo Format::htmlchars($group); ?>"><?php
+                    foreach ($types as $type=>$nfo) {
+                        if (isset($nfo[2]) && !$nfo[2]) continue; ?>
+                <option value="<?php echo $type; ?>">
+                    <?php echo $nfo[0]; ?></option>
+                    <?php } ?>
+                </optgroup>
+                <?php } ?>
+            </select></td>
+            <td><input type="checkbox" name="private-new-<?php echo $i; ?>"
+                <?php if ($form && $form->get('type') == 'U')
+                    echo 'checked="checked"'; ?>/></td>
+            <td><input type="checkbox" name="required-new-<?php echo $i; ?>"/></td>
+            <td><input type="text" size="20" name="name-new-<?php echo $i; ?>"/></td>
+            <td></td>
+        </tr>
+    <?php } ?>
+    </tbody>
+    <tbody>
+        <tr>
+            <th colspan="7">
+                <em><strong>Internal Notes:</strong> be liberal, they're internal</em>
+            </th>
+        </tr>
+        <tr>
+            <td colspan="7"><textarea class="richtext no-bar" name="notes"
+                rows="6" cols="80"><?php
+                echo $info['notes']; ?></textarea>
+            </td>
+        </tr>
+    </tbody>
+    </table>
+<p class="centered">
+    <input type="submit" name="submit" value="<?php echo $submit_text; ?>">
+    <input type="reset"  name="reset"  value="Reset">
+    <input type="button" name="cancel" value="Cancel" onclick='window.location.href="?"'>
+</p>
+</form>
+
+<div style="display:none;" class="dialog" id="field-config">
+    <div class="body"></div>
+</div>
diff --git a/include/staff/dynamic-forms.inc.php b/include/staff/dynamic-forms.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..2c4fa1d2c413191f5e648f16bc614292470814c7
--- /dev/null
+++ b/include/staff/dynamic-forms.inc.php
@@ -0,0 +1,128 @@
+<div style="width:700;padding-top:5px; float:left;">
+ <h2>Custom Forms</h2>
+</div>
+<div style="float:right;text-align:right;padding-top:5px;padding-right:5px;">
+ <b><a href="forms.php?a=add" class="Icon form-add">Add New Custom Form</a></b></div>
+<div class="clear"></div>
+
+<?php
+$page = ($_GET['p'] && is_numeric($_GET['p'])) ? $_GET['p'] : 1;
+$count = DynamicForm::objects()->filter(array('type__in'=>array('T','U','G')))->count();
+$pageNav = new Pagenate($count, $page, PAGE_LIMIT);
+$pageNav->setURL('forms.php');
+$showing=$pageNav->showing().' forms';
+?>
+
+<form action="forms.php" method="POST" name="forms">
+<?php csrf_token(); ?>
+<input type="hidden" name="do" value="mass_process" >
+<input type="hidden" id="action" name="a" value="" >
+<table class="list" border="0" cellspacing="1" cellpadding="0" width="940">
+    <thead>
+        <tr>
+            <th width="7">&nbsp;</th>
+            <th>Client Information Form <em>Added to all clients</em></th>
+            <th>Last Updated</th>
+        </tr>
+    </thead>
+    <tbody>
+    <?php foreach (UserForm::objects()->order_by('title')
+                ->limit($pageNav->getLimit())
+                ->offset($pageNav->getStart()) as $form) { ?>
+        <tr>
+            <td/>
+            <td><a href="?id=<?php echo $form->get('id'); ?>"><?php echo $form->get('title'); ?></a></td>
+            <td><?php echo $form->get('updated'); ?></td>
+        </tr>
+    <?php } ?>
+    </tbody>
+    <thead>
+        <tr>
+            <th width="7">&nbsp;</th>
+            <th>Common Ticket Form <em>Added to all tickets</em></th>
+            <th>Last Updated</th>
+        </tr>
+    </thead>
+    <tbody>
+    <?php foreach (TicketForm::objects()->order_by('title')
+                ->limit($pageNav->getLimit())
+                ->offset($pageNav->getStart()) as $form) { ?>
+        <tr>
+            <td/>
+            <td><a href="?id=<?php echo $form->get('id'); ?>"><?php echo $form->get('title'); ?></a></td>
+            <td><?php echo $form->get('updated'); ?></td>
+        </tr>
+    <?php } ?>
+    </tbody>
+    <tbody>
+    <caption><?php echo $showing; ?></caption>
+    <thead>
+        <tr>
+            <th width="7">&nbsp;</th>
+            <th>Title</th>
+            <th>Last Updated</th>
+        </tr>
+    </thead>
+    <tbody>
+    <?php foreach (DynamicForm::objects()->filter(array('type'=>'G'))
+                ->order_by('title')
+                ->limit($pageNav->getLimit())
+                ->offset($pageNav->getStart()) as $form) {
+            $sel=false;
+            if($ids && in_array($form->get('id'),$ids))
+                $sel=true; ?>
+        <tr>
+            <td><?php if ($form->isDeletable()) { ?>
+                <input type="checkbox" class="ckb" name="ids[]" value="<?php echo $form->get('id'); ?>"
+                    <?php echo $sel?'checked="checked"':''; ?>>
+            <?php } ?></td>
+            <td><a href="?id=<?php echo $form->get('id'); ?>"><?php echo $form->get('title'); ?></a></td>
+            <td><?php echo $form->get('updated'); ?></td>
+        </tr>
+    <?php }
+    ?>
+    </tbody>
+    <tfoot>
+     <tr>
+        <td colspan="3">
+            <?php if($count){ ?>
+            Select:&nbsp;
+            <a id="selectAll" href="#ckb">All</a>&nbsp;&nbsp;
+            <a id="selectNone" href="#ckb">None</a>&nbsp;&nbsp;
+            <a id="selectToggle" href="#ckb">Toggle</a>&nbsp;&nbsp;
+            <?php }else{
+                echo 'No extra forms defined yet &mdash; add one!';
+            } ?>
+        </td>
+     </tr>
+    </tfoot>
+</table>
+<?php
+if ($count) //Show options..
+    echo '<div>&nbsp;Page:'.$pageNav->getPageLinks().'&nbsp;</div>';
+?>
+<p class="centered" id="actions">
+    <input class="button" type="submit" name="delete" value="Delete">
+</p>
+</form>
+
+<div style="display:none;" class="dialog" id="confirm-action">
+    <h3>Please Confirm</h3>
+    <a class="close" href="">&times;</a>
+    <hr/>
+    <p class="confirm-action" style="display:none;" id="delete-confirm">
+        <font color="red"><strong>Are you sure you want to DELETE selected forms?</strong></font>
+        <br><br>Deleted forms CANNOT be recovered.
+    </p>
+    <div>Please confirm to continue.</div>
+    <hr style="margin-top:1em"/>
+    <p class="full-width">
+        <span class="buttons" style="float:left">
+            <input type="button" value="No, Cancel" class="close">
+        </span>
+        <span class="buttons" style="float:right">
+            <input type="button" value="Yes, Do it!" class="confirm">
+        </span>
+     </p>
+    <div class="clear"></div>
+</div>
diff --git a/include/staff/dynamic-list.inc.php b/include/staff/dynamic-list.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..fffe5d9b2ad549a8ebe34deb9c57167bac7dd04a
--- /dev/null
+++ b/include/staff/dynamic-list.inc.php
@@ -0,0 +1,129 @@
+<?php
+
+$info=array();
+if($list && $_REQUEST['a']!='add') {
+    $title = 'Update custom list';
+    $action = 'update';
+    $submit_text='Save Changes';
+    $info = $list->ht;
+    $newcount=2;
+} else {
+    $title = 'Add new custom list';
+    $action = 'add';
+    $submit_text='Add List';
+    $newcount=4;
+}
+$info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
+
+?>
+<form action="?" method="post" id="save">
+    <?php csrf_token(); ?>
+    <input type="hidden" name="do" value="<?php echo $action; ?>">
+    <input type="hidden" name="id" value="<?php echo $info['id']; ?>">
+    <h2>Custom List</h2>
+    <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2">
+    <thead>
+        <tr>
+            <th colspan="2">
+                <h4><?php echo $title; ?></h4>
+                <em>Custom lists are used to provide drop-down lists for custom forms</em>
+            </th>
+        </tr>
+    </thead>
+    <tbody>
+        <tr>
+            <td width="180" class="required">Name:</td>
+            <td><input size="50" type="text" name="name" value="<?php echo $info['name']; ?>"/></td>
+        </tr>
+        <tr>
+            <td width="180">Plural Name:</td>
+            <td><input size="50" type="text" name="name_plural" value="<?php echo $info['name_plural']; ?>"/></td>
+        </tr>
+        <tr>
+            <td width="180">Sort Order:</td>
+            <td><select name="sort_mode">
+                <?php foreach (DynamicList::getSortModes() as $key=>$desc) { ?>
+                <option value="<?php echo $key; ?>" <?php
+                    if ($key == $info['sort_mode']) echo 'selected="selected"';
+                    ?>><?php echo $desc; ?></option>
+                <?php } ?>
+                </select></td>
+        </tr>
+    </tbody>
+    </table>
+    <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2">
+    <thead>
+    <?php if ($list) {
+        $page = ($_GET['p'] && is_numeric($_GET['p'])) ? $_GET['p'] : 1;
+        $count = $list->getItemCount();
+        $pageNav = new Pagenate($count, $page, PAGE_LIMIT);
+        $pageNav->setURL('dynamic-list.php', 'id='.urlencode($_REQUEST['id']));
+        $showing=$pageNav->showing().' list items';
+        ?>
+    <?php }
+        else $showing = 'Add a few initial items to the list';
+    ?>
+        <tr>
+            <th colspan="4">
+                <em><?php echo $showing; ?></em>
+            </th>
+        </tr>
+        <tr>
+            <th></th>
+            <th>Value</th>
+            <th>Extra <em style="display:inline">&mdash; abbreviations and such</em></th>
+            <th>Delete</th>
+        </tr>
+    </thead>
+    <tbody <?php if ($info['sort_mode'] == 'SortCol') { ?>
+            class="sortable-rows" data-sort="sort-"<?php } ?>>
+        <?php if ($list)
+        $icon = ($info['sort_mode'] == 'SortCol')
+            ? '<i class="icon-sort"></i>&nbsp;' : '';
+        if ($list) {
+        foreach ($list->getItems() as $i) {
+            $id = $i->get('id'); ?>
+        <tr>
+            <td><?php echo $icon; ?>
+                <input type="hidden" name="sort-<?php echo $id; ?>"
+                value="<?php echo $i->get('sort'); ?>"/></td>
+            <td><input type="text" size="40" name="value-<?php echo $id; ?>"
+                value="<?php echo $i->get('value'); ?>"/></td>
+            <td><input type="text" size="30" name="extra-<?php echo $id; ?>"
+                value="<?php echo $i->get('extra'); ?>"/></td>
+            <td>
+                <input type="checkbox" name="delete-<?php echo $id; ?>"/></td>
+        </tr>
+    <?php }
+    }
+    for ($i=0; $i<$newcount; $i++) { ?>
+        <tr>
+            <td><?php echo $icon; ?> <em>+</em>
+                <input type="hidden" name="sort-new-<?php echo $i; ?>"/></td>
+            <td><input type="text" size="40" name="value-new-<?php echo $i; ?>"/></td>
+            <td><input type="text" size="30" name="extra-new-<?php echo $i; ?>"/></td>
+            <td></td>
+        </tr>
+    <?php } ?>
+    </tbody>
+    <tbody>
+        <tr>
+            <th colspan="7">
+                <em><strong>Internal Notes:</strong> be liberal, they're internal</em>
+            </th>
+        </tr>
+        <tr>
+            <td colspan="7"><textarea name="notes" class="richtext no-bar"
+                rows="6" cols="80"><?php
+                echo $info['notes']; ?></textarea>
+            </td>
+        </tr>
+    </tbody>
+    </table>
+    </table>
+<p class="centered">
+    <input type="submit" name="submit" value="<?php echo $submit_text; ?>">
+    <input type="reset"  name="reset"  value="Reset">
+    <input type="button" name="cancel" value="Cancel" onclick='window.location.href="?"'>
+</p>
+</form>
diff --git a/include/staff/dynamic-lists.inc.php b/include/staff/dynamic-lists.inc.php
new file mode 100644
index 0000000000000000000000000000000000000000..846cab58b8bc4d17dbfcbd275a193d7175cd2da6
--- /dev/null
+++ b/include/staff/dynamic-lists.inc.php
@@ -0,0 +1,92 @@
+<div style="width:700;padding-top:5px; float:left;">
+ <h2>Custom Lists</h2>
+</div>
+<div style="float:right;text-align:right;padding-top:5px;padding-right:5px;">
+ <b><a href="lists.php?a=add" class="Icon list-add">Add New Custom List</a></b></div>
+<div class="clear"></div>
+
+<?php
+$page = ($_GET['p'] && is_numeric($_GET['p'])) ? $_GET['p'] : 1;
+$count = DynamicList::objects()->count();
+$pageNav = new Pagenate($count, $page, PAGE_LIMIT);
+$pageNav->setURL('lists.php');
+$showing=$pageNav->showing().' custom lists';
+?>
+
+<form action="lists.php" method="POST" name="lists">
+<?php csrf_token(); ?>
+<input type="hidden" name="do" value="mass_process" >
+<input type="hidden" id="action" name="a" value="" >
+<table class="list" border="0" cellspacing="1" cellpadding="0" width="940">
+    <caption><?php echo $showing; ?></caption>
+    <thead>
+        <tr>
+            <th width="7">&nbsp;</th>
+            <th>List Name</th>
+            <th>Created</th>
+            <th>Last Updated</th>
+        </tr>
+    </thead>
+    <tbody>
+    <?php foreach (DynamicList::objects()->order_by('name')
+                ->limit($pageNav->getLimit())
+                ->offset($pageNav->getStart()) as $list) {
+            $sel = false;
+            if ($ids && in_array($form->get('id'),$ids))
+                $sel = true; ?>
+        <tr>
+            <td>
+                <input type="checkbox" class="ckb" name="ids[]" value="<?php echo $list->get('id'); ?>"
+                    <?php echo $sel?'checked="checked"':''; ?>></td>
+            <td><a href="?id=<?php echo $list->get('id'); ?>"><?php echo $list->get('name'); ?></a></td>
+            <td><?php echo $list->get('created'); ?></td>
+            <td><?php echo $list->get('updated'); ?></td>
+        </tr>
+    <?php }
+    ?>
+    </tbody>
+    <tfoot>
+     <tr>
+        <td colspan="4">
+            <?php if($count){ ?>
+            Select:&nbsp;
+            <a id="selectAll" href="#ckb">All</a>&nbsp;&nbsp;
+            <a id="selectNone" href="#ckb">None</a>&nbsp;&nbsp;
+            <a id="selectToggle" href="#ckb">Toggle</a>&nbsp;&nbsp;
+            <?php } else {
+                echo 'No custom lists defined yet &mdash; add one!';
+            } ?>
+        </td>
+     </tr>
+    </tfoot>
+</table>
+<?php
+if ($count) //Show options..
+    echo '<div>&nbsp;Page:'.$pageNav->getPageLinks().'&nbsp;</div>';
+?>
+
+<p class="centered" id="actions">
+    <input class="button" type="submit" name="delete" value="Delete">
+</p>
+</form>
+
+<div style="display:none;" class="dialog" id="confirm-action">
+    <h3>Please Confirm</h3>
+    <a class="close" href="">&times;</a>
+    <hr/>
+    <p class="confirm-action" style="display:none;" id="delete-confirm">
+        <font color="red"><strong>Are you sure you want to DELETE selected lists?</strong></font>
+        <br><br>Deleted forms CANNOT be recovered.
+    </p>
+    <div>Please confirm to continue.</div>
+    <hr style="margin-top:1em"/>
+    <p class="full-width">
+        <span class="buttons" style="float:left">
+            <input type="button" value="No, Cancel" class="close">
+        </span>
+        <span class="buttons" style="float:right">
+            <input type="button" value="Yes, Do it!" class="confirm">
+        </span>
+    </p>
+    <div class="clear"></div>
+</div>
diff --git a/include/staff/filter.inc.php b/include/staff/filter.inc.php
index b029fbb682a8ebfdebf386027d561c772aba2382..37ac6c69925bf4dc15711f0a76767803aeacc66a 100644
--- a/include/staff/filter.inc.php
+++ b/include/staff/filter.inc.php
@@ -125,11 +125,14 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                     <select name="rule_w<?php echo $i; ?>">
                         <option value="">&mdash; Select One &dash;</option>
                         <?php
-                        foreach($matches as $k=>$v){
-                            $sel=($info["rule_w$i"]==$k)?'selected="selected"':'';
-                            echo sprintf('<option value="%s" %s>%s</option>',$k,$sel,$v);
-                        }
-                        ?>
+                        foreach ($matches as $group=>$ms) { ?>
+                            <optgroup label="<?php echo $group; ?>"><?php
+                            foreach ($ms as $k=>$v) {
+                                $sel=($info["rule_w$i"]==$k)?'selected="selected"':'';
+                                echo sprintf('<option value="%s" %s>%s</option>',$k,$sel,$v);
+                            } ?>
+                        </optgroup>
+                        <?php } ?>
                     </select>
                     <select name="rule_h<?php echo $i; ?>">
                         <option value="0">&mdash; Select One &dash;</option>
diff --git a/include/staff/header.inc.php b/include/staff/header.inc.php
index e5b04bff53e4fec7dd0880423aee27b43704e41f..d4e2ce612239c405dc5335650a2c0cf869ff6996 100644
--- a/include/staff/header.inc.php
+++ b/include/staff/header.inc.php
@@ -23,7 +23,8 @@
     <link rel="stylesheet" href="./css/scp.css" media="screen">
     <link rel="stylesheet" href="<?php echo ROOT_PATH; ?>css/redactor.css" media="screen">
     <link rel="stylesheet" href="./css/typeahead.css" media="screen">
-    <link type="text/css" href="<?php echo ROOT_PATH; ?>css/ui-lightness/jquery-ui-1.10.3.custom.min.css" rel="stylesheet" />
+    <link type="text/css" href="<?php echo ROOT_PATH; ?>css/ui-lightness/jquery-ui-1.10.3.custom.min.css"
+         rel="stylesheet" media="screen" />
     <link type="text/css" rel="stylesheet" href="../css/font-awesome.min.css">
     <link type="text/css" rel="stylesheet" href="./css/dropdown.css">
     <script type="text/javascript" src="./js/jquery.dropdown.js"></script>
diff --git a/include/staff/helptopic.inc.php b/include/staff/helptopic.inc.php
index fdf82a404c187cf9d8f0ba6421b635f70a7e3f4a..39de0b76e4bcf48af7b9c82de365834fbcd38c00 100644
--- a/include/staff/helptopic.inc.php
+++ b/include/staff/helptopic.inc.php
@@ -89,6 +89,22 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
         </tr>
 
         <tr><th colspan="2"><em>New ticket options</em></th></tr>
+       <tr>
+           <td><strong>Custom Form</strong>:</td>
+           <td><select name="form_id">
+               <option value="0">&mdash; No Extra Fields &mdash;</option>
+               <?php foreach (DynamicForm::objects()->filter(array('type'=>'G')) as $group) { ?>
+                   <option value="<?php echo $group->get('id'); ?>"
+                       <?php if ($group->get('id') == $info['form_id'])
+                            echo 'selected="selected"'; ?>>
+                       <?php echo $group->get('title'); ?>
+                   </option>
+               <?php } ?>
+               </select>
+               <em>Extra information for tickets associated with this help topic</em>
+               &nbsp;<span class="error">&nbsp;<?php echo $errors['form_id']; ?></span>
+           </td>
+       </tr>
         <tr>
             <td width="180" class="required">
                 Priority:
@@ -217,7 +233,6 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                     this topic (Overrides Dept. settings).
             </td>
         </tr>
-
         <tr>
             <th colspan="2">
                 <em><strong>Admin Notes</strong>: Internal notes about the help topic.&nbsp;</em>
diff --git a/include/staff/settings-emails.inc.php b/include/staff/settings-emails.inc.php
index e433cd7a2d9eb0d10243d886ce06e941d8dc7773..f8b96f04b345ef4ecf8d6f80847da53f48a5f2fb 100644
--- a/include/staff/settings-emails.inc.php
+++ b/include/staff/settings-emails.inc.php
@@ -15,6 +15,23 @@ if(!defined('OSTADMININC') || !$thisstaff || !$thisstaff->isAdmin() || !$config)
         </tr>
     </thead>
     <tbody>
+        <tr>
+            <td width="180" class="required">Default Email Templates:</td>
+            <td>
+                <select name="default_template_id">
+                    <option value="">&mdash; Select Default Template &mdash;</option>
+                    <?php
+                    $sql='SELECT tpl_id,name FROM '.EMAIL_TEMPLATE_GRP_TABLE.' WHERE isactive=1 ORDER BY name';
+                    if(($res=db_query($sql)) && db_num_rows($res)){
+                        while (list($id, $name) = db_fetch_row($res)){
+                            $selected = ($config['default_template_id']==$id)?'selected="selected"':''; ?>
+                            <option value="<?php echo $id; ?>"<?php echo $selected; ?>><?php echo $name; ?></option>
+                        <?php
+                        }
+                    } ?>
+                </select>&nbsp;<font class="error">*&nbsp;<?php echo $errors['default_template_id']; ?></font>
+            </td>
+        </tr>
         <tr>
             <td width="180" class="required">Default System Email:</td>
             <td>
diff --git a/include/staff/settings-system.inc.php b/include/staff/settings-system.inc.php
index 8dd170e4161a97601b589017b4430ba8a15303ae..838b4c0fcb323cb26042d6f9ed8b99a195f08199 100644
--- a/include/staff/settings-system.inc.php
+++ b/include/staff/settings-system.inc.php
@@ -54,23 +54,6 @@ $gmtime = Misc::gmtime();
                 </select>&nbsp;<font class="error">*&nbsp;<?php echo $errors['default_dept_id']; ?></font>
             </td>
         </tr>
-        <tr>
-            <td width="220" class="required">Default Email Templates:</td>
-            <td>
-                <select name="default_template_id">
-                    <option value="">&mdash; Select Default Template &mdash;</option>
-                    <?php
-                    $sql='SELECT tpl_id,name FROM '.EMAIL_TEMPLATE_GRP_TABLE.' WHERE isactive=1 ORDER BY name';
-                    if(($res=db_query($sql)) && db_num_rows($res)){
-                        while (list($id, $name) = db_fetch_row($res)){
-                            $selected = ($config['default_template_id']==$id)?'selected="selected"':''; ?>
-                            <option value="<?php echo $id; ?>"<?php echo $selected; ?>><?php echo $name; ?></option>
-                        <?php
-                        }
-                    } ?>
-                </select>&nbsp;<font class="error">*&nbsp;<?php echo $errors['default_template_id']; ?></font>
-            </td>
-        </tr>
 
         <tr><td>Default Page Size:</td>
             <td>
@@ -112,6 +95,19 @@ $gmtime = Misc::gmtime();
                 </select>
             </td>
         </tr>
+        <tr>
+            <td width="180">Default Name Formatting:</td>
+            <td>
+                <select name="name_format">
+<?php foreach (PersonsName::allFormats() as $n=>$f) {
+    list($desc, $func) = $f;
+    $selected = ($config['name_format'] == $n) ? 'selected="selected"' : ''; ?>
+                    <option value="<?php echo $n; ?>" <?php echo $selected;
+                        ?>><?php echo $desc; ?></option>
+<?php } ?>
+                </select>
+            </td>
+        </tr>
         <tr>
             <th colspan="2">
                 <em><b>Authentication Settings</b></em>
diff --git a/include/staff/settings-tickets.inc.php b/include/staff/settings-tickets.inc.php
index d360b4d29bf1c9364ade32ce3f5955f043e15f26..6585e8aaa798be387eb119ebcd3f843f3244b726 100644
--- a/include/staff/settings-tickets.inc.php
+++ b/include/staff/settings-tickets.inc.php
@@ -77,13 +77,6 @@ if(!($maxfileuploads=ini_get('max_file_uploads')))
             </td>
         </tr>
         <tr>
-                    <td width="180">Web Tickets Priority:</td>
-                    <td>
-                        <input type="checkbox" name="allow_priority_change" value="1" <?php echo $config['allow_priority_change'] ?'checked="checked"':''; ?>>
-                        <em>(Allow user to override/set priority)</em>
-                    </td>
-                </tr>
-                <tr>
                     <td width="180">Emailed Tickets Priority:</td>
                     <td>
                         <input type="checkbox" name="use_email_priority" value="1" <?php echo $config['use_email_priority'] ?'checked="checked"':''; ?> >
diff --git a/include/staff/templates/dynamic-field-config.tmpl.php b/include/staff/templates/dynamic-field-config.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..aa6b01696c45645cd5c29fedfecaa60c4138014c
--- /dev/null
+++ b/include/staff/templates/dynamic-field-config.tmpl.php
@@ -0,0 +1,80 @@
+    <h3>Field Configuration &mdash; <?php echo $field->get('label') ?></h3>
+    <a class="close" href="">&times;</a>
+    <hr/>
+    <form method="post" action="ajax.php/form/field-config/<?php
+            echo $field->get('id'); ?>" onsubmit="javascript:
+            var form = $(this);
+            $.post(this.action, form.serialize(), function(data, status, xhr) {
+                    if (!data.length) {
+                        form.closest('.dialog').hide();
+                        $('#overlay').hide();
+                    } else {
+                        form.closest('.dialog').empty().append(data);
+                    }
+            });
+            return false;
+            ">
+        <table width="100%">
+        <?php
+        echo csrf_token();
+        $config = $field->getConfiguration();
+        foreach ($field->getConfigurationForm() as $name=>$f) {
+            if (isset($config[$name]))
+                $f->value = $config[$name];
+            else if ($f->get('default'))
+                $f->value = $f->get('default');
+            ?>
+            <tr><td>
+            <label for="<?php echo $f->getWidget()->name; ?>"
+                style="vertical-align:top;padding-top:0.2em">
+                <?php echo Format::htmlchars($f->get('label')); ?>:</label>
+            </td><td>
+            <span style="display:inline-block">
+            <?php
+            $f->render();
+            if ($f->get('required')) { ?>
+                <font class="error">*</font>
+            <?php
+            }
+            if ($f->get('hint')) { ?>
+                <br /><em style="color:gray;display:inline-block"><?php
+                    echo Format::htmlchars($f->get('hint')); ?></em>
+            <?php
+            }
+            ?>
+            </span>
+            <?php
+            foreach ($f->errors() as $e) { ?>
+                <br />
+                <font class="error"><?php echo $e; ?></font>
+            <?php } ?>
+            </td></tr>
+            <?php
+        }
+        ?>
+        <tr><td colspan="2"><hr/></td></tr>
+        <tr><td>
+        <label for="hint"
+            style="vertical-align:top;padding-top:0.2em">Help Text:</label>
+        </td><td>
+        <span style="display:inline-block">
+        <textarea name="hint" rows="2" cols="40"><?php
+            echo Format::htmlchars($field->get('hint')); ?></textarea>
+            <br />
+            <em style="color:gray;display:inline-block">
+                Help text shown with the field</em>
+        </span>
+        </td></tr>
+        </table>
+        <hr style="margin-top:3em"/>
+        <p class="full-width">
+            <span class="buttons" style="float:left">
+                <input type="reset" value="Reset">
+                <input type="button" value="Cancel" class="close">
+            </span>
+            <span class="buttons" style="float:right">
+                <input type="submit" value="Save">
+            </span>
+         </p>
+    </form>
+    <div class="clear"></div>
diff --git a/include/staff/templates/dynamic-form.tmpl.php b/include/staff/templates/dynamic-form.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..c60cb8e0af7abe788132c06e49b3b5439d2783ae
--- /dev/null
+++ b/include/staff/templates/dynamic-form.tmpl.php
@@ -0,0 +1,37 @@
+    <?php if ($form->getTitle()) { ?>
+    <tr><th colspan="2">
+        <em><strong><?php echo Format::htmlchars($form->getTitle()); ?></strong>:
+        <?php echo Format::htmlchars($form->getInstructions()); ?></em>
+    </th></tr>
+    <?php
+    }
+    foreach ($form->getFields() as $field) {
+        ?>
+        <tr><?php if ($field->isBlockLevel()) { ?>
+                <td colspan="2">
+                <?php
+            }
+            else { ?>
+                <td class="multi-line <?php if ($field->get('required')) echo 'required'; ?>">
+                <?php echo Format::htmlchars($field->get('label')); ?>:</td>
+                <td><?php
+            }
+            $field->render(); ?>
+            <?php if ($field->get('required')) { ?>
+                <font class="error">*</font>
+            <?php
+            }
+            if ($field->get('hint') && !$field->isBlockLevel()) { ?>
+                <br /><em style="color:gray;display:inline-block"><?php
+                    echo Format::htmlchars($field->get('hint')); ?></em>
+            <?php
+            }
+            foreach ($field->errors() as $e) { ?>
+                <br />
+                <font class="error"><?php echo $e; ?></font>
+            <?php } ?>
+            </td>
+        </tr>
+        <?php
+    }
+?>
diff --git a/include/staff/templates/user-info.tmpl.php b/include/staff/templates/user-info.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..b9802b8f0ad16064fc5172f81c9aab43aee0ff6b
--- /dev/null
+++ b/include/staff/templates/user-info.tmpl.php
@@ -0,0 +1,36 @@
+<h3>User Information &mdash; <?php echo $user->getFullName() ?></h3>
+<a class="close" href="">&times;</a>
+<hr/>
+<form method="post" action="ajax.php/form/user-info/<?php
+        echo $user->get('id'); ?>" onsubmit="javascript:
+        var form = $(this);
+        $.post(this.action, form.serialize(), function(data, status, xhr) {
+            if (!data.length) {
+                form.closest('.dialog').hide();
+                $('#overlay').hide();
+                location.reload();
+            } else {
+                form.closest('.dialog').empty().append(data);
+            }
+        });
+        return false;
+        ">
+    <table width="100%">
+    <?php
+        echo csrf_token();
+        foreach ($custom as $form)
+            $form->render();
+    ?>
+    </table>
+    <hr style="margin-top:3em"/>
+    <p class="full-width">
+        <span class="buttons" style="float:left">
+            <input type="reset" value="Reset">
+            <input type="button" value="Cancel" class="close">
+        </span>
+        <span class="buttons" style="float:right">
+            <input type="submit" value="Save">
+        </span>
+     </p>
+</form>
+<div class="clear"></div>
diff --git a/include/staff/ticket-edit.inc.php b/include/staff/ticket-edit.inc.php
index 4a641d782b41005e0e17b4197b1bff668523d8d7..e2d7864a42c710fd50c049d15e655cacfd00c9cf 100644
--- a/include/staff/ticket-edit.inc.php
+++ b/include/staff/ticket-edit.inc.php
@@ -8,46 +8,9 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$ticket->getUpdateInfo());
  <input type="hidden" name="do" value="update">
  <input type="hidden" name="a" value="edit">
  <input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
- <h2>Update Ticket# <?php echo $ticket->getExtId(); ?></h2>
+ <h2>Update Ticket #<?php echo $ticket->getExtId(); ?></h2>
  <table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2">
-    <thead>
-        <tr>
-            <th colspan="2">
-                <h4>Ticket Update</h4>
-                <em><strong>User Information</strong>: Make sure the email address is valid.</em>
-            </th>
-        </tr>
-    </thead>
     <tbody>
-        <tr>
-            <td width="160" class="required">
-                Full Name:
-            </td>
-            <td>
-                <input type="text" size="50" name="name" value="<?php echo $info['name']; ?>">
-                &nbsp;<span class="error">*&nbsp;<?php echo $errors['name']; ?></span>
-            </td>
-        </tr>
-        <tr>
-            <td width="160" class="required">
-                Email Address:
-            </td>
-            <td>
-                <input type="text" size="50" name="email" value="<?php echo $info['email']; ?>">
-                &nbsp;<span class="error">*&nbsp;<?php echo $errors['email']; ?></span>
-            </td>
-        </tr>
-        <tr>
-            <td width="160">
-                Phone Number:
-            </td>
-            <td>
-                <input type="text" size="20" name="phone" value="<?php echo $info['phone']; ?>">
-                &nbsp;<span class="error">&nbsp;<?php echo $errors['phone']; ?></span>
-                Ext <input type="text" size="6" name="phone_ext" value="<?php echo $info['phone_ext']; ?>">
-                &nbsp;<span class="error">&nbsp;<?php echo $errors['phone_ext']; ?></span>
-            </td>
-        </tr>
         <tr>
             <th colspan="2">
                 <em><strong>Ticket Information</strong>: Due date overrides SLA's grace period.</em>
@@ -88,34 +51,6 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$ticket->getUpdateInfo());
                 &nbsp;<font class="error"><b>*</b>&nbsp;<?php echo $errors['topicId']; ?></font>
             </td>
         </tr>
-        <tr>
-            <td width="160" class="required">
-                Priority Level:
-            </td>
-            <td>
-                <select name="priorityId">
-                    <option value="" selected >&mdash; Select Priority &mdash;</option>
-                    <?php
-                    if($priorities=Priority::getPriorities()) {
-                        foreach($priorities as $id =>$name) {
-                            echo sprintf('<option value="%d" %s>%s</option>',
-                                    $id, ($info['priorityId']==$id)?'selected="selected"':'',$name);
-                        }
-                    }
-                    ?>
-                </select>
-                &nbsp;<font class="error">*&nbsp;<?php echo $errors['priorityId']; ?></font>
-            </td>
-        </tr>
-        <tr>
-            <td width="160" class="required">
-                Subject:
-            </td>
-            <td>
-                 <input type="text" name="subject" size="60" value="<?php echo $info['subject']; ?>">
-                 &nbsp;<font class="error">*&nbsp;<?php $errors['subject']; ?></font>
-            </td>
-        </tr>
         <tr>
             <td width="160">
                 SLA Plan:
@@ -153,6 +88,14 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$ticket->getUpdateInfo());
                 <em>Time is based on your time zone (GMT <?php echo $thisstaff->getTZoffset(); ?>)</em>
             </td>
         </tr>
+        </tbody>
+        <tbody id="dynamic-form">
+        <?php if ($forms)
+            foreach ($forms as $form) {
+                $form->render(true);
+        } ?>
+        </tbody>
+        <tbody>
         <tr>
             <th colspan="2">
                 <em><strong>Internal Note</strong>: Reason for editing the ticket (required) <font class="error">&nbsp;<?php echo $errors['note'];?></font></em>
diff --git a/include/staff/ticket-open.inc.php b/include/staff/ticket-open.inc.php
index cf9c49dfbec5be1211cb9b74696ba9595e223b79..826d19e7962553244971c135af0c4ce5280c59bd 100644
--- a/include/staff/ticket-open.inc.php
+++ b/include/staff/ticket-open.inc.php
@@ -13,48 +13,21 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
         <tr>
             <th colspan="2">
                 <h4>New Ticket</h4>
-                <em><strong>User Information</strong></em>
             </th>
         </tr>
     </thead>
     <tbody>
+        <?php
+        $uf = UserForm::objects();
+        $uf[0]->render();
+        if($cfg->notifyONNewStaffTicket()) {  ?>
         <tr>
-            <td width="160" class="required">
-                Email Address:
-            </td>
-            <td>
-
-                <input type="text" size="50" name="email" id="email" class="typeahead" value="<?php echo $info['email']; ?>"
-                    autocomplete="off" autocorrect="off" autocapitalize="off">
-                &nbsp;<span class="error">*&nbsp;<?php echo $errors['email']; ?></span>
-            <?php 
-            if($cfg->notifyONNewStaffTicket()) { ?>
-               &nbsp;&nbsp;&nbsp;
-               <input type="checkbox" name="alertuser" <?php echo (!$errors || $info['alertuser'])? 'checked="checked"': ''; ?>>Send alert to user.
-            <?php 
-             } ?>
-            </td>
-        </tr>
-        <tr>
-            <td width="160" class="required">
-                Full Name:
-            </td>
-            <td>
-                <input type="text" size="50" name="name" id="name" value="<?php echo $info['name']; ?>">
-                &nbsp;<span class="error">*&nbsp;<?php echo $errors['name']; ?></span>
-            </td>
-        </tr>
-        <tr>
-            <td width="160">
-                Phone Number:
-            </td>
+            <td width="160">Alert:</td>
             <td>
-                <input type="text" size="20" name="phone" id="phone" value="<?php echo $info['phone']; ?>">
-                &nbsp;<span class="error">&nbsp;<?php echo $errors['phone']; ?></span>
-                Ext <input type="text" size="6" name="phone_ext" id="phone_ext" value="<?php echo $info['phone_ext']; ?>">
-                &nbsp;<span class="error">&nbsp;<?php echo $errors['phone_ext']; ?></span>
+            <input type="checkbox" name="alertuser" <?php echo (!$errors || $info['alertuser'])? 'checked="checked"': ''; ?>>Send alert to user.
             </td>
         </tr>
+        <?php } ?>
         <tr>
             <th colspan="2">
                 <em><strong>Ticket Information &amp; Options</strong>:</em>
@@ -99,7 +72,10 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                 Help Topic:
             </td>
             <td>
-                <select name="topicId">
+                <select name="topicId" onchange="javascript:
+                        $('#dynamic-form').load(
+                            'ajax.php/form/help-topic/' + this.value);
+                        ">
                     <option value="" selected >&mdash; Select Help Topic &mdash;</option>
                     <?php
                     if($topics=Topic::getHelpTopics()) {
@@ -113,25 +89,6 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                 &nbsp;<font class="error"><b>*</b>&nbsp;<?php echo $errors['topicId']; ?></font>
             </td>
         </tr>
-        <tr>
-            <td width="160">
-                Priority:
-            </td>
-            <td>
-                <select name="priorityId">
-                    <option value="0" selected >&mdash; System Default &mdash;</option>
-                    <?php
-                    if($priorities=Priority::getPriorities()) {
-                        foreach($priorities as $id =>$name) {
-                            echo sprintf('<option value="%d" %s>%s</option>',
-                                    $id, ($info['priorityId']==$id)?'selected="selected"':'',$name);
-                        }
-                    }
-                    ?>
-                </select>
-                &nbsp;<font class="error">&nbsp;<?php echo $errors['priorityId']; ?></font>
-            </td>
-         </tr>
          <tr>
             <td width="160">
                 SLA Plan:
@@ -203,29 +160,16 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
             </td>
         </tr>
         <?php
-        } ?>
-        <tr>
-            <th colspan="2">
-                <em><strong>Issue</strong>: The user will be able to see the issue summary below and any associated responses.</em>
-            </th>
-        </tr>
-        <tr>
-            <td colspan=2>
-                <div>
-                    <em><strong>Subject</strong>: Issue summary </em> &nbsp;<font class="error">*&nbsp;<?php echo $errors['subject']; ?></font><br>
-                    <input type="text" name="subject" size="60" value="<?php echo $info['subject']; ?>">
-                </div>
-                <div style="margin-top:0.5em; margin-bottom:0.5em">
-                    <em><strong>Issue</strong></em>
-                    <font class="error">*&nbsp;<?php echo $errors['issue']; ?></font>
-                </div>
-                <textarea class="richtext ifhtml draft draft-delete"
-                    placeholder="Details on the reason(s) for opening the ticket."
-                    data-draft-namespace="ticket.staff" name="issue"
-                    cols="21" rows="8" style="width:80%;"
-                    ><?php echo $info['issue']; ?></textarea>
-            </td>
-        </tr>
+        }
+        TicketForm::getInstance()->render(true);
+        ?>
+        </tbody>
+        <tbody id="dynamic-form">
+        <?php
+            if ($form) $form->render(true);
+        ?>
+        </tbody>
+        <tbody>
         <?php
         //is the user allowed to post replies??
         if($thisstaff->canPostReply()) {
diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php
index c8dcde436704a486d0c42ee112adb1b88b1e6483..a3ef79d5d4d29f0752ef720c41cd769ab318d6df 100644
--- a/include/staff/ticket-view.inc.php
+++ b/include/staff/ticket-view.inc.php
@@ -140,32 +140,35 @@ if($ticket->isOverdue())
                 </tr>
             </table>
         </td>
-        <td width="50%">
+        <td width="50%" style="vertical-align:top">
             <table border="0" cellspacing="" cellpadding="4" width="100%">
                 <tr>
-                    <th width="100">Name:</th>
-                    <td><?php echo Format::htmlchars($ticket->getName()); ?></td>
-                </tr>
-                <tr>
-                    <th>Email:</th>
-                    <td>
-                    <?php
-                        echo $ticket->getEmail();
+                    <th width="100">Client:</th>
+                    <td><a href="ajax.php/form/user-info/<?php
+                            echo $ticket->getOwnerId(); ?>"
+                        onclick="javascript:
+                            $('#overlay').show();
+                            $('#user-info .body').load(this.href);
+                            $('#user-info').show();
+                            return false;
+                            "><i class="icon-user"></i> <?php
+                        echo Format::htmlchars($ticket->getName()); ?></a>
+                        <?php
                         if(($client=$ticket->getClient())) {
-                            echo sprintf('&nbsp;&nbsp;<a href="tickets.php?a=search&query=%s" title="Related Tickets" data-dropdown="#action-dropdown-stats">(<b>%d</b>)</a>',
-                                    urlencode($ticket->getEmail()), $client->getNumTickets());
+                            echo sprintf('&nbsp;&nbsp;<a href="tickets.php?a=search&ownerId=%d" title="Related Tickets" data-dropdown="#action-dropdown-stats">(<b>%d</b>)</a>',
+                                    urlencode($ticket->getOwnerId()), $client->getNumTickets());
                         ?>
                             <div id="action-dropdown-stats" class="action-dropdown anchor-right">
                                 <ul>
                                     <?php
                                     if(($open=$client->getNumOpenTickets()))
-                                        echo sprintf('<li><a href="tickets.php?a=search&status=open&query=%s"><i class="icon-folder-open-alt"></i> %d Open Tickets</a></li>',
-                                                $ticket->getEmail(), $open);
+                                        echo sprintf('<li><a href="tickets.php?a=search&status=open&ownerId=%s"><i class="icon-folder-open-alt"></i> %d Open Tickets</a></li>',
+                                                $ticket->getOwnerId(), $open);
                                     if(($closed=$client->getNumClosedTickets()))
-                                        echo sprintf('<li><a href="tickets.php?a=search&status=closed&query=%s"><i class="icon-folder-close-alt"></i> %d Closed Tickets</a></li>',
-                                                $ticket->getEmail(), $closed);
+                                        echo sprintf('<li><a href="tickets.php?a=search&status=closed&ownerId=%d"><i class="icon-folder-close-alt"></i> %d Closed Tickets</a></li>',
+                                                $ticket->getOwnerId(), $closed);
                                     ?>
-                                    <li><a href="tickets.php?a=search&query=<?php echo $ticket->getEmail(); ?>"><i class="icon-double-angle-right"></i> All Tickets</a></li>
+                                    <li><a href="tickets.php?a=search&ownerId=<?php echo $ticket->getOwnerId(); ?>"><i class="icon-double-angle-right"></i> All Tickets</a></li>
                                 </u>
                             </div>
                     <?php
@@ -174,8 +177,10 @@ if($ticket->isOverdue())
                     </td>
                 </tr>
                 <tr>
-                    <th>Phone:</th>
-                    <td><?php echo $ticket->getPhoneNumber(); ?></td>
+                    <th>Email:</th>
+                    <td>
+                    <?php echo $ticket->getEmail(); ?>
+                    </td>
                 </tr>
                 <tr>
                     <th>Source:</th>
@@ -184,8 +189,6 @@ if($ticket->isOverdue())
 
                         if($ticket->getIP())
                             echo '&nbsp;&nbsp; <span class="faded">('.$ticket->getIP().')</span>';
-
-
                         ?>
                     </td>
                 </tr>
@@ -265,6 +268,43 @@ if($ticket->isOverdue())
         </td>
     </tr>
 </table>
+<br>
+<table class="ticket_info" cellspacing="0" cellpadding="0" width="940" border="0">
+<?php
+$idx = 0;
+foreach (DynamicFormEntry::forTicket($ticket->getId()) as $form) {
+    // Skip core fields shown earlier in the ticket view
+    // TODO: Rewrite getAnswers() so that one could write
+    //       ->getAnswers()->filter(not(array('field__name__in'=>
+    //           array('email', ...))));
+    $answers = array_filter($form->getAnswers(), function ($a) {
+        return !in_array($a->getField()->get('name'),
+                array('email','subject','name','priority'));
+        });
+    if (count($answers) == 0)
+        continue;
+    ?>
+        </tr><tr>
+        <td colspan="2">
+            <table cellspacing="0" cellpadding="4" width="100%" border="0">
+            <?php foreach($answers as $a) {
+                if (!$a->toString()) continue; ?>
+                <tr>
+                    <th width="100"><?php
+    echo $a->getField()->get('label');
+                    ?>:</th>
+                    <td><?php
+    echo $a->toString();
+                    ?></td>
+                </tr>
+                <?php } ?>
+            </table>
+        </td>
+    <?php
+    $idx++;
+    } ?>
+    </tr>
+</table>
 <div class="clear"></div>
 <h2 style="padding:10px 0 5px 0; font-size:11pt;"><?php echo Format::htmlchars($ticket->getSubject()); ?></h2>
 <?php
@@ -411,9 +451,9 @@ if(!$cfg->showNotesInline()) { ?>
                 </td>
                 <td width="765">
                     <?php
-                    $to = $ticket->getEmail();
+                    $to = $ticket->getReplyToEmail();
                     if(($name=$ticket->getName()) && !strpos($name,'@'))
-                        $to =sprintf('%s <em>&lt;%s&gt;</em>', $name, $ticket->getEmail());
+                        $to =sprintf('%s <em>&lt;%s&gt;</em>', $name, $to);
                     echo $to;
                     ?>
                     &nbsp;&nbsp;&nbsp;
@@ -785,6 +825,9 @@ if(!$cfg->showNotesInline()) { ?>
     <?php
     } ?>
 </div>
+<div style="display:none;" class="dialog" id="user-info">
+    <div class="body"></div>
+</div>
 <div style="display:none;" class="dialog" id="print-options">
     <h3>Ticket Print Options</h3>
     <a class="close" href="">&times;</a>
diff --git a/include/staff/tickets.inc.php b/include/staff/tickets.inc.php
index ac38d5ff8c87eddf718c1a547315f292fed5ccb7..eb2b6f1315e8dd67edd5aaaa6e9e94b32f59f7bb 100644
--- a/include/staff/tickets.inc.php
+++ b/include/staff/tickets.inc.php
@@ -12,7 +12,7 @@ $searchTerm='';
 //make sure the search query is 3 chars min...defaults to no query with warning message
 if($search) {
   $searchTerm=$_REQUEST['query'];
-  if( ($_REQUEST['query'] && strlen($_REQUEST['query'])<3) 
+  if( ($_REQUEST['query'] && strlen($_REQUEST['query'])<3)
       || (!$_REQUEST['query'] && isset($_REQUEST['basic_search'])) ){ //Why do I care about this crap...
       $search=false; //Instead of an error page...default back to regular query..with no search.
       $errors['err']='Search term must be more than 3 chars';
@@ -21,7 +21,7 @@ if($search) {
 }
 $showoverdue=$showanswered=false;
 $staffId=0; //Nothing for now...TODO: Allow admin and manager to limit tickets to single staff level.
-$showassigned= true; //show Assigned To column - defaults to true 
+$showassigned= true; //show Assigned To column - defaults to true
 
 //Get status we are actually going to use on the query...making sure it is clean!
 $status=null;
@@ -49,17 +49,17 @@ switch(strtolower($_REQUEST['status'])){ //Status is overloaded
         $results_type='Answered Tickets';
         break;
     default:
-        if(!$search)
+        if(!$search && !isset($_REQUEST['advsid']))
             $_REQUEST['status']=$status='open';
 }
 
 $qwhere ='';
-/* 
+/*
    STRICT DEPARTMENTS BASED PERMISSION!
    User can also see tickets assigned to them regardless of the ticket's dept.
 */
 
-$depts=$thisstaff->getDepts();    
+$depts=$thisstaff->getDepts();
 $qwhere =' WHERE ( '
         .'  ticket.staff_id='.db_input($thisstaff->getId());
 
@@ -73,7 +73,7 @@ $qwhere .= ' )';
 
 //STATUS
 if($status) {
-    $qwhere.=' AND status='.db_input(strtolower($status));    
+    $qwhere.=' AND status='.db_input(strtolower($status));
 }
 
 //Queues: Overloaded sub-statuses  - you've got to just have faith!
@@ -87,10 +87,10 @@ if($staffId && ($staffId==$thisstaff->getId())) { //My tickets
     $qwhere.=' AND isanswered=1 ';
 }elseif(!strcasecmp($status, 'open') && !$search) { //Open queue (on search OPEN means all open tickets - regardless of state).
     //Showing answered tickets on open queue??
-    if(!$cfg->showAnsweredTickets()) 
+    if(!$cfg->showAnsweredTickets())
         $qwhere.=' AND isanswered=0 ';
 
-    /* Showing assigned tickets on open queue? 
+    /* Showing assigned tickets on open queue?
        Don't confuse it with show assigned To column -> F'it it's confusing - just trust me!
      */
     if(!($cfg->showAssignedTickets() || $thisstaff->showAssignedTickets())) {
@@ -99,7 +99,7 @@ if($staffId && ($staffId==$thisstaff->getId())) { //My tickets
     }
 }
 
-//Search?? Somebody...get me some coffee 
+//Search?? Somebody...get me some coffee
 $deep_search=false;
 if($search):
     $qstr.='&a='.urlencode($_REQUEST['a']);
@@ -109,92 +109,36 @@ if($search):
     if($searchTerm){
         $qstr.='&query='.urlencode($searchTerm);
         $queryterm=db_real_escape($searchTerm,false); //escape the term ONLY...no quotes.
-        if(is_numeric($searchTerm)){
+        if (is_numeric($searchTerm)) {
             $qwhere.=" AND ticket.ticketID LIKE '$queryterm%'";
-        }elseif(strpos($searchTerm,'@') && Validator::is_email($searchTerm)){ //pulling all tricks!
+        } elseif (strpos($searchTerm,'@') && Validator::is_email($searchTerm)) {
+            //pulling all tricks!
             # XXX: What about searching for email addresses in the body of
             #      the thread message
-            $qwhere.=" AND ticket.email='$queryterm'";
-        }else{//Deep search!
-            //This sucks..mass scan! search anything that moves! 
-            
-            $deep_search=true;
-            $qwhere.=" AND ( ticket.email LIKE '%$queryterm%'".
-                        " OR ticket.name LIKE '%$queryterm%'".
-                        " OR ticket.subject LIKE '%$queryterm%'".
-                        " OR thread.body LIKE '%$queryterm%'".
-                        " OR thread.title LIKE '%$queryterm%'".
-                        ' ) ';
-        }
-    }
-    //department
-    if($_REQUEST['deptId'] && in_array($_REQUEST['deptId'],$thisstaff->getDepts())) {
-        //This is dept based search..perm taken care above..put the sucker in.
-        $qwhere.=' AND ticket.dept_id='.db_input($_REQUEST['deptId']);
-        $qstr.='&deptId='.urlencode($_REQUEST['deptId']);
-    }
-
-    //Help topic
-    if($_REQUEST['topicId']) {
-        $qwhere.=' AND ticket.topic_id='.db_input($_REQUEST['topicId']);
-        $qstr.='&topicId='.urlencode($_REQUEST['topicId']);
-    }
-        
-    //Assignee 
-    if(isset($_REQUEST['assignee']) && strcasecmp($_REQUEST['status'], 'closed'))  {
-        $id=preg_replace("/[^0-9]/", "", $_REQUEST['assignee']);
-        $assignee = $_REQUEST['assignee'];
-        $qstr.='&assignee='.urlencode($_REQUEST['assignee']);
-        $qwhere.= ' AND ( 
-                ( ticket.status="open" ';
-                  
-        if($assignee[0]=='t')
-            $qwhere.='  AND ticket.team_id='.db_input($id);
-        elseif($assignee[0]=='s')
-            $qwhere.='  AND ticket.staff_id='.db_input($id);
-        elseif(is_numeric($id))
-            $qwhere.='  AND ticket.staff_id='.db_input($id);
-        
-       $qwhere.=' ) ';
-                   
-        if($_REQUEST['staffId'] && !$_REQUEST['status']) { //Assigned TO + Closed By
-            $qwhere.= ' OR (ticket.staff_id='.db_input($_REQUEST['staffId']). ' AND ticket.status="closed") ';
-            $qstr.='&staffId='.urlencode($_REQUEST['staffId']);
-        }elseif(isset($_REQUEST['staffId'])) {
-            $qwhere.= ' OR ticket.status="closed" ';
-            $qstr.='&staffId='.urlencode($_REQUEST['staffId']);
-        }
-            
-        $qwhere.= ' ) ';
-    } elseif($_REQUEST['staffId']) {
-        $qwhere.=' AND (ticket.staff_id='.db_input($_REQUEST['staffId']).' AND ticket.status="closed") ';
-        $qstr.='&staffId='.urlencode($_REQUEST['staffId']);
-    }
-
-    //dates
-    $startTime  =($_REQUEST['startDate'] && (strlen($_REQUEST['startDate'])>=8))?strtotime($_REQUEST['startDate']):0;
-    $endTime    =($_REQUEST['endDate'] && (strlen($_REQUEST['endDate'])>=8))?strtotime($_REQUEST['endDate']):0;
-    if( ($startTime && $startTime>time()) or ($startTime>$endTime && $endTime>0)){
-        $errors['err']='Entered date span is invalid. Selection ignored.';
-        $startTime=$endTime=0;
-    }else{
-        //Have fun with dates.
-        if($startTime){
-            $qwhere.=' AND ticket.created>=FROM_UNIXTIME('.$startTime.')';
-            $qstr.='&startDate='.urlencode($_REQUEST['startDate']);
-                        
-        }
-        if($endTime){
-            $qwhere.=' AND ticket.created<=FROM_UNIXTIME('.$endTime.')';
-            $qstr.='&endDate='.urlencode($_REQUEST['endDate']);
+            $qwhere.=" AND email.address='$queryterm'";
+        } else {//Deep search!
+            //This sucks..mass scan! search anything that moves!
+            require_once(INCLUDE_DIR.'ajax.tickets.php');
+
+            $tickets = TicketsAjaxApi::_search(array('query'=>$queryterm));
+            if (count($tickets))
+                $qwhere .= ' AND ticket.ticket_id IN ('.
+                    implode(',',db_input($tickets)).')';
         }
    }
 
 endif;
 
-$sortOptions=array('date'=>'ticket.created','ID'=>'ticketID','pri'=>'priority_urgency','name'=>'ticket.name',
-                   'subj'=>'ticket.subject','status'=>'ticket.status','assignee'=>'assigned','staff'=>'staff',
-                   'dept'=>'dept_name');
+if ($_REQUEST['advsid'] && isset($_SESSION['adv_'.$_REQUEST['advsid']])) {
+    $qstr.='advsid='.$_REQUEST['advsid'];
+    $qwhere .= ' AND ticket.ticket_id IN ('. implode(',',
+        db_input($_SESSION['adv_'.$_REQUEST['advsid']])).')';
+}
+
+$sortOptions=array('date'=>'ticket.created','ID'=>'ticketID',
+    'pri'=>'priority_id','name'=>'user.name','subj'=>'subject',
+    'status'=>'ticket.status','assignee'=>'assigned','staff'=>'staff',
+    'dept'=>'dept_name');
 
 $orderWays=array('DESC'=>'DESC','ASC'=>'ASC');
 
@@ -222,21 +166,21 @@ if($_REQUEST['sort'] && $queue) {
 
 //Set default sort by columns.
 if(!$order_by ) {
-    if($showanswered) 
+    if($showanswered)
         $order_by='ticket.lastresponse, ticket.created'; //No priority sorting for answered tickets.
     elseif(!strcasecmp($status,'closed'))
         $order_by='ticket.closed, ticket.created'; //No priority sorting for closed tickets.
     elseif($showoverdue) //priority> duedate > age in ASC order.
-        $order_by='priority_urgency ASC, ISNULL(duedate) ASC, duedate ASC, effective_date ASC, ticket.created';
-    else //XXX: Add due date here?? No - 
-        $order_by='priority_urgency ASC, effective_date DESC, ticket.created';
+        $order_by='priority_id, ISNULL(duedate) ASC, duedate ASC, effective_date ASC, ticket.created';
+    else //XXX: Add due date here?? No -
+        $order_by='priority_id, effective_date DESC, ticket.created';
 }
 
 $order=$order?$order:'DESC';
 if($order_by && strpos($order_by,',') && $order)
     $order_by=preg_replace('/(?<!ASC|DESC),/', " $order,", $order_by);
 
-$sort=$_REQUEST['sort']?strtolower($_REQUEST['sort']):'urgency'; //Urgency is not on display table.
+$sort=$_REQUEST['sort']?strtolower($_REQUEST['sort']):'priority_id'; //Urgency is not on display table.
 $x=$sort.'_sort';
 $$x=' class="'.strtolower($order).'" ';
 
@@ -244,11 +188,21 @@ if($_GET['limit'])
     $qstr.='&limit='.urlencode($_GET['limit']);
 
 $qselect ='SELECT DISTINCT ticket.ticket_id,lock_id,ticketID,ticket.dept_id,ticket.staff_id,ticket.team_id '
-         .' ,ticket.subject,ticket.name,ticket.email,dept_name '
-         .' ,ticket.status,ticket.source,isoverdue,isanswered,ticket.created,pri.* ';
+    .',MAX(IF(field.name = \'subject\', ans.value, NULL)) as `subject`'
+    .',MAX(IF(field.name = \'priority\', ans.value, NULL)) as `priority_desc`'
+    .',MAX(IF(field.name = \'priority\', ans.value_id, NULL)) as `priority_id`'
+    .' ,user.name'
+    .' ,email.address as email, dept_name '
+         .' ,ticket.status,ticket.source,isoverdue,isanswered,ticket.created ';
 
 $qfrom=' FROM '.TICKET_TABLE.' ticket '.
-       ' LEFT JOIN '.DEPT_TABLE.' dept ON ticket.dept_id=dept.dept_id ';
+       ' LEFT JOIN '.USER_TABLE.' user ON user.id = ticket.user_id'.
+       ' LEFT JOIN '.USER_EMAIL_TABLE.' email ON user.id = email.user_id'.
+       ' LEFT JOIN '.DEPT_TABLE.' dept ON ticket.dept_id=dept.dept_id '.
+       ' LEFT JOIN ost_form_entry entry ON entry.object_type=\'T\'
+             and entry.object_id=ticket.ticket_id'.
+       ' LEFT JOIN ost_form_entry_values ans ON ans.entry_id = entry.id'.
+       ' LEFT JOIN ost_form_field field ON field.id=ans.field_id';
 
 $sjoin='';
 if($search && $deep_search) {
@@ -273,8 +227,7 @@ $qselect.=' ,count(attach.attach_id) as attachments '
          .' ,IF(staff.staff_id IS NULL,team.name,CONCAT_WS(" ", staff.lastname, staff.firstname)) as assigned '
          .' ,IF(ptopic.topic_pid IS NULL, topic.topic, CONCAT_WS(" / ", ptopic.topic, topic.topic)) as helptopic ';
 
-$qfrom.=' LEFT JOIN '.TICKET_PRIORITY_TABLE.' pri ON (ticket.priority_id=pri.priority_id) '
-       .' LEFT JOIN '.TICKET_LOCK_TABLE.' tlock ON (ticket.ticket_id=tlock.ticket_id AND tlock.expire>NOW() 
+$qfrom.=' LEFT JOIN '.TICKET_LOCK_TABLE.' tlock ON (ticket.ticket_id=tlock.ticket_id AND tlock.expire>NOW()
                AND tlock.staff_id!='.db_input($thisstaff->getId()).') '
        .' LEFT JOIN '.TICKET_ATTACHMENT_TABLE.' attach ON (ticket.ticket_id=attach.ticket_id) '
        .' LEFT JOIN '.TICKET_THREAD_TABLE.' thread ON ( ticket.ticket_id=thread.ticket_id) '
@@ -284,6 +237,11 @@ $qfrom.=' LEFT JOIN '.TICKET_PRIORITY_TABLE.' pri ON (ticket.priority_id=pri.pri
        .' LEFT JOIN '.TOPIC_TABLE.' topic ON (ticket.topic_id=topic.topic_id) '
        .' LEFT JOIN '.TOPIC_TABLE.' ptopic ON (ptopic.topic_id=topic.topic_pid) ';
 
+// Fetch priority information
+$res = db_query('select * from '.PRIORITY_TABLE);
+$prios = array();
+while ($row = db_fetch_array($res))
+    $prios[$row['priority_id']] = $row;
 
 $query="$qselect $qfrom $qwhere $qgroup ORDER BY $order_by $order LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
 //echo $query;
@@ -333,13 +291,13 @@ $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting..
 	        <th width="8px">&nbsp;</th>
             <?php } ?>
 	        <th width="70">
-                <a <?php echo $id_sort; ?> href="tickets.php?sort=ID&order=<?php echo $negorder; ?><?php echo $qstr; ?>" 
+                <a <?php echo $id_sort; ?> href="tickets.php?sort=ID&order=<?php echo $negorder; ?><?php echo $qstr; ?>"
                     title="Sort By Ticket ID <?php echo $negorder; ?>">Ticket</a></th>
 	        <th width="70">
-                <a  <?php echo $date_sort; ?> href="tickets.php?sort=date&order=<?php echo $negorder; ?><?php echo $qstr; ?>" 
+                <a  <?php echo $date_sort; ?> href="tickets.php?sort=date&order=<?php echo $negorder; ?><?php echo $qstr; ?>"
                     title="Sort By Date <?php echo $negorder; ?>">Date</a></th>
 	        <th width="280">
-                 <a <?php echo $subj_sort; ?> href="tickets.php?sort=subj&order=<?php echo $negorder; ?><?php echo $qstr; ?>" 
+                 <a <?php echo $subj_sort; ?> href="tickets.php?sort=subj&order=<?php echo $negorder; ?><?php echo $qstr; ?>"
                     title="Sort By Subject <?php echo $negorder; ?>">Subject</a></th>
             <th width="170">
                 <a <?php echo $name_sort; ?> href="tickets.php?sort=name&order=<?php echo $negorder; ?><?php echo $qstr; ?>"
@@ -352,27 +310,27 @@ $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting..
             <?php
             } else { ?>
                 <th width="60" <?php echo $pri_sort;?>>
-                    <a <?php echo $pri_sort; ?> href="tickets.php?sort=pri&order=<?php echo $negorder; ?><?php echo $qstr; ?>" 
+                    <a <?php echo $pri_sort; ?> href="tickets.php?sort=pri&order=<?php echo $negorder; ?><?php echo $qstr; ?>"
                         title="Sort By Priority <?php echo $negorder; ?>">Priority</a></th>
             <?php
             }
 
-            if($showassigned ) { 
+            if($showassigned ) {
                 //Closed by
                 if(!strcasecmp($status,'closed')) { ?>
                     <th width="150">
-                        <a <?php echo $staff_sort; ?> href="tickets.php?sort=staff&order=<?php echo $negorder; ?><?php echo $qstr; ?>" 
+                        <a <?php echo $staff_sort; ?> href="tickets.php?sort=staff&order=<?php echo $negorder; ?><?php echo $qstr; ?>"
                             title="Sort By Closing Staff Name <?php echo $negorder; ?>">Closed By</a></th>
                 <?php
                 } else { //assigned to ?>
                     <th width="150">
-                        <a <?php echo $assignee_sort; ?> href="tickets.php?sort=assignee&order=<?php echo $negorder; ?><?php echo $qstr; ?>" 
+                        <a <?php echo $assignee_sort; ?> href="tickets.php?sort=assignee&order=<?php echo $negorder; ?><?php echo $qstr; ?>"
                             title="Sort By Assignee <?php echo $negorder;?>">Assigned To</a></th>
                 <?php
                 }
             } else { ?>
                 <th width="150">
-                    <a <?php echo $dept_sort; ?> href="tickets.php?sort=dept&order=<?php echo $negorder;?><?php echo $qstr; ?>" 
+                    <a <?php echo $dept_sort; ?> href="tickets.php?sort=dept&order=<?php echo $negorder;?><?php echo $qstr; ?>"
                         title="Sort By Department <?php echo $negorder; ?>">Department</a></th>
             <?php
             } ?>
@@ -411,8 +369,8 @@ $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting..
                 }
                 ?>
             <tr id="<?php echo $row['ticket_id']; ?>">
-                <?php if($thisstaff->canManageTickets()) { 
-                              
+                <?php if($thisstaff->canManageTickets()) {
+
                     $sel=false;
                     if($ids && in_array($row['ticket_id'], $ids))
                         $sel=true;
@@ -422,34 +380,34 @@ $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting..
                 </td>
                 <?php } ?>
                 <td align="center" title="<?php echo $row['email']; ?>" nowrap>
-                  <a class="Icon <?php echo strtolower($row['source']); ?>Ticket ticketPreview" title="Preview Ticket" 
+                  <a class="Icon <?php echo strtolower($row['source']); ?>Ticket ticketPreview" title="Preview Ticket"
                     href="tickets.php?id=<?php echo $row['ticket_id']; ?>"><?php echo $tid; ?></a></td>
                 <td align="center" nowrap><?php echo Format::db_date($row['created']); ?></td>
-                <td><a <?php if($flag) { ?> class="Icon <?php echo $flag; ?>Ticket" title="<?php echo ucfirst($flag); ?> Ticket" <?php } ?> 
+                <td><a <?php if($flag) { ?> class="Icon <?php echo $flag; ?>Ticket" title="<?php echo ucfirst($flag); ?> Ticket" <?php } ?>
                     href="tickets.php?id=<?php echo $row['ticket_id']; ?>"><?php echo $subject; ?></a>
                      &nbsp;
                      <?php echo ($threadcount>1)?" <small>($threadcount)</small>&nbsp;":''?>
                      <?php echo $row['attachments']?"<span class='Icon file'>&nbsp;</span>":''; ?>
                 </td>
                 <td nowrap>&nbsp;<?php echo Format::truncate($row['name'],22,strpos($row['name'],'@')); ?>&nbsp;</td>
-                <?php 
+                <?php
                 if($search && !$status){
                     $displaystatus=ucfirst($row['status']);
                     if(!strcasecmp($row['status'],'open'))
                         $displaystatus="<b>$displaystatus</b>";
                     echo "<td>$displaystatus</td>";
                 } else { ?>
-                <td class="nohover" align="center" style="background-color:<?php echo $row['priority_color']; ?>;">
-                    <?php echo $row['priority_desc']; ?></td>
+                <td class="nohover" align="center" style="background-color:<?php echo $prios[$row['priority_id']]['priority_color']; ?>;">
+                    <?php echo $prios[$row['priority_id']]['priority_desc']; ?></td>
                 <?php
-                } 
+                }
                 ?>
                 <td nowrap>&nbsp;<?php echo $lc; ?></td>
             </tr>
             <?php
             } //end of while.
         else: //not tickets found!! set fetch error.
-            $ferror='There are no tickets here. (Leave a little early today).';  
+            $ferror='There are no tickets here. (Leave a little early today).';
         endif; ?>
     </tbody>
     <tfoot>
@@ -477,7 +435,7 @@ $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting..
     ?>
         <?php
          if($thisstaff->canManageTickets()) { ?>
-           <p class="centered" id="actions">  
+           <p class="centered" id="actions">
             <?php
             $status=$_REQUEST['status']?$_REQUEST['status']:$status;
             switch (strtolower($status)) {
@@ -572,7 +530,7 @@ $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting..
                 <?php
                 if(($mydepts = $thisstaff->getDepts()) && ($depts=Dept::getDepartments())) {
                     foreach($depts as $id =>$name) {
-                        if(!in_array($id, $mydepts)) continue; 
+                        if(!in_array($id, $mydepts)) continue;
                         echo sprintf('<option value="%d">%s</option>', $id, $name);
                     }
                 }
@@ -594,7 +552,7 @@ $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting..
                     }
                     echo '</OPTGROUP>';
                 }
-                
+
                 if(($teams=Team::getTeams())) {
                     echo '<OPTGROUP label="Teams ('.count($teams).')">';
                     foreach($teams as $id => $name) {
@@ -635,6 +593,17 @@ $negorder=$order=='DESC'?'ASC':'DESC'; //Negate the sorting..
             <span>TO</span>
             <input class="dp" type="input" size="20" name="endDate">
         </fieldset>
+        <fieldset>
+        <?php
+        foreach (TicketForm::getInstance()->getFields() as $f) {
+            if (in_array($f->get('type'), array('text', 'memo', 'phone', 'thread')))
+                continue;
+            elseif (!$f->hasData())
+                continue;
+            ?><label><?php echo $f->getLabel(); ?>:</label>
+                <div style="display:inline-block;width: 12.5em;"><?php $f->render(); ?></div>
+        <?php } ?>
+        </fieldset>
         <p>
             <span class="buttons">
                 <input type="submit" value="Search">
diff --git a/include/upgrader/streams/core.sig b/include/upgrader/streams/core.sig
index 8ced61f0cdd122a0aaeead6269f21f5ee31c8d88..ce6d3fd6537de8fbe1b5c9acda7833e5972d37b6 100644
--- a/include/upgrader/streams/core.sig
+++ b/include/upgrader/streams/core.sig
@@ -1 +1 @@
-dad45ca24a3800102f8b92c7279347db
+17f0cc96b366a747113622fa4780f9bc
diff --git a/include/upgrader/streams/core/d51f303a-dad45ca2.patch.sql b/include/upgrader/streams/core/d51f303a-dad45ca2.patch.sql
index 6f2727600eed75fcf85c3e7c0bc844470c842738..94b8f8aa7fcd59f202bcc281324c58894f160a72 100644
--- a/include/upgrader/streams/core/d51f303a-dad45ca2.patch.sql
+++ b/include/upgrader/streams/core/d51f303a-dad45ca2.patch.sql
@@ -45,92 +45,129 @@ CREATE TABLE `%TABLE_PREFIX%draft` (
 
 -- Migrate email templates to HTML
 UPDATE `%TABLE_PREFIX%email_template`
-    SET `body` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `body`))));
+    SET `body` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `body`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;');
 
 -- Migrate notes to HTML
 UPDATE `%TABLE_PREFIX%api_key`
-    SET `notes` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `notes`))));
+    SET `notes` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `notes`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;');
 UPDATE `%TABLE_PREFIX%email`
-    SET `notes` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `notes`))));
+    SET `notes` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `notes`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;');
 UPDATE `%TABLE_PREFIX%email_template_group`
-    SET `notes` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `notes`))));
+    SET `notes` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `notes`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;');
 UPDATE `%TABLE_PREFIX%faq`
-    SET `notes` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `notes`))));
+    SET `notes` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `notes`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;');
 UPDATE `%TABLE_PREFIX%faq_category`
-    SET `notes` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `notes`))));
+    SET `notes` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `notes`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;');
 UPDATE `%TABLE_PREFIX%filter`
-    SET `notes` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `notes`))));
+    SET `notes` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `notes`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;');
 UPDATE `%TABLE_PREFIX%groups`
-    SET `notes` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `notes`))));
+    SET `notes` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `notes`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;');
 UPDATE `%TABLE_PREFIX%help_topic`
-    SET `notes` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `notes`))));
+    SET `notes` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `notes`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;');
 UPDATE `%TABLE_PREFIX%page`
-    SET `notes` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `notes`))));
+    SET `notes` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `notes`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;');
 UPDATE `%TABLE_PREFIX%sla`
-    SET `notes` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `notes`))));
+    SET `notes` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `notes`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;');
 UPDATE `%TABLE_PREFIX%staff`
-    SET `notes` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `notes`))));
+    SET `notes` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `notes`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;');
 UPDATE `%TABLE_PREFIX%team`
-    SET `notes` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `notes`))));
+    SET `notes` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `notes`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;');
 
 -- Migrate canned responses to HTML
 UPDATE `%TABLE_PREFIX%canned_response`
-    SET `notes` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `notes`)))),
-    `response` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;',
-                REPLACE('&', '&amp;', `response`))));
+    SET `notes` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `notes`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;'),
+    `response` = REPLACE( REPLACE( REPLACE( REPLACE(
+        `response`,
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>'),
+        '&', '&amp;');
 
 -- Migrate ticket-thread to HTML
 -- XXX: Migrate & -> &amp; ? -- the problem is that there's a fix in 1.7.1
 -- that properly encodes these characters, so encoding & would mean possible
 -- double encoding.
 UPDATE `%TABLE_PREFIX%ticket_thread`
-    SET `body` = REPLACE('\n', '<br/>',
-        REPLACE('<', '&lt;',
-            REPLACE('>', '&gt;', `body`)));
+    SET `body` = REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE(
+        `body`,
+        '\r', ''),
+        '\n ', '\n'),
+        '\n\n\n', '\n\n'),
+        '\n\n\n', '\n\n'),
+        '\n\n\n', '\n\n'),
+        '<', '&lt;'),
+        '>', '&gt;'),
+        '\n', '<br/>');
 
 -- Finished with patch
 UPDATE `%TABLE_PREFIX%config`
diff --git a/include/upgrader/streams/core/dad45ca2-17f0cc96.cleanup.sql b/include/upgrader/streams/core/dad45ca2-17f0cc96.cleanup.sql
new file mode 100644
index 0000000000000000000000000000000000000000..4fe8c0d0a9253566015880bba8b3c615ae143c23
--- /dev/null
+++ b/include/upgrader/streams/core/dad45ca2-17f0cc96.cleanup.sql
@@ -0,0 +1,104 @@
+-- Port data from the ticket table
+-- 1. Create form entries for each ticket
+INSERT INTO `%TABLE_PREFIX%form_entry` (
+    `form_id`, `object_id`, `object_type`, `sort`, `created`, `updated`)
+    SELECT (SELECT id FROM ost_form WHERE `type`='T'),
+        `ticket_id`, 'T', 10, `created`, `updated`
+    FROM `%TABLE_PREFIX%ticket`;
+
+-- 2. Copy subject lines from the ticket table into form entry
+INSERT INTO `%TABLE_PREFIX%form_entry_values` (
+    `field_id`, `entry_id`, `value`)
+    SELECT A3.`id`, A2.`id`, A1.`subject`
+    FROM `%TABLE_PREFIX%ticket` A1
+        INNER JOIN `%TABLE_PREFIX%form` A4 ON (`type`='T')
+        INNER JOIN `%TABLE_PREFIX%form_entry` A2 ON (A2.`object_id`
+                = A1.`ticket_id` AND A2.`object_type` = 'T')
+        INNER JOIN `%TABLE_PREFIX%form_field` A3 ON (A2.`form_id`
+                = A4.`id`)
+    WHERE A3.`name` = 'subject';
+
+-- 2b. Copy priority from ticket to custom form entry
+INSERT INTO `%TABLE_PREFIX%form_entry_values` (
+    `field_id`, `entry_id`, `value`, `value_id`)
+    SELECT A3.`id`, A2.`id`, A5.`priority_desc`, A1.`priority_id`
+    FROM `%TABLE_PREFIX%ticket` A1
+        INNER JOIN `%TABLE_PREFIX%form` A4 ON (`type`='T')
+        INNER JOIN `%TABLE_PREFIX%form_entry` A2 ON (A2.`object_id`
+                = A1.`ticket_id` AND A2.`object_type` = 'T')
+        INNER JOIN `%TABLE_PREFIX%form_field` A3 ON (A2.`form_id`
+                = A4.`id`)
+        INNER JOIN `%TABLE_PREFIX%ticket_priority` A5 ON (A5.`priority_id`
+                = A1.`priority_id`)
+    WHERE A3.`name` = 'priority';
+
+-- 3. Create <user> accounts for everybody
+--      - Start with creating email addresses for the accounts
+INSERT INTO `%TABLE_PREFIX%user_email` (`address`)
+    SELECT DISTINCT `email` FROM `%TABLE_PREFIX%ticket`;
+
+--      - Then create the accounts and link the `default_email`s
+INSERT INTO `%TABLE_PREFIX%user` (`name`, `default_email_id`, `created`, `updated`)
+    SELECT MAX(`name`), A2.`id`, A1.`created`, A1.`updated`
+    FROM `%TABLE_PREFIX%ticket` A1
+        INNER JOIN `%TABLE_PREFIX%user_email` A2 ON (A1.`email` = A2.`address`)
+    GROUP BY A2.`id`;
+
+--      - Now link the user and user_email tables
+ALTER TABLE `%TABLE_PREFIX%user` ADD KEY `def_eml_id` (`default_email_id`, `id`);
+UPDATE `%TABLE_PREFIX%user_email` A1
+    SET user_id = (
+        SELECT A2.`id` FROM `%TABLE_PREFIX%user` A2
+        WHERE `default_email_id` = A1.`id`);
+ALTER TABLE `%TABLE_PREFIX%user` DROP INDEX `def_eml_id`;
+
+--      - Update the ticket table
+ALTER TABLE `%TABLE_PREFIX%ticket` ADD KEY `email_lookup` (`email`);
+UPDATE `%TABLE_PREFIX%ticket` A1
+    JOIN `%TABLE_PREFIX%user_email` A2 ON A2.`address` = A1.`email`
+    SET A1.`user_id` = A2.`user_id`,
+        A1.`user_email_id` = A2.`id`;
+ALTER TABLE `%TABLE_PREFIX%ticket` DROP INDEX `email_lookup`;
+
+-- TODO: Move this to a client info dynamic entry
+-- 4. Create form entries for each ticket
+INSERT INTO `%TABLE_PREFIX%form_entry` (
+    `form_id`, `object_id`, `object_type`, `sort`, `created`, `updated`)
+    SELECT DISTINCT A2.`id`, `user_id`, 'U', 10, MIN(A1.`created`),
+        MAX(A1.`updated`)
+    FROM `%TABLE_PREFIX%ticket` A1
+    JOIN `%TABLE_PREFIX%form` A2 ON (A2.`type` = 'U')
+    GROUP BY `user_id`, A2.`id`;
+
+-- 5. Copy Phone from the ticket table to section #1
+INSERT INTO `%TABLE_PREFIX%form_entry_values` (
+    `field_id`, `entry_id`, `value`)
+    SELECT A3.`id`, A2.`id`, MAX(CONCAT(
+        REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE(
+            A1.`phone`,
+            ' ', ''),
+            ')', ''),
+            '(', ''),
+            '+', ''),
+            '-', ''),
+            '.', ''), 'X', A1.`phone_ext`))
+    FROM `%TABLE_PREFIX%ticket` A1
+        INNER JOIN `%TABLE_PREFIX%form` A4 ON (`type`='U')
+        INNER JOIN `%TABLE_PREFIX%form_entry` A2 ON (A2.`object_id`
+                = A1.`ticket_id` AND A2.`object_type` = 'U')
+        INNER JOIN `%TABLE_PREFIX%form_field` A3 ON (A2.`form_id`
+                = A4.`id`)
+    WHERE A3.`name` = 'phone' AND LENGTH(A1.`phone`)
+    GROUP BY A3.`id`, A2.`id`;
+
+-- 6. Remove columns from ticket table
+ALTER TABLE `%TABLE_PREFIX%ticket`
+    DROP COLUMN `name`,
+    DROP COLUMN `email`,
+    DROP COLUMN `phone`,
+    DROP COLUMN `phone_ext`,
+    DROP COLUMN `subject`,
+    DROP COLUMN `priority_id`;
+
+-- 5. Cleanup ticket table with dropped varchar columns
+OPTIMIZE TABLE `%TABLE_PREFIX%ticket`;
diff --git a/include/upgrader/streams/core/dad45ca2-17f0cc96.patch.sql b/include/upgrader/streams/core/dad45ca2-17f0cc96.patch.sql
new file mode 100644
index 0000000000000000000000000000000000000000..d6c7bd6304bb56cdaba8a4c38700ca5fcf9b7185
--- /dev/null
+++ b/include/upgrader/streams/core/dad45ca2-17f0cc96.patch.sql
@@ -0,0 +1,124 @@
+/**
+ * @version v1.8.0-dpr1 Dynamic Forms
+ * @signature 17f0cc96b366a747113622fa4780f9bc
+ *
+ * Adds the database structure for the dynamic forms feature and migrates
+ * the database from the legacy <=1.7 format to the new format with the
+ * dynamic forms feature. Basically, a default form is installed with the
+ * fields found in the legacy version of osTicket, the data is migrated from
+ * the fields in the ticket table to the new forms tables, and then the
+ * fields are dropped from the ticket table.
+ */
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%form`;
+CREATE TABLE `%TABLE_PREFIX%form` (
+    `id` int(11) unsigned NOT NULL auto_increment,
+    `type` char(1) NOT NULL DEFAULT 'G',
+    `deletable` tinyint(1) NOT NULL DEFAULT 1,
+    `title` varchar(255) NOT NULL,
+    `instructions` varchar(512),
+    `notes` text,
+    `created` datetime NOT NULL,
+    `updated` datetime NOT NULL,
+    PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%form_field`;
+CREATE TABLE `%TABLE_PREFIX%form_field` (
+    `id` int(11) unsigned NOT NULL auto_increment,
+    `form_id` int(11) unsigned NOT NULL,
+    `type` varchar(255) NOT NULL DEFAULT 'text',
+    `label` varchar(255) NOT NULL,
+    `required` tinyint(1) NOT NULL DEFAULT 0,
+    `private` tinyint(1) NOT NULL DEFAULT 0,
+    `edit_mask` tinyint(1) NOT NULL DEFAULT 0,
+    `name` varchar(64) NOT NULL,
+    `configuration` text,
+    `sort` int(11) unsigned NOT NULL,
+    `hint` varchar(512),
+    `created` datetime NOT NULL,
+    `updated` datetime NOT NULL,
+    PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%form_entry`;
+CREATE TABLE `%TABLE_PREFIX%form_entry` (
+    `id` int(11) unsigned NOT NULL auto_increment,
+    `form_id` int(11) unsigned NOT NULL,
+    `object_id` int(11) unsigned,
+    `object_type` char(1) NOT NULL DEFAULT 'T',
+    `sort` int(11) unsigned NOT NULL DEFAULT 1,
+    `created` datetime NOT NULL,
+    `updated` datetime NOT NULL,
+    PRIMARY KEY (`id`),
+    KEY `entry_lookup` (`object_id`, `object_type`)
+) DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%form_entry_values`;
+CREATE TABLE `%TABLE_PREFIX%form_entry_values` (
+    -- references form_entry.id
+    `entry_id` int(11) unsigned NOT NULL,
+    `field_id` int(11) unsigned NOT NULL,
+    `value` text,
+    `value_id` int(11),
+    PRIMARY KEY (`entry_id`, `field_id`)
+) DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%list`;
+CREATE TABLE `%TABLE_PREFIX%list` (
+    `id` int(11) unsigned NOT NULL auto_increment,
+    `name` varchar(255) NOT NULL,
+    `name_plural` varchar(255),
+    `sort_mode` enum('Alpha', '-Alpha', 'SortCol') NOT NULL DEFAULT 'Alpha',
+    `notes` text,
+    `created` datetime NOT NULL,
+    `updated` datetime NOT NULL,
+    PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%list_items`;
+CREATE TABLE `%TABLE_PREFIX%list_items` (
+    `id` int(11) unsigned NOT NULL auto_increment,
+    `list_id` int(11),
+    `value` varchar(255) NOT NULL,
+    -- extra value such as abbreviation
+    `extra` varchar(255),
+    `sort` int(11) NOT NULL DEFAULT 1,
+    PRIMARY KEY (`id`),
+    KEY `list_item_lookup` (`list_id`)
+) DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%user`;
+CREATE TABLE `%TABLE_PREFIX%user` (
+  `id` int(10) unsigned NOT NULL auto_increment,
+  `default_email_id` int(10) NOT NULL,
+  `name` varchar(128) NOT NULL,
+  `created` datetime NOT NULL,
+  `updated` datetime NOT NULL,
+  PRIMARY KEY  (`id`)
+) DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%user_email`;
+CREATE TABLE `%TABLE_PREFIX%user_email` (
+  `id` int(10) unsigned NOT NULL auto_increment,
+  `user_id` int(10) unsigned NOT NULL,
+  `address` varchar(128) NOT NULL,
+  PRIMARY KEY  (`id`),
+  UNIQUE KEY `address` (`address`),
+  KEY `user_email_lookup` (`user_id`)
+) DEFAULT CHARSET=utf8;
+
+ALTER TABLE `%TABLE_PREFIX%filter_rule`
+    CHANGE `what` `what` varchar(32) NOT NULL;
+
+ALTER TABLE `%TABLE_PREFIX%help_topic`
+    ADD `formset_id` int(11) unsigned NOT NULL default '0' AFTER `sla_id`;
+
+ALTER TABLE `%TABLE_PREFIX%ticket`
+    ADD `user_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `ticket_id`,
+    ADD `user_email_id` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `user_id`;
+
+-- Finished with patch
+UPDATE `%TABLE_PREFIX%config`
+    SET `value` = '17f0cc96b366a747113622fa4780f9bc'
+    WHERE `key` = 'schema_signature' AND `namespace` = 'core';
diff --git a/include/upgrader/streams/core/dad45ca2-17f0cc96.task.php b/include/upgrader/streams/core/dad45ca2-17f0cc96.task.php
new file mode 100644
index 0000000000000000000000000000000000000000..98d128fbdaed3a1a4a57fe3af06cd0fbb99c591e
--- /dev/null
+++ b/include/upgrader/streams/core/dad45ca2-17f0cc96.task.php
@@ -0,0 +1,21 @@
+<?php
+
+/*
+ * Loads the initial data for dynamic forms into the system. This is
+ * preferred over providing the data inside the SQL scripts
+ */
+
+class DynamicFormLoader extends MigrationTask {
+    var $description = "Loading initial data for dynamic forms";
+
+    function run($max_time) {
+        $i18n = new Internationalization('en_US');
+        $forms = $i18n->getTemplate('form.yaml')->getData();
+        foreach ($forms as $f)
+            DynamicForm::create($f);
+    }
+}
+
+return 'DynamicFormLoader';
+
+?>
diff --git a/js/jquery-ui-1.10.3.custom.min.js b/js/jquery-ui-1.10.3.custom.min.js
index 8d62da712ce1181ff7030358326918325a3dc5db..bdd65eebc8cf831258c641abba61ff9bb1a7cb26 100755
--- a/js/jquery-ui-1.10.3.custom.min.js
+++ b/js/jquery-ui-1.10.3.custom.min.js
@@ -1,7 +1,7 @@
-/*! jQuery UI - v1.10.3 - 2013-08-24
+/*! jQuery UI - v1.10.3 - 2013-10-08
 * http://jqueryui.com
-* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.draggable.js, jquery.ui.datepicker.js
-* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */
+* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js
+* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
 
-(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.3",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.3",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e){e.widget("ui.draggable",e.ui.mouse,{version:"1.10.3",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"!==this.options.helper||/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(t){var i=this.options;return this.helper||i.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(e(i.iframeFix===!0?"iframe":i.iframeFix).each(function(){e("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var i=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offsetParent=this.helper.offsetParent(),this.offsetParentCssPosition=this.offsetParent.css("position"),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.offset.scroll=!1,e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,i){if("fixed"===this.offsetParentCssPosition&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",t,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var i=this,s=!1;return e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),"original"!==this.options.helper||e.contains(this.element[0].ownerDocument,this.element[0])?("invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",t)!==!1&&i._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1):!1},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:!0},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper)?e(i.helper.apply(this.element[0],[t])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return s.parents("body").length||s.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s[0]===this.element[0]||/(fixed|absolute)/.test(s.css("position"))||s.css("position","absolute"),s},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){var t=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&e.ui.ie)&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options;return n.containment?"window"===n.containment?(this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):"document"===n.containment?(this.containment=[0,0,e(document).width()-this.helperProportions.width-this.margins.left,(e(document).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):n.containment.constructor===Array?(this.containment=n.containment,undefined):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=e(n.containment),s=i[0],s&&(t="hidden"!==i.css("overflow"),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(t?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=i),undefined):(this.containment=null,undefined)},_convertPositionTo:function(t,i){i||(i=this.position);var s="absolute"===t?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent;return this.offset.scroll||(this.offset.scroll={top:n.scrollTop(),left:n.scrollLeft()}),{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top)*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)*s}},_generatePosition:function(t){var i,s,n,a,o=this.options,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=t.pageX,l=t.pageY;return this.offset.scroll||(this.offset.scroll={top:r.scrollTop(),left:r.scrollLeft()}),this.originalPosition&&(this.containment&&(this.relative_container?(s=this.relative_container.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,t.pageX-this.offset.click.left<i[0]&&(h=i[0]+this.offset.click.left),t.pageY-this.offset.click.top<i[1]&&(l=i[1]+this.offset.click.top),t.pageX-this.offset.click.left>i[2]&&(h=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,h=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(t,i,s){return s=s||this._uiHash(),e.ui.plugin.call(this,t,[i,s]),"drag"===t&&(this.positionAbs=this._convertPositionTo("absolute")),e.Widget.prototype._trigger.call(this,t,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,i){var s=e(this).data("ui-draggable"),n=s.options,a=e.extend({},i,{item:s.element});s.sortables=[],e(n.connectToSortable).each(function(){var i=e.data(this,"ui-sortable");i&&!i.options.disabled&&(s.sortables.push({instance:i,shouldRevert:i.options.revert}),i.refreshPositions(),i._trigger("activate",t,a))})},stop:function(t,i){var s=e(this).data("ui-draggable"),n=e.extend({},i,{item:s.element});e.each(s.sortables,function(){this.instance.isOver?(this.instance.isOver=0,s.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=this.shouldRevert),this.instance._mouseStop(t),this.instance.options.helper=this.instance.options._helper,"original"===s.options.helper&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",t,n))})},drag:function(t,i){var s=e(this).data("ui-draggable"),n=this;e.each(s.sortables,function(){var a=!1,o=this;this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(a=!0,e.each(s.sortables,function(){return this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this!==o&&this.instance._intersectsWith(this.instance.containerCache)&&e.contains(o.instance.element[0],this.instance.element[0])&&(a=!1),a})),a?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=e(n).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return i.helper[0]},t.target=this.instance.currentItem[0],this.instance._mouseCapture(t,!0),this.instance._mouseStart(t,!0,!0),this.instance.offset.click.top=s.offset.click.top,this.instance.offset.click.left=s.offset.click.left,this.instance.offset.parent.left-=s.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=s.offset.parent.top-this.instance.offset.parent.top,s._trigger("toSortable",t),s.dropped=this.instance.element,s.currentItem=s.element,this.instance.fromOutside=s),this.instance.currentItem&&this.instance._mouseDrag(t)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",t,this.instance._uiHash(this.instance)),this.instance._mouseStop(t,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),s._trigger("fromSortable",t),s.dropped=!1)})}}),e.ui.plugin.add("draggable","cursor",{start:function(){var t=e("body"),i=e(this).data("ui-draggable").options;t.css("cursor")&&(i._cursor=t.css("cursor")),t.css("cursor",i.cursor)},stop:function(){var t=e(this).data("ui-draggable").options;t._cursor&&e("body").css("cursor",t._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,i){var s=e(i.helper),n=e(this).data("ui-draggable").options;s.css("opacity")&&(n._opacity=s.css("opacity")),s.css("opacity",n.opacity)},stop:function(t,i){var s=e(this).data("ui-draggable").options;s._opacity&&e(i.helper).css("opacity",s._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(){var t=e(this).data("ui-draggable");t.scrollParent[0]!==document&&"HTML"!==t.scrollParent[0].tagName&&(t.overflowOffset=t.scrollParent.offset())},drag:function(t){var i=e(this).data("ui-draggable"),s=i.options,n=!1;i.scrollParent[0]!==document&&"HTML"!==i.scrollParent[0].tagName?(s.axis&&"x"===s.axis||(i.overflowOffset.top+i.scrollParent[0].offsetHeight-t.pageY<s.scrollSensitivity?i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop+s.scrollSpeed:t.pageY-i.overflowOffset.top<s.scrollSensitivity&&(i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop-s.scrollSpeed)),s.axis&&"y"===s.axis||(i.overflowOffset.left+i.scrollParent[0].offsetWidth-t.pageX<s.scrollSensitivity?i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft+s.scrollSpeed:t.pageX-i.overflowOffset.left<s.scrollSensitivity&&(i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft-s.scrollSpeed))):(s.axis&&"x"===s.axis||(t.pageY-e(document).scrollTop()<s.scrollSensitivity?n=e(document).scrollTop(e(document).scrollTop()-s.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<s.scrollSensitivity&&(n=e(document).scrollTop(e(document).scrollTop()+s.scrollSpeed))),s.axis&&"y"===s.axis||(t.pageX-e(document).scrollLeft()<s.scrollSensitivity?n=e(document).scrollLeft(e(document).scrollLeft()-s.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<s.scrollSensitivity&&(n=e(document).scrollLeft(e(document).scrollLeft()+s.scrollSpeed)))),n!==!1&&e.ui.ddmanager&&!s.dropBehaviour&&e.ui.ddmanager.prepareOffsets(i,t)}}),e.ui.plugin.add("draggable","snap",{start:function(){var t=e(this).data("ui-draggable"),i=t.options;t.snapElements=[],e(i.snap.constructor!==String?i.snap.items||":data(ui-draggable)":i.snap).each(function(){var i=e(this),s=i.offset();this!==t.element[0]&&t.snapElements.push({item:this,width:i.outerWidth(),height:i.outerHeight(),top:s.top,left:s.left})})},drag:function(t,i){var s,n,a,o,r,h,l,u,c,d,p=e(this).data("ui-draggable"),f=p.options,m=f.snapTolerance,g=i.offset.left,v=g+p.helperProportions.width,b=i.offset.top,y=b+p.helperProportions.height;for(c=p.snapElements.length-1;c>=0;c--)r=p.snapElements[c].left,h=r+p.snapElements[c].width,l=p.snapElements[c].top,u=l+p.snapElements[c].height,r-m>v||g>h+m||l-m>y||b>u+m||!e.contains(p.snapElements[c].item.ownerDocument,p.snapElements[c].item)?(p.snapElements[c].snapping&&p.options.snap.release&&p.options.snap.release.call(p.element,t,e.extend(p._uiHash(),{snapItem:p.snapElements[c].item})),p.snapElements[c].snapping=!1):("inner"!==f.snapMode&&(s=m>=Math.abs(l-y),n=m>=Math.abs(u-b),a=m>=Math.abs(r-v),o=m>=Math.abs(h-g),s&&(i.position.top=p._convertPositionTo("relative",{top:l-p.helperProportions.height,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:u,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r-p.helperProportions.width}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:h}).left-p.margins.left)),d=s||n||a||o,"outer"!==f.snapMode&&(s=m>=Math.abs(l-b),n=m>=Math.abs(u-y),a=m>=Math.abs(r-g),o=m>=Math.abs(h-v),s&&(i.position.top=p._convertPositionTo("relative",{top:l,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:u-p.helperProportions.height,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:h-p.helperProportions.width}).left-p.margins.left)),!p.snapElements[c].snapping&&(s||n||a||o||d)&&p.options.snap.snap&&p.options.snap.snap.call(p.element,t,e.extend(p._uiHash(),{snapItem:p.snapElements[c].item})),p.snapElements[c].snapping=s||n||a||o||d)}}),e.ui.plugin.add("draggable","stack",{start:function(){var t,i=this.data("ui-draggable").options,s=e.makeArray(e(i.stack)).sort(function(t,i){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(i).css("zIndex"),10)||0)});s.length&&(t=parseInt(e(s[0]).css("zIndex"),10)||0,e(s).each(function(i){e(this).css("zIndex",t+i)}),this.css("zIndex",t+s.length))}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,i){var s=e(i.helper),n=e(this).data("ui-draggable").options;s.css("zIndex")&&(n._zIndex=s.css("zIndex")),s.css("zIndex",n.zIndex)},stop:function(t,i){var s=e(this).data("ui-draggable").options;s._zIndex&&e(i.helper).css("zIndex",s._zIndex)}})})(jQuery);(function(t,e){function i(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},t.extend(this._defaults,this.regional[""]),this.dpDiv=s(t("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function s(e){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return e.delegate(i,"mouseout",function(){t(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).removeClass("ui-datepicker-next-hover")}).delegate(i,"mouseover",function(){t.datepicker._isDisabledDatepicker(a.inline?e.parent()[0]:a.input[0])||(t(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),t(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).addClass("ui-datepicker-next-hover"))})}function n(e,i){t.extend(e,i);for(var s in i)null==i[s]&&(e[s]=i[s]);return e}t.extend(t.ui,{datepicker:{version:"1.10.3"}});var a,r="datepicker";t.extend(i.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(t){return n(this._defaults,t||{}),this},_attachDatepicker:function(e,i){var s,n,a;s=e.nodeName.toLowerCase(),n="div"===s||"span"===s,e.id||(this.uuid+=1,e.id="dp"+this.uuid),a=this._newInst(t(e),n),a.settings=t.extend({},i||{}),"input"===s?this._connectDatepicker(e,a):n&&this._inlineDatepicker(e,a)},_newInst:function(e,i){var n=e[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1");return{id:n,input:e,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:i,dpDiv:i?s(t("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(e,i){var s=t(e);i.append=t([]),i.trigger=t([]),s.hasClass(this.markerClassName)||(this._attachments(s,i),s.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp),this._autoSize(i),t.data(e,r,i),i.settings.disabled&&this._disableDatepicker(e))},_attachments:function(e,i){var s,n,a,r=this._get(i,"appendText"),o=this._get(i,"isRTL");i.append&&i.append.remove(),r&&(i.append=t("<span class='"+this._appendClass+"'>"+r+"</span>"),e[o?"before":"after"](i.append)),e.unbind("focus",this._showDatepicker),i.trigger&&i.trigger.remove(),s=this._get(i,"showOn"),("focus"===s||"both"===s)&&e.focus(this._showDatepicker),("button"===s||"both"===s)&&(n=this._get(i,"buttonText"),a=this._get(i,"buttonImage"),i.trigger=t(this._get(i,"buttonImageOnly")?t("<img/>").addClass(this._triggerClass).attr({src:a,alt:n,title:n}):t("<button type='button'></button>").addClass(this._triggerClass).html(a?t("<img/>").attr({src:a,alt:n,title:n}):n)),e[o?"before":"after"](i.trigger),i.trigger.click(function(){return t.datepicker._datepickerShowing&&t.datepicker._lastInput===e[0]?t.datepicker._hideDatepicker():t.datepicker._datepickerShowing&&t.datepicker._lastInput!==e[0]?(t.datepicker._hideDatepicker(),t.datepicker._showDatepicker(e[0])):t.datepicker._showDatepicker(e[0]),!1}))},_autoSize:function(t){if(this._get(t,"autoSize")&&!t.inline){var e,i,s,n,a=new Date(2009,11,20),r=this._get(t,"dateFormat");r.match(/[DM]/)&&(e=function(t){for(i=0,s=0,n=0;t.length>n;n++)t[n].length>i&&(i=t[n].length,s=n);return s},a.setMonth(e(this._get(t,r.match(/MM/)?"monthNames":"monthNamesShort"))),a.setDate(e(this._get(t,r.match(/DD/)?"dayNames":"dayNamesShort"))+20-a.getDay())),t.input.attr("size",this._formatDate(t,a).length)}},_inlineDatepicker:function(e,i){var s=t(e);s.hasClass(this.markerClassName)||(s.addClass(this.markerClassName).append(i.dpDiv),t.data(e,r,i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(e),i.dpDiv.css("display","block"))},_dialogDatepicker:function(e,i,s,a,o){var h,l,c,u,d,p=this._dialogInst;return p||(this.uuid+=1,h="dp"+this.uuid,this._dialogInput=t("<input type='text' id='"+h+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.keydown(this._doKeyDown),t("body").append(this._dialogInput),p=this._dialogInst=this._newInst(this._dialogInput,!1),p.settings={},t.data(this._dialogInput[0],r,p)),n(p.settings,a||{}),i=i&&i.constructor===Date?this._formatDate(p,i):i,this._dialogInput.val(i),this._pos=o?o.length?o:[o.pageX,o.pageY]:null,this._pos||(l=document.documentElement.clientWidth,c=document.documentElement.clientHeight,u=document.documentElement.scrollLeft||document.body.scrollLeft,d=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[l/2-100+u,c/2-150+d]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),p.settings.onSelect=s,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),t.blockUI&&t.blockUI(this.dpDiv),t.data(this._dialogInput[0],r,p),this},_destroyDatepicker:function(e){var i,s=t(e),n=t.data(e,r);s.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),t.removeData(e,r),"input"===i?(n.append.remove(),n.trigger.remove(),s.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):("div"===i||"span"===i)&&s.removeClass(this.markerClassName).empty())},_enableDatepicker:function(e){var i,s,n=t(e),a=t.data(e,r);n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!1,a.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().removeClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}))},_disableDatepicker:function(e){var i,s,n=t(e),a=t.data(e,r);n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!0,a.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().addClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}),this._disabledInputs[this._disabledInputs.length]=e)},_isDisabledDatepicker:function(t){if(!t)return!1;for(var e=0;this._disabledInputs.length>e;e++)if(this._disabledInputs[e]===t)return!0;return!1},_getInst:function(e){try{return t.data(e,r)}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(i,s,a){var r,o,h,l,c=this._getInst(i);return 2===arguments.length&&"string"==typeof s?"defaults"===s?t.extend({},t.datepicker._defaults):c?"all"===s?t.extend({},c.settings):this._get(c,s):null:(r=s||{},"string"==typeof s&&(r={},r[s]=a),c&&(this._curInst===c&&this._hideDatepicker(),o=this._getDateDatepicker(i,!0),h=this._getMinMaxDate(c,"min"),l=this._getMinMaxDate(c,"max"),n(c.settings,r),null!==h&&r.dateFormat!==e&&r.minDate===e&&(c.settings.minDate=this._formatDate(c,h)),null!==l&&r.dateFormat!==e&&r.maxDate===e&&(c.settings.maxDate=this._formatDate(c,l)),"disabled"in r&&(r.disabled?this._disableDatepicker(i):this._enableDatepicker(i)),this._attachments(t(i),c),this._autoSize(c),this._setDate(c,o),this._updateAlternate(c),this._updateDatepicker(c)),e)},_changeDatepicker:function(t,e,i){this._optionDatepicker(t,e,i)},_refreshDatepicker:function(t){var e=this._getInst(t);e&&this._updateDatepicker(e)},_setDateDatepicker:function(t,e){var i=this._getInst(t);i&&(this._setDate(i,e),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(t,e){var i=this._getInst(t);return i&&!i.inline&&this._setDateFromField(i,e),i?this._getDate(i):null},_doKeyDown:function(e){var i,s,n,a=t.datepicker._getInst(e.target),r=!0,o=a.dpDiv.is(".ui-datepicker-rtl");if(a._keyEvent=!0,t.datepicker._datepickerShowing)switch(e.keyCode){case 9:t.datepicker._hideDatepicker(),r=!1;break;case 13:return n=t("td."+t.datepicker._dayOverClass+":not(."+t.datepicker._currentClass+")",a.dpDiv),n[0]&&t.datepicker._selectDay(e.target,a.selectedMonth,a.selectedYear,n[0]),i=t.datepicker._get(a,"onSelect"),i?(s=t.datepicker._formatDate(a),i.apply(a.input?a.input[0]:null,[s,a])):t.datepicker._hideDatepicker(),!1;case 27:t.datepicker._hideDatepicker();break;case 33:t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(a,"stepBigMonths"):-t.datepicker._get(a,"stepMonths"),"M");break;case 34:t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(a,"stepBigMonths"):+t.datepicker._get(a,"stepMonths"),"M");break;case 35:(e.ctrlKey||e.metaKey)&&t.datepicker._clearDate(e.target),r=e.ctrlKey||e.metaKey;break;case 36:(e.ctrlKey||e.metaKey)&&t.datepicker._gotoToday(e.target),r=e.ctrlKey||e.metaKey;break;case 37:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,o?1:-1,"D"),r=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(a,"stepBigMonths"):-t.datepicker._get(a,"stepMonths"),"M");break;case 38:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,-7,"D"),r=e.ctrlKey||e.metaKey;break;case 39:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,o?-1:1,"D"),r=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(a,"stepBigMonths"):+t.datepicker._get(a,"stepMonths"),"M");break;case 40:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,7,"D"),r=e.ctrlKey||e.metaKey;break;default:r=!1}else 36===e.keyCode&&e.ctrlKey?t.datepicker._showDatepicker(this):r=!1;r&&(e.preventDefault(),e.stopPropagation())},_doKeyPress:function(i){var s,n,a=t.datepicker._getInst(i.target);return t.datepicker._get(a,"constrainInput")?(s=t.datepicker._possibleChars(t.datepicker._get(a,"dateFormat")),n=String.fromCharCode(null==i.charCode?i.keyCode:i.charCode),i.ctrlKey||i.metaKey||" ">n||!s||s.indexOf(n)>-1):e},_doKeyUp:function(e){var i,s=t.datepicker._getInst(e.target);if(s.input.val()!==s.lastVal)try{i=t.datepicker.parseDate(t.datepicker._get(s,"dateFormat"),s.input?s.input.val():null,t.datepicker._getFormatConfig(s)),i&&(t.datepicker._setDateFromField(s),t.datepicker._updateAlternate(s),t.datepicker._updateDatepicker(s))}catch(n){}return!0},_showDatepicker:function(e){if(e=e.target||e,"input"!==e.nodeName.toLowerCase()&&(e=t("input",e.parentNode)[0]),!t.datepicker._isDisabledDatepicker(e)&&t.datepicker._lastInput!==e){var i,s,a,r,o,h,l;i=t.datepicker._getInst(e),t.datepicker._curInst&&t.datepicker._curInst!==i&&(t.datepicker._curInst.dpDiv.stop(!0,!0),i&&t.datepicker._datepickerShowing&&t.datepicker._hideDatepicker(t.datepicker._curInst.input[0])),s=t.datepicker._get(i,"beforeShow"),a=s?s.apply(e,[e,i]):{},a!==!1&&(n(i.settings,a),i.lastVal=null,t.datepicker._lastInput=e,t.datepicker._setDateFromField(i),t.datepicker._inDialog&&(e.value=""),t.datepicker._pos||(t.datepicker._pos=t.datepicker._findPos(e),t.datepicker._pos[1]+=e.offsetHeight),r=!1,t(e).parents().each(function(){return r|="fixed"===t(this).css("position"),!r}),o={left:t.datepicker._pos[0],top:t.datepicker._pos[1]},t.datepicker._pos=null,i.dpDiv.empty(),i.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),t.datepicker._updateDatepicker(i),o=t.datepicker._checkOffset(i,o,r),i.dpDiv.css({position:t.datepicker._inDialog&&t.blockUI?"static":r?"fixed":"absolute",display:"none",left:o.left+"px",top:o.top+"px"}),i.inline||(h=t.datepicker._get(i,"showAnim"),l=t.datepicker._get(i,"duration"),i.dpDiv.zIndex(t(e).zIndex()+1),t.datepicker._datepickerShowing=!0,t.effects&&t.effects.effect[h]?i.dpDiv.show(h,t.datepicker._get(i,"showOptions"),l):i.dpDiv[h||"show"](h?l:null),t.datepicker._shouldFocusInput(i)&&i.input.focus(),t.datepicker._curInst=i))}},_updateDatepicker:function(e){this.maxRows=4,a=e,e.dpDiv.empty().append(this._generateHTML(e)),this._attachHandlers(e),e.dpDiv.find("."+this._dayOverClass+" a").mouseover();var i,s=this._getNumberOfMonths(e),n=s[1],r=17;e.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),n>1&&e.dpDiv.addClass("ui-datepicker-multi-"+n).css("width",r*n+"em"),e.dpDiv[(1!==s[0]||1!==s[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),e.dpDiv[(this._get(e,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),e===t.datepicker._curInst&&t.datepicker._datepickerShowing&&t.datepicker._shouldFocusInput(e)&&e.input.focus(),e.yearshtml&&(i=e.yearshtml,setTimeout(function(){i===e.yearshtml&&e.yearshtml&&e.dpDiv.find("select.ui-datepicker-year:first").replaceWith(e.yearshtml),i=e.yearshtml=null},0))},_shouldFocusInput:function(t){return t.input&&t.input.is(":visible")&&!t.input.is(":disabled")&&!t.input.is(":focus")},_checkOffset:function(e,i,s){var n=e.dpDiv.outerWidth(),a=e.dpDiv.outerHeight(),r=e.input?e.input.outerWidth():0,o=e.input?e.input.outerHeight():0,h=document.documentElement.clientWidth+(s?0:t(document).scrollLeft()),l=document.documentElement.clientHeight+(s?0:t(document).scrollTop());return i.left-=this._get(e,"isRTL")?n-r:0,i.left-=s&&i.left===e.input.offset().left?t(document).scrollLeft():0,i.top-=s&&i.top===e.input.offset().top+o?t(document).scrollTop():0,i.left-=Math.min(i.left,i.left+n>h&&h>n?Math.abs(i.left+n-h):0),i.top-=Math.min(i.top,i.top+a>l&&l>a?Math.abs(a+o):0),i},_findPos:function(e){for(var i,s=this._getInst(e),n=this._get(s,"isRTL");e&&("hidden"===e.type||1!==e.nodeType||t.expr.filters.hidden(e));)e=e[n?"previousSibling":"nextSibling"];return i=t(e).offset(),[i.left,i.top]},_hideDatepicker:function(e){var i,s,n,a,o=this._curInst;!o||e&&o!==t.data(e,r)||this._datepickerShowing&&(i=this._get(o,"showAnim"),s=this._get(o,"duration"),n=function(){t.datepicker._tidyDialog(o)},t.effects&&(t.effects.effect[i]||t.effects[i])?o.dpDiv.hide(i,t.datepicker._get(o,"showOptions"),s,n):o.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?s:null,n),i||n(),this._datepickerShowing=!1,a=this._get(o,"onClose"),a&&a.apply(o.input?o.input[0]:null,[o.input?o.input.val():"",o]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),t.blockUI&&(t.unblockUI(),t("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(t){t.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(e){if(t.datepicker._curInst){var i=t(e.target),s=t.datepicker._getInst(i[0]);(i[0].id!==t.datepicker._mainDivId&&0===i.parents("#"+t.datepicker._mainDivId).length&&!i.hasClass(t.datepicker.markerClassName)&&!i.closest("."+t.datepicker._triggerClass).length&&t.datepicker._datepickerShowing&&(!t.datepicker._inDialog||!t.blockUI)||i.hasClass(t.datepicker.markerClassName)&&t.datepicker._curInst!==s)&&t.datepicker._hideDatepicker()}},_adjustDate:function(e,i,s){var n=t(e),a=this._getInst(n[0]);this._isDisabledDatepicker(n[0])||(this._adjustInstDate(a,i+("M"===s?this._get(a,"showCurrentAtPos"):0),s),this._updateDatepicker(a))},_gotoToday:function(e){var i,s=t(e),n=this._getInst(s[0]);this._get(n,"gotoCurrent")&&n.currentDay?(n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear):(i=new Date,n.selectedDay=i.getDate(),n.drawMonth=n.selectedMonth=i.getMonth(),n.drawYear=n.selectedYear=i.getFullYear()),this._notifyChange(n),this._adjustDate(s)},_selectMonthYear:function(e,i,s){var n=t(e),a=this._getInst(n[0]);a["selected"+("M"===s?"Month":"Year")]=a["draw"+("M"===s?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(a),this._adjustDate(n)},_selectDay:function(e,i,s,n){var a,r=t(e);t(n).hasClass(this._unselectableClass)||this._isDisabledDatepicker(r[0])||(a=this._getInst(r[0]),a.selectedDay=a.currentDay=t("a",n).html(),a.selectedMonth=a.currentMonth=i,a.selectedYear=a.currentYear=s,this._selectDate(e,this._formatDate(a,a.currentDay,a.currentMonth,a.currentYear)))},_clearDate:function(e){var i=t(e);this._selectDate(i,"")},_selectDate:function(e,i){var s,n=t(e),a=this._getInst(n[0]);i=null!=i?i:this._formatDate(a),a.input&&a.input.val(i),this._updateAlternate(a),s=this._get(a,"onSelect"),s?s.apply(a.input?a.input[0]:null,[i,a]):a.input&&a.input.trigger("change"),a.inline?this._updateDatepicker(a):(this._hideDatepicker(),this._lastInput=a.input[0],"object"!=typeof a.input[0]&&a.input.focus(),this._lastInput=null)},_updateAlternate:function(e){var i,s,n,a=this._get(e,"altField");a&&(i=this._get(e,"altFormat")||this._get(e,"dateFormat"),s=this._getDate(e),n=this.formatDate(i,s,this._getFormatConfig(e)),t(a).each(function(){t(this).val(n)}))},noWeekends:function(t){var e=t.getDay();return[e>0&&6>e,""]},iso8601Week:function(t){var e,i=new Date(t.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),e=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((e-i)/864e5)/7)+1},parseDate:function(i,s,n){if(null==i||null==s)throw"Invalid arguments";if(s="object"==typeof s?""+s:s+"",""===s)return null;var a,r,o,h,l=0,c=(n?n.shortYearCutoff:null)||this._defaults.shortYearCutoff,u="string"!=typeof c?c:(new Date).getFullYear()%100+parseInt(c,10),d=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,p=(n?n.dayNames:null)||this._defaults.dayNames,f=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,m=(n?n.monthNames:null)||this._defaults.monthNames,g=-1,v=-1,_=-1,b=-1,y=!1,x=function(t){var e=i.length>a+1&&i.charAt(a+1)===t;return e&&a++,e},k=function(t){var e=x(t),i="@"===t?14:"!"===t?20:"y"===t&&e?4:"o"===t?3:2,n=RegExp("^\\d{1,"+i+"}"),a=s.substring(l).match(n);if(!a)throw"Missing number at position "+l;return l+=a[0].length,parseInt(a[0],10)},w=function(i,n,a){var r=-1,o=t.map(x(i)?a:n,function(t,e){return[[e,t]]}).sort(function(t,e){return-(t[1].length-e[1].length)});if(t.each(o,function(t,i){var n=i[1];return s.substr(l,n.length).toLowerCase()===n.toLowerCase()?(r=i[0],l+=n.length,!1):e}),-1!==r)return r+1;throw"Unknown name at position "+l},D=function(){if(s.charAt(l)!==i.charAt(a))throw"Unexpected literal at position "+l;l++};for(a=0;i.length>a;a++)if(y)"'"!==i.charAt(a)||x("'")?D():y=!1;else switch(i.charAt(a)){case"d":_=k("d");break;case"D":w("D",d,p);break;case"o":b=k("o");break;case"m":v=k("m");break;case"M":v=w("M",f,m);break;case"y":g=k("y");break;case"@":h=new Date(k("@")),g=h.getFullYear(),v=h.getMonth()+1,_=h.getDate();break;case"!":h=new Date((k("!")-this._ticksTo1970)/1e4),g=h.getFullYear(),v=h.getMonth()+1,_=h.getDate();break;case"'":x("'")?D():y=!0;break;default:D()}if(s.length>l&&(o=s.substr(l),!/^\s+/.test(o)))throw"Extra/unparsed characters found in date: "+o;if(-1===g?g=(new Date).getFullYear():100>g&&(g+=(new Date).getFullYear()-(new Date).getFullYear()%100+(u>=g?0:-100)),b>-1)for(v=1,_=b;;){if(r=this._getDaysInMonth(g,v-1),r>=_)break;v++,_-=r}if(h=this._daylightSavingAdjust(new Date(g,v-1,_)),h.getFullYear()!==g||h.getMonth()+1!==v||h.getDate()!==_)throw"Invalid date";return h},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(t,e,i){if(!e)return"";var s,n=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,a=(i?i.dayNames:null)||this._defaults.dayNames,r=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,o=(i?i.monthNames:null)||this._defaults.monthNames,h=function(e){var i=t.length>s+1&&t.charAt(s+1)===e;return i&&s++,i},l=function(t,e,i){var s=""+e;if(h(t))for(;i>s.length;)s="0"+s;return s},c=function(t,e,i,s){return h(t)?s[e]:i[e]},u="",d=!1;if(e)for(s=0;t.length>s;s++)if(d)"'"!==t.charAt(s)||h("'")?u+=t.charAt(s):d=!1;else switch(t.charAt(s)){case"d":u+=l("d",e.getDate(),2);break;case"D":u+=c("D",e.getDay(),n,a);break;case"o":u+=l("o",Math.round((new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()-new Date(e.getFullYear(),0,0).getTime())/864e5),3);break;case"m":u+=l("m",e.getMonth()+1,2);break;case"M":u+=c("M",e.getMonth(),r,o);break;case"y":u+=h("y")?e.getFullYear():(10>e.getYear()%100?"0":"")+e.getYear()%100;break;case"@":u+=e.getTime();break;case"!":u+=1e4*e.getTime()+this._ticksTo1970;break;case"'":h("'")?u+="'":d=!0;break;default:u+=t.charAt(s)}return u},_possibleChars:function(t){var e,i="",s=!1,n=function(i){var s=t.length>e+1&&t.charAt(e+1)===i;return s&&e++,s};for(e=0;t.length>e;e++)if(s)"'"!==t.charAt(e)||n("'")?i+=t.charAt(e):s=!1;else switch(t.charAt(e)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":n("'")?i+="'":s=!0;break;default:i+=t.charAt(e)}return i},_get:function(t,i){return t.settings[i]!==e?t.settings[i]:this._defaults[i]},_setDateFromField:function(t,e){if(t.input.val()!==t.lastVal){var i=this._get(t,"dateFormat"),s=t.lastVal=t.input?t.input.val():null,n=this._getDefaultDate(t),a=n,r=this._getFormatConfig(t);try{a=this.parseDate(i,s,r)||n}catch(o){s=e?"":s}t.selectedDay=a.getDate(),t.drawMonth=t.selectedMonth=a.getMonth(),t.drawYear=t.selectedYear=a.getFullYear(),t.currentDay=s?a.getDate():0,t.currentMonth=s?a.getMonth():0,t.currentYear=s?a.getFullYear():0,this._adjustInstDate(t)}},_getDefaultDate:function(t){return this._restrictMinMax(t,this._determineDate(t,this._get(t,"defaultDate"),new Date))},_determineDate:function(e,i,s){var n=function(t){var e=new Date;return e.setDate(e.getDate()+t),e},a=function(i){try{return t.datepicker.parseDate(t.datepicker._get(e,"dateFormat"),i,t.datepicker._getFormatConfig(e))}catch(s){}for(var n=(i.toLowerCase().match(/^c/)?t.datepicker._getDate(e):null)||new Date,a=n.getFullYear(),r=n.getMonth(),o=n.getDate(),h=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,l=h.exec(i);l;){switch(l[2]||"d"){case"d":case"D":o+=parseInt(l[1],10);break;case"w":case"W":o+=7*parseInt(l[1],10);break;case"m":case"M":r+=parseInt(l[1],10),o=Math.min(o,t.datepicker._getDaysInMonth(a,r));break;case"y":case"Y":a+=parseInt(l[1],10),o=Math.min(o,t.datepicker._getDaysInMonth(a,r))}l=h.exec(i)}return new Date(a,r,o)},r=null==i||""===i?s:"string"==typeof i?a(i):"number"==typeof i?isNaN(i)?s:n(i):new Date(i.getTime());return r=r&&"Invalid Date"==""+r?s:r,r&&(r.setHours(0),r.setMinutes(0),r.setSeconds(0),r.setMilliseconds(0)),this._daylightSavingAdjust(r)},_daylightSavingAdjust:function(t){return t?(t.setHours(t.getHours()>12?t.getHours()+2:0),t):null},_setDate:function(t,e,i){var s=!e,n=t.selectedMonth,a=t.selectedYear,r=this._restrictMinMax(t,this._determineDate(t,e,new Date));t.selectedDay=t.currentDay=r.getDate(),t.drawMonth=t.selectedMonth=t.currentMonth=r.getMonth(),t.drawYear=t.selectedYear=t.currentYear=r.getFullYear(),n===t.selectedMonth&&a===t.selectedYear||i||this._notifyChange(t),this._adjustInstDate(t),t.input&&t.input.val(s?"":this._formatDate(t))},_getDate:function(t){var e=!t.currentYear||t.input&&""===t.input.val()?null:this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return e},_attachHandlers:function(e){var i=this._get(e,"stepMonths"),s="#"+e.id.replace(/\\\\/g,"\\");e.dpDiv.find("[data-handler]").map(function(){var e={prev:function(){t.datepicker._adjustDate(s,-i,"M")},next:function(){t.datepicker._adjustDate(s,+i,"M")},hide:function(){t.datepicker._hideDatepicker()},today:function(){t.datepicker._gotoToday(s)},selectDay:function(){return t.datepicker._selectDay(s,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return t.datepicker._selectMonthYear(s,this,"M"),!1},selectYear:function(){return t.datepicker._selectMonthYear(s,this,"Y"),!1}};t(this).bind(this.getAttribute("data-event"),e[this.getAttribute("data-handler")])})},_generateHTML:function(t){var e,i,s,n,a,r,o,h,l,c,u,d,p,f,m,g,v,_,b,y,x,k,w,D,T,C,M,S,N,I,P,A,z,H,E,F,O,W,j,R=new Date,L=this._daylightSavingAdjust(new Date(R.getFullYear(),R.getMonth(),R.getDate())),Y=this._get(t,"isRTL"),B=this._get(t,"showButtonPanel"),J=this._get(t,"hideIfNoPrevNext"),K=this._get(t,"navigationAsDateFormat"),Q=this._getNumberOfMonths(t),V=this._get(t,"showCurrentAtPos"),U=this._get(t,"stepMonths"),q=1!==Q[0]||1!==Q[1],X=this._daylightSavingAdjust(t.currentDay?new Date(t.currentYear,t.currentMonth,t.currentDay):new Date(9999,9,9)),G=this._getMinMaxDate(t,"min"),$=this._getMinMaxDate(t,"max"),Z=t.drawMonth-V,te=t.drawYear;if(0>Z&&(Z+=12,te--),$)for(e=this._daylightSavingAdjust(new Date($.getFullYear(),$.getMonth()-Q[0]*Q[1]+1,$.getDate())),e=G&&G>e?G:e;this._daylightSavingAdjust(new Date(te,Z,1))>e;)Z--,0>Z&&(Z=11,te--);for(t.drawMonth=Z,t.drawYear=te,i=this._get(t,"prevText"),i=K?this.formatDate(i,this._daylightSavingAdjust(new Date(te,Z-U,1)),this._getFormatConfig(t)):i,s=this._canAdjustMonth(t,-1,te,Z)?"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>":J?"":"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>",n=this._get(t,"nextText"),n=K?this.formatDate(n,this._daylightSavingAdjust(new Date(te,Z+U,1)),this._getFormatConfig(t)):n,a=this._canAdjustMonth(t,1,te,Z)?"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>":J?"":"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>",r=this._get(t,"currentText"),o=this._get(t,"gotoCurrent")&&t.currentDay?X:L,r=K?this.formatDate(r,o,this._getFormatConfig(t)):r,h=t.inline?"":"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>"+this._get(t,"closeText")+"</button>",l=B?"<div class='ui-datepicker-buttonpane ui-widget-content'>"+(Y?h:"")+(this._isInRange(t,o)?"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>"+r+"</button>":"")+(Y?"":h)+"</div>":"",c=parseInt(this._get(t,"firstDay"),10),c=isNaN(c)?0:c,u=this._get(t,"showWeek"),d=this._get(t,"dayNames"),p=this._get(t,"dayNamesMin"),f=this._get(t,"monthNames"),m=this._get(t,"monthNamesShort"),g=this._get(t,"beforeShowDay"),v=this._get(t,"showOtherMonths"),_=this._get(t,"selectOtherMonths"),b=this._getDefaultDate(t),y="",k=0;Q[0]>k;k++){for(w="",this.maxRows=4,D=0;Q[1]>D;D++){if(T=this._daylightSavingAdjust(new Date(te,Z,t.selectedDay)),C=" ui-corner-all",M="",q){if(M+="<div class='ui-datepicker-group",Q[1]>1)switch(D){case 0:M+=" ui-datepicker-group-first",C=" ui-corner-"+(Y?"right":"left");break;case Q[1]-1:M+=" ui-datepicker-group-last",C=" ui-corner-"+(Y?"left":"right");break;default:M+=" ui-datepicker-group-middle",C=""}M+="'>"}for(M+="<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix"+C+"'>"+(/all|left/.test(C)&&0===k?Y?a:s:"")+(/all|right/.test(C)&&0===k?Y?s:a:"")+this._generateMonthYearHeader(t,Z,te,G,$,k>0||D>0,f,m)+"</div><table class='ui-datepicker-calendar'><thead>"+"<tr>",S=u?"<th class='ui-datepicker-week-col'>"+this._get(t,"weekHeader")+"</th>":"",x=0;7>x;x++)N=(x+c)%7,S+="<th"+((x+c+6)%7>=5?" class='ui-datepicker-week-end'":"")+">"+"<span title='"+d[N]+"'>"+p[N]+"</span></th>";for(M+=S+"</tr></thead><tbody>",I=this._getDaysInMonth(te,Z),te===t.selectedYear&&Z===t.selectedMonth&&(t.selectedDay=Math.min(t.selectedDay,I)),P=(this._getFirstDayOfMonth(te,Z)-c+7)%7,A=Math.ceil((P+I)/7),z=q?this.maxRows>A?this.maxRows:A:A,this.maxRows=z,H=this._daylightSavingAdjust(new Date(te,Z,1-P)),E=0;z>E;E++){for(M+="<tr>",F=u?"<td class='ui-datepicker-week-col'>"+this._get(t,"calculateWeek")(H)+"</td>":"",x=0;7>x;x++)O=g?g.apply(t.input?t.input[0]:null,[H]):[!0,""],W=H.getMonth()!==Z,j=W&&!_||!O[0]||G&&G>H||$&&H>$,F+="<td class='"+((x+c+6)%7>=5?" ui-datepicker-week-end":"")+(W?" ui-datepicker-other-month":"")+(H.getTime()===T.getTime()&&Z===t.selectedMonth&&t._keyEvent||b.getTime()===H.getTime()&&b.getTime()===T.getTime()?" "+this._dayOverClass:"")+(j?" "+this._unselectableClass+" ui-state-disabled":"")+(W&&!v?"":" "+O[1]+(H.getTime()===X.getTime()?" "+this._currentClass:"")+(H.getTime()===L.getTime()?" ui-datepicker-today":""))+"'"+(W&&!v||!O[2]?"":" title='"+O[2].replace(/'/g,"&#39;")+"'")+(j?"":" data-handler='selectDay' data-event='click' data-month='"+H.getMonth()+"' data-year='"+H.getFullYear()+"'")+">"+(W&&!v?"&#xa0;":j?"<span class='ui-state-default'>"+H.getDate()+"</span>":"<a class='ui-state-default"+(H.getTime()===L.getTime()?" ui-state-highlight":"")+(H.getTime()===X.getTime()?" ui-state-active":"")+(W?" ui-priority-secondary":"")+"' href='#'>"+H.getDate()+"</a>")+"</td>",H.setDate(H.getDate()+1),H=this._daylightSavingAdjust(H);M+=F+"</tr>"}Z++,Z>11&&(Z=0,te++),M+="</tbody></table>"+(q?"</div>"+(Q[0]>0&&D===Q[1]-1?"<div class='ui-datepicker-row-break'></div>":""):""),w+=M}y+=w}return y+=l,t._keyEvent=!1,y},_generateMonthYearHeader:function(t,e,i,s,n,a,r,o){var h,l,c,u,d,p,f,m,g=this._get(t,"changeMonth"),v=this._get(t,"changeYear"),_=this._get(t,"showMonthAfterYear"),b="<div class='ui-datepicker-title'>",y="";if(a||!g)y+="<span class='ui-datepicker-month'>"+r[e]+"</span>";else{for(h=s&&s.getFullYear()===i,l=n&&n.getFullYear()===i,y+="<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>",c=0;12>c;c++)(!h||c>=s.getMonth())&&(!l||n.getMonth()>=c)&&(y+="<option value='"+c+"'"+(c===e?" selected='selected'":"")+">"+o[c]+"</option>");y+="</select>"}if(_||(b+=y+(!a&&g&&v?"":"&#xa0;")),!t.yearshtml)if(t.yearshtml="",a||!v)b+="<span class='ui-datepicker-year'>"+i+"</span>";else{for(u=this._get(t,"yearRange").split(":"),d=(new Date).getFullYear(),p=function(t){var e=t.match(/c[+\-].*/)?i+parseInt(t.substring(1),10):t.match(/[+\-].*/)?d+parseInt(t,10):parseInt(t,10);
-return isNaN(e)?d:e},f=p(u[0]),m=Math.max(f,p(u[1]||"")),f=s?Math.max(f,s.getFullYear()):f,m=n?Math.min(m,n.getFullYear()):m,t.yearshtml+="<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";m>=f;f++)t.yearshtml+="<option value='"+f+"'"+(f===i?" selected='selected'":"")+">"+f+"</option>";t.yearshtml+="</select>",b+=t.yearshtml,t.yearshtml=null}return b+=this._get(t,"yearSuffix"),_&&(b+=(!a&&g&&v?"":"&#xa0;")+y),b+="</div>"},_adjustInstDate:function(t,e,i){var s=t.drawYear+("Y"===i?e:0),n=t.drawMonth+("M"===i?e:0),a=Math.min(t.selectedDay,this._getDaysInMonth(s,n))+("D"===i?e:0),r=this._restrictMinMax(t,this._daylightSavingAdjust(new Date(s,n,a)));t.selectedDay=r.getDate(),t.drawMonth=t.selectedMonth=r.getMonth(),t.drawYear=t.selectedYear=r.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(t)},_restrictMinMax:function(t,e){var i=this._getMinMaxDate(t,"min"),s=this._getMinMaxDate(t,"max"),n=i&&i>e?i:e;return s&&n>s?s:n},_notifyChange:function(t){var e=this._get(t,"onChangeMonthYear");e&&e.apply(t.input?t.input[0]:null,[t.selectedYear,t.selectedMonth+1,t])},_getNumberOfMonths:function(t){var e=this._get(t,"numberOfMonths");return null==e?[1,1]:"number"==typeof e?[1,e]:e},_getMinMaxDate:function(t,e){return this._determineDate(t,this._get(t,e+"Date"),null)},_getDaysInMonth:function(t,e){return 32-this._daylightSavingAdjust(new Date(t,e,32)).getDate()},_getFirstDayOfMonth:function(t,e){return new Date(t,e,1).getDay()},_canAdjustMonth:function(t,e,i,s){var n=this._getNumberOfMonths(t),a=this._daylightSavingAdjust(new Date(i,s+(0>e?e:n[0]*n[1]),1));return 0>e&&a.setDate(this._getDaysInMonth(a.getFullYear(),a.getMonth())),this._isInRange(t,a)},_isInRange:function(t,e){var i,s,n=this._getMinMaxDate(t,"min"),a=this._getMinMaxDate(t,"max"),r=null,o=null,h=this._get(t,"yearRange");return h&&(i=h.split(":"),s=(new Date).getFullYear(),r=parseInt(i[0],10),o=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(r+=s),i[1].match(/[+\-].*/)&&(o+=s)),(!n||e.getTime()>=n.getTime())&&(!a||e.getTime()<=a.getTime())&&(!r||e.getFullYear()>=r)&&(!o||o>=e.getFullYear())},_getFormatConfig:function(t){var e=this._get(t,"shortYearCutoff");return e="string"!=typeof e?e:(new Date).getFullYear()%100+parseInt(e,10),{shortYearCutoff:e,dayNamesShort:this._get(t,"dayNamesShort"),dayNames:this._get(t,"dayNames"),monthNamesShort:this._get(t,"monthNamesShort"),monthNames:this._get(t,"monthNames")}},_formatDate:function(t,e,i,s){e||(t.currentDay=t.selectedDay,t.currentMonth=t.selectedMonth,t.currentYear=t.selectedYear);var n=e?"object"==typeof e?e:this._daylightSavingAdjust(new Date(s,i,e)):this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return this.formatDate(this._get(t,"dateFormat"),n,this._getFormatConfig(t))}}),t.fn.datepicker=function(e){if(!this.length)return this;t.datepicker.initialized||(t(document).mousedown(t.datepicker._checkExternalClick),t.datepicker.initialized=!0),0===t("#"+t.datepicker._mainDivId).length&&t("body").append(t.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof e||"isDisabled"!==e&&"getDate"!==e&&"widget"!==e?"option"===e&&2===arguments.length&&"string"==typeof arguments[1]?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof e?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this].concat(i)):t.datepicker._attachDatepicker(this,e)}):t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i))},t.datepicker=new i,t.datepicker.initialized=!1,t.datepicker.uuid=(new Date).getTime(),t.datepicker.version="1.10.3"})(jQuery);
\ No newline at end of file
+(function(e,t){function i(t,i){var s,a,o,r=t.nodeName.toLowerCase();return"area"===r?(s=t.parentNode,a=s.name,t.href&&a&&"map"===s.nodeName.toLowerCase()?(o=e("img[usemap=#"+a+"]")[0],!!o&&n(o)):!1):(/input|select|textarea|button|object/.test(r)?!t.disabled:"a"===r?t.href||i:i)&&n(t)}function n(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var s=0,a=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.3",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,n){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),n&&n.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var n,s,a=e(this[0]);a.length&&a[0]!==document;){if(n=a.css("position"),("absolute"===n||"relative"===n||"fixed"===n)&&(s=parseInt(a.css("zIndex"),10),!isNaN(s)&&0!==s))return s;a=a.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++s)})},removeUniqueId:function(){return this.each(function(){a.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,n){return!!e.data(t,n[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),s=isNaN(n);return(s||n>=0)&&i(t,!s)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(i,n){function s(t,i,n,s){return e.each(a,function(){i-=parseFloat(e.css(t,"padding"+this))||0,n&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var a="Width"===n?["Left","Right"]:["Top","Bottom"],o=n.toLowerCase(),r={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+n]=function(i){return i===t?r["inner"+n].call(this):this.each(function(){e(this).css(o,s(this,i)+"px")})},e.fn["outer"+n]=function(t,i){return"number"!=typeof t?r["outer"+n].call(this,t):this.each(function(){e(this).css(o,s(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,n){var s,a=e.ui[t].prototype;for(s in n)a.plugins[s]=a.plugins[s]||[],a.plugins[s].push([i,n[s]])},call:function(e,t,i){var n,s=e.plugins[t];if(s&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(n=0;s.length>n;n++)e.options[s[n][0]]&&s[n][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var n=i&&"left"===i?"scrollLeft":"scrollTop",s=!1;return t[n]>0?!0:(t[n]=1,s=t[n]>0,t[n]=0,s)}})})(jQuery);(function(t,e){var i=0,s=Array.prototype.slice,n=t.cleanData;t.cleanData=function(e){for(var i,s=0;null!=(i=e[s]);s++)try{t(i).triggerHandler("remove")}catch(o){}n(e)},t.widget=function(i,s,n){var o,a,r,h,l={},c=i.split(".")[0];i=i.split(".")[1],o=c+"-"+i,n||(n=s,s=t.Widget),t.expr[":"][o.toLowerCase()]=function(e){return!!t.data(e,o)},t[c]=t[c]||{},a=t[c][i],r=t[c][i]=function(t,i){return this._createWidget?(arguments.length&&this._createWidget(t,i),e):new r(t,i)},t.extend(r,a,{version:n.version,_proto:t.extend({},n),_childConstructors:[]}),h=new s,h.options=t.widget.extend({},h.options),t.each(n,function(i,n){return t.isFunction(n)?(l[i]=function(){var t=function(){return s.prototype[i].apply(this,arguments)},e=function(t){return s.prototype[i].apply(this,t)};return function(){var i,s=this._super,o=this._superApply;return this._super=t,this._superApply=e,i=n.apply(this,arguments),this._super=s,this._superApply=o,i}}(),e):(l[i]=n,e)}),r.prototype=t.widget.extend(h,{widgetEventPrefix:a?h.widgetEventPrefix:i},l,{constructor:r,namespace:c,widgetName:i,widgetFullName:o}),a?(t.each(a._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,r,i._proto)}),delete a._childConstructors):s._childConstructors.push(r),t.widget.bridge(i,r)},t.widget.extend=function(i){for(var n,o,a=s.call(arguments,1),r=0,h=a.length;h>r;r++)for(n in a[r])o=a[r][n],a[r].hasOwnProperty(n)&&o!==e&&(i[n]=t.isPlainObject(o)?t.isPlainObject(i[n])?t.widget.extend({},i[n],o):t.widget.extend({},o):o);return i},t.widget.bridge=function(i,n){var o=n.prototype.widgetFullName||i;t.fn[i]=function(a){var r="string"==typeof a,h=s.call(arguments,1),l=this;return a=!r&&h.length?t.widget.extend.apply(null,[a].concat(h)):a,r?this.each(function(){var s,n=t.data(this,o);return n?t.isFunction(n[a])&&"_"!==a.charAt(0)?(s=n[a].apply(n,h),s!==n&&s!==e?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):e):t.error("no such method '"+a+"' for "+i+" widget instance"):t.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+a+"'")}):this.each(function(){var e=t.data(this,o);e?e.option(a||{})._init():t.data(this,o,new n(a,this))}),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(e,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this.bindings=t(),this.hoverable=t(),this.focusable=t(),s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:t.noop,_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(t.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:t.noop,widget:function(){return this.element},option:function(i,s){var n,o,a,r=i;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof i)if(r={},n=i.split("."),i=n.shift(),n.length){for(o=r[i]=t.widget.extend({},this.options[i]),a=0;n.length-1>a;a++)o[n[a]]=o[n[a]]||{},o=o[n[a]];if(i=n.pop(),s===e)return o[i]===e?null:o[i];o[i]=s}else{if(s===e)return this.options[i]===e?null:this.options[i];r[i]=s}return this._setOptions(r),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return this.options[t]=e,"disabled"===t&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!e).attr("aria-disabled",e),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var o,a=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=o=t(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,o=this.widget()),t.each(n,function(n,r){function h(){return i||a.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof r?a[r]:r).apply(a,arguments):e}"string"!=typeof r&&(h.guid=r.guid=r.guid||h.guid||t.guid++);var l=n.match(/^(\w+)\s*(.*)$/),c=l[1]+a.eventNamespace,u=l[2];u?o.delegate(u,c,h):s.bind(c,h)})},_off:function(t,e){e=(e||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(e).undelegate(e)},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){t(e.currentTarget).addClass("ui-state-hover")},mouseleave:function(e){t(e.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){t(e.currentTarget).addClass("ui-state-focus")},focusout:function(e){t(e.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}})})(jQuery);(function(t){var e=!1;t(document).mouseup(function(){e=!1}),t.widget("ui.mouse",{version:"1.10.3",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.bind("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).bind("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&t(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!e){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?t(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===t.data(i.target,this.widgetName+".preventClickEvent")&&t.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return s._mouseMove(t)},this._mouseUpDelegate=function(t){return s._mouseUp(t)},t(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),e=!0,!0)):!0}},_mouseMove:function(e){return t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button?this._mouseUp(e):this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){return t(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),!1},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(t,e){function i(t,e,i){return[parseFloat(t[0])*(p.test(t[0])?e/100:1),parseFloat(t[1])*(p.test(t[1])?i/100:1)]}function s(e,i){return parseInt(t.css(e,i),10)||0}function n(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}t.ui=t.ui||{};var a,o=Math.max,r=Math.abs,l=Math.round,h=/left|center|right/,c=/top|center|bottom/,u=/[\+\-]\d+(\.[\d]+)?%?/,d=/^\w+/,p=/%$/,f=t.fn.position;t.position={scrollbarWidth:function(){if(a!==e)return a;var i,s,n=t("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=n.children()[0];return t("body").append(n),i=o.offsetWidth,n.css("overflow","scroll"),s=o.offsetWidth,i===s&&(s=n[0].clientWidth),n.remove(),a=i-s},getScrollInfo:function(e){var i=e.isWindow?"":e.element.css("overflow-x"),s=e.isWindow?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.width<e.element[0].scrollWidth,a="scroll"===s||"auto"===s&&e.height<e.element[0].scrollHeight;return{width:a?t.position.scrollbarWidth():0,height:n?t.position.scrollbarWidth():0}},getWithinInfo:function(e){var i=t(e||window),s=t.isWindow(i[0]);return{element:i,isWindow:s,offset:i.offset()||{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:s?i.width():i.outerWidth(),height:s?i.height():i.outerHeight()}}},t.fn.position=function(e){if(!e||!e.of)return f.apply(this,arguments);e=t.extend({},e);var a,p,g,m,v,_,b=t(e.of),y=t.position.getWithinInfo(e.within),k=t.position.getScrollInfo(y),w=(e.collision||"flip").split(" "),D={};return _=n(b),b[0].preventDefault&&(e.at="left top"),p=_.width,g=_.height,m=_.offset,v=t.extend({},m),t.each(["my","at"],function(){var t,i,s=(e[this]||"").split(" ");1===s.length&&(s=h.test(s[0])?s.concat(["center"]):c.test(s[0])?["center"].concat(s):["center","center"]),s[0]=h.test(s[0])?s[0]:"center",s[1]=c.test(s[1])?s[1]:"center",t=u.exec(s[0]),i=u.exec(s[1]),D[this]=[t?t[0]:0,i?i[0]:0],e[this]=[d.exec(s[0])[0],d.exec(s[1])[0]]}),1===w.length&&(w[1]=w[0]),"right"===e.at[0]?v.left+=p:"center"===e.at[0]&&(v.left+=p/2),"bottom"===e.at[1]?v.top+=g:"center"===e.at[1]&&(v.top+=g/2),a=i(D.at,p,g),v.left+=a[0],v.top+=a[1],this.each(function(){var n,h,c=t(this),u=c.outerWidth(),d=c.outerHeight(),f=s(this,"marginLeft"),_=s(this,"marginTop"),x=u+f+s(this,"marginRight")+k.width,C=d+_+s(this,"marginBottom")+k.height,M=t.extend({},v),T=i(D.my,c.outerWidth(),c.outerHeight());"right"===e.my[0]?M.left-=u:"center"===e.my[0]&&(M.left-=u/2),"bottom"===e.my[1]?M.top-=d:"center"===e.my[1]&&(M.top-=d/2),M.left+=T[0],M.top+=T[1],t.support.offsetFractions||(M.left=l(M.left),M.top=l(M.top)),n={marginLeft:f,marginTop:_},t.each(["left","top"],function(i,s){t.ui.position[w[i]]&&t.ui.position[w[i]][s](M,{targetWidth:p,targetHeight:g,elemWidth:u,elemHeight:d,collisionPosition:n,collisionWidth:x,collisionHeight:C,offset:[a[0]+T[0],a[1]+T[1]],my:e.my,at:e.at,within:y,elem:c})}),e.using&&(h=function(t){var i=m.left-M.left,s=i+p-u,n=m.top-M.top,a=n+g-d,l={target:{element:b,left:m.left,top:m.top,width:p,height:g},element:{element:c,left:M.left,top:M.top,width:u,height:d},horizontal:0>s?"left":i>0?"right":"center",vertical:0>a?"top":n>0?"bottom":"middle"};u>p&&p>r(i+s)&&(l.horizontal="center"),d>g&&g>r(n+a)&&(l.vertical="middle"),l.important=o(r(i),r(s))>o(r(n),r(a))?"horizontal":"vertical",e.using.call(this,t,l)}),c.offset(t.extend(M,{using:h}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,l=n-r,h=r+e.collisionWidth-a-n;e.collisionWidth>a?l>0&&0>=h?(i=t.left+l+e.collisionWidth-a-n,t.left+=l-i):t.left=h>0&&0>=l?n:l>h?n+a-e.collisionWidth:n:l>0?t.left+=l:h>0?t.left-=h:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,l=n-r,h=r+e.collisionHeight-a-n;e.collisionHeight>a?l>0&&0>=h?(i=t.top+l+e.collisionHeight-a-n,t.top+=l-i):t.top=h>0&&0>=l?n:l>h?n+a-e.collisionHeight:n:l>0?t.top+=l:h>0?t.top-=h:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,a=n.offset.left+n.scrollLeft,o=n.width,l=n.isWindow?n.scrollLeft:n.offset.left,h=t.left-e.collisionPosition.marginLeft,c=h-l,u=h+e.collisionWidth-o-l,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-o-a,(0>i||r(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-l,(s>0||u>r(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,a=n.offset.top+n.scrollTop,o=n.height,l=n.isWindow?n.scrollTop:n.offset.top,h=t.top-e.collisionPosition.marginTop,c=h-l,u=h+e.collisionHeight-o-l,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,g=-2*e.offset[1];0>c?(s=t.top+p+f+g+e.collisionHeight-o-a,t.top+p+f+g>c&&(0>s||r(c)>s)&&(t.top+=p+f+g)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+g-l,t.top+p+f+g>u&&(i>0||u>r(i))&&(t.top+=p+f+g))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}},function(){var e,i,s,n,a,o=document.getElementsByTagName("body")[0],r=document.createElement("div");e=document.createElement(o?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&t.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(a in s)e.style[a]=s[a];e.appendChild(r),i=o||document.documentElement,i.insertBefore(e,i.firstChild),r.style.cssText="position: absolute; left: 10.7432222px;",n=t(r).offset().left,t.support.offsetFractions=n>10&&11>n,e.innerHTML="",i.removeChild(e)}()})(jQuery);(function(t){t.widget("ui.draggable",t.ui.mouse,{version:"1.10.3",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"!==this.options.helper||/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(e){var i=this.options;return this.helper||i.disabled||t(e.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(e),this.handle?(t(i.iframeFix===!0?"iframe":i.iframeFix).each(function(){t("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(t(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(e){var i=this.options;return this.helper=this._createHelper(e),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),t.ui.ddmanager&&(t.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offsetParent=this.helper.offsetParent(),this.offsetParentCssPosition=this.offsetParent.css("position"),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.offset.scroll=!1,t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",e)===!1?(this._clear(),!1):(this._cacheHelperProportions(),t.ui.ddmanager&&!i.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this._mouseDrag(e,!0),t.ui.ddmanager&&t.ui.ddmanager.dragStart(this,e),!0)},_mouseDrag:function(e,i){if("fixed"===this.offsetParentCssPosition&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",e,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),!1},_mouseStop:function(e){var i=this,s=!1;return t.ui.ddmanager&&!this.options.dropBehaviour&&(s=t.ui.ddmanager.drop(this,e)),this.dropped&&(s=this.dropped,this.dropped=!1),"original"!==this.options.helper||t.contains(this.element[0].ownerDocument,this.element[0])?("invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||t.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?t(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",e)!==!1&&i._clear()}):this._trigger("stop",e)!==!1&&this._clear(),!1):!1},_mouseUp:function(e){return t("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),t.ui.ddmanager&&t.ui.ddmanager.dragStop(this,e),t.ui.mouse.prototype._mouseUp.call(this,e)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(e){return this.options.handle?!!t(e.target).closest(this.element.find(this.options.handle)).length:!0},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return s.parents("body").length||s.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s[0]===this.element[0]||/(fixed|absolute)/.test(s.css("position"))||s.css("position","absolute"),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.element.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;return n.containment?"window"===n.containment?(this.containment=[t(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,t(window).scrollLeft()+t(window).width()-this.helperProportions.width-this.margins.left,t(window).scrollTop()+(t(window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):"document"===n.containment?(this.containment=[0,0,t(document).width()-this.helperProportions.width-this.margins.left,(t(document).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):n.containment.constructor===Array?(this.containment=n.containment,undefined):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=t(n.containment),s=i[0],s&&(e="hidden"!==i.css("overflow"),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(e?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=i),undefined):(this.containment=null,undefined)},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent;return this.offset.scroll||(this.offset.scroll={top:n.scrollTop(),left:n.scrollLeft()}),{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top)*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)*s}},_generatePosition:function(e){var i,s,n,a,o=this.options,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,l=e.pageX,h=e.pageY;return this.offset.scroll||(this.offset.scroll={top:r.scrollTop(),left:r.scrollLeft()}),this.originalPosition&&(this.containment&&(this.relative_container?(s=this.relative_container.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.left<i[0]&&(l=i[0]+this.offset.click.left),e.pageY-this.offset.click.top<i[1]&&(h=i[1]+this.offset.click.top),e.pageX-this.offset.click.left>i[2]&&(l=i[2]+this.offset.click.left),e.pageY-this.offset.click.top>i[3]&&(h=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,h=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((l-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,l=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a)),{top:h-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top),left:l-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(e,i,s){return s=s||this._uiHash(),t.ui.plugin.call(this,e,[i,s]),"drag"===e&&(this.positionAbs=this._convertPositionTo("absolute")),t.Widget.prototype._trigger.call(this,e,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),t.ui.plugin.add("draggable","connectToSortable",{start:function(e,i){var s=t(this).data("ui-draggable"),n=s.options,a=t.extend({},i,{item:s.element});s.sortables=[],t(n.connectToSortable).each(function(){var i=t.data(this,"ui-sortable");i&&!i.options.disabled&&(s.sortables.push({instance:i,shouldRevert:i.options.revert}),i.refreshPositions(),i._trigger("activate",e,a))})},stop:function(e,i){var s=t(this).data("ui-draggable"),n=t.extend({},i,{item:s.element});t.each(s.sortables,function(){this.instance.isOver?(this.instance.isOver=0,s.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=this.shouldRevert),this.instance._mouseStop(e),this.instance.options.helper=this.instance.options._helper,"original"===s.options.helper&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",e,n))})},drag:function(e,i){var s=t(this).data("ui-draggable"),n=this;t.each(s.sortables,function(){var a=!1,o=this;this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(a=!0,t.each(s.sortables,function(){return this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this!==o&&this.instance._intersectsWith(this.instance.containerCache)&&t.contains(o.instance.element[0],this.instance.element[0])&&(a=!1),a})),a?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=t(n).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return i.helper[0]},e.target=this.instance.currentItem[0],this.instance._mouseCapture(e,!0),this.instance._mouseStart(e,!0,!0),this.instance.offset.click.top=s.offset.click.top,this.instance.offset.click.left=s.offset.click.left,this.instance.offset.parent.left-=s.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=s.offset.parent.top-this.instance.offset.parent.top,s._trigger("toSortable",e),s.dropped=this.instance.element,s.currentItem=s.element,this.instance.fromOutside=s),this.instance.currentItem&&this.instance._mouseDrag(e)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",e,this.instance._uiHash(this.instance)),this.instance._mouseStop(e,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),s._trigger("fromSortable",e),s.dropped=!1)})}}),t.ui.plugin.add("draggable","cursor",{start:function(){var e=t("body"),i=t(this).data("ui-draggable").options;e.css("cursor")&&(i._cursor=e.css("cursor")),e.css("cursor",i.cursor)},stop:function(){var e=t(this).data("ui-draggable").options;e._cursor&&t("body").css("cursor",e._cursor)}}),t.ui.plugin.add("draggable","opacity",{start:function(e,i){var s=t(i.helper),n=t(this).data("ui-draggable").options;s.css("opacity")&&(n._opacity=s.css("opacity")),s.css("opacity",n.opacity)},stop:function(e,i){var s=t(this).data("ui-draggable").options;s._opacity&&t(i.helper).css("opacity",s._opacity)}}),t.ui.plugin.add("draggable","scroll",{start:function(){var e=t(this).data("ui-draggable");e.scrollParent[0]!==document&&"HTML"!==e.scrollParent[0].tagName&&(e.overflowOffset=e.scrollParent.offset())},drag:function(e){var i=t(this).data("ui-draggable"),s=i.options,n=!1;i.scrollParent[0]!==document&&"HTML"!==i.scrollParent[0].tagName?(s.axis&&"x"===s.axis||(i.overflowOffset.top+i.scrollParent[0].offsetHeight-e.pageY<s.scrollSensitivity?i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop+s.scrollSpeed:e.pageY-i.overflowOffset.top<s.scrollSensitivity&&(i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop-s.scrollSpeed)),s.axis&&"y"===s.axis||(i.overflowOffset.left+i.scrollParent[0].offsetWidth-e.pageX<s.scrollSensitivity?i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft+s.scrollSpeed:e.pageX-i.overflowOffset.left<s.scrollSensitivity&&(i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft-s.scrollSpeed))):(s.axis&&"x"===s.axis||(e.pageY-t(document).scrollTop()<s.scrollSensitivity?n=t(document).scrollTop(t(document).scrollTop()-s.scrollSpeed):t(window).height()-(e.pageY-t(document).scrollTop())<s.scrollSensitivity&&(n=t(document).scrollTop(t(document).scrollTop()+s.scrollSpeed))),s.axis&&"y"===s.axis||(e.pageX-t(document).scrollLeft()<s.scrollSensitivity?n=t(document).scrollLeft(t(document).scrollLeft()-s.scrollSpeed):t(window).width()-(e.pageX-t(document).scrollLeft())<s.scrollSensitivity&&(n=t(document).scrollLeft(t(document).scrollLeft()+s.scrollSpeed)))),n!==!1&&t.ui.ddmanager&&!s.dropBehaviour&&t.ui.ddmanager.prepareOffsets(i,e)}}),t.ui.plugin.add("draggable","snap",{start:function(){var e=t(this).data("ui-draggable"),i=e.options;e.snapElements=[],t(i.snap.constructor!==String?i.snap.items||":data(ui-draggable)":i.snap).each(function(){var i=t(this),s=i.offset();this!==e.element[0]&&e.snapElements.push({item:this,width:i.outerWidth(),height:i.outerHeight(),top:s.top,left:s.left})})},drag:function(e,i){var s,n,a,o,r,l,h,c,u,d,p=t(this).data("ui-draggable"),g=p.options,f=g.snapTolerance,m=i.offset.left,_=m+p.helperProportions.width,v=i.offset.top,b=v+p.helperProportions.height;for(u=p.snapElements.length-1;u>=0;u--)r=p.snapElements[u].left,l=r+p.snapElements[u].width,h=p.snapElements[u].top,c=h+p.snapElements[u].height,r-f>_||m>l+f||h-f>b||v>c+f||!t.contains(p.snapElements[u].item.ownerDocument,p.snapElements[u].item)?(p.snapElements[u].snapping&&p.options.snap.release&&p.options.snap.release.call(p.element,e,t.extend(p._uiHash(),{snapItem:p.snapElements[u].item})),p.snapElements[u].snapping=!1):("inner"!==g.snapMode&&(s=f>=Math.abs(h-b),n=f>=Math.abs(c-v),a=f>=Math.abs(r-_),o=f>=Math.abs(l-m),s&&(i.position.top=p._convertPositionTo("relative",{top:h-p.helperProportions.height,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:c,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r-p.helperProportions.width}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:l}).left-p.margins.left)),d=s||n||a||o,"outer"!==g.snapMode&&(s=f>=Math.abs(h-v),n=f>=Math.abs(c-b),a=f>=Math.abs(r-m),o=f>=Math.abs(l-_),s&&(i.position.top=p._convertPositionTo("relative",{top:h,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:c-p.helperProportions.height,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:l-p.helperProportions.width}).left-p.margins.left)),!p.snapElements[u].snapping&&(s||n||a||o||d)&&p.options.snap.snap&&p.options.snap.snap.call(p.element,e,t.extend(p._uiHash(),{snapItem:p.snapElements[u].item})),p.snapElements[u].snapping=s||n||a||o||d)}}),t.ui.plugin.add("draggable","stack",{start:function(){var e,i=this.data("ui-draggable").options,s=t.makeArray(t(i.stack)).sort(function(e,i){return(parseInt(t(e).css("zIndex"),10)||0)-(parseInt(t(i).css("zIndex"),10)||0)});s.length&&(e=parseInt(t(s[0]).css("zIndex"),10)||0,t(s).each(function(i){t(this).css("zIndex",e+i)}),this.css("zIndex",e+s.length))}}),t.ui.plugin.add("draggable","zIndex",{start:function(e,i){var s=t(i.helper),n=t(this).data("ui-draggable").options;s.css("zIndex")&&(n._zIndex=s.css("zIndex")),s.css("zIndex",n.zIndex)},stop:function(e,i){var s=t(this).data("ui-draggable").options;s._zIndex&&t(i.helper).css("zIndex",s._zIndex)}})})(jQuery);(function(t){function e(t,e,i){return t>e&&e+i>t}t.widget("ui.droppable",{version:"1.10.3",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var e=this.options,i=e.accept;this.isover=!1,this.isout=!0,this.accept=t.isFunction(i)?i:function(t){return t.is(i)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},t.ui.ddmanager.droppables[e.scope]=t.ui.ddmanager.droppables[e.scope]||[],t.ui.ddmanager.droppables[e.scope].push(this),e.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){for(var e=0,i=t.ui.ddmanager.droppables[this.options.scope];i.length>e;e++)i[e]===this&&i.splice(e,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(e,i){"accept"===e&&(this.accept=t.isFunction(i)?i:function(t){return t.is(i)}),t.Widget.prototype._setOption.apply(this,arguments)},_activate:function(e){var i=t.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger("activate",e,this.ui(i))},_deactivate:function(e){var i=t.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger("deactivate",e,this.ui(i))},_over:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",e,this.ui(i)))},_out:function(e){var i=t.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",e,this.ui(i)))},_drop:function(e,i){var s=i||t.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var e=t.data(this,"ui-droppable");return e.options.greedy&&!e.options.disabled&&e.options.scope===s.options.scope&&e.accept.call(e.element[0],s.currentItem||s.element)&&t.ui.intersect(s,t.extend(e,{offset:e.element.offset()}),e.options.tolerance)?(n=!0,!1):undefined}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",e,this.ui(s)),this.element):!1):!1},ui:function(t){return{draggable:t.currentItem||t.element,helper:t.helper,position:t.position,offset:t.positionAbs}}}),t.ui.intersect=function(t,i,s){if(!i.offset)return!1;var n,a,o=(t.positionAbs||t.position.absolute).left,r=o+t.helperProportions.width,l=(t.positionAbs||t.position.absolute).top,h=l+t.helperProportions.height,c=i.offset.left,u=c+i.proportions.width,d=i.offset.top,p=d+i.proportions.height;switch(s){case"fit":return o>=c&&u>=r&&l>=d&&p>=h;case"intersect":return o+t.helperProportions.width/2>c&&u>r-t.helperProportions.width/2&&l+t.helperProportions.height/2>d&&p>h-t.helperProportions.height/2;case"pointer":return n=(t.positionAbs||t.position.absolute).left+(t.clickOffset||t.offset.click).left,a=(t.positionAbs||t.position.absolute).top+(t.clickOffset||t.offset.click).top,e(a,d,i.proportions.height)&&e(n,c,i.proportions.width);case"touch":return(l>=d&&p>=l||h>=d&&p>=h||d>l&&h>p)&&(o>=c&&u>=o||r>=c&&u>=r||c>o&&r>u);default:return!1}},t.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(e,i){var s,n,a=t.ui.ddmanager.droppables[e.options.scope]||[],o=i?i.type:null,r=(e.currentItem||e.element).find(":data(ui-droppable)").addBack();t:for(s=0;a.length>s;s++)if(!(a[s].options.disabled||e&&!a[s].accept.call(a[s].element[0],e.currentItem||e.element))){for(n=0;r.length>n;n++)if(r[n]===a[s].element[0]){a[s].proportions.height=0;continue t}a[s].visible="none"!==a[s].element.css("display"),a[s].visible&&("mousedown"===o&&a[s]._activate.call(a[s],i),a[s].offset=a[s].element.offset(),a[s].proportions={width:a[s].element[0].offsetWidth,height:a[s].element[0].offsetHeight})}},drop:function(e,i){var s=!1;return t.each((t.ui.ddmanager.droppables[e.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&t.ui.intersect(e,this,this.options.tolerance)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],e.currentItem||e.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(e,i){e.element.parentsUntil("body").bind("scroll.droppable",function(){e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)})},drag:function(e,i){e.options.refreshPositions&&t.ui.ddmanager.prepareOffsets(e,i),t.each(t.ui.ddmanager.droppables[e.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,a,o=t.ui.intersect(e,this,this.options.tolerance),r=!o&&this.isover?"isout":o&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,a=this.element.parents(":data(ui-droppable)").filter(function(){return t.data(this,"ui-droppable").options.scope===n}),a.length&&(s=t.data(a[0],"ui-droppable"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(e,i){e.element.parentsUntil("body").unbind("scroll.droppable"),e.options.refreshPositions||t.ui.ddmanager.prepareOffsets(e,i)}}})(jQuery);(function(t){function e(t){return parseInt(t,10)||0}function i(t){return!isNaN(parseInt(t,10))}t.widget("ui.resizable",t.ui.mouse,{version:"1.10.3",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var e,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(t("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),e=this.handles.split(","),this.handles={},i=0;e.length>i;i++)s=t.trim(e[i]),a="ui-resizable-"+s,n=t("<div class='ui-resizable-handle "+a+"'></div>"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(e){var i,s,n,a;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=t(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=t(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,a),this._proportionallyResize()),t(this.handles[i]).length},this._renderAxis(this.element),this._handles=t(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),t(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(t(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(t(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=e(this.helper.css("left")),n=e(this.helper.css("top")),o.containment&&(s+=t(o.containment).scrollLeft()||0,n+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(e){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,c=this.size.height,u=e.pageX-a.left||0,d=e.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[e,u,d]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==c&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(n)||this._trigger("resize",e,this.ui()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&t.ui.hasScroll(i[0],"left")?0:c.sizeDiff.height,a=s?0:c.sizeDiff.width,o={width:c.helper.width()-a,height:c.helper.height()-n},r=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null,h=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null,l.animate||this.element.css(t.extend(o,{top:h,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!l.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(t){var e,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),i(t.left)&&(this.position.left=t.left),i(t.top)&&(this.position.top=t.top),i(t.height)&&(this.size.height=t.height),i(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,s=this.size,n=this.axis;return i(t.height)?t.width=t.height*this.aspectRatio:i(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===n&&(t.left=e.left+(s.width-t.width),t.top=null),"nw"===n&&(t.top=e.top+(s.height-t.height),t.left=e.left+(s.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,s=this.axis,n=i(t.width)&&e.maxWidth&&e.maxWidth<t.width,a=i(t.height)&&e.maxHeight&&e.maxHeight<t.height,o=i(t.width)&&e.minWidth&&e.minWidth>t.width,r=i(t.height)&&e.minHeight&&e.minHeight>t.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,c=/sw|nw|w/.test(s),u=/nw|ne|n/.test(s);return o&&(t.width=e.minWidth),r&&(t.height=e.minHeight),n&&(t.width=e.maxWidth),a&&(t.height=e.maxHeight),o&&c&&(t.left=h-e.minWidth),n&&c&&(t.left=h-e.maxWidth),r&&u&&(t.top=l-e.minHeight),a&&u&&(t.top=l-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var t,e,i,s,n,a=this.helper||this.element;for(t=0;this._proportionallyResizeElements.length>t;t++){if(n=this._proportionallyResizeElements[t],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],e=0;i.length>e;e++)this.borderDif[e]=(parseInt(i[e],10)||0)+(parseInt(s[e],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("<div style='overflow:hidden;'></div>"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&t.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,c=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(h,c&&l?{top:c,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=t(this).data("ui-resizable"),c=l.options,u=l.element,d=c.containment,p=d instanceof t?d.get(0):/parent/.test(d)?u.parent().get(0):d;p&&(l.containerElement=t(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(i=t(p),s=[],t(["Top","Right","Left","Bottom"]).each(function(t,n){s[t]=e(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=t.ui.hasScroll(p,"left")?p.scrollWidth:o,h=t.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(e){var i,s,n,a,o=t(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,c=o._aspectRatio||e.shiftKey,u={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(u=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-u.left),c&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),c&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-u.left:o.offset.left-u.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-u.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,c&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,c&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.containerOffset,n=e.containerPosition,a=e.containerElement,o=t(e.helper),r=o.offset(),h=o.outerWidth()-e.sizeDiff.width,l=o.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(a.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l}),e._helper&&!i.animate&&/static/.test(a.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).data("ui-resizable"),i=e.options,s=function(e){t(e).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseInt(e.width(),10),height:parseInt(e.height(),10),left:parseInt(e.css("left"),10),top:parseInt(e.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):t.each(i.alsoResize,function(t){s(t)})},resize:function(e,i){var s=t(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(e,s){t(e).each(function(){var e=t(this),n=t(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(n[e]||0)+(r[e]||0);i&&i>=0&&(a[e]=i||null)}),e.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):t.each(n.alsoResize,function(t,e){h(t,e)})},stop:function(){t(this).removeData("resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).data("ui-resizable");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).data("ui-resizable");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.size,n=e.originalSize,a=e.originalPosition,o=e.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,c=Math.round((s.width-n.width)/h)*h,u=Math.round((s.height-n.height)/l)*l,d=n.width+c,p=n.height+u,f=i.maxWidth&&d>i.maxWidth,g=i.maxHeight&&p>i.maxHeight,m=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,m&&(d+=h),v&&(p+=l),f&&(d-=h),g&&(p-=l),/^(se|s|e)$/.test(o)?(e.size.width=d,e.size.height=p):/^(ne)$/.test(o)?(e.size.width=d,e.size.height=p,e.position.top=a.top-u):/^(sw)$/.test(o)?(e.size.width=d,e.size.height=p,e.position.left=a.left-c):(e.size.width=d,e.size.height=p,e.position.top=a.top-u,e.position.left=a.left-c)}})})(jQuery);(function(t){t.widget("ui.selectable",t.ui.mouse,{version:"1.10.3",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var e,i=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){e=t(i.options.filter,i.element[0]),e.addClass("ui-selectee"),e.each(function(){var e=t(this),i=e.offset();t.data(this,"selectable-item",{element:this,$element:e,left:i.left,top:i.top,right:i.left+e.outerWidth(),bottom:i.top+e.outerHeight(),startselected:!1,selected:e.hasClass("ui-selected"),selecting:e.hasClass("ui-selecting"),unselecting:e.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=e.addClass("ui-selectee"),this._mouseInit(),this.helper=t("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(e){var i=this,s=this.options;this.opos=[e.pageX,e.pageY],this.options.disabled||(this.selectees=t(s.filter,this.element[0]),this._trigger("start",e),t(s.appendTo).append(this.helper),this.helper.css({left:e.pageX,top:e.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=t.data(this,"selectable-item");s.startselected=!0,e.metaKey||e.ctrlKey||(s.$element.removeClass("ui-selected"),s.selected=!1,s.$element.addClass("ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",e,{unselecting:s.element}))}),t(e.target).parents().addBack().each(function(){var s,n=t.data(this,"selectable-item");return n?(s=!e.metaKey&&!e.ctrlKey||!n.$element.hasClass("ui-selected"),n.$element.removeClass(s?"ui-unselecting":"ui-selected").addClass(s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",e,{selecting:n.element}):i._trigger("unselecting",e,{unselecting:n.element}),!1):undefined}))},_mouseDrag:function(e){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,a=this.opos[0],o=this.opos[1],r=e.pageX,l=e.pageY;return a>r&&(i=r,r=a,a=i),o>l&&(i=l,l=o,o=i),this.helper.css({left:a,top:o,width:r-a,height:l-o}),this.selectees.each(function(){var i=t.data(this,"selectable-item"),h=!1;i&&i.element!==s.element[0]&&("touch"===n.tolerance?h=!(i.left>r||a>i.right||i.top>l||o>i.bottom):"fit"===n.tolerance&&(h=i.left>a&&r>i.right&&i.top>o&&l>i.bottom),h?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,s._trigger("selecting",e,{selecting:i.element}))):(i.selecting&&((e.metaKey||e.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",e,{unselecting:i.element}))),i.selected&&(e.metaKey||e.ctrlKey||i.startselected||(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",e,{unselecting:i.element})))))}),!1}},_mouseStop:function(e){var i=this;return this.dragged=!1,t(".ui-unselecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");s.$element.removeClass("ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",e,{unselected:s.element})}),t(".ui-selecting",this.element[0]).each(function(){var s=t.data(this,"selectable-item");s.$element.removeClass("ui-selecting").addClass("ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",e,{selected:s.element})}),this._trigger("stop",e),this.helper.remove(),!1}})})(jQuery);(function(t){function e(t,e,i){return t>e&&e+i>t}function i(t){return/left|right/.test(t.css("float"))||/inline|table-cell/.test(t.css("display"))}t.widget("ui.sortable",t.ui.mouse,{version:"1.10.3",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_create:function(){var t=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?"x"===t.axis||i(this.items[0].item):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var t=this.items.length-1;t>=0;t--)this.items[t].item.removeData(this.widgetName+"-item");return this},_setOption:function(e,i){"disabled"===e?(this.options[e]=i,this.widget().toggleClass("ui-sortable-disabled",!!i)):t.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(e,i){var s=null,n=!1,o=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(e),t(e.target).parents().each(function(){return t.data(this,o.widgetName+"-item")===o?(s=t(this),!1):undefined}),t.data(e.target,o.widgetName+"-item")===o&&(s=t(e.target)),s?!this.options.handle||i||(t(this.options.handle,s).find("*").addBack().each(function(){this===e.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(e,i,s){var n,o,a=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(e),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,a.cursorAt&&this._adjustOffsetFromHelper(a.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),a.containment&&this._setContainment(),a.cursor&&"auto"!==a.cursor&&(o=this.document.find("body"),this.storedCursor=o.css("cursor"),o.css("cursor",a.cursor),this.storedStylesheet=t("<style>*{ cursor: "+a.cursor+" !important; }</style>").appendTo(o)),a.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",a.opacity)),a.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",a.zIndex)),this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,o,a=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY<a.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+a.scrollSpeed:e.pageY-this.overflowOffset.top<a.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-a.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-e.pageX<a.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+a.scrollSpeed:e.pageX-this.overflowOffset.left<a.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-a.scrollSpeed)):(e.pageY-t(document).scrollTop()<a.scrollSensitivity?r=t(document).scrollTop(t(document).scrollTop()-a.scrollSpeed):t(window).height()-(e.pageY-t(document).scrollTop())<a.scrollSensitivity&&(r=t(document).scrollTop(t(document).scrollTop()+a.scrollSpeed)),e.pageX-t(document).scrollLeft()<a.scrollSensitivity?r=t(document).scrollLeft(t(document).scrollLeft()-a.scrollSpeed):t(window).width()-(e.pageX-t(document).scrollLeft())<a.scrollSensitivity&&(r=t(document).scrollLeft(t(document).scrollLeft()+a.scrollSpeed))),r!==!1&&t.ui.ddmanager&&!a.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e)),this.positionAbs=this._convertPositionTo("absolute"),this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),i=this.items.length-1;i>=0;i--)if(s=this.items[i],n=s.item[0],o=this._intersectsWithPointer(s),o&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===o?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===o?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),o=this.options.axis,a={};o&&"x"!==o||(a.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft)),o&&"y"!==o||(a.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(a,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,o=t.left,a=o+t.width,r=t.top,h=r+t.height,l=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+l>r&&h>s+l,d="y"===this.options.axis||e+c>o&&a>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>o&&a>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&h>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var i="x"===this.options.axis||e(this.positionAbs.top+this.offset.click.top,t.top,t.height),s="y"===this.options.axis||e(this.positionAbs.left+this.offset.click.left,t.left,t.width),n=i&&s,o=this._getDragVerticalDirection(),a=this._getDragHorizontalDirection();return n?this.floating?a&&"right"===a||"down"===o?2:1:o&&("down"===o?2:1):!1},_intersectsWithSides:function(t){var i=e(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),s=e(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),n=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return this.floating&&o?"right"===o&&s||"left"===o&&!s:n&&("down"===n&&i||"up"===n&&!i)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){var i,s,n,o,a=[],r=[],h=this._connectWith();if(h&&e)for(i=h.length-1;i>=0;i--)for(n=t(h[i]),s=n.length-1;s>=0;s--)o=t.data(n[s],this.widgetFullName),o&&o!==this&&!o.options.disabled&&r.push([t.isFunction(o.options.items)?o.options.items.call(o.element):t(o.options.items,o.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),o]);for(r.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),i=r.length-1;i>=0;i--)r[i][0].each(function(){a.push(this)});return t(a)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,o,a,r,h,l,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i]),s=n.length-1;s>=0;s--)o=t.data(n[s],this.widgetFullName),o&&o!==this&&!o.options.disabled&&(u.push([t.isFunction(o.options.items)?o.options.items.call(o.element[0],e,{item:this.currentItem}):t(o.options.items,o.element),o]),this.containers.push(o));for(i=u.length-1;i>=0;i--)for(a=u[i][1],r=u[i][0],s=0,l=r.length;l>s;s++)h=t(r[s]),h.data(this.widgetName+"-item",a),c.push({item:h,instance:a,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,o;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),o=n.offset(),s.left=o.left,s.top=o.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)o=this.containers[i].element.offset(),this.containers[i].containerCache.left=o.left,this.containers[i].containerCache.top=o.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]).addClass(i||e.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");return"tr"===s?e.currentItem.children().each(function(){t("<td>&#160;</td>",e.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(n)}):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_contactContainers:function(s){var n,o,a,r,h,l,c,u,d,p,f=null,g=null;for(n=this.containers.length-1;n>=0;n--)if(!t.contains(this.currentItem[0],this.containers[n].element[0]))if(this._intersectsWith(this.containers[n].containerCache)){if(f&&t.contains(this.containers[n].element[0],f.element[0]))continue;f=this.containers[n],g=n}else this.containers[n].containerCache.over&&(this.containers[n]._trigger("out",s,this._uiHash(this)),this.containers[n].containerCache.over=0);if(f)if(1===this.containers.length)this.containers[g].containerCache.over||(this.containers[g]._trigger("over",s,this._uiHash(this)),this.containers[g].containerCache.over=1);else{for(a=1e4,r=null,p=f.floating||i(this.currentItem),h=p?"left":"top",l=p?"width":"height",c=this.positionAbs[h]+this.offset.click[h],o=this.items.length-1;o>=0;o--)t.contains(this.containers[g].element[0],this.items[o].item[0])&&this.items[o].item[0]!==this.currentItem[0]&&(!p||e(this.positionAbs.top+this.offset.click.top,this.items[o].top,this.items[o].height))&&(u=this.items[o].item.offset()[h],d=!1,Math.abs(u-c)>Math.abs(u+this.items[o][l]-c)&&(d=!0,u+=this.items[o][l]),a>Math.abs(u-c)&&(a=Math.abs(u-c),r=this.items[o],this.direction=d?"up":"down"));if(!r&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[g])return;r?this._rearrange(s,r,null,!0):this._rearrange(s,null,this.containers[g].element,!0),this._trigger("change",s,this._uiHash()),this.containers[g]._trigger("change",s,this._uiHash(this)),this.currentContainer=this.containers[g],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[g]._trigger("over",s,this._uiHash(this)),this.containers[g].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,t("document"===n.containment?document:window).width()-this.helperProportions.width-this.margins.left,(t("document"===n.containment?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())*s}},_generatePosition:function(e){var i,s,n=this.options,o=e.pageX,a=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==document&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.left<this.containment[0]&&(o=this.containment[0]+this.offset.click.left),e.pageY-this.offset.click.top<this.containment[1]&&(a=this.containment[1]+this.offset.click.top),e.pageX-this.offset.click.left>this.containment[2]&&(o=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(a=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((a-this.originalPageY)/n.grid[1])*n.grid[1],a=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((o-this.originalPageX)/n.grid[0])*n.grid[0],o=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){this.reverting=!1;var i,s=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(i in this._storedCSS)("auto"===this._storedCSS[i]||"static"===this._storedCSS[i])&&(this._storedCSS[i]="");this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&s.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||s.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(s.push(function(t){this._trigger("remove",t,this._uiHash())}),s.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),s.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),i=this.containers.length-1;i>=0;i--)e||s.push(function(t){return function(e){t._trigger("deactivate",e,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over&&(s.push(function(t){return function(e){t._trigger("out",e,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,this.cancelHelperRemoval){if(!e){for(this._trigger("beforeStop",t,this._uiHash()),i=0;s.length>i;i++)s[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}if(e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null,!e){for(i=0;s.length>i;i++)s[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}})})(jQuery);(function(e){var t=0,i={},a={};i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="hide",a.height=a.paddingTop=a.paddingBottom=a.borderTopWidth=a.borderBottomWidth="show",e.widget("ui.accordion",{version:"1.10.3",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var t=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),t.collapsible||t.active!==!1&&null!=t.active||(t.active=0),this._processPanels(),0>t.active&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():e(),content:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("<span>").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),e=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),"content"!==this.options.heightStyle&&e.css("height","")},_setOption:function(e,t){return"active"===e?(this._activate(t),undefined):("event"===e&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),"collapsible"!==e||t||this.options.active!==!1||this._activate(0),"icons"===e&&(this._destroyIcons(),t&&this._createIcons()),"disabled"===e&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t),undefined)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var i=e.ui.keyCode,a=this.headers.length,s=this.headers.index(t.target),n=!1;switch(t.keyCode){case i.RIGHT:case i.DOWN:n=this.headers[(s+1)%a];break;case i.LEFT:case i.UP:n=this.headers[(s-1+a)%a];break;case i.SPACE:case i.ENTER:this._eventHandler(t);break;case i.HOME:n=this.headers[0];break;case i.END:n=this.headers[a-1]}n&&(e(t.target).attr("tabIndex",-1),e(n).attr("tabIndex",0),n.focus(),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t=this.options;this._processPanels(),t.active===!1&&t.collapsible===!0||!this.headers.length?(t.active=!1,this.active=e()):t.active===!1?this._activate(0):this.active.length&&!e.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=e()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide()},_refresh:function(){var i,a=this.options,s=a.heightStyle,n=this.element.parent(),r=this.accordionId="ui-accordion-"+(this.element.attr("id")||++t);this.active=this._findActive(a.active).addClass("ui-accordion-header-active ui-state-active ui-corner-top").removeClass("ui-corner-all"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(t){var i=e(this),a=i.attr("id"),s=i.next(),n=s.attr("id");a||(a=r+"-header-"+t,i.attr("id",a)),n||(n=r+"-panel-"+t,s.attr("id",n)),i.attr("aria-controls",n),s.attr("aria-labelledby",a)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false",tabIndex:-1}).next().attr({"aria-expanded":"false","aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true",tabIndex:0}).next().attr({"aria-expanded":"true","aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(a.event),"fill"===s?(i=n.height(),this.element.siblings(":visible").each(function(){var t=e(this),a=t.css("position");"absolute"!==a&&"fixed"!==a&&(i-=t.outerHeight(!0))}),this.headers.each(function(){i-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,i-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):"auto"===s&&(i=0,this.headers.next().each(function(){i=Math.max(i,e(this).css("height","").height())}).height(i))},_activate:function(t){var i=this._findActive(t)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:e.noop}))},_findActive:function(t){return"number"==typeof t?this.headers.eq(t):e()},_setupEvents:function(t){var i={keydown:"_keydown"};t&&e.each(t.split(" "),function(e,t){i[t]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var i=this.options,a=this.active,s=e(t.currentTarget),n=s[0]===a[0],r=n&&i.collapsible,o=r?e():s.next(),h=a.next(),d={oldHeader:a,oldPanel:h,newHeader:r?e():s,newPanel:o};t.preventDefault(),n&&!i.collapsible||this._trigger("beforeActivate",t,d)===!1||(i.active=r?!1:this.headers.index(s),this.active=n?e():s,this._toggle(d),a.removeClass("ui-accordion-header-active ui-state-active"),i.icons&&a.children(".ui-accordion-header-icon").removeClass(i.icons.activeHeader).addClass(i.icons.header),n||(s.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),i.icons&&s.children(".ui-accordion-header-icon").removeClass(i.icons.header).addClass(i.icons.activeHeader),s.next().addClass("ui-accordion-content-active")))},_toggle:function(t){var i=t.newPanel,a=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=a,this.options.animate?this._animate(i,a,t):(a.hide(),i.show(),this._toggleComplete(t)),a.attr({"aria-expanded":"false","aria-hidden":"true"}),a.prev().attr("aria-selected","false"),i.length&&a.length?a.prev().attr("tabIndex",-1):i.length&&this.headers.filter(function(){return 0===e(this).attr("tabIndex")}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}).prev().attr({"aria-selected":"true",tabIndex:0})},_animate:function(e,t,s){var n,r,o,h=this,d=0,c=e.length&&(!t.length||e.index()<t.index()),l=this.options.animate||{},u=c&&l.down||l,v=function(){h._toggleComplete(s)};return"number"==typeof u&&(o=u),"string"==typeof u&&(r=u),r=r||u.easing||l.easing,o=o||u.duration||l.duration,t.length?e.length?(n=e.show().outerHeight(),t.animate(i,{duration:o,easing:r,step:function(e,t){t.now=Math.round(e)}}),e.hide().animate(a,{duration:o,easing:r,complete:v,step:function(e,i){i.now=Math.round(e),"height"!==i.prop?d+=i.now:"content"!==h.options.heightStyle&&(i.now=Math.round(n-t.outerHeight()-d),d=0)}}),undefined):t.animate(i,o,r,v):e.animate(a,o,r,v)},_toggleComplete:function(e){var t=e.oldPanel;t.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"),t.length&&(t.parent()[0].className=t.parent()[0].className),this._trigger("activate",null,e)}})})(jQuery);(function(e){var t=0;e.widget("ui.autocomplete",{version:"1.10.3",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var t,i,s,n=this.element[0].nodeName.toLowerCase(),a="textarea"===n,o="input"===n;this.isMultiLine=a?!0:o?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[a||o?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return t=!0,s=!0,i=!0,undefined;t=!1,s=!1,i=!1;var a=e.ui.keyCode;switch(n.keyCode){case a.PAGE_UP:t=!0,this._move("previousPage",n);break;case a.PAGE_DOWN:t=!0,this._move("nextPage",n);break;case a.UP:t=!0,this._keyEvent("previous",n);break;case a.DOWN:t=!0,this._keyEvent("next",n);break;case a.ENTER:case a.NUMPAD_ENTER:this.menu.active&&(t=!0,n.preventDefault(),this.menu.select(n));break;case a.TAB:this.menu.active&&this.menu.select(n);break;case a.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(t)return t=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),undefined;if(!i){var n=e.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(e){return s?(s=!1,e.preventDefault(),undefined):(this._searchTimeout(e),undefined)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,undefined):(clearTimeout(this.searching),this.close(e),this._change(e),undefined)}}),this._initSource(),this.menu=e("<ul>").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({role:null}).hide().data("ui-menu"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var i=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(s){s.target===t.element[0]||s.target===i||e.contains(i,s.target)||t.close()})})},menufocus:function(t,i){if(this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type)))return this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)}),undefined;var s=i.item.data("ui-autocomplete-item");!1!==this._trigger("focus",t,{item:s})?t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(s.value):this.liveRegion.text(s.value)},menuselect:function(e,t){var i=t.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",e,{item:i})&&this._value(i.value),this.term=this._value(),this.close(e),this.selectedItem=i}}),this.liveRegion=e("<span>",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertBefore(this.element),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),"source"===e&&this._initSource(),"appendTo"===e&&this.menu.element.appendTo(this._appendTo()),"disabled"===e&&t&&this.xhr&&this.xhr.abort()},_appendTo:function(){var t=this.options.appendTo;return t&&(t=t.jquery||t.nodeType?e(t):this.document.find(t).eq(0)),t||(t=this.element.closest(".ui-front")),t.length||(t=this.document[0].body),t},_initSource:function(){var t,i,s=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(i,s){s(e.ui.autocomplete.filter(t,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(t,n){s.xhr&&s.xhr.abort(),s.xhr=e.ajax({url:i,data:t,dataType:"json",success:function(e){n(e)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){return e=null!=e?e:this._value(),this.term=this._value(),e.length<this.options.minLength?this.close(t):this._trigger("search",t)!==!1?this._search(e):undefined},_search:function(e){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:e},this._response())},_response:function(){var e=this,i=++t;return function(s){i===t&&e.__response(s),e.pending--,e.pending||e.element.removeClass("ui-autocomplete-loading")}},__response:function(e){e&&(e=this._normalize(e)),this._trigger("response",null,{content:e}),!this.options.disabled&&e&&e.length&&!this.cancelSearch?(this._suggest(e),this._trigger("open")):this._close()},close:function(e){this.cancelSearch=!0,this._close(e)},_close:function(e){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",e))},_change:function(e){this.previous!==this._value()&&this._trigger("change",e,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:e.map(t,function(t){return"string"==typeof t?{label:t,value:t}:e.extend({label:t.label||t.value,value:t.value||t.label},t)})},_suggest:function(t){var i=this.menu.element.empty();this._renderMenu(i,t),this.isNewMenu=!0,this.menu.refresh(),i.show(),this._resizeMenu(),i.position(e.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(t,i){var s=this;e.each(i,function(e,i){s._renderItemData(t,i)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-autocomplete-item",t)},_renderItem:function(t,i){return e("<li>").append(e("<a>").text(i.label)).appendTo(t)},_move:function(e,t){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)?(this._value(this.term),this.menu.blur(),undefined):(this.menu[e](t),undefined):(this.search(null,t),undefined)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(e,t),t.preventDefault())}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,i){var s=RegExp(e.ui.autocomplete.escapeRegex(i),"i");return e.grep(t,function(e){return s.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var t;this._superApply(arguments),this.options.disabled||this.cancelSearch||(t=e&&e.length?this.options.messages.results(e.length):this.options.messages.noResults,this.liveRegion.text(t))}})})(jQuery);(function(e){var t,i,n,s,a="ui-button ui-widget ui-state-default ui-corner-all",o="ui-state-hover ui-state-active ",r="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",h=function(){var t=e(this);setTimeout(function(){t.find(":ui-button").button("refresh")},1)},u=function(t){var i=t.name,n=t.form,s=e([]);return i&&(i=i.replace(/'/g,"\\'"),s=n?e(n).find("[name='"+i+"']"):e("[name='"+i+"']",t.ownerDocument).filter(function(){return!this.form})),s};e.widget("ui.button",{version:"1.10.3",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,h),"boolean"!=typeof this.options.disabled?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var o=this,r=this.options,l="checkbox"===this.type||"radio"===this.type,c=l?"":"ui-state-active",d="ui-state-focus";null===r.label&&(r.label="input"===this.type?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(a).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){r.disabled||this===t&&e(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){r.disabled||e(this).removeClass(c)}).bind("click"+this.eventNamespace,function(e){r.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this.element.bind("focus"+this.eventNamespace,function(){o.buttonElement.addClass(d)}).bind("blur"+this.eventNamespace,function(){o.buttonElement.removeClass(d)}),l&&(this.element.bind("change"+this.eventNamespace,function(){s||o.refresh()}),this.buttonElement.bind("mousedown"+this.eventNamespace,function(e){r.disabled||(s=!1,i=e.pageX,n=e.pageY)}).bind("mouseup"+this.eventNamespace,function(e){r.disabled||(i!==e.pageX||n!==e.pageY)&&(s=!0)})),"checkbox"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){return r.disabled||s?!1:undefined}):"radio"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){if(r.disabled||s)return!1;e(this).addClass("ui-state-active"),o.buttonElement.attr("aria-pressed","true");var t=o.element[0];u(t).not(t).map(function(){return e(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){return r.disabled?!1:(e(this).addClass("ui-state-active"),t=this,o.document.one("mouseup",function(){t=null}),undefined)}).bind("mouseup"+this.eventNamespace,function(){return r.disabled?!1:(e(this).removeClass("ui-state-active"),undefined)}).bind("keydown"+this.eventNamespace,function(t){return r.disabled?!1:((t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass("ui-state-active"),undefined)}).bind("keyup"+this.eventNamespace+" blur"+this.eventNamespace,function(){e(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption("disabled",r.disabled),this._resetButton()},_determineButtonType:function(){var e,t,i;this.type=this.element.is("[type=checkbox]")?"checkbox":this.element.is("[type=radio]")?"radio":this.element.is("input")?"input":"button","checkbox"===this.type||"radio"===this.type?(e=this.element.parents().last(),t="label[for='"+this.element.attr("id")+"']",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass("ui-helper-hidden-accessible"),i=this.element.is(":checked"),i&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",i)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(a+" "+o+" "+r).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(e,t){return this._super(e,t),"disabled"===e?(t?this.element.prop("disabled",!0):this.element.prop("disabled",!1),undefined):(this._resetButton(),undefined)},refresh:function(){var t=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOption("disabled",t),"radio"===this.type?u(this.element[0]).each(function(){e(this).is(":checked")?e(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):"checkbox"===this.type&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if("input"===this.type)return this.options.label&&this.element.val(this.options.label),undefined;var t=this.buttonElement.removeClass(r),i=e("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),n=this.options.icons,s=n.primary&&n.secondary,a=[];n.primary||n.secondary?(this.options.text&&a.push("ui-button-text-icon"+(s?"s":n.primary?"-primary":"-secondary")),n.primary&&t.prepend("<span class='ui-button-icon-primary ui-icon "+n.primary+"'></span>"),n.secondary&&t.append("<span class='ui-button-icon-secondary ui-icon "+n.secondary+"'></span>"),this.options.text||(a.push(s?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||t.attr("title",e.trim(i)))):a.push("ui-button-text-only"),t.addClass(a.join(" "))}}),e.widget("ui.buttonset",{version:"1.10.3",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(e,t){"disabled"===e&&this.buttons.button("option",e,t),this._super(e,t)},refresh:function(){var t="rtl"===this.element.css("direction");this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(t?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function(e,t){function i(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},e.extend(this._defaults,this.regional[""]),this.dpDiv=a(e("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function a(t){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return t.delegate(i,"mouseout",function(){e(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).removeClass("ui-datepicker-next-hover")}).delegate(i,"mouseover",function(){e.datepicker._isDisabledDatepicker(n.inline?t.parent()[0]:n.input[0])||(e(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),e(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).addClass("ui-datepicker-next-hover"))})}function s(t,i){e.extend(t,i);for(var a in i)null==i[a]&&(t[a]=i[a]);return t}e.extend(e.ui,{datepicker:{version:"1.10.3"}});var n,r="datepicker";e.extend(i.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(e){return s(this._defaults,e||{}),this},_attachDatepicker:function(t,i){var a,s,n;a=t.nodeName.toLowerCase(),s="div"===a||"span"===a,t.id||(this.uuid+=1,t.id="dp"+this.uuid),n=this._newInst(e(t),s),n.settings=e.extend({},i||{}),"input"===a?this._connectDatepicker(t,n):s&&this._inlineDatepicker(t,n)},_newInst:function(t,i){var s=t[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1");return{id:s,input:t,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:i,dpDiv:i?a(e("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(t,i){var a=e(t);i.append=e([]),i.trigger=e([]),a.hasClass(this.markerClassName)||(this._attachments(a,i),a.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp),this._autoSize(i),e.data(t,r,i),i.settings.disabled&&this._disableDatepicker(t))},_attachments:function(t,i){var a,s,n,r=this._get(i,"appendText"),o=this._get(i,"isRTL");i.append&&i.append.remove(),r&&(i.append=e("<span class='"+this._appendClass+"'>"+r+"</span>"),t[o?"before":"after"](i.append)),t.unbind("focus",this._showDatepicker),i.trigger&&i.trigger.remove(),a=this._get(i,"showOn"),("focus"===a||"both"===a)&&t.focus(this._showDatepicker),("button"===a||"both"===a)&&(s=this._get(i,"buttonText"),n=this._get(i,"buttonImage"),i.trigger=e(this._get(i,"buttonImageOnly")?e("<img/>").addClass(this._triggerClass).attr({src:n,alt:s,title:s}):e("<button type='button'></button>").addClass(this._triggerClass).html(n?e("<img/>").attr({src:n,alt:s,title:s}):s)),t[o?"before":"after"](i.trigger),i.trigger.click(function(){return e.datepicker._datepickerShowing&&e.datepicker._lastInput===t[0]?e.datepicker._hideDatepicker():e.datepicker._datepickerShowing&&e.datepicker._lastInput!==t[0]?(e.datepicker._hideDatepicker(),e.datepicker._showDatepicker(t[0])):e.datepicker._showDatepicker(t[0]),!1}))},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t,i,a,s,n=new Date(2009,11,20),r=this._get(e,"dateFormat");r.match(/[DM]/)&&(t=function(e){for(i=0,a=0,s=0;e.length>s;s++)e[s].length>i&&(i=e[s].length,a=s);return a},n.setMonth(t(this._get(e,r.match(/MM/)?"monthNames":"monthNamesShort"))),n.setDate(t(this._get(e,r.match(/DD/)?"dayNames":"dayNamesShort"))+20-n.getDay())),e.input.attr("size",this._formatDate(e,n).length)}},_inlineDatepicker:function(t,i){var a=e(t);a.hasClass(this.markerClassName)||(a.addClass(this.markerClassName).append(i.dpDiv),e.data(t,r,i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(t),i.dpDiv.css("display","block"))},_dialogDatepicker:function(t,i,a,n,o){var u,c,l,h,d,p=this._dialogInst;return p||(this.uuid+=1,u="dp"+this.uuid,this._dialogInput=e("<input type='text' id='"+u+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.keydown(this._doKeyDown),e("body").append(this._dialogInput),p=this._dialogInst=this._newInst(this._dialogInput,!1),p.settings={},e.data(this._dialogInput[0],r,p)),s(p.settings,n||{}),i=i&&i.constructor===Date?this._formatDate(p,i):i,this._dialogInput.val(i),this._pos=o?o.length?o:[o.pageX,o.pageY]:null,this._pos||(c=document.documentElement.clientWidth,l=document.documentElement.clientHeight,h=document.documentElement.scrollLeft||document.body.scrollLeft,d=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[c/2-100+h,l/2-150+d]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),p.settings.onSelect=a,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),e.blockUI&&e.blockUI(this.dpDiv),e.data(this._dialogInput[0],r,p),this},_destroyDatepicker:function(t){var i,a=e(t),s=e.data(t,r);a.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),e.removeData(t,r),"input"===i?(s.append.remove(),s.trigger.remove(),a.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):("div"===i||"span"===i)&&a.removeClass(this.markerClassName).empty())},_enableDatepicker:function(t){var i,a,s=e(t),n=e.data(t,r);s.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),"input"===i?(t.disabled=!1,n.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(a=s.children("."+this._inlineClass),a.children().removeClass("ui-state-disabled"),a.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}))},_disableDatepicker:function(t){var i,a,s=e(t),n=e.data(t,r);s.hasClass(this.markerClassName)&&(i=t.nodeName.toLowerCase(),"input"===i?(t.disabled=!0,n.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(a=s.children("."+this._inlineClass),a.children().addClass("ui-state-disabled"),a.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=e.map(this._disabledInputs,function(e){return e===t?null:e}),this._disabledInputs[this._disabledInputs.length]=t)},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;this._disabledInputs.length>t;t++)if(this._disabledInputs[t]===e)return!0;return!1},_getInst:function(t){try{return e.data(t,r)}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(i,a,n){var r,o,u,c,l=this._getInst(i);return 2===arguments.length&&"string"==typeof a?"defaults"===a?e.extend({},e.datepicker._defaults):l?"all"===a?e.extend({},l.settings):this._get(l,a):null:(r=a||{},"string"==typeof a&&(r={},r[a]=n),l&&(this._curInst===l&&this._hideDatepicker(),o=this._getDateDatepicker(i,!0),u=this._getMinMaxDate(l,"min"),c=this._getMinMaxDate(l,"max"),s(l.settings,r),null!==u&&r.dateFormat!==t&&r.minDate===t&&(l.settings.minDate=this._formatDate(l,u)),null!==c&&r.dateFormat!==t&&r.maxDate===t&&(l.settings.maxDate=this._formatDate(l,c)),"disabled"in r&&(r.disabled?this._disableDatepicker(i):this._enableDatepicker(i)),this._attachments(e(i),l),this._autoSize(l),this._setDate(l,o),this._updateAlternate(l),this._updateDatepicker(l)),t)},_changeDatepicker:function(e,t,i){this._optionDatepicker(e,t,i)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var i=this._getInst(e);i&&(this._setDate(i,t),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(e,t){var i=this._getInst(e);return i&&!i.inline&&this._setDateFromField(i,t),i?this._getDate(i):null},_doKeyDown:function(t){var i,a,s,n=e.datepicker._getInst(t.target),r=!0,o=n.dpDiv.is(".ui-datepicker-rtl");if(n._keyEvent=!0,e.datepicker._datepickerShowing)switch(t.keyCode){case 9:e.datepicker._hideDatepicker(),r=!1;break;case 13:return s=e("td."+e.datepicker._dayOverClass+":not(."+e.datepicker._currentClass+")",n.dpDiv),s[0]&&e.datepicker._selectDay(t.target,n.selectedMonth,n.selectedYear,s[0]),i=e.datepicker._get(n,"onSelect"),i?(a=e.datepicker._formatDate(n),i.apply(n.input?n.input[0]:null,[a,n])):e.datepicker._hideDatepicker(),!1;case 27:e.datepicker._hideDatepicker();break;case 33:e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(n,"stepBigMonths"):-e.datepicker._get(n,"stepMonths"),"M");break;case 34:e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(n,"stepBigMonths"):+e.datepicker._get(n,"stepMonths"),"M");break;case 35:(t.ctrlKey||t.metaKey)&&e.datepicker._clearDate(t.target),r=t.ctrlKey||t.metaKey;break;case 36:(t.ctrlKey||t.metaKey)&&e.datepicker._gotoToday(t.target),r=t.ctrlKey||t.metaKey;break;case 37:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,o?1:-1,"D"),r=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?-e.datepicker._get(n,"stepBigMonths"):-e.datepicker._get(n,"stepMonths"),"M");break;case 38:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,-7,"D"),r=t.ctrlKey||t.metaKey;break;case 39:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,o?-1:1,"D"),r=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&e.datepicker._adjustDate(t.target,t.ctrlKey?+e.datepicker._get(n,"stepBigMonths"):+e.datepicker._get(n,"stepMonths"),"M");break;case 40:(t.ctrlKey||t.metaKey)&&e.datepicker._adjustDate(t.target,7,"D"),r=t.ctrlKey||t.metaKey;break;default:r=!1}else 36===t.keyCode&&t.ctrlKey?e.datepicker._showDatepicker(this):r=!1;r&&(t.preventDefault(),t.stopPropagation())},_doKeyPress:function(i){var a,s,n=e.datepicker._getInst(i.target);return e.datepicker._get(n,"constrainInput")?(a=e.datepicker._possibleChars(e.datepicker._get(n,"dateFormat")),s=String.fromCharCode(null==i.charCode?i.keyCode:i.charCode),i.ctrlKey||i.metaKey||" ">s||!a||a.indexOf(s)>-1):t},_doKeyUp:function(t){var i,a=e.datepicker._getInst(t.target);if(a.input.val()!==a.lastVal)try{i=e.datepicker.parseDate(e.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,e.datepicker._getFormatConfig(a)),i&&(e.datepicker._setDateFromField(a),e.datepicker._updateAlternate(a),e.datepicker._updateDatepicker(a))}catch(s){}return!0},_showDatepicker:function(t){if(t=t.target||t,"input"!==t.nodeName.toLowerCase()&&(t=e("input",t.parentNode)[0]),!e.datepicker._isDisabledDatepicker(t)&&e.datepicker._lastInput!==t){var i,a,n,r,o,u,c;i=e.datepicker._getInst(t),e.datepicker._curInst&&e.datepicker._curInst!==i&&(e.datepicker._curInst.dpDiv.stop(!0,!0),i&&e.datepicker._datepickerShowing&&e.datepicker._hideDatepicker(e.datepicker._curInst.input[0])),a=e.datepicker._get(i,"beforeShow"),n=a?a.apply(t,[t,i]):{},n!==!1&&(s(i.settings,n),i.lastVal=null,e.datepicker._lastInput=t,e.datepicker._setDateFromField(i),e.datepicker._inDialog&&(t.value=""),e.datepicker._pos||(e.datepicker._pos=e.datepicker._findPos(t),e.datepicker._pos[1]+=t.offsetHeight),r=!1,e(t).parents().each(function(){return r|="fixed"===e(this).css("position"),!r}),o={left:e.datepicker._pos[0],top:e.datepicker._pos[1]},e.datepicker._pos=null,i.dpDiv.empty(),i.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),e.datepicker._updateDatepicker(i),o=e.datepicker._checkOffset(i,o,r),i.dpDiv.css({position:e.datepicker._inDialog&&e.blockUI?"static":r?"fixed":"absolute",display:"none",left:o.left+"px",top:o.top+"px"}),i.inline||(u=e.datepicker._get(i,"showAnim"),c=e.datepicker._get(i,"duration"),i.dpDiv.zIndex(e(t).zIndex()+1),e.datepicker._datepickerShowing=!0,e.effects&&e.effects.effect[u]?i.dpDiv.show(u,e.datepicker._get(i,"showOptions"),c):i.dpDiv[u||"show"](u?c:null),e.datepicker._shouldFocusInput(i)&&i.input.focus(),e.datepicker._curInst=i))}},_updateDatepicker:function(t){this.maxRows=4,n=t,t.dpDiv.empty().append(this._generateHTML(t)),this._attachHandlers(t),t.dpDiv.find("."+this._dayOverClass+" a").mouseover();var i,a=this._getNumberOfMonths(t),s=a[1],r=17;t.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),s>1&&t.dpDiv.addClass("ui-datepicker-multi-"+s).css("width",r*s+"em"),t.dpDiv[(1!==a[0]||1!==a[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),t.dpDiv[(this._get(t,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),t===e.datepicker._curInst&&e.datepicker._datepickerShowing&&e.datepicker._shouldFocusInput(t)&&t.input.focus(),t.yearshtml&&(i=t.yearshtml,setTimeout(function(){i===t.yearshtml&&t.yearshtml&&t.dpDiv.find("select.ui-datepicker-year:first").replaceWith(t.yearshtml),i=t.yearshtml=null},0))},_shouldFocusInput:function(e){return e.input&&e.input.is(":visible")&&!e.input.is(":disabled")&&!e.input.is(":focus")},_checkOffset:function(t,i,a){var s=t.dpDiv.outerWidth(),n=t.dpDiv.outerHeight(),r=t.input?t.input.outerWidth():0,o=t.input?t.input.outerHeight():0,u=document.documentElement.clientWidth+(a?0:e(document).scrollLeft()),c=document.documentElement.clientHeight+(a?0:e(document).scrollTop());return i.left-=this._get(t,"isRTL")?s-r:0,i.left-=a&&i.left===t.input.offset().left?e(document).scrollLeft():0,i.top-=a&&i.top===t.input.offset().top+o?e(document).scrollTop():0,i.left-=Math.min(i.left,i.left+s>u&&u>s?Math.abs(i.left+s-u):0),i.top-=Math.min(i.top,i.top+n>c&&c>n?Math.abs(n+o):0),i},_findPos:function(t){for(var i,a=this._getInst(t),s=this._get(a,"isRTL");t&&("hidden"===t.type||1!==t.nodeType||e.expr.filters.hidden(t));)t=t[s?"previousSibling":"nextSibling"];return i=e(t).offset(),[i.left,i.top]},_hideDatepicker:function(t){var i,a,s,n,o=this._curInst;!o||t&&o!==e.data(t,r)||this._datepickerShowing&&(i=this._get(o,"showAnim"),a=this._get(o,"duration"),s=function(){e.datepicker._tidyDialog(o)},e.effects&&(e.effects.effect[i]||e.effects[i])?o.dpDiv.hide(i,e.datepicker._get(o,"showOptions"),a,s):o.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?a:null,s),i||s(),this._datepickerShowing=!1,n=this._get(o,"onClose"),n&&n.apply(o.input?o.input[0]:null,[o.input?o.input.val():"",o]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),e.blockUI&&(e.unblockUI(),e("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(t){if(e.datepicker._curInst){var i=e(t.target),a=e.datepicker._getInst(i[0]);(i[0].id!==e.datepicker._mainDivId&&0===i.parents("#"+e.datepicker._mainDivId).length&&!i.hasClass(e.datepicker.markerClassName)&&!i.closest("."+e.datepicker._triggerClass).length&&e.datepicker._datepickerShowing&&(!e.datepicker._inDialog||!e.blockUI)||i.hasClass(e.datepicker.markerClassName)&&e.datepicker._curInst!==a)&&e.datepicker._hideDatepicker()}},_adjustDate:function(t,i,a){var s=e(t),n=this._getInst(s[0]);this._isDisabledDatepicker(s[0])||(this._adjustInstDate(n,i+("M"===a?this._get(n,"showCurrentAtPos"):0),a),this._updateDatepicker(n))},_gotoToday:function(t){var i,a=e(t),s=this._getInst(a[0]);this._get(s,"gotoCurrent")&&s.currentDay?(s.selectedDay=s.currentDay,s.drawMonth=s.selectedMonth=s.currentMonth,s.drawYear=s.selectedYear=s.currentYear):(i=new Date,s.selectedDay=i.getDate(),s.drawMonth=s.selectedMonth=i.getMonth(),s.drawYear=s.selectedYear=i.getFullYear()),this._notifyChange(s),this._adjustDate(a)},_selectMonthYear:function(t,i,a){var s=e(t),n=this._getInst(s[0]);n["selected"+("M"===a?"Month":"Year")]=n["draw"+("M"===a?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(n),this._adjustDate(s)},_selectDay:function(t,i,a,s){var n,r=e(t);e(s).hasClass(this._unselectableClass)||this._isDisabledDatepicker(r[0])||(n=this._getInst(r[0]),n.selectedDay=n.currentDay=e("a",s).html(),n.selectedMonth=n.currentMonth=i,n.selectedYear=n.currentYear=a,this._selectDate(t,this._formatDate(n,n.currentDay,n.currentMonth,n.currentYear)))},_clearDate:function(t){var i=e(t);this._selectDate(i,"")},_selectDate:function(t,i){var a,s=e(t),n=this._getInst(s[0]);i=null!=i?i:this._formatDate(n),n.input&&n.input.val(i),this._updateAlternate(n),a=this._get(n,"onSelect"),a?a.apply(n.input?n.input[0]:null,[i,n]):n.input&&n.input.trigger("change"),n.inline?this._updateDatepicker(n):(this._hideDatepicker(),this._lastInput=n.input[0],"object"!=typeof n.input[0]&&n.input.focus(),this._lastInput=null)},_updateAlternate:function(t){var i,a,s,n=this._get(t,"altField");n&&(i=this._get(t,"altFormat")||this._get(t,"dateFormat"),a=this._getDate(t),s=this.formatDate(i,a,this._getFormatConfig(t)),e(n).each(function(){e(this).val(s)}))},noWeekends:function(e){var t=e.getDay();return[t>0&&6>t,""]},iso8601Week:function(e){var t,i=new Date(e.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),t=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((t-i)/864e5)/7)+1},parseDate:function(i,a,s){if(null==i||null==a)throw"Invalid arguments";if(a="object"==typeof a?""+a:a+"",""===a)return null;var n,r,o,u,c=0,l=(s?s.shortYearCutoff:null)||this._defaults.shortYearCutoff,h="string"!=typeof l?l:(new Date).getFullYear()%100+parseInt(l,10),d=(s?s.dayNamesShort:null)||this._defaults.dayNamesShort,p=(s?s.dayNames:null)||this._defaults.dayNames,g=(s?s.monthNamesShort:null)||this._defaults.monthNamesShort,m=(s?s.monthNames:null)||this._defaults.monthNames,f=-1,_=-1,v=-1,k=-1,b=!1,y=function(e){var t=i.length>n+1&&i.charAt(n+1)===e;return t&&n++,t},D=function(e){var t=y(e),i="@"===e?14:"!"===e?20:"y"===e&&t?4:"o"===e?3:2,s=RegExp("^\\d{1,"+i+"}"),n=a.substring(c).match(s);if(!n)throw"Missing number at position "+c;return c+=n[0].length,parseInt(n[0],10)},w=function(i,s,n){var r=-1,o=e.map(y(i)?n:s,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)});if(e.each(o,function(e,i){var s=i[1];return a.substr(c,s.length).toLowerCase()===s.toLowerCase()?(r=i[0],c+=s.length,!1):t}),-1!==r)return r+1;throw"Unknown name at position "+c},M=function(){if(a.charAt(c)!==i.charAt(n))throw"Unexpected literal at position "+c;c++};for(n=0;i.length>n;n++)if(b)"'"!==i.charAt(n)||y("'")?M():b=!1;else switch(i.charAt(n)){case"d":v=D("d");break;case"D":w("D",d,p);break;case"o":k=D("o");break;case"m":_=D("m");break;case"M":_=w("M",g,m);break;case"y":f=D("y");break;case"@":u=new Date(D("@")),f=u.getFullYear(),_=u.getMonth()+1,v=u.getDate();break;case"!":u=new Date((D("!")-this._ticksTo1970)/1e4),f=u.getFullYear(),_=u.getMonth()+1,v=u.getDate();break;case"'":y("'")?M():b=!0;break;default:M()}if(a.length>c&&(o=a.substr(c),!/^\s+/.test(o)))throw"Extra/unparsed characters found in date: "+o;if(-1===f?f=(new Date).getFullYear():100>f&&(f+=(new Date).getFullYear()-(new Date).getFullYear()%100+(h>=f?0:-100)),k>-1)for(_=1,v=k;;){if(r=this._getDaysInMonth(f,_-1),r>=v)break;_++,v-=r}if(u=this._daylightSavingAdjust(new Date(f,_-1,v)),u.getFullYear()!==f||u.getMonth()+1!==_||u.getDate()!==v)throw"Invalid date";return u},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(e,t,i){if(!t)return"";var a,s=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,n=(i?i.dayNames:null)||this._defaults.dayNames,r=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,o=(i?i.monthNames:null)||this._defaults.monthNames,u=function(t){var i=e.length>a+1&&e.charAt(a+1)===t;return i&&a++,i},c=function(e,t,i){var a=""+t;if(u(e))for(;i>a.length;)a="0"+a;return a},l=function(e,t,i,a){return u(e)?a[t]:i[t]},h="",d=!1;if(t)for(a=0;e.length>a;a++)if(d)"'"!==e.charAt(a)||u("'")?h+=e.charAt(a):d=!1;else switch(e.charAt(a)){case"d":h+=c("d",t.getDate(),2);break;case"D":h+=l("D",t.getDay(),s,n);break;case"o":h+=c("o",Math.round((new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()-new Date(t.getFullYear(),0,0).getTime())/864e5),3);break;case"m":h+=c("m",t.getMonth()+1,2);break;case"M":h+=l("M",t.getMonth(),r,o);break;case"y":h+=u("y")?t.getFullYear():(10>t.getYear()%100?"0":"")+t.getYear()%100;break;case"@":h+=t.getTime();break;case"!":h+=1e4*t.getTime()+this._ticksTo1970;break;case"'":u("'")?h+="'":d=!0;break;default:h+=e.charAt(a)}return h},_possibleChars:function(e){var t,i="",a=!1,s=function(i){var a=e.length>t+1&&e.charAt(t+1)===i;return a&&t++,a};for(t=0;e.length>t;t++)if(a)"'"!==e.charAt(t)||s("'")?i+=e.charAt(t):a=!1;else switch(e.charAt(t)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":s("'")?i+="'":a=!0;break;default:i+=e.charAt(t)}return i},_get:function(e,i){return e.settings[i]!==t?e.settings[i]:this._defaults[i]},_setDateFromField:function(e,t){if(e.input.val()!==e.lastVal){var i=this._get(e,"dateFormat"),a=e.lastVal=e.input?e.input.val():null,s=this._getDefaultDate(e),n=s,r=this._getFormatConfig(e);try{n=this.parseDate(i,a,r)||s}catch(o){a=t?"":a}e.selectedDay=n.getDate(),e.drawMonth=e.selectedMonth=n.getMonth(),e.drawYear=e.selectedYear=n.getFullYear(),e.currentDay=a?n.getDate():0,e.currentMonth=a?n.getMonth():0,e.currentYear=a?n.getFullYear():0,this._adjustInstDate(e)}},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,"defaultDate"),new Date))},_determineDate:function(t,i,a){var s=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},n=function(i){try{return e.datepicker.parseDate(e.datepicker._get(t,"dateFormat"),i,e.datepicker._getFormatConfig(t))}catch(a){}for(var s=(i.toLowerCase().match(/^c/)?e.datepicker._getDate(t):null)||new Date,n=s.getFullYear(),r=s.getMonth(),o=s.getDate(),u=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,c=u.exec(i);c;){switch(c[2]||"d"){case"d":case"D":o+=parseInt(c[1],10);break;case"w":case"W":o+=7*parseInt(c[1],10);break;case"m":case"M":r+=parseInt(c[1],10),o=Math.min(o,e.datepicker._getDaysInMonth(n,r));break;case"y":case"Y":n+=parseInt(c[1],10),o=Math.min(o,e.datepicker._getDaysInMonth(n,r))}c=u.exec(i)}return new Date(n,r,o)},r=null==i||""===i?a:"string"==typeof i?n(i):"number"==typeof i?isNaN(i)?a:s(i):new Date(i.getTime());return r=r&&"Invalid Date"==""+r?a:r,r&&(r.setHours(0),r.setMinutes(0),r.setSeconds(0),r.setMilliseconds(0)),this._daylightSavingAdjust(r)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,i){var a=!t,s=e.selectedMonth,n=e.selectedYear,r=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=r.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=r.getMonth(),e.drawYear=e.selectedYear=e.currentYear=r.getFullYear(),s===e.selectedMonth&&n===e.selectedYear||i||this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(a?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&""===e.input.val()?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(t){var i=this._get(t,"stepMonths"),a="#"+t.id.replace(/\\\\/g,"\\");t.dpDiv.find("[data-handler]").map(function(){var t={prev:function(){e.datepicker._adjustDate(a,-i,"M")},next:function(){e.datepicker._adjustDate(a,+i,"M")},hide:function(){e.datepicker._hideDatepicker()},today:function(){e.datepicker._gotoToday(a)},selectDay:function(){return e.datepicker._selectDay(a,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return e.datepicker._selectMonthYear(a,this,"M"),!1},selectYear:function(){return e.datepicker._selectMonthYear(a,this,"Y"),!1}};e(this).bind(this.getAttribute("data-event"),t[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t,i,a,s,n,r,o,u,c,l,h,d,p,g,m,f,_,v,k,b,y,D,w,M,C,x,I,N,T,A,E,S,Y,F,P,O,j,K,R,H=new Date,W=this._daylightSavingAdjust(new Date(H.getFullYear(),H.getMonth(),H.getDate())),L=this._get(e,"isRTL"),U=this._get(e,"showButtonPanel"),B=this._get(e,"hideIfNoPrevNext"),z=this._get(e,"navigationAsDateFormat"),q=this._getNumberOfMonths(e),G=this._get(e,"showCurrentAtPos"),J=this._get(e,"stepMonths"),Q=1!==q[0]||1!==q[1],V=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),$=this._getMinMaxDate(e,"min"),X=this._getMinMaxDate(e,"max"),Z=e.drawMonth-G,et=e.drawYear;if(0>Z&&(Z+=12,et--),X)for(t=this._daylightSavingAdjust(new Date(X.getFullYear(),X.getMonth()-q[0]*q[1]+1,X.getDate())),t=$&&$>t?$:t;this._daylightSavingAdjust(new Date(et,Z,1))>t;)Z--,0>Z&&(Z=11,et--);for(e.drawMonth=Z,e.drawYear=et,i=this._get(e,"prevText"),i=z?this.formatDate(i,this._daylightSavingAdjust(new Date(et,Z-J,1)),this._getFormatConfig(e)):i,a=this._canAdjustMonth(e,-1,et,Z)?"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(L?"e":"w")+"'>"+i+"</span></a>":B?"":"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(L?"e":"w")+"'>"+i+"</span></a>",s=this._get(e,"nextText"),s=z?this.formatDate(s,this._daylightSavingAdjust(new Date(et,Z+J,1)),this._getFormatConfig(e)):s,n=this._canAdjustMonth(e,1,et,Z)?"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='"+s+"'><span class='ui-icon ui-icon-circle-triangle-"+(L?"w":"e")+"'>"+s+"</span></a>":B?"":"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+s+"'><span class='ui-icon ui-icon-circle-triangle-"+(L?"w":"e")+"'>"+s+"</span></a>",r=this._get(e,"currentText"),o=this._get(e,"gotoCurrent")&&e.currentDay?V:W,r=z?this.formatDate(r,o,this._getFormatConfig(e)):r,u=e.inline?"":"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>"+this._get(e,"closeText")+"</button>",c=U?"<div class='ui-datepicker-buttonpane ui-widget-content'>"+(L?u:"")+(this._isInRange(e,o)?"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>"+r+"</button>":"")+(L?"":u)+"</div>":"",l=parseInt(this._get(e,"firstDay"),10),l=isNaN(l)?0:l,h=this._get(e,"showWeek"),d=this._get(e,"dayNames"),p=this._get(e,"dayNamesMin"),g=this._get(e,"monthNames"),m=this._get(e,"monthNamesShort"),f=this._get(e,"beforeShowDay"),_=this._get(e,"showOtherMonths"),v=this._get(e,"selectOtherMonths"),k=this._getDefaultDate(e),b="",D=0;q[0]>D;D++){for(w="",this.maxRows=4,M=0;q[1]>M;M++){if(C=this._daylightSavingAdjust(new Date(et,Z,e.selectedDay)),x=" ui-corner-all",I="",Q){if(I+="<div class='ui-datepicker-group",q[1]>1)switch(M){case 0:I+=" ui-datepicker-group-first",x=" ui-corner-"+(L?"right":"left");break;case q[1]-1:I+=" ui-datepicker-group-last",x=" ui-corner-"+(L?"left":"right");break;default:I+=" ui-datepicker-group-middle",x=""}I+="'>"}for(I+="<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix"+x+"'>"+(/all|left/.test(x)&&0===D?L?n:a:"")+(/all|right/.test(x)&&0===D?L?a:n:"")+this._generateMonthYearHeader(e,Z,et,$,X,D>0||M>0,g,m)+"</div><table class='ui-datepicker-calendar'><thead>"+"<tr>",N=h?"<th class='ui-datepicker-week-col'>"+this._get(e,"weekHeader")+"</th>":"",y=0;7>y;y++)T=(y+l)%7,N+="<th"+((y+l+6)%7>=5?" class='ui-datepicker-week-end'":"")+">"+"<span title='"+d[T]+"'>"+p[T]+"</span></th>";for(I+=N+"</tr></thead><tbody>",A=this._getDaysInMonth(et,Z),et===e.selectedYear&&Z===e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,A)),E=(this._getFirstDayOfMonth(et,Z)-l+7)%7,S=Math.ceil((E+A)/7),Y=Q?this.maxRows>S?this.maxRows:S:S,this.maxRows=Y,F=this._daylightSavingAdjust(new Date(et,Z,1-E)),P=0;Y>P;P++){for(I+="<tr>",O=h?"<td class='ui-datepicker-week-col'>"+this._get(e,"calculateWeek")(F)+"</td>":"",y=0;7>y;y++)j=f?f.apply(e.input?e.input[0]:null,[F]):[!0,""],K=F.getMonth()!==Z,R=K&&!v||!j[0]||$&&$>F||X&&F>X,O+="<td class='"+((y+l+6)%7>=5?" ui-datepicker-week-end":"")+(K?" ui-datepicker-other-month":"")+(F.getTime()===C.getTime()&&Z===e.selectedMonth&&e._keyEvent||k.getTime()===F.getTime()&&k.getTime()===C.getTime()?" "+this._dayOverClass:"")+(R?" "+this._unselectableClass+" ui-state-disabled":"")+(K&&!_?"":" "+j[1]+(F.getTime()===V.getTime()?" "+this._currentClass:"")+(F.getTime()===W.getTime()?" ui-datepicker-today":""))+"'"+(K&&!_||!j[2]?"":" title='"+j[2].replace(/'/g,"&#39;")+"'")+(R?"":" data-handler='selectDay' data-event='click' data-month='"+F.getMonth()+"' data-year='"+F.getFullYear()+"'")+">"+(K&&!_?"&#xa0;":R?"<span class='ui-state-default'>"+F.getDate()+"</span>":"<a class='ui-state-default"+(F.getTime()===W.getTime()?" ui-state-highlight":"")+(F.getTime()===V.getTime()?" ui-state-active":"")+(K?" ui-priority-secondary":"")+"' href='#'>"+F.getDate()+"</a>")+"</td>",F.setDate(F.getDate()+1),F=this._daylightSavingAdjust(F);I+=O+"</tr>"}Z++,Z>11&&(Z=0,et++),I+="</tbody></table>"+(Q?"</div>"+(q[0]>0&&M===q[1]-1?"<div class='ui-datepicker-row-break'></div>":""):""),w+=I}b+=w}return b+=c,e._keyEvent=!1,b},_generateMonthYearHeader:function(e,t,i,a,s,n,r,o){var u,c,l,h,d,p,g,m,f=this._get(e,"changeMonth"),_=this._get(e,"changeYear"),v=this._get(e,"showMonthAfterYear"),k="<div class='ui-datepicker-title'>",b="";if(n||!f)b+="<span class='ui-datepicker-month'>"+r[t]+"</span>";else{for(u=a&&a.getFullYear()===i,c=s&&s.getFullYear()===i,b+="<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>",l=0;12>l;l++)(!u||l>=a.getMonth())&&(!c||s.getMonth()>=l)&&(b+="<option value='"+l+"'"+(l===t?" selected='selected'":"")+">"+o[l]+"</option>");b+="</select>"}if(v||(k+=b+(!n&&f&&_?"":"&#xa0;")),!e.yearshtml)if(e.yearshtml="",n||!_)k+="<span class='ui-datepicker-year'>"+i+"</span>";else{for(h=this._get(e,"yearRange").split(":"),d=(new Date).getFullYear(),p=function(e){var t=e.match(/c[+\-].*/)?i+parseInt(e.substring(1),10):e.match(/[+\-].*/)?d+parseInt(e,10):parseInt(e,10);
+return isNaN(t)?d:t},g=p(h[0]),m=Math.max(g,p(h[1]||"")),g=a?Math.max(g,a.getFullYear()):g,m=s?Math.min(m,s.getFullYear()):m,e.yearshtml+="<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";m>=g;g++)e.yearshtml+="<option value='"+g+"'"+(g===i?" selected='selected'":"")+">"+g+"</option>";e.yearshtml+="</select>",k+=e.yearshtml,e.yearshtml=null}return k+=this._get(e,"yearSuffix"),v&&(k+=(!n&&f&&_?"":"&#xa0;")+b),k+="</div>"},_adjustInstDate:function(e,t,i){var a=e.drawYear+("Y"===i?t:0),s=e.drawMonth+("M"===i?t:0),n=Math.min(e.selectedDay,this._getDaysInMonth(a,s))+("D"===i?t:0),r=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(a,s,n)));e.selectedDay=r.getDate(),e.drawMonth=e.selectedMonth=r.getMonth(),e.drawYear=e.selectedYear=r.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(e)},_restrictMinMax:function(e,t){var i=this._getMinMaxDate(e,"min"),a=this._getMinMaxDate(e,"max"),s=i&&i>t?i:t;return a&&s>a?a:s},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return null==t?[1,1]:"number"==typeof t?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return new Date(e,t,1).getDay()},_canAdjustMonth:function(e,t,i,a){var s=this._getNumberOfMonths(e),n=this._daylightSavingAdjust(new Date(i,a+(0>t?t:s[0]*s[1]),1));return 0>t&&n.setDate(this._getDaysInMonth(n.getFullYear(),n.getMonth())),this._isInRange(e,n)},_isInRange:function(e,t){var i,a,s=this._getMinMaxDate(e,"min"),n=this._getMinMaxDate(e,"max"),r=null,o=null,u=this._get(e,"yearRange");return u&&(i=u.split(":"),a=(new Date).getFullYear(),r=parseInt(i[0],10),o=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(r+=a),i[1].match(/[+\-].*/)&&(o+=a)),(!s||t.getTime()>=s.getTime())&&(!n||t.getTime()<=n.getTime())&&(!r||t.getFullYear()>=r)&&(!o||o>=t.getFullYear())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t="string"!=typeof t?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,i,a){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var s=t?"object"==typeof t?t:this._daylightSavingAdjust(new Date(a,i,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),s,this._getFormatConfig(e))}}),e.fn.datepicker=function(t){if(!this.length)return this;e.datepicker.initialized||(e(document).mousedown(e.datepicker._checkExternalClick),e.datepicker.initialized=!0),0===e("#"+e.datepicker._mainDivId).length&&e("body").append(e.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof t||"isDisabled"!==t&&"getDate"!==t&&"widget"!==t?"option"===t&&2===arguments.length&&"string"==typeof arguments[1]?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof t?e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this].concat(i)):e.datepicker._attachDatepicker(this,t)}):e.datepicker["_"+t+"Datepicker"].apply(e.datepicker,[this[0]].concat(i))},e.datepicker=new i,e.datepicker.initialized=!1,e.datepicker.uuid=(new Date).getTime(),e.datepicker.version="1.10.3"})(jQuery);(function(e){var t={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.10.3",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var i=e(this).css(t).offset().top;0>i&&e(this).css("top",t.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&e.fn.draggable&&this._makeDraggable(),this.options.resizable&&e.fn.resizable&&this._makeResizable(),this._isOpen=!1},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var t=this.options.appendTo;return t&&(t.jquery||t.nodeType)?e(t):this.document.find(t||"body").eq(0)},_destroy:function(){var e,t=this.originalPosition;this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},disable:e.noop,enable:e.noop,close:function(t){var i=this;this._isOpen&&this._trigger("beforeClose",t)!==!1&&(this._isOpen=!1,this._destroyOverlay(),this.opener.filter(":focusable").focus().length||e(this.document[0].activeElement).blur(),this._hide(this.uiDialog,this.options.hide,function(){i._trigger("close",t)}))},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(e,t){var i=!!this.uiDialog.nextAll(":visible").insertBefore(this.uiDialog).length;return i&&!t&&this._trigger("focus",e),i},open:function(){var t=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),undefined):(this._isOpen=!0,this.opener=e(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger("focus")}),this._trigger("open"),undefined)},_focusTabbable:function(){var e=this.element.find("[autofocus]");e.length||(e=this.element.find(":tabbable")),e.length||(e=this.uiDialogButtonPane.find(":tabbable")),e.length||(e=this.uiDialogTitlebarClose.filter(":tabbable")),e.length||(e=this.uiDialog),e.eq(0).focus()},_keepFocus:function(t){function i(){var t=this.document[0].activeElement,i=this.uiDialog[0]===t||e.contains(this.uiDialog[0],t);i||this._focusTabbable()}t.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=e("<div>").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===e.ui.keyCode.ESCAPE)return t.preventDefault(),this.close(t),undefined;if(t.keyCode===e.ui.keyCode.TAB){var i=this.uiDialog.find(":tabbable"),a=i.filter(":first"),s=i.filter(":last");t.target!==s[0]&&t.target!==this.uiDialog[0]||t.shiftKey?t.target!==a[0]&&t.target!==this.uiDialog[0]||!t.shiftKey||(s.focus(1),t.preventDefault()):(a.focus(1),t.preventDefault())}},mousedown:function(e){this._moveToTop(e)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=e("<div>").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(t){e(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=e("<button></button>").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(e){e.preventDefault(),this.close(e)}}),t=e("<span>").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(t),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(e){this.options.title||e.html("&#160;"),e.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=e("<div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=e("<div>").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var t=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),e.isEmptyObject(i)||e.isArray(i)&&!i.length?(this.uiDialog.removeClass("ui-dialog-buttons"),undefined):(e.each(i,function(i,a){var s,n;a=e.isFunction(a)?{click:a,text:i}:a,a=e.extend({type:"button"},a),s=a.click,a.click=function(){s.apply(t.element[0],arguments)},n={icons:a.icons,text:a.showText},delete a.icons,delete a.showText,e("<button></button>",a).button(n).appendTo(t.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),undefined)},_makeDraggable:function(){function t(e){return{position:e.position,offset:e.offset}}var i=this,a=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(a,s){e(this).addClass("ui-dialog-dragging"),i._blockFrames(),i._trigger("dragStart",a,t(s))},drag:function(e,a){i._trigger("drag",e,t(a))},stop:function(s,n){a.position=[n.position.left-i.document.scrollLeft(),n.position.top-i.document.scrollTop()],e(this).removeClass("ui-dialog-dragging"),i._unblockFrames(),i._trigger("dragStop",s,t(n))}})},_makeResizable:function(){function t(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}var i=this,a=this.options,s=a.resizable,n=this.uiDialog.css("position"),r="string"==typeof s?s:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:a.maxWidth,maxHeight:a.maxHeight,minWidth:a.minWidth,minHeight:this._minHeight(),handles:r,start:function(a,s){e(this).addClass("ui-dialog-resizing"),i._blockFrames(),i._trigger("resizeStart",a,t(s))},resize:function(e,a){i._trigger("resize",e,t(a))},stop:function(s,n){a.height=e(this).height(),a.width=e(this).width(),e(this).removeClass("ui-dialog-resizing"),i._unblockFrames(),i._trigger("resizeStop",s,t(n))}}).css("position",n)},_minHeight:function(){var e=this.options;return"auto"===e.height?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(){var e=this.uiDialog.is(":visible");e||this.uiDialog.show(),this.uiDialog.position(this.options.position),e||this.uiDialog.hide()},_setOptions:function(a){var s=this,n=!1,r={};e.each(a,function(e,a){s._setOption(e,a),e in t&&(n=!0),e in i&&(r[e]=a)}),n&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",r)},_setOption:function(e,t){var i,a,s=this.uiDialog;"dialogClass"===e&&s.removeClass(this.options.dialogClass).addClass(t),"disabled"!==e&&(this._super(e,t),"appendTo"===e&&this.uiDialog.appendTo(this._appendTo()),"buttons"===e&&this._createButtons(),"closeText"===e&&this.uiDialogTitlebarClose.button({label:""+t}),"draggable"===e&&(i=s.is(":data(ui-draggable)"),i&&!t&&s.draggable("destroy"),!i&&t&&this._makeDraggable()),"position"===e&&this._position(),"resizable"===e&&(a=s.is(":data(ui-resizable)"),a&&!t&&s.resizable("destroy"),a&&"string"==typeof t&&s.resizable("option","handles",t),a||t===!1||this._makeResizable()),"title"===e&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var e,t,i,a=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),a.minWidth>a.width&&(a.width=a.minWidth),e=this.uiDialog.css({height:"auto",width:a.width}).outerHeight(),t=Math.max(0,a.minHeight-e),i="number"==typeof a.maxHeight?Math.max(0,a.maxHeight-e):"none","auto"===a.height?this.element.css({minHeight:t,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,a.height-e)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var t=e(this);return e("<div>").css({position:"absolute",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(t){return e(t.target).closest(".ui-dialog").length?!0:!!e(t.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var t=this,i=this.widgetFullName;e.ui.dialog.overlayInstances||this._delay(function(){e.ui.dialog.overlayInstances&&this.document.bind("focusin.dialog",function(a){t._allowInteraction(a)||(a.preventDefault(),e(".ui-dialog:visible:last .ui-dialog-content").data(i)._focusTabbable())})}),this.overlay=e("<div>").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:"_keepFocus"}),e.ui.dialog.overlayInstances++}},_destroyOverlay:function(){this.options.modal&&this.overlay&&(e.ui.dialog.overlayInstances--,e.ui.dialog.overlayInstances||this.document.unbind("focusin.dialog"),this.overlay.remove(),this.overlay=null)}}),e.ui.dialog.overlayInstances=0,e.uiBackCompat!==!1&&e.widget("ui.dialog",e.ui.dialog,{_position:function(){var t,i=this.options.position,a=[],s=[0,0];i?(("string"==typeof i||"object"==typeof i&&"0"in i)&&(a=i.split?i.split(" "):[i[0],i[1]],1===a.length&&(a[1]=a[0]),e.each(["left","top"],function(e,t){+a[e]===a[e]&&(s[e]=a[e],a[e]=t)}),i={my:a[0]+(0>s[0]?s[0]:"+"+s[0])+" "+a[1]+(0>s[1]?s[1]:"+"+s[1]),at:a.join(" ")}),i=e.extend({},e.ui.dialog.prototype.options.position,i)):i=e.ui.dialog.prototype.options.position,t=this.uiDialog.is(":visible"),t||this.uiDialog.show(),this.uiDialog.position(i),t||this.uiDialog.hide()}})})(jQuery);(function(t){t.widget("ui.menu",{version:"1.10.3",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,t.proxy(function(t){this.options.disabled&&t.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(t){t.preventDefault()},"click .ui-state-disabled > a":function(t){t.preventDefault()},"click .ui-menu-item:has(a)":function(e){var i=t(e.target).closest(".ui-menu-item");!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.mouseHandled=!0,this.select(e),i.has(".ui-menu").length?this.expand(e):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(e){var i=t(e.currentTarget);i.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(e,i)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this.element.children(".ui-menu-item").eq(0);e||this.focus(t,i)},blur:function(e){this._delay(function(){t.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(e)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(e){t(e.target).closest(".ui-menu").length||this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var e=t(this);e.data("ui-menu-submenu-carat")&&e.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(e){function i(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var s,n,a,o,r,l=!0;switch(e.keyCode){case t.ui.keyCode.PAGE_UP:this.previousPage(e);break;case t.ui.keyCode.PAGE_DOWN:this.nextPage(e);break;case t.ui.keyCode.HOME:this._move("first","first",e);break;case t.ui.keyCode.END:this._move("last","last",e);break;case t.ui.keyCode.UP:this.previous(e);break;case t.ui.keyCode.DOWN:this.next(e);break;case t.ui.keyCode.LEFT:this.collapse(e);break;case t.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(e);break;case t.ui.keyCode.ENTER:case t.ui.keyCode.SPACE:this._activate(e);break;case t.ui.keyCode.ESCAPE:this.collapse(e);break;default:l=!1,n=this.previousFilter||"",a=String.fromCharCode(e.keyCode),o=!1,clearTimeout(this.filterTimer),a===n?o=!0:a=n+a,r=RegExp("^"+i(a),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return r.test(t(this).children("a").text())}),s=o&&-1!==s.index(this.active.next())?this.active.nextAll(".ui-menu-item"):s,s.length||(a=String.fromCharCode(e.keyCode),r=RegExp("^"+i(a),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return r.test(t(this).children("a").text())})),s.length?(this.focus(e,s),s.length>1?(this.previousFilter=a,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}l&&e.preventDefault()},_activate:function(t){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var e,i=this.options.icons.submenu,s=this.element.find(this.options.menus);s.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var e=t(this),s=e.prev("a"),n=t("<span>").addClass("ui-menu-icon ui-icon "+i).data("ui-menu-submenu-carat",!0);s.attr("aria-haspopup","true").prepend(n),e.attr("aria-labelledby",s.attr("id"))}),e=s.add(this.element),e.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),e.children(":not(.ui-menu-item)").each(function(){var e=t(this);/[^\-\u2014\u2013\s]/.test(e.text())||e.addClass("ui-widget-content ui-menu-divider")}),e.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!t.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){"icons"===t&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(e.submenu),this._super(t,e)},focus:function(t,e){var i,s;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),s=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=e.children(".ui-menu"),i.length&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(e){var i,s,n,a,o,r;this._hasScroll()&&(i=parseFloat(t.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(t.css(this.activeMenu[0],"paddingTop"))||0,n=e.offset().top-this.activeMenu.offset().top-i-s,a=this.activeMenu.scrollTop(),o=this.activeMenu.height(),r=e.height(),0>n?this.activeMenu.scrollTop(a+n):n+r>o&&this.activeMenu.scrollTop(a+n-o+r))},blur:function(t,e){e||clearTimeout(this.timer),this.active&&(this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",t,{item:this.active}))},_startOpening:function(t){clearTimeout(this.timer),"true"===t.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(t)},this.delay))},_open:function(e){var i=t.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(e.parents(".ui-menu")).hide().attr("aria-hidden","true"),e.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(e,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:t(e&&e.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(e),this.activeMenu=s},this.delay)},_close:function(t){t||(t=this.active?this.active.parent():this.element),t.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(t){var e=this.active&&this.active.parent().closest(".ui-menu-item",this.element);e&&e.length&&(this._close(),this.focus(t,e))},expand:function(t){var e=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();e&&e.length&&(this._open(e.parent()),this._delay(function(){this.focus(t,e)}))},next:function(t){this._move("next","first",t)},previous:function(t){this._move("prev","last",t)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(t,e,i){var s;this.active&&(s="first"===t||"last"===t?this.active["first"===t?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[t+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.children(".ui-menu-item")[e]()),this.focus(i,s)},nextPage:function(e){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=t(this),0>i.offset().top-s-n}),this.focus(e,i)):this.focus(e,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())),undefined):(this.next(e),undefined)},previousPage:function(e){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=t(this),i.offset().top-s+n>0}),this.focus(e,i)):this.focus(e,this.activeMenu.children(".ui-menu-item").first())),undefined):(this.next(e),undefined)},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(e){this.active=this.active||t(e.target).closest(".ui-menu-item");var i={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(e,!0),this._trigger("select",e,i)}})})(jQuery);(function(t,e){t.widget("ui.progressbar",{version:"1.10.3",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min}),this.valueDiv=t("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(t){return t===e?this.options.value:(this.options.value=this._constrainedValue(t),this._refreshValue(),e)},_constrainedValue:function(t){return t===e&&(t=this.options.value),this.indeterminate=t===!1,"number"!=typeof t&&(t=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,t))},_setOptions:function(t){var e=t.value;delete t.value,this._super(t),this.options.value=this._constrainedValue(e),this._refreshValue()},_setOption:function(t,e){"max"===t&&(e=Math.max(this.min,e)),this._super(t,e)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var e=this.options.value,i=this._percentage();this.valueDiv.toggle(this.indeterminate||e>this.min).toggleClass("ui-corner-right",e===this.options.max).width(i.toFixed(0)+"%"),this.element.toggleClass("ui-progressbar-indeterminate",this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=t("<div class='ui-progressbar-overlay'></div>").appendTo(this.valueDiv))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":e}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),e===this.options.max&&this._trigger("complete")}})})(jQuery);(function(t){var e=5;t.widget("ui.slider",t.ui.mouse,{version:"1.10.3",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"),this._refresh(),this._setOption("disabled",this.options.disabled),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var e,i,s=this.options,n=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),a="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",o=[];for(i=s.values&&s.values.length||1,n.length>i&&(n.slice(i).remove(),n=n.slice(0,i)),e=n.length;i>e;e++)o.push(a);this.handles=n.add(t(o.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.each(function(e){t(this).data("ui-slider-handle-index",e)})},_createRange:function(){var e=this.options,i="";e.range?(e.range===!0&&(e.values?e.values.length&&2!==e.values.length?e.values=[e.values[0],e.values[0]]:t.isArray(e.values)&&(e.values=e.values.slice(0)):e.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?this.range.removeClass("ui-slider-range-min ui-slider-range-max").css({left:"",bottom:""}):(this.range=t("<div></div>").appendTo(this.element),i="ui-slider-range ui-widget-header ui-corner-all"),this.range.addClass(i+("min"===e.range||"max"===e.range?" ui-slider-range-"+e.range:""))):this.range=t([])},_setupEvents:function(){var t=this.handles.add(this.range).filter("a");this._off(t),this._on(t,this._handleEvents),this._hoverable(t),this._focusable(t)},_destroy:function(){this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(e){var i,s,n,a,o,r,l,h,u=this,c=this.options;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),i={x:e.pageX,y:e.pageY},s=this._normValueFromMouse(i),n=this._valueMax()-this._valueMin()+1,this.handles.each(function(e){var i=Math.abs(s-u.values(e));(n>i||n===i&&(e===u._lastChangedValue||u.values(e)===c.min))&&(n=i,a=t(this),o=e)}),r=this._start(e,o),r===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,a.addClass("ui-state-active").focus(),l=a.offset(),h=!t(e.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=h?{left:0,top:0}:{left:e.pageX-l.left-a.width()/2,top:e.pageY-l.top-a.height()/2-(parseInt(a.css("borderTopWidth"),10)||0)-(parseInt(a.css("borderBottomWidth"),10)||0)+(parseInt(a.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(e,o,s),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(t){var e={x:t.pageX,y:t.pageY},i=this._normValueFromMouse(e);return this._slide(t,this._handleIndex,i),!1},_mouseStop:function(t){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(t,this._handleIndex),this._change(t,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(t){var e,i,s,n,a;return"horizontal"===this.orientation?(e=this.elementSize.width,i=t.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(e=this.elementSize.height,i=t.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),s=i/e,s>1&&(s=1),0>s&&(s=0),"vertical"===this.orientation&&(s=1-s),n=this._valueMax()-this._valueMin(),a=this._valueMin()+s*n,this._trimAlignValue(a)},_start:function(t,e){var i={handle:this.handles[e],value:this.value()};return this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("start",t,i)},_slide:function(t,e,i){var s,n,a;this.options.values&&this.options.values.length?(s=this.values(e?0:1),2===this.options.values.length&&this.options.range===!0&&(0===e&&i>s||1===e&&s>i)&&(i=s),i!==this.values(e)&&(n=this.values(),n[e]=i,a=this._trigger("slide",t,{handle:this.handles[e],value:i,values:n}),s=this.values(e?0:1),a!==!1&&this.values(e,i,!0))):i!==this.value()&&(a=this._trigger("slide",t,{handle:this.handles[e],value:i}),a!==!1&&this.value(i))},_stop:function(t,e){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("stop",t,i)},_change:function(t,e){if(!this._keySliding&&!this._mouseSliding){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._lastChangedValue=e,this._trigger("change",t,i)}},value:function(t){return arguments.length?(this.options.value=this._trimAlignValue(t),this._refreshValue(),this._change(null,0),undefined):this._value()},values:function(e,i){var s,n,a;if(arguments.length>1)return this.options.values[e]=this._trimAlignValue(i),this._refreshValue(),this._change(null,e),undefined;if(!arguments.length)return this._values();if(!t.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(e):this.value();for(s=this.options.values,n=arguments[0],a=0;s.length>a;a+=1)s[a]=this._trimAlignValue(n[a]),this._change(null,a);this._refreshValue()},_setOption:function(e,i){var s,n=0;switch("range"===e&&this.options.range===!0&&("min"===i?(this.options.value=this._values(0),this.options.values=null):"max"===i&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),t.isArray(this.options.values)&&(n=this.options.values.length),t.Widget.prototype._setOption.apply(this,arguments),e){case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":for(this._animateOff=!0,this._refreshValue(),s=0;n>s;s+=1)this._change(null,s);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1;break;case"range":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_value:function(){var t=this.options.value;return t=this._trimAlignValue(t)},_values:function(t){var e,i,s;if(arguments.length)return e=this.options.values[t],e=this._trimAlignValue(e);if(this.options.values&&this.options.values.length){for(i=this.options.values.slice(),s=0;i.length>s;s+=1)i[s]=this._trimAlignValue(i[s]);return i}return[]},_trimAlignValue:function(t){if(this._valueMin()>=t)return this._valueMin();if(t>=this._valueMax())return this._valueMax();var e=this.options.step>0?this.options.step:1,i=(t-this._valueMin())%e,s=t-i;return 2*Math.abs(i)>=e&&(s+=i>0?e:-e),parseFloat(s.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var e,i,s,n,a,o=this.options.range,r=this.options,l=this,h=this._animateOff?!1:r.animate,u={};this.options.values&&this.options.values.length?this.handles.each(function(s){i=100*((l.values(s)-l._valueMin())/(l._valueMax()-l._valueMin())),u["horizontal"===l.orientation?"left":"bottom"]=i+"%",t(this).stop(1,1)[h?"animate":"css"](u,r.animate),l.options.range===!0&&("horizontal"===l.orientation?(0===s&&l.range.stop(1,1)[h?"animate":"css"]({left:i+"%"},r.animate),1===s&&l.range[h?"animate":"css"]({width:i-e+"%"},{queue:!1,duration:r.animate})):(0===s&&l.range.stop(1,1)[h?"animate":"css"]({bottom:i+"%"},r.animate),1===s&&l.range[h?"animate":"css"]({height:i-e+"%"},{queue:!1,duration:r.animate}))),e=i}):(s=this.value(),n=this._valueMin(),a=this._valueMax(),i=a!==n?100*((s-n)/(a-n)):0,u["horizontal"===this.orientation?"left":"bottom"]=i+"%",this.handle.stop(1,1)[h?"animate":"css"](u,r.animate),"min"===o&&"horizontal"===this.orientation&&this.range.stop(1,1)[h?"animate":"css"]({width:i+"%"},r.animate),"max"===o&&"horizontal"===this.orientation&&this.range[h?"animate":"css"]({width:100-i+"%"},{queue:!1,duration:r.animate}),"min"===o&&"vertical"===this.orientation&&this.range.stop(1,1)[h?"animate":"css"]({height:i+"%"},r.animate),"max"===o&&"vertical"===this.orientation&&this.range[h?"animate":"css"]({height:100-i+"%"},{queue:!1,duration:r.animate}))},_handleEvents:{keydown:function(i){var s,n,a,o,r=t(i.target).data("ui-slider-handle-index");switch(i.keyCode){case t.ui.keyCode.HOME:case t.ui.keyCode.END:case t.ui.keyCode.PAGE_UP:case t.ui.keyCode.PAGE_DOWN:case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(i.preventDefault(),!this._keySliding&&(this._keySliding=!0,t(i.target).addClass("ui-state-active"),s=this._start(i,r),s===!1))return}switch(o=this.options.step,n=a=this.options.values&&this.options.values.length?this.values(r):this.value(),i.keyCode){case t.ui.keyCode.HOME:a=this._valueMin();break;case t.ui.keyCode.END:a=this._valueMax();break;case t.ui.keyCode.PAGE_UP:a=this._trimAlignValue(n+(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.PAGE_DOWN:a=this._trimAlignValue(n-(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:if(n===this._valueMax())return;a=this._trimAlignValue(n+o);break;case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(n===this._valueMin())return;a=this._trimAlignValue(n-o)}this._slide(i,r,a)},click:function(t){t.preventDefault()},keyup:function(e){var i=t(e.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(e,i),this._change(e,i),t(e.target).removeClass("ui-state-active"))}}})})(jQuery);(function(t){function e(t){return function(){var e=this.element.val();t.apply(this,arguments),this._refresh(),e!==this.element.val()&&this._trigger("change")}}t.widget("ui.spinner",{version:"1.10.3",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var e={},i=this.element;return t.each(["min","max","step"],function(t,s){var n=i.attr(s);void 0!==n&&n.length&&(e[s]=n)}),e},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t),void 0)},mousewheel:function(t,e){if(e){if(!this.spinning&&!this._start(t))return!1;this._spin((e>0?1:-1)*this.options.step,t),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(t)},100),t.preventDefault()}},"mousedown .ui-spinner-button":function(e){function i(){var t=this.element[0]===this.document[0].activeElement;t||(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),e.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(e)!==!1&&this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(e){return t(e.currentTarget).hasClass("ui-state-active")?this._start(e)===!1?!1:(this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var t=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=t.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(.5*t.height())&&t.height()>0&&t.height(t.height()),this.options.disabled&&this.disable()},_keydown:function(e){var i=this.options,s=t.ui.keyCode;switch(e.keyCode){case s.UP:return this._repeat(null,1,e),!0;case s.DOWN:return this._repeat(null,-1,e),!0;case s.PAGE_UP:return this._repeat(null,i.page,e),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,e),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>&#9650;</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>&#9660;</span>"+"</a>"},_start:function(t){return this.spinning||this._trigger("start",t)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(t,e,i){t=t||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,e,i)},t),this._spin(e*this.options.step,i)},_spin:function(t,e){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+t*this._increment(this.counter)),this.spinning&&this._trigger("spin",e,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(e){var i=this.options.incremental;return i?t.isFunction(i)?i(e):Math.floor(e*e*e/5e4-e*e/500+17*e/200+1):1},_precision:function(){var t=this._precisionOf(this.options.step);return null!==this.options.min&&(t=Math.max(t,this._precisionOf(this.options.min))),t},_precisionOf:function(t){var e=""+t,i=e.indexOf(".");return-1===i?0:e.length-i-1},_adjustValue:function(t){var e,i,s=this.options;return e=null!==s.min?s.min:0,i=t-e,i=Math.round(i/s.step)*s.step,t=e+i,t=parseFloat(t.toFixed(this._precision())),null!==s.max&&t>s.max?s.max:null!==s.min&&s.min>t?s.min:t},_stop:function(t){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",t))},_setOption:function(t,e){if("culture"===t||"numberFormat"===t){var i=this._parse(this.element.val());return this.options[t]=e,this.element.val(this._format(i)),void 0}("max"===t||"min"===t||"step"===t)&&"string"==typeof e&&(e=this._parse(e)),"icons"===t&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(e.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(e.down)),this._super(t,e),"disabled"===t&&(e?(this.element.prop("disabled",!0),this.buttons.button("disable")):(this.element.prop("disabled",!1),this.buttons.button("enable")))},_setOptions:e(function(t){this._super(t),this._value(this.element.val())}),_parse:function(t){return"string"==typeof t&&""!==t&&(t=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(t,10,this.options.culture):+t),""===t||isNaN(t)?null:t},_format:function(t){return""===t?"":window.Globalize&&this.options.numberFormat?Globalize.format(t,this.options.numberFormat,this.options.culture):t},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},_value:function(t,e){var i;""!==t&&(i=this._parse(t),null!==i&&(e||(i=this._adjustValue(i)),t=this._format(i))),this.element.val(t),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:e(function(t){this._stepUp(t)}),_stepUp:function(t){this._start()&&(this._spin((t||1)*this.options.step),this._stop())},stepDown:e(function(t){this._stepDown(t)}),_stepDown:function(t){this._start()&&(this._spin((t||1)*-this.options.step),this._stop())},pageUp:e(function(t){this._stepUp((t||1)*this.options.page)}),pageDown:e(function(t){this._stepDown((t||1)*this.options.page)}),value:function(t){return arguments.length?(e(this._value).call(this,t),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}})})(jQuery);(function(t,e){function i(){return++n}function s(t){return t.hash.length>1&&decodeURIComponent(t.href.replace(a,""))===decodeURIComponent(location.href.replace(a,""))}var n=0,a=/#.*$/;t.widget("ui.tabs",{version:"1.10.3",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var e=this,i=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",i.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(e){t(this).is(".ui-state-disabled")&&e.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){t(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),i.active=this._initialActive(),t.isArray(i.disabled)&&(i.disabled=t.unique(i.disabled.concat(t.map(this.tabs.filter(".ui-state-disabled"),function(t){return e.tabs.index(t)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):t(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var i=this.options.active,s=this.options.collapsible,n=location.hash.substring(1);return null===i&&(n&&this.tabs.each(function(s,a){return t(a).attr("aria-controls")===n?(i=s,!1):e}),null===i&&(i=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===i||-1===i)&&(i=this.tabs.length?0:!1)),i!==!1&&(i=this.tabs.index(this.tabs.eq(i)),-1===i&&(i=s?!1:0)),!s&&i===!1&&this.anchors.length&&(i=0),i},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):t()}},_tabKeydown:function(i){var s=t(this.document[0].activeElement).closest("li"),n=this.tabs.index(s),a=!0;if(!this._handlePageNav(i)){switch(i.keyCode){case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:n++;break;case t.ui.keyCode.UP:case t.ui.keyCode.LEFT:a=!1,n--;break;case t.ui.keyCode.END:n=this.anchors.length-1;break;case t.ui.keyCode.HOME:n=0;break;case t.ui.keyCode.SPACE:return i.preventDefault(),clearTimeout(this.activating),this._activate(n),e;case t.ui.keyCode.ENTER:return i.preventDefault(),clearTimeout(this.activating),this._activate(n===this.options.active?!1:n),e;default:return}i.preventDefault(),clearTimeout(this.activating),n=this._focusNextTab(n,a),i.ctrlKey||(s.attr("aria-selected","false"),this.tabs.eq(n).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",n)},this.delay))}},_panelKeydown:function(e){this._handlePageNav(e)||e.ctrlKey&&e.keyCode===t.ui.keyCode.UP&&(e.preventDefault(),this.active.focus())},_handlePageNav:function(i){return i.altKey&&i.keyCode===t.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):i.altKey&&i.keyCode===t.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):e},_findNextTab:function(e,i){function s(){return e>n&&(e=0),0>e&&(e=n),e}for(var n=this.tabs.length-1;-1!==t.inArray(s(),this.options.disabled);)e=i?e+1:e-1;return e},_focusNextTab:function(t,e){return t=this._findNextTab(t,e),this.tabs.eq(t).focus(),t},_setOption:function(t,i){return"active"===t?(this._activate(i),e):"disabled"===t?(this._setupDisabled(i),e):(this._super(t,i),"collapsible"===t&&(this.element.toggleClass("ui-tabs-collapsible",i),i||this.options.active!==!1||this._activate(0)),"event"===t&&this._setupEvents(i),"heightStyle"===t&&this._setupHeightStyle(i),e)},_tabId:function(t){return t.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(t){return t?t.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var e=this.options,i=this.tablist.children(":has(a[href])");e.disabled=t.map(i.filter(".ui-state-disabled"),function(t){return i.index(t)}),this._processTabs(),e.active!==!1&&this.anchors.length?this.active.length&&!t.contains(this.tablist[0],this.active[0])?this.tabs.length===e.disabled.length?(e.active=!1,this.active=t()):this._activate(this._findNextTab(Math.max(0,e.active-1),!1)):e.active=this.tabs.index(this.active):(e.active=!1,this.active=t()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var e=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return t("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=t(),this.anchors.each(function(i,n){var a,o,r,h=t(n).uniqueId().attr("id"),l=t(n).closest("li"),c=l.attr("aria-controls");s(n)?(a=n.hash,o=e.element.find(e._sanitizeSelector(a))):(r=e._tabId(l),a="#"+r,o=e.element.find(a),o.length||(o=e._createPanel(r),o.insertAfter(e.panels[i-1]||e.tablist)),o.attr("aria-live","polite")),o.length&&(e.panels=e.panels.add(o)),c&&l.data("ui-tabs-aria-controls",c),l.attr({"aria-controls":a.substring(1),"aria-labelledby":h}),o.attr("aria-labelledby",h)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(e){return t("<div>").attr("id",e).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(e){t.isArray(e)&&(e.length?e.length===this.anchors.length&&(e=!0):e=!1);for(var i,s=0;i=this.tabs[s];s++)e===!0||-1!==t.inArray(s,e)?t(i).addClass("ui-state-disabled").attr("aria-disabled","true"):t(i).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=e},_setupEvents:function(e){var i={click:function(t){t.preventDefault()}};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(e){var i,s=this.element.parent();"fill"===e?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=t(this).outerHeight(!0)}),this.panels.each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.panels.each(function(){i=Math.max(i,t(this).height("").height())}).height(i))},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),a=n.closest("li"),o=a[0]===s[0],r=o&&i.collapsible,h=r?t():this._getPanelForTab(a),l=s.length?this._getPanelForTab(s):t(),c={oldTab:s,oldPanel:l,newTab:r?t():a,newPanel:h};e.preventDefault(),a.hasClass("ui-state-disabled")||a.hasClass("ui-tabs-loading")||this.running||o&&!i.collapsible||this._trigger("beforeActivate",e,c)===!1||(i.active=r?!1:this.tabs.index(a),this.active=o?t():a,this.xhr&&this.xhr.abort(),l.length||h.length||t.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(a),e),this._toggle(e,c))},_toggle:function(e,i){function s(){a.running=!1,a._trigger("activate",e,i)}function n(){i.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),o.length&&a.options.show?a._show(o,a.options.show,s):(o.show(),s())}var a=this,o=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),n()}):(i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),r.hide(),n()),r.attr({"aria-expanded":"false","aria-hidden":"true"}),i.oldTab.attr("aria-selected","false"),o.length&&r.length?i.oldTab.attr("tabIndex",-1):o.length&&this.tabs.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),o.attr({"aria-expanded":"true","aria-hidden":"false"}),i.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(e){var i,s=this._findActive(e);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return e===!1?t():this.tabs.eq(e)},_getIndex:function(t){return"string"==typeof t&&(t=this.anchors.index(this.anchors.filter("[href$='"+t+"']"))),t},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){t.data(this,"ui-tabs-destroy")?t(this).remove():t(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var e=t(this),i=e.data("ui-tabs-aria-controls");i?e.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):e.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(i){var s=this.options.disabled;s!==!1&&(i===e?s=!1:(i=this._getIndex(i),s=t.isArray(s)?t.map(s,function(t){return t!==i?t:null}):t.map(this.tabs,function(t,e){return e!==i?e:null})),this._setupDisabled(s))},disable:function(i){var s=this.options.disabled;if(s!==!0){if(i===e)s=!0;else{if(i=this._getIndex(i),-1!==t.inArray(i,s))return;s=t.isArray(s)?t.merge([i],s).sort():[i]}this._setupDisabled(s)}},load:function(e,i){e=this._getIndex(e);var n=this,a=this.tabs.eq(e),o=a.find(".ui-tabs-anchor"),r=this._getPanelForTab(a),h={tab:a,panel:r};s(o[0])||(this.xhr=t.ajax(this._ajaxSettings(o,i,h)),this.xhr&&"canceled"!==this.xhr.statusText&&(a.addClass("ui-tabs-loading"),r.attr("aria-busy","true"),this.xhr.success(function(t){setTimeout(function(){r.html(t),n._trigger("load",i,h)},1)}).complete(function(t,e){setTimeout(function(){"abort"===e&&n.panels.stop(!1,!0),a.removeClass("ui-tabs-loading"),r.removeAttr("aria-busy"),t===n.xhr&&delete n.xhr},1)})))},_ajaxSettings:function(e,i,s){var n=this;return{url:e.attr("href"),beforeSend:function(e,a){return n._trigger("beforeLoad",i,t.extend({jqXHR:e,ajaxSettings:a},s))}}},_getPanelForTab:function(e){var i=t(e).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}})})(jQuery);(function(t){function e(e,i){var s=(e.attr("aria-describedby")||"").split(/\s+/);s.push(i),e.data("ui-tooltip-id",i).attr("aria-describedby",t.trim(s.join(" ")))}function i(e){var i=e.data("ui-tooltip-id"),s=(e.attr("aria-describedby")||"").split(/\s+/),n=t.inArray(i,s);-1!==n&&s.splice(n,1),e.removeData("ui-tooltip-id"),s=t.trim(s.join(" ")),s?e.attr("aria-describedby",s):e.removeAttr("aria-describedby")}var s=0;t.widget("ui.tooltip",{version:"1.10.3",options:{content:function(){var e=t(this).attr("title")||"";return t("<a>").text(e).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(e,i){var s=this;return"disabled"===e?(this[i?"_disable":"_enable"](),this.options[e]=i,void 0):(this._super(e,i),"content"===e&&t.each(this.tooltips,function(t,e){s._updateContent(e)}),void 0)},_disable:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0)}),this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.is("[title]")&&e.data("ui-tooltip-title",e.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.data("ui-tooltip-title")&&e.attr("title",e.data("ui-tooltip-title"))})},open:function(e){var i=this,s=t(e?e.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),e&&"mouseover"===e.type&&s.parents().each(function(){var e,s=t(this);s.data("ui-tooltip-open")&&(e=t.Event("blur"),e.target=e.currentTarget=this,i.close(e,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._updateContent(s,e))},_updateContent:function(t,e){var i,s=this.options.content,n=this,o=e?e.type:null;return"string"==typeof s?this._open(e,t,s):(i=s.call(t[0],function(i){t.data("ui-tooltip-open")&&n._delay(function(){e&&(e.type=o),this._open(e,t,i)})}),i&&this._open(e,t,i),void 0)},_open:function(i,s,n){function o(t){l.of=t,a.is(":hidden")||a.position(l)}var a,r,h,l=t.extend({},this.options.position);if(n){if(a=this._find(s),a.length)return a.find(".ui-tooltip-content").html(n),void 0;s.is("[title]")&&(i&&"mouseover"===i.type?s.attr("title",""):s.removeAttr("title")),a=this._tooltip(s),e(s,a.attr("id")),a.find(".ui-tooltip-content").html(n),this.options.track&&i&&/^mouse/.test(i.type)?(this._on(this.document,{mousemove:o}),o(i)):a.position(t.extend({of:s},this.options.position)),a.hide(),this._show(a,this.options.show),this.options.show&&this.options.show.delay&&(h=this.delayedShow=setInterval(function(){a.is(":visible")&&(o(l.of),clearInterval(h))},t.fx.interval)),this._trigger("open",i,{tooltip:a}),r={keyup:function(e){if(e.keyCode===t.ui.keyCode.ESCAPE){var i=t.Event(e);i.currentTarget=s[0],this.close(i,!0)}},remove:function(){this._removeTooltip(a)}},i&&"mouseover"!==i.type||(r.mouseleave="close"),i&&"focusin"!==i.type||(r.focusout="close"),this._on(!0,s,r)}},close:function(e){var s=this,n=t(e?e.currentTarget:this.element),o=this._find(n);this.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&n.attr("title",n.data("ui-tooltip-title")),i(n),o.stop(!0),this._hide(o,this.options.hide,function(){s._removeTooltip(t(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),e&&"mouseleave"===e.type&&t.each(this.parents,function(e,i){t(i.element).attr("title",i.title),delete s.parents[e]}),this.closing=!0,this._trigger("close",e,{tooltip:o}),this.closing=!1)},_tooltip:function(e){var i="ui-tooltip-"+s++,n=t("<div>").attr({id:i,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return t("<div>").addClass("ui-tooltip-content").appendTo(n),n.appendTo(this.document[0].body),this.tooltips[i]=e,n},_find:function(e){var i=e.data("ui-tooltip-id");return i?t("#"+i):t()},_removeTooltip:function(t){t.remove(),delete this.tooltips[t.attr("id")]},_destroy:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0),t("#"+i).remove(),s.data("ui-tooltip-title")&&(s.attr("title",s.data("ui-tooltip-title")),s.removeData("ui-tooltip-title"))})}})})(jQuery);(function(t,e){var i="ui-effects-";t.effects={effect:{}},function(t,e){function i(t,e,i){var s=u[e.type]||{};return null==t?i||!e.def?null:e.def:(t=s.floor?~~t:parseFloat(t),isNaN(t)?e.def:s.mod?(t+s.mod)%s.mod:0>t?0:t>s.max?s.max:t)}function s(i){var s=h(),n=s._rgba=[];return i=i.toLowerCase(),f(l,function(t,a){var o,r=a.re.exec(i),l=r&&a.parse(r),h=a.space||"rgba";return l?(o=s[h](l),s[c[h].cache]=o[c[h].cache],n=s._rgba=o._rgba,!1):e}),n.length?("0,0,0,0"===n.join()&&t.extend(n,a.transparent),s):a[i]}function n(t,e,i){return i=(i+1)%1,1>6*i?t+6*(e-t)*i:1>2*i?e:2>3*i?t+6*(e-t)*(2/3-i):t}var a,o="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,l=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[t[1],t[2],t[3],t[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[2.55*t[1],2.55*t[2],2.55*t[3],t[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(t){return[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(t){return[parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(t){return[t[1],t[2]/100,t[3]/100,t[4]]}}],h=t.Color=function(e,i,s,n){return new t.Color.fn.parse(e,i,s,n)},c={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},u={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},d=h.support={},p=t("<p>")[0],f=t.each;p.style.cssText="background-color:rgba(1,1,1,.5)",d.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(c,function(t,e){e.cache="_"+t,e.props.alpha={idx:3,type:"percent",def:1}}),h.fn=t.extend(h.prototype,{parse:function(n,o,r,l){if(n===e)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=t(n).css(o),o=e);var u=this,d=t.type(n),p=this._rgba=[];return o!==e&&(n=[n,o,r,l],d="array"),"string"===d?this.parse(s(n)||a._default):"array"===d?(f(c.rgba.props,function(t,e){p[e.idx]=i(n[e.idx],e)}),this):"object"===d?(n instanceof h?f(c,function(t,e){n[e.cache]&&(u[e.cache]=n[e.cache].slice())}):f(c,function(e,s){var a=s.cache;f(s.props,function(t,e){if(!u[a]&&s.to){if("alpha"===t||null==n[t])return;u[a]=s.to(u._rgba)}u[a][e.idx]=i(n[t],e,!0)}),u[a]&&0>t.inArray(null,u[a].slice(0,3))&&(u[a][3]=1,s.from&&(u._rgba=s.from(u[a])))}),this):e},is:function(t){var i=h(t),s=!0,n=this;return f(c,function(t,a){var o,r=i[a.cache];return r&&(o=n[a.cache]||a.to&&a.to(n._rgba)||[],f(a.props,function(t,i){return null!=r[i.idx]?s=r[i.idx]===o[i.idx]:e})),s}),s},_space:function(){var t=[],e=this;return f(c,function(i,s){e[s.cache]&&t.push(i)}),t.pop()},transition:function(t,e){var s=h(t),n=s._space(),a=c[n],o=0===this.alpha()?h("transparent"):this,r=o[a.cache]||a.to(o._rgba),l=r.slice();return s=s[a.cache],f(a.props,function(t,n){var a=n.idx,o=r[a],h=s[a],c=u[n.type]||{};null!==h&&(null===o?l[a]=h:(c.mod&&(h-o>c.mod/2?o+=c.mod:o-h>c.mod/2&&(o-=c.mod)),l[a]=i((h-o)*e+o,n)))}),this[n](l)},blend:function(e){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=h(e)._rgba;return h(t.map(i,function(t,e){return(1-s)*n[e]+s*t}))},toRgbaString:function(){var e="rgba(",i=t.map(this._rgba,function(t,e){return null==t?e>2?1:0:t});return 1===i[3]&&(i.pop(),e="rgb("),e+i.join()+")"},toHslaString:function(){var e="hsla(",i=t.map(this.hsla(),function(t,e){return null==t&&(t=e>2?1:0),e&&3>e&&(t=Math.round(100*t)+"%"),t});return 1===i[3]&&(i.pop(),e="hsl("),e+i.join()+")"},toHexString:function(e){var i=this._rgba.slice(),s=i.pop();return e&&i.push(~~(255*s)),"#"+t.map(i,function(t){return t=(t||0).toString(16),1===t.length?"0"+t:t}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),h.fn.parse.prototype=h.fn,c.hsla.to=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e,i,s=t[0]/255,n=t[1]/255,a=t[2]/255,o=t[3],r=Math.max(s,n,a),l=Math.min(s,n,a),h=r-l,c=r+l,u=.5*c;return e=l===r?0:s===r?60*(n-a)/h+360:n===r?60*(a-s)/h+120:60*(s-n)/h+240,i=0===h?0:.5>=u?h/c:h/(2-c),[Math.round(e)%360,i,u,null==o?1:o]},c.hsla.from=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e=t[0]/360,i=t[1],s=t[2],a=t[3],o=.5>=s?s*(1+i):s+i-s*i,r=2*s-o;return[Math.round(255*n(r,o,e+1/3)),Math.round(255*n(r,o,e)),Math.round(255*n(r,o,e-1/3)),a]},f(c,function(s,n){var a=n.props,o=n.cache,l=n.to,c=n.from;h.fn[s]=function(s){if(l&&!this[o]&&(this[o]=l(this._rgba)),s===e)return this[o].slice();var n,r=t.type(s),u="array"===r||"object"===r?s:arguments,d=this[o].slice();return f(a,function(t,e){var s=u["object"===r?t:e.idx];null==s&&(s=d[e.idx]),d[e.idx]=i(s,e)}),c?(n=h(c(d)),n[o]=d,n):h(d)},f(a,function(e,i){h.fn[e]||(h.fn[e]=function(n){var a,o=t.type(n),l="alpha"===e?this._hsla?"hsla":"rgba":s,h=this[l](),c=h[i.idx];return"undefined"===o?c:("function"===o&&(n=n.call(this,c),o=t.type(n)),null==n&&i.empty?this:("string"===o&&(a=r.exec(n),a&&(n=c+parseFloat(a[2])*("+"===a[1]?1:-1))),h[i.idx]=n,this[l](h)))})})}),h.hook=function(e){var i=e.split(" ");f(i,function(e,i){t.cssHooks[i]={set:function(e,n){var a,o,r="";if("transparent"!==n&&("string"!==t.type(n)||(a=s(n)))){if(n=h(a||n),!d.rgba&&1!==n._rgba[3]){for(o="backgroundColor"===i?e.parentNode:e;(""===r||"transparent"===r)&&o&&o.style;)try{r=t.css(o,"backgroundColor"),o=o.parentNode}catch(l){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{e.style[i]=n}catch(l){}}},t.fx.step[i]=function(e){e.colorInit||(e.start=h(e.elem,i),e.end=h(e.end),e.colorInit=!0),t.cssHooks[i].set(e.elem,e.start.transition(e.end,e.pos))}})},h.hook(o),t.cssHooks.borderColor={expand:function(t){var e={};return f(["Top","Right","Bottom","Left"],function(i,s){e["border"+s+"Color"]=t}),e}},a=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(e){var i,s,n=e.ownerDocument.defaultView?e.ownerDocument.defaultView.getComputedStyle(e,null):e.currentStyle,a={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(a[t.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(a[i]=n[i]);return a}function s(e,i){var s,n,o={};for(s in i)n=i[s],e[s]!==n&&(a[s]||(t.fx.step[s]||!isNaN(parseFloat(n)))&&(o[s]=n));return o}var n=["add","remove","toggle"],a={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};t.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(e,i){t.fx.step[i]=function(t){("none"!==t.end&&!t.setAttr||1===t.pos&&!t.setAttr)&&(jQuery.style(t.elem,i,t.end),t.setAttr=!0)}}),t.fn.addBack||(t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.effects.animateClass=function(e,a,o,r){var l=t.speed(a,o,r);return this.queue(function(){var a,o=t(this),r=o.attr("class")||"",h=l.children?o.find("*").addBack():o;h=h.map(function(){var e=t(this);return{el:e,start:i(this)}}),a=function(){t.each(n,function(t,i){e[i]&&o[i+"Class"](e[i])})},a(),h=h.map(function(){return this.end=i(this.el[0]),this.diff=s(this.start,this.end),this}),o.attr("class",r),h=h.map(function(){var e=this,i=t.Deferred(),s=t.extend({},l,{queue:!1,complete:function(){i.resolve(e)}});return this.el.animate(this.diff,s),i.promise()}),t.when.apply(t,h.get()).done(function(){a(),t.each(arguments,function(){var e=this.el;t.each(this.diff,function(t){e.css(t,"")})}),l.complete.call(o[0])})})},t.fn.extend({addClass:function(e){return function(i,s,n,a){return s?t.effects.animateClass.call(this,{add:i},s,n,a):e.apply(this,arguments)}}(t.fn.addClass),removeClass:function(e){return function(i,s,n,a){return arguments.length>1?t.effects.animateClass.call(this,{remove:i},s,n,a):e.apply(this,arguments)}}(t.fn.removeClass),toggleClass:function(i){return function(s,n,a,o,r){return"boolean"==typeof n||n===e?a?t.effects.animateClass.call(this,n?{add:s}:{remove:s},a,o,r):i.apply(this,arguments):t.effects.animateClass.call(this,{toggle:s},n,a,o)}}(t.fn.toggleClass),switchClass:function(e,i,s,n,a){return t.effects.animateClass.call(this,{add:i,remove:e},s,n,a)}})}(),function(){function s(e,i,s,n){return t.isPlainObject(e)&&(i=e,e=e.effect),e={effect:e},null==i&&(i={}),t.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||t.fx.speeds[i])&&(n=s,s=i,i={}),t.isFunction(s)&&(n=s,s=null),i&&t.extend(e,i),s=s||i.duration,e.duration=t.fx.off?0:"number"==typeof s?s:s in t.fx.speeds?t.fx.speeds[s]:t.fx.speeds._default,e.complete=n||i.complete,e}function n(e){return!e||"number"==typeof e||t.fx.speeds[e]?!0:"string"!=typeof e||t.effects.effect[e]?t.isFunction(e)?!0:"object"!=typeof e||e.effect?!1:!0:!0}t.extend(t.effects,{version:"1.10.3",save:function(t,e){for(var s=0;e.length>s;s++)null!==e[s]&&t.data(i+e[s],t[0].style[e[s]])},restore:function(t,s){var n,a;for(a=0;s.length>a;a++)null!==s[a]&&(n=t.data(i+s[a]),n===e&&(n=""),t.css(s[a],n))},setMode:function(t,e){return"toggle"===e&&(e=t.is(":hidden")?"show":"hide"),e},getBaseline:function(t,e){var i,s;switch(t[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=t[0]/e.height}switch(t[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=t[1]/e.width}return{x:s,y:i}},createWrapper:function(e){if(e.parent().is(".ui-effects-wrapper"))return e.parent();var i={width:e.outerWidth(!0),height:e.outerHeight(!0),"float":e.css("float")},s=t("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:e.width(),height:e.height()},a=document.activeElement;try{a.id}catch(o){a=document.body}return e.wrap(s),(e[0]===a||t.contains(e[0],a))&&t(a).focus(),s=e.parent(),"static"===e.css("position")?(s.css({position:"relative"}),e.css({position:"relative"})):(t.extend(i,{position:e.css("position"),zIndex:e.css("z-index")}),t.each(["top","left","bottom","right"],function(t,s){i[s]=e.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),e.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),e.css(n),s.css(i).show()},removeWrapper:function(e){var i=document.activeElement;return e.parent().is(".ui-effects-wrapper")&&(e.parent().replaceWith(e),(e[0]===i||t.contains(e[0],i))&&t(i).focus()),e},setTransition:function(e,i,s,n){return n=n||{},t.each(i,function(t,i){var a=e.cssUnit(i);a[0]>0&&(n[i]=a[0]*s+a[1])}),n}}),t.fn.extend({effect:function(){function e(e){function s(){t.isFunction(a)&&a.call(n[0]),t.isFunction(e)&&e()}var n=t(this),a=i.complete,r=i.mode;(n.is(":hidden")?"hide"===r:"show"===r)?(n[r](),s()):o.call(n[0],i,s)}var i=s.apply(this,arguments),n=i.mode,a=i.queue,o=t.effects.effect[i.effect];return t.fx.off||!o?n?this[n](i.duration,i.complete):this.each(function(){i.complete&&i.complete.call(this)}):a===!1?this.each(e):this.queue(a||"fx",e)},show:function(t){return function(e){if(n(e))return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="show",this.effect.call(this,i)}}(t.fn.show),hide:function(t){return function(e){if(n(e))return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="hide",this.effect.call(this,i)}}(t.fn.hide),toggle:function(t){return function(e){if(n(e)||"boolean"==typeof e)return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="toggle",this.effect.call(this,i)}}(t.fn.toggle),cssUnit:function(e){var i=this.css(e),s=[];return t.each(["em","px","%","pt"],function(t,e){i.indexOf(e)>0&&(s=[parseFloat(i),e])}),s}})}(),function(){var e={};t.each(["Quad","Cubic","Quart","Quint","Expo"],function(t,i){e[i]=function(e){return Math.pow(e,t+2)}}),t.extend(e,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;((e=Math.pow(2,--i))-1)/11>t;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),t.each(e,function(e,i){t.easing["easeIn"+e]=i,t.easing["easeOut"+e]=function(t){return 1-i(1-t)},t.easing["easeInOut"+e]=function(t){return.5>t?i(2*t)/2:1-i(-2*t+2)/2}})}()})(jQuery);(function(t){var e=/up|down|vertical/,i=/up|left|vertical|horizontal/;t.effects.effect.blind=function(s,n){var a,o,r,l=t(this),h=["position","top","bottom","left","right","height","width"],c=t.effects.setMode(l,s.mode||"hide"),u=s.direction||"up",d=e.test(u),p=d?"height":"width",f=d?"top":"left",g=i.test(u),m={},v="show"===c;l.parent().is(".ui-effects-wrapper")?t.effects.save(l.parent(),h):t.effects.save(l,h),l.show(),a=t.effects.createWrapper(l).css({overflow:"hidden"}),o=a[p](),r=parseFloat(a.css(f))||0,m[p]=v?o:0,g||(l.css(d?"bottom":"right",0).css(d?"top":"left","auto").css({position:"absolute"}),m[f]=v?r:o+r),v&&(a.css(p,0),g||a.css(f,r+o)),a.animate(m,{duration:s.duration,easing:s.easing,queue:!1,complete:function(){"hide"===c&&l.hide(),t.effects.restore(l,h),t.effects.removeWrapper(l),n()}})}})(jQuery);(function(t){t.effects.effect.bounce=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","height","width"],l=t.effects.setMode(o,e.mode||"effect"),h="hide"===l,c="show"===l,u=e.direction||"up",d=e.distance,p=e.times||5,f=2*p+(c||h?1:0),g=e.duration/f,m=e.easing,v="up"===u||"down"===u?"top":"left",_="up"===u||"left"===u,b=o.queue(),y=b.length;for((c||h)&&r.push("opacity"),t.effects.save(o,r),o.show(),t.effects.createWrapper(o),d||(d=o["top"===v?"outerHeight":"outerWidth"]()/3),c&&(a={opacity:1},a[v]=0,o.css("opacity",0).css(v,_?2*-d:2*d).animate(a,g,m)),h&&(d/=Math.pow(2,p-1)),a={},a[v]=0,s=0;p>s;s++)n={},n[v]=(_?"-=":"+=")+d,o.animate(n,g,m).animate(a,g,m),d=h?2*d:d/2;h&&(n={opacity:0},n[v]=(_?"-=":"+=")+d,o.animate(n,g,m)),o.queue(function(){h&&o.hide(),t.effects.restore(o,r),t.effects.removeWrapper(o),i()}),y>1&&b.splice.apply(b,[1,0].concat(b.splice(y,f+1))),o.dequeue()}})(jQuery);(function(t){t.effects.effect.clip=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","height","width"],l=t.effects.setMode(o,e.mode||"hide"),h="show"===l,c=e.direction||"vertical",u="vertical"===c,d=u?"height":"width",p=u?"top":"left",f={};t.effects.save(o,r),o.show(),s=t.effects.createWrapper(o).css({overflow:"hidden"}),n="IMG"===o[0].tagName?s:o,a=n[d](),h&&(n.css(d,0),n.css(p,a/2)),f[d]=h?a:0,f[p]=h?0:a/2,n.animate(f,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){h||o.hide(),t.effects.restore(o,r),t.effects.removeWrapper(o),i()}})}})(jQuery);(function(t){t.effects.effect.drop=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","opacity","height","width"],o=t.effects.setMode(n,e.mode||"hide"),r="show"===o,l=e.direction||"left",h="up"===l||"down"===l?"top":"left",c="up"===l||"left"===l?"pos":"neg",u={opacity:r?1:0};t.effects.save(n,a),n.show(),t.effects.createWrapper(n),s=e.distance||n["top"===h?"outerHeight":"outerWidth"](!0)/2,r&&n.css("opacity",0).css(h,"pos"===c?-s:s),u[h]=(r?"pos"===c?"+=":"-=":"pos"===c?"-=":"+=")+s,n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}})}})(jQuery);(function(t){t.effects.effect.explode=function(e,i){function s(){b.push(this),b.length===u*d&&n()}function n(){p.css({visibility:"visible"}),t(b).remove(),g||p.hide(),i()}var a,o,r,l,h,c,u=e.pieces?Math.round(Math.sqrt(e.pieces)):3,d=u,p=t(this),f=t.effects.setMode(p,e.mode||"hide"),g="show"===f,m=p.show().css("visibility","hidden").offset(),v=Math.ceil(p.outerWidth()/d),_=Math.ceil(p.outerHeight()/u),b=[];for(a=0;u>a;a++)for(l=m.top+a*_,c=a-(u-1)/2,o=0;d>o;o++)r=m.left+o*v,h=o-(d-1)/2,p.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-o*v,top:-a*_}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:v,height:_,left:r+(g?h*v:0),top:l+(g?c*_:0),opacity:g?0:1}).animate({left:r+(g?0:h*v),top:l+(g?0:c*_),opacity:g?1:0},e.duration||500,e.easing,s)}})(jQuery);(function(t){t.effects.effect.fade=function(e,i){var s=t(this),n=t.effects.setMode(s,e.mode||"toggle");s.animate({opacity:n},{queue:!1,duration:e.duration,easing:e.easing,complete:i})}})(jQuery);(function(t){t.effects.effect.fold=function(e,i){var s,n,a=t(this),o=["position","top","bottom","left","right","height","width"],r=t.effects.setMode(a,e.mode||"hide"),l="show"===r,h="hide"===r,c=e.size||15,u=/([0-9]+)%/.exec(c),d=!!e.horizFirst,p=l!==d,f=p?["width","height"]:["height","width"],g=e.duration/2,m={},v={};t.effects.save(a,o),a.show(),s=t.effects.createWrapper(a).css({overflow:"hidden"}),n=p?[s.width(),s.height()]:[s.height(),s.width()],u&&(c=parseInt(u[1],10)/100*n[h?0:1]),l&&s.css(d?{height:0,width:c}:{height:c,width:0}),m[f[0]]=l?n[0]:c,v[f[1]]=l?n[1]:0,s.animate(m,g,e.easing).animate(v,g,e.easing,function(){h&&a.hide(),t.effects.restore(a,o),t.effects.removeWrapper(a),i()})}})(jQuery);(function(t){t.effects.effect.highlight=function(e,i){var s=t(this),n=["backgroundImage","backgroundColor","opacity"],a=t.effects.setMode(s,e.mode||"show"),o={backgroundColor:s.css("backgroundColor")};"hide"===a&&(o.opacity=0),t.effects.save(s,n),s.show().css({backgroundImage:"none",backgroundColor:e.color||"#ffff99"}).animate(o,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===a&&s.hide(),t.effects.restore(s,n),i()}})}})(jQuery);(function(t){t.effects.effect.pulsate=function(e,i){var s,n=t(this),a=t.effects.setMode(n,e.mode||"show"),o="show"===a,r="hide"===a,l=o||"hide"===a,h=2*(e.times||5)+(l?1:0),c=e.duration/h,u=0,d=n.queue(),p=d.length;for((o||!n.is(":visible"))&&(n.css("opacity",0).show(),u=1),s=1;h>s;s++)n.animate({opacity:u},c,e.easing),u=1-u;n.animate({opacity:u},c,e.easing),n.queue(function(){r&&n.hide(),i()}),p>1&&d.splice.apply(d,[1,0].concat(d.splice(p,h+1))),n.dequeue()}})(jQuery);(function(t){t.effects.effect.puff=function(e,i){var s=t(this),n=t.effects.setMode(s,e.mode||"hide"),a="hide"===n,o=parseInt(e.percent,10)||150,r=o/100,l={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()};t.extend(e,{effect:"scale",queue:!1,fade:!0,mode:n,complete:i,percent:a?o:100,from:a?l:{height:l.height*r,width:l.width*r,outerHeight:l.outerHeight*r,outerWidth:l.outerWidth*r}}),s.effect(e)},t.effects.effect.scale=function(e,i){var s=t(this),n=t.extend(!0,{},e),a=t.effects.setMode(s,e.mode||"effect"),o=parseInt(e.percent,10)||(0===parseInt(e.percent,10)?0:"hide"===a?0:100),r=e.direction||"both",l=e.origin,h={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()},c={y:"horizontal"!==r?o/100:1,x:"vertical"!==r?o/100:1};n.effect="size",n.queue=!1,n.complete=i,"effect"!==a&&(n.origin=l||["middle","center"],n.restore=!0),n.from=e.from||("show"===a?{height:0,width:0,outerHeight:0,outerWidth:0}:h),n.to={height:h.height*c.y,width:h.width*c.x,outerHeight:h.outerHeight*c.y,outerWidth:h.outerWidth*c.x},n.fade&&("show"===a&&(n.from.opacity=0,n.to.opacity=1),"hide"===a&&(n.from.opacity=1,n.to.opacity=0)),s.effect(n)},t.effects.effect.size=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","width","height","overflow","opacity"],l=["position","top","bottom","left","right","overflow","opacity"],h=["width","height","overflow"],c=["fontSize"],u=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],d=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=t.effects.setMode(o,e.mode||"effect"),f=e.restore||"effect"!==p,g=e.scale||"both",m=e.origin||["middle","center"],v=o.css("position"),_=f?r:l,b={height:0,width:0,outerHeight:0,outerWidth:0};"show"===p&&o.show(),s={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},"toggle"===e.mode&&"show"===p?(o.from=e.to||b,o.to=e.from||s):(o.from=e.from||("show"===p?b:s),o.to=e.to||("hide"===p?b:s)),a={from:{y:o.from.height/s.height,x:o.from.width/s.width},to:{y:o.to.height/s.height,x:o.to.width/s.width}},("box"===g||"both"===g)&&(a.from.y!==a.to.y&&(_=_.concat(u),o.from=t.effects.setTransition(o,u,a.from.y,o.from),o.to=t.effects.setTransition(o,u,a.to.y,o.to)),a.from.x!==a.to.x&&(_=_.concat(d),o.from=t.effects.setTransition(o,d,a.from.x,o.from),o.to=t.effects.setTransition(o,d,a.to.x,o.to))),("content"===g||"both"===g)&&a.from.y!==a.to.y&&(_=_.concat(c).concat(h),o.from=t.effects.setTransition(o,c,a.from.y,o.from),o.to=t.effects.setTransition(o,c,a.to.y,o.to)),t.effects.save(o,_),o.show(),t.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),m&&(n=t.effects.getBaseline(m,s),o.from.top=(s.outerHeight-o.outerHeight())*n.y,o.from.left=(s.outerWidth-o.outerWidth())*n.x,o.to.top=(s.outerHeight-o.to.outerHeight)*n.y,o.to.left=(s.outerWidth-o.to.outerWidth)*n.x),o.css(o.from),("content"===g||"both"===g)&&(u=u.concat(["marginTop","marginBottom"]).concat(c),d=d.concat(["marginLeft","marginRight"]),h=r.concat(u).concat(d),o.find("*[width]").each(function(){var i=t(this),s={height:i.height(),width:i.width(),outerHeight:i.outerHeight(),outerWidth:i.outerWidth()};f&&t.effects.save(i,h),i.from={height:s.height*a.from.y,width:s.width*a.from.x,outerHeight:s.outerHeight*a.from.y,outerWidth:s.outerWidth*a.from.x},i.to={height:s.height*a.to.y,width:s.width*a.to.x,outerHeight:s.height*a.to.y,outerWidth:s.width*a.to.x},a.from.y!==a.to.y&&(i.from=t.effects.setTransition(i,u,a.from.y,i.from),i.to=t.effects.setTransition(i,u,a.to.y,i.to)),a.from.x!==a.to.x&&(i.from=t.effects.setTransition(i,d,a.from.x,i.from),i.to=t.effects.setTransition(i,d,a.to.x,i.to)),i.css(i.from),i.animate(i.to,e.duration,e.easing,function(){f&&t.effects.restore(i,h)})})),o.animate(o.to,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){0===o.to.opacity&&o.css("opacity",o.from.opacity),"hide"===p&&o.hide(),t.effects.restore(o,_),f||("static"===v?o.css({position:"relative",top:o.to.top,left:o.to.left}):t.each(["top","left"],function(t,e){o.css(e,function(e,i){var s=parseInt(i,10),n=t?o.to.left:o.to.top;return"auto"===i?n+"px":s+n+"px"})})),t.effects.removeWrapper(o),i()}})}})(jQuery);(function(t){t.effects.effect.shake=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","height","width"],o=t.effects.setMode(n,e.mode||"effect"),r=e.direction||"left",l=e.distance||20,h=e.times||3,c=2*h+1,u=Math.round(e.duration/c),d="up"===r||"down"===r?"top":"left",p="up"===r||"left"===r,f={},g={},m={},v=n.queue(),_=v.length;for(t.effects.save(n,a),n.show(),t.effects.createWrapper(n),f[d]=(p?"-=":"+=")+l,g[d]=(p?"+=":"-=")+2*l,m[d]=(p?"-=":"+=")+2*l,n.animate(f,u,e.easing),s=1;h>s;s++)n.animate(g,u,e.easing).animate(m,u,e.easing);n.animate(g,u,e.easing).animate(f,u/2,e.easing).queue(function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}),_>1&&v.splice.apply(v,[1,0].concat(v.splice(_,c+1))),n.dequeue()}})(jQuery);(function(t){t.effects.effect.slide=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","width","height"],o=t.effects.setMode(n,e.mode||"show"),r="show"===o,l=e.direction||"left",h="up"===l||"down"===l?"top":"left",c="up"===l||"left"===l,u={};t.effects.save(n,a),n.show(),s=e.distance||n["top"===h?"outerHeight":"outerWidth"](!0),t.effects.createWrapper(n).css({overflow:"hidden"}),r&&n.css(h,c?isNaN(s)?"-"+s:-s:s),u[h]=(r?c?"+=":"-=":c?"-=":"+=")+s,n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}})}})(jQuery);(function(t){t.effects.effect.transfer=function(e,i){var s=t(this),n=t(e.to),a="fixed"===n.css("position"),o=t("body"),r=a?o.scrollTop():0,l=a?o.scrollLeft():0,h=n.offset(),c={top:h.top-r,left:h.left-l,height:n.innerHeight(),width:n.innerWidth()},d=s.offset(),u=t("<div class='ui-effects-transfer'></div>").appendTo(document.body).addClass(e.className).css({top:d.top-r,left:d.left-l,height:s.innerHeight(),width:s.innerWidth(),position:a?"fixed":"absolute"}).animate(c,e.duration,e.easing,function(){u.remove(),i()})}})(jQuery);
\ No newline at end of file
diff --git a/js/redactor-osticket.js b/js/redactor-osticket.js
index 8cb4de81737beb78afbc895e8d980b7b7fd39064..0fd53146f7e986b754f48e565476dffcf0dbbe18 100644
--- a/js/redactor-osticket.js
+++ b/js/redactor-osticket.js
@@ -130,12 +130,13 @@ $(function() {
                 'air': el.hasClass('no-bar'),
                 'airButtons': ['formatting', '|', 'bold', 'italic', 'deleted', '|', 'unorderedlist', 'orderedlist', 'outdent', 'indent', '|', 'image'],
                 'autoresize': !el.hasClass('no-bar'),
-                'minHeight': 150,
+                'minHeight': el.hasClass('small') ? 75 : 150,
                 'focus': false,
                 'plugins': ['fontcolor','fontfamily'],
                 'imageGetJson': 'ajax.php/draft/images/browse',
                 'syncBeforeCallback': captureImageSizes
             };
+        if (el.data('redactor')) return;
         if (el.hasClass('draft')) {
             var reset = $('input[type=reset]', el.closest('form')),
                 draft_saved = $('<span>')
@@ -174,16 +175,20 @@ $(function() {
                 options['draft_object_id'] = el.data('draftObjectId');
         }
         el.redactor(options);
-    }
-    $('.richtext').each(function(i,el) {
-        if ($(el).hasClass('ifhtml'))
-            // Check if html_thread is enabled first
-            getConfig().then(function(c) {
-                if (c.html_thread)
-                    redact(el);
-            });
-        else
-            // Make a rich text editor immediately
-            redact(el);
-    });
+    },
+    findRichtextBoxes = function() {
+        $('.richtext').each(function(i,el) {
+            if ($(el).hasClass('ifhtml'))
+                // Check if html_thread is enabled first
+                getConfig().then(function(c) {
+                    if (c.html_thread)
+                        redact(el);
+                });
+            else
+                // Make a rich text editor immediately
+                redact(el);
+        });
+    };
+    findRichtextBoxes();
+    $('#user-info').ajaxComplete(findRichtextBoxes);
 });
diff --git a/main.inc.php b/main.inc.php
index 5dd4109d3f6f4b940e95243cfba7901958f877fd..56da2cb710261bb7fa21c04c700aa9823981f669 100644
--- a/main.inc.php
+++ b/main.inc.php
@@ -1,42 +1,43 @@
 <?php
 /*********************************************************************
-    main.inc.php
+main.inc.php
 
-    Master include file which must be included at the start of every file.
-    The brain of the whole sytem. Don't monkey with it.
+Master include file which must be included at the start of every file.
+The brain of the whole sytem. Don't monkey with it.
 
-    Peter Rotich <peter@osticket.com>
-    Copyright (c)  2006-2013 osTicket
-    http://www.osticket.com
+Peter Rotich <peter@osticket.com>
+Copyright (c)  2006-2013 osTicket
+http://www.osticket.com
 
-    Released under the GNU General Public License WITHOUT ANY WARRANTY.
-    See LICENSE.TXT for details.
+Released under the GNU General Public License WITHOUT ANY WARRANTY.
+See LICENSE.TXT for details.
 
-    vim: expandtab sw=4 ts=4 sts=4:
+vim: expandtab sw=4 ts=4 sts=4:
 **********************************************************************/
 
-    #Disable direct access.
-    if(!strcasecmp(basename($_SERVER['SCRIPT_NAME']),basename(__FILE__))) die('kwaheri rafiki!');
+#Disable direct access.
+if(!strcasecmp(basename($_SERVER['SCRIPT_NAME']),basename(__FILE__))) die('kwaheri rafiki!');
 
-    require('bootstrap.php');
-    Bootstrap::loadConfig();
-    Bootstrap::defineTables(TABLE_PREFIX);
-    Bootstrap::connect();
+require('bootstrap.php');
+Bootstrap::loadConfig();
+Bootstrap::defineTables(TABLE_PREFIX);
+Bootstrap::loadCode();
+Bootstrap::connect();
 
-    if(!($ost=osTicket::start()) || !($cfg = $ost->getConfig()))
-        Bootstrap::croak('Unable to load config info from DB. Get tech support.');
+if(!($ost=osTicket::start()) || !($cfg = $ost->getConfig()))
+Bootstrap::croak('Unable to load config info from DB. Get tech support.');
 
-    //Init
-    $session = $ost->getSession();
+//Init
+$session = $ost->getSession();
 
-    //System defaults we might want to make global//
-    #pagenation default - user can override it!
-    define('DEFAULT_PAGE_LIMIT', $cfg->getPageSize()?$cfg->getPageSize():25);
+//System defaults we might want to make global//
+#pagenation default - user can override it!
+define('DEFAULT_PAGE_LIMIT', $cfg->getPageSize()?$cfg->getPageSize():25);
 
-    #Cleanup magic quotes crap.
-    if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
-        $_POST=Format::strip_slashes($_POST);
-        $_GET=Format::strip_slashes($_GET);
-        $_REQUEST=Format::strip_slashes($_REQUEST);
-    }
+#Cleanup magic quotes crap.
+if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
+$_POST=Format::strip_slashes($_POST);
+$_GET=Format::strip_slashes($_GET);
+$_REQUEST=Format::strip_slashes($_REQUEST);
+}
 ?>
diff --git a/open.php b/open.php
index db51e85d395fab9225dbb4ca0efb88df7f7139cb..468f700b562289c56cda08d69c465acec420a63c 100644
--- a/open.php
+++ b/open.php
@@ -30,13 +30,38 @@ if($_POST):
             $errors['captcha']='Invalid - try again!';
     }
 
-    if(!$errors && $cfg->allowOnlineAttachments() && $_FILES['attachments'])
+    $interest = array('subject');
+    if ($topic = Topic::lookup($vars['topicId'])) {
+        if ($form = DynamicForm::lookup($topic->ht['form_id'])) {
+            $form = $form->instanciate();
+            if (!$form->isValid())
+                $errors += $form->errors();
+        }
+    }
+    // Don't process contact information for logged-in clients
+    if (!$thisclient) {
+        $contact_form = UserForm::getInstance();
+        if (!$contact_form->isValid())
+            $errors += $contact_form->errors();
+    }
+
+    if (!$errors && $cfg->allowOnlineAttachments() && $_FILES['attachments'])
         $vars['files'] = AttachmentFile::format($_FILES['attachments'], true);
 
     //Ticket::create...checks for errors..
     if(($ticket=Ticket::create($vars, $errors, SOURCE))){
         $msg='Support ticket request created';
         Draft::deleteForNamespace('ticket.client.'.substr(session_id(), -12));
+        # TODO: Save dynamic form(s)
+        if (isset($form)) {
+            $form->setTicketId($ticket->getId());
+            $form->save();
+            $ticket->loadDynamicData();
+        }
+        if (isset($contact_form)) {
+            $contact_form->setClientId($ticket->getOwnerId());
+            $contact_form->save();
+        }
         //Logged in...simply view the newly created ticket.
         if($thisclient && $thisclient->isValid()) {
             if(!$cfg->showRelatedTickets())
diff --git a/scp/ajax.php b/scp/ajax.php
index 3eeca0f0062e868f67aa660739943b356edd43fe..46fc6385cba5f40b401e5744730bd2763f09dfde 100644
--- a/scp/ajax.php
+++ b/scp/ajax.php
@@ -45,6 +45,13 @@ $dispatcher = patterns('',
     url('^/config/', patterns('ajax.config.php:ConfigAjaxAPI',
         url_get('^scp', 'scp')
     )),
+    url('^/form/', patterns('ajax.forms.php:DynamicFormsAjaxAPI',
+        url_get('^help-topic/(?P<id>\d+)$', 'getFormsForHelpTopic'),
+        url_get('^field-config/(?P<id>\d+)$', 'getFieldConfiguration'),
+        url_post('^field-config/(?P<id>\d+)$', 'saveFieldConfiguration'),
+        url_get('^user-info/(?P<id>\d+)$', 'getUserInfo'),
+        url_post('^user-info/(?P<id>\d+)$', 'saveUserInfo')
+    )),
     url('^/report/overview/', patterns('ajax.reports.php:OverviewReportAjaxAPI',
         # Send
         url_get('^graph$', 'getPlotData'),
diff --git a/scp/css/scp.css b/scp/css/scp.css
index 648d05c1348e68f8ea600ef8338caaf7d5dea101..557f03442b14d53f3ecb72d18207125acc3a337b 100644
--- a/scp/css/scp.css
+++ b/scp/css/scp.css
@@ -295,6 +295,9 @@ a.newDepartment { background:url(../images/icons/new_department.gif) }
 a.pages { background:url(../images/icons/pages.gif) }
 a.newPage { background:url(../images/icons/new_page.gif) }
 
+a.forms { background:url(../images/icons/icon-form.png); background-size: 16px 16px; }
+a.lists { background:url(../images/icons/icon-list.png); background-size: 16px 16px; }
+
 /* Generic CSS based Icons. use=> <tag class="Icon iconname">text</tag> */
 
 .Icon {
@@ -302,6 +305,8 @@ a.newPage { background:url(../images/icons/new_page.gif) }
     padding-left:20px;
     background-position: left center;
     background-repeat: no-repeat;
+    min-height: 16px;
+    display: inline-block;
 }
 
 
@@ -352,6 +357,8 @@ a.Icon:hover {
 .Icon.alertLog { background:url(../images/icons/log_alert.gif) 0 2px no-repeat; }
 .Icon.errorLog { background:url(../images/icons/log_error.gif) 0 2px no-repeat; }
 
+.Icon.form-add { background:url(../images/icons/icon-form-add.png) 0 0 no-repeat; background-size: 16px 16px; }
+.Icon.list-add { background:url(../images/icons/icon-list-add.png) 0 0 no-repeat; background-size: 16px 16px; }
 
 
 #content {
@@ -536,6 +543,8 @@ a.print {
 
 .form_table td.multi-line {
     vertical-align:top;
+    padding-top: 0.4em;
+    padding-bottom: 0.4em;
 }
 
 .form_table input[type=text], .form_table input[type=password], .form_table textarea {
@@ -565,23 +574,31 @@ a.print {
     border:1px solid #f00;
 }
 
-.form_table th {
+.form_table th, div.section-break {
     text-align:left;
     border:1px solid #ccc;
     background:#eee;
     padding:0;
+    padding:5px;
+}
+
+div.section-break h3 {
+    margin: 0;
+    padding: 0;
 }
 
 .form_table th h4 {
-    margin:0;
-    padding:5px;
+    margin: -0.3em -0.3em;
     color:#fff;
     background:#929292;
+    padding: 0.3em;
 }
 
+.form_table th em:not(:first-child) {
+    margin-top: 0.6em;
+}
 .form_table th em {
     display:block;
-    padding:5px;
     color:#000;
 }
 
@@ -1195,13 +1212,13 @@ time {
     background:#f8f8f8;
     border:2px solid #2a67ac;
     display:none;
-    z-index:1200;
+    z-index:5;
     box-shadow: 0 5px 60px #001;
     border-radius: 5px;
 }
 
 .redactor_air {
-    z-index: 1201 !important;
+    z-index: 6 !important;
 }
 
 .dialog#advanced-search {
@@ -1328,6 +1345,14 @@ time {
     background-position:bottom left;
 }
 
+/* Dynamic forms in dialogs */
+.dialog th {
+    background-color: #eee;
+    padding: 0.3em;
+    text-align: left;
+    padding-left: 1em;
+}
+
 #result-count div {
     padding:5px 10px;
     text-align:left;
@@ -1395,7 +1420,7 @@ ul.progress li.no small {color:red;}
     width: 100%;
     height: 100%;
     background: #000;
-    z-index: 1000;
+    z-index: 1;
     -webkit-transform: translate3d(0,0,0);
 }
 
@@ -1455,3 +1480,7 @@ ul.progress li.no small {color:red;}
     display: block;
     opacity: 0.3;
 }
+
+input[type=text]:disabled, input[type=checkbox]:disabled {
+    background-color: #eee;
+}
diff --git a/scp/forms.php b/scp/forms.php
new file mode 100644
index 0000000000000000000000000000000000000000..5c0a2ad0481f53c013cc4cd509d778a91a0dd2ba
--- /dev/null
+++ b/scp/forms.php
@@ -0,0 +1,109 @@
+<?php
+require('admin.inc.php');
+require_once(INCLUDE_DIR."/class.dynamic_forms.php");
+
+$form=null;
+if($_REQUEST['id'] && !($form=DynamicForm::lookup($_REQUEST['id'])))
+    $errors['err']='Unknown or invalid dynamic form ID.';
+
+if($_POST) {
+    $fields = array('title', 'notes', 'instructions');
+    $required = array('subject');
+    $max_sort = 0;
+    switch(strtolower($_POST['do'])) {
+        case 'update':
+            foreach ($fields as $f)
+                if (isset($_POST[$f]))
+                    $form->set($f, $_POST[$f]);
+            if ($form->isValid())
+                $form->save(true);
+            foreach ($form->getDynamicFields() as $field) {
+                $id = $field->get('id');
+                if ($_POST["delete-$id"] == 'on' && $field->isDeletable()) {
+                    $field->delete();
+                    // Don't bother updating the field
+                    continue;
+                }
+                if (isset($_POST["type-$id"]) && $field->isChangeable())
+                    $field->set('type', $_POST["type-$id"]);
+                if (isset($_POST["name-$id"]) && !$field->isNameForced())
+                    $field->set('name', $_POST["name-$id"]);
+                # TODO: make sure all help topics still have all required fields
+                if (!$field->isRequirementForced())
+                    $field->set('required', $_POST["required-$id"] == 'on' ?  1 : 0);
+                if (!$field->isPrivacyForced())
+                    $field->set('private', $_POST["private-$id"] == 'on' ?  1 : 0);
+                foreach (array('sort','label') as $f) {
+                    if (isset($_POST["$f-$id"])) {
+                        $field->set($f, $_POST["$f-$id"]);
+                    }
+                }
+                if ($field->isValid())
+                    $field->save();
+                // Keep track of the last sort number
+                $max_sort = max($max_sort, $field->get('sort'));
+            }
+            break;
+        case 'add':
+            $form = DynamicForm::create(array(
+                'title'=>$_POST['title'],
+                'instructions'=>$_POST['instructions'],
+                'notes'=>$_POST['notes']));
+            if ($form->isValid())
+                $form->save(true);
+            break;
+
+        case 'mass_process':
+            if(!$_POST['ids'] || !is_array($_POST['ids']) || !count($_POST['ids'])) {
+                $errors['err'] = 'You must select at least one API key';
+            } else {
+                $count = count($_POST['ids']);
+                switch(strtolower($_POST['a'])) {
+                    case 'delete':
+                        $i=0;
+                        foreach($_POST['ids'] as $k=>$v) {
+                            if(($t=DynamicForm::lookup($v)) && $t->delete())
+                                $i++;
+                        }
+                        if ($i && $i==$count)
+                            $msg = 'Selected custom forms deleted successfully';
+                        elseif ($i > 0)
+                            $warn = "$i of $count selected forms deleted";
+                        elseif (!$errors['err'])
+                            $errors['err'] = 'Unable to delete selected custom forms';
+                        break;
+                }
+            }
+            break;
+    }
+
+    if ($form) {
+        for ($i=0; isset($_POST["sort-new-$i"]); $i++) {
+            if (!$_POST["label-new-$i"])
+                continue;
+            $field = DynamicFormField::create(array(
+                'form_id'=>$form->get('id'),
+                'sort'=>$_POST["sort-new-$i"] ? $_POST["sort-new-$i"] : $max_sort++,
+                'label'=>$_POST["label-new-$i"],
+                'type'=>$_POST["type-new-$i"],
+                'name'=>$_POST["name-new-$i"],
+                'private'=>$_POST["private-new-$i"] == 'on' ? 1 : 0,
+                'required'=>$_POST["required-new-$i"] == 'on' ? 1 : 0
+            ));
+            if ($field->isValid())
+                $field->save();
+        }
+        // XXX: Move to an instrumented list that can handle this better
+        $form->_dfields = $form->_fields = null;
+    }
+}
+
+$page='dynamic-forms.inc.php';
+if($form || ($_REQUEST['a'] && !strcasecmp($_REQUEST['a'],'add')))
+    $page='dynamic-form.inc.php';
+
+$nav->setTabActive('manage');
+require(STAFFINC_DIR.'header.inc.php');
+require(STAFFINC_DIR.$page);
+include(STAFFINC_DIR.'footer.inc.php');
+?>
diff --git a/scp/helptopics.php b/scp/helptopics.php
index 7cb150741e307951f5d80d1a4ba5d5b30ffeee54..9f34fab9e848a01f36928a266cc6b69d2cb09d09 100644
--- a/scp/helptopics.php
+++ b/scp/helptopics.php
@@ -15,6 +15,7 @@
 **********************************************************************/
 require('admin.inc.php');
 include_once(INCLUDE_DIR.'class.topic.php');
+require_once(INCLUDE_DIR.'class.dynamic_forms.php');
 
 $topic=null;
 if($_REQUEST['id'] && !($topic=Topic::lookup($_REQUEST['id'])))
@@ -95,6 +96,9 @@ if($_POST){
             $errors['err']='Unknown command/action';
             break;
     }
+    if ($id or $topic) {
+        if (!$id) $id=$topic->getId();
+    }
 }
 
 $page='helptopics.inc.php';
diff --git a/scp/images/icons/icon-form-add.png b/scp/images/icons/icon-form-add.png
new file mode 100644
index 0000000000000000000000000000000000000000..55a300f10b9f8ccccd1bc7f8005f03aa9cc03634
Binary files /dev/null and b/scp/images/icons/icon-form-add.png differ
diff --git a/scp/images/icons/icon-form.png b/scp/images/icons/icon-form.png
new file mode 100644
index 0000000000000000000000000000000000000000..810092eeab835eb478442b5971cc92f4a4b0e7e0
Binary files /dev/null and b/scp/images/icons/icon-form.png differ
diff --git a/scp/images/icons/icon-list-add.png b/scp/images/icons/icon-list-add.png
new file mode 100644
index 0000000000000000000000000000000000000000..425e949d33bd31f44e49feffa45fee319e46af32
Binary files /dev/null and b/scp/images/icons/icon-list-add.png differ
diff --git a/scp/images/icons/icon-list.png b/scp/images/icons/icon-list.png
new file mode 100644
index 0000000000000000000000000000000000000000..1b6ac133d500da5c83c7f97cb07d26ce96d9d736
Binary files /dev/null and b/scp/images/icons/icon-list.png differ
diff --git a/scp/js/scp.js b/scp/js/scp.js
index d7db69d13008ea9d98e15b757f0a1b217f735493..961e9e9326516fff7de9bdf98a88ff7b53a4d77b 100644
--- a/scp/js/scp.js
+++ b/scp/js/scp.js
@@ -295,13 +295,14 @@ $(document).ready(function(){
             });
         },
         onselect: function (obj) {
+            $('#basic-ticket-search').val(obj.value);
             $('#basic-ticket-search').closest('form').submit();
         },
-        property: "value"
+        property: "matches"
     });
 
     /* Typeahead user lookup */
-    $('#email.typeahead').typeahead({
+    $('.email.typeahead').typeahead({
         source: function (typeahead, query) {
             if(query.length > 2) {
                 $.ajax({
@@ -314,9 +315,9 @@ $(document).ready(function(){
             }
         },
         onselect: function (obj) {
-            var fObj=$('#email.typeahead').closest('form');
+            var fObj=$('.email.typeahead').closest('form');
             if(obj.name)
-                $('#name', fObj).val(obj.name);
+                $('.auto.name', fObj).val(obj.name);
         },
         property: "email"
     });
@@ -419,6 +420,24 @@ $(document).ready(function(){
                 $('.buttons', elem).show();
              });
     });
+
+   // Return a helper with preserved width of cells
+   var fixHelper = function(e, ui) {
+      ui.children().each(function() {
+          $(this).width($(this).width());
+      });
+      return ui;
+   };
+   // Sortable tables for dynamic forms objects
+   $('.sortable-rows').sortable({
+       'helper': fixHelper,
+       'stop': function(e, ui) {
+           var attr = ui.item.parent('tbody').data('sort');
+           $('input[name^='+attr+']', ui.item.parent('tbody')).each(function(i, el) {
+               $(el).val(i+1);
+           });
+       }
+   });
 });
 
 // NOTE: getConfig should be global
diff --git a/scp/lists.php b/scp/lists.php
new file mode 100644
index 0000000000000000000000000000000000000000..81cf2663d2e4d3cfc3f26bc48dbee0da150cb679
--- /dev/null
+++ b/scp/lists.php
@@ -0,0 +1,92 @@
+<?php
+require('admin.inc.php');
+require_once(INCLUDE_DIR."/class.dynamic_forms.php");
+
+$list=null;
+if($_REQUEST['id'] && !($list=DynamicList::lookup($_REQUEST['id'])))
+    $errors['err']='Unknown or invalid dynamic list ID.';
+
+if($_POST) {
+    $fields = array('name', 'name_plural', 'sort_mode', 'notes');
+    switch(strtolower($_POST['do'])) {
+        case 'update':
+            foreach ($fields as $f)
+                if (isset($_POST[$f]))
+                    $list->set($f, $_POST[$f]);
+            if ($list->isValid())
+                $list->save(true);
+            foreach ($list->getItems() as $item) {
+                $id = $item->get('id');
+                if ($_POST["delete-$id"] == 'on') {
+                    $item->delete();
+                    continue;
+                }
+                foreach (array('sort','value','extra') as $i)
+                    if (isset($_POST["$i-$id"]))
+                        $item->set($i, $_POST["$i-$id"]);
+                if ($item->isValid())
+                    $item->save();
+            }
+            break;
+        case 'add':
+            $list = DynamicList::create(array(
+                'name'=>$_POST['name'],
+                'name_plural'=>$_POST['name_plural'],
+                'sort_mode'=>$_POST['sort_mode'],
+                'notes'=>$_POST['notes']));
+            if ($list->isValid())
+                $list->save(true);
+            break;
+
+        case 'mass_process':
+            if(!$_POST['ids'] || !is_array($_POST['ids']) || !count($_POST['ids'])) {
+                $errors['err'] = 'You must select at least one API key';
+            } else {
+                $count = count($_POST['ids']);
+                switch(strtolower($_POST['a'])) {
+                    case 'delete':
+                        $i=0;
+                        foreach($_POST['ids'] as $k=>$v) {
+                            if(($t=DynamicList::lookup($v)) && $t->delete())
+                                $i++;
+                        }
+                        if ($i && $i==$count)
+                            $msg = 'Selected custom lists deleted successfully';
+                        elseif ($i > 0)
+                            $warn = "$i of $count selected lists deleted";
+                        elseif (!$errors['err'])
+                            $errors['err'] = 'Unable to delete selected custom lists'
+                                .' &mdash; they may be in use on a custom form';
+                        break;
+                }
+            }
+            break;
+    }
+
+    if ($list) {
+        for ($i=0; isset($_POST["sort-new-$i"]); $i++) {
+            if (!$_POST["value-new-$i"])
+                continue;
+            $item = DynamicListItem::create(array(
+                'list_id'=>$list->get('id'),
+                'sort'=>$_POST["sort-new-$i"],
+                'value'=>$_POST["value-new-$i"],
+                'extra'=>$_POST["extra-new-$i"]
+            ));
+            if ($item->isValid())
+                $item->save();
+        }
+        # Invalidate items cache
+        $list->_items = false;
+    }
+}
+
+$page='dynamic-lists.inc.php';
+if($list || ($_REQUEST['a'] && !strcasecmp($_REQUEST['a'],'add')))
+    $page='dynamic-list.inc.php';
+
+$nav->setTabActive('manage');
+require(STAFFINC_DIR.'header.inc.php');
+require(STAFFINC_DIR.$page);
+include(STAFFINC_DIR.'footer.inc.php');
+?>
diff --git a/scp/tickets.php b/scp/tickets.php
index 45d0cd44a9634e4662ab249dba0ae2a73e7b29cb..0fde54a63b35bfb20c1116aacf90836a17ab894e 100644
--- a/scp/tickets.php
+++ b/scp/tickets.php
@@ -20,6 +20,7 @@ require_once(INCLUDE_DIR.'class.dept.php');
 require_once(INCLUDE_DIR.'class.filter.php');
 require_once(INCLUDE_DIR.'class.canned.php');
 require_once(INCLUDE_DIR.'class.json.php');
+require_once(INCLUDE_DIR.'class.dynamic_forms.php');
 
 
 $page='';
@@ -193,12 +194,17 @@ if($_POST && !$errors):
             break;
         case 'edit':
         case 'update':
+            $forms=DynamicFormEntry::forTicket($ticket->getId());
+            foreach ($forms as $form)
+                if (!$form->isValid())
+                    $errors = array_merge($errors, $form->errors());
             if(!$ticket || !$thisstaff->canEditTickets())
                 $errors['err']='Perm. Denied. You are not allowed to edit tickets';
             elseif($ticket->update($_POST,$errors)) {
                 $msg='Ticket updated successfully';
                 $_REQUEST['a'] = null; //Clear edit action - going back to view.
                 //Check to make sure the staff STILL has access post-update (e.g dept change).
+                foreach ($forms as $f) $f->save();
                 if(!$ticket->checkStaffAccess($thisstaff))
                     $ticket=null;
             } elseif(!$errors['err']) {
@@ -451,6 +457,22 @@ if($_POST && !$errors):
                 break;
             case 'open':
                 $ticket=null;
+                $interest=array('name','email','subject');
+                if ($topic=Topic::lookup($_POST['topicId'])) {
+                    if ($form = DynamicForm::lookup($topic->ht['form_id'])) {
+                        $form = $form->instanciate();
+                        # Collect name, email, and subject address for banning and such
+                        foreach ($form->getAnswers() as $answer) {
+                            $fname = $answer->getField()->get('name');
+                            if (in_array($fname, $interest))
+                                # XXX: Assigning to _POST not considered great PHP
+                                #      coding style
+                                $_POST[$fname] = $answer->getField()->getClean();
+                        }
+                        if (!$form->isValid())
+                            $errors = array_merge($errors, $form->errors());
+                    }
+                }
                 if(!$thisstaff || !$thisstaff->canCreateTickets()) {
                      $errors['err']='You do not have permission to create tickets. Contact admin for such access';
                 } else {
@@ -461,7 +483,12 @@ if($_POST && !$errors):
                     if(($ticket=Ticket::open($vars, $errors))) {
                         $msg='Ticket created successfully';
                         $_REQUEST['a']=null;
-                        if(!$ticket->checkStaffAccess($thisstaff) || $ticket->isClosed())
+                        # Save extra dynamic form(s)
+                        if (isset($form)) {
+                            $form->setTicketId($ticket->getId());
+                            $form->save();
+                        }
+                        if (!$ticket->checkStaffAccess($thisstaff) || $ticket->isClosed())
                             $ticket=null;
                         Draft::deleteForNamespace('ticket.staff%', $thisstaff->getId());
                     } elseif(!$errors['err']) {
@@ -555,9 +582,12 @@ if($ticket) {
     $ost->setPageTitle('Ticket #'.$ticket->getNumber());
     $nav->setActiveSubMenu(-1);
     $inc = 'ticket-view.inc.php';
-    if($_REQUEST['a']=='edit' && $thisstaff->canEditTickets())
+    if($_REQUEST['a']=='edit' && $thisstaff->canEditTickets()) {
         $inc = 'ticket-edit.inc.php';
-    elseif($_REQUEST['a'] == 'print' && !$ticket->pdfExport($_REQUEST['psize'], $_REQUEST['notes']))
+        if (!$forms) $forms=DynamicFormEntry::forTicket($ticket->getId());
+        // Auto add new fields to the entries
+        foreach ($forms as $f) $f->addMissingFields();
+    } elseif($_REQUEST['a'] == 'print' && !$ticket->pdfExport($_REQUEST['psize'], $_REQUEST['notes']))
         $errors['err'] = 'Internal error: Unable to export the ticket to PDF for print.';
 } else {
     $inc = 'tickets.inc.php';
diff --git a/setup/doc/forms.md b/setup/doc/forms.md
new file mode 100644
index 0000000000000000000000000000000000000000..c3545096c5e6daaee3ff394eb4b490f9a5a84daa
--- /dev/null
+++ b/setup/doc/forms.md
@@ -0,0 +1,51 @@
+osTicket Forms API
+==================
+
+osTicket now includes a (relatively) complete forms API. Forms can be
+created as objects and used to render their corresponding widgets to the
+screen without actually writing and HTML.
+
+Defining a form
+---------------
+Instanciate a form from a list of fields. PHP unfortunately does not allow
+one to create a class and instanciate a list of instances into a static
+property. Because of this limitation, the field list is specified at the
+form instance construction time by passing the list of fields into the
+constructor.
+
+The simplest way to create forms is to instanciate the Form instance
+directly:
+
+    $form = new Form(array(
+        'email' => new TextboxField(array('label'=>'Email Address')),
+    );
+
+The form can then be rendered to HTML and sent to the user. Later the form
+can be recreated after a POST and the data from the request will
+automatically be placed into the form. Check if the form is valid:
+
+    if ($form->isValid())
+        $object->update($form->getClean());
+
+The `getClean()` method will return a hash array, where the keys are the
+keys in the field array passed to the form constructor, and the values are
+the cleaned values from the form fields based on the data from the request.
+
+To create a class that defines the fields statically, one might write a
+trampoline constructor:
+
+    class UserForm extends Form {
+        function __construct() {
+            $args = func_get_args();
+            $fields = array(
+                'email' => new TextboxField(array(
+                    'label'=>'Email Address')
+                ),
+            );
+            array_unshift($args, $fields);
+            call_user_func_array(array('parent','__construct'), $args);
+        }
+    }
+
+Here, the fields are defined statically in the constructor. Do not bother
+trying to specify the fields in a static property. You'll end up crying.
diff --git a/setup/doc/orm.md b/setup/doc/orm.md
new file mode 100644
index 0000000000000000000000000000000000000000..3a77fc7de41e58534f155cd7b66d5ca1870e7997
--- /dev/null
+++ b/setup/doc/orm.md
@@ -0,0 +1,11 @@
+osTicket ORM
+============
+
+Creating a new model
+--------------------
+Eventually, we will have scripts to create the orm model from a mockup file
+with field definitions, complete with validation routines. Currently, the
+model validation must be written manually, and the fields are assumed based
+on the fields available in the database on fetch, and the name of the field
+updated on update.
+
diff --git a/setup/inc/class.installer.php b/setup/inc/class.installer.php
index 78fd35849c546468251c9151152c4efa73816435..ad2ee14a3c0459dd3b1fee34e52a42d03c85cebe 100644
--- a/setup/inc/class.installer.php
+++ b/setup/inc/class.installer.php
@@ -15,7 +15,6 @@
 **********************************************************************/
 require_once INCLUDE_DIR.'class.migrater.php';
 require_once INCLUDE_DIR.'class.setup.php';
-require_once INCLUDE_DIR.'class.i18n.php';
 
 class Installer extends SetupWizard {
 
@@ -111,6 +110,7 @@ class Installer extends SetupWizard {
         define('ADMIN_EMAIL',$vars['admin_email']); //Needed to report SQL errors during install.
         define('PREFIX',$vars['prefix']); //Table prefix
         Bootstrap::defineTables(PREFIX);
+        Bootstrap::loadCode();
 
         $debug = true; // Change it to false to squelch SQL errors.
 
@@ -141,26 +141,28 @@ class Installer extends SetupWizard {
             }
         }
 
-        // TODO: Use language selected from install worksheet
-        $i18n = new Internationalization('en_US');
-        $i18n->loadDefaultData();
+        if(!$this->errors) {
+            // TODO: Use language selected from install worksheet
+            require_once INCLUDE_DIR.'class.i18n.php';
 
-        $sql='SELECT `id` FROM '.PREFIX.'sla ORDER BY `id` LIMIT 1';
-        $sla_id_1 = db_result(db_query($sql, false), 0);
+            $i18n = new Internationalization('en_US');
+            $i18n->loadDefaultData();
 
-        $sql='SELECT `dept_id` FROM '.PREFIX.'department ORDER BY `dept_id` LIMIT 1';
-        $dept_id_1 = db_result(db_query($sql, false), 0);
+            $sql='SELECT `id` FROM '.PREFIX.'sla ORDER BY `id` LIMIT 1';
+            $sla_id_1 = db_result(db_query($sql, false), 0);
 
-        $sql='SELECT `tpl_id` FROM '.PREFIX.'email_template_group ORDER BY `tpl_id` LIMIT 1';
-        $template_id_1 = db_result(db_query($sql, false), 0);
+            $sql='SELECT `dept_id` FROM '.PREFIX.'department ORDER BY `dept_id` LIMIT 1';
+            $dept_id_1 = db_result(db_query($sql, false), 0);
 
-        $sql='SELECT `group_id` FROM '.PREFIX.'groups ORDER BY `group_id` LIMIT 1';
-        $group_id_1 = db_result(db_query($sql, false), 0);
+            $sql='SELECT `tpl_id` FROM '.PREFIX.'email_template_group ORDER BY `tpl_id` LIMIT 1';
+            $template_id_1 = db_result(db_query($sql, false), 0);
 
-        $sql='SELECT `id` FROM '.PREFIX.'timezone WHERE offset=-5.0 LIMIT 1';
-        $eastern_timezone = db_result(db_query($sql, false), 0);
+            $sql='SELECT `group_id` FROM '.PREFIX.'groups ORDER BY `group_id` LIMIT 1';
+            $group_id_1 = db_result(db_query($sql, false), 0);
+
+            $sql='SELECT `id` FROM '.PREFIX.'timezone WHERE offset=-5.0 LIMIT 1';
+            $eastern_timezone = db_result(db_query($sql, false), 0);
 
-        if(!$this->errors) {
             //Create admin user.
             $sql='INSERT INTO '.PREFIX.'staff SET created=NOW() '
                 .", isactive=1, isadmin=1, group_id=$group_id_1, dept_id=$dept_id_1"
@@ -232,25 +234,22 @@ class Installer extends SetupWizard {
             .", autoresp_email_id=$support_email_id";
         db_query($sql, false);
 
+        global $cfg;
+        $cfg = new OsticketConfig();
+
         //Create a ticket to make the system warm and happy.
-        $sql='INSERT INTO '.PREFIX.'ticket SET created=NOW(), status="open", source="Web" '
-            ." ,priority_id=0, dept_id=$dept_id_1, topic_id=0 "
-            .' ,ticketID='.db_input(Misc::randNumber(6))
-            .' ,email="support@osticket.com" '
-            .' ,name="osTicket Support" '
-            .' ,subject="osTicket Installed!"';
-        if(db_query($sql, false) && ($tid=db_insert_id())) {
-            if(!($msg=file_get_contents(INC_DIR.'msg/installed.txt')))
-                $msg='Congratulations and Thank you for choosing osTicket!';
-
-            $sql='INSERT INTO '.PREFIX.'ticket_thread SET created=NOW()'
-                .', source="Web" '
-                .', thread_type="M" '
-                .', ticket_id='.db_input($tid)
-                .', title='.db_input('osTicket Installed')
-                .', body='.db_input($msg);
-            db_query($sql, false);
-        }
+        if(!($msg=file_get_contents(INC_DIR.'msg/installed.txt')))
+            $msg='Congratulations and Thank you for choosing osTicket!';
+        $errors = array();
+        $tid = Ticket::create(array(
+            'email' =>      'support@osticket.com',
+            'name' =>       'osTicket Support',
+            'subject' =>    'osTicket Installed!',
+            'message' =>    $msg,
+            'source' =>     'email',
+            'deptId' =>     $dept_id_1),
+            $errors,
+            'api', false, false);
         //TODO: create another personalized ticket and assign to admin??
 
         //Log a message.
diff --git a/setup/inc/streams/core/install-mysql.sql b/setup/inc/streams/core/install-mysql.sql
index 4891bcb0f9023b7cf97a1facd84b7bd19e54cc7c..e5859e815129110747cd04653679859e6ce9c2f8 100644
--- a/setup/inc/streams/core/install-mysql.sql
+++ b/setup/inc/streams/core/install-mysql.sql
@@ -170,6 +170,85 @@ INSERT INTO `%TABLE_PREFIX%config` (`namespace`, `key`, `value`) VALUES
   ('core', 'helpdesk_url', ''),
   ('core', 'schema_signature', '');
 
+DROP TABLE IF EXISTS `%TABLE_PREFIX%form`;
+CREATE TABLE `%TABLE_PREFIX%form` (
+    `id` int(11) unsigned NOT NULL auto_increment,
+    `type` char(1) NOT NULL DEFAULT 'G',
+    `deletable` tinyint(1) NOT NULL DEFAULT 1,
+    `title` varchar(255) NOT NULL,
+    `instructions` varchar(512),
+    `notes` text,
+    `created` datetime NOT NULL,
+    `updated` datetime NOT NULL,
+    PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%form_field`;
+CREATE TABLE `%TABLE_PREFIX%form_field` (
+    `id` int(11) unsigned NOT NULL auto_increment,
+    `form_id` int(11) unsigned NOT NULL,
+    `type` varchar(255) NOT NULL DEFAULT 'text',
+    `label` varchar(255) NOT NULL,
+    `required` tinyint(1) NOT NULL DEFAULT 0,
+    `private` tinyint(1) NOT NULL DEFAULT 0,
+    `edit_mask` tinyint(1) NOT NULL DEFAULT 0,
+    `name` varchar(64) NOT NULL,
+    `configuration` text,
+    `sort` int(11) unsigned NOT NULL,
+    `hint` varchar(512),
+    `created` datetime NOT NULL,
+    `updated` datetime NOT NULL,
+    PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%form_entry`;
+CREATE TABLE `%TABLE_PREFIX%form_entry` (
+    `id` int(11) unsigned NOT NULL auto_increment,
+    `form_id` int(11) unsigned NOT NULL,
+    `object_id` int(11) unsigned,
+    `object_type` char(1) NOT NULL DEFAULT 'T',
+    `sort` int(11) unsigned NOT NULL DEFAULT 1,
+    `created` datetime NOT NULL,
+    `updated` datetime NOT NULL,
+    PRIMARY KEY (`id`),
+    KEY `entry_lookup` (`object_id`, `object_type`)
+) DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%form_entry_values`;
+CREATE TABLE `%TABLE_PREFIX%form_entry_values` (
+    -- references form_entry.id
+    `entry_id` int(11) unsigned NOT NULL,
+    `field_id` int(11) unsigned NOT NULL,
+    `value` text,
+    `value_id` int(11),
+    PRIMARY KEY (`entry_id`, `field_id`)
+) DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%list`;
+CREATE TABLE `%TABLE_PREFIX%list` (
+    `id` int(11) unsigned NOT NULL auto_increment,
+    `name` varchar(255) NOT NULL,
+    `name_plural` varchar(255),
+    `sort_mode` enum('Alpha', '-Alpha', 'SortCol') NOT NULL DEFAULT 'Alpha',
+    `notes` text,
+    `created` datetime NOT NULL,
+    `updated` datetime NOT NULL,
+    PRIMARY KEY (`id`)
+) DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%list_items`;
+CREATE TABLE `%TABLE_PREFIX%list_items` (
+    `id` int(11) unsigned NOT NULL auto_increment,
+    `list_id` int(11),
+    `value` varchar(255) NOT NULL,
+    -- extra value such as abbreviation
+    `extra` varchar(255),
+    `sort` int(11) NOT NULL DEFAULT 1,
+    PRIMARY KEY (`id`),
+    KEY `list_item_lookup` (`list_id`)
+) DEFAULT CHARSET=utf8;
+
+
 DROP TABLE IF EXISTS `%TABLE_PREFIX%department`;
 CREATE TABLE `%TABLE_PREFIX%department` (
   `dept_id` int(11) unsigned NOT NULL auto_increment,
@@ -258,6 +337,7 @@ CREATE TABLE `%TABLE_PREFIX%filter` (
   `staff_id` int(10) unsigned NOT NULL default '0',
   `team_id` int(10) unsigned NOT NULL default '0',
   `sla_id` int(10) unsigned NOT NULL default '0',
+  `form_id` int(11) unsigned NOT NULL default '0',
   `target` ENUM(  'Any',  'Web',  'Email',  'API' ) NOT NULL DEFAULT  'Any',
   `name` varchar(32) NOT NULL default '',
   `notes` text,
@@ -272,7 +352,7 @@ DROP TABLE IF EXISTS `%TABLE_PREFIX%filter_rule`;
 CREATE TABLE `%TABLE_PREFIX%filter_rule` (
   `id` int(11) unsigned NOT NULL auto_increment,
   `filter_id` int(10) unsigned NOT NULL default '0',
-  `what` enum('name','email','subject','body','header') NOT NULL,
+  `what` varchar(32) NOT NULL,
   `how` enum('equal','not_equal','contains','dn_contain','starts','ends') NOT NULL,
   `val` varchar(255) NOT NULL,
   `isactive` tinyint(1) unsigned NOT NULL DEFAULT '1',
@@ -376,6 +456,7 @@ CREATE TABLE `%TABLE_PREFIX%help_topic` (
   `team_id` int(10) unsigned NOT NULL default '0',
   `sla_id` int(10) unsigned NOT NULL default '0',
   `page_id` int(10) unsigned NOT NULL default '0',
+  `form_id` int(10) unsigned NOT NULL default '0',
   `topic` varchar(32) NOT NULL default '',
   `notes` text,
   `created` datetime NOT NULL,
@@ -502,17 +583,13 @@ DROP TABLE IF EXISTS `%TABLE_PREFIX%ticket`;
 CREATE TABLE `%TABLE_PREFIX%ticket` (
   `ticket_id` int(11) unsigned NOT NULL auto_increment,
   `ticketID` int(11) unsigned NOT NULL default '0',
+  `user_id` int(11) unsigned NOT NULL default '0',
+  `user_email_id` int(11) unsigned NOT NULL default '0',
   `dept_id` int(10) unsigned NOT NULL default '0',
   `sla_id` int(10) unsigned NOT NULL default '0',
-  `priority_id` int(10) unsigned NOT NULL default '0',
   `topic_id` int(10) unsigned NOT NULL default '0',
   `staff_id` int(10) unsigned NOT NULL default '0',
   `team_id` int(10) unsigned NOT NULL default '0',
-  `email` varchar(255) NOT NULL default '',
-  `name` varchar(255) NOT NULL default '',
-  `subject` varchar(255) NOT NULL default '[no subject]',
-  `phone` varchar(16) default NULL,
-  `phone_ext` varchar(8) default NULL,
   `ip_address` varchar(64) NOT NULL default '',
   `status` enum('open','closed') NOT NULL default 'open',
   `source` enum('Web','Email','Phone','API','Other') NOT NULL default 'Other',
@@ -526,12 +603,10 @@ CREATE TABLE `%TABLE_PREFIX%ticket` (
   `created` datetime NOT NULL,
   `updated` datetime NOT NULL,
   PRIMARY KEY  (`ticket_id`),
-  UNIQUE KEY `email_extid` (`ticketID`,`email`),
   KEY `dept_id` (`dept_id`),
   KEY `staff_id` (`staff_id`),
   KEY `team_id` (`staff_id`),
   KEY `status` (`status`),
-  KEY `priority_id` (`priority_id`),
   KEY `created` (`created`),
   KEY `closed` (`closed`),
   KEY `duedate` (`duedate`),
@@ -677,3 +752,23 @@ CREATE TABLE IF NOT EXISTS `%TABLE_PREFIX%page` (
   PRIMARY KEY  (`id`),
   UNIQUE KEY `name` (`name`)
 ) DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%user`;
+CREATE TABLE `%TABLE_PREFIX%user` (
+  `id` int(10) unsigned NOT NULL auto_increment,
+  `default_email_id` int(10) NOT NULL,
+  `name` varchar(128) NOT NULL,
+  `created` datetime NOT NULL,
+  `updated` datetime NOT NULL,
+  PRIMARY KEY  (`id`)
+) DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%user_email`;
+CREATE TABLE `%TABLE_PREFIX%user_email` (
+  `id` int(10) unsigned NOT NULL auto_increment,
+  `user_id` int(10) unsigned NOT NULL,
+  `address` varchar(128) NOT NULL,
+  PRIMARY KEY  (`id`),
+  UNIQUE KEY `address` (`address`),
+  KEY `user_email_lookup` (`user_id`)
+) DEFAULT CHARSET=utf8;
diff --git a/setup/setup.inc.php b/setup/setup.inc.php
index c68bd7a62a2c9658411f36cd0fe4bd7cd0dee41f..6eb4a495fb3c2a98350b033a0a80a88f3d25fa48 100644
--- a/setup/setup.inc.php
+++ b/setup/setup.inc.php
@@ -14,9 +14,6 @@
     vim: expandtab sw=4 ts=4 sts=4:
 **********************************************************************/
 
-#This  version - changed on every release
-define('THIS_VERSION', '1.8-git');
-
 #inits - error reporting.
 $error_reporting = E_ALL & ~E_NOTICE;
 if (defined('E_STRICT')) # 5.4.0