We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 36702
    • 76 Posts
    I have a placeholder in my page template, eg [+theImage+]

    The idea is that in some pages, a snippet will replace this with a banner, slider or other content. If no snippet sets the placeholder, I want it replaced by a default image tag.

    I thought I could do this with a plugin, but I'm having trouble working out how to do this.

    The plugin is just:
    $modx->setPlaceholder('theImage', '<img src="/images/banner_default.jpg" width="100%" />');


    I have tried attaching the plugin to OnWebPagePrerender or OnWebPageComplete, but these seem to run too late (the placeholder is set to empty before these events).

    I then tried OnWebPageInit - the plugin works, but now it's too early - it happens BEFORE any snippet on the page is run.

    Is there another event I should be using, or is there a better way to achieve what I want?

    This question has been answered by multiple community members. See the first response.

      • 36702
      • 76 Posts
      Nobody?

      I'd appreciate any thoughts - if anyone can understand what I'm going on about smiley

      Just to restate the problem, and add a bit more info..

      THE ISSUE

      • All web pages include a banner area
      • On specific pages and under specific conditions, a snippet in the content area will set the banner to an image, slider or other markup appropriate for that page.
      • If a snippet has NOT set the banner, we want it to be a default image.

      ATTEMPT 1 - snippet tag in the template
      The 'obvious' solution seems to be a snippet call, eg [[theBanner]] in the template.
      PROBLEM: the snippet would need to include lots of disparate logic for selecting the banner depending on the page and other conditions.
      This logic should be (and in some cases already is) in individual page snippets.

      ATTEMPT 2 - placeholder in the template
      (a) default set by plugin
      We added a placeholder, eg [+theBanner+] in the template. A snippet in specific pages can then set this placeholder to the correct content.
      If the placeholder has NOT been set by a snippet, a plugin should set it to the default image.
      PROBLEM: We couldn't find an event to attach the plugin to.
      OnWebPageInit ........ happens too soon - the plugin ALWAYS set the default image, before any snippet gets a chance
      OnWebPagePrerender ... happens too late - MODX removes the placeholder before this event fires
      OnWebPageComplete .... happens too late - MODX removes the placeholder before this event fires
      (b) default set by new snippet
      We tried replacing the plugin with a "late" snippet call in the template (eg [[defaultBanner]] just before the closing body tag).
      We were hoping that any snippet call in the page content would run before the "late" snippet, so the latter would only set the default image if no other snippet had set the placeholder.
      PROBLEM: We always get the default image, ie the "late" snippet is being run BEFORE any snippet in the page content.

      ATTEMPT 3 - default image in the template
      Instead of a placeholder, we put the default image directly in the template, eg <img src="banner_default.jpg" width="100%" />
      The snippets in individual pages could then, instead of setting the placeholder, use str_replace to replace this specific string with something else when necessary.
      PROBLEM: it doesn't work?
      We tried updating $modx->documentOutput (also tried $modx->documentContent) - these strings definitely do contain the text, but changing these variables had no effect on the rendered output.
        • 4041
        • 788 Posts
        - removed - [ed. note: breezer last edited this post 6 years, 10 months ago.]
          xforum
          http://frsbuilders.net (under construction) forum for evolution
          • 36702
          • 76 Posts
          Thanks for the reply.

          I think your suggestion is basically the same as my attempt 2(b). The uncached snippet call runs before the in-page snippet for some reason - so the default image is always shown.
          • discuss.answer
            • 4041
            • 788 Posts
            I got this method to work with my limited testing.
            I used the following uncached snippet in the content of a couple pages to use a different image:
            <?php
            // [[banner_placeholder]]
            $array =array( '2', '6' );
            if( in_array( $modx->documentObject['id'], $array )){
                $modx->setPlaceholder( 'banner', '<img src="assets/images/modx-logo.png" />' );	
            }
            


            In your template wrap the placeholder like this:
            <!--banner-->[+banner+]<!--/banner-->


            In a plugin that fires OnWebPagePrerender:
            // OnWebPagePrerender
            $pos = strpos( $this->documentOutput, '<!--banner--><!--/banner-->' );
            
            if ($pos !== false) {
                
                // no other snippet filled the placeholder by now so it was removed, so insert the default image   
                $this->documentOutput = str_replace( '<!--banner--><!--/banner-->', '<img src="assets/images/noimage.jpg">', $this->documentOutput );
            	
            }
            
              xforum
              http://frsbuilders.net (under construction) forum for evolution
              • 36702
              • 76 Posts
              Hi breezer

              Thanks again for your suggestions, and continued interest (how long can this last? :/).

              I'm not too fussed about checking whether the placeholder has already been set. If it HAS previously been set, any call to $modx->setPlaceholder() or str_replace() will run without errors, but just won't do anything - that's fine.

              I do like your idea of wrapping the placeholder, so that a plugin running OnWebPagePrerender will know it's been removed. I'll try out this idea and let you know how it goes (probably 12+ hours from now).

              One thing still bothers me - I've had trouble getting changes to $this->documentOutput to work - but maybe this is only a problem in a snippet - it might work in a plugin (I'm sure I've previously done something similar in a plugin).
              • discuss.answer
                • 36702
                • 76 Posts
                Brilliant! That has solved the problem. smiley

                So simple in the end, but I just couldn't see it.

                I almost had it in my original post, but instead of the plugin (OnWebPagePrerender) trying to set a placeholder that wasn't there, it does str_replace for where the placeholder was!

                A couple of stack-overflow questions indicate that there's no real value in checking strpos() before str_replace(), so the final plugin code is:
                $modx->documentOutput = str_replace('<div id="hero"></div>', 
                                                    '<div id="hero"><img src="/images/banner_default.jpg" width="100%" /></div>', 
                                                    $modx->documentOutput);

                Thank you thank you breezer!
                  • 4041
                  • 788 Posts
                  You're welcome, glad it worked smiley
                    xforum
                    http://frsbuilders.net (under construction) forum for evolution