Closed rowdyrabbit closed 11 years ago
Note that jQuery has a different API to the default selector engine; text()
is a function.
$('h3 .search-results b').text.toLowerCase()
should instead be $('h3 .search-results b').text().toLowerCase()
Refer to the jQuery docs for more information
Hi,
I've tried the code with the change you suggested, but I'm still getting the same error:
var results = $('h3 .search-results b').text().toLowerCase();
^
TypeError: undefined is not a function
I'll post the entire app below, so you can run it yourself.
var http = require('http');
var URL = require('url');
var nodeio = require('node.io');
var port = 8081;
var gigParkSearchJobOptions = {timeout : 10, jsdom:true};
var gigParkSearchJob = {
input: false,
run: function (keyword) {
var phone = this.options.args[0];
this.getHtml("http://www.gigpark.com/?search=" + phone + "&commit=Search&city", function (err, $) {
var results = $('h3 .search-results b').text().toLowerCase();
this.emit('Results found: ' + results);
});
}
};
/**
* Main http serve method.
*/
function serve() {
var serv = http.createServer(function(req, res) {
var url = URL.parse(req.url);
if (req.method == 'GET' && url.pathname == '/gigpark_search') {
res.statusCode = 200;
//query looks like this: 'q=1234567890, so we split it.
var phoneNum = url.query.split('=')[1];
console.log('query is: ' + phoneNum);
nodeio.start(new nodeio.Job(gigParkSearchJobOptions, gigParkSearchJob), [phoneNum], function(err, output) {
console.log('result is: ' + output);
res.write(JSON.stringify(output));
res.end();
});
} else {
res.statusCode = 404;
res.end("Sorry, page not found.");
}
});
serv.listen(port);
}
console.log("Starting server...");
serve();
It's a pretty rough piece of code, not well structured, I know, but I just copied it off the web to try out node.io to see if it'll do what I want. I really need to be able to use the jQuery selectors as I have a webpage that needs this jQuery selector in order to select the correct part of the DOM:
$('.timetable:eq(' +day_of_week_index+ ') tbody tr')
I run the node server (which all lives in the one .js file called tester.js) like so:
$ node --debug tester.js
and I hit the URL which calls the node.io code like so:
http://localhost:8081/gigpark_search?q=7788911331
That's when I get the $ not defined error, which to me looks like the option I'm passing through to use jsdom isn't working.
Ok I've had a better look at your code. This is outside the scope of the library but I'll help you with your code this one time.
Here's what's wrong
nodeio.start()
incorrectly - the function expects nodeio.start(job, options, callback, capture_output)
h3 .search-results b
should have no space after h3 => h3.search-results b
$(selector)
returns an array like result. You need to say $(selector).first()
if you want only one of the matchesHave a look at the jQuery and node.io documentation for more information.
Here's a working version of your initial snippet
var nodeio = require('node.io');
var options = {
timeout: 10
, jsdom: true
};
var job = {
input: [ '0912341234' ],
run: function (input) {
var url = 'http://www.gigpark.com/?search=' + input + '&commit=Search&city';
console.log(url);
this.getHtml(url, function (err, $) {
var result = $('h3.search-results b').first().text().toLowerCase();
this.emit(result);
});
}
};
nodeio.start(new nodeio.Job(options, job), {}, function (err, output) {
console.log(output);
}, true);
I realise that this works from the command line, the problem is that I can't get the node.io job to be called from within the node.js app with jquery, the above code works fine if I don't try to set jsdom:true in the options.
Also, with the input hard-coded like that, it won't work for my app, I need it to be passed through from the request parameter.
Thanks for taking a look at the code.
This is where I got the example from: http://tommytcchan.blogspot.com.au/2012_05_01_archive.html
All I want to do is make it work with jquery by setting jsdom:true in the options.
Updated the app to take into account all the changes you suggested, including the hard-coded input and still getting the 'undefined is not a function' error.
var http = require('http');
var URL = require('url');
var nodeio = require('node.io');
var port = 8081;
var options = {timeout : 10, jsdom:true};
var job = {
input: ['0912341234'],
run: function (input) {
console.log("phone is: "+input);
this.getHtml("http://www.gigpark.com/?search=" + input + "&commit=Search&city", function (err, $) {
var result = $('h3.search-results b').first().text().toLowerCase();
this.emit(result);
});
}
};
/**
* Main http serve method.
*/
function serve() {
var serv = http.createServer(function(req, res) {
var url = URL.parse(req.url);
if (req.method == 'GET' && url.pathname == '/gigpark_search') {
res.statusCode = 200;
nodeio.start(new nodeio.Job(options, job), {}, function(err, output) {
console.log('result is: ' + output);
res.write(JSON.stringify(output));
res.end();
}, true);
} else {
res.statusCode = 404;
res.end("Sorry, page not found.");
}
});
serv.listen(port);
}
console.log("Starting server...");
serve();
Cheers.
You're not checking if getHtml()
returns an error. Cleaning up your code a bit I can only reproduce the error when the request times out.
var http = require('http')
, URL = require('url')
, nodeio = require('node.io')
, port = 8081;
var options = {
timeout: 30
, jsdom: true
};
function getResult(phone_number, callback) {
var job = new nodeio.Job(options, {
input: [ phone_number ],
run: function (input) {
var url = 'http://www.gigpark.com/?search=' + input + '&commit=Search&city';
this.getHtml(url, function (err, $) {
if (err) {
return this.error(err);
}
var result = $('h3.search-results b').first().text().toLowerCase();
this.emit(result);
});
}
});
nodeio.start(job, { debug: true }, callback, true);
}
function serve() {
var serv = http.createServer(function(req, res) {
var url = URL.parse(req.url);
if (req.method == 'GET' && url.pathname == '/gigpark_search') {
getResult('foo', function (err, result) {
if (err) {
res.statusCode = 500;
} else {
res.statusCode = 200;
res.write(JSON.stringify(result));
}
res.end();
});
} else {
res.statusCode = 404;
res.end();
}
});
serv.listen(port);
}
console.log('Starting server...');
serve();
Ok, I've taken your code above and modified it, this works (without jsdom:true):
var http = require('http')
, URL = require('url')
, nodeio = require('node.io')
, port = 8081;
var options = {
timeout: 30
// , jsdom: true //comment this out when not using jsdom
};
function getResult(search_str, callback) {
var job = new nodeio.Job(options, {
input: [ search_str ],
run: function (input) {
var url = 'http://www.gigpark.com/?search=' + input + '&commit=Search&city';
this.getHtml(url, function (err, $) {
console.log("url: "+url);
if (err != undefined) {
console.log("error occurred: "+err);
return err;
}
console.log("got here");
// var result = $('h3.search-results b').first().text().toLowerCase(); //use when jsdom:true property is set
var result = $('h3 .search-results b').first().text.toLowerCase(); //use when not using jsdom
console.log(result);
this.emit(result);
});
}
});
nodeio.start(job, { debug: true }, callback, true);
}
function serve() {
var serv = http.createServer(function(req, res) {
var url = URL.parse(req.url);
if (req.method == 'GET' && url.pathname == '/gigpark_search') {
getResult('hairdresser', function (err, result) {
console.log(result);
if (err) {
res.statusCode = 500;
} else {
res.statusCode = 200;
res.write(JSON.stringify(result));
}
res.end();
});
} else {
res.statusCode = 404;
res.end();
}
});
serv.listen(port);
}
console.log('Starting server...');
serve();
However this, with jsdom: true does not:
var http = require('http')
, URL = require('url')
, nodeio = require('node.io')
, port = 8081;
var options = {
timeout: 30
, jsdom: true
};
function getResult(search_str, callback) {
var job = new nodeio.Job(options, {
input: [ search_str ],
run: function (input) {
var url = 'http://www.gigpark.com/?search=' + input + '&commit=Search&city';
this.getHtml(url, function (err, $) {
console.log("url: "+url);
if (err != undefined) {
console.log("error occurred: "+err);
return err;
}
console.log("got here");
var result = $('h3.search-results b').first().text().toLowerCase();
// var result = $('h3 .search-results b').first().text.toLowerCase(); // for when not using jsdom
console.log(result);
this.emit(result);
});
}
});
nodeio.start(job, { debug: true }, callback, true);
}
function serve() {
var serv = http.createServer(function(req, res) {
var url = URL.parse(req.url);
if (req.method == 'GET' && url.pathname == '/gigpark_search') {
getResult('hairdresser', function (err, result) {
console.log(result);
if (err) {
res.statusCode = 500;
} else {
res.statusCode = 200;
res.write(JSON.stringify(result));
}
res.end();
});
} else {
res.statusCode = 404;
res.end();
}
});
serv.listen(port);
}
console.log('Starting server...');
serve();
However, notice that the output of the
console.log("error occurred: "+err);
log statement is:
error occurred: TypeError: Cannot read property 'prototype' of undefined
Try throw err
instead of of console.log
so you get a stack trace
Ok, here's my stack trace:
url: http://www.gigpark.com/?search=hairdresser&commit=Search&city
error occurred: TypeError: Cannot read property 'prototype' of undefined
/Users/myhome/Documents/workspace/fitnessfirst/WebContent/tester.js:20
throw err;
^
TypeError: Cannot read property 'prototype' of undefined
at create (/Users/myhome/node_modules/node.io/node_modules/jquery/lib/node-jquery.js:10:26)
at /Users/myhome/node_modules/node.io/node_modules/jquery/lib/node-jquery.js:9471:18
at Object.
Try reinstalling jquery => npm install jquery
Hmm, did that and still getting the same issue, here are some versions if it helps:
node -v = v0.8.14 npm -v = 1.1.65
jquery - A stupid-simple wrapper over jQuery for Node.JS (server). Currently 1.7.2.
Everything was installed via npm, and it's a fresh install of everything too, so should be picking up the latest packages.
Can you npm ls
? You should get
└─┬ node.io@0.4.12
├── coffee-script@1.4.0
├── htmlparser@1.7.6
├─┬ jquery@1.8.2
│ ├── location@0.0.1
│ ├── navigator@1.0.1
│ └── xmlhttprequest@1.4.2
├─┬ jsdom@0.2.19
│ ├─┬ contextify@0.1.3
│ │ └── bindings@1.0.0
│ ├── cssom@0.2.5
│ └── cssstyle@0.2.3
└── request@2.9.202
Ok, it looks like this:
/Users/myhome ├─┬ jquery@1.8.2 │ ├── htmlparser@1.7.6 │ ├── location@0.0.1 │ ├── navigator@1.0.1 │ └── xmlhttprequest@1.4.2 ├─┬ jsdom@0.2.19 │ ├─┬ contextify@0.1.3 │ │ └── bindings@1.0.0 │ ├── cssom@0.2.5 │ ├── cssstyle@0.2.3 │ ├── htmlparser@1.7.6 │ └─┬ request@2.12.0 │ ├─┬ form-data@0.0.3 │ │ ├── async@0.1.9 │ │ └─┬ combined-stream@0.0.3 │ │ └── delayed-stream@0.0.5 │ └── mime@1.2.7 ├─┬ node.io@0.4.12 │ ├── coffee-script@1.4.0 │ ├── htmlparser@1.7.6 │ ├─┬ jquery@1.8.2 │ │ ├── location@0.0.1 │ │ ├── navigator@1.0.1 │ │ └── xmlhttprequest@1.4.2 │ ├─┬ jsdom@0.2.19 │ │ ├── cssom@0.2.5 │ │ └── cssstyle@0.2.3 │ └── request@2.9.202 ├─┬ phantom@0.3.5 │ ├─┬ dnode@0.9.12 │ │ ├─┬ dnode-protocol@0.1.5 │ │ │ └── traverse@0.6.3 │ │ ├── jsonify@0.0.0 │ │ ├── lazy@1.0.8 │ │ ├─┬ socket.io@0.8.6 │ │ │ ├── policyfile@0.0.4 │ │ │ └── redis@0.6.7 │ │ └─┬ socket.io-client@0.8.6 │ │ ├── uglify-js@1.0.6 │ │ ├── websocket-client@1.0.0 │ │ └── xmlhttprequest@1.2.2 │ ├─┬ dnode-protocol@0.2.2 │ │ ├── jsonify@0.0.0 │ │ └── traverse@0.6.3 │ └─┬ express@3.0.3 │ ├── commander@0.6.1 │ ├─┬ connect@2.7.0 │ │ ├── bytes@0.1.0 │ │ ├── formidable@1.0.11 │ │ ├── pause@0.0.1 │ │ └── qs@0.5.1 │ ├── cookie@0.0.5 │ ├── cookie-signature@0.0.1 │ ├── crc@0.2.0 │ ├── debug@0.7.0 │ ├── fresh@0.1.0 │ ├── methods@0.0.1 │ ├── mkdirp@0.3.3 │ ├── range-parser@0.0.4 │ └─┬ send@0.1.0 │ └── mime@1.2.6 ├─┬ socket.io@0.8.7 │ ├── policyfile@0.0.4 │ ├── redis@0.6.7 │ └─┬ socket.io-client@0.8.7 │ ├── uglify-js@1.0.6 │ ├── websocket-client@1.0.0 │ └── xmlhttprequest@1.2.2 └─┬ socket.io-client@0.8.7 ├── uglify-js@1.0.6 ├── websocket-client@1.0.0 └── xmlhttprequest@1.2.2
Ooh, ok, looks like contextify wasn't in my node.io jsdom install. I uninstalled node.io and jsdom and re-installed node.io, all seems to be working now!
Thanks so much for all your help, you rock :)
No probs ;) good luck
When I set jsdom:true in my options and create and start a new job like this (not on the command line):
I get the following error:
It looks like jsdom isn't actually being turned on and that I can't use jQuery.
Any idea what the problem is?