diff --git a/README.txt b/README.txt
index 33a44744bda070fce0676c7dd2e05416803451f8..9290dc70009770fc136ad15b8985a6f8b4bdb823 100644
--- a/README.txt
+++ b/README.txt
@@ -88,6 +88,34 @@ Tip: You may find it easier to start with a "Table" display and convert it to a
 chart display after setting up the data. It can be easier to visualize what
 the result of the chart will be if it's been laid out in a table first.
 
+Creating Multiple Series and Combo Charts in the UI
+---------------------------------------------------
+
+When using Views to build your charts, you may find it difficult to retrieve
+more than a single set of data generated by a COUNT() query. For example if you
+wanted to retrieve the age of all your site users, but display "Male" and
+"Female" values in a column chart at the same time, constructing the underlying
+table of data is quite difficult.
+
+To solve this problem, you can combine multiple charts on top of each other. The
+"parent" chart provides the global information, such as the height, width,
+title, and other properties. Charts that are "children" provide only data and
+(optionally) a secondary axis. After you've assembled the first series of data
+in your chart according to the instructions in the "Creating Charts in the UI"
+section, add a new display to the same view of the type "Chart Add-on". The
+"Chart Add-on" type is added the same way you would add a new Page or Block
+display, from the "+ Add" menu at the top of the view configuration.
+
+After this new display has been added, find the setting for "Combine with parent
+chart" and change this value to point at the parent chart you have already
+assembled. Then adjust the settings for the child chart to pull in different
+data (often by overriding the filter settings). Now you can go back to your
+parent display, and see that the results from the child chart have been
+merged into the results from the parent chart. You can even use this approach
+to combine different types of charts, such as a line chart over the top of
+a column chart. Note that not all chart types can be combined together and
+invalid combinations may cause your chart to throw errors.
+
 Create Charts through the API
 -----------------------------
 
diff --git a/charts.info b/charts.info
index 193d8a986f3d146ef9af5204f0183535b6446bce..2bb80e779529b4479917e678d922ffea8b40834f 100644
--- a/charts.info
+++ b/charts.info
@@ -5,3 +5,4 @@ core = 7.x
 php = 5.2
 
 files[] = views/charts_plugin_style_chart.inc
+files[] = views/charts_plugin_display_chart.inc
diff --git a/js/charts.admin.js b/js/charts.admin.js
index 74c2f0946cb94ab83f208fdb8d55b631a1fcf4fd..af616524f125da38dea5d0030531f90edc3695c7 100644
--- a/js/charts.admin.js
+++ b/js/charts.admin.js
@@ -10,7 +10,9 @@ Drupal.behaviors.chartsAdmin.attach = function(context, settings) {
   $(context).find('.form-radios.chart-type-radios').once('charts-axis-inverted-processed', function() {
 
     // Manually attach collapsible fieldsets first.
-    Drupal.behaviors.collapse.attach(context, settings);
+    if (Drupal.behaviors.collapse) {
+      Drupal.behaviors.collapse.attach(context, settings);
+    }
 
     var xAxisLabel = $('fieldset.chart-xaxis .fieldset-title').html();
     var yAxisLabel = $('fieldset.chart-yaxis .fieldset-title').html();
diff --git a/views/charts.views.inc b/views/charts.views.inc
index d4e54a96382070fc7a70f4e60f84528c523b6448..eaf21a2f323b15b0595a28756e14faeedfe9735b 100644
--- a/views/charts.views.inc
+++ b/views/charts.views.inc
@@ -23,6 +23,22 @@ function charts_views_plugins() {
     'uses grouping' => FALSE,
     'type' => 'normal',
   );
+  $plugins['style']['chart_extension'] = $plugins['style']['chart'];
+  $plugins['style']['chart_extension']['type'] = 'chart';
+
+  $plugins['display']['chart'] = array(
+    'title' => t('Chart add-on'),
+    'admin' => t('Chart add-on'),
+    'help' => t('Add chart data to a new or existing chart.'),
+    'handler' => 'charts_plugin_display_chart',
+    'theme' => 'views_view',
+    'register theme' => FALSE,
+    'use ajax' => FALSE,
+    'use pager' => FALSE,
+    'use more' => FALSE,
+    'accept attachments' => FALSE,
+    'type' => 'chart',
+  );
 
   return $plugins;
 }
diff --git a/views/charts_plugin_display_chart.inc b/views/charts_plugin_display_chart.inc
new file mode 100644
index 0000000000000000000000000000000000000000..7d7bb29da08ca095105955ec879d618c9d97c978
--- /dev/null
+++ b/views/charts_plugin_display_chart.inc
@@ -0,0 +1,130 @@
+<?php
+/**
+ * @file
+ * Contains the Chart display type (similar to Page, Block, Attachment, etc.)
+ */
+
+/**
+ * Display plugin to attach multiple chart configurations to the same chart.
+ *
+ * @ingroup views_style_plugins
+ */
+class charts_plugin_display_chart extends views_plugin_display {
+  function get_style_type() {
+    return 'chart';
+  }
+
+  function option_definition() {
+    $options = parent::option_definition();
+
+    // Overrides of standard options.
+    $options['style_plugin']['default'] = 'chart_extension';
+    $options['row_plugin']['default'] = 'fields';
+    $options['defaults']['default']['style_plugin'] = FALSE;
+    $options['defaults']['default']['style_options'] = FALSE;
+    $options['defaults']['default']['row_plugin'] = FALSE;
+    $options['defaults']['default']['row_options'] = FALSE;
+
+    $options['parent_display'] = array('default' => '');
+    $options['inherit_yaxis'] = array('default' => '1');
+
+    return $options;
+  }
+
+  /**
+   * Provide the summary for page options in the views UI.
+   *
+   * This output is returned as an array.
+   */
+  function options_summary(&$categories, &$options) {
+    // It is very important to call the parent function here:
+    parent::options_summary($categories, $options);
+
+    $categories['chart'] = array(
+      'title' => t('Chart settings'),
+      'column' => 'second',
+      'build' => array(
+        '#weight' => -10,
+      ),
+    );
+
+    $parent_title = NULL;
+    $parent_display = $this->get_option('parent_display');
+    if (!empty($this->view->display[$parent_display])) {
+      $parent_title = check_plain($this->view->display[$parent_display]->display_title);
+    }
+    $options['parent_display'] = array(
+      'category' => 'chart',
+      'title' => t('Combine with parent chart'),
+      'value' => $parent_title ? $parent_title : t('None'),
+    );
+    $options['inherit_yaxis'] = array(
+      'category' => 'chart',
+      'title' => t('Axis settings'),
+      'value' => $this->get_option('inherit_yaxis') ? t('Use primary Y-axis') : t('Create secondary axis'),
+    );
+    
+  }
+
+  /**
+   * Provide the default form for setting options.
+   */
+  function options_form(&$form, &$form_state) {
+    // It is very important to call the parent function here:
+    parent::options_form($form, $form_state);
+
+    switch ($form_state['section']) {
+      case 'parent_display':
+        $form['#title'] .= t('Parent display');
+
+        // Filter down the list of displays to include only those that use
+        // the chart display style.
+        $display_options = array();
+        foreach ($this->view->display as $display_name => $display) {
+          if ($this->view->display[$display_name]->display_options['style_plugin'] === 'chart' && $display_name !== $this->view->current_display) {
+            $display_options[$display_name] = $this->view->display[$display_name]->display_title;
+          }
+        }
+        $form['parent_display'] = array(
+          '#title' => t('Parent display'),
+          '#type' => 'select',
+          '#options' => $display_options,
+          '#empty_option' => t('- None - '),
+          '#required' => TRUE,
+          '#default_value' => $this->get_option('parent_display'),
+          '#description' => t('Select a parent display onto which this chart will be overlaid. Only other displays using a "Chart" format are included here. This option may be used to create charts with several series of data or to create combination charts.'),
+        );
+        break;
+      case 'inherit_yaxis':
+        $form['#title'] .= t('Axis settings');
+        $form['inherit_yaxis'] = array(
+          '#title' => t('Y-Axis settings'),
+          '#type' => 'radios',
+          '#options' => array(
+            1 => t('Inherit primary of parent display'),
+            0 => t('Create a secondary axis'),
+          ),
+          '#default_value' => $this->get_option('inherit_yaxis'),
+          '#description' => t('In most charts, the X and Y axis from the parent display are both shared with each attached child chart. However, if this chart is going to use a different unit of measurement, a secondary axis may be added on the opposite side of the normal Y-axis.'),
+        );
+        break;
+
+    }
+  }
+
+  /**
+   * Perform any necessary changes to the form values prior to storage.
+   * There is no need for this function to actually store the data.
+   */
+  function options_submit(&$form, &$form_state) {
+    // It is very important to call the parent function here:
+    parent::options_submit($form, $form_state);
+    switch ($form_state['section']) {
+      case 'parent_display':
+      case 'inherit_yaxis':
+        $this->set_option($form_state['section'], $form_state['values'][$form_state['section']]);
+        break;
+    }
+  }
+}
+
diff --git a/views/charts_plugin_style_chart.inc b/views/charts_plugin_style_chart.inc
index 67758761281c4022ad6729e0adbbab24f0c414ec..cf27d28816635b3261e6d8a63e4eb211b29d3fdb 100644
--- a/views/charts_plugin_style_chart.inc
+++ b/views/charts_plugin_style_chart.inc
@@ -1,7 +1,7 @@
 <?php
 /**
  * @file
- * Contains the chart style plugin.
+ * Contains the Chart style (format) plugin (similar to Table, HTML List, etc.)
  */
 
 /**
@@ -24,6 +24,12 @@ class charts_plugin_style_chart extends views_plugin_style {
       $options[$default_key]['default'] = $default_value;
     }
 
+    // Remove the default setting for chart type so it can be inherited if this
+    // is a chart extension type.
+    if ($this->plugin_name === 'chart_extension') {
+      $options['type']['default'] = NULL;
+    }
+
     return $options;
   }
 
@@ -44,6 +50,27 @@ class charts_plugin_style_chart extends views_plugin_style {
     module_load_include('inc', 'charts', 'includes/charts.pages');
     $field_options = $this->display->handler->get_field_labels();
     $form = charts_settings_form($form, $this->options, $field_options, array('style_options'));
+
+    // Reduce the options if this is a chart extension.
+    if ($parent_display = $this->get_parent_chart_display()) {
+      $parent_chart_type = chart_get_type($parent_display->display_options['style_options']['type']);
+      if (empty($form['type']['#default_value'])) {
+        $form['type']['#default_value'] = $parent_display->display_options['style_options']['type'];
+      }
+
+      $form['type']['#description'] = empty($form['type']['#description']) ? '' : $form['type']['#description'] . ' ';
+      $form['type']['#description'] .= t('This chart will be combined with the parent display "@display_title", which is a "@type" chart. Not all chart types may be combined. Selecting a different chart type than the parent may cause errors.', array('@display_title' => $parent_display->display_title, '@type' => $parent_chart_type['label']));
+      $form['fields']['label_field']['#disabled'] = TRUE;
+      $form['display']['#access'] = FALSE;
+      $form['xaxis']['#access'] = FALSE;
+      if ($this->display->handler->options['inherit_yaxis']) {
+        $form['yaxis']['#access'] = FALSE;
+      }
+      else {
+        $form['yaxis']['#title'] = t('Secondary axis');
+        $form['yaxis']['#attributes']['class'] = array();
+      }
+    }
   }
 
   /**
@@ -68,7 +95,12 @@ class charts_plugin_style_chart extends views_plugin_style {
       return;
     }
 
-    if (count($field_handlers)) {
+    // Make sure that all chart extensions first have a parent chart selected.
+    if ($this->plugin_name === 'chart_extension' && $this->get_parent_chart_display() === FALSE) {
+      $errors[] = t('This chart add-on must have a parent chart selected under the chart settings.');
+    }
+    // Make sure that at least one data column has been selected.
+    elseif (count($field_handlers)) {
       $data_field_key = !empty($this->options['data_fields']) ? current($this->options['data_fields']) : NULL;
       if (empty($data_field_key)) {
         $errors[] = t('At least one data field must be selected in the chart configuration before this chart may be shown');
@@ -88,14 +120,17 @@ class charts_plugin_style_chart extends views_plugin_style {
    * Define and display a chart from the grouped values.
    */
   function render() {
-    // Calculate the labels field alias.
     $field_handlers = $this->display->handler->get_handlers('field');
+
+    // Calculate the labels field alias.
     $label_field = FALSE;
     $label_field_key = NULL;
     if ($this->options['label_field'] && array_key_exists($this->options['label_field'], $field_handlers)) {
       $label_field = $field_handlers[$this->options['label_field']];
       $label_field_key = $this->options['label_field'];
     }
+
+    // Assemble the fields to be used to provide data access.
     $data_field_options = array_filter($this->options['data_fields']);
     $data_fields = array();
     foreach ($data_field_options as $field_key) {
@@ -145,7 +180,7 @@ class charts_plugin_style_chart extends views_plugin_style {
         $chart['#legend_title'] = $label_field->options['label'];
       }
 
-      $chart['series'] = array(
+      $chart[$this->view->current_display . '_series'] = array(
         '#type' => 'chart_data',
         '#data' => $data,
         '#title' => $data_field->options['label'],
@@ -165,7 +200,7 @@ class charts_plugin_style_chart extends views_plugin_style {
         '#min' => $this->options['yaxis_min'],
       );
       foreach ($data_fields as $field_key => $field_handler) {
-        $chart[$field_key] = array(
+        $chart[$this->view->current_display . '__' . $field_key] = array(
           '#type' => 'chart_data',
           '#data' => array(),
           '#color' => isset($this->options['field_colors'][$field_key]) ? $this->options['field_colors'][$field_key] : NULL,
@@ -182,13 +217,101 @@ class charts_plugin_style_chart extends views_plugin_style {
           $chart['xaxis']['#labels'][] = $renders[$row_number][$label_field_key];
         }
         foreach ($data_fields as $field_key => $field_handler) {
-          $chart[$field_key]['#data'][] = (float) $renders[$row_number][$field_key];
+          $chart[$this->view->current_display . '__' . $field_key]['#data'][] = (float) $renders[$row_number][$field_key];
+        }
+      }
+    }
+
+    // Check if this display has any children charts that should be applied
+    // on top of it.
+    $parent_display_id = $this->view->current_display;
+    $children_displays = $this->get_children_chart_displays();
+    foreach ($children_displays as $child_display_id => $child_display) {
+      // If the user doesn't have access to the child display, skip.
+      if (!$this->view->access($child_display_id)) {
+        continue;
+      }
+
+      // Generate the subchart by executing the child display. We load a fresh
+      // view here to avoid collisions in shifting the current display while in
+      // a display.
+      $subview = $this->view->clone_view();
+      $subview->set_display($child_display_id);
+
+      // Copy the settings for our axes over to the child view.
+      foreach ($this->options as $option_name => $option_value) {
+        if (strpos($option_name, 'yaxis') === 0 && $child_display->display_options['inherit_yaxis']) {
+          $subview->display_handler->options['style_options'][$option_name] = $option_value;
+        }
+        elseif (strpos($option_name, 'xaxis') === 0) {
+          $subview->display_handler->options['style_options'][$option_name] = $option_value;
+        }
+      }
+
+      // Execute the subview and get the result.
+      $subview->pre_execute();
+      $subview->execute();
+      $subchart = $subview->style_plugin->render($subview->result);
+      $subview->post_execute();
+      unset($subview);
+
+      // Create a secondary axis if needed.
+      if (!$child_display->display_options['inherit_yaxis'] && isset($subchart['yaxis'])) {
+        $chart['secondary_yaxis'] = $subchart['yaxis'];
+        $chart['secondary_yaxis']['#opposite'] = TRUE;
+      }
+
+      // Merge in the child chart data.
+      foreach (element_children($subchart) as $key) {
+        if ($subchart[$key]['#type'] === 'chart_data') {
+          $chart[$key] = $subchart[$key];
+          // If the subchart is a different type than the parent chart, set
+          // the #chart_type property on the individual chart data elements.
+          if ($chart[$key]['#chart_type'] !== $chart['#chart_type']) {
+            $chart[$key]['#chart_type'] = $subchart['#chart_type'];
+          }
+          if (!$child_display->display_options['inherit_yaxis']) {
+            $chart[$key]['#target_axis'] = 'secondary_yaxis';
+          }
         }
       }
     }
 
     // Print the chart.
-    return drupal_render($chart);
+    return $chart;
+  }
+
+  /**
+   * Utility function to check if this chart has a parent display.
+   */
+  function get_parent_chart_display() {
+    $parent_display = FALSE;
+    if ($this->plugin_name === 'chart_extension' && $this->display && $this->display->handler->options['parent_display']) {
+      $parent_display_name = $this->display->handler->options['parent_display'];
+      if (isset($this->view->display[$parent_display_name])) {
+        $parent_display = $this->view->display[$parent_display_name];
+      }
+    }
+    // Ensure the parent is a chart.
+    if ($parent_display && $parent_display->display_options['style_plugin'] !== 'chart') {
+      $parent_display = FALSE;
+    }
+    return $parent_display;
   }
 
+  /**
+   * Utility function to check if this chart has children displays.
+   */
+  function get_children_chart_displays() {
+    $children_displays = array();
+    foreach ($this->view->display as $display_name => $display) {
+      if ($display->display_plugin === 'chart' && $display->display_options['parent_display']) {
+        $parent_display_name = $display->display_options['parent_display'];
+        if ($parent_display_name === $this->view->current_display) {
+          $children_displays[$display_name] = $this->view->display[$display_name];
+        }
+      }
+    }
+    return $children_displays;
+  }
 }