Giter Site home page Giter Site logo

Comments (10)

misaki-web avatar misaki-web commented on August 18, 2024

For the record, there's a workaround with the filter do_shortcode_tag. Example:

# Add this code in the `functions.php` theme file.
function chartjs_filter($output, $tag, $atts) {
	if ($tag == 'chartjs') {
		$my_custom_options = 'plugins: {legend: {labels: {font: {size: 24}}}}';
		$output = str_replace('options = {', 'options = {' . $my_custom_options . ',', $output);
	}
	
	return $output;
}
add_filter('do_shortcode_tag', 'chartjs_filter', 10, 3);

from sb-chart-block.

bobbingwide avatar bobbingwide commented on August 18, 2024

@misaki-web thanks for your contributions. I'm working through them slowly.
Re:

There are many ways to add font customization

  1. in the Gutenberg block settings
  2. as new shortcode attributes (like labelFontSize="16")
  3. as a more generic way to set any option supported by Chart.js, for example a textarea in the Gutenberg block settings or a new shortcode attribute like moreOptions="...".

1.1 Setting typography.fontSize true in block.json enables the font size where you enter the CSV data to be adjusted
1.2 But a range control is needed to allow the legend font size to be changed.
1.3 Is it also necessary to set the font size for the labels on the axes? If so, how is this done?

  1. I'd use labelsFontSize for the attribute/shortcode parameter name

  2. I'm not sure how to implement moreOptions in the block editor.

from sb-chart-block.

misaki-web avatar misaki-web commented on August 18, 2024

Is it also necessary to set the font size for the labels on the axes? If so, how is this done?

Actually, I think it would be useful to be able to customize the font everywhere. For example, IMO the default Chart.js font size is too small for legends, axis labels and tooltips.

Here's the Chart.js documentation for each one:

The following example customizes the font for all of them (so you can see what's the namespace for each one):

function customize_chart_font($options, $atts, $series) {
	$custom_options = to_array($options);
	
	$custom_options['plugins']['legend']['labels']['font']['size'] = 16;
	$custom_options['plugins']['legend']['labels']['color'] = '#000000';
	
	$custom_options['scales']['x']['ticks']['font']['size'] = 14;
	$custom_options['scales']['x']['ticks']['color'] = '#000000';
	
	$custom_options['scales']['y']['ticks']['font']['size'] = 14;
	$custom_options['scales']['y']['ticks']['color'] = '#000000';
	
	if (isset($custom_options['scales']['y1'])) {
		$custom_options['scales']['y1']['ticks']['font']['size'] = 14;
		$custom_options['scales']['y1']['ticks']['color'] = '#000000';
	}
	
	$custom_options['plugins']['tooltip']['titleFont']['size'] = 16;
	$custom_options['plugins']['tooltip']['bodyFont']['size'] = 15;
	$custom_options['plugins']['tooltip']['footerFont']['size'] = 15;
	
	return json_decode(json_encode($custom_options));
}
add_filter('sb_chart_block_options', 'customize_chart_font', 10, 3);

function to_array($data) {
	$array = [];
	
	if (is_array($data) || is_object($data)) {
		foreach ($data as $key => $value) {
			$array[$key] = (is_array($value) || is_object($value)) ? to_array($value) : $value;
		}
	} else {
		$array[] = $data;
	}
	
	return $array;
}

I'm not sure how to implement moreOptions in the block editor.

I think it could be a textarea (bonus: with code highlighting for json), something similar to the style/CSS textarea added by some plugins. Example with Blocks CSS:

Blocks CSS screenshot

from sb-chart-block.

bobbingwide avatar bobbingwide commented on August 18, 2024

PR #23 contained some changes for this issue but not all of them.

from sb-chart-block.

bobbingwide avatar bobbingwide commented on August 18, 2024

I struggled to find the best code for setting the nested properties font size options.

Where the original code to set the font size for the legend labels was

$custom_options['plugins']['legend']['labels']['font']['size'] = 16;

I wanted to be able to achieve the equivalent of

 $options->plugins->legend->labels->font->size = $this->atts['labelsFontSize'];

but the above only works when all the intermediate properties are objects.
It produces a Fatal error when attempting to assign a new property to a null property.

Stack overflow searches helped a bit.
One way of achieving this is to use json_decode & json_encode to convert an array to an object.

$temp = [];
$temp['legend']['labels']['font']['size'] = $this->atts['labelsFontSize'];
$options->plugins = json_decode( json_encode( $temp));

or, for simple objects like this casting to an object seems to work.

$options->plugins = (object) ['legend' => ['labels' => ['font' => ['size' => $this->atts['labelsFontSize']]]]];

Here I didn't use $temp; the array is created on the fly.

The code's a bit ugly but it seems to work.

I could have also tried the json_decode() method documented in Example 2 in https://www.php.net/manual/en/class.stdclass.php

from sb-chart-block.

misaki-web avatar misaki-web commented on August 18, 2024

In relation to this topic, see the section Are there hooks available for developers? I added in the README file some time ago:

sb-chart-block/README.md

Lines 125 to 175 in 3e5b787

### Are there hooks available for developers?
The following filter hooks are available:
- `sb_chart_block_content`: filter allowing to manipulate the content before it's processed
- `sb_chart_block_options`: filter allowing to add custom Chart.js options
For example, to customize the legend, use the `sb_chart_block_options` filter in your `functions.php` theme file as follows:
```php
function customize_legend($options, $atts, $series) {
$custom_options = to_array($options);
$custom_options['plugins']['legend']['labels']['font']['size'] = 16;
$custom_options['plugins']['legend']['labels']['color'] = '#0000FF';
return json_decode(json_encode($custom_options));
}
add_filter('sb_chart_block_options', 'customize_legend', 10, 3);
function to_array($data) {
$array = [];
if (is_array($data) || is_object($data)) {
foreach ($data as $key => $value) {
$array[$key] = (is_array($value) || is_object($value)) ? to_array($value) : $value;
}
} else {
$array[] = $data;
}
return $array;
}
```
Here's another way (without array conversion):
```php
function customize_legend($options, $atts, $series) {
if (!isset($options->plugins)) $options->plugins = new stdClass();
if (!isset($options->plugins->legend)) $options->plugins->legend = new stdClass();
if (!isset($options->plugins->legend->labels)) $options->plugins->legend->labels = new stdClass();
if (!isset($options->plugins->legend->labels->font)) $options->plugins->legend->labels->font = new stdClass();
$options->plugins->legend->labels->font->size = 16;
$options->plugins->legend->labels->color = '#0000FF';
return $options;
}
add_filter('sb_chart_block_options', 'customize_legend', 10, 3);
```

Also, what about a function that would take the value and the object path to be set? Let's say we have the following variables:

$options = new stdClass();
$options->abc = 'def';
$options->plugins = new stdClass();
$options->plugins->ghi = 'jkl';

$labelsFontSize = 14;

Here's another way to update the object:

set_object($options, 'legend->labels->font->size', $labelsFontSize);

function set_object(&$object, $path, $value) {
	if (is_object($object)) {
		if (is_array($path)) {
			$keys = $path;
		} else {
			$keys = explode('->', $path);
		}
		
		$tmp_object =& $object;
		
		foreach ($keys as $key) {
			if (!isset($tmp_object->$key)) {
				$tmp_object->$key = new stdClass();
			}
			
			$tmp_object =& $tmp_object->$key;
		}
		
		$tmp_object = $value;
		$success = true;
	}
	
	return;
}

The object is updated as expected:

var_dump($options);
// Output:
/*
object(stdClass)#1 (3) {
  ["abc"]=>
  string(3) "def"
  ["plugins"]=>
  object(stdClass)#2 (1) {
    ["ghi"]=>
    string(3) "jkl"
  }
  ["legend"]=>
  object(stdClass)#3 (1) {
    ["labels"]=>
    object(stdClass)#4 (1) {
      ["font"]=>
      object(stdClass)#5 (1) {
        ["size"]=>
        int(14)
      }
    }
  }
}
*/

The object could also be updated with the path as an array:

set_object($options, ['legend', 'labels', 'font', 'size'], $labelsFontSize);

from sb-chart-block.

bobbingwide avatar bobbingwide commented on August 18, 2024

set_object() is similar to the method I was thinking about/started writing yesterday...setProperty().

Rather than using -> for the separator I would have used . and I would have returned the value to be set.
eg

$options->plugins = setProperty( $options, 'legend.labels.font.size', $this->atts['labelsFontSize'] ); 

Also, I'm thinking of extracting the utility functions from the main plugin file into a library file.
I've got some non WordPress code that also creates charts.
Functions needed:

  • sb_chart_block_array_get
  • sb_chart_block_get_csv
  • sb_chart_block_array_replace
  • sb_chart_block_merge_objects

from sb-chart-block.

misaki-web avatar misaki-web commented on August 18, 2024

Rather than using -> for the separator I would have used . and I would have returned the value to be set.

Brainstorming: a way to create the object:

$path = 'plugins.legend.labels.font.size';
$value = $this->atts['labelsFontSize'];
$props = explode('.', $path);
while ($prop = array_pop($props)) {
    $value = (object) [$prop => $value];
}

var_dump($value);
/*
object(stdClass)#10 (1) {
  ["plugins"]=>
  object(stdClass)#9 (1) {
    ["legend"]=>
    object(stdClass)#8 (1) {
      ["labels"]=>
      object(stdClass)#7 (1) {
        ["font"]=>
        object(stdClass)#2 (1) {
          ["size"]=>
          int(14)
        }
      }
    }
  }
}
*/

from sb-chart-block.

bobbingwide avatar bobbingwide commented on August 18, 2024

Tests for this issue are part of the tests for #22. https://s.b/oikcom/block_example/chart-block-multiple-y-axes/

from sb-chart-block.

bobbingwide avatar bobbingwide commented on August 18, 2024

Delivered in v1.2.0

from sb-chart-block.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.