Browse Source

Merge branch 'feature/removing-jquery' into develop

pull/74/head
Simon Vieille 2 weeks ago
parent
commit
228f07ea25
  1. 2
      Makefile
  2. 8
      css/admin.css
  3. 2
      src/SideMenu.js
  4. 8
      src/SideMenu.vue
  5. 8
      src/SideMenuBig.vue
  6. 8
      src/SideMenuWithCategories.vue
  7. 181
      src/admin.js
  8. 46
      templates/js/_alwaysDisplayed.js
  9. 17
      templates/js/_loaderEnabled.js
  10. 240
      templates/js/_topMenuApps.js
  11. 158
      templates/js/script.php
  12. 3
      templates/settings/admin-form.php
  13. 2
      templates/settings/personal-form.php
  14. 2
      vendor/html5sortable.min.js

2
Makefile

@ -13,7 +13,7 @@ release: npm-build translations
test -d releases/$$VERSION && rm -fr releases/$$VERSION
mkdir -p releases/$$VERSION/side_menu
cp -r README.md CHANGELOG.md appinfo css lib img l10n js src templates screenshots releases/$$VERSION/side_menu
cp -r README.md CHANGELOG.md appinfo css lib img l10n js src templates screenshots vendor releases/$$VERSION/side_menu
cd releases/$$VERSION
zip -r side_menu_v$$VERSION.zip side_menu
tar cvzf side_menu_v$$VERSION.tar.gz side_menu

8
css/admin.css

@ -20,7 +20,7 @@
margin: 10px 0 10px 0;
}
#side-menu-section input[type="checkbox"] {
#-dropside-menu-section input[type="checkbox"] {
vertical-align: middle;
}
@ -81,6 +81,12 @@
cursor: pointer;
}
.side-menu-setting-list-drop {
background: yellow;
border-color: yellow;
height: 34px;
}
.side-menu-setting.arrow {
color: #ccc;
padding-right: 5px;

2
src/SideMenu.js

@ -41,7 +41,7 @@ const mountSideMenuComponent = () => {
sideMenu.$mount('#side-menu')
$('body').trigger('side-menu.ready')
document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.ready'))
} else {
window.setTimeout(mountSideMenuComponent, 50)
}

8
src/SideMenu.vue

@ -122,13 +122,15 @@ export default {
name: trim(element.querySelector('span').innerHTML),
icon: svg,
active: element.classList.contains('active')
});
})
}
}
(function(apps) {
window.setTimeout(function() {
jQuery('body').trigger('side-menu.apps', [apps])
document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.apps', {
detail: {apps: apps},
}))
}, 1000)
})(this.apps)
},
@ -147,7 +149,7 @@ export default {
that.logo = config['logo']
that.logoLink = config['logo-link']
that.settings = config['settings']
});
})
},
},
mounted() {

8
src/SideMenuBig.vue

@ -97,8 +97,10 @@ export default {
}
}
jQuery('body').trigger('side-menu.apps', [apps])
});
document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.apps', {
detail: {apps: apps},
}))
})
},
retrieveActiveApp() {
@ -116,7 +118,7 @@ export default {
that.targetBlankApps = config['target-blank-apps']
that.settings = config['settings']
});
})
},
},
mounted() {

8
src/SideMenuWithCategories.vue

@ -95,8 +95,10 @@ export default {
}
}
jQuery('body').trigger('side-menu.apps', [apps])
});
document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.apps', {
detail: {apps: apps},
}))
})
},
retrieveActiveApp() {
@ -114,7 +116,7 @@ export default {
that.targetBlankApps = config['target-blank-apps']
that.settings = config['settings']
});
})
},
},
mounted() {

181
src/admin.js

@ -17,13 +17,23 @@
let elements = []
const selector = '#side-menu-message';
const selector = '#side-menu-message'
const userConfig = (name, value, callbacks) => {
const url = OC.generateUrl('/apps/side_menu/personalSetting/valueSet')
$.post(url, {name: name, value: value}, callbacks.success)
.fail(callbacks.error)
const formData = new FormData()
formData.append('name', name)
formData.append('value', value)
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData
})
.then(callbacks.success)
.catch(callbacks.error)
}
const appConfig = (name, value, callbacks) => {
@ -31,23 +41,29 @@ const appConfig = (name, value, callbacks) => {
}
const saveSettings = (key) => {
const element = elements.get(key)
const element = elements[key]
if (!element) {
return
}
let value
let name
if (jQuery(element).is('[data-checkbox]')) {
name = jQuery(element).attr('data-name')
const inputs = jQuery('input[name="' + name + '[]"]:checked')
if (element.hasAttribute('data-checkbox')) {
name = element.getAttribute('data-name')
value = []
inputs.each((i, v) => {
value.push(v.value)
})
const inputs = document.querySelectorAll('input[name="' + name + '[]"]:checked')
for (let input of inputs) {
value.push(input.value)
}
value = JSON.stringify(value)
} else {
name = jQuery(element).attr('name')
value = jQuery(element).val()
name = element.getAttribute('name')
value = element.value
}
const size = elements.length
@ -63,8 +79,8 @@ const saveSettings = (key) => {
t('side_menu', (key + 1) + '/' + size)
)
if (key < size - 1) {
saveSettings(++key)
if (key < size) {
saveSettings(key + 1)
} else {
OC.msg.finishedSuccess(selector, t('side_menu', 'Saved'))
}
@ -74,7 +90,7 @@ const saveSettings = (key) => {
}
}
if (jQuery(element).is('[data-personal]')) {
if (element.hasAttribute('data-personal')) {
userConfig(name, value, callbacks)
} else {
appConfig(name, value, callbacks)
@ -82,84 +98,105 @@ const saveSettings = (key) => {
}
const elementToggler = (element) => {
jQuery(element).toggle()
let display = 'none'
if (window.getComputedStyle(element).display === 'none') {
display = 'block'
}
element.style.display = display
}
jQuery(document).ready(() => {
elements = jQuery('.side-menu-setting')
document.addEventListener('DOMContentLoaded', () => {
elements = document.querySelectorAll('.side-menu-setting')
jQuery('#side-menu-save').on('click', (event) => {
document.querySelector('#side-menu-save').addEventListener('click', (event) => {
event.preventDefault()
OC.msg.startSaving(selector)
saveSettings(0)
});
})
jQuery('.side-menu-display').on('click', (event) => {
var target = jQuery(event.target)
const displays = document.querySelectorAll('.side-menu-display')
jQuery('.side-menu-display').removeClass('is-active')
target.addClass('is-active')
for (let display of displays) {
display.addEventListener('click', (event) => {
const target = event.target
jQuery('#side-menu-always-displayed').val(target.attr('data-alwaysdiplayed'))
jQuery('#side-menu-big-menu').val(target.attr('data-bigmenu'))
jQuery('#side-menu-side-with-categories').val(target.attr('data-sidewithcategories'))
})
for (let d of displays) {
d.classList.toggle('is-active', d === display)
}
jQuery('.side-menu-setting-live').on('change', (event) => {
var target = jQuery(event.target)
var name = target.attr('name')
var value = target.val()
document.querySelector('#side-menu-always-displayed').value = target.getAttribute('data-alwaysdiplayed')
document.querySelector('#side-menu-big-menu').value = target.getAttribute('data-bigmenu')
document.querySelector('#side-menu-side-with-categories').value = target.getAttribute('data-sidewithcategories')
})
}
if ('background-color-opacity' === name) {
return $('#side-menu-background-color, #side-menu-background-color-to').trigger('change');
} else if ('dark-mode-background-color-opacity' === name) {
return $('#side-menu-dark-mode-background-color, #side-menu-dark-mode-background-color-to').trigger('change');
}
for (let item of document.querySelectorAll('.side-menu-setting-live')) {
item.addEventListener('change', (event) => {
const target = event.target
const name = target.getAttribute('name')
if (name === 'opener') {
var url = OC.generateUrl(`/apps/side_menu/img/${value}.svg`).replace('/index.php', '')
let value = target.value
let id = null
value = `url(${url})`;
}
if (name === 'background-color-opacity') {
id = '#side-menu-background-color, #side-menu-background-color-to'
} else if (name === 'dark-mode-background-color-opacity') {
id = '#side-menu-dark-mode-background-color, #side-menu-dark-mode-background-color-to'
}
if (name === 'icon-invert-filter' || name === 'icon-opacity') {
value/=100;
}
if (id) {
document.querySelector(id).dispatchEvent(new CustomEvent('change'))
if (['dark-mode-background-color', 'dark-mode-background-color-to'].indexOf(name) > -1) {
var opacity = parseInt($('#side-menu-dark-mode-background-color-opacity').val() * 255 / 100);
return
}
value = [value, opacity.toString(16)].join('');
} else if (['background-color', 'background-color-to'].indexOf(name) > -1) {
var opacity = parseInt($('#side-menu-background-color-opacity').val() * 255 / 100);
if (name === 'opener') {
const url = OC.generateUrl(`/apps/side_menu/img/${value}.svg`).replace('/index.php', '')
value = [value, opacity.toString(16)].join('');
}
value = `url(${url})`
}
document.documentElement.style.setProperty('--side-menu-' + name, value)
})
if (name === 'icon-invert-filter' || name === 'icon-opacity') {
value/=100
}
jQuery('.side-menu-toggler').on('click', (event) => {
var target = jQuery(event.target)
var element = target.attr('data-target')
if (['dark-mode-background-color', 'dark-mode-background-color-to'].indexOf(name) > -1) {
const opacity = parseInt(document.querySelector('#side-menu-dark-mode-background-color-opacity').value * 255 / 100)
elementToggler(element)
})
value = [value, opacity.toString(16)].join('')
} else if (['background-color', 'background-color-to'].indexOf(name) > -1) {
const opacity = parseInt(document.querySelector('#side-menu-background-color-opacity').value * 255 / 100)
jQuery("#categories-list .side-menu-setting-list").sortable({
forcePlaceholderSize: true,
placeholder: 'placeholder',
stop: function (event, ui) {
let value = []
value = [value, opacity.toString(16)].join('')
}
jQuery('#categories-list .side-menu-setting-list-item').each(function() {
value.push(jQuery(this).attr('data-id'))
});
document.documentElement.style.setProperty('--side-menu-' + name, value)
})
}
value = JSON.stringify(value)
for (let toggler of document.querySelectorAll('.side-menu-toggler')) {
toggler.addEventListener('click', (event) => {
const target = event.target
const element = document.querySelector(target.getAttribute('data-target'))
jQuery('input[name="categories-order"]').val(value)
}
});
});
elementToggler(element)
})
}
sortable('#categories-list .side-menu-setting-list', {
placeholderClass: 'side-menu-setting-list-drop'
})
sortable('#categories-list .side-menu-setting-list')[0].addEventListener('sortstop', (e) => {
let value = []
for (let item of document.querySelectorAll('#categories-list .side-menu-setting-list-item')) {
value.push(item.getAttribute('data-id'))
}
document.querySelector('input[name="categories-order"]').value = JSON.stringify(value)
})
})

46
templates/js/_alwaysDisplayed.js

@ -1,21 +1,19 @@
var alwaysDisplayed = function() {
var elements = document.querySelectorAll('*');
var fixedElements = []
for (var i in elements) {
var element = elements[i]
const alwaysDisplayed = function() {
const elements = querySelectorAll('*')
const fixedElements = []
for (var element of elements) {
if (typeof element !== 'object') {
continue
}
var position = window.getComputedStyle(element, null).getPropertyValue('position');
const position = window.getComputedStyle(element, null).getPropertyValue('position')
if (position !== 'fixed') {
continue
}
var id = element.getAttribute('id')
const id = element.getAttribute('id')
if (id === 'header' || id === 'side-menu' || id === 'side-menu-loader') {
continue
@ -25,7 +23,21 @@ var alwaysDisplayed = function() {
continue
}
if (jQuery(element).parents('#side-menu').length) {
let elementIsInSideMenu = false
let parent = element.parentNode
while (parent && !elementIsInSideMenu) {
try {
if (parent.getAttribute('id') === 'side-menu') {
elementIsInSideMenu = true
}
} catch (e) {
}
parent = parent.parentNode
}
if (elementIsInSideMenu) {
continue
}
@ -33,19 +45,19 @@ var alwaysDisplayed = function() {
}
for (var i in fixedElements) {
var element = fixedElements[i]
var computedStyle = window.getComputedStyle(element, null)
var left = computedStyle.getPropertyValue('left')
var right = computedStyle.getPropertyValue('right')
const element = fixedElements[i]
const computedStyle = window.getComputedStyle(element, null)
const left = computedStyle.getPropertyValue('left')
const right = computedStyle.getPropertyValue('right')
if (right !== '0px') {
var intValue = parseInt(left.replace('px', ''))
element.style.setProperty('transform', 'translateX(' + (intValue + 50) + 'px)')
const intValue = parseInt(left.replace('px', '')) + 50
element.style.setProperty('transform', 'translateX(' + intValue.toString() + 'px)')
}
}
}
let content = document.getElementById('content')
const content = querySelector('#content')
if (content && content.classList.contains('app-settings')) {
let loaded = false
@ -56,7 +68,7 @@ if (content && content.classList.contains('app-settings')) {
}
const observer = new MutationObserver(() => {
if (loaded) {
return;
return
}
const element = content.querySelector('#app-category-your-apps') || content.querySelector('#app-navigation ul')

17
templates/js/_loaderEnabled.js

@ -1,15 +1,14 @@
var pageLoader = jQuery('<div id="side-menu-loader">')
var pageLoaderBar = jQuery('<div id="side-menu-loader-bar">')
let pageLoader = createElement('div', {id: 'side-menu-loader'})
let pageLoaderBar = createElement('div', {id: 'side-menu-loader-bar'})
body.append(pageLoader)
pageLoader.append(pageLoaderBar)
pageLoader.appendChild(pageLoaderBar)
querySelector('body').appendChild(pageLoader)
var pageLoaderValue = 0
$(window).on('beforeunload', function() {
setInterval(function() {
pageLoaderBar.width(pageLoaderValue.toString() + '%')
let pageLoaderValue = 0
window.addEventListener('beforeunload', () => {
setInterval(() => {
pageLoaderBar.style.width = pageLoaderValue.toString() + '%'
pageLoaderValue = Math.min(pageLoaderValue + .2, 100)
}, 25)
})

240
templates/js/_topMenuApps.js

@ -1,32 +1,55 @@
var menuCache = null
var updateTopMenu = function() {
var breakpointMobileWidth = 1024
var menu = jQuery('#appmenu')
var apps = menu.find('li')
var minAppsDesktop = 8
var usePercentualAppMenuLimit = 0.8
var isMobile = jQuery(window).width() < breakpointMobileWidth
var lastShownApp = null
var appShown = []
var moreApps = jQuery('#more-apps')
var navigation = jQuery('#navigation')
var navigationApps = jQuery('#apps ul')
var appCount = null
var currentMenuCache = menu.html() + menu.next().html()
if (currentMenuCache === menuCache) {
let menuCache = null
const breakpointMobileWidth = 1024
const usePercentualAppMenuLimit = 0.8
const minAppsDesktop = 8
const handleMenuClick = (e, icon) => {
let element = e.target
while (element.tagName !== 'LI') {
element = element.parentNode
}
const a = querySelector('a', element)
if (a.getAttribute('target') !== '_blank' && e.which === 1 && !e.ctrlKey && !e.metaKey) {
for (let tag of ['svg', 'div']) {
let el = querySelector(tag, element)
if (el) {
el.remove()
}
}
const loader = createElement('div', {'class': icon})
a.insertBefore(loader, querySelector('span', a))
}
}
const updateTopMenu = function() {
const isMobile = window.innerWidth < breakpointMobileWidth
const menu = querySelector('#appmenu')
const moreApps = querySelector('#more-apps')
const navigation = querySelector('#navigation')
const navigationApps = querySelector('#apps ul')
let apps = querySelectorAll('li', menu)
let lastShownApp = null
let appShown = []
if ((menu.innerHTML + menu.nextSibling.innerHTML) === menuCache) {
return
}
navigationApps.html('')
navigationAppsHtml = ''
apps.each(function(i, app) {
var dataId = app.getAttribute('data-id')
for (let app of apps) {
const dataId = app.getAttribute('data-id')
if (dataId === null) {
return
continue
}
if (topMenuApps.indexOf(dataId) === -1) {
@ -35,26 +58,31 @@ var updateTopMenu = function() {
} else {
app.classList.remove('hidden')
app.classList.add('app-external-site')
appShown.push(app)
navigationApps.append(app.outerHTML)
navigationAppsHtml = navigationAppsHtml + app.outerHTML
}
if (targetBlankApps.indexOf(dataId) !== -1) {
jQuery(app).children('a').attr('target', '_blank');
querySelector('a', app).setAttribute('target', '_blank')
}
})
var rightHeaderWidth = jQuery('.header-right').outerWidth()
var headerWidth = jQuery('header').outerWidth()
var availableWidth = headerWidth - jQuery('#nextcloud').outerWidth()
- jQuery('#header .side-menu-opener').outerWidth()
- (rightHeaderWidth > 230 ? rightHeaderWidth : 230)
if (!isMobile) {
availableWidth = availableWidth * usePercentualAppMenuLimit
}
appCount = Math.floor(availableWidth / jQuery('#appmenu li').width())
navigationApps.innerHTML = navigationAppsHtml
const rightHeaderWidth = querySelector('.header-right').offsetWidth
const headerWidth = querySelector('header').offsetWidth
let availableWidth = headerWidth
availableWidth -= nextcloud.offsetWidth
availableWidth -= querySelector('#header .side-menu-opener').offsetWidth
availableWidth -= rightHeaderWidth > 230 ? rightHeaderWidth : 230
availableWidth *= isMobile ? usePercentualAppMenuLimit : 1
let appCount = Math.floor(availableWidth / querySelector('#appmenu li:not(.hidden)').offsetWidth)
if (isMobile && appCount > minAppsDesktop) {
appCount = minAppsDesktop
@ -62,111 +90,125 @@ var updateTopMenu = function() {
appCount = minAppsDesktop
}
if (appCount === 0) {
menu.addClass('hidden')
}
menu.removeClass('hidden')
menu.css('opacity', 1)
menu.style.opacity = 1
if (appShown.length - 1 - appCount >= 1) {
appCount--
}
moreApps.find('a').removeClass('active')
for (let item of querySelectorAll('a', moreApps)) {
item.classList.remove('active')
}
let k = 0
let notInHeader = 0
var k = 0
var notInHeader = 0
var name
jQuery(appShown).each(function(i, app) {
app = jQuery(app)
name = app.data('id')
for (let app of appShown) {
const name = app.getAttribute('data-id')
const li = querySelector('#apps li[data-id=' + name + '].app-external-site')
if (k < appCount && appCount > 0) {
app.removeClass('hidden')
lastShownApp = app
app.classList.remove('hidden')
li.classList.add('in-header')
jQuery('#apps li[data-id=' + name + '].app-external-site').addClass('in-header')
lastShownApp = app
} else {
app.addClass('hidden')
app.classList.add('hidden')
li.classList.remove('in-header')
notInHeader++
jQuery('#apps li[data-id=' + name + '].app-external-site').removeClass('in-header')
const a = querySelector('a', app)
if (appCount > 0 && app.children('a').hasClass('active')) {
lastShownApp.addClass('hidden')
app.removeClass('hidden')
if (appCount > 0 && a.classList.contains('active')) {
lastShownApp.classList.add('hidden')
app.classList.remove('hidden')
notInHeader++
jQuery('#apps li[data-id=' + name + '].app-external-site')
.removeClass('in-header')
.addClass('in-header')
li.classList.add('in-header')
}
}
k++
})
// Hack for https://github.com/nextcloud/server/blob/23b0b63c213f5b31eecae817ffd4a9e26f6624d0/core/src/components/MainMenu.js#L74-L96
menu.undelegate('li:not(#more-apps) > a', 'click')
menu.delegate('li:not(#more-apps) > a', 'click', function(e) {
var a = $(e.target)
if (!a.is('a')) {
a = a.closest('a')
}
if (a.attr('target') !== '_blank' && e.which === 1 && !e.ctrlKey && !e.metaKey && a.parent('#more-apps').length === 0) {
a.find('svg').remove()
a.find('div').remove()
a.prepend(jQuery('<div/>').addClass(
OCA.Theming && OCA.Theming.inverted
? 'icon-loading-small'
: 'icon-loading-small-dark'
))
}
window.location.href = a.attr('href')
// Hack for:
// - https://github.com/nextcloud/server/blob/master/core/src/components/MainMenu.js#L97-L119
// - https://github.com/nextcloud/server/blob/master/core/src/components/MainMenu.js#L97-L119
jQuery(menu).undelegate('li:not(#more-apps) > a', 'click')
jQuery(navigation).undelegate('a', 'click')
const confs = [
{
items: querySelectorAll('#navigation li'),
icon: 'icon-loading-small'
},
{
items: querySelectorAll('li:not(#more-apps)', menu),
icon: OCA.Theming && OCA.Theming.inverted ? 'icon-loading-small' : 'icon-loading-small-dark'
},
]
for (let conf of confs) {
for (let item of conf.items) {
item.addEventListener('click', (e) => {
handleMenuClick(e, conf.icon)
})
}
})
}
jQuery('#apps li.app-external-site').each(function(i, app) {
app = jQuery(app)
var appId = app.attr('data-id')
for (let app of querySelectorAll('#apps li.app-external-site')) {
const appId = app.getAttribute('data-id')
if (app.hasClass('in-header')) {
app.find('svg').find('defs').remove()
if (app.classList.contains('in-header')) {
for (let defs of querySelectorAll('svg defs', app)) {
defs.remove()
}
} else {
var svg = app.find('svg');
const svg = querySelector('svg', app)
if (svg.find('defs').length > 0) {
return;
if (querySelectorAll('svg defs', app).length > 0) {
continue
}
var defs = `
const defs = `
<defs>
<filter id="invertMenuMore-${appId}">
<feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"></feColorMatrix>
</filter>
</defs>`
svg.prepend(defs)
svg.find('image').attr('filter', `url(#invertMenuMore-${appId})`)
svg.innerHTML = defs + svg.innerHTML
var html = svg.get(0).innerHTML.replace(/fecolormatrix/g, 'feColorMatrix');
for (let image of querySelectorAll('image', svg)) {
image.setAttribute('filter', `url(#invertMenuMore-${appId})`)
}
svg.html(html)
svg.innerHTML = svg.innerHTML.replace(/fecolormatrix/g, 'feColorMatrix')
}
})
}
if (notInHeader === 0) {
moreApps.hide()
navigation.hide()
moreApps.style.display = 'none'
navigation.style.display = 'none'
} else {
moreApps.show()
moreApps.style.display = 'flex'
}
menuCache = menu.html() + menu.next().html()
menuCache = menu.innerHTML + menu.nextSibling.innerHTML
}
setInterval(updateTopMenu, 50)
for (let timeout of [300, 500, 700, 900, 1100]) {
setTimeout(updateTopMenu, timeout)
}
let resizeTimeout = null;
window.addEventListener('resize', () => {
if (resizeTimeout !== null) {
clearTimeout(resizeTimeout)
}
resizeTimeout = setTimeout(updateTopMenu, 100)
})

158
templates/js/script.php

@ -13,63 +13,98 @@ if ($_['always-displayed']) {
?>
(function() {
var sideMenuContainer = jQuery('<div id="side-menu-container">')
var sideMenuOpener = jQuery('<button class="side-menu-opener"></button>')
var sideMenu = jQuery('<div id="side-menu">')
var body = jQuery('body')
var html = jQuery('html')
var isTouchDevice = window.matchMedia("(pointer: coarse)").matches
const querySelector = function(selector, element) {
if (element) {
return element.querySelector(selector)
}
return document.querySelector(selector)
}
const querySelectorAll = function(selector, element) {
if (element) {
return element.querySelectorAll(selector)
}
return document.querySelectorAll(selector)
}
const createElement = function(tagName, attributes) {
const element = document.createElement(tagName)
if (typeof attributes === 'object') {
for (let i in attributes) {
element.setAttribute(i, attributes[i])
}
}
return element
}
const sideMenuContainer = createElement('div', {id: 'side-menu-container'})
const sideMenuOpener = createElement('button', {'class': 'side-menu-opener'})
const sideMenu = createElement('div', {id: 'side-menu'})
const body = querySelector('body')
const html = querySelector('html')
const nextcloud = querySelector('#nextcloud')
const isTouchDevice = window.matchMedia("(pointer: coarse)").matches
const targetBlankApps = <?php echo json_encode($_['target-blank-apps']) ?>
<?php if ($display === 'big-menu'): ?>
sideMenu.attr('data-bigmenu', '1')
sideMenu.setAttribute('data-bigmenu', '1')
<?php elseif ($display === 'side-with-categories'): ?>
sideMenu.attr('data-sidewithcategories', '1')
sideMenu.setAttribute('data-sidewithcategories', '1')
<?php endif; ?>
var targetBlankApps = <?php echo json_encode($_['target-blank-apps']) ?>;
querySelector('body').addEventListener('side-menu.apps', (e) => {
const apps = e.detail.apps;
body.on('side-menu.apps', function(e, apps) {
<?php if ($_['hide-when-no-apps']): ?>
sideMenu = jQuery('#side-menu')
const sideMenu = querySelector('#side-menu')
if (apps.length === 0) {
sideMenu.removeClass('open')
sideMenu.addClass('hide')
sideMenuOpener.addClass('hide')
sideMenu.classList.remove('open')
sideMenu.classList.add('hide')
sideMenuOpener.classList.add('hide')
} else {
sideMenu.removeClass('hide')
sideMenuOpener.removeClass('hide')
sideMenu.classList.remove('hide')
sideMenuOpener.classList.remove('hide')
}
<?php if ($display === 'always-displayed'): ?>
if (apps.length === 0) {
html.removeClass('side-menu-always-displayed');
html.classList.remove('side-menu-always-displayed')
} else {
html.addClass('side-menu-always-displayed');
html.classList.add('side-menu-always-displayed')
}
<?php endif; ?>
<?php else: ?>
<?php if ($display === 'always-displayed'): ?>
if (apps.length === 0) {
html.removeClass('side-menu-always-displayed');
html.classList.remove('side-menu-always-displayed')
} else {
html.addClass('side-menu-always-displayed');
html.classList.add('side-menu-always-displayed')
}
<?php endif; ?>
<?php endif; ?>
})
body.on('side-menu.ready', function() {
sideMenu = jQuery('#side-menu')
body.addEventListener('side-menu.ready', () => {
const sideMenu = querySelector('#side-menu')
const headerMenuOpener = querySelector('#header .side-menu-opener')
const sideMenuOpener = querySelectorAll('#side-menu .side-menu-opener')
var headerMenuOpener = jQuery('#header .side-menu-opener')
var sideMenuOpener = jQuery('#side-menu .side-menu-opener')
sideMenuFocus = () => {
let a = querySelector('.side-menu-app.active a', sideMenu)
sideMenuFocus = function() {
var a = sideMenu.find('.side-menu-app.active a')
if (!a) {
return
}
if (a.length === 0) {
a = sideMenu.find('.side-menu-app:first-child a')
a = querySelector('.side-menu-app:first-child a', sideMenu)
}
if (a.length > 0) {
@ -77,79 +112,82 @@ if ($_['always-displayed']) {
}
}
<?php if ($_['opener-hover'] || $display === 'always-displayed'): ?>
var sideMenuMouseLeave = function() {
sideMenu
.removeClass('open')
.off('mouseleave', sideMenuMouseLeave)
<?php if ($_['opener-hover']): ?>
const sideMenuMouseLeave = () => {
sideMenu.classList.remove('open')
sideMenu.removeEventListener('mouseleave', sideMenuMouseLeave)
}
var sideMenuMouseEnter = function() {
sideMenu.on('mouseleave', sideMenuMouseLeave)
const sideMenuMouseEnter = () => {
sideMenu.addEventListener('mouseleave', sideMenuMouseLeave)
}
var sideMenuOpenerMouseEnter = function() {
sideMenu
.addClass('open')
.on('mouseenter', sideMenuMouseEnter)
const sideMenuOpenerMouseEnter = () => {
sideMenu.classList.add('open')
sideMenu.addEventListener('mouseenter', sideMenuMouseEnter)
sideMenuFocus()
}
if (!isTouchDevice) {
<?php if ($_['opener-hover']): ?>
headerMenuOpener.on('mouseenter', sideMenuOpenerMouseEnter)
headerMenuOpener.addEventListener('mouseenter', sideMenuOpenerMouseEnter)
sideMenu.addClass('hide-opener')
sideMenu.classList.add('hide-opener')
<?php endif ?>
sideMenu.on('mouseleave', sideMenuMouseLeave)
sideMenu.on('mouseenter', sideMenuOpenerMouseEnter)
sideMenu.addEventListener('mouseleave', sideMenuMouseLeave)
sideMenu.addEventListener('mouseenter', sideMenuOpenerMouseEnter)
}
<?php endif; ?>
headerMenuOpener.on('click', function() {
sideMenu.addClass('open')
sideMenu.find('.side-menu-app.active a').focus()
headerMenuOpener.addEventListener('click', () => {
sideMenu.classList.add('open')
const a = querySelector('.side-menu-app.active a', sideMenu)
if (a !== null) {
a.focus()
}
})
<?php if ($display === 'always-displayed'): ?>
sideMenuOpener.on('click', function() {
sideMenu.toggleClass('open')
})
<?php else: ?>
sideMenuOpener.on('click', function() {
sideMenu.removeClass('open')
for (let opener of sideMenuOpener) {
opener.addEventListener('click', () => {
<?php if ($display === 'always-displayed'): ?>
sideMenu.classList.toggle('open')
<?php else: ?>
sideMenu.classList.remove('open')
<?php endif; ?>
})
<?php endif; ?>
}
jQuery(document).keydown(function(e) {
document.addEventListener('keydown', (e) => {
var key = e.key || e.keyCode
if ((key === 'o' || key === 79) && e.ctrlKey === true) {
e.preventDefault()
sideMenu.toggleClass('open')
sideMenu.classList.toggle('open')
sideMenuFocus()
}
})
})
body.append(sideMenuContainer)
sideMenuContainer.append(sideMenu)
body.appendChild(sideMenuContainer)
sideMenuContainer.appendChild(sideMenu)
<?php if ($_['loader-enabled'] === true): ?>
<?php require_once __DIR__.'/_loaderEnabled.js'; ?>
<?php endif; ?>
<?php if ($_['opener-position'] === 'before'): ?>
sideMenuOpener.insertBefore('#nextcloud')
nextcloud.parentNode.insertBefore(sideMenuOpener, nextcloud)
<?php else: ?>
sideMenuOpener.insertAfter('#nextcloud')
nextcloud.parentNode.insertBefore(sideMenuOpener, nextcloud.nextSibling)
<?php endif; ?>
<?php if (!empty($_['top-menu-apps'])): ?>
var topMenuApps = <?php echo json_encode($_['top-menu-apps']); ?>;
const topMenuApps = <?php echo json_encode($_['top-menu-apps']); ?>
<?php require_once __DIR__.'/_topMenuApps.js'; ?>
<?php endif; ?>

3
templates/settings/admin-form.php

@ -20,6 +20,7 @@ use OCP\IURLGenerator;
use OCP\IConfig;
use OCA\SideMenu\AppInfo\Application;
vendor_script('side_menu', 'html5sortable.min');
script('side_menu', 'admin');
style('side_menu', 'admin');
@ -799,7 +800,7 @@ $choicesSizes = [
🖱️ <?php p($l->t('Show and hide the list of categories')); ?>
</a>
<div class="side-menu-setting" data-name="categories" id="categories-list" style="display: none">
<div id="categories-list" style="display: none">
<ul class="side-menu-setting-list">
<?php foreach ($_['categories'] as $key => $label): ?>
<li data-id="<?php echo $key; ?>" class="side-menu-setting-list-item">

2
templates/settings/personal-form.php

@ -44,8 +44,6 @@ $choicesYesNo = [
<?php p($l->t('Menu')); ?>
</h2>
<div>
<label for="side-menu-enabled">
<?php p($l->t('Enable the custom menu')); ?>

2
vendor/html5sortable.min.js

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save