Add basic capabilities

stores and loads bookmarks from localStorage, import/export capabilities
This commit is contained in:
Neil Brommer 2017-11-07 20:00:42 -08:00
parent bee398bcef
commit 5798bad50a
7 changed files with 424 additions and 0 deletions

34
.gitignore vendored Normal file
View file

@ -0,0 +1,34 @@
bootstrap/css/
bootstrap/js/
js/jquery-3\.2\.1\.js
js/jquery-3\.2\.1\.min\.js
js/jquery-3\.2\.1\.min\.map
js/popper\.js
img/0\.png
img/1\.png
img/2\.png
img/3\.png
img/4\.png
img/5\.png
img/6\.png
img/7\.png
img/8\.png
js/popper\.js\.map
bookmarkList\.json

0
bootstrap/.gitkeep Normal file
View file

BIN
favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

0
img/.gitkeep Normal file
View file

177
index.html Normal file
View file

@ -0,0 +1,177 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="A new tab page">
<meta name="author" content="Neil Brommer">
<link rel="icon" href="favicon.png">
<title>New Start</title>
<!-- Bootstrap core CSS -->
<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles -->
<link href="main.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-md navbar-dark bg-dark mb-4">
<!-- <a class="navbar-brand" href=".">Start</a >-->
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav mr-auto">
<!-- Keep this to push elements to the right -->
</ul>
<form class="form-inline mt-2 mt-md-0">
<button class="btn btn-light ml-sm-2" type="button" data-Toggle="modal" data-target="#aboutModal">About</button>
<button class="btn btn-light ml-sm-2" type="button" data-Toggle="modal" data-target="#importExportModal">Import/Export</button>
<button class="btn btn-light ml-sm-2" type="button">Edit</button>
<button class="btn btn-light ml-sm-2" type="button" data-toggle="modal" data-target="#newBookmarkModal">Add</button>
</form>
</div>
</nav>
<div id="wrapper" class="container">
<div id="cardList" class="card-columns">
</div>
</div>
<div id="newBookmarkModal" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add Bookmark</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="newBookmarkName">Name</label>
<input id="newBookmarkName" type="text" class="form-control">
</div>
<div class="form-group">
<label for="newBookmarkURL">Address</label>
<input id="newBookmarkURL" type="url" class="form-control">
</div>
<div class="form-group">
<label for="newBookmarkGroup">Group</label>
<select id="newBookmarkGroup" name="Group" class="form-control" onchange="selectGroupChanged(this.value)">
<option value="-">New Group</option>
</select>
</div>
<div id="createGroup" class="form-group newGroup">
<label for="newBookMarkGroupNew">New Group</label>
<input id="newBookMarkGroupNew" type="text" class="form-control">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary">Add</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="importExportModal" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Import/Export</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="exportText">Export</label>
<textarea id="exportText" class="form-control" rows="4"></textarea>
</div>
<div class="form-group">
<label for="importText">Import</label>
<textarea id="importText" class="form-control" rows="4"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" id="btnImport" class="btn btn-primary">Import</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="aboutModal" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">About</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>
<a href="https://github.com/NeilBrommer/NewTabPage">Project on GitHub</a>
</p>
<p>
This page keeps a list of bookmarks separated into groups. It's intended to be used a a new tab page.
</p>
<p>
It uses localStorage to store the list of bookmarks rather than storing them server side.
</p>
<p>
The format for the import/export JSON is:
</p>
<pre>
[
{
"title": "Group title",
"bookmarks": [
{
"name": "Bookmark 1",
"address": "http://example.com"
},
{
"name": "Bookmark 2",
"address": "http://example.net"
}
]
},
{
"title": "Group 2",
"bookmarks": [
{
"name": "Bookmark 3",
"address": "http://example.org"
}
]
}
]
</pre>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="js/jquery-3.2.1.min.js"></script>
<script src="js/popper.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>

145
js/main.js Normal file
View file

@ -0,0 +1,145 @@
$(document).ready(function () {
calcBackground();
loadBookmarks();
$("#importExportModal").on("shown.bs.modal", function () {
var data = getListString();
if (data != null)
$("#exportText").text(data);
else
$("#exportText").text("[]");
});
$("#newBookmarkModal").on("shown.bs.modal", function () {
var combo = $("#newBookmarkGroup");
var data = getList();
for (var i = 0; i < data.length; i++) {
combo.append($("<option></option>").attr({ "value": i }).text(data[i].title));
}
// TODO complete adding bookmarks
window.alert("Adding bookmarks is still incomplete");
$("#newBookmarkModal").modal("hide");
});
$("#btnImport").click(importBookmarks);
$("#exportText").click(function () {
$("#exportText").select();
});
});
function importBookmarks() {
try {
var newData = $.parseJSON($("#importText").val());
} catch (err) {
console.error("Import failed: " + err.message);
window.alert("Failed to import");
return;
}
setList(newData);
$(".bookmarkGroup").remove();
loadBookmarks();
$("#importExportModal").modal("hide");
}
function loadBookmarks() {
var groups = getList();
if (groups != null) {
for (var i = 0; i < groups.length; i++) {
var item = groups[i];
buildCard(item.title, item.bookmarks);
}
} else {
$("#aboutModal").modal("show");
}
}
function buildCard(title, itemList) {
var card = $(document.createElement("div"));
card.attr({ "id": "group-" + title, "class": "card bookmarkGroup" });
var cardHead = $(document.createElement("div"));
cardHead.attr({ "class": "card-header" });
cardHead.text(title);
card.append(cardHead);
var cardList = $(document.createElement("div"));
cardList.attr({ "class": "list-group list-group-flush" });
card.append(cardList);
for (var i = 0; i < itemList.length; i++) {
var item = itemList[i];
var link = $(document.createElement("a"));
link.attr({
"class": "list-group-item list-group-item-action",
"href": item.address
});
link.text(item.name);
cardList.append(link);
}
$("#cardList").append(card);
}
function selectGroupChanged(value) {
if (value == "-")
$("#createGroup").show();
else
$("#createGroup").hide();
}
function calcBackground() {
var now = new Date();
var hours = now.getHours();
var mins = now.getMinutes();
var total = (hours * 60) + mins;
// 24*60 = 1440
// 2:40 between each step
if (total > 300 && total < 460) // 5:00 - 7:40
setBackground(1, false);
else if (total > 460 && total < 620)
setBackground(2, false);
else if (total > 620 && total < 780)
setBackground(3, false);
else if (total > 780 && total < 940)
setBackground(4, false);
else if (total > 940 && total < 1100)
setBackground(5, false);
else if (total > 1100 && total < 1260)
setBackground(6, true);
else if (total > 1260 && total < 1420)
setBackground(7, true);
else
setBackground(8, true);
}
function setBackground(num, dark) {
$("body").css("background-image", "url(img/" + num + ".png)");
if (dark)
$(".btn-light").removeClass("btn-light").addClass("btn-dark");
else
$(".btn-dark").removeClass("btn-dark").addClass("btn-light");
}
function getList() {
return $.parseJSON(window.localStorage.getItem("bookmarks"));
}
function getListString() {
return window.localStorage.getItem("bookmarks");
}
function setList(list) {
if (typeof list == "string") {
window.localStorage.setItem("bookmarks", list);
} else {
var stringified = JSON.stringify(list, null, 4);
window.localStorage.setItem("bookmarks", stringified);
}
}

68
main.css Normal file
View file

@ -0,0 +1,68 @@
body {
width: 100%;
height: 100%;
background: white no-repeat center center fixed;
background-size: cover;
tab-size: 4;
-moz-tab-size: 4;
}
#wrapper {
width: 60%;
}
.card-header {
background-color: #FEA63C;
color: white;
font-size: 16px;
font-weight: 600;
height: 32px;
padding-top: 4px;
}
.list-group-item {
height: 32px;
padding-top: 4px;
}
.card {
border: 0px;
}
.navbar {
background: transparent !important;
}
/* change the number of columns in card-columns */
@media (min-width: 34em) {
.card-columns {
-webkit-column-count: 1;
-moz-column-count: 1;
column-count: 1;
}
}
@media (min-width: 48em) {
.card-columns {
-webkit-column-count: 1;
-moz-column-count: 1;
column-count: 1;
}
}
@media (min-width: 62em) {
.card-columns {
-webkit-column-count: 2;
-moz-column-count: 2;
column-count: 2;
}
}
@media (min-width: 75em) {
.card-columns {
-webkit-column-count: 2;
-moz-column-count: 2;
column-count: 2;
}
}