You are here

private function IpGeoLocPluginStyleLeaflet::addClusterDifferentiator in IP Geolocation Views & Maps 8

Form part definition.

1 call to IpGeoLocPluginStyleLeaflet::addClusterDifferentiator()
IpGeoLocPluginStyleLeaflet::buildOptionsForm in src/Plugin/views/style/IpGeoLocPluginStyleLeaflet.php
Provide a form to edit options for this plugin.

File

src/Plugin/views/style/IpGeoLocPluginStyleLeaflet.php, line 762

Class

IpGeoLocPluginStyleLeaflet
Views Style plugin extension for Leaflet (if enabled).

Namespace

Drupal\ip_geoloc\Plugin\views\style

Code

private function addClusterDifferentiator(&$form, FormStateInterface &$form_state, $lib_markercluster, &$weight) {
  $path = drupal_get_path('module', 'ip_geoloc');
  $intro = $this
    ->t('Region-aware marker clustering with <a target="regionbound" href="!url_regionbound">RegionBound</a>. See the <a target="readme" href="!url_readme">README</a> for details.', [
    // '!url_regionbound' => url('http://regionbound.com'),
    // '!url_readme' => url("$path/README.txt"),.
    '!url_regionbound' => 'http://regionbound.com',
    '!url_readme' => "{$path}/README.txt",
  ]);
  $form['cluster_differentiator'] = [
    '#type' => 'fieldset',
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#title' => $this
      ->t('Cluster region differentiator'),
    '#description' => '<em>' . $intro . '</em><br/>',
    // The id in the prefix must match the AJAX submit handlers below.
    '#prefix' => '<div id="cluster-differentiator-wrapper">',
    '#suffix' => '</div>',
    '#weight' => $weight++,
  ];
  $region_field_names = NULL;
  if ($trigger = $form_state
    ->getTriggeringElement()) {

    // Get here when any form element with #ajax was changed/clicked causing
    // an auto-rebuild of the form.
    if (strpos($trigger['#id'], 'cluster-differentiator-field') > 0) {

      // Get here when it was the cluster-differentiator multi-select that was clicked.
      $region_field_names = $trigger['#value'];
    }
  }
  else {
    $region_field_names = $this->options['cluster_differentiator']['cluster_differentiator_fields'];
  }
  if (!$this->moduleHandler
    ->moduleExists('leaflet_markercluster')) {
    $desc = $this
      ->t('Requires the <a target="project" href="!url_project">Leaflet MarkerCluster</a> module', [
      '!url_project' => 'http://drupal.org/project/leaflet_markercluster',
    ]);
    $form['cluster_differentiator']['#description'] .= $desc . ' ' . $this
      ->t('and <a href="!url_regionbound">RegionBound</a> JS plugin.', [
      '!url_regionbound' => 'http://regionbound.com',
    ]);
  }
  elseif ($lib_markercluster && (empty($region_field_names) || !reset($region_field_names))) {
    $note_region = $this
      ->t('Download the file %js from <a target="regionbound" href="!url_regionbound">Regionbound</a> and drop it in %directory, without renaming. Then select your region differentiator below.', [
      '%js' => IP_GEOLOC_LEAFLET_MARKERCLUSTER_REGIONBOUND_JS,
      '%directory' => $lib_markercluster,
      '!url_regionbound' => 'http://regionbound.com',
    ]);
    $form['cluster_differentiator']['#description'] .= "<p>{$note_region}</p>";
  }

  // @TODO check how to migrate this
  // $fields = ip_geoloc_get_display_fields($this->displayHandler, FALSE, FALSE);
  $fields = ip_geoloc_get_display_fields($this->displayHandler, TRUE);
  $form['cluster_differentiator']['cluster_differentiator_fields'] = [
    '#title' => $this
      ->t('Region differentiator'),
    '#type' => 'select',
    '#multiple' => TRUE,
    '#size' => 6,
    '#options' => $fields,
    '#default_value' => $region_field_names,
    '#ajax' => [
      'callback' => [
        self::class,
        'pluginStyleLeafletRefreshClusterFieldsetJs',
      ],
      'wrapper' => 'cluster-differentiator-wrapper',
      'prevent' => 'submit',
    ],
    '#description' => $this
      ->t('Select a field (or sequence of fields) that reflect for each location marker the region hierarchy it belongs to. Examples are an <a target="drupal" href="!url_addressfield">AddressField</a>, a hierarchical taxonomy term based on regions, or individual fields for country, state, city, suburb (<em>in that order</em>). Make sure that the region differentiator you wish to use is included as a field in your view, so it appears in the list above. Note that region differentiators do <em>not</em> need to be associated with latitudes or longitudes. They are just name fields.', [
      '!url_addressfield' => 'http://drupal.org/project/addressfield',
    ]),
  ];
  $level = 0;
  if (!empty($region_field_names)) {
    foreach ($region_field_names as $region_field_name) {
      if (!empty($region_field_name)) {
        $region_field = FieldStorageConfig::loadByName('node', $region_field_name);

        //$region_field = \Drupal::entityManager()->getStorage($region_field_name)->loadMultiple();

        // $region_field = field_info_field($region_field_name);
        $field_type = empty($region_field
          ->get('type')) ? '' : $region_field
          ->get('type');
        $region_depth = $this
          ->getRegionFieldDepth($region_field);
        $zoom_titles = $this
          ->getZoomTitles($field_type, $fields[$region_field_name], $region_depth);
        foreach ($zoom_titles as $title) {
          $level++;
          $default_value = isset($this->options['cluster_differentiator']['zoom_ranges'][$level]) ? $this->options['cluster_differentiator']['zoom_ranges'][$level] : '';
          $form['cluster_differentiator']['zoom_ranges'][$level] = [
            '#type' => 'textfield',
            '#title' => Xss::filterAdmin($title),
            '#size' => 28,
            '#default_value' => $default_value,
            '#element_validate' => [
              'ip_geoloc_range_widget_validate',
            ],
          ];
        }
      }
    }
    if ($level > 0) {
      $desc1 = $level === 1 ? $this
        ->t('Below enter the zoom level range to be associated with the selected differentiator.') : $this
        ->t('Below enter the zoom level ranges to which each of the region hierarchy levels apply.') . '<br/>' . $this
        ->t('Zoom ranges may start and end at any level, but must not overlap.');

      // $this->t('Minimum and maximum zoom levels for this map can be found below under <strong>More map options</strong>.');.
      $desc2 = '';
      $desc3 = $this
        ->t('Or leave all fields blank to use the defaults and refine later.');
      $zoom1 = $this
        ->t('Typical zoom ranges for Europe: country: 3--6, province: 7--9, city: 10--14, postcode: 15--18');
      $zoom2 = $this
        ->t('Typical zoom ranges for US & Canada: country: 1--3, state: 4--8, city: 9--13, zip: 14--18');
      $zoom3 = $this
        ->t('Typical zoom ranges for Australia: country: 1--2, state: 3--9, city: 10--13, suburb/postcode: 14--18');
      $form['cluster_differentiator']['cluster_differentiator_fields']['#description'] = implode('<br/>', [
        "{$desc1} {$desc2}<br/>{$desc3}<br/>",
        $zoom1,
        $zoom2,
        $zoom3,
      ]);
    }
    $form['cluster_differentiator']['cluster_tooltips'] = [
      '#title' => $this
        ->t('Add cluster tooltips'),
      '#type' => 'checkbox',
      '#default_value' => $this->options['cluster_differentiator']['cluster_tooltips'],
      '#description' => $this
        ->t("When hovering a cluster, tooltips reveal the cluster region name and the names of its populated subregions."),
    ];
    $form['cluster_differentiator']['cluster_touch_mode'] = [
      '#title' => $this
        ->t('Cluster action on touch devices (e.g. mobile phones)'),
      '#type' => 'radios',
      '#options' => [
        1 => $this
          ->t('Single tap displays cluster regions, double-tap drills into cluster (default)'),
        0 => $this
          ->t('Single tap drills into cluster. Sub-region names not displayed, but visible on mouse devices.'),
      ],
      '#default_value' => $this->options['cluster_differentiator']['cluster_touch_mode'],
      '#description' => $this
        ->t('Applies only to devices that do not have a mouse, like mobile phones.'),
    ];
    $form['cluster_differentiator']['cluster_outline'] = [
      '#title' => $this
        ->t('Cluster population outline'),
      '#type' => 'select',
      '#options' => [
        0 => $this
          ->t('Traditional (convex hull)'),
        1 => $this
          ->t('Avant-garde (heuristic hull)'),
      ],
      '#default_value' => $this->options['cluster_differentiator']['cluster_outline'],
      '#description' => $this
        ->t('When hovering a cluster, a <a target="regionbound" href="!url_regionbound">coverage outline</a> visualises the envelope or footprint of the underlying marker population. Select your preferred style of doing this.', [
        '!url_regionbound' => 'http://regionbound.com/enhanced-cluster-envelope-using-heuristic-hull',
      ]),
    ];
  }
  $intro = $this
    ->t('Use clusters to report on region aggregates; requires <a target="regionbound" href="!url_regionbound">RegionBound</a>', [
    '!url_regionbound' => 'http://regionbound.com/coffee-prices-across-melbourne',
  ]);
  $desc = $this
    ->t('This feature aggregates values of a selected field across every region and displays the resulting <em>sum/average/min/max</em> on each cluster icon at every zoom level. It also colours each cluster icon based on its aggregated value, rather than its marker count.');
  $form['cluster_aggregation'] = [
    '#type' => 'fieldset',
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#title' => $this
      ->t('Cluster aggregation'),
    '#description' => "<em>{$intro}</em><p>{$desc}</p>",
    '#weight' => $weight++,
  ];
  $form['cluster_aggregation']['aggregation_field'] = [
    '#title' => $this
      ->t('Field to perform aggregation on'),
    '#type' => 'select',
    '#default_value' => $this->options['cluster_aggregation']['aggregation_field'],
    '#options' => $fields,
    '#description' => $this
      ->t('For aggregation to make sense, the selected field must be numeric or represent a list. If a list, aggregation will be applied to the element <em>count</em>.'),
  ];
  $form['cluster_aggregation']['aggregation_function'] = [
    '#title' => $this
      ->t('Aggregation function'),
    '#type' => 'select',
    '#default_value' => $this->options['cluster_aggregation']['aggregation_function'],
    '#options' => [
      'average' => $this
        ->t('Average'),
      'maximum' => $this
        ->t('Maximum'),
      'minimum' => $this
        ->t('Minimum'),
      'sum' => $this
        ->t('Sum'),
    ],
  ];
  $form['cluster_aggregation']['ranges'] = [
    '#type' => 'item',
    '#description' => $this
      ->t('Edit the above to change the color-coding of cluster icons based on their aggregate values.'),
    '#prefix' => '<div id="cluster-aggregation-aggregate">',
    '#suffix' => '</div>',
  ];
  foreach ([
    'small',
    'medium',
    'large',
  ] as $size) {
    $default_value = isset($this->options['cluster_aggregation']['ranges'][$size]) ? $this->options['cluster_aggregation']['ranges'][$size] : '';
    $form['cluster_aggregation']['ranges'][$size] = [
      '#title' => "{$size} " . $this
        ->t('goes to'),
      '#type' => 'textfield',
      '#size' => 8,
      '#default_value' => $default_value,
    ];
  }
  $form['cluster_aggregation']['precision'] = [
    '#title' => $this
      ->t('Precision'),
    '#type' => 'textfield',
    '#size' => 2,
    '#default_value' => $this->options['cluster_aggregation']['precision'],
    '#description' => $this
      ->t('Number of significant digits used to display the aggregate value on the cluster icon. Leave blank for native formatting.'),
  ];
}