Button Events in JavaScript

How to bind callback functions to custom buttons in D3.js-based JavaScript charts.


New to Plotly?

Plotly is a free and open-source graphing library for JavaScript. We recommend you read our Getting Started guide for the latest installation or upgrade instructions, then move on to our Plotly Fundamentals tutorials or dive straight in to some Basic Charts tutorials.

The restyle method should be used when modifying the data and data attributes of the graph This example demonstrates how to update a single data attribute: chart type with the restyle method.

d3.csv('https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv', function(err, rows){
function unpack(rows, key) {
  return rows.map(function(row) { return row[key]; });
}
var z_data=[ ]
for(i=0;i<24;i++)
{
  z_data.push(unpack(rows,i));
}

var data = [{
        z: z_data,
        type:'surface',
        colorscale:'Viridis'
}]

var updatemenus=[
    {
        buttons: [
            {
                args: ['type', 'surface'],
                label: '3D Surface',
                method: 'restyle'
            },
            {
                args: ['type', 'heatmap'],
                label:'Heatmap',
                method:'restyle'
            }
        ],
        direction: 'left',
        pad: {'r': 10, 't': 10},
        showactive: true,
        type: 'buttons',
        x: 0.1,
        xanchor: 'left',
        y: 1.1,
        yanchor: 'top'
    }
]

var annotations = [
    {
      text: 'Trace type:',
      x: 0,
      y: 1.085,
      yref: 'paper',
      align: 'left',
      showarrow: false
    }
]

var layout = {
    width: 800,
    height: 900,
    autosize: false,
    margin: {t: 0, b: 0, l: 0, r: 0},
    updatemenus: updatemenus,
    annotations: annotations,
    scene: {
        xaxis:{
            gridcolor: 'rgb(255, 255, 255)',
            zerolinecolor: 'rgb(255, 255, 255)',
            showbackground: true,
            backgroundcolor:'rgb(230, 230,230)'
        },
        yaxis: {
            gridcolor: 'rgb(255, 255, 255)',
            zerolinecolor: 'rgb(255, 255, 255)',
            showbackground: true,
            backgroundcolor: 'rgb(230, 230, 230)'
        },
        zaxis: {
            gridcolor: 'rgb(255, 255, 255)',
            zerolinecolor: 'rgb(255, 255, 255)',
            showbackground: true,
            backgroundcolor: 'rgb(230, 230,230)'
        },
        aspectratio: {x: 1, y: 1, z: 0.7},
        aspectmode: 'manual'
  }
}


Plotly.newPlot("myDiv", data, layout);

});

This example demonstrates how to use a restyle button to update single attributes by passing a two element array to a button's args attribute or update multiple attributes at the same time by passing an array containing an object.

d3.csv('https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv', function(err, rows){
function unpack(rows, key) {
  return rows.map(function(row) { return row[key]; });
}

var button_layer_1_height = 1.12
var button_layer_2_height = 1.0
var annotation_offset = 0.04

var z_data=[ ]
for(i=0;i<24;i++)
{
  z_data.push(unpack(rows,i));
}

var data = [{
        z: z_data,
        type:'surface',
        colorscale:'Viridis'
}]

var updatemenus=[
    {
        buttons: [
            {
                args: ['type', 'surface'],
                label: '3D Surface',
                method: 'restyle'
            },
            {
                args: ['type', 'heatmap'],
                label:'Heatmap',
                method:'restyle'
            },
            {
                args: ['type', 'contour'],
                label:'Contour',
                method:'restyle'
            }
        ],
        direction: 'left',
        pad: {'r': 10, 't': 10},
        showactive: true,
        type: 'buttons',
        x: 0.15,
        xanchor: 'left',
        y: button_layer_2_height,
        yanchor: 'top'
    },
    {
        buttons: [
            {
                args: ['reversescale', true],
                label: 'Reverse',
                method: 'restyle'
            },
            {
                args: ['reversescale', false],
                label:'Undo Reverse',
                method:'restyle'
            }
        ],
        direction: 'down',
        pad: {'r': 10, 't': 10},
        showactive: true,
        type: 'dropdown',
        x: 0.56,
        xanchor: 'left',
        y: button_layer_2_height,
        yanchor: 'top'
    },
    {
        buttons: [
            {
                args: [{'contours.showlines':false, 'type':'contour'}],
                label: 'Hide lines',
                method: 'restyle'
            },
            {
                args: [{'contours.showlines':true, 'type':'contour'}],
                label:'Show lines',
                method:'restyle'
            }
        ],
        direction: 'down',
        pad: {'r': 10, 't': 10},
        showactive: true,
        type: 'dropdown',
        x: 0.78,
        xanchor: 'left',
        y: button_layer_2_height,
        yanchor: 'top'
    },
    {
        buttons: [
            {
                args: ['colorscale', 'Viridis'],
                label: 'Viridis',
                method: 'restyle'
            },
            {
                args: ['colorscale', 'Electric'],
                label:'Electric',
                method:'restyle'
            },
            {
                args: ['colorscale', 'Earth'],
                label:'Earth',
                method:'restyle'
            },
            {
                args: ['colorscale', 'Hot'],
                label:'Hot',
                method:'restyle'
            },
            {
                args: ['colorscale', 'Jet'],
                label:'Jet',
                method:'restyle'
            },
            {
                args: ['colorscale', 'Portland'],
                label:'Portland',
                method:'restyle'
            },
            {
                args: ['colorscale', 'Rainbow'],
                label:'Rainbow',
                method:'restyle'
            },
            {
                args: ['colorscale', 'Blackbody'],
                label:'Blackbody',
                method:'restyle'
            },

            {
                args: ['colorscale', 'Cividis'],
                label:'Cividis',
                method:'restyle'
            }
        ],
        direction: 'left',
        pad: {'r': 10, 't': 10},
        showactive: true,
        type: 'buttons',
        x: 0.15,
        xanchor: 'left',
        y: button_layer_1_height,
        yanchor: 'top'
    },
]

var annotations = [
    {
      text: 'Trace type:',
      x: 0,
      y: button_layer_2_height - annotation_offset,
      yref: 'paper',
      align: 'left',
      showarrow: false
    },
    {
      text: 'Colorscale:',
      x: 0,
      y: button_layer_1_height - annotation_offset,
      yref: 'paper',
      align: 'left',
      showarrow: false
    },
]

var layout = {
    margin: {t: 0, b: 0, l: 0, r: 0},
    updatemenus: updatemenus,
    annotations: annotations,
    scene: {
        xaxis:{
            gridcolor: 'rgb(255, 255, 255)',
            zerolinecolor: 'rgb(255, 255, 255)',
            showbackground: true,
            backgroundcolor:'rgb(230, 230,230)'
        },
        yaxis: {
            gridcolor: 'rgb(255, 255, 255)',
            zerolinecolor: 'rgb(255, 255, 255)',
            showbackground: true,
            backgroundcolor: 'rgb(230, 230, 230)'
        },
        zaxis: {
            gridcolor: 'rgb(255, 255, 255)',
            zerolinecolor: 'rgb(255, 255, 255)',
            showbackground: true,
            backgroundcolor: 'rgb(230, 230,230)'
        },
        aspectratio: {x: 1, y: 1, z: 0.7},
        aspectmode: 'manual'
  }
}


Plotly.newPlot("myDiv", data, layout);

});

The relayout method should be used when modifying the layout attributes of the graph. Update One Layout Attribute This example demonstrates how to update a layout attribute: chart type with the relayout method.

d3.csv('https://raw.githubusercontent.com/plotly/datasets/master/normal-clusters.csv', function(err, rows){
function unpack(rows, key) {
  return rows.map(function(row) { return parseFloat(row[key]); });
}

var button_layer_height = 1.2
var x0 = unpack(rows,'x0')
var x1 = unpack(rows,'x1')
var x2 = unpack(rows,'x2')
var y0 = unpack(rows,'y0')
var y1 = unpack(rows,'y1')
var y2 = unpack(rows,'y2')

var data = [{
    x: x0,
    y: y0,
    mode: 'markers',
    marker: {color: '#835AF1'}
  },
  {
    x: x1,
    y: y1,
    mode: 'markers',
    marker: {color: '#7FA6EE'}
  },
  {
    x: x2,
    y: y2,
    mode: 'markers',
    marker: {color: '#B8F7D4'}
  },

]

var cluster0 = {type: 'circle',
                 xref: 'x', yref: 'y',
                 x0: Math.min(...x0), y0: Math.min(...y0),
                 x1: Math.max(...x0), y1: Math.max(...y0),
                 opacity: 0.25,
                 line: {color: '#835AF1'},
                 fillcolor: '#835AF1'}

var cluster1 = {type: 'circle',
                 xref: 'x', yref: 'y',
                 x0: Math.min(...x1), y0: Math.min(...y1),
                 x1: Math.max(...x1), y1: Math.max(...y1),
                 opacity: 0.25,
                 line: {color: '#7FA6EE'},
                 fillcolor: '#7FA6EE'}

var cluster2 = {type: 'circle',
                 xref: 'x', yref: 'y',
                 x0: Math.min(...x2), y0: Math.min(...y2),
                 x1: Math.max(...x2), y1: Math.max(...y2),
                 opacity: 0.25,
                 line: {color: '#B8F7D4'},
                 fillcolor: '#B8F7D4'}

var updatemenus=[
    {
        buttons: [
            {
                args: ['shapes', []],
                label: 'None',
                method: 'relayout'
            },
            {
                args: ['shapes', [cluster0]],
                label: 'Cluster 0',
                method: 'relayout'
            },
            {
                args: ['shapes', [cluster1]],
                label: 'Cluster 1',
                method: 'relayout'
            },
            {
                args: ['shapes', [cluster2]],
                label: 'Cluster 2',
                method: 'relayout'
            },
            {
                args: ['shapes', [cluster0, cluster1, cluster2]],
                label: 'All',
                method: 'relayout'
            },
        ],
        direction: 'left',
        pad: {'r': 10, 't': 10},
        showactive: true,
        type: 'buttons',
        x: 0.1,
        xanchor: 'left',
        y: button_layer_height,
        yanchor: 'top'
    },

]

var layout = {
    updatemenus: updatemenus,
    showlegend: false
}


Plotly.newPlot("myDiv", data, layout);

});

The update method should be used when modifying the data and layout sections of the graph. This example demonstrates how to update which traces are displayed while simulaneously updating layout attributes such as the chart title and annotations.

d3.csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv', function(err, rows){
function unpack(rows, key) {
  return rows.map(function(row) { return row[key]; });
}

const arrAvg = arr => arr.reduce((a,b) => a + b, 0) / arr.length

var button_layer_2_height = 1.2
var high = unpack(rows, 'AAPL.High').map(x => parseFloat(x))
var low = unpack(rows, 'AAPL.Low').map(x => parseFloat(x))
var date = unpack(rows, 'Date')


var high_ave = arrAvg(high)
var high_max = Math.max(...high)
var low_ave = arrAvg(low)
var low_min = Math.min(...low)

var data = [{
    x: date,
    y: high,
    mode: 'lines',
    name: 'High',
    marker: {color: '#33CFA5'}
  },
  {
    x: date,
    y: date.map(a => high_ave),
    mode: 'lines',
    name: 'Low Average',
    line: {color: '#33CFA5', dash: 'dash'},
    visible: false
  },
  {
    x: date,
    y: low,
    name: 'Low',
    mode: 'lines',
    marker: {color: '#F06A6A'}
  },
  {
    x: date,
    y: date.map(a => low_ave),
    mode: 'lines',
    name: 'High Average',
    visible: false,
    line: {color: '#F06A6A', dash: 'dash'}
  },

]

var high_annotations = [
    {
      text: 'High Average:<br>' + high_ave.toFixed(2),
      x: '2016-03-01',
      y: high_ave,
      yref: 'y', xref: 'x',
      ay: -40, ax: 0
    },
    {
      text: 'High Max:<br>' + high_max.toFixed(2),
      x: date[high.indexOf(high_max)],
      y: high_max,
      yref: 'y', xref: 'x',
      ay: -40, ax: 0
    },
]

var low_annotations = [{
      text: 'Low Average:<br>' + low_ave.toFixed(2),
      x: '2015-05-01',
      y: low_ave,
      yref: 'y', xref: 'x',
      ay: 40, ax: 0
    },
    {
      text: 'Low Min:<br>' + low_min.toFixed(2),
      x: date[low.indexOf(low_min)],
      y: low_min,
      yref: 'y', xref: 'x',
      ay: 40, ax: 0
    }
 ]

var updatemenus=[
    {
        buttons: [
            {
                args: [{'visible': [true, true, false, false]},
                       {'title': 'Yahoo High',
                        'annotations': high_annotations}],
                label: 'High',
                method: 'update'
            },
            {
                args: [{'visible': [false, false, true, true,]},
                       {'title': 'Yahoo Low',
                        'annotations': low_annotations}],
                label: 'Low',
                method: 'update'
            },
            {
                args: [{'visible': [true, true, true, true,]},
                       {'title': 'Yahoo',
                        'annotations': [...low_annotations, ...high_annotations]}],
                label: 'Both',
                method: 'update'
            },
            {
                args: [{'visible': [true, false, true, false,]},
                       {'title': 'Yahoo',
                        'annotations': []}],
                label: 'Reset',
                method: 'update'
            },

        ],
        direction: 'left',
        pad: {'r': 10, 't': 10},
        showactive: true,
        type: 'buttons',
        x: 0.1,
        xanchor: 'left',
        y: button_layer_2_height,
        yanchor: 'top'
    },

]

var layout = {
  title: {
      text: 'Yahoo'
  },
  updatemenus: updatemenus,
  showlegend: false
}


Plotly.newPlot("myDiv", data, layout);

});

Refer to our animation docs: https://plotly.com/javascript/#animations for examples on how to use the animate method with Plotly buttons.

When adding buttons to Plotly charts, users have the option of styling the color, font, padding, and position of the buttons. The example below demonstrates how to apply different styling options. See all updatemenus styling attributes here: https://plotly.com/javascript/reference/layout/#layout-updatemenus.

d3.csv('https://raw.githubusercontent.com/plotly/datasets/master/api_docs/mt_bruno_elevation.csv', function(err, rows){
function unpack(rows, key) {
  return rows.map(function(row) { return row[key]; });
}

var button_layer_1_height = 1.12
var button_layer_2_height = 1.0
var annotation_offset = 0.04

var z_data=[ ]
for(i=0;i<24;i++)
{
  z_data.push(unpack(rows,i));
}

var data = [{
        z: z_data,
        type:'surface',
        colorscale:'Viridis'
}]

var updatemenus=[
    {
        buttons: [
            {
                args: ['type', 'surface'],
                label: '3D Surface',
                method: 'restyle'
            },
            {
                args: ['type', 'heatmap'],
                label:'Heatmap',
                method:'restyle'
            },
            {
                args: ['type', 'contour'],
                label:'Contour',
                method:'restyle'
            }
        ],
        direction: 'left',
        pad: {'r': 10, 't': 10},
        showactive: true,
        type: 'buttons',
        x: 0.15,
        xanchor: 'left',
        y: button_layer_2_height,
        yanchor: 'top',
        font: {color: '#5072a8'}
    },
    {
        buttons: [
            {
                args: ['reversescale', true],
                label: 'Reverse',
                method: 'restyle'
            },
            {
                args: ['reversescale', false],
                label:'Undo Reverse',
                method:'restyle'
            }
        ],
        direction: 'down',
        pad: {'r': 10, 't': 10},
        showactive: true,
        type: 'dropdown',
        x: 0.56,
        xanchor: 'left',
        y: button_layer_2_height,
        yanchor: 'top',
        active: 1,
        font: {color: '#5072a8'}
    },
    {
        buttons: [
            {
                args: [{'contours.showlines':false, 'type':'contour'}],
                label: 'Hide lines',
                method: 'restyle'
            },
            {
                args: [{'contours.showlines':true, 'type':'contour'}],
                label:'Show lines',
                method:'restyle'
            }
        ],
        direction: 'down',
        pad: {'r': 10, 't': 10},
        showactive: true,
        type: 'dropdown',
        x: 0.78,
        xanchor: 'left',
        y: button_layer_2_height,
        yanchor: 'top',
        font: {color: '#5072a8'}
    },
    {
        buttons: [
            {
                args: ['colorscale', 'Viridis'],
                label: 'Viridis',
                method: 'restyle'
            },
            {
                args: ['colorscale', 'Electric'],
                label:'Electric',
                method:'restyle'
            },
            {
                args: ['colorscale', 'Earth'],
                label:'Earth',
                method:'restyle'
            },
            {
                args: ['colorscale', 'Hot'],
                label:'Hot',
                method:'restyle'
            },
            {
                args: ['colorscale', 'Jet'],
                label:'Jet',
                method:'restyle'
            },
            {
                args: ['colorscale', 'Portland'],
                label:'Portland',
                method:'restyle'
            },
            {
                args: ['colorscale', 'Rainbow'],
                label:'Rainbow',
                method:'restyle'
            },
            {
                args: ['colorscale', 'Blackbody'],
                label:'Blackbody',
                method:'restyle'
            },

            {
                args: ['colorscale', 'Cividis'],
                label:'Cividis',
                method:'restyle'
            }
        ],
        direction: 'left',
        pad: {'r': 10, 't': 10},
        showactive: true,
        type: 'buttons',
        x: 0.15,
        xanchor: 'left',
        y: button_layer_1_height,
        yanchor: 'top',
        active: 1,
        bgcolor: '#aaaaaa',
        bordercolor: '#FFFFFF'
    },
]

var annotations = [
    {
      text: 'Trace type:',
      x: 0,
      y: button_layer_2_height - annotation_offset,
      yref: 'paper',
      align: 'left',
      showarrow: false
    },
    {
      text: 'Colorscale:',
      x: 0,
      y: button_layer_1_height - annotation_offset,
      yref: 'paper',
      align: 'left',
      showarrow: false
    },
]

var layout = {
    paper_bgcolor: 'black',
    margin: {t: 0, b: 0, l: 0, r: 0},
    updatemenus: updatemenus,
    annotations: annotations,
    scene: {
        bgcolor: 'black',
        aspectratio: {x: 1, y: 1, z: 0.7},
        aspectmode: 'manual'
  }
}


Plotly.newPlot("myDiv", data, layout);

});