syncfusion/JavaScript-Widgets

ej.core.js function definition order breaks in lazily loaded scripts

Closed this issue · 1 comments

I generated a script using the custom script generator. When including it statically using a script tag in an HTML file it worked fine, but when lazily loading it from JS code (creating a script element, setting its src attribute and appending it to the document body) it failed on wd.init is not a function. When debugging it turned out that in the case of lazily loaded script, the function that calls wd.init() runs before wd.init is defined (because it's wrapped in a shorthand of "document ready" callback $(function(){...}), and the document is already ready then). I moved wd.init and the functions it calls to before that function and that resolved the issue. The order of function definitions that worked for me is:

  1. findElements
  2. initControls
  3. checkUnobtrusive
  4. wd.init
  5. $(function () {...})

complete code chunk is:

var findElements = function (name, op, el, proto) {
        var query = [], controlName = name.replace("ej", '').toLowerCase(), res = {};

        if (op.dataRole === true) {
            query.push("[data-role='" + name.toLowerCase() + "']");
        }
        if (op.ejRole === true) {
            query.push("[ej-" + controlName + "]");
        }

        res["role"] = el.find(query.join(','));

        if (op.directive === true) {
            res["directive"] = findAndChangeTag(el.find(controlName), (proto.validTags && proto.validTags[0]) || "div", controlName, el);
        }
        return res;
    };

    var initControls = function (controls, op, name, proto, map, dir) {
        var types = proto.dataTypes, len = controls.length;
        for (var i = 0; i < len; i++) {
            var control = controls.eq(i), model = {};
            iterateAndSetModel(model, readAttributes(control, op, name), map, types);
            control[name](model);
        }
    }

    var checkUnobtrusive = function (name, proto, op, el) {
        var controls = findElements(name, op, el, proto), map = propMaps[name];

        if (((controls.role && controls.role.length) || (controls.directive && controls.directive.length)) && !map) {
            propMaps[name] = map = generatePropMap(proto.defaults);

            if (proto._unobtrusive)
                $.extend(true, map, proto._unobtrusive);
        }

        initControls(controls.role, op, name, proto, map);

        if (controls.directive)
            initControls(controls.directive, op, name, proto, map, true);
    };

    wd.init = function (element) {
        if (!element) element = $(document);
        else element = element.jquery ? element : $(element);

        var widgets = wd.registeredWidgets;
        for (var name in widgets) {
            checkUnobtrusive(widgets[name].name, widgets[name].proto, options, element);
        }
    }

    $(function () {
        var ds = $(document.body).data();
        options.ejRole = ds.hasOwnProperty("ejrole") ? readBoolAttr(ds, "ejrole") : options.ejRole;
        options.directive = ds.hasOwnProperty("directive") ? readBoolAttr(ds, "directive") : options.directive;
        if (options.ejRole !== true && options.directive !== true) options.dataRole = true;
        options.dataRole = ds.hasOwnProperty("datarole") ? readBoolAttr(ds, "datarole") : options.dataRole;

        if (options.ejRole !== true && options.dataRole !== true && options.directive !== true)
            return;

        wd.autoInit = ds.hasOwnProperty("autoinit") ? readBoolAttr(ds, "autoinit") : true;

        if (wd.autoInit !== true)
            return;

        var query = [], el;
        if (options.dataRole === true)
            query.push("[data-ej-init]");
        if (options.ejRole === true)
            query.push("[ej-init]");
        el = $(query.join(','));

        if (!el.length) el = $(document);
        wd.init(el);
    });

Version 14.2.32 solves this issue.