<commit_before>DataExplorer.QueryEditor = (function () {
    var editor, field, query,
        options = {
            'mode': 'text/x-t-sql'
        };

    function exists() {
        return !!editor || !!query;
    }

    function create(target, callback) {
        if (typeof target === 'string') {
            target = $(target);
        }

        if (!target.length) {
            return;
        }

        field = target;
        target = target[0];

        if (target.nodeName === 'TEXTAREA') {
            function run() {
                field.closest('form').submit();
            }

            editor = CodeMirror.fromTextArea(target, $.extend({}, options, {
                'lineNumbers': true,
                'extraKeys': {
                    'Ctrl-Enter': run,
                    'F5': run
                }
            }));
        } else {
            query = target[_textContent];
            editor = CodeMirror.runMode(query, options.mode, target);
        }

        if (callback && typeof callback === 'function') {
            callback(editor);
        }
    }

    function getValue() {
        if (!exists()) {
            return null;
        }

        if (query) {
            return query;
        }

        var value = editor.getValue();

        // Strip zero-width that randomly appears when copying text from the current
        // Data Explorer query editor into this one, at least until I can figure out
        // where it's coming from.
        if (value.charCodeAt(value.length - 1) === 8203) {
            value = value.substring(0, value.length - 1);
        }

        // Explicitly update the field, since CodeMirror might not have gotten a
        // chance to yet
        field.val(value);

        return value;
    }

    return {
        'create': create,
        'value': getValue,
        'exists': exists
    };
})();

DataExplorer.ready(function () {
    var schema = $('#schema'),
        history = $('#history'),
        panel = $('#editor-panel'),
        metadata = $('#query-metadata .info'),
        error = $('#error-message'),
        form = $('#runQueryForm');

    DataExplorer.QueryEditor.create('#queryBodyText');
    DataExplorer.QueryEditor.create('#sql', function (editor) {
        var wrapper;

        DataExplorer.Sidebar.init({
            editorTheme: editor.getOption('theme'),
            panel: panel,
            toolbar: '#editor-toolbar'
        });

        if (editor) {
            wrapper = $(editor.getScrollerElement());
        }

        function resizePanel(available) {
            var remaining = available - history.outerHeight(),
                list = schema.children('ul'),
                offset = schema.outerHeight() - list.height();

            list.height(remaining - offset);
            DataExplorer.TableHelpers.resize((available - offset) + 9);

            if (wrapper) {
                offset = wrapper.closest('.CodeMirror').outerHeight() - wrapper.height();

                wrapper.height(available - offset);
                editor.refresh();
            }
        }

        // Set this resizer up after because the grippie adds height to the
        // sidebar that we need to factor in
        $('#editor').TextAreaResizer(resizePanel, {
            'useParentWidth': true,
            'resizeWrapper': true,
            'minHeight': 300,
            'initCallback': true
        });
    });

    $('.miniTabs').tabs(false);

    form.submit(function () {
        $('.report-option').hide();
        error.hide();

        var cleanup = function () {
            $('#loading').hide();

            form.find('input, button').prop('disabled', function () {
                return this.id == 'cancel-query';
            });
        };

        var fail = function() {
            showError({ 'error': "Something unexpected went wrong while running "
                            + "your query. Don't worry, blame is already being assigned." });
        };

        var cancel = function () {
            showError({ 'error': 'Query execution has been cancelled' }, 'notice');
        }

        var pending = { request: null, timeout: null, setupCancel: true };
        var success = function(response) {
            if (response.running === true)
            {
                var poll = function () {
                    pending.timeout = setTimeout(function(){
                        pending.request = $.ajax({
                            'type': 'GET',
                            'url': '/query/job/' + response.job_id,
                            'success': success,
                            'error': [cleanup, fail],
                            'cache': false
                        });
                    }, 1500);
                };

                if (!pending.timeout && pending.setupCancel) {
                    var job = response.job_id;
                    pending.setupCancel = false;

                    $('#cancel-query').one('click', function () {
                        this.disabled = true;

                        clearTimeout(pending.timeout);

                        if (pending.request) {
                            pending.request.abort();
                        }

                        $.ajax({
                            type: 'POST',
                            url:  '/query/job/' + job + '/cancel',
                            success: function (response) {
                                if (response.cancelled) {
                                    cleanup();
                                    cancel();
                                } else {
                                    // There were some results, so we're going to try and get whatever
                                    // was being returned when the user decided to cancel
                                    poll();
                                }
                            },
                            error: [cleanup, fail],
                            cache: false
                        });
                    }).prop('disabled', false);
                }

                poll();
            }
            else
            {
                cleanup();
                parseQueryResponse(response);
            }
        };

        if (verifyParameters()) {
            var data = form.serialize();
            form.find('input, button').prop('disabled', true);

            $('#loading').show();

            $.ajax({
                'type': 'POST',
                'url': this.action,
                'data': data,
                'success': success,
                'error': [cleanup, fail],
                'cache': false,
            });
        }

        return false;
    });

    $('#query-options').find('input, select').each(function () {
        var value = window.location.param('opt.' + this.name);

        if (value) {
            if (this.type === 'checkbox') {
                this.checked = value;
            } else {
                this.value = value;
            }
        }
    });

    $('#query-results').bind('show', function (event) {
        $('.download-button', this).hide();
        $(event.target.href.from('#') + 'Button').show();
    });

    $('#executionPlanTab').click(function () {
        QP.drawLines();
    });

    // Ideally we can separate out the actual displaying bits so that the user
    // doesn't have to click the button before getting the form.
    function verifyParameters() {
        var sql = null;

        // Ugh, this is ugly, need to rework this soon
        if (DataExplorer.QueryEditor.exists()) {
            sql = DataExplorer.QueryEditor.value();
        } else {
            // This is a pretty big assumption
            sql = $('#queryBodyText').text();
        }

        if (!sql) {
            return false;
        }

        var parameters = new DataExplorer.ParameterParser.parse(sql, {
            multilineStrings: true,
            multilineComments: true,
            stringEscapeCharacter: "'",
            nestedMultilineComments: true
        });

        var complete = true,
            wrapper = document.getElementById('query-params'),
            fieldList = wrapper.getElementsByTagName('input'),
            fields = {},
            field, name, label, row, value, hasValue, key, first;

        $(wrapper).toggle(!!parameters.length);

        for (var i = fieldList.length - 1; i > -1 ; --i) {
            field = fieldList.item(i);
            value = field.getAttribute('value');
            name = field.name;

            if (field.value && field.value.length /*&& value != field.value*/) {
                fields[name] = field.value;
            }

            field.parentNode.parentNode.removeChild(field.parentNode);
        }

        for (var i = 0; i < parameters.length; ++i) {
            label = document.createElement('label');
            label.htmlFor = 'dynParam' + i;
            label[_textContent] = parameters[i].label || parameters[i].name;

            if (parameters[i].description) {
                label.title = parameters[i].description;
            }

            value = fields[parameters[i].name];
            hasValue = !(!value && value !== 0);

            if (!hasValue) {
                value = window.location.param(parameters[i].name);
                hasValue = !(!value && value !== 0);
            }

            if (!hasValue) {
                value = parameters[i].auto;
                hasValue = !(!value && value !== 0);
            }

            if (!hasValue && parameters[i].name.toLowerCase() === 'userid') {
                if (DataExplorer.options.User.isAuthenticated && DataExplorer.options.User.guessedID) {
                    hasValue = true;
                    value = DataExplorer.options.User.guessedID;
                }
            }

            if (complete) {
                complete = hasValue;
            }

            field = document.createElement('input');
            field.name = parameters[i].name;
            field.id = 'dynParam' + i;
            field.type = 'text';

            if (hasValue) {
                field.setAttribute('value', value);
            } else if (!first) {
                first = field;
            }

            row = document.createElement('div');
            row.className = 'form-row';
            row.appendChild(label);
            row.appendChild(field);

            wrapper.appendChild(row);
        }

        if (!complete && first) {
            first.focus();
        }

        return complete;
    }

    function parseQueryResponse(response) {
        if (showError(response) || showCaptcha(response)) {
            return;
        }

        var action = form[0].action,
            records = 0,
            results,
            slug = response.slug,
            params = $('#query-params input[type="text"]').serialize(),
            textOnly = false,
            userid;

        if (params) {
            params = params.replace(/(^|&)UserId=(\d+)(&|$)/i, function (match, g1, g2, g3) {
                userid = g2;

                return g1 ? g3 : "";
            });

            if (params.length) {
                params = '?' + params;
            } else {
                params = null;
            }
        }

        if (/[^\d]\/\d+$/.test(action)) {
            form[0].action = action + '/' + response.querySetId;
        }

        if (response.resultSets.length) {
            results = response.resultSets[0];
            records = results.rows.length;
        } else {
            textOnly = true;
            response.resultSets = null;
        }

        document.getElementById('messages').children[0][_textContent] = response.messages;

        if (!slug && !/\/[^\/]+\/query\/new/.test(window.location.pathname) && /.*?\/[^\/]+$/.test(window.location.pathname)) {
            slug = window.location.pathname.substring(window.location.pathname.lastIndexOf('/'));

            if (/\d+/.test(slug)) {
                slug = null;
            }
        } else if (slug && slug.indexOf('/') !== 0) {
            slug = '/' + slug;
        }

        DataExplorer.template('#execution-stats', 'text', {
            'records': textOnly ? "Results" : records + " rows",
            'time': response.executionTime === 0 ? "<1" : response.executionTime,
            'cached': response.fromCache ? ' (cached)' : ''
        });

        var target = "";
        if (response.targetSites == 1) { target = "all-"; } // all sites
        else if (response.targetSites == 2) { target = "all-meta-"; } // all meta sites
        else if (response.targetSites == 3) { target = "all-non-meta-"; } // all non meta sites
        else if (response.targetSites == 4) { target = "all-meta-but-mse-"; } // all meta sites except mse
        else if (response.targetSites == 5) { target = "all-non-meta-but-so-"; } // all non meta sites except so

        var options;

        $('#query-options').find('input, select').each(function () {
            var value;

            if (this.type === 'checkbox') {
                if (this.checked) {
                    value = true;
                }
            } else {
                value = this.value;

                // If this is a select and the selected option is set in the HTML as the default one,
                // there's no sense in appending it to the query string
                if (this.tagName == 'SELECT' && this.options[this.selectedIndex].getAttribute('selected') !== null) {
                    value = null;
                }
            }

            if (value) {
                options = (options ? options + '&' : '') + 'opt.' + this.name + '=' + encodeURIComponent(value);
            }
        });

        if (options) {
            params = (params ? params + '&' : '?') + options;
        }

        var formatOptions = {
            'targetsites': target,
            'site': response.siteName,
            'revisionid': response.revisionId,
            'slug': slug,
            'params': params,
            'id' : response.querySetId
        };

        DataExplorer.template('a.templated.site', 'href', formatOptions);
        DataExplorer.SiteSwitcher.update(formatOptions);

        if (userid) {
            formatOptions.params = (params ? params + '&' : '?') + 'UserId=' + userid;
        }

        DataExplorer.template('a.templated:not(.site), a.templated.related-site', 'href', formatOptions);

        if (DataExplorer.Sidebar) {
            DataExplorer.Sidebar.updateHistory(response);
        }

        response.graph = !textOnly && DataExplorer.Graph.isGraph(results);

        $('#query-results .miniTabs a.optional').each(function () {
            $(this).toggleClass('hidden', !response[this.hash.substring(1)]);
        });

        // We have to start showing the contents so that SlickGrid can figure
        // out the heights of its components correctly
        $('.result-option').fadeIn('fast').promise().done(function () {
            var tabset = $('#query-results .miniTabs a').off('show'),
                firstTab = tabset.filter(':not(.hidden):first'),
                selectedTab;

            if (window.location.hash) {
                selectedTab = $(window.location.hash + 'Tab');

                if (!selectedTab.length || selectedTab.hasClass('hidden')) {
                    selectedTab = null;
                }
            }

            if (response.graph) {
                var graph = new DataExplorer.Graph(results, '#graph');

                tabset.on('show', function (event, panel) {
                    if (panel === '#graph' && !graph.isInitialized()) {
                        graph.show();
                    }
                });
            }

            var permalink = $('#permalink a')[0];

            if (permalink) {
                tabset.off('click.permalink');
                tabset.on('click.permalink', function () {
                    // We should probably be using the formatter here, but for now we'll
                    // just hack around it because this whole mess needs tidying anyway
                    permalink.href = permalink.href.replace(/#.*$/, '') + (this != firstTab[0] ? this.hash : '');
                });
            }

            if (response.executionPlan && QP && typeof QP.drawLines === 'function') {
                $('#executionPlan').html(response.executionPlan);
            }

            if (!textOnly) {
                var grid = new DataExplorer.ResultSet(results, response.url, '#resultSets');

                tabset.on('show', function (event, panel) {
                    if (panel === '#resultSets' && !grid.isInitialized()) {
                        grid.show();
                    }
                });
            }

            if (!selectedTab) {
                selectedTab = firstTab;
            }

            selectedTab.click();

            var height = 0,
                maxHeight = 500;

            $('#query-results .panel').each(function () {
                var currentHeight = $(this).height();

                if (currentHeight >= maxHeight) {
                    height = maxHeight;
                    return false;
                }

                height = Math.max(currentHeight, height);
            }).css({ 'height': Math.min(height, maxHeight) });

            $('html, body').animate({
                scrollTop: $("#query-results").offset().top - 10
            }, 500);
        });
    }

    // Temporary workaround
    window.loadCachedResults = function (cache) {
        verifyParameters();

        if (cache) {
            parseQueryResponse(cache);
        }
    }

    function showError(response, className) {
        if (response && !response.error) {
            error.hide();

            return false;
        }

        error.text(response.error).show()[0].className = 'error-message' + (className || '');

        return true;
    }

    var captcha = $('#captcha'), captchaSubmit = captcha.find('button[type=submit]');

    function showCaptcha(response) {
        if (!response || !response.captcha) {
            return false;
        }

        captcha.find('input[type=text]').off('keydown').on('keydown', function (key) {
            if (key.keyCode === 13) {
                captchaSubmit.click();

                return false;
            }

            return true;
        });

        var submit = function () {
            $.post('/captcha', captcha.find('input').serialize(), function (response) {
                if (response.success) {
                    $('form button[type=submit]').not(captchaSubmit).prop('disabled', true);
                    captcha.hide().closest('form').submit();
                } else {
                    var error = captcha.find('.error-message');

                    captcha.find('input[type=text]').one('keydown', function () {
                        error.hide();
                    });
                    captchaSubmit.one('click', submit);
                    error.show();
                }
            });

            return false;
        };

        $('form button[type=submit]').not(captchaSubmit).prop('disabled', true);

        captchaSubmit.one('click', submit);
        captcha.show().find('input[type=text]').focus();

        return true;
    }
});<commit_msg>Remove unnecessary response.graph property<commit_after>DataExplorer.QueryEditor = (function () {
    var editor, field, query,
        options = {
            'mode': 'text/x-t-sql'
        };

    function exists() {
        return !!editor || !!query;
    }

    function create(target, callback) {
        if (typeof target === 'string') {
            target = $(target);
        }

        if (!target.length) {
            return;
        }

        field = target;
        target = target[0];

        if (target.nodeName === 'TEXTAREA') {
            function run() {
                field.closest('form').submit();
            }

            editor = CodeMirror.fromTextArea(target, $.extend({}, options, {
                'lineNumbers': true,
                'extraKeys': {
                    'Ctrl-Enter': run,
                    'F5': run
                }
            }));
        } else {
            query = target[_textContent];
            editor = CodeMirror.runMode(query, options.mode, target);
        }

        if (callback && typeof callback === 'function') {
            callback(editor);
        }
    }

    function getValue() {
        if (!exists()) {
            return null;
        }

        if (query) {
            return query;
        }

        var value = editor.getValue();

        // Strip zero-width that randomly appears when copying text from the current
        // Data Explorer query editor into this one, at least until I can figure out
        // where it's coming from.
        if (value.charCodeAt(value.length - 1) === 8203) {
            value = value.substring(0, value.length - 1);
        }

        // Explicitly update the field, since CodeMirror might not have gotten a
        // chance to yet
        field.val(value);

        return value;
    }

    return {
        'create': create,
        'value': getValue,
        'exists': exists
    };
})();

DataExplorer.ready(function () {
    var schema = $('#schema'),
        history = $('#history'),
        panel = $('#editor-panel'),
        metadata = $('#query-metadata .info'),
        error = $('#error-message'),
        form = $('#runQueryForm');

    DataExplorer.QueryEditor.create('#queryBodyText');
    DataExplorer.QueryEditor.create('#sql', function (editor) {
        var wrapper;

        DataExplorer.Sidebar.init({
            editorTheme: editor.getOption('theme'),
            panel: panel,
            toolbar: '#editor-toolbar'
        });

        if (editor) {
            wrapper = $(editor.getScrollerElement());
        }

        function resizePanel(available) {
            var remaining = available - history.outerHeight(),
                list = schema.children('ul'),
                offset = schema.outerHeight() - list.height();

            list.height(remaining - offset);
            DataExplorer.TableHelpers.resize((available - offset) + 9);

            if (wrapper) {
                offset = wrapper.closest('.CodeMirror').outerHeight() - wrapper.height();

                wrapper.height(available - offset);
                editor.refresh();
            }
        }

        // Set this resizer up after because the grippie adds height to the
        // sidebar that we need to factor in
        $('#editor').TextAreaResizer(resizePanel, {
            'useParentWidth': true,
            'resizeWrapper': true,
            'minHeight': 300,
            'initCallback': true
        });
    });

    $('.miniTabs').tabs(false);

    form.submit(function () {
        $('.report-option').hide();
        error.hide();

        var cleanup = function () {
            $('#loading').hide();

            form.find('input, button').prop('disabled', function () {
                return this.id == 'cancel-query';
            });
        };

        var fail = function() {
            showError({ 'error': "Something unexpected went wrong while running "
                            + "your query. Don't worry, blame is already being assigned." });
        };

        var cancel = function () {
            showError({ 'error': 'Query execution has been cancelled' }, 'notice');
        }

        var pending = { request: null, timeout: null, setupCancel: true };
        var success = function(response) {
            if (response.running === true)
            {
                var poll = function () {
                    pending.timeout = setTimeout(function(){
                        pending.request = $.ajax({
                            'type': 'GET',
                            'url': '/query/job/' + response.job_id,
                            'success': success,
                            'error': [cleanup, fail],
                            'cache': false
                        });
                    }, 1500);
                };

                if (!pending.timeout && pending.setupCancel) {
                    var job = response.job_id;
                    pending.setupCancel = false;

                    $('#cancel-query').one('click', function () {
                        this.disabled = true;

                        clearTimeout(pending.timeout);

                        if (pending.request) {
                            pending.request.abort();
                        }

                        $.ajax({
                            type: 'POST',
                            url:  '/query/job/' + job + '/cancel',
                            success: function (response) {
                                if (response.cancelled) {
                                    cleanup();
                                    cancel();
                                } else {
                                    // There were some results, so we're going to try and get whatever
                                    // was being returned when the user decided to cancel
                                    poll();
                                }
                            },
                            error: [cleanup, fail],
                            cache: false
                        });
                    }).prop('disabled', false);
                }

                poll();
            }
            else
            {
                cleanup();
                parseQueryResponse(response);
            }
        };

        if (verifyParameters()) {
            var data = form.serialize();
            form.find('input, button').prop('disabled', true);

            $('#loading').show();

            $.ajax({
                'type': 'POST',
                'url': this.action,
                'data': data,
                'success': success,
                'error': [cleanup, fail],
                'cache': false,
            });
        }

        return false;
    });

    $('#query-options').find('input, select').each(function () {
        var value = window.location.param('opt.' + this.name);

        if (value) {
            if (this.type === 'checkbox') {
                this.checked = value;
            } else {
                this.value = value;
            }
        }
    });

    $('#query-results').bind('show', function (event) {
        $('.download-button', this).hide();
        $(event.target.href.from('#') + 'Button').show();
    });

    $('#executionPlanTab').click(function () {
        QP.drawLines();
    });

    // Ideally we can separate out the actual displaying bits so that the user
    // doesn't have to click the button before getting the form.
    function verifyParameters() {
        var sql = null;

        // Ugh, this is ugly, need to rework this soon
        if (DataExplorer.QueryEditor.exists()) {
            sql = DataExplorer.QueryEditor.value();
        } else {
            // This is a pretty big assumption
            sql = $('#queryBodyText').text();
        }

        if (!sql) {
            return false;
        }

        var parameters = new DataExplorer.ParameterParser.parse(sql, {
            multilineStrings: true,
            multilineComments: true,
            stringEscapeCharacter: "'",
            nestedMultilineComments: true
        });

        var complete = true,
            wrapper = document.getElementById('query-params'),
            fieldList = wrapper.getElementsByTagName('input'),
            fields = {},
            field, name, label, row, value, hasValue, key, first;

        $(wrapper).toggle(!!parameters.length);

        for (var i = fieldList.length - 1; i > -1 ; --i) {
            field = fieldList.item(i);
            value = field.getAttribute('value');
            name = field.name;

            if (field.value && field.value.length /*&& value != field.value*/) {
                fields[name] = field.value;
            }

            field.parentNode.parentNode.removeChild(field.parentNode);
        }

        for (var i = 0; i < parameters.length; ++i) {
            label = document.createElement('label');
            label.htmlFor = 'dynParam' + i;
            label[_textContent] = parameters[i].label || parameters[i].name;

            if (parameters[i].description) {
                label.title = parameters[i].description;
            }

            value = fields[parameters[i].name];
            hasValue = !(!value && value !== 0);

            if (!hasValue) {
                value = window.location.param(parameters[i].name);
                hasValue = !(!value && value !== 0);
            }

            if (!hasValue) {
                value = parameters[i].auto;
                hasValue = !(!value && value !== 0);
            }

            if (!hasValue && parameters[i].name.toLowerCase() === 'userid') {
                if (DataExplorer.options.User.isAuthenticated && DataExplorer.options.User.guessedID) {
                    hasValue = true;
                    value = DataExplorer.options.User.guessedID;
                }
            }

            if (complete) {
                complete = hasValue;
            }

            field = document.createElement('input');
            field.name = parameters[i].name;
            field.id = 'dynParam' + i;
            field.type = 'text';

            if (hasValue) {
                field.setAttribute('value', value);
            } else if (!first) {
                first = field;
            }

            row = document.createElement('div');
            row.className = 'form-row';
            row.appendChild(label);
            row.appendChild(field);

            wrapper.appendChild(row);
        }

        if (!complete && first) {
            first.focus();
        }

        return complete;
    }

    function parseQueryResponse(response) {
        if (showError(response) || showCaptcha(response)) {
            return;
        }

        var action = form[0].action,
            records = 0,
            results,
            slug = response.slug,
            params = $('#query-params input[type="text"]').serialize(),
            textOnly = false,
            userid;

        if (params) {
            params = params.replace(/(^|&)UserId=(\d+)(&|$)/i, function (match, g1, g2, g3) {
                userid = g2;

                return g1 ? g3 : "";
            });

            if (params.length) {
                params = '?' + params;
            } else {
                params = null;
            }
        }

        if (/[^\d]\/\d+$/.test(action)) {
            form[0].action = action + '/' + response.querySetId;
        }

        if (response.resultSets.length) {
            results = response.resultSets[0];
            records = results.rows.length;
        } else {
            textOnly = true;
            response.resultSets = null;
        }

        document.getElementById('messages').children[0][_textContent] = response.messages;

        if (!slug && !/\/[^\/]+\/query\/new/.test(window.location.pathname) && /.*?\/[^\/]+$/.test(window.location.pathname)) {
            slug = window.location.pathname.substring(window.location.pathname.lastIndexOf('/'));

            if (/\d+/.test(slug)) {
                slug = null;
            }
        } else if (slug && slug.indexOf('/') !== 0) {
            slug = '/' + slug;
        }

        DataExplorer.template('#execution-stats', 'text', {
            'records': textOnly ? "Results" : records + " rows",
            'time': response.executionTime === 0 ? "<1" : response.executionTime,
            'cached': response.fromCache ? ' (cached)' : ''
        });

        var target = "";
        if (response.targetSites == 1) { target = "all-"; } // all sites
        else if (response.targetSites == 2) { target = "all-meta-"; } // all meta sites
        else if (response.targetSites == 3) { target = "all-non-meta-"; } // all non meta sites
        else if (response.targetSites == 4) { target = "all-meta-but-mse-"; } // all meta sites except mse
        else if (response.targetSites == 5) { target = "all-non-meta-but-so-"; } // all non meta sites except so

        var options;

        $('#query-options').find('input, select').each(function () {
            var value;

            if (this.type === 'checkbox') {
                if (this.checked) {
                    value = true;
                }
            } else {
                value = this.value;

                // If this is a select and the selected option is set in the HTML as the default one,
                // there's no sense in appending it to the query string
                if (this.tagName == 'SELECT' && this.options[this.selectedIndex].getAttribute('selected') !== null) {
                    value = null;
                }
            }

            if (value) {
                options = (options ? options + '&' : '') + 'opt.' + this.name + '=' + encodeURIComponent(value);
            }
        });

        if (options) {
            params = (params ? params + '&' : '?') + options;
        }

        var formatOptions = {
            'targetsites': target,
            'site': response.siteName,
            'revisionid': response.revisionId,
            'slug': slug,
            'params': params,
            'id' : response.querySetId
        };

        DataExplorer.template('a.templated.site', 'href', formatOptions);
        DataExplorer.SiteSwitcher.update(formatOptions);

        if (userid) {
            formatOptions.params = (params ? params + '&' : '?') + 'UserId=' + userid;
        }

        DataExplorer.template('a.templated:not(.site), a.templated.related-site', 'href', formatOptions);

        if (DataExplorer.Sidebar) {
            DataExplorer.Sidebar.updateHistory(response);
        }

        $('#query-results .miniTabs a.optional').each(function () {
            $(this).toggleClass('hidden', !response[this.hash.substring(1)]);
        });

        // We have to start showing the contents so that SlickGrid can figure
        // out the heights of its components correctly
        $('.result-option').fadeIn('fast').promise().done(function () {
            var tabset = $('#query-results .miniTabs a').off('show'),
                firstTab = tabset.filter(':not(.hidden):first'),
                selectedTab;

            if (window.location.hash) {
                selectedTab = $(window.location.hash + 'Tab');

                if (!selectedTab.length || selectedTab.hasClass('hidden')) {
                    selectedTab = null;
                }
            }

            if (!textOnly && DataExplorer.Graph.isGraph(results)) {
                var graph = new DataExplorer.Graph(results, '#graph');

                tabset.on('show', function (event, panel) {
                    if (panel === '#graph' && !graph.isInitialized()) {
                        graph.show();
                    }
                });
            }

            var permalink = $('#permalink a')[0];

            if (permalink) {
                tabset.off('click.permalink');
                tabset.on('click.permalink', function () {
                    // We should probably be using the formatter here, but for now we'll
                    // just hack around it because this whole mess needs tidying anyway
                    permalink.href = permalink.href.replace(/#.*$/, '') + (this != firstTab[0] ? this.hash : '');
                });
            }

            if (response.executionPlan && QP && typeof QP.drawLines === 'function') {
                $('#executionPlan').html(response.executionPlan);
            }

            if (!textOnly) {
                var grid = new DataExplorer.ResultSet(results, response.url, '#resultSets');

                tabset.on('show', function (event, panel) {
                    if (panel === '#resultSets' && !grid.isInitialized()) {
                        grid.show();
                    }
                });
            }

            if (!selectedTab) {
                selectedTab = firstTab;
            }

            selectedTab.click();

            var height = 0,
                maxHeight = 500;

            $('#query-results .panel').each(function () {
                var currentHeight = $(this).height();

                if (currentHeight >= maxHeight) {
                    height = maxHeight;
                    return false;
                }

                height = Math.max(currentHeight, height);
            }).css({ 'height': Math.min(height, maxHeight) });

            $('html, body').animate({
                scrollTop: $("#query-results").offset().top - 10
            }, 500);
        });
    }

    // Temporary workaround
    window.loadCachedResults = function (cache) {
        verifyParameters();

        if (cache) {
            parseQueryResponse(cache);
        }
    }

    function showError(response, className) {
        if (response && !response.error) {
            error.hide();

            return false;
        }

        error.text(response.error).show()[0].className = 'error-message' + (className || '');

        return true;
    }

    var captcha = $('#captcha'), captchaSubmit = captcha.find('button[type=submit]');

    function showCaptcha(response) {
        if (!response || !response.captcha) {
            return false;
        }

        captcha.find('input[type=text]').off('keydown').on('keydown', function (key) {
            if (key.keyCode === 13) {
                captchaSubmit.click();

                return false;
            }

            return true;
        });

        var submit = function () {
            $.post('/captcha', captcha.find('input').serialize(), function (response) {
                if (response.success) {
                    $('form button[type=submit]').not(captchaSubmit).prop('disabled', true);
                    captcha.hide().closest('form').submit();
                } else {
                    var error = captcha.find('.error-message');

                    captcha.find('input[type=text]').one('keydown', function () {
                        error.hide();
                    });
                    captchaSubmit.one('click', submit);
                    error.show();
                }
            });

            return false;
        };

        $('form button[type=submit]').not(captchaSubmit).prop('disabled', true);

        captchaSubmit.one('click', submit);
        captcha.show().find('input[type=text]').focus();

        return true;
    }
});<|endoftext|>


<commit_before>
var _classGen = {
    logId: false,
    elemCount: 0,

    getImports: function(classCode){
        // TODO optimize imports
        var imports = [
            'package com.sdl;\n'
        ];
        if(classCode.indexOf('Button') != -1){
            imports.push('import com.sdl.bootstrap.button.Button;')
        }
        if(classCode.indexOf('TextField') != -1){
            imports.push('import com.sdl.bootstrap.form.TextField;')
        }
        if(classCode.indexOf('SimpleCheckbox') != -1){
            imports.push('import com.sdl.selenium.form.SimpleCheckbox;')
        }
        if(classCode.indexOf('TextArea') != -1){
            imports.push('import com.sdl.bootstrap.form.TextArea;')
        }
        if(classCode.indexOf('Table') != -1){
            imports.push('import com.sdl.selenium.web.table.Table;')
        }
        return imports.join('\n') + '\n\n';
    },

    getVarName: function(name){
        name = name ? name : 'item' + (_classGen.elemCount++);
        // remove spaces and capitalize each word
        var words = name.split(/\s/);
        $.each(words, function(i, w){
            words[i] = !w ? w : w.charAt(0).toUpperCase() + w.substr(1).toLowerCase();
        });
        name = words.join('');

        name = name.replace(/[\(\)/\\:;\<>=\-",+&]/gi, '');
        //name = Ext.util.Format.capitalize(name);
        return !name ? name : name.charAt(0).toLowerCase() + name.substr(1);
    },

    getPanelConfig: function (item){
         var code = '';
        if(item.text()){
            code += '.setLabel("' + item.text() + '")';
        } else if(item.id){
            code += '.setId("' + item.id + '")';
        }
        return code;
    },

    getFieldConfig: function (item){
        var code = '';

        if(item.prop("id")){
            code += '.setId("' + item.prop("id") + '")';
        } else if (item.boxLabel){
            code += '.setLabel("' + item.boxLabel + '")';
        } else if (item.name){
            code += '.setName("' + item.name + '")';
        }
        return code;
    },

    getButtonConfig: function (item){
        var code = '';
        if(item.prop("id")){
            code += '.setId("' + item.prop("id") + '")';
        } else if (item.text()){
            code += '.setText("' + item.text() + '")';
        }

        // start bootstrap
        if(!code){
            var kids = $(item).children(),
                cls;
            if(kids){
                cls = kids.get(0).className;
                code += '.setElPath("//button[count(*[contains(@class, ' + cls + ')]) > 0]")';
            }
        }
        // end bootstrap

        return code;
    },

    getItemCode: function (container, item){
        var me = this,
            name = '',
            className = '',
            code = '\tpublic ',
            tag = item.prop("tagName").toLowerCase();

        // all classes that are or extend panels
        if(tag == 'input'){
            var type = item.prop("type");
            if(type == 'text' || type == 'email'){
                className = 'TextField';
            } else if(type == 'checkbox'){
                className = 'SimpleCheckbox';
            }
            if(className){
                name = item.prop("id"); // create order for variable name
                name = _classGen.getVarName(name) + className;
                code += className + ' ' + name + ' = new ' + className + '()';
                code += _classGen.getFieldConfig(item);
            } else {
                code = '';
                console.warn('no field className found', container, tag, item.id);
            }
        } else if(tag == 'button'){
            className = 'Button';
            name = item.prop("id") || item.text(); // create order for variable name
            name = _classGen.getVarName(name) + className;
            code += className + ' ' + name + ' = new ' + className + '()';
            code += _classGen.getButtonConfig(item);
        } else if(tag == 'textarea'){
            className = 'TextArea';
            if(className){
                name = item.prop("id"); // create order for variable name
                name = _classGen.getVarName(name) + className;
                code += className + ' ' + name + ' = new ' + className + '()';
                code += _classGen.getFieldConfig(item);
            } else {
                code = '';
            }
        } else if(tag == 'table'){
            className = 'Table';
            if(className){
                name = item.prop("id"); // create order for variable name
                name = _classGen.getVarName(name) + className;
                code += className + ' ' + name + ' = new ' + className + '()';
                code += _classGen.getButtonConfig(item);
            } else {
                code = '';
            }
        } else if(item.attr("role") == 'dialog'){
            className = 'Window';
            var title = item.children('div').children('h3').text();
            if(className && title != ''){
            console.debug('window: ', item)
                name = _classGen.getVarName(title) + className;
                code += className + ' ' + name + ' = new ' + className + '("' + title + '")';
            } else {
                code = '';
            }
        } else if(false){
            code = '';
        } else {
            //code += 'XYZ xyz = new XYZ("' + xtype + '", "' + xtypes + '")';
            code = '';
            console.warn('no classified xtype found', container, tag, item.id);
        }
        if(code != ''){
            code += ';';
            if(_classGen.logId){
                code += '// ' + item.id;
            }
            code += '\n';
        }
        return {
            code: code,
            name: name
        };
    },

    isNecesaryType : function (xtype, xtypes){
        return true;
        var me = this,
            necesary = true;
        if(me.isTypeOf(xtype, xtypes, 'hidden')){
            necesary = false;
        } else if(me.isTypeOf(xtype, xtypes, 'tbfill')){
            necesary = false;
        } else if(me.isTypeOf(xtype, xtypes, 'tbtext')){
            necesary = false;
        } else if(me.isTypeOf(xtype, xtypes, 'tbseparator')){
            necesary = false;
        } else if(me.isTypeOf(xtype, xtypes, 'tbseparator')){
            necesary = false;
        } else if(me.isTypeOf(xtype, xtypes, 'box')){
            necesary = false; // TODO this is temporary
        }
        return necesary;
    },

    isTypeOf: function(xtype, xtypes, type){
        return xtype == type;
    },

    getEachElementsCode : function (container, items){
        var code = '';
        if(items){
            items.each(function(i, e){
                code += _classGen.getItemsCode(container, $(e));
            });
        }

        return code;
    },

    getItemsCode: function (container, item){
        //console.debug('getItemsCode', container, item);
        var elements,
            code = '';

        elements = _classGen.getItemCode(container, item);
        code += elements.code;
        container = elements.name || container;

        code += _classGen.getInsideItems(container, item);

        return code;
    },

    getInsideItems: function(container, item){
        var code = '';
        code += _classGen.getEachElementsCode(container, $(item).children());
        return code;
    },

    getBadyClassCode : function (){
        return _classGen.getElClassCode($("body").children().first());
    },

    getElClassCode : function (el){
        var
            name = _classGen.getVarName(el.title),
            code,
            container = 'this';
            name = name.charAt(0).toUpperCase() + name.substr(1);
        code = 'public class ' + name + 'MyWebLocator extends WebLocator {\n';
        //code += '\tpublic ' + name + 'Window(){\n';
        //code += '\t\tsetTitle("' + w.title + '");\n';
        //code += '\t}\n';

        code += _classGen.getInsideItems(container, el);

        code += '\n// methods hire \n';
        code += '\n}\n';

        code = _classGen.getImports(code) + code;

        return code;
    }
};

console.info('\n'+ _classGen.getBadyClassCode());
<commit_msg>add Form element in generate.page.class.js<commit_after>
var _classGen = {
    logId: false,
    elemCount: 0,

    getImports: function(classCode){
        // TODO optimize imports
        var imports = [
            'package com.sdl;\n'
        ];
        if(classCode.indexOf('Button') != -1){
            imports.push('import com.sdl.bootstrap.button.Button;')
        }
        if(classCode.indexOf('TextField') != -1){
            imports.push('import com.sdl.bootstrap.form.TextField;')
        }
        if(classCode.indexOf('SimpleCheckbox') != -1){
            imports.push('import com.sdl.selenium.form.SimpleCheckbox;')
        }
        if(classCode.indexOf('TextArea') != -1){
            imports.push('import com.sdl.bootstrap.form.TextArea;')
        }
        if(classCode.indexOf('Table') != -1){
            imports.push('import com.sdl.selenium.web.table.Table;')
        }
        if(classCode.indexOf('Form') != -1){
            imports.push('import com.sdl.bootstrap.form.Form;')
        }
        return imports.join('\n') + '\n\n';
    },

    getVarName: function(name){
        name = name ? name : 'item' + (_classGen.elemCount++);
        // remove spaces and capitalize each word
        var words = name.split(/\s/);
        $.each(words, function(i, w){
            words[i] = !w ? w : w.charAt(0).toUpperCase() + w.substr(1).toLowerCase();
        });
        name = words.join('');

        name = name.replace(/[\(\)/\\:;\<>=\-",+&]/gi, '');
        //name = Ext.util.Format.capitalize(name);
        return !name ? name : name.charAt(0).toLowerCase() + name.substr(1);
    },

    getPanelConfig: function (item){
         var code = '';
        if(item.text()){
            code += '.setLabel("' + item.text() + '")';
        } else if(item.id){
            code += '.setId("' + item.id + '")';
        }
        return code;
    },

    getFieldConfig: function (item){
        var code = '';

        if(item.prop("id")){
            code += '.setId("' + item.prop("id") + '")';
        } else if (item.boxLabel){
            code += '.setLabel("' + item.boxLabel + '")';
        } else if (item.name){
            code += '.setName("' + item.name + '")';
        }
        return code;
    },

    getButtonConfig: function (item){
        var code = '';
        if(item.prop("id")){
            code += '.setId("' + item.prop("id") + '")';
        } else if (item.text()){
            code += '.setText("' + item.text() + '")';
        }

        // start bootstrap
        if(!code){
            var kids = $(item).children(),
                cls;
            if(kids){
                cls = kids.get(0).className;
                code += '.setElPath("//button[count(*[contains(@class, ' + cls + ')]) > 0]")';
            }
        }
        // end bootstrap

        return code;
    },

    getFormConfig: function (item){
             var code = '';
             var kids = $(item).children('legend');
            if(item.id){
                code += '.setId("' + item.id + '")';
            } else if(kids){
                code += '.setTitle("' + kids.text() + '")';
            }
            return code;
        },

    getItemCode: function (container, item){
        var me = this,
            name = '',
            className = '',
            code = '\tpublic ',
            tag = item.prop("tagName").toLowerCase();

        if(tag == 'input'){
            var type = item.prop("type");
            if(type == 'text' || type == 'email'){
                className = 'TextField';
            } else if(type == 'checkbox'){
                className = 'SimpleCheckbox';
            }
            if(className){
                name = item.prop("id"); // create order for variable name
                name = _classGen.getVarName(name) + className;
                code += className + ' ' + name + ' = new ' + className + '(' + container + ')';
                code += _classGen.getFieldConfig(item);
            } else {
                code = '';
                console.warn('no field className found', container, tag, item.id);
            }
        } else if(tag == 'button'){
            className = 'Button';
            name = item.prop("id") || item.text(); // create order for variable name
            name = _classGen.getVarName(name) + className;
            code += className + ' ' + name + ' = new ' + className + '(' + container + ')';
            code += _classGen.getButtonConfig(item);
        } else if(tag == 'textarea'){
            className = 'TextArea';
            if(className){
                name = item.prop("id"); // create order for variable name
                name = _classGen.getVarName(name) + className;
                code += className + ' ' + name + ' = new ' + className + '(' + container + ')';
                code += _classGen.getFieldConfig(item);
            } else {
                code = '';
            }
        } else if(tag == 'table'){
            className = 'Table';
            if(className){
                name = item.prop("id"); // create order for variable name
                name = _classGen.getVarName(name) + className;
                code += className + ' ' + name + ' = new ' + className + '(' + container + ')';
                code += _classGen.getButtonConfig(item);
            } else {
                code = '';
            }
        } else if(tag == 'form'){
             className = 'Form';
             if(className){
                 name = item.children('legend').text();
                 name = _classGen.getVarName(name) + className;
                 code += className + ' ' + name + ' = new ' + className + '(' + container + ')';
                 code += _classGen.getFormConfig(item);
             } else {
                 code = '';
             }
        } else if(item.attr("role") == 'dialog'){
            className = 'Window';
            var title = item.children('div').children('h3').text();
            if(className && title != ''){
            console.debug('window: ', item)
                name = _classGen.getVarName(title) + className;
                code += className + ' ' + name + ' = new ' + className + '("' + title + '")';
            } else {
                code = '';
            }
        } else if(false){
            code = '';
        } else {
            //code += 'XYZ xyz = new XYZ("' + xtype + '", "' + xtypes + '")';
            code = '';
            console.warn('no classified xtype found', container, tag, item.id);
        }
        if(code != ''){
            code += ';';
            if(_classGen.logId){
                code += '// ' + item.id;
            }
            code += '\n';
        }
        return {
            code: code,
            name: name
        };
    },

    isNecesaryType : function (xtype, xtypes){
        return true;
        var me = this,
            necesary = true;
        if(me.isTypeOf(xtype, xtypes, 'hidden')){
            necesary = false;
        } else if(me.isTypeOf(xtype, xtypes, 'tbfill')){
            necesary = false;
        } else if(me.isTypeOf(xtype, xtypes, 'tbtext')){
            necesary = false;
        } else if(me.isTypeOf(xtype, xtypes, 'tbseparator')){
            necesary = false;
        } else if(me.isTypeOf(xtype, xtypes, 'tbseparator')){
            necesary = false;
        } else if(me.isTypeOf(xtype, xtypes, 'box')){
            necesary = false; // TODO this is temporary
        }
        return necesary;
    },

    isTypeOf: function(xtype, xtypes, type){
        return xtype == type;
    },

    getEachElementsCode : function (container, items){
        var code = '';
        if(items){
            items.each(function(i, e){
                code += _classGen.getItemsCode(container, $(e));
            });
        }

        return code;
    },

    getItemsCode: function (container, item){
        //console.debug('getItemsCode', container, item);
        var elements,
            code = '';

        elements = _classGen.getItemCode(container, item);
        code += elements.code;
        container = elements.name || container;

        code += _classGen.getInsideItems(container, item);

        return code;
    },

    getInsideItems: function(container, item){
        var code = '';
        code += _classGen.getEachElementsCode(container, $(item).children());
        return code;
    },

    getBadyClassCode : function (){
//        return _classGen.getElClassCode($("body").children().first());
        var el;
        $("body").children().first().children().last().children().each(function (){
            var style = $(this).attr('style');
            if(style == "display: block;" || style != "display: none;"){
                el = this;
            }
        });
        return  _classGen.getElClassCode(el);
    },

    getElClassCode : function (el){
        var
            name = _classGen.getVarName(el.title),
            code,
            container = 'this';
            name = name.charAt(0).toUpperCase() + name.substr(1);
        code = 'public class ' + name + 'MyWebLocator extends WebLocator {\n';
        //code += '\tpublic ' + name + 'Window(){\n';
        //code += '\t\tsetTitle("' + w.title + '");\n';
        //code += '\t}\n';

        code += _classGen.getInsideItems(container, el);

        code += '\n// methods hire \n';
        code += '\n}\n';

        code = _classGen.getImports(code) + code;

        return code;
    }
};

console.info('\n'+ _classGen.getBadyClassCode());
<|endoftext|>


<commit_before>'use strict'

var http = require('http');
var https = require('https');
var url = require('url');

var generateCallbacks = function(testResultId, operation, requests, callbackUrl) {
  var records = [];

  /**
   * ArrayBuffer to String
   * @param {ArrayBuffer} buffer
   * @returns {String}
   */
  var arrayBufferToString = function (buffer) {
  	var str = '',
      uArrayVal = new Uint8Array(buffer),
  		i, ii;

    for (i = 0, ii = uArrayVal.length; i < ii; i++) {
      str += String.fromCharCode(uArrayVal[i]);
  	}
  	return str;
  };

  var callbacks = {
    // Called any time we see a new assertion in the test scripts
    // *note* Not used yet.
    assertion: function (name, result) {
        // name: string
        // result: Boolean
    },

    // Called when the run begins
    start: function (err, cursor) {
        // err: null or Error
        // cursor = {
        //     position: Number,
        //     iteration: Number,
        //     length: Number,
        //     cycles: Number,
        //     eof: Boolean,
        //     empty: Boolean,
        //     bof: Boolean,
        //     cr: Boolean,
        //     ref: String
        // }
    },

    // Called before starting a new iteration
    beforeIteration: function (err, cursor) {
        /* Same as arguments for "start" */
    },

    // Called when an iteration is completed
    iteration: function (err, cursor) {
        /* Same as arguments for "start" */
    },

    // Called before running a new Item (check the postman collection v2 format for what Item means)
    beforeItem: function (err, cursor, item) {
        // err, cursor: Same as arguments for "start"
        // item: sdk.Item
    },

    // Called after completion of an Item
    item: function (err, cursor, item) {
        /* Same as arguments for "beforeItem" */
    },

    // Called before running pre-request script(s) (Yes, Runtime supports multiple pre-request scripts!)
    beforePrerequest: function (err, cursor, events, item) {
        // err, cursor: Same as arguments for "start"
        // events: Array of sdk.Event objects
        // item: sdk.Item
    },

    // Called after running pre-request script(s)
    prerequest: function (err, cursor, results, item) {
        // err, cursor: Same as arguments for "start"
        // item: sdk.Item
        // results: Array of objects. Each object looks like this:
        //  {
        //      error: Error,
        //      event: sdk.Event,
        //      script: sdk.Script,
        //      result: {
        //          target: 'prerequest'
        //
        //          -- Updated environment
        //          environment: <VariableScope>
        //
        //          -- Updated globals
        //          globals: <VariableScope>
        //
        //          data: <Object of data variables>
        //          return: <Object, contains set next request params, etc>
        //      }
        //  }
    },

    // Called before running test script(s)
    beforeTest: function (err, cursor, events, item) {
        // err, cursor: Same as arguments for "start"
        // events: Array of sdk.Event objects
        // item: sdk.Item
    },

    // Called just after running test script (s)
    test: function (err, cursor, results, item) {
        // results: Array of objects. Each object looks like this:
        //  {
        //      error: Error,
        //      event: sdk.Event,
        //      script: sdk.Script,
        //      result: {
        //          target: 'test'
        //          -- Updated environment
        //          environment: <VariableScope>
        //          -- Updated globals
        //          globals: <VariableScope>
        //          response: <sdk.Response>
        //          request: <sdk.Request>
        //          data: <Object of data variables>
        //          cookies: <Array of "sdk.Cookie" objects>
        //          tests: <Object>
        //          return: <Object, contains set next request params, etc>
        //      }
        //  }
        records.push(results);
        //for (var i=0; i<results.length; i++) {
        //  var result = results[i];
        //  console.log('Tests: ' + JSON.stringify(result.result.tests));
        //  if (result.error != undefined) {
        //    console.log('Errors: ' + JSON.stringify(result.error.message));
        //  }
        //}
    },

    // Called just before sending a request
    beforeRequest: function (err, cursor, request, item) {
        // err, cursor: Same as arguments for "start"
        // item: sdk.Item
        // request: sdk.request
    },

    // Called just after sending a request
    request: function (err, cursor, response, request, item, cookies) {
        // err, cursor: Same as arguments for "start"
        // item: sdk.Item
        // response: sdk.Response
        // request: sdk.request
    },

    // Called at the end of a run
    done: function (err) {
        // err: null or Error
        //console.log('============================');
        console.log('Got ' + records.length + ' records to process for ' + testResultId + ' - ' + operation);

        var testReturns = [];

        for (var i=0; i<records.length; i++) {
          if (records[i][0] != undefined) {
            var record = records[i][0];

            // Prepare a testReturn with default being a failure.
            var testReturn = {
              "code": 1
            };

            //console.log('Record: ' + JSON.stringify(record));
            //console.log('============================');
            //console.log('Response: ' + JSON.stringify(record.result.response));
            //console.log('============================');
            if (record.result != undefined) {
              //console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
              //console.log('stream: ' + record.result.response.stream);
              //console.log('data: ' + arrayBufferToString(record.result.response.stream.values()));
              //console.log('response: ' + JSON.stringify(record.result.response));
              //console.log('code: ' + JSON.stringify(record.result.response.code));
              //console.log('header: ' + JSON.stringify(record.result.response.header));
              //console.log('headers: ' + JSON.stringify(record.result.response.headers));
              testReturn.elapsedTime = record.result.response.responseTime;

              // Build corresponding request sent.
              testReturn.request = {
                "headers": record.result.request.headers.map(function(header) {
                  return {"name": header.key, "values": [header.value]};
                })
              };
              if (record.result.request.body.raw != undefined) {
                testReturn.request.content = record.result.request.body.raw;
              }
              for (var j=0; j<requests.length; j++) {
                var request = requests[j];
                //console.log('Comparing record.result.request to ' + JSON.stringify(request));
                //console.log(record.result.request.url + ' VS ' + request.endpointUrl);
                //console.log(record.result.request.method + ' VS ' + request.method);
                if (request.endpointUrl == record.result.request.url
                    && request.method == record.result.request.method) {
                  //console.log('Found a match')
                  testReturn.request.name = request.name;
                }
              }
              // Build response objects as expected by Microcks.
              testReturn.response = {
                "headers": record.result.response.headers.map(function(header) {
                  return {"name": header.key, "values": [header.value]};
                }),
                "content": arrayBufferToString(record.result.response.stream.values()),
                "status": record.result.response.code
              };
            }
            // Complete error code and message if any.
            if (record.error == undefined) {
              testReturn.code = 0;
            } else {
              testReturn.message = record.error.message;
            }
            testReturns.push(testReturn);
          }
        }
        //console.log('Prepared returns: ' + JSON.stringify(testReturns));
        console.log('Find ' + testReturns.length + ' returns to send for ' + testResultId + ' - ' + operation);

        var req;
        var callbackURL = url.parse(callbackUrl);
        var data = JSON.stringify({"operationName": operation, "testReturns": testReturns});

        if (callbackURL.protocol === "http:") {
          req = http.request({
            hostname: callbackURL.hostname,
            port: callbackURL.port,
            path: callbackURL.path,
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              'Content-Length': Buffer.byteLength(data)
            }
          }, function(response) {
            response.on('data', function(data) {
              //console.log('Got data as response !');
              //console.log(arrayBufferToString(data.values()));
            });
            response.on('error', function(e) {
              console.log('Error received from callback endpoint: ' + JSON.stringify(e));
            });
          });
        }
        else {
          req = https.request({
            hostname: callbackURL.hostname,
            port: callbackURL.port,
            path: callbackURL.path,
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              'Content-Length': Buffer.byteLength(data)
            }
          }, function(response) {
            response.on('data', function(data) {
              //console.log('Got data as response !');
              //console.log(arrayBufferToString(data.values()));
            });
            response.on('error', function(e) {
              console.log('Error received from callback endpoint: ' + JSON.stringify(e));
            });
          });
        }
        req.on('error', function(err) {
          console.log('Problem with callback request: ' + err.message);
        });
        req.write(data);
        req.end();

        console.log('Done with requests for ' + testResultId + ' - ' + operation);
    },

    // Called any time a console.* function is called in test/pre-request scripts
    console: function (cursor, level, ...logs) {
      //console.log('console called with "' + logs + '"');
    },

    io: function (err, cursor, trace, ...otherArgs) {
        // err, cursor: Same as arguments for "start"
        // trace: An object which looks like this:
        // {
        //     -- Indicates the type of IO event, may be HTTP, File, etc. Any requests sent out as a part of
        //     -- auth flows, replays, etc will show up here.
        //     type: 'http',
        //
        //     -- Indicates what this IO event originated from, (collection, auth flows, etc)
        //     source: 'collection'
        // }
        // otherArgs: Variable number of arguments, specific to the type of the IO event.

        // For http type, the otherArgs are:
        // response: sdk.Response()
        // request: sdk.Request()
        // cookies: Array of sdk.Cookie()
    }
  }
  return callbacks;
}

module.exports.generateCallbacks = generateCallbacks;
<commit_msg>Event more debug message<commit_after>'use strict'

var http = require('http');
var https = require('https');
var url = require('url');

var generateCallbacks = function(testResultId, operation, requests, callbackUrl) {
  var records = [];

  /**
   * ArrayBuffer to String
   * @param {ArrayBuffer} buffer
   * @returns {String}
   */
  var arrayBufferToString = function (buffer) {
  	var str = '',
      uArrayVal = new Uint8Array(buffer),
  		i, ii;

    for (i = 0, ii = uArrayVal.length; i < ii; i++) {
      str += String.fromCharCode(uArrayVal[i]);
  	}
  	return str;
  };

  var callbacks = {
    // Called any time we see a new assertion in the test scripts
    // *note* Not used yet.
    assertion: function (name, result) {
        // name: string
        // result: Boolean
    },

    // Called when the run begins
    start: function (err, cursor) {
        // err: null or Error
        // cursor = {
        //     position: Number,
        //     iteration: Number,
        //     length: Number,
        //     cycles: Number,
        //     eof: Boolean,
        //     empty: Boolean,
        //     bof: Boolean,
        //     cr: Boolean,
        //     ref: String
        // }
        console.log('start: ' + JSON.stringify(err));
    },

    // Called before starting a new iteration
    beforeIteration: function (err, cursor) {
        /* Same as arguments for "start" */
        console.log('beforeIteration: ' + JSON.stringify(err));
    },

    // Called when an iteration is completed
    iteration: function (err, cursor) {
        /* Same as arguments for "start" */
    },

    // Called before running a new Item (check the postman collection v2 format for what Item means)
    beforeItem: function (err, cursor, item) {
        // err, cursor: Same as arguments for "start"
        // item: sdk.Item
    },

    // Called after completion of an Item
    item: function (err, cursor, item) {
        /* Same as arguments for "beforeItem" */
    },

    // Called before running pre-request script(s) (Yes, Runtime supports multiple pre-request scripts!)
    beforePrerequest: function (err, cursor, events, item) {
        // err, cursor: Same as arguments for "start"
        // events: Array of sdk.Event objects
        // item: sdk.Item
        console.log('beforePrerequest: ' + JSON.stringify(err));
    },

    // Called after running pre-request script(s)
    prerequest: function (err, cursor, results, item) {
        // err, cursor: Same as arguments for "start"
        // item: sdk.Item
        // results: Array of objects. Each object looks like this:
        //  {
        //      error: Error,
        //      event: sdk.Event,
        //      script: sdk.Script,
        //      result: {
        //          target: 'prerequest'
        //
        //          -- Updated environment
        //          environment: <VariableScope>
        //
        //          -- Updated globals
        //          globals: <VariableScope>
        //
        //          data: <Object of data variables>
        //          return: <Object, contains set next request params, etc>
        //      }
        //  }
        console.log('prerequest: ' + JSON.stringify(err));
    },

    // Called before running test script(s)
    beforeTest: function (err, cursor, events, item) {
        // err, cursor: Same as arguments for "start"
        // events: Array of sdk.Event objects
        // item: sdk.Item
        console.log('beforeTest: ' + JSON.stringify(err));
    },

    // Called just after running test script (s)
    test: function (err, cursor, results, item) {
        // results: Array of objects. Each object looks like this:
        //  {
        //      error: Error,
        //      event: sdk.Event,
        //      script: sdk.Script,
        //      result: {
        //          target: 'test'
        //          -- Updated environment
        //          environment: <VariableScope>
        //          -- Updated globals
        //          globals: <VariableScope>
        //          response: <sdk.Response>
        //          request: <sdk.Request>
        //          data: <Object of data variables>
        //          cookies: <Array of "sdk.Cookie" objects>
        //          tests: <Object>
        //          return: <Object, contains set next request params, etc>
        //      }
        //  }
        console.log('test: ' + JSON.stringify(err));
        records.push(results);
        //for (var i=0; i<results.length; i++) {
        //  var result = results[i];
        //  console.log('Tests: ' + JSON.stringify(result.result.tests));
        //  if (result.error != undefined) {
        //    console.log('Errors: ' + JSON.stringify(result.error.message));
        //  }
        //}
    },

    // Called just before sending a request
    beforeRequest: function (err, cursor, request, item) {
        // err, cursor: Same as arguments for "start"
        // item: sdk.Item
        // request: sdk.request
        console.log('beforeRequest: ' + JSON.stringify(err));
    },

    // Called just after sending a request
    request: function (err, cursor, response, request, item, cookies) {
        // err, cursor: Same as arguments for "start"
        // item: sdk.Item
        // response: sdk.Response
        // request: sdk.request
        console.log('request: ' + JSON.stringify(err));
    },

    // Called at the end of a run
    done: function (err) {
        // err: null or Error
        //console.log('============================');
        console.log('Got ' + records.length + ' records to process for ' + testResultId + ' - ' + operation);

        var testReturns = [];

        for (var i=0; i<records.length; i++) {
          if (records[i][0] != undefined) {
            var record = records[i][0];

            // Prepare a testReturn with default being a failure.
            var testReturn = {
              "code": 1
            };

            //console.log('Record: ' + JSON.stringify(record));
            //console.log('============================');
            //console.log('Response: ' + JSON.stringify(record.result.response));
            //console.log('============================');
            if (record.result != undefined) {
              //console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
              //console.log('stream: ' + record.result.response.stream);
              //console.log('data: ' + arrayBufferToString(record.result.response.stream.values()));
              //console.log('response: ' + JSON.stringify(record.result.response));
              //console.log('code: ' + JSON.stringify(record.result.response.code));
              //console.log('header: ' + JSON.stringify(record.result.response.header));
              //console.log('headers: ' + JSON.stringify(record.result.response.headers));
              testReturn.elapsedTime = record.result.response.responseTime;

              // Build corresponding request sent.
              testReturn.request = {
                "headers": record.result.request.headers.map(function(header) {
                  return {"name": header.key, "values": [header.value]};
                })
              };
              if (record.result.request.body.raw != undefined) {
                testReturn.request.content = record.result.request.body.raw;
              }
              for (var j=0; j<requests.length; j++) {
                var request = requests[j];
                //console.log('Comparing record.result.request to ' + JSON.stringify(request));
                //console.log(record.result.request.url + ' VS ' + request.endpointUrl);
                //console.log(record.result.request.method + ' VS ' + request.method);
                if (request.endpointUrl == record.result.request.url
                    && request.method == record.result.request.method) {
                  //console.log('Found a match')
                  testReturn.request.name = request.name;
                }
              }
              // Build response objects as expected by Microcks.
              testReturn.response = {
                "headers": record.result.response.headers.map(function(header) {
                  return {"name": header.key, "values": [header.value]};
                }),
                "content": arrayBufferToString(record.result.response.stream.values()),
                "status": record.result.response.code
              };
            }
            // Complete error code and message if any.
            if (record.error == undefined) {
              testReturn.code = 0;
            } else {
              testReturn.message = record.error.message;
            }
            testReturns.push(testReturn);
          }
        }
        //console.log('Prepared returns: ' + JSON.stringify(testReturns));
        console.log('Find ' + testReturns.length + ' returns to send for ' + testResultId + ' - ' + operation);

        var req;
        var callbackURL = url.parse(callbackUrl);
        var data = JSON.stringify({"operationName": operation, "testReturns": testReturns});

        if (callbackURL.protocol === "http:") {
          req = http.request({
            hostname: callbackURL.hostname,
            port: callbackURL.port,
            path: callbackURL.path,
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              'Content-Length': Buffer.byteLength(data)
            }
          }, function(response) {
            response.on('data', function(data) {
              //console.log('Got data as response !');
              //console.log(arrayBufferToString(data.values()));
            });
            response.on('error', function(e) {
              console.log('Error received from callback endpoint: ' + JSON.stringify(e));
            });
          });
        }
        else {
          req = https.request({
            hostname: callbackURL.hostname,
            port: callbackURL.port,
            path: callbackURL.path,
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              'Content-Length': Buffer.byteLength(data)
            }
          }, function(response) {
            response.on('data', function(data) {
              //console.log('Got data as response !');
              //console.log(arrayBufferToString(data.values()));
            });
            response.on('error', function(e) {
              console.log('Error received from callback endpoint: ' + JSON.stringify(e));
            });
          });
        }
        req.on('error', function(err) {
          console.log('Problem with callback request: ' + err.message);
        });
        req.write(data);
        req.end();

        console.log('Done with requests for ' + testResultId + ' - ' + operation);
    },

    // Called any time a console.* function is called in test/pre-request scripts
    console: function (cursor, level, ...logs) {
      //console.log('console called with "' + logs + '"');
    },

    io: function (err, cursor, trace, ...otherArgs) {
        // err, cursor: Same as arguments for "start"
        // trace: An object which looks like this:
        // {
        //     -- Indicates the type of IO event, may be HTTP, File, etc. Any requests sent out as a part of
        //     -- auth flows, replays, etc will show up here.
        //     type: 'http',
        //
        //     -- Indicates what this IO event originated from, (collection, auth flows, etc)
        //     source: 'collection'
        // }
        // otherArgs: Variable number of arguments, specific to the type of the IO event.

        // For http type, the otherArgs are:
        // response: sdk.Response()
        // request: sdk.Request()
        // cookies: Array of sdk.Cookie()
    }
  }
  return callbacks;
}

module.exports.generateCallbacks = generateCallbacks;
<|endoftext|>


<commit_before><commit_msg>.<commit_after><|endoftext|>


<commit_before>String.prototype.format = function (data) {
    return this.replace(/{{([\w@]+)}}/g, function(match, key) {
        return data[key];
    }).replace(/{\?(\w+)\?}(.*){\?}/g, function(match, key, value) {
        return (data[key] == 'true') ? value : '';

    })
};

document.addEventListener('DOMContentLoaded', function () {
    var store = new DOMStore(),
        tmpl = document.querySelector('template#todo-row').innerHTML;
        input = document.querySelector('input.new-todo'),
        main = document.querySelector('ul.todo-list'),
        footer = document.querySelector('.footer'),
        rowcount = document.querySelector('.todo-count strong');

    FILTER = {'': '', 'active': '[data-completed=false]', 'completed': '[data-completed=true]'}
    function render () {
        var rows = store.query('[type=todo]' + FILTER[filter.value]);
        main.innerHTML = rows.map(function (rec) { return tmpl.format(rec); }).join('');
        rowcount.innerHTML = store.query({'@type': 'todo', 'completed': 'false'}).length;
        footer.classList[(rows.length == 0) ? 'add' : 'remove']('hidden');
    }

    // Make all entries state track 'toggle all' flag
    document.querySelector('.toggle-all').addEventListener('change', function (ev) {
        store.query({'@type': 'todo'}).forEach(function (rec) {
            rec.completed = ev.target.checked;
        });
    });
    // Remove all records marked completed
    document.querySelector('.clear-completed').addEventListener('click', function (ev) {
        store.query({'@type': 'todo', 'completed': 'true'}).forEach(function (rec) {
            rec['@el'].parentNode.removeChild(rec['@el'])
        });
    });
    // track routing - controls filtering
    window.addEventListener('hashchange', function () {
        var hash = window.location.hash;
        Array.apply(null, document.querySelectorAll('.filters a')).forEach(function (el) {
            el.classList.remove('selected');
        });
        document.querySelector('.filters a[href="' + hash + '"]').classList.add('selected');
        filter.value = hash.slice(2);
    });

    // catch change of complete status
    main.addEventListener('change', function (ev) {
        if(!ev.target.matches('input[type=checkbox]')) return;
        store.get(ev.target.name).completed = ev.target.checked;
    });
    // catch Click on "done" button
    main.addEventListener('click', function (ev) {
        if(!ev.target.matches('button.destroy')) return;
        var _id = ev.target.parentNode.querySelector('input[type=checkbox]').name;
        store.remove(_id);
    });
    // catch Double Click on todo labels
    main.addEventListener('dblclick', function (ev) {
        if(!ev.target.matches('label')) return;
        ev.target.parentNode.parentNode.classList.add('editing');
        ev.target.parentNode.parentNode.querySelector('input.edit').focus();
    });
    // catch Enter in edit inputs
    main.addEventListener('keyup', function (ev) {
        if(ev.code !== 'Enter') return;
        var val = ev.target.value;
        var _id = ev.target.parentNode.querySelector('input[type=checkbox]').name;
        store.get(_id).message = val;
        ev.target.parentNode.classList.remove('editing');
    });
    // catch Enter in new todo input
    input.addEventListener('keyup', function (ev) {
        if(ev.code !== 'Enter') return;
        var _id = new Date().valueOf().toString();
        store.add(_id, {"@type": "todo", message: input.value, completed: false});
        input.value = '';
    });

    // watch for state changes
    store.subscribe(null, render);

    // Record to watch current filter state.  -- also triggers a render
    var filter = store.add('filter', {'@type': 'filter', value: window.location.hash.slice(2)});

    input.focus();
});
<commit_msg>Only one edit at a time.<commit_after>String.prototype.format = function (data) {
    return this.replace(/{{([\w@]+)}}/g, function(match, key) {
        return data[key];
    }).replace(/{\?(\w+)\?}(.*){\?}/g, function(match, key, value) {
        return (data[key] == 'true') ? value : '';

    })
};

document.addEventListener('DOMContentLoaded', function () {
    var store = new DOMStore(),
        tmpl = document.querySelector('template#todo-row').innerHTML;
        input = document.querySelector('input.new-todo'),
        main = document.querySelector('ul.todo-list'),
        footer = document.querySelector('.footer'),
        rowcount = document.querySelector('.todo-count strong');

    FILTER = {'': '', 'active': '[data-completed=false]', 'completed': '[data-completed=true]'}
    function render () {
        var rows = store.query('[type=todo]' + FILTER[filter.value]);
        main.innerHTML = rows.map(function (rec) { return tmpl.format(rec); }).join('');
        rowcount.innerHTML = store.query({'@type': 'todo', 'completed': 'false'}).length;
        footer.classList[(rows.length == 0) ? 'add' : 'remove']('hidden');
    }

    // Make all entries state track 'toggle all' flag
    document.querySelector('.toggle-all').addEventListener('change', function (ev) {
        store.query({'@type': 'todo'}).forEach(function (rec) {
            rec.completed = ev.target.checked;
        });
    });
    // Remove all records marked completed
    document.querySelector('.clear-completed').addEventListener('click', function (ev) {
        store.query({'@type': 'todo', 'completed': 'true'}).forEach(function (rec) {
            rec['@el'].parentNode.removeChild(rec['@el'])
        });
    });
    // track routing - controls filtering
    window.addEventListener('hashchange', function () {
        var hash = window.location.hash;
        Array.apply(null, document.querySelectorAll('.filters a')).forEach(function (el) {
            el.classList.remove('selected');
        });
        document.querySelector('.filters a[href="' + hash + '"]').classList.add('selected');
        filter.value = hash.slice(2);
    });

    // catch change of complete status
    main.addEventListener('change', function (ev) {
        if(!ev.target.matches('input[type=checkbox]')) return;
        store.get(ev.target.name).completed = ev.target.checked;
    });
    // catch Click on "done" button
    main.addEventListener('click', function (ev) {
        if(!ev.target.matches('button.destroy')) return;
        var _id = ev.target.parentNode.querySelector('input[type=checkbox]').name;
        store.remove(_id);
    });
    // catch Double Click on todo labels
    main.addEventListener('dblclick', function (ev) {
        if(!ev.target.matches('label')) return;
        Array.apply(null, main.querySelectorAll('li.editing')).forEach(function (el) {
            el.classList.remove('editing');
        });
        ev.target.parentNode.parentNode.classList.add('editing');
        ev.target.parentNode.parentNode.querySelector('input.edit').focus();
    });
    // catch Enter in edit inputs
    main.addEventListener('keyup', function (ev) {
        if(ev.code !== 'Enter') return;
        var val = ev.target.value;
        var _id = ev.target.parentNode.querySelector('input[type=checkbox]').name;
        store.get(_id).message = val;
        ev.target.parentNode.classList.remove('editing');
    });
    // catch Enter in new todo input
    input.addEventListener('keyup', function (ev) {
        if(ev.code !== 'Enter') return;
        var _id = new Date().valueOf().toString();
        store.add(_id, {"@type": "todo", message: input.value, completed: false});
        input.value = '';
    });

    // watch for state changes
    store.subscribe(null, render);

    // Record to watch current filter state.  -- also triggers a render
    var filter = store.add('filter', {'@type': 'filter', value: window.location.hash.slice(2)});

    input.focus();
});
<|endoftext|>