Why does Save Chart function work so differently across browsers? - javascript

I am using the following function to allow the user to save an image. (Half the charts they might want to save as image are hidden, so they can't right click on them. They're displayed instead as SVGs.) I also want download-as-image options available for those who don't know about right clicking on images.
This is all working perfectly in my text editor & Chrome. I click the button with the saveChart function attached and the file downloads. In Safari a new tab opens at the URL - not the behaviour I want but understandable. I can't test on IE. But on Firefox nothing happens at all. It's as though i haven't pressed the button.
JS is enabled and works on other buttons / functions.
function saveChart(obj) {
var tempStr = obj.parentNode.id;
var newID = Number(tempStr.substr(6,tempStr.length-6));
var a = document.createElement('a');
a.href = 'charts/chart'+newID+'.png';
a.download = 'image.png';
a.click();
}
Is the difference caused by user security settings and if so what are they? Is there any way to secure the same (download) behaviour cross-browser?
Thanks
Emma

Related

Javascript Bookmarklet - Download Images

Edit: Thanks to #Dogoku, I was able to find a solution (here). It turns out that Chrome doesn't allow/handle the download attribute anymore, so we have to force a workaround.
I'm trying to create a javascript bookmarklet that downloads images (code shown below). It's accessing the url correctly, but instead of downloading the image it just opens the image in a new tab.
Please help!
r.addEventListener('click', function(ev) {
r.href = h;
r.download = c;
}, false);
document.body.appendChild(r), r.click(), document.body.removeChild(r);
the variable r is created using document.createElement("a") which creates an element like so:
Before, when using a bookmarklet you could basically just "click" on the image and it would download.

using modernizr to determine if multiple window open is supported

the problem I've encountered is documented here.
window.open behaviour in chrome tabs/windows
where you can not open multiple windows via javascript in chrome.
I would like to open the multiple windows if it is supported, if it is not supported I will simply return a list of links.
is there a way using modernizr or something besides browser sniffing that I can determine if the behavior is supported?
This ability to open multiple windows various widely between browser and even by browser config.
So never assume you will be able to open multiple pop ups, you might be able to, but you can only know by testing, it's very easy to test tough.
To test if opening a pop up succeeded, inspect the return value.
var popupWindow = window.open('http://www.google.com/');
if (!popupWindow) {
console.log('the window did not open');
// do other stuff
}
If the window opened the return value will be a Window object.
If the the window did not open, the return value will be be falsy, this exact return value can vary from pop up blocker to pop up blocker, but generally you can assume the value to be falsy if the window did not open; meaning undefined or null.
As such it's very easy to trigger an alternate method in case the window failed to open.
You do not need modernizr or any plugins for this, this behavior of returning the Window object is the same in all browsers.
MDN reference:
https://developer.mozilla.org/en-US/docs/Web/API/Window/open
Firefox and Safari seem to support opening multiple windows by default. Chrome however will block the second window and show the little "pop up" blocked message.
Additionally Chrome will also block opening windows that did not originate from direct users actions; meaning a click or a key press.
Nothing like modernizr or any custom code is going to give you any type of feature detection. The main reason is because all major browsers require some sort of user action to open a new window programmatically - usually a click. So creating a feature detection is out of the question.
This is an interesting question and one where thinking in terms of "progressive enhancement" might help you get to a good solution.
First, let's assume that you cannot open multiple windows in any browser. What would you do? Show a list of links as you've suggested. By adding something like target="_blank" to each link, now we have a working app without any JavaScript (or if the user has JavaScript disabled):
<section id="links-wrap">
<a href="/page-A.html" target="_blank" />
<a href="/page-B.html" target="_blank" />
</section>
This baseline of functionality will work on every single browser ever made - your Treo visitors will love you. However, this experience is less than ideal because the links are likely to open new tabs instead of new windows. So let's use JavaScript to open a new window whenever a link is clicked. Lets also hide each link after it is clicked and position each window so that they are not overlapping:
function openWindowFromLink (link, idx) {
var top = idx % 2 * 600;
var left = Math.floor(idx/2) * 600;
var win = window.open(link.href, 'Window '+ top +'x'+ left, 'width=600,height=600,top='+ top +',left='+ left);
if (win) {
link.style.display = "none";
}
return win;
}
function handleLinkClick(ev) {
ev.preventDefault();
var link = ev.target;
var idx = 0;
var prev = link.previousSibling;
while (prev) {
if (prev.nodeType === 1) {
idx++;
}
prev = prev.previousSibling;
}
openWindowFromLink(link, idx);
}
document.getElementById('links-wrap').addEventListener('click', handleLinkClick);
Now comes the hard part: how can we open many windows at once. As we know, Chrome will only allow one window to open per user click. While other browsers might not have this same restriction, they may add it in the future (I'm actually surprised that they don't all have this restriction right now). So lets assume that all browsers have the same limitation as Chrome. Users don't want to click every single link every time - so lets give them a click target that they can click really fast to open all of the windows. Creative wording will reduce the annoyance of this task.
<div id="rapid-click-box">
Click me really fast and see what happens!
</div>
... and some JavaScript:
var clickBox = document.getElementById('rapid-click-box');
var clickCount = 0;
clickBox.addEventListener('click', function handleRapidClick (ev) {
var link = links[clickCount];
if (link.style.display !== 'none') {
openWindowFromLink(link, clickCount);
}
if (++clickCount === links.length) {
clickBox.removeEventListener('click', handleRapidClick);
clickBox.style.display = 'none';
}
});
Finally, lets take care of those browser which allow multiple windows to be opened at once. We still need the user to click in order to call window.open - so lets get creative and see how we can make the user click something. A cleverly worded welcome message should suffice:
<div id="welcome-message" style="display:none">
<h1>Hey, welcome to my site. Are you a human?</h1>
<button>Yes</button>
</div>
<script>
// show the welcome message immediately if JS is enabled
document.getElementById('welcome-message').style.display = 'block';
</script>
... and once again, a little bit of JavaScript:
var button = document.getElementsByTagName('button')[0];
button.addEventListener('click', function handleYesClick (ev) {
ev.preventDefault();
button.removeEventListener('click', handleYesClick);
document.getElementById('welcome-message').style.display = 'none';
for (var i = 0, l = links.length; i < l; i++) {
if ( !openWindowFromLink(links[i], i) ) {
break;
}
}
if (i === links.length) {
clickBox.style.display = 'none';
}
});
And a fiddle to show it all in action:
https://jsfiddle.net/q8x5pqsw/

Script works in console but doesn't work in chrome extension [duplicate]

This question already has an answer here:
Can't trigger click with jQuery in a Chrome extension
(1 answer)
Closed 7 years ago.
I'm trying to write a google chrome extension to scarpe some data from an internet store (product title, description, price etc.) and put that data to a classified adds website.
I also want to download all images from the product gallery to be able to upload them to the latter website.
Because the product page contains small resolution pics I click on them in order to load a mid resolution pics and then download them using HTML5 attribute download.
Here is the script that I've wrote:
//Fing li elements with small versions of pics
var li = $('#product_card_nav li');
var li_length = li.length;
for (i=0; i<li_length; i++) {
//click on each small pic to load a mid resolution pic
li.eq(i).find('a').trigger('click');
var img = $('.b-gallery2__img img');
//create a link to download a mid resolution pic
var link = document.createElement('a');
link.href = img.attr('src');
link.download = 'MyToy.jpeg';
document.body.appendChild(link);
link.click();
}
This script works fine when I copy and paste it in the chrome console. But when I try to use it in the content script of my chrome extension it always downloads only first pic several times.
What is the reason for such behaviour?
Content script can access the javascript in your web page. When you trigger click, nothing happend because the code that you want to run is from the web page.
For more information - https://developer.chrome.com/extensions/content_scripts#execution-environment
(I'm sorry about my english)

JQuery Feature Detection for <a href="data:..."> support?

I have am using html2canvas to enable screenshots of divs within my web application. It's working well enough in Chrome (including Android), Safari (including iOS) and FireFox. In IE 11, however the image won't save.
Code looks like this:
function displayModalWithImage(canvas, filename) {
var modalcontainer = $('#snapshot');
var modalcontainer_body = modalcontainer.children().find('.snap_shot_container');
var modalcontainer_save = modalcontainer.children().find('.save_snapshot');
var image = new Image();
var data = canvas.toDataURL("image/png");
image.src = data;
modalcontainer_save.attr('download', filename +".png");
modalcontainer_save.attr('href',
data.replace(/^data[:]image\/png[;]/i, "data:application/octet-stream;"));
$(modalcontainer_body).html('');
$(image).appendTo(modalcontainer_body);
$(modalcontainer_save).on('click', function() {
modalcontainer.modal('hide');
});
modalcontainer.modal();
}
Browser behavior varies:
Chrome: displays modal and then saves the file when "Save" is clicked. (acceptable)
Firefox: displays modal and then displays a separate dialog when "Save" is clicked (acceptable)
Safari: display modal and then loads image in a separate tab when "Save" is clicked (acceptable... maybe)
IE 11: displays modal, but does nothing but hide the dialog when "Save" is clicked (unacceptable)
The data.replace was suggested by another SO answer, but it did not appear to have any effect on the behavior of any of the browsers. Previously the href attribute was simply set to data.
So, anyway, at this point replacing the modal dialog with a simple window.location = data is a viable alternative. But, since Chrome works well and Safari and FF work well enough, i'd like to simply do a feature detection that would window.location for IE but show the modal for the other browsers. But, I don't know what "feature" is missing in IE to check for.
tl;dr
is there simply a change or bug in my javascript that would enable IE to work (save the image encoded as data to a file).
if not, which feature in IE should I detect for that would enable me to customize the behavior for IE
if that's not an option; what's the current best practices for old-fashioned browser detection?

Save image as jpg with extension

I'm using Backbone and html2canvas.js, this is the code I have so far for transforming a div to canvas and saving it. It works, but it doesn't add the .jpg extension. Because of this, after downloading the image, FF and Chrome first ask me about the program I want to use to open the file and IE just tells me that I don't have the right program and suggests visiting the store.
In FF and Chrome I can see the image when choosing the default Windows picture viewer etc.
What I would like to achieve is to add the .jpg extension so the file opens in the default program right away:
savePicture: function() {
//$(this.el).find('.drag-img').unwrap();
var image = $(this.el).find('#droppable2');
html2canvas(image, {
onrendered: function(canvas) {
var img = canvas.toDataURL("image/jpeg");
var frame = document.getElementById("myHideFrame");
if (!frame) {
frame = document.createElement("iframe");
frame.id = "myHideFrame";
document.body.appendChild(frame);
}
frame.src = img.replace(/^data[:]image\/(png|jpg|jpeg)[;]/i, "data:application/octet-stream;");
}
});
},
Sadly, IE8 and above only supports data URIs in CSS, <link>, and <img>. So adding it to a frame as you are doing will not work.
Could you, for IE8 and above, put the data into an <img> and ask the user to right click and save the image?

Categories