var preloadScript = [];
var loadScript = [];
var pageLayout;
var engErrorMessage = 'There was an error loading the page.  Please contact the survey administrator.';
var revertToHTML = false;
var isRTL;
var isstudio;

//TODO: fix form.submit() when multiple submit buttons by creating a submit function to always click next

$(document).ready(function() {
    try {
        isstudio = location.href.search(/question\.htm/i) > 0;
        isRTL = checkRTL('css/laf_rtl.css');
        $(".container").show();
        pageLayout = new layout(); // create the global survey page.
        pageLayout.init();

    } catch (err) {
        handleSurveyEngineError(err);
    }
});

/**
 * In case a console.log message gets in here
 * @private
 */
var console = window.console || {
    log: function() {}
};

/**
 * Object.create not supported in IE8 or below
 * @private
 */
if (Object.create === undefined) {
    Object.create = function(o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}


var layout = function() {

    this.form = $('form');
    this.menu = $('#menuButtons');
    this.next = $('.mrNext'), this.prev = $('.mrPrev');
    this.tempNext = $(".tempNext"), this.tempPrev = $(".tempPrev")
    this.content = $('#questions');
    this.questions = this.content.find('div.questionContainer');
    this.sharedContent = $('#sharedContent').attr('src').replace(/\\/g, '/');
    this.imageCache = this.resolveImageCache().replace(/\\/g, '/'); //todo: check that this works with server locations \\konapmri033
    this.synch = "/synch/projects/" + projectName + "/";
    this.themePath = (typeof tJSON == 'undefined') ? this.sharedContent + "LAF/Themes/default/1.0/" : ((typeof tJSON.themeSource == 'undefined') ? this.sharedContent + "LAF/Themes" : ((tJSON.themeSource.toLowerCase().substring(0, 4) == 'http') ? "" : this.imageCache) + tJSON.themeSource) + "/" + tJSON.themeName + "/" + tJSON.themeVersion + "/";
    this.interviewer = (sampleSource == 'IPL01');
    this.TIB = null;
    this.loader = null;
    this.infoSource = $('#infoPanel');
    this.footer1 = $('.footer1'), this.footer2 = $('.footer2');
    this.allInputs = $([]), this.img = $('img'), this.table = $("table");
    this.deviceType = (typeof deviceType != 'undefined' ? deviceType : "UNKNOWN").toUpperCase();
    this.showonly = ($('input[type=hidden][name=I\\.ShowOnly]').length > 0);

}

layout.prototype = {
    init: function() {

        this.secure();
        this.setupNavs();
        this.createLoader();
        this.updateMenu();
        this.moveErrors();
        this.addAttributes();
        this.v3Styles();
        this.applyThemes();
        if (isRTL) {
            this.applyRTLStyle();
        }
        this.TIB = new testPanel(isTest);
        var imagesLoaded = this.preloadImages();
        var that = this;
        $.when(imagesLoaded).always(function() {
            that.evaluateScripts(preloadScript, that.build, that);
        })


    },
    secure: function() {
        if (isTest) return;
        if (typeof isDebug != 'undefined')
            if (parseInt(isDebug, 10) > 0) return;
        document.oncontextmenu = function() {
            return false
        };
        var body = $('body');
        body.addClass("noselect");
        body.prop('unselectable', 'on');
        if (typeof document.onselectstart != "undefined") {
            document.onselectstart = function(e) {
                var evt = (evt) ? evt : ((window.event) ? event : null);
                if (evt) {
                    var target = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
                    if (target) {
                        switch (target.tagName.toLowerCase()) {
                            case "input":
                            case "textarea":
                            case "select":
                                return true;
                            default:
                                return false;
                        }
                    }
                }
                return false;
            }
        }
    },
    lazyLoad: function(dependencies, callback, context) {
        var defer = [];
        while (dependencies.length > 0) {
            var objDepend = dependencies.shift();
            objDepend.url = this.resolveFilePath(objDepend.url);
            if (typeof engVersion != "undefined")
                objDepend.url = objDepend.url + ((objDepend.url.indexOf("?") == -1) ? "?" : "&") + 'p=' + projectName + '&rid=' + serial + '&SE=' + engVersion + '&deviceType=' + this.deviceType.toUpperCase();
            if (objDepend.type == "script") {
                defer.push(
                    jQuery.ajax({
                        type: "GET",
                        context: this,
                        url: objDepend.url,
                        error: function() {
                            console.log("error loading: " + objDepend.url)
                        },
                        dataType: objDepend.type,
                        cache: true,
                        crossDomain: true
                    })
                );
            } else if (objDepend.type == "stylesheet") {
                $("head").append("<link>");
                var css = $("head").children(":last");
                css.attr({
                    rel: "stylesheet",
                    type: "text/css",
                    href: objDepend.url
                });
            }
        }
        $.when.apply(context, defer).always(function() {
            callback.apply(context)
        });
    },
    resolveFilePath: function(stringVal) {
        stringVal = stringVal.replace(/\[%ImageCacheBase%\]/gi, pageLayout.imageCache);
        stringVal = stringVal.replace(/\[%SharedContentBase%\]/gi, pageLayout.sharedContent);
        stringVal = stringVal.replace(/\[%synchBase%\]/gi, pageLayout.synch);
        return stringVal;
    },
    updateMenu: function() {
        if (this.menu.find('.help').attr("href") == "") {
            $('.tempHelp').remove();
        }
        if (this.menu.find('.privacy').attr("href") == "") {
            $('.tempPrivacy').remove();
        }
        var subMenus = this.menu.find('a');
        if (subMenus.length > 0) {
            $('.tempMenuButtons').show();
            if ($('.tempHelp').length > 0) {
                $(".tempHelp").click(function() {
                    window.open($(".help").attr('href'), '_blank');
                });
            }
            if ($('.tempPrivacy').length > 0) {
                $(".tempPrivacy").click(function() {
                    window.open($(".privacy").attr('href'), '_blank');
                });
            }

            $(".tempPrivacy").click(function() {
                window.open($(".privacy").attr('href'), '_blank');
            });
        }
    },
    menuClick: function() {
        var that = this.menu;
        this.menu.addClass('hand');
        var ulmenu = this.menu.find('ul');
        if (deviceType != "PC") {
            ulmenu.insertBefore($('#survey'));
        }
        this.menu.click(function() {
            ulmenu.slideToggle(400);
        });
    },
    moveErrors: function() {
        var errors = $('.mrErrorText');
        errors.each(function() {
            var jThis = $(this);
            var qText = null;
            var parent = jThis.parent();
            var isParentDIV = (parent[0].nodeName == "DIV");
            var qContainer = (isParentDIV) ? parent.parent() : parent.closest('tr');
            qText = qContainer.find('.mrQuestionText:first');
            if (qText) {
                jThis.append($("<br>"));
                qText.prepend(jThis);
                if (isParentDIV) parent.remove();
            }
        });
    },
    setupNavs: function() {
        if (this.next.length > 0) {
            this.next.addClass("hidden");
            this.tempNext.css("display", "block");
            this.tempNext.click(function() {
                pageLayout.next.click()
            });
        }
        if (this.prev.length > 0) {
            this.prev.addClass("hidden");
            this.tempPrev.css("display", "block");
            this.tempPrev.click(function() {
                pageLayout.prev.click()
            });
        } else {
            $('.nextNavButton ').css('width', '100%');
        }
    },
    createLoader: function() {
        this.loader = $('<div id="loader"><div class="preloader-wrapper big active"><div class="spinner-layer spinner-blue-only"><div class="circle-clipper left"><div class="circle"></div></div><div class="gap-patch"><div class="circle"></div></div><div class="circle-clipper right"><div class="circle"></div></div></div></div></div>');
        this.content.after(this.loader);
        this.showLoader();
    },
    showLoader: function() {
        this.content.hide();
        this.footer1.hide();
        this.loader.show();
    },
    hideLoader: function() {
        this.loader.hide();
        this.content.show();
        this.footer1.show();
    },
    build: function() {
        //customButtons.init();
        this.convertEndLink('mrEndLink');
        this.evaluateScripts(loadScript, this.render, this);
    },
    render: function() {

        this.setCursorInOpens();
        this.TIB.init();
        this.hideLoader();
        console.log("page ready");
    },
    preloadImages: function() {
        var defer = new $.Deferred();
        var images = pageLayout.getDocumentImages();
        var promises = [];
        var failedImages = [];
        $(images).each(function() {
            var deferImage = new $.Deferred();
            var image = document.createElement('img');
            image.onload = function() {
                deferImage.resolve();
            };
            image.onerror = function() {
                failedImages.push(this.src);
                deferImage.resolve();
            };
            image.onabort = function() {
                deferImage.resolve();
            };
            image.src = this;

            promises.push(deferImage.promise());
        });
        $.when.apply(this, promises).then(function() {
            if (failedImages.length > 0) pageLayout.infoSource.append($('<div>').attr('id', 'imageErrorsURLs').text(failedImages.toString()));
            defer.resolve();
        });
        return defer.promise();
    },
    getDocumentImages: function() {
        var images = [];
        $(document.images).each(function(i, e) {
            if (this.src != '')
                if (this.src.indexOf("aspx?") != -1 || this.src.indexOf("?") == -1)
                    if (this.src.indexOf(".swf") == -1 && this.src.indexOf("#") == -1) {
                        images.push(this.src);
                    }
        });
        return images;
    },
    evaluateScripts: function(scripts, callback, context) {
        var promises = [];
        console.log(scripts);
        while (scripts.length > 0) {
            var theScript = scripts.shift();

            if (typeof theScript == "function") {
                console.log('Executing function');
                promises.push(theScript());
            } else {
                console.log('Executing ' + theScript);
                promises.push(eval(theScript));
            }
        }
        $.when.apply(this, promises).always(function() {
            callback.apply(context)
        });
    },
    resolveImageCache: function() {
        var imageCacheArray, tempICBase;
        if (typeof imageCacheBaseString == 'undefined') return "";
        tempICBase = imageCacheBaseString; //by deafult they are the same UNLESS multiple questions on page
        tempICBase = tempICBase.replace(/-- unknown ----- unknown --\//, ""); //fix es-us language issue
        tempICBase = tempICBase.replace(/&amp;/g, "&"); //update escaped & to be actual character, needed for chrome/opera/safari

        if (tempICBase.charAt(1) == ':') { //loaded from a mapped drive letter
            imageCacheArray = tempICBase.split("/" + tempICBase.substr(0, 2))
            if (imageCacheArray.length > 1)
                tempICBase = imageCacheArray[0] + "/";
            return tempICBase;
        }
        if (tempICBase.indexOf("http://") == 0) { //loaded with an http:// reference
            imageCacheArray = tempICBase.split("http://")
            if (imageCacheArray.length > 1)
                tempICBase = "http://" + imageCacheArray[1];
            return tempICBase;
        }

        if (tempICBase.indexOf("\\\\") == 0) { //loaded from a sever share
            imageCacheArray = tempICBase.split("\\\\");
            if (imageCacheArray.length > 1) tempICBase = "\\\\" + imageCacheArray[1];
            return tempICBase;
        }

        if (tempICBase.indexOf("//") > 0) {
            imageCacheArray = tempICBase.split("//");
            tempICBase = imageCacheArray[0] + "/";
            return tempICBase;
        }
        return tempICBase;
    },
    addAttributes: function() {
        var that = this;
        this.createQuestionContainers();
        this.questions = $('.questionContainer');
        this.questions.each(function(i, e) {
            var container = $(this);
            var subContainers = container.find('.questionContainer');
            var hasOther = false;
            for (var z = 0; z < subContainers.length; z++) {
                var subInputs = subContainers.eq(z).find(':input, textarea');
                if (subInputs.length > 0) {
                    firstInputID = subInputs.eq(0).attr('id');
                    if (firstInputID.indexOf("_O") != -1) {
                        hasOther = true;
                        break;
                    }
                }
            }
            if (subContainers.length > 0 && !hasOther) return;
            var qName = null;
            var isGrid = false;
            var inputs = null;
            inputs = container.find(':input');
            inputs.each(function(i, b) {
                var jInput = $(this);
                qName = that.processInputAttributes(jInput, inputs, that);
                if (i == 0) {
                    isGrid = that.isGridInput(jInput);
                    that.setQuestionName(container, qName, isGrid);
                }
            });
            that.allInputs = that.allInputs.add(inputs);
        });
        this.questions.each(function() {
            var jThis = $(this);
            if (!jThis.attr("questionname")) {
                var nameArray = jThis.find('.questionContainer').eq(0).attr('questionname');
                if (nameArray == null) return;
                nameArray = nameArray.split('.');
                jThis.attr('questionname', nameArray.slice(0, nameArray.length - 1).join('.'));
            }
            jThis.find('[otherid]:not([otherid=""])').parent().find('input[type="text"]').attr('otherinput', 'true');
        });
        var page = this.content.children('.mrQuestionText');
        if (page.length == 0) return;
        var childName = page.siblings('.questionContainer').eq(0).attr("questionname");

        if (childName) {
            var nameArray = childName.split(".");
            var blockName = nameArray.slice(0, nameArray.length - 1).join('.');
            var innerQ = page.siblings('.questionContainer[questionname^="' + blockName + '."]');
            if (innerQ.length > 0) {
                var newQC = $('<div>').addClass('questionContainer').attr('questionname', blockName);
                page.before(newQC);
                newQC.append(page).append(innerQ);
                this.questions = this.questions.add(newQC);
            }
        }

    },
    isGridInput: function(jInput) {
        var inputType = jInput[0].nodeName.toLowerCase();
        if (inputType == 'input') inputType = jInput.attr('type').toLowerCase();
        var labelMatch = 'label[for=' + jInput.attr('id') + ']';
        switch (inputType) {
            case "radio":
            case "checkbox":
                var label = jInput.parent().find(labelMatch);
                if (label.length > 0) return false; //grid standard inputs don't have labels
                var id = jInput.attr('id');
                if (id.indexOf("_F") == -1) return true; //if input not a code and no label it is a grid
                var codeParent = jInput.parent().parent();
                if (codeParent[0].nodeName.toLowerCase() == "td") return true; //if code and its container is cell it is a grid
                return false; //get here all grid tests fail
            case "text":
            case "textarea":
                var parentTable = jInput.closest('table');
                if (parentTable.length == 0) return false; //no containing table, no grid
                if (parentTable.find(labelMatch).length == 0) return true; //if no label of text, its a grid
                return false;
            case "option":
            case "select":
                var parent = jInput.parent();
                if (parent[0].nodeName.toLowerCase() == "td") return true; //assuming if parent is td then grid
                return false; //get here, no grid
        }
        return false;
    },
    createQuestionContainers: function() {
        this.questions.find('span > .mrQuestionText').parent().addClass('questionContainer');
        this.questions.find('span > label > .mrQuestionText').parent().parent().addClass('questionContainer');
    },
    processInputAttributes: function(jInput, inputs, that) {
        var isCat, isCode, isOth, type, qName;
        var jID = jInput.attr("id");
        if (typeof jID === "undefined") return qName = "";
        isCat = (jID.indexOf("_C") > 0);
        jInput.attr("openendid", "");
        jInput.attr("iscode", "");
        jInput.attr("otherid", "");
        jInput.attr("isexclusive", that.isExclusive(jInput.attr("value"))); //determine if exclusive

        if (isCat) type = "_C";
        if (!isCat) {
            isCode = (jID.indexOf("_X") > 0);
            isOth = (jID.indexOf("_O") > 0);
            if (isCode) type = "_X";
            if (isOth) type = "_O";
            if (isCode) {
                jInput.attr("openendid", jID.split("_X")[0]); //set otherid to other (text box) question ID if exists
                jInput.attr("iscode", true); //set flag if code category
            }
            if (isOth) {
                var othCat = inputs.filter("input[id='" + jID.replace(type, "_C") + "']");
                othCat.attr("otherid", jID);
            }
        }
        qName = that.resolveHTMLValueToMDDName(jInput.attr("name"), type);
        jInput.attr("questionname", qName); //set questionname attribute for grouping later
        return qName;
    },
    setQuestionName: function(container, qName, isGrid) {
        if (isGrid) {
            var nameArray = qName.split('.');
            qName = nameArray.slice(0, nameArray.length - 2).join('.');
        }
        container.attr("questionname", qName);
        nameArray = qName.split('.');
        return nameArray.slice(0, nameArray.length - 1).join('.');
    },
    isExclusive: function(name) {
        if (name == null) return false; //no name no exclusive
        name = name.toUpperCase(); //remove case sensitivity
        name = this.resolveHTMLValueToMDDName(name); //remove special SPSS formatting
        return (name == "NA" || name == "REF" || name == "DK" || name == "NONE" || name == "DONTKNOW" || name.charAt(name.length - 1) == "@"); //check against standard names
    },
    resolveHTMLValueToMDDName: function(htmlName, delimiter) {
        //http://pic.dhe.ibm.com/infocenter/spssdc/v6r0m1/topic/com.spss.ddl/mrscriptbasic_langref_namingconventions.htm
        //http://pic.dhe.ibm.com/infocenter/spssdc/v6r0m1/topic/com.spss.ddl/mrintover_html_player_elements.htm
        htmlName = htmlName.replace(/__/g, "~"); //replace __ with ~.  __ represents _ in any name (used so flags below could be used with an underscore without confusion). Replacing with ~ to remove _ from name so other replacements can be done.
        htmlName = htmlName.replace(/_D/g, "@"); //replace _D with @ (@ is used to denote exclusive mention)
        htmlName = htmlName.replace(/_H/g, "#"); //replace _D with @ (@ is used to denote exclusive mention)
        htmlName = htmlName.replace(/_S/g, "."); //replace _S with a dot (used when namespacing)
        htmlName = htmlName.replace(/^\s+|\s+$/g, ''); //trim string of leading and trailing spaces
        if (delimiter == "_O") htmlName = htmlName.replace(delimiter, '.'); //trim string of leading and trailing spaces
        if (htmlName.indexOf("_Q") == 0) htmlName = htmlName.replace(/_Q/g, ".").substr(1);
        if (delimiter) htmlName = htmlName.split(delimiter)[0];
        return htmlName.replace(/~/g, "_");
    },
    convertEndLink: function(id) {
        var endLink = $('#' + id);
        if (endLink.length == 0) return;
        var href = endLink.attr("href")
        var arrUrl = [href.substring(0, href.indexOf("?", 0)), href.substring(href.indexOf("?", 0) + 1, href.length)];
        endLink.addClass('none');

        var hasNavs = (this.footer1.find('input').length > 0)
        if (hasNavs) {
            this.content.children().addClass('none');
            $('.endText').parent().removeClass('none');
        } else {
            $('input').filter(':hidden').remove();
            this.form.attr('action', arrUrl[0]);
            this.form.attr('method', "get");
        }

        this.TIB.createPassback(href);

        if (arrUrl.length > 1) {
            var urlParams = arrUrl[1].split('&');
            for (var i = 0; i < urlParams.length; i++) {
                var nameValue = urlParams[i].split('=');
                this.TIB.addPassbackRow(nameValue);
                var inputTag = "<input type='hidden' name='" + nameValue[0] + "' value='" + unescape(nameValue[1]) + "' />";
                if (!hasNavs) this.form.append(inputTag);
            }
        }

        var mrButtonText = endLink.text();
        if (mrButtonText == '') mrButtonText = "Submit"
        var submitButton = "<input type='submit' id='endLinkButton' value='" + mrButtonText + "' />";
        submitButton = endLink.after(submitButton).next()
        if (!hasNavs)
            this.next = submitButton;
        else
            submitButton.prop('disabled', true);
    },
    setCursorInOpens: function() {
        if (cursorInOpens != 1) return;
        var textInputs = this.allInputs.filter('.mrEdit').filter(':visible');
        if (textInputs.length == 0) return;
        for (var i = 0; i < textInputs.length; i++) {
            var jInput = textInputs.eq(i); //get jquery object
            if (!jInput.attr("disabled")) { //make sure its not disabled
                if (jInput.attr("id").indexOf("_O") == -1) { //make sure not an other specify
                    try { //just in case an error is thrown
                        jInput.focus(); //try to add focus
                        window.scrollTo(0, 0); //scroll to top just in case text area is off screen
                    } catch (err) {
                        //die gracefully
                    }
                    return;
                }
            }
        }

    },
    /**
     * Gets the height of arbitrary text
     * @param {string} - Text value
     * @returns {integer} height
     */
    textHeight: function(value) {
        var html_calc = $('<span>' + $(value).html() + '</span>');
        html_calc.css('font-size', $(value).css('font-size')).hide();
        html_calc.prependTo('body');
        var height = html_calc.height();
        html_calc.remove();
        return height;
    },
    /**
     * Gets the width of arbitrary text
     * @param {string} - Text value
     * @returns {integer} height
     */
    textWidth: function(value) {
        var html_calc = $('<span>' + $(value).html() + '</span>');
        html_calc.css('font-size', $(value).css('font-size')).hide();
        html_calc.prependTo('body');
        var width = html_calc.width();
        html_calc.remove();
        return width;
    },
    /**
     * Gets the size of an image
     * @param {string} - Image src location
     * @returns {{width: number, height: number}}
     */
    imgSize: function(img) {
        var $img = $(img);
        if (typeof $img.attr('src') == 'undefined') return {
            'width': 0,
            'height': 0
        }
        if ($img.prop('naturalWidth') == undefined) {
            var $tmpImg = $('<img/>').attr('src', $img.attr('src'));
            $img.prop('naturalWidth', $tmpImg[0].width);
            $img.prop('naturalHeight', $tmpImg[0].height);
        }
        return {
            'width': $img.prop('naturalWidth'),
            'height': $img.prop('naturalHeight')
        }
    },
    /**
     * Gets image dimensions
     * @param imgsrc
     * @param usezoom
     * @param zoomscale
     * @param defwidth
     * @param defheight
     * @returns {{width: number, height: number}}
     */
    imageDimensions: function(imgsrc, usezoom, zoomscale, defwidth, defheight) {
        var w = 0,
            h = 0;
        var imgsz = pageLayout.imgSize(imgsrc); // get the native image size.

        if (usezoom) { // Check for zoomscale first.
            if (zoomscale !== null && !isNaN(zoomscale)) {
                w = imgsz.width * zoomscale;
                h = imgsz.height * zoomscale;
            } else {
                w = imgsz.width * surveyPage.options.zoomScale;
                h = imgsz.height * surveyPage.options.zoomScale;
            }
        } else { // If zoom isn't used then check defaultt nwidth/height - if not, the native image size is used.
            w = (defwidth != null && !isNaN(defwidth)) ? defwidth : w;
            h = (defheight != null && !isNaN(defheight)) ? defheight : h;
        }
        w = ((w <= 0) ? imgsz.width : w);
        h = ((h <= 0) ? imgsz.height : h);
        return {
            'width': w,
            'height': h
        };
    },
    v3Styles: function() {
        if (isstudio) {
            $(".tempNext").html("<img src='" + pageLayout.themePath + "images/Next.png' height='56'>");
            $(".tempPrev").html("<img src='" + pageLayout.themePath + "images/Prev.png' height='56'>");

            $(".tempNext").hover(
                function() {
                    $(this).html("<img src='" + pageLayout.themePath + "images/Hover.png' height='56'>");
                },
                function() {
                    $(this).html("<img src='" + pageLayout.themePath + "images/Next.png' height='56'>");
                }
            );
        }

        //MDB form styles
        this.img.addClass("img-responsive img-fluid waves-effect waves-light");
        this.allInputs.not("select").addClass("form-control");

        this.table.addClass("table table-bordered");

        this.allInputs.filter('select').addClass("mdb-select");
        this.allInputs.filter('textarea').attr("type", "text").attr("rows", "2").addClass("md-textarea");
        this.allInputs.filter('textarea').autogrow();

        this.allInputs.filter("input[type=radio]").addClass("with-gap");
        this.table.css("display", "table");
        this.table.find(".mrGridQuestionText, .mrGridCategoryText").css("width", "");

        $('.mdb-select').material_select();

        this.footer1.addClass("z-depth-1");
        this.footer2.addClass("z-depth-1");


        //Question deviders question text and question component
        var blockQuestionsCount = $('div.questionContainer').find('div.questionContainer').length;
        if (blockQuestionsCount > 0) {
            // This code for Block question
            $('div.questionContainer:eq(0) > .mrQuestionText').wrap('<div class="col-sm-12 question-text z-depth-1" style="margin-bottom: 1px;"></div>');
            questionsContainers = $('div.questionContainer > div.questionContainer');

            // Grouping first 4 elements as Question text elements and applying classes
            questionsContainers.each(function() {
                //Question text
                var a = $(this).children();
                for (var i = 0; i < 4; i += 4) {
                    a.slice(i, i + 4).wrapAll('<div class="col-sm-12 question-text z-depth-1"></div>');
                }
                //Question component
                for (var i = 4; i < a.length; i += a.length) {
                    a.slice(i, i + a.length).wrapAll('<div class="col-sm-12 question-component z-depth-1"></div>');
                }

                var questionFullName = $(this).attr('questionname');
                var questionNameArray = questionFullName.split(".");
                if (questionNameArray.length > 1) {
                    $(this).after('<div id="container_' + questionNameArray[1] + '" class="col-sm-12 z-depth-1"></div>');
                } else {
                    $(this).after('<div id="container_' + questionFullName + '" class="col-sm-12 z-depth-1"></div>');
                }
                $(this).after('<div id="container_' + questionFullName + '" class="col-sm-12 z-depth-1"></div>');

            });
        } else {
            questionsContainers = $('div.questionContainer');
            // Grouping first 4 elements as Question text elements and applying classes
            questionsContainers.each(function() {
                //Question text
                var a = $(this).children();
                for (var i = 0; i < 4; i += 4) {
                    a.slice(i, i + 4).wrapAll('<div class="col-sm-12 question-text z-depth-1"></div>');
                }
                //Question component
                for (var i = 4; i < a.length; i += a.length) {
                    a.slice(i, i + a.length).wrapAll('<div class="col-sm-12 question-component z-depth-1"></div>');
                }

                var questionName = $(this).attr('questionname');
                $(this).after('<div id="container_' + questionName + '" class="col-sm-12 z-depth-1"></div>');
            });
        }

        var vc = 0;
        $('input[iscode="true"]').each(function() {
            $(this).next('label').andSelf().wrapAll('<span id="Cell.0.' + vc + '" style=""></span>');
            vc++;
        });


        //Table styles
        this.table.find("tbody tr td").each(function() {
            var inputID = $(this).find('input').attr('id');
            $(this).append("<label for='" + inputID + "'></label>");
        });


        var multicolumn = false;
        if (typeof qJSON != 'undefined') {
            $.each(qJSON, function(index, json) {
                if (typeof json.CustomProps.metaType != 'undefined'||typeof json.CustomProps.flaMetaType != 'undefined') {
                    if (typeof json.CustomProps.metaType != 'undefined')
					 var metaTypeArray = (json.CustomProps.metaType.toLowerCase()).split(",");
					else if (typeof json.CustomProps.flaMetaType != 'undefined')
					 var metaTypeArray = (json.CustomProps.flaMetaType.toLowerCase()).split(",");
					
                    for (var j = 0; j < metaTypeArray.length; j++) {
                        if (metaTypeArray[j] == 'multicolumn') {
                            multicolumn = true;
                        }
                    }
                }
            });
        }

        if (!multicolumn) {
            this.defaultCategoricalRules();
        }




        var questions = this.questions;
        if (questions.find('input[type="radio"]:checked').length > 0) {
            questions.find('input[type="radio"]:checked + label, input[type="radio"]:not(:checked) + label').css({
                "color": "ddd"
            });
        }

        //Grid headers question error issue

        $('table tbody tr').each(function() {
            $errorSpan = $(this).find('td[rowspan][id^="Cell.0."] .mrQuestionText .mrErrorText').clone();
            $errorSpanLength = $(this).find('td[rowspan][id^="Cell.0."] .mrQuestionText .mrErrorText').length;
            if ($errorSpanLength > 0) {
                $(this).find('td[rowspan][id^="Cell.0."] .mrQuestionText .mrErrorText').remove();
                $(this).find('td[id^="Cell.1."] .mrQuestionText').prepend($errorSpan);
            }
        });

        $("td[id^='Cell.']").on('click', function(e) {
            if (($(this).find('input[iscode="true"]')).length < 1) {
                var checkbox = $(this).find("input[type='checkbox'][otherid='']");
                checkbox.prop("checked", !checkbox.prop("checked"));

                var radio = $(this).find("input[type='radio'][otherid='']");
                radio.prop("checked", true);

                var questionname = checkbox.attr('questionname');
                var isexclusive = checkbox.attr('isexclusive');
                // DK, None of these			
                if (isexclusive == "true") {
                    console.log('checkbox - isexclusive');
                    questions.find('input[type="checkbox"][questionname="' + questionname + '"]:not([isexclusive="true"])').attr('checked', false);
                    questions.find('input[type="checkbox"][questionname="' + questionname + '"]:not([isexclusive="true"])').prop('checked', false);
                    questions.find('input[type="text"][otherinput="true"]').val('');
                } else {
                    questions.find('input[type="checkbox"][questionname="' + questionname + '"][isexclusive="true"]').attr('checked', false);
                    questions.find('input[type="checkbox"][questionname="' + questionname + '"][isexclusive="true"]').prop('checked', false);
                }
            }
        });



        questions.find("input[type='radio']").change(function() {
            var questionname = $(this).attr('questionname');
            questions.find('input[type="radio"][questionname="' + questionname + '"]:checked + label').css({
                "color": "#ddd"
            });
            questions.find('input[type="radio"][questionname="' + questionname + '"]:not(:checked) + label').css({
                "color": "#ddd"
            });
            var otherid = $(this).attr('otherid');
            if (otherid == "") {
                questions.find('input[type="text"][questionname^="' + questionname + '"][otherinput="true"]').val('');
            }

        });

        questions.find("input[type='checkbox']").change(function() {
            //console.log('checkbox');
            var questionname = $(this).attr('questionname');
            var isexclusive = $(this).attr('isexclusive');
            // DK, None of these			
            if (isexclusive == "true") {
                console.log('checkbox - isexclusive');
                questions.find('input[type="checkbox"][questionname="' + questionname + '"]:not([isexclusive="true"])').attr('checked', false);
                questions.find('input[type="checkbox"][questionname="' + questionname + '"]:not([isexclusive="true"])').prop('checked', false);
                questions.find('input[type="text"][otherinput="true"]').val('');
            } else {
                questions.find('input[type="checkbox"][questionname="' + questionname + '"][isexclusive="true"]').attr('checked', false);
                questions.find('input[type="checkbox"][questionname="' + questionname + '"][isexclusive="true"]').prop('checked', false);
            }
        });


        //Other question logic

        $("input[type='text'][otherinput='true']").keyup(function() {
            var inputlen = $(this).val();
            var otherid = $(this).attr('id');
            var questionNameArray = $(this).attr('questionname').split(".");
            questionNameArray.pop();
            var questionName = questionNameArray.join('.');
            if (inputlen.length > 0) {
                $("input[questionname='" + questionName + "'][otherid='" + otherid + "']").prop('checked', true);
                $("input[questionname='" + questionName + "'][otherid='" + otherid + "']").attr('checked', true);
                $("input[questionname='" + questionName + "'][isexclusive='true']").prop('checked', false);
                $("input[questionname='" + questionName + "'][isexclusive='true']").attr('checked', false);
            } else {
                $("input[questionname='" + questionName + "'][otherid='" + otherid + "']").prop('checked', false);
                $("input[questionname='" + questionName + "'][otherid='" + otherid + "']").attr('checked', false);
            }
        });


        var blockQuestionsCount = $('div.questionContainer').find('div.questionContainer').length;
        if (blockQuestionsCount > 0) {
            eachQuestion = $('div.questionContainer > div.questionContainer');
        } else {
            eachQuestion = $('div.questionContainer');
        }

        eachQuestion.each(function() {

            //Inputs placeholders
            var ph = $(this).find(".mrQuestionText span[ph]").attr('ph');
            if (typeof ph != "undefined") {
                $(this).find("input[type=date], input[type=datetime-local], input[type=email], input[type=number], input[type=password], input[type=search-md], input[type=tel], input[type=text]:not(input[type='text'][otherinput='true']), input[type=time], input[type=url], textarea.md-textarea").each(function() {
                    $(this).attr("placeholder", ph);
                });
            }

            //Inputs MD inside labels
            var ilabel = $(this).find(".mrQuestionText span[ilabel]").attr('ilabel');
            if (typeof ilabel != "undefined") {
                $(this).find("input[type=date], input[type=datetime-local], input[type=email], input[type=number], input[type=password], input[type=search-md], input[type=tel], input[type=text]:not(input[type='text'][otherinput='true']), input[type=time], input[type=url], textarea.md-textarea").each(function() {
                    $(this).wrap('<div class="md-form"></div>');
                    $(this).after("<label for='" + $(this).attr('id') + "'>" + ilabel + "</label>");
                });
            }

            // numerickeypad layout feature
            var numerickeypad = $(this).find(".mrQuestionText span[numerickeypad]").attr('numerickeypad');
            if (numerickeypad == 'true') {
                $(this).find("input[type='text']").attr("type", "number");
            }

        });



        // Image zoom code for Global level

        if ($(".imagezoom").length > 0) {
            $('form').after('<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true"><div class="pswp__bg"></div><div class="pswp__scroll-wrap"><div class="pswp__container"><div class="pswp__item"></div><div class="pswp__item"></div><div class="pswp__item"></div></div><div class="pswp__ui pswp__ui--hidden"><div class="pswp__top-bar"><div class="pswp__counter"></div><button class="pswp__button pswp__button--close" title="Close (Esc)"></button><button class="pswp__button pswp__button--share" title="Share"></button><button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button><button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button><div class="pswp__preloader"><div class="pswp__preloader__icn"><div class="pswp__preloader__cut"><div class="pswp__preloader__donut"></div></div></div></div></div><div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap"><div class="pswp__share-tooltip"></div></div><button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)"></button><button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"></button><div class="pswp__caption"><div class="pswp__caption__center"></div></div></div></div></div>');

            $('.imagezoom').each(function() {
                $(this).css('position', 'relative').find('img').css({
                    'display': 'inline',
                    'margin': '15px 15px 0px 0px'
                }).after('<span class="imgZoom theme-font-color" style="position: absolute; right: 0px; cursor: pointer; padding: 2px;"><i class="fa fa-search-plus" aria-hidden="true"></i></span>');
            });

            // build items array
            var items = [];
            var that = this;

            $("body").on("click", ".imgZoom", function(e) {
                e.stopPropagation();
                e.preventDefault();
                items = [];
                items.length = 0;
                var img = new Image();
                img.src = $(this).parent().find("img").attr('src');
                items.push({
                    src: $(this).parent().find("img").attr('src'),
                    w: img.width,
                    h: img.height
                });
                var pswpElement = document.querySelectorAll('.pswp')[0];
                var options = {
                    history: false,
                    focus: false,
                    shareEl: false,
                    showAnimationDuration: 0,
                    hideAnimationDuration: 0
                };
                var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options);
                gallery.init();
            });
        }


        if ($("[data-toggle='popover']").length > 0) {
            $('[data-toggle="popover"]').html("").css({
                "display": "inline",
                "margin": "5px 10px"
            }).append('<i class="fa fa-info-circle fa-1x theme-font-color" aria-hidden="true"></i>');


            var cssPath = this.sharedContent + "LAF/Lib/css/1.0/jquery.webui-popover.min.css";

            var pLayout = this;

            var link = document.createElement('link');
            link.rel = 'stylesheet';
            link.type = 'text/css';
            link.href = cssPath;
            link.addEventListener('load', pLayout.postLoadCss);
            document.head.appendChild(link);

        }

        //Jagged hidden elements
        this.allInputs.each(function(index) {
            if (this.style.visibility == 'hidden') {
                $(this).next('label').css("visibility", "hidden");
            }
        });

    },
    applyThemes: function() {
        $(".question-text").addClass("theme-standard-bg-color2 theme-standard-font-color1");
        $(".nextNavButton").addClass("theme-bg-color");
        $(".previousNavButton ").addClass("theme-standard-bg-color2 theme-standard-font-color1");
        var footerNavNext = $(".nextNavButton").find("a");
        footerNavNext.addClass("theme-standard-font-color3 hoverable");
        footerNavNext.hover(function() {
            $(this).removeClass("theme-standard-font-color3").addClass("theme-standard-font-color1");
        }, function() {
            $(this).removeClass("theme-standard-font-color1").addClass("theme-standard-font-color3");
        });

        var footerNavPrev = $(".previousNavButton").find("a");
        footerNavPrev.addClass("theme-standard-font-color1 hoverable");

        var footerMenuButton = this.footer2.find("a.menuButton, .tempMenuButtons .dropup .dropdown-menu a");
        footerMenuButton.addClass("theme-standard-font-color1");

        this.footer2.find("a.menuButton i").addClass("hoverable");
        this.footer2.find(" .tempMenuButtons .dropup .dropdown-menu a").addClass("hoverable");
    },
    postLoadCss: function() {
        var scriptPath = pageLayout.sharedContent + "LAF/Lib/js/1.0/jquery.webui-popover.min.js";
        var script = document.createElement('script');
        script.src = scriptPath;
        script.addEventListener('load', pageLayout.postLoadJS);
        document.head.appendChild(script);
    },
    postLoadJS: function() {

        $("[data-toggle='popover']").webuiPopover();

        $("body").on("mousedown touchstart", "[data-toggle='popover']", function() {
            $(this).webuiPopover();
        });

        /*
        Default options
        {
        	placement:'auto',//values: auto,top,right,bottom,left,top-right,top-left,bottom-right,bottom-left,auto-top,auto-right,auto-bottom,auto-left,horizontal,vertical
        	container: document.body,// The container in which the popover will be added (i.e. The parent scrolling area). May be a jquery object, a selector string or a HTML element. See https://jsfiddle.net/1x21rj9e/1/
        	width:'auto',//can be set with  number
        	height:'auto',//can be set with  number
        	trigger:'click',//values:  click,hover,manual(handle events by your self),sticky(always show after popover is created);
        	selector:false,// jQuery selector, if a selector is provided, popover objects will be delegated to the specified. 
        	style:'',// Not to be confused with inline `style=""`, adds a classname to the container for styling, prefixed by `webui-popover-`. Default '' (light theme), 'inverse' for dark theme
        	animation:null, //pop with animation,values: pop,fade (only take effect in the browser which support css3 transition)
        	delay: {//show and hide delay time of the popover, works only when trigger is 'hover',the value can be number or object
        		show: null,
        		hide: 300
        	},
        	async: {
        		type:'GET', // ajax request method type, default is GET
        		before: function(that, xhr) {},//executed before ajax request
        		success: function(that, data) {}//executed after successful ajax request
        		error: function(that, xhr, data) {} //executed after error ajax request
        	},
        	cache:true,//if cache is set to false,popover will destroy and recreate
        	multi:false,//allow other popovers in page at same time
        	arrow:true,//show arrow or not
        	title:'',//the popover title, if title is set to empty string,title bar will auto hide
        	content:'',//content of the popover,content can be function
        	closeable:false,//display close button or not
        	direction:'', // direction of the popover content default is ltr ,values:'rtl';
        	padding:true,//content padding
        	type:'html',//content type, values:'html','iframe','async'
        	url:'',//if type equals 'html', value should be jQuery selecor.  if type equels 'async' the plugin will load content by url.
        	backdrop:false,//if backdrop is set to true, popover will use backdrop on open
        	dismissible:true, // if popover can be dismissed by  outside click or escape key
        	autoHide:false, // automatic hide the popover by a specified timeout, the value must be false,or a number(1000 = 1s).
        	offsetTop:0,  // offset the top of the popover
        	offsetLeft:0,  // offset the left of the popover
        	onShow: function($element) {}, // callback after show
        	onHide: function($element) {}, // callback after hide
        }*/
    },
    defaultCategoricalRules: function() {
        //Categorical question
        var cells = this.questions.find("span[id^='Cell.']");
        if (cells.length == 1 || cells.length == 2) {
            cells.each(function() {
				if (navigator.appVersion.indexOf("MSIE 10") !== -1) {
					$(this).wrap('<div class="col-xs-12 col-border"></div>');
				}else{
					$(this).wrap('<div class="col-xs-12 col-border waves-effect waves-light"></div>');
				}
                //Other question style
                if ($(this).children('input').attr("otherid") != "") {
                    $(this).parent().removeClass("col-md-4 col-sm-6");
                    var otherText = ($(this).find('label').eq(0).text()).trim();
                    $(this).find('span').addClass('col-xs-12');
                    $(this).find('label').html("").attr('style', 'display: none !important;');
                    $(this).find('input[type="text"][otherinput="true"]').wrap('<div class="md-form"></div>');
                    var otherTextId = $(this).find('input[type="text"]').attr('id');
                    $(this).find('input[type="text"]').after("<label for='" + otherTextId + "'>" + otherText + "</label>");
                    $(this).find('.md-form label').attr('style', 'text-align:left;');
                }
                if ($(this).children('input').attr("isexclusive") == "true") {
                    $(this).parent().removeClass("col-md-4 col-sm-6");
                }
            });
        }
        if (cells.length > 2) {
            cells.each(function() {
				if (navigator.appVersion.indexOf("MSIE 10") !== -1) {
					$(this).wrap('<div class="col-md-4 col-sm-6 col-xs-12 col-border"></div>');
				}else{
					$(this).wrap('<div class="col-md-4 col-sm-6 col-xs-12 col-border waves-effect waves-light"></div>');
				}   
                //Other question style
                if ($(this).children('input').attr("otherid") != "") {
                    $(this).parent().removeClass("col-md-4 col-sm-6");
                    var otherText = ($(this).find('label').eq(0).text()).trim();
                    $(this).find('span').addClass('col-xs-12');
                    $(this).find('label').html("").attr('style', 'display: none !important;');
                    $(this).find('input[type="text"][otherinput="true"]').wrap('<div class="md-form"></div>');
                    var otherTextId = $(this).find('input[type="text"]').attr('id');
                    $(this).find('input[type="text"]').after("<label for='" + otherTextId + "'>" + otherText + "</label>");
                    $(this).find('.md-form label').attr('style', 'text-align:left;');
                }
                if ($(this).children('input').attr("isexclusive") == "true") {
                    $(this).parent().removeClass("col-md-4 col-sm-6");
                }
            });

            var blockQuestionsCount = $('div.questionContainer').find('div.questionContainer').length;
            if (blockQuestionsCount > 0) {
                questionsContainers = $('div.questionContainer > div.questionContainer');
                questionsContainers.each(function() {
                    if (($(this).find('.col-border input[iscode="true"]')).length < 1) {
                        $(this).find(".col-border").wrapAll("<div class='flex-row row'></div>");
                    }
                });
            } else {
                questionsContainers = $('div.questionContainer');
                questionsContainers.each(function() {
                    if (($(this).find('.col-border input[iscode="true"]')).length < 1) {
                        $(this).find(".col-border").wrapAll("<div class='flex-row row'></div>");
                    }
                });
            }

            //this.questions.find(".col-border").wrapAll("<div class='flex-row row'></div>");
        }
    },
    applyRTLStyle: function() {
        $('.container').attr("dir", "rtl");
        var temp = $(".previousNavButton").detach();
        temp.insertAfter(".nextNavButton");

        var temp1 = $(".tempMenuButtons").detach();
        temp1.insertAfter(".logo");
        $(".tempMenuButtons").removeClass("text-xs-left").addClass("text-xs-right");
        $(".dropdown-menu").removeClass(" dropdown-menu-left").addClass("dropdown-menu-right");
    }
}

/**
 * Any errors in with the Engine will be handled here
 */
function handleSurveyEngineError(error, callback) {
    $.event.trigger({
        type: 'SurveyEngineEvent',
        eventType: 'engine_error',
        message: 'There was an error: ' + error.message
    });
    var msg = engErrorMessage + "\n\nError message: " + error.message;
    var htmlMsg = "<p class='mrErrorText'><br/>" + msg.replace('\n', '<br/>') + "</p>";
    if (!revertToHTML) {
        $('form').hide();
        $('body').prepend(htmlMsg);
        alert(msg);
    } else {
        if (callback !== null) callback()
    }
    console.log(msg);
    return false;
}


// Textarea auto resize event
$.fn.autogrow = function() {
    return this.each(function() {
        var textarea = this;
        $.fn.autogrow.resize(textarea);
        $(textarea).focus(function() {
            textarea.interval = setInterval(function() {
                $.fn.autogrow.resize(textarea);
            }, 200);
        }).blur(function() {
            clearInterval(textarea.interval);
        });
    });
};
$.fn.autogrow.resize = function(textarea) {
    var lineHeight = parseInt($(textarea).css('line-height'), 8);
    var lines = textarea.value.split('\n');
    var columns = textarea.cols;
    var lineCount = 0;
    $.each(lines, function() {
        lineCount += Math.ceil(this.length / columns) || 1;
    });
    var height = lineHeight * (lineCount + 1);
    $(textarea).css('height', height);
};

// RTL Functions

function checkRTL(fileName) {
    var found = false;
    var headString = ($("head").html()).toString();
    var n = headString.search(fileName);
    if (0 < n) {
        found = true;
    }
    return found;
}




function loadModel(callback, context) {
    callback.apply(context)
    return
}


var testPanel = function(tester) {
    this.isTest = tester;
    this.infoSource = pageLayout.infoSource;
    this.banner = $('<div>').attr("id", "testPanel").css('display', 'none');
    this.panelModal = $('<div class="modal fade" id="testModal" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"><div class="modal-dialog" role="document"><div class="modal-content"><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button><h4 class="modal-title" id="myModalLabel">Interview Details</h4></div><div class="modal-body" id="modalBody"></div></div></div></div>');

    this.passback = null;
};
testPanel.prototype = {
    init: function() {
        loadModel(this.build, this);
    },
    build: function() {
        var that = this;
        if (this.isTest) this.show();
        var innerTest = $('<div>').attr("id", "innerTest").addClass("theme-bg-color ").text("Test - v" + projectVersion);
        this.banner.append(innerTest).appendTo("body");
        this.panelModal.appendTo("body")
        this.modal = $('#modalBody');
        this.modal.append(this.createProjectDetails());
        this.modal.append(this.infoSource.find('#passbackTable'));
        this.modal.append(this.processQuotas());
        this.modal.append(this.processImageErrors(innerTest));
        this.modal.append(this.processRoutingErrors(innerTest));
        var testTables = this.modal.find('.testTable');
        testTables.removeClass('none');
        this.rowHighlight(testTables.find('tr'));
        innerTest.click(function() {
            that.panelModal.modal('toggle')
        });
        if (innerTest.find('.errorCount').length)
            innerTest.removeClass('theme-bg-color').addClass('animated shake errorBackground');
    },
    hide: function() {
        this.banner.hide();
    },
    show: function() {
        this.banner.show();
    },
    rowHighlight: function(jRows) {
        jRows.hover(function() {
            $(this).addClass('rowHighlight')
        }, function() {
            $(this).removeClass('rowHighlight')
        });
    },
    processImageErrors: function(notifyContainer) {
        var that = this;
        var errorContainer = this.infoSource.find('#imageErrorsURLs')
        if (errorContainer.length == 0) return;
        var imageErrors = errorContainer.text().split(",");
        if (imageErrors.length) {
            var errorCount = imageErrors.length;
            if (isstudio) {
                var errorNotify = $(' <img> ').attr("src", pageLayout.themePath + "images/image.png").css({
                    "float": "left",
                    "width": "20px"
                });
            } else {
                var errorNotify = $(' <i> ').addClass("fa fa-file-image-o").attr("aria-hidden", "true").css('float', 'left');
            }
            notifyContainer.append(errorNotify);
            notifyContainer.append($('<span>').addClass('errorCount').text(errorCount).css('margin-left', '5px'));

            var imageErrorTable = this.createTestTable('imageErrors', 'Image Errors');
            imageErrorTable.append(this.createRowHead('th', ['Location']));
            $(imageErrors).each(function() {
                imageErrorTable.append(that.createRow('td', [this]));
            });

            return imageErrorTable;
        }
    },
    createProjectDetails: function() {
        var projectDetailsTable = this.createTestTable('projectDetails', 'Respondent Details');
        projectDetailsTable.append(this.createRowHead('th', ['Object', 'Value']));
        projectDetailsTable.append(this.createRow('td', ['Project', projectName + " v" + projectVersion]));
        projectDetailsTable.append(this.createRow('td', ['Server', location.host]));
        projectDetailsTable.append(this.createRow('td', ['Serial', serial]));
        projectDetailsTable.append(this.createRow('td', ['PID', id]));
        projectDetailsTable.append(this.createRow('td', ['comp', '{' + comp + '}']));
        projectDetailsTable.append(this.createRow('td', ['Debug', isDebug]));
        var savePoint = $('input[name="I\.SavePoint"]');
        projectDetailsTable.append(this.createRow('td', ['Question', ((savePoint.length > 0) ? savePoint.val() : "End Screen")]));
        return projectDetailsTable;
    },
    processQuotas: function() {
        var jQuotas = $('#quotaPath');
        if (jQuotas.length == 0) return;
        var quotaTables = $('<div>');
        var quotaPaths = jQuotas.text().split("~");
        for (var i = 0; i < quotaPaths.length; i++) {
            var quotas = quotaPaths[i].split(';');
            quotas.pop();
            if (quotas.length) {
                var caption = '';
                if (quotaPaths.length > 1) caption = (i == 0) ? "Initial " : i + 1 + " ";
                var quotaTable = this.createTestTable('quotaPathTable', caption + 'Quota Path');
                quotaTable.append(this.createRowHead('th', ['Quota Group', 'Pass', 'Variable={checked values}->{result values}']));
                for (var x = 0; x < quotas.length; x++) {
                    var pattern = /(.*)\((.*)\)\[(.*)\]/;
                    var qGroup = quotas[x].replace(pattern, "\$1");
                    var qPass = quotas[x].replace(pattern, "\$2");
                    var variableValues = quotas[x].replace(pattern, "\$3").replace(/:/g, " = ").replace(/\},/g, "}<br/>");
                    var quotaRow = this.createRow('td', [qGroup, qPass, variableValues])
                    if (qPass.toLowerCase() == "false") quotaRow.addClass('quotaFail');
                    quotaTable.append(quotaRow)
                }
                quotaTables.append(quotaTable);
            }
        }
        return quotaTables;
    },
    processRoutingErrors: function(notifyContainer) {
        var routingErrors = $('.routingError');
        var that = this;
        if (routingErrors.length) {
            if (isstudio) {
                var errorNotify = $(' <img> ').attr("src", pageLayout.themePath + "images/alert.png").css({
                    "float": "left",
                    "width": "20px"
                });
            } else {
                var errorNotify = $(' <i> ').addClass("fa fa-exclamation-triangle").attr("aria-hidden", "true").css('float', 'left');
            }
            notifyContainer.append(errorNotify);
            notifyContainer.append($('<span>').addClass('errorCount').text(routingErrors.length).css('margin-left', '5px'));
            var errorsTable = this.createTestTable('errorsTable', 'Routing Errors');
            errorsTable.append(this.createRowHead('th', ['Last Question', 'Line #', 'Additional Info', 'Error Message']));
            routingErrors.each(function() {
                errorsTable.append(that.createRow('td', this.innerHTML.split("::")))
            });
            return errorsTable;
        }
    },
    createRow: function(type, cells) {
        if (cells.length > 0) {
            var tempRow = $('<tr>');
            for (var i = 0; i < cells.length; i++)
                tempRow.append($('<' + type + '>').html(cells[i]));
            return tempRow;
        } else {
            return null;
        }
    },
    createRowHead: function(type, cells) {
        if (cells.length > 0) {
            var tempRow = $('<tr>');
            for (var i = 0; i < cells.length; i++)
                tempRow.append($('<' + type + '>').html(cells[i]));
            var tempHead = $('<thead>').addClass("theme-bg-color").append(tempRow);
            return tempHead;
        } else {
            return null;
        }
    },
    createTestTable: function(id, caption) {

        var tempTable = $('<table>').attr('id', id).addClass('testTable table table-bordered table-responsive').addClass('none').css("display", "table");
        if (typeof(caption) != 'undefined') {
            var tempCaption = $('<caption>').html(caption);
            tempTable.append(tempCaption);
        }
        return tempTable;
    },
    createPassback: function(link) {
        this.passback = this.createTestTable('passbackTable', "Passback<br/><div class='linkShow'>" + link + "</div>");
        this.passback.append(this.createRowHead('th', ['Parameter', 'Value']));
        this.passback.append(this.createRow('td', ['<b>base URL</b>', link.split("?")[0] + '?']));
        this.infoSource.append(this.passback);
    },
    addPassbackRow: function(arrParam) {
        this.passback.append(this.createRow('td', arrParam));
    }
}