From 38a7dd355e568c3f92be7b44c02f658cdf3bcb66 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 8 May 2019 11:36:51 +0200 Subject: [PATCH 1/2] MOBILE-3010 core: Support Bootstrap tooltips --- src/components/bs-tooltip/bs-tooltip.scss | 2 + src/components/bs-tooltip/bs-tooltip.ts | 33 +++++++++++++ .../bs-tooltip/core-bs-tooltip.html | 4 ++ src/components/components.module.ts | 10 ++-- src/directives/format-text.ts | 2 + src/providers/utils/dom.ts | 46 +++++++++++++++++-- 6 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 src/components/bs-tooltip/bs-tooltip.scss create mode 100644 src/components/bs-tooltip/bs-tooltip.ts create mode 100644 src/components/bs-tooltip/core-bs-tooltip.html diff --git a/src/components/bs-tooltip/bs-tooltip.scss b/src/components/bs-tooltip/bs-tooltip.scss new file mode 100644 index 000000000..54640d936 --- /dev/null +++ b/src/components/bs-tooltip/bs-tooltip.scss @@ -0,0 +1,2 @@ +ion-app.app-root core-bs-tooltip { +} diff --git a/src/components/bs-tooltip/bs-tooltip.ts b/src/components/bs-tooltip/bs-tooltip.ts new file mode 100644 index 000000000..8248fa9f1 --- /dev/null +++ b/src/components/bs-tooltip/bs-tooltip.ts @@ -0,0 +1,33 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { Component } from '@angular/core'; +import { NavParams } from 'ionic-angular'; + +/** + * Component to display a Bootstrap Tooltip in a popover. + */ +@Component({ + selector: 'core-bs-tooltip', + templateUrl: 'core-bs-tooltip.html' +}) +export class CoreBSTooltipComponent { + content: string; + html: boolean; + + constructor(navParams: NavParams) { + this.content = navParams.get('content') || ''; + this.html = !!navParams.get('html'); + } +} diff --git a/src/components/bs-tooltip/core-bs-tooltip.html b/src/components/bs-tooltip/core-bs-tooltip.html new file mode 100644 index 000000000..198b17159 --- /dev/null +++ b/src/components/bs-tooltip/core-bs-tooltip.html @@ -0,0 +1,4 @@ + +

+

{{content}}

+
\ No newline at end of file diff --git a/src/components/components.module.ts b/src/components/components.module.ts index e72475548..b562dbec3 100644 --- a/src/components/components.module.ts +++ b/src/components/components.module.ts @@ -52,6 +52,7 @@ import { CoreIonTabComponent } from './ion-tabs/ion-tab'; import { CoreInfiniteLoadingComponent } from './infinite-loading/infinite-loading'; import { CoreUserAvatarComponent } from './user-avatar/user-avatar'; import { CoreStyleComponent } from './style/style'; +import { CoreBSTooltipComponent } from './bs-tooltip/bs-tooltip'; @NgModule({ declarations: [ @@ -89,12 +90,14 @@ import { CoreStyleComponent } from './style/style'; CoreIonTabComponent, CoreInfiniteLoadingComponent, CoreUserAvatarComponent, - CoreStyleComponent + CoreStyleComponent, + CoreBSTooltipComponent ], entryComponents: [ CoreContextMenuPopoverComponent, CoreCoursePickerMenuPopoverComponent, - CoreRecaptchaModalComponent + CoreRecaptchaModalComponent, + CoreBSTooltipComponent ], imports: [ IonicModule, @@ -134,7 +137,8 @@ import { CoreStyleComponent } from './style/style'; CoreIonTabComponent, CoreInfiniteLoadingComponent, CoreUserAvatarComponent, - CoreStyleComponent + CoreStyleComponent, + CoreBSTooltipComponent ] }) export class CoreComponentsModule {} diff --git a/src/directives/format-text.ts b/src/directives/format-text.ts index c54b4389d..8cfbd3067 100644 --- a/src/directives/format-text.ts +++ b/src/directives/format-text.ts @@ -442,6 +442,8 @@ export class CoreFormatTextDirective implements OnChanges { this.iframeUtils.treatFrame(frame); }); + this.domUtils.handleBootstrapTooltips(div); + return div; }); } diff --git a/src/providers/utils/dom.ts b/src/providers/utils/dom.ts index bf303e859..d9c192341 100644 --- a/src/providers/utils/dom.ts +++ b/src/providers/utils/dom.ts @@ -14,8 +14,8 @@ import { Injectable, SimpleChange } from '@angular/core'; import { - LoadingController, Loading, ToastController, Toast, AlertController, Alert, Platform, Content, - ModalController + LoadingController, Loading, ToastController, Toast, AlertController, Alert, Platform, Content, PopoverController, + ModalController, } from 'ionic-angular'; import { DomSanitizer } from '@angular/platform-browser'; import { TranslateService } from '@ngx-translate/core'; @@ -24,6 +24,7 @@ import { CoreAppProvider } from '../app'; import { CoreConfigProvider } from '../config'; import { CoreUrlUtilsProvider } from './url'; import { CoreConstants } from '@core/constants'; +import { CoreBSTooltipComponent } from '@components/bs-tooltip/bs-tooltip'; import { Md5 } from 'ts-md5/dist/md5'; import { Subject } from 'rxjs'; @@ -65,7 +66,7 @@ export class CoreDomUtilsProvider { constructor(private translate: TranslateService, private loadingCtrl: LoadingController, private toastCtrl: ToastController, private alertCtrl: AlertController, private textUtils: CoreTextUtilsProvider, private appProvider: CoreAppProvider, private platform: Platform, private configProvider: CoreConfigProvider, private urlUtils: CoreUrlUtilsProvider, - private modalCtrl: ModalController, private sanitizer: DomSanitizer) { + private modalCtrl: ModalController, private sanitizer: DomSanitizer, private popoverCtrl: PopoverController) { // Check if debug messages should be displayed. configProvider.get(CoreConstants.SETTINGS_DEBUG_DISPLAY, false).then((debugDisplay) => { @@ -564,6 +565,45 @@ export class CoreDomUtilsProvider { return this.instances[id]; } + /** + * Handle bootstrap tooltips in a certain element. + * + * @param {HTMLElement} element Element to check. + */ + handleBootstrapTooltips(element: HTMLElement): void { + const els = Array.from(element.querySelectorAll('[data-toggle="tooltip"]')); + + els.forEach((el) => { + const content = el.getAttribute('title') || el.getAttribute('data-original-title'), + trigger = el.getAttribute('data-trigger') || 'hover focus', + treated = el.getAttribute('data-bstooltip-treated'); + + if (!content || treated === 'true' || + (trigger.indexOf('hover') == -1 && trigger.indexOf('focus') == -1 && trigger.indexOf('click') == -1)) { + return; + } + + el.setAttribute('data-bstooltip-treated', 'true'); // Mark it as treated. + + // Store the title in data-original-title instead of title, like BS does. + el.setAttribute('data-original-title', content); + el.setAttribute('title', ''); + + el.addEventListener('click', (e) => { + const html = el.getAttribute('data-html'); + + const popover = this.popoverCtrl.create(CoreBSTooltipComponent, { + content: content, + html: html === 'true' + }); + + popover.present({ + ev: e + }); + }); + }); + } + /** * Check if an element is outside of screen (viewport). * From 1f42ea990aec449008afa7cd73f189cdbd368878 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 8 May 2019 12:05:36 +0200 Subject: [PATCH 2/2] MOBILE-3010 resource: Fix error if no mimetype --- src/addon/mod/resource/providers/module-handler.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/addon/mod/resource/providers/module-handler.ts b/src/addon/mod/resource/providers/module-handler.ts index 905f192e5..573546982 100644 --- a/src/addon/mod/resource/providers/module-handler.ts +++ b/src/addon/mod/resource/providers/module-handler.ts @@ -175,7 +175,9 @@ export class AddonModResourceModuleHandler implements CoreCourseModuleHandler { if (module.contentsinfo) { // No need to use the list of files. const mimetype = module.contentsinfo.mimetypes[0]; - resourceData.icon = this.mimetypeUtils.getMimetypeIcon(mimetype); + if (mimetype) { + resourceData.icon = this.mimetypeUtils.getMimetypeIcon(mimetype); + } resourceData.extra = this.textUtils.cleanTags(module.afterlink); } else if (files && files.length) {