• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

Defer spoiler html parsing until toggled

Luke F

Well-known member
#1
A reasonably common usage of spoiler tags is to make image-heavy posts/threads more accessible. However in the current XF implementation, images within spoiler tags are still loaded in the background.

It would be nice if spoiler html could be moved to a data attribute or similar and inserted into the dom on first toggle

I've implemented spoilers in this way on my forum without much bother, though it does make the issues mentioned here trickier to fix
 

cclaerhout

Well-known member
#2
May be its the img tag which should be modified. If the img tag has a spoiler parent, then the src can target to a blank img and put the real src of the img as a data-src. Once the spoiler is toggled the first time it should be possible to play with the dom and load the images.
 

cclaerhout

Well-known member
#3
Even simpler:

In the container function:
Code:
  $(function() {
     $('.AdvSpoilerbbCommand').find('img').each(function(){
       var $this = $(this);
       $this.data('src', $this.attr('src')).attr('src', XenForo._baseUrl+'styles/default/xenforo/clear.png');
     });
   });
Then in the spoiler click event :
Code:
          $e.find('img').each(function(){
             var $img = $(this);
             if($img.data('src')){
               $img.attr('src', $img.data('src'))
               $img.data('src', '')
             }
           });
 

cclaerhout

Well-known member
#6
Tested on a live board: the above code (first function) doesn't work, which means the modification mustbe done directly from php.
 

cclaerhout

Well-known member
#7
PHP:
  public static function parseTagSpoilerbb(&$content, array &$options, &$templateName, &$fallBack, array $rendererStates, $parentClass)
   {
     $xenOptions = XenForo_Application::get('options');
     $visitor = XenForo_Visitor::getInstance();

     $content = preg_replace_callback(
       '#<(img|iframe)[^>]+?>#ui',
       array('Sedo_AdvBBcodeBar_BbCode_Formatter_AdvBbCodes', '_filterSpoilerBb'),
       $content
     );
   }
   
   protected static function _filterSpoilerBb($match)
   {
     $tag = $match[1];
     $line = $match[0];
     $noscript = "<noscript>{$line}</noscript>";
     
     if(preg_match('#class="(.*?)"#', $line, $getClass))
     {
       $classes = explode(' ', $getClass[1]);
       if(!in_array('JsOnly', $classes))
       {
         $line = str_replace('class="', 'class="JsOnly ', $line);
       }
     }
     else
     {
       $line = str_replace('<'.$tag, '<'.$tag.' class="JsOnly"', $line);
     }
     
     $search = '#src="(.*?)"#ui';
     $replace = 'src="styles/default/xenforo/clear.png" data-spoiler-src="$1"';

     $line = preg_replace($search, $replace, $line);
     $line .= $noscript;

     return $line;
   }
That's better.