+ },
+
+ /**
+ * Toggles the visibility mode for marked items.
+ *
+ * @param {Event} event
+ * @protected
+ */
+ _toggleVisibility: function (event) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ var button = event.currentTarget;
+ if (this._dropdown === null) {
+ var dropdown = elCreate('ul');
+ dropdown.className = 'dropdownMenu';
+
+ ['activeOnly', 'highlightActive', 'showAll'].forEach((function (type) {
+ var link = elCreate('a');
+ elData(link, 'type', type);
+ link.href = '#';
+ link.textContent = Language.get('wcf.global.filter.visibility.' + type);
+ link.addEventListener(WCF_CLICK_EVENT, this._setVisibility.bind(this));
+
+ var li = elCreate('li');
+ li.appendChild(link);
+
+ if (type === 'showAll') {
+ li.className = 'active';
+
+ var divider = elCreate('li');
+ divider.className = 'dropdownDivider';
+ dropdown.appendChild(divider);
+ }
+
+ dropdown.appendChild(li);
+ }).bind(this));
+
+ UiSimpleDropdown.initFragment(button, dropdown);
+
+ // add `active` classes required for the visibility filter
+ this._setupVisibilityFilter();
+
+ this._dropdown = dropdown;
+ this._dropdownId = button.id;
+ }
+
+ UiSimpleDropdown.toggleDropdown(button.id, button);
+ },
+
+ /**
+ * Set-ups the visibility filter by assigning an active class to the
+ * list items that hold the checkboxes and observing the checkboxes
+ * for any changes.
+ *
+ * This process involves quite a few DOM changes and new event listeners,
+ * therefore we'll delay this until the filter has been accessed for
+ * the first time, because none of these changes matter before that.
+ *
+ * @protected
+ */
+ _setupVisibilityFilter: function () {
+ var nextSibling = this._element.nextSibling;
+ var parent = this._element.parentNode;
+ var scrollTop = this._element.scrollTop;
+
+ // mass-editing of DOM elements is slow while they're part of the document
+ var fragment = document.createDocumentFragment();
+ fragment.appendChild(this._element);
+
+ elBySelAll('li', this._element, function(li) {
+ var checkbox = elBySel('input[type="checkbox"]', li);
+ if (checkbox.checked) li.classList.add('active');
+
+ checkbox.addEventListener('change', function() {
+ li.classList[(checkbox.checked ? 'add' : 'remove')]('active');
+ });
+ });
+
+ // re-insert the modified DOM
+ parent.insertBefore(this._element, nextSibling);
+ this._element.scrollTop = scrollTop;
+ },
+
+ /**
+ * Sets the visibility of marked items.
+ *
+ * @param {Event} event
+ * @protected
+ */
+ _setVisibility: function (event) {
+ event.preventDefault();
+
+ var link = event.currentTarget;
+ var type = elData(link, 'type');
+
+ UiSimpleDropdown.close(this._dropdownId);
+
+ if (elData(this._element, 'filter') === type) {
+ // filter did not change
+ return;
+ }
+
+ elData(this._element, 'filter', type);
+
+ elBySel('.active', this._dropdown).classList.remove('active');
+ link.parentNode.classList.add('active');
+
+ var button = elById(this._dropdownId);
+ button.classList[(type === 'showAll' ? 'remove' : 'add')]('active');
+
+ var icon = elBySel('.icon', button);
+ icon.classList[(type === 'showAll' ? 'add' : 'remove')]('fa-eye');
+ icon.classList[(type === 'showAll' ? 'remove' : 'add')]('fa-eye-slash');