Skip to content
This repository was archived by the owner on May 30, 2023. It is now read-only.

JS programming model #8

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Makefile*
bin/**/*
*.xcodeproj
*.moc
*.o
qrc_*.cpp
1 change: 1 addition & 0 deletions examples/fibo.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ var ticker = window.setInterval(function () {
phantom.exit();
}
}, 300);
return -1;
1 change: 1 addition & 0 deletions examples/ipgeocode.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ cb = function (data) {
var el = document.createElement('script');
el.src = 'http://freegeoip.net/json/?callback=cb';
document.body.appendChild(el);
return -1;
41 changes: 41 additions & 0 deletions examples/localweather.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
phantom.addCtxVar('start', Date.now().toString());
phantom.open('http://freegeoip.net/xml/', function(err) {
if (err) {
console.log('Cannot get the location');
} else {
var city = document.querySelector('City').textContent + ', '
+ document.querySelector('RegionCode').textContent;
var elapsed = Date.now() - new Date().setTime(phantom.ctx.start);
console.log('Geolocated city: ' + city + ' (in ' + elapsed + 'msec)');
phantom.addCtxVar('city', city);
phantom.addCtxVar('start', Date.now().toString());
phantom.open(encodeURI('http://www.google.com/ig/api?weather=' + city), function(err) {
if (err || document.querySelectorAll('problem_cause').length > 0) {
console.log('Cannot get weather for ' + phantom.ctx.city);
} else {
function data (s, e) {
var el;
e = e || document;
el = e.querySelector(s);
return el ? el.attributes.data.value : undefined;
};

var elapsed = Date.now() - new Date().setTime(phantom.ctx.start);
console.log('Forecast city: ' + data('weather > forecast_information > city') + ' (in ' + elapsed + 'msec)');
console.log('Current condition: ' + data('weather > current_conditions > condition'));
console.log('Temperature: ' + data('weather > current_conditions > temp_f') + ' F');
console.log(data('weather > current_conditions > humidity'));
console.log(data('weather > current_conditions > wind_condition'));
console.log('');

var forecasts = document.querySelectorAll('weather > forecast_conditions');
for (var i = 0; i < forecasts.length; ++i) {
var f = forecasts[i];
console.log(data('day_of_week', f) + ': ' +
data('low', f) + '-' + data('high', f) + ' F ' +
data('condition', f));
}
}
});
}
});
3 changes: 2 additions & 1 deletion examples/movies.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// List movies from kids-in-mind.com

var cbfunc = function (data) {
cbfunc = function (data) {
globaldata= data;
var list = data.query.results.movie;
list.forEach(function (item) {
Expand All @@ -12,3 +12,4 @@ var cbfunc = function (data) {
var el = document.createElement('script');
el.src = 'http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20movies.kids-in-mind&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=cbfunc';
document.body.appendChild(el);
return -1;
1 change: 1 addition & 0 deletions examples/run-jasmine.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ if (phantom.state.length === 0) {
phantom.exit();
}
}, 100);
return -1;
}
1 change: 1 addition & 0 deletions examples/run-qunit.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ if (phantom.state.length === 0) {
}
}
}, 100);
return -1;
}
3 changes: 2 additions & 1 deletion examples/seasonfood.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Show BBC seasonal food list.

var cbfunc = function (data) {
cbfunc = function (data) {
var list = data.query.results.results.result,
names = ['January', 'February', 'March',
'April', 'May', 'June',
Expand All @@ -17,3 +17,4 @@ var cbfunc = function (data) {
var el = document.createElement('script');
el.src = 'http://query.yahooapis.com/v1/public/yql?q=SELECT%20*%20FROM%20bbc.goodfood.seasonal%3B&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=cbfunc';
document.body.appendChild(el);
return -1;
51 changes: 46 additions & 5 deletions src/phantomjs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
#define PHANTOMJS_VERSION_PATCH 0
#define PHANTOMJS_VERSION_STRING "1.1.0"

#define PHANTOMJS_WRAPMAIN(script) ("(function() {" + (script) + "})();")
#define PHANTOMJS_WRAPCALLBACK(script, success) ("(" + (script) + ")(" + ((success) ? "false" : "true") + ");")

void showUsage()
{
std::cerr << "phantomjs script.js" << std::endl << std::endl;
Expand Down Expand Up @@ -114,6 +117,7 @@ class Phantom: public QObject
Q_PROPERTY(QString content READ content WRITE setContent)
Q_PROPERTY(QString loadStatus READ loadStatus)
Q_PROPERTY(QString state READ state WRITE setState)
Q_PROPERTY(QVariantMap ctx READ ctx WRITE setCtx)
Q_PROPERTY(QString userAgent READ userAgent WRITE setUserAgent)
Q_PROPERTY(QVariantMap version READ version)
Q_PROPERTY(QVariantMap viewportSize READ viewportSize WRITE setViewportSize)
Expand All @@ -134,6 +138,9 @@ class Phantom: public QObject
void setState(const QString &value);
QString state() const;

void setCtx(const QVariantMap &value);
QVariantMap ctx() const;

void setUserAgent(const QString &ua);
QString userAgent() const;

Expand All @@ -144,10 +151,11 @@ class Phantom: public QObject

public slots:
void exit(int code = 0);
void open(const QString &address);
void open(const QString &address, const QString &callback = "");
void setFormInputFile(QWebElement el, const QString &fileTag);
bool render(const QString &fileName);
void sleep(int ms);
void addCtxVar(const QString &key, const QVariant &value);

private slots:
void inject();
Expand All @@ -160,7 +168,11 @@ private slots:
WebPage m_page;
int m_returnValue;
QString m_script;
QString m_cbscript;
QString m_state;
QVariantMap m_ctx;
bool m_exit;
void runScript(const QString &script);
};

Phantom::Phantom(QObject *parent)
Expand Down Expand Up @@ -271,6 +283,14 @@ void Phantom::setContent(const QString &content)
m_page.mainFrame()->setHtml(content);
}

void Phantom::runScript(const QString &script)
{
int exitCode = m_page.mainFrame()->evaluateJavaScript(script).toInt();
if (m_exit && exitCode >= 0) // if no callback and non-negative exit code then quit
exit(exitCode);
m_exit = true;
}

bool Phantom::execute()
{
if (m_scriptFile.isEmpty())
Expand All @@ -290,7 +310,8 @@ bool Phantom::execute()
m_script.prepend("//");
}

m_page.mainFrame()->evaluateJavaScript(m_script);
m_exit = true;
runScript(PHANTOMJS_WRAPMAIN(m_script));
return true;
}

Expand All @@ -303,8 +324,11 @@ void Phantom::exit(int code)

void Phantom::finish(bool success)
{
m_loadStatus = success ? "success" : "fail";
m_page.mainFrame()->evaluateJavaScript(m_script);
m_loadStatus = success ? "success" : "fail";
if (!m_script.isEmpty()) { // don't run before loading the script
QString script = m_cbscript.isEmpty() ? PHANTOMJS_WRAPMAIN(m_script) : PHANTOMJS_WRAPCALLBACK(m_cbscript, success);
runScript(script);
}
}

void Phantom::inject()
Expand All @@ -317,10 +341,12 @@ QString Phantom::loadStatus() const
return m_loadStatus;
}

void Phantom::open(const QString &address)
void Phantom::open(const QString &address, const QString &callback)
{
m_page.triggerAction(QWebPage::Stop);
m_loadStatus = "loading";
m_cbscript = callback;
m_exit = false;
m_page.mainFrame()->setUrl(address);
}

Expand Down Expand Up @@ -393,6 +419,21 @@ QString Phantom::state() const
return m_state;
}

void Phantom::setCtx(const QVariantMap &value)
{
m_ctx = value;
}

void Phantom::addCtxVar(const QString &key, const QVariant &value)
{
m_ctx.insert(key, value);
}

QVariantMap Phantom::ctx() const
{
return m_ctx;
}

void Phantom::setUserAgent(const QString &ua)
{
m_page.m_userAgent = ua;
Expand Down