-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
IE/Edge SVG export fixes #2068
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IE/Edge SVG export fixes #2068
Changes from 4 commits
57437eb
15579e1
1825153
fd1c501
69cdbd8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,9 @@ var Plotly = require('@lib/index'); | |
var createGraphDiv = require('../assets/create_graph_div'); | ||
var destroyGraphDiv = require('../assets/destroy_graph_div'); | ||
var textchartMock = require('@mocks/text_chart_arrays.json'); | ||
var fail = require('../assets/fail_test'); | ||
|
||
var Lib = require('@src/lib'); | ||
|
||
var LONG_TIMEOUT_INTERVAL = 2 * jasmine.DEFAULT_TIMEOUT_INTERVAL; | ||
|
||
|
@@ -14,6 +17,11 @@ describe('Plotly.downloadImage', function() { | |
// download an image each time they are run | ||
// full credit goes to @etpinard; thanks | ||
var createElement = document.createElement; | ||
var msSaveBlob = navigator.msSaveBlob; | ||
var isIE = Lib.isIE; | ||
var slzProto = (new window.XMLSerializer()).__proto__; | ||
var serializeToString = slzProto.serializeToString; | ||
|
||
beforeAll(function() { | ||
document.createElement = function(args) { | ||
var el = createElement.call(document, args); | ||
|
@@ -32,6 +40,9 @@ describe('Plotly.downloadImage', function() { | |
|
||
afterEach(function() { | ||
destroyGraphDiv(); | ||
Lib.isIE = isIE; | ||
slzProto.serializeToString = serializeToString; | ||
navigator.msSaveBlob = msSaveBlob; | ||
}); | ||
|
||
it('should be attached to Plotly', function() { | ||
|
@@ -59,8 +70,55 @@ describe('Plotly.downloadImage', function() { | |
it('should create link, remove link, accept options', function(done) { | ||
downloadTest(gd, 'svg', done); | ||
}, LONG_TIMEOUT_INTERVAL); | ||
}); | ||
|
||
it('should produce the right SVG output in IE', function(done) { | ||
// mock up IE behavior | ||
Lib.isIE = function() { return true; }; | ||
slzProto.serializeToString = function() { | ||
return serializeToString.apply(this, arguments) | ||
.replace(/(\(#)([^")]*)(\))/gi, '(\"#$2\")'); | ||
}; | ||
var savedBlob; | ||
navigator.msSaveBlob = function(blob) { savedBlob = blob; }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be best to use jasmine There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ha, you can only There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks good! |
||
|
||
var expectedStart = '<svg class=\'main-svg\' xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\''; | ||
var plotClip = /clip-path='url\("#clip[0-9a-f]{6}xyplot"\)/; | ||
var legendClip = /clip-path=\'url\("#legend[0-9a-f]{6}"\)/; | ||
|
||
Plotly.plot(gd, textchartMock.data, textchartMock.layout) | ||
.then(function(gd) { | ||
savedBlob = undefined; | ||
return Plotly.downloadImage(gd, { | ||
format: 'svg', | ||
height: 300, | ||
width: 300, | ||
filename: 'plotly_download' | ||
}); | ||
}) | ||
.then(function() { | ||
expect(savedBlob).toBeDefined(); | ||
if(savedBlob === undefined) return; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps if(saveBlob === undefined) {
fail('undefined save blob');
} would be more readable than an |
||
|
||
return new Promise(function(resolve, reject) { | ||
var reader = new FileReader(); | ||
reader.onloadend = function() { | ||
var res = reader.result; | ||
|
||
expect(res.substr(0, expectedStart.length)).toBe(expectedStart); | ||
expect(res.match(plotClip)).not.toBe(null); | ||
expect(res.match(legendClip)).not.toBe(null); | ||
|
||
resolve(); | ||
}; | ||
reader.onerror = function(e) { reject(e); }; | ||
|
||
reader.readAsText(savedBlob); | ||
}); | ||
}) | ||
.catch(fail) | ||
.then(done); | ||
}, LONG_TIMEOUT_INTERVAL); | ||
}); | ||
|
||
function downloadTest(gd, format, done) { | ||
// use MutationObserver to monitor the DOM | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder what's better (i.e. faster)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see perf as too important in this block. An advantage (at least it looks like an advantage to me...) of the current one is that if
url
does NOT start with the expected'data:image/svg+xml,'
it will throw an error, rather than saving garbage, which seems easier to investigate.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. 👍