diff --git a/package-lock.json b/package-lock.json
index 9dc24bbf0..18d46b811 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4224,6 +4224,12 @@
"integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==",
"dev": true
},
+ "@types/resize-observer-browser": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@types/resize-observer-browser/-/resize-observer-browser-0.1.5.tgz",
+ "integrity": "sha512-8k/67Z95Goa6Lznuykxkfhq9YU3l1Qe6LNZmwde1u7802a3x8v44oq0j91DICclxatTr0rNnhXx7+VTIetSrSQ==",
+ "dev": true
+ },
"@types/source-list-map": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
diff --git a/package.json b/package.json
index 73602ebcc..69d03672b 100644
--- a/package.json
+++ b/package.json
@@ -140,6 +140,7 @@
"@ionic/v4-migration-tslint": "^1.7.1",
"@types/faker": "^5.1.3",
"@types/node": "^12.12.64",
+ "@types/resize-observer-browser": "^0.1.5",
"@types/webpack-env": "^1.16.0",
"@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "^4.22.0",
diff --git a/src/addons/block/recentlyaccessedcourses/components/recentlyaccessedcourses/addon-block-recentlyaccessedcourses.html b/src/addons/block/recentlyaccessedcourses/components/recentlyaccessedcourses/addon-block-recentlyaccessedcourses.html
index fe13ea87b..56d9ffb91 100644
--- a/src/addons/block/recentlyaccessedcourses/components/recentlyaccessedcourses/addon-block-recentlyaccessedcourses.html
+++ b/src/addons/block/recentlyaccessedcourses/components/recentlyaccessedcourses/addon-block-recentlyaccessedcourses.html
@@ -29,9 +29,11 @@
class="core-horizontal-scroll"
(scroll)="scrollControls.updateScrollPosition()"
>
-
-
-
+
+
+
+
+
diff --git a/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html b/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html
index a2e1fde5e..62267a363 100644
--- a/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html
+++ b/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html
@@ -12,25 +12,27 @@
class="core-horizontal-scroll"
(scroll)="scrollControls.updateScrollPosition()"
>
-
-
-
-
-
-
- {{ item.iconTitle }}
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ {{ item.iconTitle }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/recentlyaccesseditems.scss b/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/recentlyaccesseditems.scss
index 14a35cad6..ce246a96f 100644
--- a/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/recentlyaccesseditems.scss
+++ b/src/addons/block/recentlyaccesseditems/components/recentlyaccesseditems/recentlyaccesseditems.scss
@@ -1,7 +1,7 @@
@import "~theme/globals";
:host {
- .core-horizontal-scroll > div {
+ .core-horizontal-scroll > div > div {
@include horizontal_scroll_item(80%, 250px, 300px);
}
diff --git a/src/addons/block/starredcourses/components/starredcourses/addon-block-starredcourses.html b/src/addons/block/starredcourses/components/starredcourses/addon-block-starredcourses.html
index bd010b101..9b3cbaa37 100644
--- a/src/addons/block/starredcourses/components/starredcourses/addon-block-starredcourses.html
+++ b/src/addons/block/starredcourses/components/starredcourses/addon-block-starredcourses.html
@@ -30,9 +30,11 @@
class="core-horizontal-scroll"
(scroll)="scrollControls.updateScrollPosition()"
>
-
-
-
+
+
+
+
+
diff --git a/src/core/directives/directives.module.ts b/src/core/directives/directives.module.ts
index b83ee4534..f60c2d19d 100644
--- a/src/core/directives/directives.module.ts
+++ b/src/core/directives/directives.module.ts
@@ -25,6 +25,7 @@ import { CoreLongPressDirective } from './long-press';
import { CoreSupressEventsDirective } from './supress-events';
import { CoreUserLinkDirective } from './user-link';
import { CoreAriaButtonClickDirective } from './aria-button';
+import { CoreOnResizeDirective } from './on-resize';
@NgModule({
declarations: [
@@ -39,6 +40,7 @@ import { CoreAriaButtonClickDirective } from './aria-button';
CoreSupressEventsDirective,
CoreUserLinkDirective,
CoreAriaButtonClickDirective,
+ CoreOnResizeDirective,
],
exports: [
CoreAutoFocusDirective,
@@ -52,6 +54,7 @@ import { CoreAriaButtonClickDirective } from './aria-button';
CoreSupressEventsDirective,
CoreUserLinkDirective,
CoreAriaButtonClickDirective,
+ CoreOnResizeDirective,
],
})
export class CoreDirectivesModule {}
diff --git a/src/core/directives/on-resize.ts b/src/core/directives/on-resize.ts
new file mode 100644
index 000000000..8660008f0
--- /dev/null
+++ b/src/core/directives/on-resize.ts
@@ -0,0 +1,99 @@
+// (C) Copyright 2015 Moodle Pty Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { Directive, ElementRef, OnInit, Output, EventEmitter, OnDestroy } from '@angular/core';
+import { CoreUtils } from '@services/utils/utils';
+
+/**
+ * Directive to listen for element resize events.
+ */
+@Directive({
+ selector: '[onResize]',
+})
+export class CoreOnResizeDirective implements OnInit, OnDestroy {
+
+ @Output() onResize = new EventEmitter();
+
+ private element: HTMLElement;
+ private resizeObserver?: ResizeObserver;
+ private mutationObserver?: MutationObserver;
+
+ constructor(element: ElementRef) {
+ this.element = element.nativeElement;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ ngOnInit(): void {
+ 'ResizeObserver' in window
+ ? this.watchResize()
+ : this.watchMutations();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ ngOnDestroy(): void {
+ this.resizeObserver?.disconnect();
+ this.mutationObserver?.disconnect();
+ }
+
+ /**
+ * Watch resize events.
+ */
+ private watchResize(): void {
+ this.resizeObserver = new ResizeObserver(() => this.onResize.emit());
+
+ this.resizeObserver.observe(this.element);
+ }
+
+ /**
+ * Watch mutation events to detect resizing.
+ */
+ private watchMutations(): void {
+ let size = this.getElementSize();
+ const onMutation = () => {
+ const newSize = this.getElementSize();
+
+ if (newSize.width !== size.width || newSize.height !== size.height) {
+ size = newSize;
+
+ this.onResize.emit();
+ }
+ };
+
+ // Debounce 20ms to let mutations resolve before checking the new size.
+ this.mutationObserver = new MutationObserver(CoreUtils.debounce(onMutation, 20));
+
+ this.mutationObserver.observe(this.element, {
+ subtree: true,
+ childList: true,
+ characterData: true,
+ });
+ }
+
+ /**
+ * Get element size.
+ *
+ * @returns Element size.
+ */
+ private getElementSize(): { width: number; height: number } {
+ return {
+ width: this.element.clientWidth,
+ height: this.element.clientHeight,
+ };
+ }
+
+}
diff --git a/tsconfig.app.json b/tsconfig.app.json
index feedfbd74..530f84a16 100644
--- a/tsconfig.app.json
+++ b/tsconfig.app.json
@@ -8,6 +8,7 @@
"cordova",
"dom-mediacapture-record",
"node",
+ "resize-observer-browser",
"webpack-env"
],
"paths": {
diff --git a/tsconfig.json b/tsconfig.json
index 0e32c7acc..700301d46 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -27,6 +27,7 @@
"faker",
"jest",
"node",
+ "resize-observer-browser",
"webpack-env"
],
"paths": {
diff --git a/tsconfig.test.json b/tsconfig.test.json
index 34d2a3698..58fd560d7 100644
--- a/tsconfig.test.json
+++ b/tsconfig.test.json
@@ -12,7 +12,8 @@
"dom-mediacapture-record",
"faker",
"jest",
- "node"
+ "node",
+ "resize-observer-browser"
],
"paths": {
"@addons/*": ["addons/*"],