I am using js to get the HTML for my websites navbar. instead of having to paste it on each page,
that part works great. the issue is afterwards i create a script and link element, to provide the javascript and the css file that goes with the navbar. using brackets application it works. but in real world application i'm getting error 404, i've checked the location and it seams to be correct.
also. is there a way to tell when the html from the fetch method is completed? i have a set timeout() function of 6ms as without it it's a 50-50 shot of loading the js file before the html. like a window.onload() command.
//Getting include attribute value
function getHTML() {
var includes = document.getElementsByTagName('include');
for(let i=0; i<includes.length; i++){
let include = includes[i];
//Loading include src value
load_file(includes[i].attributes.src.value, function(text){
include.insertAdjacentHTML('afterend', text);
include.remove();
});
}
const body = document.getElementsByTagName('body')[0],
script = document.createElement("script"),
head = document.getElementsByTagName('head')[0],
link = document.createElement('Link');
link.setAttribute('rel',"styleSheet")
link.setAttribute('href','/wont-work');
head.appendChild(link)
setTimeout(()=> {
script.setAttribute("src","/Navbar.js");
script.setAttribute("type","text/javaScript")
body.appendChild(script);
},6);
}
function load_file(filename, callback) {
fetch(filename).then(response => response.text()).then(text => callback(text));
console.log('file loaded')
}
window.addEventListener("load", getHTML);
expecting the CSS and Javascript to NOT be 404
Related
I'm working in an embed script while loads HTML form with JS validation while loaded in web pages. For now only one script loads on a page. If we add more embed script on a single page, the last added or loaded one will work & its related form & validation will execute. What I'm trying is to run multiple embed scripts in a single page.
Here is the current embed script pattern which is placed in HTML page:
<script src="http://link-to-my-embed-code-executer/embed_form.js"></script>
<div id="12345wertyui67890" class="form_wrap"><!-- HTML form with validation loads here --></div>
<script>
window.onload = function() {
EmbedManager.embed({
key:"12345wertyui67890",
is_embed_form:"1",
external_style:"1"
})
}
</script>
Here is the current script in embed_form.js
var EmbedManager = {
key: '',
is_embed_form: !0,
external_style: 0,
resizeCallback: function() {},
init: function(embedParams) {
EmbedManager.key = embedParams.key;
EmbedManager.is_embed_form = embedParams.is_embed_form;
EmbedManager.external_style = embedParams.external_style;
EmbedManager.serverUrl = ''; // Here is the URL which provide HTML Form as response
},
embed: function(embedParams) {
var xhr = new XMLHttpRequest();
xhr.open('POST', EmbedManager.serverUrl);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
xhr.onload = function() {
if (xhr.status !== 200) {
document.getElementById(EmbedManager.key).innerHTML = "Unable to load form"
}
var response = JSON.parse(xhr.responseText);
// Attempt to get the element using document.getElementById
var elementDOC = document.getElementById(EmbedManager.key);
// If it isn't "undefined" and it isn't "null", then it exists.
if ((typeof(elementDOC) != 'undefined') && (elementDOC != null) && (EmbedManager.is_embed_form)) {
// Only for Form, not used in LP
document.getElementById(EmbedManager.key).innerHTML = response.form_html;
}
}
// More code here to load Form in place of embed script & do validations
}
}
I'm trying to manage the updates in JS file because embed scripts are already provided to clients & I'm not interested in making bigger updates in those embed scripts. If it could be handled inside the JS file, it will be better.
What I'm trying to do is add a new function remapEmbed which will be a copy of codes in current embed function & also after that will replace codes in embed function to such a manner to collect multiple requests from embed scripts & make an array, later I will call remapEmbed function to do the rest. I know little changes will be needed there also, I will look into it later.
Here is the expected script in embed_form.js
var EmbedManager = {
key: '',
is_embed_form: !0,
external_style: 0,
resizeCallback: function() {},
init: function(embedParams) {
EmbedManager.key = embedParams.key;
EmbedManager.is_embed_form = embedParams.is_embed_form;
EmbedManager.external_style = embedParams.external_style;
},
remapEmbed: function(embedParams) {
// Code which was in `embed` function
// More code here to load Form in place of embed script & do validations
},
embed: function(embedParams) {
// Code to collect request & make a array
// Expecting to add codes here
// Later will call `remapEmbed` function & do rest.
EmbedManager.remapEmbed(embedParamsOne);
}
}
But the issue is that I'm getting only the call from the last embed script which is added on the page. It might be because of the last call overwriting the previous ones. How can I handle multiple requests?
Here I'm adding the Codepen, so you can check the code.
Unfortunately, you cannot place multiple onload events on a single
page. You can nest multiple functions within the one onload call. Ref
It working fine with Your script. Because you are calling embed scripts in Onload. Make sure all scripts inside last window.onload function.
Change html to
<!-- The embed code that will not replace with the response -->
<div id="12345AAA67890" class="form_wrap">HTML form with validation loads here: First Embed Code</div>
<!-- This embed code will be replaced with HTML content -->
<div id="12345BBB67890" class="form_wrap">HTML form with validation loads here: Second Embed Code</div>
<script>
window.onload = function() {
EmbedManager.embed({
key:"12345BBB67890",
is_embed_form:"1",
external_style:"1"
})
EmbedManager.embed({
key:"12345AAA67890",
is_embed_form:"1",
external_style:"1"
})
}
</script>
Hope this is the solution you are looking.
I create an iframe in a file and insert a <script> tag as its content. The Script src is loaded from a different file called test.js. Here is how it is done:
var scriptElement = document.querySelector("#your-widget");
var iframe = document.createElement("iframe");
scriptElement.parentNode.insertBefore(iframe, scriptElement.nextSibling);
var script = document.createElement("script");
iframe.contentWindow.document.appendChild(script);
script.src = "http://www.example.com/test.js";
Instead of loading the content of the script from http://www.example.com/test.js I want to take it from the same file where the above code is. This would like this:
var scriptElement = document.querySelector("#your-widget");
var iframe = document.createElement("iframe");
scriptElement.parentNode.insertBefore(iframe, scriptElement.nextSibling);
var script = document.createElement("script");
iframe.contentWindow.document.appendChild(script);
script.src = // ????
// the following JavaScript code should be placed inside the script
function mywidget() {
// some code
return true;
}
mywidget.succeeded = mywidget();
How can I set the Script Source from the same file instead of a different one?
If you literally just want to place that exact snippet in a script tag, you can just do so using .innerText.
script.innerText = 'function mywidget() { ...';
Then it will execute as is when it's inserted into the DOM. If you want to dynamically find and inject that code, read on.
There are exactly two ways to load a script on a page.
Add a <script> with the src attribute pointing to a file.
Create a <script> tag then set the contents to whatever you want to execute.
var script = document.createElement('script');
script.innerText = 'console.log("Hello, World!")';
document.body.appendChild(script);
If you want to extract part of a script and use those contents then the best you can do is load the contents via ajax and inject it using method 2.
Assuming you have jQuery (for easy AJAX work):
$.ajax({
url: 'path/to/script.js',
dataType: 'text', // make sure it doesn't get eval'd
success: function(contentsOfScript) {
// Refer to method 2
}
});
Now you can go about extracting the contents of that snippet in one of two ways:
Know exactly which line it begins on.
var lines = contentsOfScript.split('\n');
var snippet = lines.slice(lineNumber + 1); // adjust for 0 indexing
Generate a regular expression to identify where your code begins. This is rather tricky and very error prone if your snippet isn't easily distinguished from other code.
var snippet = contentsOfScript.match(/function mywidget.+/)[0];
Neither of these methods will work if you perform any minification on your code.
My javascript file with function:
scr.js:
function myf(){
alert('aaa');
}
myf();
After load page, I see dialog box with 'aaa'. This is right.
The next, I change script source to:
function myf(){
alert('bbb'); ///////////
}
myf();
and src file by add to him timestamp (for update file):
$('script[src^="./scr.js"]').attr('src','./scr.js?='+new Date().getTime());
The problems:
after update file, the myf() function doesn't run.
after run myf() function from browser console I see dialog with 'aaa' not with 'bbb'
when I remove script tag with src scr.js, I can call again my function
Where is problem and what do for update scritpt?
As far as I know, changing a script src attribute, doesn't force the browser to download the script; you need to create a new script tag and append it to the DOM.
Because the browser didn't downloaded and executed the new script.
When your script was first run by the browser it created a global function, which has been attached to the global object; that's why you can still call it, even though you've dinamically removed the script.
UPDATE (Possible solution):
Create a script element dinamically using something like this:
function createScript(src) {
var s = document.createElement("script");
s.src = src;
return s;
}
Update the DOM:
var oldScript = document.querySelector("script[src^='s.js']");
var newScript = createScript("s.js?t=" + (new Date()).getTime());
document.body.replaceChild(newScript, oldScript);
(you can translate that into jQuery if you want)
My HTML block as follows,
<html>
<title>Example</title>
<head>
</head>
<body>
<h2>Profile Photo</h2>
<div id="photo-container">Photo will load here</div>
<script type='text/javascript' src='http://example.com/js/coverphoto.js?name=johndoe'></script>
</body>
</html>
and I have saved this file as test.html. In JavaScript source the name will be dynamic.
I want to collect the name in coverphoto.js. Tried in coverphoto.js as,
window.location.href.slice(window.location.href.indexOf('?') + 1).split('&')
but it is getting the html file name (test.html) only. How can I retrieve the name key from http://example.com/js/coverphoto.js?name=johndoe in coverphoto.js?
To get the URL of the current JavaScript file you can use the fact that it will be the last <script> element currently on the page.
var scripts = document.getElementsByTagName('script');
var script = scripts[scripts.length - 1];
var scriptURL = script.src;
Please note that this code will only work if it executes directly within the JS file, i.e. not inside a document-ready callback or anything else that's called asynchronously. Then you can use any "get querystring parameter" JS (but make sure to replace any location.search references in there) to extract the argument.
I'd suggest you to put the value in a data-name argument though - that way you can simply use e.g. script.getAttribute('data-name') to get the value.
You can use the stack trace technique.
This technique will detect the source of the JS file the script is running from and it doesn't depend on the way you have injected the script. It can be dynamically injected (ajax) or in whatever method you can think of.
Just use the following code in your JS file:
const STACK_TRACE_SPLIT_PATTERN = /(?:Error)?\n(?:\s*at\s+)?/;
const STACK_TRACE_ROW_PATTERN1 = /^.+?\s\((.+?):\d+:\d+\)$/;
const STACK_TRACE_ROW_PATTERN2 = /^(?:.*?#)?(.*?):\d+(?::\d+)?$/;
const getFileParams = () => {
const stack = new Error().stack;
const row = stack.split(STACK_TRACE_SPLIT_PATTERN, 2)[1];
const [, url] = row.match(STACK_TRACE_ROW_PATTERN1) || row.match(STACK_TRACE_ROW_PATTERN2) || [];
if (!url) {
console.warn("Something went wrong. This probably means that the browser you are using is non-modern. You should debug it!");
return;
}
try {
const urlObj = new URL(url);
return urlObj.searchParams;
} catch (e) {
console.warn(`The URL '${url}' is not valid.`);
}
};
const params = getFileParams();
if ( params ) {
console.log(params.get('name'));
}
Note:
The params.searchParams will not work for IE browser, instead you can use params.search. But, for the sake of you nerves don't. Whoever is still using IE in 2020, just let him suffer.
is it possible to get my website 2,3 js variables in an extensions i build so i will be able to see the info behind the site i build
the extension will help me develop my sites
Seeing the variables of a given website (using Content Scripts) is possible. Just inject your own content script, and create an script tag that reads your variables. You cannot use those variables, or modify them on your extension due to some limitations of what Content script can do. You can read the following docs on Communication with the embedding page.
For example the following will read a JS variable in the webpage and transfer its contents to the background page so we can let our extension deal with it. You will notice in the background page inspector, that the variable is successfully passed:
content_script.js
// JS script injection, so that we can read the JS class 'InternalJSVariable'
var postFriendMap = function() {
var textarea = document.getElementById('transfer-dom-area');
textarea.value = JSON.stringify(InternalJSVariable);
};
// Create a dummy textarea DOM.
var textarea = document.createElement('textarea');
textarea.setAttribute('id', 'transfer-dom-area');
textarea.style.display = 'none';
document.body.appendChild(textarea);
// Start injecting the JS script.
var script = document.createElement('script');
script.appendChild(document.createTextNode('(' + postFriendMap + ')();'));
document.body.appendChild(script);
// Inform our world that we have received the friend map data.
chrome.extension.sendRequest({internalVariable: textarea.value});
// Clean up since we no longer need this.
document.body.removeChild(textarea);
background.html
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.internalVariable) {
var internal_object = JSON.parse(request.internalVariable);
console.log(internal_object );
}
});