<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Der Interaktionsdesigner - PHP, jQuery und CSS</title>
	<atom:link href="http://www.interaktionsdesigner.de/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.interaktionsdesigner.de</link>
	<description>Pauls Blog beschäftigt sich mit Webentwicklungsthemen, im Focus stehen jQuery, TYPO3, CSS und PHP.</description>
	<lastBuildDate>Thu, 04 Mar 2010 11:17:22 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Kiwi Teaser Version 1.1.0</title>
		<link>http://www.interaktionsdesigner.de/2010/03/04/kiwi-teaser-version-1-1-0/</link>
		<comments>http://www.interaktionsdesigner.de/2010/03/04/kiwi-teaser-version-1-1-0/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 11:17:22 +0000</pubDate>
		<dc:creator>Paul</dc:creator>
				<category><![CDATA[Kiwi Teaser]]></category>

		<guid isPermaLink="false">http://www.interaktionsdesigner.de/?p=664</guid>
		<description><![CDATA[Seit gestern steht die neue Version meiner Extension Kiwi Teaser im Repository bereit. Neben einem Icon für die Teaser Inhaltselemente ist auch ein kleiner Fehler in den generierten Pfaden zu den Ressourcen behoben. Die wirklich interessante, und diesen Post rechtfertigende Neuerung ist die komplette Konfigurationsmöglichkeit über Typoscript.
Dadurch ist es möglich einen Teaserport direkt per Typoscript [...]]]></description>
			<content:encoded><![CDATA[<p>Seit gestern steht die neue Version meiner Extension Kiwi Teaser im <a title="Kiwi Teaser im TYPO3 Repository" href="http://typo3.org/extensions/repository/view/kiwi_teaser/current/" target="_blank">Repository</a> bereit. Neben einem Icon für die Teaser Inhaltselemente ist auch ein kleiner Fehler in den generierten Pfaden zu den Ressourcen behoben. Die wirklich interessante, und diesen Post rechtfertigende Neuerung ist die <strong>komplette Konfigurationsmöglichkeit über Typoscript</strong>.</p>
<p>Dadurch ist es möglich einen Teaserport direkt per Typoscript einzubinden und zum Beispiel einem Marker zuzuweisen. Außerdem kann man mit dieser praktischen Extension <strong>jede beliebige Tabelle</strong> auslesen!</p>
<p><span id="more-664"></span></p>
<h2>Einbindung über Typoscript</h2>
<p>Nach der Installation steht im Typoscript das Objekt <strong>plugin.tx_kiwiteaser_pi1</strong> bereit. Das kann einem Marker zugewiesen werden und über die Eigenschaften <strong>content</strong> und <strong>ports</strong> mit Inhalt befüllt werden.</p>
<pre><code class=''>page.10.marks.CONTENT &lt; plugin.tx_kiwiteaser_pi1<br />
page.10.marks.CONTENT {<br />
&nbsp;&nbsp;content = pages_21, tt_content_123, pages_22, tx_kiwiteaser_content_2<br />
&nbsp;&nbsp;ports = 4<br />
}</code></pre>
<p>Und zack findet sich im Frontend statt ###CONTENT### ein cooler Kiwi Teaser mit vier Slots und den ausgelesenen Datensätzen, angegeben in <strong>content</strong>. Das Format ist simpel: Name der Datenbank - Unterstrich - UID des Datensatzes. Extra angelegten Teaserinhalte befinden sich in der Datenbank <strong>tx_kiwiteaser_content</strong>.</p>
<h2>Ansprechen von beliebigen Datenbanken</h2>
<p>Wenn man die Inhalte einfach per Typoscript beschreibt, lässt sich natürlich jede beliebige Datenbank ansprechen. Ja, das funktioniert! Damit die Extension weiß, welche Spalten sie auslesen soll, muss man diese per Typoscript bekannt geben. Zum Beispiel könnte man die besten Frontend Benutzer teasern:</p>
<pre><code class=''>plugin.tx_kiwiteaser_pi1 {<br />
tables.fe_users {<br />
&nbsp;&nbsp;title = name<br />
&nbsp;&nbsp;content = address<br />
&nbsp;&nbsp;image = image<br />
}<br />
}</code></pre>
<p>Das Format sollte eigentlich selbsterklärend werden. Der Inhalt aus der Spalte name landet im Marker ###TITLE### usw. Anschließend muss der Datensatz nur noch dem Teaser zugewiesen werden. Dem Beispiel von oben folgend so:</p>
<pre><code class=''>page.10.marks.CONTENT.content = fe_users_1, fe_users_3, pages_12, tt_content_21</code></pre>
<p>Nett, oder?</p>
<h2>Mehr Komfort für Redakteure</h2>
<p>Um <strong>weitere Tabellen</strong> im Teaser zu erlauben, und diese vorallem im Backend auszuwählen muss man im Moment leider noch hart an den Quelltext ran. In der Datei <strong>typo3conf/ext/kiwi_teaser/ext_tables.php</strong> wird im Array <strong>$tempColumns</strong> ab Zeile 33 das Feld <strong>tx_kiwiteaser_teasers</strong> als Datenbankrelationsfeld definiert. In Zeile 41 werden unter dem Schlüssel <strong>allowed</strong> alle erlaubten Datenbanknamen aufgezählt. Um den Redakteuren die Auswahl von Benutzern zu erlauben, muss der Eintrag erweitert werden:</p>
<pre><code class=''>$tempColumns['tx_kiwiteaser_teasers']['allowed'] = 'tx_kiwiteaser_content,pages,tt_content,fe_users';</code></pre>
<h2>Ausblick und Weiterentwicklung</h2>
<p>Der aufmerksame Betrachter wird die auskommentierte Zeile 40 bemerken, in der tt_news noch erlaubt war. Daran arbeiten wir im Moment. Verbessert werden muss die <strong>Verlinkung auf ausgewählte Inhalte</strong>.</p>
<p>Außerdem auf der Liste steht eine <strong>dynamische Darstellung von Teaserinhalten</strong>. Das bedeutet zum Beispiel das auslesen aller Seiten ab einem Einstiegspunkt, oder die Angabe von verschiedenen Bedingungen.</p>
<p>Wer diese Funktionen für sein Projekt gut gebrauchen kann oder mehr Ideen hat, ist natürlich herzlich eingeladen mit <a title="Webentwicklung aus Berlin" href="http://www.apeunit.com" target="_blank">uns</a> darüber zu reden.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.interaktionsdesigner.de/2010/03/04/kiwi-teaser-version-1-1-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TYPO3 Extension Kiwi Accordion Version 1.6</title>
		<link>http://www.interaktionsdesigner.de/2010/02/11/typo3-extension-kiwi-accordion-version-1-6/</link>
		<comments>http://www.interaktionsdesigner.de/2010/02/11/typo3-extension-kiwi-accordion-version-1-6/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 20:28:35 +0000</pubDate>
		<dc:creator>Paul</dc:creator>
				<category><![CDATA[Kiwi Accordion]]></category>
		<category><![CDATA[TYPO3]]></category>

		<guid isPermaLink="false">http://www.interaktionsdesigner.de/?p=654</guid>
		<description><![CDATA[Nach einigen Mails und Forenbeiträgen hatte ich schon Bauchschmerzen und fühlte mich ungut, denn meine kleine, feine Extension Kiwi Accordion setzte die "Rahmen"-Eigenschaft von Inhaltselementen außer kraft.
Aber damit ist jetzt Schluss! Die neue Version legt ihre Container unabhängig von den Rahmen um den Inhalt. Zeitnah im Repository verfügbar. Auf meiner privaten Seite gibt es eine [...]]]></description>
			<content:encoded><![CDATA[<p>Nach einigen Mails und Forenbeiträgen hatte ich schon Bauchschmerzen und fühlte mich ungut, denn meine kleine, feine Extension <a title="Kiwi Accordion im Repository" href="http://typo3.org/extensions/repository/view/kiwi_accordion/current/" target="_blank"><strong>Kiwi Accordion</strong></a> setzte die "Rahmen"-Eigenschaft von Inhaltselementen außer kraft.</p>
<p>Aber damit ist jetzt Schluss! <strong>Die neue Version</strong> legt ihre Container unabhängig von den Rahmen um den Inhalt. Zeitnah im Repository verfügbar. Auf meiner <a title="Webentwickler aus Berlin" href="http://www.paul-lunow.de" target="_blank">privaten Seite</a> gibt es eine Demonstration und im folgenden Eintrag ein paar technische Erklärungen.</p>
<p><span id="more-654"></span></p>
<h2>Für Redakteure</h2>
<p>Die Funktionsweise für Redakteure ist <strong>sehr einfach</strong>. Über die Seiteneigenschaften lässt sich bestimmen, ob mehrere Panels gleichzeitig offen sein dürfen.</p>
<p><a href="http://www.interaktionsdesigner.de/wp-content/uploads/2010/02/HiVars-Demoprojekt-TYPO3-4.3.1.jpg"><img class="aligncenter size-full wp-image-655" title="Kiwi Accordion Seiteneigenschaften" src="http://www.interaktionsdesigner.de/wp-content/uploads/2010/02/HiVars-Demoprojekt-TYPO3-4.3.1.jpg" alt="Kiwi Accordion Seiteneigenschaften" width="606" height="114" /></a><br />
Jedes Inhaltselement wiederum hat zwei Eigenschaften, <strong>Aufklappbar</strong> und <strong>Offen</strong>.</p>
<p><a href="http://www.interaktionsdesigner.de/wp-content/uploads/2010/02/HiVars-Demoprojekt-TYPO3-4.3.1-1.jpg"><img class="aligncenter size-full wp-image-656" title="Inhaltselemente aufklappbar" src="http://www.interaktionsdesigner.de/wp-content/uploads/2010/02/HiVars-Demoprojekt-TYPO3-4.3.1-1.jpg" alt="Inhaltselemente aufklappbar" width="598" height="121" /><br />
</a>Die erste Option initalisiert den Effekt, die zweite öffnet das Inhaltselement beim laden der Seite. Das wars! Eine Beispiel gibt es auf meiner <a title="Webentwickler aus Berlin" href="http://www.paul-lunow.de" target="_blank">privaten Seite</a>.</p>
<h2>Für Techniker</h2>
<p>Der kleinere Teil der Arbeit wird vom mitgelieferten Typoscript übernommen. Über die Eigenschaft <strong>tt_content.stdWrap.innerWrap.prepend</strong> und <strong>append</strong> wird ein DIV Container um den Inhalt gelegt (<strong>div.ka-panel</strong>) und je nach gewählten Eigenschaften die Klasse <strong>open</strong> oder <strong>close</strong> hinzugefügt.</p>
<p>In Version 4.3 hat sich dieser Teil grundlegend geändert. Inhaltselemente werden jetzt immer innerhalb eines DIV Containers ausgegeben was ich wesentlich besser finde als die nervigen Links ala <strong>&lt;a href="#c123"&gt;&lt;/a&gt;</strong>. Das hat leider zur Folge, dass in älteren Versionen der <strong>tt_content.stdWrap.innerWrap</strong> nur ausgeführt wird, wenn ein Rahmen ausgewählt wurde. Um das zu verhindern fügt die Extension einen Standardwert hinzu, damit die Eigenschaft aufjedenfall greift. Möglich wird das über die Abfrage der eingestellten TYPO3 Version.</p>
<pre><code class=''>[compatVersion &lt; 4.3]<br />
tt_content.stdWrap.innerWrap.cObject.default = TEXT<br />
tt_content.stdWrap.innerWrap.cObject.default.value = |<br />
[end]</code></pre>
<p>Der größere Teil der Arbeit erfolgt als jQuery Script. Das Kiwi Accordion arbeitet mit jQuery, <strong>bringt das Framework aber selbst nicht mit</strong>. Ich bin bei der Entwicklung davon ausgegangen, dass es in jedem Projekt integriert ist.</p>
<p>Im Script wird jeder Container mit der Klasse <strong>ka-panel</strong> untersucht und für die weitere Verwendung angepasst. Dabei wird mit <strong>$(':header:first', '.ka-panel')</strong> die erste Überschrift gesucht und als Handler benutzt. Alle Elemente nach der Überschrift werden mit einem Container umschlossen (<strong>div.ka-content</strong>) und bei Klick ein- oder ausgeblendet.</p>
<p>Bei Mauskontakt erhält das Panel zusätzlich die Klasse <strong>hover</strong>, damit lassen sich dann Pfeile anzeigen oder Farben ändern, je nach Vorgabe.</p>
<p>Wenn bei der Initialisierung etwas nicht funktioniert, gibt die Extension ein paar Hinweise in der Firebug Konsole aus. Ich hoffe das hilft weiter. Ansonsten sei auf die <a title="TYPO3, Extensions, Webstandards" href="http://www.paul-lunow.de" target="_blank">Demo auf meiner Seite</a> verwiesen.</p>
<p>Getestet hab ich die Extension mit TYPO3 Version <strong>4.3</strong>, <strong>4.3.1</strong> und <strong>4.2.6</strong>. Über weitere Kompatibilitätshinweise, Fragen und Anregungen freue ich mich natürlich sehr.</p>
<ul>
<li><a href="http://typo3.org/extensions/repository/view/kiwi_accordion/current/" target="_blank">Kiwi Accordion im TYPO3 Repository</a></li>
<li><a href="http://www.interaktionsdesigner.de/wp-content/uploads/2010/02/T3X_kiwi_accordion-1_6_0.t3x">Kiwi Accordion 1.6.0</a></li>
<li><a title="Pauls Seite" href="http://www.paul-lunow.de" target="_blank">Demonstration auf paul-lunow.de</a></li>
</ul>
<p>Danke für die ganzen Mails und die netten Worte! Frohes rumklappen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.interaktionsdesigner.de/2010/02/11/typo3-extension-kiwi-accordion-version-1-6/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Auf Inhalte aufmerksam machen: Kiwi Teaser</title>
		<link>http://www.interaktionsdesigner.de/2009/12/17/auf-inhalte-aufmerksam-machen-kiwi-teaser/</link>
		<comments>http://www.interaktionsdesigner.de/2009/12/17/auf-inhalte-aufmerksam-machen-kiwi-teaser/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 19:58:14 +0000</pubDate>
		<dc:creator>Paul</dc:creator>
				<category><![CDATA[Kiwi Teaser]]></category>
		<category><![CDATA[TYPO3]]></category>

		<guid isPermaLink="false">http://www.interaktionsdesigner.de/?p=647</guid>
		<description><![CDATA[Darf ich vorstellen? Meine neuste Extension, der Kiwi Teaser. Mit dessen Hilfe präsentiert man ganz einfach vorhandene Inhalte auf der einen Seite. Dazu legt man eine Teaseranzeige an und bestimmt wieviele Teaser sie anzeigen soll.
Die Teaser sind entweder Teaserdatensätze (mit Titel, Inhalt, Bild und Link), ganze Seiten oder einzelne Inhaltselemente. Fertig! Auf der Startseite kann [...]]]></description>
			<content:encoded><![CDATA[<p>Darf ich vorstellen? Meine neuste Extension, der <strong>Kiwi Teaser</strong>. Mit dessen Hilfe präsentiert man ganz einfach vorhandene Inhalte auf der einen Seite. Dazu legt man eine Teaseranzeige an und bestimmt wieviele Teaser sie anzeigen soll.</p>
<p>Die Teaser sind entweder <strong>Teaserdatensätze</strong> (mit Titel, Inhalt, Bild und Link), <strong>ganze Seiten</strong> oder einzelne <strong>Inhaltselemente</strong>. Fertig! Auf der Startseite kann der Redakteur jetzt ganz genau bestimmen, auf welche Inhalte die Benutzer aufmerksam gemacht werden sollen und in welcher Reihenfolge.</p>
<p>Die Extension gibts im <a title="Kiwi Teaser im TYPO3 Repositorie" href="http://typo3.org/extensions/repository/view/kiwi_teaser/current/" target="_blank">TYPO3 Repository</a> oder auf <a title="Kiwi Teaser auf GitHub" href="http://github.com/kiwi-service/Kiwi-Teasers" target="_blank">GitHub</a> - live im Einsatz bisher auf unserer <a title="Kiwi Service" href="http://www.kiwi-service.de" target="_blank">Firmenpräsenz</a>.</p>
<p><span id="more-647"></span></p>
<h2>Berechtigung</h2>
<p>Es liegt natürlich nahe tt_news einzusetzen. Aber erst sagt der Redakteur mir, ich soll das Datum ausblenden, denn regelmäßige News gibt es  gar nicht. Als nächstes will er die Reihenfolge ändern und ich sage, pass doch einfach das Datum entsprechend der Reihenfolge an. Klar, das geht aber so richtig genial ist das nicht.</p>
<p>Zumal die meisten Hinweise sich auf entsprechende Seiten in der Präsenz beziehen, auf externe Links oder einfach nur einen kurzen Hinweis darstellen. Das geht jetzt eleganter.</p>
<h2>Inhalte</h2>
<p>Es können verschiedene Inhalte vorgestellt werden. Die Extension bringt eigene Datensätze mit welche Titel, Inhalt, Bild und einen Link aufnehmen. Es können aber auch Seiten oder Seiteninhalte angeteast werden.</p>
<h2>Installation</h2>
<p>Entweder man holt sich die stabile Version aus dem Repository oder die aktuellste, brandheiße aus meinem ersten Projekt auf <a title="Kiwi Teaser auf GitHub" href="http://github.com/kiwi-service/Kiwi-Teasers">GitHub</a>. Ein großartiges Portal!</p>
<p>Die restliche Installation ist alt bekannt und ganz normal. Der Kiwi Teaser <strong>bindet standardmäßig jQuery ins Projekt ein</strong> um ein paar coole Extras zu ermöglichen.</p>
<h2>Konfiguration</h2>
<p>Über Typoscript hat man viele Einstellungsmöglichkeiten. Alles natürlich unter <strong>plugin.tx_kiwiteaser_pi1</strong> im Template - das schreibe ich jetzt nicht jedesmal mit auf. Die angegebenen Typoscriptschnipsel stellen jeweils die Standardeinstellung dar.</p>
<pre><code class=''>include.css.standard = 1</code></pre>
<p>Mit dieser Anweisung wird ein minimales Stylesheet geladen welches dafür sorgt das die Boxen nebeneinander stehen und einen Abstand zueinander haben.</p>
<pre><code class=''>include.javascript.jquery = 1</code></pre>
<p>Bindet die aktuelle jQuery Version ein. Hat man diese schon im Projekt sollte man diese Eigenschaft unbedingt mit <strong>include.javascript.jquery &gt;</strong> löschen (auf diese Art kann man jeden include verhindern).</p>
<pre><code class=''>include.javascript.clickbox = 1</code></pre>
<p>Holt mein Plugin Clickbox ins Projekt, welches <strong>die komplette Teaserbox klickbar</strong> macht und nicht nur den kleinen Link. <a title="Clickbox" href="http://www.interaktionsdesigner.de/2008/04/22/mein-jquery-plugin-clickbox/" target="_blank">Mehr zur Clickbox gibts hier</a>.</p>
<pre><code class=''>include.javascript.height = 1</code></pre>
<p>Bindet ein Script ein, welches dafür sorgt das <strong>alle Teaserboxen die gleiche Höhe</strong> haben. Besonders praktisch wenn man einen Rahmen oder eine Hintergrundfarbe gesetzt hat.</p>
<pre><code class=''>template.file = EXT:kiwi_teaser/res/html/template.html</code></pre>
<p>Der Pfad zum HTML Template. Das Standardtemplate sollte man sich unbedingt angucken und die Klassennamen beibehalten, denn sonst kriegen die oben erwähnten Scripte Schwierigkeiten.</p>
<pre><code class=''>stdWrap</code></pre>
<p>Der StandardWrap ist eine richtig schöne Sache! Damit kann man <strong>jeden Inhalt mit Typoscript bearbeiten</strong> bevor er ausgegeben wird. Dieser kann auf alle Felder angewendet werden: <strong>title, image, link</strong> und <strong>content</strong>. Zum Beispiel:</p>
<pre><code class=''>stdWrap.title.wrap = &lt;b&gt;|&lt;/b&gt;</code></pre>
<p>Außerdem kann man für verschiedene Quellen verschiedene Optionen angeben. Seiten kommen aus der Tabelle <strong>pages</strong>, Seiteninhalte aus <strong>tt_content</strong> und die Standardinhalte aus <strong>tx_kiwiteaser_content</strong>. Mit diesem Wissen kann man die Ausgabe je nach Datenbank bestimmen. Möchte man also die Überschriften von Seiten nicht fett sondern kursiv darstellen, reicht folgende Anweisung:</p>
<pre><code class=''>stdWrap.title.pages.wrap = &lt;i&gt;|&lt;/i&gt;</code></pre>
<p>Besonders wichtig ist diese Möglichkeit für <strong>den Linktext</strong>. Dieser wird über die Eigenschaft <strong>link.value</strong> gesetzt.</p>
<pre><code class=''>stdWrap.link.value = Mehr...</code></pre>
<p>Die Extension setzt den generierten oder angegebenen Wert vor der Verarbeitung in das Feld <strong>stdWrap.link.typolink.parameter</strong>. Das typolink Objekt lässt sich natürlich trotzdem noch erweitern. Will man alle Teaserlinks in einem neuen Fenster öffnen geht das ganz einfach:</p>
<pre><code class=''>stdWrap.link.typolink.target = _blank</code></pre>
<h2>Mapping der Inhalte</h2>
<p>Um zu entscheiden, welche Daten aus einem Datensatz den Titel und welche z.B. den Inhalt darstellen, gibt es eine <strong>Mappingtabelle im Typoscript</strong>. In der Standardkonfiguration wird der Untertitel einer Seite als Inhalt benutzt. Das passiert über folgende Angabe:</p>
<pre><code class=''>tables.pages.content = subtitle</code></pre>
<p>Dabei bezeichnet der Schlüssel das Feld im Teaser und der Wert das Feld in der Zieltabelle. Das lässt sich je nach Anforderung beliebig anpassen. Wenn die Eigenschaft link leer ist, erzeugt die Extension den Link je nach Tabelle automatisch.</p>
<h2>Template</h2>
<p>Im Template stehen verschiedene Marker zur Verfügung:</p>
<ul>
<li><strong>###TITLE### </strong>Ein Beispieltitel</li>
<li><strong>###IMAGE### </strong>uplodas/media/picture.jpg</li>
<li><strong>###CONTENT### </strong>Das ist je nach eingabe verschieden.</li>
<li><strong>###LINK### </strong>&lt;a href="index.php?id=123"&gt;Mehr...&lt;/a&gt;</li>
<li><strong>###CLASS### </strong>teaser-first port1</li>
</ul>
<p><strong>Image</strong> beinhaltet den originalen Inhalt aus der Datenbank, also im Idealfall den Pfad zum Bild, sollte also noch mit einem &lt;img&gt; Tag gewrappt oder per Javascript weiter verarbeitet werden.</p>
<p><strong>Link</strong> ist ein kompletter &lt;a&gt; Tag - generiert über Typoscript.</p>
<p><strong>Class</strong> wird automatisch gesetzt, je nach Position des Teasers steht da <strong>first-teaser</strong> oder <strong>last-teaser</strong> drin. Außerdem kriegt jeder Teaser die Klasse <strong>portX</strong> wobei das X für die aktuelle Position steht. So kann man also den zweiten Teaser gezielt ansprechen:</p>
<pre><code class=''>.tx-kiwiteaser-pi1 .port2 {<br />
&nbsp;&nbsp;font-size:200%;<br />
}</code></pre>
<h2>Alpha</h2>
<p>Heute, am 17.12.2009 habe ich die erste Version fertig gestellt und in meinem Projekt eingesetzt. Als nächstes wird sie in Kundenprojekt eingesetzt und die Redakteure darauf losgelassen. Dabei werde ich sicher noch die eine oder andere Erweiterung entwickeln, <strong>mit mehreren Updates ist also zu rechnen</strong>. <a title="Der Interaktionsdesigner auf Twitter" href="http://twitter.com/paul_lunow/" target="_blank">Auf dem neusten Stand ist man natürlich bei Twitter</a>.</p>
<h2>Ausblick</h2>
<p>Der wichtigeste Punkt auf meiner Liste ist die <strong>Unterstützung von tt_news</strong>. Damit ist es dann auch möglich eine schön ausgearbeitete Nachricht zu teasern. Natürlich muss sich das nicht auf tt_news beschränken, <strong>sondern kann im Prinzip jeden beliebigen Datensatz beinhalten</strong>!</p>
<p>Darüber hinaus sind die Pläne natürlich groß und die Möglichkeiten auch. Ich denke an jQuery Effekte wie das faden von Inhalten, die Integration vom <a title="Der Kiwi Slider" href="http://www.interaktionsdesigner.de/category/kiwi-slider/" target="_blank">Kiwi Slider</a> oder das dynamische Anpassen der Inhalte.</p>
<p><strong>Da wird noch einiges passieren!</strong></p>
<h2>Fazit</h2>
<p>Ich möchte kein zweites tt_news programmieren, hier geht es wirklich nur um das Teasern von eigenen und fremden Inhalten. So bequem und einfach für die Redakteure wie möglich.</p>
<p>Ich hoffe ihr könnt die Extension gut einsetzen - über Ideen, Fragen und Anregungen in den Kommentaren freue ich mich natürlich. Und wenn jemand per GitHub mitarbeiten möchte, ist er hiermit herzlich eingeladen.</p>
<p>Ganz unauffällig sei auch noch auf meine Firma hingewiesen - wenn du die Extension oder ähnliches für dein Projekt brauchst, aber nicht selbst programmieren möchtest oder kannst, dann ist der <a title="Kiwi Service" href="http://www.kiwi-service.de" target="_blank">Kiwi Service</a> ein verantwortungsbewusster und kompetenter Partner!</p>
<p>Wenn dir der Artikel gefällt und du mit uns zusammen mehr solche Lösungen entwickeln möchtest, an das Internet und OpenSource glaubst und einen Job in Berlin suchst, dann <strong>bewirb dich bei uns</strong>. <a title="Webentwickler gesucht in Berlin" href="http://www.kiwi-service.de/jobs/" target="_blank">Wir suchen neue Freunde!</a></p>
<p><em>Danke fürs lesen, und fröhliches teasen!</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.interaktionsdesigner.de/2009/12/17/auf-inhalte-aufmerksam-machen-kiwi-teaser/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mehrere Domains in einem TYPO3 Projekt verwalten</title>
		<link>http://www.interaktionsdesigner.de/2009/12/08/mehrere-domains-in-einem-typo3-projekt-verwalten/</link>
		<comments>http://www.interaktionsdesigner.de/2009/12/08/mehrere-domains-in-einem-typo3-projekt-verwalten/#comments</comments>
		<pubDate>Tue, 08 Dec 2009 08:00:34 +0000</pubDate>
		<dc:creator>Paul</dc:creator>
				<category><![CDATA[TYPO3]]></category>

		<guid isPermaLink="false">http://www.interaktionsdesigner.de/?p=639</guid>
		<description><![CDATA[Viele kleinen Projekte brauchen keine eigene TYPO3 Installation. Eine einfache Seite, zum Beispiel mit News, ein paar persönlichen Seiten und einem Kontaktformular legt man nach diesem Tutorial an - ohne Installtion, neue Datenbank und noch einem Eintrag in der Liste für die Bugfix Updates. Aber inklusive RealURL!
Dieses Tutorial bezieht sich auf TYPO3 Version 4.3, aber [...]]]></description>
			<content:encoded><![CDATA[<p>Viele kleinen Projekte brauchen keine eigene TYPO3 Installation. Eine einfache Seite, zum Beispiel mit News, ein paar persönlichen Seiten und einem Kontaktformular legt man nach diesem Tutorial an -<strong> ohne Installtion</strong>, neue Datenbank und noch einem Eintrag in der Liste für die Bugfix Updates. Aber <strong>inklusive RealURL</strong>!</p>
<p>Dieses Tutorial bezieht sich auf TYPO3 <strong>Version 4.3</strong>, aber ich vermute es funktioniert in allen neueren Versionen. Los gehts!</p>
<p><span id="more-639"></span></p>
<h2>Vorbereitungen</h2>
<p>Eine aktuelle TYPO3 Installation mit benötigten Extensions (RealURL vorallem) und ein paar Domains die alle in das gleiche Verzeichnis zeigen. Das reicht.</p>
<h2>Die Seitenstruktur</h2>
<p><img class="alignleft size-full wp-image-641" title="Seitenstruktur mit mehreren Domains" src="http://www.interaktionsdesigner.de/wp-content/uploads/2009/12/mehrere-domains-1.jpg" alt="Seitenstruktur mit mehreren Domains" width="197" height="82" />Direkt unter die Weltkugel kommt die <strong>Root Seite</strong>. Diese beinhaltet ein grundlegendes <strong>Typoscript</strong>, dass sich alle Domains teilen. Es lohnt sich ein einfaches Layout aufzubauen und alle benötigten Marker anzulegen, dann kann man später schnell etwas zeigen. Auch tt_news, mailformplus, kiwi_slider oder was auch immer kann man hier schonmal gut <strong>Vorkonfigurieren</strong>.</p>
<p>Unter Root kriegt <strong>jede Domain eine eigene Seite</strong>. Die besitzen folgende Eigenschaften:</p>
<ul>
<li>Typ: Verweis - auf erste Unterseite</li>
<li>Im Menü verbergen</li>
<li>Seitentitel wie die Domain</li>
<li>Nicht in sprechende URL aufnehmen</li>
</ul>
<p>Jeder Seite müssen über <strong>Liste</strong> &gt; <strong>Neuer Datensatz</strong> &gt; <strong>System Records</strong> &gt; <strong>Domäne</strong> die entsprechenden Domains zugewiesen werden. Am besten man legt als erstes die Hauptdomain an, zum Beispiel www.kiwi-service.de - <strong>ohne Umleitung</strong>.</p>
<p>Ein zweiter Datensatz kriegt dann die Domäne kiwi-service.de <strong>mit Umleitung</strong> auf www.kiwi-service.de. Die Checkbox Parameter zur Umleitungs-URL übertragen sollte man anschalten und speichern.</p>
<h2>Typoscript</h2>
<p>Auf der Root Seite lohnt es sich ein fertiges Template aufzubauen. Die wichtigesten Marker, wie Menü, Inhalt und Sidebar empfehle ich als <strong>COA Elemente</strong> anzulegen, wobei der Hauptinhalt immer auf Ebene 50 eingebunden wird. Damit kann man auf den Unterseiten einfach die Marker erweitern.</p>
<p>Über Konstanten lässt sich sehr viel steuern. Zum Beispiel die <strong>Start ID für das Menü</strong>. Dazu legt man in den Konstanten einen beliebigen Namen fest:</p>
<pre><code class=''>menu.special.value = 123</code></pre>
<p>Im Typoscript kann man auf diese Eigenschaften dann über die Syntax <strong>{$NAME}</strong> zugreifen. Vereinfacht könnte das dann so aussehen:</p>
<pre><code class=''>MENU = COA<br />
MENU.50 = TMENU<br />
MENU.50.special.value = {$menu.special.value}</code></pre>
<p>Mit diesem Vorgehen kann dann jede Seite grundlegend über Konstanten steuern. Man sollte es aber nicht übertreiben. Ideal sind die Grundeinstellungen damit man etwas sieht und klicken kann, alle Strukur- und Layoutanpassungen passieren dann gezielt im Extensiontemplate der Seite.</p>
<p>Am wichtigesten ist die Bekanntmachung der <strong>BaseURL</strong>. Entweder über Konstanten oder direkt im Template:</p>
<pre><code class=''>config.baseURL = http://www.kiwi-service.de</code></pre>
<h2>RealURL</h2>
<p>Jetzt zum schönsten Teil (<em>leichte Ironie</em>), damit man sich über die netten Domains freuen kann: <strong>RealURL</strong>. Installiert, ohne automatische Konfiguration ist die wichtigste Aufgabe, für jede Domain die richtige <strong>rootpage_id</strong> zu setzen.</p>
<p>Um sowenig wie möglich doppelt zu schreiben, legt man dafür als erstes eine Standardkonfiguration an:</p>
<pre><code class=''>$tx_realurl_config = array(<br />
'init' =&gt; array(<br />
'enableCHashCache' =&gt; true,<br />
'appendMissingSlash' =&gt; 'ifNotFile',<br />
'enableUrlDecodeCache' =&gt; true,<br />
'enableUrlEncodeCache' =&gt; true,<br />
'emptyUrlReturnValue' =&gt; '/',<br />
),<br />
'preVars' =&gt; array(),<br />
'postVarSets' =&gt; array(<br />
'_DEFAULT' =&gt; array(),<br />
),<br />
'pagePath' =&gt; array(<br />
'type' =&gt; 'user',<br />
'userFunc' =&gt; 'EXT:realurl/class.tx_realurl_advanced.php:&amp;tx_realurl_advanced-&gt;main',<br />
'spaceCharacter' =&gt; '_',<br />
'languageGetVar' =&gt; 'L',<br />
'expireDays' =&gt; 3,<br />
),<br />
);</code></pre>
<p>Die ist für alle gleich und sollte auch Konfigurationen für tt_news und andere Extensions beinhalten. Diese wird jetzt jeder <strong>Hauptdomain</strong> zugewiesen.</p>
<pre><code class=''>$TYPO3_CONF_VARS['EXTCONF']['realurl'] = array(<br />
&nbsp;&nbsp;'www.alexandrepeschel.de' =&gt; $tx_realurl_config,<br />
&nbsp;&nbsp;'www.kiwi-service.de' =&gt; $tx_realurl_config,<br />
);</code></pre>
<p>Die Aufrufe ohne www kann man vernachlässigen, weil TYPO3 sie weiterleitet. Als nächstes wird für jede Domain die <strong>UID</strong> der entsprechenden TYPO3 Einstiegsseite angegeben. Damit versteht RealURL dann, welcher Teil des Seitenbaums zu welcher Domain gehört.</p>
<pre><code class=''>$TYPO3_CONF_VARS['EXTCONF']['realurl']['www.kiwi-service.de']['pagePath']['rootpage_id'] = 12;<br />
$TYPO3_CONF_VARS['EXTCONF']['realurl']['www.alexandrepeschel.de']['pagePath']['rootpage_id'] = 34;</code></pre>
<p>Beim rumprobieren sollte man daran denken, dass man mit dem Leeren vom Frontend-Cache <strong>nicht</strong> den RealURL-Cache löscht! Das passiert über <strong>Info</strong> &gt; <strong>Root Seite</strong> &gt; <strong>RealURL-Verwaltung</strong>. Da sind sehr interessante Informationen drin versteckt!</p>
<h2>Fazit</h2>
<p>Das war schnell und effektiv! Wer sich das in Aktion ansehen will, geht auf unsere neue Firmenseite <a title="Die neue Agentur aus Berlin" href="http://www.kiwi-service.de" target="_blank">www.kiwi-service.de</a> und auf <a title="Alexandre Peschel" href="http://www.alexandrepeschel.de" target="_blank">www.alexandrepeschel.de</a>, die Seite meines lieben Kollegen. Im Moment ist das zum Teil im Aufbau und demnächst wird meine persönliche Seite auch dahin umziehen. Aber erst wenn die Seite auf dem neuen Server liegt!</p>
<p>Wenn du Spaß an diesem Tutorial hattest, und Lust hast mit uns noch <strong>viel mehr geilen Scheiß</strong> zu entwickeln, dann bewirb dich bei uns! <a title="Agentur aus Berlin sucht coole Leute!" href="http://www.kiwi-service.de/jobs/" target="_blank">Wir suchen Webentwickler mit Ideen und Tatendrang!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.interaktionsdesigner.de/2009/12/08/mehrere-domains-in-einem-typo3-projekt-verwalten/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TYPO3 Klickvergrößern durch eine jQuery Lightbox ersetzen</title>
		<link>http://www.interaktionsdesigner.de/2009/12/04/typo3-klickvergrosern-durch-eine-jquery-lightbox-ersetzen/</link>
		<comments>http://www.interaktionsdesigner.de/2009/12/04/typo3-klickvergrosern-durch-eine-jquery-lightbox-ersetzen/#comments</comments>
		<pubDate>Fri, 04 Dec 2009 13:07:44 +0000</pubDate>
		<dc:creator>Paul</dc:creator>
				<category><![CDATA[TYPO3]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.interaktionsdesigner.de/?p=629</guid>
		<description><![CDATA[Wenn jQuery auf einer Seite eingebunden ist (z.B. durch die coole Extension Kiwi Slider) dann beißt sich das Javascriptframework mit anderen wie MooTools oder Prototype. Insgesamt sollte man bevorzugt ein Framework einsetzen, wenn man unbedingt beide braucht, dann lohnt sich die Suche nach dem NoConflict Mode von jQuery.
Wenn aber das unbedingt nur von einer Lightbox [...]]]></description>
			<content:encoded><![CDATA[<p>Wenn jQuery auf einer Seite eingebunden ist (z.B. durch die coole Extension <a title="Kiwi Slider" href="http://www.interaktionsdesigner.de/2008/09/09/typo3-extension-kiwi-slider-2/">Kiwi Slider</a>) dann beißt sich das Javascriptframework mit anderen wie MooTools oder Prototype. Insgesamt sollte man bevorzugt ein Framework einsetzen, wenn man unbedingt beide braucht, dann lohnt sich die Suche nach dem <a title="jQuery noConflict" href="http://docs.jquery.com/Core/jQuery.noConflict" target="_blank">NoConflict Mode</a> von jQuery.</p>
<p>Wenn aber das <em>unbedingt</em> nur von einer Lightbox kommt, dann sollte man sich kurz hinsetzen, einen geeigneten Klon aussuchen (<a title="Lightboxclone Matrix" href="http://planetozh.com/projects/lightbox-clones/" target="_blank">hier ist die große Lightbox Matrix</a>) und die <strong>Klickvergrößerung von TYPO3</strong> damit ersetzen. Das ist schnell, effektiv und in diesem Beitrag erklärt.<span id="more-629"></span></p>
<h2>Vorbereitungen</h2>
<p>Für mein aktuelles Projekt habe ich mich für den Lightbox Clone <a title="TopUp" href="http://gettopup.com/" target="_blank">TopUp</a> entschieden. Sieht sehr vielversprechend aus. Also welcher Klone auch immer: <strong>Daten herunterladen</strong> und <strong>ins Projekt einbinden</strong>. Dazu gehören mind. jQuery und das entsprechende Plugin, in vielen Fällen auch noch eine CSS Datei. Firebug verrät im <em>Script</em> Reiter ob es funktioniert hat.</p>
<p>TopUp benötigt keine CSS Datei, dafür aber <strong>einen Bilder- und einen Players-Ordner</strong> in dem SWF Dateien gespeichert sind um verschiedene Medien wiederzugeben. Per JavaScript können die Pfade angepasst werden:</p>
<pre><code class=''>TopUp.host = 'http://www.kiwi-service.de/';<br />
TopUp.images_path = 'fileadmin/template/img/topup/';<br />
TopUp.players_path = 'fileadmin/template/flash/';</code></pre>
<h2>JavaScript einbinden</h2>
<p>Eine Besonderheit bringt TopUp mit: Es lädt dynamisch die benötigten JavaScriptdateien nach. Dafür braucht er den <strong>kompletten javascripts/jquery Ordner</strong>. Dieser muss im gleichen Ordner liegen wie <strong>top_up-min.js</strong>.</p>
<pre><code class=''>fileadmin/template/js/top_up-min.js<br />
fileadmin/template/js/jquery/...</code></pre>
<h2>Test</h2>
<p>Alle benötigten Dateien sind eingebunden und in Firebug sichtbar. Um zu testen ob es funktioniert, füge ich ein Inhaltselement vom Typ HTML ein und schreibe mein eigenes Bild rein. Testbilder sind im <em>Images</em> Ordner vorhanden.</p>
<pre><code class=''>&lt;a href="fileadmin/template/img/topup/photos/1.jpg" class="top_up"&gt;<br />
&nbsp;&nbsp;&lt;img src="fileadmin/template/img/topup/thumbnails/1.jpg"&gt;<br />
&lt;/a&gt;</code></pre>
<p>Funktioniert, wunderbar! Wenn nicht, dann die eigene Seite mit den <a title="TopUp Beispiele" href="http://gettopup.com/examples" target="_blank">Beispielen</a> vergleichen.</p>
<h2>Typoscript</h2>
<p>Nun muss man <strong>TYPO3</strong> noch das hässliche JavaScript PopUp austreiben. Hier mein Konfiguration für <strong>Version 4.3</strong></p>
<pre><code class=''>temp.imageLinkWrap = 1<br />
temp.imageLinkWrap {<br />
enable = 1<br />
typolink {</p>
<p>parameter.cObject = IMG_RESOURCE<br />
parameter.cObject.file.import.data = TSFE:lastImageInfo|origFile<br />
parameter.cObject.file.maxW = {$styles.content.imgtext.maxW}<br />
parameter.override.listNum.stdWrap.data = register : IMAGE_NUM_CURRENT</p>
<p>title.field = imagecaption // title<br />
title.split.token.char = 10<br />
title.if.isTrue.field = imagecaption // header<br />
title.split.token.char = 10<br />
title.split.returnKey.data = register : IMAGE_NUM_CURRENT<br />
parameter.cObject = IMG_RESOURCE<br />
parameter.cObject.file.import.data = TSFE:lastImageInfo|origFile<br />
ATagParams = target="_blank"<br />
}<br />
}</p>
<p>tt_content.image.20.1.imageLinkWrap &gt;<br />
tt_content.image.20.1.imageLinkWrap &lt; temp.imageLinkWrap<span> </span></code></pre>
<p>Als erstes wird das temporäre Objekt <strong>temp.imageLinkWrap</strong> erzeugt und konfiguriert. Interessant ist die letzte Angabe <strong>ATagParams</strong> - darüber gibt man jedem Link die Klasse <em>top_up</em> mit, damit das Plugin sich um die Bilder kümmert.</p>
<p>Anschließend wird die Standardvergrößerung in <strong>tt_content.image.20.1.imageLinkWrap</strong> überschrieben. <strong>Cache leeren</strong> und Seite neuladen, fertig!</p>
<h2>TopUp Spezialitäten</h2>
<p>Dieses TopUp ist wirklich ein schönes Teil. Mit der Funktion <strong>addPresets()</strong> lassen sich für Links in DOM Bereichen Voreinstellungen treffen. Zum Beispiel alle Bilder die über <strong>ein Inhaltselement</strong> eingestellt sind, zu einer Gruppe zusammenfassen:</p>
<pre><code class=''>TopUp.addPresets({<br />
".csc-textpic-imagewrap a": {<br />
group: "images"<br />
}<br />
});</code></pre>
<p>Das bedeutet alle TopUp-Links im Div <strong>.csc-textpic-imagewrap</strong> werden der Gruppe <em>images</em> zugewiesen. Im Overlay gibts dann Vor- und Zurückpfeile.</p>
<h2>Fazit</h2>
<p>Die Initialisierung und Einstellungen einer Lightbox variieren natürlich. Es gibt aber ein paar schöne und elegante Tools deren Einsatz sich lohnen. Vorallem im Zusammenspiel mit der brand neuen TYPO3 Version 4.3 - ein großartiger Schritt mit schönen Verbesserungen. Unbedingt ansehen. Und TopUp einbinden!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.interaktionsdesigner.de/2009/12/04/typo3-klickvergrosern-durch-eine-jquery-lightbox-ersetzen/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ajax in Webapplikationen mit CakePHP und jQuery</title>
		<link>http://www.interaktionsdesigner.de/2009/11/21/ajax-in-webapplikationen-mit-cakephp-und-jquery/</link>
		<comments>http://www.interaktionsdesigner.de/2009/11/21/ajax-in-webapplikationen-mit-cakephp-und-jquery/#comments</comments>
		<pubDate>Sat, 21 Nov 2009 14:38:09 +0000</pubDate>
		<dc:creator>Paul</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.interaktionsdesigner.de/?p=618</guid>
		<description><![CDATA[Jeder Webentwickler weiß, dass kein Benutzer mehr auf das Neuladen einer Seite warten will. Vorallem nicht, wenn es in Webapplikationen darum geht Elemente hinzuzufügen, zu bearbeiten oder zu entfernen.
Zum Beispiel in einem Tool welches umfangreiche Exportmöglichkeiten besitzt und gerade von einer jungen, dynamischen Agentur entwickelt wird. In dem Programm legt man ein Exportscript an und [...]]]></description>
			<content:encoded><![CDATA[<p>Jeder Webentwickler weiß, dass kein Benutzer mehr auf das Neuladen einer Seite warten will. Vorallem nicht, wenn es in Webapplikationen darum geht Elemente hinzuzufügen, zu bearbeiten oder zu entfernen.</p>
<p>Zum Beispiel in einem Tool welches umfangreiche Exportmöglichkeiten besitzt und gerade von einer <a title="Meine junge dynamische Agentur!" href="http://www.kiwi-service.de" target="_blank">jungen, dynamischen Agentur</a> entwickelt wird. In dem Programm legt man ein Exportscript an und kann diesem verschiedene Exportdateien zuweisen die beim durchlaufen dynamisch erstellt werden.</p>
<p>Diese einfache 1:n Beziehung ist mit Cake schnell gebacken, mit ein paar Zeilen erweitert und läuft. Allerdings verteilt auf mehreren Seiten. Zum Glück gibt uns Cake einfache Möglichkeiten an die Hand um das zu verhindern.</p>
<p>In diesem Artikel will ich aufschreiben wie man praktisch jedes Cake Projekt zusammen mit dem Lieblings-Javascriptframework jQuery in eine coole Web 2.0 Anwendung verwandeln kann.</p>
<p><span id="more-618"></span></p>
<h2>Grundlagen</h2>
<p>Ich gehe mal von einer laufenden Cakeanwendung aus. Da gibt es die Tabelle Export und die Tabelle Exportfiles. Die beiden sind über eine 1:n Beziehung verknüpft, die Anwendung wurde gebacken und man verfügt über die normalen CRUD Funktionen.</p>
<p><em>Wenn Interesse an einem Tutorial dazu besteht, wäre ein kurzer Hinweis in den Kommentaren oder per Mail nett.</em></p>
<h2>Der AppController</h2>
<p>Den schönsten Teil bringt Cake schon mit: den <strong>RequestHandler</strong>. Mit dessen Hilfe kann man auf Ajaxanfragen reagieren. Als erstes muss er in der Datei <strong>app/app_controller.php</strong> eingebunden werden:</p>
<pre><code class=''>$components = array('RequestHandler');</code></pre>
<p>Anschließend stehen in jedem Controller über <strong>$this-&gt;RequestHandler</strong> umfangreiche Möglichkeiten zur Verfügung. Besonders toll wirds im Callback <strong>beforRender()</strong>. Dieser wird im AppController definiert und von Cake automatisch aufgerufen, wenn die Logik im entsprechenden Controller abgearbeitet wurde.</p>
<p>So sieht die Killerfunktion aus:</p>
<pre><code class=''>function beforeRender() {<br />
&nbsp;&nbsp;if($this-&gt;RequestHandler-&gt;isAjax()) {<br />
&nbsp;&nbsp;   Configure::write('debug', 0);<br />
&nbsp;&nbsp;   if($this-&gt;RequestHandler-&gt;prefers() == 'json') {<br />
&nbsp;&nbsp;      die(json_encode($this-&gt;viewVars));<br />
&nbsp;&nbsp;   }<br />
&nbsp;&nbsp;   else {<br />
&nbsp;&nbsp;      $this-&gt;layout = 'ajax';<br />
&nbsp;&nbsp;   }<br />
&nbsp;&nbsp;}<br />
}</code></pre>
<p>Was hier passiert ist so gut wie selbsterklärend: Wenn es sich um eine asynchrone Anfrage handelt <strong>if($this-&gt;RequestHandler-&gt;isAjax())</strong>, dann wird als erstes jegliche Debugausgabe verboten. Das muss man sich unbedingt merken, sonst besteht die Gefahr auszuflippen weil <strong>debug()</strong> "aufeinmal" nichts mehr ausgibt. Auf der anderen Seite kann man aber nicht mit einem JSON String in Javascript weiterarbeiten, wenn dem ein Datenbanklog <span style="text-decoration: line-through;">am Hintern</span> an der schließenden Klammer klebt. <em>Also nicht vergessen!</em></p>
<p>Nach dem Cake weiß, das es eine Ajaxanfrage bearbeitet, wird geprüft, welche Rückantwort erwartet wird <strong>$this-&gt;RequestHandler-&gt;prefers()</strong>. Wenn diese JSON ist, werden alle <strong>viewVars</strong>, dass sind alle Variablen die über <strong>$this-&gt;set() </strong>im Controller gesetzt wurden, als JSON Objekt zurück gegeben. Damit stehen dem Javascript alle Informationen zur Verfügung die sonst im View verarbeitet werden. Toll oder?</p>
<p>Dieses <strong>die(json_encode()) </strong>finde ich noch nicht ganz so elegant wie der ganze Rest von Cake, tut aber seine Arbeit. Vielleicht hat jemand einen schöneren Ansatz?!</p>
<p>Wenn die Anfrage kein JSON erwartet, wird nicht das Standardlayout genutzt, sondern auf das Ajax umgeschaltet. Das befindet sich in der Datei <strong>app/views/layouts/ajax.ctp</strong> und besteht nur aus einer Zeile:</p>
<pre><code class=''>&lt;?php echo $content_for_layout; ?&gt;</code></pre>
<h2>Standardlayout</h2>
<p>Um Probleme beim ändern der BaseURL zu vermeiden habe ich mir angewöhnt im Standardlayout das Tag <strong>base</strong> zu verwenden um mit jQuery schnell auf die URL zugreifen zu können. In der Datei <strong>app/views/layouts/default.ctp</strong> muss dafür folgende Zeile hinzugefügt werden:</p>
<pre><code class=''>&lt;base href="http://&lt;?=$_SERVER['HTTP_HOST']?&gt;&lt;?=$this-&gt;base?&gt;/" host="http://&lt;?=$_SERVER['HTTP_HOST']?&gt;" /&gt;</code></pre>
<p>Ich weiß, das Attribut <strong>host</strong> verhindert eine komplette Validierung, allerdings brauche ich in einigen Fällen nur den Host und in anderen die komplette BaseURL, da zum Beispiel die erstellen Formulare mit <strong>$form-&gt;create(...) </strong>schon die BaseURL enthalten.</p>
<p>Das wird man gleich sehen.</p>
<h2>jQuery Action</h2>
<p>Da sind jetzt in wenigen Zeilen mächtige Grundlagen gelegt worden, die man mit jQuery an seiner Seite ausnutzen möchte. Im Formular zur Erstellung eines neuen Exports habe ich ein Button "Neue Exportdatei", die bei Klick in den Container <strong>div#new</strong> das Formular lädt um eine neue Datei zu speichern. Nichts leichter als das:</p>
<pre><code class=''>$ajax({<br />
&nbsp;&nbsp;url: $('base').attr('href')+'exportfiles/add/export:'+$('#ExportEditForm').attr('rel'),<br />
&nbsp;&nbsp;dataType: 'html',<br />
&nbsp;&nbsp;success: function(form) {<br />
&nbsp;&nbsp;    $('#new').html(form);<br />
&nbsp;&nbsp;}<br />
};</code></pre>
<p>Als benannten Parameter wird die ID des aktuellen Exports übergeben. Im Controller steht diese Information im Array <strong>$this-&gt;params['named']</strong> zur Verfügung. Von da wird sie an den View übergeben und hier wird, sofern gesetzt ein verstecktes Formularfeld erzeugt, anstatt der gebackenen Liste der vorhandenen Exports.</p>
<p>Mit der Verwendung des Ajax-Layouts und der Angabe <strong>dataType: 'html'</strong> steht in der Variable <strong>form</strong> der Success Funktion genau das Formular zur Verfügung, welches im View definiert wurde.</p>
<h2>JSON benutzen</h2>
<p>Wenn das Formular ausgefüllt wurde, muss man das Abschicken abfangen. Leider unterstützt die <strong>Live</strong> Funktion noch nicht den Event <strong>submit</strong>, deshalb muss man sich mit einem Klick auf den Submitbutton helfen.</p>
<pre><code class=''>$('#new .submit input').live('click', function() { ... });</code></pre>
<p>Das wirklick spannende ist natürlich auch hier die Ajaxanfrage und das Geheimnis liegt im <strong>dataType: 'json'</strong>.</p>
<pre><code class=''>$.ajax({<br />
&nbsp;&nbsp;url: $('base').attr('host')+$form.attr('action'),<br />
&nbsp;&nbsp;data: $form.serialize(),<br />
&nbsp;&nbsp;type: 'POST',<br />
&nbsp;&nbsp;dataType: 'json',<br />
&nbsp;&nbsp;success: function(content) {<br />
&nbsp;&nbsp;  if(content.saved) {<br />
&nbsp;&nbsp;      $form.closest('fieldset').prev().find('ul')<br />
&nbsp;&nbsp;          .find('li.empty').remove().end()<br />
&nbsp;&nbsp;          .append('&lt;li&gt;Neuer Eintrag &lt;b&gt;'+$form.find('input[type=text]:first').val()+'&lt;/b&gt; angelegt.&lt;/li&gt;');<br />
&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;  else {<br />
&nbsp;&nbsp;      alert("Leider ist ein Fehler beim speichern aufgetreten.");<br />
&nbsp;&nbsp;  }<br />
&nbsp;&nbsp;}<br />
});</code></pre>
<p>In der Variable <strong>$form</strong> ist das jQuery Objekt gespeichert, welches das Formular widerspiegelt, dass gerade abgeschickt wurde. Da man immer wieder darauf zugreifen muss, macht es Sinn das in eine Variable zu legen um Zeit bei der Abarbeitung zu sparen.</p>
<p>In der Variable <strong>content</strong> stehen jetzt dank <em>AppController</em> und <em>RequestHandler</em> alle View-Variablen zur Verfügung. Über das Auslesen des Attributs <strong>Action</strong> des Formulars muss man sich nicht mal mehr Gedanken machen wo das Formular überhaupt abgearbeitet wird. Wichtig ist nur das in der entsprechenden Funktion ein Status gesetzt wird:</p>
<pre><code class=''>$this-&gt;set('saved', true);</code></pre>
<h2>Fazit</h2>
<p>Nach genau dem gleichen Prinzip funktioniert auch das Löschen oder jeder andere Anwendungsfall der einem einfällt. Ich bin im Moment mal wieder begeistert von diesen beiden tollen Frameworks und den schier unerschöpflichen Möglichkeiten.</p>
<p>Demnächst gibt es dann hoffentlich mal die Vorstellung von einem fertigen Tool. Bis dahin freue ich mich auf Fragen und Verbesserungsvorschläge. Vielen Dank fürs lesen!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.interaktionsdesigner.de/2009/11/21/ajax-in-webapplikationen-mit-cakephp-und-jquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Einen Mini-Blog mit TYPO3 realisieren</title>
		<link>http://www.interaktionsdesigner.de/2009/10/11/einen-mini-blog-mit-typo3-realisieren/</link>
		<comments>http://www.interaktionsdesigner.de/2009/10/11/einen-mini-blog-mit-typo3-realisieren/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 10:26:11 +0000</pubDate>
		<dc:creator>Paul</dc:creator>
				<category><![CDATA[TYPO3]]></category>

		<guid isPermaLink="false">http://www.interaktionsdesigner.de/?p=613</guid>
		<description><![CDATA[Der Kiwi Service (meine Firma) hat mit großer Freude sein neustes Projekt realisert: Der Internetauftritt der Lauscherlounge erstrahlt in schönem neuen Design und bietet mit TYPO3 im Hintergrund den gewohnten Komfort, die Trauer aber vorallem die Freude und Effizienz!
Eine von vielen schönen Kleinigkeiten ist Olis Notziblog auf der rechten Seite. Es handelt sich um ein [...]]]></description>
			<content:encoded><![CDATA[<p>Der <a title="Computer und Medienservice aus Berlin" href="http://www.kiwi-service.de" target="_blank">Kiwi Service</a> (meine Firma) hat mit großer Freude sein neustes Projekt realisert: Der Internetauftritt der <a title="Kiwi realisiert den Relaunch der Lauscherlounge" href="http://www.lauscherlounge.de" target="_blank">Lauscherlounge</a> erstrahlt in schönem neuen Design und bietet mit TYPO3 im Hintergrund den gewohnten Komfort, die Trauer aber vorallem die Freude und Effizienz!</p>
<p>Eine von vielen schönen Kleinigkeiten ist <strong>Olis Notziblog</strong> auf der rechten Seite. Es handelt sich um ein Widget in dem immer mal wieder, unkompliziert neue Inhalte eingetragen werden sollen. Das Besondere ist, dass ein Inhalt aus einem Bild (der Handschrift) und der Abschrift besteht. Sprich <strong>Text mit Bild</strong>. Das kommt dem geschulten TYPO3 Ohr natürlich bekannt vor. Und genauso werden die Daten vorgehalten. <strong>In Contentelementen.</strong></p>
<p>Dieses Tutorial beschreibt die <strong>Einrichtung</strong>, <strong>Verwaltung</strong> und <strong>Ausgabe</strong> eines Miniblogs, der einfach zu pflegen ist und Informationen ohne große Funktionen zur Verfügung stellt.</p>
<p><span id="more-613"></span></p>
<h2>Backend</h2>
<p>Es wird eine <strong>nicht im Menü sichtbare Seite</strong> angelegt, dem Redakteur freigegeben und die ID (z.B. <em>50</em>) notiert. Hier sollte man jetzt testweise einen Inhalt anlegen. Soweit sehr einfach.</p>
<h2>Typoscript</h2>
<p>Entweder wird ein <strong>eigener Marker</strong> im Template festgelegt, oder, was ich empfehlen würde, der Marker für die rechte Spalte wird als <strong>COA</strong> angelegt. COA beschreibt eine Sammlung von Objekten die nacheinander ausgegeben werden. Im ersten Schritt soll schlicht der <strong>Inhalt der rechten Spalte</strong> aus dem Backend ausgegeben werden:</p>
<pre><code class=''>page.10.marks.RIGHT = COA<br />
page.10.marks.RIGHT.50 = CONTENT<br />
page.10.marks.RIGHT.50 {<br />
&nbsp;&nbsp;table = tt_content<br />
&nbsp;&nbsp;select.orderBy = sorting<br />
&nbsp;&nbsp;select.where = colPos = 2<br />
&nbsp;&nbsp;select.languageField = sys_language_uid<br />
}</code></pre>
<p>Mit dieser Struktur, die man auch bedenkenlos für die linke und die Hauptspalte benutzen kann, hat man <strong>absolute Flexibilität</strong> auf den Unterseiten. Olis Blog erscheint nur auf der Startseite. Also wird ein <strong>Extensiontemplate</strong> angelegt und der Marker <em>RIGHT</em> erweitert:</p>
<pre><code class=''>page.10.marks.RIGHT.40 = PHP_SCRIPT<br />
page.10.marks.RIGHT.40.file = fileadmin/template/scripts/olis_notizblog.php</code></pre>
<p>Vor dem Menü wird dem Marker ein <strong>PHP Script </strong>hinzugefügt.</p>
<h2>PHP Script</h2>
<p>Jetzt ist es nicht mehr weit. Hinter oben angegebenen Pfad erstellt man eine Datei. Zwei Dinge muss man beachten:</p>
<ol>
<li>Alle Inhalte die später im Marker erscheinen sollen, müssen in die Variable <em>$content </em>geschrieben werden</li>
<li>Auch wenn der Testserver die PHP Kurzschreibweise <em>&lt;? ... ?&gt;</em> unterstützt, sollte man diese nicht mehr verwenden! In PHP 6 soll sie abgeschafft werden und etliche Konfigurationen verbieten sie jetzt schon, was zur Folge hat, dass der Code einfach als Text ausgegeben wird.</li>
</ol>
<p>Die erste Aufgabe besteht darin, das neuste Element aus der <strong>tt_content Tabelle</strong> auszulesen. Es muss also nach Zeit sortiert werden und das Element muss auf der richtigen Seite gespeichert werden (<em>ID 50</em>). Das erreicht man über die Abfrage der Spalte <strong>PID</strong>.</p>
<pre><code class=''>$posts = $GLOBALS['TYPO3_DB']-&gt;exec_SELECTgetRows(<br />
&nbsp;&nbsp;'uid, header, bodytext, image',<br />
&nbsp;&nbsp;'tt_content',<br />
&nbsp;&nbsp;'pid = "50" AND deleted = "0" AND hidden = "0"',<br />
&nbsp;&nbsp;'',<br />
&nbsp;&nbsp;'sorting ASC',<br />
&nbsp;&nbsp;1<br />
);</code></pre>
<p>Der äußerst praktische Befehl <em>exec_SELECTgetRows</em> erwartet folgende Parameter: auszulesende Felder, gewünschte Tabelle, WHERE-Bedingung, eventuell Gruppierung, Bedingung zum Sortieren und die Anzahl der erwarteten Ergebnisse.</p>
<p>Das kann man sich natürlich nur schwer merken, aber dafür gibt es zum Glück eine <a title="TYPO3 API" href="http://typo3.org/fileadmin/typo3api-4.2.6/" target="_blank">Dokumentation</a> zum nachsehen.</p>
<p><em>exec_SELECTgetRows</em> liefert im Gegensatz zu <em>exec_SELECTquery</em> keine Datenbankressource zurück, sondern ein Objekt über alle gefundenen Zeilen. In unserem Fall ist das nur eine und es wird auch immer eine bleiben, deshalb kann man immer so an sie herankommen:</p>
<pre><code class=''>$post = $posts[0];</code></pre>
<p>Jetzt ist es nur noch eine Frage der Anforderung und einer testweisen Ausgabe mit <em>print_r($post)</em> um ein Ergebnis zu erhalten:</p>
<pre><code class=''>$content = '&lt;div class="blog"&gt;';<br />
$content.= '&lt;h3&gt;'.$post['header'].'&lt;/h3&gt;';<br />
$content.= '&lt;p&gt;'.$post['bodytext'].'&lt;/p&gt;';<br />
$content.= '&lt;/div&gt;';</code></pre>
<h2>Fazit</h2>
<p>Fertig ist der Lack/<strong>Blog</strong>! Über dem Hauptmenü erscheint jetzt immer das neuste Element aus der versteckten Seite. Sicher hätte man das ganze auch mit puren Typoscript lösen können, aber meiner Ansicht nach ist diese Lösung flexibler. Eventuell sollen die Inhalte demnächst auf Twitter, Facebook, MySpace und SpiegelOnline erscheinen. Da ist es dann schön ein Script zur Verfügung zu haben, in dem man sich austoben kann.</p>
<p>Bleibt noch zu sagen, <a title="Hörbücher, großartige Literatur bei der Lauscherlounge!" href="http://www.lauscherlounge.de" target="_blank">hört mehr Hörbücher</a>!!!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.interaktionsdesigner.de/2009/10/11/einen-mini-blog-mit-typo3-realisieren/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>TYPO3 Seiten und tt_news Kategorien synchron halten</title>
		<link>http://www.interaktionsdesigner.de/2009/09/30/typo3-seiten-und-tt_news-kategorien-synchron-halten/</link>
		<comments>http://www.interaktionsdesigner.de/2009/09/30/typo3-seiten-und-tt_news-kategorien-synchron-halten/#comments</comments>
		<pubDate>Wed, 30 Sep 2009 13:40:15 +0000</pubDate>
		<dc:creator>Paul</dc:creator>
				<category><![CDATA[TYPO3]]></category>

		<guid isPermaLink="false">http://www.interaktionsdesigner.de/?p=608</guid>
		<description><![CDATA[Heute mal wieder ein richtig schönes Thema: Es geht um Seiten in einem TYPO3 Projekt und Nachrichten, die zu diesen Seiten gehören. Die Anforderung besteht darin, beim anlegen oder verändern von Seiten tt_news Kategorien auf dem gleichen Stand zu halten.
Legt der Redakteur eine neue Seite Namens "Zimmerschlacht" an, könnte er anschließend in die Listenansicht wechseln [...]]]></description>
			<content:encoded><![CDATA[<p>Heute mal wieder ein richtig schönes Thema: Es geht um Seiten in einem TYPO3 Projekt und Nachrichten, die zu diesen Seiten gehören. Die Anforderung besteht darin, beim <strong>anlegen</strong> oder <strong>verändern</strong> von Seiten <strong>tt_news Kategorien</strong> auf dem gleichen Stand zu halten.</p>
<p>Legt der Redakteur eine neue Seite Namens "<em>Zimmerschlacht</em>" an, könnte er anschließend in die Listenansicht wechseln und eine neue <strong>News Kategorie</strong> anlegen. Aber mach das mal einem <em>DAR</em> (analog zu DAU) klar. Und warum den Mund fusselig reden, wenn das auch <strong>automatisch</strong> geht?!</p>
<p>Es gibt in TYPO3 eine Möglichkeit mit einem Hook in das <strong>Speichern von Datensätzen</strong> einzugreifen. Da kann man sich dann austoben. Es funktioniert auch mit <strong>DAM Kategorien</strong> und jeder anderen vorstellbaren <strong>Datenbankanforderung</strong>.</p>
<p><span id="more-608"></span></p>
<h2>Vorbereitung</h2>
<p>Wenn der Redakteur in einem bestimmten Zweig des Seitenbaums eine Aktion auslöst (neue Seite erstellen, bearbeiten oder löschen) muss mit einem Script darauf reagiert werden. Dafür legt man an seinem <strong>Lieblingsplatz</strong> eine Datei an und merkt sich sowohl Pfad und Namen. Mein Vorschlag:</p>
<pre><code class=''>fileadmin/template/hooks/class.tx_createCategories_tcemainprocdm.php</code></pre>
<p>In dieser Datei sucht TYPO3 später eine Klasse deren Namen wir auch selbst bestimmen können.</p>
<pre><code class=''>class tx_createCategories_tcemainprocdm {<br />
}</code></pre>
<h2>Hooks verstehen</h2>
<p>Hooks sind Funktionen die während der Abarbeitung eines Scripts aufgerufen werden. Meistens erstellt TYPO3 ein <strong>Objekt von der übergebenen Klasse</strong> und das Script sucht nach einer passenden Funktion mit <strong>fest definiertem Namen</strong>.</p>
<h2>Hooks suchen</h2>
<p>Google ist natürlich Anlaufpunkt Nummer eins, aber auch der <strong>Quelltext</strong> der betreffenden Datei bietet gute Anhaltspunkte. Wie die Vorschläge oben schon deutlich machen geht es mir um <em>class.t3lib_tcemain.php</em> welches sich um sämtliche Datenbankoperationen kümmert. Die <a href="http://typo3.org/documentation/document-library/core-documentation/doc_core_api/4.2.0/view/" target="_self">Core API</a> bietet einen guten Anlaufpunkt. Nach einigem hin und her weiß man dann, dass man den Hook Namens <em>processDatamap_afterDatabaseOperations</em> braucht.</p>
<h2>Hooks registrieren</h2>
<p>Über die Datei <em>localconf.php</em> wird das <em>$GLOBALS Array</em> erweitert. Die genauen Bezeichnungen findet man meistens in der Dokumentation oder dem Quelltext. Um auf das verändern von Seiten zu reagieren muss man folgende Zeile hinzufügen:</p>
<pre><code class=''>$GLOBALS["TYPO3_CONF_VARS"]["SC_OPTIONS"]["t3lib/class.t3lib_tcemain.php"]["processDatamapClass"][] = "fileadmin/template/hooks/class.tx_createCategories_tcemainprocdm.php:tx_createCategories_tcemainprocdm";</code></pre>
<p>Der Inhalt dieser Angabe ist in zwei Teile durch ein Doppelpunkt geteilt: Der erste gibt den <strong>Pfad zur Datei</strong> an, der zweite den <strong>Namen der zu initalisierenden Klasse</strong>.</p>
<p><big><strong>Nicht vergessen den Cache zu löschen!!!</strong></big> Sonst ärgert man sich zu tode!</p>
<h2>Logik hinzufügen</h2>
<p>Bis hierher alles klar? TYPO3 erstellt eine neue Seite, initalisiert anschließend das eben angegebene Objekt und sucht darin die Funktion <em>processDatamap_afterDatabaseOperations</em> und führt sie aus. In dem Script im fileadmin legt man also los und führt aus was man ausführen muss:</p>
<pre><code class=''>class tx_createCategories_tcemainprocdm {<br />
&nbsp;&nbsp;function processDatamap_afterDatabaseOperations($status, $table, $id, $fieldArray, &amp;$reference) {<br />
&nbsp;&nbsp;}<br />
}</code></pre>
<p>Spannend sind die Parameter:</p>
<ul>
<li><strong>$status</strong> gibt an, was der User getan hat. z.B. "new"</li>
<li><strong>$table</strong> sagt, in welcher Tabelle der User es getan hat. z.B. "pages"</li>
<li><strong>$id</strong> beinhaltet die UID des Datensatzes (aber mit Einschränkungen! Siehe unten).</li>
<li><strong>$fieldArray</strong> enthält die neuen Felder. Wenn der Redakteur nur den Titel geändert hat, dann steht hier nur der neue Titel in einem assoziativen Array drin.</li>
<li><strong>$reference</strong> ist ein Objekt und beinhaltet die ggf. schon vorhandenen Inhalte.</li>
</ul>
<p>Mit diesen Informationen ausgerüstet kann man schon eine ganze Menge erreichen. Mit einem <em>echo</em> kann man sich auch ohne Probleme Daten ausgeben. Die erscheinen dann über dem Formular im Backend. Sieht nicht schön aus, aber man kann etwas lesen.</p>
<h2>Die richtige UID erkennen</h2>
<p>Das Problem ist, dass bei einem neuen Datensatz im Parameter <em>$id</em> eine temporäre UID gespeichert ist. Irgendwas wie<em> NEW_2352</em>. Also definitiv keine Integer sondern ein <strong>String</strong>. Der Hook wird aber nach dem Speichern ausgeführt, deshalb muss man sich über <em>$reference</em> die richtige UID besorgen:</p>
<pre><code class=''>if(!is_numeric($id)) {<br />
&nbsp;&nbsp;$id = $reference-&gt;substNEWwithIDs[$id];<br />
}</code></pre>
<p>Das habe ich auch nur in irgendeiner Mailingliste aufgeschnappt. Selbsterklärend ist etwas anderes.</p>
<h2>Neue Kategorien anlegen</h2>
<p>Zurück zur Anforderung. Wenn ein Redakteur eine neue Seite anlegt, muss <strong>eine neue Kategorie angelegt</strong> werden. Dafür muss als erstes geprüft werden, ob überhaupt eine Seite angelegt wurde und der Titel geändert wurde:</p>
<pre><code class=''>if($table == 'pages' &amp;&amp; $id &gt; 0 &amp;&amp; !empty($fieldArray['title']) {<br />
&nbsp;&nbsp;//hier gehts weiter<br />
}</code></pre>
<p>In dieser Abfrage muss auch noch geklärt werden, ob sich die Seite an der richtigen Stelle befindet. Das kann man über die <strong>PID</strong> erreichen oder wie in meinem Fall über einen eigenen Seitentyp. Beide Angaben findet man im Array <em>$reference-&gt;checkValue_currentRecord</em>.</p>
<pre><code class=''>if($status == 'new')</code></pre>
<p>Endlich mal wieder etwas schönes. Alternativ könnte man auch mit Switch auf die verschiedenen Operationen reagieren. Je nach Vorliebe. Wurde also eine neue Seite an der richtigen Position angelegt, wird nichts weiter getan als eine Zeile in der Tabelle <em>tt_news_cat</em> zu speichern:</p>
<pre><code class=''>$GLOBALS['TYPO3_DB']-&gt;exec_INSERTquery(<br />
&nbsp;&nbsp;'tt_news_cat',<br />
&nbsp;&nbsp;array(<br />
&nbsp;&nbsp;[tab]'pid' =&gt; 194,<br />
&nbsp;&nbsp;[tab]'title' =&gt; $fieldArray['title'],<br />
&nbsp;&nbsp;[tab]'shortcut' =&gt; $id<br />
&nbsp;&nbsp;)<br />
);</code></pre>
<h2>Seiten und Kategorien umbenennen</h2>
<p>Da kommt nochmal das Array <em>$reference-&gt;checkValue_currentRecord</em> zum Einsatz. Wird eine Seite aktualisiert steht dort der alte Titel drin und im <em>$fieldArray</em> der neue. Schöne Sache das und nur eine handvoll Zeilen um die entsprechende Kategorie zu <strong>identifizieren</strong> und <strong>umzubenennen</strong>:</p>
<pre><code class=''>$GLOBALS['TYPO3_DB']-&gt;exec_UPDATEquery(<br />
&nbsp;&nbsp;'tt_news_cat',<br />
&nbsp;&nbsp;'title = "'.$reference-&gt;checkValue_currentRecord['title'].'"',<br />
&nbsp;&nbsp;array(<br />
&nbsp;&nbsp;[tab]'title' =&gt; $fieldArray['title']<br />
&nbsp;&nbsp;)<br />
);</code></pre>
<p>Nach diesen beiden Beispielen sollte das Löschen auch keine Schwierigkeiten mehr bereiten. Der Redakteur wird es gar nicht bemerken, aber der effektive Teil vom Webentwicklerherz schlägt jetzt schon schneller.</p>
<p>Mit ein bisschen PHP Erfahrung sollte man sich unbedingt mit den <strong>Hooks</strong> auseinander setzen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.interaktionsdesigner.de/2009/09/30/typo3-seiten-und-tt_news-kategorien-synchron-halten/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>entireHtml 2.0</title>
		<link>http://www.interaktionsdesigner.de/2009/09/23/entirehtml-2-0/</link>
		<comments>http://www.interaktionsdesigner.de/2009/09/23/entirehtml-2-0/#comments</comments>
		<pubDate>Wed, 23 Sep 2009 15:24:04 +0000</pubDate>
		<dc:creator>Paul</dc:creator>
				<category><![CDATA[Allgemein]]></category>

		<guid isPermaLink="false">http://www.interaktionsdesigner.de/?p=600</guid>
		<description><![CDATA[Ich habe schon mal darüber bereichtet. Die Funktion $('.test').html() liefert nicht das komplette HTML, sondern nur das innerHTML. Mit meinem vorhergehenden Post kriegt man schon sehr einfach das komplette HTML eines Elements, und genau das ist das Problem: eines Elements.
Mit ein paar Zeilen mehr im Plugin läufts auch mit beliebig vielen Objekten. So funktionierts:

Die Anforderung
...ist [...]]]></description>
			<content:encoded><![CDATA[<p>Ich habe schon mal darüber bereichtet. Die Funktion <strong>$('.test').html()</strong> liefert nicht das komplette HTML, sondern nur das <strong>innerHTML</strong>. Mit meinem <a title="entireHtml in Pauls Blog" href="http://www.interaktionsdesigner.de/2009/05/06/das-komplette-html-eines-elements-mit-jquery-auslesen/" target="_self">vorhergehenden Post</a> kriegt man schon sehr einfach das komplette HTML eines Elements, und genau das ist das Problem: <strong>eines Elements</strong>.</p>
<p>Mit ein paar Zeilen mehr im Plugin läufts auch mit beliebig vielen Objekten. So funktionierts:</p>
<p><span id="more-600"></span></p>
<h2>Die Anforderung</h2>
<p>...ist alt bekannt. Folgendes HTML liegt vor:</p>
<pre><code class=''>&lt;div class="test"&gt;<br />
&nbsp;&nbsp;Wir sind &lt;strong&gt;wichtig&lt;/strong&gt;<br />
&lt;/div&gt;</code></pre>
<p>Wenn man dieses HTML auslesen will und nur weiß, dass das Zielelement die Klasse <em>test</em> hat, schlägt folgender Versuch fehl:</p>
<pre><code class=''>$('.test').html(); //funktioniert nicht</code></pre>
<p>Funktioniert nicht, weil das Ergebnis nicht komplett ist.</p>
<pre><code class=''>Wir sind &lt;strong&gt;wichtig&lt;/strong&gt;</code></pre>
<p>Mein kleines <a title="entireHtml in Pauls Blog" href="http://www.interaktionsdesigner.de/2009/05/06/das-komplette-html-eines-elements-mit-jquery-auslesen/">Plugin entireHtml</a> hilft weiter, und liefert wie erwartet das komplette HTML. So wirds allerdings nervig:</p>
<pre><code class=''>&lt;div class="test"&gt;<br />
&nbsp;&nbsp;Wir sind &lt;strong&gt;wichtig&lt;/strong&gt;<br />
&lt;/div&gt;<br />
&lt;div class="test"&gt;<br />
&nbsp;&nbsp;und das ist &lt;strong&gt;schön&lt;/strong&gt;.<br />
&lt;/div&gt;</code></pre>
<p>Die Funktion <em>entireHtml</em> liefert nur das HTML des <strong>ersten</strong> divs zurück.</p>
<h2>Die Lösung</h2>
<p>Im Plugin stehen alle Objekte in der Variable <em>this</em> zur Verfügung. Das Plugin muss, wenn mehr als ein Element im Stack liegt, <strong>jedes</strong> Element durchgehen und das komplette HTML zurückgeben.</p>
<p>Und ohne große Worte folgt jetzt das <strong>komplette Plugin</strong>:</p>
<pre style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; "><span style="color:#e27600;">/*
 *  entireHtml
 *  Ein kleines, nettes Plugin um das komplette HTML eines Selectors zu bekommen.
 *
 *  Mehr Infos unter http://www.interaktionsdesigner.de
 */</span>

(<span style="color:#3f7bc6;">function</span>($) {
  jQuery.fn.entireHtml = <span style="color:#3f7bc6;">function</span>() {
    <span style="color:#3f7bc6;">if</span>(<span style="color:#3f7bc6;">this</span>.length == <span style="color:#fe2d00;">1</span>) {
      <span style="color:#3f7bc6;">return</span> <span style="color:#3f7bc6;">this</span>.<span style="color:#4080ff;">clone</span>().<span style="color:#4080ff;">wrap</span>(<span style="color:#df2800;">'&lt;div&gt;&lt;/div&gt;'</span>).<span style="color:#4080ff;">parent</span>().<span style="color:#4080ff;">html</span>();
    }
    <span style="color:#3f7bc6;">else</span> {
      <span style="color:#3f7bc6;">var</span> html = <span style="color:#df2800;">''</span>;
      $(<span style="color:#3f7bc6;">this</span>).<span style="color:#4080ff;">each</span>(<span style="color:#3f7bc6;">function</span>() {
        html+= $(<span style="color:#3f7bc6;">this</span>).<span style="color:#4080ff;">entireHtml</span>();
      });
      <span style="color:#3f7bc6;">return</span> html;
    }
  }
})(jQuery);</pre>
<h2>Fazit</h2>
<p>Schön, oder? Funktioniert wie erwartet. Noch eine Antwort: <strong>Wozu braucht man das?</strong> Im Moment arbeiten wir an einem interaktiven Tool um PDFs zu erstellen. Das Formular kommt aus der Extension Powermail für TYPO3 und wird von einem Redakteursteam gepflegt. Im Frontend sollen aber bestimmte Optionen erst auf Nachfrage sichtbar sein.</p>
<p>Redakteur fügt also Dateiuploadfelder hinzu und speichert. jQuery "merkt" das, nimmt das komplette HTML raus, packt es in eine Box, versteckt die Felder und legt einen Link ala "Klicken Sie hier, wenn Sie eine Datei hochladen möchten".</p>
<p>Ich sach nur: Kundenprojekte...</p>
]]></content:encoded>
			<wfw:commentRss>http://www.interaktionsdesigner.de/2009/09/23/entirehtml-2-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Select Boxes dynamisch verändern</title>
		<link>http://www.interaktionsdesigner.de/2009/09/03/select-boxes-dynamisch-verandern/</link>
		<comments>http://www.interaktionsdesigner.de/2009/09/03/select-boxes-dynamisch-verandern/#comments</comments>
		<pubDate>Thu, 03 Sep 2009 08:00:00 +0000</pubDate>
		<dc:creator>Paul</dc:creator>
				<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://www.interaktionsdesigner.de/?p=591</guid>
		<description><![CDATA[Die praktische Auswahl von Daten über eine Selectbox ist immer wieder ein Thema. Vorallem bei den ganzen neuen Beta-Ajax-Web-Applications kommen sie einem immer wieder unter.
Das Problem mit den Dingern, ist die dynamische Veränderung. Ein einfaches $("select").find("option:first").remove(); funktioniert zwar zum entfernen, aber das hinzufügen von Options ist schon schwieriger (-böser Blick zum Internet Explorer-). Und wenn [...]]]></description>
			<content:encoded><![CDATA[<p>Die praktische Auswahl von Daten über eine Selectbox ist immer wieder ein Thema. Vorallem bei den ganzen neuen <strong>Beta-Ajax-Web-Applications</strong> kommen sie einem immer wieder unter.</p>
<p><strong>Das Problem </strong>mit den Dingern, ist die dynamische Veränderung. Ein einfaches <em>$("select").find("option:first").remove();</em> funktioniert zwar zum entfernen, aber das hinzufügen von Options ist schon schwieriger (<strong>-böser Blick zum Internet Explorer-</strong>). Und wenn die Selectbox sich dann an einer weiteren orientieren soll, dann wirds haarig.</p>
<p><strong>Die Lösung</strong> ist das Klonen und verstecken der "originalen" Box. Aus dem Klon kann man dann die überflüssigen Auswahlmöglichkeiten entfernen.</p>
<p>Und jetzt folgt der Artikel wie man das effizient anstellen könnte. Natürlich Hand in Hand mit <strong>jQuery</strong>.</p>
<p><span id="more-591"></span></p>
<h2>Das Problem</h2>
<p>Folgende Anforderung bestand im aktuellen Projekt: In der ersten Selectbox wird die Frequenz gewählt (monatlich, vierteljährlich usw.). Die zweite Box bietet eine Auswahl an Monaten zur Angabe der Dauer.</p>
<pre><code class=''>&lt;select name="frequency" class="frequency"&gt;<br />
&nbsp;&nbsp;&lt;option value="1"&gt;monatlich&lt;/option&gt;<br />
&nbsp;&nbsp;&lt;option value="3"&gt;vierteljährlich&lt;/option&gt;<br />
&nbsp;&nbsp;&lt;option value="6"&gt;halbjährlich&lt;/option&gt;<br />
&nbsp;&nbsp;&lt;option value="12"&gt;jährlich&lt;/option&gt;<br />
&lt;/select&gt;</code></pre>
<pre><code class=''>&lt;select name="months" class="months"&gt;<br />
&nbsp;&nbsp;&lt;option value="0"&gt;0&lt;/option&gt;<br />
&nbsp;&nbsp;&lt;option value="1"&gt;1&lt;/option&gt;<br />
&nbsp;&nbsp;&lt;option value="2"&gt;2&lt;/option&gt;<br />
&nbsp;&nbsp;&lt;option value="3"&gt;3&lt;/option&gt;<br />
&nbsp;&nbsp;&lt;option value="4"&gt;4&lt;/option&gt;<br />
&nbsp;&nbsp;&lt;option value="5"&gt;5&lt;/option&gt;<br />
&nbsp;&nbsp;&lt;option value="6"&gt;6&lt;/option&gt;<br />
&nbsp;&nbsp;&lt;option value="7"&gt;7&lt;/option&gt;<br />
&nbsp;&nbsp;&lt;option value="8"&gt;8&lt;/option&gt;<br />
&nbsp;&nbsp;&lt;option value="9"&gt;9&lt;/option&gt;<br />
&nbsp;&nbsp;&lt;option value="10"&gt;10&lt;/option&gt;<br />
&nbsp;&nbsp;&lt;option value="11"&gt;11&lt;/option&gt;<br />
&lt;/select&gt;</code></pre>
<h2>Theoretisch</h2>
<p>Sehr einfach zu erklären: Der Anwender wählt in der ersten Auswahl "<em>halbjährlich</em>" - darauf hin stehen in der Monatsauswahl nur noch "<em>0</em>" und "<em>6</em>" zur Verfügung. Welcher Monat angezeigt wird, kann ganz einfach mit der <strong>Modulo-Operation</strong> berechnet werden. <a title="Pauls Blog über die Modulo Operation" href="http://www.interaktionsdesigner.de/2009/01/27/modulo-verstehen-und-benutzen/" target="_blank">Darüber hatte ich mich auch schon im Blog ausgelassen.</a></p>
<p><span>Der Klon wird mit der Klasse <em>active</em> gekennzeichnet und muss vor der nächsten Veränderung entfernt werden.<br />
</span></p>
<h2>Praktisch</h2>
<p>Jetzt wirds nett. jQuery ist natürlich im Projekt eingebunden. Sobald das Dokument geladen wurde, muss ein <strong>Eventhandler</strong> auf die Frequenzauswahl gelegt werden.</p>
<pre><code class=''>jQuery(function($) {<br />
&nbsp;&nbsp;$("select.frequency").onChange(function() {<br />
&nbsp;&nbsp;//hier gehts weiter!!<br />
&nbsp;&nbsp;});<br />
});</code></pre>
<p><span>Diese Form ist besser als das überall gesehene <em>$(document).ready(function() {})</em>, denn die <em>$</em> Funktion muss nicht mehr zwangsläufig von jQuery besetzt sein, sondern wird dem eigenen Code als Parameter übergeben.</span></p>
<p><span>Als nächstes beschreibe ich alle Schritte zum Ändern der Selectbox <em>$("select.months")</em> einzelnd. Anschließend gibts nochmal die komplette Funktion unkommentiert im Ganzen.</span></p>
<p><span><br />
</span></p>
<pre><code class=''>new_frequency = $(this).val();<br />
$form = $(this).parents("form:first");</code></pre>
<p>Die Auswahl wird in <em>new_frequency</em> zwischengespeichert und das umfassende Formular in der Variable <strong>$form</strong> abgelegt, um später schneller darauf zugreifen zu können.</p>
<p>Die Variable <em>$form</em> beginnt mit einem Dollarzeichen. Damit kennzeichne ich Variablen, die ein jQuery-Objekt enthalten. So ist es leicher, diese im weiteren Verlauf zu erkennen. Dieses Vorgehensweise kann ich <strong>wärmstens empfehlen</strong>.</p>
<pre><code class=''>if($("select.months.active", $form).length &gt; 0) {<br />
&nbsp;&nbsp;$("select.months", $form).filter(".active").remove().end().show();<br />
}</code></pre>
<p>Mit der Anweisung <em>$("select.months.active", $form).length</em> werden alle Selectboxen mit der Klasse <em>active</em> gesucht. Sind diese vorhanden, werden <strong>beide Selectboxen</strong> (die ggf. versteckte und der Klon) selektiert.</p>
<p>Mit der Funktion <em>filter(".active")</em> wird davon die aktive Selectbox ausgewählt und entfernt. Das <em>end() </em>setzt die Auswahl von <em>filter()</em> zurück und<em> show() </em>zeigt die übrig gebliebene Selectbox an.</p>
<p><strong>jQuery Power</strong> in einer einzigen Zeile! Aber es wird noch besser...</p>
<p>Die Selectbox mit der Klasse <em>.months</em> muss geklont werden, verändert, angezeigt und die ursprüngliche Box versteckt werden. Zum Glück braucht man dazu auch nicht mehr als <strong>eine Zeile</strong>.</p>
<pre><code class=''>$("select.months", $form).clone().hide().insertBefore("select.months").end().addClass("active").find("option").filter(function(i) { return i%new_frequency == 0 ? false : true; }).remove();</code></pre>
<p>Sieht komplizierter aus als es ist. Man kann es praktisch Stück für Stück lesen:</p>
<ol>
<li><strong>$("select.months", $form)</strong> sucht die Selectbox im aktuellen Formular mit der Klasse <em>months</em>.</li>
<li><strong>clone()</strong> kopiert die aktuelle Auswahl und speichert sie <em>irgendwo</em> zwischen. Die Auswahl besteht <strong>nicht</strong> aus dem Klon, sondern der ursprünglichen Auswahl.</li>
<li><strong>hide() -</strong> deshalb kann die Auswahl, also die <strong>erste</strong> Selectbox, auch einfach versteckt werden. Das passiert nach dem klonen, damit der Klon nicht extra wieder eingeblendet werden muss.</li>
<li><strong>insertBefore("select.months")</strong> fügt den Klon vor der Selectbox ein.</li>
<li><strong>end()</strong> setzt die Auswahl zurück. Damit besteht die Auswahl aus dem Klon und nicht mehr aus der ursprünglichen Selectbox.</li>
<li><strong>addClass("active")</strong><em> </em>fügt die Klasse hinzu damit der Klon später erkannt werden kann.</li>
<li><strong>find("option")</strong> sucht alle Optiontags innerhalb der geklonten Selectbox.</li>
<li><strong>filter(function(i) { return i%new_frequency == 0 ? false : true; })</strong><br />
Ein großartiges Stück jQuery präsentiert hier die ganze Power der <em>filter()</em> Funktion. Dieser kann man nicht nur einen <strong>Tagnamen</strong>, eine <strong>ID</strong> oder eine <strong>Klasse</strong> übergeben, sondern auch eine <strong>anonyme Funktion</strong>! Anhand dieser wird jedes enthaltene Element überprüft. Gibt die Funktion <em>true</em> zurück, bleibt das Element in der Auswahl; ansonsten fliegt es raus.<br />
Diese Funktion besteht nur aus einer simplen Berechnung und schmeißt alle Monate raus, welche zur gespeicherten Frequenz passen.<br />
Schön, oder?</li>
<li><strong>remove()</strong> entfernt dann die übrig gebliebenen Auswahlmöglichkeiten.</li>
</ol>
<p><strong>Fertig!</strong> Eine einzige Zeile klont und bearbeitet die Auswahlmöglichkeit. Und das sooft der Benutzer möchte. So sieht die Funktion im ganzen aus:</p>
<pre><code class=''>$(".frequency").change(function() {<br />
&nbsp;&nbsp;new_frequency = $(this).val();<br />
&nbsp;&nbsp;$form = $(this).parents("form:first");<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;if($("select.months.active", $form).length &gt; 0) {<br />
&nbsp;&nbsp;  $("select.months", $form).filter(".active").remove().end().show();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;$("select.months", $form)<br />
&nbsp;&nbsp;    .clone().hide().insertBefore(".plan:visible select.months").end().addClass("active")<br />
&nbsp;&nbsp;    .find("option").filter(function(i) { return i%new_frequency == 0 ? false : true; }).remove();<br />
});</code></pre>
<h2>Fazit</h2>
<p>Ich mag jQuery. Kennst du eine besser Lösung? Mal abgesehen von Plugins die das ganze mit einem unüberschaubaren Overhead erledigen?</p>
<p>Ansonten viel Spaß mit <em>abhängigen</em> Selectboxen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.interaktionsdesigner.de/2009/09/03/select-boxes-dynamisch-verandern/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
