<commit_before>availableTemplates = null;
var model = {};
var baseUrl = "http://squirrel.flymine.org/intermine-test";
var flyMineBase = "http://preview.flymine.org/preview";
$(function() {
    IMBedding.setBaseUrl(baseUrl);
    Syntax.root = "http://squirrel.flymine.org/imbedding/lib/jquery-syntax/";
    $('.js-snippet').syntax({
        brush: 'javascript', 
        layout: 'list', 
        replace: true,
        tabWidth: 4,
        root: "lib/jquery-syntax/"
    });
    $('.html-snippet').syntax({
        brush: 'html', 
        layout: 'list', 
        replace: true,
        tabWidth: 4,
        root: "lib/jquery-syntax/"
    });
    $('#showGraphAreaContainer').hide();
    loadTable1();
    loadTable3a();
    loadTable3b();
    loadTable4a();
    loadTable4b();
    loadTable4c();
    loadTable4d();
    loadTable4();
    loadTable5();
    $('#faq').accordion({collapsible: true, autoHeight: false});
});

function setActiveStyleSheet(title) {
    var i, a, main;
    for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
        if(a.getAttribute("rel").indexOf("style") != -1
                && a.getAttribute("title")) {
            a.disabled = true;
            if(a.getAttribute("title") == title) a.disabled = false;
        }
    }
}

function loadTable1() {
    IMBedding.loadTemplate(
        {
            name:           "Gene_Identifiers",

            constraint1:    "Gene.secondaryIdentifier",
            op1:            "<",
            value1:         "CG1046",
            code1:          "A"
        },
        "#placeholderEx2",
        {openOnLoad: true, baseUrl: flyMineBase}
    );
}
function loadTable2() {
    IMBedding.loadTemplate(
        {
            name:           "Gene_upstreamRegulatoryRegions",

            constraint1:    "Gene",
            op1:            "LOOKUP",
            value1:         "eve",
            code1:          "A"
        },
        "#positionExample",
        {baseUrl: flyMineBase}
    );
}
function loadTable3a() {
    IMBedding.loadTemplate(
        {
            name:           "Gene_allGOTerms2",

            constraint1:    "Gene",
            op1:            "LOOKUP",
            value1:         "CG11348",
            code1:          "A"
        },
        "#placeholderEx3a",
        {onTitleClick: "mine", baseUrl: flyMineBase}
    );
}

function loadTable3b() {
    IMBedding.loadTemplate(
        {
            name:           "Gene_allGOTerms2",
            size: 10,

            constraint1:    "Gene",
            op1:            "LOOKUP",
            value1:         "CG11348",
            code1:          "A"
        },
        "#placeholderEx3b",
        {onTitleClick: "none", baseUrl: flyMineBase}
    );
}

function loadTable4a() {
    IMBedding.loadTemplate(
        {
            name:           "Organism_GeneDomain_new",
            size: 10,

            constraint1:    "ProteinDomain.proteins.genes.organism.name",
            op1:            "=",
            value1:         "Drosophila melanogaster",
            code1:          "A",

            constraint2:    "ProteinDomain.shortName",
            op2:            "=",
            value2:         "*homeo*",
            code2:          "B"
        },
        "#placeholderEx4a",
        {showExportLinks: false, baseUrl: flyMineBase}
    );
}

function loadTable4b() {
    IMBedding.loadTemplate(
        {
            name:           "Organism_GeneDomain_new",
            size: 10,

            constraint1:    "ProteinDomain.proteins.genes.organism.name",
            op1:            "=",
            value1:         "Drosophila melanogaster",
            code1:          "A",

            constraint2:    "ProteinDomain.shortName",
            op2:            "=",
            value2:         "*homeo*",
            code2:          "B"
        },
        "#placeholderEx4b",
        {showCount: false, baseUrl: flyMineBase}
    );
}
function loadTable4c() {
    IMBedding.loadTemplate(
        {
            name:           "Organism_GeneDomain_new",
            size: 10,

            constraint1:    "ProteinDomain.proteins.genes.organism.name",
            op1:            "=",
            value1:         "Drosophila melanogaster",
            code1:          "A",

            constraint2:    "ProteinDomain.shortName",
            op2:            "=",
            value2:         "*homeo*",
            code2:          "B"
        },
        "#placeholderEx4c",
        {showMineLink: false, baseUrl: flyMineBase}
    );
}
function loadTable4d() {
    IMBedding.loadTemplate(
        {
            name:           "Organism_GeneDomain_new",
            size: 15,

            constraint1:    "ProteinDomain.proteins.genes.organism.name",
            op1:            "=",
            value1:         "Drosophila melanogaster",
            code1:          "A",

            constraint2:    "ProteinDomain.shortName",
            op2:            "=",
            value2:         "*homeo*",
            code2:          "B"
        },
        "#placeholderEx4d",
        {baseUrl: flyMineBase}
    );
}
function loadTable4() {
    IMBedding.loadTemplate(
        {
            name:           "Chromosome_Gene",
        
            constraint1:    "Gene.chromosome.primaryIdentifier",
            op1:            "=",
            value1:         "2L",
            code1:          "A",
        
            constraint2:    "Gene.organism.name",
            op2:            "=",
            value2:         "Drosophila melanogaster",
            code2:          "B"
        },
        '#placeholder1',
        {baseUrl: flyMineBase}
    );
}

function loadTable5() {
    IMBedding.loadTemplate(
        {
            name:           "Chromosome_Gene",
        
            constraint1:    "Gene.chromosome.primaryIdentifier",
            op1:            "=",
            value1:         "2L",
            code1:          "A",
        
            constraint2:    "Gene.organism.name",
            op2:            "=",
            value2:         "Drosophila melanogaster",
            code2:          "B"
        },
        '#styleDemo',
        {baseUrl: flyMineBase}
    );
}

function loadGraph1() {
    IMBedding.loadQuery(
        {
            select: ["Employee.age", "Employee.department.company.name"],
            from: "testmodel"
        },
        {size: 1000, format: "jsonpobjects"},
        function(resultSet) {
            var graphData = [];
            var ageSum = 0;
            var countAtAgeAtCompany = {};
            for (i in resultSet.results) {
                var employee = resultSet.results[i];
                var age = employee.age;
                var company = employee.department.company.name
                ageSum += age;
                if (! countAtAgeAtCompany[company]) {
                    countAtAgeAtCompany[company] = {};
                }
                if (! countAtAgeAtCompany[company][age]) {
                    countAtAgeAtCompany[company][age] = 1;
                } else {
                    countAtAgeAtCompany[company][age] 
                        = countAtAgeAtCompany[company][age] + 1;
                }
            }
            for (name in countAtAgeAtCompany) {
                var company = countAtAgeAtCompany[name];
                var count = 0;
                var sum = 0;
                var companyData = {
                    data: []
                }
                for (age in company) {
                    count += company[age];
                    sum += age * company[age];
                    companyData.data.push([age, company[age]]);
                }
                var companyAverage = parseInt(sum / count);
                companyData.label = 
                    name + " [av: " + companyAverage + "]";
                graphData.push(companyData);
            }
            var options = {
                series: {
                    stack: true,
                    lines: {show: false},
                    bars: {show: true, barWidth: 0.9}
                },
                legend: {position: "nw"}
            };
            var plot = $.plot("#graph", graphData, options);
            var averageAge = parseInt(ageSum / resultSet.results.length);
            $('<span></span>').html("Age (average:" + averageAge + ")")
                              .addClass("axis-label").appendTo('#graph');
        }
    );
}

function showTooltip(x, y, content) {
     $('<div id="tooltip"></div>').html(content)
                                  .addClass("tooltip")
                                  .css( {
        position:             'absolute',
        display:              'none',
        top:                  y + 10,
        left:                 x + 10,
        border:               '2px solid #FF0084',
        padding:              '5px',
        'border-radius':      '5px',
        '-moz-border-radius': '5px',
        'background-color':   '#FE45A5',
        color:                "white",
        opacity:              0.70
      }).appendTo("body").fadeIn(200);
}

function findLineByLeastSquares(datapoints) {
    var sum_x = 0;
    var sum_y = 0;
    var sum_xy = 0;
    var sum_xx = 0;
    var count = 0;
    
    /*
     * We'll use those variables for faster read/write access.
     */
    var x = 0;
    var y = 0;
    var values_length = datapoints.length;
    
    /*
     * Nothing to do.
     */
    if (values_length === 0) {
        return [ ];
    }
    
    /*
     * Calculate the sum for each of the parts necessary.
     */
    for (var i = 0; i < values_length; i++) {
        x = datapoints[i][0];
        y = datapoints[i][1];
        sum_x += x;
        sum_y += y;
        sum_xx += x*x;
        sum_xy += x*y;
        count++;
    }
    
    /*
     * Calculate m and b for the formular:
     * y = x * m + b
     */
    var m = (count*sum_xy - sum_x*sum_y) / (count*sum_xx - sum_x*sum_x);
    var b = (sum_y/count) - (m*sum_x)/count;
    
    /*
     * We will make the x and y result line now
     */
    var data = [];
    
    for (var i = 0; i < values_length; i++) {
        x = datapoints[i][0];
        y = x * m + b;
        data.push([x, y]);
    }
    
    return data;
}

function loadGraph2() {
    IMBedding.loadQuery(
        {
            select: ["Manager.age", "Manager.seniority", "Manager.name"],
            where: [{path: "Manager.age", op: ">", value: 30}],
            from: "testmodel"
        },
        {size: 1000, format: "jsonpobjects"},
        function(resultSet) {
            var graphData = [];
            var managers = {};
            var ageVsSen = {
                label: "Seniority by Age",
                color: "rgb(0, 115, 234)",
                points: {show: true},
                data: []
            };
            var trendLine = {
                label: "Trend Line",
                color: "rgb(255, 0, 132)",
                lines: {show: true}
            };
            for (i in resultSet.results) {
                var manager = resultSet.results[i];
                var seniority =manager.seniority;
                var age = manager.age;
                ageVsSen.data.push([age, seniority]);
                managers[age + "-" + seniority] = manager;
            }
            trendLine.data = findLineByLeastSquares(ageVsSen.data);
            graphData.push(ageVsSen);
            graphData.push(trendLine);
            var options = {
                grid: {hoverable: true, clickable: true},
                legend: {position: "nw"}
            };
            var plot = $.plot("#graph", graphData, options);
            $('#graph').bind("plothover", function(event, pos, item) {
                if (item) {
                    $("#tooltip").remove();
                    var x = item.datapoint[0].toFixed(2),
                        y = item.datapoint[1].toFixed(2);
                    var key = parseInt(x) + "-" + parseInt(y);
                    var manager = managers[key];
                    showTooltip(item.pageX, item.pageY, manager.name);
                }
                else {
                    $("#tooltip").remove();
                    previousPoint = null;            
                }
            }).bind("plotclick", function(event, pos, item) {
                if (item) {
                    var x = item.datapoint[0].toFixed(2),
                        y = item.datapoint[1].toFixed(2);
                    var key = parseInt(x) + "-" + parseInt(y);
                    var manager = managers[key];
                    var url = baseUrl + "/objectDetails.do?id=" 
                                + manager.objectId;
                    window.location.replace(url);
                }
            });
            $('<span></span>').html("Age").addClass("axis-label").appendTo('#graph');
        }
    );
}

function loadDepartmentSummary(departmentName) {
    departmentName = departmentName || "Sales";
    IMBedding.loadQuery(
        {
            select: [
                "Department.name", "Department.company.name", 
                "Department.employees.name", 
                "Department.employees.age", 
                "Department.employees.address.address", 
                "Department.manager.name",
                "Department.company.departments.name"
            ],
            where: [
                {
                    path: "Department.name", 
                    op: "=", value: departmentName
                },
                {
                    path: "Department.company.name", 
                    op: "=", value: "Wernham-Hogg"
                }
            ],
            from: "testmodel"
        },
        {size: 1000, format: "jsonpobjects"},
        function(resultSet) {
            var department = resultSet.results[0];
            var summary = $('<div></div>').addClass("department-summary");
            var title = document.createElement("h2");
            title.appendChild(document.createTextNode(
                        department.company.name + ": "));
            var depSelect = document.createElement("select");
            $(depSelect).button();
            var noOfDeps = department.company.departments.length;
            for (var i = 0; i < noOfDeps; i++) {
                var dep = department.company.departments[i];
                var depOption = document.createElement("option");
                if (dep.objectId == department.objectId) {
                    depOption.selected = true;
                }
                depOption.innerHTML = dep.name;
                depSelect.appendChild(depOption);
            }
            title.appendChild(depSelect);
            $(depSelect).change(function() {
                loadDepartmentSummary($(depSelect).val());
            });
            summary.append(title);
            var subtitle = document.createElement("h3");
            subtitle.innerHTML = "Manager: " + department.manager.name;
            summary.append(subtitle);
            var employeeCount = department.employees.length;
            var list = document.createElement("ul");
            for (var i = 0; i < employeeCount; i++) {
                var employee = department.employees[i];
                if (employee.objectId == department.manager.objectId) {
                    continue;
                }
                var item = document.createElement("li");
                var link = document.createElement("a");
                link.href = baseUrl + "/objectDetails.do?id=" 
                                    + employee.objectId;
                link.innerHTML = employee.name;
                item.appendChild(link);
                $(link).hover(
                    getEmployeeTooltipper(employee),
                    function(event) {
                        $('.tooltip').remove();
                    }
                );
                list.appendChild(item);
            }
            summary.append(list);
            $('#graph').empty().append(summary);
        }
    );
};

var getEmployeeTooltipper = function(employee) {
    return function(event) {
        var tooltip = document.createElement("div");
        var ttTitle = document.createElement("h3");
        ttTitle.innerHTML = employee.name;
        tooltip.appendChild(ttTitle);
        var table = document.createElement("table");
        table.className = "employee-details";
        var rowA = document.createElement("tr");
        var cellA1 = document.createElement("td");
        cellA1.innerHTML = "Age:";
        cellA1.className = "summary-cell";
        var cellA2 = document.createElement("td");
        cellA2.innerHTML = employee.age;
        cellA2.align = "right";
        cellA2.className = "summary-cell";
        rowA.appendChild(cellA1);
        rowA.appendChild(cellA2);
        table.appendChild(rowA);
        var rowB = document.createElement("tr");
        var cellB1 = document.createElement("td");
        cellB1.innerHTML = "Address:";
        cellB1.className = "summary-cell";
        var cellB2 = document.createElement("td");
        cellB2.innerHTML = employee.address.address;
        cellB2.className = "summary-cell";
        rowB.appendChild(cellB1);
        rowB.appendChild(cellB2);
        table.appendChild(rowB);
        tooltip.appendChild(table);
        var x = event.pageX;
        var y = event.pageY;
        showTooltip(x, y, tooltip);
    };
};

var toggleExample = function() {
    $('#exampleCode').slideToggle('fast', function(){});
    $('#querybuilder').slideToggle('fast', function(){});
};

var firstline = "/* Below is the Javascript to load this table using ajax:\n"
+ "You can cut and paste this into a page to get started.\n"
+ "Don't forget you need to include the imbedding.js library"
+ " in your head */\n\n"
+ '/* You only need to do the following once */' + "\n";

var JSON = JSON || {};
// implement JSON.stringify serialization
JSON.stringify = JSON.stringify || function (obj) {
    var t = typeof (obj);
    if (t != "object" || obj === null) {
        // simple data type
        if (t == "string") obj = '"'+obj+'"';
        return String(obj);
    }
    else {
        // recurse array or object
        var n, v, json = [], arr = (obj && obj.constructor == Array);
        for (n in obj) {
            v = obj[n]; t = typeof(v);
            if (t == "string") v = '"'+v+'"';
            else if (t == "object" && v !== null) v = JSON.stringify(v);
            json.push((arr ? "" : '"' + n + '":') + String(v));
        }
        return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
    }
};

var getQueryFromForm = function() {
    var rootClass = $("#root-class").val();
    var views = [];
    var viewsFormValues = $("#views-form").serializeArray();
    for (var i = 0; i < viewsFormValues.length; i++) {
        var nameValuePair = viewsFormValues[i];
        views.push(rootClass + "." + nameValuePair.value);
    }
    var constraints = {};
    var consFormValues = $("#constraints-form").serializeArray();
    var typeConstraints = {};
    for (var i = 0; i < consFormValues.length; i++) {
        var nameValuePair = consFormValues[i];
        var consNo = nameValuePair.name.match(/\d+/)[0];
        if (! constraints[consNo]) {
            constraints[consNo] = {
                code: letters.charAt(parseInt(consNo) - 1)
            };
        }
        var consProp = nameValuePair.name.match(/[a-z]+/)[0];
        if (consProp == "constraint") {
            constraints[consNo].path
                = rootClass + "." + nameValuePair.value;
        } else if (consProp == "op") {
            if (nameValuePair.value == "ISA") {
                typeConstraints[consNo] = true;
            } else {
                constraints[consNo].op = nameValuePair.value;
            }
        } else if (consProp == "value") {
            if (typeConstraints[consNo]) {
                constraints[consNo].type = nameValuePair.value;
            } else {
                constraints[consNo].value = nameValuePair.value;
            }
        } else {
            throw("Unexpected constraint property: " + consProp);
        }
    }
    var constraintsList = [];
    for (key in constraints) {
        constraintsList.push(constraints[key]);
    }
    var joinsFormsValues = $('#joins-form').serializeArray();
    var joins = {};
    for (var i = 0; i < joinsFormsValues.length; i++) {
        var nameValuePair = joinsFormsValues[i];
        var joinNo = nameValuePair.name.match(/\d+/)[0];
        if (! joins[joinNo]) {
            joins[joinNo] = {};
        }
        var joinProp = nameValuePair.name.match(/[a-z]+/)[0];
        if (joinProp == "join") {
            joins[joinNo].path
                = rootClass + "." + nameValuePair.value;
        } else if (joinProp == "style") {
            joins[joinNo].style = nameValuePair.value;
        } else {
            throw("Unexpected join property: " + joinProp);
        }
    }
    var joinList = [];
    for (key in joins) {
        joinList.push(joins[key]);
    }

    var sortOrder = $('#sortOrderSelector').val() + " "
       + $('input:radio[name=sortDirection]:checked').val();

    var logic = $('#logic').val();

    var query = {
        select: views,
        where: constraintsList,
        joins: joinList,
        sortOrder: sortOrder,
        from: model.name
    };

    if (logic.length > 0) {
        query.constraintLogic = logic;
    }
    return query;
};

var getQueryFromBox = function() {
    var format = $('#boxselector').val();
    if (format == "xml") {
        return $('#xmlarea').val();
    } else if (format == "json") {
        var jsonString = $('#jsonarea').val();
        var parsedQuery;
        try {
            parsedQuery = eval('(' + jsonString + ')');
        } catch(e) {
            alert("Something is wrong with your json\n" + e);
        }
        return parsedQuery;
    } else {
        return null;
    }
};

var makeQueryDisplayStrings = function(query) {
    if (! jQuery.isPlainObject(query)) {
        // assume it is xml
        var xmlString = query
                            .replace(/&gt;/g, "&amp;gt;")
                            .replace(/&lt;/g, "&amp;lt;")
                            .replace(/</g, "&lt;")
                            .replace(/>/g, "&gt;");
        return [null, xmlString];
    }
    // Make the displayed json string
    // It needs munging to prettify it as well
    var jsonString = JSON.stringify(query);
    var keys = jsonString.match(/"\w+":/g);
    if (keys) {
        for (var i = 0; i < keys.length; i++) {
            var key = keys[i];
            var newKey = key.replace(/"/g, "").replace(":", ": ");
            jsonString = jsonString.replace(key, newKey);
        }
    }
    jsonString = jsonString.replace(/\}\],/g, "}\n\t],")
                            .replace(/\},\{/g, "},\n\t{")
                            .replace(/\],/g, "],\n\t")
                            .replace(/^\{/, "{\n\t")
                            .replace(/\[\{/g, "[\n\t{")
                            .replace(/\}$/, "\n}")
                            .replace(/",/g, "\", ")
                            .replace(/\t\{/g, "\t\t{");
    var xmlString = IMBedding.makeQueryXML(query)
                            .replace(/&gt;/g, "&amp;gt;")
                            .replace(/&lt;/g, "&amp;lt;")
                            .replace(/</g, "&lt;")
                            .replace(/>/g, "&gt;");
    return [jsonString, xmlString];
};

function loadUserQuery() {
    var source = $('input:radio[name=query]:checked').val();
    var query;
    if (source == "querybuilder") {
        query = getQueryFromForm();
    } else {
        query = getQueryFromBox();
    }
    if (! query) {
        return false;
    }
    var displayStrings = makeQueryDisplayStrings(query);
    if (! displayStrings) {
        return false;
    }

    var data = {size: 10};
    var newValue = firstline + "IMBedding.setBaseUrl('";

    var urlToQuery = flyMineBase;
    newValue += urlToQuery + "');\n\n";
    var opts = {baseUrl: urlToQuery};

    if (displayStrings[0]) {
        newValue 
            += "/*You can define the query as a regular javascript object*/\n"
            +  "var query = " + displayStrings[0] + ";\n";<commit_msg>Added a demonstration of click customisation<commit_after>availableTemplates = null;
var model = {};
var baseUrl = "http://squirrel.flymine.org/intermine-test";
var flyMineBase = "http://preview.flymine.org/preview";
$(function() {
    IMBedding.setBaseUrl(baseUrl);
    Syntax.root = "http://squirrel.flymine.org/imbedding/lib/jquery-syntax/";
    $('.js-snippet').syntax({
        brush: 'javascript', 
        layout: 'list', 
        replace: true,
        tabWidth: 4,
        root: "lib/jquery-syntax/"
    });
    $('.html-snippet').syntax({
        brush: 'html', 
        layout: 'list', 
        replace: true,
        tabWidth: 4,
        root: "lib/jquery-syntax/"
    });
    $('#showGraphAreaContainer').hide();
    loadTable1();
    loadTable3a();
    loadTable3b();
    loadTable3c();
    loadTable4a();
    loadTable4b();
    loadTable4c();
    loadTable4d();
    loadTable4();
    loadTable5();
    $('#faq').accordion({collapsible: true, autoHeight: false});
});

function setActiveStyleSheet(title) {
    var i, a, main;
    for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
        if(a.getAttribute("rel").indexOf("style") != -1
                && a.getAttribute("title")) {
            a.disabled = true;
            if(a.getAttribute("title") == title) a.disabled = false;
        }
    }
}

function loadTable1() {
    IMBedding.loadTemplate(
        {
            name:           "Gene_Identifiers",

            constraint1:    "Gene.secondaryIdentifier",
            op1:            "<",
            value1:         "CG1046",
            code1:          "A" 
        },
        "#placeholderEx2",
        {openOnLoad: true, baseUrl: flyMineBase}
    );
}
function loadTable2() {
    IMBedding.loadTemplate(
        {
            name:           "Gene_upstreamRegulatoryRegions",

            constraint1:    "Gene",
            op1:            "LOOKUP",
            value1:         "eve",
            code1:          "A"
        },
        "#positionExample",
        {baseUrl: flyMineBase}
    );
}
function loadTable3a() {
    IMBedding.loadTemplate(
        {
            name:           "Gene_allGOTerms2",

            constraint1:    "Gene",
            op1:            "LOOKUP",
            value1:         "CG11348",
            code1:          "A"
        },
        "#placeholderEx3a",
        {onTitleClick: "mine", baseUrl: flyMineBase}
    );
}

function loadTable3b() {
    IMBedding.loadTemplate(
        {
            name:           "Gene_allGOTerms2",
            size: 10,

            constraint1:    "Gene",
            op1:            "LOOKUP",
            value1:         "CG11348",
            code1:          "A"
        },
        "#placeholderEx3b",
        {onTitleClick: "none", baseUrl: flyMineBase}
    );
}

function loadTable3c() {
    var callback = function() {
        alert( "You clicked on:\n" + $(this).text());
    };
    IMBedding.loadTemplate(
        {
            name:           "Gene_allGOTerms2",
            size: 10,

            constraint1:    "Gene",
            op1:            "LOOKUP",
            value1:         "CG11348",
            code1:          "A"
        },
        "#placeholderEx3c",
        {onTitleClick: callback, titleHoverCursor: "help", baseUrl: flyMineBase}
    );
}

function loadTable4a() {
    IMBedding.loadTemplate(
        {
            name:           "Organism_GeneDomain_new",
            size: 10,

            constraint1:    "ProteinDomain.proteins.genes.organism.name",
            op1:            "=",
            value1:         "Drosophila melanogaster",
            code1:          "A",

            constraint2:    "ProteinDomain.shortName",
            op2:            "=",
            value2:         "*homeo*",
            code2:          "B"
        },
        "#placeholderEx4a",
        {showExportLinks: false, baseUrl: flyMineBase}
    );
}

function loadTable4b() {
    IMBedding.loadTemplate(
        {
            name:           "Organism_GeneDomain_new",
            size: 10,

            constraint1:    "ProteinDomain.proteins.genes.organism.name",
            op1:            "=",
            value1:         "Drosophila melanogaster",
            code1:          "A",

            constraint2:    "ProteinDomain.shortName",
            op2:            "=",
            value2:         "*homeo*",
            code2:          "B"
        },
        "#placeholderEx4b",
        {showCount: false, baseUrl: flyMineBase}
    );
}
function loadTable4c() {
    IMBedding.loadTemplate(
        {
            name:           "Organism_GeneDomain_new",
            size: 10,

            constraint1:    "ProteinDomain.proteins.genes.organism.name",
            op1:            "=",
            value1:         "Drosophila melanogaster",
            code1:          "A",

            constraint2:    "ProteinDomain.shortName",
            op2:            "=",
            value2:         "*homeo*",
            code2:          "B"
        },
        "#placeholderEx4c",
        {showMineLink: false, baseUrl: flyMineBase}
    );
}
function loadTable4d() {
    IMBedding.loadTemplate(
        {
            name:           "Organism_GeneDomain_new",
            size: 15,

            constraint1:    "ProteinDomain.proteins.genes.organism.name",
            op1:            "=",
            value1:         "Drosophila melanogaster",
            code1:          "A",

            constraint2:    "ProteinDomain.shortName",
            op2:            "=",
            value2:         "*homeo*",
            code2:          "B"
        },
        "#placeholderEx4d",
        {baseUrl: flyMineBase}
    );
}
function loadTable4() {
    IMBedding.loadTemplate(
        {
            name:           "Chromosome_Gene",
        
            constraint1:    "Gene.chromosome.primaryIdentifier",
            op1:            "=",
            value1:         "2L",
            code1:          "A",
        
            constraint2:    "Gene.organism.name",
            op2:            "=",
            value2:         "Drosophila melanogaster",
            code2:          "B"
        },
        '#placeholder1',
        {baseUrl: flyMineBase}
    );
}

function loadTable5() {
    IMBedding.loadTemplate(
        {
            name:           "Chromosome_Gene",
        
            constraint1:    "Gene.chromosome.primaryIdentifier",
            op1:            "=",
            value1:         "2L",
            code1:          "A",
        
            constraint2:    "Gene.organism.name",
            op2:            "=",
            value2:         "Drosophila melanogaster",
            code2:          "B"
        },
        '#styleDemo',
        {baseUrl: flyMineBase}
    );
}

function loadGraph1() {
    IMBedding.loadQuery(
        {
            select: ["Employee.age", "Employee.department.company.name"],
            from: "testmodel"
        },
        {size: 1000, format: "jsonpobjects"},
        function(resultSet) {
            var graphData = [];
            var ageSum = 0;
            var countAtAgeAtCompany = {};
            for (i in resultSet.results) {
                var employee = resultSet.results[i];
                var age = employee.age;
                var company = employee.department.company.name
                ageSum += age;
                if (! countAtAgeAtCompany[company]) {
                    countAtAgeAtCompany[company] = {};
                }
                if (! countAtAgeAtCompany[company][age]) {
                    countAtAgeAtCompany[company][age] = 1;
                } else {
                    countAtAgeAtCompany[company][age] 
                        = countAtAgeAtCompany[company][age] + 1;
                }
            }
            for (name in countAtAgeAtCompany) {
                var company = countAtAgeAtCompany[name];
                var count = 0;
                var sum = 0;
                var companyData = {
                    data: []
                }
                for (age in company) {
                    count += company[age];
                    sum += age * company[age];
                    companyData.data.push([age, company[age]]);
                }
                var companyAverage = parseInt(sum / count);
                companyData.label = 
                    name + " [av: " + companyAverage + "]";
                graphData.push(companyData);
            }
            var options = {
                series: {
                    stack: true,
                    lines: {show: false},
                    bars: {show: true, barWidth: 0.9}
                },
                legend: {position: "nw"}
            };
            var plot = $.plot("#graph", graphData, options);
            var averageAge = parseInt(ageSum / resultSet.results.length);
            $('<span></span>').html("Age (average:" + averageAge + ")")
                              .addClass("axis-label").appendTo('#graph');
        }
    );
}

function showTooltip(x, y, content) {
     $('<div id="tooltip"></div>').html(content)
                                  .addClass("tooltip")
                                  .css( {
        position:             'absolute',
        display:              'none',
        top:                  y + 10,
        left:                 x + 10,
        border:               '2px solid #FF0084',
        padding:              '5px',
        'border-radius':      '5px',
        '-moz-border-radius': '5px',
        'background-color':   '#FE45A5',
        color:                "white",
        opacity:              0.70
      }).appendTo("body").fadeIn(200);
}

function findLineByLeastSquares(datapoints) {
    var sum_x = 0;
    var sum_y = 0;
    var sum_xy = 0;
    var sum_xx = 0;
    var count = 0;
    
    /*
     * We'll use those variables for faster read/write access.
     */
    var x = 0;
    var y = 0;
    var values_length = datapoints.length;
    
    /*
     * Nothing to do.
     */
    if (values_length === 0) {
        return [ ];
    }
    
    /*
     * Calculate the sum for each of the parts necessary.
     */
    for (var i = 0; i < values_length; i++) {
        x = datapoints[i][0];
        y = datapoints[i][1];
        sum_x += x;
        sum_y += y;
        sum_xx += x*x;
        sum_xy += x*y;
        count++;
    }
    
    /*
     * Calculate m and b for the formular:
     * y = x * m + b
     */
    var m = (count*sum_xy - sum_x*sum_y) / (count*sum_xx - sum_x*sum_x);
    var b = (sum_y/count) - (m*sum_x)/count;
    
    /*
     * We will make the x and y result line now
     */
    var data = [];
    
    for (var i = 0; i < values_length; i++) {
        x = datapoints[i][0];
        y = x * m + b;
        data.push([x, y]);
    }
    
    return data;
}

function loadGraph2() {
    IMBedding.loadQuery(
        {
            select: ["Manager.age", "Manager.seniority", "Manager.name"],
            where: [{path: "Manager.age", op: ">", value: 30}],
            from: "testmodel"
        },
        {size: 1000, format: "jsonpobjects"},
        function(resultSet) {
            var graphData = [];
            var managers = {};
            var ageVsSen = {
                label: "Seniority by Age",
                color: "rgb(0, 115, 234)",
                points: {show: true},
                data: []
            };
            var trendLine = {
                label: "Trend Line",
                color: "rgb(255, 0, 132)",
                lines: {show: true}
            };
            for (i in resultSet.results) {
                var manager = resultSet.results[i];
                var seniority =manager.seniority;
                var age = manager.age;
                ageVsSen.data.push([age, seniority]);
                managers[age + "-" + seniority] = manager;
            }
            trendLine.data = findLineByLeastSquares(ageVsSen.data);
            graphData.push(ageVsSen);
            graphData.push(trendLine);
            var options = {
                grid: {hoverable: true, clickable: true},
                legend: {position: "nw"}
            };
            var plot = $.plot("#graph", graphData, options);
            $('#graph').bind("plothover", function(event, pos, item) {
                if (item) {
                    $("#tooltip").remove();
                    var x = item.datapoint[0].toFixed(2),
                        y = item.datapoint[1].toFixed(2);
                    var key = parseInt(x) + "-" + parseInt(y);
                    var manager = managers[key];
                    showTooltip(item.pageX, item.pageY, manager.name);
                }
                else {
                    $("#tooltip").remove();
                    previousPoint = null;            
                }
            }).bind("plotclick", function(event, pos, item) {
                if (item) {
                    var x = item.datapoint[0].toFixed(2),
                        y = item.datapoint[1].toFixed(2);
                    var key = parseInt(x) + "-" + parseInt(y);
                    var manager = managers[key];
                    var url = baseUrl + "/objectDetails.do?id=" 
                                + manager.objectId;
                    window.location.replace(url);
                }
            });
            $('<span></span>').html("Age").addClass("axis-label").appendTo('#graph');
        }
    );
}

function loadDepartmentSummary(departmentName) {
    departmentName = departmentName || "Sales";
    IMBedding.loadQuery(
        {
            select: [
                "Department.name", "Department.company.name", 
                "Department.employees.name", 
                "Department.employees.age", 
                "Department.employees.address.address", 
                "Department.manager.name",
                "Department.company.departments.name"
            ],
            where: [
                {
                    path: "Department.name", 
                    op: "=", value: departmentName
                },
                {
                    path: "Department.company.name", 
                    op: "=", value: "Wernham-Hogg"
                }
            ],
            from: "testmodel"
        },
        {size: 1000, format: "jsonpobjects"},
        function(resultSet) {
            var department = resultSet.results[0];
            var summary = $('<div></div>').addClass("department-summary");
            var title = document.createElement("h2");
            title.appendChild(document.createTextNode(
                        department.company.name + ": "));
            var depSelect = document.createElement("select");
            $(depSelect).button();
            var noOfDeps = department.company.departments.length;
            for (var i = 0; i < noOfDeps; i++) {
                var dep = department.company.departments[i];
                var depOption = document.createElement("option");
                if (dep.objectId == department.objectId) {
                    depOption.selected = true;
                }
                depOption.innerHTML = dep.name;
                depSelect.appendChild(depOption);
            }
            title.appendChild(depSelect);
            $(depSelect).change(function() {
                loadDepartmentSummary($(depSelect).val());
            });
            summary.append(title);
            var subtitle = document.createElement("h3");
            subtitle.innerHTML = "Manager: " + department.manager.name;
            summary.append(subtitle);
            var employeeCount = department.employees.length;
            var list = document.createElement("ul");
            for (var i = 0; i < employeeCount; i++) {
                var employee = department.employees[i];
                if (employee.objectId == department.manager.objectId) {
                    continue;
                }
                var item = document.createElement("li");
                var link = document.createElement("a");
                link.href = baseUrl + "/objectDetails.do?id=" 
                                    + employee.objectId;
                link.innerHTML = employee.name;
                item.appendChild(link);
                $(link).hover(
                    getEmployeeTooltipper(employee),
                    function(event) {
                        $('.tooltip').remove();
                    }
                );
                list.appendChild(item);
            }
            summary.append(list);
            $('#graph').empty().append(summary);
        }
    );
};

var getEmployeeTooltipper = function(employee) {
    return function(event) {
        var tooltip = document.createElement("div");
        var ttTitle = document.createElement("h3");
        ttTitle.innerHTML = employee.name;
        tooltip.appendChild(ttTitle);
        var table = document.createElement("table");
        table.className = "employee-details";
        var rowA = document.createElement("tr");
        var cellA1 = document.createElement("td");
        cellA1.innerHTML = "Age:";
        cellA1.className = "summary-cell";
        var cellA2 = document.createElement("td");
        cellA2.innerHTML = employee.age;
        cellA2.align = "right";
        cellA2.className = "summary-cell";
        rowA.appendChild(cellA1);
        rowA.appendChild(cellA2);
        table.appendChild(rowA);
        var rowB = document.createElement("tr");
        var cellB1 = document.createElement("td");
        cellB1.innerHTML = "Address:";
        cellB1.className = "summary-cell";
        var cellB2 = document.createElement("td");
        cellB2.innerHTML = employee.address.address;
        cellB2.className = "summary-cell";
        rowB.appendChild(cellB1);
        rowB.appendChild(cellB2);
        table.appendChild(rowB);
        tooltip.appendChild(table);
        var x = event.pageX;
        var y = event.pageY;
        showTooltip(x, y, tooltip);
    };
};

var toggleExample = function() {
    $('#exampleCode').slideToggle('fast', function(){});
    $('#querybuilder').slideToggle('fast', function(){});
};

var firstline = "/* Below is the Javascript to load this table using ajax:\n"
+ "You can cut and paste this into a page to get started.\n"
+ "Don't forget you need to include the imbedding.js library"
+ " in your head */\n\n"
+ '/* You only need to do the following once */' + "\n";

var JSON = JSON || {};
// implement JSON.stringify serialization
JSON.stringify = JSON.stringify || function (obj) {
    var t = typeof (obj);
    if (t != "object" || obj === null) {
        // simple data type
        if (t == "string") obj = '"'+obj+'"';
        return String(obj);
    }
    else {
        // recurse array or object
        var n, v, json = [], arr = (obj && obj.constructor == Array);
        for (n in obj) {
            v = obj[n]; t = typeof(v);
            if (t == "string") v = '"'+v+'"';
            else if (t == "object" && v !== null) v = JSON.stringify(v);
            json.push((arr ? "" : '"' + n + '":') + String(v));
        }
        return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}");
    }
};

var getQueryFromForm = function() {
    var rootClass = $("#root-class").val();
    var views = [];
    var viewsFormValues = $("#views-form").serializeArray();
    for (var i = 0; i < viewsFormValues.length; i++) {
        var nameValuePair = viewsFormValues[i];
        views.push(rootClass + "." + nameValuePair.value);
    }
    var constraints = {};
    var consFormValues = $("#constraints-form").serializeArray();
    var typeConstraints = {};
    for (var i = 0; i < consFormValues.length; i++) {
        var nameValuePair = consFormValues[i];
        var consNo = nameValuePair.name.match(/\d+/)[0];
        if (! constraints[consNo]) {
            constraints[consNo] = {
                code: letters.charAt(parseInt(consNo) - 1)
            };
        }
        var consProp = nameValuePair.name.match(/[a-z]+/)[0];
        if (consProp == "constraint") {
            constraints[consNo].path
                = rootClass + "." + nameValuePair.value;
        } else if (consProp == "op") {
            if (nameValuePair.value == "ISA") {
                typeConstraints[consNo] = true;
            } else {
                constraints[consNo].op = nameValuePair.value;
            }
        } else if (consProp == "value") {
            if (typeConstraints[consNo]) {
                constraints[consNo].type = nameValuePair.value;
            } else {
                constraints[consNo].value = nameValuePair.value;
            }
        } else {
            throw("Unexpected constraint property: " + consProp);
        }
    }
    var constraintsList = [];
    for (key in constraints) {
        constraintsList.push(constraints[key]);
    }
    var joinsFormsValues = $('#joins-form').serializeArray();
    var joins = {};
    for (var i = 0; i < joinsFormsValues.length; i++) {
        var nameValuePair = joinsFormsValues[i];
        var joinNo = nameValuePair.name.match(/\d+/)[0];
        if (! joins[joinNo]) {
            joins[joinNo] = {};
        }
        var joinProp = nameValuePair.name.match(/[a-z]+/)[0];
        if (joinProp == "join") {
            joins[joinNo].path
                = rootClass + "." + nameValuePair.value;
        } else if (joinProp == "style") {
            joins[joinNo].style = nameValuePair.value;
        } else {
            throw("Unexpected join property: " + joinProp);
        }
    }
    var joinList = [];
    for (key in joins) {
        joinList.push(joins[key]);
    }

    var sortOrder = $('#sortOrderSelector').val() + " "
       + $('input:radio[name=sortDirection]:checked').val();

    var logic = $('#logic').val();

    var query = {
        select: views,
        where: constraintsList,
        joins: joinList,
        sortOrder: sortOrder,
        from: model.name
    };

    if (logic.length > 0) {
        query.constraintLogic = logic;
    }
    return query;
};

var getQueryFromBox = function() {
    var format = $('#boxselector').val();
    if (format == "xml") {
        return $('#xmlarea').val();
    } else if (format == "json") {
        var jsonString = $('#jsonarea').val();
        var parsedQuery;
        try {
            parsedQuery = eval('(' + jsonString + ')');
        } catch(e) {
            alert("Something is wrong with your json\n" + e);
        }
        return parsedQuery;
    } else {
        return null;
    }
};

var makeQueryDisplayStrings = function(query) {
    if (! jQuery.isPlainObject(query)) {
        // assume it is xml
        var xmlString = query
                            .replace(/&gt;/g, "&amp;gt;")
                            .replace(/&lt;/g, "&amp;lt;")
                            .replace(/</g, "&lt;")
                            .replace(/>/g, "&gt;");
        return [null, xmlString];
    }
    // Make the displayed json string
    // It needs munging to prettify it as well
    var jsonString = JSON.stringify(query);
    var keys = jsonString.match(/"\w+":/g);
    if (keys) {
        for (var i = 0; i < keys.length; i++) {
            var key = keys[i];
            var newKey = key.replace(/"/g, "").replace(":", ": ");
            jsonString = jsonString.replace(key, newKey);
        }
    }
    jsonString = jsonString.replace(/\}\],/g, "}\n\t],")
                            .replace(/\},\{/g, "},\n\t{")
                            .replace(/\],/g, "],\n\t")
                            .replace(/^\{/, "{\n\t")
                            .replace(/\[\{/g, "[\n\t{")
                            .replace(/\}$/, "\n}")
                            .replace(/",/g, "\", ")
                            .replace(/\t\{/g, "\t\t{");
    var xmlString = IMBedding.makeQueryXML(query)
                            .replace(/&gt;/g, "&amp;gt;")
                            .replace(/&lt;/g, "&amp;lt;")
                            .replace(/</g, "&lt;")
                            .replace(/>/g, "&gt;");
    return [jsonString, xmlString];
};

function loadUserQuery() {
    var source = $('input:radio[name=query]:checked').val();
    var query;
    if (source == "querybuilder") {
        query = getQueryFromForm();
    } else {
        query = getQueryFromBox();
    }
    if (! query) {
        return false;
    }
    var displayStrings = makeQueryDisplayStrings(query);
    if (! displayStrings) {
        return false;
    }

    var data = {size: 10};
    var newValue = firstline + "IMBedding.setBaseUrl('";

    var urlToQuery = flyMineBase;
    newValue += urlToQuery + "');\n\n";
    var opts = {baseUrl: urlToQuery};

    if (displayStrings[0]) {
        newValue 
            += "/*You can define the query as a regular javascript object*/\n"
            +  "var query = " + displayStrings[0] + ";\n";
{'fraction_non_alphanumeric': 0.13954152973116413, 'fraction_numerical': 0.010063483639184306, 'mean_word_length': 1.4299389911214722, 'pattern_counts': {'":': 10, '<': 41, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 14}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5526873', 'n_tokens_mistral': 14409, 'n_tokens_neox': 13696, 'n_words': 2771}