How to capture console.log from external sources? - javascript

I understand how to modify the console.log function to intercept the logs and push it into an array. However this does not seem to work for all console log. In my html, I've loaded a html webapp (\creative\300x600 with video\index.html) that also does a console.log("click detected") that I can see in my chrome dev tools, but is not captured by console. ogs (The second script in the code example). I suspect that because this is an external file being loaded in, I cannot intercept it.
Is there a solution to get all console.log from any source and save it?
<!DOCTYPE html>
<head>
<script>
//add index.html to div on click
function load_home() {
console.log("Loaded");
document.getElementById("content").src='creative\\300x600 with video\\index.html';
}
window.addEventListener("click",load_home);
</script>
<script>
//modify console.log
console.defaultLog = console.log.bind(console);
console.logs = [];
console.log = function() {
console.defaultLog.apply(console, arguments);
console.logs.push(Array.from(arguments));
};
</script>
</head>
<html>
<iframe id="content" style="width: 300px; height:600px; background-color:blue" ></iframe>
</body>
</html>
EDIT:
Tried making it on a div rather than in an iframe, same issue of not being able to record the console.log of the external html. Only console.log("loaded") from the load_home function gets logged.
<!DOCTYPE html>
<head>
<script>
function load_home() {
console.log("Loaded");
document.getElementById("content").innerHTML='<object type="text/html" data="creative\\300x600 with video\\index.html" ></object>';
}
window.addEventListener("click",load_home);
</script>
<script>
console.defaultLog = console.log.bind(console);
console.logs = [];
console.log = function() {
console.defaultLog.apply(console, arguments);
console.logs.push(Array.from(arguments));
};
</script>
</head>
<html>
<div id="content" style="width: 300px; height:600px; z-index:-1;" ,"onclick=load_home();" </div>
</body>
</html>

The problem here is because of that iframe. iframes have a different window object, independent from the parent's window object. This means whatever modifications you did to the parent's window.console will not affect the iframe's window.console.
You could get the frame's window object via contentWindow and modify its console. But you'd have to do this for each present and future iframe. Additionally, you cannot access the contentWindow of a iframe rendering a page from another domain.
If you're attempting to capture the logs of all the frames and somehow consolidate them into one big log, a better option is to have that same console-altering script on every page you want tracked. Then send all your logs to the server, ordered by timestamp or something. That's pretty much how Sentry works.

Related

Loading widget on web page

I'm trying to make a loadable widget that would call an api when a button is clicked.
Widget page itself
widget.html
<html>
<head>
<title>Widget</title>
</head>
<body>
<button id="test"></button>
<script>
window.onload = init;
function clicked() {
// some logic
}
function init() {
document.getElementById('test').addEventListener('click', clicked, false);
}
export {clicked}
</script>
</body>
</html>
The page it embeds on
index.html
<!DOCTYPE HTML>
<html>
<head>
<title>Getting started</title>
</head>
<body>
<div>
<div id="widget_box"></div>
<script src="http://localhost:8080/js/widget.js" type="text/javascript"></script>
<script type="text/javascript">wdgt.init('widget_box');</script>
</div>
</body>
</html>
js code that loads the widget
widget.js
var wdgt= {
idBox: 'wdgt',
url_widget: 'http://localhost:8080/pages/widgets/widget.html',
url_style: 'http://localhost:8080/css/widget.css',
init: function (id) {
console.log("Begin Widget initialization");
if (!id) {
id = this.idBox;
}
if (document.getElementById(id)) {
this.addStyle();
try {
var XHR = ("onload" in new XMLHttpRequest()) ? XMLHttpRequest : XDomainRequest;
var xhr = new XHR();
xhr.open('GET', this.url_widget, true);
xhr.onload = function () {
if (this.response) {
document.getElementById(id).innerHTML = this.response;
}
}
xhr.onerror = function () {
console.log('onerror ' + this.status);
}
xhr.send();
} catch (ignore) {
}
} else {
console.log('The specified block id="' + id + '" is missing');
}
},
addStyle: function () {
style = document.createElement('link');
style.rel = 'stylesheet';
style.type = 'text/css';
style.href = this.url_style;
document.head.appendChild(style);
}
}
If I open the widget in a separate window, the code attached to the button works. But when I try to embed it, nothing happens.
Moreover, in this script, document.getElementById() returns null when trying to find the button.
The back is a simple Spring application that returns index.html
TL;DR: It's not supposed to work. You should use iframe element to fetch and render external pages.
Your script widget.js is trying to render the contents of fetched widget.html into a <div> element.
The browser will to do the best, though it won't be able to create another DOM tree inside of <div>. Because when you feed a whole HTML page to innerHTML, you basically ask the browser to render a document inside a document. This is not allowed.
Still it will render the contents of you document's body. So you'll be able to see the button. But it won't execute any <script> tags. It's a safety measure to prevent XSS attacks. A couple of dirty ways to execute your code do exist, but I won't recommend them.
So what should you do to add an external widget into a page? The answer is neat: meet the <iframe>! This dude is created just for those things. For you case, you should rewrite index.html this way:
<!DOCTYPE HTML>
<html>
<head>
<title>Getting started</title>
</head>
<body>
<iframe src="http://localhost:8080/pages/widgets/widget.html" width="800" height="600"></iframe>
</body>
</html>
With iframes, you don't need to manually fetch your widget HTML. The browser will download and render it inside your iframe. Like a document inside a document with all the styles, embedded resources and scripts.
Please note, that when you embed something using iframe, security limitations apply. You won't be able to directly interact with your main page from inside the iframe and vice versa. It will be like a separate window inside you document. And it will have additional constraints. Please address to the docs.

why this console.log() function doesn't work?

<!DOCTYPE html>
<html>
<head>
<title>LearnJS</title>
</head>
<body>
<script>
console.log('hello World\nThis is me');
alert("This is an \nalert.");
</script>
</body>
</html>
I have tried this code and run in TORCH borwser... The only output shown is alert But it doesn't display output of console.log...
What is the possible solution...
I have use
document.write('hello World\nThis is me');
But this code doesn't feed new line so i was supposed to use console.log...
It is working fine here :). Run Code Snippet
<!DOCTYPE html>
<html>
<head>
<title>LearnJS</title>
</head>
<body>
<script>
console.log('hello World\nThis is me on console');
alert("This is an \nalert.");
document.write("This is an document.write.");
</script>
</body>
</html>
Note:
developers use console.log() for logging useful information on browser console
document.write() modifies what user sees in the browser by adding additional content to DOM.
alert()'s are used to alert end users who access the web page on browser.
N.B If you're in confusion about How stackoverflow.com shows console.log() on a browser div. Then see here https://stackoverflow.com/a/20256785/1138192 it is kind of overriding the default behavior of console.log() to show the messages on browser div. Hope this helps :)
console.log() only displays in the developer console of the browser. It does not display on the web page itself.
Your code is not feeding a new line because \n only shows in the source code not on the page. To display a new line in HTML on the page you need to use a <br> tag or use other form of spacing.
So, instead of:
document.write('hello World\nThis is me');
You could use:
document.write('hello World<br>This is me');
However, rather than using document.write(), you may prefer to write to a specific element in the page. Below I give an element an id of data and then use the JavaScript code to write to this element.
<!DOCTYPE html>
<html>
<body>
<div id="data">You can put text here or leave it blank. It will be replaced.</div>
<script>
document.getElementById("data").innerHTML = "Hello world<br>This is me";
</script>
</body>
</html>
Notice also, I need to place the document.getElementByID("data") script after the div is created. If I place it before it will not be able to find it. The script code is therefore placed at the end of the <body> section. There are better ways to do this (such as placing JavaScript code in an external file and using defer), but for your purposes this should work quite well.

Why use window.onload

I have tried finding an answer to this on my own, but only found instructions on how to use onload events. I seem to be missing the point.
I've been taught that if I want something to happen when the page loads, I should use window.onload like this:
<script>
window.onload = dosomething();
function dosomething()
{
window.alert('hello');
}
</script>
But now that I am thinking on my own I wonder what the point of doing that is. Because this also produces the same result:
<script>
dosomething();
function dosomething()
{
window.alert('hello');
}
</script>
Anything I put at the top inside <script> is going to execute anyway... so what's the point of window.onload?
If you're directly running your code with dosomething();, you're delaying your browser's rendering for the time it takes your JavaScript code to run.
You can try to insert your code to the <head> of your html document:
<!DOCTYPE html>
<html>
<head>
<script>
dosomething();
function dosomething()
{
window.alert('hello');
}
</script>
</head>
<body>
Does not render before the alert is dismissed!
</body>
</html>
You'll see that the page stays blank until you dismiss the alert. So every second the browser takes to run your JavaScript code is a second that your users have to wait for the site to be rendered.
Now if you change the code to be run on body's onload, the page gets rendered before the alert is shown:
<!doctype html>
<html>
<head>
<script>
function dosomething()
{
window.alert('hello');
}
</script>
</head>
<body onload="dosomething()">
This page gets rendered before the alert!
</body>
</html>
Consider these two blocks of code:
<head>
<script>
alert(document.getElementById('foo').value);
</script>
</head>
<body>
<input id="foo" value="hello">
</body>
<head>
<script>
window.onload = function() {
alert(document.getElementById('foo').value);
}
</script>
</head>
<body>
<input id="foo" value="hello">
</body>
In the first example, we'll get an error because the element you are referencing isn't found when the script runs - and so you are trying to get value of null.
In the second example, document.getElementById() will find the element with the id foo, because window.onload will get fired only when the complete DOM has been loaded and so the element is available.
window.onload will fire once the DOM has finished loading. In your example, the DOM is not required. However, the following code will fail if the DOM has not yet loaded:
function doSomething() {
alert(document.getElementById('test').innerText);
}
// Throws: TypeError: Cannot read property 'innerText' of null
Assuming your page contains an element with id test, it will alert its text.
waiting for the onload event assures you that all of your scripts and resources are loaded
Assume you are using jquery in your page and you invoked a function that uses it directly without onload , you can't guarantee that the jquery file has been loaded, which will lead to errors and possibly ruining your whole logic
The onload event is handy to make sure the page is fully loaded before you run a script. For your example above it doesn't make sense, but if your page is still loading an item on the bottom and you try to call it then nothing will run.
I recommend using jQuery and using the ready function. This way you will ensure your page is completely loaded.
$( document ).ready(function() {
// This will only run after the whole page is loaded.
});
If you don't want to load query, just put your javascript at the bottom of the page. It's best practice, and ensures the DOM is loaded in full.
For more info on the jquery ready function go here: https://api.jquery.com/ready/

javascript print() method is not working as expected

I have a simple HTML code to print the page. Below is the code:
<!DOCTYPE html>
<html>
<head>
<script>
function printPage()
{
var w = window.open("http://www.sigmaaldrich.com/catalog/CofADocRequest.do?symbol=209104&LotNo=MKBP0842V&brandTest=SIGMA","_self");
window.focus();
window.print();
}
</script>
</head>
<body >
<input type="button" onclick="printPage()" value="print a div!" />
</body>
</html>
What the code does is, it displays a button, on clicking that button it calls a function. The function uses open() to open a new URL in the same page by using the “_self ” parameter.
As we can see in the code, the print() is being called after the call to open method. But in my browser IE11, the print pop is being shown befor loading the page.
Due to this I am not printing the correct page.
Can anybody help me on this.
The problem is that window refers to the current window, which is the original.
By opening a new window in self you replace the page, this is basically a redirect.
And if you open it via popup and print it as w.print() than you run into cross-origin security error.
You could use iframe to this with a proxy as shown here
How do print specific content inside the iframe
and
here
How do print specific content inside the iframe

Can I communicate between two local html files using javascript?

I have two local .html files in the same folder. One page opens a window with the other page, and attempts to call a function in the newly opened window. However, the function call fails, and I get this in the console:
Unsafe JavaScript attempt to access frame with URL file:///***/A.html from frame with URL file:///***/B.html. Domains, protocols and ports must match.
This happens on both Chrome and Webkit (Mac). Is there any way I can either: disable the cross-domain checks for the file:// protocol, or call a javascript function in a different local file?
You can use window.postMessage to do something like this:
The initial window html file:
<!DOCTYPE html>
<html>
<head>
<script>
var otherWindow;
function openOther() {
otherWindow = window.open("other.html", "otherWindow");
}
function otherFunc() {
otherWindow.postMessage("otherFunc", "*");
}
</script>
</head>
<body>
<div onclick="openOther()">Open the other window</div>
<div onclick="otherFunc()">Call the other window's function</div>
</body>
</html>
Html for the second window:
<!DOCTYPE html>
<html>
<head>
<script>
window.addEventListener("message", function(event) {
alert("The other window's function executed.");
}, false);
</script>
</head>
<body>
<div>This is the other window.</div>
</body>
</html>
Here's a good reference for window.postMessage.

Categories

Resources