Ich war gerade in meinem Picasa Album unterwegs und mir fiel mal wieder ein, dass ich noch nicht über mein – mittlerweile nicht mehr neues – Autoradio geschrieben habe. Dabei gebe ich gerne kurzes Feedback zu guten Käufen.

Also, September letztens Jahres habe ich mir das JVC KD-411 in Rot gekauft. Ziel war ein hübscheres Autoradio (mein altes Modell hatte total hässliche Nippel-Knöpfe), dass USB kann und preisgünstig ist. Ich brauchte keine dutzenden Equalizer Einstellungen oder Features, kein farbiges 4″ Display oder andere Spielereien.

Ich habe mir also erst etliche Autoradio Tests (meins) und Meinungen zu Modellen unter 200€ angesehen. Schnell war klar, für ein Autoradio muss man nicht viel Geld auf den Tisch legen, wenn man keine HiFi-Fanatiker ist. Alle Grundfunktionen und Möglichkeiten und guter (in den Augen eines Laien) Sound ist schon für maximal 100€ zu haben.
Die Wahl fiel nach einigen Stunden Recherche also auf das JVC. Der Hersteller ist bekannt, keine No-Name Mist. Das KD-411 ist für 70€ zu haben und damit ein absoluter Preis-Leistungsknaller und für Jedermann erschwinglich. Coolerweise gab es das Modell in meiner Wagenfarbe, das Design finde ich ebenfalls ziemlich cool.

Ich habe das Radio also seit einem halbes Jahr in Verwendung und bis jetzt noch keine Unzufriedenheiten oder Probleme festgestellt.
In short: es ist leicht zu bedienen, unterstützt die wichtigsten Dateitypen, hat USB und AUX in der Front, 3 Equalizer Einstellung (Bass, Middle, Treble), viele Funktionen wie Repeat/Random (Einzeln/Folder/All), kommt mit Zubehör wie Rahmen und Klammern und hastenichgesehen.

Für den Preis bis jetzt also ein absolut erfolgreicher Kauf!
Der nächste Schritt ist dann wohl ein 1-DIN Radio mit ausfahrbarem Touch Display, DVD und son Kram. Die sind nämlich auch nicht so teuer wie ich erst dachte.

Ich bin ein Freund von bunten Statusmeldungen. „Speichern erfolgreich“, „Anmeldung fehlgeschlagen“, ein kleines Icon, schön farbig, user-friendly und ein bisschen Animations-Spielerei.

Das Coole ist: mit jQuery kann man eine solche Statusmeldung mit Style und Fading recht problemlos mit nur 1 Zeile realisieren!

Code
$.ajax({ type: 'POST', url: 'mailer.php', data:{'submit':'1','values':values}, success: function(data)
   {
	if($('#contact-wrapper .status').is(':hidden')) $('#contact-wrapper .status').html(data).addClass(data).fadeToggle().delay(3000).fadeToggle(function () { $(this).removeClass(data) }); /* 1 Zeile, ein Traum */
   } /* $.ajax success */
}); /* $.ajax */

(Update 1.1)

Die $.ajax Funktion liefert einen Rückgabewert der mailer.php. Dieser Rückgabewert ist entweder „success“ oder „error“. Das ließe sich natürlich ausbauen.
Die Statusmeldung ist mit CSS gestyled, wird eingeblendet, enthält einen bestimmten Text (in diesem Beispiel nur „success“ oder „error“), bleibt ein paar Sekunden stehen und wird dann ausgeblendet.

.status {
	display: none;
	border: 1px solid; 
}
.status.success {
	background: #DFF2BF url("img/10er-iconset.png") no-repeat 0px -38px;
	color: #4F8A10;
}
.status.error {
	background: #FFBABA url("img/10er-iconset.png") no-repeat 0px -58px;
	color: #D8000C;
}

Sehen wir uns die Codezeile im Detail an:

if($('#contact-wrapper .status').is(':hidden')) {
  $('#contact-wrapper .status').html(data)
    .addClass(data)
	  .fadeToggle()
	    .delay(3000)
		  .fadeToggle(function () { 
		    $(this).removeClass(data) 
		  });
}

(Update 1.1)

Zeile 1 überprüft, ob die Statusmeldung gerade angezeigt wird. Nur, wenn die Statusmeldung gerade nicht angezeigt wird, soll ein Klick (und damit das Einblenden der Statusmeldung) ausgelöst werden.
Zeile 2 setzt den Inhalt, also den Text, der Statusnachricht auf „error“ (

data

enthält den Rückgabewert der mailer.php). Hier sollte man vorher vielleicht eine aussagekräftigere Nachricht festlegen.
Zeile 3 fügt dem Zielelement die Klasse „error“ hinzu. Im CSS Dokument müssen die Klassen also so benannt sein wie die möglichen Rückgabewerte der mailer.php.
Zeile 4 blendet das Element ein, Zeile 5 wartet 3 Sekunden ab (lässt es also 3 Sekunden stehen),
Zeile 6 blendet das Element wieder aus, als callback Funktion (diese Funktion wird am Ende der Ausführung der fadeToggle Funktion ausgeführt) wird in
Zeile 7 die Klasse „error“ wieder entfernt.
(Update 1.1)

.fadeToggle(function(){}); mit callback muss sein, da sonst noch während der Ausblendeanimation (asynchron) die Styleklasse entfernt wird. Das führt zu Anzeigefehlern.

Dank jQuery ist das auch für den Internet Explorer kein Problem, kompatibel zu allen Versionen*.

Demo

Link

Download

jQuery-status-msg [.zip]
(Update 1.1)

Changelog

v1.1: Anzeigefehler bei mehrfachem Klick behoben (siehe Kommentar 1+2)

Einige kleine Ergänzungen zu dem letzten Post.

Bei der Eingabe der genauen Zeit kann man sogar ziemlich sprechend schreiben und mathematische Operationen durchführen. „now + 1 minute“ funktioniert also genauso wie „tomorrow + 24h“.

Wenn ihr oben rechts auf den Boomerang Link klickt werdet ihr auf eine Art Administrationsseite geschickt.
Hier habt ihr einen Überblick über alle ausstehenden Boomerang Aktionen und Mails, die gerade verarbeitet werden.
Zusätzlich könnt ihr Einstellungen bearbeiten. Die Art wie Mails durch Boomerang wieder in den Posteingang geholt werden („Return to inbox [if]“) kann hier angepasst werden. Die Optionen „Starred“ und „Labaled as Boomerang“ finde ich zum Beispiel nicht so sinnvoll.

Endlich habe ich da eine Lösung für 3 Funktionen, die ich schon lange bei GMail vermisse!

Boomerang ist eine Erweiterung für Chrome und Firefox und Google Mail User werden sie lieben!
Leider gibt es 2 Voraussetzungen: Google Mail muss auf englisch eingestellt sein. Und man muss einmalig (bei der ersten Aktion mit Boomerang) den Zugriff des Dienstes auf das eigene GMail Konto zulassen.
Dann kann es losgehen.

Was bietet Boomerang?

Ich zeige hier die 3 von mir heiß ersehnten Features. Boomerang kann sicher noch ein wenig mehr, schaut dazu auf die Homepage.

Emails später versenden

Das ist überhaupt die beste Funktion! Boomerang fügt in GMail einen „Send Later“ Button ein.
Dieser ermöglicht das Absenden einer Mail zu einem fest definierten Zeitpunkt, X Stunden/Tage später oder zu einem zufälligen Zeitpunkt.
Die Angabe eines ganz bestimmten Zeitpunktes sollte am interessantestens sein und ist einfach und verständlich gemacht. Die Handhabung der Funktion ist also ein Kinderspiel.
Getestet, works!

Emails später nochmal empfangen

Wie oft habe ich mir überlegt wie ich Mails, die in meinem Posteingang immer weiter nach unten rutschen, wieder nach oben holen kann. Bei 20-40 Mails am Tag verschwindet eine bestimmte Mail in kürzester Zeit aus dem Blickfeld des Posteingangs. Man kann sie labeln, mit Sternchen markieren aber im Posteingang wieder nach oben holen, den aktuellen Zeitstempel aufdrücken, das geht nicht.
„Return to inbox“ also, die Funktion ist jetzt gegeben und ist ein Traum.
Wie bei „Send Later“ wählt man bei empfangenen Mails aus, wann diese Nachricht nochmal in den Posteingang flattern soll.

Emails nochmal empfangen wenn […]

Ist praktisch das Gleiche wie der vorherige Punkt, allerdings ist die Funktion beim Versenden möglich. Mails werden nochmal nach oben geholt wenn entweder keine Antwort auf diese Mail kommt oder selbst wenn eine eintrifft. Finde ich sehr praktisch wenn ich auf wichtige Mails innerhalb von 1, 2 Wochen eine Antwort erwarte und die dann aus dem Blickfeld verschwinden nach 2, 3 Tagen. So werde ich 100%ig erinnert nach einer oder zwei Wochen wenn keine Antwort kam.


Fazit: Also Leute, ein Traum. Das Plugin wird hoffentlich iirgendwann mal auch auf das deutsche Google Mail eingestellt, bis dahin ist das für mich ein verträgliches Opfer für diese wunderbaren Funktionen.

Sooo, gestern ist mein aktuelles Gewinnspiel abgelaufen und ich habe die Gewinner direkt ermittelt. Es gibt 2 Gewinner für die 2 angekündigten Gewinne: die Tastatur und die DVD.
Es gab 17 Teilnehmer, davon 2 mit doppelter Gewinnchance. Rein in die Random.org Liste, rütteln, schütteln und die Gewinner siiiind:

1. Michael – Tastatur
2. Catrin – DVD

So ihr Beiden, Adresse zu mir und dann kommt bald Post 😉

Ich danke euch allen für die vielen Tipps, Meinungen und so, das wird mir bei der Vollendung des Designs sehr helfen. Bis das Design mit dem neuen Namen online geht wird aber wahrscheinlich ein wenig Zeit vergehen. Einige private Zeitfresser kommen mir momentan in den Weg. Aber es eilt ja nicht.

Bis dahin!

Ich kam letztens einfach nicht umher meinen alten C# Ordner zu durchstöbern. Ich hatte mich damals wenige Wochen mit C# beschäftigt. Also beschäftigt im Sinne von: Einsteigerkurse in der S-Bahn lesen, paar Tutorials im Netz und los gehts 😀
Ein Projekt hatte ich damals tatsächlich realisieren wollen. Ein kleines Programm, mit dem ich eine kleine Investition rechtfertigen und strategisch präsentieren konnte.
Damals wollte ich mir nämlich einen Kaffeevollautomaten kaufen, der gerade im Angebot war. Solch ein Gerät ist ja nicht gerade günstig, also habe ich die Ersparnisse, die mit so einem Gerät möglich sind, versucht einfach zu verdeutlichen.

Und somit, let me proudly introduce to you:

Kaffe-Kalkulator

DIE Rechtfertigung, wenn es um den Kauf eines Kaffeevollautomaten geht!

Der Sinn dieser Software ist einfach: sie soll die Rechenarbeit bei der Frage „Lohnt sich der Kauf eines Kaffeevollautomaten?“ für euch erledigen.
Das Programm fragt nach einigen Grundangaben aus denen dann ein kurzer Infotext gebastelt wird.

Simple thing, huh?! 🙂

Wie gesagt war das ein recht kurzer Abstecher in die C# Welt, der Code ist jetzt also nicht sonderlich cool.
Ich habe mich gestern und heute kurz damit beschäftigt und den Code stark gereinigt und umgeschrieben, Funktionen geschrieben, Fehler abgefangen, Code gekürzt und sowas. Aber mittlerweile würde ich einige Schritte anders realisieren (Stichwort „.“ bei Kaffeebohnenpreis und MaskedTextBoxes) und würde auch einige andere Details ändern (z.B. variabler durchschnittlicher Verbrauch von Kaffeebohnen pro Tasse (ist ja je nach Tassengröße unterschiedlich)) aber wichtig ist das alles nicht. Dazu müsste das Programm grundlegend umgestaltet werden und so viel Langeweile habe ich ja nun auch wieder nicht. Es funktioniert grundlegend und erfüllt seine Aufgabe mit Stolz. 🙂

Code

Code anzeigenDen Code könnt ihr bequem mit den Links/Rechts Pfeiltasten horizontal bewegen.

public partial class Main : Form
    {
        // Variablen einzeln setzen, für Kommentare
        const char nl = (char)10; // Zeilenumbruch als Konstante
        double PrUn = 0; // Preisunterschied zwischen eigenem und alternativem Kaffee
        double PrKa = 0; // Preis der eigenen Tasse
        double PrAlKa = 0; // Preis des altern. Kaffees
        double MaxKaBo = 0; // maximale Anzahl der Tassen pro voller Kaffeebohnenpackung
        double DuVeKaBo = 20; // Durchschnittlicher Kaffeebohnenverbrauch pro Tasse
        double KaAuBezWo = 0; // Anzahl an Wochen die man braucht um mit dem Preisunterschied den Kaffeevollautomaten zu bezahlen
        bool empty = true; // Felder leer?
        
        public Main() {
            InitializeComponent();
        }

        void btnBerechne_Click(object sender, EventArgs e) {
            try {
                // Setze intern berechnete Variablen zurück
                initReset(false, true);
                // GET: Preis des alternativen Kaffees
                PrAlKa = checkPrAlKa();

                if (PrAlKa == 0 || checkEmpty() == true)
                    emptyErr();
                else {
                    if (checkNegative() == true) showStats("negative");
                    else showStats("positive");
                }
            }
            catch {
                unknownErr();
            }
        }

        void negativeErr() {
            lblStatistik.Text = "Die berechnete Statistik zeigt, dass du mit deinen Angaben keinen Gewinn machen würdest. Der Kaffee deines Vollautomaten ist teurer als der Kaffee, den du dir im Laden kaufst.";
            gbxStatistik.Visible = true;
        }

        void emptyErr() {
            lblStatistik.Text = "Fehler bei der Eingabe. Es wurden nicht alle Felder ausgefüllt.";
            gbxStatistik.Visible = true;
        }

        void unknownErr() {
            lblStatistik.Text = "Ein unbekannter Fehler ist aufgetreten... sorry...\nPrüfe deine Eingaben, irgendetwas stimmt hier nicht ;)";
            gbxStatistik.Visible = true;
        }

        double checkPrAlKa() {
            switch (cbxPrAlKa.Text) {
                case "": { return 0; break; }
                case "0,50€ - Berlin Ost billig": { return 50; break; }
                case "0,80€ - Berlin West billig": { return 80; break; }
                case "1,00€ - Berlin Mitte billig": { return 100; break; }
                case "1,30€ - Berlin Mitte normal": { return 130; break; }
                case "2,00€ - Berlin Mitte teuer": { return 200; break; }
                case "3,50€ - Berlin Fucking Luxus": { return 350; break; }
                case "6,00€ - Scheiße wo trinkst du Kaffee?!": { return 600; break; }
                default: { return 0; break; }
            }
        }

        bool checkEmpty() {
            // CHECK: leere Eingaben
            if (tbxAnKaWo.Text == "" || tbxMeKaBo.Text == "" || tbxPrKaAu.Text == "" || tbxPrKaBo.Text == "")
                return true;
            else
                return false;
        }

        bool checkNegative() {
            // CALC: Preis der eigenen Tasse in Cent
            PrKa = (((double.Parse(tbxPrKaBo.Text) * 100) / double.Parse(tbxMeKaBo.Text)) * DuVeKaBo);
            // CALC: Preisunterschied zwischen eigenem und alternativem Kaffee
            PrUn = PrAlKa - PrKa;
            // CALC: maximale Anzahl der Tassen pro voller Kaffeebohnenpackung beim angegebenen Durchschnittsverbrauch pro Tasse
            MaxKaBo = Math.Round((double.Parse(tbxMeKaBo.Text) / DuVeKaBo), 1);
            // CALC: Anzahl an Wochen die man braucht um mit dem Preisunterschied den Kaffeevollautomaten zu bezahlen
            KaAuBezWo = double.Parse(tbxPrKaAu.Text) / (PrUn * double.Parse(tbxAnKaWo.Text));
            // PRINT: Preis der eigenen Tasse in €
            tbxPrTaKa.Text = Math.Round((PrKa / 100), 2).ToString();
            // PRINT: Preisunterschied zwischen eigenem und alternativem Kaffee in €
            tbxPrUn.Text = Math.Round((PrUn / 100), 2).ToString();

            if (PrUn < 0) return true;
            else return false;
        }

        void showStats(string pon) {
            if (pon == "positive") {
                // PRINT: Statistiktext
                lblStatistik.Text = tbxMeKaBo.Text
                    + "g Kaffeebohnen kosten " + tbxPrKaBo.Text
                    + " €. Für eine kleine Tasse werden " + DuVeKaBo
                    + "g Kaffeebohnen verbraucht, mit den " + tbxMeKaBo.Text
                    + "g Kaffeebohnen lassen sich also bis zu " + MaxKaBo
                    + " Tassen machen." + nl
                    + "Eine Tasse Kaffee zu Hause kostet nur " + tbxPrTaKa.Text
                    + " € ! Günstig, oder?! Und dann noch lecker Kakao drin, hhmmmm lecker." + nl
                    + "Wenn ein gekaufter Kaffee in der Stadt " + Math.Round((PrAlKa / 100), 2)
                    + " € kostet, ist ein selbstgemachter Kaffee also " + Math.Round((PrUn / 100), 2)
                    + " € günstiger!" + nl
                    + "Bei " + tbxAnKaWo.Text
                    + " Tassen Kaffee pro Woche sparst du also " +
                    // CALC: Ersparnis pro Woche: Anzahl der Tassen pro Woche * Preisunterschied in € gerundet auf 2 Stellen
                    Math.Round((double.Parse(tbxAnKaWo.Text) * Math.Round((PrUn / 100), 2)), 2)
                    + " € pro Woche, " +
                    // CALC: Ersparnis pro Monat: Anz. d. Tassen pro Woche / 7 (Ersparnis pro Tag) * 30.416 (durchschnittliche Tagesanzahl pro Monat) gerundet auf 2 Stellen
                    Math.Round(((Math.Round((double.Parse(tbxAnKaWo.Text) * Math.Round((PrUn / 100), 2)), 2) / 7) * 30.416), 2)
                    // Math.Round((double.Parse(tbxAnKaWo.Text) * Math.Round((PrUn / 100), 2) * 30.416), 2)
                    + " € pro Monat und ganze " +
                    // CALC: Ersparnis pro Jahr: Anz. d. Tassen pro Woche / 7 (Ersparnis pro Tag) * 365,25 (durchschnittliche Tagesanzahl pro Jahr) gerundet auf 2 Stellen
                    Math.Round(((Math.Round((double.Parse(tbxAnKaWo.Text) * Math.Round((PrUn / 100), 2)), 2) / 7) * 365.25), 2)
                    //Math.Round((double.Parse(tbxAnKaWo.Text) * Math.Round((PrUn / 100), 2) * 365.25), 2)
                    + " € im Jahr!!" + nl
                    + "Es erklärt sich also von selbst, dass der Kaffeevollautomat bei einem Preis von satten " + tbxPrKaAu.Text
                    + ",00 € bereits nach " +
                    //CALC: Wochen die zum Abbezahlen nötig sind: (Preis der Automats / Ersparnis pro Tag) / 7
                    Math.Round(((double.Parse(tbxPrKaAu.Text) / Math.Round(((Math.Round((double.Parse(tbxAnKaWo.Text) * Math.Round((PrUn / 100), 2)), 2) / 7)), 2)) / 7), 1)
                    + " Wochen abbezahlt ist!" + nl
                    + "Danach sparst du bei jeder Tasse wirklich die " + Math.Round((PrUn / 100), 2)
                    + " €.";
                gbxStatistik.Visible = true;
            }
            else if (pon == "negative") {
                negativeErr();
            }
        }

        void resetToolStripMenuItem_Click(object sender, EventArgs e) {
            initReset(true, true);
        }

        void btnReset_Click(object sender, EventArgs e) {
            initReset(true, true);
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e) {
            Form2 About = new Form2();
            About.Show();
        }

        private void beendenToolStripMenuItem_Click(object sender, EventArgs e) {
            Application.Exit();
        }

        void initReset (bool elems,bool vars) {
            if (elems==true) resetElements();
            if (vars==true) resetVars();
        }

        void resetElements() {
            tbxMeKaBo.Text = tbxPrKaAu.Text = tbxPrKaAu.Text = 
            tbxPrKaBo.Text = tbxPrTaKa.Text = tbxPrUn.Text = 
            tbxAnKaWo.Text = "";
            cbxPrAlKa.ResetText();
            gbxStatistik.Visible = false;
            tbxPrKaAu.Focus();
        }

        void resetVars() {
            PrUn=PrKa=PrAlKa=MaxKaBo=KaAuBezWo=0;
            DuVeKaBo = 20;
        }
    }
Download

Kaffee-Kalkulator [.exe]

Ich denke nicht, dass es eine ausgebaute Version 2 des Programms geben wird aber trotzdem; Kritik, Verbesserungsvorschläge, Ausbauvorschläge, Spam und puren Stuss, einfach Kommentar schreiben.

PS: Was haltet ihr von meiner neuen „Code anzeigen“ Methode? Ich dachte mir so bleibt die Übersichtlichkeit meines Blogs unverändert und ich kann trotzdem lange Codeschnipsel präsentieren. Ob und wenn ja wie der Code dann allerdings im RSS Reader erscheint weiß ich noch nicht. Werden display:none divs im RSS beachtet? Naja mal sehen.