From 38e6f10c57a936b7386eb752fca5be2b58925bc5 Mon Sep 17 00:00:00 2001
From: Jared Hancock <jared@osticket.com>
Date: Tue, 9 Sep 2014 22:34:30 -0500
Subject: [PATCH] ui: Tabs revisited

This reworks the tabs CSS and javascript coding to be more flexible and to
support vertical tabs. (Bootstrap calls this stacked.) The javascript also
allows the URL to include the hash-tag of the last-clicked tab so that the
tab can be automatically shown when the page is reloaded.
---
 include/staff/dynamic-list.inc.php            |  2 +-
 include/staff/org-view.inc.php                |  2 +-
 include/staff/page.inc.php                    |  2 +-
 include/staff/templates/org-profile.tmpl.php  |  2 +-
 .../staff/templates/ticket-preview.tmpl.php   |  2 +-
 include/staff/templates/user-account.tmpl.php |  6 +-
 include/staff/templates/user-import.tmpl.php  | 12 +--
 include/staff/templates/user.tmpl.php         |  2 +-
 include/staff/ticket-view.inc.php             |  8 +-
 include/staff/user-view.inc.php               |  2 +-
 scp/css/scp.css                               | 91 +++++++++++++++++--
 scp/js/scp.js                                 | 43 +++++++--
 scp/js/ticket.js                              | 25 +----
 13 files changed, 142 insertions(+), 57 deletions(-)

diff --git a/include/staff/dynamic-list.inc.php b/include/staff/dynamic-list.inc.php
index 3b5d93197..fbeb00208 100644
--- a/include/staff/dynamic-list.inc.php
+++ b/include/staff/dynamic-list.inc.php
@@ -28,7 +28,7 @@ $info=Format::htmlchars(($errors && $_POST) ? array_merge($info,$_POST) : $info)
     <?php echo $list ? $list->getName() : 'Add new list'; ?></h2>
 
 <ul class="tabs">
-    <li><a href="#definition" class="active">
+    <li class="active"><a href="#definition">
         <i class="icon-plus"></i> <?php echo __('Definition'); ?></a></li>
     <li><a href="#items">
         <i class="icon-list"></i> <?php echo __('Items'); ?></a></li>
diff --git a/include/staff/org-view.inc.php b/include/staff/org-view.inc.php
index c5cea44eb..5bc9d3281 100644
--- a/include/staff/org-view.inc.php
+++ b/include/staff/org-view.inc.php
@@ -64,7 +64,7 @@ if(!defined('OSTSCPINC') || !$thisstaff || !is_object($org)) die('Invalid path')
 <br>
 <div class="clear"></div>
 <ul class="tabs">
-    <li><a class="active" id="users_tab" href="#users"><i
+    <li class="active"><a id="users_tab" href="#users"><i
     class="icon-user"></i>&nbsp;<?php echo __('Users'); ?></a></li>
     <li><a id="tickets_tab" href="#tickets"><i
     class="icon-list-alt"></i>&nbsp;<?php echo __('Tickets'); ?></a></li>
diff --git a/include/staff/page.inc.php b/include/staff/page.inc.php
index ab74e8231..301374b1a 100644
--- a/include/staff/page.inc.php
+++ b/include/staff/page.inc.php
@@ -110,7 +110,7 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
         <tr>
             <td colspan="2">
                 <ul class="tabs">
-                    <li><a class="active" href="#content"><?php echo __('Page Content'); ?></a></li>
+                    <li class="active"><a href="#content"><?php echo __('Page Content'); ?></a></li>
                     <li><a href="#notes"><?php echo __('Internal Notes'); ?></a></li>
                 </ul>
     <div class="tab_content active" id="content">
diff --git a/include/staff/templates/org-profile.tmpl.php b/include/staff/templates/org-profile.tmpl.php
index 2b83f76b6..bdfbd681a 100644
--- a/include/staff/templates/org-profile.tmpl.php
+++ b/include/staff/templates/org-profile.tmpl.php
@@ -16,7 +16,7 @@ if ($info['error']) {
     echo sprintf('<p id="msg_notice">%s</p>', $info['msg']);
 } ?>
 <ul class="tabs">
-    <li><a href="#tab-profile" class="active"
+    <li class="active"><a href="#tab-profile"
         ><i class="icon-edit"></i>&nbsp;<?php echo __('Fields'); ?></a></li>
     <li><a href="#contact-settings"
         ><i class="icon-fixed-width icon-cogs faded"></i>&nbsp;<?php
diff --git a/include/staff/templates/ticket-preview.tmpl.php b/include/staff/templates/ticket-preview.tmpl.php
index 5e2d2219b..e045ed4f6 100644
--- a/include/staff/templates/ticket-preview.tmpl.php
+++ b/include/staff/templates/ticket-preview.tmpl.php
@@ -31,7 +31,7 @@ elseif($warn)
 echo '<ul class="tabs">';
 
 echo '
-        <li><a id="preview_tab" href="#preview" class="active"
+        <li class="active"><a id="preview_tab" href="#preview"
             ><i class="icon-list-alt"></i>&nbsp;'.__('Ticket Summary').'</a></li>';
 if ($ticket->getNumCollaborators()) {
 echo sprintf('
diff --git a/include/staff/templates/user-account.tmpl.php b/include/staff/templates/user-account.tmpl.php
index e68261a29..ef3c9eb3d 100644
--- a/include/staff/templates/user-account.tmpl.php
+++ b/include/staff/templates/user-account.tmpl.php
@@ -15,15 +15,15 @@ if ($info['error']) {
 } elseif ($info['msg']) {
     echo sprintf('<p id="msg_notice">%s</p>', $info['msg']);
 } ?>
+<form method="post" class="user" action="#users/<?php echo $user->getId(); ?>/manage" >
 <ul class="tabs">
-    <li><a href="#user-account" <?php echo !$access? 'class="active"' : ''; ?>
+    <li <?php echo !$access? 'class="active"' : ''; ?>><a href="#user-account"
         ><i class="icon-user"></i>&nbsp;<?php echo __('User Information'); ?></a></li>
-    <li><a href="#user-access" <?php echo $access? 'class="active"' : ''; ?>
+    <li <?php echo $access? 'class="active"' : ''; ?>><a href="#user-access"
         ><i class="icon-fixed-width icon-lock faded"></i>&nbsp;<?php echo __('Manage Access'); ?></a></li>
 </ul>
 
 
-<form method="post" class="user" action="#users/<?php echo $user->getId(); ?>/manage" >
  <input type="hidden" name="id" value="<?php echo $user->getId(); ?>" />
  <div class="tab_content"  id="user-account" style="display:<?php echo $access? 'none' : 'block'; ?>; margin:5px;">
     <form method="post" class="user" action="#users/<?php echo $user->getId(); ?>/manage" >
diff --git a/include/staff/templates/user-import.tmpl.php b/include/staff/templates/user-import.tmpl.php
index 447f83ee2..ad57afc16 100644
--- a/include/staff/templates/user-import.tmpl.php
+++ b/include/staff/templates/user-import.tmpl.php
@@ -10,18 +10,18 @@ if ($info['error']) {
 } elseif ($info['msg']) {
     echo sprintf('<p id="msg_notice">%s</p>', $info['msg']);
 } ?>
-<ul class="tabs">
-    <li><a href="#copy-paste" class="active"
-        ><i class="icon-edit"></i>&nbsp;<?php echo __('Copy Paste'); ?></a></li>
-    <li><a href="#upload"
-        ><i class="icon-fixed-width icon-cloud-upload"></i>&nbsp;<?php echo __('Upload'); ?></a></li>
-</ul>
 <form action="<?php echo $info['action']; ?>" method="post" enctype="multipart/form-data"
     onsubmit="javascript:
     if ($(this).find('[name=import]').val()) {
         $(this).attr('action', '<?php echo $info['upload_url']; ?>');
         $(document).unbind('submit.dialog');
     }">
+<ul class="tabs">
+    <li class="active"><a href="#copy-paste"
+        ><i class="icon-edit"></i>&nbsp;<?php echo __('Copy Paste'); ?></a></li>
+    <li><a href="#upload"
+        ><i class="icon-fixed-width icon-cloud-upload"></i>&nbsp;<?php echo __('Upload'); ?></a></li>
+</ul>
 <?php echo csrf_token();
 if ($org_id) { ?>
     <input type="hidden" name="id" value="<?php echo $org_id; ?>"/>
diff --git a/include/staff/templates/user.tmpl.php b/include/staff/templates/user.tmpl.php
index af21b0128..aabd5cd17 100644
--- a/include/staff/templates/user.tmpl.php
+++ b/include/staff/templates/user.tmpl.php
@@ -35,7 +35,7 @@ if ($info['error']) {
 
 <div class="clear"></div>
 <ul class="tabs" style="margin-top:5px">
-    <li><a href="#info-tab" class="active"
+    <li class="active"><a href="#info-tab"
         ><i class="icon-info-sign"></i>&nbsp;<?php echo __('User'); ?></a></li>
 <?php if ($org) { ?>
     <li><a href="#organization-tab"
diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php
index 83f7622ed..bab1d22e5 100644
--- a/include/staff/ticket-view.inc.php
+++ b/include/staff/ticket-view.inc.php
@@ -464,7 +464,7 @@ $tcount+= $ticket->getNumNotes();
     </ul>
     <?php
     if($thisstaff->canPostReply()) { ?>
-    <form id="reply" action="tickets.php?id=<?php echo $ticket->getId(); ?>#reply" name="reply" method="post" enctype="multipart/form-data">
+    <form id="reply" class="tab_content" action="tickets.php?id=<?php echo $ticket->getId(); ?>#reply" name="reply" method="post" enctype="multipart/form-data">
         <?php csrf_token(); ?>
         <input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
         <input type="hidden" name="msgId" value="<?php echo $msgId; ?>">
@@ -642,7 +642,7 @@ print $response_form->getField('attachments')->render();
     </form>
     <?php
     } ?>
-    <form id="note" action="tickets.php?id=<?php echo $ticket->getId(); ?>#note" name="note" method="post" enctype="multipart/form-data">
+    <form id="note" class="tab_content" action="tickets.php?id=<?php echo $ticket->getId(); ?>#note" name="note" method="post" enctype="multipart/form-data">
         <?php csrf_token(); ?>
         <input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
         <input type="hidden" name="locktime" value="<?php echo $cfg->getLockTime(); ?>">
@@ -723,7 +723,7 @@ print $note_form->getField('attachments')->render();
    </form>
     <?php
     if($thisstaff->canTransferTickets()) { ?>
-    <form id="transfer" action="tickets.php?id=<?php echo $ticket->getId(); ?>#transfer" name="transfer" method="post" enctype="multipart/form-data">
+    <form id="transfer" class="tab_content" action="tickets.php?id=<?php echo $ticket->getId(); ?>#transfer" name="transfer" method="post" enctype="multipart/form-data">
         <?php csrf_token(); ?>
         <input type="hidden" name="ticket_id" value="<?php echo $ticket->getId(); ?>">
         <input type="hidden" name="a" value="transfer">
@@ -783,7 +783,7 @@ print $note_form->getField('attachments')->render();
     } ?>
     <?php
     if($thisstaff->canAssignTickets()) { ?>
-    <form id="assign" action="tickets.php?id=<?php echo $ticket->getId(); ?>#assign" name="assign" method="post" enctype="multipart/form-data">
+    <form id="assign" class="tab_content" action="tickets.php?id=<?php echo $ticket->getId(); ?>#assign" name="assign" method="post" enctype="multipart/form-data">
         <?php csrf_token(); ?>
         <input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
         <input type="hidden" name="a" value="assign">
diff --git a/include/staff/user-view.inc.php b/include/staff/user-view.inc.php
index 58f4348ee..2e563ae0c 100644
--- a/include/staff/user-view.inc.php
+++ b/include/staff/user-view.inc.php
@@ -125,7 +125,7 @@ $org = $user->getOrganization();
 <br>
 <div class="clear"></div>
 <ul class="tabs">
-    <li><a class="active" id="tickets_tab" href="#tickets"><i
+    <li class="active"><a id="tickets_tab" href="#tickets"><i
     class="icon-list-alt"></i>&nbsp;<?php echo __('User Tickets'); ?></a></li>
     <li><a id="notes_tab" href="#notes"><i
     class="icon-pushpin"></i>&nbsp;<?php echo __('Notes'); ?></a></li>
diff --git a/scp/css/scp.css b/scp/css/scp.css
index dab7b3a67..191f3d88b 100644
--- a/scp/css/scp.css
+++ b/scp/css/scp.css
@@ -894,30 +894,26 @@ h2 .reload {
 ul.tabs {
     padding:4px 0 0 20px;
     margin:0;
-    margin-bottom: 5px;
     text-align:left;
     height:29px;
     border-bottom:1px solid #aaa;
     background:#eef3f8;
+    position: relative;
 }
 
 #response_options ul.tabs {
     padding-left:190px;
 }
 
-
 ul.tabs li {
     margin:0;
     padding:0;
-    display:inline;
+    display:inline-block;
     list-style:none;
-}
-
-ul.tabs li a {
+    text-align:center;
     min-width:130px;
     font-weight:bold;
-    padding:5px;
-    height:18px;
+    height:28px;
     line-height:20px;
     color:#444;
     display:inline-block;
@@ -925,9 +921,85 @@ ul.tabs li a {
     position:relative;
     bottom:1px;
     background:#fbfbfb;
-    border:1px solid #eee;
+    background-color: rgba(251, 251, 251, 0.5);
+    border:1px solid #ccc;
+    border:1px solid rgba(204, 204, 204, 0.5);
+    border-bottom:none;
+    position: relative;
+    bottom: 1px;
+    border-top-left-radius: 5px;
+    border-top-right-radius: 5px;
+    font-size: 95%;
+}
+ul.tabs li.active {
+    color:#184E81;
+    background-color:#f9f9f9;
+    border:1px solid #aaa;
     border-bottom:none;
     text-align: center;
+    border-top:2px solid #81a9d7;
+    bottom: 0;
+    box-shadow: 4px -1px 6px -3px rgba(0,0,0,0.3);
+}
+
+ul.tabs li a {
+    font-weight: normal;
+    line-height: 20px;
+    color: #444;
+    display: block;
+    outline: none;
+    padding: 5px 10px;
+}
+
+ul.tabs li.active a {
+    font-weight: bold;
+}
+
+ul.tabs.vertical {
+    display: inline-block;
+    height: auto;
+    border-bottom: initial;
+    border-right: 1px solid #aaa;
+    padding-left: 0;
+    padding-bottom: 40px;
+    padding-top: 10px;
+    background: transparent;
+}
+ul.tabs.vertical.left {
+    float: left;
+    margin-right: 19px;
+}
+
+ul.tabs.vertical li {
+    border:1px solid #ccc;
+    border:1px solid rgba(204, 204, 204, 0.5);
+    border-right: none;
+    min-width: 0;
+    display: block;
+    border-top-right-radius: 0;
+    border-bottom-left-radius: 5px;
+    right: 0;
+    height: auto;
+}
+
+ul.tabs.vertical li + li {
+    margin-top: 5px;
+}
+
+ul.tabs.vertical li.active {
+    border: 1px solid #aaa;
+    border-left: 2px solid #81a9d7;
+    border-right: none;
+    right: -1px;
+    box-shadow: -1px 4px 6px -3px rgba(0,0,0,0.3);
+}
+
+ul.tabs.vertical.left li {
+    text-align: right;
+}
+
+ul.tabs.vertical li a {
+    padding: 5px;
 }
 
 #response_options .reply_tab.tell {
@@ -1871,6 +1943,7 @@ tr.disabled th {
 
 .tab_content {
     position: relative;
+    padding: 10px;
 }
 .floating-options {
     display: inline-block;
diff --git a/scp/js/scp.js b/scp/js/scp.js
index 1650871ec..d55684d93 100644
--- a/scp/js/scp.js
+++ b/scp/js/scp.js
@@ -446,6 +446,10 @@ var scp_prep = function() {
 
    // Make translatable fields translatable
    $('input[data-translate-tag], textarea[data-translate-tag]').translatable();
+
+   if (window.location.hash) {
+     $('ul.tabs li a[href="' + window.location.hash + '"]').trigger('click');
+   }
 };
 
 $(document).ready(scp_prep);
@@ -626,15 +630,42 @@ $.uid = 1;
 
 //Tabs
 $(document).on('click.tab', 'ul.tabs li a', function(e) {
-    e.preventDefault();
-    if ($('.tab_content'+$(this).attr('href')).length) {
+    var target = $('.tab_content'+$(this).attr('href'));
+    if (target.length) {
         var ul = $(this).closest('ul');
-        $('ul.tabs li a', ul.parent()).removeClass('active');
-        $(this).addClass('active');
-        $('.tab_content', ul.parent()).hide();
-        $('.tab_content'+$(this).attr('href')).show();
+        ul.children('li.active').removeClass('active');
+        $(this).closest('li').addClass('active');
+        ul.parent().children('.tab_content').hide();
+        target.fadeIn('fast');
+        $.changeHash($(this).attr('href'), true);
+        return false;
     }
 });
+$.changeHash = function(hash, quiet) {
+  if (quiet) {
+    hash = hash.replace( /^#/, '' );
+    var fx, node = $( '#' + hash );
+    if ( node.length ) {
+      node.attr( 'id', '' );
+      fx = $( '<div></div>' )
+              .css({
+                  position:'absolute',
+                  visibility:'hidden',
+                  top: $(document).scrollTop() + 'px'
+              })
+              .attr( 'id', hash )
+              .appendTo( document.body );
+    }
+    document.location.hash = hash;
+    if ( node.length ) {
+      fx.remove();
+      node.attr( 'id', hash );
+    }
+  }
+  else {
+    document.location.hash = hash;
+  }
+};
 
 //Collaborators
 $(document).on('click', 'a.collaborator, a.collaborators', function(e) {
diff --git a/scp/js/ticket.js b/scp/js/ticket.js
index 2c9398a5a..26ab20c75 100644
--- a/scp/js/ticket.js
+++ b/scp/js/ticket.js
@@ -319,22 +319,9 @@ $.refreshTicketView = function() {
 }
 
 var ticket_onload = function($) {
-    $('#response_options form').hide();
-    $('#ticket_notes').hide();
-    if(location.hash != "" && $('#response_options '+location.hash).length) {
-        $('#response_options '+location.hash+'_tab').addClass('active');
-        $('#response_options '+location.hash).show();
-    } else if(location.hash == "#notes" && $('#ticket_notes').length) {
-        $('#response_options #note_tab').addClass('active');
-        $('#response_options form').hide();
-        $('#response_options #note').show();
-        $('#ticket_thread').hide();
-        $('#ticket_notes').show();
-        $('#toggle_ticket_thread').removeClass('active');
-        $('#toggle_notes').addClass('active');
-    } else {
-        $('#response_options ul.tabs li:first a').addClass('active');
-        $('#response_options '+$('#response_options ul.tabs li:first a').attr('href')).show();
+    if (!location.hash || !$('#response_options .tab_content' + location.hash).length) {
+        console.log('ajshdasdhfasd');
+        $('#response_options ul.tabs li:first a').trigger('click');
     }
 
     $('#reply_tab').click(function() {
@@ -348,12 +335,6 @@ var ticket_onload = function($) {
      });
 
     $('#response_options ul.tabs li a').click(function(e) {
-        e.preventDefault();
-        $('#response_options ul.tabs li a').removeClass('active');
-        $(this).addClass('active');
-        $('#response_options form').hide();
-        //window.location.hash = this.hash;
-        $('#response_options '+$(this).attr('href')).show();
         $("#msg_error, #msg_notice, #msg_warning").fadeOut();
      });
 
-- 
GitLab