Make sure <a href="local file"> is opened outside of browser - html

For an Intranet web application (document management), I want to show a list of files associated with a certain customer. The resulting HTML is like this:
somefile.docx
somefile.pdf
yetanotherfile.txt
This works fine. Unfortunetly, when clicking on a text file (or image file), Internet Explorer (and I guess most other browsers as well) insist on showing it in the browser instead of opening the file with the associated application (e.g. Notepad). In our case, this is undesired behavior, since it does not allow the user to edit the file.
Is there some workaround to this behavior (e.g. something like <a href="file:///..." open="external">)? I'm aware that this is a browser-specific thing, and an IE-only solution would be fine (it's an Intranet application after all).

Do you WANT people to just mess around with things lying on your server? That reeks of lack of security to me...
I'd recommend letting the user check it out locally and using a database or similar to allow people to check in new drafts. Said drafts should be verified and validated somehow before they are actually written to the server's filesystem.

I just tested this and it seems to work (IE6, not in FF or Chrome):
<HTML>
<script language="JavaScript">
function startWord(strFile)
{
var myApp = new ActiveXObject("Word.Application");
if (myApp != null)
{
myApp.Visible = true;
myApp.Documents.Open(strFile);
}
}
</script>
test.doc.
Found it here.

Related

Asp.net link to file: in IE strange behaviour

We are working on migrating an older ASP.Net application to the cloud and for that we did several things also updated the application to use a newer .net framework.
Now we face a strange problem, in the application a link is created from data in the database. The html:
<asp:HyperLink ID="linkProjectFolder" CssClass="imageLink" runat="server" ToolTip="Open de folder in de Windows Explorer">
<asp:Image ID="Image1" runat="server" ImageUrl="~/pages/img/openHS.png" />
</asp:HyperLink>
The code behind:
string url = string.Concat(((TextBox)viewINFO.FindControl("txtProjectmapBasePath")).Text, ((TextBox)viewINFO.FindControl("txtProjectmapPath")).Text);
HyperLink hl = (HyperLink)viewINFO.FindControl("linkProjectFolder");
if (hl != null)
{
hl.NavigateUrl = Uri.EscapeUriString(#"file:///" + url);
}
Nothing special and this code has not changed between the old version and the new version. I know that this code does not work in firefox and chrome, but the old version does work in IE11.
Now from the enduser the old version in IE just works, if you click the link a windows explorer window is opened to the file path. For the same end user, from the same workstation with the same browser the new version does not work. When you click the link nothing happens.
Now the strange part, on my development machine, I simulate a network drive by mapping a folder to a drive letter (susbst N: c:\temp\Ndrive) when I try the link I see the same behavior as the end user, just nothing happens. Now if I unmap the drive, start the application and click the link, the link opens in the browser and I get a "page cannot be displayed". If I remap the drive at that moment, go back in the browser and retry the link it works.....
There are of course differences, the .net framework, IIS vs IISExpress vs IIS on azure, but as it is just a simple href I would say it must be client side. Also that the code sometimes works suggests that the urlencoding at least is correct (it does exactly the same as in the old version for the tested url's)
In the database the links are a path to a mapped drive so something like "N:\folder\folder 2\folder & folder\", that is correctly urlencoded and that only works half the time as described above. If I use a link to my C drive "C:\Temp" it never works, if I use "127.0.0.1/C$/Temp/" as link it always works but changing all the links in the database to use an IP address is not really the way we want to go.
After eliminating all the things above I have no clue on what could cause this behavior. Can anybody point me in the right direction ?
Consider revising the asp:HyperLink tag with a nested asp:Image tag with one of these two (2) options:
1) Use an asp:HyperLink tag with ImageUrl property and remove the nested image tag. See this Microsoft Hyperlink.ImageUrl Property page for more information.
2) Use an asp:ImageButton tag with the ImageUrl property. See this SO question titled: how to link imagebutton to url visual developer for more information.
If none of these options resolves your problem, then you may have a file resource access issue rather than an ASP.NET syntax issue.

Does Postmessage work between individual web pages under the same domain? If so, how?

In my code, I have this:
<script>
var iframe = document.getElementById("some_iframe").contentWindow; //sending part
iframe.postMessage("X", 'http?://example.com');
</script>
On the receiving page, I have
<script>
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) { alert(e.data); } // no security concerns here, just the message is needed
</script>
When I look into the console of the sending page, I get this error:
Unable to post message to http?://example.com. Recipient has origin http?://www.example.com
Can't post more than two links, whatever so I put a ? just after http. Not actually in the code.
Actually, I think I found the answer. It's subtle, but www is what's interfering, right? But just to be sure, you can use postMessage for communication between two documents on the same server?
Some example code would be great as well. Thanks!
You can look in detail about how postMessage works and the quirks when dealing with same-or-cross-domain and sandboxing in this tutorial. For basic reference see this article.
In short, you can do postMessage between any two windows, no matter the domain.
Now that I think of it, just to be clear, both windows have to be open under the same document tree, meaning they must have a common parent document (as in the same browser tab on the same device). I am not sure if you think you can achieve this on different browsers or tabs or devices, which is not the case, and you must look at web-sockets and webRTC for that, as this is a completely different feature.

Alternative to iFrames with HTML5

I would like to know if there is an alternative to iFrames with HTML5.
I mean by that, be able to inject cross-domains HTML inside of a webpage without using an iFrame.
Basically there are 4 ways to embed HTML into a web page:
<iframe> An iframe's content lives entirely in a separate context than your page. While that's mostly a great feature and it's the most compatible among browser versions, it creates additional challenges (shrink wrapping the size of the frame to its content is tough, insanely frustrating to script into/out of, nearly impossible to style).
AJAX. As the solutions shown here prove, you can use the XMLHttpRequest object to retrieve data and inject it to your page. It is not ideal because it depends on scripting techniques, thus making the execution slower and more complex, among other drawbacks.
Hacks. Few mentioned in this question and not very reliable.
HTML5 Web Components. HTML Imports, part of the Web Components, allows to bundle HTML documents in other HTML documents. That includes HTML, CSS, JavaScript or anything else an .html file can contain. This makes it a great solution with many interesting use cases: split an app into bundled components that you can distribute as building blocks, better manage dependencies to avoid redundancy, code organization, etc. Here is a trivial example:
<!-- Resources on other origins must be CORS-enabled. -->
<link rel="import" href="http://example.com/elements.html">
Native compatibility is still an issue, but you can use a polyfill to make it work in evergreen browsers Today.
You can learn more here and here.
You can use object and embed, like so:
<object data="http://www.web-source.net" width="600" height="400">
<embed src="http://www.web-source.net" width="600" height="400"> </embed>
Error: Embedded data could not be displayed.
</object>
Which isn't new, but still works. I'm not sure if it has the same functionality though.
object is an easy alternative in HTML5:
<object data="https://github.com/AbrarJahin/Asp.NetCore_3.1-PostGRE_Role-Claim_Management/"
width="400"
height="300"
type="text/html">
Alternative Content
</object>
You can also try embed:
<embed src="https://github.com/AbrarJahin/Asp.NetCore_3.1-PostGRE_Role-Claim_Management/"
width=200
height=200
onerror="alert('URL invalid !!');" />
Re-
As currently, StackOverflow has turned off support for showing external URL contents, run code snippet is not showing anything. But for your site, it will work perfectly.
No, there isn't an equivalent. The <iframe> element is still valid in HTML5. Depending on what exact interaction you need there might be different APIs. For example there's the postMessage method which allows you to achieve cross domain javascript interaction. But if you want to display cross domain HTML contents (styled with CSS and made interactive with javascript) iframe stays as a good way to do.
If you want to do this and control the server from which the base page or content is being served, you can use Cross Origin Resource Sharing (http://www.w3.org/TR/access-control/) to allow client-side JavaScript to load data into a <div> via XMLHttpRequest():
// I safely ignore IE 6 and 5 (!) users
// because I do not wish to proliferate
// broken software that will hurt other
// users of the internet, which is what
// you're doing when you write anything
// for old version of IE (5/6)
xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState == 4 && xhr.status == 200) {
document.getElementById('displayDiv').innerHTML = xhr.responseText;
}
};
xhr.open('GET', 'http://api.google.com/thing?request=data', true);
xhr.send();
Now for the lynchpin of this whole operation, you need to write code for your server that will give clients the Access-Control-Allow-Origin header, specifying which domains you want the client-side code to be able to access via XMLHttpRequest(). The following is an example of PHP code you can include at the top of your page in order to send these headers to clients:
<?php
header('Access-Control-Allow-Origin: http://api.google.com');
header('Access-Control-Allow-Origin: http://some.example.com');
?>
This also does seem to work, although W3C specifies it is not intended "for an external (typically non-HTML) application or interactive content"
<embed src="http://www.somesite.com" width=200 height=200 />
More info:
http://www.w3.org/wiki/HTML/Elements/embed
http://www.w3schools.com/tags/tag_embed.asp
An iframe is still the best way to download cross-domain visual content. With AJAX you can certainly download the HTML from a web page and stick it in a div (as others have mentioned) however the bigger problem is security. With iframes you'll be able to load the cross domain content but won't be able to manipulate it since the content doesn't actually belong to you. On the other hand with AJAX you can certainly manipulate any content you are able to download but the other domain's server needs to be setup in such a way that will allow you to download it to begin with. A lot of times you won't have access to the other domain's configuration and even if you do, unless you do that kind of configuration all the time, it can be a headache. In which case the iframe can be the MUCH easier alternative.
As others have mentioned you can also use the embed tag and the object tag but that's not necessarily more advanced or newer than the iframe.
HTML5 has gone more in the direction of adopting web APIs to get information from cross domains. Usually web APIs just return data though and not HTML.
I created a node module to solve this problem node-iframe-replacement. You provide the source URL of the parent site and CSS selector to inject your content into and it merges the two together.
Changes to the parent site are picked up every 5 minutes.
var iframeReplacement = require('node-iframe-replacement');
// add iframe replacement to express as middleware (adds res.merge method)
app.use(iframeReplacement);
// create a regular express route
app.get('/', function(req, res){
// respond to this request with our fake-news content embedded within the BBC News home page
res.merge('fake-news', {
// external url to fetch
sourceUrl: 'http://www.bbc.co.uk/news',
// css selector to inject our content into
sourcePlaceholder: 'div[data-entityid="container-top-stories#1"]',
// pass a function here to intercept the source html prior to merging
transform: null
});
});
The source contains a working example of injecting content into the BBC News home page.
You can use an XMLHttpRequest to load a page into a div (or any other element of your page really). An exemple function would be:
function loadPage(){
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else{
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
document.getElementById("ID OF ELEMENT YOU WANT TO LOAD PAGE IN").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("POST","WEBPAGE YOU WANT TO LOAD",true);
xmlhttp.send();
}
If your sever is capable, you could also use PHP to do this, but since you're asking for an HTML5 method, this should be all you need.
The key issue to load another site's page in your own site's page is security. There is cross-site security policy defined, you would have no chance to load it directly in your iframe if another site has it set to strict same origin policy. Hence to find an alternative to iframe, they must be able to bypass this security policy restriction, even in the future, if any new component is introduced by WSC, it would have similar security restrictions.
For now, the best way to bypass this is to simulate a normal page access in your logic, this means AJAX + server side access maybe a good option. You can set up some proxy at your server side and fetch the page content and load it into the iframe. This works but not perfect as if there is any link or image in the content and they may not be accessible.
Normally if you try to load a page in your own iframe, you would need to check whether the page can be loaded in iframe or not. This post gives some guidelines on how to do the check.
You should have a look into JSON-P - that was a perfect solution for me when I had that problem:
https://en.wikipedia.org/wiki/JSONP
You basically define a javascript file that loads all your data and another javascript file that processes and displays it. That gets rid of the ugly scrollbar of iframes.

Directory Chooser in HTML page

How can I create a directory chooser in html page.
If I use input file element I can select file only, but I need to select directory instead.
I need to do this beacause the user should select a right path inside his computer.
Any solutions ?
Try this, I think it will work for you:
<input type="file" webkitdirectory directory multiple/>
You can find the demo of this at https://plus.google.com/+AddyOsmani/posts/Dk5UhZ6zfF3 ,
and if you need further information you can find it
here.
Can't be done in pure HTML/JavaScript for security reasons.
Selecting a file for upload is the best you can do, and even then you won't get its full original path in modern browsers.
You may be able to put something together using Java or Flash (e.g. using SWFUpload as a basis), but it's a lot of work and brings additional compatibility issues.
Another thought would be opening an iframe showing the user's C: drive (or whatever) but even if that's possible nowadays (could be blocked for security reasons, haven't tried in a long time) it will be impossible for your web site to communicate with the iframe (again for security reasons).
What do you need this for?
As of 2022 there is now a directory picker API:
https://developer.mozilla.org/en-US/docs/Web/API/Window/showDirectoryPicker
async function getDir() {
const dirHandle = await window.showDirectoryPicker();
// run code for dirHandle
}
In case if you are the server and the user (e.g. you are creating an app which works via browser and you need to choose a folder) then try to call JFileChooser from the server when some button is clicked in the browser
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle("select folder");
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setAcceptAllFileFilterUsed(false);
This code snipped is from here
This is my solution. It is the same as the above answers but you should notice that webkitdirectory = "true".
<input id="design" type="file" webkitdirectory = "true" directory/>
I did a work around. I had a hidden textbox to hold the value. Then, on form_onsubmit,
I copied the path value, less the file name to the hidden folder. Then, set the fileInput box to "". That way, no file is uploaded.
I don't recall the event of the fileUpload control. Maybe onchange. It's been a while. If there's a value, I parse off the file name and put the folder back to the box. Of, course you'd validate that the file as a valid file.
This would give you the clients workstation folder.
However, if you want to reflect server paths, that requires a whole different coding approach.
This isn't provided by HTML because of the security risk. <input type='file' /> is closest, but not what you are looking for.
If you're still using IE11 on Windows 10, you may try this example that uses an ActiveX control to achieve what you want.
Again if the OS is Windows, you can use VB scripts to access the core control files to browse for a folder.
If you do not have too many folders then I suggest you use if statements to choose an upload folder depending on the user input details.
E.g.
String user= request.getParameter("username");
if (user=="Alfred"){
//Path A;
}
if (user=="other"){
//Path B;
}

How do I make Firefox auto-refresh on file change?

Does anyone know of an extension for Firefox, or a script or some other mechanism, that can monitor one or more local files. Firefox would auto-refresh or otherwise update its canvas when it detected a change (of timestamp) in the files(s).
For editing CSS, it would be ideal if just the CSS could be reloaded, rather than a full HTML re-render.
Effectively it would enable similar behaviour to Firebug with its dynamic HTML/CSS editing, only through external files.
Live.js
From the website:
How?
Just include Live.js and it will monitor the current page including local CSS and Javascript by sending consecutive HEAD requests to the server. Changes to CSS will be applied dynamically and HTML or Javascript changes will reload the page. Try it!
Where?
Live.js works in Firefox, Chrome, Safari, Opera and IE6+ until proven otherwise. Live.js is independent of the development framework or language you use, whether it be Ruby, Handcraft, Python, Django, NET, Java, Php, Drupal, Joomla or what-have-you.
It has the huge benefit of working with IETester, dynamically refreshing each open IE tab.
Try it out by adding the following to your <head>
<script type="text/javascript" src="http://livejs.com/live.js"></script>
Have a look at FileWatcher extension:
https://addons.mozilla.org/en-US/firefox/addon/filewatcher/
it's a WebExtension, so it works with the latest Firefox
it has a native app (to be installed locally) that monitors watched files for changes using native OS calls (no polling!) and notifies the WebExtension to let it reload the web page
reload is driven by rules: a rule contains the page URL (with regular expression support) and its included/excluded local source files
open source: https://github.com/coolsoft-ita/filewatcher
DISCLAIMER: I'm the author of the extension ;)
I would recommend livejs
But it has following Advantages and Disadvantages
Advantages:
1. Easy setup
2. Works seamlessly on different browsers (Live.js works in Firefox, Chrome, Safari, Opera and IE6+)
3. Don't add irritating interval for refreshing browser specially when you want to debug along with designing
4. Only refreshing when you save change ctrl + S
5. Directly saves CSS etc from firebug I have not used that feature but read on their site http://livejs.com/ that they support it too!!!
Disadvantages:
1. It will not work on file protocol file:///C:/Users/Admin/Desktop/livejs/live.html
2. You need to have server to run it like http://localhost
3. You have to remove it while deploying on staging/production
4. Doesn't serves CDN I have tried cheating & applying direct link http://livejs.com/live.js but it will not work you have to download and keep on local to work.
Xrefresh with firebug.
Firefox has an extension called mozRepl.
Emacs can plug into this, with moz-reload-on-save-mode.
when it's set up, saving the file forces a refresh of the browser window.
There are some IDE's that contain this ability (They'll have a pane within them or some other means to auto-refresh a page on save).
If you want to do this yourself a quick hack is to set the meta refresh on the page to a low value - one or two seconds.
# Will refresh the page content every second
<meta http-equiv="refresh" content="1" />
You could just place a javascript interval on your page, have it query a local script which checks the last date modified of the css file, and refreshes it if it changed.
jQuery Example:
var modTime = 0;
setInterval(function(){
$.post("isModified.php", {"file":"main.css", "time":modTime}, function(rst) {
if (rst.time != modTime) {
modTime = rst.time;
// reload style tag
$("head link[rel='stylesheet']:eq(0)").remove();
$("head").prepend($(document.createElement("link")).attr({
"rel":"stylesheet",
"href":"http://sstatic.net/mso/all.css?v=4372"
})
);
}
});
}, 5000);
Browsersync can do this from the server side / outside of the browser.
This can achieve more repeatable results / things that don't require so much clicking.
This will serve a page and refresh on change
cd static_content
browser-sync start --server --files .
It also allows a scripting mode.
This is certainly hacky, but if you want to work locally without making any external request (to live.js, for example), or run any local server, I think this might be useful. This is not specific to web development, you can adopt similar strategy to any other workflow.
You will need two tiny tools (which are present in almost all distribution repos): inotify-tools and xdotool.
First get the ID of your Firefox and your editor window using xdotool.
$ xdotool search --name "Mozilla Firefox"
60817411
60817836
$ xdotool search --name "Pluma" # Pluma is my editor
94371842
Depending on the number of processes running, you will get one or more window ID. Use xdotool windowactivate <ID> to know which one you want (the focus changes to the respective window).
Use inotifywait -e close_write to monitor changes to your local file and when you save the file using your editor, change focus to your browser, reload xdotool key CTRL+R and focus back to your editor. This is so instantaneous you will not notice nothing.
Also, inotifywait exits on change, so you might have to do it in a loop. Here is a minimum working example (in Bash in your working directory).
while /usr/bin/true
do
inotifywait -e close_write index.html;
xdotool windowactivate 60917411; # Switch to Firefox
xdotool key CTRL+R; # Reload Firefox
xdotool windowactivate 94371842 # Switch back to Pluma
done
You can use inotifywait to watch for the entire directory or some selected files in your directory.
You can write a script that can automate is easily.
This works on Linux (I've tested this on Void Linux.)
You can use live.js with a tampermonkey script to avoid having to include https://livejs.com/live.js in your HTML file.
// ==UserScript==
// #name Auto reload
// #author weirane
// #version 0.1
// #match http://127.0.0.1/*
// #grant none
// ==/UserScript==
(function() {
'use strict';
if (Number(window.location.port) === 8000) {
const script = document.createElement('script');
script.src = 'https://livejs.com/live.js';
document.body.appendChild(script);
}
})();
With this tampermonkey script, the live.js script will be automatically inserted to pages whose address matches http://127.0.0.1:8000/*. You can change the port according to your need.
I think that you can solve it by using some ajax requests after a determinate interval. You can do a request to CSS files and then if you don't get the "not modified" header you delete your css and load it again. For dynamic files you do a request and store the response and then every time you make a request to that file you compare the response to the latest.