Fenster aus 'global/window' importieren;
dokument aus 'global/document' importieren;
importiere MergeOptions aus '.. /utils/merge-options ';
importiere {getAbsoluteUrl} aus '.. /utils/url ';
/**
* Diese Funktion wird verwendet, um ein Sourceset auszulösen, wenn etwas vorhanden ist
* ähnlich wie `Mediael.load () `aufgerufen wird. Es wird versuchen, die Quelle zu finden über
* das `src`-Attribut und dann die<`source>` -Elemente. Es wird dann `sourceset` auslösen
* mit der gefundenen Quelle oder einer leeren Zeichenfolge, falls wir es nicht wissen können. Wenn es nicht kann
* finde eine Quelle dann wird `sourceset` nicht ausgelöst.
*
* @param {Html5} tech
* Das Tech-Objekt, auf dem Sourceset eingerichtet wurde
*
* @return {boolean}
* gibt false zurück, wenn das Sourceset nicht ausgelöst wurde, andernfalls true.
* /
const sourceSetLoad = (tech) => {
const el = tech.el();
//wenn `el.src` gesetzt ist, wird diese Quelle geladen.
wenn (el.hasAttribute ('src')) {
tech.triggerSourceset(el.src);
true zurückgeben;
}
/**
* Da es für das Medienelement keine src-Eigenschaft gibt, werden Quellelemente verwendet für
* Implementierung des Algorithmus zur Quellenauswahl. Das passiert asynchron und
* In den meisten Fällen, in denen es mehr als eine Quelle gibt, können wir nicht sagen, welche Quelle
* geladen werden, ohne den Quellauswahlalgorithmus erneut zu implementieren. Zu diesem Zeitpunkt sind wir nicht
* werde das machen. Es gibt jedoch drei Sonderfälle, mit denen wir uns hier befassen:
*
* 1. Wenn es keine Quellen gibt, feuere `sourceset` nicht aus.
* 2. Wenn es nur eine `<source>` mit einer `src`-Eigenschaft/einem `src`-Attribut gibt, ist das unser `src`
* 3. Wenn es mehr als eine `<source>` gibt, aber alle dieselbe `src`-URL haben.
* Das wird unser SRC sein.
* /
const sources = tech.$$ ('Quelle');
const srCurls = [];
sei src = „;
//wenn es keine Quellen gibt, feuere Sourceset nicht
if (!sources.length) {
return false;
}
//Zähle nur gültige/nicht doppelte Quellelemente
for (let i = 0; i < sources.length; i++) {
const url = quellen [i] .src;
if (url && srCurls.indexOf (url) === -1) {
srcURLs.push (URL);
}
}
//es gab keine gültigen Quellen
wenn (! srcurls.Länge) {
return false;
}
//es gibt nur eine gültige URL für das Quellelement
//benutze das
wenn (srCURLs.length === 1) {
src = srCurls [0];
}
tech.triggerSourceSet (src);
true zurückgeben;
};
/**
* unsere Implementierung eines `innerHTML`-Deskriptors für Browser
* die nicht über eine solche verfügen.
* /
const innerHTMLDescriptorPolyFill = Object.defineProperty ({}, 'innerHTML', {
get() {
gib this.cloneNode (true) .innerHTML zurück;
},
set(v) {
//erstelle einen Dummy-Node, auf dem innerHTML verwendet werden soll
const dummy = document.createElement (this.nodeName.toLowerCase ());
//setze innerHTML auf den angegebenen Wert
dummy.innerHTML = v;
//erstelle ein Dokumentfragment, das die Knoten von Dummy enthält
const docFrag = document.createDocumentFragment ();
//kopiere alle vom innerHTML erstellten Knoten auf Dummy
//zum Dokumentfragment
während (dummy.childNodes.length) {
docFrag.appendChild (dummy.childNodes [0]);
}
//Inhalt entfernen
this.innerText = „;
//jetzt fügen wir all diesen HTML-Code in einem hinzu, indem wir das anhängen
//Dokumentfragment. So macht InnerHTML das.
window.element.prototype.appendChild.call (das, docFrag);
//dann das Ergebnis zurückgeben, das der Setter von innerHTML tun würde
gib this.innerHTML zurück;
}
});
/**
* Holen Sie sich einen Eigenschaftsdeskriptor mit einer Prioritätenliste und
* Eigentum zum Anschaffen.
* /
const getDescriptor = (Priorität, Requisite) => {
sei der Deskriptor = {};
für (sei i = 0; i < Priorität.Länge; i++) {
Deskriptor = Object.getOwnPropertyDescriptor (Priorität [i], Eigenschaft);
if (Deskriptor && Deskriptor.set && descriptor.get) {
pause;
}
}
descriptor.enumerable = wahr;
descriptor.configurable = wahr;
Deskriptor zurückgeben;
};
const getInnerHTMLDescriptor = (tech) => getDescriptor ([
tech.el (),
Fenster.HtmlMediaElement.Prototyp,
Fensterelement.Prototyp,
innerHtmlDescriptorPolyFill
], 'innerHTML');
/**
* Patcht die internen Funktionen des Browsers, sodass wir synchron erkennen können
* wenn eine `<Quelle>` an das Medienelement angehängt wurde. Aus irgendeinem Grund das
* verursacht ein `Sourceset`, wenn das Medienelement bereit ist und keine Quelle hat.
* Das passiert, wenn:
* - Die Seite wurde gerade geladen und das Medienelement hat keine Quelle.
* - Das Medienelement wurde von allen Quellen geleert, dann wurde `load () `aufgerufen.
*
* Dazu werden die folgenden Funktionen/Eigenschaften gepatcht, sofern sie unterstützt werden:
*
* - `append () `- kann verwendet werden, um dem Medienelement ein<` source>` -Element hinzuzufügen
* - `appendChild () `- kann verwendet werden, um dem Medienelement ein<` source>` -Element hinzuzufügen
* - `insertAdjacentHTML () `- kann verwendet werden, um dem Medienelement ein<` source>` -Element hinzuzufügen
* - `innerHTML` - kann verwendet werden, um dem Medienelement ein<`source>` -Element hinzuzufügen
*
* @param {Html5} tech
* Das Tech-Objekt, für das Sourceset eingerichtet wird.
* /
const firstSourceWatch = Funktion (Technik) {
const el = tech.el();
//stelle sicher, dass FirstSourceWatch nicht zweimal eingerichtet wird.
if (el.resetSourceWatch_) {
rückkehr;
}
const old = {};
const innerDescriptor = getInnerHTMLDescriptor (technisch);
const AppendWrapper = (AppendFn) => (... Argumente) => {
const retval = appendFn.apply (el, args);
sourceSetLoad (tech);
return retval;
};
['anhängen', 'appendChild', 'insertAdjacentHTML'] .forEach (k) => {
wenn (! el [k]) {
rückkehr;
}
//speichere die alte Funktion
alt [k] = el [k];
//rufe die alte Funktion mit einem Sourceset auf, wenn eine Quelle
//wurde geladen
el [k] = AppendWrapper (alt [k]);
});
Object.defineProperty (de), 'innerHTML', mergeOptions (innerDescriptor, {
Satz: AppendWrapper (innerDescriptor.set)
}));
el.resetSourceWatch_ = () => {
el.resetSourceWatch_ = null;
Object.keys (alt) .forEach (k) => {
el [k] = alt [k];
});
Object.defineProperty (de, 'innerHTML', innerDescriptor);
};
//Im ersten Sourceset müssen wir unsere Änderungen rückgängig machen
tech.one ('sourceset', el.resetSourceWatch_);
};
/**
* unsere Implementierung eines `src`-Deskriptors für Browser
* die nicht über eine solche verfügen.
* /
const srcDescriptorPolyFill = Object.defineProperty ({}, 'src', {
get() {
wenn (this.hasAttribute ('src')) {
return getAbsoluteUrl (window.element.prototype.getAttribute.call (this, 'src'));
}
zurückgeben '';
},
set(v) {
window.element.prototype.setAttribute.call (this, 'src', v);
gib v zurück;
}
});
const getSrcDescriptor = (tech) => getDescriptor ([tech.el (), window.HtmlMediaElement.prototype, srcDescriptorPolyFill], 'src');
/**
* Richten Sie die `Sourceset`-Handhabung auf der `Html5`-Technologie ein. Diese Funktion
* patcht die folgenden Elementeigenschaften/Funktionen:
*
* - `src` - um festzustellen, wann `src` gesetzt ist
* - `setAttribute () `- um festzustellen, wann `src` gesetzt ist
* - `load () `- dies löst den Algorithmus zur Quellenauswahl erneut aus und kann
* verursacht ein Sourceset.
*
* Wenn es keine Quelle gibt, wenn wir die `sourceset`-Unterstützung hinzufügen oder während eines `load () `
* Wir patchen auch die in `FirstSourceWatch` aufgelisteten Funktionen.
*
* @param {Html5} tech
* Die Technik zum Patchen
* /
const setupSourceSet = Funktion (Technik) {
wenn (! tech.featureResourceSet) {
rückkehr;
}
const el = tech.el();
//stelle sicher, dass Sourceset nicht zweimal eingerichtet wird.
wenn (el.resetSourceSet_) {
rückkehr;
}
const srcDescriptor = getSrcDescriptor (technisch);
const oldSetAttribute = el.setAttribute;
const oldLoad = el.load;
Object.defineProperty (de), 'src', mergeOptions (srcDescriptor, {
setze: (v) => {
const retval = srcDescriptor.set.Call (el, v);
//wir verwenden den Getter hier, um den tatsächlichen Wert zu erhalten, der auf src gesetzt wurde
tech.triggerSourceset(el.src);
return retval;
}
}));
el.setAttribute = (n, v) => {
const retval = oldSetAttribute.call (el, n, v);
wenn ((/src/i) .test (n)) {
tech.triggerSourceset(el.src);
}
return retval;
};
el.load = () => {
const retval = oldLoad.Call (el);
//wenn load aufgerufen wurde, aber es keine Feuerquelle gab
//sourceset on. Wir müssen nach einem Quellanhängen Ausschau halten
//da das ein `Sourceset` auslösen kann, wenn das Medienelement
//hat keine Quelle
wenn (! sourceSetLoad (tech)) {
tech.triggerSourceSet („);
firstSourceWatch(tech);
}
return retval;
};
wenn (el.currentSrc) {
tech.triggerSourceSet (el.CurrentSrc);
} sonst wenn (! sourceSetLoad (tech)) {
firstSourceWatch(tech);
}
el.resetSourceSet_ = () => {
el.resetSourceSet_ = null;
el.load = OldLoad;
el.setAttribute = Altes SetAttribut;
Object.defineProperty (de, 'src', srcDescriptor);
if (el.resetSourceWatch_) {
el.resetSourceWatch_ ();
}
};
};
exportiert das Standard-SetupSourceSet;