commit
97b53123ee
|
@ -0,0 +1,37 @@
|
||||||
|
// (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 { AddonModLabelModuleHandler } from './providers/module-handler';
|
||||||
|
import { AddonModLabelLinkHandler } from './providers/link-handler';
|
||||||
|
import { CoreCourseModuleDelegate } from '../../../core/course/providers/module-delegate';
|
||||||
|
import { CoreContentLinksDelegate } from '../../../core/contentlinks/providers/delegate';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
AddonModLabelModuleHandler,
|
||||||
|
AddonModLabelLinkHandler
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AddonModLabelModule {
|
||||||
|
constructor(moduleDelegate: CoreCourseModuleDelegate, moduleHandler: AddonModLabelModuleHandler,
|
||||||
|
contentLinksDelegate: CoreContentLinksDelegate, linkHandler: AddonModLabelLinkHandler) {
|
||||||
|
moduleDelegate.registerHandler(moduleHandler);
|
||||||
|
contentLinksDelegate.registerHandler(linkHandler);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// (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 { Injectable } from '@angular/core';
|
||||||
|
import { CoreContentLinksModuleIndexHandler } from '../../../../core/contentlinks/classes/module-index-handler';
|
||||||
|
import { CoreCourseHelperProvider } from '../../../../core/course/providers/helper';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler to treat links to label.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class AddonModLabelLinkHandler extends CoreContentLinksModuleIndexHandler {
|
||||||
|
name = 'AddonModLabelLinkHandler';
|
||||||
|
|
||||||
|
constructor(courseHelper: CoreCourseHelperProvider) {
|
||||||
|
super(courseHelper, 'mmaModLabel', 'label');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
// (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 { Injectable } from '@angular/core';
|
||||||
|
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '../../../../core/course/providers/module-delegate';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler to support label modules.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class AddonModLabelModuleHandler implements CoreCourseModuleHandler {
|
||||||
|
name = 'label';
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the handler is enabled on a site level.
|
||||||
|
*
|
||||||
|
* @return {boolean} Whether or not the handler is enabled on a site level.
|
||||||
|
*/
|
||||||
|
isEnabled(): boolean | Promise<boolean> {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data required to display the module in the course contents view.
|
||||||
|
*
|
||||||
|
* @param {any} module The module object.
|
||||||
|
* @param {number} courseId The course ID.
|
||||||
|
* @param {number} sectionId The section ID.
|
||||||
|
* @return {CoreCourseModuleHandlerData} Data to render the module.
|
||||||
|
*/
|
||||||
|
getData(module: any, courseId: number, sectionId: number): CoreCourseModuleHandlerData {
|
||||||
|
// Remove the description from the module so it isn't rendered twice.
|
||||||
|
const title = module.description;
|
||||||
|
module.description = '';
|
||||||
|
|
||||||
|
return {
|
||||||
|
icon: '',
|
||||||
|
title: title,
|
||||||
|
class: 'addon-mod-label-handler'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the component to render the module. This is needed to support singleactivity course format.
|
||||||
|
*
|
||||||
|
* @param {any} course The course object.
|
||||||
|
* @param {any} module The module object.
|
||||||
|
* @return {any} The component to use, undefined if not found.
|
||||||
|
*/
|
||||||
|
getMainComponent(course: any, module: any): any {
|
||||||
|
// There's no need to implement this because label cannot be used in singleactivity course format.
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,6 +66,7 @@ import { CoreUserModule } from '../core/user/user.module';
|
||||||
import { AddonCalendarModule } from '../addon/calendar/calendar.module';
|
import { AddonCalendarModule } from '../addon/calendar/calendar.module';
|
||||||
import { AddonUserProfileFieldModule } from '../addon/userprofilefield/userprofilefield.module';
|
import { AddonUserProfileFieldModule } from '../addon/userprofilefield/userprofilefield.module';
|
||||||
import { AddonFilesModule } from '../addon/files/files.module';
|
import { AddonFilesModule } from '../addon/files/files.module';
|
||||||
|
import { AddonModLabelModule } from '../addon/mod/label/label.module';
|
||||||
|
|
||||||
// For translate loader. AoT requires an exported function for factories.
|
// For translate loader. AoT requires an exported function for factories.
|
||||||
export function createTranslateLoader(http: HttpClient): TranslateHttpLoader {
|
export function createTranslateLoader(http: HttpClient): TranslateHttpLoader {
|
||||||
|
@ -103,7 +104,8 @@ export function createTranslateLoader(http: HttpClient): TranslateHttpLoader {
|
||||||
CoreUserModule,
|
CoreUserModule,
|
||||||
AddonCalendarModule,
|
AddonCalendarModule,
|
||||||
AddonUserProfileFieldModule,
|
AddonUserProfileFieldModule,
|
||||||
AddonFilesModule
|
AddonFilesModule,
|
||||||
|
AddonModLabelModule
|
||||||
],
|
],
|
||||||
bootstrap: [IonicApp],
|
bootstrap: [IonicApp],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
|
|
|
@ -24,31 +24,28 @@ import { CoreCourseHelperProvider } from '../../course/providers/helper';
|
||||||
*/
|
*/
|
||||||
export class CoreContentLinksModuleGradeHandler extends CoreContentLinksHandlerBase {
|
export class CoreContentLinksModuleGradeHandler extends CoreContentLinksHandlerBase {
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the addon as it's registered in course delegate. It'll be used to check if it's disabled.
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
addon: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the module (assign, book, ...).
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
modName: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the module can be reviewed in the app. If true, the handler needs to implement the goToReview function.
|
* Whether the module can be reviewed in the app. If true, the handler needs to implement the goToReview function.
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
canReview: boolean;
|
canReview: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the handler.
|
||||||
|
*
|
||||||
|
* @param {CoreCourseHelperProvider} courseHelper The CoreCourseHelperProvider instance.
|
||||||
|
* @param {CoreDomUtilsProvider} domUtils The CoreDomUtilsProvider instance.
|
||||||
|
* @param {CoreSitesProvider} sitesProvider The CoreSitesProvider instance.
|
||||||
|
* @param {string} addon Name of the addon as it's registered in course delegate. It'll be used to check if it's disabled.
|
||||||
|
* @param {string} modName Name of the module (assign, book, ...).
|
||||||
|
*/
|
||||||
constructor(protected courseHelper: CoreCourseHelperProvider, protected domUtils: CoreDomUtilsProvider,
|
constructor(protected courseHelper: CoreCourseHelperProvider, protected domUtils: CoreDomUtilsProvider,
|
||||||
protected sitesProvider: CoreSitesProvider) {
|
protected sitesProvider: CoreSitesProvider, public addon: string, public modName: string) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
// Match the grade.php URL with an id param.
|
// Match the grade.php URL with an id param.
|
||||||
this.pattern = new RegExp('\/mod\/' + this.modName + '\/grade\.php.*([\&\?]id=\\d+)');
|
this.pattern = new RegExp('\/mod\/' + modName + '\/grade\.php.*([\&\?]id=\\d+)');
|
||||||
this.featureName = '$mmCourseDelegate_' + this.addon;
|
this.featureName = '$mmCourseDelegate_' + addon;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,23 +22,18 @@ import { CoreCourseHelperProvider } from '../../course/providers/helper';
|
||||||
export class CoreContentLinksModuleIndexHandler extends CoreContentLinksHandlerBase {
|
export class CoreContentLinksModuleIndexHandler extends CoreContentLinksHandlerBase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name of the addon as it's registered in course delegate. It'll be used to check if it's disabled.
|
* Construct the handler.
|
||||||
* @type {string}
|
*
|
||||||
|
* @param {CoreCourseHelperProvider} courseHelper The CoreCourseHelperProvider instance.
|
||||||
|
* @param {string} addon Name of the addon as it's registered in course delegate. It'll be used to check if it's disabled.
|
||||||
|
* @param {string} modName Name of the module (assign, book, ...).
|
||||||
*/
|
*/
|
||||||
addon: string;
|
constructor(protected courseHelper: CoreCourseHelperProvider, public addon: string, public modName: string) {
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the module (assign, book, ...).
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
modName: string;
|
|
||||||
|
|
||||||
constructor(private courseHelper: CoreCourseHelperProvider) {
|
|
||||||
super();
|
super();
|
||||||
|
|
||||||
// Match the view.php URL with an id param.
|
// Match the view.php URL with an id param.
|
||||||
this.pattern = new RegExp('\/mod\/' + this.modName + '\/view\.php.*([\&\?]id=\\d+)');
|
this.pattern = new RegExp('\/mod\/' + modName + '\/view\.php.*([\&\?]id=\\d+)');
|
||||||
this.featureName = '$mmCourseDelegate_' + this.addon;
|
this.featureName = '$mmCourseDelegate_' + addon;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, Input, OnInit, OnChanges, OnDestroy, SimpleChange, Output, EventEmitter } from '@angular/core';
|
import { Component, Input, OnInit, OnChanges, OnDestroy, SimpleChange, Output, EventEmitter } from '@angular/core';
|
||||||
|
import { Content } from 'ionic-angular';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { CoreEventsProvider } from '../../../../providers/events';
|
import { CoreEventsProvider } from '../../../../providers/events';
|
||||||
import { CoreSitesProvider } from '../../../../providers/sites';
|
import { CoreSitesProvider } from '../../../../providers/sites';
|
||||||
|
@ -42,6 +43,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
@Input() downloadEnabled?: boolean; // Whether the download of sections and modules is enabled.
|
@Input() downloadEnabled?: boolean; // Whether the download of sections and modules is enabled.
|
||||||
@Input() initialSectionId?: number; // The section to load first (by ID).
|
@Input() initialSectionId?: number; // The section to load first (by ID).
|
||||||
@Input() initialSectionNumber?: number; // The section to load first (by number).
|
@Input() initialSectionNumber?: number; // The section to load first (by number).
|
||||||
|
@Input() moduleId?: number; // The module ID to scroll to. Must be inside the initial selected section.
|
||||||
@Output() completionChanged?: EventEmitter<void>; // Will emit an event when any module completion changes.
|
@Output() completionChanged?: EventEmitter<void>; // Will emit an event when any module completion changes.
|
||||||
|
|
||||||
// All the possible component classes.
|
// All the possible component classes.
|
||||||
|
@ -64,7 +66,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
|
|
||||||
constructor(private cfDelegate: CoreCourseFormatDelegate, translate: TranslateService,
|
constructor(private cfDelegate: CoreCourseFormatDelegate, translate: TranslateService,
|
||||||
private courseHelper: CoreCourseHelperProvider, private domUtils: CoreDomUtilsProvider,
|
private courseHelper: CoreCourseHelperProvider, private domUtils: CoreDomUtilsProvider,
|
||||||
eventsProvider: CoreEventsProvider, private sitesProvider: CoreSitesProvider,
|
eventsProvider: CoreEventsProvider, private sitesProvider: CoreSitesProvider, private content: Content,
|
||||||
prefetchDelegate: CoreCourseModulePrefetchDelegate) {
|
prefetchDelegate: CoreCourseModulePrefetchDelegate) {
|
||||||
|
|
||||||
this.selectOptions.title = translate.instant('core.course.sections');
|
this.selectOptions.title = translate.instant('core.course.sections');
|
||||||
|
@ -132,7 +134,8 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
// We have an input indicating the section ID to load. Search the section.
|
// We have an input indicating the section ID to load. Search the section.
|
||||||
for (let i = 0; i < this.sections.length; i++) {
|
for (let i = 0; i < this.sections.length; i++) {
|
||||||
const section = this.sections[i];
|
const section = this.sections[i];
|
||||||
if (section.id == this.initialSectionId || section.section == this.initialSectionNumber) {
|
if ((section.id && section.id == this.initialSectionId) ||
|
||||||
|
(section.section && section.section == this.initialSectionNumber)) {
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
this.sectionChanged(section);
|
this.sectionChanged(section);
|
||||||
break;
|
break;
|
||||||
|
@ -212,6 +215,12 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
const previousValue = this.selectedSection;
|
const previousValue = this.selectedSection;
|
||||||
this.selectedSection = newSection;
|
this.selectedSection = newSection;
|
||||||
this.data.section = this.selectedSection;
|
this.data.section = this.selectedSection;
|
||||||
|
|
||||||
|
if (this.moduleId && typeof previousValue == 'undefined') {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.domUtils.scrollToElementBySelector(this.content, '#core-course-module-' + this.moduleId);
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
|
|
||||||
<core-loading [hideUntil]="dataLoaded">
|
<core-loading [hideUntil]="dataLoaded">
|
||||||
<core-course-format [course]="course" [sections]="sections" [initialSectionId]="sectionId" [initialSectionNumber]="sectionNumber" [downloadEnabled]="downloadEnabled" (completionChanged)="onCompletionChange()"></core-course-format>
|
<core-course-format [course]="course" [sections]="sections" [initialSectionId]="sectionId" [initialSectionNumber]="sectionNumber" [downloadEnabled]="downloadEnabled" [moduleId]="moduleId" (completionChanged)="onCompletionChange()"></core-course-format>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
|
@ -50,12 +50,14 @@ export class CoreCourseSectionPage implements OnDestroy {
|
||||||
prefetchCourseData = {
|
prefetchCourseData = {
|
||||||
prefetchCourseIcon: 'spinner'
|
prefetchCourseIcon: 'spinner'
|
||||||
};
|
};
|
||||||
|
moduleId: number;
|
||||||
|
|
||||||
|
protected module: any;
|
||||||
protected completionObserver;
|
protected completionObserver;
|
||||||
protected courseStatusObserver;
|
protected courseStatusObserver;
|
||||||
protected isDestroyed = false;
|
protected isDestroyed = false;
|
||||||
|
|
||||||
constructor(private navParams: NavParams, private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider,
|
constructor(navParams: NavParams, private courseProvider: CoreCourseProvider, private domUtils: CoreDomUtilsProvider,
|
||||||
private courseFormatDelegate: CoreCourseFormatDelegate, private courseOptionsDelegate: CoreCourseOptionsDelegate,
|
private courseFormatDelegate: CoreCourseFormatDelegate, private courseOptionsDelegate: CoreCourseOptionsDelegate,
|
||||||
private translate: TranslateService, private courseHelper: CoreCourseHelperProvider, eventsProvider: CoreEventsProvider,
|
private translate: TranslateService, private courseHelper: CoreCourseHelperProvider, eventsProvider: CoreEventsProvider,
|
||||||
private textUtils: CoreTextUtilsProvider, private coursesProvider: CoreCoursesProvider,
|
private textUtils: CoreTextUtilsProvider, private coursesProvider: CoreCoursesProvider,
|
||||||
|
@ -64,6 +66,7 @@ export class CoreCourseSectionPage implements OnDestroy {
|
||||||
this.course = navParams.get('course');
|
this.course = navParams.get('course');
|
||||||
this.sectionId = navParams.get('sectionId');
|
this.sectionId = navParams.get('sectionId');
|
||||||
this.sectionNumber = navParams.get('sectionNumber');
|
this.sectionNumber = navParams.get('sectionNumber');
|
||||||
|
this.module = navParams.get('module');
|
||||||
this.handlerData.courseId = this.course.id;
|
this.handlerData.courseId = this.course.id;
|
||||||
|
|
||||||
// Get the title to display. We dont't have sections yet.
|
// Get the title to display. We dont't have sections yet.
|
||||||
|
@ -88,9 +91,9 @@ export class CoreCourseSectionPage implements OnDestroy {
|
||||||
*/
|
*/
|
||||||
ionViewDidLoad(): void {
|
ionViewDidLoad(): void {
|
||||||
|
|
||||||
const module = this.navParams.get('module');
|
if (this.module) {
|
||||||
if (module) {
|
this.moduleId = this.module.id;
|
||||||
this.courseHelper.openModule(this.navCtrl, module, this.course.id, this.sectionId);
|
this.courseHelper.openModule(this.navCtrl, this.module, this.course.id, this.sectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loadData().finally(() => {
|
this.loadData().finally(() => {
|
||||||
|
|
|
@ -641,13 +641,20 @@ export class CoreCourseHelperProvider {
|
||||||
* @param {any} module The module to open.
|
* @param {any} module The module to open.
|
||||||
* @param {number} courseId The course ID of the module.
|
* @param {number} courseId The course ID of the module.
|
||||||
* @param {number} [sectionId] The section ID of the module.
|
* @param {number} [sectionId] The section ID of the module.
|
||||||
|
* @param {boolean} True if module can be opened, false otherwise.
|
||||||
*/
|
*/
|
||||||
openModule(navCtrl: NavController, module: any, courseId: number, sectionId?: number): void {
|
openModule(navCtrl: NavController, module: any, courseId: number, sectionId?: number): boolean {
|
||||||
if (!module.handlerData) {
|
if (!module.handlerData) {
|
||||||
module.handlerData = this.moduleDelegate.getModuleDataFor(module.modname, module, courseId, sectionId);
|
module.handlerData = this.moduleDelegate.getModuleDataFor(module.modname, module, courseId, sectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.handlerData.action(new Event('click'), navCtrl, module, courseId, { animate: false });
|
if (module.handlerData && module.handlerData.action) {
|
||||||
|
module.handlerData.action(new Event('click'), navCtrl, module, courseId, { animate: false });
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -205,7 +205,7 @@ export class CoreLoginEmailSignupPage {
|
||||||
create(): void {
|
create(): void {
|
||||||
if (!this.signupForm.valid) {
|
if (!this.signupForm.valid) {
|
||||||
// Form not valid. Scroll to the first element with errors.
|
// Form not valid. Scroll to the first element with errors.
|
||||||
if (!this.domUtils.scrollToInputError(this.content, document.body)) {
|
if (!this.domUtils.scrollToInputError(this.content)) {
|
||||||
// Input not found, show an error modal.
|
// Input not found, show an error modal.
|
||||||
this.domUtils.showErrorModal('core.errorinvalidform', true);
|
this.domUtils.showErrorModal('core.errorinvalidform', true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Directive, ElementRef, Input, Output, EventEmitter, OnChanges, SimpleChange } from '@angular/core';
|
import { Directive, ElementRef, Input, Output, EventEmitter, OnChanges, SimpleChange, Optional } from '@angular/core';
|
||||||
import { Platform, NavController } from 'ionic-angular';
|
import { Platform, NavController, Content } from 'ionic-angular';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { CoreAppProvider } from '../providers/app';
|
import { CoreAppProvider } from '../providers/app';
|
||||||
import { CoreFilepoolProvider } from '../providers/filepool';
|
import { CoreFilepoolProvider } from '../providers/filepool';
|
||||||
|
@ -62,7 +62,8 @@ export class CoreFormatTextDirective implements OnChanges {
|
||||||
private textUtils: CoreTextUtilsProvider, private translate: TranslateService, private platform: Platform,
|
private textUtils: CoreTextUtilsProvider, private translate: TranslateService, private platform: Platform,
|
||||||
private utils: CoreUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private loggerProvider: CoreLoggerProvider,
|
private utils: CoreUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private loggerProvider: CoreLoggerProvider,
|
||||||
private filepoolProvider: CoreFilepoolProvider, private appProvider: CoreAppProvider,
|
private filepoolProvider: CoreFilepoolProvider, private appProvider: CoreAppProvider,
|
||||||
private contentLinksHelper: CoreContentLinksHelperProvider, private navCtrl: NavController) {
|
private contentLinksHelper: CoreContentLinksHelperProvider, private navCtrl: NavController,
|
||||||
|
@Optional() private content: Content) {
|
||||||
this.element = element.nativeElement;
|
this.element = element.nativeElement;
|
||||||
this.element.classList.add('opacity-hide'); // Hide contents until they're treated.
|
this.element.classList.add('opacity-hide'); // Hide contents until they're treated.
|
||||||
this.afterRender = new EventEmitter();
|
this.afterRender = new EventEmitter();
|
||||||
|
@ -280,7 +281,7 @@ export class CoreFormatTextDirective implements OnChanges {
|
||||||
anchors.forEach((anchor) => {
|
anchors.forEach((anchor) => {
|
||||||
// Angular 2 doesn't let adding directives dynamically. Create the CoreLinkDirective manually.
|
// Angular 2 doesn't let adding directives dynamically. Create the CoreLinkDirective manually.
|
||||||
const linkDir = new CoreLinkDirective(anchor, this.domUtils, this.utils, this.sitesProvider, this.urlUtils,
|
const linkDir = new CoreLinkDirective(anchor, this.domUtils, this.utils, this.sitesProvider, this.urlUtils,
|
||||||
this.contentLinksHelper, this.navCtrl);
|
this.contentLinksHelper, this.navCtrl, this.content);
|
||||||
linkDir.capture = true;
|
linkDir.capture = true;
|
||||||
linkDir.ngOnInit();
|
linkDir.ngOnInit();
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Directive, Input, OnInit, ElementRef } from '@angular/core';
|
import { Directive, Input, OnInit, ElementRef } from '@angular/core';
|
||||||
import { NavController } from 'ionic-angular';
|
import { NavController, Content } from 'ionic-angular';
|
||||||
import { CoreSitesProvider } from '../providers/sites';
|
import { CoreSitesProvider } from '../providers/sites';
|
||||||
import { CoreDomUtilsProvider } from '../providers/utils/dom';
|
import { CoreDomUtilsProvider } from '../providers/utils/dom';
|
||||||
import { CoreUrlUtilsProvider } from '../providers/utils/url';
|
import { CoreUrlUtilsProvider } from '../providers/utils/url';
|
||||||
|
@ -38,8 +38,9 @@ export class CoreLinkDirective implements OnInit {
|
||||||
protected element: HTMLElement;
|
protected element: HTMLElement;
|
||||||
|
|
||||||
constructor(element: ElementRef, private domUtils: CoreDomUtilsProvider, private utils: CoreUtilsProvider,
|
constructor(element: ElementRef, private domUtils: CoreDomUtilsProvider, private utils: CoreUtilsProvider,
|
||||||
private sitesProvider: CoreSitesProvider, private urlUtils: CoreUrlUtilsProvider,
|
private sitesProvider: CoreSitesProvider, private urlUtils: CoreUrlUtilsProvider,
|
||||||
private contentLinksHelper: CoreContentLinksHelperProvider, private navCtrl: NavController) {
|
private contentLinksHelper: CoreContentLinksHelperProvider, private navCtrl: NavController,
|
||||||
|
private content: Content) {
|
||||||
// This directive can be added dynamically. In that case, the first param is the anchor HTMLElement.
|
// This directive can be added dynamically. In that case, the first param is the anchor HTMLElement.
|
||||||
this.element = element.nativeElement || element;
|
this.element = element.nativeElement || element;
|
||||||
}
|
}
|
||||||
|
@ -93,8 +94,7 @@ export class CoreLinkDirective implements OnInit {
|
||||||
// $location.url(href);
|
// $location.url(href);
|
||||||
} else {
|
} else {
|
||||||
// Look for id or name.
|
// Look for id or name.
|
||||||
const scrollEl = <HTMLElement> this.domUtils.closest(this.element, 'scroll-content');
|
this.domUtils.scrollToElementBySelector(this.content, '#' + href + ', [name=\'' + href + '\']');
|
||||||
this.domUtils.scrollToElement(scrollEl, document.body, '#' + href + ', [name=\'' + href + '\']');
|
|
||||||
}
|
}
|
||||||
} else if (href.indexOf(contentLinksScheme) === 0) {
|
} else if (href.indexOf(contentLinksScheme) === 0) {
|
||||||
// Link should be treated by Custom URL Scheme. Encode the right part, otherwise ':' is removed in iOS.
|
// Link should be treated by Custom URL Scheme. Encode the right part, otherwise ':' is removed in iOS.
|
||||||
|
|
|
@ -584,22 +584,39 @@ export class CoreDomUtilsProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scroll to a certain element inside another element.
|
* Scroll to a certain element.
|
||||||
*
|
*
|
||||||
* @param {Content|HTMLElement} scrollEl The content that must be scrolled.
|
* @param {Content} content The content that must be scrolled.
|
||||||
* @param {HTMLElement} container Element to search in.
|
* @param {HTMLElement} element The element to scroll to.
|
||||||
* @param {string} [selector] Selector to find the element to scroll to. If not defined, scroll to the container.
|
|
||||||
* @param {string} [scrollParentClass] Parent class where to stop calculating the position. Default scroll-content.
|
* @param {string} [scrollParentClass] Parent class where to stop calculating the position. Default scroll-content.
|
||||||
* @return {boolean} True if the element is found, false otherwise.
|
* @return {boolean} True if the element is found, false otherwise.
|
||||||
*/
|
*/
|
||||||
scrollToElement(scrollEl: Content | HTMLElement, container: HTMLElement, selector?: string, scrollParentClass?: string)
|
scrollToElement(content: Content, element: HTMLElement, scrollParentClass?: string): boolean {
|
||||||
: boolean {
|
const position = this.getElementXY(element, undefined, scrollParentClass);
|
||||||
const position = this.getElementXY(container, selector, scrollParentClass);
|
|
||||||
if (!position) {
|
if (!position) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollEl.scrollTo(position[0], position[1]);
|
content.scrollTo(position[0], position[1]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scroll to a certain element using a selector to find it.
|
||||||
|
*
|
||||||
|
* @param {Content} content The content that must be scrolled.
|
||||||
|
* @param {string} selector Selector to find the element to scroll to.
|
||||||
|
* @param {string} [scrollParentClass] Parent class where to stop calculating the position. Default scroll-content.
|
||||||
|
* @return {boolean} True if the element is found, false otherwise.
|
||||||
|
*/
|
||||||
|
scrollToElementBySelector(content: Content, selector: string, scrollParentClass?: string): boolean {
|
||||||
|
const position = this.getElementXY(content.getScrollElement(), selector, scrollParentClass);
|
||||||
|
if (!position) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
content.scrollTo(position[0], position[1]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -607,17 +624,16 @@ export class CoreDomUtilsProvider {
|
||||||
/**
|
/**
|
||||||
* Search for an input with error (core-input-error directive) and scrolls to it if found.
|
* Search for an input with error (core-input-error directive) and scrolls to it if found.
|
||||||
*
|
*
|
||||||
* @param {Content|HTMLElement} scrollEl The element that must be scrolled.
|
* @param {Content} content The content that must be scrolled.
|
||||||
* @param {HTMLElement} container Element to search in.
|
|
||||||
* @param [scrollParentClass] Parent class where to stop calculating the position. Default scroll-content.
|
* @param [scrollParentClass] Parent class where to stop calculating the position. Default scroll-content.
|
||||||
* @return {boolean} True if the element is found, false otherwise.
|
* @return {boolean} True if the element is found, false otherwise.
|
||||||
*/
|
*/
|
||||||
scrollToInputError(scrollEl: Content | HTMLElement, container: HTMLElement, scrollParentClass?: string): boolean {
|
scrollToInputError(content: Content, scrollParentClass?: string): boolean {
|
||||||
if (!scrollEl) {
|
if (!content) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.scrollToElement(scrollEl, container, '.core-input-error', scrollParentClass);
|
return this.scrollToElementBySelector(content, '.core-input-error', scrollParentClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue