MOBILE-2310 core: Implement image viewer

main
Dani Palou 2018-01-03 10:36:07 +01:00
parent cbc9bc715c
commit 764309edd7
6 changed files with 161 additions and 10 deletions

View File

@ -17,6 +17,7 @@ import { CoreSitesProvider } from '../../../../providers/sites';
import { CoreDomUtilsProvider } from '../../../../providers/utils/dom';
import { CoreTextUtilsProvider } from '../../../../providers/utils/text';
import { CoreUtilsProvider } from '../../../../providers/utils/utils';
import { CoreCourseProvider } from '../../../course/providers/course';
import * as moment from 'moment';
/**
@ -41,7 +42,8 @@ export class CoreCoursesOverviewEventsComponent implements OnChanges {
future: any[] = [];
constructor(private utils: CoreUtilsProvider, private textUtils: CoreTextUtilsProvider,
private domUtils: CoreDomUtilsProvider, private sitesProvider: CoreSitesProvider) {
private domUtils: CoreDomUtilsProvider, private sitesProvider: CoreSitesProvider,
private courseProvider: CoreCourseProvider) {
this.loadMore = new EventEmitter();
}
@ -73,7 +75,7 @@ export class CoreCoursesOverviewEventsComponent implements OnChanges {
return start <= event.timesort;
}).map((event) => {
// @todo: event.iconUrl = this.courseProvider.getModuleIconSrc(event.icon.component);
event.iconUrl = this.courseProvider.getModuleIconSrc(event.icon.component);
return event;
});
}

View File

@ -0,0 +1,14 @@
<ion-header>
<ion-navbar>
<ion-title>{{ title }}</ion-title>
<ion-buttons end *ngIf="isModal">
<button ion-button icon-only (click)="closeModal()" [attr.aria-label]="'core.close' | translate">
<ion-icon name="close"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content padding>
<img [src]="image" alt="{{ title }}" core-external-content [component]="component" [componentId]="componentId">
</ion-content>

View File

@ -0,0 +1,31 @@
// (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 { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { TranslateModule } from '@ngx-translate/core';
import { CoreViewerImagePage } from './image';
import { CoreDirectivesModule } from '../../../../directives/directives.module';
@NgModule({
declarations: [
CoreViewerImagePage
],
imports: [
CoreDirectivesModule,
IonicPageModule.forChild(CoreViewerImagePage),
TranslateModule.forChild()
]
})
export class CoreViewerImagePageModule {}

View File

@ -0,0 +1,48 @@
// (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 { TranslateService } from '@ngx-translate/core';
import { IonicPage, ViewController, NavParams } from 'ionic-angular';
/**
* Page to view an image. If opened as a modal, it will have a button to close the modal.
*/
@IonicPage({segment: 'core-viewer-image'})
@Component({
selector: 'page-core-viewer-image',
templateUrl: 'image.html',
})
export class CoreViewerImagePage {
title: string; // Page title.
image: string; // Image URL.
isModal: boolean; // Whether it should be opened in a modal or in a page.
component: string; // Component to use in external-content.
componentId: string|number; // Component ID to use in external-content.
constructor(private viewCtrl: ViewController, params: NavParams, translate: TranslateService) {
this.title = params.get('title') || translate.instant('core.imageviewer');
this.image = params.get('image');
this.isModal = params.get('isModal');
this.component = params.get('component');
this.componentId = params.get('componentId');
}
/**
* Close modal.
*/
closeModal() : void {
this.viewCtrl.dismiss();
}
}

View File

@ -125,15 +125,35 @@ export class CoreFormatTextDirective implements OnChanges {
if (imgWidth > elWidth) {
// The image has been adapted, add an anchor to view it in full size.
let imgSrc = this.textUtils.escapeHTML(img.getAttribute('src')),
label = this.textUtils.escapeHTML(this.translate.instant('core.openfullimage'));
// @todo: Implement image viewer. Maybe we can add the listener here directly?
container.innerHTML += '<a href="#" class="core-image-viewer-icon" core-image-viewer img="' + imgSrc +
'" aria-label="' + label + '"><ion-icon name="search"></ion-icon></a>';
this.addMagnifyingGlass(container, img);
}
}
/**
* Add a magnifying glass icon to view an image at full size.
*
* @param {HTMLElement} container The container of the image.
* @param {HTMLElement} img The image.
*/
addMagnifyingGlass(container: HTMLElement, img: HTMLElement) : void {
let imgSrc = this.textUtils.escapeHTML(img.getAttribute('src')),
label = this.textUtils.escapeHTML(this.translate.instant('core.openfullimage')),
anchor = document.createElement('a');
anchor.classList.add('core-image-viewer-icon');
anchor.setAttribute('aria-label', label);
// Add an ion-icon item to apply the right styles, but the ion-icon component won't be executed.
anchor.innerHTML = '<ion-icon name="search" class="icon icon-md ion-md-search"></ion-icon>';
anchor.addEventListener('click', (e: Event) => {
e.preventDefault();
e.stopPropagation();
this.domUtils.viewImage(imgSrc, img.getAttribute('alt'), true, this.component, this.componentId);
});
container.appendChild(anchor);
}
/**
* Finish the rendering, displaying the element again and calling afterRender.
*/

View File

@ -13,7 +13,8 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { LoadingController, Loading, ToastController, Toast, AlertController, Alert, Platform, Content } from 'ionic-angular';
import { LoadingController, Loading, ToastController, Toast, AlertController, Alert, Platform, Content,
NavController, ModalController } from 'ionic-angular';
import { TranslateService } from '@ngx-translate/core';
import { CoreTextUtilsProvider } from './text';
import { CoreAppProvider } from '../app';
@ -33,7 +34,8 @@ 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 platform: Platform, private configProvider: CoreConfigProvider, private urlUtils: CoreUrlUtilsProvider,
private modalCtrl: ModalController) {}
/**
* Wraps a message with core-format-text if the message contains HTML tags.
@ -840,6 +842,40 @@ export class CoreDomUtilsProvider {
(el.tagName.toLowerCase() == 'input' && this.inputSupportKeyboard.indexOf(el.type) != -1));
}
/**
* View an image in a new page or modal.
*
* @param {string} image URL of the image.
* @param {string} title Title of the page or modal.
* @param {boolean} [isModal] Whether it should be opened in a modal (true) or in a new page (false).
* @param {string} [component] Component to link the image to if needed.
* @param {string|number} [componentId] An ID to use in conjunction with the component.
* @param {NavController} [navCtrl] The NavController instance to use.
*/
viewImage(image: string, title?: string, isModal?: boolean, component?: string, componentId?: string|number,
navCtrl?: NavController) : void {
if (image) {
let params: any = {
title: title,
image: image,
component: component,
componentId: componentId
};
if (isModal) {
// Open a modal with the contents.
params.isModal = true;
let modal = this.modalCtrl.create('CoreViewerImagePage', params);
modal.present();
} else if (navCtrl) {
// Open a new page with the contents.
navCtrl.push('CoreViewerImagePage', params);
}
}
}
/**
* Wrap an HTMLElement with another element.
*