29
0
mirror of https://github.com/joomla/joomla-cms.git synced 2024-06-25 14:53:01 +00:00

[4.0] highlight js (#33089)

This commit is contained in:
Dimitris Grammatikogiannis 2021-04-19 08:30:11 +02:00 committed by GitHub
parent 2126f03726
commit fab283efd8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 220 additions and 10430 deletions

View File

@ -1,111 +0,0 @@
/**
* @package Joomla.JavaScript
* @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
// Only define the Joomla namespace if not defined.
if (typeof(Joomla) === 'undefined') {
var Joomla = {};
}
Joomla.Highlighter = function(_options){
var $, words, options = {
autoUnhighlight: true,
caseSensitive: false,
startElement: false,
endElement: false,
elements: [],
className: 'highlight',
onlyWords: true,
tag: 'span'
},
highlight = function (words) {
if (words.constructor === String) {
words = [words];
}
if (options.autoUnhighlight) {
unhighlight(words);
}
var pattern = options.onlyWords ? '\b' + pattern + '\b' : '(' + words.join('\\b|\\b') + ')',
regex = new RegExp(pattern, options.caseSensitive ? '' : 'i');
options.elements.map(function(el){
recurse(el, regex, options.className);
});
return this;
},
unhighlight = function (words) {
if (words.constructor === String) {
words = [words];
}
var $elements, tn;
words.map(function(word){
word = (options.caseSensitive ? word : word.toUpperCase());
if (words[word]) {
$elements = $(words[word]);
$elements.removeClass();
$elements.each(function (index, el) {
tn = document.createTextNode($(el).text());
el.parentNode.replaceChild(tn, el);
});
}
});
return this;
},
recurse = function (node, regex, klass) {
if (node.nodeType === 3) {
var match = node.nodeValue.match(regex), highlight, $highlight, wordNode, wordClone, comparer, i;
if (match) {
highlight = document.createElement(options.tag);
$highlight = $(highlight);
$highlight.addClass(klass);
wordNode = node.splitText(match.index);
wordNode.splitText(match[0].length);
wordClone = wordNode.cloneNode(true);
$highlight.append(wordClone);
$(wordNode).replaceWith(highlight)
$highlight.attr('rel', $highlight.text());
comparer = $highlight.text()
if (!options.caseSensitive) {
comparer = $highlight.text().toUpperCase();
}
if (!words[comparer]) {
words[comparer] = [];
}
words[comparer].push(highlight);
return 1;
}
} else if ((node.nodeType === 1 && node.childNodes) && !/(script|style|textarea|iframe)/i.test(node.tagName) && !(node.tagName === options.tag.toUpperCase() && node.className === klass)) {
for (i = 0; i < node.childNodes.length; i++) {
i += recurse(node.childNodes[i], regex, klass);
}
}
return 0;
},
getElements = function ($start, $end) {
var $next = $start.next();
if ($next.attr('id') !== $end.attr('id')) {
options.elements.push($next.get(0));
getElements($next, $end);
}
},
initialize = function(_options) {
$ = jQuery.noConflict();
$.extend(options, _options);
getElements($(options.startElement), $(options.endElement));
words = [];
};
initialize(_options);
return {
highlight: highlight,
unhighlight : unhighlight
};
};

View File

@ -1,5 +0,0 @@
span.highlight {
background-color:#FFFFCC;
font-weight:bold;
padding:1px 0;
}

View File

@ -135,6 +135,29 @@
"dragula"
]
},
{
"name": "highlight-legacy",
"type": "script",
"uri": "system/highlight-es5.min.js",
"attributes": {
"defer": true,
"nomodule": true
},
"dependencies": [
"core"
]
},
{
"name": "highlight",
"type": "script",
"uri": "system/highlight.min.js",
"attributes": {
"type": "module"
},
"dependencies": [
"highlight-legacy"
]
},
{
"name": "field.passwordview",
"type": "script",

View File

@ -0,0 +1,70 @@
import Mark from 'mark.js/src/vanilla';
// mark.js defaults
const defaultOptions = {
exclude: [],
separateWordSearch: true,
accuracy: 'partially',
diacritics: true,
synonyms: {},
iframes: false,
iframesTimeout: 5000,
acrossElements: true,
caseSensitive: false,
ignoreJoiners: false,
wildcards: 'disabled',
compatibility: false,
};
if (Joomla.getOptions && typeof Joomla.getOptions === 'function' && Joomla.getOptions('highlight')) {
const scriptOptions = Joomla.getOptions('highlight');
scriptOptions.forEach((currentOpts) => {
const options = { ...defaultOptions, ...currentOpts };
// Continue only if the element exists
if (!options.compatibility) {
const element = document.querySelector(`.${options.class}`);
if (element) {
const instance = new Mark(element);
// Loop through the terms
options.highLight.forEach((term) => {
instance.mark(term, options);
});
}
} else {
const start = document.querySelector(`#${options.start}`);
const end = document.querySelector(`#${options.end}`);
const parent = start.parentNode;
const targetNodes = [];
const allElems = Array.from(parent.childNodes);
let startEl = false;
let stopEl = false;
// Remove all elements till start element
allElems.forEach((element) => {
if (!startEl || stopEl) {
return;
}
if (element === start) {
startEl = true;
return;
}
if (element === end) {
stopEl = true;
return;
}
if (startEl && !stopEl) {
targetNodes.push(element);
}
});
targetNodes.forEach((node) => {
const instance = new Mark(node);
// Loop through the terms
options.highLight.map((term) => instance.mark(term, options));
});
}
});
}

View File

@ -10,7 +10,6 @@
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri;
@ -48,11 +47,19 @@ use Joomla\CMS\Uri\Uri;
<?php endif; ?>
<?php // Activate the highlighter if enabled. ?>
<?php if (!empty($this->query->highlight) && $this->params->get('highlight_terms', 1)) : ?>
<?php HTMLHelper::_('behavior.highlighter', $this->query->highlight); ?>
<?php
$this->document->getWebAssetManager()->useScript('highlight');
$this->document->addScriptOptions(
'highlight',
[[
'class' => 'js-highlight',
'highLight' => $this->query->highlight,
]]
);
?>
<?php endif; ?>
<?php // Display a list of results ?>
<br id="highlighter-start" />
<ol id="search-result-list" class="com-finder__results-list" start="<?php echo (int) $this->pagination->limitstart + 1; ?>">
<ol id="search-result-list" class="js-highlight com-finder__results-list" start="<?php echo (int) $this->pagination->limitstart + 1; ?>">
<?php $this->baseUrl = Uri::getInstance()->toString(array('scheme', 'host', 'port')); ?>
<?php foreach ($this->results as $i => $result) : ?>
<?php $this->result = &$result; ?>
@ -61,7 +68,6 @@ use Joomla\CMS\Uri\Uri;
<?php echo $this->loadTemplate($layout); ?>
<?php endforeach; ?>
</ol>
<br id="highlighter-end" />
<?php // Display the pagination ?>
<div class="com-finder__navigation search-pagination">
<?php if ($this->params->get('show_pagination', 1) > 0) : ?>

View File

@ -11,7 +11,6 @@ namespace Joomla\CMS\HTML\Helpers;
\defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Filter\OutputFilter;
use Joomla\CMS\Language\Text;
/**
@ -56,6 +55,7 @@ abstract class Behavior
* @return void
*
* @since 3.4
* @deprecated 5.0 Use the script directly
*/
public static function formvalidator()
{
@ -79,6 +79,7 @@ abstract class Behavior
* @return void
*
* @since 1.5
* @deprecated 5.0 Use the script directly
*/
public static function combobox()
{
@ -93,6 +94,7 @@ abstract class Behavior
* @return void
*
* @since 1.7
* @deprecated 5.0 Use the script directly
*/
public static function multiselect($id = 'adminForm')
{
@ -139,59 +141,29 @@ abstract class Behavior
* @return void
*
* @since 2.5
*
* @deprecated 5.0 Use the script directly
*/
public static function highlighter(array $terms, $start = 'highlighter-start', $end = 'highlighter-end', $className = 'highlight', $tag = 'span')
{
$sig = md5(serialize(array($terms, $start, $end)));
if (isset(static::$loaded[__METHOD__][$sig]))
{
return;
}
$terms = array_filter($terms, 'strlen');
// Nothing to Highlight
if (empty($terms))
if (!empty($terms))
{
static::$loaded[__METHOD__][$sig] = true;
$doc = Factory::getDocument();
return;
$doc->getWebAssetManager()->useScript('highlight');
$doc->addScriptOptions(
'highlight',
[[
'class' => 'js-highlight',
'highLight' => $terms,
'compatibility' => true,
'start' => $start,
'end' => $end,
]]
);
}
/** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */
$wa = Factory::getApplication()->getDocument()->getWebAssetManager();
$wa
->registerScript('joomla.highlighter', 'legacy/highlighter.min.js', ['dependencies' => ['core', 'jquery']])
->useScript('joomla.highlighter');
foreach ($terms as $i => $term)
{
$terms[$i] = OutputFilter::stringJSSafe($term);
}
$document = Factory::getDocument();
$document->addScriptDeclaration("
jQuery(function ($) {
var start = document.getElementById('" . $start . "');
var end = document.getElementById('" . $end . "');
if (!start || !end || !Joomla.Highlighter) {
return true;
}
highlighter = new Joomla.Highlighter({
startElement: start,
endElement: end,
className: '" . $className . "',
onlyWords: false,
tag: '" . $tag . "'
}).highlight([\"" . implode('","', $terms) . "\"]);
$(start).remove();
$(end).remove();
});"
);
static::$loaded[__METHOD__][$sig] = true;
}
/**

10339
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -48,6 +48,7 @@
"joomla-ui-custom-elements": "0.0.40",
"jquery": "^3.6.0",
"jquery-migrate": "^3.3.2",
"mark.js": "^8.11.1",
"mediaelement": "^4.2.16",
"metismenujs": "^1.2.1",
"punycode": "^2.1.1",

View File

@ -10,8 +10,8 @@
defined('_JEXEC') or die;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Filter\InputFilter;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Component\Finder\Administrator\Indexer\Result;
@ -86,12 +86,24 @@ class PlgSystemHighlight extends CMSPlugin
}
// Activate the highlighter.
HTMLHelper::_('behavior.highlighter', $cleanTerms);
if (!empty($cleanTerms))
{
$doc = Factory::getDocument();
$doc->getWebAssetManager()->useScript('highlight');
$doc->addScriptOptions(
'highlight',
[[
'class' => 'js-highlight',
'highLight' => $cleanTerms,
]]
);
}
// Adjust the component buffer.
$doc = $this->app->getDocument();
$buf = $doc->getBuffer('component');
$buf = '<br id="highlighter-start" />' . $buf . '<br id="highlighter-end" />';
$buf = '<div class="js-highlight">' . $buf . '</div>';
$doc->setBuffer($buf, 'component');
}

View File

@ -224,3 +224,6 @@ $state-warning-border: scale-color($warning, $lightness: -5%) !de
$state-danger-text: $white !default;
$state-danger-bg: $danger !default;
$state-danger-border: scale-color($danger, $lightness: -5%) !default;
// Mark element
$mark-bg: #fbeea8 !default;