2013-02-25 3 views
7

Das bringt mich immer. Nachdem ich alle schönen UI-Elemente auf einer Webseite initialisiert habe, lade ich einige Inhalte ein (zum Beispiel in ein Modal oder Tabs) und der neu geladene Inhalt hat nicht die UI-Elemente initialisiert. zB:Welches ist das bevorzugte Muster zum erneuten Binden von jQuery-artigen UI-Schnittstellen nach dem Laden von AJAX?

$('a.button').button(); // jquery ui button as an example 
$('select').chosen(); // chosen ui as another example 
$('#content').load('/uri'); // content is not styled :(

Mein aktueller Ansatz ist es, eine Registrierung von Elementen zu erstellen, die Bindung muß:

var uiRegistry = { 
    registry: [], 
    push: function (func) { this.registry.push(func) }, 
    apply: function (scope) { 
    $.each(uiRegistry.registry, function (i, func) { 
     func(scope); 
    }); 
    } 
}; 

uiRegistry.push(function (scope) { 
    $('a.button', scope).button(); 
    $('select', scope).chosen(); 
}); 

uiRegistry.apply('body'); // content gets styled as per usual 

$('#content').load('/uri', function() { 
    uiRegistry.apply($(this)); // content gets styled :) 
}); 

ich nicht die einzige Person mit diesem Problem sein kann, so gibt es keine besseren Muster um das zu tun?

+1

Ihre Methode sieht zumindest besser aus als die meisten, sie zielt nur auf neue Elemente, was gut ist. Ich hätte nicht "apply" als Namen der Eigenschaft verwendet, aber das könnte verwirrend sein. –

+0

Einverstanden, deine ist eine gute Methode. Das ist so ziemlich das, was jQuery Mobile macht, wenn das 'create' -Ereignis für ein Container-Element ausgelöst wird, außer dass es' data -'-Attribute anstelle von Klassen verwendet, um die Elemente zu vergleichen und die Widgets zu bestimmen, die verwendet werden, um sie zu erweitern. –

+0

Danke. Ich werde den jQuery Mobile-Code ausprobieren, um zu sehen, ob sie dort etwas Interessantes tun. – stephenfrank

Antwort

0

bester Ansatz all ui-Code in einer Funktion -Auch besser eine separate Datei wickeln wird - und auf Ajax-Last nur die Funktion als Rück Anruf angeben .. Hier ist ein kleines Beispiel

Lassen Sie sich sagen Sie Code haben, die Textfelder mit Klasse someclass-for-date zu einem Datumsauswahl dann den Code wie folgt ..

$('.someclass-for-date').datepicker(); 

hier aussehen würde binden, was ich denke,

function datepickerUi(){ 
    $('.someclass-for-date').datepicker(); 
} 
0 am besten

und hier ist es, was die Last wie

$('#content').load('/uri', function(){ 

    datepickerUi(); 

}) 

oder Sie am Ende Ihres html in Script-Tag laden .. (aber ich nicht so, Cuz es ist schwieriger zu debuggen)

aussehen sollte

hier einige Tipps

halten sie Ihren Code und CSS-Stile so sauber wie möglich .. was bedeutet, dass für Textfelder, die Datumsauswahl geben ihnen eine Klasse überall auf Ihrer Webseite .. mit dieser Rate gesamten Code sein sollte wird sauber und pflegeleicht sein.

Lesen Sie mehr auf OOCss das wird klar, was ich meine.

meist mit jquery alles über die Organisation ist ... geben ihm einige Gedanken und Sie bekommen, was Sie mit einer Zeile Code ..

bearbeiten

hier getan wollen, ist eine js Geige mit etwas ähnliches zu deinem aber ich denke, dass es ein bisschen sauberer ist click here

1

Meine Antwort ist im Grunde das selbe wie das, das du umreißst, aber ich benutze jquery Ereignisse, um den Installationscode auszulösen. Ich nenne es das "Moddom" -Ereignis.

Wenn ich den neuen Inhalt zu laden, auslösen ich meine Veranstaltung auf dem parent:

parent.append(newcode).trigger('moddom'); 

Im Widget, ich sehe für dieses Ereignis:

$.on('moddom', function(ev) { 
    $(ev.target).find('.myselector') 
}) 

Dies wird stark vereinfacht das Ereignis zu illustrieren Methode.

In Wirklichkeit wickle ich es in eine Funktion domInit, die ein Selektor und ein Callback-Argument dauert.Es ruft den Callback auf, sobald ein neues Element gefunden wird, das mit dem Selektor übereinstimmt - mit einem jquery-Element als erstem Argument.

Also in meinem Widget-Code, kann ich dies tun:

domInit('.myselector', function(myelement) { 
    myelement.css('color', 'blue'); 
}) 

Dominit setzt Daten auf dem betreffenden Element „Dominit“, die eine Registrierung der Funktionen, die bereits angewendet wurden.

Meine volle Dominit Funktion:

window.domInit = function(select, once, callback) { 
    var apply, done; 
    done = false; 
    apply = function() { 
    var applied, el; 
    el = $(this); 
    if (once && !done) { 
     done = true; 
    } 
    applied = el.data('domInit') || {}; 
    if (applied[callback]) { 
     return; 
    } 
    applied[callback] = true; 
    el.data('domInit', applied); 
    callback(el); 
    }; 
    $(select).each(apply); 
    $(document).on('moddom', function(ev) { 
    if (done) { 
     return; 
    } 
    $(ev.target).find(select).each(apply); 
    }); 
}; 

Jetzt müssen wir nur daran denken, die ‚MODDOM‘ Ereignis auslösen, wenn wir dom Änderungen vornehmen.

Sie könnten dies vereinfachen, wenn Sie nicht die "einmal" -Funktionalität benötigen, was ein ziemlich seltener Randfall ist. Es ruft den Rückruf nur einmal auf. Zum Beispiel, wenn Sie etwas Globales tun wollen, wenn ein passendes Element gefunden wird - aber es muss nur einmal passieren. Vereinfachte ohne getan Parameter:

window.domInit = function(select, callback) { 
    var apply; 
    apply = function() { 
    var applied, el; 
    el = $(this); 
    applied = el.data('domInit') || {}; 
    if (applied[callback]) { 
     return; 
    } 
    applied[callback] = true; 
    el.data('domInit', applied); 
    callback(el); 
    }; 
    $(select).each(apply); 
    $(document).on('moddom', function(ev) { 
    $(ev.target).find(select).each(apply); 
    }); 
}; 

Es scheint mir Browser eine Möglichkeit hat, sollte einen Rückruf zu erhalten, wenn die dom Veränderungen, aber ich habe noch nie von so etwas gehört.

+0

Ich schaue mir das genauer an. – stephenfrank

Verwandte Themen