In this tutorial, we are going to create a simple pagination program in Node JS and Mongo DB. For the sake of simplicity, we will be using the Express framework. If you prefer a video tutorial over a textual tutorial, then you can follow the video tutorial below:
Video tutorial
Pagination – Node JS, Mongo DB, Express
Mongo DB data
First, we are going to fill the data in Mongo DB. You can apply this tutorial to your own collections and documents. Or you can import the following (at the end) JSON file in your database using Mongo DB compass. You need to create a database named “pagination_nodejs_mongodb” before importing the file.
Setup the project
Create an empty new folder and enter it with the following commands from Terminal:
mkdir pagination-nodejs-mongodb
cd pagination-nodejs-mongodb
Once in the folder, you can install the required modules by running the following commands:
The express framework is used to create web applications and APIs, and we will be creating an API to fetch the data for pagination. HTTP module will be used to start the server at a specific port. Mongo DB module will be used to connect and interact with the Mongo DB database. And finally, EJS will be used to render HTML files.
Create a file named “server.js” and write the following code in it:
// initialize express framework
var express = require("express");
var app = express();
// create http server
var http = require("http").createServer(app);
// start the server
http.listen(3000, function () {
console.log("Server started at port 3000");
});
Run the following command to start the server.
nodemon server.js
This will start the server at port 3000. If you open your terminal, you will see the above message.
Pagination
Now you need to include the Mongo DB module, write the following lines before line 8.
// include mongo DB module
var mongodb = require("mongodb");
var mongoClient = mongodb.MongoClient;
var ObjectId = mongodb.ObjectId;
Then you can connect with the Mongo DB server. You need to write the following lines inside http.listen function callback (2nd parameter):
// connect with mongo DB server and database
mongoClient.connect("mongodb://localhost:27017", {
useUnifiedTopology: true
}, function (error, client) {
var database = client.db("pagination_nodejs_mongodb");
console.log("Database connected.");
});
If you check your terminal now, you will see a second message that your database has been connected. Now we need to create a GET route which when accessed will display 2 users per page from the users collection data. So paste the following lines after the database is connected:
// create a GET HTTP route
app.get("/", async function (request, result) {
// number of records you want to show per page
const perPage = 2
// total number of records from database
const total = await database.collection("users").countDocuments()
// Calculating number of pagination links required
const pages = Math.ceil(total / perPage)
// get current page number
const pageNumber = parseInt(request.query.page || 1)
// get records to skip
const startFrom = (pageNumber - 1) * perPage
// get data from mongo DB using pagination
var users = await database.collection("users").find({})
.sort({ "id": -1 })
.skip(startFrom)
.limit(perPage)
.toArray();
// render an HTML page with number of pages, and users data
result.render("index", {
"pages": pages,
"users": users
});
});
Comments have been added with each line for an explanation. To display the HTML file, we need to tell the Express framework that we will be using the EJS engine. Write the following line before the http.listen function:
// set the view engine as EJS for displaying HTML files
app.set("view engine", "ejs");
Create a folder named “views” at the root of your project. Inside the views folder, create a file named “index.ejs”. Following will be the content of “index.ejs” file:
<table>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
<tbody>
<% for (var a = 0; a < users.length; a++) { %>
<tr>
<td><%= users[a].name %></td>
<td><%= users[a].age %></td>
</tr>
<% } %>
</tbody>
</table>
<ul class="pagination">
<% for (var a = 1; a <= pages; a++) { %>
<li>
<a href="?page=<%= a; %>">
<%= a; %>
</a>
</li>
<% } %>
</ul>
You can run the project from browser by accessing the URL: http://localhost:3000/ and you will see 2 pages on first page along with pagination links at the bottom. On clicking the other page link, you will see further records.
We are going to create customized task management and time tracking script using simple HTML and Javascript. Since we are creating our own script, so we can customize it as much as we need. You can check the demo from here.
Video tutorial
Include libraries
First, we need to include all the libraries that we are going to use. We will be using Bootstrap for design and SweetAlert for displaying pop-up messages.
<!-- to make responsive -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- include bootstrap css -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" />
<!-- include jquery and bootstrap js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.min.js"></script>
<!-- include sweetalert for displaying dialog messages -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/2.1.2/sweetalert.min.js"></script>
Add project
Then we are going to create a button that when clicked will display a Bootstrap modal to add a task.
Then we are going to create a Bootstrap modal. It will have a form with project and task name fields. It will also have a dropdown from which the user can select his already created projects.
Then we need to create a Javascript function “addProject” inside the “taskObj” object. It will first check if there is any project selected, if not, then it will show an error message. Then it will create an empty array in local storage if not already created. Then it will create a new project object with empty “tasks” array. Finally, it will push the project into an array and update the local storage value, and also it will reload the projects and tasks.
// main object
var taskObj = {
// local storage key
key: "projects",
// add project
addProject: function () {
// check if project is selected
if (document.getElementById("add-project").value == "") {
swal("Please enter project name");
return false;
}
// initialize local storage if not already initialized
var option = "";
if (localStorage.getItem(this.key) == null) {
localStorage.setItem(this.key, "[]");
}
// get stored object from local storage
var data = JSON.parse(localStorage.getItem(this.key));
// project object
var project = {
id: data.length,
name: document.getElementById("add-project").value,
tasks: []
};
// push new project in local storage
data.push(project);
localStorage.setItem(this.key, JSON.stringify(data));
// re-load all projects
this.loadAllProjects();
// show all tasks
this.showAllTasks();
},
};
To load all the projects, we will be using the following 2 functions inside this object:
// get all stored projects
getAllProjects: function() {
if (localStorage.getItem(this.key) == null) {
localStorage.setItem(this.key, "[]");
}
return JSON.parse(localStorage.getItem(this.key))
},
// load all projects in dropdown
loadAllProjects: function () {
var projects = taskObj.getAllProjects();
projects = projects.reverse();
var html = "<option value=''>Select Project</option>";
for (var a = 0; a < projects.length; a++) {
html += "<option value='" + projects[a].id + "'>" + projects[a].name + "</option>";
}
document.getElementById("add-task-project").innerHTML = html;
document.getElementById("form-task-hour-calculator-all-projects").innerHTML = html;
},
We will do the “showAllTasks” function later. Now, when the page loads, we need to fetch all the projects and tasks and display them.
// when page loads
window.addEventListener("load", function () {
// show all projects and tasks
taskObj.loadAllProjects();
taskObj.showAllTasks();
});
At this point, you will be able to create projects and see them in the dropdown. Now we need to add tasks.
Add task
To add a task, we will get the project and task name. Then we will push the newly created task object into the “tasks” array. Finally, we will update the local storage value, hide the Bootstrap modal and reload the tasks.
// add new task
addTask: function (form) {
// get selected project and entered task
var project = form.project.value;
var task = form.task.value;
// add task in project's array
var projects = this.getAllProjects();
for (var a = 0; a < projects.length; a++) {
if (projects[a].id == project) {
var taskObj = {
id: projects[a].tasks.length,
name: task,
status: "Progress", // Progress, Completed
isStarted: false,
logs: [],
started: this.getCurrentTimeInTaskStartEndFormat(),
ended: ""
}
projects[a].tasks.push(taskObj);
break;
}
}
// update local storage
localStorage.setItem(this.key, JSON.stringify(projects));
// hide modal
jQuery("#addTaskModal").modal("hide");
jQuery('.modal-backdrop').remove();
// re-load all tasks
this.showAllTasks();
// prevent form from submitting
return false;
},
You might have see the function “getCurrentTimeInTaskStartEndFormat”. Our task management script will save the date and time in format YYYY-MM-DD HH:mm:ss e.g. 2021-06-15 20:53:15.
// get current datetime in proper format (e.g. 2021-06-15 20:53:15)
getCurrentTimeInTaskStartEndFormat() {
let current_datetime = new Date();
var date = current_datetime.getDate();
date = (date < 10) ? "0" + date : date;
var month = (current_datetime.getMonth() + 1);
month = (month < 10) ? "0" + month : month;
var hours = current_datetime.getHours();
hours = (hours < 10) ? "0" + hours : hours;
var minutes = current_datetime.getMinutes();
minutes = (minutes < 10) ? "0" + minutes : minutes;
var seconds = current_datetime.getSeconds();
seconds = (seconds < 10) ? "0" + seconds : seconds;
let formatted_date = current_datetime.getFullYear() + "-" + month + "-" + date + " " + hours + ":" + minutes + ":" + seconds;
return formatted_date;
},
Show all tasks
To show all tasks, we need to create a table where we will display all tasks created.
Now is the time to create a function “showAllTasks” in our “taskObj” object. This will be a long function, so we will explain the working of this function step-by-step:
// show all tasks in table
showAllTasks: function () {
var html = "";
// get all projects
var projects = this.getAllProjects();
for (var a = 0; a < projects.length; a++) {
projects[a].tasks = projects[a].tasks.reverse();
// get tasks in each project
for (var b = 0; b < projects[a].tasks.length; b++) {
html += "<tr>";
html += "<td>" + projects[a].tasks[b].name + "</td>";
html += "<td>" + projects[a].name + "</td>";
if (projects[a].tasks[b].isStarted) {
html += "<td><label class='started'>Started</label></td>";
} else {
if (projects[a].tasks[b].status == "Completed") {
html += "<td><label class='completed'>" + projects[a].tasks[b].status + "</label></td>";
} else {
html += "<td>" + projects[a].tasks[b].status + "</td>";
}
}
// get total duration of each task using it's logs
var duration = 0;
for (var c = 0; c < projects[a].tasks[b].logs.length; c++) {
var log = projects[a].tasks[b].logs[c];
if (log.endTime > 0) {
duration += log.endTime - log.startTime;
}
}
// convert millisecond into hours, minutes and seconds
duration = Math.abs((duration / 1000).toFixed(0));
var hours = Math.floor(duration / 3600) % 24;
hours = (hours < 10) ? "0" + hours : hours;
// var days = Math.floor(diff / 86400);
var minutes = Math.floor(duration / 60) % 60;
minutes = (minutes < 10) ? "0" + minutes : minutes;
var seconds = duration % 60;
seconds = (seconds < 10) ? "0" + seconds : seconds;
// show timer if task is already started
if (projects[a].tasks[b].isStarted) {
var dataStartedObj = {
"duration": duration,
"project": projects[a].id,
"task": projects[a].tasks[b].id
};
html += "<td data-started='" + JSON.stringify(dataStartedObj) + "'>" + hours + ":" + minutes + ":" + seconds + "</td>";
} else {
html += "<td>" + hours + ":" + minutes + ":" + seconds + "</td>";
}
// show task duration if completed
if (projects[a].tasks[b].status == "Completed") {
html += "<td>" + projects[a].tasks[b].started + "<br><span style='margin-left: 30px;'>to</span><br>" + projects[a].tasks[b].ended + "</td>";
} else {
html += "<td>" + projects[a].tasks[b].started + "</td>";
}
// form to change task status
html += "<td>";
html += "<form method='POST' id='form-change-task-status-" + projects[a].id + projects[a].tasks[b].id + "'>";
html += "<input type='hidden' name='project' value='" + projects[a].id + "'>";
html += "<input type='hidden' name='task' value='" + projects[a].tasks[b].id + "'>";
html += "<select class='form-control' name='status' onchange='taskObj.changeTaskStatus(this);' data-form-id='form-change-task-status-" + projects[a].id + projects[a].tasks[b].id + "'>";
html += "<option value=''>Change status</option>";
if (projects[a].tasks[b].isStarted) {
html += "<option value='stop'>Stop</option>";
} else {
html += "<option value='start'>Start</option>";
}
if (projects[a].tasks[b].status == "Progress") {
html += "<option value='complete'>Mark as Completed</option>";
} else {
html += "<option value='progress'>Make in Progress Again</option>";
}
html += "<option value='delete'>Delete</option>";
html += "</select>";
html += "</form>";
html += "</td>";
html += "</tr>";
}
}
document.getElementById("all-tasks").innerHTML = html;
},
The step number corresponds to the highlighted line above.
First, we are looping through all projects and each project’s tasks.
Displaying the task name and project name.
If the task status is “started” then displaying a started message. (we will do this later).
And if the task status is “completed”, then displaying a message for the completed task.
Then we will get the total duration of each task.
The duration will be in milliseconds, so we will convert that into days, hours, minutes, and seconds.
If the task is started, then we will attach an attribute “data-started” to the <td> tag. This will allow us to continuously update the timer every second.
And if the task is completed, then we will display the start and end times of the task. So you can know when the task started and when it is finished.
And finally, we are creating a form from which we can change the status of the task.
Change task status
Now we need to create a function to change the status of the task. Again, this will be a long function, we will explain that step-by-step too.
// change task status
changeTaskStatus: function (self) {
// if task is not selected
if (self.value == "") {
return;
}
// loop through all projects
var formId = self.getAttribute("data-form-id");
var form = document.getElementById(formId);
var projects = this.getAllProjects();
for (var a = 0; a < projects.length; a++) {
// if project matches
if (projects[a].id == form.project.value) {
// loop through all tasks of that project
for (var b = 0; b < projects[a].tasks.length; b++) {
// if task matches
if (projects[a].tasks[b].id == form.task.value) {
// if the status is set to delete
if (self.value == "delete") {
// ask for confirmation
swal({
title: "Are you sure?",
text: "Deleting the task will delete its hours too.",
icon: "warning",
buttons: true,
dangerMode: true,
})
.then((willDelete) => {
if (willDelete) {
// remove task from array
projects[a].tasks.splice(b, 1);
// update local storage
localStorage.setItem(this.key, JSON.stringify(projects));
// re-load all tasks
this.showAllTasks();
} else {
// reset dropdown
self.value = "";
}
});
} else if (self.value == "complete") {
// mark as completed
projects[a].tasks[b].status = "Completed";
// stop the timer
projects[a].tasks[b].isStarted = false;
// log end time
projects[a].tasks[b].ended = this.getCurrentTimeInTaskStartEndFormat();
for (var c = 0; c < projects[a].tasks[b].logs.length; c++) {
if (projects[a].tasks[b].logs[c].endTime == 0) {
projects[a].tasks[b].logs[c].endTime = new Date().getTime();
break;
}
}
} else if (self.value == "progress") {
// mark as in progress
projects[a].tasks[b].status = "Progress";
// stop the timer
projects[a].tasks[b].isStarted = false;
} else if (self.value == "start") {
// ask for confirmation
swal({
title: "Are you sure?",
text: "This will start the timer.",
icon: "warning",
buttons: true,
dangerMode: true,
})
.then((doStart) => {
if (doStart) {
// mark as started
projects[a].tasks[b].isStarted = true;
// add in log
var logObj = {
id: projects[a].tasks[b].logs.length,
startTime: new Date().getTime(),
endTime: 0
};
projects[a].tasks[b].logs.push(logObj);
// update local storage
localStorage.setItem(this.key, JSON.stringify(projects));
// re-load all tasks
this.showAllTasks();
} else {
// reset dropdown
self.value = "";
}
});
} else if (self.value == "stop") {
// ask for confirmation
swal({
title: "Are you sure?",
text: "This will stop the timer.",
icon: "warning",
buttons: true,
dangerMode: true,
})
.then((doStop) => {
if (doStop) {
// mark as stopped
projects[a].tasks[b].isStarted = false;
// update end time in log
for (var c = 0; c < projects[a].tasks[b].logs.length; c++) {
if (projects[a].tasks[b].logs[c].endTime == 0) {
projects[a].tasks[b].logs[c].endTime = new Date().getTime();
break;
}
}
// update local storage
localStorage.setItem(this.key, JSON.stringify(projects));
// re-load tasks
this.showAllTasks();
} else {
// reset dropdown
self.value = "";
}
});
}
break;
}
}
break;
}
}
// delete, start and stop are already handled above
if (self.value == "delete"
|| self.value == "start"
|| self.value == "stop") {
//
} else {
// update local storage and re-load tasks
localStorage.setItem(this.key, JSON.stringify(projects));
this.showAllTasks();
}
},
Comments have been added with each line for an explanation. If you still find it difficult, please feel free to mention it in the comments section below.
At this point, you will be able to start and stop the timer. Upon stopping, you will be able to see the start and end time of the task along with the total duration of the task.
Now, we need to update the timer each second if the task is started. You need to write the following lines in your window “load” event listener:
// call this function each second
setInterval(function () {
// increment 1 second in all running tasks
var dataStarted = document.querySelectorAll("td[data-started]");
for (var i = 0; i < dataStarted.length; i++) {
var dataStartedObj = dataStarted[i].getAttribute("data-started");
var dataStartedObj = JSON.parse(dataStartedObj);
dataStartedObj.duration++;
// convert timestamp into readable format
var hours = Math.floor(dataStartedObj.duration / 3600) % 24;
hours = (hours < 10) ? "0" + hours : hours;
// var days = Math.floor(diff / 86400);
var minutes = Math.floor(dataStartedObj.duration / 60) % 60;
minutes = (minutes < 10) ? "0" + minutes : minutes;
var seconds = dataStartedObj.duration % 60;
seconds = (seconds < 10) ? "0" + seconds : seconds;
dataStarted[i].innerHTML = hours + ":" + minutes + ":" + seconds;
// update log end time
var projects = taskObj.getAllProjects();
for (var a = 0; a < projects.length; a++) {
if (projects[a].id == dataStartedObj.project) {
for (var b = 0; b < projects[a].tasks.length; b++) {
if (projects[a].tasks[b].id == dataStartedObj.task) {
for (var c = 0; c < projects[a].tasks[b].logs.length; c++) {
if (c == projects[a].tasks[b].logs.length - 1) {
projects[a].tasks[b].logs[c].endTime = new Date().getTime();
// update local storage
window.localStorage.setItem(taskObj.key, JSON.stringify(projects));
// update timer
dataStarted[i].setAttribute("data-started", JSON.stringify(dataStartedObj));
break;
}
}
break;
}
}
break;
}
}
}
}, 1000);
For explanation, comments have been added. Feel free to ask if you are having trouble understanding something.
Delete project
You are now able to create projects, now is the time to have the ability to delete them. So create a simple form that displays a list of all created projects in a dropdown:
Then we need to create a function “deleteProject” in our “taskObj” object that will delete the project from local storage and refresh the projects and tasks UI.
// delete project
deleteProject: function (self) {
// check if any project is selected
if (self.project.value == "") {
swal("Please select a project to delete");
return false;
}
// ask for confirmation
swal({
title: "Are you sure?",
text: "Deleting the project will delete its tasks too.",
icon: "warning",
buttons: true,
dangerMode: true,
})
.then((willDelete) => {
if (willDelete) {
// remove from array and update local storage
var projects = taskObj.getAllProjects();
for (var a = 0; a < projects.length; a++) {
if (projects[a].id == self.project.value) {
projects.splice(a, 1);
localStorage.setItem(taskObj.key, JSON.stringify(projects));
// re-load data
taskObj.loadAllProjects();
taskObj.showAllTasks();
break;
}
}
} else {
// reset project dropdown
self.project.value = "";
}
});
return false;
}
Applying CSS Styles
This may not be the major concern for you, but just to highlight the task when it is started and when it is completed, we are applying some CSS styles to it.
/* style when project is started */
.started {
color: white;
font-weight: bold;
background: green;
padding: 5px;
border-radius: 5px;
}
/* style when project is completed */
.completed {
color: white;
font-weight: bold;
background: greenyellow;
padding: 5px;
border-radius: 5px;
}
Congratulations ! You just created your own task management and time tracking script in Javascript. Feel free to add more features in it as per your needs.
Suppose you have a PHP variable or an object which you want to pass as an argument to a Javascript function whenever a button is clicked. Following this tutorial, you will be able to do so.
We will not be directly sending the PHP variable, but instead, we will attach the PHP variable to the HTML tag attribute and then send that tag to the Javascript function.
When the button is clicked, we are sending a PHP object to the Javascript function as an argument. We are also sending a complete PHP object too. PHP objects can be sent by first converting them into JSON string format. You can learn more about the htmlentities function from PHP official documentation. Then we will convert the JSON string characters into HTML entities.
And on the Javascript side, we simply have to parse the JSON string back into a Javascript array or object. If you face any problems implementing this in your project, please let us know in the comments section.
In this tutorial, we are going to show you can count extended fingers of your hand using Leap and Javascript. Extended fingers mean your stretched or opened fingers. If you prefer a video tutorial, you can check our video tutorial on YouTube.
Leap Motion Controller is a device used to detect hand motions and gestures. It came with a software development kit (SDK) for different languages i.e. C++, C#, Python, Javascript, Java, Unity, and Unreal Engine. You can buy Leap Motion Controller from here. You can get all the languages SDK from this link.
Video tutorial
We are going to show different images based on extended fingers. If you have downloaded the Javascript SDK then you will find a file named “leap-0.6.4.min.js” in it. You need to copy that file in your project. We have created a folder named “images”. In this folder, we have placed 3 images named “1.jpg”, “2.jpg” and “3.jpg”.
We will be using “index.php” file as the main file. The following code will show images based on your hand’s extended fingers.
<script src="leap-0.6.4.min.js"></script>
<img id="image" style="display: none;" />
<script>
// Setup Leap loop with frame callback function
var controllerOptions = {};
Leap.loop(controllerOptions, function(frame) {
// Body of callback function
var hands = frame.hands;
if (hands.length > 0) {
var hand = hands[0];
var extendedFingers = 0;
for(var f = 0; f < hand.fingers.length; f++){
var finger = hand.fingers[f];
if(finger.extended) {
extendedFingers++;
}
}
if (extendedFingers > 0 && extendedFingers <= 3) {
document.getElementById("image").setAttribute("src", "images/" + extendedFingers + ".jpg");
document.getElementById("image").style.display = "";
} else {
document.getElementById("image").style.display = "none";
}
}
});
</script>
<style>
#image {
width: 100%;
height: 100%;
object-fit: contain;
}
</style>
Explanation
First we have included Leap JS SDK.
Then we created an empty image tag and hide it.
Leap.loop function will be called on each frame.
On each frame, we are checking if there is any hand on top of Leap.
If there is, then we are counting extended fingers.
If there are more than zero and less than 4 extended fingers, then we are rendering image and displaying it.
Otherwise, we are hiding the image.
CSS styles are applied to fit the image inside the browser window.
Move your hand on top of your Leap Motion Controller and try to extend your fingers one-by-one. You will see the images will be changed as per the number of fingers extended. That’s how you can count extended fingers on your hand in Leap Motion Controller.
Check out our more tutorials on Leap Motion Controller.