From 79a90191189ebee17b2259f8a5885d88b77419f4 Mon Sep 17 00:00:00 2001
From: Ian C <ianc@noddybox.co.uk>
Date: Tue, 31 Jul 2018 07:08:54 +0000
Subject: Reverted back to multi-line display.  Found out it was using
 hyperlinks as buttons that was causing the jumping.

---
 www/css/main.css    |  43 +-----
 www/index.html      |  43 +-----
 www/scripts/main.js | 388 +++++++++++++++++++++++++++++++---------------------
 3 files changed, 240 insertions(+), 234 deletions(-)

(limited to 'www')

diff --git a/www/css/main.css b/www/css/main.css
index 64c46f8..33446e3 100644
--- a/www/css/main.css
+++ b/www/css/main.css
@@ -9,49 +9,20 @@ body
 	font-size: x-small;
 }
 
-.fill
+input.fill
 {
 	box-sizing: border-box;
 	display: block;
 	width: 100%;
 }
 
-.fillabs
+tr.style1
 {
-	box-sizing: border-box;
-	display: block;
-	width: 99%;
-	position: absolute;
-	left: 1px;
-	top: 11px;
-}
-
-.fill_0_0_lower
-{
-	box-sizing: border-box;
-	display: block;
-	width: 99%;
-	position: absolute;
-	z-index: 0;
-	left: 1px;
-	top: 11px;
-}
-
-.fill_0_0_higher
-{
-	box-sizing: border-box;
-	display: block;
-	width: 94%;
-	position: absolute;
-	z-index: 100;
-	left: 1px;
-	top: 11px;
+	background-color: #ddddff;
 }
 
-tr.datatable
+tr.style2
 {
-	height: 30px;
-	position: relative;
 	background-color: #ccccff;
 }
 
@@ -73,9 +44,8 @@ td.headerbutton
 td.description
 {
 	width: 35%;
-	min-width: 300px;
+	min-width: 100px;
 	max-width: 500px;
-	position: relative;
 }
 
 td.username
@@ -83,7 +53,6 @@ td.username
 	width: 20%;
 	min-width: 50px;
 	max-width: 200px;
-	position: relative;
 }
 
 td.password
@@ -91,7 +60,6 @@ td.password
 	width: 20%;
 	min-width: 50px;
 	max-width: 200px;
-	position: relative;
 }
 
 td.commands
@@ -99,7 +67,6 @@ td.commands
 	width: 25%;
 	min-width: 50px;
 	max-width: 100px;
-	position: relative;
 }
 
 table.datatable
diff --git a/www/index.html b/www/index.html
index 088767d..ce53bb4 100644
--- a/www/index.html
+++ b/www/index.html
@@ -26,7 +26,7 @@
 <tr>
 <td class="headertext">Group:</td>
 <td class="headerinput">
-<select id="Group" onchange="DoSelectGroup()" class="fill">
+<select id="Group" onchange="DoSelectGroup()">
 </select>
 </td>
 <td class="headerbutton"></td>
@@ -50,51 +50,14 @@
 <input type="password" id="NewPassPhrase" maxlength="512" class="fill">
 </td>
 <td class="headerbutton">
-<input id="ChangePassphrase" type="button" value="Change"
- onclick="DoChangePassphrase()" class="fill" disabled>
+<input id="ChangePassphrase" type="button" value="Change" onclick="DoChangePassphrase()" class="fill" disabled>
 </td>
 </tr>
 </table>
 
 <hr>
 
-<table id="DataTable" class="datatable">
-<tr class="datatable">
-<td class="description">Description</td>
-<td class="username">Username</td>
-<td class="password">Password</td>
-<td class="commands">Commands</td>
-<tr class="datatable">
-<td class="description">
-<select id="DescriptionSelect" class="fill_0_0_lower"
- onchange="DoSelectDescription()">
-</select>
-<input type="text" maxlength="1024" class="fill_0_0_higher" id="Description">
-</td>
-<td class="username">
-<input type="text" maxlength="64" class="fillabs" id="Username">
-</td>
-<td class="password">
-<input type="password" maxlength="64" class="fillabs" id="Password">
-</td>
-<td class="commands">
-<input type="button" id="Edit" value="Edit" onclick="DoEdit()"
- class="smalltext" disabled>
-<input type="button" id="Delete" value="Delete" onclick="DoDelete()"
- class="smalltext" disabled>
-<input type="button" id="Add" value="Add" onclick="DoAdd()" class="smalltext">
-<input type="button" id="Up" value="Up" onclick="DoUp()" class="smalltext"
- disabled>
-<input type="button" id="Down" value="Down" onclick="DoDown()"
- class="smalltext" disabled>
-<br>
-<input type="button" id="CopyUsername" value="Copy Username"
- onclick="DoCopyUsername()" class="smalltext" disabled>
-<input type="button" id="CopyPassword" value="Copy Password"
- onclick="DoCopyPassword()" class="smalltext" disabled>
-</td>
-</tr>
-</table>
+<table id="DataTable" class="datatable"></table>
 
 </body>
 </html>
diff --git a/www/scripts/main.js b/www/scripts/main.js
index 36ac5f3..f75f23c 100644
--- a/www/scripts/main.js
+++ b/www/scripts/main.js
@@ -2,13 +2,28 @@
 var globalDb = [];
 var globalGroups = [];
 var globalCurrentGroup = "";
-var globalCurrentSelection = -1;
+
+var globalScrollY = 0;
 
 function Error(message)
 {
 	alert(message);
 }
 
+function SaveScroll()
+{
+	globalScrollY = window.pageYOffset;
+}
+
+function RestoreScroll()
+{
+	if (globalScrollY > 0)
+	{
+		window.scroll(0, globalScrollY);
+		globalScrollY = 0;
+	}
+}
+
 function SetEnable(id, enabled)
 {
 	var elem = document.getElementById(id);
@@ -107,70 +122,6 @@ function SetInputType(id, type)
 	document.getElementById(id).type = type;
 }
 
-function GetGroupRows()
-{
-	var result = [];
-
-	for(var f = 0; f < globalDb.length; f++)
-	{
-		if (globalDb[f].group == globalCurrentGroup)
-		{
-			result.push(globalDb[f]);
-		}
-	}
-
-	return result;
-}
-
-function GetData(id)
-{
-	for(var f = 0; f < globalDb.length; f++)
-	{
-		if (globalDb[f].id == id)
-		{
-			return globalDb[f];
-		}
-	}
-
-	return null;
-}
-
-function FindNextPrevious()
-{
-	var rows = GetGroupRows();
-	var f;
-	var ret = {prev: -1, next: -1};
-	var prev = -1;
-
-	for(f = 0; f < rows.length; f++)
-	{
-		if (rows[f].id == globalCurrentSelection)
-		{
-			ret.prev = prev;
-
-			if (f < rows.length - 1)
-			{
-				ret.next = rows[f + 1].id;
-			}
-		}
-
-		prev = rows[f].id;
-	}
-
-	return ret;
-}
-
-function SetButtonState()
-{
-	SetEnable("Add", true);
-	SetEnable("Edit", globalCurrentSelection != -1);
-	SetEnable("Delete", globalCurrentSelection != -1);
-	SetEnable("CopyUsername", globalCurrentSelection != -1);
-	SetEnable("CopyPassword", globalCurrentSelection != -1);
-	SetEnable("Up", globalCurrentSelection != -1);
-	SetEnable("Down", globalCurrentSelection != -1);
-}
-
 function LoadGroups(keep_selection)
 {
 	globalGroups = [];
@@ -222,82 +173,207 @@ function LoadGroups(keep_selection)
 	elem.value = globalCurrentGroup;
 }
 
-function LoadDescriptions(keep_selection)
+function AddTableInputCell(id, text, name, maxlen, classname, type, node)
 {
-	var rows = GetGroupRows();
-	var elem = document.getElementById("DescriptionSelect");
-	var f;
+	var td = document.createElement("td");
+	var input = document.createElement("input");
 
-	if (!keep_selection)
+	input.value = text;
+	input.id = name + id;
+	input.type = type;
+	input.maxLength = maxlen;
+	input.className = "fill";
+
+	td.className = classname;
+
+	td.appendChild(input);
+	node.appendChild(td);
+}
+
+function AddSmallButton(node, text, func, id)
+{
+	var button = document.createElement("input");
+
+	button.type = "button";
+	button.onclick = func;
+	button.value = text;
+	button.className = "smalltext";
+	button.dataset.pmId = id;
+
+	node.appendChild(button);
+}
+
+function AddSmallButtonPrevNext(node, text, func, id, prev, next)
+{
+	var button = document.createElement("input");
+
+	button.type = "button";
+	button.onclick = func;
+	button.value = text;
+	button.className = "smalltext";
+	button.dataset.pmId = id;
+	button.dataset.pmPrevId = prev;
+	button.dataset.pmNextId = next;
+
+	node.appendChild(button);
+}
+
+function AddSmallButtonUpDown(node, text, down_func, up_func, id)
+{
+	var button = document.createElement("input");
+
+	button.type = "button";
+	button.onmousedown = down_func;
+	button.onmouseup = up_func;
+	button.value = text;
+	button.className = "smalltext";
+	button.dataset.pmId = id;
+
+	node.appendChild(button);
+}
+
+function AddText(node, text)
+{
+	var t = document.createTextNode(text);
+	node.appendChild(t);
+}
+
+function AddElement(node, elementname)
+{
+	var elem = document.createElement(elementname);
+
+	node.appendChild(elem);
+}
+
+function AddRow(table, id, prev_id, next_id, desc, username, password, rowcount)
+{
+	var tr = document.createElement("tr");
+
+	if ((rowcount % 2) == 1)
 	{
-		globalCurrentSelection = -1;
+		tr.className = "style1";
 	}
-
-	while(elem.length > 0)
+	else
 	{
-		elem.remove(0);
+		tr.className = "style2";
 	}
 
-	var firstid = -1;
-	var selected = false;
+	AddTableInputCell(id, desc, "Description", 1024, "description", "text", tr);
+	AddTableInputCell(id, username, "Username", 256, "username", "text", tr); 
 
-	for(f = 0; f < rows.length; f++)
+	if (ShowPasswords())
 	{
-		var option = document.createElement("option");
+		AddTableInputCell(id, password, "Password", 256,
+							"password", "text", tr); 
+	}
+	else
+	{
+		AddTableInputCell(id, password, "Password", 256,
+							"password", "password", tr); 
+	}
 
-		option.text = rows[f].description;
-		option.value = rows[f].id;
+	var td = document.createElement("td");
 
-		if (firstid == -1)
-		{
-			firstid = rows[f].id;
-		}
+	td.className = "commands";
+
+	if (id == -1)
+	{
+		AddSmallButton(td, "Add", DoAdd, id);
+	}
+	else
+	{
+		AddSmallButton(td, "Edit", DoEdit, id);
+		AddText(td, "\u00a0");
+		AddSmallButton(td, "Delete", DoDelete, id);
+		AddText(td, "\u00a0");
+		AddSmallButtonUpDown(td, "Show", DoShow, DoHide, id);
 
-		if (globalCurrentSelection == rows[f].id)
+		if (next_id != -1 || prev_id != -1)
 		{
-			selected = true;
+			if (prev_id != -1)
+			{
+				AddText(td, "\u00a0");
+				AddSmallButtonPrevNext(td, "Up", DoUp, id, prev_id, next_id);
+			}
+
+			if (next_id != -1)
+			{
+				AddText(td, "\u00a0");
+				AddSmallButtonPrevNext
+					(td, "Down", DoDown, id, prev_id, next_id);
+			}
 		}
 
-		elem.add(option);
-	}
+		AddElement(td, "br");
 
-	if (!selected)
-	{
-		globalCurrentSelection = firstid;
+		AddSmallButton(td, "Copy Username", DoCopyUsername, id);
+		AddText(td, "\u00a0");
+		AddSmallButton(td, "Copy Password", DoCopyPassword, id);
 	}
 
-	if (globalCurrentSelection != -1)
+	tr.appendChild(td);
+
+	table.appendChild(tr);
+}
+
+function GetGroupRows()
+{
+	var result = [];
+
+	for(var f = 0; f < globalDb.length; f++)
 	{
-		elem.value = globalCurrentSelection;
+		if (globalDb[f].group == globalCurrentGroup)
+		{
+			result.push(globalDb[f]);
+		}
 	}
+
+	return result;
 }
 
 function LoadTable()
 {
-	var record = GetData(globalCurrentSelection);
+	var table = document.getElementById("DataTable");
+
+	table.innerHTML = "";
+
+	var rowcount = 0;
 
-	if (record != null)
+	var rows = GetGroupRows();
+
+	for(var f = 0; f < rows.length; f++)
 	{
-		var elem;
+		var prevId = -1;
+		var nextId = -1;
 
-		elem = document.getElementById("Description");
-		elem.value = record.description;
+		if (f > 0)
+		{
+			prevId = rows[f-1].id;
+		}
 
-		elem = document.getElementById("Username");
-		elem.value = record.username;
+		if (f < rows.length - 1)
+		{
+			nextId = rows[f+1].id;
+		}
 
-		elem = document.getElementById("Password");
-		elem.value = Decrypt(record.password);
+		AddRow(table,
+			   rows[f].id,
+			   prevId,
+			   nextId,
+			   rows[f].description,
+			   rows[f].username,
+			   Decrypt(rows[f].password),
+			   rowcount++);
 	}
+
+	AddRow(table, -1, -1, -1, "", "", "", rowcount++);
 }
 
 function RefreshDataAsync()
 {
 	globalDb = JSON.parse(this.responseText);
 	LoadGroups(true);
-	LoadDescriptions(true);
 	LoadTable();
-	SetButtonState();
 }
 
 function RefreshData()
@@ -308,7 +384,6 @@ function RefreshData()
 function LoadInitialData()
 {
 	LoadGroups(false);
-	LoadDescriptions(false);
 	LoadTable();
 }
 
@@ -324,7 +399,6 @@ function DoLoadAsync()
 	else
 	{
 		LoadInitialData();
-		SetButtonState();
 		SetEnable("ChangePassphrase", true);
 	}
 }
@@ -338,7 +412,6 @@ function DoLoad()
 	}
 
 	WebRequest("get.php", DoLoadAsync, []);
-	LoadInitialData();
 }
 
 function DoChangePassphraseAsync()
@@ -383,7 +456,6 @@ function DoChangePassphrase()
 			);
 		}
 
-		document.getElementById("PassPhrase").value = newphrase;
 		document.getElementById("NewPassPhrase").value = "";
 	}
 }
@@ -394,15 +466,6 @@ function DoSelectGroup()
 
 	globalCurrentGroup = elem.value;
 	document.getElementById("NewGroup").value = "";
-	LoadDescriptions(false);
-	LoadTable();
-}
-
-function DoSelectDescription()
-{
-	var elem = document.getElementById("DescriptionSelect");
-
-	globalCurrentSelection = elem.value;
 	LoadTable();
 }
 
@@ -417,28 +480,22 @@ function DoAddAsync()
 	else
 	{
 		globalCurrentGroup = response.group;
-		globalCurrentSelection = response.id;
 		RefreshData();
 	}
 }
 
 function DoAdd()
 {
-	if (IsEmpty("PassPhrase"))
-	{
-		Error("Passphrase empty");
-		return;
-	}
-
 	if (IsEmpty("Group") && IsEmpty("NewGroup"))
 	{
 		Error("No groups defined -- please enter a group name");
 		return;
 	}
 
-	var description = document.getElementById("Description").value;
-	var username = document.getElementById("Username").value;
-	var password = document.getElementById("Password").value;
+	var id = this.dataset.pmId;
+	var description = document.getElementById("Description" + id).value;
+	var username = document.getElementById("Username" + id).value;
+	var password = document.getElementById("Password" + id).value;
 	var group;
 
 	if (description == "" || username == "" | password == "")
@@ -478,16 +535,16 @@ function DoEditAsync()
 	else
 	{
 		globalCurrentGroup = response.group;
-		globalCurrentSelection = response.id;
 		RefreshData();
 	}
 }
 
 function DoEdit()
 {
-	var description = document.getElementById("Description").value;
-	var username = document.getElementById("Username").value;
-	var password = document.getElementById("Password").value;
+	var id = this.dataset.pmId;
+	var description = document.getElementById("Description" + id).value;
+	var username = document.getElementById("Username" + id).value;
+	var password = document.getElementById("Password" + id).value;
 	var group;
 
 	if (description == "" || username == "" | password == "")
@@ -508,7 +565,7 @@ function DoEdit()
 
 	WebRequest("edit.php", DoEditAsync,
 	[
-		"id", globalCurrentSelection,
+		"id", id,
 		"description", description,
 		"group", group,
 		"username", username,
@@ -533,21 +590,26 @@ function DoDeleteAsync()
 
 function DoDelete()
 {
+	var id = this.dataset.pmId;
+
 	WebRequest("delete.php", DoDeleteAsync,
 	[
-		"id", globalCurrentSelection
+		"id", id
 	]
 	);
 }
 
 function DoCopyUsername()
 {
-	Copy("Username");
+	var id = "Username" + this.dataset.pmId;
+	Copy(id);
 }
 
 function DoCopyPassword()
 {
-	var id = "Password";
+	var id = "Password" + this.dataset.pmId;
+
+	SaveScroll();
 
 	if (!ShowPasswords())
 	{
@@ -560,12 +622,15 @@ function DoCopyPassword()
 	{
 		SetInputType(id, "password");
 	}
+
+	RestoreScroll();
 }
 
 function DoShow()
 {
 	if (!ShowPasswords())
 	{
+		SaveScroll();
 		SetInputType("Password" + this.dataset.pmId, "text");
 	}
 }
@@ -575,6 +640,7 @@ function DoHide()
 	if (!ShowPasswords())
 	{
 		SetInputType("Password" + this.dataset.pmId, "password");
+		setTimeout(RestoreScroll, 0);
 	}
 }
 
@@ -589,37 +655,38 @@ function DoReorderAsync()
 	else
 	{
 		RefreshData();
+		RestoreScroll();
 	}
 }
 
 function DoUp()
 {
-	var rec = FindNextPrevious();
+	var id = this.dataset.pmId;
+	var prev = this.dataset.pmPrevId;
 
-	if (rec.prev != -1)
-	{
-		WebRequest("reorder.php", DoReorderAsync,
-		[
-			"from_id", globalCurrentSelection,
-			"to_id", rec.prev
-		]
-		);
-	}
+	SaveScroll();
+
+	WebRequest("reorder.php", DoReorderAsync,
+	[
+		"from_id", id,
+		"to_id", prev
+	]
+	);
 }
 
 function DoDown()
 {
-	var rec = FindNextPrevious();
+	var id = this.dataset.pmId;
+	var next = this.dataset.pmNextId;
 
-	if (rec.next != -1)
-	{
-		WebRequest("reorder.php", DoReorderAsync,
-		[
-			"from_id", globalCurrentSelection,
-			"to_id", rec.next
-		]
-		);
-	}
+	SaveScroll();
+
+	WebRequest("reorder.php", DoReorderAsync,
+	[
+		"from_id", id,
+		"to_id", next
+	]
+	);
 }
 
 function DoShowPasswords()
@@ -637,7 +704,16 @@ function DoShowPasswords()
 
 	SetInputType("PassPhrase", type);
 	SetInputType("NewPassPhrase", type);
-	SetInputType("Password", type);
+	SetInputType("Password-1", type);
+
+	var rows = GetGroupRows();
+	var f;
+
+	for(f = 0; f < rows.length;f++)
+	{
+		var id = "Password" + rows[f].id;
+		SetInputType(id, type);
+	}
 }
 
 // vim: sw=4 ts=4
-- 
cgit v1.2.3