
Abstraktion ist ein wichtiges Konzept in jeder Sprache. Man kann CSS als eine Möglichkeit betrachten, das Design vom Inhalt einer Website zu abstrahieren. Das macht den Code für beides wesentlich einfacher zu lesen, zu verstehen und zu warten. Javascript ist eine Möglichkeit, die Funktionalität einer Website zu abstrahieren, und jQuery eine weitere Abstraktion, die gängige Aufgaben viel, viel einfacher macht. Das Schreiben von Plugins für jQuery ist eine noch tiefere Abstraktion, die Ihr jQuery einfacher zu schreiben und zu verstehen macht.
Um diese Idee zu veranschaulichen, bauen wir ein jQuery-Plugin. Während wir dabei sind, kann es auch etwas Nützliches sein! Wir werden es MaxSide nennen. Die Idee hier ist, jedes beliebige Seitenelement zu nehmen und es so zu verkleinern, dass die Länge seiner längsten Seite einen von Ihnen festgelegten Wert erhält. Wenn Sie beispielsweise ein Bild haben, das 300x180 Pixel groß ist, könnten Sie MaxSide darauf mit einem Wert von 100 aufrufen und das resultierende Bild wäre 100x60 Pixel groß (es behält sein Verhältnis).
Legen wir los.
Ohne Plugin
Legen wir drei Bilder auf die Seite, eines 200x200px, eines 200x50px und eines 50x200px.
<body>
<img src="images/200x200.jpg" alt="" />
<img src="images/200x50.jpg" alt="" />
<img src="images/50x200.jpg" alt="" />
</body>
Wir möchten, dass auf diese Bilder etwas jQuery angewendet wird, sodass jede ihrer längsten Seiten 100 wird. 200x200px wird zu 100x100px, 200x50px wird zu 100x25px und 50x200px wird zu 25x100px.
Fügen wir jQuery zu unserer Seite hinzu (im <head>-Bereich) und schreiben den Code, der dies bewirkt.
<script type="text/javascript" src="../jquery-1.2.6.min.js"></script>
<script type="text/javascript">
// don't run until all images are loaded
$(window).bind("load", function() {
// run on every image on the page
$("img").each(function(){
// set a variable for this, quicker
var $this = $(this);
// maximum length is hard-coded here
var $maximum = 100;
// jQuery 1.2.6 has "dimensions" built-in
var $thewidth = $(this).width();
var $theheight = $(this).height();
if ($thewidth >= $theheight) {
if ($thewidth >= $maximum) {
$(this).attr({
width: $maximum
});
}
}
if ($theheight >= $thewidth) {
if ($theheight >= $maximum) {
$(this).attr({
height: $maximum
});
}
}
});
});
</script>
In einfacher Sprache bedeutet dies: „Betrachte jedes Bild auf der Seite. Wenn es breiter als hoch ist, mache seine Breite 100. Wenn es höher als breit ist, mache seine Höhe 100.“
Funktioniert wie am Schnürchen, siehe das Beispiel ohne das Plugin.
Mit Plugin
Bei der „ohne Plugin“-Methode gibt es ein paar Probleme. Erstens verschmutzt es unsere Seite wirklich. Wir sollten all diesen Code aus unserer HTML-Datei entfernen, da dort unser Inhalt lebt und wir hier versuchen, zu abstrahieren. Zweitens ist die „MaxSide“ hier hartcodiert. Was ist, wenn wir dieses gleiche Stück auf der Seite verwenden möchten, aber einen anderen MaxSide-Wert verwenden möchten? Wir müssten sehr ähnlichen Code wiederholen. Nie eine gute Idee.
jQuery macht es uns leicht, unsere eigenen Funktionen in Form von Plugins zu schreiben, um Code wie diesen zu abstrahieren. Schauen Sie sich den neuen Code in unserem Header an, der das Plugin verwendet.
<script type="text/javascript" src="jquery-1.2.6.min.js"></script>
<script type="text/javascript" src="jquery.maxside.js"></script>
<script type="text/javascript">
$(window).bind("load", function() {
$("img").maxSide({ maxSide: "100" });
});
</script>
Viel einfacher, oder? Aber nicht nur einfacher, sondern wir könnten jetzt die maxSide-Funktion auf verschiedenen Seitenelementen und mit unterschiedlichen Werten aufrufen.
jQuery.fn.maxSide = function(settings) {
// if no paramaters supplied...
settings = jQuery.extend({
maxSide: 100
}, settings);
return this.each(function(){
var maximum = settings.maxSide;
var thing = jQuery(this);
var thewidth = thing.width();
var theheight = thing.height();
if (thewidth >= theheight) {
if (thewidth >= maximum) {
thing.attr({
width: maximum
});
}
}
if (theheight >= thewidth) {
if (theheight >= maximum) {
thing.attr({
height: maximum
});
}
}
});
};
Beachten Sie, dass der Code hier nicht wirklich anders ist. Es gibt jedoch ein paar wichtige Dinge zu beachten.
- Dieses Plugin ist so konzipiert, dass es bei jedem Seitenelement, auf das Sie es anwenden, seine Arbeit verrichtet. Daher die „each“-Funktion. Wenn Sie ein Plugin schreiben möchten, das nur ein einzelnes Seitenelement beeinflusst, ist es noch einfacher. Lassen Sie die „each“-Funktion weg und schreiben Sie normales jQuery, aber fügen Sie am Ende eine Zeile „return this;“ hinzu.
- Der „settings“-Teil am Anfang der Funktion behandelt den Fall, in dem der Funktion kein Parameter übergeben wird (er ist standardmäßig auf 100px eingestellt). Sie könnten diese Funktion technisch mit nur .maxSide() aufrufen, wenn Sie möchten.
- Wenn Sie diese Funktion für Bilder verwenden, sollte sie nur nach dem Fensterladeereignis aufgerufen werden. Viele jQuery-Funktionen werden stattdessen aufgerufen, wenn der DOM bereit ist, was viel schneller ist, aber die Breiten- und Höhenberechnungen schlagen fehl, wenn die Bilder noch nicht vollständig geladen sind (sehr wahrscheinlich).
- Variablen innerhalb des Plugins benötigen nicht das „$“.
Demo ansehen Beispiel herunterladen
Sauber und prägnant. Exzellentes Tutorial zum Erstellen von Plugins.
$(window).bind("load", function() {
//Etwas passiert hier
}
Ich muss, dass das, was passiert, passiert, nachdem die Bilder geladen wurden, wie Sie angegeben haben,
aber in Firefox passiert es nur, nachdem der DOM geladen wurde (bevor die Bilder geladen wurden).
Ich benutze hauptsächlich Opera und dort ist es in Ordnung.
PS: Der Unterschied in meinem Code ist, dass ich Bilder per CSS als Hintergrund verwende, also berücksichtigt Opera sie anscheinend, Firefox aber nicht.
Wenn Sie etwas tun möchten, wenn der DOM bereit ist
Wenn Sie etwas tun möchten, wenn die Seite geladen ist
Meinen Sie, dass es selbst bei der Verwendung der zweiten Option zu früh feuert? Wenn das der Fall ist, ist das ein interessantes Problem, auf das ich noch nie gestoßen bin.
Ja, es ist zu früh.
Aber nur in Firefox, Opera und IE ist es in Ordnung. Und ich glaube, es betrifft nur die Bilder, die ein Hintergrund sind (und auf meinen Websites sind fast alle Bilder normalerweise Hintergrund).
Und ich habe Firefox noch nicht aktualisiert – ich mag es irgendwie nicht :)
Hah, es ist in Firefox3 behoben.
Ok, das ist gut ... Ich muss keine seltsame Lösung schreiben.
Entschuldigen Sie die Rechtschreibung des letzten Kommentars :)
Gut für dieses Plugin. Bitte beachten Sie, dass die Downloadseite derzeit einen 404-Fehler liefert. Ich musste die js von der Beispielseite herunterladen.
Ein kleiner Anwendungstipp: Da ich es mit einem großen Logo ausprobiert habe, stellen Sie sich vor, Sie verwenden dieses Plugin dort, wo es ein Logo gibt, das vor dem Hochladen nicht verkleinert werden kann und sehr groß sein kann… Beim Laden der Seite erscheint zuerst die große Bildversion, dann wird sie dank des Plugins auf den richtigen Wert skaliert. Wenn Sie display:none festlegen und $(“#logo”).show(); nach $(“#logo”).maxSide({ maxSide: “xx” }); hinzufügen, bleibt Ihr Logo bis zur Skalierung verborgen :)
@Tinny: Sicher, das ist eine Möglichkeit, dieses Problem zu lösen. Das Problem tritt jedoch auf, wenn der Benutzer Javascript deaktiviert hat, dann sieht er die Bilder überhaupt nicht. Das liegt in Ihrem Ermessen, ist aber im Allgemeinen eine schlechte Idee. Eine andere Möglichkeit wäre, das Bild auszublenden, wenn der DOM bereit ist, aber dann maxSize erst aufzurufen, wenn die Seite geladen ist.
Das stimmt. Mit Ihrer Lösung wäre es perfekt. Vielleicht kann die maxside-Funktion vor dem show noch besser sein (im Millisekundenbereich...)
Ein schönes Feature wäre ein anderer Maximalwert für Breite und Höhe.
Exzellentes Plugin. Gibt es eine Möglichkeit, es so zu modifizieren, dass es nur Bilder verkleinert, die eine bestimmte Breite überschreiten? Zum Beispiel jedes Bild, das breiter als 300 Pixel ist, auf 300 Pixel Breite verkleinern. Alles, was kleiner als 300 Pixel breit ist, wird nicht skaliert.
Das sieht großartig aus und ist dem sehr nahe, was ich suche.
Gibt es eine Möglichkeit, diesen Code so zu modifizieren, dass er alle Bilder in einem div sucht und wenn sie breiter als 600 Pixel sind oder zu breit für das enthaltende div sind, sie auf nur 500 Pixel Breite skaliert und die Proportionen beibehält?
Ich suche überall nach dieser Art von Funktionalität.
Jede Hilfe wäre sehr dankbar! :)
AAron, ich denke, Sie müssen dieses Plugin mit dem Dimensions-Plugin http://docs.jquery.com/Plugins/dimensions kombinieren und ein each für alle Bilder innerhalb des div durchführen, dann basierend auf der Größe.
etwas wie
$.(“#IDDESDIV”).children(“img”).each(function(){
if ((this).innerWidth() > 600)
{
$(this).maxSide({ maxSide: “500” });
}
});
Habe es nicht ausprobiert, aber ich denke, es sollte funktionieren.
Vielen Dank, Tinny, für die schnelle Antwort! Wow!
Ich habe das Dimensions-Plugin heruntergeladen und den obigen Code ausprobiert, erhalte aber einen Fehler.
Das habe ich.
jQuery(document).ready(function(){
$.(“.Content”).children(“img”).each(function(){
if ((this).innerWidth() > 550)
{
$(this).maxSide({ maxSide: 500 });
}
});
});
Der Fehler lautet „Expected Identifier“ in Zeile 5, was diese Zeile ist.
if ((this).innerWidth() > 550)
Haben Sie Ideen oder Hilfe, die sehr geschätzt würde!
Vielen Dank nochmals für die Hilfe!
Ich habe gerade erkannt, dass ich auch Ihr Plugin maxside verwenden muss... Huch!
ABER... ich habe Ihr Plugin zusammen mit dem Dimensions-Plugin eingebunden und den Aufruf geändert in...
$(window).bind("load", function() {
$.(“.Content .p-20”).children(“img”).each(function(){
if ((this).innerWidth() > 550) {
$(this).maxSide({ maxSide: “500” });
}
});
});
Aber ich bekomme immer noch den gleichen Fehler.