typo3typoscripttt-news

tt_news: Modify image src


In order to be able to use lazy loading, I need to modify the src attribute of tt_news' image output like so:

<img src="/foo/bar/baz.png" … /> // <-- before
<img data-original="/foo/bar/baz.png" … /> // <-- after, no src!

I have tried:

plugin.tt_news.displayList.content_stdWrap {
    parseFunc < lib.parseFunc_RTE
    HTMLparser = 1
    HTMLparser.keepNonMatchedTags = 1
    HTMLparser.tags.img.fixAttrib.src.unset = 1
}

but to no avail, since

So, what should I do aside from pulling my hair out?


Solution

  • This cannot be solved via typoscript, because the src attribute is hard coded in the cImage function:

    $theValue = '<img src="' . htmlspecialchars($GLOBALS['TSFE']->absRefPrefix .
    t3lib_div::rawUrlEncodeFP($info[3])) . '" width="' . $info[0] . '" height="' . $info[1] . '"' .
    $this->getBorderAttr(' border="' . intval($conf['border']) . '"') .
    $params .
    ($altParam) . ' />';
    

    The only way I see to modify the src attribute is through a user function. tt_news provides a hook for a user function that allows the custom processing of images (see line 2150 of class.tx_ttnews.php).

    Example:

    Insert the following typoscript:

    includeLibs.user_ttnewsImageMarkerFunc = fileadmin/templates/php/user_ttnewsImageMarkerFunc.php
    plugin.tt_news.imageMarkerFunc = user_ttnewsImageMarkerFunc->ttnewsImageMarkerFunc
    

    Whereas the file user_ttnewsImageMarkerFunc.php contains:

    <?php
    
        class user_ttnewsImageMarkerFunc {
    
            /**
            * Fills the image markers with data.
            *
            * @param    array        $paramArray: $markerArray and $config of the current news item in an array
            * @param    [type]        $conf: ...
            * @return    array        the processed markerArray
            */
            function ttnewsImageMarkerFunc($paramArray, $conf) {
                $markerArray = $paramArray[0];
                $lConf = $paramArray[1];
                $pObj = &$conf['parentObj'];
                $row = $pObj->local_cObj->data;
    
                $imageNum = isset($lConf['imageCount']) ? $lConf['imageCount'] : 1;
                $imageNum = t3lib_div::intInRange($imageNum, 0, 100);
                $theImgCode = '';
                $imgs = t3lib_div::trimExplode(',', $row['image'], 1);
                $imgsCaptions = explode(chr(10), $row['imagecaption']);
                $imgsAltTexts = explode(chr(10), $row['imagealttext']);
                $imgsTitleTexts = explode(chr(10), $row['imagetitletext']);
    
                reset($imgs);
    
                if ($pObj->config['code'] == 'SINGLE') {
                    $markerArray = $this->getSingleViewImages($lConf, $imgs, $imgsCaptions, $imgsAltTexts, $imgsTitleTexts, $imageNum, $markerArray, $pObj);
                } else {
    
                    $imageMode = (strpos($textRenderObj, 'LATEST') ? $lConf['latestImageMode'] : $lConf['listImageMode']);
    
                    $suf = '';
                    if (is_numeric(substr($lConf['image.']['file.']['maxW'], - 1))) { // 'm' or 'c' not set by TS
                        if ($imageMode) {
                            switch ($imageMode) {
                                case 'resize2max' :
                                    $suf = 'm';
                                    break;
                                case 'crop' :
                                    $suf = 'c';
                                    break;
                                case 'resize' :
                                    $suf = '';
                                    break;
                            }
                        }
                    }
    
                    // only insert width/height if it is not given by TS and width/height is empty
                    if ($lConf['image.']['file.']['maxW'] && ! $lConf['image.']['file.']['width']) {
                        $lConf['image.']['file.']['width'] = $lConf['image.']['file.']['maxW'] . $suf;
                        unset($lConf['image.']['file.']['maxW']);
                    }
                    if ($lConf['image.']['file.']['maxH'] && ! $lConf['image.']['file.']['height']) {
                        $lConf['image.']['file.']['height'] = $lConf['image.']['file.']['maxH'] . $suf;
                        unset($lConf['image.']['file.']['maxH']);
                    }
    
                    $cc = 0;
                    foreach ($imgs as $val) {
                        if ($cc == $imageNum)
                            break;
                        if ($val) {
                            $lConf['image.']['altText'] = $imgsAltTexts[$cc];
                            $lConf['image.']['titleText'] = $imgsTitleTexts[$cc];
                            $lConf['image.']['file'] = 'uploads/pics/' . $val;
    
                            $theImgCode .= str_replace('src="', 'class="lazy" data-original="', $pObj->local_cObj->IMAGE($lConf['image.'])) . $pObj->local_cObj->stdWrap($imgsCaptions[$cc], $lConf['caption_stdWrap.']);
                        }
                        $cc++;
                    }
    
                    if ($cc) {
                        $markerArray['###NEWS_IMAGE###'] = $pObj->local_cObj->wrap($theImgCode, $lConf['imageWrapIfAny']);
                    } else {
                        $markerArray['###NEWS_IMAGE###'] = $pObj->local_cObj->stdWrap($markerArray['###NEWS_IMAGE###'], $lConf['image.']['noImage_stdWrap.']);
                    }
                }
                if ($pObj->debugTimes) {
                    $pObj->hObj->getParsetime(__METHOD__);
                }
                //        debug($markerArray, '$$markerArray ('.__CLASS__.'::'.__FUNCTION__.')', __LINE__, __FILE__, 2);
    
    
                return $markerArray;
            }
    
    
    
            /**
            * Fills the image markers for the SINGLE view with data. Supports Optionssplit for some parameters
            *
            * @param    [type]        $lConf: ...
            * @param    [type]        $imgs: ...
            * @param    [type]        $imgsCaptions: ...
            * @param    [type]        $imgsAltTexts: ...
            * @param    [type]        $imgsTitleTexts: ...
            * @param    [type]        $imageNum: ...
            * @return    array        $markerArray: filled markerarray
            */
            function getSingleViewImages($lConf, $imgs, $imgsCaptions, $imgsAltTexts, $imgsTitleTexts, $imageNum, $markerArray, $pObj) {
                $marker = 'NEWS_IMAGE';
                $sViewSplitLConf = array();
                $tmpMarkers = array();
                $iC = count($imgs);
    
                // remove first img from image array in single view if the TSvar firstImageIsPreview is set
                if (($iC > 1 && $pObj->config['firstImageIsPreview']) || ($iC >= 1 && $pObj->config['forceFirstImageIsPreview'])) {
                    array_shift($imgs);
                    array_shift($imgsCaptions);
                    array_shift($imgsAltTexts);
                    array_shift($imgsTitleTexts);
                    $iC--;
                }
    
                if ($iC > $imageNum) {
                    $iC = $imageNum;
                }
    
                // get img array parts for single view pages
                if ($pObj->piVars[$pObj->config['singleViewPointerName']]) {
    
                    /**
                    * TODO
                    * does this work with optionsplit ?
                    */
                    $spage = $pObj->piVars[$pObj->config['singleViewPointerName']];
                    $astart = $imageNum * $spage;
                    $imgs = array_slice($imgs, $astart, $imageNum);
                    $imgsCaptions = array_slice($imgsCaptions, $astart, $imageNum);
                    $imgsAltTexts = array_slice($imgsAltTexts, $astart, $imageNum);
                    $imgsTitleTexts = array_slice($imgsTitleTexts, $astart, $imageNum);
                }
    
                if ($pObj->conf['enableOptionSplit']) {
                    if ($lConf['imageMarkerOptionSplit']) {
                        $ostmp = explode('|*|', $lConf['imageMarkerOptionSplit']);
                        $osCount = count($ostmp);
                    }
                    $sViewSplitLConf = $pObj->processOptionSplit($lConf, $iC);
                }
                // reset markers for optionSplitted images
                for ($m = 1; $m <= $imageNum; $m++) {
                    $markerArray['###' . $marker . '_' . $m . '###'] = '';
                }
    
                $cc = 0;
                foreach ($imgs as $val) {
                    if ($cc == $imageNum)
                        break;
                    if ($val) {
                        if (! empty($sViewSplitLConf[$cc])) {
                            $lConf = $sViewSplitLConf[$cc];
                        }
    
                        //                if (1) {
                        //                    $lConf['image.']['imgList.'] = '';
                        //                    $lConf['image.']['imgList'] = $val;
                        //                    $lConf['image.']['imgPath'] = 'uploads/pics/';
                        //    debug($lConf['image.'], ' ('.__CLASS__.'::'.__FUNCTION__.')', __LINE__, __FILE__, 3);
                        //
                        //                    $imgHtml = $pObj->local_cObj->IMGTEXT($lConf['image.']);
                        //
                        //                } else {
                        $lConf['image.']['altText'] = $imgsAltTexts[$cc];
                        $lConf['image.']['titleText'] = $imgsTitleTexts[$cc];
                        $lConf['image.']['file'] = 'uploads/pics/' . $val;
    
    
                        $imgHtml = str_replace('src="', 'class="lazy" data-original="', $pObj->local_cObj->IMAGE($lConf['image.'])) . $pObj->local_cObj->stdWrap($imgsCaptions[$cc], $lConf['caption_stdWrap.']);
    
                        //                }
    
    
                        //debug($imgHtml, '$imgHtml ('.__CLASS__.'::'.__FUNCTION__.')', __LINE__, __FILE__, 3);
    
    
                        if ($osCount) {
                            if ($iC > 1) {
                                $mName = '###' . $marker . '_' . $lConf['imageMarkerOptionSplit'] . '###';
                            } else { // fall back to the first image marker if only one image has been found
                                $mName = '###' . $marker . '_1###';
                            }
                            $tmpMarkers[$mName]['html'] .= $imgHtml;
                            $tmpMarkers[$mName]['wrap'] = $lConf['imageWrapIfAny'];
                        } else {
                            $theImgCode .= $imgHtml;
                        }
                    }
                    $cc++;
                }
    
                if ($cc) {
                    if ($osCount) {
                        foreach ($tmpMarkers as $mName => $res) {
                            $markerArray[$mName] = $pObj->local_cObj->wrap($res['html'], $res['wrap']);
                        }
                    } else {
                        $markerArray['###' . $marker . '###'] = $pObj->local_cObj->wrap($theImgCode, $lConf['imageWrapIfAny']);
                    }
                } else {
                    if ($lConf['imageMarkerOptionSplit']) {
                        $m = '_1';
                    }
                    $markerArray['###' . $marker . $m . '###'] = $pObj->local_cObj->stdWrap($markerArray['###' . $marker . $m . '###'], $lConf['image.']['noImage_stdWrap.']);
                }
                //        debug($sViewSplitLConf, '$sViewSplitLConf ('.__CLASS__.'::'.__FUNCTION__.')', __LINE__, __FILE__, 2);
    
    
                return $markerArray;
            }
    
    
    
        }
    
    ?>
    

    Most of this code is copied from class.tx_ttnews.php. The important line is the following (in each of the two functions):

    str_replace('src="', 'class="lazy" data-original="', $pObj->local_cObj->IMAGE($lConf['image.']))
    

    Then you'll get the following image tags:

    <img class="lazy" data-original="uploads/pics/myimage.jpg" width="110" height="70" border="0" alt="" />