MOBILE-4616 chore: Isolate convertHTMLToHTMLElement
parent
90ec21333b
commit
323ccc8c76
|
@ -20,6 +20,7 @@ import { makeSingleton } from '@singletons';
|
||||||
import { CoreH5PPlayerComponent } from '@features/h5p/components/h5p-player/h5p-player';
|
import { CoreH5PPlayerComponent } from '@features/h5p/components/h5p-player/h5p-player';
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreH5PHelper } from '@features/h5p/classes/helper';
|
import { CoreH5PHelper } from '@features/h5p/classes/helper';
|
||||||
|
import { CoreTemplateElement } from '@/core/utils/create-html-element';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler to support the Display H5P filter.
|
* Handler to support the Display H5P filter.
|
||||||
|
@ -30,17 +31,15 @@ export class AddonFilterDisplayH5PHandlerService extends CoreFilterDefaultHandle
|
||||||
name = 'AddonFilterDisplayH5PHandler';
|
name = 'AddonFilterDisplayH5PHandler';
|
||||||
filterName = 'displayh5p';
|
filterName = 'displayh5p';
|
||||||
|
|
||||||
protected template = document.createElement('template'); // A template element to convert HTML to element.
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
filter(
|
filter(
|
||||||
text: string,
|
text: string,
|
||||||
): string | Promise<string> {
|
): string | Promise<string> {
|
||||||
this.template.innerHTML = text;
|
CoreTemplateElement.innerHTML = text;
|
||||||
|
|
||||||
const h5pIframes = <HTMLIFrameElement[]> Array.from(this.template.content.querySelectorAll('iframe.h5p-iframe'));
|
const h5pIframes = <HTMLIFrameElement[]> Array.from(CoreTemplateElement.content.querySelectorAll('iframe.h5p-iframe'));
|
||||||
|
|
||||||
// Replace all iframes with an empty div that will be treated in handleHtml.
|
// Replace all iframes with an empty div that will be treated in handleHtml.
|
||||||
h5pIframes.forEach((iframe) => {
|
h5pIframes.forEach((iframe) => {
|
||||||
|
@ -53,7 +52,9 @@ export class AddonFilterDisplayH5PHandlerService extends CoreFilterDefaultHandle
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle H5P iframes embedded using the embed HTML code.
|
// Handle H5P iframes embedded using the embed HTML code.
|
||||||
const embeddedH5PIframes = <HTMLIFrameElement[]> Array.from(this.template.content.querySelectorAll('iframe.h5p-player'));
|
const embeddedH5PIframes = <HTMLIFrameElement[]> Array.from(
|
||||||
|
CoreTemplateElement.content.querySelectorAll('iframe.h5p-player'),
|
||||||
|
);
|
||||||
|
|
||||||
embeddedH5PIframes.forEach((iframe) => {
|
embeddedH5PIframes.forEach((iframe) => {
|
||||||
// Add the preventredirect param to allow authenticating if auto-login fails.
|
// Add the preventredirect param to allow authenticating if auto-login fails.
|
||||||
|
@ -70,7 +71,7 @@ export class AddonFilterDisplayH5PHandlerService extends CoreFilterDefaultHandle
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.template.innerHTML;
|
return CoreTemplateElement.innerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,6 +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 { CoreTemplateElement } from '@/core/utils/create-html-element';
|
||||||
import { AddonFilterMediaPluginVideoJS } from '@addons/filter/mediaplugin/services/videojs';
|
import { AddonFilterMediaPluginVideoJS } from '@addons/filter/mediaplugin/services/videojs';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@ -28,21 +29,19 @@ export class AddonFilterMediaPluginHandlerService extends CoreFilterDefaultHandl
|
||||||
name = 'AddonFilterMediaPluginHandler';
|
name = 'AddonFilterMediaPluginHandler';
|
||||||
filterName = 'mediaplugin';
|
filterName = 'mediaplugin';
|
||||||
|
|
||||||
protected template = document.createElement('template'); // A template element to convert HTML to element.
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
filter(text: string): string | Promise<string> {
|
filter(text: string): string | Promise<string> {
|
||||||
this.template.innerHTML = text;
|
CoreTemplateElement.innerHTML = text;
|
||||||
|
|
||||||
const videos = Array.from(this.template.content.querySelectorAll('video'));
|
const videos = Array.from(CoreTemplateElement.content.querySelectorAll('video'));
|
||||||
|
|
||||||
videos.forEach((video) => {
|
videos.forEach((video) => {
|
||||||
AddonFilterMediaPluginVideoJS.treatYoutubeVideos(video);
|
AddonFilterMediaPluginVideoJS.treatYoutubeVideos(video);
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.template.innerHTML;
|
return CoreTemplateElement.innerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,6 +33,7 @@ import {
|
||||||
} from '../../services/bigbluebuttonbn';
|
} from '../../services/bigbluebuttonbn';
|
||||||
import { ADDON_MOD_BBB_COMPONENT } from '../../constants';
|
import { ADDON_MOD_BBB_COMPONENT } from '../../constants';
|
||||||
import { CoreLoadings } from '@services/loadings';
|
import { CoreLoadings } from '@services/loadings';
|
||||||
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that displays a Big Blue Button activity.
|
* Component that displays a Big Blue Button activity.
|
||||||
|
@ -147,7 +148,7 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
|
||||||
|
|
||||||
this.recordings = recordingsTable.parsedData.map(recordingData => {
|
this.recordings = recordingsTable.parsedData.map(recordingData => {
|
||||||
const details: RecordingDetail[] = [];
|
const details: RecordingDetail[] = [];
|
||||||
const playbacksEl = CoreDomUtils.convertToElement(String(recordingData.playback));
|
const playbacksEl = convertHTMLToHTMLElement(String(recordingData.playback));
|
||||||
const playbacks: RecordingPlayback[] = Array.from(playbacksEl.querySelectorAll('a')).map(playbackAnchor => ({
|
const playbacks: RecordingPlayback[] = Array.from(playbacksEl.querySelectorAll('a')).map(playbackAnchor => ({
|
||||||
name: playbackAnchor.textContent ?? '',
|
name: playbackAnchor.textContent ?? '',
|
||||||
url: playbackAnchor.href,
|
url: playbackAnchor.href,
|
||||||
|
@ -164,7 +165,7 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
|
||||||
value = CoreTimeUtils.userDate(Number(value), 'core.strftimedaydate');
|
value = CoreTimeUtils.userDate(Number(value), 'core.strftimedaydate');
|
||||||
} else if (columnData.allowHTML && typeof value === 'string') {
|
} else if (columnData.allowHTML && typeof value === 'string') {
|
||||||
// If the HTML is empty, don't display it.
|
// If the HTML is empty, don't display it.
|
||||||
const valueElement = CoreDomUtils.convertToElement(value);
|
const valueElement = convertHTMLToHTMLElement(value);
|
||||||
if (!valueElement.querySelector('img') && (valueElement.textContent ?? '').trim() === '') {
|
if (!valueElement.querySelector('img') && (valueElement.textContent ?? '').trim() === '') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import { CoreModuleHandlerBase } from '@features/course/classes/module-base-hand
|
||||||
import { CoreCourseModuleData } from '@features/course/services/course-helper';
|
import { CoreCourseModuleData } from '@features/course/services/course-helper';
|
||||||
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate';
|
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { ADDON_MOD_FOLDER_PAGE_NAME } from '../../constants';
|
import { ADDON_MOD_FOLDER_PAGE_NAME } from '../../constants';
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ export class AddonModFolderModuleHandlerService extends CoreModuleHandlerBase im
|
||||||
|
|
||||||
if (module.description) {
|
if (module.description) {
|
||||||
// Module description can contain the folder contents if it's inline, remove it.
|
// Module description can contain the folder contents if it's inline, remove it.
|
||||||
const descriptionElement = CoreDomUtils.convertToElement(module.description);
|
const descriptionElement = convertHTMLToHTMLElement(module.description);
|
||||||
|
|
||||||
Array.from(descriptionElement.querySelectorAll('.foldertree, .folderbuttons, .tertiary-navigation'))
|
Array.from(descriptionElement.querySelectorAll('.foldertree, .folderbuttons, .tertiary-navigation'))
|
||||||
.forEach(element => element.remove());
|
.forEach(element => element.remove());
|
||||||
|
|
|
@ -28,6 +28,7 @@ import {
|
||||||
import { CoreTime } from '@singletons/time';
|
import { CoreTime } from '@singletons/time';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { AddonModLessonPageSubtype } from '../constants';
|
import { AddonModLessonPageSubtype } from '../constants';
|
||||||
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper service that provides some features for quiz.
|
* Helper service that provides some features for quiz.
|
||||||
|
@ -46,7 +47,7 @@ export class AddonModLessonHelperProvider {
|
||||||
* @returns Formatted data.
|
* @returns Formatted data.
|
||||||
*/
|
*/
|
||||||
formatActivityLink(activityLink: string): AddonModLessonActivityLink {
|
formatActivityLink(activityLink: string): AddonModLessonActivityLink {
|
||||||
const element = CoreDomUtils.convertToElement(activityLink);
|
const element = convertHTMLToHTMLElement(activityLink);
|
||||||
const anchor = element.querySelector('a');
|
const anchor = element.querySelector('a');
|
||||||
|
|
||||||
if (!anchor) {
|
if (!anchor) {
|
||||||
|
@ -76,7 +77,7 @@ export class AddonModLessonHelperProvider {
|
||||||
buttonText: '',
|
buttonText: '',
|
||||||
content: '',
|
content: '',
|
||||||
};
|
};
|
||||||
const element = CoreDomUtils.convertToElement(html);
|
const element = convertHTMLToHTMLElement(html);
|
||||||
|
|
||||||
// Search the input button.
|
// Search the input button.
|
||||||
const button = <HTMLInputElement> element.querySelector('input[type="button"]');
|
const button = <HTMLInputElement> element.querySelector('input[type="button"]');
|
||||||
|
@ -100,7 +101,7 @@ export class AddonModLessonHelperProvider {
|
||||||
*/
|
*/
|
||||||
getPageButtonsFromHtml(html: string): AddonModLessonPageButton[] {
|
getPageButtonsFromHtml(html: string): AddonModLessonPageButton[] {
|
||||||
const buttons: AddonModLessonPageButton[] = [];
|
const buttons: AddonModLessonPageButton[] = [];
|
||||||
const element = CoreDomUtils.convertToElement(html);
|
const element = convertHTMLToHTMLElement(html);
|
||||||
|
|
||||||
// Get the container of the buttons if it exists.
|
// Get the container of the buttons if it exists.
|
||||||
let buttonsContainer = element.querySelector('.branchbuttoncontainer');
|
let buttonsContainer = element.querySelector('.branchbuttoncontainer');
|
||||||
|
@ -152,7 +153,7 @@ export class AddonModLessonHelperProvider {
|
||||||
*/
|
*/
|
||||||
getPageContentsFromPageData(data: AddonModLessonGetPageDataWSResponse): string {
|
getPageContentsFromPageData(data: AddonModLessonGetPageDataWSResponse): string {
|
||||||
// Search the page contents inside the whole page HTML. Use data.pagecontent because it's filtered.
|
// Search the page contents inside the whole page HTML. Use data.pagecontent because it's filtered.
|
||||||
const element = CoreDomUtils.convertToElement(data.pagecontent || '');
|
const element = convertHTMLToHTMLElement(data.pagecontent || '');
|
||||||
const contents = element.querySelector('.contents');
|
const contents = element.querySelector('.contents');
|
||||||
|
|
||||||
if (contents) {
|
if (contents) {
|
||||||
|
@ -178,7 +179,7 @@ export class AddonModLessonHelperProvider {
|
||||||
* @returns Question data.
|
* @returns Question data.
|
||||||
*/
|
*/
|
||||||
getQuestionFromPageData(questionForm: FormGroup, pageData: AddonModLessonGetPageDataWSResponse): AddonModLessonQuestion {
|
getQuestionFromPageData(questionForm: FormGroup, pageData: AddonModLessonGetPageDataWSResponse): AddonModLessonQuestion {
|
||||||
const element = CoreDomUtils.convertToElement(pageData.pagecontent || '');
|
const element = convertHTMLToHTMLElement(pageData.pagecontent || '');
|
||||||
|
|
||||||
// Get the container of the question answers if it exists.
|
// Get the container of the question answers if it exists.
|
||||||
const fieldContainer = <HTMLElement> element.querySelector('.fcontainer');
|
const fieldContainer = <HTMLElement> element.querySelector('.fcontainer');
|
||||||
|
@ -463,7 +464,7 @@ export class AddonModLessonHelperProvider {
|
||||||
* @returns Object with the data to render the answer. If the answer doesn't require any parsing, return a string with the HTML.
|
* @returns Object with the data to render the answer. If the answer doesn't require any parsing, return a string with the HTML.
|
||||||
*/
|
*/
|
||||||
getQuestionPageAnswerDataFromHtml(html: string): AddonModLessonAnswerData {
|
getQuestionPageAnswerDataFromHtml(html: string): AddonModLessonAnswerData {
|
||||||
const element = CoreDomUtils.convertToElement(html);
|
const element = convertHTMLToHTMLElement(html);
|
||||||
|
|
||||||
// Check if it has a checkbox.
|
// Check if it has a checkbox.
|
||||||
let input = element.querySelector<HTMLInputElement>('input[type="checkbox"][name*="answer"]');
|
let input = element.querySelector<HTMLInputElement>('input[type="checkbox"][name*="answer"]');
|
||||||
|
@ -588,7 +589,7 @@ export class AddonModLessonHelperProvider {
|
||||||
* @returns Feedback without the question text.
|
* @returns Feedback without the question text.
|
||||||
*/
|
*/
|
||||||
removeQuestionFromFeedback(html: string): string {
|
removeQuestionFromFeedback(html: string): string {
|
||||||
const element = CoreDomUtils.convertToElement(html);
|
const element = convertHTMLToHTMLElement(html);
|
||||||
|
|
||||||
// Remove the question text.
|
// Remove the question text.
|
||||||
CoreDomUtils.removeElement(element, '.generalbox:not(.feedback):not(.correctanswer)');
|
CoreDomUtils.removeElement(element, '.generalbox:not(.feedback):not(.correctanswer)');
|
||||||
|
|
|
@ -18,7 +18,7 @@ import { CoreSite } from '@classes/sites/site';
|
||||||
import { CoreCourseCommonModWSOptions } from '@features/course/services/course';
|
import { CoreCourseCommonModWSOptions } from '@features/course/services/course';
|
||||||
import { CoreCourseLogHelper } from '@features/course/services/log-helper';
|
import { CoreCourseLogHelper } from '@features/course/services/log-helper';
|
||||||
import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
|
import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
import { CoreText } from '@singletons/text';
|
import { CoreText } from '@singletons/text';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
|
import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
|
||||||
|
@ -164,7 +164,7 @@ export class AddonModLessonProvider {
|
||||||
if (page.answerdata && !this.answerPageIsQuestion(page)) {
|
if (page.answerdata && !this.answerPageIsQuestion(page)) {
|
||||||
// It isn't a question page, but it can be an end of branch, etc. Check if the first answer has a button.
|
// It isn't a question page, but it can be an end of branch, etc. Check if the first answer has a button.
|
||||||
if (page.answerdata.answers && page.answerdata.answers[0]) {
|
if (page.answerdata.answers && page.answerdata.answers[0]) {
|
||||||
const element = CoreDomUtils.convertToElement(page.answerdata.answers[0][0]);
|
const element = convertHTMLToHTMLElement(page.answerdata.answers[0][0]);
|
||||||
|
|
||||||
return !!element.querySelector('input[type="button"]');
|
return !!element.querySelector('input[type="button"]');
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ import { CoreGroups } from '@services/groups';
|
||||||
import { CoreTimeUtils } from '@services/utils/time';
|
import { CoreTimeUtils } from '@services/utils/time';
|
||||||
import { CoreModals } from '@services/modals';
|
import { CoreModals } from '@services/modals';
|
||||||
import { CoreLoadings } from '@services/loadings';
|
import { CoreLoadings } from '@services/loadings';
|
||||||
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper service that provides some features for quiz.
|
* Helper service that provides some features for quiz.
|
||||||
|
@ -301,7 +302,7 @@ export class AddonModQuizHelperProvider {
|
||||||
* @returns Question's mark.
|
* @returns Question's mark.
|
||||||
*/
|
*/
|
||||||
getQuestionMarkFromHtml(html: string): string | undefined {
|
getQuestionMarkFromHtml(html: string): string | undefined {
|
||||||
const element = CoreDomUtils.convertToElement(html);
|
const element = convertHTMLToHTMLElement(html);
|
||||||
|
|
||||||
return CoreDomUtils.getContentsOfElement(element, '.grade');
|
return CoreDomUtils.getContentsOfElement(element, '.grade');
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ import {
|
||||||
} from '@features/question/services/question';
|
} from '@features/question/services/question';
|
||||||
import { CoreQuestionDelegate } from '@features/question/services/question-delegate';
|
import { CoreQuestionDelegate } from '@features/question/services/question-delegate';
|
||||||
import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
|
import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
import { CoreTimeUtils } from '@services/utils/time';
|
import { CoreTimeUtils } from '@services/utils/time';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreStatusWithWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
|
import { CoreStatusWithWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
|
||||||
|
@ -1588,7 +1588,7 @@ export class AddonModQuizProvider {
|
||||||
* @returns Whether it's blocked.
|
* @returns Whether it's blocked.
|
||||||
*/
|
*/
|
||||||
isQuestionBlocked(question: CoreQuestionQuestionParsed): boolean {
|
isQuestionBlocked(question: CoreQuestionQuestionParsed): boolean {
|
||||||
const element = CoreDomUtils.convertToElement(question.html);
|
const element = convertHTMLToHTMLElement(question.html);
|
||||||
|
|
||||||
return !!element.querySelector('.mod_quiz-blocked_question_warning');
|
return !!element.querySelector('.mod_quiz-blocked_question_warning');
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { Injectable, Type } from '@angular/core';
|
||||||
|
|
||||||
import { CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/question/services/question';
|
import { CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/question/services/question';
|
||||||
import { CoreQuestionHandler } from '@features/question/services/question-delegate';
|
import { CoreQuestionHandler } from '@features/question/services/question-delegate';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { AddonQtypeCalculatedComponent } from '../../component/calculated';
|
import { AddonQtypeCalculatedComponent } from '../../component/calculated';
|
||||||
|
@ -53,7 +53,7 @@ export class AddonQtypeCalculatedHandlerService implements CoreQuestionHandler {
|
||||||
*/
|
*/
|
||||||
hasSeparateUnitField(question: CoreQuestionQuestionParsed): boolean {
|
hasSeparateUnitField(question: CoreQuestionQuestionParsed): boolean {
|
||||||
if (!question.parsedSettings) {
|
if (!question.parsedSettings) {
|
||||||
const element = CoreDomUtils.convertToElement(question.html);
|
const element = convertHTMLToHTMLElement(question.html);
|
||||||
|
|
||||||
return !!(element.querySelector('select[name*=unit]') || element.querySelector('input[type="radio"]'));
|
return !!(element.querySelector('select[name*=unit]') || element.querySelector('input[type="radio"]'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { CoreQuestionHandler } from '@features/question/services/question-delega
|
||||||
import { CoreQuestionHelper } from '@features/question/services/question-helper';
|
import { CoreQuestionHelper } from '@features/question/services/question-helper';
|
||||||
import { CoreFileSession } from '@services/file-session';
|
import { CoreFileSession } from '@services/file-session';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
import { CoreText } from '@singletons/text';
|
import { CoreText } from '@singletons/text';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreWSFile } from '@services/ws';
|
import { CoreWSFile } from '@services/ws';
|
||||||
|
@ -90,7 +90,7 @@ export class AddonQtypeEssayHandlerService implements CoreQuestionHandler {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const element = CoreDomUtils.convertToElement(question.html);
|
const element = convertHTMLToHTMLElement(question.html);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
text: !!element.querySelector('textarea[name*=_answer]'),
|
text: !!element.querySelector('textarea[name*=_answer]'),
|
||||||
|
@ -116,7 +116,7 @@ export class AddonQtypeEssayHandlerService implements CoreQuestionHandler {
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
getPreventSubmitMessage(question: CoreQuestionQuestionParsed): string | undefined {
|
getPreventSubmitMessage(question: CoreQuestionQuestionParsed): string | undefined {
|
||||||
const element = CoreDomUtils.convertToElement(question.html);
|
const element = convertHTMLToHTMLElement(question.html);
|
||||||
const uploadFilesSupported = question.responsefileareas !== undefined;
|
const uploadFilesSupported = question.responsefileareas !== undefined;
|
||||||
|
|
||||||
if (!uploadFilesSupported && element.querySelector('div[id*=filemanager]')) {
|
if (!uploadFilesSupported && element.querySelector('div[id*=filemanager]')) {
|
||||||
|
@ -293,7 +293,7 @@ export class AddonQtypeEssayHandlerService implements CoreQuestionHandler {
|
||||||
siteId?: string,
|
siteId?: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
|
||||||
const element = CoreDomUtils.convertToElement(question.html);
|
const element = convertHTMLToHTMLElement(question.html);
|
||||||
const attachmentsInput = <HTMLInputElement> element.querySelector('.attachments input[name*=_attachments]');
|
const attachmentsInput = <HTMLInputElement> element.querySelector('.attachments input[name*=_attachments]');
|
||||||
|
|
||||||
// Search the textarea to get its name.
|
// Search the textarea to get its name.
|
||||||
|
@ -375,7 +375,7 @@ export class AddonQtypeEssayHandlerService implements CoreQuestionHandler {
|
||||||
siteId?: string,
|
siteId?: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
|
||||||
const element = CoreDomUtils.convertToElement(question.html);
|
const element = convertHTMLToHTMLElement(question.html);
|
||||||
const attachmentsInput = <HTMLInputElement> element.querySelector('.attachments input[name*=_attachments]');
|
const attachmentsInput = <HTMLInputElement> element.querySelector('.attachments input[name*=_attachments]');
|
||||||
|
|
||||||
if (attachmentsInput) {
|
if (attachmentsInput) {
|
||||||
|
@ -454,7 +454,7 @@ export class AddonQtypeEssayHandlerService implements CoreQuestionHandler {
|
||||||
isPlainText = question.parsedSettings.responseformat == 'monospaced' ||
|
isPlainText = question.parsedSettings.responseformat == 'monospaced' ||
|
||||||
question.parsedSettings.responseformat == 'plain';
|
question.parsedSettings.responseformat == 'plain';
|
||||||
} else {
|
} else {
|
||||||
const questionEl = CoreDomUtils.convertToElement(question.html);
|
const questionEl = convertHTMLToHTMLElement(question.html);
|
||||||
isPlainText = !!questionEl.querySelector('.qtype_essay_monospaced') || !!questionEl.querySelector('.qtype_essay_plain');
|
isPlainText = !!questionEl.querySelector('.qtype_essay_monospaced') || !!questionEl.querySelector('.qtype_essay_plain');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
import { Component, AfterViewInit, Input, ContentChild, ViewEncapsulation } from '@angular/core';
|
import { Component, AfterViewInit, Input, ContentChild, ViewEncapsulation } from '@angular/core';
|
||||||
import { IonInput } from '@ionic/angular';
|
import { IonInput } from '@ionic/angular';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
|
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
|
@ -84,7 +84,7 @@ export class CoreShowPasswordComponent implements AfterViewInit {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const toggle = CoreDomUtils.convertToElement('<ion-input-password-toggle slot="end" />');
|
const toggle = convertHTMLToHTMLElement('<ion-input-password-toggle slot="end" />');
|
||||||
input.parentElement?.appendChild(toggle.children[0]);
|
input.parentElement?.appendChild(toggle.children[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
import { Injectable, Type } from '@angular/core';
|
import { Injectable, Type } from '@angular/core';
|
||||||
|
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
import { CoreTagAreaHandler } from '@features/tag/services/tag-area-delegate';
|
import { CoreTagAreaHandler } from '@features/tag/services/tag-area-delegate';
|
||||||
import { CoreCourseTagAreaComponent } from '../../components/tag-area/tag-area';
|
import { CoreCourseTagAreaComponent } from '../../components/tag-area/tag-area';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
|
@ -45,7 +45,7 @@ export class CoreCourseTagAreaHandlerService implements CoreTagAreaHandler {
|
||||||
*/
|
*/
|
||||||
parseContent(content: string): CoreCouseTagItems[] {
|
parseContent(content: string): CoreCouseTagItems[] {
|
||||||
const items: CoreCouseTagItems[] = [];
|
const items: CoreCouseTagItems[] = [];
|
||||||
const element = CoreDomUtils.convertToElement(content);
|
const element = convertHTMLToHTMLElement(content);
|
||||||
|
|
||||||
Array.from(element.querySelectorAll('div.coursebox')).forEach((coursebox) => {
|
Array.from(element.querySelectorAll('div.coursebox')).forEach((coursebox) => {
|
||||||
const courseId = parseInt(coursebox.getAttribute('data-courseid') || '', 10);
|
const courseId = parseInt(coursebox.getAttribute('data-courseid') || '', 10);
|
||||||
|
|
|
@ -44,6 +44,7 @@ import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||||
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
|
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
|
||||||
import { CoreCourseAccess } from '@features/course/services/course-options-delegate';
|
import { CoreCourseAccess } from '@features/course/services/course-options-delegate';
|
||||||
import { CoreLoadings } from '@services/loadings';
|
import { CoreLoadings } from '@services/loadings';
|
||||||
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
|
|
||||||
export const GRADES_PAGE_NAME = 'grades';
|
export const GRADES_PAGE_NAME = 'grades';
|
||||||
export const GRADES_PARTICIPANTS_PAGE_NAME = 'participant-grades';
|
export const GRADES_PARTICIPANTS_PAGE_NAME = 'participant-grades';
|
||||||
|
@ -573,7 +574,7 @@ export class CoreGradesHelperProvider {
|
||||||
const modname = module?.[1];
|
const modname = module?.[1];
|
||||||
|
|
||||||
if (modname !== undefined) {
|
if (modname !== undefined) {
|
||||||
const modicon = CoreDomUtils.convertToElement(text).querySelector('img')?.getAttribute('src') ?? undefined;
|
const modicon = convertHTMLToHTMLElement(text).querySelector('img')?.getAttribute('src') ?? undefined;
|
||||||
|
|
||||||
row.itemtype = 'mod';
|
row.itemtype = 'mod';
|
||||||
row.itemmodule = modname;
|
row.itemmodule = modname;
|
||||||
|
|
|
@ -25,6 +25,7 @@ import { CoreLogger } from '@singletons/logger';
|
||||||
import { CoreQuestionBehaviourButton, CoreQuestionHelper, CoreQuestionQuestion } from '../services/question-helper';
|
import { CoreQuestionBehaviourButton, CoreQuestionHelper, CoreQuestionQuestion } from '../services/question-helper';
|
||||||
import { ContextLevel } from '@/core/constants';
|
import { ContextLevel } from '@/core/constants';
|
||||||
import { toBoolean } from '@/core/transforms/boolean';
|
import { toBoolean } from '@/core/transforms/boolean';
|
||||||
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for components to render a question.
|
* Base class for components to render a question.
|
||||||
|
@ -87,7 +88,7 @@ export class CoreQuestionBaseComponent<T extends AddonModQuizQuestion = AddonMod
|
||||||
|
|
||||||
this.hostElement.classList.add('core-question-container');
|
this.hostElement.classList.add('core-question-container');
|
||||||
|
|
||||||
const questionElement = CoreDomUtils.convertToElement(this.question.html);
|
const questionElement = convertHTMLToHTMLElement(this.question.html);
|
||||||
|
|
||||||
// Extract question text.
|
// Extract question text.
|
||||||
this.question.text = CoreDomUtils.getContentsOfElement(questionElement, '.qtext');
|
this.question.text = CoreDomUtils.getContentsOfElement(questionElement, '.qtext');
|
||||||
|
@ -433,7 +434,7 @@ export class CoreQuestionBaseComponent<T extends AddonModQuizQuestion = AddonMod
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const element = CoreDomUtils.convertToElement(this.question.html);
|
const element = convertHTMLToHTMLElement(this.question.html);
|
||||||
|
|
||||||
// Get question content.
|
// Get question content.
|
||||||
const content = element.querySelector<HTMLElement>(contentSelector);
|
const content = element.querySelector<HTMLElement>(contentSelector);
|
||||||
|
|
|
@ -31,6 +31,7 @@ import { CoreUrl } from '@singletons/url';
|
||||||
import { ContextLevel } from '@/core/constants';
|
import { ContextLevel } from '@/core/constants';
|
||||||
import { CoreIonicColorNames } from '@singletons/colors';
|
import { CoreIonicColorNames } from '@singletons/colors';
|
||||||
import { CoreViewer } from '@features/viewer/services/viewer';
|
import { CoreViewer } from '@features/viewer/services/viewer';
|
||||||
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service with some common functions to handle questions.
|
* Service with some common functions to handle questions.
|
||||||
|
@ -131,7 +132,7 @@ export class CoreQuestionHelperProvider {
|
||||||
|
|
||||||
selector = selector || '.im-controls [type="submit"]';
|
selector = selector || '.im-controls [type="submit"]';
|
||||||
|
|
||||||
const element = CoreDomUtils.convertToElement(question.html);
|
const element = convertHTMLToHTMLElement(question.html);
|
||||||
|
|
||||||
// Search the buttons.
|
// Search the buttons.
|
||||||
const buttons = <HTMLInputElement[]> Array.from(element.querySelectorAll(selector));
|
const buttons = <HTMLInputElement[]> Array.from(element.querySelectorAll(selector));
|
||||||
|
@ -150,7 +151,7 @@ export class CoreQuestionHelperProvider {
|
||||||
* @returns Wether the certainty is found.
|
* @returns Wether the certainty is found.
|
||||||
*/
|
*/
|
||||||
extractQbehaviourCBM(question: CoreQuestionQuestion): boolean {
|
extractQbehaviourCBM(question: CoreQuestionQuestion): boolean {
|
||||||
const element = CoreDomUtils.convertToElement(question.html);
|
const element = convertHTMLToHTMLElement(question.html);
|
||||||
|
|
||||||
const labels = Array.from(element.querySelectorAll('.im-controls .certaintychoices label[for*="certainty"]'));
|
const labels = Array.from(element.querySelectorAll('.im-controls .certaintychoices label[for*="certainty"]'));
|
||||||
question.behaviourCertaintyOptions = [];
|
question.behaviourCertaintyOptions = [];
|
||||||
|
@ -217,7 +218,7 @@ export class CoreQuestionHelperProvider {
|
||||||
* @returns Whether the seen input is found.
|
* @returns Whether the seen input is found.
|
||||||
*/
|
*/
|
||||||
extractQbehaviourSeenInput(question: CoreQuestionQuestion): boolean {
|
extractQbehaviourSeenInput(question: CoreQuestionQuestion): boolean {
|
||||||
const element = CoreDomUtils.convertToElement(question.html);
|
const element = convertHTMLToHTMLElement(question.html);
|
||||||
|
|
||||||
// Search the "seen" input.
|
// Search the "seen" input.
|
||||||
const seenInput = <HTMLInputElement> element.querySelector('input[type="hidden"][name*=seen]');
|
const seenInput = <HTMLInputElement> element.querySelector('input[type="hidden"][name*=seen]');
|
||||||
|
@ -273,7 +274,7 @@ export class CoreQuestionHelperProvider {
|
||||||
* @param attrName Name of the attribute to store the HTML in.
|
* @param attrName Name of the attribute to store the HTML in.
|
||||||
*/
|
*/
|
||||||
protected extractQuestionLastElementNotInContent(question: CoreQuestionQuestion, selector: string, attrName: string): void {
|
protected extractQuestionLastElementNotInContent(question: CoreQuestionQuestion, selector: string, attrName: string): void {
|
||||||
const element = CoreDomUtils.convertToElement(question.html);
|
const element = convertHTMLToHTMLElement(question.html);
|
||||||
const matches = <HTMLElement[]> Array.from(element.querySelectorAll(selector));
|
const matches = <HTMLElement[]> Array.from(element.querySelectorAll(selector));
|
||||||
|
|
||||||
// Get the last element and check it's not in the question contents.
|
// Get the last element and check it's not in the question contents.
|
||||||
|
@ -358,7 +359,7 @@ export class CoreQuestionHelperProvider {
|
||||||
* @returns Object where the keys are the names.
|
* @returns Object where the keys are the names.
|
||||||
*/
|
*/
|
||||||
getAllInputNamesFromHtml(html: string): Record<string, boolean> {
|
getAllInputNamesFromHtml(html: string): Record<string, boolean> {
|
||||||
const element = CoreDomUtils.convertToElement('<form>' + html + '</form>');
|
const element = convertHTMLToHTMLElement('<form>' + html + '</form>');
|
||||||
const form = <HTMLFormElement> element.children[0];
|
const form = <HTMLFormElement> element.children[0];
|
||||||
const answers: Record<string, boolean> = {};
|
const answers: Record<string, boolean> = {};
|
||||||
|
|
||||||
|
@ -424,7 +425,7 @@ export class CoreQuestionHelperProvider {
|
||||||
* @returns Attachments.
|
* @returns Attachments.
|
||||||
*/
|
*/
|
||||||
getQuestionAttachmentsFromHtml(html: string): CoreWSFile[] {
|
getQuestionAttachmentsFromHtml(html: string): CoreWSFile[] {
|
||||||
const element = CoreDomUtils.convertToElement(html);
|
const element = convertHTMLToHTMLElement(html);
|
||||||
|
|
||||||
// Remove the filemanager (area to attach files to a question).
|
// Remove the filemanager (area to attach files to a question).
|
||||||
CoreDomUtils.removeElement(element, 'div[id*=filemanager]');
|
CoreDomUtils.removeElement(element, 'div[id*=filemanager]');
|
||||||
|
@ -461,7 +462,7 @@ export class CoreQuestionHelperProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search the input holding the sequencecheck.
|
// Search the input holding the sequencecheck.
|
||||||
const element = CoreDomUtils.convertToElement(html);
|
const element = convertHTMLToHTMLElement(html);
|
||||||
const input = <HTMLInputElement> element.querySelector('input[name*=sequencecheck]');
|
const input = <HTMLInputElement> element.querySelector('input[name*=sequencecheck]');
|
||||||
|
|
||||||
if (!input || input.name === undefined || input.value === undefined) {
|
if (!input || input.name === undefined || input.value === undefined) {
|
||||||
|
@ -531,7 +532,7 @@ export class CoreQuestionHelperProvider {
|
||||||
* @returns Validation error message if present.
|
* @returns Validation error message if present.
|
||||||
*/
|
*/
|
||||||
getValidationErrorFromHtml(html: string): string | undefined {
|
getValidationErrorFromHtml(html: string): string | undefined {
|
||||||
const element = CoreDomUtils.convertToElement(html);
|
const element = convertHTMLToHTMLElement(html);
|
||||||
|
|
||||||
return CoreDomUtils.getContentsOfElement(element, '.validationerror');
|
return CoreDomUtils.getContentsOfElement(element, '.validationerror');
|
||||||
}
|
}
|
||||||
|
@ -583,7 +584,7 @@ export class CoreQuestionHelperProvider {
|
||||||
* @param question Question.
|
* @param question Question.
|
||||||
*/
|
*/
|
||||||
loadLocalAnswersInHtml(question: CoreQuestionQuestion): void {
|
loadLocalAnswersInHtml(question: CoreQuestionQuestion): void {
|
||||||
const element = CoreDomUtils.convertToElement('<form>' + question.html + '</form>');
|
const element = convertHTMLToHTMLElement('<form>' + question.html + '</form>');
|
||||||
const form = <HTMLFormElement> element.children[0];
|
const form = <HTMLFormElement> element.children[0];
|
||||||
|
|
||||||
// Search all input elements.
|
// Search all input elements.
|
||||||
|
@ -758,7 +759,7 @@ export class CoreQuestionHelperProvider {
|
||||||
* @returns Whether the button is found.
|
* @returns Whether the button is found.
|
||||||
*/
|
*/
|
||||||
protected searchBehaviourButton(question: CoreQuestionQuestion, htmlProperty: string, selector: string): boolean {
|
protected searchBehaviourButton(question: CoreQuestionQuestion, htmlProperty: string, selector: string): boolean {
|
||||||
const element = CoreDomUtils.convertToElement(question[htmlProperty]);
|
const element = convertHTMLToHTMLElement(question[htmlProperty]);
|
||||||
|
|
||||||
const button = element.querySelector<HTMLElement>(selector);
|
const button = element.querySelector<HTMLElement>(selector);
|
||||||
if (!button) {
|
if (!button) {
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service with helper functions for tags.
|
* Service with helper functions for tags.
|
||||||
|
@ -30,7 +30,7 @@ export class CoreTagHelperProvider {
|
||||||
*/
|
*/
|
||||||
parseFeedContent(content: string): CoreTagFeedElement[] {
|
parseFeedContent(content: string): CoreTagFeedElement[] {
|
||||||
const items: CoreTagFeedElement[] = [];
|
const items: CoreTagFeedElement[] = [];
|
||||||
const element = CoreDomUtils.convertToElement(content);
|
const element = convertHTMLToHTMLElement(content);
|
||||||
|
|
||||||
Array.from(element.querySelectorAll('ul.tag_feed > li')).forEach((itemElement) => {
|
Array.from(element.querySelectorAll('ul.tag_feed > li')).forEach((itemElement) => {
|
||||||
const item: CoreTagFeedElement = { details: [] };
|
const item: CoreTagFeedElement = { details: [] };
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
import { Injectable, Type } from '@angular/core';
|
import { Injectable, Type } from '@angular/core';
|
||||||
|
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { convertHTMLToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
import { CoreTagAreaHandler } from '@features/tag/services/tag-area-delegate';
|
import { CoreTagAreaHandler } from '@features/tag/services/tag-area-delegate';
|
||||||
import { CoreUserTagAreaComponent } from '@features/user/components/tag-area/tag-area';
|
import { CoreUserTagAreaComponent } from '@features/user/components/tag-area/tag-area';
|
||||||
import { CoreTagFeedElement } from '@features/tag/services/tag-helper';
|
import { CoreTagFeedElement } from '@features/tag/services/tag-helper';
|
||||||
|
@ -47,7 +47,7 @@ export class CoreUserTagAreaHandlerService implements CoreTagAreaHandler {
|
||||||
*/
|
*/
|
||||||
parseContent(content: string): CoreUserTagFeedElement[] {
|
parseContent(content: string): CoreUserTagFeedElement[] {
|
||||||
const items: CoreUserTagFeedElement[] = [];
|
const items: CoreUserTagFeedElement[] = [];
|
||||||
const element = CoreDomUtils.convertToElement(content);
|
const element = convertHTMLToHTMLElement(content);
|
||||||
|
|
||||||
Array.from(element.querySelectorAll('div.user-box')).forEach((userbox: HTMLElement) => {
|
Array.from(element.querySelectorAll('div.user-box')).forEach((userbox: HTMLElement) => {
|
||||||
const avatarLink = userbox.querySelector('a:first-child');
|
const avatarLink = userbox.querySelector('a:first-child');
|
||||||
|
|
|
@ -58,6 +58,7 @@ import { asyncInstance, AsyncInstance } from '../utils/async-instance';
|
||||||
import { CorePath } from '@singletons/path';
|
import { CorePath } from '@singletons/path';
|
||||||
import { CorePromisedValue } from '@classes/promised-value';
|
import { CorePromisedValue } from '@classes/promised-value';
|
||||||
import { CoreAnalytics, CoreAnalyticsEventType } from './analytics';
|
import { CoreAnalytics, CoreAnalyticsEventType } from './analytics';
|
||||||
|
import { convertHTMLToHTMLElement } from '../utils/create-html-element';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Factory for handling downloading files and retrieve downloaded files.
|
* Factory for handling downloading files and retrieve downloaded files.
|
||||||
|
@ -1147,7 +1148,7 @@ export class CoreFilepoolProvider {
|
||||||
extractDownloadableFilesFromHtml(html: string): string[] {
|
extractDownloadableFilesFromHtml(html: string): string[] {
|
||||||
let urls: string[] = [];
|
let urls: string[] = [];
|
||||||
|
|
||||||
const element = CoreDomUtils.convertToElement(html);
|
const element = convertHTMLToHTMLElement(html);
|
||||||
const elements: AnchorOrMediaElement[] = Array.from(element.querySelectorAll('a, img, audio, video, source, track'));
|
const elements: AnchorOrMediaElement[] = Array.from(element.querySelectorAll('a, img, audio, video, source, track'));
|
||||||
|
|
||||||
for (let i = 0; i < elements.length; i++) {
|
for (let i = 0; i < elements.length; i++) {
|
||||||
|
|
|
@ -55,6 +55,7 @@ import { CorePopovers, OpenPopoverOptions } from '@services/popovers';
|
||||||
import { CoreViewer } from '@features/viewer/services/viewer';
|
import { CoreViewer } from '@features/viewer/services/viewer';
|
||||||
import { CoreLoadings } from '@services/loadings';
|
import { CoreLoadings } from '@services/loadings';
|
||||||
import { CoreErrorHelper, CoreErrorObject } from '@services/error-helper';
|
import { CoreErrorHelper, CoreErrorObject } from '@services/error-helper';
|
||||||
|
import { convertHTMLToHTMLElement, CoreTemplateElement } from '@/core/utils/create-html-element';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "Utils" service with helper functions for UI, DOM elements and HTML code.
|
* "Utils" service with helper functions for UI, DOM elements and HTML code.
|
||||||
|
@ -68,8 +69,6 @@ export class CoreDomUtilsProvider {
|
||||||
protected readonly INPUT_SUPPORT_KEYBOARD: string[] = ['date', 'datetime', 'datetime-local', 'email', 'month', 'number',
|
protected readonly INPUT_SUPPORT_KEYBOARD: string[] = ['date', 'datetime', 'datetime-local', 'email', 'month', 'number',
|
||||||
'password', 'search', 'tel', 'text', 'time', 'url', 'week'];
|
'password', 'search', 'tel', 'text', 'time', 'url', 'week'];
|
||||||
|
|
||||||
protected template: HTMLTemplateElement = document.createElement('template'); // A template element to convert HTML to element.
|
|
||||||
|
|
||||||
protected matchesFunctionName?: string; // Name of the "matches" function to use when simulating a closest call.
|
protected matchesFunctionName?: string; // Name of the "matches" function to use when simulating a closest call.
|
||||||
protected debugDisplay = false; // Whether to display debug messages. Store it in a variable to make it synchronous.
|
protected debugDisplay = false; // Whether to display debug messages. Store it in a variable to make it synchronous.
|
||||||
protected displayedAlerts: Record<string, HTMLIonAlertElement> = {}; // To prevent duplicated alerts.
|
protected displayedAlerts: Record<string, HTMLIonAlertElement> = {}; // To prevent duplicated alerts.
|
||||||
|
@ -196,12 +195,11 @@ export class CoreDomUtilsProvider {
|
||||||
*
|
*
|
||||||
* @param html Text to convert.
|
* @param html Text to convert.
|
||||||
* @returns Element.
|
* @returns Element.
|
||||||
|
*
|
||||||
|
* @deprecated since 4.5. Use convertToElement directly instead.
|
||||||
*/
|
*/
|
||||||
convertToElement(html: string): HTMLElement {
|
convertToElement(html: string): HTMLElement {
|
||||||
// Add a div to hold the content, that's the element that will be returned.
|
return convertHTMLToHTMLElement(html);
|
||||||
this.template.innerHTML = '<div>' + html + '</div>';
|
|
||||||
|
|
||||||
return <HTMLElement> this.template.content.children[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -263,7 +261,7 @@ export class CoreDomUtilsProvider {
|
||||||
* @returns Fixed HTML text.
|
* @returns Fixed HTML text.
|
||||||
*/
|
*/
|
||||||
fixHtml(html: string): string {
|
fixHtml(html: string): string {
|
||||||
this.template.innerHTML = html;
|
CoreTemplateElement.innerHTML = html;
|
||||||
|
|
||||||
// eslint-disable-next-line no-control-regex
|
// eslint-disable-next-line no-control-regex
|
||||||
const attrNameRegExp = /[^\x00-\x20\x7F-\x9F"'>/=]+/;
|
const attrNameRegExp = /[^\x00-\x20\x7F-\x9F"'>/=]+/;
|
||||||
|
@ -278,9 +276,9 @@ export class CoreDomUtilsProvider {
|
||||||
Array.from(element.children).forEach(fixElement);
|
Array.from(element.children).forEach(fixElement);
|
||||||
};
|
};
|
||||||
|
|
||||||
Array.from(this.template.content.children).forEach(fixElement);
|
Array.from(CoreTemplateElement.content.children).forEach(fixElement);
|
||||||
|
|
||||||
return this.template.innerHTML;
|
return CoreTemplateElement.innerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -389,7 +387,7 @@ export class CoreDomUtilsProvider {
|
||||||
* @returns Attribute value.
|
* @returns Attribute value.
|
||||||
*/
|
*/
|
||||||
getHTMLElementAttribute(html: string, attribute: string): string | null {
|
getHTMLElementAttribute(html: string, attribute: string): string | null {
|
||||||
return this.convertToElement(html).children[0].getAttribute(attribute);
|
return convertHTMLToHTMLElement(html).children[0].getAttribute(attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -650,7 +648,7 @@ export class CoreDomUtilsProvider {
|
||||||
* @returns HTML without the element.
|
* @returns HTML without the element.
|
||||||
*/
|
*/
|
||||||
removeElementFromHtml(html: string, selector: string, removeAll?: boolean): string {
|
removeElementFromHtml(html: string, selector: string, removeAll?: boolean): string {
|
||||||
const element = this.convertToElement(html);
|
const element = convertHTMLToHTMLElement(html);
|
||||||
|
|
||||||
if (removeAll) {
|
if (removeAll) {
|
||||||
const selected = element.querySelectorAll(selector);
|
const selected = element.querySelectorAll(selector);
|
||||||
|
@ -698,7 +696,7 @@ export class CoreDomUtilsProvider {
|
||||||
paths: {[url: string]: string},
|
paths: {[url: string]: string},
|
||||||
anchorFn?: (anchor: HTMLElement, href: string) => void,
|
anchorFn?: (anchor: HTMLElement, href: string) => void,
|
||||||
): string {
|
): string {
|
||||||
const element = this.convertToElement(html);
|
const element = convertHTMLToHTMLElement(html);
|
||||||
|
|
||||||
// Treat elements with src (img, audio, video, ...).
|
// Treat elements with src (img, audio, video, ...).
|
||||||
const media = Array.from(element.querySelectorAll<HTMLElement>('img, video, audio, source, track, iframe, embed'));
|
const media = Array.from(element.querySelectorAll<HTMLElement>('img, video, audio, source, track, iframe, embed'));
|
||||||
|
@ -1401,7 +1399,7 @@ export class CoreDomUtilsProvider {
|
||||||
* @returns Same text converted to HTMLCollection.
|
* @returns Same text converted to HTMLCollection.
|
||||||
*/
|
*/
|
||||||
toDom(text: string): HTMLCollection {
|
toDom(text: string): HTMLCollection {
|
||||||
const element = this.convertToElement(text);
|
const element = convertHTMLToHTMLElement(text);
|
||||||
|
|
||||||
return element.children;
|
return element.children;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,7 @@ import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreEventObserver } from '@singletons/events';
|
import { CoreEventObserver } from '@singletons/events';
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
import { CoreWait } from './wait';
|
import { CoreWait } from './wait';
|
||||||
|
import { CoreTemplateElement } from '../utils/create-html-element';
|
||||||
// A template element to convert HTML to element.
|
|
||||||
export const CoreTemplateElement: HTMLTemplateElement = document.createElement('template');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Singleton with helper functions for dom.
|
* Singleton with helper functions for dom.
|
||||||
|
|
|
@ -16,7 +16,7 @@ import { Clipboard, Translate } from '@singletons';
|
||||||
import { CoreToasts } from '@services/toasts';
|
import { CoreToasts } from '@services/toasts';
|
||||||
import { Locutus } from './locutus';
|
import { Locutus } from './locutus';
|
||||||
import { CoreError } from '@classes/errors/error';
|
import { CoreError } from '@classes/errors/error';
|
||||||
import { CoreTemplateElement } from './dom';
|
import { convertHTMLToHTMLElement } from '../utils/create-html-element';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Singleton with helper functions for text manipulation.
|
* Singleton with helper functions for text manipulation.
|
||||||
|
@ -190,7 +190,7 @@ export class CoreText {
|
||||||
// First, we use a regexpr.
|
// First, we use a regexpr.
|
||||||
text = text.replace(/(<([^>]+)>)/ig, '');
|
text = text.replace(/(<([^>]+)>)/ig, '');
|
||||||
// Then, we rely on the browser. We need to wrap the text to be sure is HTML.
|
// Then, we rely on the browser. We need to wrap the text to be sure is HTML.
|
||||||
text = CoreText.convertToElement(text).textContent || '';
|
text = convertHTMLToHTMLElement(text).textContent || '';
|
||||||
// Trim text
|
// Trim text
|
||||||
text = options.trim ? text.trim() : text;
|
text = options.trim ? text.trim() : text;
|
||||||
// Recover or remove new lines.
|
// Recover or remove new lines.
|
||||||
|
@ -199,20 +199,6 @@ export class CoreText {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert some HTML as text into an HTMLElement. This HTML is put inside a div or a body.
|
|
||||||
* This function is the same as in DomUtils, but we cannot use that one because of circular dependencies.
|
|
||||||
*
|
|
||||||
* @param html Text to convert.
|
|
||||||
* @returns Element.
|
|
||||||
*/
|
|
||||||
protected static convertToElement(html: string): HTMLElement {
|
|
||||||
// Add a div to hold the content, that's the element that will be returned.
|
|
||||||
CoreTemplateElement.innerHTML = '<div>' + html + '</div>';
|
|
||||||
|
|
||||||
return <HTMLElement> CoreTemplateElement.content.children[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode an escaped HTML text. This implementation is based on PHP's htmlspecialchars_decode.
|
* Decode an escaped HTML text. This implementation is based on PHP's htmlspecialchars_decode.
|
||||||
*
|
*
|
||||||
|
@ -243,7 +229,7 @@ export class CoreText {
|
||||||
*/
|
*/
|
||||||
static decodeHTMLEntities(text: string): string {
|
static decodeHTMLEntities(text: string): string {
|
||||||
if (text) {
|
if (text) {
|
||||||
text = CoreText.convertToElement(text).textContent || '';
|
text = convertHTMLToHTMLElement(text).textContent || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
|
@ -438,7 +424,7 @@ export class CoreText {
|
||||||
* @returns Processed HTML string.
|
* @returns Processed HTML string.
|
||||||
*/
|
*/
|
||||||
static processHTML(text: string, process: (element: HTMLElement) => unknown): string {
|
static processHTML(text: string, process: (element: HTMLElement) => unknown): string {
|
||||||
const element = CoreText.convertToElement(text);
|
const element = convertHTMLToHTMLElement(text);
|
||||||
|
|
||||||
process(element);
|
process(element);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
// (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.
|
||||||
|
|
||||||
|
// A template element to convert HTML to element.
|
||||||
|
export const CoreTemplateElement: HTMLTemplateElement = document.createElement('template');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert some HTML as text into an HTMLElement. This HTML is put inside a div or a body.
|
||||||
|
*
|
||||||
|
* @param html Text to convert.
|
||||||
|
* @returns Element.
|
||||||
|
*/
|
||||||
|
export function convertHTMLToHTMLElement(html: string): HTMLElement {
|
||||||
|
// Add a div to hold the content, that's the element that will be returned.
|
||||||
|
CoreTemplateElement.innerHTML = '<div>' + html + '</div>';
|
||||||
|
|
||||||
|
return <HTMLElement> CoreTemplateElement.content.children[0];
|
||||||
|
}
|
Loading…
Reference in New Issue