While creating a new Client-Server tvOS App, tvOS will not get the data from my external tvml file. This is the Error: ITML <Error>: Failed to load launch URL with error: (null)
This is the main.js code
function getDocument(url) {
var templateXHR = new XMLHttpRequest();
templateXHR.responseType = "document";
templateXHR.addEventListener("load", function() {pushDoc(templateXHR.responseXML);}, false);
templateXHR.open("GET", url, true);
templateXHR.send();
return templateXHR;
}
function pushDoc(document) {
navigationDocument.pushDocument(document);
}
App.onLaunch = function(options) {
var templateURL = 'niclasblog.com/appletv/main.tvml';
getDocument(templateURL);
}
App.onExit = function() {
console.log('App finished');
}
And I have attached the main.tvml file as well
<document>
<alertTemplate>
<title>Test</title>
<description>This is a test</description>
<button>
<text>Yes</text>
</button>
<button>
<text>No</text>
</button>
</alertTemplate>
</document>
That code is directly from the Apple Documentation, so I do not know why it is not working.
In your App.onLaunch function you could get the BASEURL and use this for loading all your assets:
App.onLaunch = function(options) {
var BASEURL = options.BASEURL;
// etc.
}
You can also consider a different approach to loading templates. Consider using a DOMParser to parse an XML String. This way you can write Multiline template strings with "real" content e.g.
getDocument(options) {
let parser = new DOMParser();
let templateString = `<?xml version="1.0" encoding="UTF-8" ?>
<document>
<alertTemplate>
<description>${options.translate.errorRandomErrorAlertText}</description>
<button>
<text>${options.translate.utilOk}/text>
</button>
</alertTemplate>
</document>`;
return parser.parseFromString(templateString, "application/xml");
}
I've written a generator for specfically for Apple TVML apps using es6, its still early in its development, but might help you get started.
Try replacing this
var templateURL = 'niclasblog.com/appletv/main.tvml';
with fully qualified URI
var templateURL = 'https://niclasblog.com/appletv/main.tvml';
Also
templateXHR.responseType = "document";
is not needed as that seem to be the default behavior.
Related
I am using gnuplot-js https://github.com/chhu/gnuplot-JS when I am without my laptop at university.
Is it possible to use an external url for gnuplot.js file? I host index.html, gnuplot_api.js on https://mywebsite.com/ but I would like to use another url for gnuplot.js file (for example https://external.com/blabla/ok/no/gnuplot.js) because this file is really big!
Maybe this is the part I should edit on index.html. How? :
<script src='gnuplot_api.js'></script>
<script>
gnuplot = new Gnuplot('gnuplot.js');
gnuplot.onOutput = function(text) {
document.getElementById('output').value += text + '\n';
document.getElementById('output').scrollTop = 99999;
};
or maybe this part on gnuplot_api.js?:
var Gnuplot = function(js_filename) {
this.worker = new Worker(js_filename);
this.output = [];
this.error = [];
this.isRunning = false;
Thank you very much for your support
It appears Gnuplot use an onboard webworker, so the path provided to the constructor should be on the same domain than the script.
<script src='https://cdn.jsdelivr.net/gh/chhu/gnuplot-JS/www/gnuplot_api.js'></script>
<script>
gnuplot = new Gnuplot('https://cdn.jsdelivr.net/gh/chhu/gnuplot-JS/www/gnuplot.js');
</script>
This question may be asked previously but they have no answer. I try to create a pdf file using pdfkit library with Arabic language support. So, first I downloaded a prebuilt version of pdfkit (which is assumed to work in browser) from here.
Then I wrote this code for adding an Arabic font (like in the docs)
const doc = new PDFDocument;
var text_arabic = "مرحبا مَرْحَبًا";
// Using a TrueType font (.ttf)
doc.font('./trado.ttf') // --> this line gives the error.
.text(text_arabic)
.moveDown(0.5);
The error is:
Uncaught ReferenceError: fs is not defined
at Object.fontkit.openSync (pdfkit.js:10949)
at Function.PDFFont.open (pdfkit.js:451)
at PDFDocument.font (pdfkit.js:2227)
at main.js:22
pdfkit.js from line 10949:
fontkit.openSync = function (filename, postscriptName) {
var buffer = fs.readFileSync(filename); / --> error
return fontkit.create(buffer, postscriptName);
};
So, I think 'fs' belongs to node.js part with require('fs') but anyway I don't know the solution. What is the solution then? Thanks in advance!
Here is the simple solution;
Don't forget to add pre-built pdfkit.js and blob-stream.js files
Copy below js code and include it in your html
Put your fonts to the same place with html/js (like trado.ttf)
Change the getFont(...) according to your font name
Done!
Important Notes:
If you run it without any server, chrome will give CORS policy error. (See this to disable just for try)
When you move your files to a server, or running in local server, there will be no CORS error.
Last and most importantly, give some times to xhr.onload. Because of that we create writeToPDF() function seperately for using with a button after loading.
const doc = new PDFDocument;
const stream = doc.pipe(blobStream());
var embeddedFonts = (function() {
var fontCollection = {};
function getFont(name, src) {
var xhr = new XMLHttpRequest();
xhr.open('GET', src, true);
xhr.responseType = "arraybuffer";
xhr.onload = function(evt) {
var arrayBuffer = xhr.response;
if (arrayBuffer) {
fontCollection[name] = new Uint8Array(arrayBuffer);
registerEmbeddedFonts(doc, embeddedFonts);
} else {
error = "Error downloading font resource from " + src;
}
};
xhr.send(null);
}
getFont("Trado", 'trado.ttf');
return fontCollection;
}());
function registerEmbeddedFonts(doc, fontCollection) {
doc.registerFont("Trado", fontCollection["Trado"]);
}
function writeToPDF() {
doc.fontSize(40);
doc.font('Trado').text('مَرْحَبًا');
doc.end();
stream.on('finish', function() {
// get a blob you can do whatever you like with
const blob = stream.toBlob('application/pdf');
// or get a blob URL for display in the browser
const url = stream.toBlobURL('application/pdf');
var frame = document.getElementById("pdfFrame");
frame.src = url;
});
}
<script src="https://github.com/foliojs/pdfkit/releases/download/v0.8.0/pdfkit.js"></script>
<script src="https://github.com/devongovett/blob-stream/releases/download/v0.1.3/blob-stream.js"></script>
<iframe id="pdfFrame" src="" width="300" height="300"> </iframe>
<button type="button" onclick="writeToPDF();">Write to PDF</button>
<!-- This example doesn't work because of missing trado.ttf font file.
Try to run at your PC -->
I understand that providing a physical file path to javascript is not possible due to security reasons. However, when I look at Mozilla's pdf.js and mupdf android pdf viewer I see this is very much possible. There is a mechanism by which I can pass a file path to javascript. I explored into PDF.js but it seemed little difficult to make use of when I needed a simple solution.
I want to pass android internal storage file location onto the following code instead of using input id="files" type="file" which requires me to browse and select file. In my case I want to just pass file location from sdcard.
The following code actually loads ms word (docx) file as html which I then will show in webview in my project. In the case of pdf.js we were using it to display pdf in the similar way.
<script>
$(document).ready(function(){
//Input File
var $files = $('#files');
//File Change Event
$files.on('change', function (e) {
//File Object Information
var files = e.target.files;
//Create DocxJS
var docxJS = new DocxJS();
//File Parsing
docxJS.parse(
files[0],
function () {
//After Rendering
docxJS.render($('#loaded-layout')[0], function (result) {
if (result.isError) {
console.log(result.msg);
} else {
console.log("Success Render");
}
});
}, function (e) {
console.log("Error!", e);
}
);
});
});
</script>
<input id="files" type="file" name="files[]" multiple="false" />
<div id="loaded-layout" style="width:100%;height:800px;">
</div>
You can check code of PDF.JS based pdfviewer in android here.
What I found on the PDF.js code which was used to input file :
In pdffile.js included in index.html file, url variable was mentioned pointing to real location of the file i.e. in assets folder which then was used in pdf.js but at that point the usage seems confusing. Is there any way by which I can use real path of file or pass real path somehow in android for my purpose of viewing docx?
UPDATE :
I find that PDF.js by Mozilla actually treats file location as a url and so the file in the url is converted to javascript file object or blob. Hence I create a blob of the url from server using Ajax :
var myObject;
var xhr = new XMLHttpRequest();
xhr.open("GET","10143.docx",true); // adding true will make it work asynchronously
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200){
//do some stuff
myObject = this.response;
}
};
xhr.send();
$(document).ready(function(){
//Input File
var $files = $('#files');
//File Change Event
$files.on('change', function (e) {
//File Object Information
var files = myObject.files;
//Create DocxJS
var docxJS = new DocxJS();
//File Parsing
docxJS.parse(
blobToFile(myObject, "10143.docx"),
function () {
//After Rendering
docxJS.render($('#loaded-layout')[0], function (result) {
if (result.isError) {
console.log(result.msg);
} else {
console.log("Success Render");
}
});
}, function (e) {
console.log("Error!", e);
}
);
});
});
function blobToFile(theBlob, fileName){
//A Blob() is almost a File() - it's just missing the two properties below which we will add
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
}
However now that I do that I get Parsing error from DocxJS like : {isError: true, msg: "Parse Error."}
This is related to another question, but is not a duplicate.
It deals with a proposed solution that I have reached an impasse.
I have the following code that reads an XML, makes changes, opens a window, and writes the XML into the document. The problem is that the content is not rendered as XML.
Any way to set a content type, etc, to have the browser handle the content as XML?
<script>
var wxml;
var xDoc;
var xDevices, xInputs;
var xDevice, xInput;
function fSetXmlAInput(iDevice, iNode, nodeNewVal) {
xInput = xInputs[iNode];
xValue = xInput.getElementsByTagName("value")[0];
// change node value:
// console.log("nodeVal: " + xValue.firstChild.nodeValue);
xValue.firstChild.nodeValue = nodeNewVal;
// console.log("newVal: " + xValue.firstChild.nodeValue);
}
function fSetXmlDevice(iDevice) {
xDevice = xDevices[iDevice];
xInputs = xDevice.getElementsByTagName("input");
fSetXmlAInput(iDevice, 0, "22");
fSetXmlAInput(iDevice, 1, "33");
}
function alternativeLoadXML3() {
// load xml file
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else { // IE 5/6
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xhttp.open("GET", "my_template.xml", false);
xhttp.send();
xDoc = xhttp.responseXML;
xDevices = xDoc.getElementsByTagName("device");
fSetXmlDevice(1);
var xmlText = serializeXmlNode(xDoc);
var newWindow = window.open("my_template.xml", "Test", "width=300,height=300,scrollbars=1,resizable=1");
newWindow.document.open();
newWindow.document.write(xmlText);
newWindow.document.close()
};
</script>
Below the XML as well:
<?xml version="1.0" encoding="utf-8"?>
<myXmlRoot>
<device>
<input><name>"name 1"</name><value>{replaceMe!}</value></input>
<input><name>"name 2"</name><value>{replaceMe!}</value></input>
</device>
<device>
<input><name>"name 1"</name><value>{replaceMe!}</value></input>
<input><name>"name 2"</name><value>{replaceMe!}</value></input>
</device>
<device>
<input><name>"name 1"</name><value>{replaceMe!}</value></input>
<input><name>"name 2"</name><value>{replaceMe!}</value></input>
</device>
</myXmlRoot>
Any way to force the browser to render content in new window as XML...or does using document.open and document.write mean code is rendered as HTML?
Related: Change XML content using JavaScript, missing refresh
Use dataURI to write xml into new window is very easy.
window.open('data:text/xml,'+encodeURIComponent(xmlText),
"Test", "width=300,height=300,scrollbars=1,resizable=1");
Both document.open and document.write are used to write HTML or Javascript to a document. This goes back to the DOM Level 2 Specification of document.open, which assumes that the document is opened in order to write unparsed HTML.
Instead of using document.open and document.write, I would instead suggest dymanically adding elements using the XML DOM as in sampleElement.appendChild(XMLnode)
A similar question can also be found here: how to display xml in javascript?
I am busy developing a firefox extension. I am using the Add-on Builder
What it will do:
Get an ID from a PHP page (XMLHttpRequest)
Call another function and send that ID with it
That function inserts CSS with a link tag created by javascript
My Problem:
It won't work. If I alert the currenttheme variable, nothing happens. So the XMLHttpRequest doesn't seem to work.
My code:
main.js:
var Widget = require("widget").Widget;
var tabs = require('tabs');
exports.main = function() {
var pageMod = require("page-mod");
var data = require("self").data;
scriptFiles = data.url("s.js");
pageMod.PageMod({
include: "*.facebook.com",
contentScriptWhen: 'ready',
contentScriptFile: scriptFiles
});
s.js
function addCSS(theTheme) {
var s = document.createElement('link');
s.type = 'text/css';
s.rel = 'stylesheet';
s.href = theTheme+'.css';
(document.head||document.documentElement).appendChild(s);
}
function getData() {
client = new XMLHttpRequest();
try{
client.open('GET','http://localhost:8888/istyla/login/popuplogin/myaccount.php');
} catch (e){
alert( "error while opening " + e.message );
}
client.onreadystatechange = function(){
if (client.readyState ==4){
user_data = client.responseText;
window.user_data = user_data;
var currenttheme = user_data;
window.currenttheme = currenttheme;
addCSS(currenttheme);
}
}
client.send(null);
}
getData();
P.S. The CSS file is in the data folder.
Im very new to this so not sure if I can help. Have you had a look in the error console(ctrl+shift+j) if its complaining about anything? You can console.log() and it will show in here.
Maybe use the Request lib instead of XMLHttpRequest
Here is a snippet from my code:
var Request = require("request").Request;
getUserDetails : function(userID, callback)
{
Request({
url: Proxy.remoteUrl,
content : {command:'getUser',UserID:userID},
onComplete: function(response) {callback(response.json)}
}).get();
}
Content scripts run with the privileges of the page that they are in. So if the page isn't allowed to load http://localhost/, your content script won't be able to do it either. You don't get an immediate error due to CORS but the request will fail nevertheless. What you need to do is to send a message to main.js so that it does the request (extension code is allowed to request any URI) and sends the data back to the content script.
As said, the content script has the same privileged of the web page where is attached, that is meaning you're under the Same Origin Policy.
You can solve the issue as suggested, so sent a message to the add-on code (that is not restricted by the SOP) and post the result back to the content script.
Here an example how the code could be: https://groups.google.com/d/topic/mozilla-labs-jetpack/VwkZxd_mA7c/discussion