'Javascript chart settings form', 'page callback' => 'fusioncharts_form_settings_js', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); $items['fusioncharts/js/matrixfield'] = array( 'title' => 'Javascript chart options form', 'page callback' => 'fusioncharts_form_matrixfield_js', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); return $items; } /** * Implementation of hook_node_info() */ function fusioncharts_node_info() { return array( 'fusioncharts' => array( 'name' => t('Fusion Chart'), 'module' => 'fusioncharts', 'has_body' => FALSE, 'description' => t("A chart made with the Fusion Charts system."), ) ); } /** * Implementation of hook_access(). */ function fusioncharts_access($op, $node, $account) { global $user; if ($op == 'create') { return user_access('create fusioncharts node'); } if ($op == 'update' || $op == 'delete') { if (user_access('edit own fusioncharts nodes') && ($user->uid == $node->uid)) { return TRUE; } } } /** * Implementation of hook_perm(). */ function fusioncharts_node_perm() { return array('create fusioncharts node', 'edit own fusioncharts nodes'); } /** * Implementation of hook_form(). */ function fusioncharts_form(&$node, $form_state) { drupal_add_css(drupal_get_path('module', 'fusioncharts_node') .'/fusioncharts_node.css', 'module', 'all', FALSE); drupal_add_js(drupal_get_path('module', 'fusioncharts') .'/fusioncharts.js'); //load the colorpicker css and javascript now becasue it won't get included with the ahah drupal_add_css('misc/farbtastic/farbtastic.css'); drupal_add_js('misc/farbtastic/farbtastic.js'); drupal_add_js(drupal_get_path('module', 'colorpicker'). '/js/colorpicker.js'); drupal_add_css(drupal_get_path('module', 'colorpicker'). '/css/colorpicker.css'); $type = node_get_types('type', $node); $chart_types = fusioncharts_settings('fusioncharts'); if (!isset($node->chart_type)) { $node->chart_type = 'Column 3D'; } array_unshift($chart_types, ''); //add a blank to the front of the list $form['#tree'] = FALSE; $form['title'] = array( '#type' => 'textfield', '#title' => check_plain($type->title_label), '#required' => TRUE, '#default_value' => isset($node->title) ? $node->title : '', '#weight' => -5 ); $form['chart_type'] = array( '#type' => 'select', '#title' => t('Type of chart'), '#default_value' => $node->chart_type, '#options' => $chart_types, '#description' => t('The is the type of chart to build. The chart options and data required depend on the type of chart.'), '#required' => TRUE, '#ahah' => array( 'path' => 'fusioncharts/js/chartsettings', 'wrapper' => 'chart-settings', 'method' => 'replace', 'effect' => 'fade', ), ); $form['size'] = array( '#type' => 'fieldset', '#title' => t('Chart size'), '#collapsible' => TRUE, '#collapsed' => FALSE, ); $form['size']['width'] = array( '#type' => 'textfield', '#title' => t('Chart width'), '#default_value' => isset($node->width) ? $node->width : 500, '#description' => t('The width of the chart (pixels)'), '#size' => 5, '#required' => TRUE, ); $form['size']['height'] = array( '#type' => 'textfield', '#title' => t('Chart height'), '#default_value' => isset($node->height) ? $node->height : 300, '#description' => t('The height of the chart (pixels)'), '#size' => 5, '#required' => TRUE, ); $form['rows_more'] = array( '#type' => 'submit', '#value' => t('Add more rows'), '#description' => t("If the amount of boxes above isn't enough, click here to add more rows."), // '#weight' => 0, '#ahah' => array( 'path' => 'fusioncharts/js/matrixfield', 'wrapper' => 'matrix-data', 'method' => 'replace', 'effect' => 'fade', ), ); $form['cols_more'] = array( '#type' => 'submit', '#value' => t('Add more columns'), '#description' => t("If the amount of boxes above isn't enough, click here to add more columns."), '#ahah' => array( 'path' => 'fusioncharts/js/matrixfield', 'wrapper' => 'matrix-data', 'method' => 'replace', 'effect' => 'fade', ), ); $form['chart_settings'] = fusioncharts_form_settings($node, $node->chart_type); $form['chart_settings']['#prefix'] = '
'; $form['chart_settings']['#suffix'] = '
'; return $form; } /** * Settings sub-form(). */ function fusioncharts_form_settings($node, $chart_type) { include_once(drupal_get_path('module', 'fusioncharts') .'/settings.inc'); drupal_add_css(drupal_get_path('module', 'fusioncharts_node') .'/fusioncharts_node.css'); $node->data = isset($node->data) ? $node->data : $_POST['matrix']['matrix']; $default_row = variable_get('fusioncharts_default_row', 10); $default_col = variable_get('fusioncharts_default_col', 2); $row_count = max($default_row, count($node->data)); $col_count = max($default_col, count($node->data[0])); switch ($chart_type) { case 'Column 3D': case 'Column 2D': case 'Line 2D': case 'Area 2D': case 'Bar 2D': case 'Pie 2D': case 'Pie 3D': case 'Doughnut 2D': case 'Funnel Chart': // Add the current data to the matrixfield. for ($i=1; $i<=$row_count; $i++) { $rows[] = $i; } $header = array('Series', 'Value'); $form['matrix'] = fusioncharts_form_matrixfield($node->data, $header, $rows); $form['matrix']['#prefix'] = '
'; $form['matrix']['#suffix'] = '
'; break; case 'Multi-series Column 2D': case 'Multi-series Column 3D': case 'Multi-series Line 2D': case 'Multi-series Bar 2D': case 'Multi-series Area 2D': case 'Stacked Column 3D': case 'Stacked Column 2D': case 'Stacked Bar 2D': case 'Stacked Area 2D': $rows[0] = 'Label'; // Add the current data to the matrixfield. for ($i=1; $i<=$row_count; $i++) { $rows[] = $i; } $header[] = 'Series'; for ($i=1; $i<$col_count; $i++) { $header[] = ''; } $form['matrix'] = fusioncharts_form_matrixfield($node->data, $header, $rows); $form['matrix']['#prefix'] = '
'; $form['matrix']['#suffix'] = '
'; break; case 'Multi-series Column 2D + Line - Dual Y Axis': case 'Multi-series Column 3D + Line - Dual Y Axis': $rows[0] = 'Label'; $rows[1] = 'P/S'; for ($i=2; $i<=$row_count+1; $i++) { $rows[] = $i-1; } $header[] = 'Series'; for ($i=1; $i<$col_count; $i++) { $header[] = ''; } $form['matrix'] = fusioncharts_form_matrixfield($node->data, $header, $rows); $form['matrix']['#prefix'] = '
'; $form['matrix']['#suffix'] = '
'; break; case 'Candlestick Chart': //not yet implemented break; case 'Gantt Chart': //not yet implemented break; } $form['fill_boxes'] = array( '#type' => 'checkbox', '#default_value' => isset($node->attributes['fill_boxes']) ? $node->attributes['fill_boxes'] : 1, '#title' => t('Fill blanks cells with "0"'), ); $form['settings'] = array( '#tree' => TRUE ); $form['attributes'] = array( '#tree' => TRUE ); //each chart has a number or properties that can be set. There are a number of common properties, and a number that apply to //a selection of charts. The following section defines all the possible attributes for each chart. $form = array_merge_recursive($form, _fusioncharts_settings_subform($chart_type, $node)); return $form; } /** * Menu callback for AHAH form(). */ function fusioncharts_form_settings_js() { $node_state->settings = $_POST['settings']; $node_state->attributes = $_POST['attributes']; $node_state->data = $_POST['matrix']['matrix']; $new_subform = fusioncharts_form_settings($node_state, $_POST['chart_type']); $output = ahah_render($new_subform, 'chart-settings'); switch ($_POST['chart_type']) { case 'Column 3D': case 'Column 2D': case 'Line 2D': case 'Area 2D': case 'Bar 2D': case 'Pie 2D': case 'Pie 3D': case 'Doughnut 2D': case 'Funnel Chart': $js = "$('#edit-rows-more').show(); $('#edit-cols-more').hide();"; case 'Multi-series Column 2D': case 'Multi-series Column 3D': case 'Multi-series Line 2D': case 'Multi-series Bar 2D': case 'Multi-series Area 2D': case 'Stacked Column 3D': case 'Stacked Column 2D': case 'Stacked Bar 2D': case 'Stacked Area 2D': case 'Multi-series Column 2D + Line - Dual Y Axis': case 'Multi-series Column 3D + Line - Dual Y Axis': $js = "$('#edit-rows-more').show(); $('#edit-cols-more').show();"; } // 'Candlestick Chart': // 'Gantt Chart' : $output .= ""; //reinitialise the colorpickers print drupal_to_js(array('data' => $output, 'status' => true)); exit(); } /** * Matrix sub-form. */ function fusioncharts_form_matrixfield($data, $header, $rows) { $form = array( '#type' => 'fc_matrixfield', '#title' => t('Data'), '#description' => t('Enter your data here'), '#cols' => $header, '#rows' => $rows, '#default_value' => $data, ); return $form; } /** * Menu callback for AHAH form(). */ function fusioncharts_form_matrixfield_js() { $data = $_POST['matrix']['matrix']; $header = unserialize($_POST['matrix']['header']); $first_col = unserialize($_POST['matrix']['first_col']); array_shift($header); if ($_POST['op'] == 'Add more columns') { $header[] = ''; } if ($_POST['op'] == 'Add more rows') { $row_delta = 5; } // Add the current data back to the matrixfield. for ($i=1; $i <= count($first_col)+$row_delta; $i++) { $rows[] = $i; } $form = fusioncharts_form_matrixfield($data, $header, $rows); $output = ahah_render($form, "matrix"); print drupal_to_js(array('data' => $output, 'status' => true)); exit(); } /** * Implementation of hook_insert(). */ function fusioncharts_insert($node) { if ($node->fill_boxes) { fusioncharts_node_fill_zeros($node); } foreach ($node->attributes as $sub => $subarray) { foreach ($subarray as $key => $value) { $attributes[$key] = $value; } } foreach ($node->settings as $sub => $subarray) { foreach ($subarray as $key => $value) { $settings[$key] = $value; } } db_query("INSERT INTO {fusioncharts} (nid, vid, chart_type, settings, attributes, data, width, height) VALUES (%d, %d, '%s', '%s', '%s', '%s', %d, %d)", $node->nid, $node->vid, $node->chart_type, serialize($settings), serialize($attributes), serialize($node->matrix['matrix']), $node->width, $node->height); } /** * Implementation of hook_update(). */ function fusioncharts_update($node) { if ($node->fill_boxes) { fusioncharts_node_fill_zeros($node); } foreach ((array)$node->attributes as $sub => $subarray) { foreach ($subarray as $key => $value) { $attributes[$key] = $value; } } foreach ((array)$node->settings as $sub => $subarray) { foreach ($subarray as $key => $value) { $settings[$key] = $value; } } if ($node->revision) { fusioncharts_node_insert($node); } else { db_query("UPDATE {fusioncharts} SET chart_type = '%s', settings = '%s', attributes = '%s', data = '%s', width = %d, height = %d WHERE vid = %d", $node->chart_type, serialize($settings), serialize($attributes), serialize($node->matrix['matrix']), $node->width, $node->height, $node->vid); } } /** * Implementation of hook_nodeapi(). */ function fusioncharts_nodeapi(&$node, $op, $teaser, $page) { switch ($op) { case 'delete revision': // Notice that we're matching a single revision based on the node's vid. db_query('DELETE FROM {fusioncharts} WHERE vid = %d', $node->vid); break; case 'load': $node->settings = unserialize($node->settings); $node->attributes = unserialize($node->attributes); break; } } /** * Implementation of hook_delete(). */ function fusioncharts_delete($node) { db_query('DELETE FROM {fusioncharts} WHERE nid = %d', $node->nid); } /** * Implementation of hook_load(). */ function fusioncharts_load($node) { $add = db_fetch_object(db_query("SELECT * FROM {fusioncharts} WHERE vid = %d", $node->vid)); $add->data = unserialize($add->data); return $add; } /** * Implementation of hook_view(). */ function fusioncharts_view($node, $teaser = FALSE, $page = FALSE) { $node->content['chart'] = array( '#value' => theme('fusionchart', 'fusionchart_node', 'node_'. $node->nid, $node), '#weight' => 1, ); return $node; } /** * FusionCharts callback to render the node */ function fusionchart_node_fusionchart_callback($args = NULL) { $node = $args[0]; if ($node->op == 'Preview') { //special case to deal with the data when the Preview button is pressed $raw_data = $node->matrix['matrix']; foreach ((array)$node->attributes as $sub => $subarray) { foreach ($subarray as $key => $value) { $attributes_raw[$key] = $value; } } foreach ((array)$node->settings as $sub => $subarray) { foreach ($subarray as $key => $value) { $settings[$key] = $value; } } } else { $raw_data = $node->data; $settings = $node->settings; $attributes_raw = $node->attributes; } foreach ((array)$attributes_raw as $key => $value) { if (substr($value, 0, 1) == '#' && strlen($value) == 7) { //remove the # from the color $attributes['color'][] = substr($value, 1); } else { $attributes[$key] = $value; } } //append another 50 random colours, just so we don't run out! for ($i=1; $i<50; $i++) { $attributes['color'][] = dechex(rand(0, 255)) . dechex(rand(0, 255)) . dechex(rand(0, 255)); } foreach ((array)$settings as $key => $value) { if (substr($value, 0, 1) == '#' && strlen($value) == 7) { //remove the # from the color $settings[$key] = substr($value, 1); } } switch ($node->chart_type) { case 'Column 3D': case 'Column 2D': case 'Line 2D': case 'Area 2D': case 'Bar 2D': case 'Pie 2D': case 'Pie 3D': case 'Doughnut 2D': case 'Funnel Chart': $data = $raw_data; break; case 'Multi-series Column 2D': case 'Multi-series Column 3D': case 'Multi-series Line 2D': case 'Multi-series Bar 2D': case 'Multi-series Area 2D': case 'Stacked Column 3D': case 'Stacked Column 2D': case 'Stacked Bar 2D': case 'Stacked Area 2D': $no_of_rows = count($raw_data); $no_of_cols = count($raw_data[0]); for ($i=1; $i<$no_of_cols; $i++) { for ($j=1; $j<$no_of_rows; $j++) { if ($raw_data[$j][$i] != '') { $data[] = array($raw_data[$j][0], $raw_data[0][$i], $raw_data[$j][$i]); } } } break; case 'Multi-series Column 2D + Line - Dual Y Axis': case 'Multi-series Column 3D + Line - Dual Y Axis': $no_of_rows = count($raw_data); $no_of_cols = count($raw_data[0]); for ($i=1; $i<$no_of_cols; $i++) { for ($j=2; $j<$no_of_rows; $j++) { if ($raw_data[$j][$i] != '') { $data[] = array( $raw_data[0][$i], $raw_data[$j][0], $raw_data[1][$i], $raw_data[$j][$i]); } } } break; case 'Candlestick Chart': //not implemented yet break; case 'Gantt Chart': //not implemented yet break; } $info->chart_type = $node->chart_type; $info->width = $node->width; $info->height = $node->height; $info->settings = $settings; $info->attributes = $attributes; $info->data = $data; return $info; } /** * Fill the node data with 0's if they are blank and the "fill 0's" textbox is ticked */ function fusioncharts_node_fill_zeros(&$node) { foreach ($node->matrix['matrix'] as $rowid => $row) { foreach ($row as $columnid => $cell) { if ($columnid == 0 && $cell == '') { break; //skip if the row is empty } if (!$columnid == 0) { if ($cell == '') { $node->matrix['matrix'][$rowid][$columnid] = "0"; } } } } } /** * Implementation of hook_filter_tips(). * */ function fusioncharts_node_filter_tips($delta, $format, $long = FALSE) { switch ($delta) { case 0: if ($long) { return t('Substitutes a the string "[fusionchart:#]" with a fusionchart node (where # is the node id). You can also set the width and height [fusionchart:#|w:300|h:100]'); } break; } } /** * Implementation of hook_filter(). */ function fusioncharts_node_filter($op, $delta = 0, $format = -1, $text = '') { if ($op == 'list') { return array(0 => t('FusionChart node insert')); } switch ($delta) { case 0: switch ($op) { case 'description': return t('Substitutes a the string "[fusionchart:#]" with a fusionchart node (where # is the node id).'); case 'prepare': return $text; case 'process': preg_match_all('/\[fusionchart:(\d+)\|?(.*)\]/', $text, $matches); $match_count = count($matches[0]); for ($i = 0; $i<$match_count; $i++) { unset($node); $components = explode('|', $matches[2][$i]); foreach ($components as $component) { list($key, $value) = explode(':', $component); $overrides[strtolower($key)] = $value; } $node = node_load($matches[1][$i]); $node->width = isset($overrides['w']) ? $overrides['w'] : $node->width; $node->height = isset($overrides['h']) ? $overrides['h'] : $node->height; $find[] = $matches[0][$i]; $replace[] = theme('fusionchart', 'fusionchart_node', 'node_'. $node->nid, $node); } return str_replace($find, $replace, $text); case 'settings': return array(); } break; } }