@@ -136,6 +136,167 @@ describe('ModeBar', function() {
136136 ] ] ) ;
137137 expect ( checkBtnAttr ( modeBar , 0 , 'data-title' ) ) . toEqual ( '0' ) ;
138138 } ) ;
139+
140+ describe ( 'creates a custom button' , function ( ) {
141+ function getIconSvg ( modeBar ) {
142+ if ( ! modeBar || ! modeBar . buttonElements || ! modeBar . buttonElements . length > 0 ) {
143+ return undefined ;
144+ }
145+ var button = modeBar . buttonElements [ 0 ] ;
146+ return d3 . select ( button ) . select ( 'svg' ) ;
147+ }
148+
149+ it ( 'with a Plotly icon' , function ( ) {
150+ var modeBar = createModeBar ( getMockGraphInfo ( ) , [ [
151+ {
152+ name : 'some button' ,
153+ click : noop ,
154+ icon : Plotly . Icons . home
155+ }
156+ ] ] ) ;
157+
158+ var svg = getIconSvg ( modeBar ) ;
159+ expect ( svg ) . toBeDefined ( ) ;
160+ var path = svg . select ( 'path' ) ;
161+ expect ( path . attr ( 'd' ) ) . toBeDefined ( ) ;
162+ expect ( path . attr ( 'transform' ) ) . toBeDefined ( ) ;
163+ } ) ;
164+
165+ it ( 'with a custom icon' , function ( ) {
166+ var modeBar = createModeBar ( getMockGraphInfo ( ) , [ [
167+ {
168+ name : 'some button' ,
169+ click : noop ,
170+ icon : {
171+ width : 1000 ,
172+ height : 1000 ,
173+ path : 'M0,-150 L1000,-150 L500,850 L0,-150 Z' ,
174+ transform : 'matrix(1 0 0 -1 0 850)' ,
175+ }
176+ }
177+ ] ] ) ;
178+
179+ var svg = getIconSvg ( modeBar ) ;
180+ expect ( svg ) . toBeDefined ( ) ;
181+ expect ( svg . attr ( 'viewBox' ) ) . toBe ( '0 0 1000 1000' ) ;
182+ var path = svg . select ( 'path' ) ;
183+ expect ( path . attr ( 'd' ) ) . toBeDefined ( ) ;
184+ expect ( path . attr ( 'transform' ) ) . toEqual ( 'matrix(1 0 0 -1 0 850)' ) ;
185+ } ) ;
186+
187+ it ( 'with a custom icon with no transform' , function ( ) {
188+ var modeBar = createModeBar ( getMockGraphInfo ( ) , [ [
189+ {
190+ name : 'some button' ,
191+ click : noop ,
192+ icon : {
193+ width : 1000 ,
194+ height : 1000 ,
195+ path : 'M500,0 L1000,1000 L0,1000 L500,0 Z' ,
196+ }
197+ }
198+ ] ] ) ;
199+
200+ var svg = getIconSvg ( modeBar ) ;
201+ expect ( svg ) . toBeDefined ( ) ;
202+ expect ( svg . attr ( 'viewBox' ) ) . toBe ( '0 0 1000 1000' ) ;
203+ var path = svg . select ( 'path' ) ;
204+ expect ( path . attr ( 'd' ) ) . toBeDefined ( ) ;
205+ expect ( path . attr ( 'transform' ) ) . toBeNull ( ) ;
206+ } ) ;
207+
208+ it ( 'with a custom icon created by a function' , function ( ) {
209+ var modeBar = createModeBar ( getMockGraphInfo ( ) , [ [
210+ {
211+ name : 'some button' ,
212+ click : noop ,
213+ icon : function ( ) {
214+ var xmlns = 'http://www.w3.org/2000/svg' ;
215+ var icon = document . createElementNS ( xmlns , 'svg' ) ;
216+ icon . setAttribute ( 'viewBox' , '0 0 1000 1000' ) ;
217+ icon . setAttribute ( 'height' , '1em' ) ;
218+ icon . setAttribute ( 'width' , '1em' ) ;
219+ icon . setAttribute ( 'class' , 'custom-svg' ) ;
220+ var path = document . createElementNS ( xmlns , 'path' ) ;
221+ path . setAttribute ( 'd' , 'M500,0 L1000,1000 L0,1000 L500,0 Z' ) ;
222+ icon . appendChild ( path ) ;
223+ return icon ;
224+ }
225+ }
226+ ] ] ) ;
227+
228+ var svg = getIconSvg ( modeBar ) ;
229+ expect ( svg ) . toBeDefined ( ) ;
230+ expect ( svg . attr ( 'viewBox' ) ) . toBe ( '0 0 1000 1000' ) ;
231+ expect ( svg . attr ( 'class' ) ) . toBe ( 'custom-svg' ) ;
232+ var path = svg . select ( 'path' ) ;
233+ expect ( path . attr ( 'd' ) ) . toBeDefined ( ) ;
234+ expect ( path . attr ( 'transform' ) ) . toBeNull ( ) ;
235+ } ) ;
236+
237+ it ( 'with a legacy icon config' , function ( ) {
238+ var modeBar = createModeBar ( getMockGraphInfo ( ) , [ [
239+ {
240+ name : 'some button' ,
241+ click : noop ,
242+ icon : {
243+ width : 1000 ,
244+ path : 'M0,-150 L1000,-150 L500,850 L0,-150 Z' ,
245+ ascent : 850 ,
246+ descent : - 150
247+ }
248+ }
249+ ] ] ) ;
250+
251+ var svg = getIconSvg ( modeBar ) ;
252+ expect ( svg ) . toBeDefined ( ) ;
253+ expect ( svg . attr ( 'viewBox' ) ) . toBe ( '0 0 1000 1000' ) ;
254+ var path = svg . select ( 'path' ) ;
255+ expect ( path . attr ( 'd' ) ) . toBeDefined ( ) ;
256+ expect ( path . attr ( 'transform' ) ) . toEqual ( 'matrix(1 0 0 -1 0 850)' ) ;
257+ } ) ;
258+
259+ it ( 'with the spikeline icon' , function ( ) {
260+ var modeBar = createModeBar ( getMockGraphInfo ( ) , [ [
261+ {
262+ name : 'some button' ,
263+ click : noop ,
264+ icon : Plotly . Icons . spikeline
265+ }
266+ ] ] ) ;
267+
268+ var svg = getIconSvg ( modeBar ) ;
269+ expect ( svg ) . toBeDefined ( ) ;
270+ expect ( svg . attr ( 'viewBox' ) ) . toBe ( '0 0 1000 1000' ) ;
271+ var path = svg . select ( 'path' ) ;
272+ expect ( path . attr ( 'd' ) ) . toBeDefined ( ) ;
273+ expect ( path . attr ( 'transform' ) ) . toEqual ( 'matrix(1.5 0 0 -1.5 0 850)' ) ;
274+ } ) ;
275+
276+ it ( 'with the legacy spikelines button config' , function ( ) {
277+ var modeBar = createModeBar ( getMockGraphInfo ( ) , [ [
278+ {
279+ name : 'toggleSpikelines' ,
280+ attr : '_cartesianSpikesEnabled' ,
281+ val : 'on' ,
282+ click : noop ,
283+ icon : {
284+ width : 1000 ,
285+ path : 'M512 409c0-57-46-104-103-104-57 0-104 47-104 104 0 57 47 103 104 103 57 0 103-46 103-103z m-327-39l92 0 0 92-92 0z m-185 0l92 0 0 92-92 0z m370-186l92 0 0 93-92 0z m0-184l92 0 0 92-92 0z' ,
286+ ascent : 850 ,
287+ descent : - 150
288+ }
289+ }
290+ ] ] ) ;
291+
292+ var svg = getIconSvg ( modeBar ) ;
293+ expect ( svg ) . toBeDefined ( ) ;
294+ expect ( svg . attr ( 'viewBox' ) ) . toBe ( '0 0 1000 1000' ) ;
295+ var path = svg . select ( 'path' ) ;
296+ expect ( path . attr ( 'd' ) ) . toBeDefined ( ) ;
297+ expect ( path . attr ( 'transform' ) ) . toEqual ( 'matrix(1.5 0 0 -1.5 0 850)' ) ;
298+ } ) ;
299+ } ) ;
139300 } ) ;
140301
141302 describe ( 'modeBar.removeAllButtons' , function ( ) {
0 commit comments