Any smart way of doing a "root" based path referencing in JavaScript, just the way we have ~/ in ASP.NET?
Have your page generate a tag with something like:
<link rel="home" id="ApplicationRoot" href="http://www.example.com/appRoot/" />
Then, have a function in JavaScript that extracts the value such as:
function getHome(){
return document.getElementById("ApplicationRoot").href;
}
Use base tag:
<head>
<base href="http://www.example.com/myapp/" />
</head>
...
from now any link use on this page, no matter in javascript or html, will be relative to the base tag, which is "http://www.example.com/myapp/".
You could also use the asp.net feature VirtualPathUtility:
<script>
var basePath = '<%=VirtualPathUtility.ToAbsolutePath("~/")%>';
</script>
Notice: I don't encode the path to a JSON-string (escape quotes, control characters etc). I don't think this is a big deal (quotes for example aren't allowed unescaped in an URL), but one never knows...
I usually create a variable at the top of the js file and assign it the root path. Then I use that variable when referencing a file.
var rootPath = "/";
image.src = rootPath + "images/something.png";
~/ is the application root and not a literal root, it interpets ~/ to mean <YourAppVirtualDir>/
To do a literal root in JavaScript it's just /, i.e "/root.html". There's no way of getting an application level path like that in JavaScript.
You could hack it in the ASPX file and output it in a tag but I would consider the security implications of that.
Kamarey's answer can be improved to support a dynamic base path:
<head>
<base href="http://<%= Request.Url.Authority + Request.ApplicationPath%>/" />
</head>
This will ensure a correct root path regardless of deployment configuration.
To be fair, this doesn't answer the original question, but it elimiates most needs for getting the root path from javascript. Simply use relative URL's everywhere, without prefixing with slash.
Should you still need to access it from javascript, add an id attribute and use document.getElementFromId() as MiffTheFox suggested - but on the base-tag.
Another option that's a bit simpler and more universal would be to take the following:
<script src="/assets/js/bootstrap.min.js"><script>
and use Page.ResolveClientUrl like so:
<script src='<%=ResolveClientUrl("~/assets/js/bootstrap.min.js")%>'></script>
then regardless of what subdirectory the urls will always be rendered correctly.
The following function will calculate the root of the currently running application. I use it to locate the absolute location of resources, when called from somewhere deep within the application tree.
function AppRoot() {
//
// Returns the root of the currently running ASP application.
// in the form: "http://localhost/TRMS40/"
//
// origin: "http://localhost"
// pathname: "/TRMS40/Test/Test%20EMA.aspx"
//
// usage:
// window.open( AppRoot() + "CertPlan_Editor.aspx?ID=" + ID);
//
var z = window.location.pathname.split('/');
return window.location.origin + "/" + z[1] + "/";
}
In the PreRender of your .NET base page, add this:
protected override void
OnPreRender(EventArgs e) {
base.OnPreRender(e);
if (Page.Header != null)
{
//USED TO RESOLVE URL IN JAVASCRIPT
string baseUrl = String.Format("var baseUrl='{0}';\n",
HttpContext.Current.Request.ApplicationPath);
Page.Header.Controls.Add(new LiteralControl(String.Format(Consts.JS_TAG,
baseUrl)));
}
}
Then in your global JavaScript function, add the following:
function resolveUrl(url) {
if (url.indexOf("~/") == 0) {
url = baseUrl + url.substring(2);
}
return url; }
Now you can use it like this:
document.getElementById('someimage').src = resolveUrl('~/images/protest.jpg');
May be a little much for some projects, but works great for full fledged applications.
Solution for ASP.NET MVC applications
This works when using IIS and also IIS Express in VS.
Put this snippet before all scripts load, in order to have the root url variable "approot".
at your service in the scripts:
<script>
var approot = "#Url.Content("~")";
</script>
--> other scripts go here or somewhere later in the page.
Then use it in your script or page script.
Example:
var sound_root_path = approot + "sound/";
var img_root_path = approot + "img/";
the approot variable will be something either:
"/YourWebsiteName/" <-- IIS
or just:
"/" <-- IIS Express
For ASP.net MVC Razor pages, Create a base tag like below in the <Head> tag
<base href="http://#Request.Url.Authority#Request.ApplicationPath" />
and in all your relative javascript URLs, make sure to start without a slash(/) otherwise it will refer from the root.
For ex. create all your urls like
"riskInfo": { url: "Content/images/RiskInfo.png", id: "RI" },
or
$http.POST("Account/GetModelList", this, request, this.bindModelList);
If you want to use it in HTML Still you can use ~, see this
href = #Url.Content("~/controllername/actionName")
See the check box click event in my MVC Application
#Html.CheckBoxFor(m=>Model.IsChecked,
new {#onclick=#Url.Content("~/controller/action("+ #Model.Id + ", 1)"),
#title="Select To Renew" })
Related
I am building an app with Phonegap and jQuerymobile. The app roughly works like this:
1) The app downloads a ZIP file from a public server and then unzips them to a local folder. I got the local folder path from fileSystem.root.toNativeURL() (in OS, it's something like this: file://var/mobile/Container/Data/Application/xxxx/Documents/)
2) App redirects to HTML that was unzipped in local folder (ex: file://var/mobile/Container/Data/Application/xxxx/Documents/index.html)
I am now facing issues b/c inside the index.html file, all the links are absolute path (ex: Link). This breaks all the links since (I assume) they are all now pointing to file://content/index2.html instead of file://var/mobile/Container/Data/Application/xxxx/Documents/content/index2.html.
My question is, how should I handle the links? I am thinking i should just rewrite all the links to force prepend the local folder URL in front of it. Is there a better way?
And if rewriting links is the way to go, how can I do this with jQuerymobile? I did this in jQuery which seems to work http://jsfiddle.net/jg4ouqc5/ but this code doesn't work in my app (jQueryMobile)
When you are loading index.html, you are getting file://some_path/..../index.html as your base URL. Any links which will be encountered now own-wards can be resolved in relation to the base URL.
You would know your scenario better. There could be multiple ways in which this can be fixed.
Have a contract with the CMS/Code generator. Links should always be generated either Relative to the base URL or Absolute. The links you are getting in the page are wrong - Link it ideally should be Link or fully qualified like https://www.google.com.
If you want to change the URL then you can use native code to change it after unzipping the content. It will be really straight forward.
If you want to change the URL in browser then you will have to persist the base url and then take care of couple of things:
a. absolute urls - In your case you can just check the window.location.protocol, if it starts with 'http' and then skip it.
b. sub-directories
Here is a small I have written:
Note: I have not tried this code and you might have to change it according to your need.
$(document).ready(function(){
var base_file_name = window.location.pathname.substring(window.location.pathname.lastIndexOf('/') + 1);
//In index.html (persist this value in native)
var baseUrl = window.location.href.replace(base_file_name, "");
$("a").each(function () {
this.href = baseUrl + this.pathname;
$(this).click(function (e) {
e.preventDefault();
alert(this.pathname);
window.location.href = this.href;
});
});
});
The example you linked should work, make sure you have the <base> set correctly and that you are using the correct string to replace.
Yeah, your going to have to normalize all URL's when your page loads. I can't test with phonegap right now, but your basePath will need to be one of the following:
The file path as you described in your answer (not likely)
window.location.origin (optionally including window.location.pathname)
CODE:
// mini dom ready - https://github.com/DesignByOnyx/mini-domready
(function(e,t,n){var r="attachEvent",i="addEventListener",s="DOMContentLoaded";if(!t[i])i=t[r]?(s="onreadystatechange")&&r:"";e[n]=function(r){/in/.test(t.readyState)?!i?setTimeout(function(){e[n](r)},9):t[i](s,r,false):r()}})
(window,document,"domReady");
domReady(function () {
var anchors = document.getElementsByTagName['a'],
basePath = /* get your base path here, without a trailing slash */;
Array.prototype.forEach.call(anchors, function( anchor ){
anchor.setAttribute('href', basePath + anchor.getAttribute('href'));
});
});
Remove the forward slash from the beginning of your links.
href="content/index2.html">
I have a Javascript function, where I want to call jQuery.Load() to load a file. How would I get ASP.Net to fill in the local server name, so that I can just give a relative path?
The reason for that is I can give the base, say "http://www.mydomain.com/", however I would like to be able to test locally and not have to publish on every single build. I just want to load a local file.
My first thought was just "/MyFolder/MyPage.aspx", but that did not work. I then thought of "~/MyFolder/MyPage.aspx", but that did not work either.
I figure it should be some sort of ASP.Net directive to prepend, just I am not sure what.
I wanted to give some code to show the actual use and what worked.
<head runat="server">
<script type="text/javascript">
// <![CDATA[
function DoPopupSignin()
{
var urlLoad = "http://" + window.location.host + '/Candiates/Login.aspx';
// Triggering bPopup when click event is fired
$('#popupSigninMaster').bPopup({
//modalClose: false,
//opacity: 0.6,
//positionStyle: 'fixed', //'fixed' or 'absolute'
content: 'iframe', //'iframe' or 'ajax'
contentContainer: '.content',
loadUrl: urlLoad, //Uses jQuery.load()
});
}
// ]]>
</script>
</head>
I am trying to get my jQuery Popup working loading the contents from another file. My code uses the free jQuery popup control that I found jQuery.bPopup.js.
In JavaScript as you are preparing your query, you can use window.location.host.
var path = window.location.host + '/relative/path/file.ext';
$.load(path);
It's a recurring pain, but I use something like this:
public static Uri ToAbsoluteUri(this string path)
{
Uri uri;
if (Uri.TryCreate(path, UriKind.Absolute, out uri)) return uri;
var serverUrl = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
var serverUri = new Uri(serverUrl);
return new Uri(serverUri, path);
}
Controls / Forms in .NET have a ResolveUrl(string) method that will allow you to resolve relative paths using ~/ pathing. Otherwise you use the VirtualPathUtility static class.
We can modify the document root directory path for PHP using
$_SERVER['DOCUMENT_ROOT'] = "to/some/new/directory";
//Now the "/" which represent the ^(above) path
in .htaccess we have
RewriteBase "/to/some/new/directory"
Now, I need to modify the root directory path to use in javascript. How to do it?
Currently, I am declaring a variable containing static path to the my personalized root directory and using it as
var root = "../to/new/path";
document.location = root+"/somepage.php";
Scenario
I think i should tell a little bit about the scenario, for you guys to catch my idea
Default Web Root Directory
http_docs/
inside it contain a main folder
http_docs/application <-- contains the actual application
http_docs/js <-- contains the script
http_docs/index.html
Now, the application also contains ajax feature for updating, editing, loading new content, or other resources, which if accessed at "/" will represent at /some/path/i/called not /application/some/path/i/called,
To come around this problem
I can define a static variable like
var root = "application/";
and use it somewhere like
$.post(....., function(data) { $(body).append("<img src='"+root+"resources/img1.jpg"); });
But for a single use, defining the path as static, might not be a big deal, but, when the application grows, and certain modification would cause me to change all the paths i give in the js part. I thought, it would be sensible, just like, I do it in PHP, using <img src="/resources/img1.jpg" />
I tried my best to explain this question, if still is not understandable, please community, lets help them understand. I welcome you to edit my question.
EDITED: Trying to answer the updated question
Assuming the JavaScript is called included from the index.html file, if you insert a img tag and use relative urls, they will be relative to the path of the index file. So <img src='application/resources/img1.jpg'> would work just fine. If the script should work for several sublevels (e.g. if the page "application/etc/etc2/somePage.html" needs images from "application/resources/")it may be easier to use absolute urls, and you could include a javascript block on every page generated by php that holds the absolute url to the "root" of the application, like:
<!-- included by php in all html pages, e.g. in defautlHeadter.php -->
<script type="text/javascript">
var rootUrl = "<?= getTheRootUrl() ?>";
</script>
Where getTheRootUrl() is a method or server variable that gives the root url you need. If the url is translated/remapped (by apache etc. outside of what is visible to php) you may need to hardcode the root url in the php method but at least it will be only one file to change if you ever change the root directory.
Then you can use the root url to specify absolute paths anywhere in the application/website using rootUrl + "/some/relative/path" in anywhere in the application.
I once made something like this, to set
window.app_absolute = '<?php echo GetRelativePath(dirname(__FILE__)); ?>'
I also use something like this
static function GetRelativePath($path)
{
$dr = $_SERVER['DOCUMENT_ROOT']; //Probably Apache situated
if (empty($dr)) //Probably IIS situated
{
//Get the document root from the translated path.
$pt = str_replace('\\\\', '/', Server::GetVar('PATH_TRANSLATED',
Server::GetVar('ORIG_PATH_TRANSLATED')));
$dr = substr($pt, 0, -strlen(Server::GetVar('SCRIPT_NAME')));
}
$dr = str_replace('\\\\', '/', $dr);
return substr(str_replace('\\', '/', str_replace('\\\\', '/', $path)), strlen($dr));
}
... Something along those lines, hacked up for demonstration purposes.
I am creating a webapp and I have been using tag in my JSPs to ensure that all my links (both to pages and to resources such as images/css) are always consistent from the root of the application, and not relative to my current location.
Some of the content I am creating using jQuery, for example, I am creating a HTML table by parsing a JSON object and using jquery.append() to insert it in to a div.
My question is, if I want to dynamically create a link using jquery how can I achieve a consistent URL regardless of the page being executed? I have tried just building the html with the tag in it, but no joy.
Thanks!
var baseURL = "/* Server-side JSP code that sets the base URL */";
$("<a />", { href: baseURL+"/my/resource/here.jsp" }); //Your proper link
Or you could do:
var baseURL = "http://"+location.host+"/my/base/url/";
//Which gives you something like http://mySite.com/my/base/url/
Get the root value of your webapp into a string using a jsp tag inside your javascript.
var root = < %=myRootVariable%> //This evaluates to http://www.myapp.com
var dynamicBit = "/foo/bar"
var dynamicLinkUrl = root + dynamicBit
var $newa = $("Hello, world");
$someJQElement.append($newa)
Hopefully none of this will occur in the global namespace. Just sayin'
How do I get the absolute or site-relative path for an included javascript file.
I know this can be done in PHP, (__file__, I think). Even for an included page, one can check the path (to the included file). Is there any way to have this self awareness in Javascript?
I know I can can get the page URL, but need to get the JS URL.
Eg. Javascript needs to modify the src of an image on the page. I know where the image is relative to the JavaScript file. I don't know where the Javascript is relative to the page.
<body>
<img id="img0" src="">
<script src="js/imgMaker/myscript.js"></script>
</body>
function fixPath(){
$$("#img0")[0].set('src','js/imgMaker/images/main.jpg');
}
Please do not tell me to restructure my function - the example is simplified to explain the need.
In the actual case, a Mootools class is being distributed and people can put it into whatever folder they want.
I would just read the src of the script element, but the class can be part of any number of javascript files, so I can't know what the element looks like.
JavaScript (not JScript) has no concept of file names. It was developed for Netscape back in the days. Therefore there is no __file__ feature or anything similar.
The closest you can come are these two possibilities:
What you already mentioned: Harvest all src attributes of all JS files and try to figure out which one is the right.
Make it a necessary option, that the path to the images must be set in the embedding HTML file. If not set, use a reasonable and well-documented default:
<script type="text/javascript">
var options = {
'path_to_images': '/static/images/' // defaults to '/js/img/'
};
</script>
Based on http://ejohn.org/blog/file-in-javascript/
(function(){
this.__defineGetter__("__FILE__", function() {
return (new Error).stack.split("\n")[2].split("#")[1].split(":").slice(0,-1).join(":");
});
})();
(function(){
this.__defineGetter__("__DIR__", function() {
return __FILE__.substring(0, __FILE__.lastIndexOf('/'));
});
})();
Then later
img.setAttribute('src', __DIR__ + '/' + file);
if you have folders:
/webroot
/images
/scripts
Then images would be an absolute path of /images/whatever.jpg and scripts would be an absolute path of /scripts/js.js
I'm using the following method to get the base URL and using it for loading the other prorotypes, maybe this is what you need. Lets say current script name is 'clone.js'.
/*
* get the base URL using current script
*/
var baseURL = '';
var myName = 'clone.js';
var myPattern = /(^|[\/\\])clone\.js(\?|$)/;
var scripts = document.getElementsByTagName("script");
for (var i = 0; i < scripts.length; i++) {
var src;
if (src = scripts[i].getAttribute("src")) {
if (src.match(myPattern)) {
baseURL = src.replace(myName, '');
break;
}
}
}
Var baseURL should contain what you need.
The path to the JS is irrelevant; links in the HTML file are always relative to the HTML file, even if you modify them from external JS.
[EDIT] If you need to build a path relative to the current web page, you can find its path in document.location.pathname. This path is relative to the web root but you should be able to find a known subpath and then work from there.
For example, for this page, it pathname would be /posts/1858724. You can look for posts and then build a relative path from there (for example posts/../images/smiley.png)
I know this question was asked awhile back but I have a similar situation to Sam's.
In my case, I have two reasons for the situation:
The user can access different sub-domains, each with its own index page.
The user can enter a password that causes index.php to adjust the paths.
Most of the references point to the same src locations for the scripts, but some do not. For instance, those at a different level of the tree would require a different path.
I addressed it by assigning an id to the index page's script tag. For example, the head might include...
<script id='scriptLocation' type='text/javascript' language='javascript' src='../scripts.test/script.js'></script>
My JavaScript is then able to read the path...
var myPath = document.getElementById("scriptLocation").src;
Found another approach, perhaps someone with more JS ninja can flush this out.
CSS stylesheet are able to find the node that called them using document.stylesheets.ownernode.
I could not find a similar call for javascript files.
But, in some cases, if one can include a CSS file together with the javascript, and give the first rule some unique identifier.
One can loop through all stylesheets till they find the one with the identifier [if(document.stylsheets[i].cssRules[0] == thisIs:myCSS)], than use ownerNode to get the path of that file, and assume the same for the JS.
Convoluted and not very useful, but its another approach - might trigger a better idea by someone.