Come eliminare il post-rendering "sfarfallio"?

Ho provato il mio meglio per essere un purista con il mio uso di tecniche Javascript / Ajax, assicurando che tutto il comportmento di Ajax-y sia un miglioramento delle funzionalità di base, mentre il sito è anche pienamente funzionale quando Javascript è disabilitato. Tuttavia, ciò provoca alcuni problemi.

In alcuni casi, un nodo DOM dovrebbe essere visibile solo quando Javascript è abilitato nel browser. In altri casi, dovrebbe essere visibile solo quando è disabilitato. Prendi ad esempio un button di invio in un module che abbia un drop down con un gestore di sostituzione che viene inviato automaticamente (utilizzando il module plugin di JQuery):

<form method="post" action="."> <label for="id_state">State:</label> <select name="state" id="id_state" onchange="$(this.form).ajaxSubmit(ajax_submit_handler);"> <option value="AL">Alabama</option> <option value="AK">Alaska</option> </select> <input class="with_js_disabled" type="submit" value="OK" /> </form> 

e il Javascript:

 <script type="text/javascript"> $(document).ready(function() { $(".with_js_disabled").hide(); }); </script> 

Quando Javascript è abilitato, il button di invio non è richiesto (a causa del gestore di sostituzione). Tuttavia, la function JQuery $ (documento) .ready (e il document.onload più diretto) viene chiamata solo dopo che la pagina è stata completamente caricata e resa – quindi il button di invio viene visualizzato inizialmente e viene visualizzato un "flash" quando il Javascript è eseguito e il display del nodo è impostato su "none".

Ho accettato questo come costo di fare affari, e non ho trovato un modo per farlo. Ma c'è una tecnica che non sono al corrente di ciò che minimizzerà l'effetto, o addirittura lo eliminerà?

EDIT:

La soluzione <noscript> citata da molte persone qui sotto sembra promettente, ma non funziona per me su Safari. Tuttavia il secondo suggerimento di Prestaul funziona meravigliosamente:

 <body> <script type="text/javascript"> document.body.className += ' has_js'; </script> <!-- the rest of your page --> </body> 

Questo può essere stilato utilizzando CSS diritta:

 body .js_enabled_only { display: none; } body .js_disabled_only { display: block; } body.has_js .js_enabled_only { display: block; } body.has_js .js_disabled_only { display: none; } 

Questa seconda row è solo per riferimento e può (e dovrebbe) essere rimossa per evitare circostanze in cui il tuo elemento non dovrebbe essere visualizzato: block. Allo stesso modo, potrebbe essere necessario varianti diverse nella terza row per altri stili di visualizzazione. Ma questa soluzione è bella e pulita, IMO e nelle mie prove interamente elimina l'effetto sfarfallio.

Come combinare alcune di queste soluzioni:

 <style type="text/javascript"> .only-without-script { display: none; } </style> <noscript> <style type="text/javascript"> .only-with-script { display: none; } .only-without-script { display: block; } </style> </noscript> 

o preferisco aggiungere una class al corpo (posizionare il tag <script> nella parte superiore del corpo e non utilizzare l'evento .ready):

 <head> <style type="text/javascript"> body.has-script .something-not-ajaxy { display: none; } input.ajaxy-submit { display: none; } body.has-script input.ajaxy-submit { display: inline; } </style> </head> <body> <script type="text/javascript"> document.body.className += ' has-script'; </script> <!-- the rest of your page --> </body> 

Per le situazioni identiche alla tua, solitamente metto il button di invio attorno a un tag <noscript> . Nessuno l'ha suggerito, quindi non so se sia considerata una ctriggers pratica intorno a queste parti, ma è quello che uso e funziona per me.

Se si desidera solo un nodo visibile quando Javascript è abilitato, si potrebbe fare in testa:

 <noscript> <style type="text/css"> .js-enabled { display: none; } </style> </noscript> 

E poi dare agli elementi solo Javascript una class di js-enabled .

Proprio come ha detto David, è ansible aggiungere un Javascript, che aggiunge un foglio di stile per hide tutti gli elementi html "inutili":

 <head> ... <script type="text/javascript" language="javascript"> document.write('<style type="text/css"> .disabled-if-javascript { display: none; } </style>'); </script> </head> ... 

Se Javascript è triggersto, tutti gli elementi della class "disabled-if-javascript" vengono nascosti, prima che il corpo sia addirittura caricato. Basta aggiungere questa class a tutti gli elementi che devono essere nascosti, se javascript è abilitato. Potresti anche avere bisogno di una class enabled-if-javascript che fa il contrario, per mostrare alcuni elementi nascosti per non-javascript. Forse è necessario aggiungere " !importnt " alla tua definizione di stile lì, per ignorare le regole esistenti (non javascript).

Posso pensare a due methods:

1 – Pre-rilevare se Javascript è abilitato e salvare le informazioni in un cookie / session. Questo potrebbe essere fatto sulla prima pagina e dovrebbe eliminare la maggior parte degli sfarfallamenti.

2 – Utilizzare il plugin livequery , che rileva gli elementi mentre vengono aggiunti al DOM. È ansible eseguirlo correttamente quando Javascript termina il caricamento, che dovrebbe essere molto prima del documento (è in testa).

 $('.with_js_disabled').livequery(function() { $(this).hide(); }); 

Solo un pensiero: non so se questo functionrà, ma potresti provare a mettere qualche Javascript nella testina del documento per scrivere un elemento di stile CSS che nascondesse il button.

Una cosa semplice da provare: aggiungere <script>jQuery.ready();</script> proprio prima di chiudere il tag corporeo.

Questo obbligherà tutti i legami all'evento "pronto" al fuoco. E se li fai fuoco alla fine del documento, il DOM è caricato e pronto per andare, anche se l'evento onDomContentLoaded "nativo" non è ancora stato licenziato.

Questo funziona di solito per me quando voglio togliere la sfarfallio, specialmente in IE / win, poiché IE ha il proprio emulatore domready nell'evento "pronto" di jQuery.