Another Blog about the Wide Web World
Header image

Ihr habt bereits Fancybox 3 (komplett responsive und touchfähig) im Einsatz und möchtet den Pin It Button einfügen? Solange ihr auf eurer Seite nur Thumbnails einbindet und die großen Bilder erst in der Lightbox geladen werden, sollten eure Nutzer die Möglichkeit in der Fancybox erhalten eure Bilder zu pinnen.

Und so geht’s:

Schritt 1:

Füge das JavaScript vor dem schließenden body Tag ein.

<script async defer src="//assets.pinterest.com/js/pinit.js"></script>

Schritt 2:

Danach fügt ihr Fancybox laut dieser Anleitung ein. 

Schritt 3:

Ich füge den Pin It Button in die Beschreibung des Bildes ein. Ist eine Beschreibung vorhanden, wird diese erweitert.

Dazu habe ich folgenden Code geschrieben:



$(".fancybox").fancybox({
		caption : function( instance, item ) {
			var caption, link;

			if ( item.type === 'image' ) {
				var caption = $(this).data('caption');
				
				if (caption) {
					//set description to current title
					//this will set what posts
					var description = $(this).data('caption');
					//add pinterest button for title
					pin = '<a data-pin-do="buttonPin" data-pin-tall="true" data-pin-save="false" href="https://pinterest.com/pin/create/button/?url=' +
					encodeURIComponent(document.location.href) +
					'&amp;amp;amp;media=' +
					//put the path to the image you want to share here
					encodeURIComponent(this.href) +
					'&amp;amp;amp;description=' + description + '"><img src="/fileadmin/templates/img/pinterest.png" /></a>'
					//add title information
					+ '&amp;amp;amp;nbsp;<span>' + $(this).data('caption') + '</span>';
					return pin;
				} else {
					//add pinterest button for title
					caption = '<a data-pin-do="buttonPin" data-pin-tall="true" data-pin-save="false" href="https://pinterest.com/pin/create/button/?url=' + 
					encodeURIComponent(document.location.href) +
					'&amp;amp;amp;media=' +
					encodeURIComponent(this.href) +
					'&amp;amp;amp;description=Pin%20von%20finca-ferienhaus.de%20Ferienh%C3%A4user%20und%20Fincas%20auf%20Mallorca"><img src="/fileadmin/templates/img/pinterest.png" /></a>';
					return caption;
				}

				
			}
		}
		
	});


Dieser muss natürlich in euren document ready Aufruf.

$(document).ready(function () { hier den oben gennanten Code einfügen });

Die Standard Beschreibung des Pins müsst ihr natürlich gegen die Beschreibung eurer Website austauschen. Außerdem habe ich mir einen eigenen Button erstellt.

Und so sieht es dann aus:

Fancybox 3 mit einem Pinterest Button

Mein Ziel war es von Fluid heraus die uid einer Seite an TypoScript zu übergeben



<f:cObject typoscriptObjectPath="lib.caseStudyImage" data="{casestudy}" />


Jedes Object casestudy hatte eine UID, die die uid einer Seite war. Es wurden über eine foreach Schleife mehrere Case Studys ausgegeben. Bei der Ausgabe dieser Case Studys sollte dann aus dem Inhalt der jeweiligen Seite das erste Bild ausgegeben werden.

Leider hat kein einziger Code, den ich im Netz gefunden habe korrekt mit FAL funktioniert. Daher hier meine Lösung


lib.caseStudyImage = CONTENT
lib.caseStudyImage {
	table = tt_content
	select {
		languageField = sys_language_uid
		orderBy = sorting
		max = 1
		where = (CType = "image" OR CType = "textpic") AND colPos = 0 
		pidInList.field = uid
	}
	renderObj = FILES
	renderObj {
		begin = 0
		maxItems = 1
		references {
			table = tt_content
			uid.data = uid
			fieldName = image
		}
		renderObj = IMAGE
		renderObj {
			file.import.data = file:current:uid
			file.treatIdAsReference = 1
			file.width = 335c
			file.height = 220c
			altText.data = file:current:title
		}
	}
}

et voila


temp.categorymenu = COA
temp.categorymenu.20 = CONTENT	
temp.categorymenu.20 {
	table = tx_news_domain_model_category
	select {
		selectFields = tx_news_domain_model_category.title, tx_news_domain_model_category.description
		pidInList = {$storage}
		join = tx_news_domain_model_news_category_mm ON (tx_news_domain_model_category.uid = tx_news_domain_model_news_category_mm.uid_foreign) INNER JOIN tx_news_domain_model_news ON (tx_news_domain_model_news.uid = tx_news_domain_model_news_category_mm.uid_local)
		andWhere = tx_news_domain_model_news.uid = {GP:tx_news_pi1|news}
		andWhere.insertData = 1
		max = 1
	}
	renderObj = COA
	renderObj {
		10 = TEXT
		10 {
			field= title
			wrap = <h2>|</h2>
			htmlSpecialChars = 1
		}
		20 = TEXT
		20 {
			field= description
			wrap = <p>|</p>
			htmlSpecialChars = 1
		}
	}
}

Tatsächlich ist bisher der Fehler nie aufgefallen. Erst jetzt! Da ich recht lange recherchieren musste, um eine Lösung zu finden, nehme ich das mal als Grund über das Problem in meinem Blog zu schreiben.

Ich hatte folgende Konstellation: Eine WordPress Instanz sollte über mehrere Domains erreichbar sein. In diesem Fall war es einmal die Hauptdomain www.xyz.de und die Subdomains namens stadt1.xyz.de + stadt2.xyz.de + stadt3.xyz.de + stadt4.xyz.de

Je nach Domain wurde ein anderer Inhalt ausgegeben. Dies habe ich mit einer kleinen HTTP Host Abfrage in WordPress gelöst.

Nun sollten auch Webfonts über font-face und auch die komplette Website über https laufen. Ich habe hier ein nettes, schlankes Plugin gefunden, welche alle Links (auch in der CSS Datei) zum Protokoll https zwingt (WordPress HTTPS war mir zu viel des Guten). So wird schonmal keine Info über unsichere Inhalte ausgegeben. Das Plugin nimmt einem die Arbeit ab, alle Inhalte und Plugins nach http Verbindungen abzusuchen.

Folgender Fehler trat nun auf: Besuchte man eine der Subdomains über den Firefox (bei mir war’s noch die Version 15) und dem IE9, so wurden die Webfonts nicht geladen. Ich probierte absolute Pfad, z.B. https://www.xyz.de/font.eot oder //font.eot oder /font.eot aus. Relative Pfade brachten leider auch nicht das gewünschte Ergebnis. Lustigerweise sah im Chrome auf den Subdomains alles super aus. Die Hauptdomain war auch in allen Browsern ok.

Nach einiger Zeit Recherche und nachdem ich die Web-Konsole über den Firefox öffnete, sah ich den Fehler:

Firefox meckerte aufgrund eines Cross-Domain Problems. Er versuchte nämlich weiterhin über die Hauptdomain die Fonts aufzurufen. Da man sich jedoch auf der Subdomain befand, wurden diese nicht aufgerufen.

Ich habe nun folgende Einstellungen in die .htaccess eingefügt:


AddType application/vnd.ms-fontobject .eot
AddType font/ttf .ttf
AddType font/otf .otf
AddType font/woff .woff

<FilesMatch "\.(ttf|otf|eot|woff)$">
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "*"
</IfModule>
</FilesMatch>

Die AddType Zeilen fügen die MIME types zur HTTP response hinzu. Danach prüfen wir, ob eine der Dateiendungen abgerufen wird und ob mod_headers vorhanden ist und erlauben den Zugriff über andere Domains.

Das Ganze kann man auch die Apache Config (z.B. hier zu finden /etc/apache2/apache2.conf ) schreiben.

Folgendermaßen sieht nun meine font-face CSS Bereich aus:


@font-face {
    font-family: "Font XY";
	src: url('https://www.xyz.de/wp-content/themes/xyz/fonts/Font-XY.eot'); 
	src: url('/wp-content/themes/xyz/fonts/Font-XY.woff') format('woff');
	font-weight: normal;
	font-style:normal;
}

Tjaa… Da habe ich mal wieder etwas umgestellt, hab es dann vergessen und irgendwann während ich wieder mit TextMate gearbeitet habe, fiel die Änderung auf. Egal wo man in der Datei hingeklickt hat, der Cursor blieb dort stehen, auch wenn es mitten in einer leeren Zeile war.
Ich hätte gerne gewollt, dass er an das Ende der jeweiligen Zeile geht. Die Tab-Abstände (Tabs) haben auch nicht mehr so richtig das gemacht, was ich wollte.
Um einigen vielleicht etwas Arbeit zu ersparen, hier nun die Lösung des Problems. Geht man auf Mode > Freehanded Editing und deaktiviert den zuvor eingestellte Modus, dann landet man bei Klick auf eine Zeile auch wieder am Ende einer Zeile. Wie zuvor von mir vermutet, hat das alles leider nichts mit den “Line Endings” unter Preferences zu tun.

mm_forum ist sehr mächtig und somit kann eine kleine Änderung schonmal ganz anstrengend werden.. Leider habe ich bisher keine bessere Methode gefunden,  um den Antworten Button von unter den Posts nach oben zu verschieben. Im Template “list_post.html” ist der Reply Button im Marker ###POSTBOTTOM### versteckt. Der Marker wird aber nur befüllt, wenn er sich auch zwischen dem subpart <!-- ###LIST_POSTS_END### begin --> und <!-- ###LIST_POSTS_END### end --> befindet. Würde man ###POSTBOTTOM###  nun zwischen <!-- ###LIST_POSTS_BEGIN### begin --> und <!-- ###LIST_POSTS_BEGIN### end --> einfügen, würde der Marker nicht ersetzt werden. Lösung hierfür:

In der Datei class.tx_mmforum_postfunctions.php unter ext/mm_forum/pi1 sollte man (je nach Version) ab ca. Zeile 222, also nach // Output topic name den Code für die $this->createButton('reply', $linkParams) Funktion einfügen. Der sieht folgendermaßen aus:


if ((!$topicData['read_flag'] && !$topicData['closed_flag']) || $this->getIsMod($topicData['forum_id']) || $this->getIsAdmin()) {
			if ($this->getMayWrite_topic($topicId)) {
				$linkParams[$this->prefixId] = array(
					'action' => 'new_post',
					'tid'    => $topicId
				);
				if ($this->useRealUrl()) {
					$linkParams[$this->prefixId]['fid'] = $topicData['forum_id'];
				}
				$marker['###POSTBOTTOM###'] = $this->createButton('reply', $linkParams);
			} else {
				$marker['###POSTBOTTOM###'] = '';
			}
		} else {
			$marker['###POSTBOTTOM###'] = $this->pi_getLL('topic.adminsOnly');
		}

Ich musste viel probieren, bis ich zu einer geeigneten Lösung kam. Mein IST Zustand: Ich habe über einen Link eine Slideshow mit der Fancybox geöffnet. In dem iframe befand sich eine “ganz normale” Seite (eigenes Template in TYPO3). Nun wollte, dass sich die Fancybox auch schließt, wenn ich auf einen bestimmten Link klicke.

Etliche Aufrufe über eine Funktion haben nicht geklappt. Erfolg brachte onclick:

onclick="window.top.$.fancybox.close();"

Danke an Bastian Bringenberg.

Ich konnte es kaum glauben, dass ich so lange an der Lösung eines manuellen (ohne Extension, sondern nur mit TypoScript) printlinks saß. Teilweise waren die Lösungen veraltet (z.B. GPvar anstatt GP) oder nahmen keine Rücksicht auf die Get Variablen von tt_news. Außerdem war es mir wichtig, dass ich nicht direkt über JavaScript ein window.print aufrufe und dann “nur” noch die print.css genommen wird. Ich wollte ein komplett neues Template, somit eine Druck-Vorschaufunktion für den User und erst dann das automatische OS Druck-Fenster. Das TypoScript kann natürlich nach belieben angepasst werden.

Hiermit erstelle ich den Printlink und später kopiere ich ihn einen Marker.


temp.print-link = COA
temp.print-link {
	10 = TEXT
	10.value = Seite drucken
	stdWrap.wrap = |
	stdWrap.typolinkno_cache = 1
	stdWrap.typolink.target = print
	stdWrap.typolink.ATagParams = target = _top
	stdWrap.typolink.parameter.cObject = COA
	stdWrap.typolink.parameter.cObject {
 
        5 = TEXT
        5.data = page:uid
        5.wrap = index.php?id=|
        5.required = 1
 
        10 = TEXT
        10.value = &amp;amp;amp;no_cache=1
 
        20 = TEXT
        20.data = GP:L
        20.wrap = &amp;amp;amp;L=|
        20.required = 1
 
        30 = TEXT
        30.data = GP:tx_ttnews | backPid
        30.wrap = &amp;amp;amp;tx_ttnews[backPid]=|
        30.required = 1
 
        40 = TEXT
        40.data = GP:tx_ttnews | tt_news
        40.wrap = &amp;amp;amp;tx_ttnews[tt_news]=|
        40.required = 1
 
        50 = TEXT
        50.data = GP:cHash
        50.wrap = &amp;amp;amp;cHash=|
        50.required = 1
 
        60 = TEXT
        60.value = &amp;amp;amp;type=98
    }
}

Und hiermit definiere ich das Drucktemplate


print = PAGE
print {
  typeNum = 98
  bodyTag = <body onload="javascript:window.print()">   
  ##disable typo3 index
  config.index_enable = 0
 
  ##disable google index
  headerData.123 = TEXT
  headerData.123.value = <meta name="robots" content="noindex, nofollow" />
 
  includeCSS.fileDefault = fileadmin/templates/css/print.css
  10 = TEMPLATE
  10 {
      template = FILE
      template.file = fileadmin/templates/print.tmpl
      workOnSubpart = DOCUMENT_BODY
 
      marks { 
        CONTENT < styles.content.get
      }      
   }
}

Stellt man nachträglich die TYPO3 RealURL Konfiguration mit folgendem Befehl 'defaultToHTMLsuffixOnPrev' => false um und erhält dadurch Seiten ohne eine *.html Endung, erscheint für bestehende Links mit der Endung ein Server Error. Das Entfernen der *.html Endung soll aus SEO Sicht vorteilhaft sein. Daher sollte man auf jeden Fall auch eine Weiterleitung einrichten. Diese Weiterleitung leitet dann allgemeingültig alle *.html Dateien zu dem Verzeichnis um. Dies tut man am besten über die htaccess Datei mit folgendem Befehl:


RedirectMatch (.*)\.html$ $1/

Aus http://domain.de/datei.html wird http://domain.de/datei/

Am besten wäre es noch, wenn man alle URLs von http://domain.de/datei auf http://domain.de/datei/ leiten würde, somit jedesmal den endenen Slash (trailing slash) hinzufügen würde. Somit vermeidet man Duplicate Content. Leider hat bei mir u.g. Code nicht funktioniert. Vielleicht weiß jemand Rat?


RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)([^/])$ http://domain.de/$1$2/ [R=301,L]

Vielleicht haben es einige von euch bemerkt: Hat man einen geschützten Bereich in TYPO3 (4.5.5) mit feuser und srfeuserregister laufen, außerdem eine Mehrsprachigkeit (in meinem Fall deutsch als default und englisch als id=1) und das 404 Handling an, dann kommt es zu Problemen. Anstatt die Login Maske von feuser aufzurufen, nachdem ein Link zum geschützen Bereich aufgerufen wurde, erscheint eine 404 Seite. Dieses Problem habe ich folgendermaßen mit einer kleinen Funktion behoben:


<?php
define(LOGIN_URL, "http://www.domain.de/login.html");
define(LOGIN_URL_EN, "http://www.domain.de/en/login.html");
define(NOTFOUND_URL, "http://www.domain.de/404.html");
define(NOTFOUND_URL_EN, "http://www.domain.de/en/404.html");
  
class user_pageNotFound {
  function pageNotFound($param, $ref) {
    if ($param["pageAccessFailureReasons"]["fe_group"] != array(""=>0)) {
      header("HTTP/1.0 403 Forbidden");
	  if ($_GET['L'] == 1){
      	$url = LOGIN_URL_EN."?redirect_url=" . $param["currentUrl"]; 
       } else {
			$url = LOGIN_URL."?redirect_url=" . $param["currentUrl"];
	  }
    } elseif ((substr($param['currentUrl'], 1, 2)) == "en") {
      	$url = NOTFOUND_URL_EN;   
    } else {
		$url = NOTFOUND_URL;  
	}
     
    session_start();
    $strCookie = 'PHPSESSID=' . $_COOKIE['PHPSESSID'] . '; path=/';
    session_write_close();
   
    $c = curl_init();
    curl_setopt($c, CURLOPT_URL, $url);
    curl_setopt($c, CURLOPT_COOKIE, $strCookie);
    $contents = curl_exec($c);
    curl_close($c);
 
    if ($contents) return $contents;
        else return FALSE;
  }
}
?>

Hierbei wird vor dem 404 Handling auch noch die RealURL abgefragt und je nach Sprache (in meinem Fall “en”) eine andere 404 Seite ausgegeben. Bitte ersetzt oder erweitert diesen Bereich nach euren Anforderungen. Außerdem müssen von euch natürlich auch die vier Konstanten (LOGIN_URL, NOTFOUND_URL..) geändert werden.

Zuvor muss in dem Install Tool oder in der localconf.php folgender Eintrag geändert werden: [FE][pageNotFound_handling] = USER_FUNCTION:fileadmin/scripts/pageNotFoundHandling.php:user_pageNotFound->pageNotFound und natürlich der oben genannte Code in das jeweilige Verzeichnis unter fileadmin in die Datei pageNotFoundHandling.php eingefügt werden.