]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/index/element.js
Merge remote-tracking branch 'upstream/pull/6168'
[rails.git] / app / assets / javascripts / index / element.js
1 (function () {
2   $(document).on("click", "a[href='#versions-navigation-active-page-item']", function (e) {
3     scrollToActiveVersion();
4     $("#versions-navigation-active-page-item a.page-link").trigger("focus");
5     e.preventDefault();
6   });
7
8   OSM.Element = function (map, type) {
9     const page = {};
10     let scrollStartObserver, scrollEndObserver;
11
12     page.pushstate = page.popstate = function (path, id, version) {
13       OSM.loadSidebarContent(path, function () {
14         initVersionsNavigation();
15         page._addObject(type, id, version);
16       });
17     };
18
19     page.load = function (path, id, version) {
20       initVersionsNavigation();
21       page._addObject(type, id, version, true);
22     };
23
24     page.unload = function () {
25       page._removeObject();
26       scrollStartObserver?.disconnect();
27       scrollStartObserver = null;
28       scrollEndObserver?.disconnect();
29       scrollEndObserver = null;
30     };
31
32     page._addObject = function () {};
33     page._removeObject = function () {};
34
35     function initVersionsNavigation() {
36       scrollToActiveVersion();
37
38       const $scrollableList = $("#versions-navigation-list-middle");
39       const [scrollableFirstItem] = $scrollableList.children().first();
40       const [scrollableLastItem] = $scrollableList.children().last();
41
42       if (scrollableFirstItem) {
43         scrollStartObserver = createScrollObserver("#versions-navigation-list-start", "2px 0px");
44         scrollStartObserver.observe(scrollableFirstItem);
45       }
46
47       if (scrollableLastItem) {
48         scrollEndObserver = createScrollObserver("#versions-navigation-list-end", "-2px 0px");
49         scrollEndObserver.observe(scrollableLastItem);
50       }
51     }
52
53     function createScrollObserver(shadowTarget, shadowOffset) {
54       const threshold = 0.95;
55       return new IntersectionObserver(([entry]) => {
56         const floating = entry.intersectionRatio < threshold;
57         $(shadowTarget)
58           .css("box-shadow", floating ? `rgba(0, 0, 0, 0.075) ${shadowOffset} 2px` : "")
59           .css("z-index", floating ? "5" : ""); // floating z-index should be larger than z-index of Bootstrap's .page-link:focus, which is 3
60       }, { threshold });
61     }
62
63     return page;
64   };
65
66   OSM.MappedElement = function (map, type) {
67     const page = OSM.Element(map, type);
68
69     page._addObject = function (type, id, version, center) {
70       const hashParams = OSM.parseHash();
71       map.addObject({ type: type, id: parseInt(id, 10), version: version && parseInt(version, 10) }, function (bounds) {
72         if (!hashParams.center && bounds.isValid() &&
73             (center || !map.getBounds().contains(bounds))) {
74           OSM.router.withoutMoveListener(function () {
75             map.fitBounds(bounds);
76           });
77         }
78       });
79     };
80
81     page._removeObject = function () {
82       map.removeObject();
83     };
84
85     return page;
86   };
87
88   function scrollToActiveVersion() {
89     const [scrollableList] = $("#versions-navigation-list-middle");
90
91     if (!scrollableList) return;
92
93     const [activeStartItem] = $("#versions-navigation-list-start #versions-navigation-active-page-item");
94     const [activeScrollableItem] = $("#versions-navigation-list-middle #versions-navigation-active-page-item");
95
96     if (activeStartItem) {
97       scrollableList.scrollLeft = 0;
98     } else if (activeScrollableItem) {
99       scrollableList.scrollLeft = Math.round(activeScrollableItem.offsetLeft - (scrollableList.offsetWidth / 2) + (activeScrollableItem.offsetWidth / 2));
100     } else {
101       scrollableList.scrollLeft = scrollableList.scrollWidth - scrollableList.offsetWidth;
102     }
103   }
104 }());