Ich hatte die letzten zwei Mal schwierigkeiten die neueste TYPO3 Version 4.5.x auf Localhost (XAMPP) zu installieren. In XAMPP ist der Datenbank-User, der bereits eingerichtet ist root ohne Passwort. Solange man lokal arbeitet ist es ja auch in Ordnung. Im Install-Tool kann man das Feld Passwort nicht einfach frei lassen, da es erforderlich ist. Also überspringe ich den 1-2-3-Modus und will die Datenbankzugangsdaten selbst in localconf.php eingeben. Das funktioniert aber auch nicht – TYPO3 Install Tool meldet noch immer “Keine Verbindung zur Datenbank”. Ich versuche einen neuen Datenbank-Benutzer über phpMyAdmin anzulegen – mit Passwort – und trage die Daten dann in localconf.php ein. Immer noch kein Erfolg. Nachdem ich schließlich den Datenbank-Namen in die Konfigurationsdatei geschrieben habe und eine Fehlermeldung auftauchte “ADONewConnection: Unable to load database driver”, hatte ich zumindest eine Fehlermeldung, nach der ich Suchen konnte.
Meine Recherche ergab, dass die Fehlermeldung auftaucht, wenn die Extensions adodb und dbal installiert sind, aber nicht korrekt konfiguriert sind (Quelle jweiland.net). Da es aber eine ganz neue TYPO3 Installation ist, konnte ich noch keine Extensions manuell aktivieren, also ist das wohl die Standardkonfiguration. Um die Extensions zu deaktivieren, habe ich in der localconf.php in der Extension Liste (extList) den Eintrag dbal entfernt. Und siehe da, es funktioniert sofort und die Verbindung zur Datenbank steht.
Tags: typo3
Geschrieben in typo3 | 1 Kommentar »
(attach object errors to a specific field)
Es gibt die Möglichkeit in Extbase Validatoren für Objekte zu definieren. Wenn man also ein Model mit dem Namen “Domain_Model_ObjectModel” hat, wird falls vorhanden der Validator mit dem Namen “Domain_Validator_ObjectValidator”. Dabei wird nachdem die einzelnen Felder geprüft wurden mit dem angegebenen Validator das komplette Objekt überprüft. So kann man wie in meinem Beispiel feststellen, ob der Titel bereits vergeben worden ist (Unique). Normalweise wird die Fehlermeldung bei einer nicht erfolgreichen Validierung an das Objekt drangehängt. Da ich die Fehlermeldungen neben dem Feld ausgebe (siehe dazu Fehlermeldung mit Fluid direkt neben dem Feld ausgeben), wollte ich den Fehler an das Attribut title dranhängen.
class Tx_MyExtension_Domain_Validator_ObjectValidator
extends Tx_Extbase_Validation_Validator_AbstractValidator
{
/**
* Check if there is a object with the same name
* @param Tx_MyExtension_Domain_Model_Object $object
* @return bool
*/
public function isValid($object) {
$objectRepository = t3lib_div::makeInstance('Tx_MyExtension_Domain_Repository_ObjectRepository');
$sameNameCount = $objectRepository->countByTitleExcludeUid($object->getTitle(), $object->getUid());
if($sameNameCount > 0) {
if (!isset($this->errors['title'])) {
$this->errors['title'] = new Tx_Extbase_Validation_PropertyError('title');
}
$error = new Tx_Extbase_Validation_Error(Tx_Extbase_Utility_Localization::translate('error.object_title_exists', 'MyExtension'), '1312448731');
$this->errors['title']->addErrors(array($error));
return FALSE;
}
return TRUE;
}
}
Tags: extbase, fluid, typo3
Geschrieben in typo3 | Keine Kommentare »
Leider kann der Fluid-ViewHelper keine Strings vergleichen. Ich habe ein wenig recherchiert und Lösungen gefunden.
Die erste ist ein eigener View Helper, der in der Lage ist, zwei Objekte (Strings z.B.) zu vergleichen.
<?php
class Tx_MyExt_ViewHelpers_CompareViewHelper extends Tx_Fluid_Core_ViewHelper_AbstractViewHelper {
/**
* Returns true if $a and $b are type-equal, false otherwise.
*
* @param mixed $a
* @param mixed $b
* @return boolean
*/
public function render($a, $b) {
return $a === $b;
}
}
?>
Dann soll es laut dem Eintrag so funktionieren:
<f:if condition="{myext:compare(a: 'foo', b: 'bar')}">
<f:then>...</f:then>
<f:else>...</f:else>
</f:if>
Leider hat es bei mir nicht funktioniert.
Aber der Vorschlag zwei hat hingegen funktioniert. Es wird mit Fluid ein Alias für den zu vergleichenden String defininiert und dann verglichen:
<f:alias map="{foobar: 'myString'}">
<f:if condition="{object.property} == {foobar}"><!-- do something --></f:if>
</f:alias>
Tags: fluid
Geschrieben in typo3 | 3 Kommentare »
In verschachtelten Tabs, die mit jQuery erstellt wurden, sollte eine Navigation mittels Weiter-Button umgesetzt werden. Für einfache Tabs habe ich einige Beispiele gefunden:
jQuery UI Tabs with Next/Previous oder jQuery Tabs Next Button. Allerdings sind in diesem Fall die Tabs verschachtelt. d.h. innerhalb von Tabs befinden sich wiederum Tabs: Tab A enthält Tabs A1, A2 und A3, Tab B enthält B1, B2 und B3 und C hat keine Subtabs. Wenn man also in A3 angekommen ist, sollte der Weiter-Button zu B1 verweisen. Weiterhin sollte die normale Tab-Navigation (also das Anklicken der Tab-Titel) weiterhin funktionieren. Wenn man also den Tab A2 auswählt, sollte der Weiter-Button immer noch auf A3 springen lassen.
<div id="tab">
<ul>
<li><a href="#tab-a">A</a></li>
<li><a href="#tab-b">B</a></li>
<li><a href="#tab-c">C</a></li>
</ul>
<div id="tab-a">
<ul>
<li><a href="#tab-a1">A1</a></li>
<li><a href="#tab-a2">A2</a></li>
<li><a href="#tab-a3">A3</a></li>
</ul>
<div id="a1">
Inhalt A1
</div>
<div id="a2">
Inhalt A2
</div>
<div id="a3">
Inhalt A3
</div>
</div>
<div id="tab-b">
<ul>
<li><a href="#tab-b1">B1</a></li>
<li><a href="#tab-b2">B2</a></li>
<li><a href="#tab-b3">B3</a></li>
</ul>
</div>
[... usw]
</div>
Ich habe einen Button implementiert, der sich außerhalb der Tabs befindet. Damit eine Navigation möglich ist, müssen die Tab-Objekte gespeichert werden:
var $firstLevel = $('#tabs').tabs();
var counter = 0;
$('#tabs .tabbed').each( function(index, elem) {
var cid = $(elem).parent().attr('id');
tabObjects[counter] = $(elem).tabs();
counter++;
});
Wenn der Weiter-Button geklickt wird, wird ermittelt, welcher Tab der ersten Ebene gerade aktiv ist. Falls es Tabs der zweiten Ebene gibt, wird ermittelt, welcher von denen gerade aktiv ist. Dann wird geprüft, ob auf den Tab der zweiten Ebene Geschwister-Elemente folgen. Wenn ja, dann wird der nächste aktiviert. Wenn nicht, dann wird der nächste Tab der ersten Ebene aktiviert.
$('#next-button a').click( function() {
var selected = $firstLevel.tabs('option', 'selected');
var tabId = $('#tabs > div').eq(selected).attr('id');
$subTab = tabObjects[selected];
var length = $firstLevel.tabs('length');
if($subTab != undefined) {
var subSelected = $subTab.tabs('option', 'selected');
var subLength = $subTab.tabs('length');
if(subSelected + 1 < subLength) {
/*
* switch to next tab
*/
$subTab.tabs('select', subSelected + 1);
} else if(selected + 1 < length) {
/*
* switch no next parent tab
*/
$firstLevel.tabs('select', selected + 1);
if(length == selected + 2) {
$(this).hide();
}
$subTab = tabObjects[selected + 1];
if($subTab != undefined) {
$subTab.tabs('select', 0);
}
}
} else {
$firstLevel.tabs('select', selected + 1);
}
});
Tags: jquery, jqueryUI
Geschrieben in javascript | Keine Kommentare »
Aufbau nach Split
Block A (symmetrisch):
Repeater + 2 Basic =>
Double Stomp, Mambo Chacha auf dem Boden, Turn Reverse, Basic (wird zu Kick bevor Teil 2 drangehängt wird)
Block B (assymetrisch):
Repeater + 2 Basic =>
Squat hold, Squat hold andere Seite, Kneelift, Double Stomp Tango Drehen auf dem Boden, Single Stomp
Block C (asym):
Kneelift + 3 Basic =>
2 March rauf, auf 3 öffnen, R Fuß ab, L ab Straddle, Box zurück, Basic
Block D (asym):
Repeater + 2 Knee =>
Stomp, Side Leg Lift (auf die andere Seite drehen), Stomp auf dem Boden, Chacha over zurück, Knee
Block E (asym):
Repeater + 2 Basic =>
Double Knee, Sixpoint hinten kreuzen, Mambo
Block F (asym):
3 Basic + 1 Knee =>
2 V-Step, Fersen vor, Flieger
Geschrieben in choreos | Keine Kommentare »
Wenn man das jQuery Plugin Tiny Scrollbar für Inhalte eines Tabs verwendet, dann wird die Höhe des Elements nicht korrekt berechnet und die Funktionalität nicht gesetzt. Eine Erklärung dafür gibt es auf der jQuery Tabs-Seite: der Tab-Inhalt ist versteckt, daher können die Dimensionen nicht berechnet werden.
Man kann den Tiny Scrollbar aber aktivieren, wenn der Tab (vorausgesetzt es ist nicht der erste und sichtbare) sichtbar wird.
$('#tabs').bind('tabsshow', function(event, ui) {
if (ui.panel.id == "tab1") {
$('#content1').tinyscrollbar();
} else if(ui.panel.id == "tab2") {
$('#content2').tinyscrollbar();
}
});
Tags: jquery, jqueryUI
Geschrieben in javascript | Keine Kommentare »
TYPO3 nutzt im BackEnd in in der letzten Version Tabs. Ich wollte diese Tabs in einem mit Extbase geschriebenen Modul nutzen. Das ist eigentlich nicht so schwer und funktioniert wunderbar.
Zunächst braucht man das tabmenu-Script, man kann es mit einem Hook ins Template einfügen. Den Extensionnamen habe ich immer durch xxx ersetzt.
ext_localconf.php
/*
* Hook um eigenes JavaScript im BE hinzuzufügen
*/
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/template.php']['preHeaderRenderHook'][] =
t3lib_extMgm::extPath('xxx').'Resources/Private/Backend/Scripts/class.tx_xxx_templatehook.php:tx_xxx_templatehook->addBackendJavaScript';
Dann eine Klasse im Verzeichnis oben anlegen und Script mit einem Hook hinzufügen
class tx_xxx_templatehook {
public function addBackendJavaScript(&$aParams, $oTemplate) {
// ajax calls
$oTemplate->getPageRenderer()->addJsFile('js/tabmenu.js');
}
}
Im Template braucht man nur die entsprechenden Container anzulegen:
<div class="typo3-dyntabmenu-tabs">
<table class="typo3-dyntabmenu" cellspacing="0" cellpadding="0" border="0">
<tr>
<td class="tab" id="DTM-xxx-1-MENU" nowrap="nowrap" onmouseover="DTM_mouseOver(this);"
onmouseout="DTM_mouseOut(this);">
<a href="#" onclick="this.blur(); DTM_activate("DTM-xxx","1", 0); return false;">Tab Name</a>
</td>
<td class="tab" id="DTM-xxx-2-MENU" nowrap="nowrap" onmouseover="DTM_mouseOver(this);"
onmouseout="DTM_mouseOut(this);">
<a href="#" onclick="this.blur(); DTM_activate("DTM-xxx","2", 0); return false;">Tab Name</a>
</td>
</tr>
</table>
</div>
<div class="typo3-dyntabmenu-divs">
<div style="display: none; padding: 10px;" id="DTM-xxx-1-DIV" class="c-tablayer">
Tab Inhalt
</div>
<div style="display: none; padding: 10px;" id="DTM-xxx-2-DIV" class="c-tablayer">
Tab Inhalt
</div>
</div>
<!-- Initialization JavaScript for the menu -->
<script type="text/javascript">
DTM_array["DTM-xxx"] = new Array();
DTM_array["DTM-xxx"][0] = "DTM-xxx-1";
DTM_array["DTM-xxx"][1] = "DTM-xxx-2";
DTM_activate("DTM-xxx", top.DTM_currentTabs["DTM-xxx"]?top.DTM_currentTabs["DTM-xxx"]:1, 0);
</script>
Geschrieben in typo3 | Keine Kommentare »
Ich entwickele nun schon ein wenig länger Extbase und Fluid Extensions bzw. Module. Bei jedem Fehler, der einem unterwegs begeget, lernt man ein wenig dazu und daher wollte ich mal ein paar Tipps geben.
Die Grundlage einer Extension kann man wunderbar mit dem Extension Builder anlegen. Er erstellt alles, was man braucht – Controller, Repositories, Models. Ist zwar nicht immer so, wie ich es brauche, aber schon eine sehr gute Grundlage. Allerdings kann es sein, dass man nicht alle Felder von Anfang an anlegen kann, da man sie nicht alle kennt. Dann fügt man neue Felder hinzu, und plötzlich funktioniert es nicht mehr – Fehler in der Liste oder beim Bearbeiten und Speichern.
Als erstes sollte man prüfen, ob die TCA-Definition korrekt ist. Das geht am besten darüber, dass man über die gewöhnliche Listenansicht im TYPO3-BackEnd sich die Elemente anschaut. Wenn alle Felder angezeigt werden, evtl. Relationen dargestellt werden, dann ist das TCA wohl korrekt.
Ich hatte nach dem Hinzufügen von Feldern einen ziemlich miesen Fehler. Das Formular zum Bearbeiten wurde angezeigt, nach dem Klick auf den Speichern-Button kam allerdings eine Fehlermeldung, die mir nicht unbedingt weitergeholten hat: “The value must be of type “Tx_XXX_Domain_Model_XXX”, but was of type “NULL”. ” Der Exception-Stack ist auch keine große Hilfe. Die Ursache: Ich hatte das Feld bereits im Formular angelegt, hatte es aber noch nicht im Model. d.h. wenn mal so ein Fehler auftaucht, dann prüfen, ob die Felder 1) im TCA drin sind, 2) im Model mit Getter und Setter Methoden komplett definiert sind und 3) im Formular genauso heissen.
Geschrieben in typo3 | Keine Kommentare »
Es ist schon ca. einen Monat her, seit dem das Phantasialand mit einer neuen wunderschönen Seite online gegangen ist. Ich bin schon ein wenig stolz daran mitgearbeitet zu haben. Aus der Marketingsicht wurde der Relaunch und die neue Webseite auf kernpunkt.de ausführlich betrachtet. Aus Entwicklersicht hat die Seite auch einiges zu bieten gehabt, hier einige Highlights:
Die Navigation wurde mit HTML und CSS und ein wenig Hilfe von jQuery umgesetzt. Ist es nicht schön, wie der blaue Schein dazukommt, wenn sie aufgeklappt ist und wie z.B. die Park-Themenwelten beim RollOver in den Bildern hervorgehoben werden – pure CSS Magic.
Für die Sushibar (ich wusste auch nicht, dass man es so nennen kann, für mich ist es ein Carousel), die man z.B. auf der Seite Fantasy bestaunen kann, musste ein jQuery-Plugin entwickelt werden. Vom CSS her war es in der Sushibar eine Herausforderung, dass die Elemente teilweise nach oben rausragen.
Auch sehr schön geworden ist der Parkplan – zu finden auf den Themenwelt-Seiten als Link in der rechten Spalte. Attraktionen der ausgewählten Themenwelt werden im Parkplan hervorgehoben.
Und auch der Erlebnisplaner hat ein paar nette Features: Attraktionen können am Anfang über einen Hinzufügen-Button in der Attraktion in den Erlebnisplaner gelegt werden. Sobald eine Attraktion im Erlebnisplaner ist, macht er auch schon Vorschläge. Diese Vorschläge kann man per Drag & Drop ebenfalls in die Liste der geplanten Attraktionen ziehen. Wenn man fertig ist, wird auf Wunsch eine Anfahrtbeschreibung generiert und ein personalisierter Parkplan, auf dem die gewählten Attraktionen zu sehen sind.
Geschrieben in default | Keine Kommentare »
Ich habs geahnt – wenn man per CSS mehrere Hintergrundbilder des Body zentriert und vielleicht noch einen Seiteninhalt hat, der mittig zentriert ist, dann sind der Hintergrund und der Inhalt nicht immer direkt übereinander: CSS Sub-pixel Background Misalignment
Geschrieben in css | Keine Kommentare »