Subversion Repositories web.active

Rev

Blame | Last modification | View Log | Download

<?php namespace ProcessWire;

/**
 * jQuery Tabs for ProcessWire
 *
 * ProcessWire 3.x, Copyright 2019 by Ryan Cramer
 * https://processwire.com
 * 
 * @property int $rememberTabs
 * 
 * @method string render(array $items, array $options = array())
 * 
 */

class JqueryWireTabs extends ModuleJS implements ConfigurableModule { 

  public static function getModuleInfo() {
    return array(
      'title' => __('jQuery Wire Tabs Plugin', __FILE__),
      'summary' => __('Provides a jQuery plugin for generating tabs in ProcessWire.', __FILE__),
      'version' => 110,
      'permanent' => true, 
    );
  }

  const rememberTabsNever = -1;
  const rememberTabsSubmit = 0; 
  const rememberTabsAlways = 1; 

  // extending this class causes the class named JS and CSS files to automatically be loaded

  public function init() {
    
    $defaults = array(
      'ulClass' => 'WireTabs nav',
      'ulAttrs' => '',
      'liActiveClass' => '',
      'requestID' => ((string) $this->wire('process')) . ((int) $this->wire('input')->get('id')), 
      'aActiveClass' => 'on',
      'rememberTabs' => (int) $this->rememberTabs,
      'loadStyles' => true, 
      'cookieName' => 'WireTabs',
      'tooltipAttr' => array(
        'class' => 'tooltip',
        'title' => '{tip}',
      ), 
    );

    $config = $this->wire()->config;
    $className = 'JqueryWireTabs';
    $settings = $config->get($className); 
    
    if(is_array($settings)) {
      $settings = array_merge($defaults, $settings);
    } else {
      $settings = $defaults;
    }
    
    $this->loadStyles = $settings['loadStyles'];

    /** @var JqueryCore $jQueryCore */
    $jQueryCore = $this->wire()->modules->get('JqueryCore');
    $jQueryCore->use('cookie');
    
    $config->js($className, $settings);
    
    parent::init();
  }

  public function getModuleConfigInputfields(array $data) {
    $inputfields = $this->wire(new InputfieldWrapper());
    $f = $this->wire('modules')->get('InputfieldRadios'); 
    $f->attr('name', 'rememberTabs'); 
    $f->label = $this->_('Remember tab positions between requests?');
    $f->addOption(self::rememberTabsNever, $this->_('Never'));
    $f->addOption(self::rememberTabsSubmit, $this->_('Only after form submit'));
    $f->addOption(self::rememberTabsAlways, $this->_('Always'));
    $f->attr('value', (isset($data['rememberTabs']) ? (int) $data['rememberTabs'] : self::rememberTabsSubmit)); 
    $inputfields->add($f);
    return $inputfields; 
  }

  /**
   * Pre-render a tab list (optional, as this is JS generated if not pre-rendered)
   * 
   * @param array $tabs array of (tabID => title)
   * @param array $options to modify behavior
   * @return string
   * 
   */
  public function renderTabList(array $tabs, array $options = array()) {
    $settings = $this->wire('config')->get('JqueryWireTabs');
    $defaults = array(
      'class' => isset($options['class']) ? $options['class'] : $settings['ulClass'],
      'id' => '', 
    );
    $options = array_merge($defaults, $options); 
    $attrs = "class='$options[class]'" . ($options['id'] ? " id='$options[id]'" : "");
    if(!empty($settings['ulAttrs'])) $attrs .= " $settings[ulAttrs]";
    $out = "<ul $attrs>";
    
    foreach($tabs as $tabID => $title) {
      //$title = $this->wire('sanitizer')->entities1($title);
      if(strpos($title, '<a ') !== false) {
        $out .= "<li>$title</li>";
      } else {
        $out .= "<li><a href='#$tabID' id='_$tabID'>$title</a></li>";
      }
    }
    
    $out .= "</ul>";
    return $out; 
  }

  /**
   * All-in-one tabs rendering in ProcessWire admin
   * 
   * Use this method to render tabs, tab containers, and initialization script in the return value. This method
   * requires no other initialization or setup and returns ready-to-output tabs. 
   * 
   * ~~~~~
   * echo $modules->get('JqueryWireTabs')->render([
   *   'Foo' => 'Foo tab content',
   *   'Bar' => 'Bar tab content',
   *   'Baz' => 'Baz tab content',
   * ]); 
   * ~~~~~
   * 
   * @param array $items Array of one or more [ 'Tab Title' => 'Tab Content' ]
   * @param array $options Options to modify default behavior (I recommend omitting this argument unless you really need it)
   * @return string Markup ready for output
   * @since 3.0.127
   * 
   */
  public function ___render(array $items, array $options = array()) {
  
    static $n = 0;
    $n++;
    
    $defaults = array(
      'id' => "pw-wiretabs-$n", 
      'linksID' => "pw-wiretabs-$n-links", 
      'itemClass' => "pw-wiretabs-item", 
    );
    
    $sanitizer = $this->wire('sanitizer');
    $options = array_merge($defaults, $options);
    $links = array();
    $out = '';
    $cnt = 0;
    
    foreach($items as $itemTitle => $itemContent) {
      $cnt++;
      $itemID = "pw-wiretabs-$n-$cnt";
      $links[$itemID] = $sanitizer->entities1($itemTitle);
      $out .= "<div id='$itemID' class='$options[itemClass]'>$itemContent</div>";
    }
    
    $out = 
      "<div id='$options[id]' class='pw-wiretabs'>" . 
        $this->renderTabList($links, array('id' => $options['linksID'])) . 
        $out . 
      "</div>" . 
      "<script>jQuery(document).ready(function(){" . 
      "jQuery('#$options[id]').WireTabs({" . 
        "id:'$options[linksID]'," . 
        "items:jQuery('.$options[itemClass]')" . 
      "})});</script>";
    
    return $out;
  }
}