I have a javascript function which is called by a 'onsubmit' within a form (Coldfusion).
<form action = "person2aa.cfm"
name = "pers2form"
method = "post"
style = "margin-left: 125px"
onsubmit = "return test()">
When the function test() is located directly below this form statement it works correctly:
<script>
function test(){
alert("got to test");
var yesa = document.getElementById('yesnoa').value;
var yesb = document.getElementById('yesnob').value;
var xx = document.getElementById('ln').value;
var x = xx.trim();
alert('supbpers2 x is ' + x);
if (x < "!"){
document.getElementById('writeval').innerHTML = "You must enter a last name.";
return false;}
else
return true;
}
</script>
(The remainder of the form continues below this script).
When I place this function anywhere else, it does not run. I have tried it in the header of the html page, and also on another page, person.js, to which the link is:
<script type = "text/javascript" src = "person.js"> </script>
The first alert 'got to test' runs in these places, but the first line starting var yesa = does not execute and the function therefore does not execute either.
The id's 'yesnoa', 'yesnob', 'ln' and 'writeval' are in the code and are correct (or the inline script would not run, but I checked anyway).
I previously had this script (minus the alerts) in the header section of my program, and it was working at one point. I have returned to retest the program some months later and the script was not functioning. I have not made any changes to this script at any time. The program itself was altered by the addition of 4 trivial queries to do various things but all look something like this:
<cfquery name = 'aa11' datasource = "Moxart">
update NameInfoDb
set perloc = <cfqueryparam value = "#perloc#">
</cfquery>
I cannot think of any connection between these additional queries and the failure of the javascript.
Can anyone explain what the problem might be? There must be an explanation, and I need to know it so I will not repeat whatever the bad code is.
Related
I'm trying to create a macro to have a box prompt to confirm the action like "Do you want to clear the sheet?" with a yes or no question.
If YES, to delete the given cells
If NO, do nothing.
The YES condition works. But I can't seem to make the NO work. Even if I click on NO, it still executes the clear command. What am I doing wrong?
I'm not well versed in coding. I simply rely in Google. I have tried to change the "else" to "End if" and also tried "then" but none works. I'm not sure how to stop the code from running.
function myFunction() {
var sh1=SpreadsheetApp.getActive();
var sheet1=sh1.getSheetByName("Sheet1")
var sh=SpreadsheetApp.getUi();
var response=sh.alert("Clear?",sh.ButtonSet.YES_NO)
if(response.YES);{
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
sheet.getRange('b1:b21').clearContent();
sheet.getRange('C13:C18').clearContent();
}
Else {}
}
Even clicking NO from the prompt it still executes the clearContent command.
You're not using response correctly. It contains a UI.Button.YES or UI.Button.NO value. The correct test would be
function myFunction() {
var sh1 = SpreadsheetApp.getActive();
var sheet1 = sh1.getSheetByName("Sheet1")
var sh = SpreadsheetApp.getUi();
var response = sh.alert("Clear?", sh.ButtonSet.YES_NO)
if(response == UI.Button.YES) {
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
sheet.getRange('b1:b21').clearContent();
sheet.getRange('C13:C18').clearContent();
}
}
For more information, see the documentation for UI.Alert
(You also had a misplaced ; in your original code after the if(), with if(response.YES);{, which my answer removes as well.)
I have a date input in my page, which I'm using Daterangepicker framework to populate it.
Here is the code of how I start my page!
$(function(){
startSelectors();
var variaveis = returnInputVars();
var rede = variaveis[0];
var codLoja = variaveis[1];
var period = variaveis[2];
console.log('1.'+rede+' 2.'+codLoja+' 3.'+period);
});
function returnInputVars(){
var rede = $("#dropdown-parceria").val();
var codLoja = $("#dropdown-loja").val();
var periodo = $("#datepicker-range").val();
return [rede, codLoja, periodo];
};
The function startSelectors() is set to start my datepicker and other fields, which is working perfectly. After it, I create a var called "variaveis" to fill
with the values of each field because I will use then later (this functions also works perfectly at other scripts of my page).
Running the page, my console returns this:
The funny thing is, if I type at the console this, the value is shown, just while starting the script is does not work!
Anybody experienced something like this?
***UPDATE
Adding this script to my start function:
console.log($("#datepicker-range"));
The value is shown, but the second console.log don't:
EDIT 1. FIDDLE (Suggested by #halleron)
To ensure things are loaded in the correct order, it is useful to apply a page sniffer code snippet that will scan the page continuously until a condition is met, or until a preset counter limit is reached (to prevent strain on browser memory). Below is an example of what I typically use that would fit your scenario.
I think because you are dealing with asynchronous loading, you can't have a global variable that holds the values in a global scope without an interval to detect when it can be used. Otherwise, it will attempt to read the variable when it is not yet ready.
You can invoke functions anywhere you like. But I would keep all of your variables contained within the page_sniffer_2017() because that is a controlled environment where you know that everything successfully loaded and you know that the variables are ready to be accessed without error.
That way, regardless of connection speed, your functions will only fire when ready and your code will flow, sequentially, in the right order.
Within the ajax success options, always add a class to the body of the document that you can search on to determine if it has finished loading.
$(document).ready(function() {
page_sniffer_2017();
});
function page_sniffer_2017() {
var counter = 0;
var imgScanner = setInterval(function() {
if ($("#datepicker-range").length > 0 && $("#datepicker-range").val().length && jQuery('body').hasClass('date-picker-successfully-generated')) {
var periodoDatepicker = $("#datepicker-range").val(); // ok
console.log(periodoDatepicker); // ok
var variaveis = returnInputVars(replaceDate(periodoDatepicker)); // ok
console.log(variaveis[0], variaveis[1], variaveis[2]);
//startNewSelectors(variaveis);
// start ajax call
generateData(variaveis[0], variaveis[1], variaveis[2]);
clearInterval(imgScanner);
} else {
//var doNothing = "";
counter++;
if (counter === 100) {
console.log(counter);
clearInterval(imgScanner);
}
}
}, 50);
}
I'm removing the rust and getting to do some php/javascript programming again, after a while. I'm developing a website for an event, to which people have to register themselves in order to participate.
Here's the situation: I made a form where participants can choose presentations to reserve their spot. Here's the js function I'm using:
function cbosoma(obj, valor) {
var valoratual = document.getElementById("total").value;
var newval = 0;
// Alert windows - just for testing
alert("You just marked or unmaked a checkbox!");
if (isNaN(valoratual) || valoratual < 0 ) {
valoratual = 0;
}
if (obj.checked) {
newval = parseInt(valoratual) + parseInt(valor);
} else {
newval = valoratual - valor;
}
document.getElementById("total").value = newval;
}
So, when the user checks or unchecks courses they wanna participate, their "bill" ("total" input text label) should be increased or decrease. The test alert should also pop up on the screen, just to confirm that the script is being called. Here's how I called the function from inside the PHP code:
<input type="checkbox" value="100" onchange='cbosoma(this, this.value)'>
The problem is: I tested this on a separated test page and it worked just fine. However, inside Joomla!, nothing happens. I tried everything: using js control modules, calling the script as a .js file, putting it inside my PHP file using <script> tags, putting the script inside Joomla!'s index.php... Nothing worked.
Can someone give me some advise on that, please?
I'm working on a Google Docs Add-On based on Google's Quickstart tutorial. I'm trying to change the workflow of the Add On in the tutorial to append a new page and then insert a translation on that new page rather than the line-by-line workflow.
I have a script working in single documents but I'm having a hard time moving it to the Add On architecture. I think it's something to do with passing selections from client-side JS to the server-side script doing the translation.
Here's the translate script
function translate(origin, dest, savePrefs) {
Logger.log('Starting the script');
if (savePrefs == true) {
var userProperties = PropertiesService.getUserProperties();
userProperties.setProperty('originLang', origin);
userProperties.setProperty('destLang', dest);
Logger.log(origin,dest);
}
var doc = DocumentApp.getActiveDocument();
var body = doc.getBody();
// Add a page break for the translated material.
body.appendPageBreak();
// Get the number of elements in the document
var elements = body.getNumChildren();
Logger.log('Got the page elements');
// Use the number to loop through each element in the document.
for( var i=0;i<elements;i++) {
var element = body.getChild(i).copy();
var type = element.getType();
Logger.log('Element Types were successful. Starting tests.');
// Test each type for a child element and run script based on the result
// Images are nested in a paragraph as a child, so the second `if` makes
// sure there is no image present before moving to the next paragraph.
if( type == DocumentApp.ElementType.PARAGRAPH ){
if(element.asParagraph().getNumChildren() != 0 && element.asParagraph().getChild(0).getType() == DocumentApp.ElementType.INLINE_IMAGE) {
var img = element.asParagraph().getChild(0).asInlineImage().getBlob();
body.appendImage(img);
} else if(element.asParagraph().getNumChildren() !=0 && element.asParagraph().getChild(0).getType() == DocumentApp.ElementType.INLINE_DRAWING) {
var drawing = element.asParagraph().copy();
body.appendParagraph(drawing);
} else {
var text = element.asParagraph().getText();
Logger.log(text);
var spn = LanguageApp.translate(text, origin, dest);
body.appendParagraph(spn);
}
} else if(type == DocumentApp.ElementType.TABLE) {
element.asTable().copy();
body.appendTable(element);
} else if(type == DocumentApp.ElementType.LIST_ITEM) {
var list = element.asListItem().getText();
body.appendListItem(LanguageApp.translate(list, origin, dest));
}
}
The client-side JS is:
$(function() {
$('#run-translation').click(loadPreferences);
google.script.run(runTranslation)
});
function runTranslation() {
this.disabled = true;
var origin = $('input[name=origin]:checked').val();
var dest = $('input[name=dest]:checked').val();
var savePrefs = $('#save-prefs').is(':checked');
google.script.run
.runTranslation(origin, dest, savePrefs);
}
If I hard-code the languages to use in translation into the server-side script, it works. But as soon as I try to use variables from the radio buttons, it doesn't run. I don't see any errors in the console and I can't run scripts from the editor to check the logs. How can I debug this code?
Calling server-side functions from client Javascript
You've got a minor syntax error with google.run:
google.script.run(runTranslation)
It should be:
google.script.run
.withFailureHander(failFunc) // Optional
.withSuccessHander(succFunc) // Optional
.serverFunction(optionalParams...);
The two Handler methods assign callback functions from your client-side JavaScript to be invoked in the case of success or failure of the server-side function. In both cases, the client-side function is provided as the only parameter.
The server-side function you want to communicate with is presented as if it is a method itself, with optional parameters to be passed across the divide.
The simplest case for you is:
google.script.run
.translate(origin, dest, savePrefs);
(You had runTranslation in your posted code, but the server-side function is named translate()... I assume that's the right one.)
Now, this might will not take care of all your problems, so you wisely asked about debugging...
Debugging asynchronous client / server code in Google Apps Script
The provided debug environment isn't enough for debugging this sort of client / server exchange. There are also weaknesses in the Debugger for use with asynchronous execution - you can read more about that in Not seeing logs from onEdit trigger.
The simplest tool to get you debugging in this case would be to write logs to a spreadsheet
/**
* Write message and timestamp to log spreadsheet.
* From: https://stackoverflow.com/a/32212124/1677912
*/
function myLog( message ) {
var ss = SpreadsheetApp.openById( logSpreadsheetId );
var logSheet = ss.getSheetByName("Log") || ss.insertSheet("Log");
logSheet.appendRow([ new Date(), message );
}
You can call this from your client-side Javascript thusly:
google.script.run.myLog( "CLIENT: " + message );
That's a basic approach, but you can extend it more through use of utility functions and the BetterLog library. See more about that in my blog entry Did you know? (You can log to a spreadsheet from client JavaScript!)
I've finished off a script that runs on a page that contains a textarea where an email goes.
I'm doing a variety of things on this page, however one of these is to load an iframe, based on a selected number, then once the iframe loads grab the relevant details I need from this page.
I've written the code for this inside a function called frameLoaded and I'm setting this as the onload event, yet the script still runs in to an error where it can't find the .innerHTML of an element.
If I load the iframe and then execute this script it works fine, however if I try to load the iframe and execute the script together then it runs in to this error.
Here's the code I'm using:
//Getting text currently in the textarea
var selectedTxt = document.getElementById('txtEmailText').value;
//Converting it to a string - this is just for troubleshooting purposes that I've used two variables
var insertText = selectedTxt.toString();
//Loads in the highlighted purchase number
var purchaseNumber = window.getSelection();
purchaseNumber = purchaseNumber.toString();
//Declares global variables to hold the title and number
var purchaseTitle;
var purchaseNumber;
//Function to execute code to grab title and number once the frame has loaded
function frameLoaded() {
var iframe = document.getElementById('purchaseIframe');
var innerDoc = iframe.contentDocument || iframe.contentWindow.document;
purchaseTitle = innerDoc.getElementById('listingTitle');
purchaseNumber = innerDoc.getElementById('auctionSoldIdDisplay');
}
//Checks to see if a purchase number has been selected
if(purchaseNumber.length > 0){
var purchaseIframe = document.createElement('iframe');
purchaseIframe.src = 'http://www.mysite.co.nz/Admin/Listing/PurchaseDisplay.aspx?asid=' + purchaseNumber + '&submit1=++GO++';
purchaseIframe.setAttribute("height","1000");
purchaseIframe.setAttribute("width","100%");
purchaseIframe.setAttribute("id","purchaseIframe");
purchaseIframe.setAttribute("onload", "frameLoaded();");
void(document.body.appendChild(purchaseIframe));
}
//Converting the value in the title to readable text
purchaseTitle = purchaseTitle.innerHTML;
//Placing the values in to the format I need
var purchaseDetails = purchaseTitle + " - " + purchaseNumber;
//Placing the values in to the string to go back in to the email textarea
insertText = insertText.replace("PURCHASEDETAILS", purchaseDetails);
//Pasting the variable in to the textarea
document.getElementById('txtEmailText').value = insertText;
Am I doing something wrong here or using the wrong event as it seems to me that maybe it's trying to grab the values before the iframe has fully loaded, hence the error when I'm generating the iframe at the same time.
Please note that I cannot use JQuery
window.onload = function() is your answer.
Note in the example below, the first instance of document.getElementById('mydiv') returns null because the page (DOM) was not yet loaded and therefore neither was the div.
The second instance is fired on the windows.onload which means all the page content is present and can therefore be found.
<script type='text/javascript'>
console.log("Page not ready:" + document.getElementById('mydiv'));
window.onload = function() {
console.log("Page ready:" + document.getElementById('mydiv'));
}
</script>
<div id="mydiv">
</div>