Compare commits
12
Commits
d54e48263b
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3fd128057d | ||
|
|
789469e89a | ||
|
|
20287ddfbc | ||
|
|
487f4e0bfb | ||
|
|
b9ebe41370 | ||
|
|
e4a008d41e | ||
|
|
190076b3b6 | ||
|
|
fefde63871 | ||
|
|
1e6a4b2fdf | ||
|
|
029d2276fa | ||
|
|
e7a34b32cb | ||
|
|
098ffc7d77 |
No files matched your search
@@ -0,0 +1,90 @@
|
|||||||
|
body{
|
||||||
|
background-color:#f9f5f4;
|
||||||
|
columns:#555555;
|
||||||
|
font-family:Arial, Helvetica, sans-serif;
|
||||||
|
font-size:16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#storageBrowser{
|
||||||
|
background-color: #ddfe7d ;
|
||||||
|
margin:2.5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
border:1px black solid;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#storageBrowserHeader{
|
||||||
|
background-color:#f9f5f4;
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: bold;
|
||||||
|
border-radius: 5px;
|
||||||
|
border-bottom:1px black solid;
|
||||||
|
border-right: 1px black solid;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right{
|
||||||
|
float:right;
|
||||||
|
padding: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#addNoteDiv{
|
||||||
|
margin:2.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#addNoteButton{
|
||||||
|
height: 26px;
|
||||||
|
width: 26px;
|
||||||
|
font-size: 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mainHeader h1{
|
||||||
|
margin:0;
|
||||||
|
padding:2.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mainHeader h6{
|
||||||
|
margin-top:0;
|
||||||
|
padding:2.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.noteDiv{
|
||||||
|
background-color: #ddfe7d ;
|
||||||
|
padding:5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-top:2px;
|
||||||
|
display: inline-block;
|
||||||
|
border:1px black solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.browserElement{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader {
|
||||||
|
border: 3.2px solid #f3f3f3;
|
||||||
|
border-radius: 50%;
|
||||||
|
border-top: 3.2px solid #3498db;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
-webkit-animation: spin 2s linear infinite; /* Safari */
|
||||||
|
animation: spin 2s linear infinite;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes spin {
|
||||||
|
0% { -webkit-transform: rotate(0deg); }
|
||||||
|
100% { -webkit-transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Document</title>
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
||||||
|
<script src="/scripts/notes_app.js"></script>
|
||||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="/css/notes_app.css" type="text/css">
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id=mainHeader>
|
||||||
|
<h1>
|
||||||
|
Quick Notes
|
||||||
|
</h1>
|
||||||
|
<h6>
|
||||||
|
A simple note web app to demonstrate the usage of Promises/Async/Await.
|
||||||
|
</h6>
|
||||||
|
</div>
|
||||||
|
<div id=storageBrowser>
|
||||||
|
<div id=storageBrowserHeader>All Notes</div>
|
||||||
|
<div class=right>
|
||||||
|
<button class="btn btn-default btn-xs" id="refreshButton"><span class="glyphicon glyphicon-refresh"></span></button>
|
||||||
|
</div>
|
||||||
|
<div id=noteStorage></div>
|
||||||
|
</div>
|
||||||
|
<div id=addNoteDiv>
|
||||||
|
<button type="button" id=addNoteButton>+</button>
|
||||||
|
</div>
|
||||||
|
<div id=allNotesDiv>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,378 @@
|
|||||||
|
$(document).ready(function(){
|
||||||
|
|
||||||
|
$("#addNoteDiv").on('click', function() {
|
||||||
|
|
||||||
|
// Listener für den Plus Button zum hinzufügen von Note Forms.
|
||||||
|
|
||||||
|
console.log("Add")
|
||||||
|
|
||||||
|
createForm();
|
||||||
|
})
|
||||||
|
|
||||||
|
$('#allNotesDiv').on('click', 'button', async function() {
|
||||||
|
|
||||||
|
// Listener für den Save Button zum speichern von Note Forms.
|
||||||
|
|
||||||
|
console.log("Save")
|
||||||
|
|
||||||
|
let buttonId = (this.id).split("_")[1];
|
||||||
|
let type = (this.id).split("_")[0];
|
||||||
|
try {
|
||||||
|
if (type == 'saveNoteButton'){
|
||||||
|
// Speichern einer neuen Note.
|
||||||
|
await saveNoteObject(buttonId);
|
||||||
|
} else if (type == 'editNoteButton'){
|
||||||
|
// Editieren einer gespeicherten Note.
|
||||||
|
await saveNoteObject(buttonId, true);
|
||||||
|
}
|
||||||
|
} catch(err){
|
||||||
|
alert(err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$('#noteStorage').on('click', 'button', async function() {
|
||||||
|
|
||||||
|
// Listener für den Delete Button zum Löschen einer Note aus dem Note Browser und Local Storage.
|
||||||
|
|
||||||
|
console.log("Delete")
|
||||||
|
|
||||||
|
let buttonId = (this.id).split("_")[1];
|
||||||
|
try {
|
||||||
|
await removeBrowserItem(buttonId);
|
||||||
|
} catch(err) {
|
||||||
|
alert(err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
$("#refreshButton").on('click', async function() {
|
||||||
|
|
||||||
|
// Listener für den Refresh Button zum aktualisieren der gespeicherten Notes.
|
||||||
|
|
||||||
|
console.log("Refresh")
|
||||||
|
|
||||||
|
createLoadingSign(id="", append="noteStorage");
|
||||||
|
enableLoadingSign(id="");
|
||||||
|
await sleep(2000);
|
||||||
|
disableLoadingSign(id="");
|
||||||
|
try {
|
||||||
|
await refreshBrowser();
|
||||||
|
} catch(err){
|
||||||
|
alert(err);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
let id=1;
|
||||||
|
|
||||||
|
function createForm(){
|
||||||
|
|
||||||
|
// DOM-Schnittstelle zur Erstellung einer NoteForm mit ID-Kennung.
|
||||||
|
// Initialisiert die OnClick-Listener auf den Buttons der Form.
|
||||||
|
|
||||||
|
id++;
|
||||||
|
|
||||||
|
console.log("createForm() "+id)
|
||||||
|
|
||||||
|
let wrapper = document.createElement("div");
|
||||||
|
wrapper.setAttribute('id', "note"+id);
|
||||||
|
wrapper.style.margin = '2.5px';
|
||||||
|
let inputsWrapper = document.createElement("div");
|
||||||
|
inputsWrapper.setAttribute('class', "noteDiv");
|
||||||
|
|
||||||
|
let inputDiv = document.createElement("div");
|
||||||
|
let input = document.createElement("input");
|
||||||
|
let deleteButton = document.createElement('button');
|
||||||
|
input.setAttribute('type', "text");
|
||||||
|
input.setAttribute('name',"noteTitle");
|
||||||
|
input.setAttribute('id', "inputTitle"+id);
|
||||||
|
input.setAttribute('placeholder', "Enter title...");
|
||||||
|
input.style.marginBottom='5px';
|
||||||
|
deleteButton.style.marginLeft = '2px';
|
||||||
|
deleteButton.innerHTML = "X";
|
||||||
|
deleteButton.setAttribute('id', "deleteForm_" + id);
|
||||||
|
deleteButton.setAttribute('onClick', "deleteForm(this.id)");
|
||||||
|
deleteButton.setAttribute('class', "right");
|
||||||
|
inputDiv.appendChild(input);
|
||||||
|
inputDiv.appendChild(deleteButton);
|
||||||
|
|
||||||
|
let textAreaDiv = document.createElement("div");
|
||||||
|
let textarea = document.createElement("textarea");
|
||||||
|
textarea.setAttribute('name',"noteText");
|
||||||
|
textarea.setAttribute('id', "noteText"+id);
|
||||||
|
textarea.setAttribute('placeholder', "Enter notes...");
|
||||||
|
textarea.style.width='300px';
|
||||||
|
textarea.style.height='150px';
|
||||||
|
textarea.style.boxSizing='border-box';
|
||||||
|
textAreaDiv.appendChild(textarea);
|
||||||
|
|
||||||
|
let saveNoteButton = document.createElement("button");
|
||||||
|
saveNoteButton.setAttribute('type',"button");
|
||||||
|
saveNoteButton.setAttribute('id',"saveNoteButton_"+id);
|
||||||
|
saveNoteButton.innerHTML = 'Save';
|
||||||
|
|
||||||
|
inputsWrapper.appendChild(inputDiv);
|
||||||
|
inputsWrapper.appendChild(textAreaDiv);
|
||||||
|
inputsWrapper.appendChild(saveNoteButton);
|
||||||
|
wrapper.appendChild(inputsWrapper);
|
||||||
|
|
||||||
|
document.getElementById('allNotesDiv').appendChild(wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteForm(idName){
|
||||||
|
|
||||||
|
// Aktiviert durch OnClickListener auf dem X-Button innerhalb der Form zum Schließen/Löschen einer Form mit ID-Kennung.
|
||||||
|
|
||||||
|
console.log("deleteForm() " + id);
|
||||||
|
|
||||||
|
id = idName.split("_")[1];
|
||||||
|
document.getElementById("note"+id).remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFormWithSavedContent(item, id){
|
||||||
|
|
||||||
|
// DOM-Schnittstelle.
|
||||||
|
// Holt eine gespeicherte Form aus dem Speicher und erstellt erneut eine Note Form mit alter ID-Kennung und initialisiert die OnClick-Listener auf den Buttons.
|
||||||
|
|
||||||
|
console.log("createFormWithSavedContent() "+ id)
|
||||||
|
|
||||||
|
let wrapper = document.createElement("div")
|
||||||
|
wrapper.setAttribute('id', "note"+id)
|
||||||
|
let inputsWrapper = document.createElement("div")
|
||||||
|
inputsWrapper.setAttribute('class', "noteDiv");
|
||||||
|
|
||||||
|
let inputDiv = document.createElement("div");
|
||||||
|
let input = document.createElement("input");
|
||||||
|
let deleteButton = document.createElement('button');
|
||||||
|
input.setAttribute('type', "text");
|
||||||
|
input.setAttribute('name',"noteTitle");
|
||||||
|
input.setAttribute('id', "inputTitle"+id);
|
||||||
|
input.setAttribute('value', item.title);
|
||||||
|
input.style.marginBottom='5px';
|
||||||
|
deleteButton.style.marginLeft = '2px';
|
||||||
|
deleteButton.innerHTML = "X";
|
||||||
|
deleteButton.setAttribute('id', "deleteForm_" + id);
|
||||||
|
deleteButton.setAttribute('onClick', "deleteForm(this.id)");
|
||||||
|
inputDiv.appendChild(input);
|
||||||
|
inputDiv.appendChild(deleteButton);
|
||||||
|
|
||||||
|
let textAreaDiv = document.createElement("div");
|
||||||
|
let textarea = document.createElement("textarea");
|
||||||
|
textarea.setAttribute('name',"noteText");
|
||||||
|
textarea.setAttribute('id', "noteText"+id);
|
||||||
|
textarea.setAttribute('value', item.text);
|
||||||
|
textarea.innerHTML = item.text;
|
||||||
|
textarea.style.width='300px';
|
||||||
|
textarea.style.height='150px';
|
||||||
|
textarea.style.boxSizing='border-box';
|
||||||
|
textAreaDiv.appendChild(textarea);
|
||||||
|
|
||||||
|
let editNoteButton = document.createElement("button");
|
||||||
|
editNoteButton.setAttribute('type',"button");
|
||||||
|
editNoteButton.setAttribute('id',"editNoteButton_"+id);
|
||||||
|
editNoteButton.innerHTML = 'Save';
|
||||||
|
|
||||||
|
inputsWrapper.appendChild(inputDiv);
|
||||||
|
inputsWrapper.appendChild(textAreaDiv);
|
||||||
|
inputsWrapper.appendChild(editNoteButton);
|
||||||
|
wrapper.appendChild(inputsWrapper);
|
||||||
|
|
||||||
|
document.getElementById('allNotesDiv').appendChild(wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
let ctr;
|
||||||
|
|
||||||
|
async function sleep(ms) {
|
||||||
|
|
||||||
|
// Best Practice Variante zum pausieren von Code.
|
||||||
|
// Soll hier Prozesse simulieren die bei synchronem Code zu I/O-Blocking führen würden.
|
||||||
|
|
||||||
|
console.log("sleep() " + ms);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
catch (alert) {
|
||||||
|
return alert(alert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveNote(id){
|
||||||
|
|
||||||
|
// Holt den Inhalt aus der gebindeten Note und speichert diesen als Objekt mit ID-Kennung im Local Storage.
|
||||||
|
|
||||||
|
console.log("saveNote() " + id);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
let noteTitle = document.getElementById('inputTitle' + id).value;
|
||||||
|
let noteText = document.getElementById('noteText' + id).value;
|
||||||
|
let noteObj = {
|
||||||
|
idK: id,
|
||||||
|
title: noteTitle,
|
||||||
|
text: noteText
|
||||||
|
};
|
||||||
|
let noteObj_serialized = JSON.stringify(noteObj); // Stringify noteObj damit es im LocalStorage lesbar ist.
|
||||||
|
localStorage.setItem("noteObj" + id, noteObj_serialized);
|
||||||
|
resolve(noteObj);
|
||||||
|
} catch(err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshBrowser(){
|
||||||
|
|
||||||
|
// Aktualisiert den Browserinhalt nach drücken des Refreshbuttons.
|
||||||
|
// Holt sich zuerst ein Abbild des Local Storage und erstellt dann für jedes Element ein Item im Browser.
|
||||||
|
|
||||||
|
console.log("refreshBrowser()");
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
let noteStorage = [];
|
||||||
|
let keys = Object.keys(localStorage);
|
||||||
|
let i = keys.length;
|
||||||
|
while (i--) {
|
||||||
|
noteStorage.push(localStorage.getItem(keys[i]));
|
||||||
|
}
|
||||||
|
let parentNode = document.getElementById('noteStorage');
|
||||||
|
parentNode.innerHTML = '';
|
||||||
|
noteStorage.forEach(element => {
|
||||||
|
createBrowserItem(JSON.parse(element));
|
||||||
|
});
|
||||||
|
resolve();
|
||||||
|
} catch(err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveNoteObject(id, overwrite=false){
|
||||||
|
|
||||||
|
// Wird vom Save Button zum Speichern einer Note und Erstellung eines entsprechenden Browseritems aufgerufen.
|
||||||
|
|
||||||
|
console.log("saveNoteObject() " + id + " " + overwrite);
|
||||||
|
|
||||||
|
createLoadingSign(id, append="note")
|
||||||
|
enableLoadingSign(id);
|
||||||
|
await sleep(10000)
|
||||||
|
disableLoadingSign(id);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (overwrite == true){
|
||||||
|
await removeBrowserItem(id);
|
||||||
|
}
|
||||||
|
let obj = await saveNote(id);
|
||||||
|
createBrowserItem(obj);
|
||||||
|
} catch(err){
|
||||||
|
alert(err)
|
||||||
|
}
|
||||||
|
document.getElementById("note"+id).remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
function enableLoadingSign(id){
|
||||||
|
|
||||||
|
console.log("enableLoadingSign() " + id);
|
||||||
|
|
||||||
|
let target = 'loadSign'+id;
|
||||||
|
document.getElementById(target).style.display = "block";
|
||||||
|
}
|
||||||
|
|
||||||
|
function disableLoadingSign(id){
|
||||||
|
|
||||||
|
console.log("disableLoadingSign() " + id);
|
||||||
|
|
||||||
|
let target = 'loadSign'+id;
|
||||||
|
let sign = document.getElementById(target);
|
||||||
|
sign.style.display = "none";
|
||||||
|
sign.parentNode.removeChild(sign);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createLoadingSign(id, append){
|
||||||
|
|
||||||
|
console.log("createLoadingSign() " + id);
|
||||||
|
|
||||||
|
let target = 'loadSign'+id;
|
||||||
|
let appendTo = append+id;
|
||||||
|
let loadingSign = document.createElement('div');
|
||||||
|
let loadingSignWrapper = document.createElement('div');
|
||||||
|
loadingSign.setAttribute('class', 'loader')
|
||||||
|
loadingSign.setAttribute('id', target);
|
||||||
|
loadingSignWrapper.appendChild(loadingSign);
|
||||||
|
document.getElementById(appendTo).appendChild(loadingSignWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createBrowserItem(item){
|
||||||
|
|
||||||
|
// DOM-Schnittstelle zur Erstellung eines Browseritems.
|
||||||
|
|
||||||
|
console.log("createBrowserItem() " + item);
|
||||||
|
|
||||||
|
let wrapperDiv = document.createElement('div');
|
||||||
|
let browserItem = document.createElement('div');
|
||||||
|
let deleteButton = document.createElement('button');
|
||||||
|
wrapperDiv.setAttribute('class', 'browserElement');
|
||||||
|
browserItem.innerHTML = item.title;
|
||||||
|
deleteButton.style.marginLeft = '2px';
|
||||||
|
deleteButton.innerHTML = "X";
|
||||||
|
browserItem.setAttribute('id', "browserItem_"+item.idK);
|
||||||
|
browserItem.setAttribute('onClick', "getSavedNote(this.id)");
|
||||||
|
deleteButton.setAttribute('id', "deleteItem_" + item.idK);
|
||||||
|
wrapperDiv.appendChild(browserItem);
|
||||||
|
wrapperDiv.appendChild(deleteButton);
|
||||||
|
document.getElementById('noteStorage').appendChild(wrapperDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeBrowserItem(id){
|
||||||
|
|
||||||
|
// DOM-Schnittstelle zum Löschen eines Browseritems.
|
||||||
|
|
||||||
|
console.log("removeBrowserItem() " + id);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
localStorage.removeItem('noteObj' + id);
|
||||||
|
document.getElementById("browserItem_" + id).remove();
|
||||||
|
document.getElementById("deleteItem_" + id).remove();
|
||||||
|
resolve();
|
||||||
|
} catch(err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getItemFromStorage(idTmp){
|
||||||
|
|
||||||
|
// Holt ein Note Objekt aus dem Local Storage.
|
||||||
|
|
||||||
|
console.log("getItemFromStorage() " + idTmp);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
let item = JSON.parse(localStorage.getItem('noteObj'+idTmp));
|
||||||
|
resolve(item);
|
||||||
|
} catch (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function getSavedNote(id){
|
||||||
|
|
||||||
|
// Wird durch den OnClick-Listener auf dem Browseritem aufgerufen.
|
||||||
|
|
||||||
|
console.log("getSavedNote() "+ id);
|
||||||
|
|
||||||
|
createLoadingSign("", "allNotesDiv");
|
||||||
|
enableLoadingSign("");
|
||||||
|
await sleep(5000);
|
||||||
|
disableLoadingSign("");
|
||||||
|
let idTmp = id.split("_")[1];
|
||||||
|
try {
|
||||||
|
let item = await getItemFromStorage(idTmp);
|
||||||
|
createFormWithSavedContent(item, idTmp);
|
||||||
|
} catch(err) {
|
||||||
|
alert(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user