25.12.2008 - CakePHP 1.2 ist nun stable!

Und ein neuer Cheatsheet samt TextMate Bundle ist auch dabei :)

Fröhliche Weihnachten!

Ankündigung gibt es dort
Download gibt es hier

Ein neues Lieblingsfeature von mir!

Wer schon mal mit der AuthComponent zu tun hatte kennt sicherlich den Begriff „scope“, womit man festlegen kann welche Bedienung ein Benutzer erfüllen muss damit er sich einloggen kann. Für all die die es nicht Wissen, hier eine Kurzfassung in Bezug auf das Thema dieses Beitrags: Ein „Scope“ ist eine definierte Eingrenzung von Daten. „Named“ bedeutet, dass wir dieser Eingrenzung einen Namen geben.
Read the rest of this entry »

Wenn man das debug_kit Plugin benutzt und dann ThemeView benutzen will gibt es ein kleines Problem: Das debug_kit kommt mit einem eigenem View und überschreibt somit die im AppController definierte Eigenschaft.

Wer also Themes aktivieren will muss sich dem debug_kit entledigen. Hat ein wenig gedauert bis ich den Grund gefunden habe, aber ein wenig manuelles Debugging in “beforeRender” brachte Licht ins Dunkel. Hoffe ich kann mit der Info einigen ein paar Kopfschmerzen ersparen ;-)

—– English —–
If you are using the debug_kit plugin and you want to enable themes in your CakePHP application you will run into a problem. debug_kit comes with a own view and overwrites whatever $view you’ve setup in your controllers. So if you wonder why ThemeView is not working, just delete the debug_kit and it will work. I haven’t looked at the debug_kit code yet, but i guess there is no workaround to this.

Tutorials:
theming-with-cakephp
theming-your-cakephp-apps-v12
Themes Section/cookbook

—–

UPDATE: Ich habe Mark, den Autor des Plugins, darüber informiert und er schrieb mir heute zurück, dass es doch gemeinsam kompatibel sein sollte.

“[...]From the tests I did as long as $view is set in the controller before your action ie. in your beforeFilter() you should be fine.[...]“

Tooltips.. die kleinen Text-Popups die einem helfen sich zu orientieren. Immer wieder gerne gesehen und wurde auch schon zig-mal programmiert.

Ich hab mir schon so einige fertige Scripts angesehen, aber die meisten machen einfach viel zu viel und nutzen teilweise sogar selber Prototype, nur leider nicht effizient genug.

Meistens werden die DIVs beim Aufruf der Seite generiert und irgendwo unterhalb des BODYs "versteckt". Bei sehr vielen Tooltips/Links kann das den Seitenaufbau extrem verlangsamen. Andere wiederum berechnen gott-weiss-was und haben einen mehrseitigen Umfang. Da oft gleich auch eine Klasse geschrieben wird muss man meist eine weitere Scriptdatei laden, was nochmals den Aufbau verzögert.

Ich schreibe daher meine Tooltips immer selber und bin mittlerweile runter auf 10 Zeilen. Könnte sogar in einer passen, aber man will ja nicht den Überblick verlieren.

JAVASCRIPT:
  1. $$('a[title]').invoke('observe', 'mouseover', function(evt){
  2.     var element = evt.findElement('a'), text = element.getAttribute('title');
  3.     var tooltip = new Element('div', {'class':'tooltip'}).update(text);
  4.     element.removeAttribute('title'); element.setAttribute('_title', text);
  5.     element.insert({'after': tooltip.setStyle({'left':element.positionedOffset().first()+'px'})});
  6. }).invoke('observe', 'mouseout', function(evt){
  7.     var element = evt.findElement('a'), text = element.getAttribute('_title');
  8.     element.removeAttribute('_title'); element.setAttribute('title', text);
  9.     if (element.next().hasClassName('tooltip')) element.next().remove();
  10. });

  • Es wird OnMouseOver ein DIV kreiert mit dem Inhalt des TITLE Attributs eines Links. OnMouseOut wird das DIV einfach wieder entfernt.
  • Damit das Browser Tooltip nicht zusätzlich angezeitg wird, verschiebe ich bis zum OnMouseOut den Inhalt des TITLE Attributs kurz in ein Fake-Attribut namens _TITLE.
  • Der Selector a[title] wählt nur Anker die auch wirklich ein TITLE Attribut haben. Somit brauchen wir auch nicht mehr zu kontrollieren ob eines vorhanden ist.
  • Vom Javascript aus wird nur LEFT gesetzt, TOP braucht man nicht zwingend.
  • Am Ende von OnMouseOut prüfe ich ob das nächste Element wirklich die tooltip Klasse hat. Das ist nur eine reine Vorsichtsmaßnahme. Wer dennoch Probleme hat könnte etwas radikaler einfach alle DIVs mit dieser Klasse löschen via getElementsByClassName (ist am schnellsten).

Das nachfolgende CSS kümmert sich um den z-Index und den Abstand zum Cursor.

div.tooltip {
    color: #000;
    background-color: #FAFAFA;
    position: absolute;
    z-index: 9999;
    padding: 5px;
    margin: 5px;
    margin-left: 15px; /* Abstand zum Zeiger */
}

So, und das war's. Wenn man nun irgendwo auf der Seite ein <a ... title="mein tooltip"> platziert hat man einen Link mit Tooltip. Zero config, wenn man so will.

Man kann natürlich auch ohne Probleme auf andere Elemente erweitern. Beispiel: $$('a[title], img[title]')...

Falls jemand Verbesserungsvorschläge hat: Immer her damit!
Script wurde in IE, FF und Safari getestet.

Ja, Entwickler haben es schwer manchmal. Bitte einmal umarmen. Danke! :-)

Yeah.. OpenSource!

Ich habe durch Zufall noch eine alte Amazon Komponente gefunden die ich bisher nicht veröffentlich habe. Da ich mich ja auf GitHub niederlasse, habe ich die mal kurz überarbeitet und meinem cake-bits Repository hinzugefügt.

Link:
http://github.com/m3nt0r/cake-bits/tree/master/components/amazon.php

Gucken, und ...

PHP:
  1. // some controller ...
  2.     var $components = array('Amazon');
  3.  
  4.     function beforeFilter() {
  5.         $this->Amazon->setAccessKey( Configure::read('App.APIs.AmazonKey') );
  6.         $this->Amazon->setAssociateTag( Configure::read('App.APIs.AmazonTag') );
  7.     }
  8.     function index() {
  9.         $items = $this->Amazon->itemSearch('DVD', 'Title', 'Small,Offers');
  10.         if (!$items) {
  11.             pr ($this->Amazon->getLastErrors()); // pop some errors
  12.         } else {
  13.             $this->set('items', $items);
  14.         }
  15.     }
  16.     function view($asin) {
  17.         $item = $this->Amazon->itemLookup( $asin );
  18.         if (!$item) {
  19.             pr ($this->Amazon->getLastErrors()); // pop some errors
  20.         } else {
  21.             $this->set('item', $item);
  22.         }
  23.     }

Das wäre das eine... Das andere ist der remote shopping cart.

... kaufen!

PHP:
  1. // some other controller ...
  2.     function add() {
  3.         if ($this->data) {
  4.             $this->Amazon->cartThem(array(
  5.                 array(
  6.                     'quantity' => $this->data['Cart']['quantity'],
  7.                     'offerId' => $this->data['Cart']['offerId']
  8.                 ) // ... could be a larger collection. no prob.
  9.             ));
  10.             $this->redirect(aa('action', 'view'));
  11.         }
  12.     }
  13.     function edit() {
  14.         if ($this->data) {
  15.             $item_id = $this->data['Cart']['cartItemId'];
  16.             $quantity = $this->data['Cart']['quantity'];
  17.             $this->Amazon->cartUpdate($item_id, $quantity);
  18.             $this->redirect(aa('action', 'view'));
  19.         }
  20.     }
  21.     function view() {
  22.         $this->set('cart', $this->Amazon->cartGet());
  23.         $this->set('cartHasItems', $this->Amazon->cartHasItems());
  24.         $this->set('cartIsActive', $this->Amazon->cartIsActive());
  25.     }

Viel Spass damit!

Hallo zusammen. Es ist einige Zeit her dass ich mal was geschrieben habe. Ich werde versuchen nun wieder öfters eine halbe Stunde opfern zu können.

Es gibt nun eine neue Lightbox Version. Da die bisherige 0.7 eigentlich in seiner Grundfunktion immernoch kompatibel ist gab es hier nicht viel zu tun. Daher trägt die aktuelle Version den Titel 0.7a.

Was gibt's neues?
- Settings Seite funktioniert endlich richtig.
- Neuste Lightbox 2 in der Version 2.0.4 enthalten
- Komprimiertes Javascript (nur noch 48kb, dank gzip)
- Nur noch 1 DB Feld wird für die Einstellungen verwendet (statt 8)
- Repository auf GitHub angelegt. Dort gibt's immer die neuste Version.
- Admin Panel hübsch gemacht für WP 2.6+

Die gute alte Projekt Seite (zip)
Die neue Seite auf GitHub

Readme liegt bei, alles andere kennt ihr bestimmt ja. Upgrade: Ich empfehle den Uninstall Button im Adminmenü einmal zu drücken nachdem ihr die neue Version hochgeladen habt. Diese räumt den alten Mist aus der Datenbank. Danach geht ihr einfach nochmal auf die Lightbox Settings Seite und somit wird automatisch neu installiert. :)

Viel Spass!

Justin Palmer hat ein Snippet für Prototype gepostet welches das Date Object um strftime() erweitert.

JAVASCRIPT:
  1. Object.extend(Date.prototype, {
  2.   strftime: function(format) {
  3.     var day = this.getDay(), month = this.getMonth();
  4.     var hours = this.getHours(), minutes = this.getMinutes();
  5.     function pad(num) { return num.toPaddedString(2); };
  6.  
  7.     return format.gsub(/\%([aAbBcdHImMpSwyY])/, function(part) {
  8.       switch(part[1]) {
  9.         case 'a': return $w("Sun Mon Tue Wed Thu Fri Sat")[day]; break;
  10.         case 'A': return $w("Sunday Monday Tuesday Wednesday Thursday Friday Saturday")[day]; break;
  11.         case 'b': return $w("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec")[month]; break;
  12.         case 'B': return $w("January February March April May June July August September October November December")[month]; break;
  13.         case 'c': return this.toString(); break;
  14.         case 'd': return pad(this.getDate()); break;
  15.         case 'H': return pad(hours); break;
  16.         case 'I': return pad((hours + 12) % 12); break;
  17.         case 'm': return pad(month + 1); break;
  18.         case 'M': return pad(minutes); break;
  19.         case 'p': return hours&gt; 12 ? 'PM' : 'AM'; break;
  20.         case 'S': return pad(this.getSeconds()); break;
  21.         case 'w': return day; break;
  22.         case 'y': return pad(this.getFullYear() % 100); break;
  23.         case 'Y': return this.getFullYear().toString(); break;
  24.       }
  25.     }.bind(this));
  26.   }
  27. });

[via Justin Palmer]

Schön gelöst. Weitere ähnliche Schnippsel von ihm gibt es im GitHub.

Prototype LogoJohn-David Dalton hat mal wieder das Protoculous Paket aktualisiert. Endlich ist das neue Prototype 1.6 um 60% kleiner. Diesmal hat er auch ein kleineres Protoculous (nur mit effects.js) erstellt, welches in der Packer Variante ohne GZIP nur 64k wiegt (mit GZIP nur 28k).

Natürlich gibt es auch wieder das normale Protoculous (Prototype 1.6 mit Scriptaculous 1.8) als Packer (92k) und Shrinkvars Version (152k).

Nun kann man wohl getrost umsatteln. Und wenn die "deprecated" Sektion aus Prototype rausfliegt wird es wohl noch schmaler.

Download

Happy coding!

Stylished.com Model ContestIn letzter Zeit ist es ja recht still hier im Blog. Das hat einen guten Grund: Meine Arbeit bei Stylished.com. Heute möchte ich euch die hübsche Ajax Anwendung zeigen, welche ich die letzten Tage entwickelt habe.

Stylished ist eine soziales Netzwerk für Models, Fotografen und Modelagenturen. In der angeführten Anwendung geht es darum, dass Models in einem virtuellen Contest, eins gegen eins, antreten und sich somit Punkte verdienen.

Stylished.com Model Contest RanglisteDie Teilnahme funktioniert automatisch und die entstehenden Wertungen fliessen in eine Rangliste mit den Kategorien Newcomer, Professionell und Semi-Professionell.

Von der technischen Seite ist die Anwendung komplett in Javascript geschrieben und wird liebevoll mit JSON gefüttert. Als Ajax-Bibliothek wurde natürlich das von mir bevorzugte Protoype und Script.aculo.us Paket gewählt.

Zum Contest: http://www.stylished.com/contests/

Viel Spass damit!