Simplest way to modify a URL in a link? - javascript

Our site contains href links to various subdomains: foo.mysite.com, bar.mysite.com. For testing purposes, I'd like to run the site on a completely different main domain name, and point to subdomains off the new domain name.
Rather than manually change all the links, I'd like to have only one version of the site with links that look like this:
Link
What's the simplest syntax for doing this?
I know I could write jQuery code to hijack links, but a simpler in-link syntax would be better.

You could try on click:
<a href="foo.{host}/mypage?myparam=value"
onclick="this.href=this.href.replace('{host}', window.location.hostname)">Link</a>

Couldn't you use javascripts onclick event ? tpo do this :
Link

Honestly, the easy way for such a simple, global testing change is to do a search/replace on your whole site. If you want to proceed with your plan, I would use a server side language such as PHP, if possible. It will be much more foolproof for what you want.

I've seen back-end systems use an ENV variable to make changes between production environments. For example, you would set an environment variable, like var ENV = 'live' or var ENV = 'production. You could then use that to define what subdomain to use.
var ENV = 'production';
// set subdomain based on ENV variable
var subdomain = 'bar';
if(ENV == 'production'){
var subdomain = 'foo';
}
// modify every link to use the subdomain
$('a').each(function(){
var modifyHref = 'http://' + subdomain + $(this).attr('href')
$(this).attr('href', modifyHref);
});
I don't think you should be doing this on front-end JS though.
If subdomains are an issue, I would set all the paths to <a href="/mypage?myaparam=value">. That way, it won't matter what the subdomain. If you are on the foo subdomain, it will go to "foo.whatever/mypage?myaparam=value", and if you are on the bar subdomain, it will go to "bar.whatever/mypage?myaparam=value".

Related

fill out protocol relative URLs via search-and-replace in HTML code

I have a web application that uses protocol-relavtive URLs for everything to be as dynamic as possible, the problem is that in certain cases these dont work, for example as redirect URLs for 3rd party auth, so the question is there some way I can point at a redirect url which is in the HTML code referenced as a data-redirect-url="//abc.com/auth.php" attribute inside an HTML <button> and prepend http/https to it depending on the active protocol?
by the way, I know that it's better to serve content only over HTTPS and that people might not want to use the these URLs anymore, but I want to be dynamic, because e.g. with a localhost test HTTPS REALLY isnt needed.
long story short.
if HTTP
replace
(php-regex) data-redirect-url="//(.+?)"
with
(php-regex) data-redirect-url="http://$1"
if HTTPS,
instead use
(php-regex) data-redirect-url="https://$1"
I am very bad with js (in fact I avoid it when I can) so try to keep the code understandable and not too complex if possible.
You can use location.protocol which return the protocol of the current URL. http: or https:
Per your comment, you have a button :
<button class="btn btn-block btn-lg btn-info" data-redirect-url="//somedynamicallygeneratedurl">
To change the data-redirect-url, use:
var urlButtons = document.querySelectorAll('.btn[data-redirect-url]');
for(var _index = 0; _index < urlButtons.length; _index++) {
var btn = urlButtons[_index];
btn.setAttribute('data-redirect-url', location.protocol+btn.getAttribute('data-redirect-url'));
console.log(btn.getAttribute('data-redirect-url'));
}
I used some jQuery for this solution, but this might do the trick
It changes your HTML when its ready
The only thing you have to do is paste this in your page
$( document ).ready(function(){
var el = $('[data-redirect-url]')
el.each(function(el){
var i = $(this).attr('data-redirect-url');
$(this).attr('data-redirect-url', location.protocol+i)
});
});

Javascript Get Hostname of File Host

Although this question is similar, it is not what I am looking for.
Let's say on HostA.com I include a script from HostB.com:
<script type="text/javascript" src="http://www.hostb.com/script.js">
When script.js runs, I need to get the name of HostB (let's assume it can change). If I use:
var hostName = window.location.hostname;
It will return HostA.com rather than HostB.com obviously because that is where the the window object is scoped.
How can I get the name of HostB from within the script? Do I have to locate the <script> element in the DOM and parse the src attribute or is there a better way?
EDIT
Yes, it is on my server, but may be on other servers as well. I am developing a javascript plugin and am trying to make absolute paths so it doesn't try to reference files on the server including the plugin.
Here is how: first off, include this as the first line of your script. I know it is a comment. Do it anyways
//BLAHBLAHBLAHBLAHAAABBBCCCDDDEEEFFFGGGILIKEPI
next, use this function inside of that script to determine the host
function findHost(){
var scripts=document.getElementsByTagName('script');
var thisScript=null;
for(var i=0;i<scripts.length;i++){
if(scripts[i].innerHTML.indexOf('//BLAHBLAHBLAHBLAHAAABBBCCCDDDEEEFFFGGGILIKEPI')!==-1)
var thisScript=scripts[i];
}
var urlParser=document.createElement('a');
urlParser.href=thisScript.getAttribute('src');
return urlParser.hostname;
}
I am loading the script with RequireJS which looks something like this:
<script data-main="http://hostb.com/js/app/main.js" src="http://hostb.com/js/vendor/require.js" type="text/javascript"></script>
I figured out, with help from #adeneo that I can do something like this:
$('script[data-main*="/js/app/main.js"]').attr('data-main')
Which returns:
http://hostb.com/js/app/main.js
And I can parse it for the hostname.
var url = $('script[data-main*="/main.js"]').attr('data-main');
parser = document.createElement('a');
parser.href = url;
host = parser.hostname;
Thanks for the suggestions and nudge in the right direction!
BREAKING NEWS
Turns out their is an easier way for anyone using RequireJS (who finds this question in search) and needs to be able to load absolute URL's with the script host:
var myCssPath = require.toUrl('css/mystyles.css');
That builds an absolute path using the hostname of the server running!
To omit using the hostname twice (as you described in your 'accepted answer') I implemented the solution this as follows:
HTML on HostA.com:
<script data-main="my_embed_id" src="http://hostb.com/js/vendor/require.js" type="text/javascript"></script>
require.js on HostB.com:
// get host where this javascript runs
var url = $('script[data-main="my_embed_id"]').attr('src');
var hostb = url.replace(/(\/\/.*?\/).*/g, '$1');
Which returns:
http://hostb.com
Inspired by: How to make an external javascript file knows its own host?

Cache static HTML pages with get variables

I have a website with a lot of iframes like this:
<iframes src="expamle.com\page.html?var=blabla&id=42" scrolling="no"></iframe>
I have to change var=blabla&id=42 for each iFrame. These parameters are used in the javascript of the iframe. Is there any way to cache(give hints to the browser) page.html (static) once for all variables ?
I have to use an iframe since I want to be able to update this code ( from another server) & to run it in another scope.
No - Anything changing the query string represents a seperate resource for the browser.
However, you may be able to achieve that effect if you can make some slight changes to page.html. If you write it this way:
<iframes src="expamle.com\page.html#var=blabla&id=42" scrolling="no"></iframe>
Note the use of the # character - that's the key there.
The query string becomes simply "page.html" and will cache that way. However, the Javascript of that page will have access to the variable document.location.hash, which will contain "var=blabla&id=42". It'll be written as a single string, but it shouldn't be difficult to parse. Some libraries even use that tag to pass parameters in semi-real-time to iframes for IE6 compatibility.
If it's only used in the javascript but is really only 1 page server side don't use ? But use # it will consider it as the same page but at diferent anchor pounts. So if test.com/#foo is cached then test.col/#bar is too (same page, different anchor points)
You can update the frame URLs from code:
var fr = document.getElementsByTagName('iframe');
var sites = "1.com,2.com".split(",");
for(var x=0;x<fr.length;x++) {
document.getElementsByTagName('iframe')[x].src="http://"+sites[x];
}

How should I create relative paths in javascript using MVC3?

I am having some difficulty aligning my paths without a hardcode in javascript. I am running an asp.net MVC3 web application.
If my path is of the form
var url = 'http://serverNameHardcode/websiteNameHardcode/service/service?param1=' + param;
Then things work fine when I do
$.get(url,
{},
function (data) {alert('callback success');},'json');
I would like to create a relative path. I tried
var url = 'service/service?param1=' + param;
And this works when I run locally and also in Firefox, but not in IE7. When I publish to the server without the hardcode the callback never fires. I know MVC-3 adds some complexity to routing, but I do not know if it applies to this situation; so, I marked this question as such.
How should I setup my path so I don't need hardcodes?
Just write out the app path as a global js variable from your master view, then compose links as
APPPATH + "path/whatever"
Just had to solve this for one of my jQuery plugins, where it is preferable not to modify anything global (i.e. outside the scope of the plugin use) so I had to disregard the marked answer.
I also found that because I host DEV locally in IIS I could not use a root-relative path (as localhost is not the root).
The solution I came up with extended what I had already started with: a data-controller attribute specifying which controller to use in the element I am applying my plugin to. I find it preferable to data-drive the controller names so the components can be more easily reused.
Previous:
<div data-controller="Section">
Solution:
<div data-controller="#Url.Content("~/Section")">
This injects the server root (e.g. /Test.WindowsAzure.Apr2014/ before the controller name so I wind up with /Test.WindowsAzure.Apr2014/Section which is perfect for then appending actions and other parameters as you have. It also avoids having an absolute path in the output (which takes up extra bytes for no good reason).
In your case use something like:
// Assuming $element points to the element your plugin/code is attached to...
var baseUrl = $element.data('controller');
var url = baseUrl + '/service?param1=' + param;
Update:
Another approach we now use, when we do not mind injecting a global value, is Razor-inject a single global JavaScript variable onto window in the layout file with:
<script>
window.SiteRoot = "#Url.Content("~/")";
</script>
and use it with
var url = window.SiteRoot + '/service?param1=' + param;
One option:
var editLink = '#Url.Action("_EditActivity", "Home")';
$('#activities').load(editLink + "?activityID=" + id);
another example:
var actionURL = '#Url.Action("_DeleteActivity", "Home")';
$('#activities').load(actionURL + "?goalID=" + gID + "&activityID=" + aID);
If you don't need to add to the string:
$('#activities').load('#Url.Action("_Activities", "Home", new { goalID = Model.goalID},null)');
I really need the path to get this to work, maybe its IE7. Who knows. But this worked for me.
Grab the URL and store it somewhere. I chose to implement the data attribute from HTML5.
<div id="websitePath" data-websitePath='#Request.Url.GetLeftPart(System.UriPartial.Authority)#Request.ApplicationPath'></div>
Then when you need to perform some AJAX or otherwise use a URL in javascript you simply refer to the stored value. Also, there are differences in the versions of IIS (not cool if your devbox is IIS5 and your server is IIS7). #Request.ApplicationPath may or may not come back with a '/' appended to the end. So, as a workaround I also trim the last character if it is /. Then include / as part of the url.
var urlprefix = $('#websitePath').data('websitepath');
urlprefix = urlprefix.replace(/\/$/, "");
var url = urlprefix + '/service/service?param1=' + param;
While the accepted answer is correct I would like to add a suggestion (i.e. how I do it).
I am using MVC, and any ajax request goes to a controller. My controllers have services so if a service call is required the controller will take of that.
So what's my point? So if ajax always communicates with a controller, then i would like to let the MVC routing resolve the path for me. So what I write in Javascript for url is something like this:
url: 'controller/action'
This way there is no need for the root path etc...
Also, you can put this in a separate Javascript file and it will also work whereas #Url.Content will need to be called on the view.

Javascript in Virtual Directory unaware of Virtual Directory

Say I have the site
http://localhost/virtual
where virtual is the virtual directory
I have an Ajax request that is defined in a javascript file using JQuery
$.getJSON("/Controller/Action")
When this is called, the client tries to find the url at the root level i.e.
http://localhost/Controller/Action
If I add the tilde (~) symbol in, it turns into
http://localhost/virtual/~/Controller/Action
It should (if it was to do what I wanted) resolve to
http://localhost/virtual/Controller/Action
Any ideas on how to fix this?
Aku's hint above looked right but it didn't want to work for me. Finally I figured out to use it like this
<script type="text/javascript">
var config = {
contextPath: '<%= #Url.Content("~") %>'
};
</script>
and then in my JavaScript I use it like this
config.contextPath + 'myAppPath".
So in case of no virtual directory this resolves to
"/" + "myAppPath"
and in case of a virtual directory this resolves to
"/VirtualPath/" + + "myAppPath"
and this finally worked for me.
I used this solution successfully
Place the following element in your masterpage
<%= Html.Hidden("HiddenCurrentUrl", Url.Action("Dummy"))%>
Declare a global variable in your main javascript file
var baseUrl = "";
Set baseUrl to the value of "HiddenCurrentUrl" when your javascript is loaded
baseUrl = $("#HiddenCurrentUrl").val();
baseUrl = baseUrl.substring(0, baseUrl.indexOf("Dummy"));
Use baseUrl
$.getJSON(baseUrl + "Action")
EDIT Improved solution
In your controller
ViewBag.BaseUrl = Request.Url.GetLeftPart(UriPartial.Authority) + Request.ApplicationPath + "/";
In your master page
<script type="text/javascript">
var YourNameSpace = YourNameSpace || {};
YourNameSpace.config = {
baseUrl: "#ViewBag.BaseUrl"
}
</script>
Use your baseUrl
$.getJSON(YourNameSpace.config.baseUrl + "Action")
Another way to get a base url is
<script type="text/javascript">
window.g_baseUrl = '#Url.Content("~")';
</script>
For example, if you run your app from SomeName virtual directory then
window.g_baseUrl variable will be equal to /SomeName/
Benefit of this method is an ability to call actions in the other controllers like so
$.getJSON(window.g_baseUrl + "AnotherController/Action")
Maybe,$.getJSON("Controller/Action") will do?
The tilde shortcut for your application root path is a special feature of ASP.NET, not part of URLs themselves. Consequently trying to use a URL with a tilde in from JavaScript won't resolve the site root, it'll just give you a literal ~ as you can see.
You'd need to pass the value of the application root path to JavaScript so it can construct URLs itself. I'm not that familiar with ASP.NET but I believe you could do something like:
<script type="text/javscript">
var approot= <%= JavaScriptSerializer.Serialize(Request.ApplicationPath) %>;
... $.getJSON(approot+'/Controller/Action') ...;
</script>
A simpler way to do it if you know there's a link on the page to the approot would be to read the href of that link:
var approot= $('#homepagelink').attr('href');
Relative Path to the JS file was the only solution I found
$.getJSON("../Controller/Action")
I know this question is very old but I was lately struggling with this issue and was able to resolve it using
url:'<%=VirtualPathUtility.ToAbsolute("~/Include/cntrols/Data.aspx") %>',
this works great in my ajax call...
It is too late to answer this question. But may be useful to someone as I had same problem. Instead of doing all this steps mentioned in above answers, better way is to use
Url.Action('action','controller').
It'll generate url /VIRDIR/controller/action if it is running from virtual directory or generate /controller/action in other case.

Categories

Resources