Cannot read response from AngularJS $resource JSONP get from Google Finance - get

I am following the tutorial at http://www.youtube.com/watch?v=IRelx4-ISbs to use AngularJS $resource to get JSON data of a stock index, such as the S&P 500, from Google Finance. However, when I write the result to console, I do not see the data. I get this in Google Chrome's console:
e
__proto: 3
$delete
$get
$query
$remove
$save
constructor
__proto
However, when I go to "Network" in Chrome's console, I see the get in the Name Path left column. When I click on the "info, I see five tabs on the right panel. Under the Preview and Response tabs, I see the correct data. I just don't know how to see or retrieve that in my Javascript.
I attempted to put my code to http://jsfiddle.net/curt00/ycYn7/ but Google Chrome's console is giving me "Uncaught Error: No module: Twitter". (Does anybody know how to get around this error?) Here is the HTML code from my jsfiddle:
<!doctype html>
<html ng-app="Twitter">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular-resource.min.js">
</script>
</head>
<body>
<div ng-controller="TwitterCtrl"></div>
</body>
</html>
Here is the Javascript code from my jsfiddle:
angular.module('Twitter', ['ngResource']);
function TwitterCtrl($scope, $resource) {
var tickerSymbol = "INDEXSP:.INX";
var tempurl = 'https://finance.google.com/finance/info?client=ig&q=' + tickerSymbol.replace(":","%3A") + '&callback=?:action';
$scope.googleFinance = $resource(tempurl,
{action:'&test=', q:'test', callback:'JSON_CALLBACK'},
{get:{method:'JSONP'}});
$scope.indexResult = $scope.googleFinance.get();
console.log('indexResult: ',$scope.indexResult);
}
Can anybody suggest how my code should be changed so that I can fetch the data from the response?

There are at least 2 things that are not correct:
You are duplicating the parameters on your request. The tempurl should not contain any paramaters (i.e. https://finance.google.com/finance/info). If you want to pass parameters, do it within the actions ('get', 'post', 'delete', etc...) or set default parameters. For more information, check the angular.js $resource documentation.
Google Finance response is actually an array, therefore you need to add isArray: true to your GET action in order for it to work
jsFiddle: http://jsfiddle.net/8zVxH/1/
P.S. I'm not familiar with the Google Finance API, so I don't know if the results are the ones you expect. I've just 'fixed' your jsFiddle without changing the logic...

Related

Node module 'request' returns incomplete html

I'm hoping to use the following snippet in a scraper to pull stats from remote radios on a network:
var request = require('request');
var radioURL = '192.10.1.65';
request.get({
url: pageURL
}, (error, response, html) => {
console.log(html);
The console outputs the following html:
<html>
<head>
<link rel="stylesheet" type="text/css" href="2.22.css">
<script type="text/javascript" src="2.22.js">"></script>
</head>
<body onLoad="show('viewPage=10');">
<div id="logo"><img src="logo.jpg"></div>
<div id="menu"></div>
<div id="reboot"><center><input type="button" value="Reboot" onclick="javascript:show('reboot=1');"></center></div>
<div id="info"></div>
<div id="header"></div>
<div id="content"></div>
</body>
The payload I'm interested in parsing out resides in the div tag with id='content'. Inside there is a form, and inside the form is a table with all the data I'm after. The image below shows an inspection of the page expanded to see 'Voltage' with a corresponding value inside of td tags. I've tried different combos of headers in request, as well as timeouts thinking that network latency was part of the issue. How do I get to elements below the div element?
Thanks.
inspection of elements below div element
A call to request.get() retrieves the RAW HTML that the web server sends to the browser. That's what you get. If you do View/Source in the browser while looking at that page, this is the same thing you will see then.
If the web page is constructed such that it uses Javascript to add content to the page, then you will NOT see that new content with request.get() because no Javascript is run when retrieving data with request.get(). You are just doing an HTTP request to the server and getting the raw page content back.
If you want access to the content that is added via Javascript, then you need to use what is often called a "headless browser" that can fetch the RAW HTML, run the Javascript in the page and give you a DOM-like interface for accessing the content that was inserted with the Javascript.
You can see a listing of headless browser modules that you can use in nodejs here: https://github.com/dhamaniasad/HeadlessBrowsers. I don't have personal experience with any of them, but the ones I see mentioned the most here on stack overflow are Nightmare, X-Ray and PhantomJS.
For site scraping, i am a massive advocate of x-ray. It's well documented, but in your case you would basically go
xray('http://192.10.1.65', 'form-elements-you-are-targetting')(fn)
https://github.com/matthewmueller/x-ray
It's very, very, good.

Executing <Script> elements injected into the DOM

I've been attempting to add the Google Tag Manager script to a website developed with Squarespace. Unfortunately Google implementation guidelines specify that this script should be inserted immediately after the opening <body> tag, something Squarespace doesn't permit.
Consequently, I've been playing around with YUI library to attempt to inject this code to where it is required. And have this:
<script>
Y.use('node', function() {
Y.on('domready', function() {
obj = Y.Node.create('<!-- Google Tag Manager --><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-KPT4S5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>'+'<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({\'gtm.start\':new Date().getTime(),event:\'gtm.js\'});var f=d.getElementsByTagName(s)[0],'+'j=d.createElement(s),dl=l!=\'dataLayer\'?\'&l=\'+l:\'\';j.async=true;j.src=\'//www.googletagmanager.com/gtm.js?id=\'+i+dl;f.parentNode.insertBefore(j,f);'+'})(window,document,\'script\',\'dataLayer\',\'GTM-KPT4S5\');<\/script><!-- End Google Tag Manager -->');
Y.one('body').prepend(obj);
});
});
</script>
The code above will inject the Script where required, but it wont execute it. Could someone help identify why and possibly suggest a solution please?
Incidentally, I know I can achieve this with jQuery, but I dont wish to load any additional libraries.
Many thanks.
N.B Apologies, I wasn't clear in my original post. I dont have access to the source code in Squarespace and I need to insert the GTM script directly after the opening <body> tag. I can insert scripts into the <head> in Squarespace so my attempt was to inject GTM code to the <body> from there.
You can use document.write to execute the inline script code that you've inserted as DOM text. So instead of
<script>
Y.use('node', function() {
Y.on('domready', function() {
obj = Y.Node.create('<!-- Google Tag Manager --><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-KPT4S5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>'+'<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({\'gtm.start\':new Date().getTime(),event:\'gtm.js\'});var f=d.getElementsByTagName(s)[0],'+'j=d.createElement(s),dl=l!=\'dataLayer\'?\'&l=\'+l:\'\';j.async=true;j.src=\'//www.googletagmanager.com/gtm.js?id=\'+i+dl;f.parentNode.insertBefore(j,f);'+'})(window,document,\'script\',\'dataLayer\',\'GTM-KPT4S5\');<\/script><!-- End Google Tag Manager -->');
Y.one('body').prepend(obj);
});
});
</script>
You can do
<script>
document.write('<!-- Google Tag Manager --><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-KPT4S5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>'+'<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({\'gtm.start\':new Date().getTime(),event:\'gtm.js\'});var f=d.getElementsByTagName(s)[0],'+'j=d.createElement(s),dl=l!=\'dataLayer\'?\'&l=\'+l:\'\';j.async=true;j.src=\'//www.googletagmanager.com/gtm.js?id=\'+i+dl;f.parentNode.insertBefore(j,f);'+'})(window,document,\'script\',\'dataLayer\',\'GTM-KPT4S5\');<\/script><!-- End Google Tag Manager -->');
</script>
Edit: If the JS is from a third party source that you don't have access to, you need to execute the inline JS code yourself through eval. You can do something similar to this
<script>
Y.use('node', function() {
Y.on('domready', function() {
obj = Y.Node.create('<!-- Google Tag Manager --><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-KPT4S5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>'+'<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({\'gtm.start\':new Date().getTime(),event:\'gtm.js\'});var f=d.getElementsByTagName(s)[0],'+'j=d.createElement(s),dl=l!=\'dataLayer\'?\'&l=\'+l:\'\';j.async=true;j.src=\'//www.googletagmanager.com/gtm.js?id=\'+i+dl;f.parentNode.insertBefore(j,f);'+'})(window,document,\'script\',\'dataLayer\',\'GTM-KPT4S5\');<\/script><!-- End Google Tag Manager -->');
obj.id="googleTag";
Y.one('body').prepend(obj);
Y.one('#googleTag').all('script').each(function(s, k) {
var scriptSrc = s.getHTML();
eval(scriptSrc);
});
});
});
</script>
Though this question is a bit older, it is possible to add Google Tag Manager's code in the Code Injection section of Squarespace in the "footer" area.
With administrator access, choose:
Settings -> Advanced -> Code Injection
Place your GTM script in the header and the <noscript> stuff in the footer.
I know this doesn't solve the particular point about getting it immediately after the opening <body> tag, but I have seen this proposed (and used it myself on a few client sites that were done in Squarespace).

Phantom-node module unable to load external resources

i'm working on a nodejs server which renders posted html to pdf,png or jpg.
( https://github.com/svenhornberg/pagetox (server.js) if you want to try it)
It is working really good, renders complex sites but only to that point that i want do load a simple image. For example i am sending following code to my server:
<!doctype html>
<html>
<head>
<title>logo</title>
</head>
<body>
<img alt="logo" src="http://upload.wikimedia.org/wikipedia/commons/d/de/Wikipedia_Logo_1.0.png">
</body>
</html>
The Code should be okay. But the rendered response image does not contain the logo image.
As said in the phantomjs documentation (http://phantomjs.org/api/webpage/property/settings.html) localToRemoteUrlAccessEnabled is set to false, so set it to true like said in the documentation of phantom-node (https://github.com/sgentle/phantomjs-node/):
page.set('settings.localToRemoteUrlAccessEnabled', true);
page.set('settings.loadImages', true);
to prove it is set to true, i called a getter which returns true
page.get('settings.localToRemoteUrlAccessEnabled', function(data) { console.log(data);});
i'm using node v0.10.26 with phantomjs-node (0.6.1), phantomjs(1.9.7) on linux
Now the question, does anybody see a mistake ? Or can give me a hint what i am doing wrong. Or any other possibilities why phantomjs/phtanom-node isnt loading any external images
I am using the render method to generate the png, jpg or pdf file. I am calling the method inside the evaluate function as a callback, so the site should be loaded completely.
(the full code is at https://github.com/svenhornberg/pagetox/blob/master/server.js)
Edit1: I'm not behind a proxy, which maybe blocks the requests.
looks like i need to set a timeout and wait that all external resources are loaded.
page.set('content') dosen't work with dynamic content in phantomjs
i got it working, but a timeout is not what i want. If i find any better way i will post it.
What you want to set is
page.set('settings.webSecurityEnabled', false);
Which enables cross domain requests. The other option localToRemoteUrlAccessEnabled does not affect your case because you don't use file: resources but you rather overwrite about:blank.
Other issues might be SSL/TLS related. See my answer here for more help.

How to make so that Jade (Node.js) doesn't close the <body> tag

I'm trying to send multiple chunks of data to a client each of which is rendered by Jade templating engine in Express Node.js framework.
I have several views like header, viewA, viewB, viewC, etc.
For every request I need to render the header partial view and send it as a chunk so that the client browser starts rendering it. When the header view is rendered I don't want the <body> tag inside to be closed, because more data is to come which should be inside the <body> tag.
In the meantime, I need to do some computations and after that render another view: either A, B, or C.
Once A, B, or C view is sent, I close the response which means closing the </body></html> tags.
Sounds very simple. But the problem is that Jade closes the <html> and <body> tags when rendering the header view.
I know how to do this manually using native Node.js response object, however, can't figure out how to do this with Jade the right way.
The only solution I currently see is to manually send the header part down to open <body> tag, then render the rest as Jade partials via res.partial().
Any hint is highly appreciated.
You can output any text (including raw html) with !=
!= "<body>"
some
more
tree(attr=1)
Result in this output:
<body>
<some>
<more>
<tree attr="1"></tree>
</more>
</some>
Even though I may accept the above answer which seems to have worked but haven't. Nevertheless, the following code did work.
!!! 5
<html>
head
meta(http-equiv="Content-Type",content="text/html;charset=utf-8")
meta(http-equiv="Cache-Control", content="no-cache")
meta(http-equiv="Expires", content="0")
title= title
link(rel="shortcut icon",href='/img/nelo2_logo.ico')
link(rel='stylesheet',href='/css/bootstrap.css')
link(rel='stylesheet',href='/css/jquery-ui.css')
link(rel='stylesheet',href='/css/chosen.css')
link(rel='stylesheet',href='/css/common.css')
link(rel='stylesheet',href='/css/style.css')
script(src='/js/core/require.js')
<body>
So the solution was not to indent the <html> and <body> tags but have them on the same column. This way Jade doesn't close them.

Dialog is not defined

I'm building my first Facebook Connect application, and am running into an odd problem. This example code:
<script type="text/javascript" charset="utf-8">
FB.init("{{ FACEBOOK_API_KEY }}", "{% url xd_receiver %}");
FB.ensureInit(function() {
var invite_dialog;
function showInviteDialog() {
invite_dialog = new Dialog(Dialog.DIALOG_POP).showMessage('Share with Friends', invite_friends_selector, null, null);
}
function hideInviteDialog() {
invite_dialog.hide();
}
showInviteDialog();
});
</script>
keeps throwing the error:
Dialog is not defined
Is Dialog available in Facebook connect/XFBML applications? Do I need to do anything special in order to use it?
Thanks in advance!
The Dialog you're trying to use is a construct of Facebook Javascript. Unfortunately, FBJS is only available within the Facebook domain inside an FBML page.
The plus side (and it's a big plus) is that if you're using Facebook Connect, you're either inside an iframe or on your own site. You can use real Javascript instead of the limited, watered-down FBJS, including things like MooTools/Jquery/Prototype, or any external JS you desire. You can make your own dialogs!
(Note: If you want dialog boxes that look exactly like the FBJS ones, just google around a bit for Facebook dialog boxes... there's lots out there).

Resources