morris.js - Documentation

What is Morris.js?

Morris.js is a relatively lightweight JavaScript library that produces statistical graphs directly in the browser using the HTML5 <canvas> element. It’s built on top of Raphael.js, leveraging its capabilities for vector graphics rendering. Morris.js excels at creating clean, simple charts suitable for quickly visualizing data within web applications. It supports several chart types, including line charts, bar charts, area charts, and donut charts. While no longer actively maintained, it remains a viable option for projects where its features are sufficient and its simplicity is beneficial.

Why Use Morris.js?

Morris.js offers several advantages:

Setting up Morris.js

To use Morris.js, you’ll need to include the necessary JavaScript and CSS files in your HTML document. You can download these files from the original repository (though note that it is no longer actively maintained) or use a CDN. Typically, this involves adding the following lines within the <head> section of your HTML:

<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>

Remember to replace the URLs with the correct paths if you download the files locally.

Basic Example

This example creates a simple line chart showing some sample data:

<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
</head>
<body>
<div id="myChart"></div>

<script>
  Morris.Line({
    element: 'myChart',
    data: [
      { year: '2008', value: 20 },
      { year: '2009', value: 10 },
      { year: '2010', value: 5 },
      { year: '2011', value: 15 },
      { year: '2012', value: 25 }
    ],
    xkey: 'year',
    ykeys: ['value'],
    labels: ['Value']
  });
</script>
</body>
</html>

This code creates a line chart with the ‘year’ as the x-axis and ‘value’ as the y-axis. Remember that you’ll need a <div> element with the ID “myChart” to hold the chart. This example demonstrates the basic structure of a Morris.js chart configuration. Refer to the documentation for more advanced options and chart types.

Chart Types

Line Charts

Line charts in Morris.js are used to display data points connected by straight lines. They are ideal for showing trends over time or other continuous variables.

Key Options:

Example:

Morris.Line({
  element: 'myLineChart',
  data: [
    { year: '2018', value: 20 },
    { year: '2019', value: 15 },
    { year: '2020', value: 25 }
  ],
  xkey: 'year',
  ykeys: ['value'],
  labels: ['Value']
});

Bar Charts

Bar charts in Morris.js display data as horizontal or vertical bars, making it easy to compare values across different categories.

Key Options:

The options are largely the same as for line charts, with the exception that the visual representation changes to bars. The barColors option allows customization of the bar colors.

Example:

Morris.Bar({
  element: 'myBarChart',
  data: [
    { month: 'Jan', sales: 20 },
    { month: 'Feb', sales: 15 },
    { month: 'Mar', sales: 25 }
  ],
  xkey: 'month',
  ykeys: ['sales'],
  labels: ['Sales']
});

Area Charts

Area charts are similar to line charts, but the area between the line and the x-axis is filled, providing a visual representation of the cumulative value.

Key Options:

The options are largely identical to line charts, with the visual representation changing to a filled area. The fillOpacity option can control the opacity of the filled area.

Example:

Morris.Area({
  element: 'myAreaChart',
  data: [
    { year: '2018', value: 20 },
    { year: '2019', value: 15 },
    { year: '2020', value: 25 }
  ],
  xkey: 'year',
  ykeys: ['value'],
  labels: ['Value']
});

Donut Charts

Donut charts are used to display proportions or percentages of different categories within a whole.

Key Options:

Example:

Morris.Donut({
  element: 'myDonutChart',
  data: [
    {label: "A", value: 30},
    {label: "B", value: 20},
    {label: "C", value: 50}
  ]
});

Stacked Bar Charts

Stacked bar charts display multiple datasets within the same bar, showing the contribution of each dataset to the total value. This is achieved by using multiple ykeys and labels in the chart options.

Key Options:

Uses the same core options as bar charts, but with multiple ykeys to represent the stacked data series.

Example:

Morris.Bar({
  element: 'myStackedBarChart',
  data: [
    {x: '2018', a: 10, b: 20},
    {x: '2019', a: 15, b: 15},
    {x: '2020', a: 20, b: 10}
  ],
  xkey: 'x',
  ykeys: ['a', 'b'],
  labels: ['Series A', 'Series B'],
  stacked: true // This option makes the chart stacked
});

Remember that stacked: true is crucial for creating a stacked bar chart.

Data Handling

Data Formats

Morris.js expects data in a simple JSON format. The structure depends on the chart type, but generally involves an array of objects. Each object represents a single data point. The xkey option specifies the property used for the x-axis (often representing time or categories), and ykeys specifies one or more properties for the y-axis values.

Common Structure:

[
  {x: '2023-01-01', y: 10},
  {x: '2023-01-08', y: 15},
  {x: '2023-01-15', y: 20}
]

In this example:

For charts with multiple y-axis lines, you’ll need multiple ykeys, each representing a different dataset:

[
  {x: '2023-01-01', a: 10, b: 5},
  {x: '2023-01-08', a: 15, b: 10},
  {x: '2023-01-15', a: 20, b: 15}
]

Here a and b are separate ykeys. You must also specify the labels option to provide labels for each of these ykeys.

Donut charts use a slightly different format where each object contains a label and a value property:

[
  {label: "Category A", value: 40},
  {label: "Category B", value: 60}
]

Data Preprocessing

While Morris.js handles data relatively well, preprocessing your data before passing it to the chart can significantly improve performance and code readability. This is especially true for large datasets or data requiring transformations.

Common preprocessing tasks include:

Handling Large Datasets

Morris.js is not optimized for extremely large datasets. For very large datasets (thousands or more data points), consider these strategies:

Dynamic Data Updates

Morris.js allows for dynamic updates of chart data. Instead of recreating the chart each time the data changes, you can use the setData method to update the chart with new data:

var chart = Morris.Line({
  // chart options...
});

//Later, to update the chart:
var newData = [ /* your new data */ ];
chart.setData(newData);

This approach is much more efficient than completely redrawing the chart, especially with frequent updates. This method updates the chart’s underlying data and redraws only the necessary parts. The chart will be redrawn with the changes you give it.

Customization

Chart Titles and Labels

Morris.js doesn’t directly support adding chart titles in the same way some other charting libraries do. However, you can achieve a similar effect by adding a separate heading or <p> element above or below the chart’s container. You can control axis labels using the labels option (for y-axis labels) and by careful selection of your xkey data which will form the x-axis labels. For more sophisticated title placement, you would need to use CSS and potentially modify the surrounding HTML.

Axis Configuration

You have limited control over axis configuration in Morris.js. The x-axis labels are primarily determined by your data’s xkey values. For the y-axis, while you can’t directly specify specific ranges or intervals, the library automatically scales the axis based on your data. You don’t have direct control over things like tick mark intervals or axis labels’ formatting or rotation.

Grid Lines and Background

Morris.js automatically includes grid lines, but you can customize their appearance (though options are limited). You can’t remove them entirely without modifying the source code directly. The background color is determined by the CSS styles applied to the chart container. You can customize this by setting the background color of the div element containing your chart, or using CSS to style the chart specifically. You can only control the grid’s visibility indirectly.

Colors and Themes

You can customize the colors of various chart elements, particularly bar and line charts, using the barColors (for bar charts) or by specifying individual colors for each line in a line chart by setting the lineColors array. There’s no built-in theming system; customization primarily involves adjusting these color options. You can use any valid CSS color values (hex codes, named colors, RGB, etc.).

Tooltips and Hover Effects

Morris.js provides built-in tooltips that appear when hovering over data points. You have little direct control over their appearance or content. They display the x-axis value and the corresponding y-axis value(s). To change their appearance, you would generally need to modify the Morris.js source code itself or wrap it within a custom CSS style.

Customizing Legends

Legends (if applicable to the chart type) are automatically generated by Morris.js, and there is very limited control over their appearance or positioning. You cannot easily customize their location, style, or content without making extensive modifications to the library’s source code. Consider adding separate legend elements next to the charts if you need more extensive customization. You have no direct ability to modify what is contained in the legend itself, aside from the data you feed to the chart.

Advanced Techniques

Event Handling

Morris.js offers limited built-in event handling. While it doesn’t provide extensive event APIs like some other libraries, you can indirectly interact with chart events through the underlying Raphael.js library. This requires a deeper understanding of Raphael.js’s event system and may involve manipulating the chart’s elements directly using JavaScript. This approach is not officially supported and may break with library updates.

There are no documented public events directly exposed by Morris.js that you can hook into for actions like click or hover on chart elements.

Animations and Transitions

Morris.js includes basic animations for chart rendering. These animations are built-in and cannot be customized or disabled directly through the options. The animations are generally smooth transitions when the chart is initially drawn or data is updated using setData. There are no options to configure animation speed or effects. The default animation style is fairly standard and may not be configurable to a fine degree.

Integrating with Other Libraries

Integrating Morris.js with other JavaScript libraries is generally straightforward. Since it renders within a standard <div> element, it can coexist with other UI elements. However, be mindful of potential conflicts if other libraries also modify the DOM where the chart is rendered. Ensure proper sequencing of library inclusion in your HTML to avoid unexpected behavior. If other libraries manipulate the DOM element holding the chart after Morris.js renders, this may cause the chart to be redrawn or malfunction.

Using Morris.js alongside libraries that handle data manipulation (like data tables or data grids) is common. Simply prepare your data using these external tools, and then feed the appropriately formatted data to Morris.js.

Troubleshooting Common Issues

Several common issues can arise when working with Morris.js:

Remember that Morris.js is no longer actively maintained, so finding solutions for complex problems or obtaining support may be difficult. Using a more actively developed charting library might be a better choice for new projects.

Best Practices

Performance Optimization

Morris.js, while generally efficient for moderately sized datasets, can become slow with very large amounts of data. To optimize performance:

Accessibility Considerations

Morris.js doesn’t have built-in accessibility features. To improve accessibility:

Given the lack of direct accessibility support in Morris.js, you will be highly reliant on adding your own accommodations.

Maintaining Code Readability

To maintain code readability when using Morris.js:

Following these suggestions will dramatically improve long term maintainability of any code that uses Morris.js.

Examples and Case Studies

Note: Due to the age and lack of active maintenance of Morris.js, finding readily available, extensive, and up-to-date examples online can be challenging. The examples below use the basic structure and concepts. You may need to adapt them based on any updates or changes in available versions of Morris.js or its dependencies. Always consult the (potentially outdated) official documentation for the most accurate information regarding available options.

Simple Line Chart Example

This example demonstrates a basic line chart showing website visits over a week:

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css">
  <script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
</head>
<body>
<div id="line-chart"></div>

<script>
  Morris.Line({
    element: 'line-chart',
    data: [
      { day: 'Mon', visits: 10 },
      { day: 'Tue', visits: 15 },
      { day: 'Wed', visits: 20 },
      { day: 'Thu', visits: 12 },
      { day: 'Fri', visits: 25 },
      { day: 'Sat', visits: 18 },
      { day: 'Sun', visits: 22 }
    ],
    xkey: 'day',
    ykeys: ['visits'],
    labels: ['Visits']
  });
</script>
</body>
</html>

Complex Bar Chart Example

This example shows a stacked bar chart comparing sales of different products across multiple regions:

javascript Morris.Bar({ element: 'bar-chart', data: [ { region: 'North', productA: 30, productB: 20, productC: 15 }, { region: 'South', productA: 25, productB: 35, productC: 10 }, { region: 'East', productA: 18, productB: 22, productC: 28 }, { region: 'West', productA: 35, productB: 15, productC: 22 } ], xkey: 'region', ykeys: ['productA', 'productB', 'productC'], labels: ['Product A', 'Product B', 'Product C'], stacked: true }); Remember to include the necessary <div> with the ID bar-chart.

Interactive Donut Chart Example

While Morris.js doesn’t offer highly interactive features, you can create a basic donut chart that displays data:

javascript Morris.Donut({ element: 'donut-chart', data: [ {label: "Category A", value: 40}, {label: "Category B", value: 60} ] }); Again, ensure you have a <div> with the ID donut-chart.

Real-World Application Example

A real-world application might involve displaying website analytics. Imagine a dashboard showing daily user engagement metrics. You could use line charts for daily active users and unique visitors, bar charts to compare user demographics, and donut charts to show user acquisition sources. The data would be fetched from a backend API (e.g., using AJAX) and dynamically updated using the setData method. This would require integration with backend systems and potentially additional JavaScript frameworks for handling data fetching and updates. The example provided earlier of dynamic data updates demonstrates the basic concept. A full “real-world” example would require significant additional code beyond the scope of a simple example here. Remember that the level of interactivity in such a system would be quite limited with Morris.js.

API Reference

Note: The Morris.js API is relatively limited and the documentation is outdated. The information below represents the general structure and common options available; however, always check the (potentially outdated) original documentation for the most accurate and up-to-date details. The lack of active maintenance means that some options might not behave as expected or might be entirely unavailable depending on the version you’re using.

Chart Constructor Options

These options are passed to the chart constructor (e.g., Morris.Line, Morris.Bar, etc.) to configure the chart’s overall appearance and behavior. Many options are shared across different chart types, but some are specific to certain chart types.

Data Options

These options directly relate to how the chart handles and displays the data:

Element Options

These options control the styling and appearance of specific chart elements:

Methods

Morris.js charts expose only a limited number of methods:

Remember that the options and their exact behaviors might vary slightly depending on the specific chart type and the version of Morris.js you are using. Always refer to (the potentially outdated) official documentation and test extensively. The API is not very rich in functionality.