I seem to be having an issue when using jQuery in my plugin, which results in a blank page. When I delete the last line $document->addScriptDeclaration($js);, the site display but the code doesn't work as expected.

Here is my plugin


defined('_JEXEC') or die('Restricted access');

class PlgContentEasySpoiler extends JPlugin 
    function __construct(&$subject, $config)
        parent::__construct($subject, $config);
        $this->loadLanguage('', JPATH_ADMINISTRATOR);       $document = JFactory::getDocument();

    function onContentPrepare($context, &$article, &$params, $limitstart)
        if(!preg_match("@{spoiler}(.*){/spoiler}@sU", $article->text))
        if(preg_match_all("@{spoiler}(.*){/spoiler}@sU", $article->text, $matches, PREG_PATTERN_ORDER) > 0)
            foreach($matches[1] as $match)
                $bgcolor                    = $this->params->get('bgcolor');
                $fontcolor                  = $this->params->get('fontcolor');
                $padding_top_bottom         = $this->params->get('padding_top_bottom');
                $padding_left_right         = $this->params->get('padding_left_right');
                $border_radius              = $this->params->get('border_radius');
                $anim_speed                 = $this->params->get('anim_speed');

                $html = '';    
                $spoiler = preg_replace('#<(/*)span[^>]*>#msi', '', $match);   
                $html .= '<span class="spoiler">'.$spoiler.'</span>';
                $article->text = preg_replace("@{spoiler}".$match."{/spoiler}@sU", $html, $article->text);

            $css = 'a.reveal {
                background: '.$bgcolor.' !important; 
                padding:  '.$padding_top_bottom.'px '.$padding_left_right.'px !important; 
                border-radius:'.$border_radius.'px !important; 
                box-shadow:0 0 25px #111;
                -webkit-box-shadow:0 0 25px #111;
                -moz-box-shadow:0 0 25px #111;
                color: '.$fontcolor.' !important;



            JHtml::_('script', 'easyspoiler/js/easyspoiler.js', false, true, false, false, true);           
            $js = <<<SCRIPTHERE
                jQuery(document).ready(function() {
                }); SCRIPTHERE;             

and also the XML file

     <filename plugin="easyspoiler">easyspoiler.php</filename>
     <filename plugin="easyspoiler">index.html</filename>
<media folder="media" destination="easyspoiler">
    <language tag="en-GB">language/en-GB/en-GB.plg_content_easyspoiler.sys.ini</language>
    <language tag="en-GB">language/en-GB/en-GB.plg_content_easyspoiler.ini</language>
    <language tag="de-DE">language/de-DE/de-DE.plg_content_easyspoiler.sys.ini</language>
    <language tag="de-DE">language/de-DE/de-DE.plg_content_easyspoiler.ini</language>

    <fields name="params">
        <fieldset name="EASYSPOILER">   
            <field name="bgcolor" type="color" default="#fff" 
            description="PLG_EASYSPOILER_BACKGROUND_COLOR_DESC" />
            <field name="fontcolor" type="color" default="#000" 
            description="PLG_EASYSPOILER_FONT_COLOR_DESC" />
            <field name="padding_top_bottom" type="text" default="2" label="PLG_EASYSPOILER_TOP_BOTTOM" description="PLG_EASYSPOILER_TOP_BOTTOM_DESC" filter="integer" />
            <field name="padding_left_right" type="text" default="5" label="PLG_EASYSPOILER_LEFT_RIGHT" description="PLG_EASYSPOILER_LEFT_RIGHT_DESC" filter="integer" />
            <field name="border_radius" type="text" default="5" label="PLG_EASYSPOILER_BORDER_RADIUS" description="PLG_EASYSPOILER_BORDER_RADIUS_DESC" filter="integer" />
            <field name="border_shadow" type="text" default="5" label="PLG_EASYSPOILER_BORDER_SHADOW" description="PLG_EASYSPOILER_BORDER_SHADOW_DESC" filter="integer" />
            <field name="anim_speed" type="text" default="500" label="PLG_EASYSPOILER_ANIM_SPEED" description="PLG_EASYSPOILER_ANIM_SPEED_DESC" filter="integer" />
  • your document variable is not declared inside that function. add $document = JFactory::getDocument(); – subashbasnet8 Jan 29 '15 at 5:11

$document is only declared in the __construct scope.

You have to declare it before using it in onContentPrepare scope.

Alternatively, you can call addScriptDeclaration in the same way than you do with addStyleDeclaration:

| improve this answer | |

I would refrain from using $document = ... and then go on to use JFactory::getDocument()->addStyleDeclaration($css); because you're calling the class and fucntion twice and thus slowing down the process.

All you need to do is define the variable once inside the onContentPrepare function and then add your declarations like so:

function onContentPrepare($context, &$article, &$params, $limitstart)
    $document = JFactory::getDocument();

    $css = 'YOUR CSS CODE';
    $js  = 'YOUR JS CODE';


| improve this answer | |

You should format your script variable to this:

   jQuery(document).ready(function() {

When using heredoc syntax, the closing identifier (SCRIPTHERE;) must begin in the first column, i.e. it should not be indented.

This if from the php.net documentation:

Warning It is very important to note that the line with the closing identifier must contain no other characters, except a semicolon (;). That means especially that the identifier may not be indented, and there may not be any spaces or tabs before or after the semicolon. It's also important to realize that the first character before the closing identifier must be a newline as defined by the local operating system. This is \n on UNIX systems, including Mac OS X. The closing delimiter must also be followed by a newline.

If this rule is broken and the closing identifier is not "clean", it will not be considered a closing identifier, and PHP will continue looking for one. If a proper closing identifier is not found before the end of the current file, a parse error will result at the last line.

Change that line and see if that solves anything.

| improve this answer | |

Honestly, the preg_match() condition block should be removed entirely. You can just use !preg_match_all() to perform your early return. PREG_PATTERN_ORDER can be omitted because it is the default flag value.

Your $this->params->get() lines shouldn't be declared in the loop because they will only overwrite the variables with the same data (over and over).

Instantiating $html should be done prior to entering the loop so that you don't inadvertently delete the previous iteration's text.

The m and s pattern modifiers in your $spoiler replacement call is unnecessary because you don't have any anchors (^ or $) or dots (.) in your pattern. I'm not really sure of the coding intent behind purging all of the inner <span> tags, but I'll just follow your posted code. (your preg_replace("@{spoiler}".$match."{/spoiler}@sU" pattern could have contained special characters that would cause the regex engine to fail.)

After further consideration, I reckon I'd omit the preg_match_all() and looping task entirely. preg_replace_callback() can do everything in one step. Demo

The heredoc syntax seemed to be more trouble than it is worth for you, I'll swap them out for double-quoted string declarations.

function onContentPrepare($context, &$article, &$params, $limitstart)
    $article->text = preg_replace_callback('~{spoiler}(.*?){/spoiler}~s', 
        function($m) {
            return '<span class="spoiler">' .
                   preg_replace('~</?span[^>]*>~i', '', $m[1]) .
        }, $article->text, -1, $count);

    if (!$count) return;

    $document = JFactory::getDocument();

    $bgcolor            = $this->params->get('bgcolor');
    $fontcolor          = $this->params->get('fontcolor');
    $padding_top_bottom = $this->params->get('padding_top_bottom');
    $padding_left_right = $this->params->get('padding_left_right');
    $border_radius      = $this->params->get('border_radius');
    $anim_speed         = $this->params->get('anim_speed');

    $css = "a.reveal {\n
              background: {$bgcolor} !important;\n
              padding: {$padding_top_bottom)px {$padding_left_right}px !important;\n
              border-radius: {$border_radius}px !important;\n
              box-shadow: 0 0 25px #111;\n
              -webkit-box-shadow: 0 0 25px #111;\n
              -moz-box-shadow: 0 0 25px #111;\n
              color: {$fontcolor} !important;\n

    JHtml::_('script', 'easyspoiler/js/easyspoiler.js', false, true, false, false, true);           
    $js = "jQuery(document).ready(function() {\n
                    'anim_speed': '{$anim_speed}'\n
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.