I have an HTML page that has a reference to some scripts like these ones:
<script charset="utf-8" src="Content/Styles/ThemeForest/assets/js/vendors.js"></script>
<script charset="utf-8" src="Content/Styles/ThemeForest/assets/js/app.js"></script>
The problem is, that when I upload my site to a server, it is no longer working.
I figured that if I instead add the web application name, it will work again. Something like this:
<script charset="utf-8" src="MySite/Content/Styles/ThemeForest/assets/js/vendors.js"></script>
<script charset="utf-8" src="MySite/CContent/Styles/ThemeForest/assets/js/app.js"></script>
Now, the thing is, that I may not know how the web application name would be like once it is uploaded to a server... so, I would like to dynamically add the application name to the src.
I noticed that there is a JavaScript function called window.location.pathname, which can bring me the web application name (if any). I could concatenate this to the rest of the route and it should work.
Now, the catch is, this is all on a regular HTML page.
Is there a way that I can set a custom route to those script tags using basic JavaScript functions? Or any other ideas?
You can use something like $script, just add that lines of code in your app.run or any other place, and call it with an array of the routes of the js files that you want to load. You said that you could get the web application name, so just pass the name of the app concatenated with the path of the script:
var dependenciesLoadingFactory = function(deps) {
return ['$q', '$rootScope', function($q, $rootScope) {
var deferred = $q.defer();
$script(deps, function() {
$rootScope.$apply(function() { deferred.resolve(); });
});
return deferred.promise;
}];
};
If you link to a source document starting with a directory or the filename itself (like you did in your question), the lookup will look for it starting in the same folder that your current file (this would be the html file that holds your script tags) is in.
You could also link to files in parent directories relative to your current location, like this:
../file.js
You can alternatively link to a path starting with a slash:
/dir/to/your/file.js
This will start looking in the root directory of your page, meaning the directory your domain or subdomain points to. You can't successfully link to files that are above your root directory.
Finally, if your files are on another server, make sure you include the full path including the http:// snippet:
http://example.website.com/dir/file.js
Under normal circumstances, there should really be no reason to deviate from these methods, but if you absolutely have to dynamically set a directory, I suggest you use php because it's server-side and therefore faster for the user, and available if they have javascript disabled (which is important if you link to other files such as style sheets in this way):
<?php $directory = '/dir/'; ?>
<script src="<?php print $directory; ?>file.js"></script>
Of course for this to work, your server has to have php running.
Related
I am working on an ASP.NET Web Forms project that make use of Routing.
I have two routing situations:
http://mywebsite.com/section
http://mywebsite.com/section/subsection
My js files are stored in a /js folder in the root of the project.
Fact is, when I load /section page everything works fine, the js are loaded correctly. When I load /section/subsection page the js are not loaded and actually the path appear to be something like
http://www.mywebsite.com/section/file.js
I have already tried to put a slash before the name of the js folder or even to use a server side ResolveUrl function like
<script src='<%=ResolveUrl("~/js/file.js")%>'></script>
In this case file.js il loaded correctly; anyway if file.js contains calls to an external js file, the latter is not loaded (its path is always in the form of /section/externalfile.js).
Adding the following line to the Global.asax
routes.Ignore("{*allfiles}", new { allfiles = #".*\.(css|js|gif|jpg|png)" });
did not solve the problem either.
The most surprising thing is the fact that, for instance, image or CSS files are loaded correctly even with a normal link like the following:
<link rel="stylesheet" type="text/css" href="css/owl.theme.css" media="all" />
Is there anyone who has an idea of how solving this issue ?
Edit: The master page of my project calls a cutom.js file (which is loaded correctly). This file contains for instance the following call to superfish.min.js:
Modernizr.load([{
load: kopa_variable.url.template_directory_uri + 'js/superfish.min.js',
complete: function() {
$('.top-menu').superfish({});
}
}]);
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.
I have a .NET MVC5 application using C#, HTML and Javascript.
I need to know the link of the host so I can send a specific file in a specific folder to the user.
In my local computer, when I test and develop the application, the path the app uses is the following:
localhost:1234/Home/Scripts/myScript.js
However, in the real deployment server, the path changes:
www.superhost.com/Apps/MyApp/Home/Scripts/myScript.js
I am trying to send this file to the user with the following JQuery, when a button is clicked:
$("a.btn.btn-default").click(function () {
download("/Scripts/myScript.js"); //download is a personal function, unimportant
return false; //prevent browser defualt behavior
});
The problem is that when I click the button, I get in the consolo an erorr - 404 error, which means the server is not finding the file.
In fact the server is searching for the file on the path "/Scripts/myScript.js", but the file is in "Apps/MyApp/Home/Scripts/myScript.js".
How do I make my javascript smart enough to figure the correct path?
One solution I use a lot is to inject a site-root URL into the page using something like this:
<body data-root="#Url.Content("~/")">
Which converts to the actual website base URL at runtime.
You then use that injected value, from all jQuery code, using:
var root = $('body').data("root");
You can simply prepend that to any relative URLs to make them work correctly:
$("a.btn.btn-default").click(function () {
download(root + "Scripts/myScript.js"); //download is a personal function, unimportant
return false; //prevent browser defualt behavior
});
Note: this approach will work in cases where the routing changes:
e.g / vs /home/index/ vs /home/ which are all the same page, but different URLs
Remove the leading / from your download path.
You actually don't need an absolute path (and to know server's home folder) to access a file, target it relatively from the page you invoke the download from.
note: If you are using page relative paths, you must make sure you don't move the page the download script is executed from.
I always use in my layout the next code:
<script type="text/javascript">
var rootUrl = "#Url.Content("~/")";
</script>
And when I need it, i use for example:
$("a.btn.btn-default").click(function () {
download(rootUrl + "Scripts/myScript.js"); //download is a personal function, unimportant
return false; //prevent browser defualt behavior
});
Trying to import my js file from my page.
My page is in webcontent/mydomain/templates/page.xhtml
My js is in webcontent/mydomain/test/scripts
In page.xhtml
<script type="text/javascript" src="../test/scripts/test.js"></script>
But still the script is not getting picked.
Can anyone tell how I need to give the path in src.
Try this:
<script src="/test/scripts/test.js"></script>
Provided that webcontent is the root of public web content and thus /mydomain is also a public folder and thus your JavaScript is standalone available by http://localhost:8080/context/mydomain/test/scripts/test.js, assuming a domain of http://localhost:8080 and a context path of /context, then the following should do:
<script src="#{request.contextPath}/mydomain/test/scripts/test.js"></script>
This will generate a domain-relative URL with a dynamically inlined context path, which is much more robust than fiddling with ../ which would make the URI relative to the current request URI (as you see in browser's address bar) and not to the physical location of the template file as many starters incorrectly assume.
Is it possible to get the Javascript server path?
For example, I have a javascript file that is in a directory, and in that directory there are some php scripts that I want to "post" to.
When I include the javascript file in my home page
<script type="text/javascript" src="assets/js/some.js"></script>
I can't access say a file like /post.php that resides in the assets/js/ directory using relative paths since the javascript is not being "run" in the directory that the home page is in.
Obviously, I can specify the path, but I was trying to think of a more robust way.
I know you can get the "script" tags and get the url of the file, and I could probably work from there, but I didn't know if such a function exists, that would just tell you.
Thank you!
Create a script that is served from bla.php and place it before your some.js
<script type="text/javascript" src="bla.php"></script>
Inside bla.php, render a javascript class and store your data in it.
i.e.
function MyConstants() {
this.HELLO = "hello";
this.POST_PATH = "/etc.php";
}
You can access the constants (or anything else) via:
var consts = new MyConstants();
alert(consts.HELLO);
Hope this helps! :-)
You can try to use a cross-browser stack tracer to get the current file name
however there are many cases where your idea this might break, For example if you add a JS cacher that complies all necessary JS files into one and compresses them.
I would say that a smarter approach is to have a principle in place with which you can figure out the urls for your php skripts, like RubyOnRails has routes