Paginate main UI connection list, improve pager styles, begin proper style separation.

This commit is contained in:
Michael Jumper
2013-02-19 00:04:53 -08:00
parent b467a5945c
commit a24804a39d
7 changed files with 226 additions and 173 deletions

View File

@@ -24,6 +24,7 @@
<head>
<link rel="icon" type="image/png" href="images/guacamole-logo-64.png"/>
<link rel="apple-touch-icon" type="image/png" href="images/guacamole-logo-144.png"/>
<link rel="stylesheet" type="text/css" href="styles/ui.css"/>
<link rel="stylesheet" type="text/css" href="styles/login.css"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, target-densitydpi=medium-dpi"/>
<title>Guacamole ${project.version}</title>
@@ -82,6 +83,9 @@
<div id="all-connections">
</div>
<div id="all-connections-buttons">
</div>
<h2>Clipboard</h2>
<div id="clipboardDiv">
<p>

View File

@@ -257,167 +257,6 @@ GuacAdmin.ListItem = function(type, title) {
};
/**
* A paging component. Elements can be added via the addElement() function,
* and will only be shown if they are on the current page, set via setPage().
*
* Beware that all elements will be added to the given container element, and
* all children of the container element will be removed when the page is
* changed.
*/
GuacAdmin.Pager = function(container) {
var guac_pager = this;
/**
* A container for all pager control buttons.
*/
var element = GuacUI.createElement("div", "pager");
/**
* All displayable elements.
*/
var elements = [];
/**
* The number of elements to display per page.
*/
this.page_capacity = 10;
/**
* The number of pages to generate a window for.
*/
this.window_size = 11;
/**
* The current page, where 0 is the first page.
*/
this.current_page = 0;
/**
* The last existing page.
*/
this.last_page = 0;
function update_display() {
var i;
// Calculate first and last elements of page (where the last element
// is actually the first element of the next page)
var first_element = guac_pager.current_page * guac_pager.page_capacity;
var last_element = Math.min(elements.length,
first_element + guac_pager.page_capacity);
// Clear contents, add elements
container.innerHTML = "";
for (i=first_element; i < last_element; i++)
container.appendChild(elements[i]);
// Update buttons
element.innerHTML = "";
// Create first and prev buttons
var first = GuacUI.createChildElement(element, "div", "first-page icon");
var prev = GuacUI.createChildElement(element, "div", "prev-page icon");
// Handle prev/first
if (guac_pager.current_page > 0) {
first.onclick = function() {
guac_pager.setPage(0);
};
prev.onclick = function() {
guac_pager.setPage(guac_pager.current_page - 1);
};
}
else {
GuacUI.addClass(first, "disabled");
GuacUI.addClass(prev, "disabled");
}
// Calculate page jump window start/end
var window_start = guac_pager.current_page - (guac_pager.window_size - 1) / 2;
var window_end = window_start + guac_pager.window_size - 1;
// Shift window as necessary
if (window_start < 0) {
window_end = Math.min(guac_pager.last_page, window_end - window_start);
window_start = 0;
}
else if (window_end > guac_pager.last_page) {
window_start = Math.max(0, window_start - window_end + guac_pager.last_page);
window_end = guac_pager.last_page;
}
// Add page jumps
for (i=window_start; i<=window_end; i++) {
// Create clickable element containing page number
var jump = GuacUI.createChildElement(element, "div", "set-page");
jump.textContent = i+1;
// Mark current page
if (i == guac_pager.current_page)
GuacUI.addClass(jump, "current");
// If not current, add click event
else
(function(page_number) {
jump.onclick = function() {
guac_pager.setPage(page_number);
};
})(i);
}
// Create next and last buttons
var next = GuacUI.createChildElement(element, "div", "next-page icon");
var last = GuacUI.createChildElement(element, "div", "last-page icon");
// Handle next/last
if (guac_pager.current_page < guac_pager.last_page) {
next.onclick = function() {
guac_pager.setPage(guac_pager.current_page + 1);
};
last.onclick = function() {
guac_pager.setPage(guac_pager.last_page);
};
}
else {
GuacUI.addClass(next, "disabled");
GuacUI.addClass(last, "disabled");
}
}
/**
* Adds the given element to the set of displayable elements.
*/
this.addElement = function(element) {
elements.push(element);
guac_pager.last_page = Math.max(0,
Math.floor((elements.length - 1) / guac_pager.page_capacity));
};
/**
* Sets the current page, where 0 is the first page.
*/
this.setPage = function(number) {
guac_pager.current_page = number;
update_display();
};
/**
* Returns the element representing the buttons of this pager.
*/
this.getElement = function() {
return element;
};
};
/*
* Set handler for logout
*/
@@ -963,9 +802,7 @@ GuacAdmin.reset = function() {
GuacAdmin.cached_connections = GuacamoleService.Connections.list();
// Sort connections by ID
GuacAdmin.cached_connections.sort(function(a, b) {
return a.id.localeCompare(b.id);
});
GuacAdmin.cached_connections.sort(GuacamoleService.Connections.comparator);
// Connection management
if (GuacAdmin.cached_permissions.create_connection
@@ -1044,7 +881,7 @@ GuacAdmin.reset = function() {
// Add new pager
GuacAdmin.containers.user_list.innerHTML = "";
GuacAdmin.userPager = new GuacAdmin.Pager(GuacAdmin.containers.user_list);
GuacAdmin.userPager = new GuacUI.Pager(GuacAdmin.containers.user_list);
// Add users to pager
var usernames = Object.keys(GuacAdmin.cached_permissions.read_user).sort();
@@ -1071,7 +908,7 @@ GuacAdmin.reset = function() {
// Add new pager
GuacAdmin.containers.connection_list.innerHTML = "";
GuacAdmin.connectionPager = new GuacAdmin.Pager(GuacAdmin.containers.connection_list);
GuacAdmin.connectionPager = new GuacUI.Pager(GuacAdmin.containers.connection_list);
// Add connections to pager
for (i=0; i<GuacAdmin.cached_connections.length; i++)

View File

@@ -512,3 +512,173 @@ GuacUI.Connection = function(connection) {
};
};
/**
* A paging component. Elements can be added via the addElement() function,
* and will only be shown if they are on the current page, set via setPage().
*
* Beware that all elements will be added to the given container element, and
* all children of the container element will be removed when the page is
* changed.
*/
GuacUI.Pager = function(container) {
var guac_pager = this;
/**
* A container for all pager control buttons.
*/
var element = GuacUI.createElement("div", "pager");
/**
* All displayable elements.
*/
var elements = [];
/**
* The number of elements to display per page.
*/
this.page_capacity = 10;
/**
* The number of pages to generate a window for.
*/
this.window_size = 11;
/**
* The current page, where 0 is the first page.
*/
this.current_page = 0;
/**
* The last existing page.
*/
this.last_page = 0;
function update_display() {
var i;
// Calculate first and last elements of page (where the last element
// is actually the first element of the next page)
var first_element = guac_pager.current_page * guac_pager.page_capacity;
var last_element = Math.min(elements.length,
first_element + guac_pager.page_capacity);
// Clear contents, add elements
container.innerHTML = "";
for (i=first_element; i < last_element; i++)
container.appendChild(elements[i]);
// Update buttons
element.innerHTML = "";
// Create first and prev buttons
var first = GuacUI.createChildElement(element, "div", "first-page icon");
var prev = GuacUI.createChildElement(element, "div", "prev-page icon");
// Handle prev/first
if (guac_pager.current_page > 0) {
first.onclick = function() {
guac_pager.setPage(0);
};
prev.onclick = function() {
guac_pager.setPage(guac_pager.current_page - 1);
};
}
else {
GuacUI.addClass(first, "disabled");
GuacUI.addClass(prev, "disabled");
}
// Calculate page jump window start/end
var window_start = guac_pager.current_page - (guac_pager.window_size - 1) / 2;
var window_end = window_start + guac_pager.window_size - 1;
// Shift window as necessary
if (window_start < 0) {
window_end = Math.min(guac_pager.last_page, window_end - window_start);
window_start = 0;
}
else if (window_end > guac_pager.last_page) {
window_start = Math.max(0, window_start - window_end + guac_pager.last_page);
window_end = guac_pager.last_page;
}
// Add ellipsis if window after beginning
if (window_start != 0)
GuacUI.createChildElement(element, "div", "more-pages").textContent = "...";
// Add page jumps
for (i=window_start; i<=window_end; i++) {
// Create clickable element containing page number
var jump = GuacUI.createChildElement(element, "div", "set-page");
jump.textContent = i+1;
// Mark current page
if (i == guac_pager.current_page)
GuacUI.addClass(jump, "current");
// If not current, add click event
else
(function(page_number) {
jump.onclick = function() {
guac_pager.setPage(page_number);
};
})(i);
}
// Add ellipsis if window before end
if (window_end != guac_pager.last_page)
GuacUI.createChildElement(element, "div", "more-pages").textContent = "...";
// Create next and last buttons
var next = GuacUI.createChildElement(element, "div", "next-page icon");
var last = GuacUI.createChildElement(element, "div", "last-page icon");
// Handle next/last
if (guac_pager.current_page < guac_pager.last_page) {
next.onclick = function() {
guac_pager.setPage(guac_pager.current_page + 1);
};
last.onclick = function() {
guac_pager.setPage(guac_pager.last_page);
};
}
else {
GuacUI.addClass(next, "disabled");
GuacUI.addClass(last, "disabled");
}
}
/**
* Adds the given element to the set of displayable elements.
*/
this.addElement = function(element) {
elements.push(element);
guac_pager.last_page = Math.max(0,
Math.floor((elements.length - 1) / guac_pager.page_capacity));
};
/**
* Sets the current page, where 0 is the first page.
*/
this.setPage = function(number) {
guac_pager.current_page = number;
update_display();
};
/**
* Returns the element representing the buttons of this pager.
*/
this.getElement = function() {
return element;
};
};

View File

@@ -26,7 +26,8 @@ var GuacamoleRootUI = {
"sections": {
"login_form" : document.getElementById("login-form"),
"recent_connections" : document.getElementById("recent-connections"),
"all_connections" : document.getElementById("all-connections")
"all_connections" : document.getElementById("all-connections"),
"all_connections_buttons" : document.getElementById("all-connections-buttons")
},
"messages": {
@@ -144,6 +145,9 @@ GuacamoleRootUI.reset = function() {
try {
connections = GuacamoleService.Connections.list(parameters);
// Sort connections by ID
connections.sort(GuacamoleService.Connections.comparator);
// Show admin elements if admin permissions available
var permissions = GuacamoleService.Permissions.list();
if (permissions.create_connection
@@ -169,6 +173,10 @@ GuacamoleRootUI.reset = function() {
}
// Create pager for connections
var connection_pager = new GuacUI.Pager(GuacamoleRootUI.sections.all_connections);
connection_pager.page_capacity = 20;
// Add connection icons
for (var i=0; i<connections.length; i++) {
@@ -183,11 +191,19 @@ GuacamoleRootUI.reset = function() {
GuacamoleRootUI.addRecentConnection(connection);
// Add connection to connection list
GuacamoleRootUI.sections.all_connections.appendChild(
connection_pager.addElement(
new GuacUI.Connection(connections[i]).getElement());
}
// Add buttons if more than one page
if (connection_pager.last_page != 0)
GuacamoleRootUI.sections.all_connections_buttons.appendChild(
connection_pager.getElement());
// Start at page 0
connection_pager.setPage(0);
// If connections could be retrieved, display list
GuacamoleRootUI.views.login.style.display = "none";
GuacamoleRootUI.views.connections.style.display = "";

View File

@@ -165,6 +165,13 @@ GuacamoleService.PermissionSet = function() {
*/
GuacamoleService.Connections = {
/**
* Comparator which compares two GuacamoleService.Connection objects.
*/
"comparator" : function(a, b) {
return a.id.localeCompare(b.id);
},
/**
* Returns an array of Connections for which the current user has access.
*

View File

@@ -242,8 +242,14 @@ div#recent-connections,
div#clipboardDiv,
div#settings,
div#all-connections {
margin: 0;
padding: 1em;
margin: 1em;
padding: 0;
}
#all-connections-buttons {
text-align: center;
margin: 1em;
padding: 0;
}
div#recent-connections {
@@ -366,4 +372,4 @@ div#recent-connections .protocol {
margin: 1.5em;
margin-left: 2.5em;
font-size: 0.75em;
}
}

View File

@@ -388,16 +388,28 @@ div#logout-panel {
opacity: 0.25;
}
.set-page {
text-decoration: underline;
.set-page,
.more-pages {
display: inline-block;
padding: 0.25em;
text-align: center;
min-width: 1.25em;
}
.set-page {
text-decoration: underline;
}
.set-page.current {
cursor: auto;
text-decoration: none;
font-weight: bold;
background: rgba(0, 0, 0, 0.1);
border: 1px solid rgba(0, 0, 0, 0.1);
-moz-border-radius: 0.2em;
-webkit-border-radius: 0.2em;
-khtml-border-radius: 0.2em;
border-radius: 0.2em;
}
.icon.first-page {
@@ -419,4 +431,5 @@ div#logout-panel {
#user-list-buttons,
#connection-list-buttons {
text-align: center;
margin: 1em;
}