Get site root url in javascript - javascript

Using Joomla to create my site. Let say my site is located at
https://domain.com/directory/siteName
I want to get this path in javascript on any page rendered on my site. The issue is, following internal sub menus and site's different settings, the path comes to be any one like these-
https://domain.com/directory/siteName/anyMenu/index.php
https://domain.com/directory/siteName/index.php
https://domain.com/directory/siteName/index.php?option=com_content&id=9
https://domain.com/directory/siteName/anyMenu
https://domain.com/directory/siteName/anyMenu.html
I have tried some solutions like-
var re = new RegExp(/^.*\//);
alert(re.exec(window.location.href));
It truncates the last node as index.php in case 1, also
var dummy = new Image;
dummy.src = '$';
alert(dummy.src.slice(0,-1));
does the same thing. So is there any way to get exact address where site is located using javascript only? Also the result must be generic for any site as if it is applied in any extension then that extension can be installed in any site with any level of directory structure.
I require this as I am using a js file which is internally registering another js file. So path for this, to be registered js has to be given in first js

You can use Joomla's JURI::base() function for that. Remember it's php. so you could do something like:
$document = JFactory::getDocument();
$document->addScriptDeclaration('var base = \''.JURI::base().'\'');
You can now use the base variable in your JS script. Remember to add it to the document after the declaration above.

Related

javascript window.open can't go back to parent folder

I'm trying to open a pdf that is located in the parent folder. I have no problem opening a pdf in the current directory or a child directory. However can't load the parent folder.
aLink.click(function(){
var pdf = "/../test.pdf";
window.open(pdf);
});
after running it we get Cannot GET /test.pdf.
Seems like it doesn't recognize /../ (accessing parent directory) Any help?
Write it this way:
var pdf = "../test.pdf";
Without the first slash
Many servers these days disable the ability to use relative links to access parent elements by default due to certain exploits where sloppy code can be used to expose your account level login information. Instead, you should use a base url so you can make your calls top-down.
var base_url = window.location.origin;
aLink.click(function(){
var pdf = base_url+"/folder/test.pdf";
window.open(pdf);
});

How do I make JS know about the application root?

I have some javascript that's referencing /jobs/GetIndex in an MVC project. This works great when I run it locally because I have a Controller called JobsController. When I deploy it, I deploy the application to a 'Jobs' subfolder, which means the URL should become http://site/jobs/jobs/GetIndex but it's going to http://site/jobs/GetIndex, I presume because the javascript doesn't know what the 'root URL' is, and uses the site as the root. How can I get it to work in both environments?
If you simply care about getting the root/base url of the site so you can append that to get the other url you are after, you may simply use / as the first character of your url.
var urlToJobIndex2= "/jobs/GetIndex";
Here is an alternate approach if you want more than just the app root (Ex : Specific urls( built using mvc helper methods such as Url.RouteUrl etc)
You may use the Url.Content helper method in your razor view to generate the url to the app base, assign it to a javascript variable and use that in your other js code to build your other urls.
Always make sure to use javascript namespacing when doing so to avoid possible issues with global javascript variables.
If you want to get url to a specific action method, you may use the Url.Action or Url.RouteUrl helper methods.
So in your razor view (Layout file or specific view), you may do this.
<script>
var myApp = myApp || {};
myApp.Urls = myApp.Urls || {};
myApp.Urls.baseUrl = '#Url.Content("~")';
myApp.Urls.jobIndexUrl= '#Url.Action("GetIndex","jobs")';
</script>
<script src="~/Scripts/PageSpecificExternalJsFile.js"></script>
And in your PageSpecificExternalJsFile.js file, you can read it like
var urlToJobIndex= myApp.Urls.jobIndexUrl;
// Or With the base url, you may safely add the remaining url route.
var urlToJobIndex2= myApp.Urls.baseUrl+"jobs/GetIndex";
Here is a detailed answer about the same , but using this in a specific page/view
Angular Js
You might need the correct relative url(s) in your angular controller / services / directives.The same approach will work for your angular code as well. Simply build the js namespace object and use the angular value provider to pass the data to your angular controllers/services/directives as explained in this post in detail with example code.
Add <base href="/jobs"> to your head tag. It will specify the root.
This is further explained here https://docs.angularjs.org/guide/$location

Using external JavaScript files in a WinForms/WPF WebBrowser control

I found a cool feature on a website, implemented in JavaScript, I'd like to use it as is in my desktop application (for personal use).
During my experiments I managed to generate custom HTML on the fly, feed it to the browser using webBrowser1.DocumentText = [my generated HTML]
I've managed to put some inline JavaScript into the HTML, and hook it up via a ScriptManager so that I can call the JavaScript from my C# code, pass a value to it, and get a return value.
But the feature I'm trying to use is a bit more complicated: it's no less than 10 JavaScript files. 2 of them are referenced directly in the web page the usual way <script src="/js/script1.js" type="text/javascript"></script>
The other 8 are loaded in one of the scripts:
var elem = document.createElement("script");
elem.type = "text/javascript";
elem.src = "/js/" + filename;
document.body.appendChild(elem);
These 8 files are in fact data files, even though the data is represented in JavaScript. They're pretty large, over 1MB each. Stuffing it all into the HTML file seems quite stupid. Also, the script that loads the data creates a "file map" and further refers to the data based on which file it's in:
var fileMap = [
[/[\u0020-\u00ff]/, 'file1.js'],
[/[\u3000-\u30ff]/, 'file2.js'],
[/[\u4e00-\u5dff]/, 'file3.js'],
...
I don't want to resort to modifying the JavaScript, because it's not exactly my strong point. So the browser needs to "see" the js files in order to be able to use them. I thought of creating the file structure locally, and navigating the browser there. But I don't want any loose files in my solution. I'd like to have everything embedded if possible. And I doubt I can get the browser to navigate to an embedded resource, and see other embedded resources as files. Any idea how I could get around this?
EDIT:
I've tried to do it with local files. No luck. I get the HTML to load properly, but when I try to invoke a JavaScript call, nothing happens. I tried pointing the browser to those js files, to make sure they're there. They are. I tried an element with src attribute pointing to an image in the same subfolder as the script files. It gets rendered. It's as if external js files refuse to load.
I had a similar need as your scenario and I addressed it using two key points embedded in two other Stack Overflow answers. As noted by SLaks' answer here the first key is using the syntax file:/// as the prefix for an absolute path to external files. The second is using .Replace("\\", "/") for an absolute file path as listed in Adam Plocher's answer and one of his follow-up comments here.
In short, the final output for each external file in an HTML page will look something like:
<link href="file:///c:/users/david/myApp/styles/site.css" rel="stylesheet" type="text/css">
or
<script src="file:///c:/users/david/myApp/scripts/JavaScript1.js"></script>
Using the format in the samples above in my HTML file resulted in the WebBrowser control loading external CSS, image or script files.
The details and solving the scenario in the question
In the womd's answer in the first referenced SO answer above he used the method System.IO.File.ReadAllText() to load script files and embedded the text of the script files into the <head> tag. As you indicated in your question loading script files directly into the HTML page is not what you're looking to do.
The solution below involves using the same System.IO.File.ReadAllText() method but loads the text of the HTML page instead. The premise works similar to the Razor View Engine in ASP.NET.
The main idea in the solution below involves adding a temporary string in an HTML page that will be loaded into the WebBrowser control and then replacing this temporary string in a C# method in my app just before the HTML page is set to be loaded into the WebBrowser control.
Here are the basic steps to my solution:
Add a temporary string for each external reference in the HTML file.
Declare a variable for the absolute path in a script tag within the HTML file. This step is not necessary unless you're going to use the absolute path elsewhere within your JavaScript code. Your scenario involves delay loading external script files via JavaScript code so this step was necessary.
Modify the src property in the JavaScript code that delay loads the other script files with the absolute path variable.
Add a method in your app to loads the HTML page file as a text string and then replaces all temporary string instances with an absolute path containing the prefix 'file:///'. The absolute path should have forward slashes.
Set the 'DocumentText' property on the WebBrowser control to the updated HTML.
Set the 'Copy to Output Directory' of each external file in your project to 'Copy always' or 'Copy if newer'. This step may not be necessary if you have a fixed location to your external files and that location is not within the build or publish directory used by Visual Studio.
The following are the details for each step. I added a lot of detail that you can skip. I was verbose to reduce any confusion since the steps make changes to several places in the project.
1. Using a temporary string
I used the string "/ReplaceWithAbsolutePath/" but you can use any distinct text. Each reference to an external file in the HTML page looks like:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<link href="/ReplaceWithAbsolutePath/styles/site.css" rel="stylesheet" type="text/css">
<script type="text/javascript">
var absolutePath = "/ReplaceWithAbsolutePath/";
</script>
</head>
<body>
<p>My web page</p>
<script src="/ReplaceWithAbsolutePath/scripts/JavaScript1.js"></script>
</body>
</html>
2. Declare absolute path variable
Note in the above HTML page I listed a <script> tag with the declared variable 'absolutePath' set to the temporary string. (In the HTML page above the variable is added a global variable and that is not necessarily best practice. You can declare the variable within a namespace instead of declaring it in the global namespace.)
3. Modify the delay load script to include absolute path variable
Add the 'absolutePath' variable to your JavaScript file that delay loads other JavaScript files containing your data.
elem.src = absolutePath + "/js/" + filename;
4. C# method to replace all temporary string instances
Within your project add the following line to your form load event handler or place this line somewhere in your initialization of the WebBrowser control.
webBrowser1.DocumentText = GetUpdatedHtmlWithAbsolutePaths("/ReplaceWithAbsolutePath/", "HTMLPage1.html");
Add the following method to your code. Update the call to the method in the line above with the name of the class instance where the following method is placed.
// The result of this method will look like the following example:
// <script src="file:///c:/users/david/documents/myApp/scripts/JavaScript1.js"></script>
public string GetUpdatedHtmlWithAbsolutePaths(string tempPathString, string htmlFilename)
{
// Get the directory as the application
// stackoverflow.com/questions/674857/should-i-use-appdomain-currentdomain-basedirectory-or-system-environment-current
// Note that the 'BaseDirectory' property will return a string with trailing backslashes ('\\')
string appDirectory = AppDomain.CurrentDomain.BaseDirectory;
// Replace '//' with '/' in the appDirectory string
appDirectory = appDirectory.Replace("\\", "/");
// Read all of the HTML text from the HTML page file
string html = System.IO.File.ReadAllText(appDirectory + #"\" + htmlFilename);
// Replace all '/ReplaceWithAbsolutePath/' strings within the HTML text with
// the absolute path on the local machine
html = html.Replace(tempPathString, "file:///" + appDirectory);
return html;
}
5. Set the DocumentText property of the WebBrowser control
I added the initialization of the WebBrowser control in the form load event handler but you can, of course, add the line that sets the DocumentText property wherever you initialize your WebBrowser control.
private void Form1_Load(object sender, EventArgs e)
{
// Set the document text of the web browser control with the updated HTML
webBrowser1.DocumentText = GetUpdatedHtmlWithAbsolutePaths("HTMLPage1.html");
}
6. Set the 'Copy to Output Directory' of each external file
Take a look at the answer posted by Matthew Watson in this Stack Overflow question if you want your external files included in your solution/project file structure.
You can add files to your project and select their properties: "Build
Action" as "Content" and "Copy to output directory" as "Copy Always"
or Copy if Newer (the latter is preferable because otherwise the
project rebuilds fully every time you build it).
Then those files will be copied to your output folder.
This is better than using a post build step because Visual Studio will
know that the files are part of the project. (That affects things like
ClickOnce applications which need to know what files to add to the
clickonce data.)
In short, add the external file to your project. You can add the external to any subfolder in your project. (In Visual Studio 2013 or 2015 -- I don't have VS2012) Right-click on the external file in the Solution Explorer and select Properties from the context menu. The Properties pane will be displayed. In the Properties pane change the setting for 'Copy to Output Directory' to 'Copy always' or 'Copy if newer'.
Use View Source to verify absolute path strings
Run your project and it should load your external files in the WebBrowser control. Assuming you have not set the property wbChartContainer.IsWebBrowserContextMenuEnabled = false; in code or in the Properties pane for WebBrowser control you can right-click on the WebBrowser control when your form is running. Click 'View Source' from the context menu and check the paths to your external resources in the View Source window.

Setting up a common route for javascript calls in ASP.NET MVC project

I have a bizarre routing issue with my ASP.NET MVC project that I hope you guys can help me with.
Overall everything works fine when I run the project off my localhost or run it on the server while it's deployed directly at http://myServerName. The problems start when I deploy the application to various enviornments on the server located under different virtual directories. For example: http://myServerName/QaEnviornment or http://myServerName/TestEnviornment
The problem is that all Javascript calls to application URLs ignore my environment virtual directories and fail.
For example on my QA server whenever I have to make an Ajax call I take a standard approach such as:
var myUrl = '/ControllerName/ActionMethodName/'
$.ajax({url:myUrl,success:function(){Do stuff} })
Because my application is deployed on http://myServerName/QaEnviornment, when rendered I expect myUrl to be http://myServerName/QaEnviornment/ControllerName/ActionMethodName. Instead it comes back as http://myServerName/ControllerName/ActionMethodName and ofcourse fails.
To get around this for now I declared a global Javascript variable that contains the environment folder name and when I build URLs for javascript calls I have to remember to ALWAYS construct them as var myUrl = myGlobalFolderVar + '/ControllerName/ActionMethodName/'
Using a global JavaScript variable to get around this issue seems as a bad solution to me. Is there anything I can do to get routing to work properly so whenever JavaScript calls are made whatever subfolder the application is running under is always included in the URL ?
Instead of always having to remember to construct them correctly, make a helper function that you call to create your URLs
function CreateUrl(string path){
return myGlobalFolderVar + path;
}
To answer your second question, not really. Routing is not aware of what made the request and you cannot always rely on the X-Http-RequestedWith header to base that decision on. In addition, your site application root is not at the domain root, therefore routing would only kick in when it visits your application. The only other way I am aware of is to have MVC actually generate the Url for you (var url = '#Url.RouteUrl(params)';) but this does not help at all when you have your JavaScript in a single or a few .js files.
EDIT
The above function is a JavaScript function that can sit anywhere you would like in your application, including external JS files. As for setting your myGlobalFolderVar, there are a few ways you could set this.
1.Actually hard code the variable in your external JS file.
var myGlobalFolderVar = 'TestEnviornment';
This is hard however if you are deploying to several different testing servers.
2.If you are using web.config transformations, you could add an AppSettings key/value pair in your web.config transformations depending on build type. Then, using that value, set your global Javascript variable in your master page layout/views.
<appSettings xdt:Transform="Replace">
<add key="folderLocation" value="TestEnvironment" />
</appSettings>
In your external JS file
//this makes it a site wide/global variable in any place you
//include your external JS file
var myGlobalFolderVar = '';
And in your master view
<script type="text/javascript">
myGlobalFolderVar = '#ConfigurationManager.AppSettings["folderLocation"]'
</script>
3.Same as number two, but use the URL helpers to figure out what the path to your application is in your master view instead of using the web.config transformations
<script type="text/javascript">
myGlobalFolderVar = '#Url.Content("~/")'
</script>
The basic idea is using .NET to figure out where it lives and set a global JavaScript variable with that path information. Then, in conjunction with the helper JavaScript function provided at the top of this answer, you can correctly generate paths as needed throughout your application - regardless of path depth, deployment location or any other deployment type concerns.
var myUrl = CreateUrl('/ControllerName/ActionMethodName/');
$.ajax({url:myUrl,success:function(){Do stuff} });

Can I redirect the Admin->abc.aspx to rootfolder->index.aspx using javascript?

Just explaining my question in short.
I have asp.net website with root structure as following
root Directory->
Admin
abc.aspx
xyz.aspx
index.aspx
Now I want to redirect from abc.aspx to index.aspx.
I'm using JavaScript as
window.location = "../index.aspx";
but found no any luck.
This is a very odd trick. But it works.
Have a hidden field in the page. This needn't be a server control. (Or if you want, you can even do without one.). For brevity sake I am assuming you've used a server HiddenField control, called hfNavUrl. Do something like this.
hfNavUrl.Value = Me.ResolveUrl("~/index.aspx")
Once this renders you get the full url. Find the hidden field value in javascript and work your javascript code:
window.location.href = document.getElementByValue('hfNavUrl').value;
Update: Doing it w/o using controls
There are two ways about this. However, you'd have to embed the code in your page markup file (i.e. the *.aspx file). The javascript way is something like holding the url into a variable.
var url = '<%= Me.ResolveUrl("~/index.aspx") %>';
You can now make use of the value inside of this variable at a later point of time.
Alternatively, you can simply have a <a> element with its href set directly:
Home
Ps: Me.whatever is the vb.net way of doing things. Replace it with this if you are working with c#
Try using "window.location.replace('/index.aspx')"
You issue will be resolved by one of the below solutions from java script by providing the type of application.
If Application created as Website
windows.location='/index.aspx';
and
If Application created as Virtual directory
windows.location='/[Virtual Directory Name of Root Folder]/index.aspx';

Categories

Resources