Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4.2] [GSoC 21] Keyboard-Shortcut Plugin #201

Closed
joomlapl-bot opened this issue Jun 23, 2022 · 0 comments
Closed

[4.2] [GSoC 21] Keyboard-Shortcut Plugin #201

joomlapl-bot opened this issue Jun 23, 2022 · 0 comments

Comments

@joomlapl-bot
Copy link
Collaborator

PR w związku ze zmianą oryginału joomla/joomla-cms#38092 Poniżej zmiany w oryginale:

Click to expand the diff!
diff --git a/administrator/components/com_admin/sql/updates/mysql/4.2.0-2022-06-19.sql b/administrator/components/com_admin/sql/updates/mysql/4.2.0-2022-06-19.sql
new file mode 100644
index 000000000000..55aa01c3968c
--- /dev/null
+++ b/administrator/components/com_admin/sql/updates/mysql/4.2.0-2022-06-19.sql
@@ -0,0 +1,3 @@
+-- See https://github.com/joomla/joomla-cms/pull/38092
+INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) VALUES
+(0, 'plg_system_shortcut', 'plugin', 'shortcut', 'system', 0, 1, 1, 0, 1, '', '', '', 0, 0);
diff --git a/administrator/components/com_admin/sql/updates/postgresql/4.2.0-2022-06-19.sql b/administrator/components/com_admin/sql/updates/postgresql/4.2.0-2022-06-19.sql
new file mode 100644
index 000000000000..6a2a3b204960
--- /dev/null
+++ b/administrator/components/com_admin/sql/updates/postgresql/4.2.0-2022-06-19.sql
@@ -0,0 +1,3 @@
+-- See https://github.com/joomla/joomla-cms/pull/38092
+INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") VALUES
+(0, 'plg_system_shortcut', 'plugin', 'shortcut', 'system', 0, 1, 1, 0, 1, '', '', '', 0, 0);
diff --git a/administrator/language/en-GB/plg_system_shortcut.ini b/administrator/language/en-GB/plg_system_shortcut.ini
new file mode 100644
index 000000000000..b1f63f712db3
--- /dev/null
+++ b/administrator/language/en-GB/plg_system_shortcut.ini
@@ -0,0 +1,12 @@
+; Joomla! Project
+; (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
+; License GNU General Public License version 2 or later; see LICENSE.txt
+; Note : All ini files need to be saved as UTF-8
+
+PLG_SYSTEM_SHORTCUT="System - Keyboard Shortcuts"
+PLG_SYSTEM_SHORTCUT_OVERVIEW_DESC="Press <kbd>J</kbd> to access the shortcut mode followed by the shortcut."
+PLG_SYSTEM_SHORTCUT_OVERVIEW_HINT="<span class=\"icon-keyboard fa-keyboard me-2\" aria-hidden=\"true\"></span> <kbd>J</kbd> + <kbd>X</kbd> <small>Keyboard Shortcuts</small>"
+PLG_SYSTEM_SHORTCUT_OVERVIEW_TITLE="Joomla Keyboard Shortcuts"
+PLG_SYSTEM_SHORTCUT_TIMEOUT_DESC="Maximum time that a shortcut can be pressed after pressing <kbd>J</kbd>."
+PLG_SYSTEM_SHORTCUT_TIMEOUT_LABEL="Timeout (in milliseconds)"
+PLG_SYSTEM_SHORTCUT_XML_DESCRIPTION="<p>Enables keyboard shortcuts on the administrator site, which can be provided by other plugins and includes directly the following list of shortcuts:</p><ul class=\"list-unstyled\"><li><kbd>J</kbd> <kbd>A</kbd> Save</li><li><kbd>J</kbd> <kbd>S</kbd> Save & Close</li><li><kbd>J</kbd> <kbd>Q</kbd> Cancel</li><li><kbd>J</kbd> <kbd>N</kbd> New</li><li><kbd>J</kbd> <kbd>F</kbd> Search</li><li><kbd>J</kbd> <kbd>O</kbd> Options</li><li><kbd>J</kbd> <kbd>H</kbd> Help</li><li><kbd>J</kbd> <kbd>X</kbd> Overview</li><li><kbd>J</kbd> <kbd>D</kbd> Home Dashboard</li></ul>"
diff --git a/administrator/language/en-GB/plg_system_shortcut.sys.ini b/administrator/language/en-GB/plg_system_shortcut.sys.ini
new file mode 100644
index 000000000000..365aa9ea155b
--- /dev/null
+++ b/administrator/language/en-GB/plg_system_shortcut.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
+; License GNU General Public License version 2 or later; see LICENSE.txt
+; Note : All ini files need to be saved as UTF-8
+
+PLG_SYSTEM_SHORTCUT="System - Keyboard Shortcuts"
+PLG_SYSTEM_SHORTCUT_XML_DESCRIPTION="<p>Enables keyboard shortcuts on the administrator site, which can be provided by other plugins and includes directly the following list of shortcuts:</p><ul class=\"list-unstyled\"><li><kbd>J</kbd> <kbd>A</kbd> Save</li><li><kbd>J</kbd> <kbd>S</kbd> Save & Close</li><li><kbd>J</kbd> <kbd>Q</kbd> Cancel</li><li><kbd>J</kbd> <kbd>N</kbd> New</li><li><kbd>J</kbd> <kbd>F</kbd> Search</li><li><kbd>J</kbd> <kbd>O</kbd> Options</li><li><kbd>J</kbd> <kbd>H</kbd> Help</li><li><kbd>J</kbd> <kbd>X</kbd> Overview</li><li><kbd>J</kbd> <kbd>D</kbd> Home Dashboard</li></ul>"
diff --git a/build/build-modules-js/settings.json b/build/build-modules-js/settings.json
index 8924c2334562..f6c5f39d67e9 100644
--- a/build/build-modules-js/settings.json
+++ b/build/build-modules-js/settings.json
@@ -386,6 +386,24 @@
         "dependencies": [],
         "licenseFilename": "LICENSE.txt"
       },
+      "hotkeys-js": {
+        "name": "hotkeys.js",
+        "licenseFilename": "LICENSE",
+        "js" : {
+          "dist/hotkeys.js": "js/hotkeys.js",
+          "dist/hotkeys.min.js": "js/hotkeys.min.js"
+        },
+        "provideAssets": [
+          {
+            "name": "hotkeys.js",
+            "type": "script",
+            "uri": "hotkeys.min.js",
+            "attributes": {
+              "defer": true
+            }
+          }
+        ]
+      },
       "jquery": {
         "name": "jquery",
         "js": {
diff --git a/build/media_source/plg_system_shortcut/js/shortcut.es6.js b/build/media_source/plg_system_shortcut/js/shortcut.es6.js
new file mode 100644
index 000000000000..61cbc8b27ca8
--- /dev/null
+++ b/build/media_source/plg_system_shortcut/js/shortcut.es6.js
@@ -0,0 +1,168 @@
+((document, Joomla) => {
+  'use strict';
+
+  if (!Joomla) {
+    throw new Error('Joomla API is not properly initialised');
+  }
+
+  /* global hotkeys */
+  Joomla.addShortcut = (hotkey, callback) => {
+    hotkeys(hotkey, 'joomla', (event) => {
+      event.preventDefault();
+      event.stopPropagation();
+      event.stopImmediatePropagation();
+
+      callback.call();
+    });
+  };
+
+  Joomla.addClickShortcut = (hotkey, selector) => {
+    Joomla.addShortcut(hotkey, () => {
+      const element = document.querySelector(selector);
+      if (element) {
+        element.click();
+      }
+    });
+  };
+
+  Joomla.addFocusShortcut = (hotkey, selector) => {
+    Joomla.addShortcut(hotkey, () => {
+      const element = document.querySelector(selector);
+      if (element) {
+        element.focus();
+      }
+    });
+  };
+
+  Joomla.addLinkShortcut = (hotkey, selector) => {
+    Joomla.addShortcut(hotkey, () => {
+      window.location.href = selector;
+    });
+  };
+
+  const setShortcutFilter = () => {
+    hotkeys.filter = (event) => {
+      const target = event.target || event.srcElement;
+      const { tagName } = target;
+
+      // Checkboxes should not block a shortcut event
+      if (target.type === 'checkbox') {
+        return true;
+      }
+      // Default hotkeys filter behavior
+      return !(target.isContentEditable || tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA');
+    };
+  };
+
+  const startupShortcuts = () => {
+    hotkeys('J', (event) => {
+      // If we're already in the scope, it's a normal shortkey
+      if (hotkeys.getScope() === 'joomla') {
+        return;
+      }
+
+      event.preventDefault();
+      event.stopPropagation();
+      event.stopImmediatePropagation();
+
+      hotkeys.setScope('joomla');
+
+      // Leave the scope after x milliseconds
+      setTimeout(() => {
+        hotkeys.setScope(false);
+      }, Joomla.getOptions('plg_system_shortcut.timeout', 2000));
+    });
+  };
+
+  const addOverviewHint = () => {
+    const mainContainer = document.querySelector('.com_cpanel .container-main');
+    if (mainContainer) {
+      const containerElement = document.createElement('section');
+      containerElement.className = 'content pt-4';
+      containerElement.insertAdjacentHTML('beforeend', Joomla.Text._('PLG_SYSTEM_SHORTCUT_OVERVIEW_HINT'));
+      mainContainer.appendChild(containerElement);
+    }
+  };
+
+  const initOverviewModal = (options) => {
+    const dlItems = new Map();
+    Object.values(options).forEach((value) => {
+      if (!value.shortcut || !value.title) {
+        return;
+      }
+      let titles = [];
+      if (dlItems.has(value.shortcut)) {
+        titles = dlItems.get(value.shortcut);
+        titles.push(value.title);
+      } else {
+        titles = [value.title];
+      }
+      dlItems.set(value.shortcut, titles);
+    });
+
+    let dl = '<dl>';
+    dlItems.forEach((titles, shortcut) => {
+      dl += '<dt><kbd>J</kbd>';
+      shortcut.split('+').forEach((key) => {
+        dl += ` <kbd>${key.trim()}</kbd>`;
+      });
+      dl += '</dt>';
+      titles.forEach((title) => {
+        dl += `<dd>${title}</dd>`;
+      });
+    });
+    dl += '</dl>';
+
+    const modal = `
+      <div class="modal fade" id="shortcutOverviewModal" tabindex="-1" role="dialog" data-bs-backdrop="static" aria-labelledby="shortcutOverviewModalLabel" aria-hidden="true">
+        <div class="modal-dialog" role="document">
+          <div class="modal-content">
+            <div class="modal-header">
+              <h3 id="shortcutOverviewModalLabel" class="modal-title">
+                ${Joomla.Text._('PLG_SYSTEM_SHORTCUT_OVERVIEW_TITLE')}
+              </h3>
+              <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${Joomla.Text._('JCLOSE')}"></button>
+            </div>
+            <div class="modal-body p-3">
+              <p>${Joomla.Text._('PLG_SYSTEM_SHORTCUT_OVERVIEW_DESC')}</p>
+              <div class="mb-3">
+                ${dl}
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    `;
+
+    document.body.insertAdjacentHTML('beforeend', modal);
+
+    const bootstrapModal = new bootstrap.Modal(document.getElementById('shortcutOverviewModal'), {
+      keyboard: true,
+      backdrop: true,
+    });
+    hotkeys('X', 'joomla', () => bootstrapModal.show());
+  };
+
+  document.addEventListener('DOMContentLoaded', () => {
+    const options = Joomla.getOptions('plg_system_shortcut.shortcuts');
+    Object.values(options).forEach((value) => {
+      if (!value.shortcut || !value.selector) {
+        return;
+      }
+      if (value.selector.startsWith('/') || value.selector.startsWith('http://') || value.selector.startsWith('www.')) {
+        Joomla.addLinkShortcut(value.shortcut, value.selector);
+      } else if (value.selector.includes('input')) {
+        Joomla.addFocusShortcut(value.shortcut, value.selector);
+      } else {
+        Joomla.addClickShortcut(value.shortcut, value.selector);
+      }
+    });
+    // Show hint and overview on logged in backend only (not login page)
+    if (document.querySelector('nav')) {
+      initOverviewModal(options);
+      addOverviewHint();
+    }
+    setShortcutFilter();
+    startupShortcuts();
+  });
+})(document, Joomla);
diff --git a/installation/sql/mysql/base.sql b/installation/sql/mysql/base.sql
index c0efa2026b9b..ca59eeff59fa 100644
--- a/installation/sql/mysql/base.sql
+++ b/installation/sql/mysql/base.sql
@@ -341,6 +341,7 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`,
 (0, 'plg_system_schedulerunner', 'plugin', 'schedulerunner', 'system', 0, 1, 1, 0, 0, '', '{}', '', 17, 0),
 (0, 'plg_system_sef', 'plugin', 'sef', 'system', 0, 1, 1, 0, 1, '', '', '', 18, 0),
 (0, 'plg_system_sessiongc', 'plugin', 'sessiongc', 'system', 0, 1, 1, 0, 1, '', '', '', 19, 0),
+(0, 'plg_system_shortcut', 'plugin', 'shortcut', 'system', 0, 1, 1, 0, 1, '', '{}', '', 0, 0),
 (0, 'plg_system_skipto', 'plugin', 'skipto', 'system', 0, 1, 1, 0, 1, '', '{}', '', 20, 0),
 (0, 'plg_system_stats', 'plugin', 'stats', 'system', 0, 1, 1, 0, 1, '', '', '', 21, 0),
 (0, 'plg_system_tasknotification', 'plugin', 'tasknotification', 'system', 0, 1, 1, 0, 1, '', '', '', 22, 0),
diff --git a/installation/sql/postgresql/base.sql b/installation/sql/postgresql/base.sql
index 2ae59dd8e761..4e299b0c7c37 100644
--- a/installation/sql/postgresql/base.sql
+++ b/installation/sql/postgresql/base.sql
@@ -347,6 +347,7 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder",
 (0, 'plg_system_schedulerunner', 'plugin', 'schedulerunner', 'system', 0, 1, 1, 0, 0, '', '{}', '', 17, 0),
 (0, 'plg_system_sef', 'plugin', 'sef', 'system', 0, 1, 1, 0, 1, '', '', '', 18, 0),
 (0, 'plg_system_sessiongc', 'plugin', 'sessiongc', 'system', 0, 1, 1, 0, 1, '', '', '', 19, 0),
+(0, 'plg_system_shortcut', 'plugin', 'shortcut', 'system', 0, 1, 1, 0, 1, '', '{}', '', 0, 0),
 (0, 'plg_system_skipto', 'plugin', 'skipto', 'system', 0, 1, 1, 0, 1, '', '{}', '', 20, 0),
 (0, 'plg_system_stats', 'plugin', 'stats', 'system', 0, 1, 1, 0, 1, '', '', '', 21, 0),
 (0, 'plg_system_tasknotification', 'plugin', 'tasknotification', 'system', 0, 1, 1, 0, 1, '', '', '', 22, 0),
diff --git a/libraries/src/Extension/ExtensionHelper.php b/libraries/src/Extension/ExtensionHelper.php
index ca38dc083ba6..5b20186fb519 100644
--- a/libraries/src/Extension/ExtensionHelper.php
+++ b/libraries/src/Extension/ExtensionHelper.php
@@ -295,6 +295,7 @@ class ExtensionHelper
 		array('plugin', 'schedulerunner', 'system', 0),
 		array('plugin', 'sef', 'system', 0),
 		array('plugin', 'sessiongc', 'system', 0),
+		array('plugin', 'shortcut', 'system', 0),
 		array('plugin', 'skipto', 'system', 0),
 		array('plugin', 'stats', 'system', 0),
 		array('plugin', 'tasknotification', 'system', 0),
diff --git a/package-lock.json b/package-lock.json
index 4fbab7b55add..c19a23256099 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,6 +25,7 @@
         "diff": "^5.0.0",
         "dragula": "^3.7.3",
         "focus-visible": "^5.2.0",
+        "hotkeys-js": "^3.9.3",
         "joomla-ui-custom-elements": "^0.2.0",
         "jquery": "^3.6.0",
         "jquery-migrate": "^3.3.2",
@@ -4539,6 +4540,11 @@
       "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==",
       "dev": true
     },
+    "node_modules/hotkeys-js": {
+      "version": "3.9.3",
+      "resolved": "https://registry.npmjs.org/hotkeys-js/-/hotkeys-js-3.9.3.tgz",
+      "integrity": "sha512-s+f0xyvDmf6+DyrFQ2SY+eA7lbvMbjqkqi0I0SpMgnN5tZx7DeH8nsWhkJR4KEq3pxDPHJppDUhdt1rZFW5LeQ=="
+    },
     "node_modules/html-escaper": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
@@ -11720,6 +11726,11 @@
       "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==",
       "dev": true
     },
+    "hotkeys-js": {
+      "version": "3.9.3",
+      "resolved": "https://registry.npmjs.org/hotkeys-js/-/hotkeys-js-3.9.3.tgz",
+      "integrity": "sha512-s+f0xyvDmf6+DyrFQ2SY+eA7lbvMbjqkqi0I0SpMgnN5tZx7DeH8nsWhkJR4KEq3pxDPHJppDUhdt1rZFW5LeQ=="
+    },
     "html-escaper": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
diff --git a/package.json b/package.json
index bf9f8287b1fc..947f3bb980da 100644
--- a/package.json
+++ b/package.json
@@ -47,6 +47,7 @@
     "diff": "^5.0.0",
     "dragula": "^3.7.3",
     "focus-visible": "^5.2.0",
+    "hotkeys-js": "^3.9.3",
     "joomla-ui-custom-elements": "^0.2.0",
     "jquery": "^3.6.0",
     "jquery-migrate": "^3.3.2",
diff --git a/plugins/system/shortcut/services/provider.php b/plugins/system/shortcut/services/provider.php
new file mode 100644
index 000000000000..1a848ef83c6c
--- /dev/null
+++ b/plugins/system/shortcut/services/provider.php
@@ -0,0 +1,48 @@
+<?php
+/**
+ * @package     Joomla.Plugin
+ * @subpackage  System.shortcut
+ *
+ * @copyright   (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
+ * @license     GNU General Public License version 2 or later; see LICENSE.txt
+ */
+
+defined('_JEXEC') or die;
+
+use Joomla\CMS\Extension\PluginInterface;
+use Joomla\CMS\Factory;
+use Joomla\CMS\Plugin\PluginHelper;
+use Joomla\DI\Container;
+use Joomla\DI\ServiceProviderInterface;
+use Joomla\Event\DispatcherInterface;
+use Joomla\Plugin\System\Shortcut\Extension\Shortcut;
+
+return new class implements ServiceProviderInterface
+{
+	/**
+	 * Registers the service provider with a DI container.
+	 *
+	 * @param   Container  $container  The DI container.
+	 *
+	 * @return  void
+	 *
+	 * @since   __DEPLOY_VERSION__
+	 */
+	public function register(Container $container)
+	{
+		$container->set(
+			PluginInterface::class,
+			function (Container $container)
+			{
+				$dispatcher = $container->get(DispatcherInterface::class);
+				$plugin     = new Shortcut(
+					$dispatcher,
+					(array) PluginHelper::getPlugin('system', 'shortcut')
+				);
+				$plugin->setApplication(Factory::getApplication());
+
+				return $plugin;
+			}
+		);
+	}
+};
diff --git a/plugins/system/shortcut/shortcut.xml b/plugins/system/shortcut/shortcut.xml
new file mode 100644
index 000000000000..3cb92232d97a
--- /dev/null
+++ b/plugins/system/shortcut/shortcut.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<extension type="plugin" group="system" method="upgrade">
+	<name>plg_system_shortcut</name>
+	<author>Joomla! Project</author>
+	<creationDate>2022-06</creationDate>
+	<copyright>(C) 2022 Open Source Matters, Inc.</copyright>
+	<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
+	<authorEmail>[email protected]</authorEmail>
+	<authorUrl>www.joomla.org</authorUrl>
+	<version>__DEPLOY_VERSION__</version>
+	<description>PLG_SYSTEM_SHORTCUT_XML_DESCRIPTION</description>
+	<namespace path="src">Joomla\Plugin\System\Shortcut</namespace>
+	<media destination="plg_system_shortcut" folder="media">
+		<folder>js</folder>
+	</media>
+	<files>
+		<folder plugin="shortcut">services</folder>
+		<folder>src</folder>
+	</files>
+	<languages>
+		<language tag="en-GB">language/en-GB/plg_system_shortcut.ini</language>
+		<language tag="en-GB">language/en-GB/plg_system_shortcut.sys.ini</language>
+	</languages>
+	<config>
+		<fields name="params">
+			<fieldset name="basic">
+				<field
+					name="timeout"
+					type="number"
+					label="PLG_SYSTEM_SHORTCUT_TIMEOUT_LABEL"
+					description="PLG_SYSTEM_SHORTCUT_TIMEOUT_DESC"
+					required="true"
+					start="1"
+					step="1"
+					default="2000"
+				/>
+			</fieldset>
+		</fields>
+	</config>
+</extension>
diff --git a/plugins/system/shortcut/src/Extension/Shortcut.php b/plugins/system/shortcut/src/Extension/Shortcut.php
new file mode 100644
index 000000000000..bcdf5a394472
--- /dev/null
+++ b/plugins/system/shortcut/src/Extension/Shortcut.php
@@ -0,0 +1,138 @@
+<?php
+/**
+ * @package     Joomla.Plugin
+ * @subpackage  System.shortcut
+ *
+ * @copyright   (C) 2022 Open Source Matters, Inc. <https://www.joomla.org>
+ * @license     GNU General Public License version 2 or later; see LICENSE.txt
+ */
+
+namespace Joomla\Plugin\System\Shortcut\Extension;
+
+\defined('_JEXEC') or die;
+
+use Joomla\CMS\Event\GenericEvent;
+use Joomla\CMS\Language\Text;
+use Joomla\CMS\Plugin\CMSPlugin;
+use Joomla\CMS\Router\Route;
+use Joomla\CMS\Uri\Uri;
+use Joomla\Event\Event;
+use Joomla\Event\SubscriberInterface;
+
+/**
+ * Shortcut plugin to add accessible keyboard shortcuts to the administrator templates.
+ *
+ * @since  __DEPLOY_VERSION__
+ */
+final class Shortcut extends CMSPlugin implements SubscriberInterface
+{
+	/**
+	 * Load the language file on instantiation.
+	 *
+	 * @var    boolean
+	 * @since  __DEPLOY_VERSION__
+	 */
+	protected $autoloadLanguage = true;
+
+	/**
+	 * Returns an array of events this subscriber will listen to.
+	 *
+	 * The array keys are event names and the value can be:
+	 *
+	 *  - The method name to call (priority defaults to 0)
+	 *  - An array composed of the method name to call and the priority
+	 *
+	 * For instance:
+	 *
+	 *  * array('eventName' => 'methodName')
+	 *  * array('eventName' => array('methodName', $priority))
+	 *
+	 * @return  array
+	 *
+	 * @since   __DEPLOY_VERSION__
+	 */
+	public static function getSubscribedEvents(): array
+	{
+		return [
+			'onBeforeCompileHead' => 'initialize',
+			'onLoadShortcuts'     => 'addShortcuts',
+		];
+	}
+
+	/**
+	 * Add the javascript for the shortcuts
+	 *
+	 * @return  void
+	 *
+	 * @since   __DEPLOY_VERSION__
+	 */
+	public function initialize()
+	{
+		if (!$this->getApplication()->isClient('administrator'))
+		{
+			return;
+		}
+
+		$context = $this->getApplication()->input->get('option') . '.' . $this->getApplication()->input->get('view');
+
+		$shortcuts = [];
+
+		$event = new GenericEvent(
+			'onLoadShortcuts',
+			[
+				'context'   => $context,
+				'shortcuts' => $shortcuts,
+			]
+		);
+
+		$this->getDispatcher()->dispatch('onLoadShortcuts', $event);
+
+		$shortcuts = $event->getArgument('shortcuts');
+
+		Text::script('PLG_SYSTEM_SHORTCUT_OVERVIEW_HINT');
+		Text::script('PLG_SYSTEM_SHORTCUT_OVERVIEW_TITLE');
+		Text::script('PLG_SYSTEM_SHORTCUT_OVERVIEW_DESC');
+		Text::script('JCLOSE');
+
+		$document = $this->getApplication()->getDocument();
+		$wa       = $document->getWebAssetManager();
+		$wa->useScript('bootstrap.modal');
+		$wa->registerAndUseScript('script', 'plg_system_shortcut/shortcut.min.js', ['dependencies' => ['hotkeys.js']]);
+
+		$timeout = $this->params->get('timeout', 2000);
+
+		$document->addScriptOptions('plg_system_shortcut.shortcuts', $shortcuts);
+		$document->addScriptOptions('plg_system_shortcut.timeout', $timeout);
+	}
+
+	/**
+	 * Add default shortcuts to the document
+	 *
+	 * @param   Event  $event  The event
+	 *
+	 * @return  void
+	 *
+	 * @since   __DEPLOY_VERSION__
+	 */
+	public function addShortcuts(Event $event)
+	{
+		$shortcuts = $event->getArgument('shortcuts', []);
+
+		$shortcuts = array_merge(
+			$shortcuts,
+			[
+				'applyKey'   => (object) ['selector' => 'joomla-toolbar-button .button-apply', 'shortcut' => 'A', 'title' => Text::_('JAPPLY')],
+				'saveKey'    => (object) ['selector' => 'joomla-toolbar-button .button-save', 'shortcut' => 'S', 'title' => Text::_('JTOOLBAR_SAVE')],
+				'cancelKey'  => (object) ['selector' => 'joomla-toolbar-button .button-cancel', 'shortcut' => 'Q', 'title' => Text::_('JCANCEL')],
+				'newKey'     => (object) ['selector' => 'joomla-toolbar-button .button-new', 'shortcut' => 'N', 'title' => Text::_('JTOOLBAR_NEW')],
+				'searchKey'  => (object) ['selector' => 'input[placeholder=' . Text::_('JSEARCH_FILTER') . ']', 'shortcut' => 'F', 'title' => Text::_('JSEARCH_FILTER')],
+				'optionKey'  => (object) ['selector' => 'joomla-toolbar-button .button-options', 'shortcut' => 'O', 'title' => Text::_('JOPTIONS')],
+				'helpKey'    => (object) ['selector' => 'joomla-toolbar-button .button-help', 'shortcut' => 'H', 'title' => Text::_('JHELP')],
+				'toggleMenu' => (object) ['selector' => '#menu-collapse', 'shortcut' => 'M', 'title' => Text::_('JTOGGLE_SIDEBAR_MENU')],
+				'dashboard'  => (object) ['selector' => (string) new Uri(Route::_('index.php?')), 'shortcut' => 'D', 'title' => Text::_('COM_CPANEL_DASHBOARD_BASE_TITLE')],
+			]
+		);
+
+		$event->setArgument('shortcuts', $shortcuts);
+	}
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants