How to add googlesheet checkbox to the google sheet toolbar - google-sheets

I am a starter in coding in Googlesheets (google scripts). I want to create a google script to add a checkbox to the toolbar of the google sheet. Can anybody help me on this?

You cannot add a checkbox into the toolbar but you can create an HTML custom sidebar with checkboxes
For this, use Google Apps Script
Follow the guide for custom sidebar creation
Create an html file with checkboxes
Use google.script.run to communicate between serverside and client side of the code
Sample:
Code,gs
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Custom Menu')
.addItem('Show sidebar', 'showSidebar')
.addToUi();
}
function showSidebar() {
var html = HtmlService.createHtmlOutputFromFile('index')
.setTitle('My custom sidebar')
.setWidth(300);
SpreadsheetApp.getUi()
.showSidebar(html);
}
function setValue(checked) {
var value;
if(checked == true){
value = "number 1";
} else{
value = "number 2";
}
var ss = SpreadsheetApp.getActiveSpreadsheet();
var cell = ss.getActiveSheet().getActiveCell();
cell.setValue("You clicked the checkbox: " + value);
};
index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div>
<input id="check" type="checkbox" >Click me <br>
<input type="checkbox" > Or me <br>
<input type="button" value="set value" onclick="evaluateInput()">
</div>
<script>
function evaluateInput() {
var checkedFirst = document.getElementById("check").checked;
google.script.run
.withFailureHandler(onFailure)
.setValue(checkedFirst);
};
function onFailure(error) {
console.log(error.message);
};
</script>
</body>
</html>

Related

Dynamic dropdown option load dissapears html modal dialog

My Html form has dropdown which load dynamic options using api request. I'm using google HTML Service to link google app script with html file. My problem is my modal dialog getting disappear as soon as it appears.
======== Script ========
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Call API')
.addItem('Display results','html')
.addToUi();
}
function html(){
var html = HtmlService.createTemplateFromFile('load');
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.showModalDialog(html, 'Input API Creddentials');
}
function getClients() {
var response = UrlFetchApp.fetch("http://myurl does here");
var fact = JSON.parse(response.getContentText());
var optionsHTML = [];
for (var i = 0; i < fact.length-1;i+=1) {
optionsHTML.push(fact[i].clientId.client);
}
SpreadsheetApp.getUi().alert(optionsHTML);
return optionsHTML;
}
======= HTML File ====
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form >
<div>
<select id="optionList" name="optionList">
<option>Loading...</option>
</select>
</div>
Username:
<input type="text" name="username"> <br />
Password:
<input type="password" name="password"> <br />
<input type="button" value="OK" onclick="google.script.run.callNumbers(this.parentNode);google.script.host.editor.focus();" />
</form>
</body>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js">
</script>
<script>
// The code in this function runs when the page is loaded.
$(function () {
google.script.run.withSuccessHandler(buildOptionList)
.getClients();
});
function buildOptionList(clients) {
var list = $('#optionList');
list.empty();
for (var i = 0; i < clients.length; i++) {
list.append(new Option(clients[i]));
}
}
</script>
</html>
The problem occurs due to
// The code in this function runs when the page is loaded.
$(function () {
google.script.run.withSuccessHandler(buildOptionList)
.getClients();
});
because getClients() shows an alert and Google Apps Script doesn't allow to have a Google Sheets UI alert and modal dialog shown simultaneosly.

How do I create the range picker in my google spreadsheet add-ons

I want to create my spreadsheet add-on. How can I implement the range picker like the picture:
I know the app script can use this:
SpreadsheetApp.getActiveSpreadsheet().getActiveRange().getA1Notation();
But I don't know how to send the result to the add-on html input text.
The code from this Medium post (author Piyush Goel) seems to do the trick. The range should be selected by the user before to click the button.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
</head>
<body>
<div class="sidebar branding-below">
<div class="block form-group">
<label for="names-range"><b>Comissions</b></label>
<input id="names-range" type="text" placeholder="Specify Range.." value=""/>
<button class="blue" id="names-range_button" onClick="getSelectedRange(this);">Get Selected Range</button>
</div>
<div class="block form-group">
<label for="ages-range"><b>Easyship Handling Fees</b></label>
<input id="ages-range" type="text" placeholder="Specify Range.." value=""/>
<button class="blue" id="ages-range_button" onClick="getSelectedRange(this);">Get Selected Range</button>
</div>
</div>
<div class="sidebar bottom">
<span class="gray">
Code sample by Piyush Goel</span>
</div>
<script>
function getSelectedRange(button){
button.innerHTML = "Picking.."; // Change the button value while getting range
button.disabled = true; // Disable the button while getting range
google.script.run // Executes a Apps Script JS Function
.withSuccessHandler(updateTextField) // function to be called upon successfull completion of Apps Script function
.withUserObject(button) // To pass the event element object
.getSelectedRange(); // Apps Sript JS Function
return;
}
// Function to be called on success
function updateTextField(range, button){
var textFieldId = button.id.split("_").shift();
document.getElementById(textFieldId).value = range; // Update the text field value
button.innerHTML = "Get Selected Range"; // Reset the button value
button.disabled = false;
}
</script>
</body>
</html>
// Add the options to the custom menu
function onOpen() {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.createMenu('Custom Menu')
.addItem('Show Settings', 'showSidebar')
.addToUi();
}
// initiates the sidebar
function showSidebar() {
var html = HtmlService.createHtmlOutputFromFile('settings')
.setTitle('Settings Sidebar')
.setWidth(300);
SpreadsheetApp.getUi().showSidebar(html);
}
/** Function to pick the selected range from the Google Sheet
* This returns the picked range, so that the client-side JS
* function (in HTML file) can populate it in the text field **/
function getSelectedRange(){
var selected = SpreadsheetApp.getActiveSheet().getActiveRange(); // Gets the selected range
var rangeString = selected.getA1Notation(); // converts it to the A1 type notation
return rangeString;
}

jquery load() will only load the html from the extermal page, no stylesheet or jquery ui

I have two pages. For explanations sake I'll call them page A and Page B. When I open page B in my browser it is rendered with all the styling and jquery ui code working properly, but when I open page B inside of a div in Page A via the load() method, the only thing that renders is the raw html, no styling, no interfaces. What is the problem? Directly below is the code from page B and all the way at the bottom is the code from page A:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script> //jquery ui
<link rel="stylesheet" href="http://spilot.koding.com/lbStyle.css"/> //stylesheet
<script src="http://www.parsecdn.com/js/parse-1.2.2.min.js"></script> //parse database
<script>
$(function(){
var crowd = ' ';
var ageGroup = ' ';
var activity = [];
var scene = [];
var neighborhood = [];
var date = [];
var details = [];
var time = [];
Parse.initialize("ivHLAO7z9ml1bBglUNuPSgcWabXe3UeE2yCgKM2x","gNeGt04lU7xcew893EvbEJ05qqc4POVhBsIBSCVj");
$(".menu").menu({
select: function (event, ui) {
$('.selected', this).removeClass('selected');
var selection = ui.item.addClass('selected').children('a').attr('name'); //add background color to selected menu item and get its attribute name
var choice = ui.item.text(); //get text of menu selection
if(selection == "ageGroup"){
$("#ageGroup").text(choice); //change the text in the first <a> of ageGroup menu to ageGroup selection.
ageGroup = $("#ageGroup").text();
}else{
crowd = selection;
};
} // closes select function
}); // closes menu
$("button").click(function(){
var city = JSON.parse( localStorage.getItem('city') );
var niche = Parse.Object.extend(crowd);
var query = new Parse.Query(niche);
query.equalTo("ageGroup", ageGroup);
query.equalTo("city", city);
//query.include([activity.date.details.location.neighborhood.time])
query.find({
success: function(results) {
for (i = 0; i < results.length; i++){
activity = results[i].get("activity");
scene = results[i].get("location");
neighborhood = results[i].get("neighborhood");
date = results[i].get("date");
details = results[i].get("details");
time = results[i].get("time");
};
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
//alert("working");
}); //closes click()
}); // close function()
</script>
<script>
$(function(){
$( "button" ).button();
});
</script>
</head>
<body>
<div id="div1">
<button>Button label</button>
<div id="div2">
<ul class="menu">
<li>
Age Group
<ul>
<li>18-21</li>
<li>21-30</li>
<li>30-40</li>
<li>40-50</li>
<li>50-60</li>
<li>60-70</li>
<li>70-80</li>
<li>80-90</li>
<li>90-100</li>
</ul>
</li>
</ul>
</div>
<div id="div3">
<ul class="menu" id="menu">
<li><img src="" alt="" /><h2>Academic: Art Studies</h2></li>
<li><img src="" alt="" /><h2>Academic: Literature</h2></li>
<li><img src="" alt="" /><h2>Academic: Social Sciences</h2></li>
<li><img src="" alt="" /><h2>Academic: Physical/Natural Sciences</h2></li>
</ul>
</div>
</div>
</body>
</html>
--------------//PAGE A//--------------
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script>
$(function(){
$("#mainDiv").load("http://myURl.com/find2.html"); //this is where I call load()
});
</script>
</head>
<body>
//this is the div where I want the other page to load
<div id="mainDiv">
</div>
</body>
</html>
since you are loading page "b" into page "a", you need to have all page "b" stylesheets/js in page "a" header.
please note that you are loading a complete html page into page "a", that includes html,header,body and that is not desirable, you should make page "b" a template that only contains the markup you need.
UPDATE:
you are embedding your scripts in the html, that is a bad practice, separate the JS code to different files.
When you include JS code in your file it will run as soon as the page loads, so if you put 'pageb' code in 'pagea' it will run as soon as 'pagea' was loaded and when you load 'pageb' the code will not run again.
You need to put 'pageb' code in a function and call it only after you loaded 'pageb' content.

angularjs and value of jqueryui datepicker input box

I have a datapicker of jqueryUI:
<div class="span4">
<label>Start Date; </label>
<input type="text" name="sDate" id="datepicker1" ng-model="item.date.sDate" class="ng-pristine ng-valid hasDatepicker">
<label>End Date; </label>
<input type="text" name="eDate" id="datepicker2" ng-model="item.date.eDate" class="ng-pristine ng-valid hasDatepicker">
<br> <br>
<button ng-click="add()" type="submit" class="btn btn-success">Next</button>
The datepicker is working fine, but when i click Next button which trigger the add function, I cannot get item.date.eDate value...
I've just been trying the same thing, and found that I didn't actually need to use a directive, just this code...
$.datepicker.setDefaults({
// When a date is selected from the picker
onSelect: function(newValue) {
if (window.angular && angular.element)
// Update the angular model
angular.element(this).controller("ngModel").$setViewValue(newValue);
}
});
Just place it prior to your .datepicker() initialisation code.
AngularJS and jQuery don't work too well together. You need to use a directive. Here's a quick sample app version I created for you:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.0/themes/base/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.8.3.js"></script>
<script src="http://code.jquery.com/ui/1.10.0/jquery-ui.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js"></script>
<script>
function putObject(path, object, value) {
var modelPath = path.split(".");
function fill(object, elements, depth, value) {
var hasNext = ((depth + 1) < elements.length);
if(depth < elements.length && hasNext) {
if(!object.hasOwnProperty(modelPath[depth])) {
object[modelPath[depth]] = {};
}
fill(object[modelPath[depth]], elements, ++depth, value);
} else {
object[modelPath[depth]] = value;
}
}
fill(object, modelPath, 0, value);
}
var directives = angular.module('myApp', []);
directives.directive('datepicker', function() {
return function(scope, element, attrs) {
element.datepicker({
inline: true,
dateFormat: 'dd.mm.yy',
onSelect: function(dateText) {
var modelPath = $(this).attr('ng-model');
putObject(modelPath, scope, dateText);
scope.$apply();
}
});
}
});
function myCtrl($scope) {
$scope.item = ""
$scope.add = function() {
$scope.$apply()
alert($scope.item)
}
}
</script>
</head>
<body ng-app="myApp">
<div ng-controller="myCtrl">
{{item}}
<p>Date: <input type="text" datepicker id="datepicker" ng-model="item" /></p>
<button ng-click="add()" type="submit" class="btn btn-success">Next</button>
<br />
</div>
</body>
</html>
Check out http://www.grobmeier.de/angular-js-binding-to-jquery-ui-datepicker-example-07092012.html for a a more thorough explanation.
just need to replace this element.datepicker({ to $(element).datepicker({
directives.directive('datepicker', function() {
return function(scope, element, attrs) {
$(element).datepicker({
inline: true,
dateFormat: 'dd.mm.yy',
onSelect: function(dateText) {
var modelPath = $(this).attr('ng-model');
putObject(modelPath, scope, dateText);
scope.$apply();
}
});
}
});
Actually turns out you don't have to make any inline directive or play around with the $.datepicker.
Only helpful i came up with was to get the value of datepicker element not by the ng-model directive.
suppose you have 3 inputs, first name, last name and date of birth. the date of birth input contains the jquery ui datepicker.
get the value of first name and last name input by ng-model directive< BUT to get the value of date of birth, just use jquery .val() function.

jquery unable to bind functions

I am trying to attach onBlur and onFocus handler to a SSN input field. However, I am seeing an error saying object has no method 'ON'. The code is at http://jsfiddle.net/H4Q5f/
As you can see, I commented out to figure out the details, however had no luck so far. Any help is appreciated. For convenience, here is the code:
HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Test Page</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css" />
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script>
<script type="text/javascript" src="../../appjavascript/ssa/mkwr/mytest.js"></script>
</head>
<body>
<div data-role="page" id="MyTestPage">
<div data-role="header" data-position="fixed" data-logo="true" data-tap-toggle="false" data-fullscreen="false" >
<h1> Page Title </h1>
</div>
<div data-role="content">
<div class="content-primary divcontent">
<h1 class='h1title'>Using This App</h1>
<p> Here are the instructions </a>
</p>
</div>
<div class="inputdata">
<br /> <br />
<input type="text" name="accessCode" id="AccessCode" value="" placeholder="Access Code:" /> <br />
<input type="text" id="ssn1" class="ssn" value="" placeholder="SSN1:" /> <br />
<input type="text" id="ssn2" class="ssn" value="" placeholder="SSN2:" /> <br />
</div>
<input type="button" id="myalert" value="Next" />
</div>
<!-- /content -->
</body>
</html>
And here is the java script
if (typeof TEST == "undefined" || !TEST) {
var TEST = {};
}
( function() {
TEST.mkwr = {
init : function() { // this is a public function
$("[data-role='page']").on("pagebeforeshow", TEST.mkwr.hideError());
$("[data-role='page']").on("pageshow", TEST.mkwr.setHandlers());
},
// On Blur, we need to add the '-'s if they doesn't exist so the user
// view edit the entered value formatted
ssnOnBlurHandler : function(input) { // Auto format SSN on blur
if ($(input).val().length == 9) {
var _ssn = $(input).val();
var _ssnSegmentA = _ssn.substring(0, 3);
var _ssnSegmentB = _ssn.substring(3, 5);
var _ssnSegmentC = _ssn.substring(5, 9);
$(input).val(
_ssnSegmentA + "-" + _ssnSegmentB + "-" + _ssnSegmentC);
}
}, // _ssnOnBlurHandler
// On focus, we need to remove the '-'s if they exist so the user
// can edit the entered value
ssnOnFocusHandler : function(input) {
// allow backspace, tab, delete, arrows, numbers and keypad numbers ONLY
if ($(input).val().length == 11) {
var _ssn = $(input).val();
var _ssnSegmentA = _ssn.substring(0, 3);
var _ssnSegmentB = _ssn.substring(4, 6);
var _ssnSegmentC = _ssn.substring(7, 11);
$(input).val(_ssnSegmentA + _ssnSegmentB + _ssnSegmentC);
}
}, // _ssnOnFocusHandler
// Hide all errors
hideError : function() {
$(".error").hide(); // Hide all errors
},
setHandlers : function() {
alert("Set Handlers");
// $(".ssn").each( function() {
// var input = this; input.blur(TEST.mkwr.ssnOnBlurHandler(input))
// });
// $(".ssn").each( function() {
// var input = this; input.focus(TEST.mkwr.ssnOnFocusHandler(input))
// });
}
};
})(); // end the anonymous function
$("[data-role='page']").bind("pageinit", TEST.mkwr.init());
I found a couple of issues with the code on the jsfiddle. Here is an updated one that is working to fire handlers and parse code. It looks like your ssn logic might need to be fixed a little but everything is getting you to there.
http://jsfiddle.net/H4Q5f/10/
The problems I saw were partly what was mentioned before you were using .on instead of .bind given the jquery version. But also you were not setting your handlers but rather firing your handlers. You had this:
input.bind("blur",TEST.mkwr.ssnOnBlurHandler(input))
which would return the result of the function to the set method which is not what you were looking for. So I changed it to this:
input.bind("blur",TEST.mkwr.ssnOnBlurHandler)
So now you are passing the handler to the set method so that it will fire when the event takes place.
Hope this makes sense.
The .on() function was introduced in jQuery 1.7. The code you've posted above includes jQuery 1.6.4 (<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>), which doesn't have that function. You can either upgrade to the latest version of jQuery (recommended) or use the equivalent function - .bind() - for the older versions.

Resources