XF 1.4 BBCode and javascript

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?
 
Is this lag/hang a result of using javascript in the HTML Replacement?
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.
 
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.
 
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>
 
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.
 
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:
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.
 
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?
 
Top Bottom