I created a small app using node js with express - javascript

The app is Gpa calculator using node js with express.But there is problem,it works fine for single user but when any other user doing same in same time,then the marks are getting combined and showing wrong values.I want build app which works separately for each user without combining the values.
const express=require("express");
const https=require("https");
const bodyParser=require("body-parser");
const mongoose=require("mongoose");
const lr=require("livereload");
const app=express();
app.use(express.static("public"));
app.use(bodyParser.urlencoded({extended: true}));
app.set("view engine","ejs");
var list=[0];
var clist=[0];
var len=0;
var sum=0;
var csum=0;
var fin;
var per;
app.get("/",function(req,res){
res.render("index",{len:len});
});
app.post("/",function(req,res){
var cr=req.body.crd;
var sc=req.body.scr;
var ccr=parseInt(cr);
if(sc=="S"){
sc=10;
}
else if(sc=="A"){
sc=9;
}
else if(sc=="B"){
sc=8;
}
else if(sc=="C"){
sc=7;
}
else if(sc=="D"){
sc=6;
}
else{
sc=0;
len=parseInt(len)-1;
res.send("Give valid inputs.");
}
var tot=parseInt(cr)*parseInt(sc);
len=list.length;
clist.push(ccr);
list.push(tot);
res.redirect("/");
});
app.post("/calculate",function(req,res){
for(var i=0;i<list.length;i++){
sum+=list[i];
}
for(var j=0;j<clist.length;j++){
csum+=clist[j];
}
fin=sum / csum;
var finn=fin.toString();
var finnn=finn.slice(0,4);
per=fin*9.5;
var perr=per.toString();
var perrr=perr.slice(0,5);
res.render("display",{fin:finnn, per:perrr});
})
app.post("/reset",function(req,res){
list=[0];
clist=[0];
len=0;
sum=0;
csum=0;
res.redirect("/");
})
var ser=app.listen(process.env.PORT || 3000,function(){
console.log("server is running on port 3000");
});
<%- include("bootstrap") %>
<!DOCTYPE html>
<html>
<head>
<title>Hello</title>
</head>
<body style="background-color: #fffbdf;">
<nav style="margin-bottom: 2%;" class="navbar navbar-expand-lg navbar-light bg-dark">
<a style="color: white;" class="navbar-brand" href="#">Veltech Calculator</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
<div class="navbar-nav">
</div>
</div>
</nav>
<center>
<form action="/" method="post">
<label><h6>Enter Credits :</h6></label>
<input id="crd" placeholder="Enter credits" style="margin: 2%" type="text" name="crd" required autofocus>
<label><h6>Enter Grade : </h6></label>
<input id="scr" placeholder="Enter grade in CAPITAL" style="margin: 2%" type="text" name="scr" required="Fill this" autofocus><br>
<% if(len==0){%>
<h5 style="color: red; margin-bottom: 2%;">No subject is added</h5>
<% } else{ %>
<h5 style="color: green; margin-bottom: 2%;"><%= len %> subjects are are added</h5>
<% } %>
<button type="submit" id="add" class="btn btn-warning" style="width: 80px;">ADD</button><br>
<div style="margin-bottom: 0.5%; margin-top: 2%; display:inline-block;" class="alert alert-danger" role="alert">
<b>NOTE</b>: If you done anything wrong while adding subjects,try to click on RESET button.Else may get wrong values.
</div>
</form>
<form action="/calculate" method="post">
<button type="submit" id="cal" class="btn btn-primary btn-lg" style="margin-top: 3%; width: 200px;">Calculate</button>
</form>
<form action="/reset" method="post">
<button type="submit" id="reset" class="btn btn-secondary btn-lg" style="margin-top: 1%; width: 200px;">RESET</button>
</center>
<center>
<div style="background-color: #4ca1a3; margin-top: 2%" id="cf">
<h5 id="cfh" style="padding-top: 1%; color: #0c4271">Veltech Calculator</h5>
<label><b>Website links :</b></label>
<a style="padding-bottom: 1%; color: black;" href="https://www.veltech.edu.in">Veltech official site</a>
<h6 style="padding-bottom: 1%;"> #VeltechCalculator copy rights reserved/leela sairam</h6>
</div>
</center>
</body>
</html>
<%- include("bootstrap") %>

Store your user-specific data in a session instead of in global variables.
A session works by generating a unique ID for each visitor and storing it in a cookie. It has a central data store (which could just be an in-memory object or could be a file or database) which associates whatever data you like with that unique ID. When you want to read or write to it, you just get the ID from the cookie and look up the data based on it.
The express-session module will do all the heavy lifting for you.

Related

ERR_HTTP2_PROTOCOL_ERROR in C# MVC application

I am receiving a bunch of ERR_HTTP2_PROTOCOL_ERROR messages in dev tools after 1 of the pages submits a form to a controller and then the controller displays a different view.
This is the sequence of events:
OnlineEnrollmentController presents Index.cshtml.
The View Index.cshtml displays text to the user and the user clicks a button to submit a form.
The form is sent to OnlineEnrollmentController/Agreement where a View is returned.
The View Agreement.cshtml is presented to the user and the user clicks a button to submit a form.
The form is sent to OnlineEnrollmentController/Profile where the ActionResult Profile reads data from a database, populates a model and returns the model to the View Profile.cshtml.
The View Profile.cshtml is presented to the user and the user clicks a button to submit a form.
The form is sent to OnlineEnrollmentController/Rate where the ActionResult Rate reads data from a database, populates a model and returns the model to the View Rate.cshtml.
The View Rate.cshtml is presented to the user and asks the user to enter a rate into a text box. The user enters a rate and clicks on the button to submit the form.
The form is sent to OnlineEnrollmentController/Election where the ActionResult Election gets the rate that was populated and stores in a TempData field. A new list of object is created where each object contains 3 fields and is returned to the View Election.cshtml.
The View Election.cshtml uses a foreach loop to display the contents of the list of object.
All this logic works except now I am receiving this ERR_HTTP2_PROTOCOL_ERROR when the View Election.cshtml is loaded.
Here are the specifics:
The application has a shared view called _NoMenu.cshtml. This is the contents of the file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<title>#ViewData["Title"]</title>
<link rel="stylesheet" href="~/css/site.css" />
<script src="https://use.fontawesome.com/54ec0da54f.js"></script>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous" />
<!-- font awesome -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous" />
<style>
/* Style for showing in progress bar
--------------------------------------------------*/
.submit-progress {
position: fixed;
top: 30%;
left: 50%;
height: 6em;
padding-top: 2.3em;
/* The following rules are the
ones most likely to change */
width: 20em;
/* Set 'margin-left' to a negative number
that is 1/2 of 'width' */
margin-left: -10em;
padding-left: 2.1em;
background-color: #17a2b8a8;
color: black;
-webkit-border-radius: 0.4em;
-moz-border-radius: 0.4em;
border-radius: 0.4em;
box-shadow: 0.4em 0.4em rgba(0,0,0,0.6);
-webkit-box-shadow: 0.4em 0.4em rgba(0,0,0,0.6);
-moz-box-shadow: 0.4em 0.4em rgba(0,0,0,0.6);
}
.hidden {
visibility: hidden;
}
.submit-progress i {
margin-right: 0.5em;
}
.mb-5, .my-5 {
margin-bottom: 1.5rem !important;
}
.scrollHeight {
height: 85vh;
}
.hideit {
display: none;
}
.width95 {
width: 95%;
}
.myDIV {
height: 75%;
overflow: auto;
}
.content500 {
height: 500px;
}
.content600 {
height: 600px;
}
.content800 {
height: 800px;
}
</style>
</head>
<body>
<div>
#RenderBody()
</div>
</body>
</html>
I use this for any page in my application where I dont want to show a standard bootstrap menu structure.
Here is the contents of the view Rate.schtml:
#model AccuRecordV3.Models.OnlineEnrollment_Indicative_Verify
#{
ViewData["Title"] = "Online Enrollment - Rate";
Layout = "~/Views/Shared/_NoMenu.cshtml";
}
#using (Html.BeginForm("Election", "OnlineEnrollment", FormMethod.Post))
{
<section id="rate" class="vh-100" style="background-color: #508bfc;">
<div class="container py-5 h-100">
<div class="row d-flex justify-content-center align-items-center h-100">
<div class="col-12 col-md-8 col-lg-6 col-xl-5">
<div class="card shadow-2-strong" style="border-radius: 1rem;">
<div class="card-body p-5 text-center scrollHeight">
<h3 class="mb-5">Online Enrollment</h3>
<h5 class="mb-5">Step 1 of 3</h5>
<div id="rateDIV" class="myDIV">
<div id="ratecontent" class="content500">
<div class="form-outline mb-4">
<label class="form-label text-left width95">
#Model.messageLiteral
</label>
</div>
<div class="form-outline mb-4">
<label class="form-label text-left width95">
The minimum contribution rate allowed by your plan is #Model.outputMinPct and the
maximum contribution rate allowed by your plan is #Model.outputMaxPct
</label>
</div>
<div class="form-outline mb-4">
<label class="form-label text-left">
How much would you like to contribute?
</label>
</div>
<div class="form-outline mb-4">
<input type="number" id="electedRate" asp-for="electedRate" class="form-control form-control-lg rate" value="#Model.electedRate" placeholder="0" min="#Model.ss_CtrbKMinPct" step="1" max="#Model.ss_CtrbKMaxPct" />
<label class="form-label text-danger" for="electedRate" id="rateerrorLabel"> </label>
</div>
<button class="btn btn-primary btn-lg btn-block" type="button" id="rateButton" disabled onclick="return DisplayProgressMessage(this, 'rate');">Next</button>
<button class="btn btn-outline-primary btn-lg btn-block" type="button" id="cancelRateButton" onclick="return Cancel(this, 'rate');">Cancel</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
}
<script>
$(function () {
var rate = 0;
$('.rate').each(function () {
rate += parseInt($(this).val());
});
var minRate = parseInt("#Model.ss_CtrbKMinPct");
var maxRate = parseInt("#Model.ss_CtrbKMaxPct");
if (rate < minRate || rate > maxRate) {
$("#rateButton").prop("disabled", true);
} else {
$("#rateButton").prop("disabled", false);
}
$('.rate').change(function () {
var rate = 0;
$('.rate').each(function () {
rate += parseInt($(this).val());
});
var minRate = parseInt("#Model.ss_CtrbKMinPct");
var maxRate = parseInt("#Model.ss_CtrbKMaxPct");
if (rate < minRate || rate > maxRate) {
$("#rateButton").prop("disabled", true);
} else {
$("#rateButton").prop("disabled", false);
}
})
})
function DisplayProgressMessage(ctl, msg) {
$(ctl).prop("disabled", true).text(msg);
$("#submitButton").prop("disabled", true);
$(".submit-progress").removeClass("hidden");
const myTimeout = setTimeout(function () {
$("form").submit();
}, 5);
}
</script>
The view Rate.schtml works correctly, using jquery to validate the rate the user enters and then submits the form back to the controller.
This is the contents of Election.cshtml:
#model AccuRecordV3.Models.OnlineEnrollment_Indicative_Verify
#{
ViewData["Title"] = "Online Enrollment - Rate";
Layout = "~/Views/Shared/_NoMenu.cshtml";
}
#using (Html.BeginForm("Summary", "OnlineEnrollment", FormMethod.Post))
{
<section id="elections" class="vh-100" style="background-color: #508bfc;">
<div class="container py-5 h-100">
<div class="row d-flex justify-content-center align-items-center h-100">
<div class="col-12 col-md-8 col-lg-6 col-xl-5">
<div class="card shadow-2-strong" style="border-radius: 1rem;">
<div class="card-body p-3 text-center scrollHeight">
<h3 class="mb-5">Online Enrollment</h3>
<h5 class="mb-5">Step 2 of 3</h5>
<div id="electionsDIV" class="myDIV">
<div id="electionscontent" class="content600">
<div class="form-outline mb-4">
<label class="form-label text-left width95">
These are the funds that are available to you. You can allocate your contribution to any/all of these funds. Remember, you wont be able to submit your elections all your total elections added together equal 100%.
</label>
</div>
#foreach (var localRecord in Model.electionData)
{
<div class="row width95">
<label for="NewPct" class="col-sm-9 col-form-label text-left">#localRecord.FundName</label>
<div class="col-sm-3">
<input type="number" class="form-control election" id="NewPct" name="NewPct" min="#localRecord.MinPct" max="#localRecord.MaxPct" value="0">
<input type="number" id="HostFID" name="HostFID" hidden value="#localRecord.HostFID" />
</div>
</div>
}
<div class="row width95">
<label class="col-sm-9 col-form-label text-left">Total</label>
<label id="ElectionTotal" name="ElectionTotal" class="col-sm-3 col-form-label text-right">0%</label>
</div>
<button class="btn btn-primary btn-lg btn-block" type="button" id="electionButton" disabled onclick="return DisplayProgressMessage(this, 'elections');">Next</button>
<button class="btn btn-outline-primary btn-lg btn-block" type="button" id="cancelElectionButton" onclick="return Cancel(this, 'elections');">Cancel</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
}
<script>
$(function () {
$('.election').change(function () {
var sum = 0;
$('.election').each(function () {
sum += parseInt($(this).val());
});
var totalElection = sum + "%";
$("#ElectionTotal").text(totalElection)
if (sum == 100) {
$("#electionButton").prop("disabled", false);
} else {
$("#electionButton").prop("disabled", true);
}
})
})
function DisplayProgressMessage(ctl, msg) {
$(ctl).prop("disabled", true).text(msg);
$("#submitButton").prop("disabled", true);
$(".submit-progress").removeClass("hidden");
const myTimeout = setTimeout(function () {
$("form").submit();
}, 5);
}
</script>
When this view loads, and I look at dev tools, this is what I see:
and
So, for some reason, this error is preventing jquery.min.js from loading which in turn causes the '$' not defined error.
It looks like this error is also preventing the style sheet from loading properly as well.
Some research into this says it's a CORS issue but I dont see how I could have a CORS issue on one page (Elections.schtml) and not on the others (Index.schtml, Agreement.schtml, Profile.schtml, and Rate.schtml).
Any idea how to resolve this?
Thanks.

Rearrange Bootstrap page into three columns and items under each other

I have a small tool for scrum teams to track people in the meeting. Now we are more people, one team is added and right now it seems more logical to re-arrange the elements.
Now if you click on team1/team2/team3 button, the names are sorted in 3 columns and next to each other. I want to change this, to 3 columns, but every team will have it's own column. So, team1 names will fill up the first column and the names in this team will come under each other. After that if I click on team2, the names of team2 will fill up the second column and the team3 will fill up the third column. I assume on every team button click the script should create one column and fill up this column, on the second team button click it will again create one column next to the first also on the third time. Is this possible? Thank you very much.
This is the one page working version, all names are randomly generated, completely anonym:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My Team Members</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<style>
.footer {
position: fixed;
left: 0;
bottom: 0;
right: 0;
z-index: 10;
}
.alert.member-clicked {
text-decoration-line: line-through;
background-color: #ddd;
border-color: #ddd;
}
.alert.member-absent {
text-decoration-line: line-through;
background-color: #f8d7da;
border-color: #f8d7da;
}
.copyright {
margin-top: 10px;
margin-right: 10px;
text-align: right;
}
.form-inline.form-members .input-group {
display: inline-table;
vertical-align: middle;
}
.form-inline.form-members .input-group .input-group-btn {
width: auto;
}
h2 {
margin-bottom: 20px;
}
</style>
</head>
<body>
<center>
<div class="container">
<h2 class="text text-success text-center">My Team Members</h2>
<div id="memberlist" class="row"></div>
</div>
<footer class="footer">
<div class="container">
<!-- Input for members -->
<div class="form-inline form-members">
<div class="input-group">
<input type="text" class="form-control" placeholder="Add member" id="text" value="Alasdair Mckee">
<div class="input-group-btn">
<button class="btn btn-success btn-addmember"><i class="glyphicon glyphicon-plus"></i></button>
</div>
</div>
<button class="btn btn-success" data-team="team1"><i class="glyphicon glyphicon-plus"></i> Team1</button>
<button class="btn btn-success" data-team="team2"><i class="glyphicon glyphicon-plus"></i> Team2</button>
<button class="btn btn-success" data-team="team3"><i class="glyphicon glyphicon-plus"></i> Team3</button>
</div>
<div class="form-group hidden">
<label for="exampleFormControlTextarea1">Team1</label>
<textarea class="form-control" id="team1" rows="9">
Bentley Parrish
Hunter Pineda
Ammar Burks
Tanya Vang
Aimie Ewing
Anabella Chan
Amayah Sparks
Priyanka Cooke
Boyd Pacheco
Mai Lynch
</textarea>
<label for="exampleFormControlTextarea1">Team2</label>
<textarea class="form-control" id="team2" rows="9">
Alan Rangel
Ikra Knowles
Chelsea Avalos
Aysha Glenn
Margaret Couch
Effie Corbett
Yassin Arias
Caspian Rice
</textarea>
<label for="exampleFormControlTextarea1">Team3</label>
<textarea class="form-control" id="team3" rows="9">
Armani Curran
Monica Kemp
Nur Davis
Hashir Dodson
Ty Hagan
Aariz Rowley
</textarea>
</div>
</div>
<p class="copyright">Created by: Me • me#me.com • ver 1.5</p>
</footer>
</center>
<script>
$(document).ready(function() {
var memberList = $("#memberlist");
memberList.on("click", ".alert", function () {
$(this).toggleClass("member-clicked");
});
memberList.on("click", ".close", function () {
var memberColumn = $(this).parent().parent();
memberColumn.fadeOut();
});
$(".btn-addmember").click(function () {
var newMember = $("#text").val().trim();
if (newMember) {
addMember(newMember);
} else {
alert("Please, enter the name of the member");
}
$("#text").val("");
});
$(".btn[data-team]").click(function () {
addTeam($(this).data("team"));
});
function addMember(member) {
member = member.trim();
if (member) {
memberList.append(
`<div class="col-xs-6 col-sm-4"><div class="alert alert-success">` +
`<span class="close" aria-label="close">×</span><b>` +
member +
`</b></div></div>`
);
}
}
function addTeam(id) {
var team = $("#" + id)
.val()
.trim();
if (team) {
var members = team.split("\n");
console.log(members);
for (var i = 0; i < members.length; i++) {
addMember(members[i]);
}
}
}
$(document).on('dblclick', '.alert', function() {
$(this).toggleClass("member-absent");
});
});
</script>
</body>
</html>
I think you need to use 3 member lists instead of one.
var memberList1 = $("#listteam1");
var memberList2 = $("#listteam2");
var memberList3 = $("#listteam3");
that means the layout will change:
<div class="row">
<div class="col-xs-6 col-sm-4">
<h3>Team 1</h3>
<div class="column" id="listteam1">
</div>
</div>
<div class="col-xs-6 col-sm-4">
<h3>Team 2</h3>
<div class="column" id="listteam2">
</div>
</div>
<div class="col-xs-6 col-sm-4">
<h3>Team 3</h3>
<div class="column" id="listteam3">
</div>
</div>
</div>
also, addMember needs to take the list name as an argument
function addMember(member, list) {
member = member.trim();
if (member) {
$("#list" + list).append(
`<div class="alert alert-success">` +
`<span class="close" aria-label="close">×</span><b>` +
member +
`</b></div>`
);
}
}
please find the whole script here: https://pastebin.com/VQEVKCaF

User name are duplicated for each login in html?

I have been using firebase cloud firestore. My issue is when user logged in, the user name displays on header with drop down option account, payment and logout. When user logged out and login again with same or another account details user name keeps on adding on header with previous logged in user name.
Note: here i am using firebase authentication and cloud firestore database.
here is my screen shot:
$(document).ready(function(){
//initialize the firebase app
var config = {
apiKey: "AIzaSyBDwqFKPt4D0eIspjsziweLI0nc49BRDrU",
authDomain: "cloudthrifty-demo.firebaseapp.com",
databaseURL: "https://cloudthrifty-demo.firebaseio.com",
projectId: "cloudthrifty-demo",
storageBucket: "cloudthrifty-demo.appspot.com",
messagingSenderId: "638814042535"
};
firebase.initializeApp(config);
//create firebase references
var Auth = firebase.auth();
var dbRef = firebase.database();
var contactsRef = dbRef.ref('contacts')
var usersRef = dbRef.ref('users')
var auth = null;
var db = firebase.firestore();
//Register
$('#registerForm').on('submit', function (e) {
e.preventDefault();
$('#registerModal').modal('hide');
$('#messageModalLabel').html(spanText('<i class="fa fa-cog fa-spin"></i>', ['center', 'info']));
$('#messageModal').modal('show');
var data = {
email: $('#registerEmail').val(), //get the email from Form
firstName: $('#registerFirstName').val(), // get firstName
lastName: $('#registerLastName').val(), // get lastName
};
var passwords = {
password : $('#registerPassword').val(), //get the pass from Form
cPassword : $('#registerConfirmPassword').val(), //get the confirmPass from Form
}
if( data.email != '' && passwords.password != '' && passwords.cPassword != '' ){
if( passwords.password == passwords.cPassword ){
//create the user
firebase.auth().createUserWithEmailAndPassword(data.email, passwords.password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
})
.then(function(user){
//now user is needed to be logged in to save data
auth = user;
//now saving the profile data
var uid = firebase.auth().currentUser.uid;
console.log(uid);
db.collection("users").doc(uid).set({
name: data.firstName
})
.then(function() {
console.log("Document successfully written!");
$('#messageModal').modal('hide');
$('.modal-backdrop').remove();
})
.catch(function(error) {
console.error("Error writing document: ", error);
$('#messageModal').modal('hide');
$('.modal-backdrop').remove();
});
$('#messageModalLabel').html(spanText('Success!', ['center', 'success']))
$('#messageModal').modal('hide');
$('.modal-backdrop').remove();
})
.catch(function(error){
console.log("Error creating user:", error);
$('#messageModalLabel').html(spanText('ERROR: '+error.code, ['danger']))
});
} else {
//password and confirm password didn't match
$('#messageModalLabel').html(spanText("ERROR: Passwords didn't match", ['danger']))
}
}
});
//Login
$('#loginForm').on('submit', function (e) {
e.preventDefault();
$('#loginModal').modal('hide');
$('#messageModalLabel').html(spanText('<i class="fa fa-cog fa-spin"></i>', ['center', 'info']));
$('#messageModal').modal('show');
if( $('#loginEmail').val() != '' && $('#loginPassword').val() != '' ){
//login the user
var data = {
email: $('#loginEmail').val(),
password: $('#loginPassword').val()
};
firebase.auth().signInWithEmailAndPassword(data.email, data.password)
.then(function(authData) {
auth = authData;
$('#messageModalLabel').html(spanText('Success!', ['center', 'success']))
$('#loginModal').modal('hide');
$('#messageModal').modal('hide');
$('.modal-backdrop').remove();
})
.catch(function(error) {
console.log("Login Failed!", error);
$('#messageModalLabel').html(spanText('ERROR: '+error.code, ['danger']))
$('#messageModal').modal('hide');
$('.modal-backdrop').remove();
});
}
});
$('#logout').on('click', function(e) {
e.preventDefault();
firebase.auth().signOut().then(function() {
// Sign-out successful.
// window.location='index.html';
}).catch(function(error) {
// An error happened.
});
});
//save contact
$('#contactForm').on('submit', function( event ) {
event.preventDefault();
if( auth != null ){
if( $('#name').val() != '' || $('#email').val() != '' ){
contactsRef.child(auth.uid)
.push({
name: $('#name').val(),
email: $('#email').val(),
location: {
city: $('#city').val(),
state: $('#state').val(),
zip: $('#zip').val()
}
})
document.contactForm.reset();
} else {
alert('Please fill at-lease name or email!');
}
} else {
//inform user to login
}
});
// firebase.auth().onAuthStateChanged(function(user) {
// if (user) {
// auth = user;
// $('body').removeClass('auth-false').addClass('auth-true');
// usersRef.child(user.uid).once('value').then(function (data) {
// var info = data.val();
// console.log(info);
// // if(user.photoUrl) {
// // $('.user-info img').show();
// // $('.user-info img').attr('src', user.photoUrl);
// // $('.user-info .user-name').hide();
// // } else if(user.displayName) {
// // $('.user-info img').hide();
// // $('.user-info').append('<span class="user-name">'+user.displayName+'</span>');
// // } else if(info.firstName) {
// // $('.user-info img').hide();
// // $('.user-info').append('<span class="user-name">'+info.firstName+'</span>');
// // }
// });
// contactsRef.child(user.uid).on('child_added', onChildAdd);
// } else {
// // No user is signed in.
// $('body').removeClass('auth-true').addClass('auth-false');
// auth && contactsRef.child(auth.uid).off('child_added', onChildAdd);
// $('#contacts').html('');
// auth = null;
// }
// });
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
auth = user;
var uid = firebase.auth().currentUser.uid;
console.log(uid);
$('body').removeClass('auth-false').addClass('auth-true');
db.collection("users").doc(uid)
.onSnapshot(function(doc) {
console.log("Current data: ", doc.data());
var name = doc.data().name
$('.user-info').append('<span class="user-name">'+name+'<span class="caret"></span></span>');
console.log(name);
});
} else {
// User is signed out.
$('body').removeClass('auth-true').addClass('auth-false');
auth && contactsRef.child(auth.uid).off('child_added', onChildAdd);
$('#contacts').html('');
auth = null;
}
});
});
function onChildAdd (snap) {
$('#contacts').append(contactHtmlFromObject(snap.key, snap.val()));
}
//prepare contact object's HTML
function contactHtmlFromObject(key, contact){
return '<div class="card contact" style="width: 18rem;" id="'+key+'">'
+ '<div class="card-body">'
+ '<h5 class="card-title">'+contact.name+'</h5>'
+ '<h6 class="card-subtitle mb-2 text-muted">'+contact.email+'</h6>'
+ '<p class="card-text" title="' + contact.location.zip+'">'
+ contact.location.city + ', '
+ contact.location.state
+ '</p>'
// + 'Card link'
// + 'Another link'
+ '</div>'
+ '</div>';
}
function spanText(textStr, textClasses) {
var classNames = textClasses.map(c => 'text-'+c).join(' ');
return '<span class="'+classNames+'">'+ textStr + '</span>';
}
*, *:before, *:after {
box-sizing: border-box;
}
html {
overflow-y: scroll;
}
body {
background: #fff;
font-family: 'Titillium Web', sans-serif;
}
a {
text-decoration: none;
color: #4F5459;
transition: .5s ease;
}
a:hover {
color: #71D72C;
}
/* #media only screen and (min-width: 640px) and (orientation: portrait) {
}
#media only screen and (min-width: 640px) and (orientation: landscape) {
} */
.userAuth {
display: block;
margin: 0px 0 0;
}
.modal-header:last-child{
border-bottom: 0;
}
.card {
display: inline-block;
margin: 1em;
max-width: calc(25% - 2em);
}
.user-info {
display: inline-block;
margin: 0 0.5em;
}
.user-info img{
display: inline-block;
max-width: 2em;
}
.auth-true .authenticated,
.auth-false .unauthenticated {
display: block;
}
.auth-true .unauthenticated,
.auth-false .authenticated {
display: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<title>Sign-Up/Login Form</title>
<!-- Bootstrap -->
<link href='https://fonts.googleapis.com/css?family=Titillium+Web:400,300,600' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<link rel="stylesheet" href="css/font-awesome-4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/captcha.css">
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body onLoad="ChangeCaptcha()" class="auth-false">
<nav class="navbar navbar-default" style="background-color: #6c757d; min-height: 50px">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" style="color: aliceblue; font-size: 25px" href="#">demo</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right" >
<!-- <li class="active" >What We Do <span class="sr-only">(current)</span></li> -->
<li>menu1</li>
<li>menu2 </li>
<li>menu3</li>
<li>menu4</li>
<!-- <li><button type="button" class="btn navbar-btn userAuth unauthenticated" style="color: #4F5459; font-size: 18px; font-weight: 600; background-color: #ffffff00; outline: 0; box-shadow: none!important;" data-toggle="modal" data-target="#registerModal">Register</button></li> -->
<li><button type="button" class="btn navbar-btn userAuth unauthenticated" style="color: #4F5459; font-size: 18px; font-weight: 600; background-color: #ffffff00; outline: 0; box-shadow: none!important;" data-toggle="modal" data-target="#loginModal">Login</button></li>
<!-- <li></li> -->
<!-- <li><span class="userAuth authenticated user-info"><img src="./user.svg" alt="User" class="rounded-circle"></span></li> -->
<!-- <div class="userAuth authenticated pull-right">
<span class="user-info">
<img src="./user.svg" alt="User" class="rounded-circle">
</span>
<button type="button" class="btn btn-success" id="logout">Logout</button>
</div> -->
<!-- <li><button type="button" class="btn navbar-btn userAuth authenticated" id="logout" style="color: #4F5459; font-size: 18px; font-weight: 600; background-color: #ffffff00; outline: 0; box-shadow: none!important;">Logout</button></li> -->
<button class="btn navbar-btn userAuth unauthenticated" style="background-color: #71D72C; color: #4F5459; font-size: 18px;">Free Trail</button>
<li class="dropdown">
<ul class="dropdown-menu">
<li><a href="#" role="button" class="btn userAuth authenticated" id="Account" style="color: #4F5459; font-size: 18px; text-align: left;" >Account</a></li>
<li><a href="#" role="button" class="btn userAuth authenticated" id="Scheduler" style="color: #4F5459; font-size: 18px; text-align: left;" >payment</a></li>
<li><a href="#" role="button" class="btn userAuth authenticated" id="logout" style="color: #4F5459; font-size: 18px; text-align: left;" >Logout</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<main class="authenticated">
<center>
<h1>welcome to cloud thrifty</h1>
</center>
<div id="contacts"></div>
</main>
<div class="modal fade" id="registerModal" tabindex="-1" role="dialog" aria-labelledby="Register" aria-hidden="true" >
<div class="modal-dialog">
<div class="modal-content">
<form id="registerForm" method="POST">
<div class="modal-header">
<h4 class="modal-title" id="registerModalLabel">Register</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="recipient-name" class="control-label">First Name:</label>
<input type="text" class="form-control" id="registerFirstName"required>
</div>
<div class="form-group">
<label for="recipient-name" class="control-label">Last Name:</label>
<input type="text" class="form-control" id="registerLastName"required>
</div>
<div class="form-group">
<label for="recipient-name" class="control-label">Email:</label>
<input type="text" class="form-control" id="registerEmail"required>
</div>
<div class="form-group">
<label for="message-text" class="control-label">Password:</label>
<input type="password" class="form-control" id="registerPassword"required>
</div>
<div class="form-group">
<label for="message-text" class="control-label">Confirm Password:</label>
<input type="password" class="form-control" id="registerConfirmPassword"required>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn pull-left" data-toggle="modal" data-target="#loginModal" data-dismiss="modal" style="background-color: #71D72C; border: 0px; color:#fff;">Login</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary" id="doRegister" style="background-color: #71D72C; border: 0px">Register</button>
</div>
</form>
</div>
</div>
</div>
<div class="modal fade" id="loginModal" tabindex="-1" role="dialog" aria-labelledby="Login" aria-hidden="true" >
<div class="modal-dialog">
<div class="modal-content">
<form id="loginForm" method="POST">
<div class="modal-header">
<h4 class="modal-title" id="loginModalLabel">Login</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="recipient-name" class="control-label">Email:</label>
<input type="text" class="form-control" id="loginEmail"required>
</div>
<div class="form-group">
<label for="message-text" class="control-label">Password:</label>
<input type="password" class="form-control" id="loginPassword"required>
</div>
<div class="form-group">
<button class="btn pull-right" style="background-color: #ffffff00; color: #4F5459; font-size: 14px; text-align: left">Forgot password?</button><br>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary pull-left" data-toggle="modal" data-target="#registerModal" data-dismiss="modal" style="background-color: #71D72C; border: 0px;color:#fff;">Register Now</button>
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary" id="doLogin" style="background-color: #71D72C; border: 0px" >Login</button>
</div>
</form>
</div>
</div>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="js/bootstrap.min.js"></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
<!-- Firebase App is always required and must be first -->
<!-- <script src="https://www.gstatic.com/firebasejs/5.9.0/firebase-app.js"></script> -->
<!-- Add additional services that you want to use -->
<script src="https://www.gstatic.com/firebasejs/4.3.1/firebase.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.8.4/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.1/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.1/firebase-database.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.1/firebase-firestore.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.1/firebase-messaging.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.9.1/firebase-functions.js"></script>
<!-- Comment out (or don't include) services that you don't want to use -->
<!-- <script src="https://www.gstatic.com/firebasejs/5.9.0/firebase-storage.js"></script> -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>
<!-- <script src="js/index.js"></script> -->
<!-- <script src="js/login.js"></script> -->
<!-- <script src="js/captcha.js"></script> -->
<script src="js/script.js"></script>
</body>
</html>
Every time the user's authentication state changes (i.e. they log in or out), you do:
$('.user-info').append('<span class="user-name">'+name+'<span class="caret"></span></span>');
So you're appending their new state to the existing contents of the .user-info element.
To replace the existing value, use .html instead of .append:
$('.user-info').html('<span class="user-name">'+name+'<span class="caret"></span></span>');

Call JavaScript Function Contained on _Layout.cshtml

Please help, new web developer alert!
MVC + JavaScript :)
I have a .cshtml page that has a submit button. When I press that button I want to call a JavaScript function contained on my _Layout.cshtml page.
Unfortunately I get a function not found error.
'ReferenceError: validateCheckBoxesInForm is not defined'
Here is the cshtml page...
#model FrontEnd.Web.Areas.PresentationToPolicy.ViewModels.CaseSummary.InsurersReferralViewModel
#{
ViewBag.Title = "Refer To Insurers";
}
<div>
<form asp-area="PresentationToPolicy" asp-controller="CaseSummary" asp-action="ReferToInsurers" method="POST" id="documentDownload">
<div class="panel panel-danger">
<div class="panel-body" style="padding-bottom: 15px">
<div class="row">
<div class="col-md-12">
<input class="btn btn-success btn-lg" type="submit" value="Finish" onclick="validateCheckBoxesInForm(event, 'documentDownload', 'Whooops!', 'You Must Select At Least One Insurer For Referal')" style="max-width: 100%; width: 100%"/>
</div>
</div>
</div>
</div>
</form>
</div>
Here a cut down version of my _Layout.cshtml (the script is loaded just after bootstrap etc, at the start of the body)
#inject Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet JavaScriptSnippet
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body style="background-color: #f6f8fa">
<environment include="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/jquery-ui/jquery-ui.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/dist/manifest.js"></script>
<script src="~/js/dist/vendor.js"></script>
<script src="~/js/dist/scripts.js" asp-append-version="true"></script>
</environment>
<div class="container body-content">
#RenderBody()
<hr style="margin-bottom: 2px; padding-bottom: 2px" />
<footer>
<p style="vertical-align: baseline">© 2017 - ABACUS Portfolio Portal</p>
</footer>
</div>
#RenderSection("Scripts", required: false)
</body>
</html>
Oh and the script that contains the function!
function validateCheckBoxesInForm(event, formId, title, message) {
let validated = false;
let form = $(`#${formId}`);
let elements = form.elements;
event.preventDefault();
for (var i = 0; i < elements.length; i++) {
if (elements[i].type === 'checkbox') {
if (elements[i].checked) {
validated = true;
form.submit();
break;
}
}
}
if (validated === false) {
$('<div></div>')
.appendTo('body')
.html(
`<div id="validateModal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content" style="border-color: #f00">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h3 class="modal-title">
${title}
</h3>
</div>
<div class="modal-body">
<h4>${message}</h4>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal" style="width: 150px">Ok</button>
</div>
</div>
</div>
</div>`
);
$('#validateModal').modal('show');
}
}
And finally a cut down version of 'View Source'
<body style="background-color: #f6f8fa">
<script src="/lib/jquery/dist/jquery.js"></script>
<script src="/lib/jquery-ui/jquery-ui.js"></script>
<script src="/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="/js/dist/manifest.js"></script>
<script src="/js/dist/vendor.js"></script>
<script src="/js/dist/scripts.js?v=iHOVZCmLJ7F7ev0DnwzRmkZgp-zu74ZoPGBIra9EaIk"></script>
<div class="container body-content">
<form method="POST" id="documentDownload" action="/PresentationToPolicy/CaseSummary/ReferToInsurers/43cffe87-2d8f-43eb-8ad2-e0b046fc8d20">
<div class="panel panel-danger">
<div class="panel-body" style="padding-bottom: 15px">
<div class="row">
<div class="col-md-12">
<input class="btn btn-success btn-lg" type="submit" value="Finish" onclick="validateCheckBoxesInForm(event, 'documentDownload', 'Whooops!', 'You Must Select At Least One Insurer For Referal')" style="max-width: 100%; width: 100%"/>
</div>
</div>
</div>
</div>
</form>
</body>
</html>
If I press view source and click on the script link I get this...
webpackJsonp([19],{
/***/ 749:
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__(750);
/***/ }),
/***/ 750:
/***/ (function(module, exports, __webpack_require__) {
"use strict";
//Global Functions that will be run of every page
//Called via _Layout.cshtml
function validateCheckBoxesInForm(event, formId, title, message) {
var validated = false;
var form = $('#' + formId);
var elements = form.elements;
event.preventDefault();
for (var i = 0; i < elements.length; i++) {
if (elements[i].type === 'checkbox') {
if (elements[i].checked) {
validated = true;
form.submit();
break;
}
}
}
if (validated === false) {
$('<div></div>').appendTo('body').html('<div id="validateModal" class="modal fade">\n <div class="modal-dialog">\n <div class="modal-content" style="border-color: #f00">\n <div class="modal-header">\n <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>\n <h3 class="modal-title">\n ' + title + '\n </h3>\n </div>\n <div class="modal-body">\n <h4>' + message + '</h4>\n </div>\n <div class="modal-footer">\n <button type="button" class="btn btn-danger" data-dismiss="modal" style="width: 150px">Ok</button>\n </div>\n </div>\n </div>\n </div>');
$('#validateModal').modal('show');
}
}....
So I guess my question is how to I call the function contained on the _Layout page from the child cshtml page?
I guess I could use a script section on the page, but this function is shared by multiple places. So I kinda need a central location to keep the code dry.

Issues rendering handlebars to HTML

When I render my handlebars template in html, it looks like it's essentially skipping filling in the "handle bars" portion. I'm essentially printing messages with a title and content, and I'm using a "!each" helper to display all of my messages. I originally thought it was because it was because it was escaping the html around it, so I tried using a triple handle bar {{{ on each part however using the each helper with the triple stash gave me an error. Am I possibly using the handlebars incorrectly?
the typescript I used to render the HTML and my handlebars template is below:
public static refreshData(data: any) {
$("#indexMain").html(Handlebars.templates['main.hbs'](data));
//helper function for upvote button
Handlebars.registerHelper('getUButton', function (id) {
id = Handlebars.escapeExpression(id);
return new Handlebars.SafeString(
"<button type='button' class='btn btn-default up-button' id='u" + id + "'>Upvote</button>"
);
});
//helper function for downvote button
Handlebars.registerHelper("getDButton", function (id) {
id = Handlebars.escapeExpression(id);
return new Handlebars.SafeString(
"<button type='button' class='btn btn-default down-button' id='d" + id + "'>DownVote</button>"
);
});
// Grab the template script
var theTemplateScript = $("#main-template").html();
// Compile the template
var theTemplate = Handlebars.compile(theTemplateScript);
//get messages from server and add them to the context
// This is the default context, which is passed to the template
var context = {
messages: data
}
console.log("context:")
console.log(context);
// Pass data to the template
var theCompiledHtml = theTemplate(context);
console.log(theCompiledHtml);
// Add the compiled html to the page
$("#messages-placeholder").html(theTemplate(context));
//add all click handlers
//get all buttons with id starting with u and set the click listerer
$(".up-button").click((event) => {
var id = $(event.target).attr("id").substring(1);
main.upvote(id)
});
//get all buttons with id starting with d and set the click listerer
$(".down-button").click((event) => {
var id = $(event.target).attr("id").substring(1);
main.downvote(id)
});
}
<script id="main-template" type="text/x-handlebars-template">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Current Messages</h3>
</div>
<div class="panel-body">
<div class="list-group" id="message-list">
<!-- for each message, create a post for it with title, content, upvote count, and upvote button -->
{{#each messages}}
<li class="list-group-item">
<span class="badge">Vote Count: {{likeCount}}</span>
<h4 class="list-group-item-heading">{{title}}</h4>
<p class="list-group-item-text">{{content}}</p>
<div class="btn-group btn-group-xs" role="group" aria-label="upvote">
{{getUButton id}}
</div>
<div class="btn-group btn-group-xs" role="group" aria-label="downvote">
{{getDButton id}}
</div>
</li>
{{/each}}
</div>
</div>
</div>
</script>
<div id="messages-placeholder"></div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Post New Message</h3>
</div>
<div class="input-group">
<span class="input-group-addon">Title</span>
<input id="newTitle" type="text" class="form-control" placeholder="Title" aria-describedby="newTitle">
</div>
<div class="input-group">
<span class="input-group-addon">Message</span>
<input id="newMessage" type="text" class="form-control" placeholder="Message" aria-describedby="newMessage">
</div>
<div class="btn-group" role="group" aria-label="create">
<button type="button" class="btn btn-default" id="postNewMessage">Post Message</button>
</div>
<span class="label label-danger" id="incompleteAcc"></span>
</div>
Okay, then it is likely the data provided to your template is not in the correct form. Here's a working snippet (with non-essentials stripped out). The data passed to your refreshData template must be an array. Make sure it isn't an object containing an array.
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.js"></script>
</head>
<body>
<script>
let refreshData = (data) => {
// Grab the template script
var theTemplateScript = $("#main-template").html();
// Compile the template
var theTemplate = Handlebars.compile(theTemplateScript);
//get messages from server and add them to the context
// This is the default context, which is passed to the template
var context = {
messages: data
};
console.log("context:", context);
// Add the compiled html to the page
$("#messages-placeholder").html(theTemplate(context));
}
$(() => {
var data = [
{ likeCount: 3, title: 'My Title', content: 'Some content'},
{ likeCount: 0, title: 'My 2nd Title', content: 'Some other content'}
];
refreshData(data);
})
</script>
<script id="main-template" type="text/x-handlebars-template">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Current Messages</h3>
</div>
<div class="panel-body">
<div class="list-group" id="message-list">
<!-- for each message, create a post for it with title, content, upvote count, and upvote button -->
{{#each messages}}
<li class="list-group-item">
<span class="badge">Vote Count: {{likeCount}}</span>
<h4 class="list-group-item-heading">{{title}}</h4>
<p class="list-group-item-text">{{content}}</p>
</li>
{{/each}}
</div>
</div>
</div>
</script>
<div id="messages-placeholder"></div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Post New Message</h3>
</div>
<div class="input-group">
<span class="input-group-addon">Title</span>
<input id="newTitle" type="text" class="form-control" placeholder="Title" aria-describedby="newTitle">
</div>
<div class="input-group">
<span class="input-group-addon">Message</span>
<input id="newMessage" type="text" class="form-control" placeholder="Message" aria-describedby="newMessage">
</div>
<div class="btn-group" role="group" aria-label="create">
<button type="button" class="btn btn-default" id="postNewMessage">Post Message</button>
</div>
<span class="label label-danger" id="incompleteAcc"></span>
</div>
</body>
</html>
When I am faced with issues like this, I eliminate different things until I either get clarity or something I removed fixes the problem. Now I have isolated where the problem lies. In your situation, the issue is likely the data being passed so verify that. Then try stripping out your helpers to see if they are causing issues.

Categories