View source  
  <?php
namespace Drupal\gridstack\Plugin\gridstack\engine;
use Drupal\Component\Utility\Html;
use Drupal\gridstack\GridStackEnginePluginBase;
use Drupal\gridstack\Entity\GridStack;
abstract class GridStackBase extends GridStackEnginePluginBase {
  
  protected $nodes = [
    'x',
    'y',
    'width',
    'height',
    'region',
  ];
  
  public function attach(array &$load, array $attach = []) {
    parent::attach($load, $attach);
    
    if ($this
      ->getSetting('_gridstack')) {
      $load['drupalSettings']['gridstack'] = GridStack::defaultSettings();
    }
  }
  
  public function build(array &$build, array &$element) {
    parent::build($build, $element);
    
    if ($this
      ->getSetting('_gridstack')) {
      $build['postscript']['dummy'] = $this
        ->buildDummyItem();
    }
  }
  
  protected function buildDummyItem() {
    $item['attributes']['class'][] = 'gridstack__sizer is-nixbox';
    $item['attributes']['data-gs-height'] = 1;
    $item['attributes']['data-gs-width'] = 1;
    $settings['use_inner'] = $settings['_dummy'] = TRUE;
    return $this
      ->buildItem(100, $settings, $item);
  }
  
  protected function itemAttributes(array &$attributes, array &$settings) {
    parent::itemAttributes($attributes, $settings);
    $id = $this
      ->getSetting('delta', 0);
    $nid = $this
      ->getSetting('nested_delta', -1);
    $root = $this
      ->getSetting('_root', 'grids');
    $grids = $this
      ->getSetting('_grids') ?: $this
      ->getOptionset()
      ->getLastBreakpoint($root);
    
    if (isset($settings['nested_delta']) && $root == 'nested') {
      $node = isset($grids[$id][$nid]) ? $this
        ->getOptionset()
        ->getNode($grids[$id][$nid], FALSE) : [];
    }
    else {
      
      $node = isset($grids[$id]) ? $this
        ->getOptionset()
        ->getNode($grids[$id], FALSE) : [];
    }
    if ($node) {
      $this
        ->nodeAttributes($attributes, $node);
    }
  }
  
  protected function nodeAttributes(array &$attributes, array $node) {
    $ns = $this
      ->getSetting('nameshort', 'gs');
    foreach ($this->nodes as $key) {
      if (isset($node[$key])) {
        if ($key == 'region' && $node[$key]) {
          $attributes['class'][] = 'box--' . Html::cleanCssIdentifier($node[$key]);
        }
        else {
          $attributes['data-' . $ns . '-' . $key] = (int) $node[$key];
        }
      }
    }
  }
  
  public function containerAttributes(array &$attributes, array &$settings) {
    parent::containerAttributes($attributes, $settings);
    $attributes['class'][] = 'gridstack--js';
    
    $optionset = $this
      ->getOptionset();
    $attributes['data-gs-min-width'] = $this->minWidth;
    if ($optionset
      ->getSetting('noMargin', FALSE)) {
      $attributes['class'][] = 'is-gs-nomargin';
    }
    if ($vm = $optionset
      ->getSetting('verticalMargin')) {
      $attributes['data-gs-vm'] = $vm / 2;
    }
    
    if ($this
      ->getSetting('ungridstack')) {
      $attributes['class'][] = 'ungridstack';
      return;
    }
    
    if ($this
      ->getSetting('gridstatic') && !$this
      ->getSetting('gridnative')) {
      $attributes['class'][] = 'gridstack--static';
    }
    
    if (!$this
      ->getSetting('_ipe')) {
      $attributes['class'][] = 'is-gs-packing';
    }
    $attributes['class'][] = 'is-gs-enabled';
    
    $attributes['data-gs-column'] = $optionset
      ->getLastColumn();
    $attributes['data-gs-columns'] = $optionset
      ->getJson('breakpoints');
    $attributes['data-gs-config'] = $optionset
      ->getJson('settings');
    $attributes['data-gs-data'] = $optionset
      ->getData();
  }
  
  protected function itemContentAttributes(array &$attributes, array &$settings) {
    parent::itemContentAttributes($attributes, $settings);
    
    $this
      ->attributes($attributes, $settings);
  }
}