Saturday, 19 August 2017

jQuery: Generate widget in javascript:

In this tutorial I am going to implement the javascript code that generates the javascript widget code to add in other 3rd party applications.

Step 1: In this step I am going to make a html page where we can generate the javascript widget code that you can add to your application. <!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <div id="divWidgetSettings" state="loaded">
        <div id="divAuthError">
            <span>Could not load widget settings. Are you <a href="http://localtest.me:12221/" target="_blank">logged in?</a></span>
        </div>
        <div id="divSettings">
            <input type="hidden" name="siteid" id="siteid" value="V7rXvP6G" />
            <h4>Widget Settings</h4>
            <div>
                <label>Group(s)</label>
                <ul id="list-emails"></ul>
                <button onclick="generateScript();">Generate</button>
            </div>
            <p>
                <textarea id="txt-widget-script" cols="80" rows="14" spellcheck="false"></textarea>
            </p>
        </div>
    </div>
</body>
</html>

<style>
    ul#list-emails {
        padding: 0px;
        max-height: 300px;
        overflow: auto;
    }

        ul#list-emails > li {
            list-style: none;
        }

            ul#list-emails > li > input[type=checkbox] {
                margin-right: 10px;
                margin-top: 0px;
                top: 2px;
                position: relative;
            }

    #divWidgetSettings[state="loaded"] #divSettings, #divWidgetSettings[state="error"] #divAuthError {
        display: block;
    }

    #divWidgetSettings[state="loaded"] #divAuthError, #divWidgetSettings[state="error"] #divSettings {
        display: none;
    }
</style>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript">

    getPublicGroups();

    function getPublicGroups() {
        var siteId = $('#siteid').val();
        //var url = "//" + window.location.hostname + port + "/api/widget/" + siteId + "?callback=JSON_CALLBACK";
        var url = "http://test.localtest.me:12221/api/widget/" + siteId;
        $("#divWidgetSettings").attr("state", "loaded");
        var publicEmailGroups = [];
        publicEmailGroups.push({ "Id": 69, "Name": "test5" });
        publicEmailGroups.push({ "Id": 74, "Name": "manpreetList" });

        if (publicEmailGroups.length > 0) {
            $.each(publicEmailGroups, function (index, data) {
                $("ul#list-emails").append("<li><input type='checkbox' data-id=" + data.Id + ">" + data.Name + "</li>");
            })
        }
    }

    function generateScript() {
        var baseUrl = location.protocol + '//' + location.host;
        var params = [];
        var selectedGroups = [];

        $("ul#list-emails > li").each(function () {
            if ($(this).children("input[type=checkbox]").is(":checked")) {
                selectedGroups.push({ Id: $(this).children("input[type=checkbox]").data("id"), Name: $(this).children("input[type=checkbox]").data("name") });
            }
        });
        params.push(["groups", selectedGroups]);

        var script = generateAsyncScript("_mnisubq", "subs", baseUrl, "/SubscriptionWidget.js", params);

        $("#txt-widget-script").val(script);
    }

    function generateAsyncScript(queue, type, baseUrl, path, params) {
        var id = +new Date,
            name = 'mni-' + type + '-' + id,
            script = '<div id="' + name + '"></div>\n',
            opts;

        params = params || [];
        params.push(['create', name]);

        for (var i = 0; i < params.length; i++)
            params[i][0] = id + '.' + params[i][0];

        opts = JSON.stringify(params);
        opts = opts.substring(1, opts.length - 1);

        script += '<sc' + 'ript type="text/javascript">\n';
        script += '/*<![CDATA[*/\n';
        script += 'var ' + queue + '=' + queue + '||[];\n';
        script += queue + '.push(' + opts + ');\n';
        script += '(function(b,d,a,c){b.getElementById(d)||(c=b.getElementsByTagName(a)[0],a=b.createElement(a),a.type="text/javascript",a.async=!0,a.src="' + baseUrl + path + '",c.parentNode.insertBefore(a,c))})(document,"mni-' + type + '-script","script");\n'
        script += '/*]]>*/\n';
        script += '</sc' + 'ript>';

        return script;
    };

    function makeAjaxCall(method, url, data, headers, dataType, successCallback, errorCallback) {
        $.ajax({
            type: method,
            url: url,
            headers: headers,
            data: data,
            dataType: dataType,
            cache: false,
            success: function (response) {
                successCallback(response);
            },
            error: function (errorResponse) {
                errorCallback(errorResponse);
            }
        });
    }
</script>

Step 2: In this step I am going to write a complete js file that is being used by the previous step.
Paste the following code in new js file named "SubscriptionWidget.js".

(function (document) {
    var queueVarName = '_mnisubq';

    //Get subscription script tag data
    function getScriptTagData() {
        var scripts = document.getElementsByTagName('script');

        for (var i = 0; i < scripts.length; i++) {
            var script = scripts[i],
                match = script.src.match(/^((https?:)?\/\/([^/]+))\/(api\/)?content\/publicwidgets\/subscriptionwidget\.(min\.)?js/i);

            if (match) {
                return {
                    protocol: match[2] || window.location.protocol,
                    origin: match[1] || window.location.origin,
                    domain: match[3] || window.location.host
                };
            }
        }
        return {
            protocol: window.location.protocol,
            origin: window.location.origin,
            domain: window.location.host
        };
    }

    //Get subscription api url
    function getUrl() {
        var l = getScriptTagData();
        return l.protocol + '//' + l.domain + '/ap/Subscription';
    }

    var widgets = window[queueVarName].reduce(function (o, k) {
        var params = k[0].split('.');
        var id = params[0];
        var arg = params[1];
        if (!o[id]) o[id] = {};
        if (!o[id].loaded) o[id][arg] = k[1];
        return o;
    }, {});
    Object.keys(widgets).forEach(function (k) { Init(k, widgets[k]); });

    //Returns html for popup
    function render(params) {
        return '<div class="container">' +
            '<div class="modal fade" id="signUpModal" role="dialog">' +
            '<div class="modal-dialog">' +
            '<div id="divSubscribe" class="modal-content">' +
            '<div class="modal-header">' +
            '<button type="button" class="close" data-dismiss="modal">&times;</button>' +
            '<h4 class="modal-title">MMP Subscription</h4>' +
            '</div>' +
            '<form action="" class="mn-subscribe">' +
            '<div class="modal-body">' +
            '<div class="row form-group">' +
            '<label class="col-md-3 col-sm-3">Email</label>' +
            '<div class="col-md-7 col-sm-4 mn-subscribe-email"><input id="txtEmail" class="form-control" type="email" name="email" required value="" email="true" /></div>' +
            '</div>' +
            '<div class="row form-group">' +
            '<label class="col-md-3 col-sm-3">Subscribe for</label>' +
            '<div class="col-md-7 col-sm-4">' +
            '<ul id="list-emails"></ul>' +
            '</div>' +
            '</div>' +
            '</div>' +
            '<div class="modal-footer">' +
            '<span id="spnSubscribeLoading" class="text-danger"></span>' +
            '<button type="button" id="btnClose" class="btn btn-default" data-dismiss="modal">Close</button>' +
            '<button type="button" class="btn btn-primary mn-subscribe-button">Subscribe</button>' +
            '</div>' +
            '</form>' +
            '</div>' +
            '</div>' +
            '</div>' +
            '</div>' +
            '<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" /><style>ul#list-emails {padding: 0px; max-height: 300px; overflow: auto; } ul#list-emails > li {list-style: none;} ul#list-emails > li > input[type=checkbox] {margin-right: 10px;margin-top: 0px;top: 2px;position: relative;}</style>';
    };

    function Init(id, params) {
        var $id = document.getElementById(params['create']);
        $id.innerHTML = render(params);

        var $subscribe = $id.getElementsByClassName('mn-subscribe-button')[0];
        var $email = $id.querySelector('.mn-subscribe-email input');

        $subscribe.addEventListener("click", function (e) {
            if (!validateFields($email)) {
                return false;
            }

            var listIds = [];

            $("ul#list-emails > li").each(function () {
                if ($(this).children("input[type=checkbox]").is(":checked")) {
                    listIds.push($(this).children("input[type=checkbox]").data("id"));
                }
            });

            $("#spnSubscribeLoading").text("Loading... ");

            if (!localStorage.mmpSubscribed || localStorage.mmpSubscribed == "false") {
                getEmailSubscriptions($email.value, function (response) {
                    if (response.length > 0) {
                        localStorage.mmpSubscribed = true;
                        alert("Already subscribed.");
                        $(".modal").modal("hide");
                    }
                    else {
                        subscribe($email.value, listIds);
                    }
                });
            }
            else {
                subscribe($email.value, listIds);
            }

            e.preventDefault(); return false;
        });

        loadJquery(params);
    }

    //Call subscription api
    function subscribe(email, listIds) {
        var url = getUrl();

        makeAjaxCall("Post", url, { Email: email, GroupsStr: listIds.toString() },
            { "Content-type": "application/x-www-form-urlencoded" }, "",
            function (response) {
                $("#spnSubscribeLoading").text("");
                setLocalStorage();
                alert("Thank you for Subscribing. Subscription confirmation link has been sent to your email.");
                $(".modal").modal("hide");
            },
            function (error) {
                handleAjaxError(error);
            });
    }

    //Validate input fields in subscription form
    function validateFields(email) {
        email.style.border = "1px solid #ccc";
        $("#spnSubscribeLoading").text("");

        if (!email.value || email.value == "") {
            email.style.border = "1px solid red";
            $("#spnSubscribeLoading").text("Please enter your email address. ");

            return false;
        }

        if ($("ul#list-emails > li > input[type=checkbox]:checked").length == 0) {
            $("#spnSubscribeLoading").text("Please select email list to subscribe. ");

            return false;
        }

        return true;
    }

    //Load jquery
    function loadJquery(params) {
        if (window.jQuery === undefined) {
            loadScript("https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js", function () { jqueryLoadHandler(params) });
        }
        else {
            jqueryLoadHandler(params);
        }
    }

    //Calling after load the jquery
    function jqueryLoadHandler(params) {
        var groups = params["groups"];

        $.each(groups, function (index, data) {
            $("ul#list-emails").append("<li><input type='checkbox' data-id=" + data.Id + ">" + data.Name + "</li>");
        });

        loadScript("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js", function () {
            if (!localStorage.mmpSubscribed || localStorage.mmpSubscribed == "false") {
                getEmailSubscriptions("", function (response) {
                    if (response.length > 0) {
                        localStorage.mmpSubscribed = true;
                    }
                    else {
                        $(".modal").modal("show");
                    }
                });
            }
        });
    }

    //Load and append script in page
    function loadScript(url, callback) {
        var script = document.createElement("script")
        script.type = "text/javascript";

        if (script.readyState) { //IE
            script.onreadystatechange = function () {
                if (script.readyState == "loaded" || script.readyState == "complete") {
                    script.onreadystatechange = null;
                    callback();
                }
            };
        } else { //Others
            script.onload = function () {
                callback();
            };
        }

        script.src = url;
        document.getElementsByTagName("head")[0].appendChild(script);
    }

    //Get email subscriptions
    function getEmailSubscriptions(email, successCallback) {
        var serverData = getScriptTagData();
        var url = serverData.protocol + '//' + serverData.domain + '/ap/subscription/GetEmailSubscriptions';

        makeAjaxCall("Get", url, { emailAddress: email },
            {}, "",
            function (response) {
                successCallback(response);
            },
            function (error) {
                handleAjaxError(error);
            });
    }

    //setting browser's localstorage
    function setLocalStorage() {
        localStorage.mmpSubscribed = true;
    }

    //common function to make ajax calls
    function makeAjaxCall(method, url, data, headers, dataType, successCallback, errorCallback) {
        $.ajax({
            type: method,
            url: url,
            headers: headers,
            data: data,
            dataType: dataType,
            cache: false,
            success: function (response) {
                successCallback(response);
            },
            error: function (errorResponse) {
                errorCallback(errorResponse);
            }
        });
    }

    //handles ajax call errors
    function handleAjaxError(error) {
        var errorMessage;

        if (error.responseText) {
            errorMessage = error.responseText;
        }
        else if (error.statusText) {
            errorMessage = error.statusText;
        }
        else {
            errorMessage = "Error";
        }

        errorMessage += " " + error.status;
        console.log("Error : " + errorMessage);
    }
})(window.document)

No comments:

Post a Comment