Context When Loading JS File Dynamically [duplicate] - javascript
I am a JavaScript newbie and learn by working on a pure JavaScript "project" that calculates mathematical functions. It all works well. Now, as a further step, I want to make the messaging multilingual. The code should be capable of loading the appropriate language file at runtime. For the dynamic loading issue, I read and found solutions on Web pages like this one.
Before writing the dynamic code, I loaded it statically and the test code worked well. The code I am asking for help about is just making the minor difference of loading a "script" element.
The code where I run into problems is the this.getString function, where it is not possible to access the de element in the language file. At line console.log(eval(language, tag));, I get the error message "Uncaught ReferenceError: de is not defined".
//File: Utils/Lang/js/FileUtils.js
function Language(language) {
var __construct = function(dynamicLoad) {
if (typeof language == 'undefined') {
language = "en";
}
// Load the proper language file:
loadFile("js/resources/lang.de.js");
return;
} ()
this.getString = function(tag, strDefault) {
console.log("getString(" + tag + ", " + strDefault + "): ");
console.log("getString(...): document = " + document);
console.log("getString(...): eval(" + language + ", " + tag + ") = ");
console.log(eval(language, tag));
var strReturn = eval('eval(language).' + tag);
if (typeof strReturn != 'undefined') {
return strReturn;
} else {
return (typeof strDefault != 'undefined')
? strDefault
: eval('en.' + tag);
}
}
}
The static test code that works is not included, where I can access the de element.
My question: How to load the language file properly so that the de tag is accessible?
Thank you for your help!
//File: Utils/Files/js/FileUtils.js
function loadFile(filepathname) {
var reference = document.createElement('script');
reference.setAttribute("type", "text/javascript");
reference.setAttribute("src", filepathname);
if (typeof reference != 'undefined') {
document.getElementsByTagName("head")[0].appendChild(reference);
}
console.log("loadFile(\"" + filepathname + "\"): document = " + document);
}
//File: Utils/Lang/js/resources/lang.de.js:
de = {
pleaseWait: "Bitte warten..."
};
//File: Utils/Lang/js/resources/lang.en.js
en = {
pleaseWait: "Please wait..."
};
//File: Utils/Lang/js/TestLanguage.js:
function output() {
console.log("output()");
var codes = ['de', 'en'];
for (var i = 0; i < codes.length; i++) {
var translator = new Language(codes[i]);
var message = "output(): in " + translator.getLanguage() + ": ";
message += translator.getString('pleaseWait');
console.log(message);
}
}
<!--File: Utils/Lang/TestLang.html:-->
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Test languages</title>
<script type="text/javascript" src="../Files/js/FileUtils.js"></script>
<script type="text/javascript" src="js/Language.js"></script>
<script type="text/javascript" src="js/TestLanguage.js"></script>
</head>
<body>
<button name="outputButton" onclick="output();">Click</button>
<br>Please press [F12] so that you can see the test results.
</body>
</html>
When you add the script tag to your document, it is not loaded synchronously. You need to wait for the file to be loaded before you can use the code that was in it.
you may be able to redesign your code to use a script.onload callback:
var reference = document.createElement('script');
// ...
reference.onload = function() {
alert("Script loaded and ready");
};
but for this scenario, if you don't have many language string you may be best to just load them all statically.
How to dynamically load a script file (the most basic version, also there are multiple options to this):
function loadScriptFile(scriptPath, jsFile, callBack)
{
var scriptTag = document.createElement("script"); //creates a HTML script element
scriptTag.language = "JavaScript"; //sets the language attribute
scriptTag.type = "text/javascript";
scriptTag.src = scriptPath + jsFile + ".js"; //the source
if (callBack)
{
scriptTag.onload = callback; //when loaded execute call back
}
var scriptTagParent = document.getElementsByTagName("script")[0];
if (scriptTagParent)
{
scriptTagParent.parentNode.insertBefore(scriptTag, scriptTagParent);
}
else
{
document.body.appendChild(scriptTag);
}
}
How it works:
Run loadScriptFile("scripts", "math", startProgram). The first two arguments will point to your file and folder. The last argument is a callback function. When defined this will be executed once the script tag has finished loading and the script is available in the global scope. The script will be dynamically added to your page. If there is a script element present on the page, this will be added before that (to keep the mark up nice). If not it will be appended to the body. (this is only visual).
The callback part is the most interesting. Since your script will now be asynchronical, you'll need to use callback to tell your program that the necessary files are loaded. This callback is fired when the script file is loaded, so you won't get script errors.
Just a basic example of what I meant in my comment:
This is not an answer to your question, it's an alternative way (I think it's better to manage). Pure Javascript (with help of XML)
XML-file: language.xml
Basic XML structure:
<language>
<l1033 name="english" tag="en-US">
<id1000>
<![CDATA[
Hello World!
]]>
</id1000>
</l1033>
<l1031 name="german" tag="de-DE">
<id1000>
<![CDATA[
Hallo Welt!
]]>
</id1000>
</l1031>
</language>
What did I do:
I constructed a root element called language. Within that wrote two language strings called l1033 for English and l1031 for German. Note that a letter is prepended before the language code. XML will throw an error when a tag starts with a digit. a CDATA block is used to prevent any problems with special characters.
Now the loading will be done by AJAX:
var xmlLoader = new XMLHttpRequest();
xmlLoader.onreadystatechange = trackRequest; //event to track the request, with call back
xmlLoader.open("get", "language.xml", true); //set asynchronous to true
xmlLoader.send(null);
function trackRequest()
{
if (this.status == 200 && this.readyState == 4) //all is good
{
globalLanguageFile = this.responseXML;
startProgram(); //fictive function that starts your program
}
}
Now the XML is loaded. How to load strings from it?
function loadLanguageString(code, id, fallback)
{
var word = fallback;
if (globalLanguageFile.getElementsByTagName("l"+code).length > 0)
{
if (globalLanguageFile.getElementsByTagName("l"+code).[0].getElementsByTagName("id"+id).length > 0)
{
//found the correct language tag and id tag. Now retrieve the content with textContent.
word = globalLanguageFile.getElementsByTagName("l"+code).[0].getElementsByTagName("id"+id)[0].textContent;
}
}
return word; //when failed return fall back string
}
How to call the function:
loadLanguageString(1031, 1000, "Hello World!");
I found the right answer to my question using the info from GarethOwen. Here are the code modifications I had to do:
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Test languages</title>
<script type="text/javascript" src="../Arrays/js/ArrayUtils.js"></script>
<script type="text/javascript" src="../Files/js/FileUtils.js"></script>
<script type="text/javascript" src="../Logic/js/LogicalUtils.js"></script>
<script type="text/javascript" src="js/LanguageUtils.js"></script>
<script type="text/javascript" src="js/TestLanguageUtils.js"></script>
</head>
<!-- body onload="load(null, '../Maths/js/resources')" -->
<body onload="load();">
<button onclick="output();">Click</button><br>
Please press [F12] so that you can see the test results.
</body>
</html>
TestLanguage.html: Augmented the body tag
<body onload="load()">
TestLanguage.js:
2a. Added the load() function requested by the HTML page now:
var gCodes = ['de', 'en', 'tr'];
function load() {
console.log("load()");
for (var i = 0; i < codes.length; i++) {
new Language(codes[i]);
}
}
2b. Using the global gCodes variable also in the output() function
Language.js: To test the whole better, I made the code in the function Language a little bit more elaborate by changing the line in the constructor in function Language(language) to:
// Load the proper language file:
if (eval("gLoaded.indexOf('" + language + "') < 0")) {
loadFile("js/resources/lang." + language + ".js");
gLoaded[gLoaded.length] = language;
}
Thank you for your support! :-)
//Lang/js/Lang.js:
"use strict";
/**
* Object for multilingual message handling.
*
* #param language
*/
function Language(language) {
var __construct = function(dynamicLoad) {
if (typeof language == 'undefined') {
language = "en";
}
// Load the proper language file:
switch (language) {
case "de":
loadFile("js/resources/lang.de.js");
break;
case "tr":
loadFile("js/resources/lang.tr.js");
break;
default:
loadFile("js/resources/lang.en.js");
}
return;
}()
/**
* Returns the language of that object.
*
* #returns The language
*/
this.getLanguage = function() {
var strLanguage;
switch (language) {
case "de":
strLanguage = "German";
break;
case "tr":
strLanguage = "Turkish";
break;
default:
strLanguage = "English";
}
return strLanguage;
}
/**
* Returns the language code of that object.
*
* #returns The language code
*/
this.getString = function(tag, strDefault) {
var strReturn = eval('eval(language).' + tag);
if (typeof strReturn != 'undefined') {
return strReturn;
} else {
return (typeof strDefault != 'undefined') ? strDefault : eval('en.' + tag);
}
}
}
//Lang/js/TestLang.js:
"use strict";
var gCodes = ['de', 'en', 'tr'];
function load() {
console.log("load()");
for (var i = 0; i < gCodes.length; i++) {
new Language(gCodes[i]);
}
}
/**
* Object for multilingual message handling.
*
* #param language
*/
function output() {
console.log("output()");
for (var i = 0; i < gCodes.length; i++) {
var translator = new Language(gCodes[i]);
var message = "output(): in " + translator.getLanguage() + ": ";
message += translator.getString('pleaseWait');
console.log(message);
}
}
//Utils/Files/js/FileUtils.js:
"use strict";
/**
* Object with file utilities
*
* #param filepathname
*/
function loadFile(filepathname) {
var methodName = "loadFile(" + filepathname + "): "
var reference = document.createElement('script');
reference.setAttribute("type", "text/javascript");
reference.setAttribute("src", filepathname);
if (typeof reference != 'undefined') {
document.getElementsByTagName("head")[0].appendChild(reference);
}
reference.onload = function() {
console.log(methodName + "onload(): Language script loaded and ready!");
}
}
Here is the console output:
Here is the output:
load()
loadFile(js/resources/lang.de.js): onload(): Language script loaded and ready!
loadFile(js/resources/lang.en.js): onload(): Language script loaded and ready!
loadFile(js/resources/lang.tr.js): onload(): Language script loaded and ready!
output()
output(): in German: Bitte warten...
output(): in English: Please wait...
output(): in Turkish: Lütfen bekleyiniz...
loadFile(js/resources/lang.de.js): onload(): Language script loaded and ready!
loadFile(js/resources/lang.en.js): onload(): Language script loaded and ready!
loadFile(js/resources/lang.tr.js): onload(): Language script loaded and ready!
Related
MediaInfoLib JavaScript with MVC 5 .NET C#
I have a website developed in C# MVC5 .NET and I need to use de MediaInfolib DLL javascript version. I am not able to load the .wasm file. This is my .cshtml code: <script type="text/javascript"> // Load the WebAssembly MediaInfo module if the browser supports it, // otherwise load the asmjs module var wasm_path ="#Url.Content("~/")" + "lib/MediaInfo_DLL/"; var MediaInfoJs = document.createElement('script'); if ('WebAssembly' in window) { MediaInfoJs.src = wasm_path + "MediaInfoWasm.js"; } else { MediaInfoJs.src = wasm_path + "MediaInfo.js"; } document.body.appendChild(MediaInfoJs); // Continue initialization MediaInfoJs.onload = function () { var MediaInfoModule, MI, processing = false, CHUNK_SIZE = 1024 * 1024; var finish = function() { MI.Close(); MI.delete(); processing = false; } ... MediaInfoModule = MediaInfoLib( {'locateFile': function(path, prefix) {return wasm_path + path; }}, { 'postRun': function () { console.debug('MediaInfo ready'); // Information about MediaInfo document.getElementById('result').innerText = 'Info_Parameters:\n'; document.getElementById('result').innerText += MediaInfoModule.MediaInfo.Option_Static('Info_Parameters') + '\n\n'; document.getElementById('result').innerText += 'Info_Codecs:\n'; document.getElementById('result').innerText += MediaInfoModule.MediaInfo.Option_Static('Info_Codecs') + '\n'; // Get selected file var input = document.getElementById('input'); input.onchange = function() { if(input.files.length > 0) { document.getElementById('result').innerText = "Processing..."; parseFile(input.files[0], showResult); } } } }); }; </script> I have these warnings in the MediaInfoWasm.js and the page doesn`t work: MediaInfoWasm.js:19 failed to asynchronously prepare wasm: failed to load wasm binary file at '/lib/MediaInfo_DLL/MediaInfoWasm.wasm' Module.c.printErr.c.printErr # MediaInfoWasm.js:19 MediaInfoWasm.js:19 failed to load wasm binary file at '/lib/MediaInfo_DLL/MediaInfoWasm.wasm' Module.c.printErr.c.printErr # MediaInfoWasm.js:19 Has somebody used this MediaInfolib javascript version with MVC5? Thanks in advance. María José.
JAVASCRIPT - Read local file, filter for a word and print word's line
I have the following code. It can open a file and display it in the browser. But I want to: - Select many files instead of one; - Then Filter on these files for a word (username); - Then print username's line (text file: username xxxx); - If the word "username" is not found , print - text file: not found Any idea? <!DOCTYPE html> <html> <head> <title>Read File (via User Input selection)</title> <script type="text/javascript"> var reader; //GLOBAL File Reader object for demo purpose only /** * Check for the various File API support. */ function checkFileAPI() { if (window.File && window.FileReader && window.FileList && window.Blob) { reader = new FileReader(); return true; } else { alert('The File APIs are not fully supported by your browser. Fallback required.'); return false; } } /** * read text input */ function readText(filePath) { var output = ""; //placeholder for text output if(filePath.files && filePath.files[0]) { reader.onload = function (e) { output = e.target.result; displayContents(output); };//end onload() reader.readAsText(filePath.files[0]); }//end if html5 filelist support else if(ActiveXObject && filePath) { //fallback to IE 6-8 support via ActiveX try { reader = new ActiveXObject("Scripting.FileSystemObject"); var file = reader.OpenTextFile(filePath, 1); //ActiveX File Object output = file.ReadAll(); //text contents of file file.Close(); //close file "input stream" displayContents(output); } catch (e) { if (e.number == -2146827859) { alert('Unable to access local files due to browser security settings. ' + 'To overcome this, go to Tools->Internet Options->Security->Custom Level. ' + 'Find the setting for "Initialize and script ActiveX controls not marked as safe" and change it to "Enable" or "Prompt"'); } } } else { //this is where you could fallback to Java Applet, Flash or similar return false; } return true; } /** * display content using a basic HTML replacement */ function displayContents(txt) { var el = document.getElementById('main'); el.innerHTML = txt; //display output in DOM } </script> </head> <body onload="checkFileAPI();"> <div id="container"> <input type="file" onchange='readText(this)' /> <br/> <hr/> <h3>Contents of the Text file:</h3> <div id="main"> ... </div> </div> </body> </html>
I havent tested this, but does the basic idea work? Read the files through a for-loop, and search for your target string. If you get to the end and you dont find it, return your empty message; function SearchFiles(var target_string, var file_paths){ var fs = require("fs"); my_file_paths.foreach(function(filepath){ var text = fs.readFileSync(filepath); var pos = text.search(target_string); if (pos>1) { return text.substring(pos, pos + target_string.length); } } return "not found" } // now to use the function var my_file_paths; // init this to what you want to search through var target_username; // init this as well var found_username = SearchFiles(target_username, my_file_paths); DisplayContents("text file: " + found_username);
Passing parameters while Linking to another html page in google apps script
First, this is a google-app-script issue... I can't seem to capture the second (or subsequent) parameters within the HTML page (i.e. "item" in this example)... I've seen many examples using "location.search" and "window.location.search", but none of these seem to work. Could it possibly be as simple as "location.search" is not the correct usage? Example Code.gs var myParam; /** * Get the URL for the Google Apps Script running as a WebApp. */ function getScriptUrl() { var url = ScriptApp.getService().getUrl(); return url; } /** * Get "home page", or a requested page. * Expects a 'page' parameter in querystring. * * #param {event} e Event passed to doGet, with querystring * #returns {String/html} Html to be served */ function doGet(e) { //Logger.log( Utilities.jsonStringify(e) ); Logger.log(e.parameter.page); var pgToLoad = e.parameter.page; if (!e.parameter.page) { Logger.log('!e.parameter.page') // When no specific page requested, return "home page" // return HtmlService.createTemplateFromFile('my1').evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME); return HtmlService.createTemplateFromFile('my1').evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME); } Logger.log('there is something for the page'); // else, use page parameter to pick an html file from the script // return HtmlService.createTemplateFromFile(pgToLoad).evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME); return HtmlService.createTemplateFromFile(pgToLoad).evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME); } I have multiple HTML files, but they are basically the same as my1.html below... my1.html <!DOCTYPE html> <html> <head> <base target="_top"> </head> <body> <h1>Source = my1.html</h1> <p id=myParam>Placeholder</p> <?var url = getScriptUrl();?><a href='<?=url?>?page=my2&item=1-234'> <input type='button' name='button' value='my2.html'></a> <?var url = getScriptUrl();?><a href='<?=url?>?page=my3&item=1-345'> <input type='button' name='button' value='my3.html'></a> </body> </html> <script> function getParam(sname) { var params = location.search; var sval = ""; params = params.split("&"); // split param and value into individual pieces for (var i=0; i<params.length; i++) { temp = params[i].split("="); if ( temp[0] == sname ) { sval = temp[1]; } } return sval; } function changeItem() { var param = getParam("item"); var myItem = "Item:-"+param+"-"; document.getElementById("myParam").innerHTML = myItem; } window.onload = changeItem; </script>
I think I know what you want to do. It looks like you are getting the search string parameters from the doGet(e) function on the server side, then you are trying to get the same search string parameters again on the "client side" from the onload function? If this is the case, I would abandon trying to get the search string parameters from the client side. You could store the search string parameters in the browsers sessionStorage: window.sessionStorage.setItem("searchStringOne","Value One"); and to retrieve: var valueOne = window.sessionStorage.getItem("searchStringOne"); Session Storage Information
Here's an example to show how to get the query string parameters to serve different html templates using html-service of app script : function doGet(e) { Logger.log( Utilities.jsonStringify(e) ); // Load a home page when no parameter is specified if (!e.parameter.redirect) { var template = HtmlService.createTemplateFromFile('home'); var htmlOutput = template.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME).setTitle('Home'); return htmlOutput; } //get the page from parameter and load it else{ var template=HtmlService.createTemplateFromFile(e.parameter['redirect']); var htmlOutput = template.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME).setTitle('Other Page'); return htmlOutput; } } function getScriptUrl() { var url = ScriptApp.getService().getUrl(); return url; } then HTML will look like this : home.html <?var url = getScriptUrl();?> You are on Home Page. <a href='<?=url?>?redirect=pagex'>Goto PageX</a> <a href='<?=url?>?redirect=pagey'>Goto PageY</a> pagex.html You are on PageX pagey.html You are on PageY Hope this helps!
How to save the current webpage with casperjs/phantomjs?
Is there a way to save the current webpage by using casperjs or phantomjs? I tried to get the html and save it into a file. But the resulting file was a lot different from the screenshot of that time (with casper.capture). Is there a way to save the current webpage?
Andrey Borisko suggested to use the disk cache to retrieve the resources. My solution is not that efficient, but you don't need to decompress text files. I use XMLHttpRequest to retrieve all resources after I registered them with the resource.received event handler. I then filter the resources into images, css and fonts. The current limitation is that remote resource paths that contain something like ../ or ./ are not handled correctly. I retrieve the current page content with getHTML and iterate over all captured resources to replace the path used in the markup, that is identified by a portion of the complete resource URL, with a randomly generated file name. The file extension is created from the content type of the resource. It is converted using mimeType from this gist. Since CSS files may contain background images or fonts, they have to be processed before saving to disk. The provided loadResource function loads the resource, but does not save it. Since XMLHttpRequest to download the resources the script has to be invoked with the --web-security=false flag: casperjs script.js --web-security=false script.js var casper = require("casper").create(); var utils = require('utils'); var fs = require('fs'); var mimetype = require('./mimetype'); // URL provided below var cssResources = []; var imgResources = []; var fontResources = []; var resourceDirectory = "resources"; var debug = false; fs.removeTree(resourceDirectory); casper.on("remote.message", function(msg){ this.echo("remote.msg: " + msg); }); casper.on("resource.error", function(resourceError){ this.echo("res.err: " + JSON.stringify(resourceError)); }); casper.on("page.error", function(pageError){ this.echo("page.err: " + JSON.stringify(pageError)); }); casper.on("downloaded.file", function(targetPath){ if (debug) this.echo("dl.file: " + targetPath); }); casper.on("resource.received", function(resource){ // don't try to download data:* URI and only use stage == "end" if (resource.url.indexOf("data:") != 0 && resource.stage == "end") { if (resource.contentType == "text/css") { cssResources.push({obj: resource, file: false}); } if (resource.contentType.indexOf("image/") == 0) { imgResources.push({obj: resource, file: false}); } if (resource.contentType.indexOf("application/x-font-") == 0) { fontResources.push({obj: resource, file: false}); } } }); // based on http://docs.casperjs.org/en/latest/modules/casper.html#download casper.loadResource = function loadResource(url, method, data) { "use strict"; this.checkStarted(); var cu = require('clientutils').create(utils.mergeObjects({}, this.options)); return cu.decode(this.base64encode(url, method, data)); }; function escapeRegExp(string) { // from https://stackoverflow.com/a/1144788/1816580 return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); } function replaceAll(find, replace, str) { // from https://stackoverflow.com/a/1144788/1816580 return str.replace(find, replace); } var wrapFunctions = [ function wrapQuot1(s){ return '"' + s + '"'; }, function wrapQuot2(s){ return "'" + s + "'"; }, function csswrap(s){ return '(' + s + ')'; } ]; function findAndReplace(doc, resources, resourcesReplacer) { // change page on the fly resources.forEach(function(resource){ var url = resource.obj.url; // don't download again if (!resource.file) { // set random filename and download it **or** call further processing which in turn will load ans write to disk resource.file = resourceDirectory+"/"+Math.random().toString(36).slice(2)+"."+mimetype.ext[resource.obj.contentType]; if (typeof resourcesReplacer != "function") { if (debug) casper.echo("download resource (" + resource.obj.contentType + "): " + url + " to " + resource.file); casper.download(url, resource.file, "GET"); } else { resourcesReplacer(resource); } } wrapFunctions.forEach(function(wrap){ // test the resource url (growing from the back) with a string in the document var lastURL; var lastRegExp; var subURL; // min length is 4 characters for(var i = 0; i < url.length-5; i++) { subURL = url.substring(i); lastRegExp = new RegExp(escapeRegExp(wrap(subURL)), "g"); if (doc.match(lastRegExp)) { lastURL = subURL; break; } } if (lastURL) { if (debug) casper.echo("replace " + lastURL + " with " + resource.file); doc = replaceAll(lastRegExp, wrap(resource.file), doc); } }); }); return doc; } function capturePage(){ // remove all <script> and <base> tags this.evaluate(function(){ Array.prototype.forEach.call(document.querySelectorAll("script"), function(scr){ scr.parentNode.removeChild(scr); }); Array.prototype.forEach.call(document.querySelectorAll("base"), function(scr){ scr.parentNode.removeChild(scr); }); }); // TODO: remove all event handlers in html var page = this.getHTML(); page = findAndReplace(page, imgResources); page = findAndReplace(page, cssResources, function(cssResource){ var css = casper.loadResource(cssResource.obj.url, "GET"); css = findAndReplace(css, imgResources); css = findAndReplace(css, fontResources); fs.write(cssResource.file, css, "wb"); }); fs.write("page.html", page, "wb"); } casper.start("http://www.themarysue.com/").wait(3000).then(capturePage).run(function(){ this.echo("DONE"); this.exit(); }); The magic happens in findAndReplace. capturePage is completely synchronous so it can be dropped anywhere without much head ache. URL for mimetype.js
No, I don't think there is an easy way to do this as phantomjs doesn't support rendering pages in mht format (Render as a .mht file #10117). I believe that's what you wanted. So, it needs some work to accomplish this. I did something similar, but i was doing it the other way around I had a rendered html code that I was rendering into image/pdf through phantomjs. I had to clean the file first and it worked fine for me. So, what I think you need to do is: strip all js calls, like script tags or onload attributes, etc.. if you have access from local to the resources like css, images and so on (and you don't need authentication to that domain where you grab the page) than you need to change relative paths of src attributes to absolute to load images/etc. if you don't have access to the resources when you open the page then I think you need to implement similar script to download those resources at the time phantomjs loads the page and then redirect src attributes to that folder or maybe use data uri. You might need to change links in css files as well. This will bring up the images\fonts and styling you are missing currently. I'm sure there are more points. I'll update the answer if you need more info, once I see my code.
Chrome extension : Stuck at injecting script won't execute js
I am trying to build a chrome extension. Which would do some search on the page and post the results to the extensions. I am having a hard time running this. Whenever I try to run the extension it is just stuck on Injecting Script. my re.js function printDetails(document_r) { var test = document_r.body; var text = test.innerText; var delim="^^ validatedCache :"; var endlim="</site>"; var idx = text.indexOf(delim); var endInd=text.indexOf(endlim); var tag = "accountName"; var regex = "<" + tag + ">(.*?)<\/" + tag + ">"; var regexg = new RegExp(regex,"g"); var matches = []; while (match = regexg.exec(text.substring(idx+delim.length,endInd))) matches.push("Account Name::::::"+match[1]); return matches; } chrome.extension.sendMessage({ action: "getSource", source: "\n\n\n DETAILS>>>>>\n\n"+printDetails(document) }); selection.js chrome.extension.onMessage.addListener(function(request, sender) { if (request.action == "getSource") { message.innerText = request.source; } }); function onWindowLoad() { var message = document.querySelector('#message'); chrome.tabs.executeScript(null, { file: "re.js" }, function() { // If you try and inject into an extensions page or the webstore/NTP you'll get an error if (chrome.extension.lastError) { message.innerText = 'There was an error injecting script : \n' + chrome.extension.lastError.message; } }); } window.onload = onWindowLoad; popup.html <!DOCTYPE html> <html style=''> <head> <script src='selection.js'></script> </head> <body style="background-image:url(12.png);width:400px; border: 2px solid black;background-color:white;"> <div id='message'>Injecting Script....</div> </body> </html> I know there is some problem with these 2 lines only. var test = document_r.body; var text = test.innerText; What I wan't is to extract the webpage ( contents ) into a string which I am hopefully doing by the above two lines of code. Then do some string manipulation on the code.If I run directly this code in a console with a dummy string . I can execute it so figure something is wrong with these two lines. My extension is stuck on " Injecting Script..." Some help would be appreciated. PS:yes I was able to run it earlier with the same code but somehow it doesn't run now.