GUAC-919: Copy Angular changes from old GUAC-546 branch.

This commit is contained in:
James Muehlner authored and Michael Jumper committed 2014-11-03 13:57:01 -08:00
1 parent ac2617b92a
commit 5c43ae4ff9
84 files changed
+16551 -7476

No files matched your search

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -1,25 +0,0 @@
Copyright © 2014 [Eli Grey][1].
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
[1]: http://eligrey.com
@@ -1,197 +0,0 @@
/* Blob.js
* A Blob implementation.
* 2014-07-24
*
* By Eli Grey, http://eligrey.com
* By Devin Samarin, https://github.com/dsamarin
* License: X11/MIT
* See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md
*/
/*global self, unescape */
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
plusplus: true */
/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
(function (view) {
"use strict";
view.URL = view.URL || view.webkitURL;
if (view.Blob && view.URL) {
try {
new Blob;
return;
} catch (e) {}
}
// Internally we use a BlobBuilder implementation to base Blob off of
// in order to support older browsers that only have BlobBuilder
var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) {
var
get_class = function(object) {
return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
}
, FakeBlobBuilder = function BlobBuilder() {
this.data = [];
}
, FakeBlob = function Blob(data, type, encoding) {
this.data = data;
this.size = data.length;
this.type = type;
this.encoding = encoding;
}
, FBB_proto = FakeBlobBuilder.prototype
, FB_proto = FakeBlob.prototype
, FileReaderSync = view.FileReaderSync
, FileException = function(type) {
this.code = this[this.name = type];
}
, file_ex_codes = (
"NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
+ "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
).split(" ")
, file_ex_code = file_ex_codes.length
, real_URL = view.URL || view.webkitURL || view
, real_create_object_URL = real_URL.createObjectURL
, real_revoke_object_URL = real_URL.revokeObjectURL
, URL = real_URL
, btoa = view.btoa
, atob = view.atob
, ArrayBuffer = view.ArrayBuffer
, Uint8Array = view.Uint8Array
, origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/
;
FakeBlob.fake = FB_proto.fake = true;
while (file_ex_code--) {
FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
}
// Polyfill URL
if (!real_URL.createObjectURL) {
URL = view.URL = function(uri) {
var
uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
, uri_origin
;
uri_info.href = uri;
if (!("origin" in uri_info)) {
if (uri_info.protocol.toLowerCase() === "data:") {
uri_info.origin = null;
} else {
uri_origin = uri.match(origin);
uri_info.origin = uri_origin && uri_origin[1];
}
}
return uri_info;
};
}
URL.createObjectURL = function(blob) {
var
type = blob.type
, data_URI_header
;
if (type === null) {
type = "application/octet-stream";
}
if (blob instanceof FakeBlob) {
data_URI_header = "data:" + type;
if (blob.encoding === "base64") {
return data_URI_header + ";base64," + blob.data;
} else if (blob.encoding === "URI") {
return data_URI_header + "," + decodeURIComponent(blob.data);
} if (btoa) {
return data_URI_header + ";base64," + btoa(blob.data);
} else {
return data_URI_header + "," + encodeURIComponent(blob.data);
}
} else if (real_create_object_URL) {
return real_create_object_URL.call(real_URL, blob);
}
};
URL.revokeObjectURL = function(object_URL) {
if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
real_revoke_object_URL.call(real_URL, object_URL);
}
};
FBB_proto.append = function(data/*, endings*/) {
var bb = this.data;
// decode data to a binary string
if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
var
str = ""
, buf = new Uint8Array(data)
, i = 0
, buf_len = buf.length
;
for (; i < buf_len; i++) {
str += String.fromCharCode(buf[i]);
}
bb.push(str);
} else if (get_class(data) === "Blob" || get_class(data) === "File") {
if (FileReaderSync) {
var fr = new FileReaderSync;
bb.push(fr.readAsBinaryString(data));
} else {
// async FileReader won't work as BlobBuilder is sync
throw new FileException("NOT_READABLE_ERR");
}
} else if (data instanceof FakeBlob) {
if (data.encoding === "base64" && atob) {
bb.push(atob(data.data));
} else if (data.encoding === "URI") {
bb.push(decodeURIComponent(data.data));
} else if (data.encoding === "raw") {
bb.push(data.data);
}
} else {
if (typeof data !== "string") {
data += ""; // convert unsupported types to strings
}
// decode UTF-16 to binary string
bb.push(unescape(encodeURIComponent(data)));
}
};
FBB_proto.getBlob = function(type) {
if (!arguments.length) {
type = null;
}
return new FakeBlob(this.data.join(""), type, "raw");
};
FBB_proto.toString = function() {
return "[object BlobBuilder]";
};
FB_proto.slice = function(start, end, type) {
var args = arguments.length;
if (args < 3) {
type = null;
}
return new FakeBlob(
this.data.slice(start, args > 1 ? end : this.data.length)
, type
, this.encoding
);
};
FB_proto.toString = function() {
return "[object Blob]";
};
FB_proto.close = function() {
this.size = 0;
delete this.data;
};
return FakeBlobBuilder;
}(view));
view.Blob = function(blobParts, options) {
var type = options ? (options.type || "") : "";
var builder = new BlobBuilder();
if (blobParts) {
for (var i = 0, len = blobParts.length; i < len; i++) {
builder.append(blobParts[i]);
}
}
return builder.getBlob(type);
};
}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));
@@ -1,30 +0,0 @@
This software is licensed under the MIT/X11 license.
MIT/X11 license
---------------
Copyright &copy; 2011 [Eli Grey][1].
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
[1]: http://eligrey.com
@@ -1,216 +0,0 @@
/* FileSaver.js
* A saveAs() FileSaver implementation.
* 2013-01-23
*
* By Eli Grey, http://eligrey.com
* License: X11/MIT
* See LICENSE.md
*/
/*global self */
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
plusplus: true */
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
var saveAs = saveAs
|| (navigator.msSaveBlob && navigator.msSaveBlob.bind(navigator))
|| (function(view) {
"use strict";
var
doc = view.document
// only get URL when necessary in case BlobBuilder.js hasn't overridden it yet
, get_URL = function() {
return view.URL || view.webkitURL || view;
}
, URL = view.URL || view.webkitURL || view
, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
, can_use_save_link = "download" in save_link
, click = function(node) {
var event = doc.createEvent("MouseEvents");
event.initMouseEvent(
"click", true, false, view, 0, 0, 0, 0, 0
, false, false, false, false, 0, null
);
node.dispatchEvent(event);
}
, webkit_req_fs = view.webkitRequestFileSystem
, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
, throw_outside = function (ex) {
(view.setImmediate || view.setTimeout)(function() {
throw ex;
}, 0);
}
, force_saveable_type = "application/octet-stream"
, fs_min_size = 0
, deletion_queue = []
, process_deletion_queue = function() {
var i = deletion_queue.length;
while (i--) {
var file = deletion_queue[i];
if (typeof file === "string") { // file is an object URL
URL.revokeObjectURL(file);
} else { // file is a File
file.remove();
}
}
deletion_queue.length = 0; // clear queue
}
, dispatch = function(filesaver, event_types, event) {
event_types = [].concat(event_types);
var i = event_types.length;
while (i--) {
var listener = filesaver["on" + event_types[i]];
if (typeof listener === "function") {
try {
listener.call(filesaver, event || filesaver);
} catch (ex) {
throw_outside(ex);
}
}
}
}
, FileSaver = function(blob, name) {
// First try a.download, then web filesystem, then object URLs
var
filesaver = this
, type = blob.type
, blob_changed = false
, object_url
, target_view
, get_object_url = function() {
var object_url = get_URL().createObjectURL(blob);
deletion_queue.push(object_url);
return object_url;
}
, dispatch_all = function() {
dispatch(filesaver, "writestart progress write writeend".split(" "));
}
// on any filesys errors revert to saving with object URLs
, fs_error = function() {
// don't create more object URLs than needed
if (blob_changed || !object_url) {
object_url = get_object_url(blob);
}
if (target_view) {
target_view.location.href = object_url;
} else {
window.open(object_url, "_blank");
}
filesaver.readyState = filesaver.DONE;
dispatch_all();
}
, abortable = function(func) {
return function() {
if (filesaver.readyState !== filesaver.DONE) {
return func.apply(this, arguments);
}
};
}
, create_if_not_found = {create: true, exclusive: false}
, slice
;
filesaver.readyState = filesaver.INIT;
if (!name) {
name = "download";
}
if (can_use_save_link) {
object_url = get_object_url(blob);
save_link.href = object_url;
save_link.download = name;
click(save_link);
filesaver.readyState = filesaver.DONE;
dispatch_all();
return;
}
// Object and web filesystem URLs have a problem saving in Google Chrome when
// viewed in a tab, so I force save with application/octet-stream
// http://code.google.com/p/chromium/issues/detail?id=91158
if (view.chrome && type && type !== force_saveable_type) {
slice = blob.slice || blob.webkitSlice;
blob = slice.call(blob, 0, blob.size, force_saveable_type);
blob_changed = true;
}
// Since I can't be sure that the guessed media type will trigger a download
// in WebKit, I append .download to the filename.
// https://bugs.webkit.org/show_bug.cgi?id=65440
if (webkit_req_fs && name !== "download") {
name += ".download";
}
if (type === force_saveable_type || webkit_req_fs) {
target_view = view;
}
if (!req_fs) {
fs_error();
return;
}
fs_min_size += blob.size;
req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
var save = function() {
dir.getFile(name, create_if_not_found, abortable(function(file) {
file.createWriter(abortable(function(writer) {
writer.onwriteend = function(event) {
target_view.location.href = file.toURL();
deletion_queue.push(file);
filesaver.readyState = filesaver.DONE;
dispatch(filesaver, "writeend", event);
};
writer.onerror = function() {
var error = writer.error;
if (error.code !== error.ABORT_ERR) {
fs_error();
}
};
"writestart progress write abort".split(" ").forEach(function(event) {
writer["on" + event] = filesaver["on" + event];
});
writer.write(blob);
filesaver.abort = function() {
writer.abort();
filesaver.readyState = filesaver.DONE;
};
filesaver.readyState = filesaver.WRITING;
}), fs_error);
}), fs_error);
};
dir.getFile(name, {create: false}, abortable(function(file) {
// delete file if it already exists
file.remove();
save();
}), abortable(function(ex) {
if (ex.code === ex.NOT_FOUND_ERR) {
save();
} else {
fs_error();
}
}));
}), fs_error);
}), fs_error);
}
, FS_proto = FileSaver.prototype
, saveAs = function(blob, name) {
return new FileSaver(blob, name);
}
;
FS_proto.abort = function() {
var filesaver = this;
filesaver.readyState = filesaver.DONE;
dispatch(filesaver, "abort");
};
FS_proto.readyState = FS_proto.INIT = 0;
FS_proto.WRITING = 1;
FS_proto.DONE = 2;
FS_proto.error =
FS_proto.onwritestart =
FS_proto.onprogress =
FS_proto.onwrite =
FS_proto.onabort =
FS_proto.onerror =
FS_proto.onwriteend =
null;
view.addEventListener("unload", process_deletion_queue, false);
return saveAs;
}(self));
@@ -1,400 +0,0 @@
/*
* Copyright (C) 2013 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* General set of UI elements and UI-related functions regarding user login and
* connection management.
*/
var GuacamoleRootUI = {
"sections": {
"login_form" : document.getElementById("login-form"),
"recent_connections" : document.getElementById("recent-connections"),
"all_connections" : document.getElementById("all-connections")
},
"messages": {
"login_error" : document.getElementById("login-error"),
"no_recent_connections" : document.getElementById("no-recent")
},
"fields": {
"username" : document.getElementById("username"),
"password" : document.getElementById("password"),
},
"buttons": {
"login" : document.getElementById("login"),
"logout" : document.getElementById("logout"),
"manage" : document.getElementById("manage")
},
"views": {
"login" : document.getElementById("login-ui"),
"connections" : document.getElementById("connection-list-ui")
},
"parameters" : null
};
// Get parameters from query string
GuacamoleRootUI.parameters = window.location.search.substring(1) || null;
/**
* A connection UI object which can be easily added to a list of connections
* for sake of display.
*
* @param {String} id The ID of this object, including prefix.
* @param {String} name The name that should be displayed.
*/
GuacamoleRootUI.RecentConnection = function(id, name) {
/**
* The ID of this object, including prefix.
* @type String
*/
this.id = id;
/**
* The displayable name of this object.
* @type String
*/
this.name = name;
// Create connection display elements
var element = GuacUI.createElement("div", "connection");
var thumbnail = GuacUI.createChildElement(element, "div", "thumbnail");
var caption = GuacUI.createChildElement(element, "div", "caption");
var name_element = GuacUI.createChildElement(caption, "span", "name");
// Connect on click
element.addEventListener("click", function(e) {
// Prevent click from affecting parent
e.stopPropagation();
e.preventDefault();
// Open connection
GuacUI.openObject(id, GuacamoleRootUI.parameters);
}, false);
// Set name
name_element.textContent = name;
// Add screenshot if available
var thumbnail_url = GuacamoleHistory.get(id).thumbnail;
if (thumbnail_url) {
// Create thumbnail element
var thumb_img = GuacUI.createChildElement(thumbnail, "img");
thumb_img.src = thumbnail_url;
}
/**
* Returns the DOM element representing this connection.
*/
this.getElement = function() {
return element;
};
/**
* Sets the thumbnail URL of this existing connection. Note that this will
* only work if the connection already had a thumbnail associated with it.
*/
this.setThumbnail = function(url) {
// If no image element, create it
if (!thumb_img) {
thumb_img = document.createElement("img");
thumb_img.src = url;
thumbnail.appendChild(thumb_img);
}
// Otherwise, set source of existing
else
thumb_img.src = url;
};
};
/**
* Set of all thumbnailed connections, indexed by ID. Here, each connection
* is a GuacamoleRootUI.RecentConnection.
*/
GuacamoleRootUI.recentConnections = {};
/**
* Set of all connections, indexed by ID. Each connection is a
* GuacamoleService.Connection.
*/
GuacamoleRootUI.connections = {};
/**
* Adds the given RecentConnection to the recent connections list.
*/
GuacamoleRootUI.addRecentConnection = function(id, name) {
// Create recent connection object
var connection = new GuacamoleRootUI.RecentConnection(id, name);
// Add connection object to list of thumbnailed connections
GuacamoleRootUI.recentConnections[connection.id] =
connection;
// Add connection to recent list
GuacamoleRootUI.sections.recent_connections.appendChild(
connection.getElement());
// Hide "No recent connections" message
GuacamoleRootUI.messages.no_recent_connections.style.display = "none";
};
/**
* Resets the interface such that the login UI is displayed if
* the user is not authenticated (or authentication fails) and
* the connection list UI (or the client for the only available
* connection, if there is only one) is displayed if the user is
* authenticated.
*/
GuacamoleRootUI.reset = function() {
function hasEntry(object) {
for (var name in object)
return true;
return false;
}
// Read root group
var root_group;
try {
root_group = GuacamoleService.Connections.list(GuacamoleRootUI.parameters);
// Show admin elements if admin permissions available
var permissions = GuacamoleService.Permissions.list(null, GuacamoleRootUI.parameters);
if (permissions.administer
|| permissions.create_connection
|| permissions.create_user
|| hasEntry(permissions.update_user)
|| hasEntry(permissions.remove_user)
|| hasEntry(permissions.administer_user)
|| hasEntry(permissions.update_connection)
|| hasEntry(permissions.remove_connection)
|| hasEntry(permissions.administer_connection))
GuacUI.addClass(document.body, "admin");
else
GuacUI.removeClass(document.body, "admin");
}
catch (e) {
// Show login UI if unable to get connections
GuacamoleRootUI.views.login.style.display = "";
GuacamoleRootUI.views.connections.style.display = "none";
return;
}
// Create group view
var group_view = new GuacUI.GroupView(root_group, GuacUI.GroupView.SHOW_CONNECTIONS);
GuacamoleRootUI.sections.all_connections.appendChild(group_view.getElement());
// Add any connections with thumbnails
for (var connection_id in group_view.connections) {
// Get corresponding connection
var connection = group_view.connections[connection_id];
// If thumbnail exists, add to recent connections
if (GuacamoleHistory.get("c/" + connection_id).thumbnail)
GuacamoleRootUI.addRecentConnection("c/" + connection_id, connection.name);
}
// Add any groups with thumbnails
for (var group_id in group_view.groups) {
// Get corresponding group
var group = group_view.groups[group_id];
// If thumbnail exists, add to recent connections
if (GuacamoleHistory.get("g/" + group_id).thumbnail)
GuacamoleRootUI.addRecentConnection("g/" + group_id, group.name);
}
// Open connections when clicked
group_view.onconnectionclick = function(connection) {
GuacUI.openConnection(connection.id, GuacamoleRootUI.parameters);
};
// Open connection groups when clicked
group_view.ongroupclick = function(group) {
// Connect if balancing
if (group.type === GuacamoleService.ConnectionGroup.Type.BALANCING)
GuacUI.openConnectionGroup(group.id, GuacamoleRootUI.parameters);
};
// Save all connections for later reference
GuacamoleRootUI.connections = group_view.connections;
// If connections could be retrieved, display list
GuacamoleRootUI.views.login.style.display = "none";
GuacamoleRootUI.views.connections.style.display = "";
};
GuacamoleHistory.onchange = function(id, old_entry, new_entry) {
// Get existing connection, if any
var connection = GuacamoleRootUI.recentConnections[id];
// If we are adding or updating a connection
if (new_entry) {
// Ensure connection is added
if (!connection) {
// If connection not actually defined, storage must be being
// modified externally. Stop early.
if (!GuacamoleRootUI.connections[id]) return;
// Create new connection
GuacamoleRootUI.addRecentConnection(id, connection.name);
}
// Set new thumbnail
connection.setThumbnail(new_entry.thumbnail);
}
// Otherwise, delete existing connection
else {
GuacamoleRootUI.sections.recent_connections.removeChild(
connection.getElement());
delete GuacamoleRootUI.recentConnections[id];
// Display "No recent connections" message if none left
if (GuacamoleRootUI.recentConnections.length === 0)
GuacamoleRootUI.messages.no_recent_connections.style.display = "";
}
};
/*
* This window has no name. We need it to have no name. If someone navigates
* to the root UI within the same window as a previous connection, we need to
* remove the name from that window such that new attempts to use that previous
* connection do not replace the contents of this very window.
*/
window.name = "";
/*
* Set handler for logout
*/
GuacamoleRootUI.buttons.logout.onclick = function() {
window.location.href = "logout";
};
/*
* Set handler for admin
*/
GuacamoleRootUI.buttons.manage.onclick = function() {
window.location.href = "admin.xhtml";
};
/*
* Set handler for login
*/
GuacamoleRootUI.sections.login_form.onsubmit = function() {
try {
GuacUI.removeClass(GuacamoleRootUI.views.login, "error");
// Attempt login
GuacamoleService.Auth.login(
GuacamoleRootUI.fields.username.value,
GuacamoleRootUI.fields.password.value
);
// Ensure username/password fields are blurred after login attempt
GuacamoleRootUI.fields.username.blur();
GuacamoleRootUI.fields.password.blur();
// Reset UI
GuacamoleRootUI.reset();
}
catch (e) {
window.setTimeout(function() {
// Display error
GuacUI.addClass(GuacamoleRootUI.views.login, "error");
GuacamoleRootUI.messages.login_error.textContent = e.message;
// Reset and refocus password field
GuacamoleRootUI.fields.password.value = "";
GuacamoleRootUI.fields.password.focus();
}, 1);
}
// Always cancel submit
return false;
};
/*
* Turn off autocorrect and autocapitalization on usename
*/
GuacamoleRootUI.fields.username.setAttribute("autocorrect", "off");
GuacamoleRootUI.fields.username.setAttribute("autocapitalize", "off");
/*
* Initialize UI
*/
GuacamoleRootUI.reset();
/*
* Make sure body has an associated touch event handler such that CSS styles
* will work in browsers that require this.
*/
document.body.ontouchstart = function() {};
File diff suppressed because it is too large. Load diff