Wszystkie opublikowane do tej pory odpowiedzi zawierają właściwe rozwiązania, jednak żadna z nich nie była w stanie poprawnie wyjaśnić przyczyny leżącej u podstaw konkretnego problemu.
Facelets to technologia widoku oparta na języku XML, która wykorzystuje XHTML + XML do generowania danych wyjściowych HTML. XML ma pięć znaków specjalnych, które są specjalnie traktowane przez parser XML:
<
początek tagu.
>
koniec tagu.
"
początek i koniec wartości atrybutu.
'
alternatywny początek i koniec wartości atrybutu.
&
początek podmiotu (który kończy się ;
).
W przypadku &
których nie następuje #
(np  
,  
itp), parser XML jest niejawnie szuka jednej z pięciu predefiniowanych nazw jednostki lt
, gt
, amp
, quot
i apos
, lub dowolny ręcznie zdefiniowana nazwa podmiotu . Jednak w twoim konkretnym przypadku byłeś używany &
jako operator JavaScript, a nie jako jednostka XML. To całkowicie wyjaśnia błąd analizy XML, który otrzymałeś:
Nazwa jednostki musi znajdować się bezpośrednio po znaku „&” w odniesieniu do jednostki
Zasadniczo piszesz kod JavaScript w niewłaściwym miejscu, w dokumencie XML zamiast w pliku JS, więc powinieneś odpowiednio uciekać przed wszystkimi znakami specjalnymi XML. &
Musi być uciekł jak &
.
Tak więc w twoim konkretnym przypadku
if (Modernizr.canvas && Modernizr.localstorage &&
musi stać się
if (Modernizr.canvas && Modernizr.localstorage &&
aby był zgodny z XML.
Jednak to sprawia, że kod JavaScript jest trudniejszy do odczytania i utrzymania. Jak stwierdzono w doskonałym dokumencie Mozilla Developer Network Writing JavaScript for XHTML , kod JavaScript należy umieścić w bloku danych znakowych (CDATA). Zatem w kategoriach JSF byłoby to:
<h:outputScript>
<![CDATA[
// ...
]]>
</h:outputScript>
Parser XML zinterpretuje zawartość bloku jako dane znakowe „zwykłe”, a nie jako XML, a zatem interpretuje znaki specjalne XML „tak jak jest”.
Ale znacznie lepiej jest po prostu umieścić kod JS we własnym pliku JS, który dołączasz za pomocą <script src>
lub w terminologii JSF, pliku <h:outputScript>
.
<h:outputScript name="onload.js" target="body" />
(zwróć uwagę na target="body"
; w ten sposób JSF automatycznie wyrenderuje plik <script>
na samym końcu <body>
, niezależnie od tego, gdzie <h:outputScript>
się znajduje, uzyskując tym samym efekt, co z window.onload
i $(document).ready()
; więc nie musisz już ich używać w tym skrypcie)
W ten sposób nie musisz martwić się o znaki specjalne XML w swoim kodzie JS. Jako dodatkowy bonus, daje to możliwość, aby przeglądarka buforowała plik JS, tak aby całkowity rozmiar odpowiedzi był mniejszy.
Zobacz też: