On my page I have two buttons, button 1 and button 2. Under those buttons I want to get the value of a javascript per button, so that I can switch the javascript per button. I am a beginner and I can really use some help for this :) I have tried everything that is possible at my knowledge level. I searched on Stack but didn't find anything close to what I needed. Hopefully you can help me.
EDIT: Ive updated my snippet. Now one button is working en de graph is coming. When i push the second button nothing happens.
function myFunction1() {
var x = document.getElementById('3d-graph');
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
function myFunction2() {
var x = document.getElementById('graph');
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
var elem = document.getElementById("graph");
var drivertwo = neo4j.v1.driver("bolt+routing://90bfd895.databases.neo4j.io", neo4j.v1.auth.basic("got", "got"),{encrypted: true});
var sessiontwo = drivertwo.session();
var starttwo = new Date()
sessiontwo
.run('MATCH (n)-[r]->(m) RETURN { id: id(n), label:head(labels(n)), community:n.title, caption:n.title, size:n.title } as source, { id: id(m), label:head(labels(m)), community:n.title, caption:m.title, size:m.title } as target, { weight:r.title, type:type(r), community:case when n.title < m.title then n.title else m.title end} as rel LIMIT $limit', {limit: 1000})
.then(function (result) {
var nodes = {}
var links = result.records.map(r => {
var source = r.get('source');source.id = source.id.toNumber();
nodes[source.id] = source;
var target = r.get('target');target.id = target.id.toNumber();
nodes[target.id] = target;
var rel = r.get('rel'); if (rel.weight) { rel.weight = rel.weight.toNumber(); }
return Object.assign({source:source.id,target:target.id}, rel);
});
sessiontwo.close();
console.log(links.length+" links loaded in "+(new Date()-starttwo)+" ms.")
var gData = { nodes: Object.values(nodes), links: links}
var Graph = ForceGraph()(elem)
.graphData(gData)
.nodeAutoColorBy('label')
.linkDirectionalParticles('weight')
.linkDirectionalParticleSpeed(0.001)
.nodeLabel(node => `${node.label}: ${node.caption}`)
.onNodeHover(node => elem.style.cursor = node ? 'pointer' : null);
});
var elem = document.getElementById('3d-graph');
var driver = neo4j.v1.driver("bolt+routing://90bfd895.databases.neo4j.io", neo4j.v1.auth.basic("got", "got"),{encrypted: true});
var session = driver.session();
var start = new Date()
session
.run('MATCH (n)-[r]->(m) RETURN { id: id(n), label:head(labels(n)), community:n.title, caption:n.title, size:n.title } as source, { id: id(m), label:head(labels(m)), community:n.title, caption:m.title, size:m.title } as target, { weight:r.title, type:type(r), community:case when n.title < m.title then n.title else m.title end} as rel LIMIT $limit', {limit: 1000})
.then(function (result) {
var nodes = {}
var links = result.records.map(r => {
var source = r.get('source');source.id = source.id.toNumber();
nodes[source.id] = source;
var target = r.get('target');target.id = target.id.toNumber();
nodes[target.id] = target;
var rel = r.get('rel'); if (rel.weight) { rel.weight = rel.weight.toNumber(); }
return Object.assign({source:source.id,target:target.id}, rel);
});
session.close();
console.log(links.length+" links loaded in "+(new Date()-start)+" ms.")
var gData = { nodes: Object.values(nodes), links: links}
var Graph = ForceGraph3D()(elem)
.graphData(gData)
.nodeAutoColorBy('label')
.linkDirectionalParticles('weight')
.linkDirectionalParticleSpeed(0.001)
.nodeLabel(node => `${node.label}: ${node.caption}`)
.onNodeHover(node => elem.style.cursor = node ? 'pointer' : null);
});
<script src="https://unpkg.com/force-graph"></script>
<script src="https://unpkg.com/3d-force-graph"></script>
<script src="https://cdn.rawgit.com/neo4j/neo4j-javascript-driver/1.2/lib/browser/neo4j-web.min.js"></script>
<button onclick="myFunction1()">Try it</button>
<button onclick="myFunction2()">Try it</button>
<p id="graph"></p>
<p id="3d-graph"></p>
The buttons work correctly. The reason you don't see one of the images is that you declared var elem twice.
If you replace elem by elem2 in var elem = document.getElementById('3d-graph'); and in the code below that, then it will be fixed.
But it would be better to wrap the image loading in a separate function, like this:
function loadImage(elementId) {
var elem = document.getElementById(elementId);
...
...
}
and then call this function twice:
loadImage('graph');
loadImage('3d-graph');
try this and let me know if there are other problems:
<button id='1' onclick="myFunction(this)">button 1</button>
<button id='2' onclick="myFunction(this)">button 2</button>
<p id="graph"></p>
<p id="3d-graph"></p>
Passing "this" to myFunction, the "elem", will be the button you click.
Remember that is better to use .addEventListener('click', function(ev){}) instead "onclick=function()"
function myFunction(elem) {
document.getElementById("graph").innerHTML = "ID:" + elem.id;
document.getElementById("3d-graph").innerHTML = "ID:" + elem.id;
}
I don't know what the code below what the rest of the code will do, and if it works, but i see a lot of duplications. If you can, try to put all the neo4j call inside a function, so that you can use this every time you need it.
Related
I created a todo app to add and remove tasks on the page.
however i would like to keep todo results when browser refreshed .
Is that possible to make this like storing data on db or any storage to save these results?
any idea to make this to save data ??
Now I posted the complete code hereee! because i cant posted code here before
let menu = document.querySelector(".bs");
let btn1 = document.querySelector(".btn");
let btn2 = document.querySelector(".btn3");
let irp = document.querySelector(".date");
let inp = document.querySelector(".input");
let bsd = document.querySelector(".sss");
let brs = document.querySelector(".marker");
let addBr = () => {
btn1.addEventListener("click", addBr);
let br = document.createElement("DIV");
let dd = document.createElement("H1");
dd.innerHTML = (inp.value);
br.className = "red";
var bn = document.createElement("H1");
bn.innerHTML = (irp.value);
menu.appendChild(br);
br.appendChild(dd);
br.appendChild(bn);
if( inp.value == "") {
br.remove();
}
else {
menu.appendChild(br);
}
if( irp.value == "") {
dd.innerHTML = "Albenis";
}
else {
menu.appendChild(br);
}
let ttt = document.createElement("BUTTON");
ttt.className = "marker";
ttt.innerHTML = "Remove";
br.appendChild(ttt);
// This is the important change. Part of creating the .ttt element
// is setting up its event listeners!
ttt.addEventListener('click', () => br.remove());
};
btn1.addEventListener("click", addBr);
// Call `addBr` once to add the initial element
addBr();
<html>
<body>
<div class="bs">
<input type="text" class="input">
<input type="date" class="date">
<button class="btn">
Add
</button>
</div>
</body>
</html>
TL;DR: use localStorage to read the items at page load and write the items when they change, like in the final version
To keep your todo entries, you need to store it in a Database. This can be either a local database in the website like localStorage. Or you need to build a backend which is connected to a Database and send and load the Data from there.
localStorage example:
const items = [{ name: "My Todo" }, { name: "My Todo 2" }];
const setItems = () => {
localStorage.setItem("items", JSON.stringify(items));
};
const getItems = () => {
return JSON.parse(localStorage.getItem("items"));
};
Including your code:
const getItems = () => {
return JSON.parse(localStorage.getItem("items"));
};
const items = getItems() || [];
const setItems = () => {
localStorage.setItem("items", JSON.stringify(items));
};
let addBr = (item) => {
let br = document.createElement("DIV");
let dd = document.createElement("H1");
dd.innerHTML = (item ? item.name : inp.value);
br.className = "red";
var bn = document.createElement("H1");
bn.innerHTML = (item ? item.name : irp.value);
if (!item) {
items.push({ name: inp.value });
setItems();
}
menu.appendChild(br);
br.appendChild(dd);
br.appendChild(bn);
if( inp.value == "") {
br.remove();
}
else {
menu.appendChild(br);
}
if( irp.value == "") {
dd.innerHTML = "Albenis";
}
else {
menu.appendChild(br);
}
let ttt = document.createElement("BUTTON");
ttt.className = "marker";
ttt.innerHTML = "Remove";
br.appendChild(ttt);
// This is the important change. Part of creating the .ttt element
// is setting up its event listeners!
ttt.addEventListener('click', () => br.remove());
};
for (const item of items) {
addBr(item);
}
btn1.addEventListener("click", () => addBr());
I have a web app with one drop down list and 2 buttons. The drop down list get values from a sheet. The buttons write back in the sheet. The script I have works fine with that:
<script>
$(function() {
$('#txt1').val('');
google.script.run
.withSuccessHandler(updateSelect)
.getSelectOptions();
});
function updateSelect(opt)
{
var select = document.getElementById("sel1");
select.options.length = 0;
for(var i=0;i<opt.length;i++)
{
select.options[i] = new Option(opt[i],opt[i]);
}
}
function listS() {
const selectElem = document.getElementById('sel1')
const index = selectElem.selectedIndex;
if (index > -1) {
const e = document.getElementById("sel1");
const value = e.options[index].value;
const body = { index: index, value: value };
google.script.run.withSuccessHandler(yourCallBack).yourServerSideFunc(body);
}
}
document.getElementById("but1").addEventListener("click",listS);
function yourCallBack(response) {
}
</script>
In Java script:
function getSelectOptions()
{
var ss=SpreadsheetApp.openById('1onuWoUKh1XmvEAmKktwJekD782BFIru-MDA0omqzHjw');
var sh=ss.getSheetByName('Database');
var rg=sh.getRange(2,1,sh.getLastRow()-1,8);
var vA=rg.getValues();
var useremail = Session.getActiveUser().getEmail();
var opt=[];
for(var i=0;i<vA.length;i++)
{
if(vA[i][1] == "Pending Approval"){
if(vA[i][7]+"#xxx.com" == useremail || vA[i][7]+"#xxx.com" == useremail) {
opt.push(vA[i][3]+" REQ ID: "+vA[i][0]);
}
}
};
if (opt.length == 0) {opt.push("You do not have pending requests")};
return opt;
}
function doGet() {
var output = HtmlService.createHtmlOutputFromFile('list');
return output;
}
function yourServerSideFunc(body) {
var value = body["value"];
var ss = SpreadsheetApp.openById('1onuWoUKh1XmvEAmKktwJekD782BFIru-MDA0omqzHjw');
var sh = ss.getSheetByName('Database');
var rg=sh.getRange(1,1,sh.getLastRow()-1,4);
var vA=rg.getValues();
var str = "Approved";
for(var i=0;i<vA.length;i++)
{
if(vA[i][3]+" REQ ID: "+vA[i][0] == value) {
sh.getRange(i+1, 2).setValue(str);
}
};
return ContentService.createTextOutput(JSON.stringify({message: "ok"})).setMimeType(ContentService.MimeType.JSON);
Now I am trying to regenerate the drop down list values after the button is clicked. I tried to add
var output = HtmlService.createHtmlOutputFromFile('list');
return output;
in yourServerSideFunc(body) function to regenerate the HTML but does not work. I have tried to force a HTML refresh, but also did not work.
How can I easily re-trigger the generation of the drop down list items? Worst case scenario it is ok to refresh the whole page, but it should be simple to regenerate the drop down list since I have already the code for it.
I ended up with this work around.
function listS() {
const selectElem = document.getElementById('sel1')
const index = selectElem.selectedIndex;
if (index > -1) {
const e = document.getElementById("sel1");
const value = e.options[index].value;
const body = { index: index, value: value };
google.script.run.withSuccessHandler(yourCallBack).yourServerSideFunc(body);
//ADDED:
var select = document.getElementById("sel1");
select.options[index] = new Option("Approved! Please refresh","Approved! Please refresh");
selectElem.selectedIndex = index;
}
}
It does not really meet the original goal to refresh the list from the sheet. It would be great if someone else posted a solution to call the server function. I tried to add google.script.run.doGet() and similar, but it seems that it does not call the server side functions properly.
I developed the store locator using open street map and leaflet. The problem is when I want to type in searchbox it will become lagging to finish the word. That store locator read from the CSV file that has 300++ data. Below is the code for the searchbox:
var locationLat = [];
var locationLng = [];
var locMarker;
var infoDiv = document.getElementById('storeinfo');
var infoDivInner = document.getElementById('infoDivInner');
var toggleSearch = document.getElementById('searchIcon');
var hasCircle = 0;
var circle = [];
//close store infor when x is clicked
var userLocation;
$("#infoClose").click(function() {
$("#storeinfo").hide();
if (map.hasLayer(circle)) {
map.removeLayer(circle);
}
});
var listings = document.getElementById('listingDiv');
var stores = L.geoJson().addTo(map);
var storesData = omnivore.csv('assets/data/table_1.csv');
function setActive(el) {
var siblings = listings.getElementsByTagName('div');
for (var i = 0; i < siblings.length; i++) {
siblings[i].className = siblings[i].className
.replace(/active/, '').replace(/\s\s*$/, '');
}
el.className += ' active';
}
function sortGeojson(a,b,prop) {
return (a.properties.name.toUpperCase() < b.properties.name.toUpperCase()) ? -1 : ((a.properties.name.toUpperCase() > b.properties.name.toUpperCase()) ? 1 : 0);
}
storesData.on('ready', function() {
var storesSorted = storesData.toGeoJSON();
//console.log(storesSorted);
var sorted = (storesSorted.features).sort(sortGeojson)
//console.log(sorted);
storesSorted.features = sorted;
//console.log(storesSorted)
stores.addData(storesSorted);
map.fitBounds(stores.getBounds());
toggleSearch.onclick = function() {
//var s = document.getElementById('searchbox');
//if (s.style.display != 'none') {
//s.style.display = 'yes';
//toggleSearch.innerHTML = '<i class="fa fa-search"></i>';
//$("#search-input").val("");
//search.collapse();
//document.getElementById('storeinfo').style.display = 'none';
//$('.item').show();
//} else {
//toggleSearch.innerHTML = '<i class="fa fa-times"></i>';
//s.style.display = 'block';
//attempt to autofocus search input field when opened
//$('#search-input').focus();
//}
};
stores.eachLayer(function(layer) {
//New jquery search
$('#searchbox').on('change paste keyup', function() {
var txt = $('#search-input').val();
$('.item').each(function() {
if ($(this).text().toUpperCase().indexOf(txt.toUpperCase()) != -1) {
$(this).show();
} else {
$(this).hide();
}
});
});
I dont know what is the cause of the lag in the search box. It is something wrong in code or the csv file? Thank you
Every iteration of $('.item').each is causing a layout change because $(this).hide() or $(this).show() causes the item to removed/added to the DOM as the style is set to display:none back and forth. DOM manipulations and the corresponding layout changes are expensive.
You can consider accumulating the changes and doing one batch update to the DOM using a function like appendChild
I am creating search bar, which shows results from database dynamically on keypress, when they match the string that is in the search bar. Also when the string doesn't match anything in my database, I want to show message to user, that nothing matches his input. Problem is that I don't know how to do this in javaScript. I tried using callback function, but my implementation doesn't work. It is my first time using callback function, so I guess something is not right. Can anybody help me?
Here is simplified code:
var bars = firebase.database().ref("bars").orderByChild("rating");
var types = firebase.database().ref("types");
var searcher = document.getElementById("searcher");
var results = document.getElementById("searchResults");
function search(){
var value = searcher.value.toUpperCase();
clearTimeout(timeout);
timeout = setTimeout(function () {
if(value == null || value == ""){
results.style.display = "none";
} else{
results.innerHTML = "";
//callback function here
function findResults(callback) {
types.once("value").then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var type = childSnapshot.key;
if(type.toUpperCase().startsWith(value)){
results.style.display = "block";
var typeItem = createDiv("result-item");
typeItem.innerHTML = type;
results.append(typeItem);
}
callback(true);
});
});
bars.once("value").then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var bar = childSnapshot.key;
if(bar.toUpperCase().startsWith(value)){
results.style.display = "block";
var barItem = createDiv("result-item");
barItem.innerHTML = type;
results.append(barItem);
}
callback(true);
});
});
}
//This needs to work, when callback didn't return true
findResults(function(callback){
if(!callback){
var empty = createDiv("emptyResult");
empty.innerHTML = "No matching results";
results.appendChild(empty);
results.style.display = "block";
}
});
}
}, 400);
}
function createDiv(name){
var div = document.createElement("div");
div.className = name;
return div;
1.Let me start by pointing out that querying the Firebase Database on Keypress can be very expensive, since you'll be downloading data more frequently and Firebase has a price on data downloaded. I recommend querying the database when the user presses Enter or a Search Button.
2.I don't see why you need a callback function for this. You can use plain functions to achieve that. Like this:
function search(){
var value = searcher.value.toUpperCase();
clearTimeout(timeout);
timeout = setTimeout(function () {
if(value == null || value == ""){
results.style.display = "none";
} else{
results.innerHTML = "";
types.once("value").then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var type = childSnapshot.key;
var foundUnderTypes = false;
if(type.toUpperCase().startsWith(value)){
results.style.display = "block";
var typeItem = createDiv("result-item");
typeItem.innerHTML = type;
results.append(typeItem);
foundUnderTypes = true;
}
bars.once("value").then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var bar = childSnapshot.key;
if(bar.toUpperCase().startsWith(value)){
results.style.display = "block";
var barItem = createDiv("result-item");
barItem.innerHTML = type;
results.append(barItem);
}
else{
if(!foundUnderTypes)
emptyResult();
}
});
});
});
});
}
}, 400);
}
function emptyResult(){
var empty = createDiv("emptyResult");
empty.innerHTML = "No matching results";
results.appendChild(empty);
results.style.display = "block";
}
My current code is directly below. Everything works except my button function.
The one line that is giving me issues is the
var tesbut = new onclickfunc(buttons[g], 'testbuttloc');
line. I believe this is because I cannot make the buttons[g] into an HTMLButtonElement which is why I have this line.
buttons[g].setAttribute("type", "HTMLButtonElement");
I believe that I need the line directly above because whenever I use
var tesbut = new onclickfunc(testbutt, 'testbuttloc');
it works. (These are the names of the variables that are declared in XML) So, is there any advice?
var buttons = [];
var subbuttons = [];
for(var mainsplunkcount = 0; mainsplunkcount<mx.length; mainsplunkcount++){
buttons[mainsplunkcount] = mx[mainsplunkcount].getElementsByTagName("BUTTON")[0].childNodes[0].nodeValue;
subbuttons[mainsplunkcount] =mx[mainsplunkcount].getElementsByTagName("BUTTONLOC")[0].childNodes[0].nodeValue;
mainnewstat.id = mainstatus[mainsplunkcount];
$("<div />", { "class":"Main_Category", id:"product"+group[mainsplunkcount] })
$("<button />", { id:buttons[mainsplunkcount] })
//divs that work
.append($('</button>'))
.append($('</div>'))
.appendTo(main_sort[mainsplunkcount]);
$("<div />", { id:subbuttons[mainsplunkcount], "class" : "hidden"})
.append($('<div class="group"><font size="2">' + maingroup[mainsplunkcount] + '</div></div>'))
.append($('</div>'))
.appendTo(main_sort[mainsplunkcount]);
}
//dropdown for submenus of menus
var onclickfunc = function(button, newpost){
button.onclick = function(){
var div = document.getElementById(newpost);
if(div.style.display !== 'none'){
div.style.display = 'none';
} else{
div.style.display = 'inline';
}
};
};
for(var g = 0; g<mx.length; g++){
buttons[g].setAttribute("type", "HTMLButtonElement");
var tesbut = new onclickfunc(buttons[g], 'testbuttloc');
}
XML code
<MAINCONTAINER>
<GROUP>Test</GROUP>
<INOUT>test</INOUT>
<CRITICALITY>test</CRITICALITY>
<CALLNUMBER>6</CALLNUMBER>
<LOCATION>sortAll5</LOCATION>
<STATUSNAME>testt</STATUSNAME>
<BUTTON>testbutt</BUTTON>
<BUTTONLOC>testbuttloc</BUTTONLOC>