• This forum has been archived. New threads and replies may not be made. All add-ons/resources that are active should be migrated to the Resource Manager. See this thread for more information.

Creating a beautiful looking SPOILER tag...

Jaxel

Well-known member
I've never liked how most spoiler tags look on forums. Now with XenForo, we finally have something to work with that is truly beautiful.

I do all customization on my forum to a product called "EWRcustom", its basically an Add-On that I don't release to the public, which contains all my custom settings and changes. This add-on has things like my sub forum grid listing, advert placements, thread sticky separations, user ribbons, etc. There are many hooks, custom models, listeners etc in this custom add-on of mine, but I will not be releasing the most of them to the public.

Today I will show you how to do the spoiler tags I have on 8WAYRUN...
http://www.8wayrun.com/threads/8wayrun-com-now-running-the-xenforo-beta.6406/page-10#post-237171

First you have your listener class:
Code:
<?php
 
class EWRcustom_Listener_BbCode
{
    public static function listen($class, array &$extend)
    {
        if ($class == 'XenForo_BbCode_Formatter_Base')
        {
            $extend[] = 'EWRcustom_BbCode_Formatter';
        }
    }
}
This listener extends the EWRcustom BbCode Formatter into the existing BbCode Formatter Base.

Then you have your EWRcustom BbCode Formatter:
Code:
<?php
 
class EWRcustom_BbCode_Formatter extends XFCP_EWRcustom_BbCode_Formatter
{
    protected $_tags;
 
    public function getTags()
    {
        $this->_tags = parent::getTags();
 
        $this->_tags['spoiler'] = array(
            'trimLeadingLinesAfter' => 1,
            'callback' => array($this, 'renderTagSpoiler')
        );
 
        return $this->_tags;
    }
 
    public function renderTagSpoiler(array $tag, array $rendererStates)
    {
        $content = $this->renderSubTree($tag['children'], $rendererStates);
        $spoiler = $tag['option'];
 
        if ($this->_view)
        {
            $template = $this->_view->createTemplateObject('EWRcustom_spoiler', array(
                'content' => $content,
                'spoiler' => $spoiler
            ));
            return $template->render();
        }
        else
        {
            $name = '<div>' . new XenForo_Phrase('spoiler_warning') . ($spoiler ? ': '.$spoiler : '') . '</div>';
            return '<blockquote>' . $name . $content . '</blockquote>';
        }
    }
}
Its pretty simple, it looks for the
tag, then determines view information, as well if the post is using
or
. It then references a custom template called EWRcustom_spoiler.

Next we create that custom template "EWRcustom_spoiler".
Code:
<xen:require css="bb_code.css" />
<xen:require css="EWRcustom_spoiler.css" />
<xen:require js="js/8wayrun/EWRcustom_ajax.js" />
 
<div class="bbCodeBlock bbCodeQuote bbCodeSpoiler">
    <aside>
        <div class="spoilerBar attribution type">
            <div class="spoilerWarning">
                <b>{xen:phrase spoiler}</b><xen:if is="{$spoiler}">: {$spoiler}</xen:if>
            </div>
            <a href="#" class="spoilerToggle button primary">{xen:phrase toggle_spoiler}</a>
        </div>
        <blockquote class="spoilerContent">{xen:raw $content}</blockquote>
    </aside>
</div>
Next we create that custom template "EWRcustom_spoiler.css".
Code:
.bbCodeBlock.bbCodeSpoiler .spoilerBar { text-align: right; }
.bbCodeBlock.bbCodeSpoiler .spoilerBar .spoilerWarning { float: left; }
.bbCodeBlock.bbCodeSpoiler .spoilerBar .spoilerWarning b { font-size: 19px; }
Very simple template, you will notice that it references a custom JS file. You will now have to create this JS file. And yes, I know its not actually using AJAX, but thats just what I name every javascript I do with XenForo that uses it's jQuery base.
Code:
/** @param {jQuery} $ jQuery Object */
!function($, window, document, _undefined)
{
    XenForo.Spoiler = function($spoiler)
    {
        var $content = $spoiler.find('.spoilerContent:first').hide();
 
        $spoiler.find('.spoilerToggle:first').click(function(e)
        {
            e.preventDefault();
            $content.toggle('slow');
        });
    }
 
    // *********************************************************************
 
    XenForo.register('.bbCodeSpoiler', 'XenForo.Spoiler');
}
(jQuery, this, document);
Simple, first thing it does is find all spoiler zones and hides them... then links the spoiler toggle link to a toggle function. With this system, spoiler zones degrade gracefully, so if a user doesn't have javascript, they will still be able to access the relevant information.

Then, simply create the code event listener in your AdminCP.
(I will not write a tutorial on how to do this as there are already several on this forum)
 

sparky5693

Active member
Awesome, thank you very much. :)
For all non-developers, including myself that took more than an hour to get this working, I will attach the add-on.
The toggle isn't working for me. Everything appears visible, and the toggle takes me to forum index.
 

Saarbruecken

Active member
Where did you put the spoiler.js? Everything is supposed to be in library/spoiler/.
Edit: I can't access any files in library/spoiler, could you please check the CHMOD permissions?
 

Saarbruecken

Active member
HTML:
Forbidden
You don't have permission to access /forums/library/spoiler/spoiler.js on this server.
I guess that's the problem. Set chmod 644 the php and js files and 755 the spoiler directory.
 

Saarbruecken

Active member
Found the problem, I will update the package and re-upload it.

Edit: Done, please re-upload the files and upgrade the add-on. The library directory is .htaccess protected, I have to place the js file into the appropriate js folder.
 
Top