1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

XF 1.4 BBCode and javascript

Discussion in 'XenForo Questions and Support' started by aajobj, Jul 6, 2015.

  1. aajobj

    aajobj New Member

    Hi,

    I’m trying to create a custom BBCode for a HTML5 slideshow (Monokai's Monoslideshow) from post attachments, media gallery and img.
    In the HTML Replacement, I have the following code:
    Code:
    <script type="text/javascript" src="../monoslideshow.js"></script>
    <script type="text/javascript">
        var param = '{text}';
        var attroot = 'http://<domain.com>/forum/index.php?attachments/';
        var gallroot = 'http://<domain.com>/forum/index.php?media/';
        var timestamp = Number(new Date());
        var divid = 'postSlideshow_' + timestamp;
    
        document.write('<div id="' + divid + '" style="width: 500px; height: 400px;"></div>');
          
        String.prototype.replaceAll = function(target, replacement) {
            return this.split(target).join(replacement);
        };
    
        param = param.replace(/\s+/g, '').replace(/\r?\n|\r/g, '').replaceAll('<br />', '');
        param = param.replace(/(\[ATTACH\])([^\n\r[]*?)\[\/ATTACH\]/ig, ',' + attroot + '$2');
        param = param.replace(/(\[IMG\])([^\n\r[]*?)\[\/IMG\]/ig, ',$2');
        param = param.replace(/(\[GALLERY=media,)([0-9]+)\][^\n\r[]*?\[\/GALLERY\]/ig, ',' + gallroot + '$2/full');
        param = param.split(",");
        param.splice(0, 1);
    
        var xmlimg = '';
        var arrayLength =  param.length;
        for (var i = 0; i < arrayLength; i++) {
            xmlimg += '<image source="' + param[i] + '" thumbnail="' + param[i] + '" title="" />';
        }
    
        var xml    = '<?xml version="1.0" encoding="utf-8"?>' +
            '<album>' +
                '<configuration backgroundColor="#000000" delay="4" scaleMode="downscaleToFit">' +
                    '<transition performOutro="true" />' +
                    '<caption displayMode="never" />' +
                '</configuration>' +
                '<contents>' +
                    xmlimg +
                '</contents>' +
            '</album>';
    
        var mss = new Monoslideshow(divid, { showLogo: false, showRegistration: false });
        mss.loadXMLString(xml);
    </script>
    The code is handling uploaded attachment, media gallery and img.
    When I try to post with the BBCode tag that I have created, the browser hangs and do not stop loading.
    But if I stop the loading manually, and refresh/re-enter the thread URL, the replacement has been handled and the slideshow is displaying. Is this lag/hang a result of using javascript in the HTML Replacement?
     
  2. Mike

    Mike XenForo Developer Staff Member

    In short, yes. It doesn't really handle async loading correctly. Your JS would need to handle loading the library and not executing your code until it's loaded.

    I would also note that this code likely has a security hole by passing unfiltered text to JavaScript. You should probably handle this through a callback to ensure that what is going into {text} is being escaped for JS usage.
     
  3. aajobj

    aajobj New Member

    Ok.
    I am not sure if this is related to async issues.
    After I checked in web console (script) I suspect there is a conflict between monoslideshow.js and xenforo.js since I am getting a TypeError: e is undefined error.
    This is pointing at /js/xenforo/xenforo.js:
    Code:
    c("#NavigationLinksHiddenMenu").html(l).xfActivate()}}}}},register:function(a,b,d){if(typeof b=="string")var e=b,b=function(){XenForo.create(e,this)};c(i).bind(d||"XenForoActivateHtml",function(d){c(d.element).find(a).each(b)})},create:function(a,b){var d=c(b),e=g,f=a.split("."),h;for(h=0;h<f.length;h++)e=e[f[h]];if(typeof e!="function")return console.error("%s is not a function.",a);d.data(a)||d.data(a,new e(d));return d.data(a)},activate:function(a){var b=c(a);console.group("XenForo.activate(%o)",
    Can this be avoided with a PHP callback? And if so could you point me out a direction to where I should start.
     
  4. aajobj

    aajobj New Member

    Actually, after closer inspection this cannot be the monoslideshow.js.
    I have stripped down the javascript to the following, and get the same error (TypeError: e is undefined (at /js/xenforo/xenforo.js) (xenforo.js:220:305)):
    Code:
    <script type="text/javascript">
        var param = '{text}';
        var attroot = 'http://<domain.com>/forum/index.php?attachments/';
        var gallroot = 'http://<domain.com>/forum/index.php?media/';
        var timestamp = Number(new Date());
        var divid = 'postSlideshow_' + timestamp;
    
        String.prototype.replaceAll = function(target, replacement) {
            return this.split(target).join(replacement);
        };
    
        param = param.replace(/\s+/g, '').replace(/\r?\n|\r/g, '').replaceAll('<br />', '');
        param = param.replace(/(\[ATTACH\])([^\n\r[]*?)\[\/ATTACH\]/ig, ',' + attroot + '$2');
        param = param.replace(/(\[IMG\])([^\n\r[]*?)\[\/IMG\]/ig, ',$2');
        param = param.replace(/(\[GALLERY=media,)([0-9]+)\][^\n\r[]*?\[\/GALLERY\]/ig, ',' + gallroot + '$2/full');
        param = param.split(",");
        param.splice(0, 1);
    
        var xmlimg = '';
        var arrayLength =  param.length;
        for (var i = 0; i < arrayLength; i++) {
            xmlimg += param[i] + '<br />';
        }
        document.write(xmlimg);
    </script>
     
  5. Mike

    Mike XenForo Developer Staff Member

    I missed that you had document.write in there before, but you can't do that with dynamically loaded JS. It won't work as you expect.
     
  6. aajobj

    aajobj New Member

    Ok, so it is the "document.write" that is causing the whole problem?

    And if this could be the answer, where can I put the
    Code:
    <script type="text/javascript" src="../monoslideshow.js"></script>
    to make it globally?
     
    Last edited: Jul 7, 2015
  7. Mike

    Mike XenForo Developer Staff Member

    Well, that's one of the issues. Dynamically inserted JS also behaves differently when it comes to order than what is part of the page when it's loaded. This is what I was referring to with ensuring the library is loaded and using a callback once it happens. This isn't entirely trivial TBH and would require some custom JS development.
     
  8. aajobj

    aajobj New Member

    I was able to work around the problem by creating a JS-loader that makes sure that the monoslideshow is loaded before the code continues. I also was able to manipulate the div id programmatically first by declaring outside javascript:
    Code:
    <div id="mstemp" style="width: 500px; height: 400px;"></div>
    and then inside javascript by using this: $("#mstemp").attr('id', divid).
    My only problem now is as you pointed out when there is line breaks in the tag. What would be the easiest way to escape the raw {text} tag? You mentioned PHP callback. Do you have an example to get me started? Can I make use of any methods in the standard XenForo BBCode implementation?
     
  9. Mike

    Mike XenForo Developer Staff Member

    I don't have a particularly simple example to hand, but XFMG's gallery tag uses a callback.
     

Share This Page