This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/app/assets/javascripts/discourse/components/site-header.js.es6
2018-06-15 17:03:24 +02:00

214 lines
5.9 KiB
JavaScript

import MountWidget from "discourse/components/mount-widget";
import { observes } from "ember-addons/ember-computed-decorators";
import Docking from "discourse/mixins/docking";
const _flagProperties = [];
function addFlagProperty(prop) {
_flagProperties.pushObject(prop);
}
const PANEL_BODY_MARGIN = 30;
const SiteHeaderComponent = MountWidget.extend(Docking, {
widget: "header",
docAt: null,
dockedHeader: null,
_topic: null,
@observes(
"currentUser.unread_notifications",
"currentUser.unread_private_messages"
)
notificationsChanged() {
this.queueRerender();
},
dockCheck(info) {
if (this.docAt === null) {
const outlet = $("#main-outlet");
if (!(outlet && outlet.length === 1)) return;
this.docAt = outlet.offset().top;
}
const $body = $("body");
const offset = info.offset();
if (offset >= this.docAt) {
if (!this.dockedHeader) {
$body.addClass("docked");
this.dockedHeader = true;
}
} else {
if (this.dockedHeader) {
$body.removeClass("docked");
this.dockedHeader = false;
}
}
},
setTopic(topic) {
this._topic = topic;
this.queueRerender();
},
willRender() {
if (this.get("currentUser.staff")) {
$("body").addClass("staff");
}
},
didInsertElement() {
this._super();
$(window).on("resize.discourse-menu-panel", () => this.afterRender());
this.appEvents.on("header:show-topic", topic => this.setTopic(topic));
this.appEvents.on("header:hide-topic", () => this.setTopic(null));
this.dispatch("notifications:changed", "user-notifications");
this.dispatch("header:keyboard-trigger", "header");
this.dispatch("search-autocomplete:after-complete", "search-term");
this.appEvents.on("dom:clean", () => {
// For performance, only trigger a re-render if any menu panels are visible
if (this.$(".menu-panel").length) {
this.eventDispatched("dom:clean", "header");
}
});
},
willDestroyElement() {
this._super();
$("body").off("keydown.header");
$(window).off("resize.discourse-menu-panel");
this.appEvents.off("header:show-topic");
this.appEvents.off("header:hide-topic");
this.appEvents.off("dom:clean");
},
buildArgs() {
return {
flagCount: _flagProperties.reduce(
(prev, cur) => prev + (this.get(cur) || 0),
0
),
topic: this._topic,
canSignUp: this.get("canSignUp")
};
},
afterRender() {
const $menuPanels = $(".menu-panel");
if ($menuPanels.length === 0) {
return;
}
const $window = $(window);
const windowWidth = parseInt($window.width());
const headerWidth = $("#main-outlet .container").width() || 1100;
const remaining = parseInt((windowWidth - headerWidth) / 2);
const viewMode = remaining < 50 ? "slide-in" : "drop-down";
$menuPanels.each((idx, panel) => {
const $panel = $(panel);
let width = parseInt($panel.attr("data-max-width") || 300);
if (windowWidth - width < 50) {
width = windowWidth - 50;
}
$panel
.removeClass("drop-down")
.removeClass("slide-in")
.addClass(viewMode);
const $panelBody = $(".panel-body", $panel);
// 2 pixel fudge allows for firefox subpixel sizing stuff causing scrollbar
let contentHeight =
parseInt($(".panel-body-contents", $panel).height()) + 2;
// We use a mutationObserver to check for style changes, so it's important
// we don't set it if it doesn't change. Same goes for the $panelBody!
const style = $panel.prop("style");
if (viewMode === "drop-down") {
const $buttonPanel = $("header ul.icons");
if ($buttonPanel.length === 0) {
return;
}
// These values need to be set here, not in the css file - this is to deal with the
// possibility of the window being resized and the menu changing from .slide-in to .drop-down.
if (style.top !== "100%" || style.height !== "auto") {
$panel.css({ top: "100%", height: "auto" });
}
// adjust panel height
const fullHeight = parseInt($window.height());
const offsetTop = $panel.offset().top;
const scrollTop = $window.scrollTop();
if (
contentHeight + (offsetTop - scrollTop) + PANEL_BODY_MARGIN >
fullHeight
) {
contentHeight =
fullHeight - (offsetTop - scrollTop) - PANEL_BODY_MARGIN;
}
if ($panelBody.height() !== contentHeight) {
$panelBody.height(contentHeight);
}
$("body").addClass("drop-down-mode");
} else {
const menuTop = headerHeight();
let height;
const winHeight = $(window).height() - 16;
if (menuTop + contentHeight < winHeight) {
height = contentHeight + "px";
} else {
height = winHeight - menuTop;
}
if ($panelBody.prop("style").height !== "100%") {
$panelBody.height("100%");
}
if (style.top !== menuTop + "px" || style.height !== height) {
$panel.css({ top: menuTop + "px", height });
}
$("body").removeClass("drop-down-mode");
}
$panel.width(width);
});
}
});
export default SiteHeaderComponent;
function applyFlaggedProperties() {
const args = _flagProperties.slice();
args.push(
function() {
this.queueRerender();
}.on("init")
);
SiteHeaderComponent.reopen({
_flagsChanged: Ember.observer.apply(this, args)
});
}
addFlagProperty("currentUser.site_flagged_posts_count");
addFlagProperty("currentUser.post_queue_new_count");
export { addFlagProperty, applyFlaggedProperties };
export function headerHeight() {
const $header = $("header.d-header");
const headerOffset = $header.offset();
const headerOffsetTop = headerOffset ? headerOffset.top : 0;
return parseInt(
$header.outerHeight() + headerOffsetTop - $(window).scrollTop()
);
}