How to get value from firebase database show in p element - javascript

I'm trying to create chat app using firebase database.
I have html:
<input type="text" name="txt" id="txt">
<button type="submit" id="btn-send" onclick="addElement()">SEND</button>
<p id="list-message"></p>
and javascript :
var rootRef = firebase.database();
var message = rootRef.ref().child('/message');
function addElement() {
var x = document.getElementById('txt').value;
var node = document.createElement("li");
var text = document.createTextNode(x);
node.appendChild(text);
document.getElementById('list-message').appendChild(node);
message.push().set({
Message: $("#txt").val()
});
}
Screenshot of my Firebase data
How can I retrieve all the data and show as a list in <p id="list-message"></p>?

Add a data listener which looks out for changes in the message node then update <p id="list-message"></p>.
message.on('child_added', function(snapshot) {
var msg = snapshot.val();
var msgDiv = document.createElement("div");
msgDiv.textContent = msg.Message;
document.getElementById("list-message").appendChild(msgDiv);
});
Refer to this codelab for more on how to build a chat app: https://codelabs.developers.google.com/codelabs/cloud-firebase-chat/.

Related

how to push img file and url input with js

I'm trying to add a new item on an array that displays in a container on HTML. It's supposed to get an image file and an url from input, check the selected option and push each one to its specified array
Here is the relevant html:
<input type="file" name="comic-cover" id="comic-cover" required />
<input type="url" name="comic-url" id="comic-url" placeholder="url" required />
<select name="publisher-list" id="publisher">
<option value="publisher" disabled>Publisher</option>
<option value="dc">DC Comics</option>
<option value="marvel">Marvel</option>
</select>
<button type="submit" class="btn-submit">Add</button>
<h2 class="comic-publisher">DC Comics</h2>
<div class="dc" id="block-dc">
</div>
<h2 class="comic-publisher">Marvel</h2>
<div class="marvel" id="block-marvel">
</div>
and the js:
var comicCovers = ["imgs/Dark Knights of Steel-000.jpg", "imgs/Hawkeye-000.jpg"]
var trailers = ["https://www.youtube.com/watch?v=WspmgrmEgn4", "https://www.youtube.com/watch?v=ssj0P0uY08U"]
var publishers = [0, 1];
var i = 0;
var blockDC = document.querySelector("#block-dc");
var blockMarvel = document.querySelector("#block-marvel");
render()
var publisher = document.querySelector("select").value;
document.querySelector("select") = function renderPublisher() {
publisher = document.querySelector("select").value;
return publisher;
}
// add new comics to the list //
document.querySelector(".btn-submit") = function addOnList() {
var newCover = document.querySelector("#comic-cover");
var newTrailer = document.querySelector("#comic-url");
if (newCover.endsWith(".jpg") & newTrailer.startsWith("https://")) {
if (publisher == "dc") {
publisher.push(0);
} else {
publisher.push(1)
}
comicCovers.push(newCover.value);
trailers.push(newTrailer.value);
newCover.value = "";
newTrailer.value = "";
render()
}
}
function render() {
for (i; i < comicCovers.length; i++) {
// creates the comic covers using js var //
var comicCover = document.createElement("img");
comicCover.setAttribute("src", `${comicCovers[i]}`);
// creates trailer button //
var trailerButton = document.createElement("button");
// //
var container = document.createElement("div");
container.setAttribute("class", "container");
container.appendChild(trailerButton);
container.appendChild(comicCover);
blockDC.appendChild(container);
trailerButton.appendChild(document.createTextNode("Trailer"));
trailerButton.setAttribute("class", "trailer-button");
trailerButton.setAttribute("onclick", `openTrailer("${trailers[i]}")`);
if (publishers[i] == 0) {
blockDC.appendChild(container);
} else {
blockMarvel.appendChild(container);
}
}
}
I tried to use if (newCover != "" & newTrailer != "") and even changed the input type from file to url. What am I doing wrong?
You're tring to push values inside the variable called publisher which is just a string and not an array.
var publisher = document.querySelector("select").value;
publisher.push(0);
You're assigning a function to an html element by writing:
document.querySelector("select") = function renderPublisher() {
publisher = document.querySelector("select").value;
return publisher;
}
which is not correct.
Also The variables newCover and newTrailer are not strings.
var newCover = document.querySelector("#comic-cover");
var newTrailer = document.querySelector("#comic-url");
so you can't use the methods startsWith and endsWith for them, you have to access the elements' value instead. In order to get the name of the selected file you need to use the input tag's files attribute which returns an array of the selected files, we want the first file so we'll get the first item's name attribute.
var newCover = document.querySelector("#comic-cover").value;
var newTrailer = document.querySelector("#comic-url")?.files[0]?.name;
Overall first you need to grab the values provided inside the inputs, then push them inside the array related to the selected block(Marvel or DC), then you simply need to create the img, video and button tags and append them as a child to the selected block.
Url and file type validation should be handled also on both server and client side and it's gotta be much more than just checking if the fileName ends with ".jpg" or the url starts with "https://".
You need to store the uploaded image and video somewhere on the server. In order to do so, you'll have to attach an eventListener to the input tags so that whenever a file is selected, you'll send an upload request to the server, there you'll check if the file is valid and if so, you'll store the file somewhere on the server, then you'll pass the url of the uploaded photo/video as src to the img/video tags.
const publishers = {
dc: {
comicCovers: [],
trailers: []
},
marvel: {
comicCovers: [],
trailers: []
}
}
const blockDC = document.querySelector("#block-dc");
const blockMarvel = document.querySelector("#block-marvel");
const blocksDivs = {
dc: blockDC,
marvel: blockMarvel
};
const addButton = document.querySelector(".btn-submit");
// add new comics to the list //
addButton.addEventListener("click", () => {
const publisher = document.querySelector("#publisher").value;
const newCoverFileName = document.querySelector("#comic-cover")?.files[0]?.name;
const newTrailerUrl = document.querySelector("#comic-url").value;
if (newCoverFileName?.endsWith(".jpg") && newTrailerUrl?.startsWith("https://")) {
publishers[publisher].comicCovers.push(newCoverFileName);
publishers[publisher].trailers.push(newTrailerUrl);
var container = document.createElement("div");
var coverImg = document.createElement("img");
var playTrailerButton = document.createElement("button");
playTrailerButton.innerHTML = "play trailer"
coverImg.src = "http://yourserveraddress/imgs/" + newCoverFileName;
//test photo
coverImg.src = "https://picsum.photos/200/300"
container.appendChild(coverImg);
container.appendChild(playTrailerButton);
blocksDivs[publisher].appendChild(container);
playTrailerButton.setAttribute("class", "trailer-button");
playTrailerButton.addEventListener("click", () => {
var videoExists = document.getElementById(publishers[publisher].trailers.length)
if (!videoExists) {
var video = document.createElement('video');
video.setAttribute("id", publishers[publisher].trailers.length)
video.style.backgroundColor = "aliceblue"
video.setAttribute("src", newTrailerUrl);
video.setAttribute("width", "200")
video.setAttribute("height", "200")
container.appendChild(video);
playTrailerButton.innerHTML = "close Trailer"
} else {
container.removeChild(videoExists)
playTrailerButton.innerHTML = "play Trailer"
}
})
}
})
<input type="file" name="comic-cover" id="comic-cover" required />
<input type="url" name="comic-url" id="comic-url" placeholder="url" required />
<select name="publisher-list" id="publisher">
<option value="publisher" disabled>Publisher</option>
<option value="dc">DC Comics</option>
<option value="marvel">Marvel</option>
</select>
<button type="submit" class="btn-submit">Add</button>
<h2 class="comic-publisher">DC Comics</h2>
<div class="dc" id="block-dc">
</div>
<h2 class="comic-publisher">Marvel</h2>
<div class="marvel" id="block-marvel">
</div>

onload Function and Document Ready function in JS creating conflict

So I'm working on a section of my Website which has a TODO List built in not I want the data to load just like other data that are loading alongside the page. I tried having onload in Body Tag in my HTML and I had also tried to $(document).ready(function(){}) as well however neither of them seemed to work nor was I getting any errors in my console. But the function is working as it is also link to another function which runs on click of a button which I don't want to keep happening. I want it to be seamless. Is there any reason why this might not be working.
Thanks for any help in advance.
My HTML and Javascript Code:
function create() {
unfinished_task_container = document.getElementById("main_container");
unfinished_task_container.innerHTML = "";
var user = firebase.auth().currentUser;
var uid;
if (user != null) {
uid = user.uid;
}
task_array = [];
firebase
.database()
.ref("/Users/" + uid + "/todo/")
.once("value", (snapshot) => {
snapshot.forEach((childSnapshot) => {
var childKey = childSnapshot.key;
var childData = childSnapshot.val();
task_array.push(Object.values(childData));
});
for (var i = 0; i < task_array.length; i++) {
task_key = task_array[i][0];
task_title = task_array[i][1];
//Data
task_container = document.createElement("div");
task_container.setAttribute("class", "task_container");
task_container.setAttribute("data-key", task_key);
task_data = document.createElement("div");
task_data.setAttribute("id", "task_data");
title = document.createElement("p");
title.setAttribute("id", "task_title");
title.setAttribute("contenteditable", false);
title.innerHTML = task_title;
//Tools
task_tool = document.createElement("div");
task_tool.setAttribute("id", "task_tool");
task_done_button = document.createElement("button");
task_done_button.setAttribute("id", "task_done_button");
task_done_button.setAttribute(
"onclick",
"task_done(this.parentElement.parentElement, this.parentElement)"
);
task_done_button.setAttribute("onclick", "task_done()");
fa_done = document.createElement("i");
fa_done.setAttribute("class", "fa fa-check");
unfinished_task_container.append(task_container);
task_container.append(task_data);
task_data.append(title);
task_container.append(task_tool);
task_tool.append(task_done_button);
task_done_button.append(fa_done);
}
});
}
<body onload="create();">
<div class="dentistToDo">
<p class="divlable">Your Personal To Do List</p>
<input id="input_box" placeholder="What needs to be done?" />
<button id="input_button" onclick="add_task()">Add Task</button>
<div class="container" id="main_container">
<!-- DIV for TODO List -->
</div>
</div>

Why doesn't my sheet add new rows of data, after adding formulas to the spreadsheet?

I have created a web app to track the working hours of employees at my company, the web app is simple, it just asks employees to enter their entry time when they arrive to work and the time when they leave. I have them enter first, their ID number and a password, then they just fill out the date, the time at which they arrived/left and I added a string for any other details they would like to add. Bringing this data to a google spreadsheet, as seen in the picture. What I want to do is add a VLOOKUP function, in the column that says "Name", that will search for the employees name by looking up their ID number in a data base, the problem is once I add the formula to the column labeled "Name", the spreadsheet stops receiving new data from the web app. Here's a link to a copy of the sheet (https://docs.google.com/spreadsheets/d/1fjpKRi3k0VQ8MOoa5ruCZurXcz6vmVsQt2g3NbELSJA/edit#gid=1409321990) and an here is the simplified the JavaScript and HTML code.
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('Form');
}
function AddRecord(DateEntry, username, ArrivalTime, ExitTime ) {
// get spreadsheet details
var url = 'https://docs.google.com/spreadsheets/d/1fjpKRi3k0VQ8MOoa5ruCZurXcz6vmVsQt2g3NbELSJA/edit#gid=';
//Paste URL of GOOGLE SHEET
var ss1= SpreadsheetApp.openByUrl(url);
var webAppSheet1 = ss1.getSheetByName('ReceivedData');
const Lrow = webAppSheet1.getLastRow();
const sep_col = 2;
const data = [DateEntry, username, ArrivalTime, ExitTime, new Date()];
const data1 = data.slice(0,sep_col);
const data2 = data.slice(sep_col,data.length);
const start_col = 1;
const space_col = 1;
webAppSheet1.getRange(Lrow+1,start_col, 1, data1.length).setValues([data1]);
webAppSheet1.getRange(Lrow+1,start_col+data1.length + space_col, 1, data2.length).setValues([data2]);
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<title>Time Tracking</title>
<script>
function AddRow()
{
var DateEntry = document.getElementById("DateEntry").value;
var username = document.getElementById("username").value;
var ArrivalTime = document.getElementById("ArrivalTime").value;
var ExitTime = document.getElementById("ExitTime").value;
google.script.run.AddRecord(DateEntry, username, ArrivalTime, ExitTime);
document.getElementById("DateEntry").value = '';
document.getElementById("username").value = '';
document.getElementById("ArrivalTime").value = '';
document.getElementById("ExitTime").value = '';
}
</script>
</head>
<body>
<div class="content">
<div class="header">
<h2>Time Tracking</h2>
</div>
<div>
<label>ID</label><br>
<input class="field" id="username" type="text">
</div>
<div>
<label>Date</label><br>
<input class="field" type="date" id="DateEntry" />
</div>
<div >
<label>Arrival Time</label><br>
<input class="time" type="time" id="ArrivalTime" /><br>
</div>
<div >
<label>Exit Time</label><br>
<input class="time" type="time" id="ExitTime" /><br>
</div>
<div class="btn">
<button type="button" value="Add" onclick="AddRow()">Send</button>
</div>
</div>
</body>
</html>
Explanation / Issue:
The issue is that you are using an arrayformula which expands until the last available row in the sheet.
However, your goal is to append a new row everytime after the last row with content.
Therefore, by using getLastRow you are getting the wrong row.
Instead of using arrayformula use a single vlookup formula and
take advantage of template literals in order to dynamically
change the vlookup value:
=IFERROR(VLOOKUP(B${Lrow+1};DataBase!A2:B250;2;0);"")
In this way you don't need two different arrays (data1 and data2) because the data can be pasted directly into the sheet:
const vlp_form = `=IFERROR(VLOOKUP(B${Lrow+1};DataBase!A2:B250;2;0);"")`;
const data = [DateEntry, username ,vlp_form, ArrivalTime, ExitTime, new Date()];
webAppSheet1.getRange(Lrow+1,1, 1, data.length).setValues([data]);
I changed your formula to match the DataBase sheet from BBDD to DataBase. Change that back (in the script) if you are using the other sheet name.
Solution:
Modify only AddRecord as follows:
function AddRecord(DateEntry, username, ArrivalTime, ExitTime ) {
// get spreadsheet details
const url = 'https://docs.google.com/spreadsheets/d/1fjpKRi3k0VQ8MOoa5ruCZurXcz6vmVsQt2g3NbELSJA/edit#gid=';
//Paste URL of GOOGLE SHEET
const ss1= SpreadsheetApp.openByUrl(url);
const webAppSheet1 = ss1.getSheetByName('ReceivedData');
const Lrow = webAppSheet1.getLastRow();
const vlp_form = `=IFERROR(VLOOKUP(B${Lrow+1};DataBase!A2:B250;2;0);"")`;
const data = [DateEntry, username ,vlp_form, ArrivalTime, ExitTime, new Date()];
webAppSheet1.getRange(Lrow+1,1, 1, data.length).setValues([data]);
}
Be careful:
In order for the changes to take effect you need to re-deploy your
webApp (either new deployment in the new script editor) or if you are
using the older editor, deploy the web app again by selecting project
version new and click on update.
Also don't forget to save the script changes.

create the variable link as a hyperlink javascript

create a hyperlink with the variable link
<html>
<body>
<center><h1> retrive data</h1></center>
<h1 id="head1"> </h1>
<input type="text" placeholder="enter your unique id" id="pass"/>
<input type = "button" value = "submit" id="but" onclick="myfunction();"/>
<script>
var pass;
function myfunction()
{
pass = document.getElementById("pass").value;
document.writeln(pass);
document.writeln("<br>");
document.writeln("<br>");
document.writeln("<br>");
document.writeln("<br>");
var passwordToLookFor = pass;
var ref = firebase.database().ref("users");
var query = ref.orderByChild("password").equalTo(passwordToLookFor);
query.once("value").then(function(snapshot) {
snapshot.forEach(function(child) { // loop over the results
console.log(child.key);
console.log(child.val().user_name);
var link = child.val().user_name;
document.writeln(link);
});
});
}
</script>
</body></html>
i want to create the value of link as a hyperlink
i want the hyperlink to be created once when the function is called
Are you just looking for how to make it an anchor tag?
<script>
var pass;
function myfunction()
{
...
var link = child.val().user_name;
document.writeln("<a href='"+link+"' target='_blank'>"+link+"</a>");
});
});
}
</script>
</body></html>
You can create an a dom element like this:
let link_el = document.createElement('a')
link_el.href = link // assuming link holds the value of the href you want
Then insert it into the dom wherever you want.
If I understand correctly and the link variable contains the actual address you want to navigate to, then this will work. First simply set an ID on the div you want to populate with links:
<div id="target-div"></div>
Then populate it like so (I just created an array for demo purposes, but this would be your snapshot.forEach:
var links = ['link1', 'link2', 'link3']
var targetDiv = document.getElementById("target-div");
links.forEach(function(link) {
var anchor = document.createElement('a');
anchor.href = link;
anchor.innerText = link;
targetDiv.appendChild(anchor);
var br = document.createElement('br');
targetDiv.appendChild(br);
});
Demo: https://jsfiddle.net/csnuh7rd/2/

Only Show Messages with RoomID in Firebase

I am trying to create FireBase chat with separate rooms and only display messages from that room. How can I only show messages with roomid = somenumber (currently set to 4)
Data might look like this:
This is the code following the firebase documentation.
<body>
<!-- CHAT MARKUP -->
<div class="example-chat l-demo-container">
<header>Firebase Chat Demo</header>
<div class='example-chat-toolbar'>
<label for="nameInput">Username:</label>
<input type='text' id='nameInput' placeholder='enter a username...'>
</div>
<ul id='example-messages' class="example-chat-messages"></ul>
<footer>
<input type='text' id='messageInput' placeholder='Type a message...'>
</footer>
</div>
<!-- CHAT JAVACRIPT -->
<script>
// CREATE A REFERENCE TO FIREBASE
var messagesRef = new Firebase('https://blistering-fire-1740.firebaseio.com/');
// REGISTER DOM ELEMENTS
var messageField = $('#messageInput');
var nameField = $('#nameInput');
var messageList = $('#example-messages');
// LISTEN FOR KEYPRESS EVENT
messageField.keypress(function (e) {
if (e.keyCode == 13) {
//FIELD VALUES
var username = nameField.val();
var message = messageField.val();
//SAVE DATA TO FIREBASE AND EMPTY FIELD
messagesRef.push({name:username, text:message, roomid:4});
messageField.val('');
}
});
// Add a callback that is triggered for each chat message.
messagesRef.limitToLast(10).on('child_added', function (snapshot) {
//GET DATA
var data = snapshot.val();
var username = data.name || "anonymous";
var message = data.text;
//CREATE ELEMENTS MESSAGE & SANITIZE TEXT
var messageElement = $("<li>");
var nameElement = $("<strong class='example-chat-username'></strong>")
nameElement.text(username);
messageElement.text(message).prepend(nameElement);
//ADD MESSAGE
messageList.append(messageElement)
//SCROLL TO BOTTOM OF MESSAGE LIST
messageList[0].scrollTop = messageList[0].scrollHeight;
});
</script>
</body>
firebase doc
Dan's answer will work, but it means that you're downloading all the chat messages. User's on smaller data plans will appreciate it if you don't download data that is not needed:
var roomMessages = messagesRef.orderByChild('roomid').equalTo(4);
roomMessages.limitToLast(10).on('child_added', function (snapshot) {
//GET DATA
var data = snapshot.val();
You'll need an index on roomid, as described here.
Simply filter out messages that don't belong to that room, when you add them to the DOM.
// Add a callback that is triggered for each chat message.
messagesRef.limitToLast(10).on('child_added', function (snapshot) {
var data = snapshot.val();
// break out of the function early if this message does not
// belong in this room.
if(data.roomId !== 4) return;
var username = data.name || "anonymous";
var message = data.text;
// ...
});
You probably don't want to hardcode the roomID into your code. It would make sense to store the current room ID in a variable somewhere, then check against that instead.
var currentRoomId = getRoomId(); // get from URL, or from Firebase
// ...
if(data.roomId !== currentRoomId) return;

Categories