Chrome Extension to pull text from script - javascript

I'm attempting to pull "webId%22:%22" var string from a script tag using JS for a Chrome extension. The example I'm currently working with allows me to pull the page title.
// payload.js
chrome.runtime.sendMessage(document.title);
// popup.js
window.addEventListener('load', function (evt) {
chrome.extension.getBackgroundPage().chrome.tabs.executeScript(null, {
file: 'payload.js'
});;
});
// Listen to messages from the payload.js script and write to popout.html
chrome.runtime.onMessage.addListener(function (message) {
document.getElementById('pagetitle').innerHTML = message;
});
//HTML popup
<!doctype html>
<html>
<head>
<title>WebID</title>
<script src="popup.js"></script>
<script src="testButton.js"></script>
</head>
<body>
<button onclick="myFunction()">Try it</button>
<p id="body"></p>
<h3>It's working</h1>
<p id='pagetitle'>This is where the webID would be if I could get this stupid thing to work.</p>
</body>
</html>
What I am trying to pull is the webID from below:
<script if="inlineJs">;(function() { window.hydra = {}; hydra.state =
JSON.parse(decodeURI("%7B%22cache%22:%7B%22Co.context.configCtx%22:%7B%22webId%22:%22gmps-salvadore%22,%22locale%22:%22en_US%22,%22version%22:%22LIVE%22,%22page%22:%22HomePage%22,%22secureSiteId%22:%22b382ca78958d10048eda00145edef68b%22%7D,%22features%22:%7B%22directivePerfSwitch%22:true,%22enable.directive.localisation%22:true,%22enable.directive.thumbnailGallery%22:true,%22enable.new.newstaticmap%22:false,%22disable.forms.webId%22:false,%22use.hydra.popup.title.override.via.url%22:true,%22enable.directive.geoloc.enableHighAccuracy%22:true,%22use.hydra.theme.service%22:true,%22disable.ajax.options.contentType%22:false,%22dealerLocator.map.use.markerClustering%22:true,%22hydra.open.login.popup.on.cs.click%22:false,%22hydra.consumerlogin.use.secure.cookie%22:true,%22use.hydra.directive.vertical.thumbnailGallery.onpopup%22:true,%22hydra.encrypt.data.to.login.service%22:true,%22disable.dealerlocator.fix.loading%22:false,%22use.hydra.date.formatting%22:true,%22use.hydra.optimized.style.directive.updates%22:false,%22hydra.click.pmp.button.on.myaccount.page%22:true,%22use.hydra.fix.invalid.combination.of.filters%22:true,%22disable.vsr.view.from.preference%22:false%7D%7D,%22store%22:%7B%22properties%22:%7B%22routePrefix%22:%22/hydra-graph%22%7D%7D%7D")); }());</script>

You have inline code in onclick attribute which won't work, see this answer.
You can see an error message in devtools console for the popup: right-click it, then "Inspect".
The simplest solution is to attach a click listener in your popup.js file.
The popup is an extension page and thus it can access chrome.tabs.executeScript directly without chrome.extension.getBackgroundPage(), just don't forget to add the necessary permissions in manifest.json, preferably "activeTab".
For such a simple data extraction you don't even need a separate content script file or messaging, just provide code string in executeScript.
chrome.tabs.executeScript({
code: '(' + (() => {
for (const el of document.querySelectorAll('script[if="inlineJs"]')) {
const m = el.textContent.match(/"([^"]*%22webId%22[^"]*)"/);
if (m) return m[1];
}
}) + ')()',
}, results => {
if (!chrome.runtime.lastError && results) {
document.querySelector('p').textContent = decodeURI(results[0]);
}
});

Related

Alternate / Equivalent of jQuery.load in pure JavaScript? [duplicate]

I want home.html to load in <div id="content">.
<div id="topBar"> HOME </div>
<div id ="content"> </div>
<script>
function load_home(){
document.getElementById("content").innerHTML='<object type="type/html" data="home.html" ></object>';
}
</script>
This works fine when I use Firefox. When I use Google Chrome, it asks for plug-in. How do I get it working in Google Chrome?
I finally found the answer to my problem. The solution is
function load_home() {
document.getElementById("content").innerHTML='<object type="text/html" data="home.html" ></object>';
}
Fetch API
function load_home (e) {
(e || window.event).preventDefault();
fetch("http://www.yoursite.com/home.html" /*, options */)
.then((response) => response.text())
.then((html) => {
document.getElementById("content").innerHTML = html;
})
.catch((error) => {
console.warn(error);
});
}
XHR API
function load_home (e) {
(e || window.event).preventDefault();
var con = document.getElementById('content')
, xhr = new XMLHttpRequest();
xhr.onreadystatechange = function (e) {
if (xhr.readyState == 4 && xhr.status == 200) {
con.innerHTML = xhr.responseText;
}
}
xhr.open("GET", "http://www.yoursite.com/home.html", true);
xhr.setRequestHeader('Content-type', 'text/html');
xhr.send();
}
based on your constraints you should use ajax and make sure that your javascript is loaded before the markup that calls the load_home() function
Reference - davidwalsh
MDN - Using Fetch
JSFIDDLE demo
You can use the jQuery load function:
<div id="topBar">
HOME
</div>
<div id ="content">
</div>
<script>
$(document).ready( function() {
$("#load_home").on("click", function() {
$("#content").load("content.html");
});
});
</script>
Sorry. Edited for the on click instead of on load.
Fetching HTML the modern Javascript way
This approach makes use of modern Javascript features like async/await and the fetch API. It downloads HTML as text and then feeds it to the innerHTML of your container element.
/**
* #param {String} url - address for the HTML to fetch
* #return {String} the resulting HTML string fragment
*/
async function fetchHtmlAsText(url) {
return await (await fetch(url)).text();
}
// this is your `load_home() function`
async function loadHome() {
const contentDiv = document.getElementById("content");
contentDiv.innerHTML = await fetchHtmlAsText("home.html");
}
The await (await fetch(url)).text() may seem a bit tricky, but it's easy to explain. It has two asynchronous steps and you could rewrite that function like this:
async function fetchHtmlAsText(url) {
const response = await fetch(url);
return await response.text();
}
See the fetch API documentation for more details.
I saw this and thought it looked quite nice so I ran some tests on it.
It may seem like a clean approach, but in terms of performance it is lagging by 50% compared by the time it took to load a page with jQuery load function or using the vanilla javascript approach of XMLHttpRequest which were roughly similar to each other.
I imagine this is because under the hood it gets the page in the exact same fashion but it also has to deal with constructing a whole new HTMLElement object as well.
In summary I suggest using jQuery. The syntax is about as easy to use as it can be and it has a nicely structured call back for you to use. It is also relatively fast. The vanilla approach may be faster by an unnoticeable few milliseconds, but the syntax is confusing. I would only use this in an environment where I didn't have access to jQuery.
Here is the code I used to test - it is fairly rudimentary but the times came back very consistent across multiple tries so I would say precise to around +- 5ms in each case. Tests were run in Chrome from my own home server:
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
</head>
<body>
<div id="content"></div>
<script>
/**
* Test harness to find out the best method for dynamically loading a
* html page into your app.
*/
var test_times = {};
var test_page = 'testpage.htm';
var content_div = document.getElementById('content');
// TEST 1 = use jQuery to load in testpage.htm and time it.
/*
function test_()
{
var start = new Date().getTime();
$(content_div).load(test_page, function() {
alert(new Date().getTime() - start);
});
}
// 1044
*/
// TEST 2 = use <object> to load in testpage.htm and time it.
/*
function test_()
{
start = new Date().getTime();
content_div.innerHTML = '<object type="text/html" data="' + test_page +
'" onload="alert(new Date().getTime() - start)"></object>'
}
//1579
*/
// TEST 3 = use httpObject to load in testpage.htm and time it.
function test_()
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
{
content_div.innerHTML = xmlHttp.responseText;
alert(new Date().getTime() - start);
}
};
start = new Date().getTime();
xmlHttp.open("GET", test_page, true); // true for asynchronous
xmlHttp.send(null);
// 1039
}
// Main - run tests
test_();
</script>
</body>
</html>
try
async function load_home(){
content.innerHTML = await (await fetch('home.html')).text();
}
async function load_home() {
let url = 'https://kamil-kielczewski.github.io/fractals/mandelbulb.html'
content.innerHTML = await (await fetch(url)).text();
}
<div id="topBar"> HOME </div>
<div id="content"> </div>
When using
$("#content").load("content.html");
Then remember that you can not "debug" in chrome locally, because XMLHttpRequest cannot load -- This does NOT mean that it does not work, it just means that you need to test your code on same domain aka. your server
You can use the jQuery :
$("#topBar").on("click",function(){
$("#content").load("content.html");
});
$("button").click(function() {
$("#target_div").load("requesting_page_url.html");
});
or
document.getElementById("target_div").innerHTML='<object type="text/html" data="requesting_page_url.html"></object>';
<script>
var insertHtml = function (selector, argHtml) {
$(document).ready(function(){
$(selector).load(argHtml);
});
var targetElem = document.querySelector(selector);
targetElem.innerHTML = html;
};
var sliderHtml="snippets/slider.html";//url of slider html
var items="snippets/menuItems.html";
insertHtml("#main",sliderHtml);
insertHtml("#main2",items);
</script>
this one worked for me when I tried to add a snippet of HTML to my main.html.
Please don't forget to add ajax in your code
pass class or id as a selector and the link to the HTML snippet as argHtml
There is this plugin on github that load content into an element. Here is the repo
https://github.com/abdi0987/ViaJS
load html form a remote page ( where we have CORS access )
parse the result-html for a specific portion of the page
insert that part of the page in a div on current-page
//load page via jquery-ajax
$.ajax({
url: "https://stackoverflow.com/questions/17636528/how-do-i-load-an-html-page-in-a-div-using-javascript",
context: document.body
}).done(function(data) {
//the previous request fails beceaus we dont have CORS on this url.... just for illlustration...
//get a list of DOM-Nodes
var dom_nodes = $($.parseHTML(data));
//find the question-header
var content = dom_nodes.find('#question-header');
//create a new div and set the question-header as it's content
var newEl = document.createElement("div");
$(newEl).html(content.html());
//on our page, insert it in div with id 'inserthere'
$("[id$='inserthere']").append(newEl);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>part-result from other page:</p>
<div id="inserthere"></div>
Use this simple code
<div w3-include-HTML="content.html"></div>
<script>w3.includeHTML();</script>
</body>```
This is usually needed when you want to include header.php or whatever page.
In Javascript it's easy especially if you have HTML page and don't want to use php include function but at all you should write php function and add it as Javascript function in script tag.
In this case you should write it without function followed by name Just. Script rage the function word and start the include header.php
i.e convert the php include function to Javascript function in script tag and place all your content in that included file.
I use jquery, I found it easier
$(function() {
$("#navigation").load("navbar.html");
});
in a separate file and then load javascript file on html page
showhide.html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function showHide(switchTextDiv, showHideDiv)
{
var std = document.getElementById(switchTextDiv);
var shd = document.getElementById(showHideDiv);
if (shd.style.display == "block")
{
shd.style.display = "none";
std.innerHTML = "<span style=\"display: block; background-color: yellow\">Show</span>";
}
else
{
if (shd.innerHTML.length <= 0)
{
shd.innerHTML = "<object width=\"100%\" height=\"100%\" type=\"text/html\" data=\"showhide_embedded.html\"></object>";
}
shd.style.display = "block";
std.innerHTML = "<span style=\"display: block; background-color: yellow\">Hide</span>";
}
}
</script>
</head>
<body>
<a id="switchTextDiv1" href="javascript:showHide('switchTextDiv1', 'showHideDiv1')">
<span style="display: block; background-color: yellow">Show</span>
</a>
<div id="showHideDiv1" style="display: none; width: 100%; height: 300px"></div>
</body>
</html>
showhide_embedded.html
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function load()
{
var ts = document.getElementById("theString");
ts.scrollIntoView(true);
}
</script>
</head>
<body onload="load()">
<pre>
some text 1
some text 2
some text 3
some text 4
some text 5
<span id="theString" style="background-color: yellow">some text 6 highlight</span>
some text 7
some text 8
some text 9
</pre>
</body>
</html>
If your html file resides locally then go for iframe instead of the tag. tags do not work cross-browser, and are mostly used for Flash
For ex : <iframe src="home.html" width="100" height="100"/>

what is the error in this web app script to give the desired effect?

enter image description herewe've tried to write a script for a web app to a specific spreadsheet
the code is 2 files one in js
function doGet() {
return HtmlService.createHtmlOutputFromFile("page");
}
//function userClicked(name) {
//var url = "https://docs.google.com/spreadsheets/d/1T3AX_YBC8703g6N7sKot41tXUh6XN4zpcBF2V-_7iJ8/edit#gid=0";
//var ss = SpreadsheetApp.openByUrl(url);
//var ws = ss.getSheetByName("Data");
//ws.appendRow([name])
//Logger.log(name + "Clicked Run Button");
//}
function userClicked() {
Logger.log("Someone Clicked the button");
}
and the other in html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h1>Welcome</h1>
<button id="btn">RUN !!</button>
<script>
function doSomething() {
google.script.run.code.userClicked();
}
document.getElementById("btn").addEventListener("click", doSomething());
</script>
</body>
</html>
we can't get the desired action when run button is clicked
we don't know if it's the declaration of functions or summoning them
please help guide to rectify the error
this is yje project link for further analysis
https://script.google.com/d/1daP7bLBlL46av4Wc6-Pr9-z9lg6JyMY44FUtfA08fnKRKLeMuCTxH3LY/edit?usp=sharing
According to the Google Script client side API documentation, the path to call the App Script function is google.script.run.yourFunction() so in your html file. Also you are invoking the function straight away and passing the result of it to addEventListener(), instead of passing the function itself. The script should be this:
function doSomething() {
google.script.run.userClicked();
}
document.getElementById("btn").addEventListener("click", doSomething);

JavaScript function only works after page reload

I know this has been asked a lot on here, but all the answers work only with jQuery and I need a solution without it.
So after I do something, my Servlet leads me to a JSP page. My JS function should populate a drop down list when the page is loaded. It only works properly when the page is refreshed tho.
As I understand this is happening because I want to populate, using innerHTML and the JS function gets called faster then my HTML page.
I also get this error in my Browser:
Uncaught TypeError: Cannot read property 'innerHTML' of null
at XMLHttpRequest.xmlHttpRequest.onreadystatechange
I had a soulution for debugging but I can't leave it in there. What I did was, every time I opened that page I automatically refreshed the whole page. But my browser asked me every time if I wanted to do this. So that is not a solution that's pretty to say the least.
Is there something I could do to prevent this?
Edit:
document.addEventListener("DOMContentLoaded", pupulateDropDown);
function pupulateDropDown() {
var servletURL = "./KategorienHolen"
let xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.onreadystatechange = function () {
if (xmlHttpRequest.readyState === 4 && xmlHttpRequest.status === 200) {
console.log(xmlHttpRequest.responseText);
let katGetter = JSON.parse(xmlHttpRequest.responseText);
JSON.stringify(katGetter);
var i;
for(i = 0; i <= katGetter.length -1; i++){
console.log(katGetter[i].id);
console.log(katGetter[i].kategorie);
console.log(katGetter[i].oberkategorie);
if (katGetter[i].oberkategorie === "B") {
document.getElementById("BKat").innerHTML += "" + katGetter[i].kategorie + "</br>";
} else if (katGetter[i].oberkategorie === "S") {
document.getElementById("SKat").innerHTML += "" + katGetter[i].kategorie + "</br>";
} else if (katGetter[i].oberkategorie ==="A") {
document.getElementById("ACat").innerHTML += "" + katGetter[i].kategorie + "</br>";
}
// document.getElementsByClassName("innerDiv").innerHTML = "" + katGetter.kategorie + "";
// document.getElementById("test123").innerHTML = "" + katGetter.kategorie + "";
}
}
};
xmlHttpRequest.open("GET", servletURL, true);
xmlHttpRequest.send();
}
It can depend on how + when you're executing the code.
<html>
<head>
<title>In Head Not Working</title>
<!-- WILL NOT WORK -->
<!--<script>
const p = document.querySelector('p');
p.innerHTML = 'Replaced!';
</script>-->
</head>
<body>
<p>Replace This</p>
<!-- Will work because the page has finished loading and this is the last thing to load on the page so it can find other elements -->
<script>
const p = document.querySelector('p');
p.innerHTML = 'Replaced!';
</script>
</body>
</html>
Additionally you could add an Event handler so when the window is fully loaded, you can then find the DOM element.
<html>
<head>
<title>In Head Working</title>
<script>
window.addEventListener('load', function () {
const p = document.querySelector('p');
p.innerHTML = 'Replaced!';
});
</script>
</head>
<body>
<p>Replace This</p>
</body>
</html>
Define your function and add an onload event to body:
<body onload="pupulateDropDown()">
<!-- ... -->
</body>
Script needs to be loaded again, I tried many options but <iframe/> works better in my case. You may try to npm import for library related to your script or you can use the following code.
<iframe
srcDoc={`
<!doctype html>
<html>
<head>
<style>[Style (If you want to)]</style>
</head>
<body>
<div>
[Your data]
<script type="text/javascript" src="[Script source]"></script>
</div>
</body>
</html>
`}
/>
Inside srcDoc, it's similar to normal HTML code.
You can load data by using ${[Your Data]} inside srcDoc.
It should work :
document.addEventListener("DOMContentLoaded", function(){
//....
});
You should be using the DOMContentLoaded event to run your code only when the document has been completely loaded and all elements have been parsed.
window.addEventListener("DOMContentLoaded", function(){
//your code here
});
Alternatively, place your script tag right before the ending body tag.
<body>
<!--body content...-->
<script>
//your code here
</script>
</body>

Silence net::ERR_CONNECTION_REFUSED

Connecting to a non-existent web socket server results in loud errors being logged to the console, usually to the tune of ... net::ERR_CONNECTION_REFUSED.
Anyone have an idea for a hackaround to silence this output? XMLHttpRequest won't work since it yields the same verbose error output if the server is not reachable.
The goal here is to test if the server is available, if it is then connect to it, otherwise use a fallback, and to do this without spamming the console with error output.
Chrome itself is emitting these messages, and there is no way to block them. This is a function of how chrome was built; whenever a ResourceFetcher object attempts to fetch a resource, its response is passed back to its context, and if there's an error, the browser prints it to the console - see here.
Similar question can be found here.
If you'd like, you can use a chrome console filter as this question discusses to block these errors in your console, but there is no way to programmatically block the messages.
I don't know why do you want to prevent this error output. I guess you just want to get rid of them when debugging. So I provide a work around here may be just useful for debugging.
Live demo: http://blackmiaool.com/soa/43012334/boot.html
How to use it?
Open the demo page, click the "boot" button, it will open a new tab. Click the "test" button in the new tab and check the result below. If you want to get a positive result, change the url to wss://echo.websocket.org.
Why?
By using post message, we can make browser tabs communicate with each other. So we can move those error output to a tab that we don't concern.
P.S. You can refresh the target page freely without loosing the connection between it and boot page.
P.P.S You can also use storage event to achieve this.
boot.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>boot page</title>
</head>
<body>
<button onclick="boot()">boot</button>
<p>BTW, you can boot the page without the button if you are willing to allow the "pop-up"</p>
<script>
var targetWindow;
function init() {
targetWindow
}
function boot() {
targetWindow = window.open("target.html");
}
boot();
window.addEventListener('message', function(e) {
var msg = e.data;
var {
action,
url,
origin,
} = msg;
if (action === "testUrl") {
let ws = new WebSocket(url);
ws.addEventListener("error", function() {
targetWindow.postMessage({
action: "urlResult",
url,
data: false,
}, origin);
ws.close();
});
ws.addEventListener("open", function() {
targetWindow.postMessage({
action: "urlResult",
url,
data: true,
}, origin);
ws.close();
});
}
});
</script>
</body>
</html>
target.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>target page</title>
</head>
<body>
<h4>input the url you want to test:</h4>
<textarea type="text" id="input" style="width:300px;height:100px;">
</textarea>
<br>
<div>try <span style="color:red">wss://echo.websocket.org</span> for success result(may be slow)</div>
<button onclick="test()">test</button>
<div id="output"></div>
<script>
var origin = location.origin;
var testUrl = origin.replace(/^https?/, "ws") + "/abcdef"; //not available of course
document.querySelector("#input").value = testUrl;
function output(val) {
document.querySelector("#output").textContent = val;
}
function test() {
if (window.opener) {
window.opener.postMessage({
action: "testUrl",
url: document.querySelector("#input").value,
origin,
}, origin);
} else {
alert("opener is not available");
}
}
window.addEventListener('message', function(e) {
var msg = e.data;
if (msg.action === "urlResult") {
output(`test ${msg.url} result: ${msg.data}`);
}
});
</script>
</body>
</html>

Firefox addon - run script on page

Using Addon SDK I am trying to inject script to page on every page load. To test things, plugin is trying to add variable to window object and page should read it. When I run this, I can see "injecting" alert, but page gives me error "undefined property window.myVar". What am I doing wrong? Btw I don't want to use unsafeWindow.
main.js:
var data = require("sdk/self").data;
var pageMod = require("sdk/page-mod");
pageMod.PageMod({
include: "*",
contentScriptFile: data.url("inject.js"),
contentScriptWhen: "start",
onAttach: function(worker) {
worker.port.emit("inject", "unused param");
}
});
inject.js
function inject(arg) {
var script = document.createElement("script");
script.innerHTML = 'alert("injecting"); window.myVar=54564;';
document.head.appendChild(script);
}
self.port.on("inject", inject);
page.html
<html>
<head>
</head>
<body>
<script>
alert(window.myVar);
</script>
</body>
</html>
EDIT:
I tried canuckistani's code and it shows some weird behavior. Btw I am on Firefox 31. Here is my code
function inject(arg) {
var myVar = 123;
unsafeWindow.myVar = cloneInto(myVar, unsafeWindow);
}
self.port.on("inject", inject);
and page
<html>
<head>
</head>
<body>
<script>
alert(window.myVar); <!--This shows empty alert box-->
alert(window.myVar); <!--This shows alert box with right value (123)-->
</script>
</body>
</html>
Starting with Firefox 30 ( almost 2 versions ago! ) you can use some new apis to do this. This would look like:
let myVar = {1:2};
self.port.on("inject", function() {
unsafeWindow.myVar = cloneInto(myVar, unsafeWindow);
});
For more information, see this blog post:

Categories