MOBILE-2235 h5p: Show placeholder instead of H5P directly
parent
5e2e1d1a24
commit
690544afbf
|
@ -0,0 +1,34 @@
|
||||||
|
// (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 { NgModule } from '@angular/core';
|
||||||
|
import { IonicModule } from 'ionic-angular';
|
||||||
|
import { CoreFilterDelegate } from '@core/filter/providers/delegate';
|
||||||
|
import { AddonFilterDisplayH5PHandler } from './providers/handler';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
IonicModule
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
AddonFilterDisplayH5PHandler
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AddonFilterDisplayH5PModule {
|
||||||
|
constructor(filterDelegate: CoreFilterDelegate, handler: AddonFilterDisplayH5PHandler) {
|
||||||
|
filterDelegate.registerHandler(handler);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
|
||||||
|
// (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 { Injectable, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
|
||||||
|
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
||||||
|
import { CoreFilterFilter, CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||||
|
import { CoreH5PPlayerComponent } from '@core/h5p/components/h5p-player/h5p-player';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler to support the Display H5P filter.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class AddonFilterDisplayH5PHandler extends CoreFilterDefaultHandler {
|
||||||
|
name = 'AddonFilterDisplayH5PHandler';
|
||||||
|
filterName = 'displayh5p';
|
||||||
|
|
||||||
|
protected template = document.createElement('template'); // A template element to convert HTML to element.
|
||||||
|
|
||||||
|
constructor(protected factoryResolver: ComponentFactoryResolver) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter some text.
|
||||||
|
*
|
||||||
|
* @param text The text to filter.
|
||||||
|
* @param filter The filter.
|
||||||
|
* @param options Options passed to the filters.
|
||||||
|
* @param siteId Site ID. If not defined, current site.
|
||||||
|
* @return Filtered text (or promise resolved with the filtered text).
|
||||||
|
*/
|
||||||
|
filter(text: string, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string)
|
||||||
|
: string | Promise<string> {
|
||||||
|
|
||||||
|
this.template.innerHTML = text;
|
||||||
|
|
||||||
|
const h5pIframes = <HTMLIFrameElement[]> Array.from(this.template.content.querySelectorAll('iframe.h5p-iframe'));
|
||||||
|
|
||||||
|
// Replace all iframes with an empty div that will be treated in handleHtml.
|
||||||
|
h5pIframes.forEach((iframe) => {
|
||||||
|
const placeholder = document.createElement('div');
|
||||||
|
|
||||||
|
placeholder.classList.add('core-h5p-tmp-placeholder');
|
||||||
|
placeholder.setAttribute('data-player-src', iframe.src);
|
||||||
|
|
||||||
|
iframe.parentElement.replaceChild(placeholder, iframe);
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.template.innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle HTML. This function is called after "filter", and it will receive an HTMLElement containing the text that was
|
||||||
|
* filtered.
|
||||||
|
*
|
||||||
|
* @param container The HTML container to handle.
|
||||||
|
* @param filter The filter.
|
||||||
|
* @param options Options passed to the filters.
|
||||||
|
* @param viewContainerRef The ViewContainerRef where the container is.
|
||||||
|
* @param siteId Site ID. If not defined, current site.
|
||||||
|
* @return If async, promise resolved when done.
|
||||||
|
*/
|
||||||
|
handleHtml(container: HTMLElement, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions,
|
||||||
|
viewContainerRef: ViewContainerRef, siteId?: string): void | Promise<void> {
|
||||||
|
|
||||||
|
const placeholders = <HTMLElement[]> Array.from(container.querySelectorAll('div.core-h5p-tmp-placeholder'));
|
||||||
|
|
||||||
|
placeholders.forEach((placeholder) => {
|
||||||
|
const url = placeholder.getAttribute('data-player-src');
|
||||||
|
|
||||||
|
// Create the component to display the player.
|
||||||
|
const factory = this.factoryResolver.resolveComponentFactory(CoreH5PPlayerComponent),
|
||||||
|
componentRef = viewContainerRef.createComponent(factory);
|
||||||
|
|
||||||
|
componentRef.instance.src = url;
|
||||||
|
|
||||||
|
// Move the component to its right position.
|
||||||
|
placeholder.parentElement.replaceChild(componentRef.instance.elementRef.nativeElement, placeholder);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ import { AddonFilterActivityNamesModule } from './activitynames/activitynames.mo
|
||||||
import { AddonFilterAlgebraModule } from './algebra/algebra.module';
|
import { AddonFilterAlgebraModule } from './algebra/algebra.module';
|
||||||
import { AddonFilterCensorModule } from './censor/censor.module';
|
import { AddonFilterCensorModule } from './censor/censor.module';
|
||||||
import { AddonFilterDataModule } from './data/data.module';
|
import { AddonFilterDataModule } from './data/data.module';
|
||||||
|
import { AddonFilterDisplayH5PModule } from './displayh5p/displayh5p.module';
|
||||||
import { AddonFilterEmailProtectModule } from './emailprotect/emailprotect.module';
|
import { AddonFilterEmailProtectModule } from './emailprotect/emailprotect.module';
|
||||||
import { AddonFilterEmoticonModule } from './emoticon/emoticon.module';
|
import { AddonFilterEmoticonModule } from './emoticon/emoticon.module';
|
||||||
import { AddonFilterGlossaryModule } from './glossary/glossary.module';
|
import { AddonFilterGlossaryModule } from './glossary/glossary.module';
|
||||||
|
@ -34,6 +35,7 @@ import { AddonFilterUrlToLinkModule } from './urltolink/urltolink.module';
|
||||||
AddonFilterAlgebraModule,
|
AddonFilterAlgebraModule,
|
||||||
AddonFilterCensorModule,
|
AddonFilterCensorModule,
|
||||||
AddonFilterDataModule,
|
AddonFilterDataModule,
|
||||||
|
AddonFilterDisplayH5PModule,
|
||||||
AddonFilterEmailProtectModule,
|
AddonFilterEmailProtectModule,
|
||||||
AddonFilterEmoticonModule,
|
AddonFilterEmoticonModule,
|
||||||
AddonFilterGlossaryModule,
|
AddonFilterGlossaryModule,
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// 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 { Injectable } from '@angular/core';
|
import { Injectable, ViewContainerRef } from '@angular/core';
|
||||||
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
||||||
import { CoreFilterFilter, CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
import { CoreFilterFilter, CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||||
import { CoreEventsProvider } from '@providers/events';
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
|
@ -161,11 +161,12 @@ export class AddonFilterMathJaxLoaderHandler extends CoreFilterDefaultHandler {
|
||||||
* @param container The HTML container to handle.
|
* @param container The HTML container to handle.
|
||||||
* @param filter The filter.
|
* @param filter The filter.
|
||||||
* @param options Options passed to the filters.
|
* @param options Options passed to the filters.
|
||||||
|
* @param viewContainerRef The ViewContainerRef where the container is.
|
||||||
* @param siteId Site ID. If not defined, current site.
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @return If async, promise resolved when done.
|
* @return If async, promise resolved when done.
|
||||||
*/
|
*/
|
||||||
handleHtml(container: HTMLElement, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string)
|
handleHtml(container: HTMLElement, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions,
|
||||||
: void | Promise<void> {
|
viewContainerRef: ViewContainerRef, siteId?: string): void | Promise<void> {
|
||||||
|
|
||||||
return this.waitForReady().then(() => {
|
return this.waitForReady().then(() => {
|
||||||
this.window.M.filter_mathjaxloader.typeset(container);
|
this.window.M.filter_mathjaxloader.typeset(container);
|
||||||
|
|
|
@ -27,6 +27,8 @@ export class AddonFilterMediaPluginHandler extends CoreFilterDefaultHandler {
|
||||||
name = 'AddonFilterMediaPluginHandler';
|
name = 'AddonFilterMediaPluginHandler';
|
||||||
filterName = 'mediaplugin';
|
filterName = 'mediaplugin';
|
||||||
|
|
||||||
|
protected template = document.createElement('template'); // A template element to convert HTML to element.
|
||||||
|
|
||||||
constructor(private textUtils: CoreTextUtilsProvider,
|
constructor(private textUtils: CoreTextUtilsProvider,
|
||||||
private urlUtils: CoreUrlUtilsProvider) {
|
private urlUtils: CoreUrlUtilsProvider) {
|
||||||
super();
|
super();
|
||||||
|
@ -44,16 +46,15 @@ export class AddonFilterMediaPluginHandler extends CoreFilterDefaultHandler {
|
||||||
filter(text: string, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string)
|
filter(text: string, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string)
|
||||||
: string | Promise<string> {
|
: string | Promise<string> {
|
||||||
|
|
||||||
const div = document.createElement('div');
|
this.template.innerHTML = text;
|
||||||
div.innerHTML = text;
|
|
||||||
|
|
||||||
const videos = Array.from(div.querySelectorAll('video'));
|
const videos = Array.from(this.template.content.querySelectorAll('video'));
|
||||||
|
|
||||||
videos.forEach((video) => {
|
videos.forEach((video) => {
|
||||||
this.treatVideoFilters(video);
|
this.treatVideoFilters(video);
|
||||||
});
|
});
|
||||||
|
|
||||||
return div.innerHTML;
|
return this.template.innerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -83,6 +83,7 @@ import { CoreBlockModule } from '@core/block/block.module';
|
||||||
import { CoreRatingModule } from '@core/rating/rating.module';
|
import { CoreRatingModule } from '@core/rating/rating.module';
|
||||||
import { CoreTagModule } from '@core/tag/tag.module';
|
import { CoreTagModule } from '@core/tag/tag.module';
|
||||||
import { CoreFilterModule } from '@core/filter/filter.module';
|
import { CoreFilterModule } from '@core/filter/filter.module';
|
||||||
|
import { CoreH5PModule } from '@core/h5p/h5p.module';
|
||||||
|
|
||||||
// Addon modules.
|
// Addon modules.
|
||||||
import { AddonBadgesModule } from '@addon/badges/badges.module';
|
import { AddonBadgesModule } from '@addon/badges/badges.module';
|
||||||
|
@ -230,6 +231,7 @@ export const WP_PROVIDER: any = null;
|
||||||
CorePushNotificationsModule,
|
CorePushNotificationsModule,
|
||||||
CoreTagModule,
|
CoreTagModule,
|
||||||
CoreFilterModule,
|
CoreFilterModule,
|
||||||
|
CoreH5PModule,
|
||||||
AddonBadgesModule,
|
AddonBadgesModule,
|
||||||
AddonBlogModule,
|
AddonBlogModule,
|
||||||
AddonCalendarModule,
|
AddonCalendarModule,
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 345 150" style="enable-background:new 0 0 345 150;" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<path d="M325.7,14.7C317.6,6.9,305.3,3,289,3h-43.5H234v31h-66l-5.4,22.2c4.5-2.1,10.9-4.2,15.3-5.3c4.4-1.1,8.8-0.9,13.1-0.9
|
||||||
|
c14.6,0,26.5,4.5,35.6,13.3c9.1,8.8,13.6,20,13.6,33.4c0,9.4-2.3,18.5-7,27.2s-11.3,15.4-19.9,20c-3.1,1.6-6.5,3.1-10.2,4.1h42.4
|
||||||
|
H259V95h25c18.2,0,31.7-4.2,40.6-12.5s13.3-19.9,13.3-34.6C337.9,33.6,333.8,22.5,325.7,14.7z M288.7,60.6c-3.5,3-9.6,4.4-18.3,4.4
|
||||||
|
H259V33h13.2c8.4,0,14.2,1.5,17.2,4.7c3.1,3.2,4.6,6.9,4.6,11.5C294,53.9,292.2,57.6,288.7,60.6z"/>
|
||||||
|
<path d="M176.5,76.3c-7.9,0-14.7,4.6-18,11.2L119,81.9L136.8,3h-23.6H101v62H51V3H7v145h44V95h50v53h12.2h42
|
||||||
|
c-6.7-2-12.5-4.6-17.2-8.1c-4.8-3.6-8.7-7.7-11.7-12.3c-3-4.6-5.3-9.7-7.3-16.5l39.6-5.7c3.3,6.6,10.1,11.1,17.9,11.1
|
||||||
|
c11.1,0,20.1-9,20.1-20.1S187.5,76.3,176.5,76.3z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -1550,6 +1550,7 @@
|
||||||
"core.group": "Group",
|
"core.group": "Group",
|
||||||
"core.groupsseparate": "Separate groups",
|
"core.groupsseparate": "Separate groups",
|
||||||
"core.groupsvisible": "Visible groups",
|
"core.groupsvisible": "Visible groups",
|
||||||
|
"core.h5p.play": "Play H5P",
|
||||||
"core.hasdatatosync": "This {{$a}} has offline data to be synchronised.",
|
"core.hasdatatosync": "This {{$a}} has offline data to be synchronised.",
|
||||||
"core.help": "Help",
|
"core.help": "Help",
|
||||||
"core.hide": "Hide",
|
"core.hide": "Hide",
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// 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 { Injectable } from '@angular/core';
|
import { Injectable, ViewContainerRef } from '@angular/core';
|
||||||
import { CoreFilterHandler } from './delegate';
|
import { CoreFilterHandler } from './delegate';
|
||||||
import { CoreFilterFilter, CoreFilterFormatTextOptions } from './filter';
|
import { CoreFilterFilter, CoreFilterFormatTextOptions } from './filter';
|
||||||
import { CoreSite } from '@classes/site';
|
import { CoreSite } from '@classes/site';
|
||||||
|
@ -50,11 +50,12 @@ export class CoreFilterDefaultHandler implements CoreFilterHandler {
|
||||||
* @param container The HTML container to handle.
|
* @param container The HTML container to handle.
|
||||||
* @param filter The filter.
|
* @param filter The filter.
|
||||||
* @param options Options passed to the filters.
|
* @param options Options passed to the filters.
|
||||||
|
* @param viewContainerRef The ViewContainerRef where the container is.
|
||||||
* @param siteId Site ID. If not defined, current site.
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @return If async, promise resolved when done.
|
* @return If async, promise resolved when done.
|
||||||
*/
|
*/
|
||||||
handleHtml(container: HTMLElement, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string)
|
handleHtml(container: HTMLElement, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions,
|
||||||
: void | Promise<void> {
|
viewContainerRef: ViewContainerRef, siteId?: string): void | Promise<void> {
|
||||||
// To be overridden.
|
// To be overridden.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// 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 { Injectable } from '@angular/core';
|
import { Injectable, ViewContainerRef } from '@angular/core';
|
||||||
import { CoreEventsProvider } from '@providers/events';
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
import { CoreLoggerProvider } from '@providers/logger';
|
import { CoreLoggerProvider } from '@providers/logger';
|
||||||
import { CoreSitesProvider } from '@providers/sites';
|
import { CoreSitesProvider } from '@providers/sites';
|
||||||
|
@ -48,11 +48,12 @@ export interface CoreFilterHandler extends CoreDelegateHandler {
|
||||||
* @param container The HTML container to handle.
|
* @param container The HTML container to handle.
|
||||||
* @param filter The filter.
|
* @param filter The filter.
|
||||||
* @param options Options passed to the filters.
|
* @param options Options passed to the filters.
|
||||||
|
* @param viewContainerRef The ViewContainerRef where the container is.
|
||||||
* @param siteId Site ID. If not defined, current site.
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @return If async, promise resolved when done.
|
* @return If async, promise resolved when done.
|
||||||
*/
|
*/
|
||||||
handleHtml?(container: HTMLElement, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string)
|
handleHtml?(container: HTMLElement, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions,
|
||||||
: void | Promise<void>;
|
viewContainerRef: ViewContainerRef, siteId?: string): void | Promise<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the filter should be applied in a certain site based on some filter options.
|
* Check if the filter should be applied in a certain site based on some filter options.
|
||||||
|
@ -156,13 +157,14 @@ export class CoreFilterDelegate extends CoreDelegate {
|
||||||
*
|
*
|
||||||
* @param container The HTML container to handle.
|
* @param container The HTML container to handle.
|
||||||
* @param filters Filters to apply.
|
* @param filters Filters to apply.
|
||||||
|
* @param viewContainerRef The ViewContainerRef where the container is.
|
||||||
* @param options Options passed to the filters.
|
* @param options Options passed to the filters.
|
||||||
* @param skipFilters Names of filters that shouldn't be applied.
|
* @param skipFilters Names of filters that shouldn't be applied.
|
||||||
* @param siteId Site ID. If not defined, current site.
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
handleHtml(container: HTMLElement, filters: CoreFilterFilter[], options?: any, skipFilters?: string[], siteId?: string)
|
handleHtml(container: HTMLElement, filters: CoreFilterFilter[], viewContainerRef?: ViewContainerRef, options?: any,
|
||||||
: Promise<any> {
|
skipFilters?: string[], siteId?: string): Promise<any> {
|
||||||
|
|
||||||
// Wait for filters to be initialized.
|
// Wait for filters to be initialized.
|
||||||
return this.handlersInitPromise.then(() => {
|
return this.handlersInitPromise.then(() => {
|
||||||
|
@ -182,7 +184,7 @@ export class CoreFilterDelegate extends CoreDelegate {
|
||||||
|
|
||||||
promise = promise.then(() => {
|
promise = promise.then(() => {
|
||||||
return Promise.resolve(this.executeFunctionOnEnabled(filter.filter, 'handleHtml',
|
return Promise.resolve(this.executeFunctionOnEnabled(filter.filter, 'handleHtml',
|
||||||
[container, filter, options, siteId])).catch((error) => {
|
[container, filter, options, viewContainerRef, siteId])).catch((error) => {
|
||||||
this.logger.error('Error handling HTML' + filter.filter, error);
|
this.logger.error('Error handling HTML' + filter.filter, error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
// (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 { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { IonicModule } from 'ionic-angular';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||||
|
import { CoreH5PPlayerComponent } from './h5p-player/h5p-player';
|
||||||
|
import { CoreComponentsModule } from '@components/components.module';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
CoreH5PPlayerComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
IonicModule,
|
||||||
|
CoreDirectivesModule,
|
||||||
|
TranslateModule.forChild(),
|
||||||
|
CoreComponentsModule
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
CoreH5PPlayerComponent
|
||||||
|
],
|
||||||
|
entryComponents: [
|
||||||
|
CoreH5PPlayerComponent
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class CoreH5PComponentsModule {}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<div *ngIf="!showPackage" class="core-h5p-placeholder">
|
||||||
|
<button *ngIf="!loading" class="core-h5p-placeholder-play-button" ion-button icon-only clear color="dark" (click)="play($event)">
|
||||||
|
<core-icon name="fa-play-circle"></core-icon>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<ion-spinner *ngIf="loading" class="core-h5p-placeholder-spinner"></ion-spinner>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<core-iframe *ngIf="showPackage" [src]="src"></core-iframe>
|
|
@ -0,0 +1,24 @@
|
||||||
|
ion-app.app-root core-h5p-player {
|
||||||
|
.core-h5p-placeholder {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 230px;
|
||||||
|
background: url('../assets/img/icons/h5p.svg') center top 25px / 100px auto no-repeat $core-h5p-placeholder-bg-color;
|
||||||
|
|
||||||
|
.core-h5p-placeholder-play-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
font-size: 30px;
|
||||||
|
min-height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.core-h5p-placeholder-download-container {
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
font-size: 1.8em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
// (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 { Component, Input, ElementRef } from '@angular/core';
|
||||||
|
import { CoreSitesProvider } from '@providers/sites';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component to render an H5P package.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'core-h5p-player',
|
||||||
|
templateUrl: 'core-h5p-player.html'
|
||||||
|
})
|
||||||
|
export class CoreH5PPlayerComponent {
|
||||||
|
@Input() src: string; // The URL of the player to display the H5P package.
|
||||||
|
|
||||||
|
showPackage = false;
|
||||||
|
loading = false;
|
||||||
|
status: string;
|
||||||
|
canDownload: boolean;
|
||||||
|
calculating = true;
|
||||||
|
|
||||||
|
constructor(public elementRef: ElementRef,
|
||||||
|
protected sitesProvider: CoreSitesProvider) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Play the H5P.
|
||||||
|
*
|
||||||
|
* @param e Event.
|
||||||
|
*/
|
||||||
|
play(e: MouseEvent): void {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
|
// Get auto-login URL so the user is automatically authenticated.
|
||||||
|
this.sitesProvider.getCurrentSite().getAutoLoginUrl(this.src, false).then((url) => {
|
||||||
|
this.src = url;
|
||||||
|
this.loading = false;
|
||||||
|
this.showPackage = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
// (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 { NgModule } from '@angular/core';
|
||||||
|
import { CoreH5PComponentsModule } from './components/components.module';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [],
|
||||||
|
imports: [
|
||||||
|
CoreH5PComponentsModule
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
],
|
||||||
|
exports: []
|
||||||
|
})
|
||||||
|
export class CoreH5PModule { }
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"play": "Play H5P"
|
||||||
|
}
|
|
@ -12,7 +12,9 @@
|
||||||
// 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, Optional } from '@angular/core';
|
import {
|
||||||
|
Directive, ElementRef, Input, Output, EventEmitter, OnChanges, SimpleChange, Optional, ViewContainerRef
|
||||||
|
} from '@angular/core';
|
||||||
import { Platform, NavController, Content } 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';
|
||||||
|
@ -90,7 +92,8 @@ export class CoreFormatTextDirective implements OnChanges {
|
||||||
private eventsProvider: CoreEventsProvider,
|
private eventsProvider: CoreEventsProvider,
|
||||||
private filterProvider: CoreFilterProvider,
|
private filterProvider: CoreFilterProvider,
|
||||||
private filterHelper: CoreFilterHelperProvider,
|
private filterHelper: CoreFilterHelperProvider,
|
||||||
private filterDelegate: CoreFilterDelegate) {
|
private filterDelegate: CoreFilterDelegate,
|
||||||
|
private viewContainerRef: ViewContainerRef) {
|
||||||
|
|
||||||
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.
|
||||||
|
@ -371,7 +374,8 @@ export class CoreFormatTextDirective implements OnChanges {
|
||||||
|
|
||||||
if (result.options.filter) {
|
if (result.options.filter) {
|
||||||
// Let filters hnadle HTML. We do it here because we don't want them to block the render of the text.
|
// Let filters hnadle HTML. We do it here because we don't want them to block the render of the text.
|
||||||
this.filterDelegate.handleHtml(this.element, result.filters, result.options, [], result.siteId);
|
this.filterDelegate.handleHtml(this.element, result.filters, this.viewContainerRef, result.options, [],
|
||||||
|
result.siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.element.classList.remove('core-disable-media-adapt');
|
this.element.classList.remove('core-disable-media-adapt');
|
||||||
|
|
|
@ -514,10 +514,9 @@ export class CoreTextUtilsProvider {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const div = document.createElement('div');
|
this.template.innerHTML = content;
|
||||||
div.innerHTML = content;
|
|
||||||
|
|
||||||
return div.textContent === '' && div.querySelector('img, object, hr') === null;
|
return this.template.textContent === '' && this.template.content.querySelector('img, object, hr') === null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -369,6 +369,9 @@ $core-question-state-incorrect-color: $red-light !default;
|
||||||
$core-dd-question-selected-shadow: 2px 2px 4px $gray-dark !default;
|
$core-dd-question-selected-shadow: 2px 2px 4px $gray-dark !default;
|
||||||
$core-dd-question-colors: $white, $blue-light, #DCDCDC, #D8BFD8, #87CEFA, #DAA520, #FFD700, #F0E68C !default;
|
$core-dd-question-colors: $white, $blue-light, #DCDCDC, #D8BFD8, #87CEFA, #DAA520, #FFD700, #F0E68C !default;
|
||||||
|
|
||||||
|
// H5P variables.
|
||||||
|
$core-h5p-placeholder-bg-color: $gray-dark !default;
|
||||||
|
|
||||||
// Mixins
|
// Mixins
|
||||||
// -------------------------
|
// -------------------------
|
||||||
@mixin core-transition($where: all, $time: 500ms) {
|
@mixin core-transition($where: all, $time: 500ms) {
|
||||||
|
|
Loading…
Reference in New Issue