Error in Apple's TVML documentation? pushPage function doesn't work - tvos

UPDATED 6/1/17 with the correct code pasted at the bottom.
I'm working through Apple's TVML guide, section 2: Navigating Between Pages. (https://developer.apple.com/library/content/documentation/TVMLKitJS/Conceptual/TVMLProgrammingGuide/NavigatingBetweenPages.html#//apple_ref/doc/uid/TP40016718-CH9-SW1)
Everything is fine until the last bit (Listing 4-4), which allow you to use the menu button on the remote to return to the previous page. Whenever I try it, my sample app simply won't load:
var baseURL;
function loadingTemplate() {
var template = '<document><loadingTemplate><activityIndicator><text>Loading</text></activityIndicator></loadingTemplate></document>';
var templateParser = new DOMParser();
var parsedTemplate = templateParser.parseFromString(template, "application/xml");
return parsedTemplate;
}
function getDocument(extension) {
var templateXHR = new XMLHttpRequest();
var url = baseURL + extension;
var loadingScreen = loadingTemplate();
templateXHR.responseType = "document";
templateXHR.addEventListener("load", function() {pushPage(templateXHR.responseXML, loadingScreen);}, false);
templateXHR.open("GET", url, true);
templateXHR.send();
}
function pushPage(page, loading) {
var currentDoc = getActiveDocument();
navigationDocument.replaceDocument(page, loading);
}
App.onLaunch = function(options) {
baseURL = options.BASEURL;
var extension = "templates/InitialPage.xml";
getDocument(extension);
}
What am I missing?
This works:
var baseURL;
function loadingTemplate() {
var template = '<document><loadingTemplate><activityIndicator><text>Loading</text></activityIndicator></loadingTemplate></document>';
var templateParser = new DOMParser();
var parsedTemplate = templateParser.parseFromString(template, "application/xml");
navigationDocument.pushDocument(parsedTemplate);
return parsedTemplate;
}
function getDocument(extension) {
var templateXHR = new XMLHttpRequest();
var url = baseURL + extension;
var loadingScreen = loadingTemplate();
templateXHR.responseType = "document";
templateXHR.addEventListener("load", function() {pushPage(templateXHR.responseXML, loadingScreen);}, false);
templateXHR.open("GET", url, true);
templateXHR.send();
}
function pushPage(page, loading) {
navigationDocument.replaceDocument(page, loading);
}
App.onLaunch = function(options) {
baseURL = options.BASEURL;
var extension = "templates/InitialPage.xml";
getDocument(extension);
}

Yes, I believe there is a mistake. They should have kept the line
navigationDocument.pushDocument(parsedTemplate);
at the end of the loadingTemplate method.
The idea is to push the loading page, then replace it with the new page.
On a side note, the line
var currentDoc = getActiveDocument();
has no business here. This code was obviously not tested or reviewed.

Related

How to hand an object from backend to frontend

I try to create a Web App. Therefor I have to pass an Object from the backend to the HTML-Script. I tried a lot of possibilites but nothing worked.
Backend
function searchMain (allSeaVal) {
var headCon = DbSheet.getRange(1, 1, 1, DbSheet.getLastColumn()).getValues();
var bodyCon = DbSheet.getRange(valRow, typesCol, 1, DbSheet.getLastColumn()).getValues();
var Con = {
headline: headCon,
values: bodyCon
};
var tmp = HtmlService.createTemplateFromFile('page_js');
tmp.Con = Con.map(function(r){ return r; });
return tmp.evaluate();
}
HTML
<script>
function searchValues() {
var allSeaVal = {};
allSeaVal.seaType = document.getElementById('valSearchTyp').value;
allSeaVal.seaVal = document.getElementById('HSearchVal').value;
google.script.run.searchMain(allSeaVal);
Logger.log(Con);
}
<script/>
I want to use the information in "Con" in the Website. The script-code is stored in the file "page_js.
I don´t know why but I can´t pass the information into the frontend.
In your html interface you have to use the success and failure handler in your google.script.run.
Code will looks like
google.script.run
.withSuccessHandler(
function(msg) {
// Respond to success conditions here.
console.log('Execution successful.');
})
.withFailureHandler(
function(msg) {
// Respond to failure conditions here.
console.log('Execution failed: ' + msg, 'error');
})
.searchMain(allSeaVal);
Do not hesitate to check the documentation : https://developers.google.com/apps-script/guides/html/communication
Stéphane
I solved my problem with your help. Thank you so much. I struggled with this many days.
My solution is the code below.
Backend
function searchMain (allSeaVal) {
var typesCol = searchTypesCol(allSeaVal.seaType);
var valRow = searchRow(allSeaVal.seaVal, typesCol);
var headCon = DbSheet.getRange(1, 1, 1, DbSheet.getLastColumn()).getValues();
var bodyCon = DbSheet.getRange(valRow, typesCol, 1, DbSheet.getLastColumn()).getValues();
var Con = {
headline: headCon,
values: bodyCon
};
return Con;
}
HTML
function searchValues() {
var allSeaVal = {};
allSeaVal.seaType = document.getElementById('valSearchTyp').value;
allSeaVal.seaVal = document.getElementById('HSearchVal').value;
google.script.run
.withSuccessHandler(
function(Con) {
console.log(Con + 'success');
})
.withFailureHandler(
function(Con) {
console.log(Con + 'failure');
})
.searchMain(allSeaVal);
}

Using lastmod as a function within gulp-sitemap with cheerio

I'm attempting to use the lastmod function in conjunction with cheerio (or gulp-cheerio) to pull a value from a meta tag from each file in the stream to populate this lastmod entry.
var gulp = require('gulp');
var cheerio = require('cheerio');
var sitemap = require('gulp-sitemap');
gulp.task('sitemap', function() {
return gulp.src(['/prod/**/*.html',])
.pipe(sitemap({
siteUrl: 'https://www.somewhere.com',
lastmod: function(file) {
var $ = cheerio.load(body);
var lastmodValue = $('head > meta[name="dc.date"]').attr('content');
return lastmodValue.toString().trim();
}
}))
.pipe(gulp.dest('/prod'));
});
This works fine if I hardcode a var before the return and comment out the cheerio statements. Gulp-sitemap lastmod instructions here: https://github.com/pgilad/gulp-sitemap#lastmod
Found my issue - Here's the code that works:
.pipe(sitemap({
siteUrl: 'https://www.somewhere.com',
lastmod: function(file) {
var $ = cheerio.load(file.contents);
var lastmodValue = $('head > meta[name="dc.date"]').attr('content');
return lastmodValue.toString().trim();
}
}))

How do I extend script execution time?

I have this script to delete all ._* files from my Google Drive. But there are millions of files, and the script quits after 5 minutes or so with "Exceeded maximum execution time."
function TrashDotFiles() {
var files = DriveApp.getFiles();
while (files.hasNext()) {
var file = files.next();
var name = file.getName();
if (name.indexOf("._")==0) {
console.log(name + " • trashed");
file.setTrashed(true)
}
}
}
How can I let this script run long enough to scan the entire Drive?
One of the possible workarounds is to run plain JavaScript code in modal window that has no limit of running time:
function onOpen()
{
var ui = SpreadsheetApp.getUi();
ui.createMenu('Trash dot files')
.addItem('Run', 'openWindow')
.addToUi();
}
function openWindow()
{
var ui = SpreadsheetApp.getUi();
// get template
var template = HtmlService.createTemplateFromFile('deleteDriveFiles');
// need to have next line of text somewhere (even commented out) to trigger correct scopes for script and token:
// DriveApp.getFiles()
// pass token
template.data = {
token: ScriptApp.getOAuthToken()
};
// get output html
var html = template.evaluate();
// show modal window
ui.showModalDialog(html, 'Delete files from Drive');
}
[File - New - Html file] deleteDriveFiles.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<script>
// used for visual log
function addParagraph(text)
{
var node = document.createElement('p');
node.innerText = text;
document.body.appendChild(node);
}
// for stats
var totalProcessed = 0;
var totalTrashed = 0;
function reqListener(){
// get response obj
var res = JSON.parse(this.responseText);
if (res.items && res.items.length)
{
// loop files
for (var i = 0; i < res.items.length; i++)
{
var file = res.items[i];
// delete file
if (file.title.indexOf('._') == 0)
{
var xhr = new XMLHttpRequest();
xhr.addEventListener('load', function(){
// get response obj
var res = JSON.parse(this.responseText);
// sucessfully trashed
if (this.status == 200)
{
totalTrashed++;
addParagraph('Trashed '+res.title);
}
}.bind(xhr));
xhr.open('POST', 'https://www.googleapis.com/drive/v2/files/'+file.id+'/trash');
xhr.setRequestHeader('Authorization', 'Bearer <?=data.token?>');
xhr.send();
}
}
// for stats
totalProcessed += res.items.length;
}
// get next page of results
if (res.nextPageToken)
{
var xhr = new XMLHttpRequest();
xhr.addEventListener('load', reqListener);
xhr.open('GET', 'https://www.googleapis.com/drive/v2/files?trashed=false&pageToken='+res.nextPageToken);
xhr.setRequestHeader('Authorization', 'Bearer <?=data.token?>');
xhr.send();
}
// finished
else
{
addParagraph('Finished. Processed total: '+totalProcessed+'. Trashed total: '+totalTrashed);
}
}
var xhr = new XMLHttpRequest();
xhr.addEventListener('load', reqListener);
xhr.open('GET', 'https://www.googleapis.com/drive/v2/files?trashed=false');
xhr.setRequestHeader('Authorization', 'Bearer <?=data.token?>');
xhr.send();
</script>
</body>
</html>
After saving changes in code and refreshing spreadsheet web page you will see new menu item:
Click on Run to start processing files.
Result:

Flash hyperlink - changing var name in url

I have trouble with hyperlink in flash on site. As site is in CMS, with different
stages of approval I do not know exact url, so
function piClick(e:MouseEvent):void
{
var url:String = "/cms__Main?name=Target_name";
var request:URLRequest = new URLRequest(url);
try {
navigateToURL(request, '_self');
} catch (e:Error) {
trace("Error occurred!");
}
}
does not work, as cms_Main changes according to stage of site. What I probably need to do is:
grab url (or part after last "/" if that is even possible)
change "name" variable inside String
f.e
https://domain_name/.../status?name=Name_I_need_to_swap&sname=Country_name&..
stage.loaderInfo.url will get you the address of the swf itself so it won't get you the full address, the query or the hash tag. You can, however, grab all this information using Javascript.
import flash.external.ExternalInterface;
function getFullAddress():String {
if (ExternalInterface.available) {
var href:String = ExternalInterface.call('function(){return window.location.href}');
if (href) return href.toString();
}
throw new Error('Make sure JS is enabled.');
}
var fullAddr:String = getFullAddress();
EDIT: Here's how you can get and modify all that you're asking.
import flash.external.ExternalInterface;
import flash.net.URLVariables;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.net.navigateToURL;
function getFullAddress():String {
if (ExternalInterface.available) {
var href:String = ExternalInterface.call('function(){return window.location.href}');
if (href) return href.toString();
}
throw new Error('Make sure JS is enabled.');
}
function getQuery(fullAddr:String):URLVariables {
if (!fullAddr.match(/\?[^#]/)) return new URLVariables();
var q:String = fullAddr.replace(/^.*?\?([^#]+)(#.*)?$/,'$1');
return new URLVariables(q);
}
function getAddress(fullAddr:String):String {
return fullAddr.replace(/\?.*/,'').replace(/#.*/,'');
}
function getRequest(url:String,query:URLVariables=null,method:String='GET'):URLRequest {
method = URLRequestMethod[method] || 'GET';
var req:URLRequest = new URLRequest(url);
req.method = method;
if (method == 'GET' && query != null) {
req.url += '?' + query.toString().replace(/%5f/gi,'_').replace(/%2d/gi,'-');
// this is because dash and underscore chars are also
// encoded by URLVariables. we want to omit this.
return req;
}
req.data = query;
return req;
}
var fullAddr:String = getFullAddress();
var addr:String = getAddress(fullAddr);
var query:URLVariables = getQuery(fullAddr);
query.name = 'Name_I_need_to_swap';
query.sname = 'Country_name';
// add as many variable-value pairs as you like
// and don't worry, they will be automatically
// encoded by the function called below
var req:URLRequest = getRequest(addr,query);
//navigateToURL(req);
// check the console to see the changed address
ExternalInterface.call('console.log',req);
you can get URL with this.loaderInfo.url

Fileupload using Filereader in chrome

I have to upload a file from the local memory of application (HTML5 File api). Onselect, the user should be able to upload directly without any question. The idea is to manage download/upload seamless to the user. Here is the code :
$("body").on("click", ".upload-file", function(e){
var fileToUpload = $('input:radio[name=optionsRadios]:checked').val();
var formData = new FormData();
$('input:radio[name=optionsRadios]:checked').parent().parent().parent().remove();
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.TEMPORARY, 50*1024*1024, initFS, errorHandler);
var reader = new FileReader();
function initFS(fs){
fs.root.getDirectory('/', {}, function(dirEntry){
var dirReader = dirEntry.createReader();
dirReader.readEntries(function(entries) {
for(var key = 0; key < entries.length; key++) {
var entry = entries[key];
if (entry.isFile){
var name = entry.name;
if(name == fileToUpload){
getAsText(entry.toURL());
formData.append('file', entry.toURL);
break;
}
}
}
}, errorHandler);
}, errorHandler);
}
function errorHandler(){
console.log('An error occured');
}
function getAsText(readFile) {
alert ("getting as text :" +readFile);
var reader = new FileReader();
// Read file into memory as UTF-16
reader.readAsText(readFile, "UTF-16");
// Handle progress, success, and errors
reader.onprogress = updateProgress;
reader.onload = loaded;
reader.onerror = errorHandler;
}
function loaded(evt) {
// Obtain the read file data
alert("loaded file");
var fileString = evt.target.result;
// Handle UTF-16 file dump
if(utils.regexp.isChinese(fileString)) {
//Chinese Characters + Name validation
}
else {
// run other charset test
}
// xhr.send(fileString)
}
var serverurl = "/fileserver/uploadFile?selpath="+fileToUpload;
var xhr = new XMLHttpRequest();
xhr.open('POST', serverurl);
xhr.onload = function () {
if (xhr.status === 200) {
console.log('all done: ' + xhr.status);
} else {
console.log('Something went terribly wrong...');
}
};
xhr.send(formData);
});
Now, I am trying to read the file as text (its a bad practice but wanted to find someway to make it work) but it doesn't throw any events. Can you please help me to find where I am going wrong ?