We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
  • One of the many great things about MODX is how you can take many routes to accomplish a given task. This is great because as you get more comfortable working with snippets and plugins to tweak your website as you intended you can quite easily go back to your code and realize you could have optimized certain things much more. This is something that happens to me every single day when maintaining my websites, so I decided to make it a working philosophy to spend more time building and less time maintaining.

    As I am progressing experimentation with Revolution, I have come across multiple situations where smarter coding will save me tons of time updating websites in the future and making it much more "user friendly" for my customers. The purpose of this thread is to share precisely these simple little tricks that will save you time in the future.



    Today's tip is using the snippet getResources, which I've learned to love almost as much as BBQ.


    If you are coding your HTML correctly, you are most likely using classes on certain blocks to indicate when a list of repetitive blocks is starting or ending. For example, when displaying several columns on your HTML code, where you separate each by a margin on the right, you will most likely have a class defined on the last column, probably named "last". This is useful because you can then code in your CSS that the column with the class "last" should not have a right margin. This will earn you some more pixels to play with.

    But when you take this code into MODX, there are so many ways to format this HTML code using snippets and chunks that you might fail to realize the most efficient way to code it so it takes you less time to maintain or make further modifications to your templates. The ways people could work around this are numerous:


    • If you are in a hurry you will probably leave your structured html code in the template to make sure it doesn't break and repeat snippet calls within each column to pull the data you want. This is not awesome because you are repeating commands which can be grouped into a single request, making the processing of your page a lot faster. This also isn't ideal as you are fixing display as governed by your HTML structure whereas you could be using dynamic values to adjust and allow your client more customization when updating content.
    • Other people would make a single call (as recommended) and use two template files, one for the general results, and one specific for the last result where the "last" class can be then inserted. getResources provides a variable for this: &tplLast, and until recently this is what I was using. But it bother me having two similar chunks with just 1 difference. So i was looking for a way to make it work with a single chunk and a single request.

    So I realized something really awesome by reading the documentation at: http://rtfm.modx.com/display/ADDON/getResources

    Yes, reading the manual from time to time is awesome! What I realized was a very simple placeholder I could setup in my request. This is called "idx". The way it works is pretty simple, you set it up in your request and assign it a numeric value. This value is then used on each result that comes from your request. So if I have in my request &idx=`0` or use the default of 1, then each result will have its own numeric value on increments which you can use in many clever situations.

    So I had two different types of columns I needed to adjust. First I had a 3 column setup where I required the third column to have a class of "last", since that would always be my last column. This was as simple as:

    <div class="col2[[+idx:is=`3`:then=` last`]]">


    Nothing fancy, just a simple output modifier to check if the idx value on the entry was 3, if it was, then it would add the "last" class. If it wasn't it would just not display anything.

    By doing this simple modification I saved myself 1 chunk, which makes future updates on the template a lot simpler and faster since its all centralized on a single file.

    But I had another columns issue that was a bit more complex. I had a row of two columns that I wanted to be flexible with. I wanted to allow the customer to be able to dynamically select how many entries would be output, furthermore, based on the amount of entries I would need to use different HTML elements so that my columns would adjust accordingly, so if it was more than 2 columns, then I would need a new row of two columns and so on. So simply relying on the number of results wasn't going to cut it. I needed something smarter. So after reading further into the output modifiers I found something awesome!!

    There is an output modifier that allows you to determine "even" and "odd" numbers, so with this, I could mark every 2nd column (even number) to use the "last" class with a very simple check:

    <div class="col4[[+idx:mod:is=`1`:then=` last`]]">


    The result? every two columns it adds the class and by doing this I am able to allow an unlimited amount of entries the client can choose within his admin, I'm using contexts to store site-wide settings and template variables to store page-wide or category-wide settings (I'll write more on that some other time). So the client has full control and my HTML wont break.

    Isn't it awesome? and again, I don't have to rely on a helper chunk for the last item, so I have strictly one chunk and 1 request, making my webpage a lot faster.

    There are a lot of similar situations where clever use of what's available on the core can save you a lot of time in the future, so I would like to encourage everyone who likes to find alternatives ways or more optimized ways to do the same thing to explore such ideas, and while you are at it, share them here! MODX is awesome for this.

    Cheers,
    Jose R. Lopez
    • For the Evo users out there, you can do much the same thing with Ditto. See http://www.pogwatch.com/ditto.html
        Studying MODX in the desert - http://sottwell.com
        Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
        Join the Slack Community - http://modx.org
      • Here is another cooltip I got working on a new website I'm building... As you probably have realized, using opengraph tags from facebook is most likely breaking your validation. Using two plugins this is easy to address:

        I'm using:

        BrowserServe: http://modx.com/extras/package/browserserve
        If: http://modx.com/extras/package/if

        Getting the facebook user agent is pretty simple, just check your logs.

        Facebook User Agent:

        facebookexternalhit/1.0 (+http://www.facebook.com/externalhit_uatext.php)

        Here is how I'm using this:

          [[!If? &subject=`[[!BrowserServe? &returnAgent=`1`]]` &operator=`EQ` &operand=`facebookexternalhit/1.0 (+http://www.facebook.com/externalhit_uatext.php)` &then=`<!-- Facebook -->
          <meta property="og:title" content="[[*pagetitle]] - [[++site_name]]" />
          <meta property="og:type" content="[[++site_start:is=`[[*id]]`:then=`website`:else=`article`]]" />
          <meta property="og:url" content="[[++site_url]][[*id:isnot=`[[++site_start]]`:then=`[[~[[*id]]]]`]]" />
          <meta property="og:image" content="[[++site_url]][[*ft_img:isnot=``:then=`[[*ft_img]]`:else=`[[++site_avatar]]`]]" />
          <meta property="og:site_name" content="[[++site_name]]" />
          <meta property="fb:admins" content="your admin" />
          <meta property="og:description" content="[[*introtext:empty=`[[*content:strip_tags:strip]]`:limit=`200`]]" />`]]


        Please note the call is not cache, this is important. Basically this checks the current useragent and if it matches facebook's user agent then it inserts the corresponding meta tags, if its not facebook, it just doesn't output those tags.

        And now your page validates tongue.

        NOTE: the automatic formatting in the forum is making the url in the facebook useragent, take note of that. The correct facebook user agent is:

        facebookexternalhit/1.0 (+http://www.facebook.com/externalhit_uatext.php)

        Cheers,
          • 33968
          • 863 Posts
          Nice tip! I'd previously shrugged off the facebook thing as 'oh well, won't validate...' but that's quite a handy solution you've come up with.
          • Here is another cool tip I think some might enjoy. Have you ever wanted to pass some dynamic variable or values to a javascript function but you didn't want to use the inline script calls on the HTML page because you like calling external .js files instead (for cache reasons or CDN implementations) well, that is my case and this is how I'm doing it.

            This is usually how my scripts are called at the footer of my html template:

            <script>
            yepnope.errorTimeout = 4000;
            yepnope([{
            	load: '//ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js',
            	callback: function (url, result, key) {
            		if (!window.jQuery) {
            			yepnope('[[++base_url]]assets/templates/main/js/libs/jquery-1.6.3.min.js');
            		}
            	}
            }, {
            	load: '//ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js',
            	callback: function (url, result, key) {
            		if (!jQuery.ui) {
            			yepnope('[[++base_url]]assets/templates/main/js/libs/jquery-ui.1.8.16.min.js');
            		}
            	}
            },
             {
            	load: ['//scripts.embed.ly/jquery.embedly.min.js',
            	'//platform.twitter.com/widgets.js',
            	[[If? &subject=`[[*id]]` &operator=`isnot` &operand=`[[++site_start]]` &then=`'[[++base_url]]assets/templates/main/js/libs/jquery.ticker.js',
            	'[[++base_url]]assets/templates/main/css/ticker-style.css',
            	'[[++base_url]]assets/templates/main/js/libs/font-controller.js',
            	'[[++base_url]]assets/templates/main/js/libs/jquery.cookie.js',
            	'[[++base_url]]assets/templates/main/css/font-controller.css',`]]
            	'[[++base_url]]assets/templates/main/js/plugins.js',
            	'[[++base_url]]assets/templates/main/js/scripts.js',
            	'[[++base_url]]assets/templates/main/css/xxx-theme/jquery-ui-1.8.16.custom.css']
            }]);
            </script>


            Nothing unusual here, however, in order to keep my functions and inline scripts in their respective files and still be able to pass dynamic variables I added the following at the top:

            /* Define Variables */
            var SiteVars={
            	GAid: '[[++site_gaid]]',
            	fbappid: '[[++site.fbappid]]',
            	locale:'[[++site.jslocale]]',
            	newstitle:'[[%newstitle? &topic=`xxx` &namespace=`core` &language=`[[++cultureKey]]`]]:',
            	fontsmall:'[[%fontsmall? &topic=`xxx` &namespace=`core` &language=`[[++cultureKey]]`]]',
            	fontdef:'[[%fontdef? &topic=`xxx` &namespace=`core` &language=`[[++cultureKey]]`]]',
            	fontlarge:'[[%fontlarge? &topic=`xxx` &namespace=`core` &language=`[[++cultureKey]]`]]'
            };
            /* Define Variables */


            so the resulting code is:

            <script>
            
            /* Define Variables */
            var SiteVars={
            	GAid: '[[++site_gaid]]',
            	fbappid: '[[++site.fbappid]]',
            	locale:'[[++site.jslocale]]',
            	newstitle:'[[%newstitle? &topic=`xxx` &namespace=`core` &language=`[[++cultureKey]]`]]:',
            	fontsmall:'[[%fontsmall? &topic=`xxx` &namespace=`core` &language=`[[++cultureKey]]`]]',
            	fontdef:'[[%fontdef? &topic=`xxx` &namespace=`core` &language=`[[++cultureKey]]`]]',
            	fontlarge:'[[%fontlarge? &topic=`xxx` &namespace=`core` &language=`[[++cultureKey]]`]]'
            };
            /* Define Variables */
            
            yepnope.errorTimeout = 4000;
            yepnope([{
            	load: '//ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js',
            	callback: function (url, result, key) {
            		if (!window.jQuery) {
            			yepnope('[[++base_url]]assets/templates/main/js/libs/jquery-1.6.3.min.js');
            		}
            	}
            }, {
            	load: '//ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js',
            	callback: function (url, result, key) {
            		if (!jQuery.ui) {
            			yepnope('[[++base_url]]assets/templates/main/js/libs/jquery-ui.1.8.16.min.js');
            		}
            	}
            },
             {
            	load: ['//scripts.embed.ly/jquery.embedly.min.js',
            	'//platform.twitter.com/widgets.js',
            	[[If? &subject=`[[*id]]` &operator=`isnot` &operand=`[[++site_start]]` &then=`'[[++base_url]]assets/templates/main/js/libs/jquery.ticker.js',
            	'[[++base_url]]assets/templates/main/css/ticker-style.css',
            	'[[++base_url]]assets/templates/main/js/libs/font-controller.js',
            	'[[++base_url]]assets/templates/main/js/libs/jquery.cookie.js',
            	'[[++base_url]]assets/templates/main/css/font-controller.css',`]]
            	'[[++base_url]]assets/templates/main/js/plugins.js',
            	'[[++base_url]]assets/templates/main/js/scripts.js',
            	'[[++base_url]]assets/templates/main/css/xxx-theme/jquery-ui-1.8.16.custom.css']
            }]);
            </script>


            Basically what I am doing here is that at the very top of the block I am defining variables in javascript and using values from either my settings (in my context) or from language strings I have created. I can then access these variables like this:

            SiteVars.newstitle


            For each of the variables I have previously defined.

            So why do this? It allows me to input dynamic values in my context based on my website structure and go a step beyond, I could even modify such values on a per-page basis (if I wanted to) while keeping my scripts on seperate files and getting the added benefit of browser cache.
            • Just keep in mind that requesting and downloading a separate small file may actually take longer and use more server resources than having the relatively small amount of plain-text in the HTML file that's already being downloaded. Every external file (whether .js, .css or image) has to go through the same process of browser/server handshake and negotiation. Try opening a command line terminal and requesting a file via telnet... that's exactly what your browser is doing behind the screen. http://www.the-art-of-web.com/system/telnet-http11/
                Studying MODX in the desert - http://sottwell.com
                Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
                Join the Slack Community - http://modx.org
              • Sottwell is correct, the topic actually goes well beyond performance and goes into usability and accessibility. There is a lot more to consider. My intentions are not to dive deep into such matters but provide inputs on how to achieve simple things which might not be trivial for the average user taking advantage of the tools available through modx.

                Everyone should definitely keep an eye on their individual usage of such techniques to make sure you are not sacrificing important factors of your page load time or user's experience when being used. You should always aim to make the surfing experience through your website as enjoyable as possible by applying the most relevant (if not all) usability techniques and at the same time keeping search engines happy by implementing proper accessibility throughout your website.

                In my particular case once I am ready to move a website into a production enviorement I use Minify, this will merge (based on my needs) the JS calls and CSS calls in single files instead of calling many individual ones and also uses some caching techniques which aid the purpose of performance.

                My sample above is on a new website in the process of being build.

                Cheers,
                Jose R. Lopez
                  • 33974
                  • 156 Posts
                  You normally should reach best performance with up to 3 stylesheets and 3 js-files. You can test your browser with: http://www.der-schepp.de/http-connects/

                  Tip of the day: use my MODX-Boilerplate to start developing the layout within 3mins: https://github.com/smooth-graphics/modx-boilerplate
                  • Quote from: smooth-graphics at Sep 22, 2011, 07:43 AM
                    You normally should reach best performance with up to 3 stylesheets and 3 js-files. You can test your browser with: http://www.der-schepp.de/http-connects/

                    Tip of the day: use my MODX-Boilerplate to start developing the layout within 3mins: https://github.com/smooth-graphics/modx-boilerplate

                    I'm using your template for the first time in this project I'm bullding and I love it.
                    • Here is a really cool tip I just figured out.

                      To make even more efficient use of your chunks, specially when paired with snippets like getResources you can pass in the snippet call custom values instead of hardcoding them in your chunks.

                      For example, I re-use the same div wrapper for every getResources snippet call but pass it a custom class or id parameter which gets replaced by a placeholder within the chunk.

                      So my snippet call looks something like:

                      [[getResources? &tpl=`mycoolchunk` &elemClass=`widget col4`]]


                      Take note that the parameter &elemClass is not something specific to getResources but just a random variable name I created myself.

                      And then inside my chunk:

                      <div class="[[+elemClass]]">
                      <h2>[[+pagetitle]]</h2>
                      <p>[[+introtext]]</p>
                      </div>
                      


                      This allows me to:


                      • Be consistent with my HTML code
                      • Minimize the amount of chunks I'm using.
                      • Style content based on the location of the request (by cleverly using classes).

                      This of course is a very silly way to showcase the power of such behavior provided by modx, what's important to note here is that by sending custom parameters along with your snippet call you can do some really awesome stuff on your chunks which gives you much freedom when coding your pages.

                      Something similar can be accomplished with Property Sets, they are very powerful when used effectively too.