2022-03-08 15:55:41 +01:00
|
|
|
<?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 2021 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' => 115,
|
|
|
|
'summary' => 'Organizes multi-language fields into tabs for a cleaner easier to use interface.',
|
|
|
|
'author' => 'adamspruijt, ryan',
|
|
|
|
'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;
|
|
|
|
|
|
|
|
// 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) $this->input->get('language');
|
|
|
|
if($id) $language = $this->languages->get($id);
|
|
|
|
|
|
|
|
// if language is not specified as a GET variable, then use the user's language
|
|
|
|
if(!$language || !$language->id) $language = $this->wire()->user->language;
|
|
|
|
|
|
|
|
// determine the index of the tab for the user's language
|
|
|
|
$activeTab = 0;
|
|
|
|
foreach($this->wire()->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'),
|
|
|
|
);
|
|
|
|
|
|
|
|
$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;
|
|
|
|
|
|
|
|
if($settings['jQueryUI']) {
|
|
|
|
$adminTheme = $this->wire('adminTheme');
|
|
|
|
if($adminTheme) $adminTheme->addBodyClass('LanguageTabsJqueryUI');
|
|
|
|
}
|
|
|
|
|
|
|
|
if($settings['loadStyles']) {
|
|
|
|
$config->styles->add($config->urls->LanguageTabs . 'LanguageTabs.css');
|
|
|
|
}
|
|
|
|
if($settings['loadScripts']) {
|
|
|
|
$config->scripts->add($config->urls->LanguageTabs . 'LanguageTabs.js');
|
|
|
|
}
|
|
|
|
|
|
|
|
/** @var JqueryCore $jQueryCore */
|
|
|
|
$jQueryCore = $this->wire()->modules->get('JqueryCore');
|
|
|
|
$jQueryCore->use('longclick');
|
|
|
|
|
|
|
|
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);
|
2022-11-05 18:32:48 +01:00
|
|
|
$title = $language->get(empty($settings['tabField']) ? $this->tabField : $settings['tabField']);
|
|
|
|
if(empty($title)) $title = $language->get("$this->tabField|name");
|
2022-03-08 15:55:41 +01:00
|
|
|
$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);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|