nativescript中的window对象

Dee*_*ika 7 iframe nativescript

我需要创建一个窗口对象,以便在iframe中加载的外部文件可以调用nativescript函数.

我特别需要窗口对象,因为我加载的文件可以是符合LMS的符合(SCORM)的任何文件.

谢谢

编辑:我加载的文件是符合SCORM的文件.他们搜索window.API对象/ window.parent.API等,以便开始与已加载它们的容器进行通信.我不能改变那个文件.

告诉我是否需要更多细节.

Sea*_*ins 0

我们成功地在 NativeScript 应用程序中处理 SCORM 内容,但它确实需要一些技巧才能完成。

我编写了一个实用程序类,它将注入到 SCORM 内容的主条目文件(索引)中,并覆盖窗口 API。

背景:

  • 在我们的应用程序中,我们将 zip 课程解压到设备:documents/courses/UUID(这就是身份引用的内容)
  • 您可以根据实施需要更改路径

实用程序类的用法示例:

const documents = fs.knownFolders.documents();
const destination = fs.path.join(documents.path, 'courses', this.media.identity);
this._readAccessUrl = destination;
const src = `file://${destination}`;
if (fs.File.exists(destination)) {
    SCORMUtils.readSCORMManifest(this.media.identity).then(fileName => {
        this._src = `${src}/${fileName}`;
        SCORMUtils.makeOfflineCompatible(fs.path.join(destination, fileName))
            .then(() => {
                this._loading = false;
            });
        this._loading = false;
    });
}
Run Code Online (Sandbox Code Playgroud)

实用类:

import { File, knownFolders } from 'tns-core-modules/file-system';

const SCORM_API = `
    <script type="text/javascript">
    (function () {
        window.parent.API = (function() {
            return {
                LMSInitialize: function () {
                    if (window && window.webkit) {
                        window.webkit.messageHandlers.print.postMessage("LMSInitialize");
                    }
                    return "true";
                },
                LMSCommit: function () {
                    if (window && window.webkit) {
                        window.webkit.messageHandlers.print.postMessage("LMSCommit");
                    }
                    return "true";
                },
                LMSFinish: function () {
                    if (window && window.webkit) {
                        window.webkit.messageHandlers.print.postMessage("LMSFinish");
                    }
                    return "true";
                },
                LMSGetValue: function (key) {
                    if (window && window.webkit) {
                        window.webkit.messageHandlers.print.postMessage("LMSGetValue");
                    }
                    return "";
                },
                LMSSetValue: function (key, value) {
                    if (window && window.webkit) {
                        window.webkit.messageHandlers.print.postMessage("LMSSetValue");
                    }
                    return "true";
                },
                LMSGetLastError: function () {
                    if (window && window.webkit) {
                        window.webkit.messageHandlers.print.postMessage("LMSGetLastError");
                    }
                    return "0";
                },
                LMSGetErrorString: function (errorCode) {
                    if (window && window.webkit) {
                        window.webkit.messageHandlers.print.postMessage("LMSGetErrorString");
                    }
                    return "No error";
                },
                LMSGetDiagnostic: function (errorCode) {
                    if (window && window.webkit) {
                        window.webkit.messageHandlers.print.postMessage("LMSGetDiagnostic");
                    }
                    return "No error";
                }
            }
        })();
    })();
    </script>
    </head>
`;

export class SCORMUtils {

    /**
     * Converts a SCORM course to be opened offline
     * @param entryFile The main entry point determined by imsmanifest.xml
     */
    static makeOfflineCompatible(entryFile: string) {
        return new Promise((resolve, reject) => {
            // Rewrite the entry file first
            this._rewriteFile(entryFile)
                .then(() => {
                    this._discoverHTMLEntry(entryFile)
                        .then(() => {
                            resolve();
                        }, () => {
                            console.error('Unable to rewrite alternative HTML entry');
                            reject();
                        });
                }, () => {
                    console.error(`Unable to rewrite primary entry point: ${entryFile}`);
                    reject();
                });
        });
    }

    /**
     * Digests a SCORM Manifest file to determine the main point of entry
     * for the course viewer. Normally this is a index.html file.
     */
    static readSCORMManifest(identity: string): Promise<string> {
        return new Promise((resolve, reject) => {
            const manifestFile = knownFolders.documents()
                .getFolder('courses')
                .getFolder(identity)
                .getFile('imsmanifest.xml');
            if (!File.exists(manifestFile.path)) {
                alert({
                    title: 'Error',
                    message: 'Course is missing imsmanifest.xml file',
                    okButtonText: 'Ok'
                });
                return reject();
            }
            const data = manifestFile.readTextSync(() => {
                alert({
                    title: 'Error',
                    message: 'Cannot open course.',
                    okButtonText: 'Ok'
                });
                return reject();
            });
            const matches = data.match(/type="webcontent"+.+?href="(.*?)"/);
            if (matches === null || matches.length < 1) {
                alert({
                    title: 'Error',
                    message: 'Invalid imsmanifest.xml file',
                    okButtonText: 'Ok'
                });
            }
            else {
                resolve(matches[1]);
            }
        });
    }

    /**
     * Rewrites a file to be SCORM offline-compliant
     * @param path The path of the file to re-write
     */
    private static _rewriteFile(path: string) {
        return new Promise((resolve, reject) => {
            const entryFile = File.fromPath(path);
            entryFile.readText()
                .then(htmlText => {
                    this._injectOfflineAPI(htmlText)
                        .then(updatedHtml => {
                            entryFile.writeText(updatedHtml).then(() => {
                                resolve();
                            }, () => {
                                console.error(`Error writing to file: ${path}`);
                                reject();
                            });
                        });
                }, () => {
                    console.error(`There was an entry reading the entry file at: ${path}`);
                    reject();
                });
        });
    }

    /**
     * Attempts to find another SCORM entry point for re-write
     * @param mainEntry The main entry point to branch from
     */
    private static _discoverHTMLEntry(mainEntry: string): Promise<any> {
        return new Promise((resolve, reject) => {
            const entryFile = File.fromPath(mainEntry);
            entryFile.readText()
                .then(htmlText => {
                    let htmlEntry = htmlText.match(/{"type":"html5","url":"(.*?)"}/);
                    if (htmlEntry === null || htmlEntry.length < 1) {
                        // Check for Articulate
                        htmlEntry = htmlText.match(/location\.href\.replace\("index_lms", "(.*?)"/);
                    }
                    if (htmlEntry !== null && htmlEntry.length > 0) {
                        let fileName = htmlEntry[1];
                        if (fileName.indexOf('.html') === -1) {
                            fileName = `${fileName}.html`;
                        }
                        const directory = mainEntry.substr(0, mainEntry.lastIndexOf('/'));
                        const entryPoint = `${directory}/${fileName}`;
                        if (File.exists(entryPoint)) {
                            this._rewriteFile(entryPoint)
                                .then(() => {
                                    resolve();
                                }, () => {
                                    console.error('Error discovering main entry point.');
                                    reject();
                                });
                        }
                        else {
                            console.error(`Cannot find alternative entry point: ${entryPoint}`);
                            reject();
                        }
                    }
                    else {
                        // This course does not have an alternative entry point
                        console.error('Course does not have an alternative entry, skipping...');
                        resolve();
                    }
                }, () => {
                    reject();
                });
        });
    }

    /**
     * Injects the extended SCORM API for offline-compatible viewing
     * @param text The unmodified HTML source text
     */
    private static _injectOfflineAPI(text: string): Promise<string> {
        return new Promise((resolve, reject) => {
            // Prevent multiple rewrites of the same file
            if (this._isConverted(text)) {
                return resolve(text);
            }
            // Finds the end of the head tag for script injection
            const head = text.match(/<\/head>/gi);
            if (head !== null && head.length > 0) {
                resolve(text.replace(head.toString(), SCORM_API));
            }
            else {
                console.error('Unable to parse incoming HTML for head tag.');
                reject({
                    message: 'Unable to parse HTML'
                });
            }
        });
    }

    /**
     * Checks if the HTML has already been converted for offline-viewing
     * @param text The incoming HTML source text
     */
    private static _isConverted(text: string) {
        const match = text.match(/window.parent.API/);
        return match !== null && match.length > 0;
    }

}
Run Code Online (Sandbox Code Playgroud)