I am working on a Chrome Web App. It interacts with Google Cloud Messaging. My question is can the Chrome Web App html5 pages call a RESTful WebAPI service? I am not finding any examples on how to do this inside the app pages? The WebAPI will return JSON. Any tips - very much appreciated.
Edit:
This is in the html page:
<body>
<select id="ParametersDropDownList"></select>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="test.js"></script>
</body>
And this is in my test.js file:
var uri = 'http://localhost/custom.webapi/api/parameter?emailaddress=john#foo.bar';
var msg;
$.getJSON(uri)
.done(function(data) {
var appenddata;
$.each(data, function(key, item) {
appenddata += "<option value = '" + item.ParameterName + " '>" + item.ParameterName + " </option>";
});
$('#ParametersDropDownList').html(appenddata);
})
.fail(function(jqXHR, textStatus, err) {
var error = $.parseJSON(jqXHR.responseText);
msg = "Failed to get action data Error message is " + error.message;
});
This code works in a regular html5 page. Meaning, the webapi returns json and the dropdown list is populated with the expected values.
Turned out it was CSP related. Specifically accessing jquery from googleapis.com. I instead downloaded the minified version and added it to the project.
Related
Using node.js, I am developing a small web application where want to create a file on server with a button click on browser. I have a small file "file.js" in public folder as below,
var fs = require("fs");
console.log("Going to write into existing file");
fs.writeFile('input.txt', 'Simply Easy Learning!', function(err) {
if (err) {
return console.error(err);
}
console.log("Data written successfully! checked");
console.log("Let's read newly written data");
fs.readFile('input.txt', function (err, data) {
if (err) {
return console.error(err);
}
console.log("Asynchronous read: " + data.toString());
});
});
It works fine when i execute this as "node file.js" and creates a input.txt. Calling this file in html page where trying to call through ajax call as below,
<!DOCTYPE html>
<html>
<head>
<meta content="en-us" http-equiv="Content-Language">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>
console.log(' firstpage ');
function readTextFile(){
console.log(' in function readTextFile ');
var dataString;
$.ajax({
type: "GET",
url: "file.js",
data: dataString,
success: function(err,data){
alert( "Data Saved: " + data );
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
console.log(errorThrown);
}
});
}
</script>
</head>
<body>
<p class="auto-style1"><strong>Welcome to MyPage</strong></p>
<div >
<input class="myButton" type="button" onclick="readTextFile()" value="Submit" />
</div>
</body>
</html>
Pressing the button gives me error,
ReferenceError: require is not defined
at eval (eval at <anonymous> (jquery.min.js:2), <anonymous>:1:10)
at eval (<anonymous>)
at jquery.min.js:2
at Function.globalEval (jquery.min.js:2)
at text script (jquery.min.js:4)
at Pc (jquery.min.js:4)
at x (jquery.min.js:4)
at XMLHttpRequest.b (jquery.min.js:4)
please help , where i am making mistake and how to fix. Many thanks in advance.
A couple things to help you understand what's going wrong:
1) Running "node file.js" is executing your JavaScript file on your server in a node.js environment.
2) When you run your webpage and fetch and execute file.js, your browser is running file.js using its own JavaScript interpreter directly in the browser.
3) node.js has additional features for server side applications, one being the "require" syntax. This allows server side applications to include other JavaScript files rather than loading them in some HTML with a script src tag
4) node.js also provides some modules that are particularly useful for server side applications, such as "fs"
Your file.js looks like it's coded specifically to be run on the server side rather than on a browser client. It uses node.js syntax and even manipulates a file on the file system
You will need to run a node.js server (express.js being one popular choice) that can execute your file.js via some API endpoint. Then change your browser code to call the endpoint instead of trying to fetch and execute file.js directly in the browser
Still confused about one point with node.
I’ve got a server running at http://localhost:3030 to listen for the hit from the redirect, but the redirect never comes.
How, in Node, do you have the request actually follow the redirects. And end up at
http://localhost:3030/?code=ccf3d214669645f594b59be14032e20d
Here is the link; In the browser it does end up in the right place
https://www.instagram.com/oauth/authorize/?client_id=8901edf0746b460489427434ba5d321e&redirect_uri=http://localhost:3030&response_type=code
The authorization_code flow requires a browser, because the user have to be redirected to the third party web site to log in and authenticate your app, in this case that's the Instagram website. So you do need a browser to redirect you back to your redirect_url with the code parameter.
For that type of OAuth flow you can use Grant. You don't have to implement the OAuth flow by yourself. Just follow the basic example and replace facebook with instagram. As you can see you have a basic web server there and you have to navigate to the /connect/instagram route in your web browser. The only difference is that Grant will handle the heavy lifting for you, so you'll receive just the access_token at the end.
You can test the Instagram flow here.
My first answer and comments are still valid, but I'm going to show you how you can automate the authorization process with nwjs.
First you need to enable the Implicit flow for your OAuth app - under the Security tab.
For the purpose of this demo I'm using http://localhost:3000/callback as redirect URI for my OAuth app. So you need to add it as additional redirect URL of your OAuth app. Also fill in all of the required credentials in authorization.html.
server.js
var fs = require('fs')
var path = require('path')
var http = require('http')
var url = require('url')
var qs = require('querystring')
var child = require('child_process')
var nw = null
var server = http.createServer()
server.on('request', function (req, res) {
if (req.url == '/connect') {
var dpath = path.resolve(__dirname)
nw = child.spawn('nw', [dpath])
res.end()
}
else if (req.url == '/callback') {
var fpath = path.resolve(__dirname, 'token.html')
var body = fs.readFileSync(fpath, 'utf8')
res.writeHead(200, {'content-type': 'text/html'})
res.end(body)
}
else if (/^\/token/.test(req.url)) {
var uri = url.parse(req.url)
var query = qs.parse(uri.query)
console.log(query)
nw.on('close', function (code, signal) {
console.log('NW closed')
})
nw.kill('SIGHUP')
res.end()
}
})
server.listen(3000, function () {
console.log('HTTP server listening on port ' + 3000)
})
Start it with:
node server.js
Then navigate to http://localhost:3000/connect, you can use your browser for now.
authorize.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>Client Side Implicit OAuth Flow</title>
<script type="text/javascript" charset="utf-8">
var config = {
client_id: '[CLIENT_ID]',
redirect_uri: '[REDIRECT_URL]',
username: '[USERNAME]',
password: '[PASSWORD]'
}
var authorize_url = 'https://www.instagram.com/oauth/authorize/?' +
'client_id=' + config.client_id + '&' +
'redirect_uri=' + config.redirect_uri + '&' +
'response_type=token'
document.addEventListener('DOMContentLoaded', function (e) {
var iframe = document.querySelector('iframe')
iframe.setAttribute('src', authorize_url)
iframe.onload = function (e) {
var doc = this.contentWindow.document
// login
if (doc.querySelector('[name=username]')) {
doc.querySelector('[name=username]').value = config.username
doc.querySelector('[name=password]').value = config.password
doc.querySelector('[type=submit]').click()
}
// authorize
else if (doc.querySelector('[value=Authorize]')) {
doc.querySelector('[value=Authorize]').click()
}
}
}, false)
</script>
</head>
<body>
<iframe src=""></iframe>
</body>
</html>
Once you hit that route a new process is spawned and the authorize.html is executed. Just keep in mind that NWjs requires some graphical libraries to be installed on your server, so it's not exactly a headless browser.
There the browser navigates to the authorization URL inside an iframe. Depending on whether you are logged in or already authorized the app different pages are loaded. This code just fills in your user name and password and clicks on a few links.
Once the OAuth flow is complete you get the access_token as hash in the URL. As you may know the browser doesn't send that part of the URL to the server, so in the /callback route the server returns another page called token.html which sole purpose is to extract the access token from the URL hash and return it as a querystring in the /token route.
token.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>Client Side Implicit OAuth Flow</title>
<script type="text/javascript" charset="utf-8">
var config = {
callback_uri: 'http://localhost:3000/token'
}
var access_token = window.location.hash.replace('#access_token=', '')
var url = config.callback_uri + '?access_token=' + access_token
window.location.href = url
</script>
</head>
<body>
</body>
</html>
After you run this example you'll see your access token in the command line:
$ node server.js
HTTP server listening on port 3000
{ access_token: '1404767371.e5610d0.3381e9a2fd7340d8b90b729f407949d2' }
NW closed
You can download all files from here.
I have created a sample App for SharePoint 2013 and deployed it successfully. When launching the app, I am getting the following error for every line of code calling RegisterSod
Message: 'RegisterSod' is undefined
Line: 14
Char: 1
Code: 0
<script type="text/javascript">RegisterSod("initstrings.js", "\u002f_layouts\u002f15\u002f1033\u002finitstrings.js?rev=uNmvBiHdrBzcPQzXRpm\u00252FnQ\u00253D\u00253D");</script>
<script type="text/javascript">RegisterSod("strings.js", "\u002f_layouts\u002f15\u002f1033\u002fstrings.js?rev=cSu1pcWiRc999fyCNzJplg\u00253D\u00253D");RegisterSodDep("strings.js", "initstrings.js");</script>
Is there anyway this issue can be resolved?
I know that it's old but I hope this will help somebody else having the problem:
This issue is most likely caused by not having a root site in the SharePoint Server.
Create a root site collection by going to the Central Administration –>Create Site Collection and when selecting the Web Site Address make sure you use ‘/’ as the site address which means that this will be the root site.
I did a blog post on this error here
Hope that helps!
This script load the SP.Runtime.js and SP.js files by using the getScript function in jQuery. After downloading the file, your application has access to the JavaScript object model for SharePoint, including the function RegisterSod.
Please add this script to the page
$(document).ready(function () {
// Get the URI decoded URLs.
hostweburl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
// The js files are in a URL in the form:
// web_url/_layouts/15/resource_file
var scriptbase = hostweburl + "/_layouts/15/";
// Load the js files and continue to
// the execOperation function.
$.getScript(scriptbase + "MicrosoftAjax.js",
function () {
$.getScript(scriptbase + "SP.Runtime.js",
function () {
$.getScript(scriptbase + "SP.js", initContext);
}
);
}
);
});
I am currently new to nodejs and mongodb, so please forgive me for this newbie type of question.
What I want is to pass data from my mongodb file to my js file which is running my mini-game.
What I am doing right now is using jsp tags to retrieve data from my mongodb (I am following this practice from a project that I have seen, but he is doing this on his html file which is working out well for him. for my case I was just trying my luck)
var win = <%= user.win %>;
var lose = <%= user.lose %>;
var draw = <%= user.draw %>;
How do I retrieve the data I had from my mongodb to javascript?
If you have an Node.JS with Express application, there are many ways to do it. If you're using a template engine, you could render the data as part of the HTML page in a script block (or render it directly as HTML, avoiding script). Or, you might want to use an Ajax style request and send back the data to the client.
app.get('/api/users/:id', function(req, res) {
Users.findOne({ _id : req.params.id }, function(error, user) {
if (error || !user) {
res.send({ error: error });
} else {
res.send(user);
}
});
});
Once you've got that ready, you could use jQuery's ajax function for example to call the web service.
$.ajax({
url: "api/users/" + userId,
}).done(function(user) {
// here you have a complete user object that you can use
});
The code you posted makes me think that you're using a template engine though. I would expect that there is a render method with your template HTML file:
res.render('homepage', user);
Then, in the HTML:
<script>
var win = <%= win %>;
var lose = <%= lose %>;
var draw = <%= draw %>;
</script>
As the user object is the object with current context (as it was passed as the parameter in my example above), you can just directly refer to the properties of the user object directly (just win rather than user.win).
All pages on my 5 page site should be output using a Node.js server.
Most of the page content is static. At the bottom of each page, there is a bit of dynamic content.
My node.js code currently looks like:
var http = require('http');
http.createServer(function (request, response) {
console.log('request starting...');
response.writeHead(200, { 'Content-Type': 'text/html' });
var html = '<!DOCTYPE html><html><head><title>My Title</title></head><body>';
html += 'Some more static content';
html += 'Some more static content';
html += 'Some more static content';
html += 'Some dynamic content';
html += '</body></html>';
response.end(html, 'utf-8');
}).listen(38316);
I'm sure there are numerous things wrong about this example. Please enlighten me!
For example:
How can I add static content to the
page without storing it in a string as a variable value with += numerous times?
What is the best practices way to build a small site in Node.js where all pages are a mix between static and dynamic content?
Personally, I'd use a server that has higher level constructs. For instance, take a look at the expressjs framework - http://expressjs.com/
The constructs you'll be interested in from this package are:
Truly static files (assets etc): app.use(express.static(__dirname + '/public'));
A templating language such as jade, mustache, etc:
http://expressjs.com/en/guide/using-template-engines.html
https://github.com/visionmedia/jade/
You'll want to look up 'locals' and 'partials' for embedding small bits of dynamic content in mostly static content
For example in jade:
!!! 5
html(lang="en")
head
title= pageTitle
script(type='text/javascript')
if (foo) {
bar()
}
body
h1 Jade - node template engine
#container
- if (youAreUsingJade)
p You are amazing
- else
p Get on it!
Becomes:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Jade</title>
<script type="text/javascript">
if (foo) {
bar()
}
</script>
</head>
<body>
<h1>Jade - node template engine</h1>
<div id="container">
<p>You are amazing</p>
</div>
</body>
</html>
If you prefer something a little less drastic I would say look at mustache or one of the other engines that looks a bit more like regular-sauce html.
Alternative you can just use jsDOM. This means you have a DOM object you can manipulate on the server to add your dynamic content, then you can just flush the DOM as a HTML file / string
These days the answer is not so straightforward.
If you don't need to be indexed by Google, consider making a single-page application using socket.io and client-side templates such as jQuery Templates. There are even emerging node.js frameworks for this type of architecture, e.g. socketstream.
If you need to be indexed by Google, do you need your dynamic content to be indexed? If yes,
consider using express and server-side templates such as ejs, jade or mustache. Another (discouraged) approach might be to generate XML from JSON on server and use an XSLT front-end.
If you need only static content to be indexed, consider using express on server, but don't generate any dynamic HTML on server. Instead, send your dynamic content in JSON format to client using AJAX or socket.io, and render it using client-side templates such as jQuery Templates.
Don't consider server-side DOM: DOM doesn't scale for complex layouts, you will sink in a sea of selectors and DOM calls. Even client-side developers understood that and implemented client-side templates. A new promising approach is weld library. It offers best of both worlds, but it is not mature yet to be used in production (e.g. simple things like conditional rendering are not supported yet).
One good way is to use a templating engine. You can store the templates as separate files, and the templating engine has the ability to make the content dynamic. Personally I use yajet (http://www.yajet.net/) which is written for the web but works fine with node, and there are numerous template engines for node on npm.
One of the best things I found is to use NodeJS, Express and Mustache...
You can create your HTML pages as you normally would using Mustache syntax for placeholders for your variables {{name}}...
When a user hits your site, express routs the slug to the correct template...
NodeJS get's the file...
NodeJS get's the dataset from a DB...
Run it through Mustache on the server...
Send the completed page to the client...
Here is a scaled back version I wrote on my blog. It's simple but the idea is pretty sound. I use it to quickly deploy pages on my site.
http://devcrapshoot.com/javascript/nodejs-expressjs-and-mustachejs-template-engine
I went this route because I didn't want to learn all of the extra syntax to write a language I already knew (html). It makes more sense and follows more of a true MVC pattern.
First deliver only static HTML files from server to the client. Then use something like AJAX / server.io to serve the dynamic content. IMO Jade is really ugly for writing HTML code and its better to use a template engine.
I did some Google and found some code by this fellow, its good if you are doing it for PoC / learning.
var server = require('./server');
var controller = require("./controller");
var urlResponseHandlers = require("./urlResponseHandlers");
var handle = {};
handle["/"] = urlResponseHandlers.fetch;
handle["/fetch"] = urlResponseHandlers.fetch;
handle["/save"] = urlResponseHandlers.save;
server.start(controller.dispatch, handle);
Here is how the logic for handling URLs is displayed -
var staticHandler = require('./staticHandler');
function dispatch(handler, pathname, req, res) {
console.log("About to dispatch a request for " + pathname);
var content = "Hey " + pathname;
if (typeof handler[pathname] === 'function') {
content += handler[pathname](req);
res.writeHead(200, {
'Content-Type': 'text/html'
});
res.write(content);
res.end();
} else {
console.log("No request handler found for " + pathname);
staticHandler.handleStatic(pathname, res);
}
}
Here is how static files can be handled -
function handleStatic(pageUrl, response) {
var filename = path.join(process.cwd(), pageUrl);
path.exists(filename, function (exists) {
if (!exists) {
console.log("not exists: " + filename);
response.writeHead(404, {
'Content-Type': 'text/html'
});
response.write('404 Not Found\n');
response.end();
return;
}
//Do not send Content type, browser will pick it up.
response.writeHead(200);
var fileStream = fs.createReadStream(filename);
fileStream.on('end', function () {
response.end();
});
fileStream.pipe(response);
return;
});
}
exports.handleStatic = handleStatic;
I liked the idea. All code copied from this link!
.
A solution have found to this, without using any other modules and or other script is to make the calling script into a module and include it with the function require().
With this solution I can use javascript which ever way I want
What I would do is make an ajax call to a nodejs script (www.example.com/path/script.js)
script.js would need to be built like a module with the exports.functionName=function(){...}
After that include it in your webserver function require(pathToTheScript).functionName(res,req)
You will also need to end the response in the functionName(res,req) by doing res.end();