diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php
index e4fdafcc25a8a72fa2d0eb0cb721eebafd5feae5..9c13bd5e4affb8cb17d6e5e7c42cc428509f1d4f 100644
--- a/include/ajax.tickets.php
+++ b/include/ajax.tickets.php
@@ -695,5 +695,274 @@ class TicketsAjaxAPI extends AjaxController {
 
         return $canned->getFormattedResponse($format, $varReplacer);
     }
+
+    function changeTicketStatus($tid, $status) {
+        global $thisstaff;
+
+        if (!$thisstaff)
+            Http::response(403, 'Access denied');
+        elseif (!$tid
+                || !($ticket=Ticket::lookup($tid))
+                || !$ticket->checkStaffAccess($thisstaff))
+            Http::response(404, 'Unknown ticket #');
+
+        $info = array();
+        switch($status) {
+            case 'open':
+            case 'reopen':
+                $state = 'open';
+                $info['title'] =  __('Reopen');
+                break;
+            case 'resolve':
+                $state = 'resolved';
+                $info['title'] = __('Resolve');
+                break;
+            case 'close':
+                if (!$thisstaff->canCloseTickets())
+                    Http::response(403, 'Access denied');
+                $state = 'closed';
+                $info['title'] = __('Close');
+                break;
+            case 'archive':
+                if (!$thisstaff->canCloseTickets())
+                    Http::response(403, 'Access denied');
+
+                $state = 'archived';
+                $info['title'] = __('Archive');
+                break;
+            case 'delete':
+                if (!$thisstaff->canDeleteTickets())
+                    Http::response(403, 'Access denied');
+                $state = 'deleted';
+                $info = array(
+                        'title' => __('Delete'),
+                        'warn'  => sprintf(__('Are you sure you want to DELETE %s?'),
+                            __('this ticket')),
+                        //TODO: remove message below once we ship data retention plug
+                        'extra' => sprintf('<strong>%s</strong>',
+                            __('Deleted tickets CANNOT be recovered,
+                                including any associated attachments.')));
+                break;
+            default:
+                Http::response(404, 'Unknown status/action');
+        }
+
+        $info['action'] = sprintf('#tickets/%d/status/%s', $ticket->getId(), $status);
+        $info['title'] .= sprintf(' %s #%s', __('Ticket'), $ticket->getNumber());
+        $info['status_id'] = $_REQUEST['status_id'] ?: $ticket->getStatusId();
+
+        return self::_setStatus($state, $info);
+    }
+
+    function setTicketStatus($tid, $state) {
+        global $thisstaff, $ost;
+
+        if (!$thisstaff)
+            Http::response(403, 'Access denied');
+        elseif (!$tid
+                || !($ticket=Ticket::lookup($tid))
+                || !$ticket->checkStaffAccess($thisstaff))
+            Http::response(404, 'Unknown ticket #');
+
+        if (!($status= TicketStatus::lookup($_REQUEST['status_id'])))
+            $errors['status_id'] = sprintf('%s %s',
+                    __('Unknown or invalid'), __('status'));
+        elseif (!$errors) {
+            // Make sure the agent has permission to set the status
+            switch(mb_strtolower($status->getState())) {
+                case 'open':
+                    if (!$thisstaff->canCloseTickets()
+                            && !$thisstaff->canCreateTickets())
+                        $errors['err'] = sprintf(__('You do not have
+                                    permission to %s.'),
+                                __('reopen tickets'));
+                    break;
+                case 'resolved':
+                case 'closed':
+                    if (!$thisstaff->canCloseTickets())
+                        $errors['err'] = sprintf(__('You do not have
+                                    permission to %s.'),
+                                __('resolve/close tickets'));
+                    break;
+                case 'archived':
+                case 'deleted':
+                    if (!$thisstaff->canDeleteTickets())
+                        $errors['err'] = sprintf(__('You do not have
+                                    permission to %s.'),
+                                __('archive/delete tickets'));
+                    break;
+            }
+        }
+
+        if ($ticket->setStatus($status, $_REQUEST['comments'])) {
+            $_SESSION['::sysmsgs']['msg'] = sprintf(
+                    __('Successfully updated status to %s'),
+                    $status->getName());
+            Http::response(201, 'Successfully processed');
+        }
+
+        $errors['err'] = __('Error updating ticket status');
+        $info['errors'] = $errors;
+        return self::_setStatus($state, $info);
+    }
+    function changeTicketsStatus($status, $id=0) {
+        global $thisstaff, $cfg;
+
+        if (!$thisstaff)
+            Http::response(403, 'Access denied');
+
+        $state = null;
+        $info = array();
+        switch($status) {
+            case 'open':
+            case 'reopen':
+                $state = 'open';
+                $info = array(
+                        'title' => sprintf('%s %s',
+                            __('Reopen'), __('Tickets'))
+                        );
+                break;
+            case 'resolve':
+                $state = 'resolved';
+                $info = array(
+                        'title' => sprintf('%s %s',
+                            __('Resolve'), __('Tickets'))
+                        );
+                break;
+            case 'close':
+                if (!$thisstaff->canCloseTickets())
+                    Http::response(403, 'Access denied');
+                $state = 'closed';
+                $info = array(
+                        'title' => sprintf('%s %s',
+                            __('Close'), __('Tickets'))
+                        );
+                break;
+            case 'archive':
+                if (!$thisstaff->canCloseTickets())
+                    Http::response(403, 'Access denied');
+
+                $state = 'archived';
+                $info = array(
+                        'title' => sprintf('%s %s',
+                            __('Archive'), __('Tickets')),
+                        );
+                break;
+            case 'delete':
+                if (!$thisstaff->canDeleteTickets())
+                    Http::response(403, 'Access denied');
+
+                $state = 'deleted';
+                $info = array(
+                        'title' => sprintf('%s %s',
+                            __('Delete'), __('Tickets')),
+                        'warn'  => sprintf(__('Are you sure you want to DELETE %s?'),
+                            _N('selected ticket', 'selected tickets', $_REQUEST['count'])),
+                        //TODO: remove message below once we ship data retention plug
+                        'extra' => sprintf('<strong>%s</strong>',
+                            __('Deleted tickets CANNOT be recovered,
+                                including any associated attachments.')));
+                break;
+            default:
+                Http::response(404, 'Unknown status/action');
+        }
+
+        if ($_REQUEST['count'])
+            $info['title'] .= sprintf(' &mdash; %d selected', $_REQUEST['count']);
+
+        $info['status_id'] = $id;
+
+        return self::_setStatus($state, $info);
+    }
+
+    function setTicketsStatus($state) {
+        global $thisstaff, $ost;
+
+        $errors = array();
+        if (!$thisstaff || !$thisstaff->canManageTickets())
+            $errors['err']=__('You do not have permission to mass manage tickets. Contact admin for such access');
+        elseif (!$_REQUEST['tids'] || !count($_REQUEST['tids']))
+            $errors['err']=sprintf(__('You must select at least %s.'),
+                    __('one ticket'));
+        elseif (!($status= TicketStatus::lookup($_REQUEST['status_id'])))
+            $errors['status_id'] = sprintf('%s %s',
+                    __('Unknown or invalid'), __('status'));
+        elseif (!$errors) {
+            // Make sure the agent has permission to set the status
+            switch(mb_strtolower($status->getState())) {
+                case 'open':
+                    if (!$thisstaff->canCloseTickets()
+                            && !$thisstaff->canCreateTickets())
+                        $errors['err'] = sprintf(__('You do not have
+                                    permission to %s.'),
+                                __('reopen tickets'));
+                    break;
+                case 'resolved':
+                case 'closed':
+                    if (!$thisstaff->canCloseTickets())
+                        $errors['err'] = sprintf(__('You do not have
+                                    permission to %s.'),
+                                __('resolve/close tickets'));
+                    break;
+                case 'archived':
+                case 'deleted':
+                    if (!$thisstaff->canDeleteTickets())
+                        $errors['err'] = sprintf(__('You do not have
+                                    permission to %s.'),
+                                __('archive/delete tickets'));
+                    break;
+            }
+        }
+
+        if (!$errors) {
+            $i = 0;
+            $count = count($_REQUEST['tids']);
+            $comments = $_REQUEST['comments'];
+            foreach ($_REQUEST['tids'] as $tid) {
+                if (($ticket=Ticket::lookup($tid))
+                        && $ticket->getStatusId() != $status->getId()
+                        && $ticket->checkStaffAccess($thisstaff)
+                        && $ticket->setStatus($status, $comments))
+                    $i++;
+            }
+
+            if (!$i)
+                $errors['err'] = sprintf(__('Unable to set status for %s'),
+                        _N('selected ticket', 'selected tickets', $count));
+            else {
+                // Assume success
+                if ($i==$count) {
+                    $_SESSION['::sysmsgs']['msg'] = sprintf(
+                            __('Successfully updated %s status to %s'),
+                            _N('selected ticket', 'selected tickets',
+                                $count),
+                            $status->getName());
+                } else {
+                    $_SESSION['::sysmsgs']['warn'] = sprintf(
+                            __('%1$d of %2$d %3$s status updated to %4$s'),$i, $count,
+                            _N('selected ticket', 'selected tickets',
+                                $count),
+                            $status->getName());
+                }
+
+                Http::response(201, 'Successfully processed');
+            }
+        }
+
+        $info['errors'] = $errors;
+        return self::_setStatus($state, $info);
+    }
+
+    function _setStatus($state, $info=array()) {
+
+        $errors = array();
+        if ($info && isset($info['errors']))
+            $errors = $info['errors'];
+
+        if (!$info['error'] && isset($errors['err']))
+            $info['error'] = $errors['err'];
+
+        include(STAFFINC_DIR . 'templates/ticket-status.tmpl.php');
+    }
 }
 ?>
diff --git a/include/class.list.php b/include/class.list.php
index 326afa828fe7c96a5a005de687d755fbefde0834..03ac2a2d1fde3fb20b2ee7e55548da1614bd5ae3 100644
--- a/include/class.list.php
+++ b/include/class.list.php
@@ -999,9 +999,9 @@ class TicketStatus  extends VerySimpleModel implements CustomListItem {
 
         return $status;
     }
-}
-
-
-
 
+    static function options() {
+        include(STAFFINC_DIR . 'templates/status-options.tmpl.php');
+    }
+}
 ?>
diff --git a/include/staff/templates/status-options.tmpl.php b/include/staff/templates/status-options.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..5b383e31d46a4ecf97b91e46ff7fd9990deb2035
--- /dev/null
+++ b/include/staff/templates/status-options.tmpl.php
@@ -0,0 +1,71 @@
+<?php
+$actions= array(
+        'delete' => array(
+            'action'  => __('Delete'),
+            'icon'  => 'icon-trash',
+            'states' => array('deleted'),
+            ),
+        'archive' => array(
+            'action'  => __('Archive'),
+            'icon' => 'icon-archive',
+            'states' => array('archived')
+            ),
+        'close' => array(
+            'action' => __('Close'),
+            'icon'  => 'icon-repeat',
+            'states' => array('closed')
+            ),
+        'resolve' => array(
+            'action' => __('Resolve'),
+            'icon'  => 'icon-ok-circle',
+            'states' => array('resolved')
+            ),
+        'reopen' => array(
+            'action' =>  __('Reopen'),
+            'icon'  => 'icon-undo',
+            'states' => array('open')
+            ),
+        );
+
+foreach($actions as $k => $v) {
+    $criteria = array('states' => $v['states']);
+    if (!($statuses = TicketStatusList::getStatuses($criteria)->all()))
+        continue;
+
+    if ($statuses && count($statuses) > 1) {
+    ?>
+        <span
+            class="action-button"
+            data-dropdown="#action-dropdown-<?php echo $k; ?>">
+            <a id="tickets-<?php echo $k; ?>"
+                class="tickets-action"
+                href="#tickets/status/<?php echo $k; ?>"><i
+                class="<?php echo $v['icon']; ?>"></i> <?php echo $v['action']; ?></a>
+            <i class="icon-caret-down"></i>
+        </span>
+        <div id="action-dropdown-<?php echo $k; ?>"
+            class="action-dropdown anchor-right">
+          <ul>
+            <?php
+            foreach ($statuses as $s) {
+                ?>
+
+             <li>
+                 <a class="no-pjax tickets-action"
+                    href="#tickets/status/<?php echo $k; ?>/<?php
+                    echo $s->getId(); ?>"> <i
+                        class="icon-tag"></i> <?php echo $s->getName(); ?></a> </li>
+            <?php
+            } ?>
+          </ul>
+        </div>
+    <?php
+    } else {
+    ?>
+        <a id="tickets-<?php echo $k; ?>" class="action-button tickets-action"
+            href="#tickets/status/<?php echo $k; ?>"><i
+            class="<?php echo $v['icon']; ?>"></i> <?php echo $v['action']; ?></a>
+<?php
+    }
+}
+?>
diff --git a/include/staff/templates/ticket-status.tmpl.php b/include/staff/templates/ticket-status.tmpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..6703ca1b017cfb5bf69710062ae923ffdbad78ba
--- /dev/null
+++ b/include/staff/templates/ticket-status.tmpl.php
@@ -0,0 +1,116 @@
+<?php
+global $cfg;
+
+if (!$info['title'])
+    $info['title'] = 'Change Tickets Status';
+
+?>
+<h3><?php echo $info['title']; ?></h3>
+<b><a class="close" href="#"><i class="icon-remove-circle"></i></a></b>
+<div class="clear"></div>
+<hr/>
+<?php
+if ($info['error']) {
+    echo sprintf('<p id="msg_error">%s</p>', $info['error']);
+} elseif ($info['warn']) {
+    echo sprintf('<p id="msg_warning">%s</p>', $info['warn']);
+} elseif ($info['msg']) {
+    echo sprintf('<p id="msg_notice">%s</p>', $info['msg']);
+} elseif ($info['notice']) {
+   echo sprintf('<p id="msg_info"><i class="icon-info-sign"></i> %s</p>',
+           $info['notice']);
+}
+
+
+$action = $info['action'] ?: ('#tickets/status/'. $state);
+?>
+<div id="ticket-status" style="display:block; margin:5px;">
+    <form method="post" name="status" id="status"
+        action="<?php echo $action; ?>">
+        <table width="100%">
+            <?php
+            if ($info['extra']) {
+                ?>
+            <tbody>
+                <tr><td colspan="2"><strong><?php echo $info['extra'];
+                ?></strong></td> </tr>
+                <tr><td colspan="2">&nbsp;</td></tr>
+            </tbody>
+            <?php
+            }
+            if ($state)
+                $statuses = TicketStatusList::getStatuses(array('states'=>array($state)))->all();
+
+            if ($statuses) {
+            ?>
+            <tbody>
+                <tr>
+                    <td colspan=2>
+                        <span>
+                        <?php echo __('Status') ?>:&nbsp;
+                        <?php
+                        if (count($statuses) > 1) { ?>
+                            <select name="status_id">
+                            <?php
+                            foreach ($statuses as $s) {
+                                echo sprintf('<option value="%d" %s>%s</option>',
+                                        $s->getId(),
+                                        ($info['status_id'] == $s->getId())
+                                         ? 'selected="selected"' : '',
+                                        $s->getName()
+                                        );
+                            }
+                            ?>
+                            </select>
+                            <font class="error">*&nbsp;<?php echo $errors['status_id']; ?></font>
+                        <?php
+                        } elseif ($statuses[0]) {
+                            echo __($statuses[0]->getName());
+                            echo  "<input type='hidden' name='status_id' value={$statuses[0]->getId()} />";
+                        } ?>
+                        </span>
+                    </td>
+                </tr>
+            </tbody>
+            <?php
+            } ?>
+            <tbody>
+                <tr>
+                    <td colspan="2">
+                        <em>Reasons for status change (internal note): Optional but highly recommended.</em>
+                    </td>
+                </tr>
+                <tr>
+                    <td colspan="2">
+                        <textarea name="comments" id="comments"
+                            cols="50" rows="3" wrap="soft" style="width:100%"
+                            class="richtext ifhtml no-bar"><?php
+                            echo $info['notes']; ?></textarea>
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+        <hr>
+        <p class="full-width">
+            <span class="buttons" style="float:left">
+                <input type="reset" value="<?php echo __('Reset'); ?>">
+                <input type="button" name="cancel" class="close"
+                value="<?php echo __('Cancel'); ?>">
+            </span>
+            <span class="buttons" style="float:right">
+                <input type="submit" value="<?php echo __('Submit'); ?>">
+            </span>
+         </p>
+    </form>
+</div>
+<div class="clear"></div>
+<script type="text/javascript">
+$(function() {
+    // Copy checked tickets to status form.
+    $('form#tickets input[name="tids[]"]:checkbox:checked')
+    .clone()
+    .prop('type', 'hidden')
+    .removeAttr('class')
+    .appendTo('form#status');
+ });
+</script>
diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php
index 07c57c2678658728f7568bfcee663d0ed4a17d8a..cd0099386886315d69f03eff4c5ef922cf19effe 100644
--- a/include/staff/ticket-view.inc.php
+++ b/include/staff/ticket-view.inc.php
@@ -56,17 +56,17 @@ if($ticket->isOverdue())
             </span>
             <?php
             }
-            if ($thisstaff->canDeleteTickets()) { ?>
-                <a id="ticket-delete" class="action-button confirm-action" href="#delete"><i class="icon-trash"></i> <?php
-                    echo __('Delete'); ?></a>
-            <?php
-            }
             if($thisstaff->canCloseTickets()) {
                 if($ticket->isOpen()) {?>
-                <a id="ticket-close" class="action-button" href="#close"><i class="icon-remove-circle"></i> <?php echo __('Close');?></a>
+                <a class="action-button ticket-action"
+                    href="#tickets/<?php echo $ticket->getId()
+                    ?>/status/close"><i class="icon-remove-circle"></i> <?php echo __('Close');?></a>
                 <?php
                 } else { ?>
-                <a id="ticket-reopen" class="action-button" href="#reopen"><i class="icon-undo"></i> <?php echo __('Reopen');?></a>
+                <a class="action-button ticket-action"
+                    href="#tickets/<?php echo $ticket->getId()
+                    ?>/status/reopen"><i class="icon-undo"></i> <?php echo
+                    __('Reopen');?></a>
                 <?php
                 }
             }
@@ -100,7 +100,19 @@ if($ticket->isOverdue())
                  if($thisstaff->canEditTickets()) { ?>
                     <li><a class="change-user" href="#tickets/<?php
                     echo $ticket->getId(); ?>/change-user"><i class="icon-user"></i> <?php
-                    echo __('Change Ticket Owner'); ?></a></li>
+                    echo __('Change Owner'); ?></a></li>
+                <?php
+                 }
+                 if($thisstaff->canDeleteTickets()) {
+                     if (!$ticket->isArchived()) { ?>
+                    <li><a class="ticket-action" href="#tickets/<?php
+                    echo $ticket->getId(); ?>/status/archive"><i class="icon-archive"></i> <?php
+                    echo __('Archive Ticket'); ?></a></li>
+                    <?php
+                     } ?>
+                    <li><a class="ticket-action" href="#tickets/<?php
+                    echo $ticket->getId(); ?>/status/delete"><i class="icon-trash"></i> <?php
+                    echo __('Delete Ticket'); ?></a></li>
                 <?php
                  }
                 if($ticket->isOpen() && ($dept && $dept->isManager($thisstaff))) {
@@ -932,67 +944,6 @@ $tcount+= $ticket->getNumNotes();
     </form>
     <div class="clear"></div>
 </div>
-<div style="display:none;" class="dialog" id="ticket-status">
-    <h3><?php echo sprintf($ticket->isClosed() ? __('Reopen Ticket #%s') : __('Close Ticket #%s'),
-        $ticket->getNumber()); ?></h3>
-    <a class="close" href=""><i class="icon-remove-circle"></i></a>
-    <hr/>
-    <?php
-        echo sprintf(__('Are you sure you want to <b>%s</b> this ticket?'),
-            $ticket->isClosed()?__('REOPEN'):__('CLOSE'));
-        $action = $ticket->isClosed() ? 'reopen': 'close';
-    ?>
-    <br><br>
-    <form action="tickets.php?id=<?php echo $ticket->getId(); ?>" method="post" id="status-form" name="status-form">
-        <?php csrf_token(); ?>
-        <input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
-        <input type="hidden" name="a" value="process">
-        <input type="hidden" name="do" value="<?php echo $action; ?>">
-        <fieldset>
-            <div><strong>Ticket Status </strong>
-                <select name="status_id">
-                    <?php
-                    $statusId = $info['status_id'] ?: 0;
-                    if (!$ticket->isOpen())
-                        $states = array('open');
-                    else
-                        $states = array('resolved', 'closed');
-
-                    foreach (TicketStatusList::getAll($states) as $s) {
-                        if (!$s->isEnabled()) continue;
-                        echo sprintf('<option value="%d" %s>%s</option>',
-                                $s->getId(),
-                                ($statusId == $s->getId())
-                                 ? 'selected="selected"' : '',
-                                $s->getName()
-                                );
-                    }
-                    ?>
-                </select>
-                &nbsp;<span class='error'>*&nbsp;<?php echo $errors['status_id']; ?></span>
-            </div>
-        </fieldset>
-        <fieldset>
-            <div style="margin-bottom:0.5em">
-            <em><?php echo __('Reasons for status change (internal note). Optional but highly recommended.');?></em><br>
-            </div>
-            <textarea name="ticket_status_notes" id="ticket_status_notes" cols="50" rows="5" wrap="soft"
-                style="width:100%"
-                class="richtext ifhtml no-bar"><?php echo $info['ticket_status_notes']; ?></textarea>
-        </fieldset>
-        <hr style="margin-top:1em"/>
-        <p class="full-width">
-            <span class="buttons pull-left">
-                <input type="reset" value="<?php echo __('Reset');?>">
-                <input type="button" value="<?php echo __('Cancel');?>" class="close">
-            </span>
-            <span class="buttons pull-right">
-                <input type="submit" value="<?php echo $ticket->isClosed()?__('Reopen'):__('Close'); ?>">
-            </span>
-         </p>
-    </form>
-    <div class="clear"></div>
-</div>
 <div style="display:none;" class="dialog" id="confirm-action">
     <h3><?php echo __('Please Confirm');?></h3>
     <a class="close" href=""><i class="icon-remove-circle"></i></a>
diff --git a/include/staff/tickets.inc.php b/include/staff/tickets.inc.php
index 094d28ded43cf56a50280d5e0413f682f8f9613f..dd739c2c0c2cb0b1d16845528024e84d028f8c91 100644
--- a/include/staff/tickets.inc.php
+++ b/include/staff/tickets.inc.php
@@ -327,10 +327,24 @@ if ($results) {
 </div>
 <!-- SEARCH FORM END -->
 <div class="clear"></div>
-<div style="margin-bottom:20px">
-<form action="tickets.php" method="POST" name='tickets'>
+<div style="margin-bottom:20px; padding-top:3px;">
+<table width="940" cellpadding="1" cellspacing="0" border="0">
+    <tr>
+        <td width="20%">
+            <h2><a href="<?php echo Format::htmlchars($_SERVER['REQUEST_URI']); ?>"
+                title="Reload"><i class="icon-refresh"></i></a></h2>
+        </td>
+        <td width="80%" class="right_align">
+            <?php
+            if ($res && $results && $thisstaff->canManageTickets()) {
+                echo TicketStatus::options();
+            }
+            ?>
+        </td>
+    </tr>
+</table>
+<form action="tickets.php" method="POST" name='tickets' id="tickets">
 <?php csrf_token(); ?>
- <a class="refresh pull-right" href="<?php echo Format::htmlchars($_SERVER['REQUEST_URI']); ?>"><?php echo __('Refresh'); ?></a>
  <input type="hidden" name="a" value="mass_process" >
  <input type="hidden" name="do" id="action" value="" >
  <input type="hidden" name="status" value="<?php echo Format::htmlchars($_REQUEST['status']); ?>" >
@@ -427,7 +441,8 @@ if ($results) {
                         $sel=true;
                     ?>
                 <td align="center" class="nohover">
-                    <input class="ckb" type="checkbox" name="tids[]" value="<?php echo $row['ticket_id']; ?>" <?php echo $sel?'checked="checked"':''; ?>>
+                    <input class="ckb" type="checkbox" name="tids[]"
+                        value="<?php echo $row['ticket_id']; ?>" <?php echo $sel?'checked="checked"':''; ?>>
                 </td>
                 <?php } ?>
                 <td title="<?php echo $row['email']; ?>" nowrap>
@@ -490,42 +505,6 @@ if ($results) {
         echo '<div>&nbsp;'.__('Page').':'.$pageNav->getPageLinks().'&nbsp;';
         echo '<a class="export-csv no-pjax" href="?a=export&h='
             .$hash.'&status='.$_REQUEST['status'] .'">'.__('Export').'</a>&nbsp;<i class="help-tip icon-question-sign" href="#export"></i></div>';
-    ?>
-        <?php
-         if($thisstaff->canManageTickets()) { ?>
-           <p class="centered" id="actions">
-            <?php
-            $status=$_REQUEST['status']?$_REQUEST['status']:$status;
-            switch (strtolower($status)) {
-                case 'closed': ?>
-                    <input class="button" type="submit" name="reopen" value="<?php echo __('Reopen');?>" >
-                    <?php
-                    break;
-                case 'open':
-                case 'answered':
-                case 'assigned':
-                    ?>
-                    <input class="button" type="submit" name="mark_overdue" value="<?php echo __('Overdue');?>" >
-                    <input class="button" type="submit" name="close" value="<?php echo __('Close');?>">
-                    <?php
-                    break;
-                case 'overdue':
-                    ?>
-                    <input class="button" type="submit" name="close" value="<?php echo __('Close');?>">
-                    <?php
-                    break;
-                default: //search??
-                    ?>
-                    <input class="button" type="submit" name="close" value="<?php echo __('Close');?>" >
-                    <input class="button" type="submit" name="reopen" value="<?php echo __('Reopen');?>">
-            <?php
-            }
-            if($thisstaff->canDeleteTickets()) { ?>
-                <input class="button" type="submit" name="delete" value="<?php echo __('Delete');?>">
-            <?php } ?>
-        </p>
-        <?php
-       }
     } ?>
     </form>
 </div>
@@ -534,20 +513,9 @@ if ($results) {
     <h3><?php echo __('Please Confirm');?></h3>
     <a class="close" href=""><i class="icon-remove-circle"></i></a>
     <hr/>
-    <p class="confirm-action" style="display:none;" id="close-confirm">
-        <?php echo __('Are you sure want to <b>close</b> selected open tickets?');?>
-    </p>
-    <p class="confirm-action" style="display:none;" id="reopen-confirm">
-        <?php echo __('Are you sure want to <b>reopen</b> selected closed tickets?');?>
-    </p>
     <p class="confirm-action" style="display:none;" id="mark_overdue-confirm">
         <?php echo __('Are you sure want to flag the selected tickets as <font color="red"><b>overdue</b></font>?');?>
     </p>
-    <p class="confirm-action" style="display:none;" id="delete-confirm">
-        <font color="red"><strong><?php echo sprintf(__('Are you sure you want to DELETE %s?'),
-            _N('selected ticket', 'selected tickets', 2));?></strong></font>
-        <br><br><?php echo __('Deleted tickets CANNOT be recovered, including any associated attachments.');?>
-    </p>
     <div><?php echo __('Please confirm to continue.');?></div>
     <hr style="margin-top:1em"/>
     <p class="full-width">
@@ -683,3 +651,22 @@ if ($results) {
         </p>
     </form>
 </div>
+<script type="text/javascript">
+$(function() {
+    $(document).off('.tickets');
+    $(document).on('click.tickets', 'a.tickets-action', function(e) {
+        e.preventDefault();
+        var count = checkbox_checker($('form#tickets'), 1);
+        if (count) {
+            var url = 'ajax.php/'
+            +$(this).attr('href').substr(1)
+            +'?count='+count
+            +'&_uid='+new Date().getTime();
+            $.dialog(url, [201], function (xhr) {
+                window.location.href = window.location.href;
+             });
+        }
+        return false;
+    });
+});
+</script>
diff --git a/scp/ajax.php b/scp/ajax.php
index 664e12566b00bbcb03ab2e33511b7396b18caa55..cdeec76d9bb1f7ef5b5e3ae3b86fb009b47e4fe9 100644
--- a/scp/ajax.php
+++ b/scp/ajax.php
@@ -135,11 +135,15 @@ $dispatcher = patterns('',
         url_get('^(?P<tid>\d+)/add-collaborator/(?P<uid>\d+)$', 'addCollaborator'),
         url_get('^(?P<tid>\d+)/add-collaborator/auth:(?P<bk>\w+):(?P<id>.+)$', 'addRemoteCollaborator'),
         url('^(?P<tid>\d+)/add-collaborator$', 'addCollaborator'),
-        url_get('^lookup', 'lookup'),
-        url_get('^search', 'search'),
         url_get('^(?P<tid>\d+)/forms/manage$', 'manageForms'),
         url_post('^(?P<tid>\d+)/forms/manage$', 'updateForms'),
-        url_get('^(?P<tid>\d+)/canned-resp/(?P<cid>\w+).(?P<format>json|txt)', 'cannedResponse')
+        url_get('^(?P<tid>\d+)/canned-resp/(?P<cid>\w+).(?P<format>json|txt)', 'cannedResponse'),
+        url_get('^(?P<tid>\d+)/status/(?P<status>\w+)$', 'changeTicketStatus'),
+        url_post('^(?P<tid>\d+)/status/(?P<status>\w+)$', 'setTicketStatus'),
+        url_get('^status/(?P<status>\w+)(?:/(?P<sid>\d+))?$', 'changeTicketsStatus'),
+        url_post('^status/(?P<state>\w+)$', 'setTicketsStatus'),
+        url_get('^lookup', 'lookup'),
+        url_get('^search', 'search')
     )),
     url('^/collaborators/', patterns('ajax.tickets.php:TicketsAjaxAPI',
         url_get('^(?P<cid>\d+)/view$', 'viewCollaborator'),
diff --git a/scp/js/ticket.js b/scp/js/ticket.js
index ba70ec2df65f1a77b6f76cbf65163383c9979e19..afbf1ecc9c53b73703f33e0839f8ed5808f36b8a 100644
--- a/scp/js/ticket.js
+++ b/scp/js/ticket.js
@@ -381,7 +381,7 @@ var ticket_onload = function($) {
     autoLock.Init();
 
     /*** Ticket Actions **/
-    //print options
+    //print options TODO: move to backend
     $('a#ticket-print').click(function(e) {
         e.preventDefault();
         $('#overlay').show();
@@ -389,11 +389,17 @@ var ticket_onload = function($) {
         return false;
     });
 
-    //ticket status (close & reopen) xxx: move to backend ticket-action
-    $('a#ticket-close, a#ticket-reopen').click(function(e) {
+
+    $(document).off('.ticket-action');
+    $(document).on('click.ticket-action', 'a.ticket-action', function(e) {
         e.preventDefault();
-        $('#overlay').show();
-        $('.dialog#ticket-status').show();
+        var url = 'ajax.php/'
+        +$(this).attr('href').substr(1)
+        +'?_uid='+new Date().getTime();
+        $.dialog(url, [201], function (xhr) {
+            window.location.href = window.location.href;
+        });
+
         return false;
     });
 
diff --git a/scp/tickets.php b/scp/tickets.php
index f3502c96a2666cfcbdd8868d0a276ad03055c4cd..7fb3e3872ff7af834c633225b3ba7dc39a5c96b2 100644
--- a/scp/tickets.php
+++ b/scp/tickets.php
@@ -201,52 +201,6 @@ if($_POST && !$errors):
             break;
         case 'process':
             switch(strtolower($_POST['do'])):
-                case 'close':
-                    if(!$thisstaff->canCloseTickets()) {
-                        $errors['err'] = __('Permission Denied. You are not allowed to close tickets.');
-                    } elseif($ticket->isClosed()) {
-                        $errors['err'] = __('Ticket is already closed!');
-                    } elseif (!($status=TicketStatus::lookup($_POST['status_id']))) {
-                        $errors['err'] = __('Unknown status');
-                    } elseif (!in_array($status->getState(), array('resolved', 'closed'))) {
-                        $errors['err'] = __('Invalid status');
-                    } elseif ($ticket->setStatus($status)) {
-                        $msg=sprintf(__('Ticket #%s status set to CLOSED'),$ticket->getNumber());
-                        if($_POST['ticket_status_notes']) {
-                            $ticket->logNote(
-                                    __('Ticket Closed'),
-                                    $_POST['ticket_status_notes'],
-                                    $thisstaff);
-                        }
-                        //Going back to main listing.
-                        TicketLock::removeStaffLocks($thisstaff->getId(), $ticket->getId());
-                        $page=$ticket=null;
-                    } else {
-                        $errors['err']=__('Problems closing the ticket. Try again');
-                    }
-                    break;
-                case 'reopen':
-                    //if staff can close or create tickets ...then assume they can reopen.
-                    if (!$thisstaff->canCloseTickets() && !$thisstaff->canCreateTickets()) {
-                        $errors['err']=__('Permission Denied. You are not allowed to reopen tickets.');
-                    } elseif ($ticket->isOpen()) {
-                        $errors['err'] = __('Ticket is already open!');
-                    } elseif (!($status=TicketStatus::lookup($_POST['status_id']))) {
-                        $errors['err'] = __('Unknown status');
-                    } elseif (strcasecmp($status->getState(), 'open')) {
-                        $errors['err'] = __('Invalid status');
-                    } elseif ($ticket->setStatus($status)) {
-                        $msg=__('Ticket Reopened');
-                        if($_POST['ticket_status_notes']) {
-                            $ticket->logNote(
-                                    __('Ticket Reopened'),
-                                    $_POST['ticket_status_notes'],
-                                    $thisstaff);
-                        }
-                    } else {
-                        $errors['err']=__('Problems reopening the ticket. Try again');
-                    }
-                    break;
                 case 'release':
                     if(!$ticket->isAssigned() || !($assigned=$ticket->getAssigned())) {
                         $errors['err'] = __('Ticket is not assigned!');
@@ -336,21 +290,6 @@ if($_POST && !$errors):
                         $errors['err'] = 'Unable to change tiket ownership. Try again';
                     }
                     break;
-                case 'delete': // Dude what are you trying to hide? bad customer support??
-                    if(!$thisstaff->canDeleteTickets()) {
-                        $errors['err']=__('Permission Denied. You are not allowed to DELETE tickets!!');
-                    } elseif($ticket->delete()) {
-                        $msg=sprintf(__('Ticket #%s deleted successfully'),$ticket->getNumber());
-                        //Log a debug note
-                        $ost->logDebug(sprintf(__('Ticket #%s deleted'),$ticket->getNumber()),
-                                sprintf(__('Ticket #%1$s deleted by %2$s'),
-                                    $ticket->getNumber(), $thisstaff->getName())
-                                );
-                        $ticket=null; //clear the object.
-                    } else {
-                        $errors['err']=__('Problems deleting the ticket. Try again');
-                    }
-                    break;
                 default:
                     $errors['err']=__('You must select action to perform');
             endswitch;
@@ -363,90 +302,6 @@ if($_POST && !$errors):
     }elseif($_POST['a']) {
 
         switch($_POST['a']) {
-            case 'mass_process':
-                if(!$thisstaff->canManageTickets())
-                    $errors['err']=__('You do not have permission to mass manage tickets. Contact admin for such access');
-                elseif(!$_POST['tids'] || !is_array($_POST['tids']))
-                    $errors['err']=sprintf(__('You must select at least %s.'),
-                        __('one ticket'));
-                else {
-                    $count=count($_POST['tids']);
-                    $i = 0;
-                    switch(strtolower($_POST['do'])) {
-                        case 'reopen':
-                            if($thisstaff->canCloseTickets() || $thisstaff->canCreateTickets()) {
-                                $note=sprintf(__('Ticket reopened by %s'),$thisstaff->getName());
-                                foreach($_POST['tids'] as $k=>$v) {
-                                    if(($t=Ticket::lookup($v)) && $t->isClosed() && @$t->reopen()) {
-                                        $i++;
-                                        $t->logNote(__('Ticket Reopened'), $note, $thisstaff);
-                                    }
-                                }
-
-                                if($i==$count)
-                                    $msg = sprintf(__('Successfully reopened %s'),
-                                        _N('selected ticket', 'selected tickets', $count));
-                                elseif($i)
-                                    $warn = sprintf(__('%1$d of %2$d %3$s reopened'),$i, $count,
-                                        _N('selected ticket', 'selected tickets', $count));
-                                else
-                                    $errors['err'] = sprintf(__('Unable to reopen %s'),
-                                        _N('selected ticket', 'selected tickets', $count));
-                            } else {
-                                $errors['err'] = __('You do not have permission to reopen tickets');
-                            }
-                            break;
-                        case 'close':
-                            $errors['err'] = 'Support coming soon!';
-                            break;
-                        case 'mark_overdue':
-                            $note=sprintf(__('Ticket flagged as overdue by %s'),$thisstaff->getName());
-                            foreach($_POST['tids'] as $k=>$v) {
-                                if(($t=Ticket::lookup($v)) && !$t->isOverdue() && $t->markOverdue()) {
-                                    $i++;
-                                    $t->logNote(__('Ticket Marked Overdue'), $note, $thisstaff);
-                                }
-                            }
-
-                            if($i==$count)
-                                $msg = sprintf(__('Selected tickets (%d) marked overdue'), $i);
-                            elseif($i)
-                                $warn = sprintf(__('%1$d of %2$d selected tickets marked overdue'), $i, $count);
-                            else
-                                $errors['err'] = __('Unable to flag selected tickets as overdue');
-                            break;
-                        case 'delete':
-                            if($thisstaff->canDeleteTickets()) {
-                                foreach($_POST['tids'] as $k=>$v) {
-                                    if(($t=Ticket::lookup($v)) && @$t->delete()) $i++;
-                                }
-
-                                //Log a warning
-                                if($i) {
-                                    $log = sprintf(_S('%1$s (%2$s) just deleted %3$d ticket(s)'),
-                                            $thisstaff->getName(), $thisstaff->getUserName(), $i);
-                                    $ost->logWarning(_S('Tickets deleted'), $log, false);
-
-                                }
-
-                                if($i==$count)
-                                    $msg = sprintf(__('Successfully deleted %s'),
-                                        _N('selected ticket', 'selected tickets', $count));
-                                elseif($i)
-                                    $warn = sprintf(__('%1$d of %2$d %3$s deleted'),$i, $count,
-                                        _N('selected ticket', 'selected tickets', $count));
-                                else
-                                    $errors['err'] = sprintf(__('Unable to delete %s'),
-                                        _N('selected ticket', 'selected tickets', $count));
-                            } else {
-                                $errors['err'] = __('You do not have permission to delete tickets');
-                            }
-                            break;
-                        default:
-                            $errors['err']=__('Unknown action - get technical help.');
-                    }
-                }
-                break;
             case 'open':
                 $ticket=null;
                 if(!$thisstaff || !$thisstaff->canCreateTickets()) {