Google App Script not interpreting javascript - google-apps-script

I am trying to have a list box populate based on the selection from another list box. It works fine on a simple html/js page loaded on an Apache server, but when I try to put it into html services in Google App Script, only the first list box appears: Nothing happens in the second box. I feel I am missing some basic concept in GAS.
In code.gs I have:
function hardCode() {
var html = HtmlService.createHtmlOutputFromFile('hardcode.html')
.setWidth(600).setHeight(425);
SpreadsheetApp.getUi().showModalDialog(html, 'Why doesn't this work');
}
Then on the html side I have:
<form name="classic">
<select name="countries" size="4" onChange="updatecities(this.selectedIndex)" style="width: 150px">
<option selected>Select A City</option>
<option value="usa">USA</option>
<option value="canada">Canada</option>
<option value="uk">United Kingdom</option>
</select>
<select name="cities" size="4" style="width: 150px" onClick="alert(this.options[this.options.selectedIndex].value)">
</select>
</form>
<script type="text/javascript">
var countrieslist=document.classic.countries
var citieslist=document.classic.cities
var cities=new Array()
cities[0]=""
cities[1]=["New York|newyorkvalue", "Los Angeles|loangelesvalue", "Chicago|chicagovalue", "Houston|houstonvalue", "Austin|austinvalue"]
cities[2]=["Vancouver|vancouvervalue", "Tonronto|torontovalue", "Montreal|montrealvalue", "Calgary|calgaryvalue"]
cities[3]=["London|londonvalue", "Glasgow|glasgowsvalue", "Manchester|manchestervalue", "Edinburgh|edinburghvalue",
"Birmingham|birminghamvalue"]
function updatecities(selectedcitygroup){
citieslist.options.length=0
if (selectedcitygroup>0){
for (i=0; i<cities[selectedcitygroup].length; i++)
citieslist.options[citieslist.options.length]=new Option(cities[selectedcitygroup][i].split("|")[0],
cities[selectedcitygroup][i].split("|")[1])
}
}
</script>

The standard mode that HtmlService is either NATIVE or EMULATED (the latter being triggered by older browsers). Each brings with it security pre-parsing using Caja which can break certain functionality.
If you change the sandbox to IFRAME it should allow your code to function.
function hardCode() {
var html = HtmlService.createHtmlOutputFromFile('hardcode.html')
.setWidth(600).setHeight(425)
.setSandboxMode(HtmlService.SandboxMode.IFRAME); // ADD THIS LINE
SpreadsheetApp.getUi().showModalDialog(html, 'Why doesn't this work');
}
Caveat
Bear in mind that the IFRAME sandbox mode while it brings greater functionality, its scope of supported browsers is lower.
There is every likelihood that support for that mode will be expanded over time.

Related

All Browsers except Firefox don't react to jQuery .click()

I have the following HTML/Twig structure
<select name="herstellerSelect" class="categoryElement" id="herstellerDropdown" style="display: block;">
<option class="preselect" value="" style="display: block;">Hersteller wählen</option>
{{ _self.cpitems0(categories.categories, categories.categories_info, parts, oop_display, oop_opened) }}
</select>
The Twig macro "cpitems0" generates elements for the
This is the jQuery Code that should, amongst other things, output a text to the console once children (<option> elements of the <select>) are clicked.
$(document).ready(function() {
console.log('CATEGORY SELECTOR TEST');
$("#herstellerDropdown").children().click(function(e) {
e.preventDefault();
console.log('CATEGORY SELECTOR TEST 2');
...
I have also tried
$(document).ready(function() {
console.log('CATEGORY SELECTOR TEST');
$("#herstellerDropdown").on('click', '> *', function(e) {
e.preventDefault();
console.log('CATEGORY SELECTOR TEST 2');
...
Only Firefox (private mode and cleared browser cache) displays the second console.log output, all the other tested Browsers (Brave, Chromium, Opera Developer in private mode with cleared Browser cache on Ubuntu 20.4) only display the first console.log output
Does anyone know why this happens?
Upate 14.10.2021 14:20 -> I have to use $("#herstellerDropdown").on("change" ... ) instead of .$("#herstellerDropdown").click because it's a element.
Generally, I have to use "AJAX Cascading Dropdowns" for what should be realized. I thought I could avoid AJAX and load the server generated content into the DOM and copy the respective elements with $("selectElement").html( elements) but I guess that results in poor performance and bad design so I have to go with the Cascading Dropdowns!
Use on("change" instead of click
Options do not need ID
Why display:block?
Why preventDefault() ?
This works in Chrom(e/ium) and Fx
$(function() {
$("#herstellerDropdown").on("change", function(e) {
console.log(this.value)
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select name="herstellerSelect" class="categoryElement" id="herstellerDropdown">
<option class="preselect" value="" style="display: block;">Hersteller wählen</option>
<option data-val-one="Key0" data-val-two="" data-val-three="" value="entry0">categories_info[keyZero].elementid 0</option>
<option data-val-one="Key1" data-val-two="" data-val-three="" value="entry1">categories_info[keyZero].elementid 1</option>
<option data-val-one="Key2" data-val-two="" data-val-three="" value="entry2">categories_info[keyZero].elementid 2</option>
</select>

Using jquery load function in combination with forms

Currently developing a new website and looking to use jQuery's load() function to load content from different html pages into my main page.
load() works fine. Here's my current code.
Main.html page in which content is loaded:
<div id="answer"></div>
Javascript with the load() function:
$(document).ready(function() {
$("#answer").load( "game1content.html #p1Answer");
game1content.html content to load:
<div id="p1Answer">
<p>Some text</p>
<form id="answer1Form">
<select name="answer1" id="answer1">
<option value=""></option>
<option value="1">Website 1</option>
<option value="2">Website 2</option>
<option value="3">Website 3</option>
<option value="4">Website 4</option>
</select>
<button id="submitButton">SUBMIT</button>
</form>
</div>
So it loads html correctly into the answer div. Perfect.
Now the challenge is that when I submit the form that's loaded, it refreshes the page. When I have the game1content content in the main.html file, instead of using the load() it doesn't reload and works fine. But if I use the load() function, it does reload and also changes the url.
Here's my function on submit:
$( "#answer1Form" ).submit(function(e) {
e.preventDefault();
console.log ("clicked");
});
I've tried Googling this issue, but can't find much. Also, tried changing .submit to onclick etc, but same result. Any ideas?
That's because when you call .load, it fetch the page content and adds DOM elements but not bind them to events, so the form behave like it should, refresh the page.
In order to prevent the form from refreshing you should listen to .submit() exactly like you do in game1content.html after the DOM elements are added.
Like this:
$("#answer").load( "game1content.html #p1Answer", function() {
$( "#answer1Form" ).submit(function(e) {
e.preventDefault();
console.log("clicked");
});
});

protractor testing on multi select giving 'Element not visible' error

I have the following html code with a multiselect element. On running tests with protractor to select the options, I get the error as 'Element not visible'.
<div id="one" class="class1">
<select id="select1" style="width: 70%;" class="multiselect" multiple="multiple" ng-model="formData.abcqw">
<option value="abc">ABC</option>
<option value="xyz">XYZ</option>
<option value="pqr">PQR</option>
</select>
</div>
protractor code :
browser.actions().
mouseMove(element(by.className("multiselect"))).click().perform();
element(by.model("formData.abcqw")).sendKeys("abc");
Any help is appreciated.
It's pretty much evident from the HTML which you have shared that the <select> tag is an AngularJS element, so we have to induce wait i.e. WebDriverWait as follows for the element to be selectable:
var EC = protractor.ExpectedConditions;
// Waits for the element with id 'select1' to be selected.
browser.wait(EC.elementToBeSelected($('#select1')), 5000);
I also think that it is a wait issue.
Whenever you see this "element not visible error" you can add
browser.sleep(5000);
before the click statement and try again
if that doesn't work try below.
This when we intentionally want to click an hidden element. So this should work
var elm = element(by.className("multiselect "));
browser.executeScript("arguments[0].click();", elm.getWebElement());
browser.sleep(2000);
element(by.model("formData.abcqw")).sendKeys("abc");
Try the following code, I replicated the same in my local and verified the below code it works fine:
var EC = protractor.ExpectedConditions;
var multiSelectElement = element(by.model('formData.abcqw');
browser.wait(EC.visibilityOf(multiSelectElement))).then(function() {
browser.wait(EC.elementToBeClickable(multiSelectElement.element(by.cssContainingText('option', 'ABC'))))).then(function() {
multiSelectElement.element(by.cssContainingText('option', 'ABC')).click();
});
});

HTML tags to allow user to select multiple items and set their order

I have this input to allow user to select (with multiple choices) a product:
<select multiple="yes" name="products[]">
<option value="wood">Wood</option>
<option value="iron">Iron</option>
<option value="gold">Gold</option>
<option value="dust">Dust</option>
<option value="food">Food</option>
</select>
User can select several stuff in that list, and I can get in server-side using, for instance, PHP:
$_GET['products'] ← array('wood', 'iron', 'food');
Now, I would like to allow users to specify an order for the selection they made. So, I want the user to be able to not only set the list of items to select (like a <select multiple="yes">) but also in which order I will treat them.
In other words, let's say a user want the list to be ordered to:
$_GET['products'] ← array('gold', 'iron', 'wood', 'dust');
Currently, using the <select multiple="yes"> I can only ask user to unorderedly pick up items from a list but
what's the HTML tags I should use to allow user to select multiple options and specify its order?
I don't want to sort the options inside the <select>, I want the user to be able to tell the server in which order it should treat the selected items list.
I picked PHP example as server-side treating code (and it's the language I will use) but actually, the answer should not rely on server side language: I'm looking for the "html-client-side" code to use.
The following answer isn't exactly elegant but it get's the job done. I havn't been doing Web development long but I'm learning.
The JavaScript could be better as I'm used to jQuery (crutch I know).
Pure js (easier if you can use jQuery)
var products = [];
function add(val) {
if (!contains(products, val))
{
products.push(val);
document.getElementById('list').setAttribute('name', products);
}
}
// checks if arr 'a' has the element 'obj'
// thanks to someone at stack overflow for how to do that :)
function contains(a, obj) {
var i = a.length;
while (i--) {
if (a[i] === obj) {
return true;
}
}
return false;
}
html
// add the onclick='add()' function to your html
<select id='list' multiple="yes" name="" value='heyo'>
<option onclick='add("wood")' value="wood">Wood</option>
<option onClick='add("iron")' value="iron">Iron</option>
<option onClick='add("gold")' value="gold">Gold</option>
<option onClick='add("dust")' value="dust">Dust</option>
<option onClick='add("food")' value="food">Food</option>
</select>
Working jsfiddle here: http://jsfiddle.net/TcGt5/
<!-- language: lang-js -->
<script>
var jproducts = [];
var selectCount= 0;
function myFunction() {
var select = document.getElementById("mySelect");
// test if select value already exist
options = select.getElementsByTagName('option'),
for (var i=options.length; i--;) {
if (options[i].selected)
selectCount +=1;
if (function 'is_not_in_products_array')
jproducts.push(options[i].value)
}
// remove unselected products
for (var j=0; j< (jproducts.length-selectCount); j++;)
jproducts.shift();
}
</script>
Finnaly the products array will containt only the last selected
<select id="myselect" multiple="yes" name="products[]" onchange="myFunction()">
<option value="wood">Wood</option>
<option value="iron">Iron</option>
<option value="gold">Gold</option>
<option value="dust">Dust</option>
<option value="food">Food</option>

html - how can I display images when option from drop down menu is selected

I have the code for a drop down menu:
</center>
<p>
<center><select>
<option value="none">None selected</option>
<option value="cat">cat</option>
<option value="dog">dog</option>
</center></select>
</p>
I want to be able to display an image of a cat (such as http://www.petfinder.com/wp-content/uploads/2012/11/95142833-crate-training-cat-632x475.jpg) when the "cat" option is selected and also alternate text (such as "image of cat could not be loaded") if the image could not be loaded. How can I do this?
you can insert an image on value change in select box, i would do it like this:
html:
<select id="pic-changer">
<option value="none">None selected</option>
<option value="cat" data-picture="cat.png">cat</option>
<option value="dog" data-picture="dog.jpg">dog</option>
</select>
<div id="image-location></div>
jquery (javascript) code:
$('#pic-changer').change(function(){ //if the select value gets changed
var imageSource = $(this).find(':selected').data('picture'); //get the data from data-picture attribute
if(imageSource){ //if it has data
$('#image-location').html('<img src="'+imageSource+'">'); // insert image in div image-location
} else {
$('#image-location').html(''); //remove content from div image-location, thus removing the image
}
})
if you dont need the select box value, I would suggest putting the picture link in there:
<select id="pic-changer">
<option value="">None selected</option>
<option value="cat.png">cat</option>
<option value="dog.jpg">dog</option>
</select>
jQuery code becomes:
$('#pic-changer').change(function(){ //if the select value gets changed
var imageSource = $(this).val(); //get the selected value
if(imageSource && imageSource != ""){ //if it has data
$('#image-location').html('<img src="'+imageSource+'">'); // insert image in div image-location
} else {
$('#image-location').html(''); //remove content from div image-location, thus removing the image
}
})
You can do much more with javascript and jQuery i suggest you learn it, it ain't hard at all. http://jquery.com/
You asking Something which is not Possible by Simple HTML.
In Addition Of HTML Code you should use JavaScript.
I suggest you to Start learning Javascript.
here is the Link. http://www.tutorialspoint.com/javascript/
Lean it.. Implement it. You will reach your Goal.
All The Best..!!