<script type="text/javascript">
function Msg1(){
var a="noida";
id=1;
document.getElementById('myText').innerHTML = '<p onclick="nice(id)">'+a+'</p>';
}
function Msg2(){
document.getElementById('myText').innerHTML = 'Try message 1 again...';
}
</script>
<input type="button" onclick="Msg1()" value="Show Message 1" />
<input type="button" onclick="Msg2()" value="Show Message 2" />
<p id="myText"></p>
when i click on Show Message 1 it send id as a charecter not 1 i want to it send me 1
Thanks
You could do something like:
'<p onclick="nice(\"' + id + '\")">'+a+'</p>';
Or:
'<p onclick="nice(' + escape(JSON.stringify(id)) + ')">'+a+'</p>';
But this gets very unreadable very quickly.
Using this method you can't send things that aren't easily serializable. A more robust, and involved, solution would use the DOM API and EventListener API.
Example:
var id = { foo: "bar" };
var p = document.createElement("p");
p.addEventListener("click", function () {
nice(id);
});
p.innerText = "ipsum lorem";
document.body.appendChild(p);
You already have concatenation right near where you need it:
'<p onclick="nice('+id+')">'+a+'</p>';
make your innerHTML as
'<p onclick="nice(\"' + id + '\")">'+a+'</p>'
Replace your Msg1() Javascript function as below
function Msg1(){
var a="noida";
var id = 1;
document.getElementById('myText').innerHTML = '<p onclick="nice(\"' + id + '\")">'+a+'</p>';
}
Related
It seems like many people have had this problem in the past but none of the solutions work for me.
I have a method that is firing after receiving a response from a POST request:
xhr.onload=function(e) {
if(this.readyState === 4) {
res = JSON.parse(e.target.responseText);
var userHtml = '<p class="userText"><span>' + res.userText + "</span></p>";
document.getElementById("chatbox").append(userHtml);
var botHtml = '<p class="botText"><span>' + res.botText + "</span></p>";
document.getElementById("chatbox").append(botHtml);
document
.getElementById("userInput")
.scrollIntoView({ block: "start", behavior: "smooth" });
}
};
Inside a "chat bot", this is supposed to render a text bubble on the right (for the userText) and a text bubble on the left (for the botText). However, when this method triggers, it just appends the raw HTML into the chatbox, as so:
<p class="userText"><span>Hi, how are you.</span></p><p class="botText"><span>I'm fine thanks, how are you?</span></p>
Is there a way I can fix this?
Thanks!
You need to use jQuery / append() function not document.getElementById
I have added both methods below and you can see that $('#chatbox') is parsing the HTML while document.getElementById is displaying out as a plain HTML / (raw) text
Live Demo:
var res = {
userText: 'bar',
botText: 'foo'
}
var userHtml = '<p class="userText"><span>' + res.userText + "</span></p>";
document.getElementById("chatbox").append(userHtml);
$('#chatbox').append(userHtml)
var botHtml = '<p class="botText"><span>' + res.botText + "</span></p>";
document.getElementById("chatbox").append(botHtml);
$('#chatbox').append(botHtml)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="chatbox">
</div>
Using document.getElementById
If you are keen on using document.getElementById then you need to use innerHTML like this below.
Live Demo:
var res = {
userText: 'bar',
botText: 'foo'
}
var userHtml = '<p class="userText"><span>' + res.userText + "</span></p>";
document.getElementById("chatbox").innerHTML += userHtml;
var botHtml = '<p class="botText"><span>' + res.botText + "</span></p>";
document.getElementById("chatbox").innerHTML += botHtml;
<div id="chatbox">
</div>
I am having trouble. So I need to get data from an api. I have a search bar and the user needs to input the search bar to look up a super hero api.
How would I get data from a search bar and put in my url all in a .click function.
var userInput;
var url;
var test;
//https://superheroapi.com/api/10215865526738981
$(document).ready(function () {
// when the user types in the data and clicks the button
$(btn1).click(function () {
// this is where the search bar is
userInput = document.getElementById('mySearch').innerHTML;
});
url = 'https://www.superheroapi.com/api.php/10215865526738981/search/batman' + userInput;
// here is where the api link in say type in batman
// and is should pop up with info about batman and
$.getJSON(url, function (data) {
var html = '';
$.each(data.results, function (i, demo) {
html += '<h2>' + demo.name + '</h2>';
//html += "<h2>" + demo.biography.alter-egos + "</h2>";
html += '<h2> Power Stats ' + demo.powerstats.combat + '</h2>';
html += '<p> Connections ' + demo.connections.relatives + '</p>';
html += '<p> appearance ' + demo.appearance.gender + '</p>';
html += '<h2> Work ' + demo.work.base + '</h2>';
html += ' Profile <img src ' + demo.image.url + '>';
});
$('#demo').html(html);
});
}
<p>
<input type="search" id="mySearch" name="mySearch">
<button id="btn1">Search</button>
<p id="demo"></p>
</p>
Here is something that works that you can use to compare with your code and make something out of it. I've used plain javascript and left comments what is going on so that you can learn from it.
There were few wrong assumptions in original question.
code was executing on page load and didn't wait for user input
url was hardcoded to start with batman + what ever user wrote
Code below is not perfect, but it is close enough to original code and it should be easy to understand. I also opted not to use jQuery, but you should be able to use it if wanted. Just replace getElementById with jQuery selectors and replace XMLHttpRequest with getJson.
I hope this helps you move ahead with your problem and that you will be able to learn something new which could help you better understand javascript. Happy coding!
var button = document.getElementById('btn1');
// when user clicks on button, we want to call function start search
button.addEventListener('click', startSearch);
function startSearch(event) {
// when we are starting the search, we want to pick up the value
// input field from user
var userInputValue = document.getElementById('mySearch').value;
// this is base API url on which we can add what user wanted
var urlBase = 'https://www.superheroapi.com/api.php/10215865526738981/search/'
// if user did not provide name in input, we want to stop executing
if (userInputValue === null || userInputValue === '') return;
// if we are still in this function, append what user typed onto urlBase
var searchUrl = urlBase + userInputValue;
// call function which actually executes the remote call
performSearch(searchUrl);
}
function performSearch(searchUrl) {
// this could be jQuery getJSON if you so prefer
// here it is vanila JS solution of how to get data via AJAX call
var requestData = new XMLHttpRequest();
// because AJAX is always async, we need to wait until file is loaded
// once it is loaded we want to call function handleResults
requestData.addEventListener('load', handleResults);
requestData.open('GET', searchUrl);
requestData.send();
}
function handleResults() {
// once we get response, because we used vanilla JS, we got response
// available in this context as "this.response", however it is type string
// we need to take that string and parse it into JSON
var responseJSON = JSON.parse(this.response);
// if there is error, we didn't find any character
if (responseJSON.error) console.log('Character not found');
else {
var html = '';
responseJSON.results.forEach(function (result) {
html += '<h2>' + result.name + '</h2>';
// html += "<h2>" + demo.biography.alter-egos + "</h2>";
html += '<h2>Power Stats ' + result.powerstats.combat + '</h2>';
html += '<p>Connections ' + result.connections.relatives + '</p>';
html += '<p>Appearance ' + result.appearance.gender + '</p>';
html += '<p>Work ' + result.work.base + '</p>';
// html += ' Profile <img src ' + result.image.url + '>';
})
// this is bad thing to do, injecting html like that into DOM
// but let's leave this lesson for later stage
// so, let's take this html and drop it onto the page
document.getElementById('demo').innerHTML = html;
}
}
<input type="search" id="mySearch" name="mySearch">
<button id="btn1">Search</button>
<div id="demo"></div>
const value = document.getElementById('mySearch').value;
And then use this value in your api url.
I have a google sheet, maintaining a list of projects, with some scripting running behind it. I have been able to add functionality to click an Add Project button which opens an HTML window for entering the information, and on submit, add a new record to the sheet.
Now I am working on a process to remove a record if the status is changed to Cancelled. What I would like to do is show an html window listing certain details of the project, and give the user a chance to either go back without cancelling the project, or enter some notes as to why it's being cancelled and then continue.
Where I am stuck is populating the html window with the details of the project. I have figured out one way to do it, but I know that this isn't the best way.
Google Script:
function onEdit(e) {
if(e.range.getColumn() == 9 && e.value == "Cancelled" && e.source.getActiveSheet().getName() == "Summary") {
var cancelSheet = ss.getSheetByName(e.source.getActiveSheet().getName());
var cancelRange = cancelSheet.getRange(e.range.getRow(), 1, 1, cancelSheet.getLastColumn());
var cancelRow = cancelRange.getValues();
openCancelDialog(cancelRow);
}
}
function openCancelDialog(x) {
var html = HtmlService
//.createHtmlOutputFromFile('Cancel')
.createHtmlOutput(
'<table><tr><td colspan = \"2\"><b>You are cancelling the following project:</b></td></tr>' +
'<tr><td>Project Name: </td><td>' + x[0][4] + '</td></tr>' +
'<tr><td>Project Number: </td><td>' + x[0][0] + '</td></tr>' +
'<tr><td>Project Category: </td><td>' + x[0][1] + '</td></tr>' +
'<tr><td>Business Owner: </td><td>' + x[0][17] + '</td></tr>' +
'<tr><td>Project Manager: </td><td>' + x[0][18] + '</td></tr>' +
'</table>'
)
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
SpreadsheetApp.getUi()
.showModalDialog(html, 'Cancel a Project');
}
This way is writing the html directly in the gs. What I'd like to do is have a separate html page that gets created. That can be done with this method (and is how I'm creating the Add Project dialog elsewhere in the gs):
function openCancelDialog(x) {
var html = HtmlService.createHtmlOutputFromFile('Cancel').setSandboxMode(HtmlService.SandboxMode.IFRAME);
SpreadsheetApp.getUi()
.showModalDialog(html, 'Cancel a Project');
}
This would be Cancel.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<script>
<!-- Scripting to get my values? -->
</script>
</head>
<body>
<!-- Layout the window
Add a Comments section
Add a button to go back without cancel
Add a button to submit the cancel and update -->
</body>
</html>
But what I haven't figured out is how to pass the array from the openCancelDialog function to the html, so it cab be shown on the page..
I suspect that I need to add scripting to the Cancel.html file to get those values. But is there a way to send that array to the html while it's being created?
Kos's answer gave me some ideas on how I could work it out. That, as well as some additional reading, especially https://www.w3schools.com/js/js_json_intro.asp and the follow up sections, helped me figure this one out.
New js code:
function onEdit(e) {
if(e.range.getColumn() == 9 && e.value == "Cancelled" && e.source.getActiveSheet().getName() == "Summary") {
var cancelSheet = ss.getSheetByName(e.source.getActiveSheet().getName());
var cancelRange = cancelSheet.getRange(e.range.getRow(), 1, 1, cancelSheet.getLastColumn());
var cancelRow = cancelRange.getValues();
//openCancelDialog(cancelRow);
var aSheet = e.source.getActiveSheet().getName();
var column = e.range.getColumn();
var row = e.range.getRow();
Logger.log("Col: " + column + " Row: " + row + " Sheet: " + aSheet);
Logger.log(cancelRow);
}
Logger.log(e);
}
function openCancelDialog(row) {
var ui = SpreadsheetApp.getUi();
// get template
var template = HtmlService.createTemplateFromFile('Cancel');
var myJSON = JSON.stringify(row);
// pass data to template
template.data = myJSON;
// get output html
var html = template.evaluate();
// show modal window
ui.showModalDialog(html, 'Cancel a Project');
}
New HTML:
<!DOCTYPE html>
<html>
<body>
<table>
<tr><td>Number: </td><td id="number"></td></tr>
<tr><td>Name: </td><td id="name"></td></tr>
<tr><td>Category: </td><td id="category"></td></tr>
<tr><td>Business Owner: </td><td id="owner"></td></tr>
<tr><td>Project : </td><td id="manager"></td></tr>
</table>
<script>
var objII = JSON.parse(<?=data?>);
document.getElementById("number").innerHTML = objII[0][0];
document.getElementById("name").innerHTML = objII[0][4];
document.getElementById("category").innerHTML = objII[0][1];
document.getElementById("owner").innerHTML = objII[0][17];
document.getElementById("manager").innerHTML = objII[0][18];
</script>
</body>
</html>
I suspect there may be more elegant ways to do this, and probably even more "correct" ways. But this seems to be working for what I needed it to do, so I figured I'd post it in case someone else was looking.
Thank you
Use HtmlService.createTemplateFromFile:
function openCancelDialog(row)
{
var ui = SpreadsheetApp.getUi();
// get template
var template = HtmlService.createTemplateFromFile('Cancel');
// pass data to template
template.data = {
row: JSON.stringify(row)
};
// get output html
var html = template.evaluate();
// show modal window
ui.showModalDialog(html, 'Cancel a Project');
}
Cancel.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<script>
var row = <?!=data.row?>;
//document.write(row);
</script>
</body>
</html>
Detailed template documentation: https://developers.google.com/apps-script/guides/html/templates
Here's another way to do it. I like to do it this way because I have a lot more control than I do with templates.
This is a script that I did when I was working on an email example script that is contained in a spreadsheet. This script is a little less complicated because it's just for giving the user the option for removing sent emails from the emailsetup page and archiving them on another page. It does it by creating html on the fly and collecting it as a string and then adding it to another page of html. I launch the html at the end of the script as a dialog that allows the users to select which emails to archive by checking checkboxes and clicking on a button called Archive Selected. I found it easier to put my javascript functions together in a standard html file and then run that through HtmlService first and append the string later.
Here's the script:
function archiveSelectedEmails()
{
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sht=ss.getSheetByName('EmailSetup');
var rng=sht.getDataRange();
var rngA=rng.getValues();
var s='<html><head><script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script></head><body>';
var s='';
for(var i=2;i<rngA.length;i++)
{
var dataA={};
for(var j=0;j<rngA[1].length;j++)
{
dataA[rngA[1][j]]=rngA[i][j];
}
var row=Number(i+1);
s+='<div id="row' + row + '"><input type="checkbox" name="email" value="' + Number(i+1) + '" />' + ' <strong>Row:</strong> ' + Number(i+1) + ' <strong>Name:</strong> ' + dataA.Name + ' <strong>Email:</strong> ' + dataA.Email + ' <strong>Subject:</strong> ' + dataA.Subject + ' <strong>DateSent:</strong> ' + Utilities.formatDate(new Date(dataA.DateSent), 'GMT-6', "M/dd/yyyy HH:mm:ss") + '</div>';
}
s+='<br /><input type="button" value="Exit" onClick="google.script.host.close();" /><input type="button" value="Archive Checked" onClick="getCheckedBoxes(\'email\');" />';
var html=HtmlService.createHtmlOutputFromFile('htmlToBody').setWidth(800).setHeight(250);
html.append(s);
SpreadsheetApp.getUi().showModelessDialog(html, 'Select Emails to Archive');
}
Here's the html file 'htmlToBody':
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
function getCheckedBoxes(chkboxName) {
var checkboxes = document.getElementsByName(chkboxName);
var rowsToArchive = [];
for (var i=0; i<checkboxes.length; i++)
{
if (checkboxes[i].checked)
{
rowsToArchive.push(Number(checkboxes[i].value));
}
}
google.script.run
.withSuccessHandler(setResponse)
.archiveSelectedRows(rowsToArchive);
}
function setResponse(a)
{
var s='<br />Rows: ';
for(var i=0;i<a.length;i++)
{
if(i>0)
{
s+=', ';
}
s+=a[i];
var id='#row' + a[i]
$(id).css('display','none');
}
s+='<br />Total: ' + a.length;
google.script.run.displayMessage(s,'Archived Rows')
}
console.log('script here');
</script>
</head>
<body>
I took your project idea and ran with it a little.
These are the google scripts. You'll notice I started with the name of your function.
function openCancelDialog1()
{
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sht=ss.getSheetByName('Projects');
var rng=sht.getDataRange();
var rngA=rng.getValues();
var s='';
for(var i=1;i<rngA.length;i++)
{
var dataA={};
for(var j=0;j<rngA[0].length;j++)
{
dataA[rngA[0][j]]=rngA[i][j];
}
var row=Number(i+1);
s+='<div id="row' + row + '"><input type="checkbox" name="project" value="' + row + '" />' + ' <strong>Row:</strong> ' + Number(i+1) + ' <strong>Name:</strong> ' + dataA.Name + ' <strong>Project:</strong> ' + dataA.Description + '</div>';
}
s+='<br /><input type="button" value="Exit" onClick="google.script.host.close();" /><input type="button" value="Cancel and Archive Checked" onClick="getCheckedBoxes(\'project\');" />';
var html=HtmlService.createHtmlOutputFromFile('htmlToBody').setWidth(800).setHeight(250);
html.append(s);
SpreadsheetApp.getUi().showModelessDialog(html, 'Select Project to Cancel');
}
function archiveSelectedRows(rows)
{
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sht=ss.getSheetByName('Projects');
var dest=ss.getSheetByName('ArchivedProjects');
var rng=sht.getDataRange();
var rngA=rng.getValues();
var deleted=[];
for(var i=rngA.length-1;i>1;i--)
{
if(rows.indexOf(i+1)>-1)
{
deleted.push(Number(i+1));
rngA[i][4]=Utilities.formatDate(new Date(), 'GMT-7', 'M/d/yyyy')
dest.appendRow(rngA[i]);
sht.deleteRow(i+1);
}
}
var msg='Row Numbers Deleted = ' + deleted;
var title='Rows Deleted';
var timeout=10;
return deleted;
}
function displayMessage(msg,title)
{
msg+='<br /><input type="button" value="Exit" onClick="google.script.host.close()"; />';
var html=HtmlService.createHtmlOutput(msg).setWidth(400).setHeight(300);
SpreadsheetApp.getUi().showModelessDialog(html, title);
}
This is the htmlTobody file. It's been modified a bit for this situation.
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
function getCheckedBoxes(chkboxName) {
var checkboxes = document.getElementsByName(chkboxName);
var rowsToArchive = [];
for (var i=0; i<checkboxes.length; i++)
{
if (checkboxes[i].checked)
{
rowsToArchive.push(Number(checkboxes[i].value));
}
}
google.script.run
.withSuccessHandler(setResponse)
.archiveSelectedRows(rowsToArchive);
}
function setResponse(a)
{
var s='<br />Row Numberss: ';
for(var i=0;i<a.length;i++)
{
if(i>0)
{
s+=', ';
}
s+=a[i];
var id='#row' + a[i]
$(id).css('display','none');
}
s+='<br />Total: ' + a.length;
google.script.run.displayMessage(s,'Canceled Rows')
}
console.log('script here');
</script>
</head>
<body>
And this is what my 'Projects' tab looks like. And I have a Projects tab and an ArchivedProjects tab. When I archive the projects they get copied into the ArchivedProjects sheet.
Is there some way i can do like i can fetch and show text inputs ?
Like this:
document.getElementById('input_id')
<input type="text" placeholder="username" id="input_id">
and then the output will be like this:
document.showElementById('box_id')
<div id="box_id">Welcome + text input</div>
With this:
var name = document.getElementById('input_id').value;
document.getElementById('box_id').innerHTML = "Welcome " + name;
That's it.
EDIT
Checking at your code, it looks that you want to create a showElementById method
Trivial, but just in case:
function showElementByIds(inputId, divId){
var name = document.getElementById(inputId).value;
document.getElementById(divId).innerHTML = "Welcome " + name;
}
Then, to use it:
showElementByIds('input_id', 'box_id');
Cheers
var username = document.getElementById('input_id').value;
document.getElementById('box_id').innerHTML = 'Welcome ' + username;
I've got a simple JavaScript client that pulls from a REST API to present some book data, however I seem unable to call the function createBookRow(bookid) and return the appropriate html string to the document ready function where it is called,
The output is currently being produced correctly as verified by the append to .row-fluid on the html page, ideas or suggestions welcome
function createBookRow(bookid)
{
$.get('http://mysite.co.uk/atiwd/books/course/'+bookid+'/xml', function(xml){
$(xml).find('book').each(function(){
var $book = $(this);
var id = $book.attr("id");
var title = $book.attr("title");
var isbn = $book.attr("isbn");
var borrowedcount = $book.attr("borrowedcount");
var html = '<div class="span3"><img name="test" src="http://covers.openlibrary.org/b/isbn/'+isbn+'-L.jpg" width="32" height="32" alt=""></p>' ;
html += '<p> ' + title + '</p>' ;
html += '<p> ' + isbn + '</p>' ;
html += '<p> ' + borrowedcount + '</p>' ;
html += '</div>';
$('.row-fluid').append($(html));
});
});
}
$(document).ready(function()
{
$.get('xml/courses.xml', function(xml){
$(xml).find('course').each(function(){
var $course = $(this);
var id = $course.attr("id");
var title = $course.text();
var html = '<div class="span12"><p>' + title + '</p><row id="'+id+'" >'+createBookRow(id)+'</row></div>' ;
$('.row-fluid').append($(html));
$('.loadingPic').fadeOut(1400);
});
});
});
The line
var html = '<div class="span12"><p>' + title + '</p><row id="'+id+'" >'+createBookRow(id)+'</row></div>' ;
should be just
var html = '<div class="span12"><p>' + title + '</p><row id="'+id+'" ></row></div>' ;
createBookRow(id);
createBookRow(id) function is making a get request to get some details, which happens asynchronously. Unless you explicitly mention it is a synchronous call(which is not advised).
I guess the functionality you need is to render some rows for course and in between you need books details displayed. In that case you need to explicitly say where your book row needs to be appended.
$('.row-fluid').append($(html));
The above code will always append book row at the end.
You aren't returning anything in the code you provided. You just append some HTML to a jQuery object. Try adding a return statement
return html;