I have been successfully able to take raw html (that has been retrieved with another product) then have phantomjs take that raw html and render the full page including running any/all javascript. I recently encountered a page that was not having its javascript rendered.
This is how I run it...
phantomjs myscript.js > OUTPUT.txt 2>&1
Here is the myscript.js file that demonstrates the issue...
var page = require('webpage').create(),
var system = require('system');
var address = 'http://cloud.firebrandtech.com/#!/login';
var rawHtml = '<!DOCTYPE html>\
<html>\
<head>\
<meta charset="utf-8">\
<meta http-equiv="X-UA-Compatible" content="IE=edge">\
<meta name="viewport" content="width=device-width, initial-scale=1.0">\
<meta name="description" content="Web Portal for managing Cloud Products, Assets, and Distributions">\
<meta name="author" content="Firebrand Technologies">\
<title>Firebrand Cloud</title>\
<link rel="stylesheet" href="/widgets/css/widgets.css">\
<link rel="stylesheet" href="/css/portal.css">\
</head>\
<body ng-app="portal" fc-app="cloud" fc-direct="true" class="fc">\
<div>\
<div data-ng-if="user.isLoaded" data-ng-controller="PortalCtrl">\
<div data-ng-include="getView()"></div>\
<div class="container">\
<div data-ui-view></div>\
</div>\
</div>\
</div>\
<script src="/widgets/js/widgets.js"></script>\
<script src="/js/vendor.js"></script>\
<script src="/js/portal.js"></script>\
</body>\
</html>';
page.settings.resourceTimeout = 5000;
page.settings.loadImages = false;
page.setContent(rawHtml, address);
window.setTimeout(function () {
if(page.content.indexOf('Sign In') > -1)
console.log('YAY!!! Javascript Rendered!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
else
console.log('BOO!!! Javascript NOT Rendered!!!!!!!!!!!!!!!!!!!!!!!!!!')
phantom.exit();
}, 5000);
Seems like this page requires some auth/cors to work. I can get it to work if phantomjs makes the actual request (using page.open) to get the source like the following example. However, this solution will not work for me. Phantomjs has to use the source like in the example above (which like I mentioned, has been working great for all other sites).
var page = require('webpage').create(),
var system = require('system');
var address = 'http://cloud.firebrandtech.com/#!/login ';
page.open(address, function(status) {
setTimeout(function(){
if(page.content.indexOf('Sign In') > -1)
console.log('YAY!!! Javascript Rendered!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
else
console.log('BOO!!! Javascript NOT Rendered!!!!!!!!!!!!!!!!!!!!!!!!!!')
phantom.exit();
}, 5000)
});
I have already tried using flags like the following but they seem to have no effect...
phantomjs --web-security=false --ignore-ssl-errors=true thefilebelow.js > OUTPUT.txt 2>&1
Finally got this working...
Since I used another product (not phantomjs) to retrieve the page source, I needed to persist the cookies sent back with that request. Then I had to pass in those cookies using addCookie like so...
var page = require('webpage').create(),
var system = require('system');
var address = 'http://cloud.firebrandtech.com/#!/login';
var rawHtml = 'same raw html as above...';
//THE NEXT 3 LINES ARE WHAT CHANGED
var cookiesFromInitialRequest = [{name: 'aaa', value: 'bbb', domain: 'ccc'}, etc...]
for(var i = 0; i < cookiesFromInitialRequest.length; i++)
phantom.addCookie(cookiesFromInitialRequest[i])
page.settings.resourceTimeout = 5000;
page.settings.loadImages = false;
page.setContent(rawHtml, address);
window.setTimeout(function () {
if(page.content.indexOf('Sign In') > -1)
console.log('YAY!!! Javascript Rendered!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
else
console.log('BOO!!! Javascript NOT Rendered!!!!!!!!!!!!!!!!!!!!!!!!!!')
phantom.exit();
}, 5000);
Related
A few days ago, I was trying to build Autodesk forge viewer API with react native by following this example:
https://forge.autodesk.com/blog/forge-react-native-au-talk
It works well. It used viewer v2.17, I up to viewer v7 but unfortunately, It doesn't show anything. I caught an error: Cannot read property 'texture' of null, when I use line viewer.start();
Please, help
Looking at your code it seems to me you're not using the viewer options properly on initializing.
The way to define the access token is by a callback as per the sample posted by Bryan.
Using the code below the viewer loaded in fine.
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<link rel="stylesheet" href="https://developer.api.autodesk.com/derivativeservice/v2/viewers/style.min.css?v=v7.*" type="text/css">
<script src="https://developer.api.autodesk.com/derivativeservice/v2/viewers/three.min.js?v=v2.17"></script>
<script src="https://developer.api.autodesk.com/derivativeservice/v2/viewers/viewer3D.js?v=v7.*"></script>
</head>
<body style="margin:0">
<div id="viewer"></div>
</body>
<script>
var viewer = null;
function initializeViewer(urn, token) {
var options = {
env: "AutodeskProduction",
getAccessToken: function(onTokenReady) {
var token = 'access token provided by 2 legged api';
var timeInSeconds = 3600; // Use value provided by Forge Authentication (OAuth) API
onTokenReady(token, timeInSeconds);
}
}
Autodesk.Viewing.Initializer(options, () => {
try {
viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('viewer'));
viewer.start();
console.log('viewer loaded');
} catch (err) {
alert(err)
}
});
function onDocumentLoadSuccess(doc) {
var viewables = doc.getRoot().getDefaultGeometry();
viewer.loadDocumentNode(doc, viewables).then(i => {
// documented loaded, any action?
});
}
function onDocumentLoadFailure(viewerErrorCode) {
console.error('onDocumentLoadFailure() - errorCode:' + viewerErrorCode);
}
}
</script>
I have a html page with images, tables and some styling with Bootstrap 4. I tried to convert the pages to pdf using the JsReportMVCService, the pdf doesnot load with the proper css class from bootstrap.
HTML CONTENT
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>WeekelyReport</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
</head>
<body>
<div class="jumbotron">
<h1> Hello John Doe,</h1>
<p>
This is a generic email about something.<br />
<br />
</p>
</div>
</body>
</html>
ASP.NET CORE IMPLEMENTATION
var generatedFile = await GeneratePDFAsync(htmlContent);
File.WriteAllBytes(#"C:\temp\hello.pdf", generatedFile);
async Task<byte[]> GeneratePDFAsync(string htmlContent)
{
var report = await JsReportMVCService.RenderAsync(new RenderRequest()
{
Template = new Template
{
Content = htmlContent,
Engine = Engine.None,
Recipe = Recipe.ChromePdf
}
});
using (var memoryStream = new MemoryStream())
{
await report.Content.CopyToAsync(memoryStream);
return memoryStream.ToArray();
}
}
How my Pdf Looks after the conversion to PDF.
It is possible to convert to pdf with the same bootstrap 4 layout? or am i missing something during the conversion here?
The pdf printing uses print media type and the bootstrap has quite different styles for printing. This causes that the pdf looks different than html, but it looks the same as you would print it. I would generally not recommend using responsive css framework as bootstrap for printing static pdf, but it is of course your choice.
To make your example looking the same on pdf you just need to change the media type on the chrome settings.
var report = await JsReportMVCService.RenderAsync(new RenderRequest()
{
Template = new Template
{
Content = htmlContent,
Engine = Engine.None,
Recipe = Recipe.ChromePdf,
Chrome = new Chrome {
MediaType = MediaType.Screen,
PrintBackground = true
}
}
});
make sure you have the latest jsreport.Types#2.2.2
generaly i ask exactly the same question as here:
Safari extension: Event for a completely new tab?
in this answer (case 3) he guide to listen click event inside inject.js.
can someone show this implementation?
Here's an implementation I used for one of my previous extensions:
Create a global.html file, and inside the Extension Builder, select that file under the Extension Global Page section:
Source for global.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>My Extension</title>
</head>
<body>
<script>
function messageHandler(event) {
var newTab = null;
var url = null;
if (event.name === "open_new_tab") {
url = event.message;
newTab = safari.application.activeBrowserWindow.openTab();
newTab.url = url;
}
}
safari.application.addEventListener("message", messageHandler, false);
</script>
</body>
</html>
Create an extension.js file, and add it to the Injected Extension Content -> End Scripts section:
Source for extension.js:
(function() {
// ... rest of you extension code
openNewTabWithUrl("http://google.com")
function openNewTabWithUrl(url) {
safari.self.tab.dispatchMessage("open_new_tab", url);
}
}());
This will send a message containing a URL from your extension.js to global.html, which will pick up the message and open the new tab.
Sencha Touch application has requires:[] option to specify the list of controllers and models and stores etc that are loaded that we need for the application to work but is there a way to execute something that we need even before the loading of the dependencies. FOr e.g. I need the Browsers Language even before the loading of all dependencies. So is it possible to do?
Keep in mind: Sencha Touch is nothing but JavaScript.
You can add some script in your index.html in front of the script tag that loads the sencha microloader.
<!DOCTYPE HTML>
<html manifest="" lang="en-US">
<head>
<meta charset="UTF-8">
<title>FNL</title>
<style type="text/css">
<!-- sencha stuff -->
</style>
<script id="myScript" type="text/javascript" src="myScript.js"></script>
<!-- The line below must be kept intact for Sencha Command to build your application -->
<script id="microloader" type="text/javascript" src=".sencha/app/microloader/development.js"></script>
</head>
<body>
<div id="appLoadingIndicator">
<div></div>
<div></div>
<div></div>
</div>
</body>
</html>
I added some lines to the ST Microloader:
this.css = processAssets(manifest.css, 'css');
// Load language strings
var xhr = new XMLHttpRequest();
xhr.open('GET', 'api/Settings', false);
xhr.send(null);
var settings = eval("(" + xhr.responseText + ")");
Lang = settings.Translations[0];
Options = settings.Options[0];
// End Load Language Strings
this.js = processAssets(manifest.js, 'js');
In ExtJS i accomplished this by loading a Dependency class first
Ext.require([
'MyApp.Dependencies',
..
]);
so the Dependecies class is loaded before all controllers which looks like this
Dependencies.js:
Ext.define('MyApp.Dependencies', {
singleton: true,
init: function() {
// load translation data
}
});
MyApp.Dependecies.init();
and for completition my init function looks something like this:
inti: function(){
function loadScriptSync(url) {
var xhrObj = new XMLHttpRequest();
// open and send a synchronous request
xhrObj.open('GET', url, false);
xhrObj.send('');
// add the returned content to a newly created script tag
var se = document.createElement('script');
se.type = "text/javascript";
se.text = xhrObj.responseText;
document.getElementsByTagName('head')[0].appendChild(se);
}
var language = this.getLanguage();
loadScriptSync("resources/locale/locale." + language + ".js");
}
Sorry for such a noob question.
I just followed following google plus signin's Step1 to Step4.
https://developers.google.com/+/web/signin/
The signin seemed to succeed, while an error 'Unknown RPC service: widget-interactive-I0_1370237493291' emerged. Here are the console logs on Chrome.
XHR finished loading: "https://plusone.google.com/_/scs/apps-static/_/js/k=oz.connect.en_US.B31L_d…sv=1/d=1/ed=1/am=GA/rs=AItRSTOhxGvE7YZFbwjOy6nLkxCnNjz3og/cb=gapi.loaded_1". signin:15
XHR finished loading: "https://plusone.google.com/_/scs/apps-static/_/js/k=oz.gapi.en.hgKKOofQjvI.…sv=1/d=1/ed=1/am=EQ/rs=AItRSTOeNwU4i5ApX9gPGjnZ0AzovKWmWw/cb=gapi.loaded_0". signin:15
Unknown RPC service: widget-interactive-I0_1370237493291 cb=gapi.loaded_0:71
signed in
I think the error is about something incomplete. I cannot figure out what the exactly the error is and how to get it clear. What am I missing?
Here is the code. The origin is http://localhost:3000
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Gplus</title>
</head>
<body>
<h1>Gplus</h1>
<span id="signinButton">
<span
class="g-signin"
data-callback="signinCallback"
data-clientid="362449793624.apps.googleusercontent.com"
data-cookiepolicy="single_host_origin"
data-requestvisibleactions="http://schemas.google.com/AddActivity"
data-scope="https://www.googleapis.com/auth/plus.login">
</span>
</span>
<script type="text/javascript">
function signinCallback(authResult) {
if (authResult['access_token']) {
// Successfully authorized
// Hide the sign-in button now that the user is authorized, for example:
document.getElementById('signinButton').setAttribute('style', 'display: none');
console.log('signed in');
} else if (authResult['error']) {
// There was an error.
// Possible error codes:
// "access_denied" - User denied access to your app
// "immediate_failed" - Could not automatically log in the user
// console.log('There was an error: ' + authResult['error']);
}
}
</script>
<!-- Place this asynchronous JavaScript just before your </body> tag -->
<script type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/client:plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
</body>
</html>
I had the same problem when I was trying that code sample. When trying to figure it out, I found this post:
https://groups.google.com/forum/?fromgroups#!topic/google-plus-developers/Ax3cMLhMR4Q
in the Google+ Developers Forum that seems to indicate that it's not really an 'error' but some kind of warning. If I find out more, I'll post an update here.
Hope this helps.