Das ist eine kleine Funktion, die das Leben und Programmieren viel einfacher macht. Falls man Firebug installiert hat, kann man mit console.log(nachricht)
im JavaScript-Code eine Nachricht in der Firebug-Konsole ausgeben.
Beiträge der Kategorie javascript
Erweiterung jQuery Carousel
Ich wollte das jQuery-Carousel, das auf dieser Seite mit vielen schönen Beispielen vorgestellt wird, ein wenig anpassen, und zwar sollte es mehr möglichkeiten geben, die Buttons und die Paginierung zu positionieren, als bisher. So sollte es möglich sein, dass die Prev/Next-Buttons um die Paginierung herum gepackt werden können.
jQuery Carousel
Als erstes habe ich für den Parameter btnsPosition weitere Optionen hinzugefügt: after, paginationOutside und paginationInside. Bei after werden die Buttons beide hinter das Carousel gepackt, bei paginationOutside werden die Buttons direkt vor und hinter die Paginierung gepackt und bei paginationInside vor und hinter die Paginierung, allerdings innerhalb des umschließenden Divs.
if(params.btnsPosition == "after") { params.prevBtnInsert = "insertAfter"; params.nextBtnInsert = "insertAfter"; } if(params.btnsPosition == "paginationOutside") { params.prevBtnInsert = "insertBefore"; params.nextBtnInsert = "insertAfter"; params.btnsPosition = "pagination"; } if(params.btnsPosition == "paginationInside") { params.prevBtnInsert = "prepend"; params.nextBtnInsert = "append"; params.btnsPosition = "pagination"; }
// Prev Button if ($.isFunction(env.params.prevBtnInsertFn)) { env.$elts.prevBtn = env.params.prevBtnInsertFn(env.$elts); } else { if(env.params.pagination && params.btnsPosition == "pagination") { env.$elts.prevBtn = $(params.prevBtn)[params.prevBtnInsert](env.$elts.pagination); } else if (params.btnsPosition == "outside"){ env.$elts.prevBtn = $(params.prevBtn)[params.prevBtnInsert](env.$elts.carousel); } else { env.$elts.prevBtn = $(params.prevBtn)[params.prevBtnInsert](env.$elts.wrap); } } // Next Button if ($.isFunction(env.params.nextBtnInsertFn)) { env.$elts.nextBtn = env.params.nextBtnInsertFn(env.$elts); } else { if(env.params.pagination && params.btnsPosition == "pagination") { env.$elts.nextBtn = $(params.nextBtn)[params.nextBtnInsert](env.$elts.pagination); } else if (params.btnsPosition == "outside"){ env.$elts.nextBtn = $(params.nextBtn)[params.nextBtnInsert](env.$elts.carousel); } else { env.$elts.nextBtn = $(params.nextBtn)[params.nextBtnInsert](env.$elts.wrap); } }
Die letzten beiden Optionen werden nur dann ausgewertet, wenn die Paginierung an ist.
jQuery Validation
Um Formulare Client-seitig zu validieren, gibt es ein Plugin für jQuery: jQuery Validation
Damit ist es möglich, Formulare vor dem Absenden fast automatisch zu validieren, die Ausgabe der Fehlermeldungen kann auch gesteuert werden. Außerdem ist es möglich, eigene Validierungsfunktionen hinzuzufügen. Hier sind die Beispiele, nach denen ich länger suchen musste.
Validieren eines Felder in Abhängigkeit eines anderen:
Das Feld number_nights ist nur dann obligatorisch, wenn die Checkbox ‚checkbox‘ angekreuzt ist.
$("#dateForm").validate({ rules: { "data[number_nights]" : { required: function() { return $('#checkbox').is(":checked"); }, min: 1, digits: true },
Definieren einer eigenen Validierungsfunktion:
Die Felder number_singlerooms und number_doublerooms sind beide obligatorisch und dürfen nur Zahlen (digits) enthalten. Dadurch ist aber nicht sichergestellt, dass in Summe mindenstens 1 rauskommt, daher definiere ich eine eigene Validierungsfunktion und weise sie den Feldern hinzu.
jQuery.validator.addMethod("minNumberRooms", function(value, element) { var sumRooms = $('#field_number_singlerooms').val() + $('#field_number_doublerooms').val(); return this.optional(element) || (sumRooms > 0); }, "Bitte wählen Sie mindesten ein Zimmer"); $("#dateForm").validate({ rules: { "data[number_singlerooms]" : { required: true, digits: true, minNumberRooms : true }, "data[number_doublerooms]" : { required: true, digits: true, minNumberRooms : true },
Quelle: http://stackoverflow.com/questions/241145/jquery-validate-plugin-how-to-create-a-simple-custom-rule
Linksammlung JavaScript
jQuery Plugins
- Color Box: die jQuery Alternative zu Lightbox (die auf Prototype basiert), sehr einfach anzuwenden
- Confirm: eine Bestätigungsfunktion, dabei taucht neben einem Link zum Löschen die Abfrage auf, mit der man die auszuführende Aktion bestätigt
- Numeric Stepper: kleines Eingabefeld, versehen mit Button, ermöglicht das erhöhen/verringern eines Wertes um einen vorher angebenen Wert (Schritweite), kennt man als Flex-Komponente
Hintergrund Bilder Caching im IE erzwingen
Im IE werden die Hintergrundbild unter bestimmten Umständen nicht gecached, was bei einer Seite, die z.B. AJAX verwendet, dazu führen kann, dass der Hintergrund erst später geladen wird, oder weitere Hintergründe fehlen. Die „Lösung“ ist dieses kleine Skript, was im IE tatsächlich zu einer Verbesserung führt.
Allerdings habe ich nach dem Schnipsel erneut gesucht und noch weitere Ausführungen gefunden:
http://ajaxian.com/archives/no-more-ie6-background-flicker
JavaScript-Fehler in sr_feuser_register 2.5.21
In der letzten Version von sr_feuser_register wird ein JavaScript-Fehler gemeldet, wenn man ein Formular, dass MD5-Verschlüsselte Felder enthält (Passwort und Wiederholung) absendet. Der Fehler besteht darin, dass die Funktion (vielleicht wegen der Übersichtlichkeit) boolsche Werte groß geschrieben (als FALSE und TRUE) zurückgeben. Diese sind somit in JavaScript keine reservierten Wörter und werden als Variablen interpretiert. Die Lösung ist eigentlich ganz einfach – in der Klasse class.tx_srfeuserregister_marker.php nach FALSE suchen und in den zwei Funktion klein schreiben. Ich habe allerdings immer ein blödes Gefühl beim Patchen von Extensions.
Probleme mit upload_progress mit PHP
Ich hatte mal über Fileupload mit PHP berichtet:
Simpel mit PHP und mit AJAX
Das Prinzip an sich funktioniert, es gibt nur ein paar Dinge, die man beachten sollte.
Die Funktion zum Abfragen der Dateigröße gibt 0 oder nichts zurück, wenn die Datei, die hochgeladen wird, größer ist als die erlaubte maximale Größe definiert durch php.ini. D.h. wenn diese Grenze gering ist und man versucht eine Datei hochzuladen, die größer ist, gibt es keinen Fortschrittsbalken.
Lösung dafür habe ich noch keine gefunden, das Problem wird in diversen Foren angesprochen, kann aber anscheinend nicht gelöst werden.
Panorama mit JavaScript
Dieses Experiment ist schon ein wenig älter, trotzdem sehr schön. Jeder kennt Panoramen mit QuickTime oder Flash. Ich wollte eine Möglichkeit finden, das gleiche (wenn auch ein wenig simpler) mit JavaScript umzusetzen.
Beim Laden der Seite wird eine Funktion aufgerufen, die das Div, in dem gescrollt werden soll, ausmisst. Dieses Div wird mit drei Listenern versehen:
– beim Bewegen der Maus über das Div wird eine Variable gesetzt, dass gescrollt werden soll
– beim Bewegen der Maus aus dem Feld wird das Scrolling beendet
– beim Bewegen der Maus wird die Position ermittelt und falls die Variable „scrollActive“ gesetzt ist, wird das Hintergrundbild verschoben
Im ersten Beispiel reiht sich der Hintergrund unendlich aneinander und man kann somit unendlich scrollen.
JavaScriptScroll unendlich
Im zweiten Beispiel wird nicht mehr gescrollt, wenn der Hintergrund um einen bestimmten Wert verschoben worden ist, so dass man das Verhalten vom QuickTime-Panorama etwas simulieren kann.
JavaScriptScroll begrenzt
Fileupload Progress mit PHP und AJAX
Die Grundlagen dazu finden sich in dem Post davor, wo der Super-Simpel-Fileupload mit PHP erklärt worden ist. Das ist die Erweiterung des Beispiels, um den Fileupload auch ohne Reload üebrwachen zu können. Wie gesagt, die Beispiele, die ich gefunden habe, sind eigentlich ganz nett, aber haben meistens zu viel Code oder brauchen bestehende AJAX-Klassen, ich wollte ein Beispiel, das ohne weitere Dateien funktioniert. Ich habe es übrigends auch in eine Typo3-Extension gegossen.
Die Dateien im Beispiel davor habe ich alle mit dem Suffix _ajax versehen und bearbeitet. Das Formular bliebt, wie es ist, es kommt nur der Event-Handler onSubmit dazu, der nach dem Beginn des Uploads den Status abfragt. Das zweite iFrame, das sich ständig neugeladen hat, kommt auch raus, stattdessen werden hinter das Formular zwei divs gesetzt: response und response_counter. Im ersten wird der Ladebalken angezeigt und im zweiten will ich die Request zählen (einfach so), kann man nachher ausblenden. Das ist der Teil zwischen body-Start und -Ende.
$uid = rand(1000000,9999999);
?>
Dann braucht man noch einen AjaxRequest, den hab ich mir hier abgeschaut: http://www.w3schools.com/AJAX/ajax_server.asp. Beim Absenden des Formulars wird die Funktion upm_start mit er generierten Id aufgerufen (upm = upload progress manager), da werden alle Werte gespeichert und die Update-Funktion aufgerufen. Innerhalb der Update-Funktion wird progress_ajax mit der Upload-Id und einem zufälligen Wert aufgerufen (damit das Caching umgangen wird). Wenn die Antwort von progress_ajax in XML-Form zurückkommt, wird diese verarbeitet und es wird ein Ladebalken generiert. Danach wird mit einem Timeout die Funktion zur Fortschrittsabfrage erneut aufgerufen. Wenn der Upload fertig ist, wird aus dem iFrame heraus die Funktion upm_end aufgerufen, die die Request stoppt.
Zu beachten sind folgende Sachen:
Der IE mag es nicht, wenn man einen Request ein weiteres Mal verwendet, damit es keine Probleme gibt, muss die Callback-Funktion erneut bei onReadyStateChange hinzugefügt werden und zwar nach der Open-Anweisung.
Dann habe ich eine zusätzliche Abfrage eingebaut, um eventuelle Endlos-Schleifen zu vermeiden, es wird bei jedem leeren Request ein Zähler gesetzt und wenn dieser 100 erreicht, wird die Schleife gestoppt.
Wichtig bei der Rückgabe (progress_ajax.php) ist, dass man den Content-Type auf xml setzt, ansonsten steht die Eigenschaft responseXML nach der Rückgabe nicht zur Verfügung.
Man könnte auch setInterval verwendet, das hat aber den Nachteil, das die Requests gesendet werden unabhängig davon, ob der letzte zurückgekommen ist. Und so könnten mehrere Requests parallel unterwegs sein, was den Server auf Dauer und bei mehreren Benutzern verlangsamt.
function initAjax() {
if(window.ActiveXObject) {
try {
xmlHttp = new ActiveXObject(„Msxml2.XMLHTTP“);
} catch(e) {
try {
xmlHttp = new ActiveXObject(„Microsoft.XMLHTTP“);
} catch(e) {
return false;
}
}
} else if(window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
}
function upm_start(upload_id) {
upm_counter = 0;
upm_upload_id = upload_id;
upm_started = 1;
total_negative = 0;
document.getElementById(„response“).innerHTML = „“;
document.getElementById(„response_counter“).innerHTML = „“;
upm_update();
}
function upm_update() {
upm_counter++;
if(upm_started == 1 && total_negative < 100) {
document.getElementById("xajax_response_counter").innerHTML+= upm_counter;
var randNum = Math.ceil(Math.random()*1000);
xmlHttp.open("GET","progress_ajax.php?uid="+upm_upload_id+"&r="+randNum,false);
// set the readystatechange again for IE to reuse the object
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState==4 && xmlHttp.status == 200) {
displayProgress();
}
}
xmlHttp.send(null);
}
}
function displayProgress() {
document.getElementById("response_counter").innerHTML+= "| ";
response = xmlHttp.responseXML.documentElement;
var loaded = 0;
var total = -1;
var time = 0;
var speed = 0;
var est_sec = 0;
// Bytes loaded
try {
loaded = response.getElementsByTagName("loaded")[0].firstChild.data;
} catch(e) {}
// Bytes total
try {
total = response.getElementsByTagName("total")[0].firstChild.data;
} catch(e) {}
// PHP time() function value -> to check how often the request are send
try {
time = response.getElementsByTagName(„time“)[0].firstChild.data;
} catch(e) {}
// speed
try {
speed = response.getElementsByTagName(„speed“)[0].firstChild.data;
} catch(e) {}
// est_sec
try {
est_sec = response.getElementsByTagName(„est_sec“)[0].firstChild.data;
} catch(e) {}
//
if(total == -1) total_negative++;
var percent = Number(loaded/total*100).toFixed(2);
var width = Math.round(percent * 2.5);
var progress = „
progress+= „
„;
progress+= „
„;
document.getElementById(„xajax_response“).innerHTML = progress;
window.setTimeout(„upm_update()“,500);
}
function upm_end() {
document.getElementById(„response“).innerHTML = „“;
upm_started = 0;
}
function formatSeconds(sec) {
var min = Math.floor(sec/60);
var hour = Math.floor(min/60);
if(hour > 1) {
return hour+“ h „+min+“ m“;
} else if(min > 1) {
return min+“ m „+sec+“ s“;
} else {
return sec+“ s“;
}
}
function formatBytes(b) {
var kb = Number(b / 1024);
var mb = Number(kb / 1024);
var gb = Number(mb / 1024);
if(gb > 1) {
return gb.toFixed(2)+“ GB“;
} else if(mb > 1) {
return mb.toFixed(2)+“ MB“;
} else if(kb > 1) {
return kb.toFixed(2)+“ KB“;
} else {
return b.toFixed(2)+“ B“;
}
}
initAjax();
Das in den Header der result_ajax.php
window.parent.upm_end();
header('Content-Type: text/xml');
echo '‚;
$upload_id = $_GET[‚uid‘];
$xml = ‚‚;
echo $xml;
?>
UPDATE 26.August 2008: Hatte mit diesem Stückchen Code in den letzen Tagen tierische Probleme in den letzen Monaten. Zunächst mal funktionierte es nicht auf dem Mac – weder unter Firefox, noch unter Safari, nix. Hat mich wahnsinnig gemacht. Die Lösung war sehr dirty und nicht quick – ich musste den kompletten Upload Bar (in HTML) generieren und zurückgeben lassen, weil das Auswerten des XML-Objektes irgendwie nicht wollte. Soll auch ein bekanntes Problem sein, hab ich gehört.
Nun die nächste Problem: Unter Firefox 3 tats nicht. Also recherchiert – Firebug Bugs, Caching Probleme etc. Zum Glück gabs diesmal eine schöne Lösung, anstatt GET einfach POST zu verwenden:
xmlHttp.open(„POST“,“progress_ajax.php?uid=“+upm_upload_id+“&r=“+randNum,true);
Script Debugger für IE
http://blogs.msdn.com/ie/archive/2004/10/26/247912.aspx
Hab mal was gefunden zu Script Debugging in IE („Objekt erwartet“ ist einfach die dümmste Fehlermeldung überhaupt). Etwas scheisse, nicht zu vergleichen mit dem Debugger in Firefox, aber beser als gar nichts.
Neueste Kommentare