It's giving me cannot read property of undefined error in server.js file at this line
io.nsps['/'].adapter.rooms[roomName].length;
I want to display all the names of users those are connected in the chat room..
I take user name and room name by prompt when first time loads the page...
I am using socket.io v1.5.1
I have tried almost all the codes that are available for >v1.0 but i failed.
Here is my code..
server.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var express = require('express');
app.use(express.static('public'));
io.on('connection', function(socket){
var userName = null;
var roomName = null;
//creating chat room
socket.on('createRoom',function(data){
userName = data.userName;
//creating or joining room
socket.join(data.roomName);
roomName = data.roomName;
//broadcasting new user joined to all other sockets in room
socket.broadcast.in(data.roomName).emit('user joined','<span style="color:#10c469 !important;"><strong>'+userName+'</strong> has joined chatroom.</span><br>');
});
var userLength = io.nsps['/'].adapter.rooms[roomName].length;
//Server receives message from client
socket.on('messageForServer',function(data){
//will alert all users
socket.emit('all users',userLength);
io.sockets.in(data.roomName).emit('messageToBeDisplayed','<strong>'+data.userName+'</strong> : '+data.message+'<br>');
});
//when user is typing
socket.on('userIsTyping',function(data){
socket.broadcast.in(roomName).emit('userIsStillTyping','<span style="color:#ff4242 !important;"<strong>'+userName+'</strong></span> is typing...</br>');
});
//when user stops typing
socket.on('noLongerTyping',function(data){
socket.broadcast.in(roomName).emit('userIsNotTyping');
});
//when user gets bored
socket.on('disconnect',function(){
socket.broadcast.in(roomName).emit('disconnected','<span style="color:#ff4242 !important;"<strong>'+userName+'</strong> has left the chat room.</span><br>');
});
});
http.listen(3000, function(){
console.log('listening on localhost:3000');
});
index.html
<!DOCTYPE html>
<html>
<head>
<title>ChatterBox</title>
<link rel="stylesheet" type="text/css" href="bootstrap/css/bootstrap.css">
<link rel="stylesheet" type="text/css" href="bootstrap/css/main.css">
<link rel="stylesheet" type="text/css" href="css/core.css">
<link rel="stylesheet" type="text/css" href="css/components.css">
</head>
<style>
.bottom{
position: fixed;
text-align: center;
bottom: 10px;
width: 100%;
}
.wrapper{
padding-top: 4%;
}
</style>
<body>
<div class="container">
<div class="row">
<nav class="navbar navbar-default navbar-fixed-top">
ChatterBox
</nav>
<div class="wrapper">
<div class="col-md-7 col-md-offset-2">
<div id="message-container"></div>
</div>
<div class="col-md-3">
<div id="typer-container"></div>
</div>
<div class="form-group bottom">
<div class="col-md-7 col-md-offset-2">
<input type="text" id="message" class="form-control" placeholder="Enter message here">
</div>
<div class="col-md-1">
<button type="button" onclick="sendMessage()" class="btn btn-trans btn-inverse waves-effect w-md waves-light m-b-5">Send</button>
</div>
</div>
</div>
</div>
</div>
</body>
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/app.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
//initialize socket library and its object
var socket = io();
//taking input from user
var roomName = prompt("Enter name of chat room that you want to create or join");
var userName = prompt("Enter your username");
//create chat room
socket.emit('createRoom',{roomName:roomName,userName:userName});
//when user joins the chat room
socket.on('user joined',function(data){
document.getElementById('message-container').innerHTML += data;
});
//to display when user leave chat room
socket.on('disconnected',function(data){
document.getElementById('message-container').innerHTML += data;
});
//Press enter to send message code
$('#message').keypress(function(event){
if(event.which == 13){
sendMessage();
}
});
//Send message to server
function sendMessage()
{
var msg = document.getElementById('message').value;
document.getElementById('message').value = '';
if(msg){
socket.emit('messageForServer', {message: msg, roomName:roomName,userName: userName});
}
}
var typing = false;
var timeout = undefined;
//when user is no longer typing
function timeoutFunction(){
typing = false;
socket.emit('noLongerTyping');
}
function onKeyDownNotEnter(){
if(typing == false) {
typing = true;
socket.emit('userIsTyping',userName+' is typing...');
timeout = setTimeout(timeoutFunction, 5000);
} else {
clearTimeout(timeout);
timeout = setTimeout(timeoutFunction, 5000);
}
}
//User is typing functionality
$('#message').keyup(function(event){
if(event.which != 13 && userName != ''){
onKeyDownNotEnter();
}
});
socket.on('all users',function(data){
alert(data);
});
//users will see who is typing from this code
socket.on('userIsStillTyping',function(data){
document.getElementById('typer-container').innerHTML += data;
});
//remove user is typing
socket.on('userIsNotTyping',function(){
document.getElementById('typer-container').innerHTML = '';
});
//Display broadcasted message
socket.on('messageToBeDisplayed',function(data){
document.getElementById('message-container').innerHTML += data;
});
</script>
</html>
You can try this:
//Server receives message from client
socket.on('messageForServer',function(data){
//will alert all users
var userLength = io.nsps['/'].adapter.rooms[roomName].length;
socket.emit('all users',userLength);
io.sockets.in(data.roomName).emit('messageToBeDisplayed','<strong>'+data.userName+'</strong> : '+data.message+'<br>');
});
But it does not display the names of the connected users but only their number.
Related
So I'm building a simple web app that gets data from an API that needs to be displayed on the screen.
However after the Post request is made, the data from the API gets logged through the console.log() however it does not get displayed on the screen though I've got the correct code, it gets displayed after a manual refresh.
I'm using EJS to display the API data on the screen.
The app.js has the following:
var cityName='';
var temperature='';
var pressure='';
app.get('/',function(req,res){
res.render('home');
});
app.get('/results',function(req,res){
res.render('results',{
cityName: cityName,
pressure:pressure,
temperature:temperature,
}
);
});
app.post('/',function(req,res){
cityName=req.body.cityName;
const api_url= 'https://api.openweathermap.org/data/2.5/weather?q='+ cityName +'&appid=8bb235e1990db4b5ae16f92e920bad25';
https.get(api_url,function(output){
//console.log(output);
output.on('data', function(data){
const weatherData= JSON.parse(data);
// WEATHER
temperature=Number(weatherData.main.temp)-273.15;
pressure= Number(weatherData.main.pressure);
console.log('Temparature:'+temperature+' °C');
console.log('Pressure:'+pressure + ' hPa');
});
});
res.redirect('/results');
});
let port = process.env.PORT;
if (port == null || port == "") {
port = 3000;
}
app.listen(port, function(){
console.log("Server ativated at port successfully");
});
The results.ejs file simply has the following:
<div class="container">
<div class="card-deck">
<div class="card bg-light mb-3" >
<div class="card-header">City</div>
<div class="card-body">
<ul>
<li><p class="card-text" name="cityName">City Name: <%= cityName %>.</p></li>
<li><p class="card-text" name="temperature">Temperature: <%= temperature %> °C.</p></li>
<li><p class="card-text" name="pressure">Pressure: <%= pressure %> hPa.</p></li>
</ul>
</div>
</div>
</div>
</div>
The home.ejs file has:
<div class="container1 container">
<form method="post" action="/">
<div class="brand-logo"></div>
<div class="brand-title">WEATHER MONITORING</div>
<div class="inputs">
<label>CITY NAME</label>
<input autocomplete="off" name="cityName" type="text" placeholder="Mumbai" />
<button type="submit">CHECK</button>
</form>
</div>
You redirect the user before the data loads
Move your redirect inside the callback
app.post("/", function (req, res) {
cityName = req.body.cityName;
const api_url =
"https://api.openweathermap.org/data/2.5/weather?q=" +
cityName +
"&appid=8bb235e1990db4b5ae16f92e920bad25";
https.get(api_url, function (output) {
//console.log(output);
output.on("data", function (data) {
const weatherData = JSON.parse(data);
// WEATHER
temperature = Number(weatherData.main.temp) - 273.15;
pressure = Number(weatherData.main.pressure);
console.log("Temparature:" + temperature + " °C");
console.log("Pressure:" + pressure + " hPa");
res.redirect("/results");
});
});
});
I have a chrome extension with options.js and popup.js.
I have a setting that I want the user to control both from options and popup alternatively.
In options it's straight forward:
options.html
<!DOCTYPE html>
<html>
<head><title>Random options placeholder</title></head>
<body>
<label>
<input type="checkbox" id="activate">
Active
</label>
<div id="status"></div>
<button id="save">Save</button>
<script src="options.js"></script>
</body>
</html>
options.js
function save_options() {
var isActive = document.getElementById('activate').checked;
chrome.storage.sync.set({
isActive: true
}, function() {
// Update status to let user know options were saved.
var status = document.getElementById('status');
status.textContent = 'Options saved.';
setTimeout(function() {
status.textContent = '';
}, 750);
});
}
but in popup.js I don't understand how to use the chrome.storage.sync.set
to update the same shared value (isActive).
popup.js (fail)
var isActive = document.getElementById('activate').checked;
chrome.storage.sync.set({
isActive: true
});
Any suggestions?
How to modify following index.html and dc.js code to pull data from MongoDB database using Node.js rather than csv?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="http://cdnjs.cloudflare.com/ajax/libs/dc/1.7.5/dc.css"/>
</head>
<body>
<div class="container-fluid">
<div class="row">
<h3>
<div class="dc-data-count">
<span class="filter-count"></span> selected out of <span class="total-count"></span> transitions | Reset All
</div>
</h3>
<br>
<br>
<br>
<br>
</div>
<div class="row">
<div class="col-md-6">
<div id="pie-chart"></div>
</div>
<div class="col-md-6">
<div id="bar-chart"></div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.9/crossfilter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.8/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dc/2.0.0-beta.29/dc.js"></script>
<script type="text/javascript">
d3.csv("https://raw.githubusercontent.com/dc-js/dc.js/master/web/examples/morley.csv", function (err, experiments) {
if (err) throw err;
var pieChart = dc.pieChart("#pie-chart");
var barChart = dc.barChart("#bar-chart");
var visCount = dc.dataCount(".dc-data-count");
experiments.forEach(function(x) {
x.Speed = +x.Speed;
});
var ndx = crossfilter(experiments);
var all = ndx.groupAll();
runDimension_pie = ndx.dimension(function(d) {return "run-"+d.Run;})
speedSumGroup_pie = runDimension_pie.group().reduceSum(function(d) {return d.Speed * d.Run;});
runDimension_bar = ndx.dimension(function(d) {return +d.Run;}),
speedSumGroup_bar = runDimension_bar.group().reduceSum(function(d) {return d.Speed * d.Run / 1000;});
visCount
.dimension(ndx)
.group(all);
pieChart
.width(768)
.height(480)
.slicesCap(4)
.innerRadius(100)
.dimension(runDimension_pie)
.group(speedSumGroup_pie)
.legend(dc.legend())
.on('pretransition', function(chart) {
chart.selectAll('text.pie-slice').text(function(d) {
return d.data.key + ' ' + dc.utils.printSingleValue((d.endAngle - d.startAngle) / (2*Math.PI) * 100) + '%';
})
});
barChart
.width(768)
.height(480)
.x(d3.scale.linear().domain([6,20]))
.brushOn(false)
.yAxisLabel("This is the Y Axis!")
.dimension(runDimension_bar)
.group(speedSumGroup_bar)
.on('renderlet', function(chart) {
chart.selectAll('rect').on("click", function(d) {
console.log("click!", d);
});
});;
dc.renderAll();
})
</script>
</body>
</html>
I tried creating and using the following index.js. I get JSON at http://localhost:3000/api/data but I'm not sure how to set Node up properly to pass data to current index.html and update charts accordingly.
var express = require('express');
var app = express();
var mongoose = require('mongoose');
const connection_URI = "mongodb://localhost:27017";
const connection_DB = "myDatabase";
mongoose.connect(connection_URI, {dbName: connection_DB});
var Schema = mongoose.Schema;
var connection = mongoose.connection;
var Runs = mongoose.model('Run', new Schema({
}), 'morley');
app.get('/api/data', function(req, res) {
Runs.find({}, {}, function(err, runDetails) {
if (err)
res.send(err);
res.json(runDetails);
});
});
app.listen(3000, () => {
console.log('Listening on port 3000');
});
I looked at this example as a reference, but it's a bit too complicated.
Hi I have a problem at builder level and getter, I'm creating a small application of messages that are stored on the database. I used NodeJs for that, I created a class that allows to connect to the database and manage it,
The database contains a "message" table containing the string "id" "content" "creatd_d"
Here is the class code that I call message.js:
let connection = require("../config/connection")
let moment = require("moment")
class Message{
constructor (row) {
return this.row = row
}
get content(){
return this.row.content
}
get created_d(){
return moment(this.row.created_d)
}
static create(content, cb){
connection.query('INSERT INTO message SET content = ?, created_d = ?', [content, new Date()] , (err, results) => {
if (err) throw err
cb()
});
}
static all(cb){
connection.query('SELECT * FROM message order by created_d DESC', (err, rows) =>{
if(err) throw err
cb(rows.map((row) => new Message(row))) }) }
}
module.exports = Message
the goal of getter is to declare the module "moment" that allows to change the format of date, but the getter no longer works
Does anyone know, can this come from what please? thank you in advance
Remove the return in return this.row = row in the constructor. You are breaking the constructor and not returning the instance of Message.
For more information of my problem; this is the page "index.ejs":
<!DOCTYPE html>
<html>
<head>
<title>Ma premier app de NodeJs</title>
<link rel="stylesheet" type="text/css" href="/assets/Semantic/semantic.min.css">
</head>
<body>
<div class="ui main container">
<div class="ui fixed inverted menu">
Home
</div>
<br>
<br>
<h1>Bienvenue sur ma premier page ne NodeJs</h1>
<% if (locals.flash && locals.flash.error) { %>
<div class="ui negative message">
<%= flash.error %>
</div>
<% } %>
<% if (locals.flash && locals.flash.success) { %>
<div class="ui positive message">
<%= flash.success %>
</div>
<% } %>
<form action="/" method="post" class="ui form">
<div class="field">
<label for="message">Message</label>
<textarea name="message" id="message"></textarea>
</div>
<button type="submit" class="ui red labeled submit icon button">
<i class="icon edit"></i> Send
</button>
</form>
<br>
<h3>Les Messages</h3>
<% for (message of messages){ %>
<div class="message-item">
<div class="ui message">
<%= message.content %>
<div class="ui date"><%= message.created_d %></div>
</div>
<br>
</div>
<%}%>
</div>
</body>
</html>
And this is the page serveur.js
let express = require("express")
let bodyParser = require("body-parser")
let session = require('express-session'); // Charge le middleware de session
let app = express()
//Moteur de template
app.set('view engine', 'ejs')
//Middleware
app.use('/assets', express.static("public"))
app.use(bodyParser.urlencoded({extended: false}))
app.use(bodyParser.json())
app.use(session({
secret: "monsession",
resave: false,
saveUninitialized: true,
cookie: { secure: false }
}))
app.use(require('./middlewares/flash.js'))
// Les Routes
app.get('/', (req, res) =>{
let Message = require("./models/message")
Message.all(function(messages){
res.render('pages/index', {messages: messages})
})
})
app.post('/', (req, res)=>{
// test de disponibilité de message et si il est vide !!
if (req.body.message === undefined || req.body.message === '') {
req.flash('error', "Vous n'avez pas poster votre message")
res.redirect('/')
// res.render("pages/index", {error: "Vous n'avez pas entré aucun message"})
}else{
let Message = require("./models/message")
Message.create(req.body.message, function(){
req.flash('success', "Merci !")
res.redirect('/')
})
}
})
app.listen(8080)
thaks
I am in need to a show 2 pop ups on 2 different situation.Presently I am checking a server file and storing its credentials in a localStorage.Each time when the user clicks on the extension,it should check if the localStorage is empty or not.If it is empty,then a pop up should be seen and asks for his username.this is stored in localstorage.Next time when the user clicks on the icon,the localstorage is not empty,so it should show another pop up showind a field for username with 2 buttons namely 'change settings' and 'go to website'.When the user clicks on change settings,again the popup shuuld appear asking user name.If he clicks go to website,it should navigate to a website.How can this be done?please help me.I have tried button the button is not working.And also the 2nd pop up is always shown only on reloading the extension.Please help me.
Here is my background.js
here is my updated popup.js
window.addEventListener('DOMContentLoaded', function() {
var divLoading = document.querySelector('div#loadingContainer');
var divSettings = document.querySelector('div#settingsContainer');
var divLoggedIn = document.querySelector('div#loggedInContainer');
var divChange = document.querySelector('div#settingsChange');
var user1 = divSettings.querySelector('input#user1');
var form = divSettings.querySelector('form#userinfo');
var user2 = divLoggedIn.querySelector('span#user2');
var change = divLoggedIn.querySelector('input#change');
var calpine = divLoggedIn.querySelector('input#calpine');
var user3 = divChange.querySelector('input#user3');
var form3 = divChange.querySelector('input#changeset');
var cancel = divChange.querySelector('input#emailcancel');
var user = localStorage.username;
if (user) {
// user1.value = user2.value = user;
user1.value = user2.textContent = user;
user3.value = user;
divLoggedIn.style.display = 'block';
divSettings.style.display = 'none';
divChange.style.display = 'none';
} else {
divSettings.style.display = 'block';
divChange.style.display = 'none';
divLoggedIn.style.display = 'none';
user1.focus();
user1.select();
}
divLoading.style.display = 'none';
form.addEventListener('submit', function(evt) {
evt.preventDefault();
var userStr = user1.value;
chrome.runtime.getBackgroundPage(function(bgPage) {
bgPage.login(userStr);
});
window.close();
});
form3.addEventListener('click', function() {
var userStr = user3.value;
chrome.runtime.getBackgroundPage(function(bgPage) {
bgPage.login(userStr);
});
window.close();
});
change.addEventListener('click', function(evt) {
divLoggedIn.style.display = 'none';
divSettings.style.display = 'none';
divChange.style.display = 'block';
user3.focus();
user3.select();
});
cancel.addEventListener('click', function() {
divLoggedIn.style.display = 'block';
divSettings.style.display = 'none';
divChange.style.display = 'none';
user3.focus();
user3.select();
});
calpine.addEventListener('click', function() {
chrome.tabs.create({ url: 'http://www.calpinemate.com/' });
});
});
I have made some changed as i was asked to do so.I have added a new div named divchange.
here is my updated userinfo.html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="popbak.js"></script>
</head>
<body>
<div id="loadingContainer"></div>
<div id="settingsContainer">
<b>Please Enter your Email ID/Employee Code</b>
<br />
<br />
<form id="userinfo">
<table>
<tr><td> <label for="user">Email/Employee Code:</label></td>
<td> <input type="text" id="user1" required /></td></tr>
<tr><td> <input type="submit" id="login" value="Log In" /></td></tr>
</table>
</form>
</div>
<div id="settingsChange">
<b>Please Enter your Email ID/Employee Code</b>
<br />
<br />
<table>
<tr><td><label for="user">Email/Employee Code:</label></td>
<td><input type="text" id="user3" required /></td></tr>
<tr><td><input type="button" id="emailchange" value="Change" /></td>
<td><input type="button" id="emailcancel" value="Cancel" /></td> </tr>
</table>
</div>
<div id="loggedInContainer">
<table>
<tr><td> <label for="user">Email/Employee Code:</label></td>
<!-- <input type="text" id="user2" readonly /> -->
<td><span id="user2"></span></td> </tr>
<br />
<tr><td><input type="button" id="calpine" value="Go to Calpinemate"/></td>
<td><input type="button" id="change" value="Change Settings"/></td></tr>
</table>
</div>
</body>
</html>
here is my bgpage.login()
function login(useremail){
if(!useremail)
{
alert('Please enter your Email/Employee code'); //this is not working
return;
}
var urlPrefix = 'http://www.calpinemate.com/employees/attendanceStatus/';
var urlSuffix = '/3';
var req1 = new XMLHttpRequest();
req1.addEventListener("readystatechange", function() {
if (req1.readyState == 4) {
if (req1.status == 200) {
var item=req1.responseText;
if(item==1){
localStorage.username=useremail;
updateIcon();
}
else
{
alert('Please enter a valid Email/employee code');
updateIcon();
}
}
else {
alert("ERROR: status code " + req1.status);
}
}
});
var url = urlPrefix + encodeURIComponent(useremail) + urlSuffix;
req1.open("GET", url);
req1.send(null);
}
Here is my background.js
var myNotificationID = null;
var oldChromeVersion = !chrome.runtime;
setInterval(function() {
updateIcon();
}, 1000);
function getGmailUrl() {
return "http://calpinemate.com/";
}
function isGmailUrl(url) {
return url.indexOf(getGmailUrl()) == 0;
}
function onInit() {
updateIcon();
if (!oldChromeVersion) {
chrome.alarms.create('watchdog',{periodInMinutes:5,delayInMinutes: 0});
}
}
function onAlarm(alarm) {
if (alarm && alarm.name == 'watchdog') {
onWatchdog();
}
else {
updateIcon();
}
function onWatchdog() {
chrome.alarms.get('refresh', function(alarm) {
if (alarm) {
console.log('Refresh alarm exists. Yay.');
}
else {
updateIcon();
}
});
}
if (oldChromeVersion) {
updateIcon();
onInit();
}
else {
chrome.runtime.onInstalled.addListener(onInit);
chrome.alarms.onAlarm.addListener(onAlarm);
}
function updateIcon(){
if(localStorage.username){
var urlPrefix = 'http://www.calpinemate.com/employees/attendanceStatus/';
var urlSuffix = '/2';
var req = new XMLHttpRequest();
req.addEventListener("readystatechange", function() {
if (req.readyState == 4) {
if (req.status == 200) {
var item=req.responseText;
if(item==1){
chrome.browserAction.setIcon({path:"calpine_logged_in.png"});
chrome.browserAction.setBadgeBackgroundColor({color:[190, 190, 190, 230]});
chrome.browserAction.setBadgeText({text:""});
chrome.notifications.clear('id1', function(){});
}
else{
chrome.browserAction.setIcon({path:"calpine_not_logged_in.png"});
chrome.browserAction.setBadgeBackgroundColor({color:[190, 190, 190, 230]});
chrome.browserAction.setBadgeText({text:""});
chrome.notifications.create(
'id1',{
type: 'basic',
iconUrl: '/calpine_not_logged_in.png',
title: 'Warning : Attendance',
message: 'Please mark your Attendance !',
buttons: [{ title: 'Mark',
iconUrl: '/tick.jpg'
},{ title: 'Ignore',
iconUrl: '/cross.jpg'}],
priority: 0},
function(id) { myNotificationID = id;}
);
}
}
else {
alert("ERROR: status code " + req.status);
}
}
});
var url = urlPrefix + encodeURIComponent(localStorage.username) + urlSuffix;
req.open("GET", url);
req.send(null);
}
}
onInit();
First of all, the localStorage of the background-page and that of the popup are not the same objects. Besides, each time the popup is shown, it is loaded anew, thus the localStorage is empty.
UPDATE: Thx to rsanchez's comment, I correct my mistake: the popup shares the localStorage object of the extension (which is the same as the one of the background-page).
You should use the localStorage of the background-page. (Keep in mind this works only because you have a persistent background-page !)
The simplest (and most reliable) way is to have a single popup with two different divs (one for entering credentials and one for logging in) and display only one at a time.
E.g.:
1) Remove any chrome.browserAction.onClicked... listener from the background-page (it won't hurt leaving it there as it will never be triggered, but it will confuse you in the future).
2) Declare a popup in your manifest (if you don't have already done do):
<pre>
...
"browser_action": {
...
"default_popup": "popup.html"
},
...
</pre>
3). Create a file named popup.html with the following code:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="popup.js"></script>
</head>
<body>
<div id="loadingContainer"><h3>Loading...</h3></div>
<div id="settingsContainer" style="display:none;">
<b>Enter your Email ID/Employee Code</b>
<br />
<br />
<form id="userinfo">
<label for="user">Email/Employee Code:</label>
<input type="text" id="user1" required />
<input type="submit" id="login" value="Log In" />
</form>
</div>
<div id="loggedInContainer" style="display:none;">
<label for="user">Email/Employee Code:</label>
<!--<input type="text" id="user2" readonly />-->
<span id="user2"></span>
<br />
<input type="button" id="calpine" value="Go to Calpinemate"/>
<input type="button" id="change" value="Change Settings"/>
</div>
</body>
</html>
</pre>
4) Create a file named popup.js with the following code:
window.addEventListener('DOMContentLoaded', function() {
/* Container divs */
var divLoading = document.querySelector('div#loadingContainer');
var divSettings = document.querySelector('div#settingsContainer');
var divLoggedIn = document.querySelector('div#loggedInContainer');
/* Settings-container fields */
var user1 = divSettings.querySelector('input#user1');
var form = divSettings.querySelector('form#userinfo');
/* LoggedIn-container fields */
//var user2 = divLoggedIn.querySelector('input#user2');
var user2 = divLoggedIn.querySelector('span#user2');
var change = divLoggedIn.querySelector('input#change');
var calpine = divLoggedIn.querySelector('input#calpine');
/* Query the extension's localStorage
* in order to decide which DIV to show */
var user = localStorage.username;
if (user) {
/* 'Username' is set: Show the LoggedIn-container
* (after updating the value of the (readonly) '#user' field) */
//user1.value = user2.value = user;
user1.value = user2.textContent = user;
divLoggedIn.style.display = 'block';
} else {
/* 'Username' is not set: Show the Settings-container */
divSettings.style.display = 'block';
user1.focus();
user1.select();
}
divLoading.style.display = 'none';
/* Listener for '#userinfo' form */
form.addEventListener('submit', function(evt) {
evt.preventDefault();
var userStr = user1.value;
chrome.runtime.getBackgroundPage(function(bgPage) {
bgPage.login(userStr);
});
window.close();
});
/* Listener for '#change' button */
change.addEventListener('click', function(evt) {
divLoggedIn.style.display = 'none';
divSettings.style.display = 'block';
user1.focus();
user1.select();
});
/* Listener for '#calpine' button */
calpine.addEventListener('click', function() {
chrome.tabs.create({ url: 'https://your.domain.goes/here' });
});
});