Hello,
I'm trying to code the creation of 'sticky notes' on a webpage with a contextual menu right-click option. I nearly have it working, but there are a couple of things I cannot seem to figure out (I've been trying for a couple of weeks now!).
I'm very new to web development (beginner level).
I've combined some code for the sticky notes and context right-click menu. The problem I'm having is that when the page loads for the first time, a sticky note appears: I do not want that to happen. I would like it to initially load with no sticky notes visable, and only make them visable once they are added, or if they were previously added and automatically saved (which is already part of the code).
So I used `display: none` to hide the css "note" element. However, if I do that then when I right-click to add a note it doesn't show up at all. So I understand I need to tell it to show if it's been created by my right-click menu option, but I've been struggling to understand how to do this.
The second issue I have is that the sticky notes are created in random positions; whereas, I would like them to show up next to where I have right-clicked.
Please could someone point me in the right direction. I apologise for my lack of basic knowledge.
Here is what I have so far:
HTML
CSS
Javascript
Link to download files:
https://www.dropbox.com/s/e6ucgle1a7...-menu.zip?dl=0
I'm trying to code the creation of 'sticky notes' on a webpage with a contextual menu right-click option. I nearly have it working, but there are a couple of things I cannot seem to figure out (I've been trying for a couple of weeks now!).
I'm very new to web development (beginner level).
I've combined some code for the sticky notes and context right-click menu. The problem I'm having is that when the page loads for the first time, a sticky note appears: I do not want that to happen. I would like it to initially load with no sticky notes visable, and only make them visable once they are added, or if they were previously added and automatically saved (which is already part of the code).
So I used `display: none` to hide the css "note" element. However, if I do that then when I right-click to add a note it doesn't show up at all. So I understand I need to tell it to show if it's been created by my right-click menu option, but I've been struggling to understand how to do this.
The second issue I have is that the sticky notes are created in random positions; whereas, I would like them to show up next to where I have right-clicked.
Please could someone point me in the right direction. I apologise for my lack of basic knowledge.
Here is what I have so far:
HTML
HTML:
<!DOCTYPE html>
<html>
<head>
<title>Custom Right Click Menu</title>
<link rel="stylesheet" type="text/css" href="stickies.css" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="stickies.js"></script>
</head>
<body>
<!-- Menu div initially hidden -->
<script>
document.getElementById("newNoteButton").disabled = !db;
</script>
<div class="menu" id="newNoteButton" onclick="newNote()">
<ul>
<a href="#"><li>Add Note</li></a>
</ul>
</div>
</body>
</html>
CSS
Code:
.menu{
width: 100px;
background: #000;
color: #fff;
position:absolute;
z-index: 999999;
display: none;
box-shadow: 0 0 10px #713C3C;
}
.menu ul{
list-style: none;
padding: 0;
margin:0;
}
.menu ul a{
text-decoration: none;
}
.menu ul li{
width: 88%;
padding: 6%;
background-color: #F04D44;
color: #fff;
}
.menu ul li:hover{
background-color: #F7BA4B;
color: #444343;
}
body {
font-family: 'Lucida Grande', 'Helvetica', sans-serif;
}
.note {
background-color: rgb(255, 240, 70);
height: 100px;
padding: 10px;
position: absolute;
width: 200px;
-webkit-box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.5);
}
.note:hover .closebutton {
display: block;
}
.closebutton {
display: none;
background-image: url(deleteButton.png);
height: 30px;
position: absolute;
left: -15px;
top: -15px;
width: 30px;
}
.closebutton:active {
background-image: url(deleteButtonPressed.png);
}
.edit {
outline: none;
}
.timestamp {
position: absolute;
left: 0px;
right: 0px;
bottom: 0px;
font-size: 9px;
background-color: #db0;
color: white;
border-top: 1px solid #a80;
padding: 2px 4px;
text-align: right;
}
Javascript
Code:
$(document).ready(function () {
$("html").on("contextmenu",function(e){
//prevent default context menu for right click
e.preventDefault();
var menu = $(".menu");
//hide menu if already shown
menu.hide();
//get x and y values of the click event
var pageX = e.pageX;
var pageY = e.pageY;
//position menu div near mouse cliked area
menu.css({top: pageY , left: pageX});
var mwidth = menu.width();
var mheight = menu.height();
var screenWidth = $(window).width();
var screenHeight = $(window).height();
//if window is scrolled
var scrTop = $(window).scrollTop();
//if the menu is close to right edge of the window
if(pageX+mwidth > screenWidth){
menu.css({left:pageX-mwidth});
}
//if the menu is close to bottom edge of the window
if(pageY+mheight > screenHeight+scrTop){
menu.css({top:pageY-mheight});
}
//finally show the menu
menu.show();
});
$("html").on("click", function(){
$(".menu").hide();
});
});
var db = null;
try {
if (window.openDatabase) {
db = openDatabase("NoteTest", "1.0", "HTML5 Database API example", 200000);
if (!db)
alert("Failed to open the database on disk. This is probably because the version was bad or there is not enough space left in this domain's quota");
} else
alert("Couldn't open the database. Please try with a WebKit nightly with this feature enabled");
} catch(err) {
db = null;
alert("Couldn't open the database. Please try with a WebKit nightly with this feature enabled");
}
var captured = null;
var highestZ = 0;
var highestId = 0;
function Note()
{
var self = this;
var note = document.createElement('div');
note.className = 'note';
note.addEventListener('mousedown', function(e) { return self.onMouseDown(e) }, false);
note.addEventListener('click', function() { return self.onNoteClick() }, false);
this.note = note;
var close = document.createElement('div');
close.className = 'closebutton';
close.addEventListener('click', function(event) { return self.close(event) }, false);
note.appendChild(close);
var edit = document.createElement('div');
edit.className = 'edit';
edit.setAttribute('contenteditable', true);
edit.addEventListener('keyup', function() { return self.onKeyUp() }, false);
note.appendChild(edit);
this.editField = edit;
var ts = document.createElement('div');
ts.className = 'timestamp';
ts.addEventListener('mousedown', function(e) { return self.onMouseDown(e) }, false);
note.appendChild(ts);
this.lastModified = ts;
document.body.appendChild(note);
return this;
}
Note.prototype = {
get id()
{
if (!("_id" in this))
this._id = 0;
return this._id;
},
set id(x)
{
this._id = x;
},
get text()
{
return this.editField.innerHTML;
},
set text(x)
{
this.editField.innerHTML = x;
},
get timestamp()
{
if (!("_timestamp" in this))
this._timestamp = 0;
return this._timestamp;
},
set timestamp(x)
{
if (this._timestamp == x)
return;
this._timestamp = x;
var date = new Date();
date.setTime(parseFloat(x));
this.lastModified.textContent = modifiedString(date);
},
get left()
{
return this.note.style.left;
},
set left(x)
{
this.note.style.left = x;
},
get top()
{
return this.note.style.top;
},
set top(x)
{
this.note.style.top = x;
},
get zIndex()
{
return this.note.style.zIndex;
},
set zIndex(x)
{
this.note.style.zIndex = x;
},
close: function(event)
{
this.cancelPendingSave();
var note = this;
db.transaction(function(tx)
{
tx.executeSql("DELETE FROM WebKitStickyNotes WHERE id = ?", [note.id]);
});
var duration = event.shiftKey ? 2 : .25;
this.note.style.webkitTransition = '-webkit-transform ' + duration + 's ease-in, opacity ' + duration + 's ease-in';
this.note.offsetTop; // Force style recalc
this.note.style.webkitTransformOrigin = "0 0";
this.note.style.webkitTransform = 'skew(30deg, 0deg) scale(0)';
this.note.style.opacity = '0';
var self = this;
setTimeout(function() { document.body.removeChild(self.note) }, duration * 1000);
},
saveSoon: function()
{
this.cancelPendingSave();
var self = this;
this._saveTimer = setTimeout(function() { self.save() }, 200);
},
cancelPendingSave: function()
{
if (!("_saveTimer" in this))
return;
clearTimeout(this._saveTimer);
delete this._saveTimer;
},
save: function()
{
this.cancelPendingSave();
if ("dirty" in this) {
this.timestamp = new Date().getTime();
delete this.dirty;
}
var note = this;
db.transaction(function (tx)
{
tx.executeSql("UPDATE WebKitStickyNotes SET note = ?, timestamp = ?, left = ?, top = ?, zindex = ? WHERE id = ?", [note.text, note.timestamp, note.left, note.top, note.zIndex, note.id]);
});
},
saveAsNew: function()
{
this.timestamp = new Date().getTime();
var note = this;
db.transaction(function (tx)
{
tx.executeSql("INSERT INTO WebKitStickyNotes (id, note, timestamp, left, top, zindex) VALUES (?, ?, ?, ?, ?, ?)", [note.id, note.text, note.timestamp, note.left, note.top, note.zIndex]);
});
},
onMouseDown: function(e)
{
captured = this;
this.startX = e.clientX - this.note.offsetLeft;
this.startY = e.clientY - this.note.offsetTop;
this.zIndex = ++highestZ;
var self = this;
if (!("mouseMoveHandler" in this)) {
this.mouseMoveHandler = function(e) { return self.onMouseMove(e) }
this.mouseUpHandler = function(e) { return self.onMouseUp(e) }
}
document.addEventListener('mousemove', this.mouseMoveHandler, true);
document.addEventListener('mouseup', this.mouseUpHandler, true);
return false;
},
onMouseMove: function(e)
{
if (this != captured)
return true;
this.left = e.clientX - this.startX + 'px';
this.top = e.clientY - this.startY + 'px';
return false;
},
onMouseUp: function(e)
{
document.removeEventListener('mousemove', this.mouseMoveHandler, true);
document.removeEventListener('mouseup', this.mouseUpHandler, true);
this.save();
return false;
},
onNoteClick: function(e)
{
this.editField.focus();
getSelection().collapseToEnd();
},
onKeyUp: function()
{
this.dirty = true;
this.saveSoon();
},
}
function loaded()
{
db.transaction(function(tx) {
tx.executeSql("SELECT COUNT(*) FROM WebkitStickyNotes", [], function(result) {
loadNotes();
}, function(tx, error) {
tx.executeSql("CREATE TABLE WebKitStickyNotes (id REAL UNIQUE, note TEXT, timestamp REAL, left TEXT, top TEXT, zindex REAL)", [], function(result) {
loadNotes();
});
});
});
}
function loadNotes()
{
db.transaction(function(tx) {
tx.executeSql("SELECT id, note, timestamp, left, top, zindex FROM WebKitStickyNotes", [], function(tx, result) {
for (var i = 0; i < result.rows.length; ++i) {
var row = result.rows.item(i);
var note = new Note();
note.id = row['id'];
note.text = row['note'];
note.timestamp = row['timestamp'];
note.left = row['left'];
note.top = row['top'];
note.zIndex = row['zindex'];
if (row['id'] > highestId)
highestId = row['id'];
if (row['zindex'] > highestZ)
highestZ = row['zindex'];
}
if (!result.rows.length)
newNote();
}, function(tx, error) {
alert('Failed to retrieve notes from database - ' + error.message);
return;
});
});
}
function modifiedString(date)
{
return 'Last Modified: ' + date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ' ' + date.getHours() + ':' + date.getMinutes() + ':' + date.getSeconds();
}
function newNote()
{
var note = new Note();
note.id = ++highestId;
note.timestamp = new Date().getTime();
note.left = Math.round(Math.random() * 400) + 'px';
note.top = Math.round(Math.random() * 500) + 'px';
note.zIndex = ++highestZ;
note.saveAsNew();
}
if (db != null)
addEventListener('load', loaded, false);
Link to download files:
https://www.dropbox.com/s/e6ucgle1a7...-menu.zip?dl=0
Last edited: