Defer spoiler html parsing until toggled

Luke F

Well-known member
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
 
Upvote 11
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.
 
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', '')
             }
           });
 
Tested on a live board: the above code (first function) doesn't work, which means the modification mustbe done directly from php.
 
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.
 
Top Bottom