I have a ASP.NET website that gets published to a web server that has multiple sites. For example:
www.example.com/SiteA or www.example.com/SiteB
Plus I also test the site locally before publishing, for example at localhost:12345
When I specify a path for an image, for example: /Images/exampleImage.gif, this works when running the site locally, since the Images folder is in the root directory. localhost:12345/Images/exampleImage.gif is the correct path in this case.
But when published to the web server, for example to www.example.com/SiteA, the same path tries to go to www.example.com/Images/exampleImage.gif and the image doesn't appear correctly.
Also, this is only for HTML controls, as with a ASP control, I know I can just use the tilde (~/Images/exampleImage.gif) and it'll know to look at the site's root directory, which is www.example.com/SiteA/Images/exampleImage.gif.
For my case, It'd be strongly preferred to stay with an HTML control.
Edit: The reason for this is because I have JavaScript that changes the image of a html img control based on if a div is hidden:
function Toggle(commId, imageId) {
var div = document.getElementById(commId);
var img = document.getElementById(imageId);
if (div.style.display == 'none') {
div.style.display = 'inline';
img.src = "/Images/minus.gif";
} else {
div.style.display = 'none';
img.src = "/Images/plus.gif";
}
}
How could I get the path to the images folder, relative to the root of the site when there's folders for each site on a server, as well as still working on localhost?
You'll have to use code to do the ~/ or publish a new virtual directory called "/Images" on your server that contains the images.
I didn't know you could put embedded C# code in JavaScript, but figured it out by just doing :
function Toggle(commId, imageId) {
var div = document.getElementById(commId);
var img = document.getElementById(imageId);
if (div.style.display == 'none') {
div.style.display = 'inline';
img.src = "<%= ResolveUrl("~/Images/minus.gif") %>";
} else {
div.style.display = 'none';
img.src = "<%= ResolveUrl("~/Images/plus.gif") %>";
}
}
Since the ResolveUrl method can take the tilde (~) for the path value and knows the websites root directory over the server's.
You can also use the embedded code with the same ResolveUrl method directly in the src attribute of the img html control (and other attributes/controls), in case anyone runs into this same issue but with just the HTML controls.
Related
I am using VSCODE to make a blackjack game using HTML, CSS and javascript. I have defined a button that on clicking gives an image(that is stored in computer). Every time I refresh the live server(chrome), it says NOT ALLOWED TO LOAD LOCAL RESOURCE and FAILED TO LOAD RESOURCE: 404 not found. I am new to web development and need help with this project.
let blackjackGame = {
'you': {'scoreSpan': '#your_blackjack_result', 'div':'#your_box', 'score':0 },
'dealer': {'scoreSpan': '#dealer_blackjack_result', 'div':'#dealer_box', 'score':0 }
};
const YOU = blackjackGame['you']
const DEALER = blackjackGame["dealer"]
function blackjackHit() {
var cardImage = document.createElement('img');
cardImage.src = 'D:\Software Course\JS-Basics\Blackjack\images\Q.png';
document.querySelector(YOU['div']).appendChild(cardImage);
}
document.querySelector("#blackjack_hit_button").addEventListener("click", blackjackHit);
Every time I refresh the live server(chrome)
The web application is running from a server, even if it's one installed locally or only temporarily hosted within Visual Studio. As a result, this path won't work:
cardImage.src = 'D:\Software Course\JS-Basics\Blackjack\images\Q.png';
Because this is a file system path, not a web server URL. The browser doesn't want to mix those for security reasons. Instead, provide a URL for the file. Which might be something like:
cardImage.src = '/images/Q.png';
Finding out the URL is really up to you. But it'll be some path relative to the URL of the page being viewed in the browser.
You must use the correct local path from your computer. Then change the backslashs () to forward slashes (/) and add "file:///" before the path, so:
cardImage.src = 'file:///D:/Software Course/JS-Basics/Blackjack/images/Q.png';
function display_image(src, width, height, alt) {
var img = document.createElement("img");
img.src = src;
img.width = width;
img.height = height;
img.alt = alt;
// This next line will just add it to the <body> tag
document.body.appendChild(img);
}
Add image
I want to take a snapshot of the webpage from the url. The url is an html web page which is dynamic. Basically we needed an img of that webpage.
I thought to convert the html page to image in c# but din't work.
I first read the html using streamreader and using NReco.ImageGenerator tried to convert into bytes and finally image. This isnt working.
Finally I am trying to convert html to canvas using javascript from inside the html web page.
function report() {
let region = document.querySelector("body");
html2canvas(
$('body'),
{allowTaint: true, logging: true,'onrendered': function (canvas)
{}}).then( //getting problem here at then
function (canvas) {
let jpgUrl = canvas.toDataURL();
console.log(jpgUrl);
var text = "bottom-right Brochure1";
var imageName = text + '.jpg';
download(jpgUrl,imageName, "image/png");
}
Code explained - It will take a snpashot of the body element in the html page using js. Take the url and create the canvas from the url. and automatically download. But i face a issue ------- " html2canvas(...),then is not a function" .. I dont know why its happening. Please help.
Because of Cross-Origin Resource Sharing (CORS) restrictions in all modern browsers, this can't be done purely on the clientside. You need something on the server-side to accomplish this. To do it in javascript on the server use NodeJS there are several npm packages that can help like: node-server-screenshot, PhantomJS etc
I have been hunting around on these forums to find some code which can download the HTML page AS IS (i.e. with added elements from other buttons, and essentially everything within my div's) so that it can be picked up another time with the data still there. I cannot for the life of me find anything which just downloads the page. Below is the closest I came to actually saving a html document at all, and even that (obviously) only displays the text written. Could I edit this to make it encapsulate the entire page?
With very little experience I can only apologize.
function save() {
var anchor = document.querySelectory('button');
anchor.setAttribute('download', 'index.html');
anchor.setAttribute('href', 'data:text/html;charset=UTF-8,<p>asdf</p>')
}
One solution is FileSaver.js
Follow the example on that page, and use document.innerHTML for your blob (what I've used) Actually, I forget if that excludes the header. If so, there's a solution I found to this (also on StackOverflow) but I don't have the code here locally to look at how I got around this (if I did, indeed, have to get around this)
You can try this
download html content
<script>
function myFunction() {
var content = document.documentElement.innerHTML;
download(content, "index", "txt")
}
function download(content, fileName, fileType) {
var link = document.getElementById("donwload-link");
var file = new Blob([content], {type: fileType});
var donwloadFile = fileName + "." + fileType;
link.href = URL.createObjectURL(file);
link.download = donwloadFile
}
</script>
https://jsfiddle.net/a9oLw1zv/13/
I have made a user interface to fetch data from a MySQL table and visualize it. It is running on a bokeh server. My users connect remotely to the server using their browser (firefox). This works perfectly fine: I simply import the table into a pandas dataframe.
My users also need to download the table as excel. This means I cannot use the export_csv example which is pure javascript.
I have no experience with JavaScript. All I want is to transfer a file from the directory where my main.py is to the client side.
The technique I have tried so far is to join a normal on_click callback to a button, export the information I need to 'output.xls', then change a parameter from a dummy glyph which in turn runs a Javascript code. I got the idea from Bokeh widgets call CustomJS and Python callback for single event? . Note I haven't set the alpha to 0, so that I can see if the circle is really growing upon clicking the download button.
At the bottom of my message you can find my code. You can see I have tried with both XMLHttpRequest and with Fetch directly. In the former case, nothing happens. In the latter case I obtain a file named "mydata.xlsx" as expected, however it contains only this raw text: <html><title>404: Not Found</title><body>404: Not Found</body></html>.
Code:
p = figure(title='mydata')
#download button
download_b = Button(label="Download", button_type="success")
download_b.on_click(download)
#dummy idea from https://stackoverflow.com/questions/44212250/bokeh-widgets-call-customjs-and-python-callback-for-single-event
dummy = p.circle([1], [1],name='dummy')
JScode_xhr = """
var filename = p.title.text;
filename = filename.concat('.xlsx');
alert(filename);
var xhr = new XMLHttpRequest();
xhr.open('GET', '/output.xlsx', true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this.status == 200) {
var blob = this.response;
alert('seems to work...');
if (navigator.msSaveBlob) {
navigator.msSaveBlob(blob, filename);
}
else {
var link = document.createElement("a");
link = document.createElement('a');
link.href = URL.createObjectURL(blob);
window.open(link.href, '_blank');
link.download = filename;
link.target = "_blank";
link.style.visibility = 'hidden';
link.dispatchEvent(new MouseEvent('click'));
URL.revokeObjectURL(url);
}
}
else {
alert('Ain't working!');
}
};
"""
JScode_fetch = """
var filename = p.title.text;
filename = filename.concat('.xlsx');
alert(filename);
fetch('/output.xlsx').then(response => response.blob())
.then(blob => {
alert(filename);
//addresses IE
if (navigator.msSaveBlob) {
navigator.msSaveBlob(blob, filename);
}
else {
var link = document.createElement("a");
link = document.createElement('a')
link.href = URL.createObjectURL(blob);
window.open(link.href, '_blank');
link.download = filename
link.target = "_blank";
link.style.visibility = 'hidden';
link.dispatchEvent(new MouseEvent('click'))
URL.revokeObjectURL(url);
}
return response.text();
});
"""
dummy.glyph.js_on_change('size', CustomJS(args=dict(p=p),
code=JScode_fetch))
plot_tab = Panel(child=row(download_b,p),
title="Plot",
closable=True,
name=str(self.test))
def download():
writer = pd.ExcelWriter('output.xlsx')
data.to_excel(writer,'data')
infos.to_excel(writer,'info')
dummy = p.select(name='dummy')[0]
dummy.glyph.size = dummy.glyph.size +1
Trying out Eugene Pakhomov's answer, I found what was the issue.
The javascript code I named JScode_fetch is almost correct, however I get a 404 because it is not pointing correctly to the right path.
I made my application in the directory format: I changed my .py file to main.py, placed it into a folder called app, and changed this one line of code in JScode_fetch:
fetch('/app/static/output.xlsx', {cache: "no-store"}).then(response => response.blob())
[...]
You can see the problem was that it was trying to access localhost:5006/output.xlsx, instead of localhost:5006/app/output.xlsx. As it is in directory format, the right link is now localhost:5006/app/static/output.xlsx to count for the static directory.
I also changed a few lines in the download function:
def download():
dirpath = os.path.join(os.path.dirname(__file__),'static')
writer = pd.ExcelWriter(os.path.join(dirpath,'output.xlsx'))
writer = pd.ExcelWriter('output.xlsx')
data.to_excel(writer,'data')
infos.to_excel(writer,'info')
dummy = p.select(name='dummy')[0]
dummy.glyph.size = dummy.glyph.size +1
Now it is working flawlessly!
edit: I have added , {cache: "no-store"} within the fetch() function. Otherwise the browser thinks the file is the same if you have to download a different dataframe excel while using the same output.xlsx filename. More info here.
bokeh serve creates just a few predefined handlers to serve some static files and a WebSocket connection - by default, it doesn't have anything to serve files from the root of the project.
Instead of using the one-file format, you can try using the directory format, save your files to static directory and download them from /static/.
One downside of this approach is that you still have to write that convoluted code to just make your backend create the file before a user downloads it.
The best solution would be to go one step further and embed Bokeh Server as a library into your main application. Since you don't have any non-Bokeh code, the simplest way would be to go with Tornado (an example).
bokeh.server.server.Server accepts extra_patterns argument - you can add a handler there to dynamically create Excel files and serve them from, say, /data/. After all that, the only thing that you need in your front-end is a single link to the Excel file.
I have json feed that gives me thumbimage url.
This returns url like /webapps/CC/fileAPI/edc_eventcal/Celebrations_Todmorden%20Mills%20Harvest%20Festival_th__Vb2eHh-nEpJ8xLLEU5UFw.png
Now, before /webapps/ It needs "app.toronto.ca" to get the full path. So I've replaced "localhost" into "app.toronto.ca" like so. And it gives me full path to image.
Now, the trouble is that, even though I retrieve full URL, image.src syntax will still force computer to add 'Localhost:5000/' to my perfectly assembled URL.
function displayEvent(array,i){
var image_url = array[i].calEvent.thumbImage.url;
var image =new Image();
var hostname = location.hostname;
toronto_host = hostname.replace("localhost","app.toronto.ca") +
image_url;
alert(toronto_host); //this give me pull URL path//
image.src = toronto_host;
alert(image.src);
// this gives localhost:5000/what_i_had_in_toronto_host//
document.getElementById("party_picture").appendChild(image);
};
since no image path starts with http://localhost:5000/... i can't use any image while i'm testing the site.
Any way i could assign image src with the correct url without localhost part?
thank you!
Image src attribute will always append the localhost ( or where the page originates from ), if you don't provide a complete URL ( in your case you provide everything except the protocol ).
toronto_host = hostname.replace("localhost","//app.toronto.ca") +
image_url;
// ^ appending '//' before your
// location will force the browser
// to set the protocol to the current
// one of the page.
This will make your img.src to behave as expected.