Why is XMLHttpRequest readystate not equal to 4? - javascript

I'm learning AJAX for the first time and I'm trying to create a simple application that calculates the grade a person needs to get on their final exam based on their previous assessment results.
The user inputs their grades into the form and then using ajax I calculate the response in response.php which should then be output in the callback function in the div with ajax as its id.
For some reason the xhr.readystate property is never reaching 4 so the response is never generated. Can anybody see what I'm doing wrong?
Please bear in mind I'm only learning...
index.php
<!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">
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="../../favicon.ico">
<title>Grade Calculator</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css">
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<script>
function sendAjax() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
document.getElementById('ajax').innerHTML = xhr.responseText;
} else {
document.getElementById('ajax').innerHTML = document.write('There was a problem');
}
};
xhr.open("GET","response.php");
xhr.send();
document.getElementById('gradeForm').style.display = "none";
document.write(xhr.readyState);
}
</script>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<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" href="#">Project name</a>
</div>
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active">Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="starter-template">
<h1>Bootstrap starter template</h1><br>
<form action="index.php" method="get" id="gradeForm">
<div class="form-group">
<label for="currentGrade">What is your current Grade</label>
<input type="text" name="currentGrade"><br>
</div>
<div class="form-group">
<label for="targetGrade">What is your target Grade</label>
<input type="text" name="targetGrade"><br>
</div>
<div class="form-group">
<label for="finalWorth">What is your final worth?</label>
<input type="text" name="finalWorth"><br>
</div>
<button type="submit" class="btn btn-default" onclick="sendAjax()">Submit</button>
</form>
<div id="ajax">
</div>
</div>
</div><!-- /.container -->
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
</body>
</html>
Here is response.php
<?php
$currentGrade = $_GET['currentGrade'];
$targetGrade = $_GET['targetGrade'];
$finalWorth = $_GET['finalWorth'];
$neededMark = $currentGrade - $targetGrade;
$neededMark = $neededMark / $finalWorth;
$neededMark = $neededMark * 100;
$neededMark = round($neededMark);
if(isset($currentGrade, $targetGrade,$finalWorth)) {
echo $neededMark;
}
?>

The correct order of operations is:
construct
open
set handler
send
You are doing them in the order 1324, which is incorrect and therefore likely to not behave as expected.
Put things in the right order, see if that works :)
EDIT: Additionally, remove all document.write calls. They will not work with any asynchronous operation and will almost certainly break things.
EDIT EDIT: Also, <button type="submit" class="btn btn-default" onclick="sendAjax()"> - this should be type="button", otherwise your form will be submitted and it will look like it did nothing.

doesn't look like you are sending any parameters in your ajax request so response.php is not GETting any data...
if it were xhr.open("GET","response.php?param1=value1&param2=value2"); etc you should get something

Only one small change is required
In form division make instead of submit. Because on submit the forms behaviour is different as compared to just a button click

Related

Can't properly animate bootstrap 5 collapse element created via js

My goal is to create a collapse element when the form data has been processed by the server, to notify the user whether the data was successfully sent to the server or an error occurred.
function sendForm(event, form) {
const wrapper=document.createElement('div');
wrapper.setAttribute('role', 'alert');
wrapper.classList.add('alert', 'alert-dismissible', 'alert-success');
wrapper.innerHTML='<span>Success!</span><button type="button" class="btn-close" data-bs-dismiss="alert"></button>';
form.prepend(wrapper);
const bsWrapperCollapse = bootstrap.Collapse.getOrCreateInstance(wrapper);
bsWrapperCollapse.show();
setTimeout(() => {
bsWrapperCollapse.hide();
}, 4000);
setTimeout(() => {
wrapper.remove();
}, 7000);
form.reset();
event.preventDefault();
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
</head>
<body>
<main class="container-fluid my-5" style="max-width:300px">
<form action="#" method="post" onsubmit="sendForm(event, this)">
<button type="submit" class="btn btn-primary">My form submit btn</button>
</form>
<button class="btn btn-primary" data-bs-toggle="collapse" data-bs-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
Button with data-bs-target
</button>
<div class="collapse" id="collapseExample">
<div class="alert alert-dismissible alert-success" role="alert">
<span>Success!</span>
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
</body>
</html>
I added two implementations to the test html - the first button calls my implementation, which is in the form and when it is pressed, data should be sent, but the animation of appearing and hiding is jerky. The second button is taken from the bootstrap documentation, with the correct animation, which is what I want to achieve in my implementation using js.
I think the problem is that the element created in js haven't the collapse class, the transition is applied only if the element has collapse class. I modified the code , I added the class collapse to the wrapper and added the alerts classes to a div inside the wrapper element.Now it seems the animation works properly
function sendForm(event, form) {
const wrapper=document.createElement('div');
wrapper.setAttribute('role', 'alert');
wrapper.classList.add("collapse");
wrapper.innerHTML='<div class="alert alert-dismissible alert-success"><span>Success!</span><button type="button" class="btn-close" data-bs-dismiss="alert"></button> </div>';
form.prepend(wrapper);
const bsWrapperCollapse = bootstrap.Collapse.getOrCreateInstance(wrapper);
bsWrapperCollapse.show();
setTimeout(() => {
bsWrapperCollapse.hide();
}, 4000);
setTimeout(() => {
wrapper.remove();
}, 7000);
form.reset();
event.preventDefault();
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
</head>
<body>
<main class="container-fluid my-5" style="max-width:300px">
<form action="#" method="post" onsubmit="sendForm(event, this)">
<button type="submit" class="btn btn-primary">My form submit btn</button>
</form>
<button class="btn btn-primary" data-bs-toggle="collapse" data-bs-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
Button with data-bs-target
</button>
<div class="collapse" id="collapseExample">
<div class="alert alert-dismissible alert-success" role="alert">
<span>Success!</span>
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
</body>
</html>
So, I figured out how I can make the animation normal without even checking the answers here. I noticed that the alert container in the html code is wrapped in another container. But when I created the alert via js, I didn't wrap it. After I wrapped this element, the animation worked as it should. #Nick suggested that the animation doesn't work as expected due to the lack of a collapse class, but I tested his code without it and the animation still works. The reason the animation works correctly is that he wrapped my code in a container via innerHTML, essentially doing the same thing I did. Here's what I ended up with.
function sendForm(event, form) {
const alert=document.createElement('div');
alert.setAttribute('role', 'alert');
alert.classList.add('alert', 'alert-dismissible', 'alert-success');
alert.innerHTML='<span>Success!</span><button type="button" class="btn-close" data-bs-dismiss="alert"></button>';
const alertWrapper=document.createElement('div');
alertWrapper.append(alert);
form.prepend(alertWrapper);
const alertWrapperCollapse = bootstrap.Collapse.getOrCreateInstance(alertWrapper);
alertWrapperCollapse.show();
setTimeout(() => {
alertWrapperCollapse.hide();
}, 4000);
setTimeout(() => {
alertWrapper.remove();
}, 7000);
form.reset();
event.preventDefault();
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">
</head>
<body>
<main class="container-fluid my-5" style="max-width:300px">
<form action="#" method="post" onsubmit="sendForm(event, this)">
<button type="submit" class="btn btn-primary">My form submit btn</button>
</form>
<button class="btn btn-primary" data-bs-toggle="collapse" data-bs-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
Button with data-bs-target
</button>
<div class="collapse" id="collapseExample">
<div class="alert alert-dismissible alert-success" role="alert">
<span>Success!</span>
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>
</body>
</html>
Anyway, I marked #Nick's answer as helpful.

adding carousel items using jquery

I'm working on an inserting form that inserts a product to a [ products draft ] so I have two tables
one called ( Drafts ) and the other is ( items ) each item in the last table (items) have a draft id.
When inserting a new Draft it supposes that the client who is adding the draft have entered the number of the products in the draft so when he entered the number of the products the application well call a number of forms to insert each one of them ( the determined number of products ) so I used jquery to insert the product forms inside a bootstrap 4 carousel as a ( carousel-item ) using (append) and within each form, there is a navbar ( shows which form is this ) like this ( 1 / 50 ) and my question is which element (DOM) I have to append my code to I tried this:- and nothing happens
Code Snippet:-
<?
include("..\include\basket-module.php");
// notifications //
include("..\\include\\notif-module.php");
// module //
include("..\\include\\Insert-module.php");
?>
<html>
<head>
<title>Project - new Draft</title>
<meta charset="utf-8">
<meta http-equiv="ScreenOrientation" content="autoRotate:disabled">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Bootstrap4 Library and Font-awesome with Custom CSS -->
<link rel="stylesheet" type="text/css" href="..\Styles\profile.css">
<link rel="stylesheet" type="text/css" href="..\Styles\newdraft.css">
<link rel="stylesheet" type="text/css" href="..\Styles\newproduct.css">
<link rel="stylesheet" type="text/css" href="..\Styles\navegationbar.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- Bootstrap4 Library and Font-awesome with Custom CSS End-->
<!-- including custom javascript -->
<script src="..\js\functions\js.js"></script>
<script>
function myFunction(event){ // **** PS: I Think the problem is with the carousel-item status ( $actives )
var formscount = $('#count').val();
if (formscount > 0) {
for (i=0; i < formscount; i++) {
$('#demo').append($('<div class="carousel-item '+<?=$actives;?>+'"><center><nav class="navbar counter justify-content-center" style="width:70vh; background-color:#86377b;"><a class="navbar-brand" style="font-family:tahoma; font-size:28px; text-shadow:4px 4px rgba(0,0,0,1); color:white;">'+i+'</a></nav></center></div>'));
event.preventDefault()
}
}
}
</script>
<!-- Fontawseome Kit -->
<script src="https://kit.fontawesome.com/d75f59893e.js" crossorigin="anonymous"></script>
</head>
<body>
<!-- Bootstrap Jquery JavaScripts -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script><!-- Bootstrap Jquery JavaScripts -->
<!-- Bootstrap Jquery JavaScripts Ends -->
<!-- navegtion bar bootstrap 4 -->
<?php include("..\\home\\navbar.php"); ?>
<!-- basket sidebar -->
<?php include("..\\home\\basket.php"); ?>
<!-- Main Products Form -->
<center>
<div class="card justify-content-center cont">
<div class="card-body">
<div class="card-text">
<nav class="navbar header justify-content-center">
<a class="navbar-brand" style="font-family:hana; font-size:28px; text-shadow:4px 4px rgba(0,0,0,1); color:white;">إدخال المنتجات</a>
</nav>
<hr />
<center>
<form action="#" method="post">
<input name="count" id="count" type="number" class="form-control" placeholder="عدد النماذج">
<button onclick="myFunction(event)">إضافة النماذج</button>
</form>
<div id="demo" class="carousel slide" data-ride="carousel" style="height:50vh;">
<!-- Indicators -->
<ul class="carousel-indicators" style="background-color: black; color:black;">
<?
$i = 0;
foreach($result as $row){
$actives = '';
if($i == 0){
$actives ='active';
}
?>
<li data-target="#demo" data-slide-to="<?= $i; ?>" class="<?= $actives; ?>"></li>
<? $i++ ; }?>
</ul>
<!-- The slideshow -->
<div class="carousel-inner canner">
<div class="carousel-item"><img src="<?= $row['imageurl']?>" Height=75% alt="inner"></div>
</div>
<!-- Left and right controls -->
<a class="carousel-control-prev" href="#demo" data-slide="prev">
<span class="carousel-control-prev-icon"></span>
</a>
<a class="carousel-control-next" href="#demo" data-slide="next">
<span class="carousel-control-next-icon"></span>
</a>
</div>
</center>
</div>
</div>
</div>
</center>
</body>
</html>
Update:- a new problem pops up is when I append a new ( carouesl-items ) nothing happens it just showing one active items even the indicator is a one
updated the snippet to see the code
When you run this in the console it says that current(i) is not defined, so if you remove it and leave just second occurrence of i instead you'll get this result:

Passing value from Google Login to JSF login

I'm kinda new to all of this, but I have a JSF Web Application (which works) which also has a Google Authentication (google authentication works by itself);
I'm trying to pass the response from the google Auth to the JSF login (the email address & google Id) which will then authenticate via a JdbcRealm;
So just to clarify, the JSF authentication via a JdbcRealm works by itself, and the google login by itself works - i just want to pass the response from google (of the email address & google id) to be used as the JSF authentication, & automate the click action of the JSF auth form.
My issue is, that after i log into google, i get the error
TypeError: document.getElementById(...) is null
Here's my JSF login page with all the Javascript;
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h: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 -->
<meta name="description" content="NDIS Management System"/>
<meta name="author" content="Danielle Walker"/>
<meta name="google-signin-client_id" content="270287108664-3g7l6e6ah3gr5am9onokua84t3bvdbvf.apps.googleusercontent.com" />
<title>NDIS Home</title>
<!-- Bootstrap core CSS -->
<h:outputStylesheet name="bootstrap/css/bootstrap.min.css"/>
<h:outputStylesheet name="bootstrap/css/the-big-picture.css" />
<h:outputStylesheet name="css/google-button.css" />
<!-- 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:// -->
<f:verbatim>
<!--[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]-->
</f:verbatim>
<!-- Google API Javascript needs to be loaded in the page before the actual Javascript -->
<script src="https://apis.google.com/js/api:client.js" />
<ui:insert name="head"/>
</h:head>
<h:body class="full">
<nav class="navbar navbar-inverse navbar-fixed-bottom" role="navigation">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<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" href="#"></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">
<li>
About
</li>
<li>
Contact
</li>
</ul>
<ul class="navbar-right">
<li>
<div id="gSignInWrapper" style="padding-top:5px;">
<div id="customBtn" class="customGPlusSignIn" style="float: right;">
<span class="icon"></span><span class="buttonText">Sign In</span>
</div>
</div>
<span style="color:#f9f9f9"><div id="name"></div></span>
</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>
<h:form id="login" onsubmit="document.getElementById('login').action = 'j_security_check';" prependId="false">
<!--<h:panelGrid columns="2">-->
<h:outputLabel for="j_username" value="Username" />
<h:inputText id="j_username" />
<h:outputLabel for="j_password" value="Password" />
<h:inputText id="j_password" size="8"/>
<h:commandButton id="submit" value="Login" />
<!--</h:panelGrid>-->
</h:form>
<f:verbatim>
<script>
var googleUser = {};
var startApp = function () {
gapi.load('auth2', function () {
// Retrieve the singleton for the GoogleAuth library and set up the client.
auth2 = gapi.auth2.init({
client_id: '270287108664-3g7l6e6ah3gr5am9onokua84t3bvdbvf.apps.googleusercontent.com',
cookiepolicy: 'single_host_origin'
// Request scopes in addition to 'profile' and 'email'
//scope: 'additional_scope'
});
attachSignin(document.getElementById('customBtn'));
});
};
</script>
</f:verbatim>
<script>startApp();</script>
<f:verbatim>
<script>
function attachSignin(element) {
console.log(element.id);
auth2.attachClickHandler(element, {},
function (googleUser) {
//document.getElementById('name').text = "Signed in: " +
// googleUser.getBasicProfile().getId();
document.getElementById("login.j_username").value = googleUser.getBasicProfile().getEmail();
document.getElementById("login.j_password").value = googleUser.getBasicProfile().getId();
}, function (error) {
alert(JSON.stringify(error, undefined, 2));
//alert("Opps... an error Occured");
});
}
function signOut() {
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('User signed out.');
});
}
</script>
</f:verbatim>
<ui:insert name="body"/>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<h:outputScript name="bootstrap/js/bootstrap.min.js"/>
<script src="https://apis.google.com/js/api:client.js" />
</h:body>
</html>
I found the answer to my own problem;
With my error message, the problem was obviously in the way i was trying to access the "j_username" & "j_password elements:
TypeError: document.getElementById(...) is null
Anyway, by changing the code i had:
document.getElementById("login.j_username").value = googleUser.getBasicProfile().getEmail();
To instead look like this:
document.getElementById("login").elements[1].value = googleUser.getBasicProfile().getEmail();
In short, the problem was the way i was trying to address the elements of the form, and by addressing the form itself, and then the elements of the form (being in a 0 based array), then it works

Saving data from a page in the local storage

This is my first time asking or doing this type of question
So I created this page http://lamp.cse.fau.edu/~mcuervo5/p4/
and it does your basic to do app list thing for adding and deleting stuff.
Apparently the only thing missing is to save the data on the current page. I heard that there a code that can save the current page to a local storage that has everything already in it, so when I re-open the link, instead of having nothing in the "complete and incomplete" list, it should look like this
thanks, it the only part I have left to do & I dont know if it implemented in HTMl or Jquery. I do not know how to do it.
and if you want to see the code here instead of "inspect" from the page with the link above, here it is. for html and Jquery
$(document).ready(function() {
// $('#list').innerhtml = localStorage.getItem("List");
//$('#incomplete-tasks').html("<P>I just replaced your stuff.</P>");
$("#Sumbit_Button").click(function() {
var textbox_Value = $("#textbox").val();
$('#incomplete-tasks').append('<li><span class="text" contenteditable="false">' + textbox_Value + "</span>" +
'<input/ style="display: none" class="new-value">' +
"<button type='button' class='delete'>Delete</button>" +
"<button type='button' class='edit'>Edit</button></li>");
});
$('#incomplete-tasks').on('click', '.delete', function() {
console.log('i am clicked.delete');
$(this).parent().remove();
});
$('#incomplete-tasks').on('click', '.edit', function() {
console.log("complete task click.edit");
$(this).siblings('input').show();
$(this).siblings('.delete').hide();
$(this).hide();
});
$('#incomplete-tasks').on('click', '.edit', function() {
console.log("INcomplete task click.edit");
$(this).siblings('input').show();
$(this).siblings('span').hide();
$(this).siblings('.delete').hide();
$(this).hide();
});
$('#incomplete-tasks').on('keyup', '.new-value', function(e) {
if (e.keyCode == 13) {
console.log("Complete Task _Version 2.new_value");
$(this).siblings('span').text($(this).val()).show();
$(this).siblings('input').hide();
$(this).siblings('.delete').show();
$(this).siblings('.edit').show();
$(this).hide();
}
});
$('#incomplete-tasks').on('click', '.text', function() {
var li = $(this).parent().remove().toggleClass("strikethrough");
$('#complete-tasks').append(li);
});
$('#complete-tasks').on('click', '.delete', function() {
console.log('i am clicked.delete');
$(this).parent().remove();
});
$('#complete-tasks').on('click', '.edit', function() {
console.log("complete task click.edit");
$(this).siblings('input').show();
$(this).siblings('.delete').hide();
$(this).hide();
});
$('#complete-tasks').on('click', '.edit', function() {
console.log("INcomplete task click.edit");
$(this).siblings('input').show();
$(this).siblings('span').hide();
$(this).siblings('.delete').hide();
$(this).hide();
});
$('#complete-tasks').on('keyup', '.new-value', function(e) {
if (e.keyCode == 13) {
console.log("Complete Task _Version 2.new_value");
$(this).siblings('span').text($(this).val()).show();
$(this).siblings('input').hide();
$(this).siblings('.delete').show();
$(this).siblings('.edit').show();
$(this).hide();
}
});
$('#complete-tasks').on('click', '.text', function() {
var li = $(this).parent().remove().toggleClass("strikethrough");
$('#incomplete-tasks').append(li);
});
// var save()
//{
// localStorage.setItem("List", $("#list").innerhtml());
// }
});
<!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">
<meta name="description" content="">
<meta name="author" content="">
<title>The Reminder list</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<script src="http://cdn.jsdelivr.net/jquery.validation/1.14.0/jquery.validate.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<!-- Custom CSS -->
<link href="css/heroic-features.css" rel="stylesheet">
<!-- HTML5 Shim and Respond.js 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/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<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" href="#">To Do List</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">
<li>
About
</li>
<li>
Services
</li>
<li>
Contact
</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>
<!-- Page Content -->
<div class="container">
<!-- Jumbotron Header -->
<header class="jumbotron hero-spacer">
<h1> The Reminder Friend App </h1>
<p>this is my to do list app. type in the list you want to add & store in the list
</p>
<form>
<!-- textbox -->
<input type="text" id="textbox">
<!--add button -->
<input type="button" id="Sumbit_Button" value="Add">
</form>
</header>
<hr>
<div id='lists'>
<!-- Page Features -->
<div class="row text-center">
<div class="col-md-6 col-sm-6 hero-feature">
<div class="thumbnail">
<div class="caption">
<h3>Incomplete</h3>
<ul id="incomplete-tasks">
</ul>
</div>
</div>
</div>
<div class="col-md-6 col-sm-6 hero-feature">
<div class="thumbnail">
<div class="caption">
<h3>Complete</h3>
<ul id="complete-tasks">
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- /.row -->
<hr>
<!-- Footer -->
<footer>
<div class="row">
<div class="col-lg-12">
<p>Copyright © Mauricio Cuervo 2017</p>
</div>
</div>
</footer>
</div>
<!-- /.container -->
<!-- jQuery -->
<script src="js/jquery.js"></script>
<!-- Bootstrap Core JavaScript -->
<script src="js/bootstrap.min.js"></script>
</body>
<script src="p4.js"></script>
</html>
Hello you can do something like this:
$("#Sumbit_Button").click(function() {
var textbox_Value = $("#textbox").val();
var list = [];
list.push(textbox_Value);
localStorage.setItem("listdata", list);
// do not manage using `append` whole html. Manage through list and display as you want
});
on page load call:
var stored = localStorage.getItem("listdata");
Now here you can manage array of items and iterate on complete & incomplete list.
So whenever any action of edit, delete, add occurs you have to just manage the localstorage instance on each call. and based on that just iterate list whereever you want.

Basic Javascript doesn't display well (stack Mean)

It will be a very basic question about a problem I encountered. Nothing is specially hard in the work I intend to do, but I really don't see why it isn't working, as my code is almost the same as some examples in AngularJS documentation.
So here it is :
I'm trying to create a basic website to entertain myself on developping with Mean Stack).
I made a mere index.html page :
<!DOCTYPE hmtl>
<html class="ng-scope" ng-app="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>PreBoot</title>
<!-- Bootstrap import -->
<link href="./bootstrap.min.css" rel="stylesheet">
<!-- just a little CSS -->
<style>
body {
padding-top: 70px;
/* Required padding for .navbar-fixed-top. Remove if using .navbar-static-top. Change if height of navigation changes. */
}
</style>
</head>
<body ng-app="preBoot">
<div id='main'>
<!-- Navigation -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data- toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<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" href="#">PreBoot</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">
<li>
About
</li>
<li>
Services
</li>
<li>
Contact
</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>
<!-- Page Content -->
<div class="container">
<div class="row">
<div class="col-lg-12 text-center">
<h1> PreBoot </h1>
<p class="lead">zqesiediuhzsbadehzdebshobsezd</p>
<form ng-submit="post()" ng-controller="mainController">
<input required type="text" placeholder="Your name" ng-model="newPost.created_by"/>
<textarea required maxLength="200" rows="3" placeholder="Say something" ng-model="newPost.text"></textarea>
<input class="button" type="submit" value="Preboot that!"/>
</form>
<div id="post-stream">
<!-- INTERESTING PART !!!!!!!! -->
<h4> PreBoot Feed</h4>
<div class='post' ng-repeat="post in posts" ng-class-odd="'odd'" ng-class-even="'even'">
<p> {{post.text}} </p>
</div>
</div>
<!-- END OF IT !!!!! -->
<!-- <ul class="list-unstyled">
<li>Bootstrap v3.3.6</li>
<li>jQuery v1.11.1</li>
</ul> -->
</div>
</div>
<!-- /.row -->
</div>
<!-- /.container -->
</div>
<!-- JScript imports -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script type="text/javascript" src="./preBoot.js"></script>
<!-- jQuery Version 1.11.1 -->
<script type="text/javascript" src="./jquery.js"></script>
<!-- Bootstrap Core JavaScript -->
<script type="text/javascript" src="./bootstrap.min.js"></script>
And that's for the HTML page, the interesting part is notified. I use a serveur.js file which is following :
var app = angular.module('preBoot', []);
app.controller('mainController', function($scope){
$scope.posts = [];
$scope.newPost={created_by: '', text: '', created_at: ''};
$scope.post= function(){
$scope.newPost.created_at = Date.now();
$scope.posts.push($scope.newPost);
$scope.newPost = {created_by: '', text: '', created_at: ''};
};
});
Finally, I run everything using the serveur.js file I run with the node.js invite command.
var express = require('express');
var path = require('path');
var app = express();
app.use(express.static(__dirname));
app.get('/', function(req, res) {
res.sendFile('./index.html');
});
// Allow the error 404 selection
/* app.use(function(req, res, next){
res.setHeader('Content-Type', 'text/plain');
res.send(404, 'Page introuvable !');
}); */
app.listen(8081);
For simplicity purposes, I temporarly put every single file in the same folder, so everything (every ccs and js file is in the same folder of my html).
What I get when I run the program is :
My screenshoot
Which is pretty much what I want except when I type something, the text doesn't appear, which does not make any sense to me.
I correctly installed the npm express before in a node_module folder put in the same place than my index.html file.
Sorry to bother with that uninteresting problem, I spend hours trying to fix that problem and one more searching for any solution in the questions already asked, but everything I found didn't fix the issue.
NB : I work on Windows.
The main problem is you have defined
ng-app=""
and you have defined the controller on preBoot app
var app = angular.module('preBoot', []);
app.controller('mainController', function($scope){
Either define the controller like this
function mainController($scope){
OR define the ng-app="preBoot"
Others mistakes are
Your controller is bound to form only
<form ng-submit="post()" ng-controller="mainController">
<input required type="text" placeholder="Your name" ng-model="newPost.created_by"/>
<textarea required maxLength="200" rows="3" placeholder="Say something" ng-model="newPost.text"></textarea>
<input class="button" type="submit" value="Preboot that!"/>
</form>
This code is out of controller scope
<div class='post' ng-repeat="post in posts" ng-class-odd="'odd'" ng-class-even="'even'">
<p> {{post.text}} </p>
</div>
I did short your code and have made a jsfiddle. Working fine.
check it
https://jsfiddle.net/Lt7aP/2926/
In jsfiddle code update ng-app="preBoot" to ng-app="" you will get the error Argument 'mainController' is not a function, got undefined

Categories