Bootstrap Datetimepicker Disable Past Dates And Time Example

Bootstrap Datetimepicker Disable Past Dates And Time Example

datetimepicker bootstrap set date php, datetimepicker bootstrap example code html, bootstrap datetimepicker example code laravel, bootstrap datetimepicker example code codeigniter, how to set datetimepicker in jquery, bootstrap datetimepicker jquery example code

What's new in Bootstrap 5 and when Bootstrap 5 release date?

What's new in Bootstrap 5 and when Bootstrap 5 release date?

Bootstrap is one of the open source that many developers love. So what do we expect of the new changes when Bootstrap 5 is released?

Bootstrap is one of the open source that many developers love, including me. So what do we expect of the new changes when Bootstrap 5 is released?

In Bootstrap 5: jQuery will be removed.

jQuery is a fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers. With a combination of versatility and extensibility, jQuery has changed the way that millions of people write JavaScript.

However, with the trend of writing Single Page App with React, Angular, Vue..., jQuery has not been popular anymore. So Bootstrap 5 will completely remove jQuery.

Bootstrap 5 remaining to do after the jQuery removal #28342

Responsive font sizes with RFS v9 implementation

In Bootstrap 5, we’ve enabled responsive font sizes by default, allowing text to scale more naturally across device and viewport sizes.

Features:

  • Responsive font sizes are now enabled by default
  • Utility API integration
  • Fluid rescaling is also applied to the spacing utilities (option can be disabled)
  • Drop .font-size-sm, .font-size-base, .font-size-lg and .font-size-xl utilities
  • New .text-sm, .text-base, .text-lg and .text-xl utilities

Bootstrap’s side project RFS is a unit resizing engine which was initially developed to resize font sizes (hence its abbreviation for Responsive Font Sizes). Nowadays RFS is capable of rescaling most CSS properties with unit values like margin, padding, border-radius, or even box-shadow.

The mechanism automatically calculates the appropriate values based on the dimensions of the browser viewport. It will be compiled into calc() functions with a mix of rem and viewport units to enable the responsive scaling behavior.

Using the mixins
The rfs() mixin has shorthands for font-size, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, and padding-left. See the example below for source Sass and compiled CSS.

.title {
  @include font-size(4rem);
}
.title {
  font-size: calc(1.525rem + 3.3vw);
}

@media (max-width: 1200px) {
  .title {
    font-size: 4rem;
  }
}

Any other property can be passed to the rfs() mixin like this:

.selector {
  @include rfs(4rem, border-radius);
}

!important can also just be added to whatever value you want:

.selector {
  @include padding(2.5rem !important);
}

Using the functions

When you don’t want to use the includes, there are also two functions:

  • rfs-value() converts a value into a rem value if a px value is passed, in other cases it returns the same result.
  • rfs-fluid-value() returns the fluid version of a value if the property needs rescaling.

In this example, we use one of Bootstrap’s built-in responsive breakpoint mixins to only apply styling below the lg breakpoint.

.selector {
  @include media-breakpoint-down(lg) {
     padding: rfs-fluid-value(2rem);
     font-size: rfs-fluid-value(1.125rem);
  }
}
@media (max-width: 991.98px) {
  .selector {
    padding: calc(1.325rem + 0.9vw);
    font-size: 1.125rem; /* 1.125rem is small enough, so RFS won't rescale this */
  }
}

Add Full-Screen size to Modal and Responsive variations for breakpoints

<!-- Full screen modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target=".bd-example-modal-fullscreen">Full screen modal</button>

<div class="modal fade bd-example-modal-fullscreen" tabindex="-1" role="dialog" aria-labelledby="myFullModalLabel" aria-hidden="true">
  <div class="modal-dialog modal-xl-fullscreen">
    <div class="modal-content">
      ...
    </div>
  </div>
</div>
Bootstrap 5 grid

Set gutter width in rem instead of px

The gutter width is now 2rem instead of 30px. This way we 'll be able to use the spacing utilities to align things with the grid.

Fixes #27072

Change approach on how column paddings are set

The col classes were extended lead to this list of 60 selectors in v4. By using .row > *, we can simplify this a lot. This change will apply paddings to all children of .row. Specificity won't be influenced by this change.

Columns: switch to width instead of flex-basis and max-width

Just using width has the benefit the .col-* classes can be used without the need of a .row class. This is also how the primer works.

This also provides a solution for sizing utilities #21943. Because we only set paddings to direct children of .rows, the cols won't have any padding whenever they're not in a .row.

Closes #28312

Closes #29505

More control over gutter widths & vertical gutters

This PR introduces new responsive gutter classes. There are 3 types of gutter classes available:

  • gx-* classes control the horizontal/column gutter width
  • gy-* classes control the vertical/row gutter width
  • g-* classes control the horizontal & vertical gutter width

These gutter classes can be added to the .row and influence the negative margins on the row and the padding on the columns.

Responsive variants are also available to get control per breakpoint. With this change we might consider ditching (or disable by default) the negative margins which increase our filesize quite a lot.

How do the gutters work?

The way the gutters are set in horizontal direction is kept the same as in v4 (negative margins on the row and paddings on the columns). The vertical gutters work a little different. Margin is added to the top of each column and to counteract the top margin, a negative margin is added to the row. We use margins instead of paddings to prevent overlapping issues (like we have with the horizontal paddings).

Better nesting support

In v4, .rows couldn't be nested, once you tried to add a .row to a .col-*, the margins and paddings caused some conflicts. By removing the paddings & margins form nested rows (.row > .row), we can nest rows in a more flexible way.

List styles removed by default

@include list-unstyled() is added to the .rows by default. This way, you won't need to add .list-unstyled to <ul class="row">s.

Removal of .form-row

.form-rows had a smaller gutter width, but since we now have the gutter classes, we can use them for even more control over the gutter widths.

Removal of .form-inline

.form-inline is removed in favor of the more flexible grid. The children can now be wrapped in .col-md-auto divs when needed. With the gutter classes, we can have easier control over the vertical spacing instead of using the responsive margin utilities.

Remove position: relative from cols

Closes #25254

Closes #26512

Removal of card decks

We currently have as well card decks as the grid system, but our grid offers more responsive control, so there's not really a reason to keep the decks.

Removal of .list-inline

The grid also covers this case.

Remove global box-sizing reset from bootstrap-grid.css

In bootstrap-grid.css, box-sizing was inherited which introduces this issue: #22872. On the other hand, setting the global box-sizing behaviour can introduce unexpected behaviour for custom CSS. By only adding box-sizing to the columns, we only apply the box-sizing to the elements where it's needed.

Navbar optimizations

  • Remove redundant display: inline-block from flex children
  • Remove line-height: inherit; which is the default value of line-height
  • Use flex shorthand
  • Improve background shorthand
  • Fix removed brand margin caused by requiring containers in navbars
When Bootstrap 5 release date?

Not sure which day is certain, but with the workload completed, Bootstrap 5 is likely to be released sometime in Q4 2020. Let's wait.

Bootstrap 5: Release Date, Important Updates and Latest Tutorial

Bootstrap 5: Release Date, Important Updates and Latest Tutorial

The most popular Bootstrap source is coming up with latest version **Bootstrap 5**. In this article, we will share information about the Bootstrap 5 release date, Important updates in the latest version and Bootstrap 5 tutorial. Bootstrap is the...

The most popular Bootstrap source is coming up with latest version Bootstrap 5. In this article, we will share information about the Bootstrap 5 release date, Important updates in the latest version and Bootstrap 5 tutorial.

Bootstrap is the world’s most popular and widely used open-source framework for developing with HTML, CSS, and JS. Till now bootstrap team has introduced 4 versions of bootstrap and soon going to introduce its latest bootstrap version 5. With the launch of V5, many major changes will be introduced in the latest version.

Initially, after launching bootstrap, the team introduced a 2nd version of bootstrap after 2 years. Again after a year of launching V2, the bootstrap team introduced V3. It took 5 long years to introduce V4 to make bootstrap more efficient and productive. The current version of bootstrap is 4.3.

BOOTSTRAP 5 RELEASE DATE

The team officially announced bootstrap V5 and mentioned many major changes in its to-do list. As of today (23/1/2020), 570 tasks are done and 71 are in the to-do category. The bootstrap 5 release date is not yet announced by any officials but the expected release could be in early 2020.

MAJOR CHANGES IN BOOTSTRAP 5

The significant changes expected in bootstrap V5 includes:

  • Moving from Jekyll to Hugo: Hugo is the world’s fastest Static Site Generator that undoubtedly generates static sites in milliseconds and uses Golang language. Jekyll is the oldest static site generator and is dropped in bootstrap 5. The bootstrap team has made changes to their dependencies to support this move, and it is near completion stated by the officials.
  • Jquery Removed: In favor of pure javascript, the bootstrap team has removed the largest client-side dependencies.
  • Improving bootstrap branch for development: According to the official announcement on the website, master will become bootstrap v5’s new v3 dev branch and to develop v5 they will cut a new master branch from v4-dev.
  • IE10 support Removed: Bootstrap 5 will not continue with Internet Explorer 10 anymore and has removed IE10 browser support in the latest version.
  • SVG Icon Library: The bootstrap team is working on exploring its own Scalable Vector Graphics (SVG) library for the latest version.

Finally exploring our own SVG icon library for v5! If all goes well, we'll be using these for our own components and open sourcing them alongside our next major update :D. pic.twitter.com/0dA0ahmwOl

— Bootstrap (@getbootstrap) July 18, 2019
  • Removing of QUnit
  • Massive changes in JavaScript
  • Minor changes in CSS
  • Drop support for Node.JS 8
  • Building Testing Infrastructure in Jasmine
  • Revamp grid to blend flexbox and grid layout
  • Responsive sticky top
  • Update DevDependencies

BOOTSTRAP 5 REMOVED JQUERY

The bootstrap team has expunged Jquery as dependency for regular Javascript announced on its official website. The team had opened a pull request in 2017 aiming to remove Jquery entirely from bootstrap versions, and it is now completed and replaced entirely with vanilla Javascript. Nevertheless, developers will still be able to use bootstrap 5 with or without jquery.

We’re dropping jquery from regular Javascript. The cat is out of the bag-We’re dropping our largest client-side dependency for regular Javascript. Similar to the Hugo move, we’ve been working on this for a long time and have a pull request in progress and near completion.

This got a mixed response and opinions from web developers in development communities. It Spurred controversy for effacing Jquery from bootstrap 5. Few of the responses of web developers for removal of jquery are as follows.


BOOTSTRAP 5 COLUMNS & ROWS

Bootstrap concept offered 12-columns system is not going to vanish and will be available in Bootstrap 5 also. Web Dev can still use Grid and layout columns in Bootstrap 5.

Bootstrap rows and columns provide the most efficient solution to issues of different screen sizes. The main focus of the change in v5 is still responsiveness, though in recent bootstrap versions the development is focused mostly on improving performance and reducing the loading time.

BOOTSTRAP 5 TUTORIAL

The bootstrap team is working curiously to update bootstrap version 4 with version 5 and soon it may announce Bootstrap 5 release date. The team has done major changes till now and the last few changes to take place soon. The version is yet not developed completely and release date is also not announced officially. There’s undoubtedly a lot more in Bootstrap 5 to learn. After the lauch of bootstrap 5, we'll definitely get many new rich features in bootstrap admin templates, bootstrap themes, bootstrap ui kits, and much more.

Build a Real-time Voting App with Pusher, Node and Bootstrap

Build a Real-time Voting App with Pusher, Node and Bootstrap

In this article, I’ll walk you through building a full-stack, real-time Harry Potter house voting web application

Real-time apps usually use WebSockets, a relatively new type of transfer protocol, as opposed to HTTP, which is a single-way communication that happens only when the user requests it. WebSockets allow for persistent communication between the server and the user, and all those users connected with the application, as long as the connection is kept open.

A real-time web application is one where information is transmitted (almost) instantaneously between users and the server (and, by extension, between users and other users). This is in contrast with traditional web apps where the client has to ask for information from the server. — Quora
Our Harry Potter voting web app will show options (all the four houses) and a chart on the right side that updates itself when a connected user votes.

To give you a brief idea of look and feel, the final application is going to look like this:

Here’s a small preview of how the real-time application works:

To make our application real-time, we’re going to use Pusher and WebSockets. Pusher sits as a real-time layer between your servers and your clients. It maintains persistent connections to the clients — over a WebSocket if possible, and falling back to HTTP-based connectivity — so that, as soon as your servers have new data to push to the clients, they can do so instantly via Pusher.

Building our Application

Let’s create our fresh application using the command npm init. You’ll be interactively asked a few questions on the details of your application. Here’s what I had:

[email protected] ➜ Harry-Potter-Pusher $ npm init
{
  "name": "harry-potter-pusher",
  "version": "1.0.0",
  "description": "A real-time voting application using Harry Potter's house selection for my article for Pusher.",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/praveenscience/Harry-Potter-Pusher.git"
  },
  "keywords": [
    "Harry_Potter",
    "Pusher",
    "Voting",
    "Real_Time",
    "Web_Application"
  ],
  "author": "Praveen Kumar Purushothaman",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/praveenscience/Harry-Potter-Pusher/issues"
  },
  "homepage": "https://github.com/praveenscience/Harry-Potter-Pusher#readme"
}

Is this OK? (yes)

So, I left most settings with default values. Now it’s time to install dependencies.

Installing Dependencies

We need Express, body-parser, Cross Origin Resource Sharing (CORS), Mongoose and Pusher installed as dependencies. To install everything in a single command, use the following. You can also have a glance of what this command outputs.

[email protected] ➜ Harry-Potter-Pusher $ npm i express body-parser cors pusher mongoose
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN [email protected] requires a peer of [email protected]^6.0.0 but none is installed. You must install peer dependencies yourself.

+ [email protected]
+ [email protected]
+ [email protected]
+ [email protected]
+ [email protected]
added 264 packages in 40.000s

Requiring Our Modules

Since this is an Express application, we need to include express() as the first thing. While doing it, we also need some accompanying modules. So, initially, let’s start with this:

const express = require("express");
const path = require("path");
const bodyParser = require("body-parser");
const cors = require("cors");

Creating the Express App

Let’s start with building our Express application now. To start with, we need to get the returned object of the express() function assigned to a new variable app:

const app = express();

Serving Static Assets

Adding the above line after the initial set of includes will initialize our app as an Express application. The next thing we need to do is to set up the static resources. Let’s create a new directory in our current project called public and let’s use Express’s static middleware to serve the static files. Inside the directory, let’s create a simple index.html file that says “Hello, World”:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Hello, World</title>
  </head>
  <body>
    Hello, World!
  </body>
</html>

To serve the static files, we have a built-in .use() function with express.static() in Express. The syntax is as follows:

app.use( express.static( path.join(__dirname, "public") ) );

We also need to use the body parser middleware for getting the HTTP POST content as JSON to access within the req.body. We’ll also use urlencoded to get the middleware that only parses urlencoded bodies and only looks at requests where the Content-Type header matches the type option. This parser accepts only UTF-8 encoding of the body and supports automatic inflation of gzip and deflate encodings:

app.use( bodyParser.json() );
app.use( bodyParser.urlencoded( { extended: false } ) );

To allow cross-domain requests, we need to enable CORS. Let’s enable the CORS module by using the following code:

app.use( cors() );

Now all the initial configuration has been set. All we need to do now is to set a port and listen to the incoming connections on the specific port:

const port = 3000;
app.listen(port, () => {
  console.log(`Server started on port ${port}.`);
});

Make sure your final app.js looks like this:

const express = require("express");
const path = require("path");
const bodyParser = require("body-parser");
const cors = require("cors");

// Create an App.
const app = express();

// Serve the static files from public.
app.use( express.static( path.join(__dirname, "public") ) );

// Include the body-parser middleware.
app.use( bodyParser.json() );
app.use( bodyParser.urlencoded( { extended: false } ) );

// Enable CORS.
app.use( cors() );

// Set the port.
const port = 3000;
// Listen to incoming connections.
app.listen(port, () => {
  console.log(`Server started on port ${port}.`);
});

Run the command to start the server:

$ npm run dev

Open your http://localhost:3000/ on a new tab and see the magic. You should be seeing a new page with “Hello, World”.

Building the App’s Back End

First thing, let’s create a directory called routes and create a file in there, say vote.js. We need to connect this file with our app.js file, so let’s go back to it and include it under our express() initialization:

const app = express();

// Vote route.
const vote = require("./routes/vote")

Since the routes directory is in the same directory as the app.js, we’ll start with ./. To be able to use this one with the router, let’s go to the bottom and add the router middleware code shown below before the port definition:

app.use("/vote", vote);

Anything that goes through the /vote URL is going to be handled by the vote.js file, provided by the vote variable.

Handling GET and POST Requests

Using Express’s Router instance, we can handle the GET and POST methods through our /vote path. Let’s create a default GET route now and send a default text say, "You are in /vote".

const express = require("express");
const router = express.Router();

// Default get route.
router.get("/", (req, res) => {
  res.send("You are in /vote");
});

The code above routes all the requests to the path /vote to our newly formed routes/vote.js.

Handling POST Requests

We also need a POST handler, where we can trigger the Pusher API. It’s going to be Router.post() for the POST requests to the / so that all the requests will go to /vote because of our middleware. We’ll be giving the same type of arrow functions here, and let’s give a message like "You have POSTed to /vote.":

// Default POST route.
router.post("/", (req, res) => {
  res.send("You have POSTed to /vote.");
});

The res.send() function will be replaced by Pusher API calls in the future.

Exporting the Router

Finally, we have to export the router as a module. Use the module.exports like this at the end. This should be the end of the file, although you can have it any where. Remember, JavaScript is event oriented and not procedural:

// Export the router.
module.exports = router;

At this point, when you see the full vote.js file, it should look something like this:

const express = require("express");
const router = express.Router();

// Default GET route.
router.get("/", (req, res) => {
  res.send("You are in /vote.");
});

// Default POST route.
router.post("/", (req, res) => {
  res.send("You have POSTed to /vote.");
});

// Export the router.
module.exports = router;

Make sure you save everything and now try to run both the URLs in our web browser.

You should see output in your web browsers.

Integrating with the Pusher API

Let’s start by modifying the code we wrote for the POST handler — the one we wrote in the vote.js file. Here’s what we actually want to trigger Pusher. Let’s quickly go to our Pusher Dashboard, and select your Pusher App (praveen-science-app, in my case) and click on the Getting Started tab. You’ll see the code to kickstart.

In our vote.js we need to define (or require) the Pusher library. Then we need to create a new instance (an object) of the Pusher class, and then finally trigger the pusher service inside the POST. I’m changing the vote.js file as shown below:

Note: make sure you change your *appId**key**secret* to the one given in the dashboard.

const express = require("express");
const router = express.Router();

// ///// Step 1: Include Pusher ///// //
const Pusher = require('pusher');

// ///// Step 2: Instantiate an Object ///// //
const pusher = new Pusher({
  appId: 'appId',
  key: 'key',
  secret: 'secret',
  cluster: 'eu',
  encrypted: true
});

// Default GET route.
router.get("/", (req, res) => {
  res.send("You are in /vote.");
});

// Default POST route.
router.post("/", (req, res) => {
  // ///// Step 3: Trigger the Pusher service ///// //
  pusher.trigger('my-channel', 'my-event', {
    "message": "hello world"
  });
});

// Export the router.
module.exports = router;

The moment a user submits the form, our application fires a POST request to this route, which is going to hit the Pusher API and trigger the Pusher service using the pusher.trigger() function call. Also, we don’t want to use the default values of my-channel and my-event, so let’s change them to hp-voting and hp-house. We also don’t need to send a message, but instead, we’d like to give points and the house information:

router.post("/", (req, res) => {
  pusher.trigger('hp-voting', 'hp-house', {
    "points": 1,
    "house": req.body.house
  });

});

For now, we’re going to assign a value of 1 to the points (I’ll explain why shortly), and we’re using req.body.house for the house, because the value is going to come from the form data, and that is provided using req.body as we’re using body-parser.

Finally, we’ll return a JSON to the browser as response using the res.json() function and pass an object with a boolean success and a message thanking the user for voting and that it has been received successfully:

router.post("/", (req, res) => {
  pusher.trigger('hp-voting', 'hp-house', {
    "points": 1,
    "house": req.body.house
  });

  return res.json({
    "success": true,
    "message": "Thanks for voting."
  });
});

Building the App’s Front End

I’ve used jQuery and Bootstrap to do the front end. Here’s the part where we allow the users to vote.

I’m also going to add a chart container that will chart real-time as the votes are received.

Integrating Everything

We already have the back end done. Now we’ll see how to send the request to the Pusher service when the vote button is clicked, thanks to the front-end JavaScript. We’ll trigger the submit event of the form when the user clicks the button, and it needs to make a POST request to our back end to the route /vote.

Event Listener, User Data and Ajax

Let’s add an event listener for our form submission, code for capturing the user data, and the Ajax call:

// Execute only after the whole document is fetched and assets are loaded.
$(document).ready(function () {
  // Form submission event listener (event handler)
  $("#voteForm").submit(function (e) {
      e.preventDefault();
      // Get the checked input element's value.
      var house = $(".form-check-input:checked").val();
      // Construct the data to be sent as a payload to the AJAX call.
      var data = {
          "house": house
      };
      $.post("/vote", data, function (res) {
          // Log the output in the console.
          console.log(res);
        });
    });
});

Working with Pusher and Charts

When the form is submitted, the Ajax call triggers the /vote endpoint, and the back-end Node app will also trigger the Pusher service using the code below in routes/vote.js:

pusher.trigger('hp-voting', 'hp-house', {
  "points": 1,
  "house": req.body.house
});

When the code above is hit (or run), Pusher service will trigger an event with hp-voting and hp-house. We’re not catching the event or subscribing it yet. So we’re going to implement CanvasJS to build our chart, and we’re going to subscribe to the above event and will be adding the data points by the trigger, specified by the form’s submit event listener.

Adding CanvasJS

Once you add all the bits correctly, your client-side script.js should be similar to this:

// Execute only after the whole document is fetched and assets are loaded.
$(document).ready(function () {
  // Form submission event listener (event handler)
  $("#voteForm").submit(function (e) {
    // Prevent the default event.
    e.preventDefault();
    // Get the checked input element's value.
    var house = $(".form-check-input:checked").val();
    // Construct the data to be sent as a payload to the Ajax call.
    var data = {
      "house": house
    };
    // Fire the POST request Ajax call to our /vote end point.
    $.post("/vote", data, function (res) {
      // Log the output in the console.
      console.log(res);
    });
  });
  // Create the base data points.
  var dataPoints = [
    {
      label: "Gryffindor",
      y: 0
    }, {
      label: "Hufflepuff",
      y: 0
    }, {
      label: "Ravenclaw",
      y: 0
    }, {
      label: "Slytherin",
      y: 0
    }
  ];
  // Initialize Chart using jQuery selector.
  // Get the chart container element.
  var chartContainer = $("#chartContainer");
  // Check if the element exists in the DOM.
  if (chartContainer.length === 1) {
    // Construct the options for the chart.
    var options = {
      "animationEnabled": true,
      "theme": "light1",
      "title": {
        "text": "Harry Potter House Results"
      },
      "data": [
        {
          "type": "column",
          "dataPoints": dataPoints
        }
      ]
    };
    // Initialize the chart.
    $("#chartContainer").CanvasJSChart(options);
  }
});

Now save the file, and when you reload the page, you should be able to see a placeholder chart. It is definitely a real chart but without any values. You should be able to see something like this:

Now we have implemented our CanvasJS chart on the right side.

Initialization of Pusher on the Client Side

After the Pusher Logging, we have to initialize the Pusher object. Since we already have a client-side config.js, we’ll be leveraging that code in this part:

// Initialise a Pusher Object.
var pusher = new Pusher(PusherConfig.key, {
  cluster: PusherConfig.cluster,
  forceTLS: PusherConfigforceTLS.
});

After initialization of the Pusher object, we need to subscribe to our channel, where our messages get published by the server side. We’ll be copying the code from the Pusher Dashboard but changing a little bit to subscribe to our hp-voting channel and hp-house event. The default values of my-channel and my-event need to be updated like this in relation with our back-end code:

// Subscribe to the channel.
var channel = pusher.subscribe('hp-voting');
// Bind to a particular event and listen to the event data.
channel.bind('hp-house', function(data) {
  alert(JSON.stringify(data));
});

Instead of alert-ing a data message, we want to basically add the data to the chart. The way we can do that is by taking our dataPoints and manipulating the array with respect to the server’s response. With the already existing dataPoints variable (remember that we’ve used var instead of const as we should be able to change it at a later stage), we’ll be using a higher-order Array.map() function as follows:

// Bind to a particular event and listen to the event data.
channel.bind('hp-house', function(data) {
  // Use a higher order Array map.
  dataPoints = dataPoints.map(function (d) {
    // Check if the current label is the updated value.
    if (d.label == data.house) {
      // Increment the house's value by the number of new points.
      d.y += data.points;
    }
    // Return the original value as this is a map function.
    return d;
  });
});

We’re looping through all the dataPoints labels, and when a particular label matches the current label, we’ll be incrementing the value of the current label with the number of points updated. Since we’re using a JavaScript Array.map() function, we have to return the original value, d, back to the function call. Once we’ve updated the dataPoints, we have to re-render the chart.

After the map() function, we’ll do the following:

channel.bind('hp-house', function(data) {
  // Use a higher order Array map.
  dataPoints = dataPoints.map(function (d) {
    // Check if the current label is the updated value.
    if (d.label == data.house) {
      // Increment the house's value by the number of new points.
      d.y += data.points;
    }
    // Return the original value as this is a map function.
    return d;
  });

  // Re-render the chart.
  $("#chartContainer").CanvasJSChart(options);
});

Once you write all the above code, save and run the application in your browser, fire up your web developer tools and check out the console. You should see that Pusher Service is communicating with your application. I was able to see the following in my console (I’ve hidden my appId and secret, so other than those sensitive bits of information, everything else is shown):

Conclusion

At this point of time, when you try to open two windows of the same application and vote on one screen, you can see all the screens updating at the same time. This is basically how you use the Pusher service to create real-time applications.

Our Harry Potter voting web app now shows options (all the four houses) and a chart on the right side that updates itself when a connected user votes. The next obvious step would be to use a database, such as MongoDB, to store all the information to make sure it persists even when we reload the pages of the application.

Recommended Reading

Build a Slack Polling App with Airtable, Standard Library, and Node.js

Node.js and MongoDB Slack Bot Example

3 Ways to Convert an Array to an Object in NodeJS