Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/CoreHome/vue/src/MenuDropdown')
-rw-r--r--plugins/CoreHome/vue/src/MenuDropdown/MenuDropdown.adapter.ts36
-rw-r--r--plugins/CoreHome/vue/src/MenuDropdown/MenuDropdown.less94
-rw-r--r--plugins/CoreHome/vue/src/MenuDropdown/MenuDropdown.vue133
3 files changed, 263 insertions, 0 deletions
diff --git a/plugins/CoreHome/vue/src/MenuDropdown/MenuDropdown.adapter.ts b/plugins/CoreHome/vue/src/MenuDropdown/MenuDropdown.adapter.ts
new file mode 100644
index 0000000000..9fc8ae8e13
--- /dev/null
+++ b/plugins/CoreHome/vue/src/MenuDropdown/MenuDropdown.adapter.ts
@@ -0,0 +1,36 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+import createAngularJsAdapter from '../createAngularJsAdapter';
+import MenuDropdown from './MenuDropdown.vue';
+
+export default createAngularJsAdapter({
+ component: MenuDropdown,
+ scope: {
+ menuTitle: {
+ angularJsBind: '@',
+ },
+ tooltip: {
+ angularJsBind: '@',
+ },
+ showSearch: {
+ angularJsBind: '=',
+ },
+ menuTitleChangeOnClick: {
+ angularJsBind: '=',
+ },
+ },
+ directiveName: 'piwikMenudropdown',
+ transclude: true,
+ events: {
+ 'after-select': ($event, scope) => {
+ setTimeout(() => {
+ scope.$apply();
+ }, 0);
+ },
+ },
+});
diff --git a/plugins/CoreHome/vue/src/MenuDropdown/MenuDropdown.less b/plugins/CoreHome/vue/src/MenuDropdown/MenuDropdown.less
new file mode 100644
index 0000000000..2a04d675df
--- /dev/null
+++ b/plugins/CoreHome/vue/src/MenuDropdown/MenuDropdown.less
@@ -0,0 +1,94 @@
+
+.menuDropdown {
+ display: inline-block;
+ padding-right: 14px;
+
+ .title {
+ position: relative;
+ cursor: pointer;
+ }
+
+ .icon-arrow-bottom {
+ margin-left: 4px;
+ }
+
+ .items {
+ z-index: 200;
+ position: absolute;
+ border: 1px solid @color-silver-l80;
+ background: @theme-color-background-contrast;
+ max-height: 400px;
+ overflow-y: auto;
+ overflow-x: hidden;
+ padding: 0 !important;
+
+ .search {
+ margin: 15px 6px 10px 6px;
+ display: block;
+
+ .search_ico {
+ position: absolute;
+ right: 25px;
+ top: 27px;
+ margin: 0px;
+ left: initial;
+ }
+ .reset {
+ position: absolute;
+ top: 25px;
+ cursor: pointer;
+ margin: 0px;
+ right: 25px;
+ left: initial;
+ }
+
+ input {
+ margin: 0px;
+ width: 100%;
+
+ &::-ms-clear {
+ display: none;
+ }
+ }
+ }
+
+ .item {
+ display: block;
+ color: @theme-color-text !important;
+ text-decoration: none !important;
+ padding: 12px 25px 12px 6px !important;
+ font-size: 11px;
+ float: none;
+ text-align: left;
+ line-height: 16px;
+
+ &:hover {
+ background: @theme-color-background-tinyContrast;
+ }
+
+ &.active {
+ background-color: @theme-color-background-tinyContrast;
+ }
+
+ &.category {
+ color: @theme-color-text-light !important
+ }
+
+ &.separator {
+ padding: 0px !important;
+ border-bottom: 0px;
+ margin: 0px;
+ }
+
+ &.separator,
+ &.disabled {
+ opacity: 0.5;
+ cursor: default;
+
+ &:hover {
+ background: @theme-color-background-base;
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/CoreHome/vue/src/MenuDropdown/MenuDropdown.vue b/plugins/CoreHome/vue/src/MenuDropdown/MenuDropdown.vue
new file mode 100644
index 0000000000..fdd26bfdba
--- /dev/null
+++ b/plugins/CoreHome/vue/src/MenuDropdown/MenuDropdown.vue
@@ -0,0 +1,133 @@
+<!--
+ Matomo - free/libre analytics platform
+ @link https://matomo.org
+ @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+-->
+
+<template>
+ <div
+ ref="root"
+ class="menuDropdown"
+ v-focus-anywhere-but-here="{ blur: lostFocus }"
+ >
+ <span
+ class="title"
+ @click="showItems = !showItems"
+ :title="tooltip"
+ >
+ <span v-html="$sanitize(this.actualMenuTitle)" />
+ <span class="icon-arrow-bottom" />
+ </span>
+ <div
+ class="items"
+ v-show="showItems"
+ >
+ <div
+ class="search"
+ v-if="showSearch && showItems"
+ >
+ <input
+ type="text"
+ v-model="searchTerm"
+ v-focus-if:[showItems]="{}"
+ @keydown="onSearchTermKeydown($event)"
+ :placeholder="translate('General_Search')"
+ />
+ <img
+ v-show="!searchTerm"
+ class="search_ico"
+ src="plugins/Morpheus/images/search_ico.png"
+ :title="translate('General_Search')"
+ />
+ <img
+ v-show="searchTerm"
+ v-on:click="searchTerm = '';searchItems('')"
+ class="reset"
+ src="plugins/CoreHome/images/reset_search.png"
+ :title="translate('General_Clear')"
+ />
+ </div>
+ <div v-on:click="selectItem($event)">
+ <slot />
+ </div>
+ </div>
+ </div>
+</template>
+
+<script lang="ts">
+import { defineComponent } from 'vue';
+import FocusAnywhereButHere from '../FocusAnywhereButHere/FocusAnywhereButHere';
+import FocusIf from '../FocusIf/FocusIf';
+
+const { $ } = window;
+
+export default defineComponent({
+ props: {
+ menuTitle: String,
+ tooltip: String,
+ showSearch: Boolean,
+ menuTitleChangeOnClick: String,
+ },
+ directives: {
+ FocusAnywhereButHere,
+ FocusIf,
+ },
+ emits: ['afterSelect'],
+ watch: {
+ menuTitle() {
+ this.actualMenuTitle = this.menuTitle;
+ },
+ },
+ data() {
+ return {
+ showItems: false,
+ searchTerm: '',
+ actualMenuTitle: this.menuTitle,
+ };
+ },
+ methods: {
+ lostFocus() {
+ this.showItems = false;
+ },
+ selectItem(event: MouseEvent) {
+ const targetClasses = (event.target as HTMLElement).classList;
+ if (!targetClasses.contains('item')
+ || targetClasses.contains('disabled')
+ || targetClasses.contains('separator')
+ ) {
+ return;
+ }
+
+ if (this.menuTitleChangeOnClick !== false) {
+ this.actualMenuTitle = (event.target as HTMLElement).textContent
+ .replace(/[\u0000-\u2666]/g, (c) => `&#${c.charCodeAt(0)};`); // eslint-disable-line
+ }
+
+ this.showItems = false;
+
+ $(this.$slots.default()).find('.item').removeClass('active');
+ targetClasses.add('active');
+
+ this.$emit('afterSelect');
+ },
+ onSearchTermKeydown() {
+ setTimeout(() => {
+ this.searchItems(this.searchTerm);
+ });
+ },
+ searchItems(unprocessedSearchTerm: string) {
+ const searchTerm = unprocessedSearchTerm.toLowerCase();
+
+ $(this.$refs.root).find('.item').each((index: number, node: HTMLElement) => {
+ const $node = $(node);
+
+ if ($node.text().toLowerCase().indexOf(searchTerm) === -1) {
+ $node.hide();
+ } else {
+ $node.show();
+ }
+ });
+ },
+ },
+});
+</script>