0

I have created a JavaScript/jQuery widget which needs to have the ability to be embedded in pages multiple times, each with their own variables set differently. At the moment various variables are being over written by whichever widget loads last.

Here is a cut down version for example purposes.

(function () {

    var scriptName = "my.widget.js";
    var TGW;
    var jqueryPath = "https://ajax.googleapis.com/yada_yada..."; 
    var scriptTag;
    var jScript;

    /******** Get reference to self (scriptTag) *********/
    var allScripts = document.getElementsByTagName('script');
    var targetScripts = [];
    for (var i in allScripts) {
        var name = allScripts[i].src
        if(name && name.indexOf(scriptName) > 0)
            targetScripts.push(allScripts[i]);
    }

    scriptTag = targetScripts[targetScripts.length - 1];

    /******** Set jQuery noConflict *********/
    if (window.TGW === undefined || window.TGW.fn.jquery !== jqueryVersion) {
        loadScript(jqueryPath, initTGW);
    } else {
        initTGW();
    }

    function initTGW() {
        TGW = window.jQuery.noConflict(true);
        main();
    }

    function main() {
        TGW(document).ready(function ($) {
            loadParams();
        });
    }

    function loadParams() {
        jScript = TGW(scriptTag);
        comments = jScript.data("comment");
    }

})();

And here is how it is added to the webpage twice with different settings for the comment data attribute.

<script src='https://...my.widget.js' data-comment='yes'></script>
<script src='https://...my.widget.js' data-comment='no'></script>

With the above, if there is a hypothetical button in the widgets which displays the contents of the variable comments, the variable will randomly contain/display "yes" or "no" depending on which widget loaded last.

What needs to happen when the button on the first widget is pressed, is it display "yes". And when the button on the second widget is pressed, it display "no".

I think this is to do with namespaces or something, but I don't really understand it. I thought wrapping the entire widget in (function () { made in run as an anonymous function which would mean all the variables are separate.

Any help appreciated

superphonic
  • 7,954
  • 6
  • 30
  • 63
  • You should probably check out some design patterns, for example https://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript Also, you shouldn't load your script multiple times like that - just load the base module once and call it any number of times with different parameters. – Alex.Me Feb 24 '16 at 17:02
  • @Alex.Me This is a widget that other users will add to their own sites, it's not part of my own website. I will check that link out though. Thanks. – superphonic Feb 24 '16 at 17:17

2 Answers2

1

In the absence of a reliable document.currentScript, you might try replacing your allScripts = ....; for() {...} with the something like this :

var marker = 'data-r_e_a_d'; // something unique, that won't overwrite any data- attribs delivered in the HTML

var scriptTag = Array.prototype.slice.call(document.getElementsByTagName('script')).reduce(function(prev, current) {
    var tag = (!prev && !current.getAttribute(marker) && current.src && current.src.indexOf(scriptName) > 0) ? current : prev;
    if(tag === current) current.setAttribute(marker, true);//mark "self" as read
    return tag;
}, null);

which will deliver the latest unread qualifying script - ie "self".

In its wake this process will leave behind marker attributes in your widget's script tags. If desired, these could be cleaned up after reading the last <script>, but it should do no harm to leave them there.

Roamer-1888
  • 19,138
  • 5
  • 33
  • 44
0

I believe your scriptTag (reference to self) might always be the last script on the page.

If your supporting newer browsers only you may use document.currentScript. Otherwise you might have to assign a unique id for each script tag, see this answer for different methods of obtaining the script reference https://stackoverflow.com/a/22745553/4297908.

Community
  • 1
  • 1
mvr
  • 1,732
  • 16
  • 11
  • Thanks... `document.currentScript` doesn't seem to be widely supported at all, not just IE either. This is a widget that other non tech users will be adding to their own websites etc... Using a unique ID on the script tag won't work in this instance. Ideally end users should just be able to copy and paste the script code and add it to their site. – superphonic Feb 24 '16 at 17:15