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/*"],