New js search filter in icons doc (#33580)

* New js search filter in icons doc

* Fix code wysiwyg editor in Doc and add search input doc

* Fix code wysiwyg editor in Doc and add search input doc

* Fix autofocus

* fix js count

* comment

* comment

* fix php stan

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
This commit is contained in:
John BOTELLA
2025-03-25 10:57:15 +01:00
committed by GitHub
parent 1e9b58dc9d
commit b16b462520
17 changed files with 531 additions and 138 deletions

View File

@@ -53,6 +53,10 @@ class Documentation
*/
public $db;
/**
* @var string
*/
public $baseUrl = 'admin/tools/ui';
/**
* Constructor
@@ -82,8 +86,6 @@ class Documentation
$hookmanager->initHooks(array('uidocumentation'));
$baseUrl = 'admin/tools/ui';
// Go back to Dolibarr
$this->menu['BackToDolibarr'] = array(
'url' => DOL_URL_ROOT,
@@ -93,18 +95,18 @@ class Documentation
// Home for Ui documentation
$this->menu['DocumentationHome'] = array(
'url' => dol_buildpath($baseUrl.'/index.php', 1),
'url' => dol_buildpath($this->baseUrl.'/index.php', 1),
'icon' => 'fas fa-book',
'submenu' => array(),
);
// Components
$this->menu['Components'] = array(
'url' => dol_buildpath($baseUrl.'/components/index.php', 1),
'url' => dol_buildpath($this->baseUrl.'/components/index.php', 1),
'icon' => 'fas fa-th-large',
'submenu' => array(
'Badges' => array(
'url' => dol_buildpath($baseUrl.'/components/badges.php', 1),
'url' => dol_buildpath($this->baseUrl.'/components/badges.php', 1),
'icon' => 'fas fa-certificate pictofixedwidth',
'submenu' => array(),
'summary' => array(
@@ -118,7 +120,7 @@ class Documentation
),
),
'Buttons' => array(
'url' => dol_buildpath($baseUrl.'/components/buttons.php', 1),
'url' => dol_buildpath($this->baseUrl.'/components/buttons.php', 1),
'icon' => 'fas fa-mouse pictofixedwidth',
'submenu' => array(),
'summary' => array(
@@ -128,7 +130,7 @@ class Documentation
),
),
'Icons' => array(
'url' => dol_buildpath($baseUrl.'/components/icons.php', 1),
'url' => dol_buildpath($this->baseUrl.'/components/icons.php', 1),
'icon' => 'far fa-flag pictofixedwidth',
'submenu' => array(),
'summary' => array(
@@ -137,7 +139,7 @@ class Documentation
),
),
'Progress' => array(
'url' => dol_buildpath($baseUrl.'/components/progress-bars.php', 1),
'url' => dol_buildpath($this->baseUrl.'/components/progress-bars.php', 1),
'icon' => 'fas fa-battery-half pictofixedwidth',
'submenu' => array(),
'summary' => array(
@@ -147,7 +149,7 @@ class Documentation
),
),
'Event Message' => array(
'url' => dol_buildpath($baseUrl.'/components/event-message.php', 1),
'url' => dol_buildpath($this->baseUrl.'/components/event-message.php', 1),
'icon' => 'fas fa-comments pictofixedwidth',
'submenu' => array(),
'summary' => array(
@@ -156,12 +158,13 @@ class Documentation
)
),
'Inputs' => array(
'url' => dol_buildpath($baseUrl.'/components/inputs.php', 1),
'url' => dol_buildpath($this->baseUrl.'/components/inputs.php', 1),
'icon' => 'fas fa-comments pictofixedwidth',
'submenu' => array(),
'summary' => array(
'DocBasicUsage' => '#setinputssection-basicusage',
'DocHelperFunctionsInputUsage' => '#setinputssection-helperfunctions',
'DocHelperFunctionsGetSearchFilterToolInput' => '#setinputssection-getSearchFilterToolInput',
)
),
),
@@ -172,7 +175,7 @@ class Documentation
// Elements
$this->menu['Content'] = array(
'url' => dol_buildpath($baseUrl.'/content/index.php', 1),
'url' => dol_buildpath($this->baseUrl.'/content/index.php', 1),
'icon' => 'fas fa-th-large',
'submenu' => array(
'Tables' => array(
@@ -190,7 +193,7 @@ class Documentation
);
$parameters = array(
'baseUrl' => $baseUrl,
'baseUrl' => $this->baseUrl,
);
$action = '';
@@ -415,6 +418,13 @@ class Documentation
{
require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
print '<div class="documentation-code">';
if (isset($lines[0])) {
if ($option === 'html' && strpos(strtolower($lines[0]), '<!doctype') === false) {
array_unshift($lines, '<!DOCTYPE html>', '');
}
}
$content = implode("\n", $lines) . "\n";
$doleditor = new DolEditor(md5($content), $content, '', 0, 'Basic', 'In', true, false, 'ace', 0, '99%', 1);
print $doleditor->Create(1, '', false, '', $option);

View File

@@ -292,6 +292,7 @@ $documentation->showSidebar(); ?>
</div>
<?php
$lines = array(
"<?php ",
"/**",
" * Function dolGetBadge",
" *",
@@ -301,12 +302,13 @@ $documentation->showSidebar(); ?>
" * @param string \$mode Default '' , 'pill', 'dot'",
" * @param string \$url the url for link",
" * ... See more: core/lib/functions.lib.php ",
"*/",
"",
"<?php print dolGetBadge('your label for accessibility', 'your label <u>with</u> <em>html</em>', 'primary'); ?>",
"<?php print dolGetBadge('your label for accessibility', 'your label <u>with</u> <em>html</em>', 'danger', 'pill'); ?>",
"<?php print dolGetBadge('your label for accessibility', 'your label', 'warning', 'dot'); ?>",
"print dolGetBadge('your label for accessibility', 'your label <u>with</u> <em>html</em>', 'primary');",
"print dolGetBadge('your label for accessibility', 'your label <u>with</u> <em>html</em>', 'danger', 'pill');",
"print dolGetBadge('your label for accessibility', 'your label', 'warning', 'dot');",
);
echo $documentation->showCode($lines); ?>
echo $documentation->showCode($lines, 'php'); ?>
</div>
<!-- -->

View File

@@ -163,9 +163,9 @@ $documentation->showSidebar(); ?>
<?php
$lines = array(
'<?php',
'setEventMessages("message", null)',
'setEventMessages("message", null, "warnings")',
'setEventMessages("message", null, "errors")'
'setEventMessages("message", null);',
'setEventMessages("message", null, "warnings");',
'setEventMessages("message", null, "errors");'
);
echo $documentation->showCode($lines, 'php'); ?>
</div>

View File

@@ -42,11 +42,19 @@ $langs->load('uxdocumentation');
$documentation = new Documentation($db);
// Output html head + body - Param is Title
$documentation->docHeader('Icons');
$documentation->docHeader('Icons', [], ['admin/tools/ui/css/doc-icons.css']);
// Set view for menu and breadcrumb
// Menu must be set in constructor of documentation class
$documentation->view = array('Components','Icons');
$form = new Form($db);
$displayMode = GETPOST('displayMode') == 'kanban' ? 'kanban' : 'icon-only';
$revertDisplayMode = $displayMode == 'kanban' ? 'icon-only' : 'kanban';
$revertDisplayName = $displayMode == 'kanban' ? $langs->trans('ViewList') : $langs->trans('ViewKanban');
$switchDisplayLink = dol_buildpath($documentation->baseUrl . '/components/icons.php', 1) . '?displayMode=' . $revertDisplayMode;
$switchDisplayLinkIcon = $displayMode == 'kanban' ? 'fa fa-th' : 'fa fa-th-list';
// Output sidebar
$documentation->showSidebar(); ?>
@@ -85,11 +93,28 @@ $documentation->showSidebar(); ?>
<h2 class="documentation-title"><?php echo $langs->trans('DocIconsListImgPicto'); ?></h2>
<?php /* <p class="documentation-text"><?php echo $langs->trans('DocDocIconsListDescription'); ?></p>*/ ?>
<?php print $form->getSearchFilterToolInput(
'.documentation-img-picto-icon-list .info-box, .documentation-img-picto-icon-list .doc-icon-list-item',
'search-tools-input',
'',
['attr' => [
'data-no-item-target' => '#img-picto-section-list .search-tool-no-results',
],
]
); ?>
<div class="right">
<?php print dolGetButtonTitle($revertDisplayName, '', $switchDisplayLinkIcon, $switchDisplayLink.'#img-picto-section-list', '', 1, ['forcenohideoftext'=>1]); ?>
</div>
<div class="documentation-example">
<div class="documentation-fontawesome-icon-list">
<div class="documentation-img-picto-icon-list">
<?php
foreach (getImgPictoNameList() as $iconName) {
$labelAlt = 'Text on title tag for tooltip';
if ($displayMode == 'kanban') {
$iconCode = img_picto($iconName, $iconName);
print '<div class="info-box ">
<span class="info-box-icon bg-infobox-expensereport">
@@ -106,9 +131,16 @@ $documentation->showSidebar(); ?>
</div><!-- /.info-box-lines -->
</div><!-- /.info-box-content -->
</div>';
} else {
$tooltip = $iconName.'<br>img_picto(\''.$labelAlt.'\', \''.$iconName.'\')';
$iconCode = img_picto($tooltip, $iconName, '', 0, 0, 0, '', 'classfortooltip');
print '<span class="doc-icon-list-item">'.$iconCode.'<span class="doc-icon-hidden-name-for-search">'.$iconName.'</span></span>';
}
}
?>
</div>
<div class="search-tool-no-results center hidden-search-result" ><?php print $langs->trans('NoResults') ?></div>
</div>
</div>
<!-- -->
@@ -135,10 +167,22 @@ $documentation->showSidebar(); ?>
<h2 class="documentation-title"><?php echo $langs->trans('DocIconsListFontAwesome'); ?></h2>
<?php /* <p class="documentation-text"><?php echo $langs->trans('DocDocIconsListDescription'); ?></p>*/ ?>
<?php print $form->getSearchFilterToolInput('.documentation-fontawesome-icon-list .info-box, .documentation-fontawesome-icon-list .doc-icon-list-item',
'search-tools-input',
'',
['attr' => [
'data-no-item-target' => '#icon-section-list .search-tool-no-results',
],
]
); ?>
<div class="right">
<?php print dolGetButtonTitle($revertDisplayName, '', $switchDisplayLinkIcon, $switchDisplayLink.'#icon-section-list', '', 1, ['forcenohideoftext'=>1]); ?>
</div>
<div class="documentation-example">
<div class="documentation-fontawesome-icon-list">
<?php
$alreadyDisplay = [];
if ($fontAwesomeIcons && is_array($fontAwesomeIcons)) {
@@ -157,7 +201,7 @@ $documentation->showSidebar(); ?>
$alreadyDisplay[] = $class;
$iconCode = '<span class="'.$class.'" ></span>';
if ($displayMode == 'kanban') {
print '<div class="info-box ">
<span class="info-box-icon bg-infobox-expensereport">
' . $iconCode . '
@@ -173,10 +217,16 @@ $documentation->showSidebar(); ?>
</div><!-- /.info-box-lines -->
</div><!-- /.info-box-content -->
</div>';
} else {
$tooltip = $class;
print '<span class="doc-icon-list-item classfortooltip" title="'.dol_escape_htmltag($tooltip).'">'.$iconCode.'<span class="doc-icon-hidden-name-for-search">'.$class.'</span></span>';
}
}
}
?>
</div>
<div class="search-tool-no-results center hidden-search-result" ><?php print $langs->trans('NoResults') ?></div>
</div>
</div>
<!-- -->

View File

@@ -42,9 +42,13 @@ $action = GETPOST('action', 'alpha');
//
$documentation = new Documentation($db);
$morejs = [
'/includes/ace/src/ace.js',
'/includes/ace/src/ext-statusbar.js',
'/includes/ace/src/ext-language_tools.js',
];
// Output html head + body - Param is Title
$documentation->docHeader('Inputs');
$documentation->docHeader('Inputs', $morejs);
// Set view for menu and breadcrumb
// Menu must be set in constructor of documentation class
@@ -79,11 +83,11 @@ $documentation->showSidebar(); ?>
</div>
<?php
$lines = array(
'<td>Available Input</td>',
'<td><input id="label" name="label" class="minwidth200" maxlength="255" value=""></td>',
'Available Input',
'<input id="label" name="label" class="minwidth200" maxlength="255" value="">',
'',
'<td>Disabled Input</td>',
'<td><input id="label" name="label" class="minwidth200" maxlength="255" value="" disabled></td>',
'Disabled Input',
'<input id="label" name="label" class="minwidth200" maxlength="255" value="" disabled>',
);
echo $documentation->showCode($lines); ?>
@@ -136,6 +140,7 @@ $documentation->showSidebar(); ?>
<?php
$lines = array(
'<?php',
'',
'/**',
' * Function selectarray',
' *',
@@ -158,14 +163,15 @@ $documentation->showSidebar(); ?>
' * @return string HTML select string.,',
' */',
'',
'<td>Select with empty value</td>',
'// Select with empty value',
'print $form->selectarray(\'htmlnameselectwithemptyvalue\', $values, \'idselectwithemptyvalue\', 1, 0, 0, \'\', 0, 0, 0, \'\', \'minwidth200\');',
'',
'<td>Select within empty value</td>',
'// Select within empty value',
'print $form->selectarray(\'htmlnameselectwithinemptyvalue\', $values, \'idnameselectwithinemptyvalue\', 0,0, 0, \'\', 0, 0, 0, \'\', \'minwidth200\');',
);
echo $documentation->showCode($lines); ?>
echo $documentation->showCode($lines, 'php'); ?>
<!-- Multiselect input -->
<p class="documentation-text"><?php echo $langs->trans('DocMultiSelectInputsDescription'); ?></p>
@@ -180,6 +186,7 @@ $documentation->showSidebar(); ?>
<?php
$lines = array(
'<?php',
'',
'/**',
' * Show a multiselect form from an array. WARNING: Use this only for short lists.',
' *',
@@ -199,10 +206,10 @@ $documentation->showSidebar(); ?>
' * @see selectarray(), selectArrayAjax(), selectArrayFilter()',
' */',
'',
'<td>Multiselect</td>',
'// Multiselect',
'print $form->multiselectarray(\'categories\', $values, GETPOST(\'categories\', \'array\'), 0, 0, \'minwidth200\', 0, 0);'
);
echo $documentation->showCode($lines); ?>
echo $documentation->showCode($lines, 'php'); ?>
<!-- Date input -->
<p class="documentation-text"><?php echo $langs->trans('DocDateSelectInputsDescription'); ?></p>
@@ -223,6 +230,7 @@ $documentation->showSidebar(); ?>
</div>
<?php
$lines = array(
'<?php',
'/**',
' * Show a HTML widget to input a date or combo list for day, month, years and optionally hours and minutes.,',
' * Fields are preselected with :,',
@@ -252,13 +260,13 @@ $documentation->showSidebar(); ?>
' * @see form_date(), select_month(), select_year(), select_dayofweek(),',
' */',
'',
'<td>Date Select</td>',
'// Date Select',
'print $form->selectDate();',
'',
'<td>Date Select with hours</td>',
'// Date Select with hours',
'print $form->selectDate(\'\', \'re2\', 1, 1, 1);'
);
echo $documentation->showCode($lines); ?>
echo $documentation->showCode($lines, 'php'); ?>
<!-- Editor input -->
@@ -295,7 +303,107 @@ $documentation->showSidebar(); ?>
'$doleditor = new DolEditor(\'desc\', GETPOST(\'desc\', \'restricthtml\'), \'\', 160, \'dolibarr_details\', \'\', false, true, getDolGlobalString(\'FCKEDITOR_ENABLE_DETAILS\'), ROWS_4, \'90%\');',
'print $form->multiselectarray(\'categories\', $values, GETPOST(\'categories\', \'array\'), 0, 0, \'minwidth200\', 0, 0);'
);
echo $documentation->showCode($lines); ?>
echo $documentation->showCode($lines, 'php'); ?>
</div>
<!-- Search Filter Tool Input -->
<div class="documentation-section" id="setinputssection-getSearchFilterToolInput">
<h2 class="documentation-title"><?php echo $langs->trans('DocSearchInputUsage'); ?></h2>
<p class="documentation-text"><?php echo $langs->trans('DocSearchInputUsageDescription'); ?></p>
<div class="documentation-example">
<?php
$containerCssSelector = '#demo-search-filter-tool-container-01';
print $form->getSearchFilterToolInput(
$containerCssSelector. ' .search-item',
'',
'',
['attr' => [
'data-counter-target' => $containerCssSelector. ' .counter',
'data-no-item-target' => $containerCssSelector. ' .search-tool-no-results',
],
]
);
?>
<div id="demo-search-filter-tool-container-01">
<p>Counter : <strong class="counter">12</strong></p>
<ul>
<li class="search-item">France</li>
<li class="search-item">Italy</li>
<li class="search-item">Germany</li>
<li class="search-item">Spain</li>
<li class="search-item">Canada</li>
<li class="search-item">Brazil</li>
<li class="search-item">Argentina</li>
<li class="search-item">Japan</li>
<li class="search-item">Australia</li>
<li class="search-item">India</li>
<li class="search-item">Egypt</li>
<li class="search-item">South Africa</li>
</ul>
<div class="search-tool-no-results hidden-search-result" ><?php print $langs->trans('NoResults') ?></div>
</div>
</div>
<?php
$lines = array(
'<div class="search-tool-container">',
' <input ',
' type="search"',
' name=""',
' autofocus="" <? // To use only if search is in top of page ?> ',
' value=""',
' class="search-tool-input" <? // optional for js filter you can use custom class ?> ',
' placeholder="Search"',
' autocomplete="off"',
' data-search-tool-target="#demo-filter .search-item" <? // required for js filter ?> ',
' data-counter-target="#demo-filter .counter" <? // optional for js filter ?> ',
' data-no-item-target="#demo-filter .search-tool-no-results" <? // optional for js filter ?> ',
' >',
'</div>',
'<div id="demo-filter">',
' <p>Counter : <strong class="counter">4</strong></p>',
' <ul>',
' <li class="search-item">France</li>',
' <li class="search-item">Italy</li>',
' <li class="search-item">Germany</li>',
' <li class="search-item">Spain</li>',
' </ul>',
' <div class="search-tool-no-results hidden-search-result" >No results</div>',
'</div>',
);
echo $documentation->showCode($lines, 'php');
$lines = array(
'<?php',
'print $form->getSearchFilterToolInput(',
' \'#demo-filter .search-item\',',
' \'search-tools-input\',',
' [\'attr\' => [',
' \'data-no-item-target\' => \'#demo-filter .search-tool-no-results\', ',
' \'data-counter-target\' => \'#demo-filter .counter\', ',
' ],',
' ]',
'); ',
'?>',
'',
'<div id="demo-filter">',
' <p>Counter : <strong class="counter">4</strong></p>',
' <ul>',
' <li class="search-item">France</li>',
' <li class="search-item">Italy</li>',
' <li class="search-item">Germany</li>',
' <li class="search-item">Spain</li>',
' </ul>',
' <div class="search-tool-no-results hidden-search-result" >No results</div>',
'</div>',
);
echo $documentation->showCode($lines, 'php');
?>
</div>
</div>

View File

@@ -0,0 +1,25 @@
.doc-icon-list-item {
--icon-size : 30px;
--icon-margin : 10px;
display: inline-block;
margin-left: 15px;
font-size: var(--icon-size);
line-height: calc( var(--icon-size) + var(--icon-margin));
width: calc( var(--icon-size) + var(--icon-margin));
height: calc( var(--icon-size) + var(--icon-margin));
text-align: center;
}
.doc-icon-list-item:hover {
outline: 1px solid #00000055;
}
/* fix some icon display in list */
.doc-icon-list-item :is(.fa-toggle-on, .fa-toggle-off){
font-size: 1em;
}
.doc-icon-hidden-name-for-search{
display: none;
}

View File

@@ -122,7 +122,16 @@ function printDropdownBookmarksList()
}
$bookmarkList .= '</div>';
$searchForm .= '<input name="bookmark" id="top-bookmark-search-input" class="dropdown-search-input" placeholder="'.$langs->trans('Bookmarks').'" autocomplete="off" >';
$searchForm .= '<input ';
$searchForm .= ' name="bookmark" ';
$searchForm .= ' id="top-bookmark-search-input" ';
$searchForm .= ' class="dropdown-search-input" ';
$searchForm .= ' placeholder="' . $langs->trans('Bookmarks') . '" ';
$searchForm .= ' data-search-tool-target="#dropdown-bookmarks-list .bookmark-item" ';
$searchForm .= ' data-counter-target="#top-bookmark-search-filter-count" ';
$searchForm .= ' data-no-item-target="#top-bookmark-search-nothing-found" ';
$searchForm .= ' autocomplete="off" ';
$searchForm .= ' >';
} else {
$searchForm .= '<select name="bookmark" id="boxbookmark" class="topmenu-bookmark-dropdown .dropdown-toggle maxwidth100">';
$searchForm .= '<option hidden value="listbookmarks" class="optiongrey" selected rel="'.DOL_URL_ROOT.'/bookmarks/list.php">'.$langs->trans('Bookmarks').'</option>';
@@ -209,29 +218,6 @@ function printDropdownBookmarksList()
<span id="top-bookmark-search-nothing-found" class="'.($bookmarkNb ? 'hidden-search-result ' : '').'opacitymedium">'.dol_escape_htmltag($langs->trans("NoBookmarkFound")).'</span>
</div>
';
$html .= '<!-- script to open/close the popup -->
<script>
jQuery(document).on("keyup", "#top-bookmark-search-input", function () {
console.log("keyup in bookmark search input");
var filter = $(this).val(), count = 0;
jQuery("#dropdown-bookmarks-list .bookmark-item").each(function () {
if ($(this).text().search(new RegExp(filter, "i")) < 0) {
$(this).addClass("hidden-search-result");
} else {
$(this).removeClass("hidden-search-result");
count++;
}
});
jQuery("#top-bookmark-search-filter-count").text(count);
if (count == 0) {
jQuery("#top-bookmark-search-nothing-found").removeClass("hidden-search-result");
} else {
jQuery("#top-bookmark-search-nothing-found").addClass("hidden-search-result");
}
});
</script>';
}
return $html;

View File

@@ -12189,4 +12189,71 @@ class Form
return $out;
}
/**
* @param string $dataTarget a css target like '.element-item-to-search-in' OR '#id-of-parent .class-of-container > .element-item-to-search-in'
* Ex : search element in a table row : '#table-id tr'
* @param string $htmlName the html name attribute
* @param string $value the html value attribute
* @param array<mixed> $params a mixed array of params
*
* @return string
*/
public function getSearchFilterToolInput($dataTarget, $htmlName = 'search-tools-input', $value = '', $params = [])
{
global $langs;
$attr = array(
'type' => 'search',
'name' => $htmlName,
'value' => $value,
'class' => "search-tool-input",
'placeholder' => $langs->trans('Search'),
'autocomplete' => 'off'
);
// Optional data attr
// 'autofocus' : will set auto focus on field ,
// data-counter-target : will get count results
// data-no-item-target : will be display if count results is 0
if ($dataTarget !== false) {
$attr['data-search-tool-target'] = $dataTarget;
}
// Override attr
if (!empty($params['attr']) && is_array($params['attr'])) {
foreach ($params['attr'] as $key => $value) {
if ($key == 'class') {
$attr['class'] .= ' '.$value;
} elseif ($key == 'classOverride') {
$attr['class'] = $value;
} else {
$attr[$key] = $value;
}
}
}
// automatic add tooltip when title is detected
if (!empty($attr['title']) && !empty($attr['class']) && strpos($attr['class'], 'classfortooltip') === false) {
$attr['class'] .= ' classfortooltip';
}
$TCompiledAttr = [];
foreach ($attr as $key => $value) {
if (in_array($key, ['data-target'])
|| (!empty($params['use_unsecured_unescapedattr']) && is_array($params['use_unsecured_unescapedattr']) && in_array($key, $params['use_unsecured_unescapedattr']))) { // Not recommended
$value = dol_htmlentities($value, ENT_QUOTES | ENT_SUBSTITUTE);
} else {
$value = dolPrintHTMLForAttribute($value);
}
$TCompiledAttr[] = $key . '="' . $value . '"'; // $value has been escaped by the dolPrintHTMLForAttribute... just before
}
$compiledAttributes = implode(' ', $TCompiledAttr);
return '<div class="search-tool-container"><input '.$compiledAttributes.'></div>';
}
}

View File

@@ -415,3 +415,7 @@ print '
});
});
'."\n";
// JS CODE USED by form::getSearchFilterToolInput
include __DIR__ . '/lib_foot_search_tool.js';

View File

@@ -0,0 +1,66 @@
/* Copyright (C) 2025 John BOTELLA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
* or see https://www.gnu.org/
*/
/**
* \file htdocs/core/js/lib_foot_search_tool.js.php
* \brief File that include javascript functions (included if option use_javascript activated)
*
* this file is included in htdocs/core/js/lib_foot.js.php
*/
/**
* JS CODE USED by form::getSearchFilterToolInput
* This code allow quick filtering on user key press
* */
$(function() {
$("[data-search-tool-target]").on("keyup", function () {
let search = $(this).val();
let target = $(this).attr('data-search-tool-target');
let targetCounter = $(this).attr('data-counter-target');
let targetNoResultTarget = $(this).attr('data-no-item-target');
let count = 0;
if (target == undefined || target.length === 0) {
return;
}
if (search.length > 0) {
$(target).addClass('hidden-search-result');
$(target).each(function () {
if ($(this).text().toUpperCase().indexOf(search.toUpperCase()) != -1) {
$(this).removeClass('hidden-search-result');
count++;
}
});
} else {
$(target).removeClass('hidden-search-result');
count = $(target).length;
}
if(targetCounter != undefined && $(targetCounter)){
$(targetCounter).text(count);
}
if(targetNoResultTarget != undefined && $(targetNoResultTarget)){
if (count == 0 && search.length !== 0) {
$(targetNoResultTarget).removeClass("hidden-search-result");
} else {
$(targetNoResultTarget).addClass("hidden-search-result");
}
}
});
});

View File

@@ -107,9 +107,12 @@ DocClassicInputsDescription = Classic input to enter string values, integer valu
DocCheckboxInputsDescription = Checkbox input to enter boolean values
DocRadioInputsDescription = Radio input to enter boolean values
DocHelperFunctionsInputUsage = Helper functions usage
DocHelperFunctionsGetSearchFilterToolInput = Helper functions for search input + dynamic js filter
DocSelectInputsDescription = Select input to enter one value
DocMultiSelectInputsDescription = Multiselect input to enter several values
DocEditorInputsDescription = Editor input to enter text with HTML
DocDateSelectInputsDescription = Date input to enter a date with or without hours
DocInputsMainDescription = Documentation and examples for inputs
DocInputsTitle = Inputs
DocSearchInputUsage = Helper functions for search input + dynamic js filter
DocSearchInputUsageDescription = The attribute values `data-search-tool-target`, `data-counter-target`, and `data-no-item-target` are CSS selectors, allowing you to target multiple search areas. Example: `data-search-tool-target=".zone01, .zone02, .zone03"`

View File

@@ -451,57 +451,6 @@ li.liinputsearch {
}
/*
* SEARCH
*/
.dropdown-search-input {
width: 100%;
padding: 10px 35px 10px 20px;
background-color: transparent;
/*font-size: 14px;
line-height: 16px;*/
box-sizing: border-box;
color: #575756;
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-size: 16px 16px;
background-position: 95% center;
border-radius: 20px;
border: 1px solid #c4c4c2 !important;
transition: all 250ms ease-in-out;
backface-visibility: hidden;
transform-style: preserve-3d;
}
.dropdown-search-input::placeholder {
color: #888;
letter-spacing: 1.5px;
}
.hidden-search-result{
display: none !important;
}
.search-dropdown-body {
padding: unset;
}
.global-search-item {
font-size: 1.1em;
}
.global-search-item:before {
content: none;
}
.global-search-header {
color: #444 !important;
}
/*
* QUICK ADD
@@ -679,7 +628,7 @@ div.quickaddblock:focus {
/* smartphone */
@media only screen and (max-width: 767px)
{
.dropdown-search-input {
.dropdown-search-input,.search-tool-input {
width: 100%;
}

View File

@@ -9015,6 +9015,7 @@ include dol_buildpath($path.'/theme/'.$theme.'/emaillayout.inc.php', 0);
include dol_buildpath($path.'/theme/'.$theme.'/info-box.inc.php', 0);
include dol_buildpath($path.'/theme/'.$theme.'/progress.inc.php', 0);
include dol_buildpath($path.'/theme/'.$theme.'/timeline.inc.php', 0);
include dol_buildpath($path.'/theme/'.$theme.'/search-input.inc.css', 0);
// Add custom CSS if defined

View File

@@ -0,0 +1,68 @@
/*
* SEARCH
*/
.search-tool-container{
min-width: 70%;
margin: 2em 0 2em 0;
text-align: center;
}
.dropdown-search-input,
.search-tool-input,
input.search-tool-input:focus:not(.button):not(.buttonwebsite):not(.buttonreset):not(.select2-search__field):not(#top-bookmark-search-input):not(.search_component_input):not(.input-search-takepos) {
width: 100%;
padding: 10px 35px 10px 20px;
background-color: transparent;
font-size: 14px;
line-height: 16px;
box-sizing: border-box;
color: #575756;
background-color: transparent;
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-size: 16px 16px;
background-position: 95% center;
background-position: calc(100% - 16px) center;
border-radius: 50px !important;
border: 1px solid #c4c4c2 !important;
transition: all 250ms ease-in-out;
backface-visibility: hidden;
transform-style: preserve-3d;
font-style: oblique;
max-width: 600px;
}
:is(.dropdown-search-input,.search-tool-input)::placeholder {
color: #888;
letter-spacing: 1.5px;
}
.search-tool-no-results {
opacity: 0.4;
padding: 5px;
}
.hidden-search-result {
display: none !important;
}
.search-dropdown-body {
padding: unset;
}
.global-search-item {
font-size: 1.1em;
}
.global-search-item:before {
content: none;
}
.global-search-header {
color: #444 !important;
}

View File

@@ -506,23 +506,6 @@ li.liinputsearch {
}
.search-dropdown-body {
padding: unset;
}
.global-search-item {
font-size: 1.1em;
padding-top: 8px;
padding-bottom: 8px;
}
.global-search-item:before {
content: none;
}
.global-search-header {
color: #444 !important;
}
/*

View File

@@ -0,0 +1,70 @@
/*
* SEARCH
*/
.search-tool-container{
min-width: 70%;
margin: 2em 0 2em 0;
text-align: center;
}
.search-tool-input,
input.search-tool-input:focus:not(.button):not(.buttonwebsite):not(.buttonreset):not(.select2-search__field):not(#top-bookmark-search-input):not(.search_component_input):not(.input-search-takepos) {
width: 100%;
padding: 10px 35px 10px 20px;
background-color: transparent;
font-size: 14px;
line-height: 16px;
box-sizing: border-box;
color: #575756;
background-color: transparent;
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-size: 16px 16px;
background-position: 95% center;
background-position: calc(100% - 16px) center;
border-radius: 50px !important;
border: 1px solid #c4c4c2 !important;
transition: all 250ms ease-in-out;
backface-visibility: hidden;
transform-style: preserve-3d;
font-style: oblique;
max-width: 600px;
}
:is(.dropdown-search-input,.search-tool-input)::placeholder {
color: #888;
letter-spacing: 1.5px;
}
.search-tool-no-results {
opacity: 0.4;
padding: 5px;
}
.hidden-search-result{
display: none !important;
}
.search-dropdown-body {
padding: unset;
}
.global-search-item {
font-size: 1.1em;
padding-top: 8px;
padding-bottom: 8px;
}
.global-search-item:before {
content: none;
}
.global-search-header {
color: #444 !important;
}

View File

@@ -8767,6 +8767,7 @@ include dol_buildpath($path.'/theme/eldy/emaillayout.inc.php', 0); // actually m
include dol_buildpath($path.'/theme/'.$theme.'/info-box.inc.php', 0);
include dol_buildpath($path.'/theme/'.$theme.'/progress.inc.php', 0);
include dol_buildpath($path.'/theme/eldy/timeline.inc.php', 0); // actually md use same style as eldy theme
include dol_buildpath($path.'/theme/'.$theme.'/search-input.inc.css', 0); // actually md use same style as eldy theme
if (getDolGlobalString('THEME_CUSTOM_CSS')) {
print $conf->global->THEME_CUSTOM_CSS;