What does the hash (#) mean after a .js file? - javascript

what is the significance of the hash (#) here, how does it relate to the .js file:
<script src="foo.js#bar=1"></script>

The hash after the script is used by the embedded script for configuration. For example, have a look at the provided example (facebook):
1. window.setTimeout(function () {
2. var a = /(connect.facebook.net|facebook.com\/assets.php).*?#(.*)/;
3. FB.Array.forEach(document.getElementsByTagName('script'), function (d) {
4. if (d.src) {
5. var b = a.exec(d.src); //RegExp.exec on the SRC attribute
6. if (b) {
7. var c = FB.QS.decode(b[2]); //Gets the information at the hash
8. ...
In the script, each <script> tagline 3 is checked for occurrencesline 5 of the hash line 2 at the attribute. Then, if the hash existsline 6, the hashdata is extractedline 7, and the function continues.

I doesn't do anything in terms of loading the script. What I am guessing is, the script itself looks for its own script tag, and picks out the piece after the hash (bar=1), and uses it to configure its behavior somehow. To do this, they probably have to loop through all script tags and match against the src attribute.

It is probably used within the referenced .js file reading the raw URL and extracting the parameter (using something window.location, for example and parsing out what is after the #).

The part after the hash in a URL is know as a fragment identifier. If present, it specifies a part or a position within the overall resource or document. When used with HTTP, it usually specifies a section or location within the page, and the browser may scroll to display that part of the page.
In relation to the JavaScript file, the author of the program is in all probability using it as a method to pass arguments to the file. However, this method should not be used. URLs may contain query strings which serve the same purpose.
Nevertheless, it's never a good idea to embed arguments to the URL of a JavaScript file because for every different set of parameters the URL is cached again which is a waste of memory. Instead, it's better to set the query string on the URL of HTML page which contains the script itself. This is because JavaScript has a built in property to access the query string of the web page: location.search. You may read more about it here.

Related

In JavaScript, how do I get the URL of the JavaScript file, not the location URL?

I would like to use a query string parameter so that way I can specify the name of a DOM element.
I have some code that requires the height of the header and I would like that code to work for any theme. Only at times the header uses the <header> tag, at times it has a specific identifier, at times it is a specific class... to be able to reuse that code over and over again, I'd like to include it in a way such as:
<script src="https://www.example.com/js/my-script.js?c=header"></script>
What I want to be able to do is get the "?c=header" part from that JavaScript URL to send search a DOM object with jQuery(".header"). Do we have a way to know the URL of the JavaScript itself from the JavaScript being executed?
Obviously, I know of window.location.href and that's not the URL I'm looking for.
As mentioned by #Kaiido in a comment, there is the document.currentScript parameter that gives you access to the <script> tag which is currently running. Only there is a small trick to it, that parameter is defined on the first pass, not when executing functions within your script.
So what one can do is save that information, or at least what you need from that object, in the global scope or a static in your object.
In my case, I just did the following:
// Script to tweak things on many websites
var this_script_url = document.currentScript.src;
jQuery(document).ready(function()
{
// at this point: "document.currentScript === null"
var qs = this_script_url.split("?", 2);
if(qs && 2 == qs.length)
{
... // handle qs[1] which is the query string (a=1&b=3&...)
}
});
Please make sure you don't use a global name that's too generic. It should include the name of your script or abbreviation thereof. Otherwise you are likely to clash with another script's global.
Now if you have a prototype object, I would suggest you use a static member instead of a global.
var my_class = {};
my_class.script_url = document.currentScript.src;
// and later you can reference it directly as in:
url = my_class.script_url;
This way you are more likely to avoid clashing problems (the only thing that needs to be changing in case of a clash is the name my_class).
At this point, the ES5 or ES6 class keyword does not offer you to create variables.

HTML Append Variable to Query String

I have http://localhost/?val=1
When I click on a link, is there a way this link can append a query variable to the current string, for example:
Link
so when I click it the url would be:
http://localhost/?val=1&var2=2
but when I click the link it removes the first query string and looks like
http://localhost/&var2=2
Is such a thing possible with normal HTML?
You can't do that using only html, but you can do it with js or php:
Using JS:
<a onclick="window.location+=((window.location.href.indexOf('?')+1)?'':'?')+'&var2=2'">Link</a>
Using Php:
Link
Notice 1: make sure you don't have the new variable in the current link, or it'll be a loop of the same variable
Notice 2: this is not a professional way, but it could work if you need something fast.
Basically you want to get your current URL via JavaScript with:
var existingUrl = window.location.href; // http://localhost/?val=1
Then append any Query Strings that are applicable using:
window.location.href = existingUrl + '&var2=2';
or some other similar code. Take a look at this post about Query Parameters.
Note: A link would already have to exist with an OnClick event that calls a function with the above code in it for it to work appropriately.
Now obviously this isn't very useful information on it's own, so you are going to want to do some work either in JavaScript or in Server code (through use of NodeJS, PHP, or some other server-side language) to pass those variable names and their values down so that the button can do what you are wanting it to do.
You will have to have some logic to make sure the query parameters are put in the URL correctly though. I.E. if there is only one query param it's going to look like '?var1=1' and if it's any subsequent parameter it's going to look like '&var#=#'.

What does this javascript regular expression code do in dealing with URLS?

I am looking at someone elses codebase and I as a javascript noob and doubly so a regular expression noob I can't figure out what the following lines do:
var url = sel.anchorNode.parentNode.href;
var match = self.location.href.replace(/\/$/i, '');
var replaced = url.replace(match,'');
I read it as:
set the var url to the href value of the parent node of the currently selected node
sets the var match to the browsers current URL with the trailing '/' removed (if it exists)
sets the var replaced to the string returned in 1. with the string returned in 2. removed from it
If I am reading it correctly I just can't figure out how it would ever do anything. There isn't any situation, I can think of, where the parent node of a currently selected node would have an href value pointing to the current URL.
So I think I am reading it incorrectly.
Because the href property of an anchor is a fully-resolved URL (even if the href attribute is relative), what that does is remove the current page's path and get you back to a relative URL. E.g., on the page:
http://example.com/foo/bar/
with a link like
...
...you get the href from the anchor which is:
http://example.com/foo/bar/nifty.html
...and then remove http://example.com/foo/bar from it, giving you:
/nifty.html
In this case, of course, that's probably not what you actually want. :-) I have to admit I fail to see how the code is useful, out of context, but then context is king sometimes...

Extract src attribute from script tag and parse according to particular matches

So, I have to determine page type in a proprietary CRM, using JavaScript. The only way to determine the page type (that is, the only consistent difference on the front end) is by examining a script tag (out of many list) whose src attribute begins with /modules/.
In a list of a dozen or so script tags in the header, each page has a line of the following format
<script src="/modules/example/includes/sample.js" type="text/javascript"></script>
Now, the order of the script tag is never the same, but, there's always one script that has /modules/blah. I need to extract blah to my script can detect what kind of page it is.
So, how do I, using either JavaScript or jQuery, extract the script tag's src value, where src begins with /modules, and store the value after that ('example', in the example above) as a javascript variable?
Well, you can start by collecting all of the script elements. With jQuery, that's as simple as
var scripts = $("script");
Then limit that set to the elements that have a src attribute:
var scripts = $("script[src]");
...and further limit it to those with a src attribute beginning with "/modules/":
var scripts = $("script[src^='/modules/']");
...which given your description should result in a set of exactly one element, from which you can now pull the src attribute value itself:
var path = $("script[src^='/modules/']").attr('src');
Ok, that was easy - now to extract the next part of the path. There are plenty of ways to do this, but split is quick & dumb: create an array of parts using '/' as the separator, then pick off the third element (which will be the one after "modules"):
var pathPart = $("script[src^='/modules/']").attr('src').split('/')[2];
Obviously, this is all very specific to the exact format of the script path you're using as an example, but it should give you a good idea of how to begin...

Best way to safely read query string parameters?

We have a project that generates a code snippet that can be used on various other projects. The purpose of the code is to read two parameters from the query string and assign them to the "src" attribute of an iframe.
For example, the page at the URL http://oursite/Page.aspx?a=1&b=2 would have JavaScript in it to read the "a" and "b" parameters. The JavaScript would then set the "src" attribute of an iframe based on those parameters. For example, "<iframe src="http://someothersite/Page.aspx?a=1&b=2" />"
We're currently doing this with server-side code that uses Microsoft's Anti Cross-Scripting library to check the parameters. However, a new requirement has come stating that we need to use JavaScript, and that it can't use any third-party JavaScript tools (such as jQuery or Prototype).
One way I know of is to replace any instances of "<", single quote, and double quote from the parameters before using them, but that doesn't seem secure enough to me.
One of the parameters is always a "P" followed by 9 integers.
The other parameter is always 15 alpha-numeric characters.
(Thanks Liam for suggesting I make that clear).
Does anybody have any suggestions for us?
Thank you very much for your time.
Upadte Sep 2022: Most JS runtimes now have a URL type which exposes query parameters via the searchParams property.
You need to supply a base URL even if you just want to get URL parameters from a relative URL, but it's better than rolling your own.
let searchParams/*: URLSearchParams*/ = new URL(
myUrl,
// Supply a base URL whose scheme allows
// query parameters in case `myUrl` is scheme or
// path relative.
'http://example.com/'
).searchParams;
console.log(searchParams.get('paramName')); // One value
console.log(searchParams.getAll('paramName'));
The difference between .get and .getAll is that the second returns an array which can be important if the same parameter name is mentioned multiple time as in /path?foo=bar&foo=baz.
Don't use escape and unescape, use decodeURIComponent.
E.g.
function queryParameters(query) {
var keyValuePairs = query.split(/[&?]/g);
var params = {};
for (var i = 0, n = keyValuePairs.length; i < n; ++i) {
var m = keyValuePairs[i].match(/^([^=]+)(?:=([\s\S]*))?/);
if (m) {
var key = decodeURIComponent(m[1]);
(params[key] || (params[key] = [])).push(decodeURIComponent(m[2]));
}
}
return params;
}
and pass in document.location.search.
As far as turning < into <, that is not sufficient to make sure that the content can be safely injected into HTML without allowing script to run. Make sure you escape the following <, >, &, and ".
It will not guarantee that the parameters were not spoofed. If you need to verify that one of your servers generated the URL, do a search on URL signing.
Using a whitelist-approach would be better I guess.
Avoid only stripping out "bad" things. Strip out anything except for what you think is "safe".
Also I'd strongly encourage to do a HTMLEncode the Parameters. There should be plenty of Javascript functions that can this.
you can use javascript's escape() and unescape() functions.
Several things you should be doing:
Strictly whitelist your accepted values, according to type, format, range, etc
Explicitly blacklist certain characters (even though this is usually bypassable), IF your whitelist cannot be extremely tight.
Encode the values before output, if youre using Anti-XSS you already know that a simple HtmlEncode is not enough
Set the src property through the DOM - and not by generating HTML fragment
Use the dynamic value only as a querystring parameter, and not for arbitrary sites; i.e. hardcode the name of the server, target page, etc.
Is your site over SSL? If so, using a frame may cause inconsistencies with SSL UI...
Using named frames in general, can allow Frame Spoofing; if on a secure site, this may be a relevant attack vector (for use with phishing etc.)
You can use regular expressions to validate that you have a P followed by 9 integers and that you have 15 alphanumeric values. I think that book that I have at my desk of RegEx has some examples in JavaScript to help you.
Limiting the charset to only ASCII values will help, and follow all the advice above (whitelist, set src through DOM, etc.)

Categories

Resources