hovercss-1.0.3/hovercss_ui/hovercss_ui.module
hovercss_ui/hovercss_ui.module
<?php
/**
* @file
* Drupal`s integration with Hover.css library.
*
* Hover.css is a collection of CSS3 powered hover effects to be applied to
* links, buttons, logos, SVG, featured images and so on.
*
* Easily apply to your own elements, modify or just use for inspiration.
*
* Available in CSS, Sass, and LESS.
*
* Github: https://github.com/IanLunn/Hover
* Website: https://ianlunn.github.io/Hover/
* license: MIT licensed
*
* Copyright (C) 2013-2023 Ian Lunn
*/
use Drupal\Core\Asset\AttachedAssetsInterface;
use Drupal\Core\Installer\InstallerKernel;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Implements hook_help().
*/
function hovercss_ui_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
case 'help.page.hovercss_ui':
$output = '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('HoverCSS UI is a innovative and powerful Drupal module that provides hover effect dynamically, enhancing site interactivity with awesome animations.') . '</p>';
$output .= '<h3>' . t('Usage') . '</h3>';
$output .= '<dl>';
$output .= '<dt><strong>' . t('Hover admin page') . '</strong></dt>';
$output .= '<dd><p>' . t('Go to <a href=":hovercss_admin">Hover CSS</a> admin overview page in your Drupal administration configuration menu.', [':hovercss_admin' => Url::fromRoute('hovercss.admin')->setAbsolute()->toString()]) . '</p></dd>';
$output .= '<dd><p>' . t('Click on <a href=":add_effect">Add effect</a> button in top of the hover css admin overview page.', [':add_effect' => Url::fromRoute('hovercss.add')->setAbsolute()->toString()]) . '</p></dd>';
$output .= '<dd><p>' . t('Enter valid selector, you can use HTML tag, class with dot(.) and ID with hash(#) prefix.') . '</p></dd>';
$output .= '<dd><p>' . t('Then you can add hover effect.') . '</p></dd>';
$output .= '<dd><p>' . t('Save effect and that`s it, Enjoy animation with Hover!') . '</p></dd>';
$output .= '<br>';
$output .= '<dt><strong>' . t('HoverCSS global configuration page') . '</strong></dt>';
$output .= '<dd><p>' . t('Go to <a href=":hovercss_settings">Hover CSS settings</a> page in your Drupal configuration menu.', [':hovercss_settings' => Url::fromRoute('hovercss.settings')->setAbsolute()->toString()]) . '</p></dd>';
$output .= '<dd><p>' . t('You can change default setting options if you need such as:') . '</p></dd>';
$output .= '<div><ul>';
$output .= '<li><strong>' . t('Load Hover.css library') . '</strong><br><em>' . t('If enabled, this module will attempt to load the Hover.css library for your site.') . '</em></li>';
$output .= '<li><strong>' . t('Use Hover.css patch') . '</strong><br><em>' . t('If enabled, this module will use the patch for your hover to resolve Drupal button css conflicts.') . '</em></li>';
$output .= '<li><strong>' . t('Load on Specific URLs') . '</strong><br><em>' . t('If you use the hover library only for a special section or pages, you can control to load the Hover.css library to that page to improve performance.') . '</em></li>';
$output .= '<li><strong>' . t('Default Options') . '</strong><br><em>' . t('You can change the default settings of Hover options so that you don`t need to customize every time in the "Add effect" form.') . '</em></li>';
$output .= '<li><strong>' . t('Hover Preview') . '</strong><br><em>' . t('You can test your desired effect animation with its settings and see the result on different button types.') . '</em></li>';
$output .= '</ul></div>';
$output .= '</dl>';
$output .= '<br>';
$output .= '<h3>' . t('Additional Information') . '</h3>';
$output .= '<p>' . t('Pick existing valid selector you want to add hover effect by using right-click on your website, choose "Inspect" or "View page source (CTRL + U)" of context menu in your Chrome browser and find exact valid button class name.') . '</p>';
$output .= '<div><ul>';
$output .= '<li><strong>' . t('Use class with dot(.) and ID with hash(#) prefix or HTML tags.');
$output .= '</strong><br>e.g. "button", ".button", "#edit-submit" etc.</li>';
$output .= '<li><strong>' . t('Nested selector is allowed.');
$output .= '</strong><br>e.g. ".user-login-form .button", "body.page-node-type-article a.btn" etc.</li>';
$output .= '</ul></div>';
return $output;
}
}
/**
* Implements hook_css_alter().
*/
function hovercss_ui_css_alter(&$css, AttachedAssetsInterface $assets) {
// Load the Hover.css configuration settings.
$config = \Drupal::config('hovercss.settings');
$hover_library = [];
if (_hovercss_ui_check_admin()) {
if (hovercss_check_installed()) {
$hover_library = \Drupal::service('library.discovery')->getLibraryByName('hovercss_ui', 'hover-dev');
}
else {
$hover_library = \Drupal::service('library.discovery')->getLibraryByName('hovercss_ui', 'hover-cdn-dev');
}
$path = $hover_library['css'][0]['data'] ?? '';
if (isset($css[$path])) {
$css[$path]['group'] = 369;
// Check hover.patch.css.
if ($config->get('patch')) {
$hover_patch = \Drupal::service('library.discovery')->getLibraryByName('hovercss_ui', 'hover-patch');
$patch_path = $hover_patch['css'][0]['data'] ?? '';
if (isset($css[$patch_path])) {
$css[$patch_path]['group'] = 396;
}
}
}
}
// Don't include Hover.css library if the user has opted out of loading it.
if (!$config->get('load')) {
return TRUE;
}
// Don't add the Hover.css on specified paths.
if (!_hovercss_ui_check_url()) {
return TRUE;
}
// Check Hover.css with chosen method.
$method = hovercss_check_installed() ? $config->get('method') : 'cdn';
// Check for development and production version.
$variant_options = ['source', 'minified'];
$variant = $variant_options[$config->get('minimized.options')];
if ($method == 'cdn') {
// Check variant Hover.css is CDN.
switch ($variant) {
case 'minified':
$hover_library = \Drupal::service('library.discovery')->getLibraryByName('hovercss_ui', 'hover-cdn');
break;
case 'source':
$hover_library = \Drupal::service('library.discovery')->getLibraryByName('hovercss_ui', 'hover-cdn-dev');
break;
}
}
else {
// Check variant Hover.css is local.
switch ($variant) {
case 'minified':
$hover_library = \Drupal::service('library.discovery')->getLibraryByName('hovercss_ui', 'hover-css');
break;
case 'source':
$hover_library = \Drupal::service('library.discovery')->getLibraryByName('hovercss_ui', 'hover-dev');
break;
}
}
$path = $hover_library['css'][0]['data'] ?? '';
if (isset($css[$path])) {
$css[$path]['group'] = 369;
// Check hover.patch.css.
if ($config->get('patch')) {
$hover_patch = \Drupal::service('library.discovery')->getLibraryByName('hovercss_ui', 'hover-patch');
$patch_path = $hover_patch['css'][0]['data'] ?? '';
if (isset($css[$patch_path])) {
$css[$patch_path]['group'] = 396;
}
}
}
}
/**
* Implements hook_page_attachments().
*/
function hovercss_ui_page_attachments(array &$attachments) {
// Don't add the library during installation.
if (InstallerKernel::installationAttempted()) {
return;
}
// Load the Hover.css configuration settings.
$config = \Drupal::config('hovercss.settings');
// Checking the path to load Hover.css for demo examples,
// It's just in HoverCSS configuration.
if (_hovercss_ui_check_admin()) {
$options = $config->get('options');
$options['selector'] = '.hover__sample';
// Attach Hover.css for examples.
$attachments['#attached']['drupalSettings']['hovercss']['sample'] = $options;
if (hovercss_check_installed()) {
$attachments['#attached']['library'][] = 'hovercss_ui/hover-dev';
}
else {
$attachments['#attached']['library'][] = 'hovercss_ui/hover-cdn-dev';
}
// Attach hover.patch.css for examples.
if ($config->get('patch')) {
$attachments['#attached']['library'][] = 'hovercss_ui/hover-patch';
}
$attachments['#attached']['library'][] = 'hovercss_ui/hover-admin';
return;
}
// Don't include Hover.css library if the user has opted out of loading it.
if (!$config->get('load')) {
return TRUE;
}
// Don't add the Hover.css on specified paths.
if (!_hovercss_ui_check_url()) {
return TRUE;
}
// Check if config is an object.
if (is_object($config)) {
// Attach Hover.css by config.
_hovercss_ui_attach_library($attachments, $config);
}
// Get selectors from config.
$options = $config->get('options');
$hovered = [];
// Load enabled hover selectors from database.
$results = \Drupal::service('hovercss.effect_manager')->loadHover()->fetchAll();
if (count($results)) {
$selectors = [];
foreach ($results as $hover) {
$selectors[] = $hover->selector;
$hover_options = unserialize($hover->options, ['allowed_classes' => FALSE]);
$hovered[$hover->hid] = ['selector' => $hover->selector] + $hover_options;
}
// Merge global selectors from config with database selectors.
if (count($config->get('options.selector')) && count($selectors)) {
$options['selector'] = array_diff($options['selector'], $selectors);
// Attach config selectors after merge if there were any left.
if (count($options['selector'])) {
array_unshift($hovered, $options);
}
}
}
else {
// If global selectors are set, get the selectors from the configuration.
if (count($config->get('options.selector'))) {
$hovered = [$options];
}
}
// If there is hover selectors, then the init file
// with options will be added to the page.
if (count($hovered)) {
// Export settings.
$attachments['#attached']['drupalSettings']['hovercss']['elements'] = $hovered;
// Init hover.
$attachments['#attached']['library'][] = 'hovercss_ui/hover-init';
}
}
/**
* Check if Hover.css should be admin for the current URL.
*
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
* The request stack.
*
* @return bool
* TRUE if Hover.css should be active for the current page.
*/
function _hovercss_ui_check_admin(RequestStack $request_stack = NULL) {
if (!isset($request_stack)) {
$request_stack = \Drupal::requestStack();
}
$current_request = $request_stack->getCurrentRequest();
// Compare the lowercase path alias (if any) and internal path.
$currentPath = \Drupal::service('path.current')->getPath($current_request);
$settingPath = Url::fromRoute('hovercss.admin')->toString() . '/*';
return \Drupal::service('path.matcher')->matchPath($currentPath, $settingPath);
}
/**
* Check if Hover.css should be active for the current URL.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request to use if provided, otherwise \Drupal::request() will be used.
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
* The request stack.
*
* @return bool
* TRUE if Hover.css should be active for the current page.
*/
function _hovercss_ui_check_url(Request $request = NULL, RequestStack $request_stack = NULL) {
if (!isset($request)) {
$request = \Drupal::request();
}
// Assume there are no matches until one is found.
$page_match = FALSE;
// Make it possible deactivate letting with
// parameter ?hover=no in the url.
$query = $request->query;
if ($query->get('hover') !== NULL && $query->get('hover') == 'no') {
return $page_match;
}
// Convert path to lowercase. This allows comparison of the same path
// with different case. Ex: /Page, /page, /PAGE.
$config = \Drupal::config('hovercss.settings');
$pages = mb_strtolower(_hovercss_ui_array_to_string($config->get('url.pages')));
if (!$pages) {
return TRUE;
}
if (!isset($request_stack)) {
$request_stack = \Drupal::requestStack();
}
$current_request = $request_stack->getCurrentRequest();
// Compare the lowercase path alias (if any) and internal path.
$path = \Drupal::service('path.current')->getPath($current_request);
// Do not trim a trailing slash if that is the complete path.
$path = $path === '/' ? $path : rtrim($path, '/');
$langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
$path_alias = mb_strtolower(\Drupal::service('path_alias.manager')->getAliasByPath($path, $langcode));
$page_match = \Drupal::service('path.matcher')->matchPath($path_alias, $pages);
if ($path_alias != $path) {
$page_match = $page_match || \Drupal::service('path.matcher')->matchPath($path, $pages);
}
$page_match = $config->get('url.visibility') == 0 ? !$page_match : $page_match;
return $page_match;
}
/**
* Check if Hover.css library should be active for the current URL.
*
* @param array $attachments
* The page attachments.
* @param object $config
* The hover config settings.
*/
function _hovercss_ui_attach_library(array &$attachments, object $config) {
// Attach Hover.css to pages with chosen method.
$method = hovercss_check_installed() ? $config->get('method') : 'cdn';
// Check for load development and production version.
$variant_options = ['source', 'minified'];
$variant = $variant_options[$config->get('minimized.options')];
if ($method == 'cdn') {
// Check variant to load Hover.css from CDN.
switch ($variant) {
case 'minified':
$attachments['#attached']['library'][] = 'hovercss_ui/hover-cdn';
break;
case 'source':
$attachments['#attached']['library'][] = 'hovercss_ui/hover-cdn-dev';
break;
}
}
else {
// Check variant to load Hover.css from local.
switch ($variant) {
case 'minified':
$attachments['#attached']['library'][] = 'hovercss_ui/hover-css';
break;
case 'source':
$attachments['#attached']['library'][] = 'hovercss_ui/hover-dev';
break;
}
}
// Attach Hover.css patch .
if ($config->get('patch')) {
$attachments['#attached']['library'][] = 'hovercss_ui/hover-patch';
}
}
/**
* Converts a text with lines (\n) into an array of lines.
*
* @return array
* Array with as many items as non-empty lines in the text
*/
function _hovercss_ui_string_to_array($text) {
if (!is_string($text)) {
return NULL;
}
$text = str_replace("\r\n", "\n", $text);
return array_filter(explode("\n", $text), 'trim');
}
/**
* Converts an array of lines into a text with lines (\n).
*
* @return string
* Text with lines
*/
function _hovercss_ui_array_to_string($array) {
if (!is_array($array)) {
return NULL;
}
return implode("\r\n", $array);
}
