2016-06-23 10 views
0

Ich bin Klassenname auf <A> Elemente (im Original-HTML-Format), unter denen SVG-Elemente angehängt werden, wie sie mit $ .get geladen werden. Die SVG-Elemente haben Stile, die in Chrome nicht angewendet werden, es sei denn, ich mache etwas, das ein erneutes Rendern erzwingt. Zum Beispiel das Aktivieren/Deaktivieren eines Kontrollkästchens für ein Stilattribut in der Entwickleransicht oder die Verwendung von Brackets-IDE und das Ändern von CSS (wodurch Brackets unser gesamtes CSS zerreißt und für jedes eingegebene Zeichen ersetzt).Umgang mit Chrome-Rendering dynamisch Elemente mit unvollständigen CSS hinzugefügt

Wenn ich den Klasse hinzufügen-Code auf setTimeout, mit mindestens 80 ms Intervall, funktioniert es. In IE11, Edge, Safari und Firefox funktioniert es ohne diese Umgehung. Laut Netzwerkbereich wird CSS vor den Skripts geladen (auch versucht, sie an den Schwanz statt an den Kopf zu platzieren). Dies ist ein Problem von Chrome, das die Rendersequenz nicht richtig verwaltet (am ehesten versucht, mit minimalem Render-Algorithmus zu schlau zu sein) arbeitet gegen mich).

Wie gehe ich richtig damit um?

Dies ist ein working version, funktioniert, weil ich die Stile, die normalerweise mit jQuery angewendet werden hart-codiert (in der Produktion würde ich diese Server-Seite rendern, aber es ist keine befriedigende Lösung).

Hier ist der broken version

Sie können überprüfen, dass die Linien 55-64 in navigation.js in eine setTimeout bewegen wird es funktioniert.

Mit Chrome Version 51.0.2704.103 (64-Bit) auf Mac OS X

Edit: relevante HTML und JS wie gewünscht, die oben für vollständige Bild Links.

index.htm

<html> 
    <head> 
    <link rel="stylesheet" type="text/css" href="styles.css"></link> 
    <script type="text/javascript" src="scripts/jquery.min.js"></script> 
    <script type="text/javascript" src="scripts/navigation.js"></script> 
    </head> 

<body> 
    <header> 
    <div id="logo" class="icon" data-src="images/logo.svg"></div> 

    <nav data-src="images/navigation.svg"> 
     <a href="index.htm">news</a> 
     <a href="articles.htm">articles</a> 
     <a href="projects.htm">projects</a> 
     <a href="about.htm">about</a> 
    </nav> 

Navigation.js

$(document).ready(function() { 
    loadNavigationButtons(); 
}); 

function loadNavigationButtons() { 
    var buttonParts = 
     [ 
     "matte", 
     "border", 
     "highlight", 
     "icon", 
     "selection" 
     ]; 

    return $.Deferred(function(callback) { 
    $("nav a").each(function(index) { 
     var navigationIconSet = $(this) 
     .closest("nav[data-src]") 
     .attr("data-src"); 

     var buttonName = $(this).text(); 
     $(this).text(""); 

     if (document.URL.indexOf($(this).attr("href")) != -1) { 
     // Add navigation-selected class to <a> 
     $(this).addClass("navigation-selected"); 
     } else { 
     // Add navigation-unselected class to <a> 
     $(this).addClass("navigation-unselected"); 
     } 

     for (var partIndex in buttonParts) { 
     loadIcon(
      // Prepend to this element. 
      $(this), 

      // Attempt to find a part for this specific button. 
      navigationIconSet + "#" + buttonName + "-" + buttonParts[partIndex], 

      // Fallback to generic part name. 
      navigationIconSet + "#" + buttonParts[partIndex], 

      // Class to apply. 
      "navigation navigation-" + buttonParts[partIndex] 

      // Not passing callback parameter 
     ); 
     } 

     // Append button text. 
     $("<div></div>") 
     .text(buttonName) 
     .addClass("navigation navigation-text") 
     .appendTo($(this)); 
    }); 

    callback.resolve(); 
    }); 
} 

function loadIcon($container, iconUri, fallbackUri, classToApply, callbackParameter) { 
    if (~iconUri.indexOf("#")) { 
    var sourceComponents = iconUri.split("#"); 
    var fallbackComponents; 

    if (fallbackUri) { 
     fallbackComponents = fallbackUri.split("#"); 

     // Support fallback only within the same icon set. 
     if (sourceComponents[0] != fallbackComponents[0]) { 
     return $.Deferred(function(callback) { 
      callback.reject($container, null, callbackParameter) 
     }); 
     } 
    } else { 
     fallbackComponents = [null, null]; 
    } 

    return loadIconFromDefinition(
     $container, 
     sourceComponents[0], 
     sourceComponents[1], 
     fallbackComponents[1], 
     classToApply, 
     callbackParameter); 
    } else { 
    return loadIconFromFile(
     $container, iconUri, classToApply, callbackParameter); 
    } 
} 

function loadIconFromFile($container, iconUri, classToApply, callbackParameter) { 
    return $.Deferred(function(callback) { 
    $.get(iconUri).done(function(icon) { 
     callback.resolve(
     $("svg", icon).prependTo($container), 
     null, 
     callbackParameter); 
    }); 
    }); 
} 

function loadIconDefinition(definitionUri) { 
    if (!loadIconDefinition.loaded) { 
    loadIconDefinition.loaded = {}; 
    } 

    if (loadIconDefinition.loaded[definitionUri]) { 
    return loadIconDefinition.loaded[definitionUri]; 
    } 

    loadIconDefinition.loaded[definitionUri] = 
    $.Deferred(function(callback) { 
     loadIconFromFile($("body"), definitionUri) 
     .then(function($loaded) { 
     // Hide definition after it's loaded. 
     $loaded.get(0).setAttributeNS(null, "style", "display:none"); 
     callback.resolve($loaded); 
    }); 
    }); 

    return loadIconDefinition.loaded[definitionUri]; 
} 

function loadIconFromDefinition(
$container, definitionUri, groupName, fallbackGroupName, classToApply, callbackParameter) { 
    return $.Deferred(function(callback) { 
    loadIconDefinition(definitionUri).then(function($loaded) { 
     if (fallbackGroupName && 
      !$loaded.find("#" + groupName).length) { 
     groupName = fallbackGroupName; 
     } 
     callback.resolve(
     $("<svg class=\"" + classToApply + "\"><use xlink:href='#" + groupName + "'></use></svg>") 
     .prependTo($container), 
     $loaded, 
     callbackParameter); 
    }); 
    }); 
} 
+0

Kein Code zu zeigen? – evolutionxbox

+0

Raise einen Chrome-Bug auf ihrem Bugtracker. –

+0

Ich konnte ein jsFiddle nicht veröffentlichen, da externe Ressourcen für die Demo benötigt werden (in diesem Fall eine kleine .svg). Ich wurde gewarnt, dass die Cross-Site-Anfrage nicht funktionieren würde. –

Antwort

0

Ich fühle mich wie diese Frage genügend Zeit im Fegefeuer verbracht.

Vorgeschlagene Umgehungen:

  • Halten Sie das Hinzufügen Kinder dynamisch, aber immer gesetzt Mutterelementklassen auf Server-Seite. Verwenden Sie im Fall von ASP.net einen Razor-Ausdruck, der kurzen HTML-Code für die fraglichen übergeordneten Elemente darstellt, wobei das Klassenattribut bereits festgelegt ist, bevor der Browser die Seite erhält. Dies ist der Workaround, den ich ausgewählt habe.
  • Element (e) in Frage stellen, bis setTimeout mit genügend hoher Verzögerung verstrichen ist, wodurch alle erforderlichen Klassen gesetzt und die Elemente zum Reduzieren des Flackerns eingeblendet werden. Benutzererfahrung weiter geglättet werden durch eine Ladefortschrittsbalken in einem „Dialog“ mit, die den Rest der Seite dimmt und geht sie zu verblassen in

Nicht von dieser Lösung erreicht.

  • Suche ein Ereignis oder eine Promise, die wir einbinden können, wenn sich der Browser in einem Zustand befindet, in dem das Aktualisieren des Klassenattributs für DOM-Elemente das erneute Rendern auslösen kann.

Sonstiges:

  • Filed Chromium bug, diese Situation zu beschreiben ... Vielleicht in 5 Jahren wird es fixiert werden.
Verwandte Themen