web-dev-qa-db-fra.com

Pourquoi les éléments de script à fermeture automatique ne fonctionnent-ils pas?

Quelle est la raison pour laquelle les navigateurs ne reconnaissent pas correctement:

<script src="foobar.js" /> <!-- self-closing script element -->

Seulement ceci est reconnu:

<script src="foobar.js"></script>

Est-ce que cela casse le concept de support XHTML?

Remarque: Cette instruction est correcte au moins pour tous les IE (6-8 beta 2).

1260
dimarzionist

La spécification XHTML 1 dit:

С.3. Minimisation des éléments et contenu des éléments vides

Étant donné une instance vide d'un élément dont le modèle de contenu n'est pas EMPTY (par exemple, un titre ou un paragraphe vide), n'utilisez pas la forme réduite (par exemple, utilisez <p> </p> et non <p />).

DTD XHTML spécifie les éléments de script comme suit:

<!-- script statements, which may include CDATA sections -->
<!ELEMENT script (#PCDATA)>
459
squadette

Pour ajouter à ce que Brad et l’escouade ont dit, la syntaxe XML à fermeture automatique <script /> en fait est un XML correct, mais elle fonctionne correctement. En pratique, votre serveur Web doit également envoyer vos documents en tant que XML correctement formé avec un type MIME XML tel que application/xhtml+xml dans l'en-tête HTTP Content-Type (et non comme text/html).

Cependant, l'envoi d'un type MIME XML fera que vos pages ne seront pas analysées par IE7, qui n'aime que text/html.

De w :

En résumé, 'application/xhtml + xml' DEVRAIT être utilisé pour les documents de la famille XHTML et l'utilisation de 'text/html' DEVRAIT être limitée aux documents XHTML 1.0 compatibles HTML. 'application/xml' et 'text/xml' PEUVENT aussi être utilisés, mais le cas échéant, 'application/xhtml + xml' DEVRAIT être utilisé plutôt que ces types de média XML génériques.

Cela me laissait perplexe il y a quelques mois. La seule solution utilisable (compatible avec FF3 + et IE7) consistait à utiliser l'ancienne syntaxe <script></script> avec text/html (syntaxe HTML + type MIME HTML).

Si votre serveur envoie le type text/html dans ses en-têtes HTTP, même avec des documents XHTML correctement formés, FF3 + utilisera son mode de rendu HTML, ce qui signifie que <script /> ne fonctionnera pas (changement, Firefox a été modifié). auparavant moins stricte).

Cela se produira quels que soient les manipulations avec les éléments méta http-equiv, le prologue XML ou le type de document contenu dans votre document - Firefox se branche dès qu’il obtient l’en-tête text/html, qui détermine si l’analyseur HTML ou XML regarde à l’intérieur du document. document, et l’analyseur HTML ne comprend pas <script />.

231
joelhardi

Au cas où quiconque serait curieux, la raison ultime est que HTML était à l'origine un dialecte de SGML, qui est l'étrange frère aîné de XML. Dans SGML-land, les éléments peuvent être spécifiés dans la DTD comme étant à fermeture automatique (par exemple, BR, HR, INPUT), fermable de manière implicite (par exemple, P, LI, TD) ou explicitement pouvant être fermée (par exemple, TABLE, DIV, SCRIPT). XML n’a bien sûr pas la moindre idée de cela.

Les analyseurs syntaxiques de balises utilisés par les navigateurs modernes sont issus de cet héritage, bien que leur modèle d'analyse syntaxique ne soit plus du pur SGML. Et bien sûr, votre XHTML soigneusement conçu est traité comme une balise-tag mal inspirée par SGML, à moins que vous ne l'envoyiez avec un type mime XML. C'est aussi pourquoi ...

<p><div>hello</div></p>

... est interprété par le navigateur comme:

<p></p><div>hello</div><p></p>

... qui est la recette d'un joli bogue obscur qui peut vous gêner lorsque vous essayez de coder contre le DOM.

154
greim

D'autres ont répondu "comment" et ont cité les spécifications. Voici la véritable histoire de "pourquoi pas <script/>", après de nombreuses heures passées à fouiller dans les rapports de bugs et les listes de diffusion.


HTML 4

HTML 4 est basé sur SGML .

SGML a certains balises courtes , tels que <BR//, <B>text</>, <B/text/ ou <OL<LI>item</LI</OL>. XML prend la première forme, redéfinit la fin comme ">" (SGML est flexible), de sorte qu'il devienne <BR/>.

Cependant, HTML n'a pas redéfini, donc <SCRIPT/> devrait signifie<SCRIPT>>.
(Oui, le '>' devrait faire partie du contenu, et la balise est toujours et non fermée.)

De toute évidence, cela est incompatible avec XHTML et va casser de nombreux sites (à l’époque, les navigateurs étaient suffisamment matures pour en prendre soinà propos de cela ), alors personne mis en œuvre et la spécification les déconseille .

En réalité, toutes les balises auto-terminées "actives" sont des balises avec une balise de fin facultative sur des analyseurs non conformes sur le plan technique et sont en fait non valides. C’est le W3C qui est venu avec ce hack pour aider à la transition vers XHTML en le rendant compatible HTML .

Et la balise de fin de <script> est non facultatif .

La balise "Self-ending" est un hack en HTML 4 et n'a aucun sens.


HTML 5

HTML5 a cinq types de balises et seules les balises 'void' et 'foreign' sont autorisé à se fermer automatiquement .

Étant donné que <script> n'est pas vide (il peut avoir du contenu) et n'est pas étranger (comme MathML ou SVG), <script> ne peut pas être auto-fermé, quelle que soit la façon dont vous l'utilisez.

Mais pourquoi? Ne peuvent-ils pas le considérer comme étranger, faire un cas spécial, ou quelque chose comme ça?

HTML 5 a pour objectif d'être rétrocompatible avec les implémentations de HTML 4 et XHTML 1. Il n'est pas basé sur SGML ou XML; sa syntaxe consiste principalement à documenter et à unifier les implémentations. (C’est la raison pour laquelle <br/><hr/> etc. est HTML 5 valide bien qu’il soit invalide HTML4.)

<script> à fermeture automatique est l'une des balises pour lesquelles les implémentations différaient auparavant. It tilisé auparavant dans Chrome, Safari , et Opera ; à ma connaissance, cela n'a jamais fonctionné dans Internet Explorer ou Firefox.

Cela a été discuté lors de la rédaction de HTML 5 et de son rejet, car il romptnavigateurcompatibilité . Les pages Web dont la balise de script se ferme automatiquement risquent de ne pas s'afficher correctement (voire pas du tout) dans les anciens navigateurs. Il y avait autres propositions , mais ils ne peuvent pas résoudre le problème de compatibilité non plus.

Une fois le brouillon publié, WebKit a mis à jour l'analyseur pour qu'il soit conforme.

<script> à fermeture automatique ne se produit pas dans HTML 5 en raison de la compatibilité avec les versions antérieures de HTML 4 et XHTML 1.


XHTML 1/XHTML 5

Lorsque sert réellement en tant que XHTML, <script/> est vraiment fermé, comme indiqué par autres réponses .

Sauf que la spécification dit il devrait avoir fonctionné lorsqu'il a été utilisé en tant que HTML:

Les documents XHTML ... peuvent être étiquetés avec le type de média Internet "text/html" [RFC2854], car ils sont compatibles avec la plupart des navigateurs HTML.

Alors, qu'est-ce-qu'il s'est passé?

People a demandé à Mozilla de laissez Firefox analyser des documents conformes comme XHTML quel que soit l’en-tête de contenu spécifié (appelé recherche de conten ). Cela aurait permis des scripts à fermeture automatique et une analyse de contenu était nécessaire de toute façon, car les hébergeurs Web n'étaient pas assez matures pour servir l'en-tête correct; IE était bon à cela .

Si le première guerre des navigateurs ne s'est pas terminé par IE 6, il se peut que XHTML figure également sur la liste. Mais cela s'est terminé. Et IE 6 a un problème avec XHTML. En fait, IE ne supportait pas le type MIME correct du tout , forçant tout le monde à utiliser text/html pour XHTML car IE avait une part de marché importante pendant toute une décennie.

Et aussi contenu reniflant peut êtrevraiment mauvais et les gens disent il devrait être arrêté .

Enfin, il s'avère que le W3C ne voulait pas dire que XHTML était sniffable : le document est , à la fois , HTML et XHTML, et Content-Type. On peut dire qu'ils se tenaient fermes sur "il suffit de suivre nos spécifications" et en ignorant ce qui était pratique . Une erreur qui suite dans les versions ultérieures de XHTML.

Quoi qu'il en soit, cette décision réglé la question pour Firefox. C'était 7 ans avant Chrome était né ; il n'y avait pas d'autre navigateur significatif. C'est donc décidé.

La spécification du type de document seul ne déclenche pas l'analyse XML en raison des spécifications suivantes.

141
Sheepy

Internet Explorer 8 et les versions antérieures ne prennent pas en charge l'analyse XHTML. Même si vous utilisez une déclaration XML et/ou un doctype XHTML, l'ancien IE analyse toujours le document au format HTML brut. Et en HTML simple, la syntaxe à fermeture automatique n'est pas prise en charge. La barre oblique finale est simplement ignorée, vous devez utiliser une balise de fermeture explicite.

Même les navigateurs prenant en charge l'analyse XHTML, tels que IE 9 et versions ultérieures , analysent toujours le document au format HTML, à moins que vous ne présentiez le document avec un type de contenu XML. Mais dans ce cas, le vieux IE n’affiche plus le document!

44
JacquesB

Les personnes ci-dessus ont déjà expliqué le problème d'une manière assez précise, mais une chose qui pourrait clarifier les choses est que, bien que les gens utilisent <br/> et ainsi de suite dans les documents HTML, tout / dans une telle position est fondamentalement ignoré, et utilisé uniquement lorsqu’on essaie de rendre quelque chose à la fois analysable en XML et HTML. Essayez <p/>foo</p>, par exemple, et vous obtenez un paragraphe normal.

27
Marijn

La balise de script à fermeture automatique ne fonctionnera pas, car elle peut contenir du code intégré et HTML n'est pas assez intelligent pour activer ou désactiver cette fonctionnalité en fonction de la présence d'un attribut.

D'autre part, HTML possède une excellente balise pour inclure des références à des ressources externes: la balise <link>, et peut être à fermeture automatique. Il est déjà utilisé pour inclure les feuilles de style, les flux RSS et Atom, les URI canoniques et toutes sortes d'autres goodies. Pourquoi pas JavaScript?

Si vous voulez que la balise de script soit auto-jointe, vous ne pouvez pas le faire, comme je l’ai dit, mais il existe une alternative, bien que pas intelligente. Vous pouvez utiliser la balise de lien à fermeture automatique et le lien vers votre JavaScript en lui donnant un type de texte/javascript et rel en tant que script, comme ci-dessous:

<link type="text/javascript" rel ="script" href="/path/tp/javascript" />
22
defau1t

Contrairement à XML et XHTML, HTML n'a pas connaissance de la syntaxe à fermeture automatique. Les navigateurs qui interprètent XHTML en tant que HTML ne savent pas que le caractère / indique que la balise doit se fermer automatiquement. au lieu de cela, ils l'interprètent comme un attribut vide et l'analyseur pense toujours que la balise est "ouverte".

Tout comme <script defer> est traité comme <script defer="defer">, <script /> est traité comme <script /="/">.

20
rpetrich

Internet Explorer 8 et les versions antérieures ne prennent pas en charge le type MIME approprié pour XHTML, application/xhtml+xml. Si vous utilisez XHTML en tant que text/html, ce que vous devez faire pour que ces anciennes versions d'Internet Explorer puissent faire quoi que ce soit, il sera interprété en tant que HTML 4.01. Vous ne pouvez utiliser la syntaxe courte qu'avec n'importe quel élément permettant d'omettre la balise de fermeture. Voir le Spécification HTML 4.01 .

La 'forme abrégée' XML est interprétée comme un attribut nommé /, qui (étant donné qu'il n'y a pas de signe égal) est interprété comme ayant une valeur implicite de "/". Ceci est strictement faux dans HTML 4.01 - les attributs non déclarés ne sont pas autorisés - mais les navigateurs l'ignoreront.

IE9 et versions ultérieures support XHTML 5 servi avec application/xhtml+xml.

18
Mike Dimmick

En effet, SCRIPT TAG n'est pas un élément annulé.

Dans un document HTML - ANNULER LES ÉLÉMENTS ne pas besoin d'une "balise de fermeture" du tout!

Dans xhtml , tout est générique, par conséquent, ils ont tous besoin de résiliation p. Ex. une "balise de fermeture"; Y compris br, un simple retour à la ligne, comme <br></br> ou son raccourci <br />.

Cependant, un élément de script n'est jamais un élément vide ou paramétrique, car la balise de script est avant tout une instruction de navigateur et non une déclaration de description de données.

Principalement, une instruction de terminaison sémantique, par exemple, une "étiquette de fermeture" n'est nécessaire que pour traiter des instructions dont la sémantique ne peut pas être résiliée par une étiquette suivante. Par exemple:

La sémantique de <H1> ne peut pas être terminée par un <P> suivant, car elle ne contient pas assez de sémantique propre pour remplacer et par conséquent mettre fin au jeu d'instructions H1 précédent. Bien qu'il puisse briser le flux dans une nouvelle ligne de paragraphe, il n'est pas "assez puissant" pour remplacer la taille de la police et le style actuels line-height dans le flux , c’est-à-dire qu’il fuit H1 (parce que P ne l’a pas).

C'est comment et pourquoi la signalisation "/" (terminaison) a été inventée.

Une balise de terminaison générique no-description telle que < /> aurait suffi pour une seule baisse de la cascade rencontrée, par exemple: <H1>Title< /> mais ce n’est pas toujours le cas, car nous voulons aussi être capables d’imbrouiller, de multiples marquages ​​intermédiaires du Stream: scinder en torrents avant d’envelopper/de tomber sur une autre cascade. En conséquence, un terminateur générique tel que < /> ne serait pas en mesure de déterminer la cible d'une propriété à terminer. Par exemple: <b>gras<i> gras-italique < /> italique </>normal. Sans aucun doute, nous ne réussirions pas à bien faire comprendre notre intention et nous l’interpréterions probablement comme bold bold-itallic bold normal.

Voici comment est née la notion d'un conteneur, c'est-à-dire un conteneur. (Ces notions sont si semblables qu'il est impossible de discerner et qu'un même élément peut avoir les deux. <H1> est à la fois un emballage et un conteneur. Tandis que <B> n'est qu'un emballage sémantique). Nous aurons besoin d'un conteneur simple, sans sémantique. Et bien sûr, l'invention d'un élément DIV est arrivée.

L'élément DIV est en fait un conteneur 2BR. Bien sûr, la venue de CSS a rendu la situation plus étrange qu’elle ne l’aurait été autrement et a créé une grande confusion avec de nombreuses conséquences, indirectement!

Parce qu'avec CSS, vous pouvez facilement remplacer le comportement natif de pré-et après-BR d'un DIV nouvellement inventé, on l'appelle souvent "conteneur" ne fait rien ". Ce qui est naturellement faux! Les DIV sont des éléments de bloc et interrompent de manière native la ligne du flux avant et après la signalisation de fin. Bientôt, le WEB a commencé à souffrir de la page DIV-itis. La plupart d'entre eux le sont toujours.

L'avènement de CSS avec sa capacité à annuler et à redéfinir complètement le comportement natif de toute balise HTML a réussi à confondre et brouiller le sens de l'existence du code HTML ...

Soudainement, toutes les balises HTML sont apparues comme obsolètes, elles ont été altérées, dépouillées de toute signification, identité et finalité originales. D'une manière ou d'une autre, vous auriez l'impression qu'ils ne sont plus nécessaires. Disant: Une seule balise conteneur-wrapper suffirait pour toute la présentation des données. Ajoutez simplement les attributs requis. Pourquoi ne pas avoir des balises significatives à la place; Inventez les noms de balises au fur et à mesure et laissez le CSS s'embarrasser du reste.

C’est ainsi que xhtml est né et, bien sûr, le grand émoussé, payé si cher par les nouveaux arrivants et une vision déformée de ce qui est quoi et de son objectif. Le W3C est passé du World Wide Web à ce qui s'est mal passé, camarades? !!

Le but du HTML est de diffuser des données significatives au destinataire humain.

Fournir des informations.

La partie formelle n’est là que pour aider à la clarté de la diffusion de l’information. xhtml ne donne pas la moindre considération à l'information. - Pour lui, l'information est absolument hors de propos.

La chose la plus importante en la matière est de savoir et de pouvoir comprendre que le xhtml n’est pas simplement une version de HTML étend, le xhtml est une bête complètement différente; se remémore; et donc il est sage de les séparer.

5
Bekim Bacaj

La différence entre 'true XHTML', 'faux XHTML' et HTML, ainsi que l'importance du type MIME envoyé par le serveur avait été déjà bien décrite ici . Si vous voulez l'essayer maintenant, voici un extrait modifiable avec aperçu en direct, y compris une balise de script à fermeture automatique pour les navigateurs capables:

div { display: flex; }
div + div {flex-direction: column; }
<div>Mime type: <label><input type="radio" onchange="t.onkeyup()" id="x" checked  name="mime"> application/xhtml+xml</label>
<label><input type="radio" onchange="t.onkeyup()" name="mime"> text/html</label></div>
<div><textarea id="t" rows="4" 
onkeyup="i.src='data:'+(x.checked?'application/xhtml+xml':'text/html')+','+encodeURIComponent(t.value)"
><?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
[<!ENTITY x "true XHTML">]>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
  <p>
    <span id="greet" swapto="Hello">Hell, NO :(</span> &x;.
    <script src="data:text/javascript,(g=document.getElementById('greet')).innerText=g.getAttribute('swapto')" />
    Nice to meet you!
    <!-- 
      Previous text node and all further content falls into SCRIPT element content in text/html mode, so is not rendered. Because no end script tag is found, no script runs in text/html
    -->
  </p>
</body>
</html></textarea>

<iframe id="i" height="80"></iframe>

<script>t.onkeyup()</script>
</div>

Vous devriez voir Hello, true XHTML. Nice to meet you! sous textarea.

Pour les navigateurs incapables, vous pouvez copier le contenu de la zone de texte et l'enregistrer en tant que fichier avec l'extension .xhtml (ou .xht) ( merci Alek pour cet indice ).

2
myf