Rev 22 | Blame | Compare with Previous | Last modification | View Log | Download
<?php namespace ProcessWire;/*** ProcessWire Language Field Tabs** Organizes Language Fields into tabs for a cleaner easier to use interface** By Adamspruijt and Ryan Cramer, Copyright 2013/2014** ProcessWire 3.x, Copyright 2023 by Ryan Cramer* https://processwire.com** @property string $tabField Name of field/property to use for tab labels.***/class LanguageTabs extends WireData implements Module, ConfigurableModule {public static function getModuleInfo() {return array('title' => 'Languages Support - Tabs','version' => 117,'summary' => 'Organizes multi-language fields into tabs for a cleaner easier to use interface.','author' => 'adamspruijt, ryan, flipzoom','singular' => true,'autoload' => "template=admin",'requires' => 'LanguageSupport');}/*** Temporary storage of tabs created from addTab() method** @var array of strings**/protected $tabs = array();/*** Cached settings** @var array**/protected $settings = array();/*** Construct**/public function __construct() {parent::__construct();$this->set('tabField', 'title');}/*** Add hooks, setup JS config, and determine active tab**/public function ready() {if($this->wire()->page->template->name !== 'admin') return;$this->addHookAfter('InputfieldForm::render', $this, 'hookRenderInputfieldForm');}/*** Get language tab settings** @return array**/public function getSettings() {if(!empty($this->settings)) return $this->settings;$language = null;$input = $this->wire()->input;$languages = $this->wire()->languages;// allow for specifying language in your "edit" page link, from front-end// so if you want to focus on the Spanish tabs when the user clicks "edit"// from /es/path/to/page/, then you can by using a page edit link like:// <a href='{$config->urls->admin}page/edit/?id=$page->id&language=$user->language'>Edit</a>$id = (int) $input->get('language');if($id) $language = $languages->get($id);// if language is not specified as a GET variable, then use the user's languageif(!$language || !$language->id) $language = $this->wire()->user->language;// determine the index of the tab for the user's language$activeTab = 0;foreach($languages as $index => $lang) {if($lang->id == $language->id) $activeTab = $index;}$defaults = array('jQueryUI' => true, // use jQuery UI tabs?'labelOpen' => $this->_('Expand Language Tabs'),'labelClose' => $this->_('Collapse/Convert Back to Tabs'),'activeTab' => $activeTab,'ulClass' => '','ulAttrs' => '','liActiveClass' => '','liDisabledClass' => '','liEmptyClass' => '','aClass' => '','loadStyles' => true,'loadScripts' => true,'tabField' => $this->get('tabField'),'requestId' => ((string) $this->wire()->process) . (int) $input->get('id'),);$config = $this->wire()->config;$settings = $config->get('LanguageTabs');if(is_array($settings)) {$this->settings = array_merge($defaults, $settings);} else {$this->settings = $defaults;}$config->js('LanguageTabs', $this->settings);return $this->settings;}/*** Init language tabs in form immediately after form render** @param HookEvent $e**/public function hookRenderInputfieldForm(HookEvent $e) {$settings = $this->getSettings();$config = $this->wire()->config;$info = self::getModuleInfo();if($settings['jQueryUI']) {$adminTheme = $this->wire()->adminTheme;if($adminTheme) $adminTheme->addBodyClass('LanguageTabsJqueryUI');}if($settings['loadStyles']) {$config->styles->add($config->urls('LanguageTabs') . "LanguageTabs.css?v=$config->version-$info[version]");}if($settings['loadScripts']) {$config->scripts->add($config->urls('LanguageTabs') . "LanguageTabs.js?v=$config->version-$info[version]");}/** @var JqueryCore $jQueryCore */$jQueryCore = $this->wire()->modules->get('JqueryCore');$jQueryCore->use('longclick');$jQueryCore->use('cookie');if(strpos($e->return, 'LanguageSupport') === false) return;/** @var InputfieldForm $form */$form = $e->object;$id = $form->attr('id');$func = "setupLanguageTabs($('#$id'));";$e->return .= "<script>$func</script>";}/*** Clear any stored tabs**/public function resetTabs() {$this->tabs = array();}/*** Add a new tab, to be later retrieved by renderTabs()** @param Inputfield $inputfield* @param Language $language**/public function addTab(Inputfield $inputfield, Language $language) {$settings = $this->getSettings();$liClasses = array();$aClasses = array('langTabLink', 'langTab' . $language->id);$title = $language->get(empty($settings['tabField']) ? $this->tabField : $settings['tabField']);if(empty($title)) $title = $language->get("$this->tabField|name");$title = $this->wire()->sanitizer->entities1($title);if(!$this->wire()->languages->editable($language)) {$title = "<s>$title</s>";$liClasses[] = 'LanguageNotEditable';$liClasses[] = $settings['liDisabledClass'];}if($inputfield->isEmpty()) {$liClasses[] = 'langTabEmpty';$liClasses[] = $settings['liEmptyClass'];}$id = $inputfield->attr('id');$liClass = implode(' ', $liClasses);$aClass = implode(' ', $aClasses);/** @noinspection HtmlUnknownAnchorTarget */$this->tabs[] ="<li class='$liClass'>" ."<a data-lang='$language->id' class='$aClass' href='#langTab_$id'>$title</a>" ."</li>";}/*** Render output for all added tabs** Note that if only 1 tab has been added, tabs won't be displayed (no point in it).* This method automatically calls resetTabs() after rendering.** @param Inputfield $inputfield* @param string $content Content that will have the tabs* @return string Modified $content with tabs**/public function renderTabs(Inputfield $inputfield, $content) {$settings = $this->getSettings();if(count($this->tabs) > 1) {$inputfield->wrapClass .= " hasLangTabs";$inputfield->contentClass .= " langTabsContainer";$tabs = implode('', $this->tabs);$id = $inputfield->attr('id');$note = "<small class='langTabsNote detail'><i class='fa fa-fw fa-angle-double-left'></i>" .$this->_('click twice to change all tabs') . "</small>";$attrs = $settings['ulAttrs'];$attrs .= $settings['ulClass'] ? " class='$settings[ulClass]'" : "";$attrs = strlen($attrs) ? " " . trim($attrs) : "";$content = "<div class='langTabs' id='langTabs_$id'>$note<ul$attrs>$tabs</ul>$content</div>";} else {// do nothing, just return content because there was only 1 tab (no render necessary)}$this->resetTabs();return $content;}/*** Module config** @param InputfieldWrapper $inputfields**/public function getModuleConfigInputfields(InputfieldWrapper $inputfields) {/** @var InputfieldSelect $f */$f = $this->wire()->modules->get('InputfieldSelect');$f->attr('name', 'tabField');$f->label = $this->_('Field to use for tab labels');$f->addOption('name');foreach($this->wire()->templates->get('language')->fieldgroup as $field) {/** @var Field $field */if($field->type instanceof FieldtypeMulti) continue;$f->addOption($field->name);}$f->attr('value', $this->tabField);$f->required = true;$inputfields->add($f);}}