Skip to content

Commit

Permalink
contrib/assets/dropdown.js: refactor dropdown
Browse files Browse the repository at this point in the history
  • Loading branch information
hom3mad3 authored and goapunk committed Jul 25, 2024
1 parent 317116b commit 2c68f28
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 201 deletions.
7 changes: 7 additions & 0 deletions changelog/_5587.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

### Changed

- unify dropdown and refactor following files: dropdown.js, _dropdown.scss, item_detail_dropdown.html, user_indicator.html, _user_indicator.scss

### Removed
- deleted user_indicator.js
82 changes: 53 additions & 29 deletions meinberlin/apps/contrib/assets/dropdown.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,65 @@
const Dropdown = {
toggleDropdown (event) {
const dropdown = event.currentTarget.parentNode
const isOpen = dropdown.getAttribute('aria-expanded') === 'true'
class Dropdown {
constructor (container) {
this.container = container
this.trigger = container.querySelector('[data-dropdown-trigger]')
this.dropdown = container.querySelector('[data-dropdown-menu]')
this.closeTimeout = null

dropdown.setAttribute('aria-expanded', !isOpen)
this.init()
}

const menu = dropdown.querySelector('.dropdown__menu')
menu.classList.toggle('dropdown__menu--show', !isOpen)
init () {
this.trigger.addEventListener('click', (event) => this.toggleDropdown(event))
this.dropdown.addEventListener('keyup', (event) => this.handleKeyup(event))
this.dropdown.addEventListener('focusout', (event) => this.handleFocusout(event))
}

if (!isOpen) {
const menu = dropdown.querySelector('.dropdown__menu')
menu.firstElementChild.focus()
toggleDropdown (event) {
event.preventDefault()
if (this.container.classList.contains('dropdown--open')) {
this.closeDropdown()
} else {
this.openDropdown()
}
},
}

openDropdown () {
this.container.classList.add('dropdown--open')
this.trigger.setAttribute('aria-expanded', true)
document.addEventListener('click', this.outsideClickListener)
}

closeDropdown (event) {
const dropdowns = document.querySelectorAll('.js-dropdown')
dropdowns.forEach(function (dropdown) {
const isOpen = dropdown.getAttribute('aria-expanded') === 'true'
if (isOpen && !dropdown.contains(event.target)) {
dropdown.setAttribute('aria-expanded', 'false')
const menu = dropdown.querySelector('.dropdown__menu')
menu.classList.remove('dropdown__menu--show')
}
})
},
if (event) event.stopPropagation()
document.removeEventListener('click', this.outsideClickListener)
this.container.classList.remove('dropdown--open')
this.trigger.setAttribute('aria-expanded', false)
clearTimeout(this.closeTimeout)
}

init () {
const dropdowns = document.querySelectorAll('.js-dropdown')
if (dropdowns.length > 0) {
dropdowns.forEach(function (button) {
button.addEventListener('click', Dropdown.toggleDropdown)
})
handleKeyup (event) {
if (event.keyCode === 27) {
this.closeDropdown()
this.trigger.focus()
}
}

handleFocusout (event) {
this.closeTimeout = setTimeout(() => {
if (!this.dropdown.contains(event.relatedTarget)) {
this.closeDropdown()
}
}, 10)
}

document.addEventListener('click', Dropdown.closeDropdown)
outsideClickListener = (event) => {
if (!this.container.contains(event.target) && event.target !== this.close) {
this.closeDropdown()
}
}
}

export default Dropdown
document.addEventListener('DOMContentLoaded', () => {
const dropdowns = document.querySelectorAll('[data-dropdown]')
dropdowns.forEach(dropdown => new Dropdown(dropdown))
})
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{% load i18n item_tags contrib_tags moderatorremark_tags react_reports %}

<div class="dropdown js-dropdown">
<button title="{% translate 'Actions' %}" type="button" class="dropdown__toggle" aria-haspopup="true" aria-expanded="false" id="idea-{{ object.pk }}-actions">
<div class="dropdown" data-dropdown>
<button data-dropdown-trigger title="{% translate 'Actions' %}" type="button" class="dropdown__toggle" tabindex="0" aria-haspopup="menu" aria-controls="dropdown-menu" id="idea-{{ object.pk }}-actions">
<i class="fas fa-ellipsis-h" aria-label="{% translate 'Actions' %}"></i>
</button>
<nav class="dropdown__menu" aria-labelledby="idea-{{ object.pk }}-actions">
<nav class="dropdown__menu" aria-labelledby="idea-{{ object.pk }}-actions" tabindex="-1" data-dropdown-menu>
<ul class="list--clean">
{% if user_may_change %}
{% get_item_update_url object as change_url %}
Expand Down
63 changes: 0 additions & 63 deletions meinberlin/apps/users/assets/user_indicator.js

This file was deleted.

104 changes: 49 additions & 55 deletions meinberlin/apps/users/templates/meinberlin_users/user_indicator.html
Original file line number Diff line number Diff line change
@@ -1,61 +1,55 @@
{% load i18n static %}

<div class="user-indicator__container">
<div id="js-user-indicator" class="user-indicator__wrapper">
<div class="dropdown" data-dropdown>
{% if request.user.is_authenticated %}
<button
id="js-user-indicator-trigger"
type="button"
aria-haspopup="menu"
aria-controls="js-user-indicator-dropdown"
tabindex="0">
<i class="fas fa-user text--color-primary" aria-hidden="true"></i>
{{ request.user.username }}
</button>
<div role="menu" class="dropdown" id="js-user-indicator-dropdown" aria-label="Login of Register" tabindex="-1">
<button id="js-user-indicator-close" type="button" class="button button--close user-indicator__close" title="{% translate 'close' %}" aria-label="{% translate 'menu close' %}"></button>
<ul class="list--clean">
<li><b>{% translate "My account" %}</b></li>
<li><a href="{% url 'account' %}" role="menuitem">{% translate "Account Settings" %}</a></li>
{% for organisation in request.user.organisations %}
<li><a href="{% url 'a4dashboard:project-list' organisation_slug=organisation.slug %}" role="menuitem">{{ organisation.name }}</a></li>
{% endfor %}
{% if request.user.is_superuser %}
<li><a href="{% url 'meinberlin_platformemails:create' %}" role="menuitem">{% translate "Platform Email" %}</a></li>
{% endif %}
<li>
<form class="block--nogap text--color-dark" action="{% url 'account_logout' %}" method="post" aria-label="{% translate 'Logout' %}" role="menuitem">
{% csrf_token %}
<input type="hidden" name="next" value="{{ redirect_field_value }}">
<button type="submit">{% translate "Logout" %}</button>
</form>
</li>
</ul>
</div>
{% else %}
<button
id="js-user-indicator-trigger"
type="button"
aria-haspopup="menu"
aria-controls="js-user-indicator-dropdown"
tabindex="0">
<i class="fas fa-user text--color-primary" aria-hidden="true"></i>
{% translate "Login" %}
</button>
<div role="menu" class="dropdown" id="js-user-indicator-dropdown" aria-label="Login of Register" tabindex="-1">
<button id="js-user-indicator-close" type="button" class="button button--close user-indicator__close" title="{% translate 'close' %}" aria-label="{% translate 'menu close' %}"></button>
<ul class="list--clean">
<li>
<a class="button button--light" href="{% url 'account_login' %}?next={{ redirect_field_value|urlencode }}" role="menuitem">{% translate "Login" %}</a>
</li>
<li>
<a href="{% url 'account_signup' %}?next={{ redirect_field_value|urlencode }}" role="menuitem">{% translate "Register" %}</a>
</li>
<li>
<a href="{% url 'account_reset_password' %}?next={{ redirect_field_value|urlencode }}" role="menuitem">{% translate "Forgot password?" %}</a>
</li>
</ul>
</div>
{% endif %}
<button data-dropdown-trigger type="button" aria-haspopup="menu" aria-controls="dropdown-menu" tabindex="0">
<i class="fas fa-user text--color-primary" aria-hidden="true"></i>
{{ request.user.username }}
</button>
<div role="menu" class="dropdown__menu" aria-label="{% translate "Account" %}" tabindex="-1" data-dropdown-menu>
<h2>{% translate "My account" %}</h2>
<ul class="list--clean">
<li class="dropdown__item">
<a href="{% url 'account' %}" role="menuitem">{% translate "Account Settings" %}</a>
</li>
{% for organisation in request.user.organisations %}
<li class="dropdown__item">
<a href="{% url 'a4dashboard:project-list' organisation_slug=organisation.slug %}" role="menuitem">{{ organisation.name }}</a>
</li>
{% endfor %}
{% if request.user.is_superuser %}
<li class="dropdown__item">
<a href="{% url 'meinberlin_platformemails:create' %}" role="menuitem">{% translate "Platform Email" %}</a>
</li>
{% endif %}
<li class="dropdown__item">
<form class="block--nogap text--color-dark" action="{% url 'account_logout' %}" method="post" aria-label="{% translate 'Logout' %}" role="menuitem">
{% csrf_token %}
<input type="hidden" name="next" value="{{ redirect_field_value }}">
<button class="button button--light" type="submit">{% translate "Logout" %}</button>
</form>
</li>
</ul>
</div>
{% else %}
<button data-dropdown-trigger type="button" aria-haspopup="menu" aria-controls="dropdown-menu" tabindex="0">
<i class="fas fa-user text--color-primary" aria-hidden="true"></i>
{% translate "Login" %}
</button>
<div role="menu" class="dropdown__menu" aria-label="{% translate "Login or Register" %}" tabindex="-1" data-dropdown-menu>
<ul class="list--clean">
<li class="dropdown__item">
<a class="button button--light" href="{% url 'account_login' %}?next={{ redirect_field_value|urlencode }}" role="menuitem">{% translate "Login" %}</a>
</li>
<li class="dropdown__item">
<a href="{% url 'account_signup' %}?next={{ redirect_field_value|urlencode }}" role="menuitem">{% translate "Register" %}</a>
</li>
<li class="dropdown__item">
<a href="{% url 'account_reset_password' %}?next={{ redirect_field_value|urlencode }}" role="menuitem">{% translate "Forgot password?" %}</a>
</li>
</ul>
</div>
{% endif %}
</div>
</div>
5 changes: 1 addition & 4 deletions meinberlin/assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import 'select2' // used to select projects in containers

import '../../apps/actions/assets/timestamps.js'
import '../../apps/newsletters/assets/dynamic_fields.js'
import '../../apps/users/assets/user_indicator.js'
import Dropdown from '../../apps/contrib/assets/dropdown.js'
import '../../apps/contrib/assets/dropdown.js'

// map search function
import 'adhocracy4/adhocracy4/maps/static/a4maps/a4maps_address.js'
Expand All @@ -31,8 +30,6 @@ function init () {
minimumResultsForSearch: -1
})
}

Dropdown.init()
}

document.addEventListener('DOMContentLoaded', init, false)
Expand Down
Loading

0 comments on commit 2c68f28

Please sign in to comment.