mirror of
https://github.com/processwire/processwire.git
synced 2025-08-26 16:14:35 +02:00
Various updates supporting core admin theme customization and bump version to 3.0.54
This commit is contained in:
@@ -116,24 +116,16 @@ abstract class AdminTheme extends WireData implements Module {
|
||||
// if admin theme has already been set, then no need to continue
|
||||
if($this->wire('adminTheme')) return;
|
||||
|
||||
$isCurrent = false;
|
||||
$adminTheme = $this->wire('user')->admin_theme;
|
||||
|
||||
if($adminTheme) {
|
||||
// there is user specified admin theme
|
||||
// check if this is the one that should be used
|
||||
if($adminTheme == $this->className()) $isCurrent = true;
|
||||
if($adminTheme == $this->className()) $this->setCurrent();
|
||||
|
||||
} else if($this->wire('config')->defaultAdminTheme == $this->className()) {
|
||||
// there is no user specified admin theme, so use this one
|
||||
$isCurrent = true;
|
||||
}
|
||||
|
||||
// set as an API variable and populate configuration variables
|
||||
if($isCurrent) {
|
||||
$this->wire('adminTheme', $this);
|
||||
$this->config->paths->set('adminTemplates', $this->config->paths->get($this->className()));
|
||||
$this->config->urls->set('adminTemplates', $this->config->urls->get($this->className()));
|
||||
$this->setCurrent();
|
||||
}
|
||||
|
||||
// adjust $config adminThumbOptions[scale] for auto detect when requested
|
||||
@@ -163,6 +155,19 @@ abstract class AdminTheme extends WireData implements Module {
|
||||
return $this->wire('adminTheme') === $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this admin theme as the current one
|
||||
*
|
||||
*/
|
||||
protected function setCurrent() {
|
||||
$config = $this->wire('config');
|
||||
$name = $this->className();
|
||||
$config->paths->set('adminTemplates', $config->paths->get($name));
|
||||
$config->urls->set('adminTemplates', $config->urls->get($name));
|
||||
$config->set('defaultAdminTheme', $name);
|
||||
$this->wire('adminTheme', $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables hooks to append extra markup to various sections of the admin page
|
||||
*
|
||||
@@ -186,9 +191,11 @@ abstract class AdminTheme extends WireData implements Module {
|
||||
"window.CKEDITOR_BASEPATH='" . $this->wire('config')->urls->InputfieldCKEditor .
|
||||
'ckeditor-' . InputfieldCKEditor::CKEDITOR_VERSION . "/';</script>";
|
||||
}
|
||||
/*
|
||||
if($isLoggedin && $this->wire('config')->advanced) {
|
||||
$parts['footer'] = "<p class='AdvancedMode'><i class='fa fa-flask'></i> " . $this->_('Advanced Mode') . "</p>";
|
||||
}
|
||||
*/
|
||||
foreach($this->preRenderURLs as $url) {
|
||||
$parts['head'] .= "<link rel='prerender' href='$url'>";
|
||||
}
|
||||
|
718
wire/core/AdminThemeFramework.php
Normal file
718
wire/core/AdminThemeFramework.php
Normal file
@@ -0,0 +1,718 @@
|
||||
<?php namespace ProcessWire;
|
||||
|
||||
/**
|
||||
* AdminTheme Framework
|
||||
*
|
||||
* The methods in this class may eventually be merged to AdminTheme.php,
|
||||
* but are isolated to this class during development.
|
||||
*
|
||||
* @property bool $isSuperuser
|
||||
* @property bool $isEditor
|
||||
* @property bool $isLoggedIn
|
||||
* @property bool $isModal
|
||||
* @property bool|int $useAsLogin
|
||||
* @method array getUserNavArray()
|
||||
*
|
||||
*/
|
||||
abstract class AdminThemeFramework extends AdminTheme {
|
||||
|
||||
/**
|
||||
* Is there currently a logged in user?
|
||||
*
|
||||
* @var bool
|
||||
*
|
||||
*/
|
||||
protected $isLoggedIn = false;
|
||||
|
||||
/**
|
||||
* Is user logged in with page-edit permission?
|
||||
*
|
||||
* @var bool
|
||||
*
|
||||
*/
|
||||
protected $isEditor = false;
|
||||
|
||||
/**
|
||||
* Is current user a superuser?
|
||||
*
|
||||
* @var bool
|
||||
*
|
||||
*/
|
||||
protected $isSuperuser = false;
|
||||
|
||||
/**
|
||||
* Is the current request a modal request?
|
||||
*
|
||||
* @var bool|string Either false, true, or "inline"
|
||||
*
|
||||
*/
|
||||
protected $isModal = false;
|
||||
|
||||
/**
|
||||
* @var Sanitizer
|
||||
*
|
||||
*/
|
||||
protected $sanitizer;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->set('useAsLogin', false);
|
||||
$this->wire('modules')->get('JqueryUI')->use('panel');
|
||||
$this->sanitizer = $this->wire('sanitizer');
|
||||
}
|
||||
|
||||
/**
|
||||
* Override get() method from WireData to support additional properties
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool|int|mixed|null|string
|
||||
*
|
||||
*/
|
||||
public function get($key) {
|
||||
switch($key) {
|
||||
case 'isSuperuser': $value = $this->isSuperuser; break;
|
||||
case 'isEditor': $value = $this->isEditor; break;
|
||||
case 'isLoggedIn': $value = $this->isLoggedIn; break;
|
||||
case 'isModal': $value = $this->isModal; break;
|
||||
default: $value = parent::get($key);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize and attach hooks
|
||||
*
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
$user = $this->wire('user');
|
||||
if(!$user->isLoggedin() && $this->useAsLogin) $this->setCurrent();
|
||||
parent::init();
|
||||
|
||||
// if this is not the current admin theme, exit now so no hooks are attached
|
||||
if(!$this->isCurrent()) return;
|
||||
|
||||
$this->isLoggedIn = $user->isLoggedin();
|
||||
$this->isSuperuser = $this->isLoggedIn && $user->isSuperuser();
|
||||
$this->isEditor = $this->isLoggedIn && ($this->isSuperuser || $user->hasPermission('page-edit'));
|
||||
|
||||
$modal = $this->wire('input')->get('modal');
|
||||
if($modal) $this->isModal = $modal == 'inline' ? 'inline' : true;
|
||||
|
||||
// test notices when requested
|
||||
if($this->wire('input')->get('test_notices')) $this->testNotices();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a translation, based on text from shared admin file: /wire/templates-admin/default.php
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function _($text) {
|
||||
static $translate = null;
|
||||
if(is_null($translate)) $translate = $this->wire('languages') !== null;
|
||||
if($translate === false) return $text;
|
||||
$value = __($text, $this->wire('config')->paths->root . 'wire/templates-admin/default.php');
|
||||
if($value === $text) $value = parent::_($text);
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current page headline
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function getHeadline() {
|
||||
$headline = $this->wire('processHeadline');
|
||||
if(!$headline) $headline = $this->wire('page')->get('title|name');
|
||||
return $this->sanitizer->entities1($headline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get navigation title for the given page, return blank if page should not be shown
|
||||
*
|
||||
* @param Page $p
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function getPageTitle(Page $p) {
|
||||
|
||||
if($p->name == 'add' && $p->parent->name == 'page') {
|
||||
// ProcessPageAdd: avoid showing this menu item if there are no predefined family settings to use
|
||||
$numAddable = $this->wire('session')->getFor('ProcessPageAdd', 'numAddable');
|
||||
if($numAddable === null) {
|
||||
/** @var ProcessPageAdd $processPageAdd */
|
||||
$processPageAdd = $this->wire('modules')->getModule('ProcessPageAdd', array('noInit' => true));
|
||||
if($processPageAdd) {
|
||||
$addData = $processPageAdd->executeNavJSON(array('getArray' => true));
|
||||
$numAddable = $addData['list'];
|
||||
}
|
||||
}
|
||||
if(!$numAddable) return '';
|
||||
$title = $this->getAddNewLabel();
|
||||
|
||||
} else {
|
||||
$title = $this->_($p->title);
|
||||
}
|
||||
|
||||
$title = $this->sanitizer->entities1($title);
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get icon used by the given page
|
||||
*
|
||||
* @param Page $p
|
||||
* @return mixed|null|string
|
||||
*
|
||||
*/
|
||||
public function getPageIcon(Page $p) {
|
||||
$icon = '';
|
||||
if($p->template == 'admin') {
|
||||
$info = $this->wire('modules')->getModuleInfo($p->process);
|
||||
if(!empty($info['icon'])) $icon = $info['icon'];
|
||||
}
|
||||
// allow for option of an admin field overriding the module icon
|
||||
$pageIcon = $p->get('page_icon');
|
||||
if($pageIcon) $icon = $pageIcon;
|
||||
if(!$icon) switch($p->id) {
|
||||
case 22: $icon = 'gears'; break; // Setup
|
||||
case 21: $icon = 'plug'; break; // Modules
|
||||
case 28: $icon = 'key'; break; // Access
|
||||
}
|
||||
if(!$icon && $p->parent->id != $this->wire('config')->adminRootPageID) {
|
||||
$icon = 'file-o ui-priority-secondary';
|
||||
}
|
||||
return $icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get “Add New” button actions
|
||||
*
|
||||
* - Returns array of arrays, each with 'url', 'label' and 'icon' properties.
|
||||
* - Returns empty array if Add New button should not be displayed.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function getAddNewActions() {
|
||||
|
||||
$page = $this->wire('page');
|
||||
$process = $this->wire('process');
|
||||
$input = $this->wire('input');
|
||||
|
||||
if(!$this->isEditor) return array();
|
||||
if($page->name != 'page' || $this->wire('input')->urlSegment1) return array();
|
||||
if($input->urlSegment1 || $input->get('modal')) return array();
|
||||
if(strpos($process, 'ProcessPageList') !== 0) return array();
|
||||
|
||||
/** @var ProcessPageAdd $module */
|
||||
$module = $this->wire('modules')->getModule('ProcessPageAdd', array('noInit' => true));
|
||||
$data = $module->executeNavJSON(array('getArray' => true));
|
||||
$actions = array();
|
||||
|
||||
foreach($data['list'] as $item) {
|
||||
$item['url'] = $data['url'] . $item['url'];
|
||||
$actions[] = $item;
|
||||
}
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the translated “Add New” label that’s used in a couple spots
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function getAddNewLabel() {
|
||||
return $this->_('Add New');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the classes that will be used in the <body class=''> tag
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function getBodyClass() {
|
||||
|
||||
$page = $this->wire('page');
|
||||
$process = $this->wire('process');
|
||||
|
||||
$classes = array(
|
||||
"id-{$page->id}",
|
||||
"template-{$page->template->name}",
|
||||
"pw-init",
|
||||
parent::getBodyClass(),
|
||||
);
|
||||
|
||||
if($this->isModal) $classes[] = 'modal';
|
||||
if($this->isModal === 'inline') $classes[] = 'modal-inline';
|
||||
if($this->wire('input')->urlSegment1) $classes[] = 'hasUrlSegments';
|
||||
if($process) $classes[] = $process->className();
|
||||
|
||||
return implode(' ', $classes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Javascript that must be present in the document <head>
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function getHeadJS() {
|
||||
|
||||
/** @var Config $config */
|
||||
$config = $this->wire('config');
|
||||
|
||||
/** @var Paths $urls */
|
||||
$urls = $config->urls;
|
||||
|
||||
/** @var array $jsConfig */
|
||||
$jsConfig = $config->js();
|
||||
$jsConfig['debug'] = $config->debug;
|
||||
|
||||
$jsConfig['urls'] = array(
|
||||
'root' => $urls->root,
|
||||
'admin' => $urls->admin,
|
||||
'modules' => $urls->modules,
|
||||
'core' => $urls->core,
|
||||
'files' => $urls->files,
|
||||
'templates' => $urls->templates,
|
||||
'adminTemplates' => $urls->adminTemplates,
|
||||
);
|
||||
|
||||
$out =
|
||||
"var ProcessWire = { config: " . wireEncodeJSON($jsConfig, true, $config->debug) . " }; " .
|
||||
"var config = ProcessWire.config;\n"; // legacy support
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allow the given Page to appear in admin theme navigation?
|
||||
*
|
||||
* @param Page $p Page to test
|
||||
* @param PageArray|array $children Children of page, if applicable (optional)
|
||||
* @param string|null $permission Specify required permission (optional)
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
public function allowPageInNav(Page $p, $children = array(), $permission = null) {
|
||||
|
||||
if($this->isSuperuser) return true;
|
||||
if($p->viewable()) return true;
|
||||
$allow = false;
|
||||
|
||||
foreach($children as $child) {
|
||||
if($child->viewable()) {
|
||||
$allow = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if($allow) return true;
|
||||
|
||||
if($permission === null && $p->process) {
|
||||
// determine permission
|
||||
$moduleInfo = $this->wire('modules')->getModuleInfo($p->process);
|
||||
if(!empty($moduleInfo['permission'])) $permission = $moduleInfo['permission'];
|
||||
}
|
||||
|
||||
if($permission) {
|
||||
$allow = $this->wire('user')->hasPermission($permission);
|
||||
}
|
||||
|
||||
return $allow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return nav array of primary navigation
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function getPrimaryNavArray() {
|
||||
|
||||
$items = array();
|
||||
$config = $this->wire('config');
|
||||
$admin = $this->wire('pages')->get($config->adminRootPageID);
|
||||
|
||||
foreach($admin->children("check_access=0") as $p) {
|
||||
$item = $this->pageToNavArray($p);
|
||||
if($item) $items[] = $item;
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get navigation array from a Process module
|
||||
*
|
||||
* @param array|Module|string $module Module info array or Module object or string
|
||||
* @param Page $p Page upon which the Process module is contained
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function moduleToNavArray($module, Page $p) {
|
||||
|
||||
$config = $this->wire('config');
|
||||
$modules = $this->wire('modules');
|
||||
$textdomain = str_replace($config->paths->root, '/', $modules->getModuleFile($p->process));
|
||||
$user = $this->wire('user');
|
||||
$navArray = array();
|
||||
|
||||
if(is_array($module)) {
|
||||
$moduleInfo = $module;
|
||||
} else {
|
||||
$moduleInfo = $modules->getModuleInfo($module);
|
||||
}
|
||||
|
||||
foreach($moduleInfo['nav'] as $navItem) {
|
||||
|
||||
$permission = empty($navItem['permission']) ? '' : $navItem['permission'];
|
||||
if($permission && !$user->hasPermission($permission)) continue;
|
||||
|
||||
$navArray[] = array(
|
||||
'id' => 0,
|
||||
'parent_id' => $p->id,
|
||||
'title' => $this->sanitizer->entities1(__($navItem['label'], $textdomain)), // translate from context of Process module
|
||||
'name' => '',
|
||||
'url' => $p->url . $navItem['url'],
|
||||
'icon' => empty($navItem['icon']) ? '' : $navItem['icon'],
|
||||
'children' => array(),
|
||||
'navJSON' => empty($navItem['navJSON']) ? '' : $p->url . $navItem['navJSON'],
|
||||
);
|
||||
}
|
||||
|
||||
return $navArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a navigation array the given Page, or null if page not allowed in nav
|
||||
*
|
||||
* @param Page $p
|
||||
* @return array|null
|
||||
*
|
||||
*/
|
||||
public function pageToNavArray(Page $p) {
|
||||
|
||||
$children = $p->numChildren ? $p->children("check_access=0") : array();
|
||||
|
||||
if(!$this->allowPageInNav($p, $children)) return null;
|
||||
|
||||
$navArray = array(
|
||||
'id' => $p->id,
|
||||
'parent_id' => $p->parent_id,
|
||||
'url' => $p->url,
|
||||
'name' => $p->name,
|
||||
'title' => $this->getPageTitle($p),
|
||||
'icon' => $this->getPageIcon($p),
|
||||
'children' => array(),
|
||||
'navJSON' => '',
|
||||
);
|
||||
|
||||
if(!count($children)) {
|
||||
// no children available
|
||||
if($p->template == 'admin' && $p->process) {
|
||||
// see if process module defines its own navigation
|
||||
$moduleInfo = $this->wire('modules')->getModuleInfo($p->process);
|
||||
if(!empty($moduleInfo['nav'])) {
|
||||
$navArray['children'] = $this->moduleToNavArray($moduleInfo, $p);
|
||||
}
|
||||
} else {
|
||||
// The /page/ and /page/list/ are the same process, so just keep them on /page/ instead.
|
||||
if(strpos($navArray['url'], '/page/list/') !== false) {
|
||||
$navArray['url'] = str_replace('/page/list/', '/page/', $navArray['url']);
|
||||
}
|
||||
}
|
||||
return $navArray;
|
||||
}
|
||||
|
||||
// if we reach this point, then we have a PageArray of children
|
||||
|
||||
$modules = $this->wire('modules');
|
||||
|
||||
foreach($children as $c) {
|
||||
|
||||
if(!$c->process) continue;
|
||||
$moduleInfo = $modules->getModuleInfo($c->process);
|
||||
$permission = empty($moduleInfo['permission']) ? '' : $moduleInfo['permission'];
|
||||
if(!$this->allowPageInNav($c, array(), $permission)) continue;
|
||||
|
||||
$childItem = array(
|
||||
'id' => $c->id,
|
||||
'parent_id' => $c->parent_id,
|
||||
'title' => $this->getPageTitle($c),
|
||||
'name' => $c->name,
|
||||
'url' => $c->url,
|
||||
'icon' => $this->getPageIcon($c),
|
||||
'children' => array(),
|
||||
'navJSON' => empty($moduleInfo['useNavJSON']) ? '' : $c->url . 'navJSON/',
|
||||
);
|
||||
|
||||
if(!empty($moduleInfo['nav'])) {
|
||||
$childItem['children'] = $this->moduleToNavArray($moduleInfo, $c); // @todo should $p be $c?
|
||||
}
|
||||
|
||||
$navArray['children'][] = $childItem;
|
||||
|
||||
} // foreach
|
||||
|
||||
return $navArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get navigation items for the “user” menu
|
||||
*
|
||||
* This is hookable so that something else could add stuff to it.
|
||||
* See the method body for details on format used.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function ___getUserNavArray() {
|
||||
$urls = $this->wire('urls');
|
||||
$navArray = array();
|
||||
|
||||
$navArray[] = array(
|
||||
'url' => $urls->root,
|
||||
'title' => $this->_('View site'),
|
||||
'icon' => 'eye',
|
||||
);
|
||||
|
||||
if($this->wire('user')->hasPermission('profile-edit')) $navArray[] = array(
|
||||
'url' => $urls->admin . 'profile/',
|
||||
'title' => $this->_('Profile'),
|
||||
'icon' => 'user',
|
||||
'permission' => 'profile-edit',
|
||||
);
|
||||
|
||||
$navArray[] = array(
|
||||
'url' => $urls->admin . 'login/logout/',
|
||||
'title' => $this->_('Logout'),
|
||||
'icon' => 'power-off',
|
||||
);
|
||||
|
||||
return $navArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the browser <title>
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function getBrowserTitle() {
|
||||
|
||||
$browserTitle = $this->wire('processBrowserTitle');
|
||||
$modal = $this->wire('input')->get('modal');
|
||||
|
||||
if(!$browserTitle) {
|
||||
if($modal) return $this->wire('processHeadline');
|
||||
$browserTitle = $this->_(strip_tags($this->wire('page')->get('title|name'))) . ' • ProcessWire';
|
||||
}
|
||||
|
||||
if(!$modal) {
|
||||
$httpHost = $this->wire('config')->httpHost;
|
||||
if(strpos($httpHost, 'www.') === 0) $httpHost = substr($httpHost, 4); // remove www
|
||||
if(strpos($httpHost, ':')) $httpHost = preg_replace('/:\d+/', '', $httpHost); // remove port
|
||||
$browserTitle .= " • $httpHost";
|
||||
}
|
||||
|
||||
return $this->sanitizer->entities1($browserTitle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test all notice types
|
||||
*
|
||||
*/
|
||||
public function testNotices() {
|
||||
if(!$this->wire('user')->isLoggedin()) return;
|
||||
$this->message('Message test');
|
||||
$this->message('Message test debug', Notice::debug);
|
||||
$this->message('Message test markup <a href="#">example</a>', Notice::allowMarkup);
|
||||
$this->warning('Warning test');
|
||||
$this->warning('Warning test debug', Notice::debug);
|
||||
$this->warning('Warning test markup <a href="#">example</a>', Notice::allowMarkup);
|
||||
$this->error('Error test');
|
||||
$this->error('Error test debug', Notice::debug);
|
||||
$this->error('Error test markup <a href="#">example</a>', Notice::allowMarkup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render runtime notices div#notices
|
||||
*
|
||||
* @param array $options See defaults in method
|
||||
* @param Notices $notices
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function renderNotices($notices, array $options = array()) {
|
||||
|
||||
if(!count($notices)) return '';
|
||||
|
||||
if($this->isLoggedIn && $this->wire('modules')->isInstalled('SystemNotifications')) {
|
||||
$systemNotifications = $this->wire('modules')->get('SystemNotifications');
|
||||
if(!$systemNotifications->placement) return '';
|
||||
}
|
||||
|
||||
$defaults = array(
|
||||
'messageClass' => 'NoticeMessage', // class for messages
|
||||
'messageIcon' => 'check-square', // default icon to show with notices
|
||||
'warningClass' => 'NoticeWarning', // class for warnings
|
||||
'warningIcon' => 'exclamation-circle', // icon for warnings
|
||||
'errorClass' => 'NoticeError', // class for errors
|
||||
'errorIcon' => 'exclamation-triangle', // icon for errors
|
||||
'debugClass' => 'NoticeDebug', // class for debug items (appended)
|
||||
'debugIcon' => 'bug', // icon for debug notices
|
||||
'closeClass' => 'notice-remove', // class for close notices link <a>
|
||||
'closeIcon' => 'times', // icon for close notices link
|
||||
'listMarkup' => "<ul class='pw-notices' id='notices'>{out}</ul><!--/notices-->",
|
||||
'itemMarkup' => "<li class='{class}'>{remove}{icon}{text}</li>"
|
||||
);
|
||||
|
||||
$options = array_merge($defaults, $options);
|
||||
$config = $this->wire('config');
|
||||
$out = '';
|
||||
|
||||
foreach($notices as $n => $notice) {
|
||||
|
||||
$text = $notice->text;
|
||||
if($notice->flags & Notice::allowMarkup) {
|
||||
// leave $text alone
|
||||
} else {
|
||||
// unencode + re-encode entities, just in case module already entity some or all of output
|
||||
if(strpos($text, '&') !== false) $text = $this->sanitizer->unentities($text);
|
||||
$text = $this->sanitizer->entities($text);
|
||||
}
|
||||
|
||||
if($notice instanceof NoticeError) {
|
||||
$class = $options['errorClass'];
|
||||
$icon = $options['errorIcon'];
|
||||
|
||||
} else if($notice instanceof NoticeWarning) {
|
||||
$class = $options['warningClass'];
|
||||
$icon = $options['warningIcon'];
|
||||
|
||||
} else {
|
||||
$class = $options['messageClass'];
|
||||
$icon = $options['messageIcon'];
|
||||
}
|
||||
|
||||
if($notice->flags & Notice::debug) {
|
||||
$class .= " " . $options['debugClass'];
|
||||
$icon = $options['debugIcon'];
|
||||
}
|
||||
|
||||
// indicate which class the notice originated from in debug mode
|
||||
if($notice->class && $config->debug) $text = "{$notice->class}: $text";
|
||||
|
||||
// show remove link for first item only
|
||||
if($n) {
|
||||
$remove = '';
|
||||
} else {
|
||||
$removeIcon = $this->renderIcon($options['closeIcon']);
|
||||
$removeLabel = $this->_('Close all');
|
||||
$remove = "<a class='$options[closeClass]' href='#' title='$removeLabel'>$removeIcon</a>";
|
||||
}
|
||||
|
||||
$replacements = array(
|
||||
'{class}' => $class,
|
||||
'{remove}' => $remove,
|
||||
'{icon}' => $this->renderNavIcon($notice->icon ? $notice->icon : $icon),
|
||||
'{text}' => $text,
|
||||
);
|
||||
|
||||
$out .= str_replace(array_keys($replacements), array_values($replacements), $options['itemMarkup']);
|
||||
}
|
||||
|
||||
$out = str_replace('{out}', $out, $options['listMarkup']);
|
||||
$out .= $this->renderExtraMarkup('notices');
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render markup for a font-awesome icon
|
||||
*
|
||||
* @param string $icon Name of icon to render, excluding the “fa-” prefix
|
||||
* @param bool $fw Specify true to make fixed width (default=false).
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function renderIcon($icon, $fw = false) {
|
||||
if($fw) $icon .= ' fa-fw';
|
||||
return "<i class='fa fa-$icon'></i>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Render markup for a font-awesome icon that precedes a navigation label
|
||||
*
|
||||
* This is the same as renderIcon() except that fixed-width is assumed and a "nav-nav-icon"
|
||||
* class is added to it.
|
||||
*
|
||||
* @param string $icon Name of icon to render, excluding the “fa-” prefix
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function renderNavIcon($icon) {
|
||||
return $this->renderIcon("$icon pw-nav-icon", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render an extra markup region
|
||||
*
|
||||
* @param string $for
|
||||
* @return mixed|string
|
||||
*
|
||||
*/
|
||||
public function renderExtraMarkup($for) {
|
||||
static $extras = array();
|
||||
if(empty($extras)) $extras = $this->getExtraMarkup();
|
||||
return isset($extras[$for]) ? $extras[$for] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Module Configuration
|
||||
*
|
||||
* @param InputfieldWrapper $inputfields
|
||||
*
|
||||
*/
|
||||
public function getModuleConfigInputfields(InputfieldWrapper $inputfields) {
|
||||
|
||||
/** @var InputfieldCheckbox $f */
|
||||
$f = $this->modules->get('InputfieldCheckbox');
|
||||
$f->name = 'useAsLogin';
|
||||
$f->label = $this->_('Use this admin theme for login screen?');
|
||||
$f->description = $this->_('When checked, this admin theme will be used on the user login screen.');
|
||||
$f->icon = 'sign-in';
|
||||
$f->collapsed = Inputfield::collapsedBlank;
|
||||
if($this->get('useAsLogin')) $f->attr('checked', 'checked');
|
||||
$inputfields->add($f);
|
||||
|
||||
if($f->attr('checked') && $this->input->requestMethod('GET')) {
|
||||
$class = $this->className();
|
||||
foreach($this->modules->findByPrefix('AdminTheme') as $name) {
|
||||
if($name == $class) continue;
|
||||
$cfg = $this->modules->getConfig($name);
|
||||
if(!empty($cfg['useAsLogin'])) {
|
||||
unset($cfg['useAsLogin']);
|
||||
$this->modules->saveConfig($name, $cfg);
|
||||
$this->message("Removed 'useAsLogin' setting from $name", Notice::debug);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -45,7 +45,7 @@ class ProcessWire extends Wire {
|
||||
* Reversion revision number
|
||||
*
|
||||
*/
|
||||
const versionRevision = 53;
|
||||
const versionRevision = 54;
|
||||
|
||||
/**
|
||||
* Version suffix string (when applicable)
|
||||
@@ -282,7 +282,7 @@ class ProcessWire extends Wire {
|
||||
if($config->useFunctionsAPI) {
|
||||
$file = $config->paths->core . 'FunctionsAPI.php';
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include($file);
|
||||
include_once($file);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -35,6 +35,7 @@
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.pw-init .InputfieldAsmSelect select[multiple],
|
||||
.pw-fouc-fix .InputfieldAsmSelect select[multiple] {
|
||||
display: none;
|
||||
}
|
||||
|
@@ -116,8 +116,13 @@
|
||||
// existing link
|
||||
$existingLink = jQuery(node.$);
|
||||
selectionText = node.getHtml();
|
||||
selection.selectElement(node);
|
||||
|
||||
selection.selectElement(node);
|
||||
} else if(nodeName == 'td' || nodeName == 'th' || nodeName == 'tr') {
|
||||
var firstChar = selectionText.substring(0,1);
|
||||
if(firstChar == "\n" || firstChar == "\r") {
|
||||
ProcessWire.alert('Your selection includes part of the table. Please try selecting the text again.');
|
||||
return;
|
||||
}
|
||||
} else if(nodeName == 'img') {
|
||||
// linked image
|
||||
var $img = jQuery(node.$);
|
||||
|
@@ -1 +1 @@
|
||||
(function(){CKEDITOR.plugins.add("pwlink",{requires:"dialog,fakeobjects",init:function(b){var d="a[!href,target,name,title,rel]";var c="a[href]";var e=ProcessWire.config.InputfieldCKEditor.pwlink.classOptions;if(e.length){d+="("+e+")"}b.addCommand("pwlink",{allowedContent:d,requiredContent:c,exec:a});b.addCommand("anchor",new CKEDITOR.dialogCommand("anchor",{allowedContent:"a[!name,id]",requiredContent:"a[name]"}));b.addCommand("unlink",new CKEDITOR.unlinkCommand());b.addCommand("removeAnchor",new CKEDITOR.removeAnchorCommand());b.setKeystroke(CKEDITOR.CTRL+76,"pwlink");if(b.ui.addButton){b.ui.addButton("PWLink",{label:b.lang.link.toolbar,command:"pwlink",toolbar:"links,10",hidpi:true,icon:(CKEDITOR.env.hidpi?this.path+"images/hidpi/pwlink.png":this.path+"images/pwlink.png")});b.ui.addButton("Unlink",{label:b.lang.link.unlink,command:"unlink",toolbar:"links,20"});b.ui.addButton("Anchor",{label:b.lang.link.anchor.toolbar,command:"anchor",toolbar:"links,30"})}b.on("doubleclick",function(f){var g=CKEDITOR.plugins.link.getSelectedLink(b)||f.data.element;if(g.is("a")&&!g.getAttribute("name")&&!g.isReadOnly()){var h=jQuery(g.$);if(h.children("img").length==0){f.cancel();b.commands.pwlink.exec()}}});b.on("instanceReady",function(f){f.editor.removeMenuItem("link")});if(b.contextMenu){b.addMenuItem("pwlinkitem",{label:ProcessWire.config.InputfieldCKEditor.pwlink.edit,command:"pwlink",group:"link",icon:(CKEDITOR.env.hidpi?this.path+"images/hidpi/pwlink.png":this.path+"images/pwlink.png")});b.contextMenu.addListener(function(g){if(!g||g.isReadOnly()){return null}var f=CKEDITOR.plugins.link.tryRestoreFakeAnchor(b,g);var h={};if(!f&&!(f=CKEDITOR.plugins.link.getSelectedLink(b))){return null}if(f.getAttribute("href")&&f.getChildCount()){h={pwlinkitem:CKEDITOR.TRISTATE_OFF}}return h})}}});function a(g){var i=jQuery("#Inputfield_id");if(i.length){var f=i.val()}else{var f=jQuery("#"+g.name).closest(".Inputfield").attr("data-pid")}var u=jQuery("#"+g.name);var v=g.getSelection(true);var s=v.getStartElement();var b=s.getName();var j=v.getSelectedText();var t=null;var p=CKEDITOR.plugins.link.getEditorAnchors(g);if(b=="a"){t=jQuery(s.$);j=s.getHtml();v.selectElement(s)}else{if(b=="img"){var k=jQuery(s.$);t=k.parent("a");j=s.$.outerHTML}else{if(j.length<1){return}else{}}}var m=ProcessWire.config.urls.admin+"page/link/?id="+f+"&modal=1";var d=u.closest(".LanguageSupport");if(d.length){m+="&lang="+d.data("language")}if(t!=null){var q=["href","title","class","rel","target"];for(var r=0;r<q.length;r++){var w=t.attr(q[r]);if(w&&w.length){m+="&"+q[r]+"="+encodeURIComponent(w)}}}if(p.length>0){for(var r=0;r<p.length;r++){m+="&anchors[]="+encodeURIComponent(p[r].id)}}var c=ProcessWire.config.InputfieldCKEditor.pwlink.label;var l=ProcessWire.config.InputfieldCKEditor.pwlink.cancel;var o;function h(){var y=o.contents();var x=jQuery(jQuery("#link_markup",y).text());if(x.attr("href")&&x.attr("href").length){x.html(j);var n=jQuery("<div />").append(x).html();g.insertHtml(n)}o.dialog("close")}var e={title:"<i class='fa fa-link'></i> "+c,open:function(){if(jQuery(".cke_maximized").length>0){jQuery(".ui-dialog").css("z-index",9999);jQuery(".ui-widget-overlay").css("z-index",9998)}},buttons:[{"class":"pw_link_submit_insert",html:"<i class='fa fa-link'></i> "+c,click:h},{html:"<i class='fa fa-times-circle'></i> "+l,click:function(){o.dialog("close")},"class":"ui-priority-secondary"}]};var o=pwModalWindow(m,e,"medium");o.load(function(){var n=o.contents();n.find("#ProcessPageEditLinkForm").data("iframe",o);jQuery("#link_page_url",n).keydown(function(x){var y=jQuery(this);var z=jQuery.trim(y.val());if(x.keyCode==13){x.preventDefault();if(z.length>0){h()}return false}})})}})();
|
||||
(function(){CKEDITOR.plugins.add("pwlink",{requires:"dialog,fakeobjects",init:function(b){var d="a[!href,target,name,title,rel]";var c="a[href]";var e=ProcessWire.config.InputfieldCKEditor.pwlink.classOptions;if(e.length){d+="("+e+")"}b.addCommand("pwlink",{allowedContent:d,requiredContent:c,exec:a});b.addCommand("anchor",new CKEDITOR.dialogCommand("anchor",{allowedContent:"a[!name,id]",requiredContent:"a[name]"}));b.addCommand("unlink",new CKEDITOR.unlinkCommand());b.addCommand("removeAnchor",new CKEDITOR.removeAnchorCommand());b.setKeystroke(CKEDITOR.CTRL+76,"pwlink");if(b.ui.addButton){b.ui.addButton("PWLink",{label:b.lang.link.toolbar,command:"pwlink",toolbar:"links,10",hidpi:true,icon:(CKEDITOR.env.hidpi?this.path+"images/hidpi/pwlink.png":this.path+"images/pwlink.png")});b.ui.addButton("Unlink",{label:b.lang.link.unlink,command:"unlink",toolbar:"links,20"});b.ui.addButton("Anchor",{label:b.lang.link.anchor.toolbar,command:"anchor",toolbar:"links,30"})}b.on("doubleclick",function(f){var g=CKEDITOR.plugins.link.getSelectedLink(b)||f.data.element;if(g.is("a")&&!g.getAttribute("name")&&!g.isReadOnly()){var h=jQuery(g.$);if(h.children("img").length==0){f.cancel();b.commands.pwlink.exec()}}});b.on("instanceReady",function(f){f.editor.removeMenuItem("link")});if(b.contextMenu){b.addMenuItem("pwlinkitem",{label:ProcessWire.config.InputfieldCKEditor.pwlink.edit,command:"pwlink",group:"link",icon:(CKEDITOR.env.hidpi?this.path+"images/hidpi/pwlink.png":this.path+"images/pwlink.png")});b.contextMenu.addListener(function(g){if(!g||g.isReadOnly()){return null}var f=CKEDITOR.plugins.link.tryRestoreFakeAnchor(b,g);var h={};if(!f&&!(f=CKEDITOR.plugins.link.getSelectedLink(b))){return null}if(f.getAttribute("href")&&f.getChildCount()){h={pwlinkitem:CKEDITOR.TRISTATE_OFF}}return h})}}});function a(g){var i=jQuery("#Inputfield_id");if(i.length){var f=i.val()}else{var f=jQuery("#"+g.name).closest(".Inputfield").attr("data-pid")}var u=jQuery("#"+g.name);var w=g.getSelection(true);var s=w.getStartElement();var c=s.getName();var j=w.getSelectedText();var t=null;var p=CKEDITOR.plugins.link.getEditorAnchors(g);if(c=="a"){t=jQuery(s.$);j=s.getHtml();w.selectElement(s)}else{if(c=="td"||c=="th"||c=="tr"){var v=j.substring(0,1);if(v=="\n"||v=="\r"){ProcessWire.alert("Your selection includes part of the table. Please try selecting the text again.");return}}else{if(c=="img"){var k=jQuery(s.$);t=k.parent("a");j=s.$.outerHTML}else{if(j.length<1){return}else{}}}}var m=ProcessWire.config.urls.admin+"page/link/?id="+f+"&modal=1";var d=u.closest(".LanguageSupport");if(d.length){m+="&lang="+d.data("language")}if(t!=null){var q=["href","title","class","rel","target"];for(var r=0;r<q.length;r++){var x=t.attr(q[r]);if(x&&x.length){m+="&"+q[r]+"="+encodeURIComponent(x)}}}if(p.length>0){for(var r=0;r<p.length;r++){m+="&anchors[]="+encodeURIComponent(p[r].id)}}var b=ProcessWire.config.InputfieldCKEditor.pwlink.label;var l=ProcessWire.config.InputfieldCKEditor.pwlink.cancel;var o;function h(){var z=o.contents();var y=jQuery(jQuery("#link_markup",z).text());if(y.attr("href")&&y.attr("href").length){y.html(j);var n=jQuery("<div />").append(y).html();g.insertHtml(n)}o.dialog("close")}var e={title:"<i class='fa fa-link'></i> "+b,open:function(){if(jQuery(".cke_maximized").length>0){jQuery(".ui-dialog").css("z-index",9999);jQuery(".ui-widget-overlay").css("z-index",9998)}},buttons:[{"class":"pw_link_submit_insert",html:"<i class='fa fa-link'></i> "+b,click:h},{html:"<i class='fa fa-times-circle'></i> "+l,click:function(){o.dialog("close")},"class":"ui-priority-secondary"}]};var o=pwModalWindow(m,e,"medium");o.load(function(){var n=o.contents();n.find("#ProcessPageEditLinkForm").data("iframe",o);jQuery("#link_page_url",n).keydown(function(y){var z=jQuery(this);var A=jQuery.trim(z.val());if(y.keyCode==13){y.preventDefault();if(A.length>0){h()}return false}})})}})();
|
@@ -37,6 +37,7 @@ class InputfieldCheckboxes extends InputfieldSelectMultiple implements Inputfiel
|
||||
$inline = $columns === 1 || $columns > 10;
|
||||
$liAttr = '';
|
||||
$ulClass = '';
|
||||
$inputClass = $this->wire('sanitizer')->entities($this->attr('class'));
|
||||
$entityEncode = $this->getSetting('entityEncodeText') === false ? false : true;
|
||||
|
||||
if($this->table) {
|
||||
@@ -69,7 +70,7 @@ class InputfieldCheckboxes extends InputfieldSelectMultiple implements Inputfiel
|
||||
$checked = '';
|
||||
|
||||
if($this->isOptionSelected($key)) $checked = " checked='checked'";
|
||||
$id = $this->id . "_" . $this->wire('sanitizer')->name($key);
|
||||
$id = $this->id . "_" . $this->wire('sanitizer')->name($key);
|
||||
|
||||
$attrs = $this->getOptionAttributes($key);
|
||||
$disabled = empty($attrs['disabled']) ? '' : " disabled='disabled'";
|
||||
@@ -85,6 +86,7 @@ class InputfieldCheckboxes extends InputfieldSelectMultiple implements Inputfiel
|
||||
"type='checkbox' " .
|
||||
"name='{$this->name}[]' " .
|
||||
"id='$id' " .
|
||||
"class='$inputClass' " .
|
||||
"value='" . htmlspecialchars($key, ENT_QUOTES, 'UTF-8') . "' />";
|
||||
|
||||
if($table) {
|
||||
|
@@ -399,18 +399,27 @@ $(document).ready(function() {
|
||||
this.value = '';
|
||||
}, false);
|
||||
|
||||
dropArea.addEventListener("dragleave", function() { $(this).removeClass('ui-state-hover'); }, false);
|
||||
dropArea.addEventListener("dragenter", function() { $(this).addClass('ui-state-hover'); }, false);
|
||||
dropArea.addEventListener("dragleave", function() {
|
||||
$(this).removeClass('ui-state-hover');
|
||||
$(this).closest('.Inputfield').removeClass('pw-drag-in-file');
|
||||
}, false);
|
||||
dropArea.addEventListener("dragenter", function() {
|
||||
$(this).addClass('ui-state-hover');
|
||||
$(this).closest('.Inputfield').addClass('pw-drag-in-file InputfieldStateConfirmLeave');
|
||||
}, false);
|
||||
|
||||
dropArea.addEventListener("dragover", function (evt) {
|
||||
if(!$(this).is('ui-state-hover')) $(this).addClass('ui-state-hover');
|
||||
if(!$(this).is('ui-state-hover')) {
|
||||
$(this).addClass('ui-state-hover');
|
||||
$(this).closest('.Inputfield').addClass('pw-drag-in-file');
|
||||
}
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
}, false);
|
||||
|
||||
dropArea.addEventListener("drop", function (evt) {
|
||||
traverseFiles(evt.dataTransfer.files);
|
||||
$(this).removeClass("ui-state-hover");
|
||||
$(this).removeClass("ui-state-hover").closest('.Inputfield').removeClass('pw-drag-in-file InputfieldStateConfirmLeave');
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
}, false);
|
||||
|
File diff suppressed because one or more lines are too long
@@ -79,6 +79,14 @@ class InputfieldFile extends Inputfield implements InputfieldItemList, Inputfiel
|
||||
|
||||
protected $isAjax = false;
|
||||
|
||||
/**
|
||||
* Admin theme specific settings
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $themeSettings = array();
|
||||
|
||||
/**
|
||||
* Commonly used text labels, translated, indexed by label name
|
||||
*
|
||||
@@ -142,6 +150,12 @@ class InputfieldFile extends Inputfield implements InputfieldItemList, Inputfiel
|
||||
$this->uploadOnlyMode = (int) $this->wire('input')->get('uploadOnlyMode');
|
||||
$this->addClass('InputfieldItemList', 'wrapClass');
|
||||
$this->addClass('InputfieldHasFileList', 'wrapClass');
|
||||
|
||||
$themeDefaults = array(
|
||||
'error' => "<span class='ui-state-error-text'>{out}</span>",
|
||||
);
|
||||
$themeSettings = $this->wire('config')->InputfieldFile;
|
||||
$this->themeSettings = is_array($themeSettings) ? array_merge($themeDefaults, $themeSettings) : $themeDefaults;
|
||||
}
|
||||
|
||||
public function get($key) {
|
||||
@@ -209,6 +223,7 @@ class InputfieldFile extends Inputfield implements InputfieldItemList, Inputfiel
|
||||
$out = '';
|
||||
$tabs = '';
|
||||
static $hasLangTabs = null;
|
||||
static $langTabSettings = array();
|
||||
|
||||
if($this->renderValueMode) {
|
||||
if($this->wire('languages')) {
|
||||
@@ -231,7 +246,12 @@ class InputfieldFile extends Inputfield implements InputfieldItemList, Inputfiel
|
||||
$languages = array(null);
|
||||
} else {
|
||||
$numLanguages = $languages->count();
|
||||
if(is_null($hasLangTabs)) $hasLangTabs = $this->wire('modules')->isInstalled('LanguageTabs');
|
||||
if(is_null($hasLangTabs)) {
|
||||
$hasLangTabs = $this->wire('modules')->isInstalled('LanguageTabs');
|
||||
if($hasLangTabs) {
|
||||
$langTabSettings = $this->wire('modules')->getModule('LanguageTabs')->getSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach($languages as $language) {
|
||||
@@ -241,7 +261,8 @@ class InputfieldFile extends Inputfield implements InputfieldItemList, Inputfiel
|
||||
$labelClass = "detail";
|
||||
|
||||
if($language) {
|
||||
$descriptionFieldLabel = (string) $language->getUnformatted('title');
|
||||
$tabField = empty($langTabSettings['tabField']) ? 'title' : $langTabSettings['tabField'];
|
||||
$descriptionFieldLabel = (string) $language->getUnformatted($tabField);
|
||||
if(empty($descriptionFieldLabel)) $descriptionFieldLabel = $language->get('name');
|
||||
$descriptionFieldLabel = $this->wire('sanitizer')->entities($descriptionFieldLabel);
|
||||
if(!$language->isDefault()) $descriptionFieldName = "description{$language->id}_$id";
|
||||
@@ -251,7 +272,9 @@ class InputfieldFile extends Inputfield implements InputfieldItemList, Inputfiel
|
||||
$descriptionFieldLabel = "<s>$descriptionFieldLabel</s>";
|
||||
}
|
||||
$tabID = "langTab_{$id}__$language";
|
||||
$tabs .= "<li><a data-lang='$language' class='langTab$language' href='#$tabID'>$descriptionFieldLabel</a></li>";
|
||||
$aClass = "langTab$language";
|
||||
if(!empty($langTabSettings['aClass'])) $aClass .= " " . $langTabSettings['aClass'];
|
||||
$tabs .= "<li><a data-lang='$language' class='$aClass' href='#$tabID'>$descriptionFieldLabel</a></li>";
|
||||
$out .= "<div class='InputfieldFileDescription LanguageSupport' data-language='$language' id='$tabID'>"; // open wrapper
|
||||
} else {
|
||||
$out .= "<div class='InputfieldFileDescription'>"; // open wrapper
|
||||
@@ -271,7 +294,9 @@ class InputfieldFile extends Inputfield implements InputfieldItemList, Inputfiel
|
||||
}
|
||||
|
||||
if($numLanguages && $hasLangTabs) {
|
||||
$out = "<div class='hasLangTabs langTabsContainer'><div class='langTabs'><ul>$tabs</ul>$out</div></div>";
|
||||
$ulClass = empty($langTabSettings['ulClass']) ? '' : " class='$langTabSettings[ulClass]'";
|
||||
$ulAttr = empty($langTabSettings['ulAttrs']) ? '' : " $langTabSettings[ulAttrs]";
|
||||
$out = "<div class='hasLangTabs langTabsContainer'><div class='langTabs'><ul $ulAttr$ulClass>$tabs</ul>$out</div></div>";
|
||||
if($this->isAjax) $out .= "<script>setupLanguageTabs($('#wrap_" . $this->attr('id') . "'));</script>";
|
||||
}
|
||||
|
||||
@@ -328,7 +353,7 @@ class InputfieldFile extends Inputfield implements InputfieldItemList, Inputfiel
|
||||
|
||||
$out =
|
||||
"<p class='InputfieldFileInfo InputfieldItemHeader ui-state-default ui-widget-header'>" .
|
||||
wireIconMarkupFile($pagefile->basename, "fa-fw HideIfEmpty") .
|
||||
wireIconMarkupFile($pagefile->basename, "fa-fw HideIfEmpty") . ' ' .
|
||||
"<a class='InputfieldFileName' title='$pagefile->basename' target='_blank' href='{$pagefile->url}'>$displayName</a> " .
|
||||
"<span class='InputfieldFileStats'>" . str_replace(' ', ' ', $pagefile->filesizeStr) . "</span> ";
|
||||
|
||||
@@ -443,7 +468,7 @@ class InputfieldFile extends Inputfield implements InputfieldItemList, Inputfiel
|
||||
if(!$this->noAjax) $out .= "
|
||||
<span class='AjaxUploadDropHere description'>
|
||||
<span>
|
||||
<i class='fa fa-upload'></i> $dragDropLabel
|
||||
<i class='fa fa-cloud-upload'></i> $dragDropLabel
|
||||
</span>
|
||||
</span>
|
||||
";
|
||||
|
@@ -80,7 +80,6 @@ class InputfieldImage extends InputfieldFile implements InputfieldItemList, Inpu
|
||||
*/
|
||||
protected $modalClass = 'pw-modal-large';
|
||||
|
||||
protected $themeSettings = array();
|
||||
|
||||
public function init() {
|
||||
parent::init();
|
||||
@@ -126,15 +125,15 @@ class InputfieldImage extends InputfieldFile implements InputfieldItemList, Inpu
|
||||
'na' => $this->_('N/A'), // for JS
|
||||
'changes' => $this->_('This images field may have unsaved changes that could be lost after this action. Please save before cropping, or double-click the button proceed anyway.'),
|
||||
));
|
||||
|
||||
|
||||
$themeDefaults = array(
|
||||
'error' => "<span class='ui-state-error-text'>{out}</span>",
|
||||
// 'error' => "<span class='ui-state-error-text'>{out}</span>", // provided by InputfieldFile
|
||||
'buttonClass' => "ui-button ui-corner-all ui-state-default",
|
||||
'buttonText' => "<span class='ui-button-text'>{out}</span>",
|
||||
);
|
||||
$themeSettings = $this->wire('config')->InputfieldImage;
|
||||
$this->themeSettings = is_array($themeSettings) ? array_merge($themeDefaults, $themeSettings) : $themeDefaults;
|
||||
|
||||
$themeSettings = is_array($themeSettings) ? array_merge($themeDefaults, $themeSettings) : $themeDefaults;
|
||||
$this->themeSettings = array_merge($this->themeSettings, $themeSettings);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -67,6 +67,7 @@ class InputfieldRadios extends InputfieldSelect {
|
||||
$label = $this->entityEncode($label, Inputfield::textFormatBasic);
|
||||
$label = str_replace('!wbr!', '<wbr>', $label);
|
||||
$label = "<span class='$textClass'>$label</span>";
|
||||
$class = trim($this->wire('sanitizer')->entities($this->attr('class')));
|
||||
|
||||
$out .=
|
||||
"<li$liAttr><label$attrs>" .
|
||||
@@ -74,6 +75,7 @@ class InputfieldRadios extends InputfieldSelect {
|
||||
"type='radio' " .
|
||||
"name='{$this->name}' " .
|
||||
"id='$id' " .
|
||||
"class='$class' " .
|
||||
"value='" . htmlspecialchars($key, ENT_QUOTES) . "' />" .
|
||||
"<span class='$textClass'>$label</span>" .
|
||||
"</label></li>";
|
||||
|
@@ -7,8 +7,9 @@
|
||||
* https://processwire.com
|
||||
* License: MPL 2.0
|
||||
*
|
||||
* @property bool $header Whether or not button will also appear in header.
|
||||
* @property bool $secondary Whether or not button is secondary.
|
||||
* @property bool $header Whether or not button will also appear in header (default=false).
|
||||
* @property bool $secondary Whether or not button is secondary (default=false).
|
||||
* @property bool $small Whether or not button should be small, where supported (default=false).
|
||||
* @property string $dropdownInputName #pw-internal
|
||||
*
|
||||
*/
|
||||
@@ -42,6 +43,7 @@ class InputfieldSubmit extends Inputfield {
|
||||
$this->attr('value', $this->_('Submit')); // Standard submit button label
|
||||
$this->attr('class', 'ui-button ui-widget ui-state-default ui-corner-all');
|
||||
$this->skipLabel = Inputfield::skipLabelBlank;
|
||||
$this->set('small', false);
|
||||
|
||||
// name of 'hidden' input that will receive the clicked dropdown item value
|
||||
$this->set('dropdownInputName', '_action_value');
|
||||
@@ -95,6 +97,21 @@ class InputfieldSubmit extends Inputfield {
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make this button small?
|
||||
*
|
||||
* By default, buttons are regular size. This makes them small.
|
||||
* Supported only for non-dropdown, non-header buttons.
|
||||
*
|
||||
* @param bool $small Default=true
|
||||
* @return $this
|
||||
*
|
||||
*/
|
||||
public function setSmall($small = true) {
|
||||
$this->set('small', $small ? true : false);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render ready
|
||||
@@ -111,6 +128,9 @@ class InputfieldSubmit extends Inputfield {
|
||||
$class = str_replace('head_button_clone', 'pw-head-button', $class);
|
||||
$this->attr('class', $class);
|
||||
}
|
||||
if($this->getSetting('small')) {
|
||||
$this->addClass('InputfieldSubmitSmall', 'wrapClass');
|
||||
}
|
||||
return parent::renderReady($parent, $renderValueMode);
|
||||
}
|
||||
|
||||
@@ -126,6 +146,7 @@ class InputfieldSubmit extends Inputfield {
|
||||
$icon = $icon ? "<i class='fa fa-$icon'></i> " : '';
|
||||
$value = $this->entityEncode($this->attr('value'));
|
||||
$out = "<button $attrs><span class='ui-button-text'>$icon$value</span></button>";
|
||||
if($this->getSetting('small')) $out = "<small>$out</small>";
|
||||
if(count($this->dropdownItems)) $out .= $this->renderDropdown();
|
||||
return $out;
|
||||
}
|
||||
|
@@ -144,8 +144,14 @@
|
||||
var $oldTab = $tabList.find("a." + aActiveClass);
|
||||
var $newTab = $(this);
|
||||
|
||||
var $oldTabContent = $($oldTab.attr('href'));
|
||||
var $newTabContent = $($newTab.attr('href'));
|
||||
if(!$oldTab.length) $oldTab = $tabList.find("a:eq(0)");
|
||||
|
||||
|
||||
var oldTabHref = $oldTab.attr('href');
|
||||
var newTabHref = $newTab.attr('href');
|
||||
|
||||
var $oldTabContent = oldTabHref && oldTabHref.indexOf('#') === 0 ? $(oldTabHref) : null;
|
||||
var $newTabContent = newTabHref && newTabHref.indexOf('#') === 0 ? $(newTabHref) : null;
|
||||
|
||||
var newTabID = $newTab.attr('id');
|
||||
var oldTabID = $oldTab.attr('id');
|
||||
@@ -158,8 +164,13 @@
|
||||
$newTab.closest('li').addClass(liActiveClass);
|
||||
}
|
||||
|
||||
$oldTabContent.hide();
|
||||
$newTabContent.show();
|
||||
if($oldTabContent) $oldTabContent.hide();
|
||||
if($newTabContent) {
|
||||
$newTabContent.show();
|
||||
} else if(newTabHref && newTabHref.length) {
|
||||
window.location.href = newTabHref;
|
||||
return true;
|
||||
}
|
||||
|
||||
// add a target classname equal to the ID of the selected tab
|
||||
// so there is opportunity for 3rd party CSS adjustments outside this plugin
|
||||
|
@@ -1 +1 @@
|
||||
(function(a){a.fn.WireTabs=function(d){var e={rememberTabs:0,cookieName:"WireTabs",items:null,skipRememberTabIDs:[],itemsParent:null,ulClass:"WireTabs nav",ulAttrs:"",liActiveClass:"",aActiveClass:"on",id:""};var c=0;var b=ProcessWire.config.JqueryWireTabs;var g=["rememberTabs","cookieName","liActiveClass","aActiveClass","ulClass","ulAttrs"];for(var h=0;h<g.length;h++){var f=g[h];if(b[f]!="undefined"){e[f]=b[f]}}a.extend(e,d);return this.each(function(m){var o=null;var i=a(this);var l="";var q=true;function r(){if(!e.items){return}if(e.items.length<1){return}if(e.id.length){o=a("#"+e.id);if(o.length){q=false}else{o=null}}if(!o){o=a("<ul"+(e.ulAttrs?" "+e.ulAttrs:"")+"></ul>");o.addClass(e.ulClass);if(e.id.length){o.attr("id",e.id)}}e.items.each(j);if(q){i.prepend(o)}var t=i;var w=null;var y=p();if(e.rememberTabs==0){t.submit(function(){k(l);return true})}var s=window.location.href;var u="";if(s.indexOf("WireTab")){var v=new RegExp("[&;?]WireTab=([-_a-z0-9]+)","i");u=s.match(v);u=u?u[1]:"";if(u.length){w=o.find("a#_"+u)}}if(w==null){var x=document.location.hash.replace("#","");if(x.length){w=o.find("a#_"+x);if(w.length==0){w=null}else{document.location.hash=""}}}if(w==null&&y.length>0&&e.rememberTabs>-1){w=o.find("a#_"+y)}if(w&&w.length>0){w.click();if(e.rememberTabs==0){k("")}setTimeout(function(){w.click()},200)}else{o.children("li:first").children("a").click()}}function j(){c++;var w=a(this);if(!w.attr("id")){w.attr("id","WireTab"+c)}var v=w.attr("title")||w.attr("id");w.removeAttr("title");var s=w.attr("id");var u=a("a#_"+s);if(u.length>0){u.click(n)}else{var u=a("<a></a>").attr("href","#"+s).attr("id","_"+s).html(v).click(n);o.append(a("<li></li>").append(u))}var t=w.attr("data-tooltip");if(w.hasClass("WireTabTip")||t){u.addClass("tooltip");u.attr("title",t?t:v)}w.hide()}function n(){var u=e.aActiveClass;var s=e.liActiveClass;var t=o.find("a."+u);var w=a(this);var v=a(t.attr("href"));var y=a(w.attr("href"));var x=w.attr("id");var z=t.attr("id");t.removeClass(u);w.addClass(u);if(s.length){t.closest("li").removeClass(s);w.closest("li").addClass(s)}v.hide();y.show();if(z){i.removeClass(v.attr("id"))}i.addClass(x);if(e.rememberTabs>-1){if(jQuery.inArray(x,e.skipRememberTabIDs)!=-1){x=""}if(e.rememberTabs==1){k(x)}l=x}a(document).trigger("wiretabclick",[y,v]);return false}function k(s){document.cookie=e.cookieName+"="+escape(s)}function p(){var t=new RegExp("(?:^|;)\\s?"+e.cookieName+"=(.*?)(?:;|$)","i");var s=document.cookie.match(t);s=s?s[1]:"";return s}r()})}})(jQuery);
|
||||
(function(a){a.fn.WireTabs=function(d){var e={rememberTabs:0,cookieName:"WireTabs",items:null,skipRememberTabIDs:[],itemsParent:null,ulClass:"WireTabs nav",ulAttrs:"",liActiveClass:"",aActiveClass:"on",id:""};var c=0;var b=ProcessWire.config.JqueryWireTabs;var g=["rememberTabs","cookieName","liActiveClass","aActiveClass","ulClass","ulAttrs"];for(var h=0;h<g.length;h++){var f=g[h];if(b[f]!="undefined"){e[f]=b[f]}}a.extend(e,d);return this.each(function(m){var o=null;var i=a(this);var l="";var q=true;function r(){if(!e.items){return}if(e.items.length<1){return}if(e.id.length){o=a("#"+e.id);if(o.length){q=false}else{o=null}}if(!o){o=a("<ul"+(e.ulAttrs?" "+e.ulAttrs:"")+"></ul>");o.addClass(e.ulClass);if(e.id.length){o.attr("id",e.id)}}e.items.each(j);if(q){i.prepend(o)}var t=i;var w=null;var y=p();if(e.rememberTabs==0){t.submit(function(){k(l);return true})}var s=window.location.href;var u="";if(s.indexOf("WireTab")){var v=new RegExp("[&;?]WireTab=([-_a-z0-9]+)","i");u=s.match(v);u=u?u[1]:"";if(u.length){w=o.find("a#_"+u)}}if(w==null){var x=document.location.hash.replace("#","");if(x.length){w=o.find("a#_"+x);if(w.length==0){w=null}else{document.location.hash=""}}}if(w==null&&y.length>0&&e.rememberTabs>-1){w=o.find("a#_"+y)}if(w&&w.length>0){w.click();if(e.rememberTabs==0){k("")}setTimeout(function(){w.click()},200)}else{o.children("li:first").children("a").click()}}function j(){c++;var w=a(this);if(!w.attr("id")){w.attr("id","WireTab"+c)}var v=w.attr("title")||w.attr("id");w.removeAttr("title");var s=w.attr("id");var u=a("a#_"+s);if(u.length>0){u.click(n)}else{var u=a("<a></a>").attr("href","#"+s).attr("id","_"+s).html(v).click(n);o.append(a("<li></li>").append(u))}var t=w.attr("data-tooltip");if(w.hasClass("WireTabTip")||t){u.addClass("tooltip");u.attr("title",t?t:v)}w.hide()}function n(){var t=e.aActiveClass;var z=e.liActiveClass;var u=o.find("a."+t);var x=a(this);if(!u.length){u=o.find("a:eq(0)")}var w=u.attr("href");var y=x.attr("href");var v=w&&w.indexOf("#")===0?a(w):null;var s=y&&y.indexOf("#")===0?a(y):null;var B=x.attr("id");var A=u.attr("id");u.removeClass(t);x.addClass(t);if(z.length){u.closest("li").removeClass(z);x.closest("li").addClass(z)}if(v){v.hide()}if(s){s.show()}else{if(y&&y.length){window.location.href=y;return true}}if(A){i.removeClass(v.attr("id"))}i.addClass(B);if(e.rememberTabs>-1){if(jQuery.inArray(B,e.skipRememberTabIDs)!=-1){B=""}if(e.rememberTabs==1){k(B)}l=B}a(document).trigger("wiretabclick",[s,v]);return false}function k(s){document.cookie=e.cookieName+"="+escape(s)}function p(){var t=new RegExp("(?:^|;)\\s?"+e.cookieName+"=(.*?)(?:;|$)","i");var s=document.cookie.match(t);s=s?s[1]:"";return s}r()})}})(jQuery);
|
@@ -1,50 +1,36 @@
|
||||
.langTabs {
|
||||
.body.LanguageTabsJqueryUI .pw-content .langTabsContainer .InputfieldError,
|
||||
.body.LanguageTabsJqueryUI #content .langTabsContainer .InputfieldError {
|
||||
margin-bottom: 0; }
|
||||
|
||||
.langTabs.ui-tabs {
|
||||
position: relative;
|
||||
padding: 0; }
|
||||
|
||||
.LanguageTabsJqueryUI .langTabs > ul {
|
||||
display: none; }
|
||||
.LanguageTabsJqueryUI .hasLangTabs .langTabs > ul {
|
||||
display: block; }
|
||||
.LanguageTabsJqueryUI .pw-content .langTabsContainer,
|
||||
.LanguageTabsJqueryUI #content .langTabsContainer {
|
||||
padding-bottom: 0; }
|
||||
.LanguageTabsJqueryUI .pw-content .langTabsContainer .InputfieldError,
|
||||
.LanguageTabsJqueryUI #content .langTabsContainer .InputfieldError {
|
||||
margin-bottom: 0; }
|
||||
.LanguageTabsJqueryUI .langTabs .ui-tabs-nav.ui-widget-header {
|
||||
padding: 2px 3px 0;
|
||||
border-bottom: none; }
|
||||
.LanguageTabsJqueryUI .langTabs .ui-tabs-panel {
|
||||
padding: 0.9em;
|
||||
border-top: none; }
|
||||
.LanguageTabsJqueryUI .langTabs .ui-tabs-panel .LanguageSupportLabel {
|
||||
display: none; }
|
||||
.LanguageTabsJqueryUI .langTabs.ui-tabs .ui-tabs-nav {
|
||||
margin-bottom: 0; }
|
||||
.LanguageTabsJqueryUI .langTabs.ui-tabs .ui-tabs-nav li {
|
||||
margin: 0 4px 0 0; }
|
||||
.LanguageTabsJqueryUI .langTabs.ui-tabs .ui-tabs-nav li a {
|
||||
padding: 0.3em 0.7em;
|
||||
font-weight: bold;
|
||||
outline: none;
|
||||
font-size: 0.846153846153846em; }
|
||||
.LanguageTabsJqueryUI .langTabs.ui-tabs .ui-tabs-nav li.ui-state-active.ui-state-default {
|
||||
border: 1px solid #fff;
|
||||
padding-bottom: 0; }
|
||||
.LanguageTabsJqueryUI .langTabs.ui-tabs .ui-tabs-nav li.ui-state-active {
|
||||
background: #fff; }
|
||||
.LanguageTabsJqueryUI .langTabs.ui-tabs .ui-tabs-nav li.ui-state-active a {
|
||||
cursor: default;
|
||||
background: #fff;
|
||||
margin: 0; }
|
||||
.LanguageTabsJqueryUI .langTabEmpty a {
|
||||
opacity: 0.7;
|
||||
font-weight: normal !important; }
|
||||
.LanguageTabsJqueryUI .InputfieldImage .InputfieldFileLink + .langTabsContainer {
|
||||
margin-top: 0.5em; }
|
||||
.LanguageTabsJqueryUI .hadLanguageSupport > .InputfieldContent > .LanguageSupport {
|
||||
margin-bottom: 0; }
|
||||
.langTabs.ui-tabs .ui-tabs-nav {
|
||||
margin-bottom: 0; }
|
||||
.langTabs.ui-tabs .ui-tabs-nav.ui-widget-header {
|
||||
padding: 2px 3px 0;
|
||||
border-bottom: none; }
|
||||
.langTabs.ui-tabs .ui-tabs-nav li {
|
||||
margin: 0 4px 0 0; }
|
||||
.langTabs.ui-tabs .ui-tabs-nav li a {
|
||||
padding: 0.3em 0.7em;
|
||||
font-weight: bold;
|
||||
outline: none;
|
||||
font-size: 0.846153846153846em; }
|
||||
.langTabs.ui-tabs .ui-tabs-nav li.ui-state-active.ui-state-default {
|
||||
border: 1px solid #fff;
|
||||
padding-bottom: 0; }
|
||||
.langTabs.ui-tabs .ui-tabs-nav li.ui-state-active {
|
||||
background: #fff; }
|
||||
.langTabs.ui-tabs .ui-tabs-nav li.ui-state-active a {
|
||||
cursor: default;
|
||||
background: #fff;
|
||||
margin: 0; }
|
||||
.langTabs.ui-tabs .ui-tabs-panel {
|
||||
padding: 0.9em;
|
||||
border-top: none; }
|
||||
.langTabs.ui-tabs .ui-tabs-panel .LanguageSupportLabel {
|
||||
display: none; }
|
||||
|
||||
.langTabsToggle {
|
||||
float: right;
|
||||
@@ -53,6 +39,22 @@
|
||||
.InputfieldStateCollapsed .langTabsToggle {
|
||||
display: none; }
|
||||
|
||||
.langTabEmpty a {
|
||||
opacity: 0.7;
|
||||
font-weight: normal !important; }
|
||||
|
||||
.langTabs > ul.ui-tabs {
|
||||
display: none; }
|
||||
|
||||
.hasLangTabs .langTabs > ul.ui-tabs {
|
||||
display: block; }
|
||||
|
||||
.InputfieldImage .InputfieldFileLink + .langTabsContainer {
|
||||
margin-top: 0.5em; }
|
||||
|
||||
.hadLanguageSupport > .InputfieldContent > .LanguageSupport {
|
||||
margin-bottom: 0; }
|
||||
|
||||
.langTabsHidden,
|
||||
.hadLanguageSupport .LanguageSupportLabel {
|
||||
display: none; }
|
||||
@@ -63,7 +65,105 @@
|
||||
right: 1em;
|
||||
display: none; }
|
||||
|
||||
/*
|
||||
.langTabs {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body.LanguageTabsJqueryUI {
|
||||
.langTabs > ul {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hasLangTabs .langTabs > ul {
|
||||
display: block;
|
||||
}
|
||||
.pw-content .langTabsContainer,
|
||||
#content .langTabsContainer {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.pw-content .langTabsContainer .InputfieldError,
|
||||
#content .langTabsContainer .InputfieldError {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.langTabs .ui-tabs-nav.ui-widget-header {
|
||||
padding: 2px 3px 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
.langTabs .ui-tabs-panel {
|
||||
padding: 0.9em;
|
||||
border-top: none;
|
||||
}
|
||||
.langTabs .ui-tabs-panel .LanguageSupportLabel {
|
||||
display: none;
|
||||
|
||||
}
|
||||
.langTabs.ui-tabs .ui-tabs-nav {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.langTabs.ui-tabs .ui-tabs-nav li {
|
||||
margin: 0 4px 0 0;
|
||||
}
|
||||
.langTabs.ui-tabs .ui-tabs-nav li a {
|
||||
padding: 0.3em 0.7em;
|
||||
font-weight: bold;
|
||||
outline: none;
|
||||
font-size: 0.846153846153846em;
|
||||
}
|
||||
.langTabs.ui-tabs .ui-tabs-nav li.ui-state-active.ui-state-default {
|
||||
border: 1px solid #fff;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.langTabs.ui-tabs .ui-tabs-nav li.ui-state-active {
|
||||
background: #fff;
|
||||
}
|
||||
.langTabs.ui-tabs .ui-tabs-nav li.ui-state-active a {
|
||||
cursor: default;
|
||||
background: #fff;
|
||||
margin: 0;
|
||||
}
|
||||
.langTabEmpty a {
|
||||
opacity: 0.7;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
|
||||
.InputfieldImage .InputfieldFileLink + .langTabsContainer {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.hadLanguageSupport > .InputfieldContent > .LanguageSupport {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.langTabsToggle {
|
||||
float: right;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.InputfieldStateCollapsed .langTabsToggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.langTabsHidden,
|
||||
.hadLanguageSupport .LanguageSupportLabel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.langTabsNote {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 1em;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.langTabs > ul > li {
|
||||
cursor: pointer; }
|
||||
cursor: pointer;
|
||||
}
|
||||
*/
|
||||
|
||||
/*# sourceMappingURL=LanguageTabs.css.map */
|
||||
|
@@ -39,7 +39,7 @@ function setupLanguageTabs($form) {
|
||||
else $langTabs = $form.find('.langTabs');
|
||||
$langTabs.each(function() {
|
||||
var $this = $(this);
|
||||
if($this.hasClass('langTabsInit')) return;
|
||||
if($this.hasClass('langTabsInit') || $this.hasClass('ui-tabs')) return;
|
||||
var $inputfield = $this.closest('.Inputfield');
|
||||
var $content = $inputfield.children('.InputfieldContent');
|
||||
if(!$content.hasClass('langTabsContainer')) {
|
||||
|
@@ -1 +1 @@
|
||||
var clickLanguageTabActive=false;function longclickLanguageTab(c){if(clickLanguageTabActive){return}clickLanguageTabActive=true;var b=$(this);var d=b.attr("data-lang");var a=b.closest("form").find("a.langTab"+d).not(b);b.click();a.click();a.effect("highlight",250);setTimeout(function(){clickLanguageTabActive=false},250)}function setupLanguageTabs(b){var c;var a=ProcessWire.config.LanguageTabs;if(b.hasClass("langTabs")){c=b}else{c=b.find(".langTabs")}c.each(function(){var j=$(this);if(j.hasClass("langTabsInit")){return}var g=j.closest(".Inputfield");var f=g.children(".InputfieldContent");if(!f.hasClass("langTabsContainer")){if(g.find(".langTabsContainer").length==0){f.addClass("langTabsContainer")}}if(a.jQueryUI){j.tabs({active:a.activeTab})}j.addClass("langTabsInit");if(g.length){g.addClass("hasLangTabs")}var i=j.parent(".InputfieldContent");if(i.length){var e=$("<span></span>").attr("title",a.labelOpen).attr("class","langTabsToggle").append("<i class='fa fa-folder-o'></i>");i.prev(".InputfieldHeader").append(e)}var k=j.find("a");var h=null;var d=i.find(".langTabsNote");k.on("mouseover",function(){if(h){clearTimeout(h)}if(i.width()<500){return}h=setTimeout(function(){d.fadeIn("fast")},250)}).on("mouseout",function(){if(h){clearTimeout(h)}if(i.width()<500){return}h=setTimeout(function(){d.fadeOut("fast")},250)}).on("click",function(){var n=$(this);var o=n.closest("ul").siblings(".LanguageSupport");var m=o.filter(".LanguageSupportCurrent");var l=o.filter(n.attr("href"));if(m.attr("id")==l.attr("id")){n.trigger("longclick")}else{m.removeClass("LanguageSupportCurrent");l.addClass("LanguageSupportCurrent")}});if(!a.jQueryUI){k.eq(a.activeTab).click()}})}function toggleLanguageTabs(){var g=$(this);var b=g.closest(".InputfieldHeader");var d=b.next(".InputfieldContent");var f=b.parent(".Inputfield");var e=d.children(".langTabs");var c=e.children("ul");var a=ProcessWire.config.LanguageTabs;if(d.hasClass("langTabsContainer")){c.find("a").click();d.removeClass("langTabsContainer");f.removeClass("hasLangTabs").addClass("langTabsOff");g.addClass("langTabsOff");if(a.jQueryUI){e.tabs("destroy")}else{c.hide()}g.attr("title",ProcessWire.config.LanguageTabs.labelClose).find("i").removeClass("fa-folder-o").addClass("fa-folder-open-o")}else{d.addClass("langTabsContainer");f.addClass("hasLangTabs").removeClass("langTabsOff");g.removeClass("langTabsOff");if(a.jQueryUI){e.tabs()}else{c.show()}$(this).attr("title",a.labelOpen).find("i").addClass("fa-folder-o").removeClass("fa-folder-open-o")}return false}function hideLanguageTabs(){$(".InputfieldContent").each(function(){var c=0;$(this).children(".LanguageSupport").each(function(){if(++c==1){$(this).closest(".Inputfield").addClass("hadLanguageSupport");return}$(this).addClass("langTabsHidden")})});var b=$(".langTabs").find("li:eq(0)");var a=ProcessWire.config.LanguageTabs;if(!b.hasClass(a.liActiveClass)){b.find("a").click()}$(".langTabsToggle, .LanguageSupportLabel:visible, .langTabs > ul").addClass("langTabsHidden");$(".hasLangTabs").removeClass("hasLangTabs").addClass("hadLangTabs")}function unhideLanguageTabs(){$(".langTabsHidden").removeClass("langTabsHidden");$(".hadLangTabs").removeClass("hadLangTabs").addClass("hasLangTabs");$(".hadLanguageSupport").removeClass("hadLanguageSupport")}jQuery(document).ready(function(){$(document).on("click",".langTabsToggle",toggleLanguageTabs);$(document).on("longclick",".langTabs a",longclickLanguageTab);$(document).on("reloaded",".Inputfield",function(){setupLanguageTabs($(this))});$(document).on("AjaxUploadDone",".InputfieldHasFileList .InputfieldFileList",function(){setupLanguageTabs($(this))})});
|
||||
var clickLanguageTabActive=false;function longclickLanguageTab(c){if(clickLanguageTabActive){return}clickLanguageTabActive=true;var b=$(this);var d=b.attr("data-lang");var a=b.closest("form").find("a.langTab"+d).not(b);b.click();a.click();a.effect("highlight",250);setTimeout(function(){clickLanguageTabActive=false},250)}function setupLanguageTabs(b){var c;var a=ProcessWire.config.LanguageTabs;if(b.hasClass("langTabs")){c=b}else{c=b.find(".langTabs")}c.each(function(){var j=$(this);if(j.hasClass("langTabsInit")||j.hasClass("ui-tabs")){return}var g=j.closest(".Inputfield");var f=g.children(".InputfieldContent");if(!f.hasClass("langTabsContainer")){if(g.find(".langTabsContainer").length==0){f.addClass("langTabsContainer")}}if(a.jQueryUI){j.tabs({active:a.activeTab})}j.addClass("langTabsInit");if(g.length){g.addClass("hasLangTabs")}var i=j.parent(".InputfieldContent");if(i.length){var e=$("<span></span>").attr("title",a.labelOpen).attr("class","langTabsToggle").append("<i class='fa fa-folder-o'></i>");i.prev(".InputfieldHeader").append(e)}var k=j.find("a");var h=null;var d=i.find(".langTabsNote");k.on("mouseover",function(){if(h){clearTimeout(h)}if(i.width()<500){return}h=setTimeout(function(){d.fadeIn("fast")},250)}).on("mouseout",function(){if(h){clearTimeout(h)}if(i.width()<500){return}h=setTimeout(function(){d.fadeOut("fast")},250)}).on("click",function(){var n=$(this);var o=n.closest("ul").siblings(".LanguageSupport");var m=o.filter(".LanguageSupportCurrent");var l=o.filter(n.attr("href"));if(m.attr("id")==l.attr("id")){n.trigger("longclick")}else{m.removeClass("LanguageSupportCurrent");l.addClass("LanguageSupportCurrent")}});if(!a.jQueryUI){k.eq(a.activeTab).click()}})}function toggleLanguageTabs(){var g=$(this);var b=g.closest(".InputfieldHeader");var d=b.next(".InputfieldContent");var f=b.parent(".Inputfield");var e=d.children(".langTabs");var c=e.children("ul");var a=ProcessWire.config.LanguageTabs;if(d.hasClass("langTabsContainer")){c.find("a").click();d.removeClass("langTabsContainer");f.removeClass("hasLangTabs").addClass("langTabsOff");g.addClass("langTabsOff");if(a.jQueryUI){e.tabs("destroy")}else{c.hide()}g.attr("title",ProcessWire.config.LanguageTabs.labelClose).find("i").removeClass("fa-folder-o").addClass("fa-folder-open-o")}else{d.addClass("langTabsContainer");f.addClass("hasLangTabs").removeClass("langTabsOff");g.removeClass("langTabsOff");if(a.jQueryUI){e.tabs()}else{c.show()}$(this).attr("title",a.labelOpen).find("i").addClass("fa-folder-o").removeClass("fa-folder-open-o")}return false}function hideLanguageTabs(){$(".InputfieldContent").each(function(){var c=0;$(this).children(".LanguageSupport").each(function(){if(++c==1){$(this).closest(".Inputfield").addClass("hadLanguageSupport");return}$(this).addClass("langTabsHidden")})});var b=$(".langTabs").find("li:eq(0)");var a=ProcessWire.config.LanguageTabs;if(!b.hasClass(a.liActiveClass)){b.find("a").click()}$(".langTabsToggle, .LanguageSupportLabel:visible, .langTabs > ul").addClass("langTabsHidden");$(".hasLangTabs").removeClass("hasLangTabs").addClass("hadLangTabs")}function unhideLanguageTabs(){$(".langTabsHidden").removeClass("langTabsHidden");$(".hadLangTabs").removeClass("hadLangTabs").addClass("hasLangTabs");$(".hadLanguageSupport").removeClass("hadLanguageSupport")}jQuery(document).ready(function(){$(document).on("click",".langTabsToggle",toggleLanguageTabs);$(document).on("longclick",".langTabs a",longclickLanguageTab);$(document).on("reloaded",".Inputfield",function(){setupLanguageTabs($(this))});$(document).on("AjaxUploadDone",".InputfieldHasFileList .InputfieldFileList",function(){setupLanguageTabs($(this))})});
|
@@ -84,6 +84,7 @@ class LanguageTabs extends WireData implements Module, ConfigurableModule {
|
||||
'aClass' => '',
|
||||
'loadStyles' => true,
|
||||
'loadScripts' => true,
|
||||
'tabField' => $this->get('tabField'),
|
||||
);
|
||||
|
||||
$settings = $this->wire('config')->get('LanguageTabs');
|
||||
|
@@ -1,10 +1,105 @@
|
||||
|
||||
.body.LanguageTabsJqueryUI {
|
||||
.pw-content .langTabsContainer,
|
||||
#content .langTabsContainer {
|
||||
// padding-bottom: 0;
|
||||
}
|
||||
.pw-content .langTabsContainer .InputfieldError,
|
||||
#content .langTabsContainer .InputfieldError {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.langTabs.ui-tabs {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
|
||||
.ui-tabs-nav {
|
||||
margin-bottom: 0;
|
||||
&.ui-widget-header {
|
||||
padding: 2px 3px 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
li {
|
||||
margin: 0 4px 0 0;
|
||||
a {
|
||||
padding: 0.3em 0.7em;
|
||||
font-weight: bold;
|
||||
outline: none;
|
||||
font-size: 0.846153846153846em;
|
||||
}
|
||||
}
|
||||
li.ui-state-active.ui-state-default {
|
||||
border: 1px solid #fff;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
li.ui-state-active {
|
||||
background: #fff;
|
||||
a {
|
||||
cursor: default;
|
||||
background: #fff;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ui-tabs-panel {
|
||||
padding: 0.9em;
|
||||
border-top: none;
|
||||
.LanguageSupportLabel {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.langTabsToggle {
|
||||
float: right;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.InputfieldStateCollapsed .langTabsToggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.langTabEmpty a {
|
||||
opacity: 0.7;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
|
||||
.langTabs > ul.ui-tabs {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hasLangTabs .langTabs > ul.ui-tabs {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.InputfieldImage .InputfieldFileLink + .langTabsContainer {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
.hadLanguageSupport > .InputfieldContent > .LanguageSupport {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.langTabsHidden,
|
||||
.hadLanguageSupport .LanguageSupportLabel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.langTabsNote {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 1em;
|
||||
display: none;
|
||||
}
|
||||
/*
|
||||
.langTabs {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.LanguageTabsJqueryUI {
|
||||
body.LanguageTabsJqueryUI {
|
||||
.langTabs > ul {
|
||||
display: none;
|
||||
}
|
||||
@@ -97,3 +192,4 @@
|
||||
.langTabs > ul > li {
|
||||
cursor: pointer;
|
||||
}
|
||||
*/
|
||||
|
@@ -4,7 +4,7 @@
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#columnWidthSlider {
|
||||
.InputfieldColumnWidthSlider {
|
||||
float: left;
|
||||
width: 70%;
|
||||
position: relative;
|
||||
|
@@ -34,7 +34,7 @@ $(document).ready(function() {
|
||||
setAsmListItemStatus();
|
||||
|
||||
if($columnWidth.size() > 0) {
|
||||
var $slider = $("<div id='columnWidthSlider'></div>");
|
||||
var $slider = $("<div class='InputfieldColumnWidthSlider'></div>");
|
||||
var columnWidthVal = parseInt($("#columnWidth").val());
|
||||
$columnWidth.val(columnWidthVal + '%');
|
||||
$columnWidth.after($slider);
|
||||
|
@@ -1 +1 @@
|
||||
$(document).ready(function(){var e=function(){$("#field_filter_form").submit()};$("#templates_id").change(e);$("#fieldtype").change(e);$("#show_system").click(e);var b=$("#asmListItemStatus");var d=$("#columnWidth");function a(){var i=b.attr("data-tpl");if(!i){return}var k=$("#Inputfield_showIf").val();var j=$("#Inputfield_required").is(":checked")?true:false;if(k&&k.length>0){i="<i class='fa fa-question-circle'></i>"+i}if(j){i="<i class='fa fa-asterisk'></i>"+i}var h=parseInt(d.val());if(h==100){h=0}if(h>0){h=h+"%"}else{h=""}i=i.replace("%",h);b.val(i)}$("#Inputfield_showIf").change(a);$("#Inputfield_required").change(a);a();if(d.size()>0){var f=$("<div id='columnWidthSlider'></div>");var c=parseInt($("#columnWidth").val());d.val(c+"%");d.after(f);f.slider({range:"min",min:10,max:100,value:parseInt(d.val()),slide:function(i,h){var j=h.value+"%";d.val(j);a()}});d.change(function(){var h=parseInt($(this).val());if(h>100){h=100}if(h<10){h=10}$(this).val(h+"%");f.slider("option","value",h)})}var g=$("#ProcessFieldEdit");if(g.size()>0&&$("li.WireTab").size()>1){g.find("script").remove();g.WireTabs({items:$(".Inputfields li.WireTab"),id:"FieldEditTabs",skipRememberTabIDs:["delete"]})}$("#fieldgroupContextSelect").change(function(){var i=$("#Inputfield_id").val();var j=$(this).val();var h="./edit?id="+i;if(j>0){h+="&fieldgroup_id="+j}window.location=h});$("a.fieldFlag").click(function(){return false});$("#export_data").click(function(){$(this).select()});$(".import_toggle input[type=radio]").change(function(){var h=$(this).parents("p.import_toggle").next("table");var i=$(this).closest(".InputfieldFieldset");if($(this).is(":checked")&&$(this).val()==0){h.hide();i.addClass("ui-priority-secondary")}else{h.show();i.removeClass("ui-priority-secondary")}}).change();$("#wrap_Inputfield_send_templates").find(":input").change(function(){$("#_send_templates_changed").val("changed")});$("#viewRoles_37").click(function(){if($(this).is(":checked")){$("input.viewRoles").attr("checked","checked")}});$("input.viewRoles:not(#viewRoles_37)").click(function(){if($("#viewRoles_37").is(":checked")){return false}return true});$("input.editRoles:not(:disabled)").click(function(){if($(this).is(":checked")){$(this).closest("tr").find("input.viewRoles").attr("checked","checked")}});$(".override-select-all").click(function(){var h=$(this).closest("table").find("input[type=checkbox]");if($(this).hasClass("override-checked")){h.removeAttr("checked");$(this).removeClass("override-checked")}else{h.attr("checked","checked");$(this).addClass("override-checked")}return false})});
|
||||
$(document).ready(function(){var e=function(){$("#field_filter_form").submit()};$("#templates_id").change(e);$("#fieldtype").change(e);$("#show_system").click(e);var b=$("#asmListItemStatus");var d=$("#columnWidth");function a(){var i=b.attr("data-tpl");if(!i){return}var k=$("#Inputfield_showIf").val();var j=$("#Inputfield_required").is(":checked")?true:false;if(k&&k.length>0){i="<i class='fa fa-question-circle'></i>"+i}if(j){i="<i class='fa fa-asterisk'></i>"+i}var h=parseInt(d.val());if(h==100){h=0}if(h>0){h=h+"%"}else{h=""}i=i.replace("%",h);b.val(i)}$("#Inputfield_showIf").change(a);$("#Inputfield_required").change(a);a();if(d.size()>0){var f=$("<div class='InputfieldColumnWidthSlider'></div>");var c=parseInt($("#columnWidth").val());d.val(c+"%");d.after(f);f.slider({range:"min",min:10,max:100,value:parseInt(d.val()),slide:function(i,h){var j=h.value+"%";d.val(j);a()}});d.change(function(){var h=parseInt($(this).val());if(h>100){h=100}if(h<10){h=10}$(this).val(h+"%");f.slider("option","value",h)})}var g=$("#ProcessFieldEdit");if(g.size()>0&&$("li.WireTab").size()>1){g.find("script").remove();g.WireTabs({items:$(".Inputfields li.WireTab"),id:"FieldEditTabs",skipRememberTabIDs:["delete"]})}$("#fieldgroupContextSelect").change(function(){var i=$("#Inputfield_id").val();var j=$(this).val();var h="./edit?id="+i;if(j>0){h+="&fieldgroup_id="+j}window.location=h});$("a.fieldFlag").click(function(){return false});$("#export_data").click(function(){$(this).select()});$(".import_toggle input[type=radio]").change(function(){var h=$(this).parents("p.import_toggle").next("table");var i=$(this).closest(".InputfieldFieldset");if($(this).is(":checked")&&$(this).val()==0){h.hide();i.addClass("ui-priority-secondary")}else{h.show();i.removeClass("ui-priority-secondary")}}).change();$("#wrap_Inputfield_send_templates").find(":input").change(function(){$("#_send_templates_changed").val("changed")});$("#viewRoles_37").click(function(){if($(this).is(":checked")){$("input.viewRoles").attr("checked","checked")}});$("input.viewRoles:not(#viewRoles_37)").click(function(){if($("#viewRoles_37").is(":checked")){return false}return true});$("input.editRoles:not(:disabled)").click(function(){if($(this).is(":checked")){$(this).closest("tr").find("input.viewRoles").attr("checked","checked")}});$(".override-select-all").click(function(){var h=$(this).closest("table").find("input[type=checkbox]");if($(this).hasClass("override-checked")){h.removeAttr("checked");$(this).removeClass("override-checked")}else{h.attr("checked","checked");$(this).addClass("override-checked")}return false})});
|
@@ -634,6 +634,7 @@ class ProcessPageAdd extends Process implements ConfigurableModule, WirePageEdit
|
||||
$inputfield = $field->getInputfield($page);
|
||||
if($inputfield) {
|
||||
if($this->template && $this->template->noLang) $inputfield->useLanguages = false;
|
||||
$inputfield->columnWidth = 100;
|
||||
$form->append($inputfield);
|
||||
}
|
||||
break;
|
||||
@@ -646,6 +647,7 @@ class ProcessPageAdd extends Process implements ConfigurableModule, WirePageEdit
|
||||
// skip it
|
||||
} else {
|
||||
$inputfield = $field->getInputfield($page);
|
||||
$inputfield->columnWidth = 100;
|
||||
if($inputfield) $form->append($inputfield);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user