google drive javascript api gapi.client.drive.files undefined - google-drive-api

The JavaScript example to list files of Google Drive uses gapi.client.drive.files.list().
When trying to use this method I get the error "Cannot read property 'files' of undefined".
The issue and a workaround are already described under Google Drive API javascript
Is the documentation under https://developers.google.com/drive/v2/reference/files/list#try-it incorrect? Or is there a way to use the API as described.

The JavaScript example is correct, but you have to make sure that you only use gapi.client.drive.files (and the other Drive-specific resources) when the Drive library is loaded, i.e. after:
gapi.client.load('drive', 'v2', callback);

If it works fine after writing gapi.client.load('drive', 'v2', callback), then all good. In my case it does not work so I wrote below code.
gapi.load('client', function () {
gapi.client.load('drive', 'v2', function () {
var file = gapi.client.drive.files.get({ 'fileId': fileId });
file.execute(function (resp) {
//Write you code with resp variable
});
});
});

Related

Add JQuery reference to custom function

I want to test calling an API in a custom function for Google Sheets. code.gs is as follows:
function TApi(input) {
var url = "https://api.nytimes.com/svc/search/v2/articlesearch.json";
url += '?' + $.param({
'api-key': "cdaa59fea5f04f6f9fd8fa551e47fdc4",
'q': "MIT"
});
$.ajax({
url: url,
method: 'GET',
}).done(function(result) {
return result;
console.log(result);
}).fail(function(err) {
throw err;
});
}
But when I call =TAPI() in a sheet cell, it returns an error ReferenceError: "$" is not defined. (line 22). I guess we need to add a link to JQuery. Does anyone know how to do this?
You can only use JQuery on client side scripts which use the HTML service. It is not available server side. There is a blurb about using it in the HTML Services Best Practices.
It's not possible. You must build either a web app or custom UI (sidebar or dialog) using HtmlService and do the processing on the client. Because your code runs on Google servers, there are no 'window' or 'document' objects. DOM and BOM are only accessible on the client.
In fact, feel free to do the following little experiment. Open your browser console (I'm using Chrome developer tools) and type in
console.log(this); //this logs global object
Here's the output
This is the 'window' object used by jQuery for navigating the DOM tree. jQuery is simply a JS library that builds on top of existing DOM manipulation methods and CSS selectors.
Next, open any GAS file, run the following function and check the Logs (Ctrl + Enter):
function test() {
Logger.log(this);
}
And here's the output.
As you can see, the global object in this context consists of Google-defined pseudo classes (GAS services).
You can use urlFetch app. Try the below snippet
function fetchURL() {
try {
var url = "https://api.nytimes.com/svc/search/v2/articlesearch.json";
url += '?api-key=cdaa59fea5f04f6f9fd8fa551e47fdc4&q=MIT';
var params = {
'method': 'get',
'contentType': 'application/json',
'muteHttpExceptions': true
}
var response = UrlFetchApp.fetch(url, params);
Logger.log(response)
} catch (e) {
Logger.log(e)
}
}

How to send information from window to the devtool in chrome extension

In my app I have a namespaced application and there's information or metadata myApp carries on it that might be useful to devpane.
window.myApp = new App();
How can I relay or send the following information to the devtool.js?
window.myApp.metadata; // information
And can I send a request from the devtool with a function that customizes the serialization of that metadata?
I've seen similar posts with the solution below, which returns null when I tried it.
chrome.devtools.inspectedWindow.eval("window.myApp", {
useContentScriptContext: true
})
NOTE: If a sample template can be provided that would be wonderful.
This is how I've solved this. It feels more complicated than necessary, but it does work.
In the context of the inspected window
Based on this question.
This is where you've got access to window.myApp.metadata and can put it into the data object.
var event = new CustomEvent("RebroadcastExtensionMessage", {data: ""});
window.dispatchEvent(event);
In the content script
This just forwards the data to the background page.
window.addEventListener("RebroadcastExtensionMessage", function(evt) {
chrome.runtime.sendMessage(evt)
}, false);
In the background page
Based on the Chrome docs.
chrome.runtime.onConnect.addListener(function(devToolsConnection) {
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
devToolsConnection.postMessage(request)
});
})
In devtools.js
var backgroundPageConnection = chrome.runtime.connect({
name: "devtools-page"
});
backgroundPageConnection.onMessage.addListener(function (message) {
// Data has arrived in devtools page!!
});

HTML5 File upload with AngularJS

I'm trying to get angular to read the contents of a file that the user selects through an <input type="file" control. Even though angular does not have directives for file upload controls, it should be easy to fix that with a call to $apply:
function MyController($scope) {
$('#myFile').on('change', function() {
var that = this;
$scope.$apply(function() { $scope.files = that.files });
});
}
Unfortunately, the event is never fired. It's like the selector is unable to refer to the correct DOM element: even though the selector finds the element, the list of files is always empty. This also happens if i poke around with the js console. The DOM inspector instead has the file list among its properties.
It's driving me crazy, but the only way I've got it to work so far is to use an inline event handler that assigns to a global variable. Why is the jquery selector returning another item? Is there some template compilation mumbo-jumbo that angular does which confuses selectors?
Here is what I do:
http://plnkr.co/edit/JPxSCyrxosVXfZnzEIuS?p=preview
app.directive('filelistBind', function() {
return function( scope, elm, attrs ) {
elm.bind('change', function( evt ) {
scope.$apply(function() {
scope[ attrs.name ] = evt.target.files;
console.log( scope[ attrs.name ] );
});
});
};
});
template:
<input type="file" filelist-bind name="files"/>
<p>selected files : <pre>{{ files | json }}</pre></p>
This kind of task, you definitely want to make use of directive.
But I think that your main concern is how to access the selected file
objects and my example should clarify that.
If you are looking for file upload with angular you can use this plugin
https://github.com/danialfarid/angular-file-upload
It is basically a directive like tosh's answer that takes care of non-HTML5 browsers with FileAPI flash polyfill and has $http.uploadFile function to upload the actual file via AJAX.
This site uses Angular service for HTML5 File Upload. A simple way is to setup a controller which calls the service and updates the UI when the asynchronous call is completed.
controller:
myapp.controller('fileUploadCtrl', ['$scope', '$q', 'FileInputService', function ($scope, $q, FileInputService) {
$scope.fileInputContent = "";
$scope.onFileUpload = function (element) {
$scope.$apply(function (scope) {
var file = element.files[0];
FileInputService.readFileAsync(file).then(function (fileInputContent) {
$scope.fileInputContent = fileInputContent;
});
});
};
}]);
service:
myapp.service('FileInputService', function ($q) {
this.readFileAsync = function (file) {
var deferred = $q.defer(),
fileReader = new FileReader(),
fileReader.readAsText(file);
fileReader.onload = function (e) {
deferred.resolve(e.target.result);
};
return deferred.promise;
};
});
template:
Choose File <input type="file" onchange="angular.element(this).scope().onFileUpload(this)">
<br />
{{fileInputContent}}
Reference: You can find the full source code and reference on this site.

Displaying multiple Google Maps asynchronously

I currently have a page which shows results of a search. When the user clicks on a result, details are fetched using ajax and loaded into the page. In these details, there is a Google map.
Previously, I had the Gmaps script with callback in the details page. But I ran into this problem that the Gmaps script was inserted multiples times if the user clicked on several results.
Now, I load the script in the results page and the details page calls the initialize function while passing all the necessary parameters. But I get an undefined is not a function error.
So my question is: how to structure the Gmaps script, callback, and asynchronous initializing of the maps between the two pages (results, and details)?
results page
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&key=[key]"></script>
function initialize(params) {
var directionsService, directionsDisplay, map;
directionsService = new google.maps.DirectionsService();
directionsDisplay = new google.maps.DirectionsRenderer();
// your typical gmaps stuff
}
details page
<div id="map_canvas"></div>
initialize(params);
You can just see if the Google Map's script has already loaded by checking for the "google" global variable that gets added to the DOM.
Full jsfiddle example here: http://jsfiddle.net/gavinfoley/yD8Qt/.
// dom ready
$(function () {
if (typeof google === "undefined") {
alert("Lazy loading Google maps");
lazyLoadGoogleMaps();
} else {
alert("Google Maps is already loaded");
googleMapsLoaded();
}
});
function lazyLoadGoogleMaps() {
// Note the callback function name
$.getScript("http://maps.google.com/maps/api/js?sensor=true&callback=googleMapsLoaded")
.done(function (script, textStatus) {
alert("Google maps loaded successfully");
})
.fail(function (jqxhr, settings, ex) {
alert("Could not load Google Maps: ", ex);
});
}
// This function name is passed in to the Google maps script load above
// and will be called once Google maps has loaded
function googleMapsLoaded() {
alert("Done!");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>

dojo: define module to load google maps api, (I am a bit lost)

Somebody can explain how to define dojo module (define/require) to use google maps api.
Thanks in advance.
(function(){
var callback = function(){},
callbackName = 'gmapscallback'+(new Date()).getTime();
window[callbackName] = callback;
define(['http://maps.googleapis.com/maps/api/js?sensor=true&callback=' + callbackName], function(){
return google.maps;
});
})();
src