Why is my PhantomJS script outputting links from the first page and not the fourth? - phantomjs

I am trying to write out a phantomjs script that will print out all the 'http://librivox.org/' links on this web page:
https://librivox.org/reader/251?primary_key=251&search_category=reader&search_page=4&search_form=get_results
Here is my script:
var steps=[];
var testindex = 0;
var loadInProgress = false; //This is set to true when a page is still loading
var webPage = require('webpage');
var page = webPage.create();
var the_url = 'unknown';
page.onError = function(msg, trace) {
var msgStack = ['ERROR: ' + msg];
if (trace && trace.length) {
msgStack.push('TRACE:');
trace.forEach(function(t) {
msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
});
}
console.error(msgStack.join('\n'));
phantom.exit(1);
};
page.settings.userAgent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36';
page.settings.javascriptEnabled = true;
page.settings.loadImages = false;//Script is much faster with this field set to false
phantom.cookiesEnabled = true;
phantom.javascriptEnabled = true;
var system = require('system');
var args = system.args;
if (args.length === 1) {
console.log('usage: phantomjs --cookies-file=cookys.txt ./get-librivox-links-from-page.js');
} else {
args.forEach(function(arg, i) {
if ( i === 1 ) { the_url = arg; }
});
}
if ( the_url == 'unknown' ) { console.log('Please specify librivox url'); phantom.exit(); }
console.log( 'the_url is ' + the_url );
page.onConsoleMessage = function(msg) {
console.log(msg);
};
/**********DEFINE STEPS THAT FANTOM SHOULD DO***********************/
steps = [
function(url){
page.evaluate(function(url){
document.location.href = url;
},url);
},
function(){
page.evaluate(function(){
urls= [];
for (var i=document.links.length; i-->0;) {
if ( document.links[i].href.substring(0,20) == 'http://librivox.org/'.substring(0,20) ) {
console.log(document.links[i].href);
}
}
});
},
];
/**********END STEPS THAT FANTOM SHOULD DO***********************/
//Execute steps one by one
interval = setInterval(executeRequestsStepByStep,50);
function executeRequestsStepByStep(){
if (loadInProgress == false && typeof steps[testindex] == "function") {
if ( testindex == 0 ) {
steps[testindex](the_url);
} else {
steps[testindex]();
}
testindex++;
}
if (typeof steps[testindex] != "function") {
//We need to wait, after the steps is complete!
clearInterval(interval);interval=0;
setTimeout(function(){
setTimeout(phantom.exit,2000)
},3000);
}
}
/**
* These listeners are very important in order to phantom work properly.
* Using these listeners, we control loadInProgress marker which controls, weather a page is fully loaded.
* Without this, we will get content of the page, even a page is not fully loaded.
*/
page.onLoadStarted = function() { loadInProgress = true; };
page.onLoadFinished = function() { loadInProgress = false; };
page.onConsoleMessage = function(msg) { console.log(msg); };
I call the above script from a small shell script for convenience which looks like this:
$ cat run-get-librivox-links-from-page.sh
#!/bin/sh
script=/home/red/phantomjs/get-librivox-links-from-page.js
url=$1
if [ -z $url ]
then
echo "usage $0 <librivox url>"
exit 1
fi
/usr/bin/phantomjs --debug=false --cookies-file=cookys.txt \
$script $url
When I run the script like so:
$ ./run-get-librivox-links-from-page.sh "https://librivox.org/reader/251?primary_key=251&search_category=reader&search_page=4&search_form=get_results"
I get output that looks like I am output the links from search_page 1 instead of search_page 4:
the_url is https://librivox.org/reader/251?primary_key=251&search_category=reader&search_page=4&search_form=get_results
The page at https://librivox.org/reader/251?primary_key=251&search_category=reader&search_page=4&search_form=get_results displayed insecure content from http://archive.org/download/anythingycdo_mn_1302_librivox/anything_you_can_do_1302_thumb.jpg.
- above message repeated many times. remove for brevity. -
http://librivox.org/first-lensman-by-e-e-smith/
http://librivox.org/the-drums-of-jeopardy-by-harold-macgrath/
http://librivox.org/the-defiant-agents-by-andre-norton-2/
http://librivox.org/the-death-ship-by-william-clark-russell/
http://librivox.org/creatures-of-the-abyss-by-murray-leinster/
http://librivox.org/the-creature-from-beyond-infinity/
http://librivox.org/the-count-of-monte-cristo-by-alexandre-dumas/
http://librivox.org/the-cosmic-computer-by-h-beam-piper/
http://librivox.org/a-columbus-of-space-by-garrett-p-serviss/
http://librivox.org/the-colors-of-space-by-marion-zimmer-bradley-2/
http://librivox.org/the-colors-of-space-by-marion-zimmer-bradley/
http://librivox.org/the-city-at-worlds-end-by-edmond-hamilton/
http://librivox.org/citadel-of-fear-by-gertrude-barrows-bennett/
http://librivox.org/the-chessmen-of-mars-version-3-by-edgar-rice-burroughs/
http://librivox.org/the-bright-messenger-by-algernon-blackwood/
http://librivox.org/bat-wing-by-sax-rohmer/
http://librivox.org/at-the-earths-core-version-2-by-edgar-rice-burroughs/
http://librivox.org/astounding-stories-20-various/
http://librivox.org/astounding-stories-15-march-1931-by-ray-cummings/
http://librivox.org/astounding-stories-04-april-1930-by-ray-cummings/
http://librivox.org/astounding-stories-02-february-1930-by-various/
http://librivox.org/astounding-stories-01-january-1930-by/
http://librivox.org/anything-you-can-do-by-randall-garrett/

Related

Loading webpage incompletely Phantomjs

I have problems capturing and loading the webpage:
https://myaccount.nytimes.com/auth/login
The username and password fields as well as the submit button are missing. What could be the reason? Thanks
As you can see the code listed below waits for each and all the resources to be loaded, one by one.
I did not write the code, however it is excellent and tested by many. The original can be found here:
https://gist.github.com/cjoudrey/1341747
(ALL the credits to the guy who wrote it.)
var resourceWait = 3000,
maxRenderWait = 30000,
url = 'https://myaccount.nytimes.com/auth/login'; //'https://twitter.com/#!/nodejs';
var page = require('webpage').create(),
count = 0,
forcedRenderTimeout,
renderTimeout;
page.viewportSize = { width: 1280, height : 1024 };
function doRender() {
page.render('twitter.png');
phantom.exit();
}
page.onResourceRequested = function (req) {
count += 1;
console.log('> ' + req.id + ' - ' + req.url);
clearTimeout(renderTimeout);
};
page.onResourceReceived = function (res) {
if (!res.stage || res.stage === 'end') {
count -= 1;
console.log(res.id + ' ' + res.status + ' - ' + res.url);
if (count === 0) {
renderTimeout = setTimeout(doRender, resourceWait);
}
}
};
page.open(url, function (status) {
if (status !== "success") {
console.log('Unable to load url');
phantom.exit();
} else {
forcedRenderTimeout = setTimeout(function () {
console.log(count);
doRender();
}, maxRenderWait);
}
});

phantomjs XHR response code is null

I am using the below code to automate a web page. The web page has an XHR call which is triggered upon submitting the form. By using "onResourceRequest" and "onResponseReceived" I can look into the request body, but the response status code is always null.
PhantomJS version: 2.1.1
var page = require('webpage').create(), testindex = 0, loadInProgress = false;
var config = require('../../config/config.json');
var system = require('system');
console.log('Running Iteration 1 ...');
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function() {
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if(!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval); //< Stop this interval
}
}
}, 250); //< repeat check every 250ms
};
page.onError = function (msg, trace) {
console.log(msg);
trace.forEach(function(item) {
console.log(' ', item.file, ':', item.line);
});
};
page.onConsoleMessage = function(msg, lineNum, sourceId) {
console.log(colors.cyan('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")'));
};
page.onLoadStarted = function() {
loadInProgress = true;
console.log("load started ", page.url);
};
page.onResourceRequested = function(request) {
console.log('Request ' + request.url);
console.log('Request Header :', JSON.stringify(request.headers));
console.log('Request Body :', request.postData);
};
page.onResourceReceived = function(response) {
console.log('Receive ' + response.url, response.status);
if(response.status === null) {
console.log(JSON.stringify(response));
}
};
page.onLoadFinished = function() {
loadInProgress = false;
console.log("load finished ", page.url);
};
var steps = [
function () {
page.open(config.url, function (status) {
if (status !== 'success'){
console.log('Unable to access ', config.url); //This is a HTTPS endpoint
} else {
waitFor(function() {
// Check in the page if a specific element is now visible
return page.evaluate(function() {
return document.getElementById('code').value;
});
}, function() {
console.log("The page dialog should be visible now.");
// phantom.exit();
});
}
});
},
function () {
var isPostMessageSupported = page.evaluate(function() {
if(window.postMessage){
return true;
} else{
return false;
}
});
console.log('POST Message Support : ', isPostMessageSupported);
var guid = page.evaluate(function() {
return document.getElementById('guid').value;
});
console.log('GUID : ', guid);
page.evaluate( function () {
document.getElementById('userid').value = 'myusername';
document.getElementById('pass').value = 'mypassword';
});
},
function () {
page.evaluate(function () {
document.getElementById('myform').submit();
return;
});
},
function () {
page.render('iteration1.png');
},
];
function done(){
console.log('##completed');
}
setInterval(function() {
if (!loadInProgress && typeof steps[testindex] == "function") {
console.log("step " + (testindex + 1));
steps[testindex]();
testindex++;
}
if (typeof steps[testindex] != "function") {
console.log("test complete!");
done();
phantom.exit();
}
}, 50);
The response that I recieve for the XHR call is
{"contentType":null,"headers":[],"id":42,"redirectURL":null,"stage":"end","status":null,"statusText":null,"time":"2018-04-12T04:15:04.402Z","url":"https://example.com/p"}
I have tried all the phantomJS command line arguments
phantomjs --web-security=false --ssl-protocol=tlsv1 --ignore-ssl-errors=true phantomjs/iterations/iteration1.js
I have also tried adding header "Connection:keep-alive". But nothing solves my problem.
I am not sure what could be the problem here.

Trello API add base64 data image as an attachement

I'd like to send base64 image as an attachment to a trello card through the API
POST /1/cards/[card id or shortlink]/attachments
There's a file field but it does not specify how should look the data there.
Refs: https://developers.trello.com/advanced-reference/card#post-1-cards-card-id-or-shortlink-attachments
Any idea?
Short answer: Trello's API only works to attach binary data via multipart/form-data. Examples below.
Long answer:
The Trello API to add attachments and images is frustratingly under-documented. They do have a coffeescript Client.js for those of us using Javascript to simplify all the basic operations: https://trello.com/1/client.coffee
Using the vanilla Client.js file I have been able to attach links and text files. While the CURL example shows pulling a binary file in from a hard drive, that doesn't work for those of us completely on a server or client where we don't have permissions to create a file.
From a LOT of trial and error, I've determined all binary data (images, documents, etc.) must be attached using multipart/form-data. Here is a jQuery snippet that will take a URL to an item, get it into memory, and then send it to Trello.
var opts = {'key': 'YOUR TRELLO KEY', 'token': 'YOUR TRELLO TOKEN'};
var xhr = new XMLHttpRequest();
xhr.open('get', params); // params is a URL to a file to grab
xhr.responseType = 'blob'; // Use blob to get the file's mimetype
xhr.onload = function() {
var fileReader = new FileReader();
fileReader.onload = function() {
var filename = (params.split('/').pop().split('#')[0].split('?')[0]) || params || '?'; // Removes # or ? after filename
var file = new File([this.result], filename);
var form = new FormData(); // this is the formdata Trello needs
form.append("file", file);
$.each(['key', 'token'], function(iter, item) {
form.append(item, opts.data[item] || 'ERROR! Missing "' + item + '"');
});
$.extend(opts, {
method: "POST",
data: form,
cache: false,
contentType: false,
processData: false
});
return $.ajax(opts);
};
fileReader.readAsArrayBuffer(xhr.response); // Use filereader on blob to get content
};
xhr.send();
I have submitted a new coffeescript for Trello developer support to consider uploading to replace Client.js. It adds a "Trello.upload(url)" that does this work.
I've also attached here for convenience in JS form.
// Generated by CoffeeScript 1.12.4
(function() {
var opts={"version":1,"apiEndpoint":"https://api.trello.com","authEndpoint":"https://trello.com"};
var deferred, isFunction, isReady, ready, waitUntil, wrapper,
slice = [].slice;
wrapper = function(window, jQuery, opts) {
var $, Trello, apiEndpoint, authEndpoint, authorizeURL, baseURL, collection, fn, fn1, i, intentEndpoint, j, key, len, len1, localStorage, location, parseRestArgs, readStorage, ref, ref1, storagePrefix, token, type, version, writeStorage;
$ = jQuery;
key = opts.key, token = opts.token, apiEndpoint = opts.apiEndpoint, authEndpoint = opts.authEndpoint, intentEndpoint = opts.intentEndpoint, version = opts.version;
baseURL = apiEndpoint + "/" + version + "/";
location = window.location;
Trello = {
version: function() {
return version;
},
key: function() {
return key;
},
setKey: function(newKey) {
key = newKey;
},
token: function() {
return token;
},
setToken: function(newToken) {
token = newToken;
},
rest: function() {
var args, error, method, params, path, ref, success;
method = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
ref = parseRestArgs(args), path = ref[0], params = ref[1], success = ref[2], error = ref[3];
opts = {
url: "" + baseURL + path,
type: method,
data: {},
dataType: "json",
success: success,
error: error
};
if (!$.support.cors) {
opts.dataType = "jsonp";
if (method !== "GET") {
opts.type = "GET";
$.extend(opts.data, {
_method: method
});
}
}
if (key) {
opts.data.key = key;
}
if (token) {
opts.data.token = token;
}
if (params != null) {
$.extend(opts.data, params);
}
if (method === 'UPLOAD' && typeof (params) === "string" && params.length > 5) {
var xhr = new XMLHttpRequest();
xhr.open('get', params);
xhr.responseType = 'blob'; // Use blob to get the mimetype
xhr.onload = function() {
var fileReader = new FileReader();
fileReader.onload = function() {
var filename = (params.split('/').pop().split('#')[0].split('?')[0]) || params || '?'; // Removes # or ? after filename
var file = new File([this.result], filename);
var form = new FormData();
form.append("file", file);
$.each(['key', 'token'], function(iter, item) {
form.append(item, opts.data[item] || 'ERROR! Missing "' + item + '"');
});
$.extend(opts, {
method: "POST",
data: form,
cache: false,
contentType: false,
processData: false
});
return $.ajax(opts);
};
fileReader.readAsArrayBuffer(xhr.response); // Use filereader on blob to get content
};
xhr.send();
} else {
return $.ajax(opts);
}
},
authorized: function() {
return token != null;
},
deauthorize: function() {
token = null;
writeStorage("token", token);
},
authorize: function(userOpts) {
var k, persistToken, ref, regexToken, scope, v;
opts = $.extend(true, {
type: "redirect",
persist: true,
interactive: true,
scope: {
read: true,
write: false,
account: false
},
expiration: "30days"
}, userOpts);
regexToken = /[&#]?token=([0-9a-f]{64})/;
persistToken = function() {
if (opts.persist && (token != null)) {
return writeStorage("token", token);
}
};
if (opts.persist) {
if (token == null) {
token = readStorage("token");
}
}
if (token == null) {
token = (ref = regexToken.exec(location.hash)) != null ? ref[1] : void 0;
}
if (this.authorized()) {
persistToken();
location.hash = location.hash.replace(regexToken, "");
return typeof opts.success === "function" ? opts.success() : void 0;
}
if (!opts.interactive) {
return typeof opts.error === "function" ? opts.error() : void 0;
}
scope = ((function() {
var ref1, results;
ref1 = opts.scope;
results = [];
for (k in ref1) {
v = ref1[k];
if (v) {
results.push(k);
}
}
return results;
})()).join(",");
switch (opts.type) {
case "popup":
(function() {
var authWindow, height, left, origin, receiveMessage, ref1, top, width;
waitUntil("authorized", (function(_this) {
return function(isAuthorized) {
if (isAuthorized) {
persistToken();
return typeof opts.success === "function" ? opts.success() : void 0;
} else {
return typeof opts.error === "function" ? opts.error() : void 0;
}
};
})(this));
width = 420;
height = 470;
left = window.screenX + (window.innerWidth - width) / 2;
top = window.screenY + (window.innerHeight - height) / 2;
origin = (ref1 = /^[a-z]+:\/\/[^\/]*/.exec(location)) != null ? ref1[0] : void 0;
authWindow = window.open(authorizeURL({
return_url: origin,
callback_method: "postMessage",
scope: scope,
expiration: opts.expiration,
name: opts.name
}), "trello", "width=" + width + ",height=" + height + ",left=" + left + ",top=" + top);
receiveMessage = function(event) {
var ref2;
if (event.origin !== authEndpoint || event.source !== authWindow) {
return;
}
if ((ref2 = event.source) != null) {
ref2.close();
}
if ((event.data != null) && /[0-9a-f]{64}/.test(event.data)) {
token = event.data;
} else {
token = null;
}
if (typeof window.removeEventListener === "function") {
window.removeEventListener("message", receiveMessage, false);
}
isReady("authorized", Trello.authorized());
};
return typeof window.addEventListener === "function" ? window.addEventListener("message", receiveMessage, false) : void 0;
})();
break;
default:
window.location = authorizeURL({
redirect_uri: location.href,
callback_method: "fragment",
scope: scope,
expiration: opts.expiration,
name: opts.name
});
}
},
addCard: function(options, next) {
var baseArgs, getCard;
baseArgs = {
mode: 'popup',
source: key || window.location.host
};
getCard = function(callback) {
var height, left, returnUrl, top, width;
returnUrl = function(e) {
var data;
window.removeEventListener('message', returnUrl);
try {
data = JSON.parse(e.data);
if (data.success) {
return callback(null, data.card);
} else {
return callback(new Error(data.error));
}
} catch (error1) {}
};
if (typeof window.addEventListener === "function") {
window.addEventListener('message', returnUrl, false);
}
width = 500;
height = 600;
left = window.screenX + (window.outerWidth - width) / 2;
top = window.screenY + (window.outerHeight - height) / 2;
return window.open(intentEndpoint + "/add-card?" + $.param($.extend(baseArgs, options)), "trello", "width=" + width + ",height=" + height + ",left=" + left + ",top=" + top);
};
if (next != null) {
return getCard(next);
} else if (window.Promise) {
return new Promise(function(resolve, reject) {
return getCard(function(err, card) {
if (err) {
return reject(err);
} else {
return resolve(card);
}
});
});
} else {
return getCard(function() {});
}
}
};
ref = ["GET", "PUT", "POST", "DELETE", "UPLOAD"];
fn = function(type) {
return Trello[type.toLowerCase()] = function() {
return this.rest.apply(this, [type].concat(slice.call(arguments)));
};
};
for (i = 0, len = ref.length; i < len; i++) {
type = ref[i];
fn(type);
}
Trello.del = Trello["delete"];
ref1 = ["actions", "cards", "checklists", "boards", "lists", "members", "organizations", "lists"];
fn1 = function(collection) {
return Trello[collection] = {
get: function(id, params, success, error) {
return Trello.get(collection + "/" + id, params, success, error);
}
};
};
for (j = 0, len1 = ref1.length; j < len1; j++) {
collection = ref1[j];
fn1(collection);
}
window.Trello = Trello;
authorizeURL = function(args) {
var baseArgs;
baseArgs = {
response_type: "token",
key: key
};
return authEndpoint + "/" + version + "/authorize?" + $.param($.extend(baseArgs, args));
};
parseRestArgs = function(arg) {
var error, params, path, success;
path = arg[0], params = arg[1], success = arg[2], error = arg[3];
if (isFunction(params)) {
error = success;
success = params;
params = {};
}
path = path.replace(/^\/*/, "");
return [path, params, success, error];
};
localStorage = window.localStorage;
if (localStorage != null) {
storagePrefix = "trello_";
readStorage = function(key) {
return localStorage[storagePrefix + key];
};
writeStorage = function(key, value) {
if (value === null) {
return delete localStorage[storagePrefix + key];
} else {
return localStorage[storagePrefix + key] = value;
}
};
} else {
readStorage = writeStorage = function() {};
}
};
deferred = {};
ready = {};
waitUntil = function(name, fx) {
if (ready[name] != null) {
return fx(ready[name]);
} else {
return (deferred[name] != null ? deferred[name] : deferred[name] = []).push(fx);
}
};
isReady = function(name, value) {
var fx, fxs, i, len;
ready[name] = value;
if (deferred[name]) {
fxs = deferred[name];
delete deferred[name];
for (i = 0, len = fxs.length; i < len; i++) {
fx = fxs[i];
fx(value);
}
}
};
isFunction = function(val) {
return typeof val === "function";
};
wrapper(window, jQuery, opts);
}).call(this);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>

WebRTC + JSEP + Google Channel API - cannot receive remoteStream

I've been trying to get this works, but I don't know what's wrong, can you guys help me? I tried WebRTC code with modification like this.
Both caller and callee enter the web
Web will create channel based on their username
Caller clicks the call button and sends message to spesific channel to some user's username. When caller clicks the call button, he then creates peerConnection and adds localStream
Callee will receive message, and the process goes on like WebRTC sample code. When callee receives an offer, he then creates peerConnection and adds localStream, then creates and sends answer
My code goes like this
var my_username = '{{ current_username }}';
var friend;
var localVideo;
var remoteVideo;
var localStream;
var remoteStream;
var channel;
var channelReady = false;
var pc;
var socket;
var started = false;
// Set up audio and video regardless of what devices are present.
var mediaConstraints = {'mandatory': {
'OfferToReceiveAudio':true,
'OfferToReceiveVideo':true }};
var isVideoMuted = false;
var isAudioMuted = false;
function choiceFriendInitialize() {
var choice_visible = false;
$('ul#friendlist > li').click(function(e) {
$(this).css('background-color', '#808080');
friend = $(this).text();
var choice = $('ul#choice');
choice_visible = true;
choice.css('display', 'inline-block');
choice.css('top', e.pageY);
choice.css('left', e.pageX);
});
// trigger call from here
$('li#call').click(function() {
$('ul#friendlist > li').css('background-color', 'transparent');
$('ul#choice').css('display', 'none');
choice_visible = false;
// call
maybeStart();
doCall();
});
$('li#unfriend').click(function() {
$('ul#friendlist > li').css('background-color', 'transparent');
$('ul#choice').css('display', 'none');
choice_visible = false;
});
$("body").mouseup(function(){
if (choice_visible) {
$('ul#friendlist > li').css('background-color', 'transparent');
$('ul#choice').css('display', 'none');
choice_visible = false;
}
});
}
function initialize() {
console.log("Initializing..");
choiceFriendInitialize();
localVideo = document.getElementById("localVideo");
remoteVideo = document.getElementById("remoteVideo");
openChannel();
doGetUserMedia();
}
function openChannel() {
console.log("Opening channel.");
var channel = new goog.appengine.Channel('{{ token }}');
var handler = {
'onopen': onChannelOpened,
'onmessage': onChannelMessage,
'onerror': onChannelError,
'onclose': onChannelClosed
};
socket = channel.open(handler);
}
function doGetUserMedia() {
// Call into getUserMedia via the polyfill (adapter.js).
var constraints = {"mandatory": {}, "optional": []};
try {
getUserMedia({'audio':true, 'video':constraints}, onUserMediaSuccess, onUserMediaError);
console.log("Requested access to local media with mediaConstraints:\n" + " \"" + JSON.stringify(constraints) + "\"");
} catch (e) {
alert("getUserMedia() failed. Is this a WebRTC capable browser?");
console.log("getUserMedia failed with exception: " + e.message);
}
}
function createPeerConnection() {
var pc_config = {"iceServers": [{"url": "stun:stun.l.google.com:19302"}]};
try {
// Create an RTCPeerConnection via the polyfill (adapter.js).
pc = new RTCPeerConnection(pc_config);
pc.onicecandidate = onIceCandidate;
console.log("Created RTCPeerConnnection with config:\n" + " \"" + JSON.stringify(pc_config) + "\".");
} catch (e) {
console.log("Failed to create PeerConnection, exception: " + e.message);
alert("Cannot create RTCPeerConnection object; WebRTC is not supported by this browser.");
return;
}
pc.onconnecting = onSessionConnecting;
pc.onopen = onSessionOpened;
pc.onaddstream = onRemoteStreamAdded;
pc.onremovestream = onRemoteStreamRemoved;
}
function maybeStart() {
if (!started && localStream && channelReady) {
console.log("Creating PeerConnection.");
createPeerConnection();
console.log("Adding local stream.");
pc.addStream(localStream);
started = true;
// Caller initiates offer to peer.
//if (initiator)
//doCall();
}
}
function doCall() {
console.log("Sending offer to peer.");
pc.createOffer(setLocalAndSendMessage, null, mediaConstraints);
}
function doAnswer() {
console.log("Sending answer to peer.");
pc.createAnswer(setLocalAndSendMessage, null, mediaConstraints);
}
function setLocalAndSendMessage(sessionDescription) {
// Set Opus as the preferred codec in SDP if Opus is present.
sessionDescription.sdp = preferOpus(sessionDescription.sdp);
pc.setLocalDescription(sessionDescription);
sendMessage({from: my_username, to: friend}, sessionDescription);
}
function sendMessage(client, message) {
console.log('C->S: ' + JSON.stringify(message));
var xhr = new XMLHttpRequest();
xhr.open('POST', '/send', true);
xhr.setRequestHeader("Content-type","application/json");
var msgString = {send_info: client, data_message: message};
xhr.send(JSON.stringify(msgString));
}
function processSignalingMessage(message) {
var msg = JSON.parse(message);
var data_message = msg.data_message;
var send_info = msg.send_info;
if (data_message.type === 'offer') {
// Callee creates PeerConnection
if (!started)
maybeStart();
pc.setRemoteDescription(new RTCSessionDescription(data_message));
friend = send_info.from;
doAnswer();
} else if (data_message.type === 'answer' && started) {
pc.setRemoteDescription(new RTCSessionDescription(data_message));
} else if (data_message.type === 'candidate' && started) {
var candidate = new RTCIceCandidate({sdpMLineIndex:data_message.label, candidate:data_message.candidate});
pc.addIceCandidate(candidate);
} else if (data_message.type === 'bye' && started) {
onRemoteHangup();
}
}
function onChannelOpened() {
console.log('Channel opened.');
channelReady = true;
}
function onChannelMessage(message) {
console.log('S->C: ' + message.data);
processSignalingMessage(message.data);
}
function onChannelError() {
console.log('Channel error.');
}
function onChannelClosed() {
console.log('Channel closed.');
}
function onUserMediaSuccess(stream) {
console.log("User has granted access to local media.");
// Call the polyfill wrapper to attach the media stream to this element.
attachMediaStream(localVideo, stream);
localVideo.style.opacity = 1;
localStream = stream;
// Caller creates PeerConnection.
//if (initiator) maybeStart();
}
function onUserMediaError(error) {
console.log("Failed to get access to local media. Error code was " + error.code);
alert("Failed to get access to local media. Error code was " + error.code + ".");
}
function onIceCandidate(event) {
if (event.candidate) {
sendMessage({from: my_username, to: friend}, {type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate});
} else {
console.log("End of candidates.");
}
}
function onSessionConnecting(message) {
console.log("Session connecting.");
}
function onSessionOpened(message) {
console.log("Session opened.");
}
function onRemoteStreamAdded(event) {
console.log("Remote stream added.");
attachMediaStream(remoteVideo, event.stream);
remoteStream = event.stream;
waitForRemoteVideo();
}
function onRemoteStreamRemoved(event) {
console.log("Remote stream removed.");
}
function onHangup() {
console.log("Hanging up.");
transitionToDone();
stop();
// will trigger BYE from server
socket.close();
}
function onRemoteHangup() {
console.log('Session terminated.');
transitionToWaiting();
stop();
}
function stop() {
started = false;
isAudioMuted = false;
isVideoMuted = false;
pc.close();
pc = null;
}
function waitForRemoteVideo() {
if (remoteStream.videoTracks.length === 0 || remoteVideo.currentTime > 0) {
console.log('ada remote stream');
transitionToActive();
} else {
console.log('ga ada remote stream');
setTimeout(waitForRemoteVideo, 100);
}
}
function transitionToActive() {
remoteVideo.style.opacity = 1;
}
function transitionToWaiting() {
remoteVideo.style.opacity = 0;
}
function transitionToDone() {
localVideo.style.opacity = 0;
remoteVideo.style.opacity = 0;
}
function toggleVideoMute() {
if (localStream.videoTracks.length === 0) {
console.log("No local video available.");
return;
}
if (isVideoMuted) {
for (i = 0; i < localStream.videoTracks.length; i++) {
localStream.videoTracks[i].enabled = true;
}
console.log("Video unmuted.");
} else {
for (i = 0; i < localStream.videoTracks.length; i++) {
localStream.videoTracks[i].enabled = false;
}
console.log("Video muted.");
}
isVideoMuted = !isVideoMuted;
}
function toggleAudioMute() {
if (localStream.audioTracks.length === 0) {
console.log("No local audio available.");
return;
}
if (isAudioMuted) {
for (i = 0; i < localStream.audioTracks.length; i++) {
localStream.audioTracks[i].enabled = true;
}
console.log("Audio unmuted.");
} else {
for (i = 0; i < localStream.audioTracks.length; i++){
localStream.audioTracks[i].enabled = false;
}
console.log("Audio muted.");
}
isAudioMuted = !isAudioMuted;
}
setTimeout(initialize, 1);
// Send BYE on refreshing(or leaving) a demo page
// to ensure the room is cleaned for next session.
window.onbeforeunload = function() {
sendMessage({from: my_username, to: friend}, {type: 'bye'});
//Delay 100ms to ensure 'bye' arrives first.
setTimeout(function(){}, 100);
}
// Ctrl-D: toggle audio mute; Ctrl-E: toggle video mute.
// On Mac, Command key is instead of Ctrl.
// Return false to screen out original Chrome shortcuts.
document.onkeydown = function() {
if (navigator.appVersion.indexOf("Mac") != -1) {
if (event.metaKey && event.keyCode === 68) {
toggleAudioMute();
return false;
}
if (event.metaKey && event.keyCode === 69) {
toggleVideoMute();
return false;
}
} else {
if (event.ctrlKey && event.keyCode === 68) {
toggleAudioMute();
return false;
}
if (event.ctrlKey && event.keyCode === 69) {
toggleVideoMute();
return false;
}
}
}
// Set Opus as the default audio codec if it's present.
function preferOpus(sdp) {
var sdpLines = sdp.split('\r\n');
// Search for m line.
for (var i = 0; i < sdpLines.length; i++) {
if (sdpLines[i].search('m=audio') !== -1) {
var mLineIndex = i;
break;
}
}
if (mLineIndex === null)
return sdp;
// If Opus is available, set it as the default in m line.
for (var i = 0; i < sdpLines.length; i++) {
if (sdpLines[i].search('opus/48000') !== -1) {
var opusPayload = extractSdp(sdpLines[i], /:(\d+) opus\/48000/i);
if (opusPayload)
sdpLines[mLineIndex] = setDefaultCodec(sdpLines[mLineIndex], opusPayload);
break;
}
}
// Remove CN in m line and sdp.
sdpLines = removeCN(sdpLines, mLineIndex);
sdp = sdpLines.join('\r\n');
return sdp;
}
function extractSdp(sdpLine, pattern) {
var result = sdpLine.match(pattern);
return (result && result.length == 2)? result[1]: null;
}
// Set the selected codec to the first in m line.
function setDefaultCodec(mLine, payload) {
var elements = mLine.split(' ');
var newLine = new Array();
var index = 0;
for (var i = 0; i < elements.length; i++) {
if (index === 3) // Format of media starts from the fourth.
newLine[index++] = payload; // Put target payload to the first.
if (elements[i] !== payload)
newLine[index++] = elements[i];
}
return newLine.join(' ');
}
// Strip CN from sdp before CN constraints is ready.
function removeCN(sdpLines, mLineIndex) {
var mLineElements = sdpLines[mLineIndex].split(' ');
// Scan from end for the convenience of removing an item.
for (var i = sdpLines.length-1; i >= 0; i--) {
var payload = extractSdp(sdpLines[i], /a=rtpmap:(\d+) CN\/\d+/i);
if (payload) {
var cnPos = mLineElements.indexOf(payload);
if (cnPos !== -1) {
// Remove CN payload from m line.
mLineElements.splice(cnPos, 1);
}
// Remove CN line in sdp
sdpLines.splice(i, 1);
}
}
sdpLines[mLineIndex] = mLineElements.join(' ');
return sdpLines;
}
When it comes to waitForRemoteVideo, the function calls the else condition. But the blob url for remoteVideo exists.
It's funny that I've been searching for the error and re-writing the code for like three times, and suddenly after posted my question here, I realized my mistake.
Here in the function processSignallingMessage..
if (data_message.type === 'offer') {
// Callee creates PeerConnection
if (!started)
maybeStart();
pc.setRemoteDescription(new RTCSessionDescription(data_message));
friend = send_info.from;
doAnswer();
} else ....
Should be like this:
if (data_message.type === 'offer') {
friend = send_info.from;
// Callee creates PeerConnection
if (!started)
maybeStart();
pc.setRemoteDescription(new RTCSessionDescription(data_message));
doAnswer();
} else ....
because callee need variable friend to be filled before sending candidate message.

Page refresh with onclick event in dojo and I don't want a page refresh

For some reason in IE8 when I run this function after an onclick event it causes a page refresh. I don't wan the page refresh to happen.
var edealsButton = dojo.byId("edeals_button");
var edealEmailInput = dojo.byId("edeals_email");
var edealsSignup = dojo.byId("edeals_signup");
var edealsThankYou = dojo.byId("edeals_thankyou");
var currentValue = dojo.attr(edealEmailInput, 'value');
if (currentValue != '' && currentValue != 'Enter your email') {
var anim = dojox.fx.flip({
node: edealsSignup,
dir: "right",
duration: 300
})
dojo.connect(anim, "onEnd", this, function() {
edealsSignup.style.display = "none";
edealsThankYou.style.display = "block";
})
dojo.connect(anim, "onBegin", this, function() {
var criteria = { "emailAddress": '"' + currentValue + '"' };
alert("currentValue " + currentValue);
var d = essentials.CallWebserviceMethod('AlmondForms.asmx/SignupEdeal', criteria);
d.addCallback(function(response) {
var obj = dojo.fromJson(response);
alert(obj.d);
if (obj != null && obj.d != null) {
//alert(obj.d);
if (obj.d == false)
{
var edealSuccess = dojo.byId("edeals_succes_thankyou");
var edealError = dojo.byId("edeals_error_thankyou");
alert("edealError: " + edealError);
dojo.style(edealSuccess, "display", "none");
dojo.style(edealError, "display", "inline-block");
}
else
{
var edealSuccess = dojo.byId("edeals_succes_thankyou");
var edealError = dojo.byId("edeals_error_thankyou");
dojo.style(edealSuccess, "display","inline-block");
dojo.style(edealError, "display", "none");
}
}
else {
var edealSuccess = dojo.byId("edeals_succes_thankyou");
var edealError = dojo.byId("edeals_error_thankyou");
dojo.style(edealSuccess, "display", "none");
dojo.style(edealError, "display", "inline-block");
}
});
})
anim.play();
edealEmailInput.innerHTML == 'Enter your email';
}
else
{
dojo.attr(edealEmailInput, 'value', 'Enter your email');
dojo.style(edealEmailInput, 'color', '#CC2525');
}
It looks like your "d.addCallback" code might not be disposed of properly. You might want to try placing "dojo.stopEvent()" possibly before the "anim.play();" line and see if this would stop the postback.
From the api.dojotoolkit.org site, the dojo.stopEvent() "prevents propagation and clobbers the default action of the passed event". From the docs.dojocampus.org site, they say that "dojo.stopEvent(event) will prevent both default behavior any any propagation (bubbling) of an event."
Good luck, and hope this helps you out some.