<commit_before>define([
    'knockout',
    'underscore',
    'knockout-mapping',
    'uuid'
], function(ko, _, koMapping, uuid) {
    STEPS_LABEL = 'workflow-steps';
    STEP_ID_LABEL = 'workflow-step-id';

    var WorkflowStep = function(config) {
        var self = this;

        this.id = ko.observable();
        this.workflowId = ko.observable(config.workflow ? config.workflow.id : null);

        this.classUnvisited = 'workflow-step-icon';
        this.classActive = 'workflow-step-icon active';
        this.classComplete = 'workflow-step-icon complete';
        this.classCanAdavance = 'workflow-step-icon can-advance';

        this.icon = 'fa-chevron-circle-right';
        this.title = '';
        this.subtitle = '';
        this.description = '';

        this.informationBoxData = ko.observable();

        this.hasDirtyTile = ko.observable(false);

        this.saving = ko.observable(false);

        this.complete = ko.observable(false);
        this.required = ko.observable(ko.unwrap(config.required));
        this.autoAdvance = ko.observable(true);

        this.preSaveCallback = ko.observable();
        this.postSaveCallback = ko.observable();

        this.externalStepData = {};

        var externalStepSourceData = ko.unwrap(config.externalstepdata) || {};
        Object.keys(externalStepSourceData).forEach(function(key) {
            if (key !== '__ko_mapping__') {
                config.workflow.getStepData(externalStepSourceData[key]).then(function(data) {
                    self.externalStepData[key] = {
                        stepName: externalStepSourceData[key],
                        data: data,
                    };
                });
            }
        });
        delete config.externalstepdata;

        this.value = ko.observable();
        this.value.subscribe(function(value) {
            var getResourceIdFromComponentData = function(componentData) {
                /* iterates over each component in layout */
                return Object.values(componentData).reduce(function(acc, componentDatum) {
                    /* most components store data for a single tile */
                    if (componentDatum instanceof Array && componentDatum.length === 1) {
                        componentDatum = componentDatum[0];
                    }

                    if (!acc && componentDatum.resourceInstanceId) {
                        return componentDatum.resourceInstanceId;
                    }

                    return acc;
                }, null);
            };

            /* if we have defined that this is part of a single-resource workflow, and that this step creates the desired resource */
            if (self.shouldtrackresource && !ko.unwrap(config.workflow.resourceId)) {
                if (value) {
                    var resourceId;

                    if (value.resourceid) {  /* legacy newTileStep */
                        resourceId = value.resourceid
                    }
                    else {  /* component-based-step */
                        resourceId = getResourceIdFromComponentData(value);
                    }

                    config.workflow.resourceId(resourceId);
                }
                else {
                    config.workflow.resourceId(null);
                }
            }
        });

        this.active = ko.computed(function() {
            return config.workflow.activeStep() === this;
        }, this);
        this.active.subscribe(function(active) {
            if (active) {
                self.setStepIdToUrl();
                self.getExternalStepData();
            }
        });

        Object.keys(config).forEach(function(prop){
            if(prop !== 'workflow') {
                config[prop] = koMapping.fromJS(config[prop]);
            }
        });

        this.initialize = function() {
            /* cached ID logic */
            var cachedId = ko.unwrap(config.id);
            if (cachedId) {
                self.id(cachedId)
            }
            else {
                self.id(uuid.generate());
            }

            /* cached value logic */
            var cachedValue = self.getFromLocalStorage('value');
            if (cachedValue) {
                self.value(cachedValue);
                self.complete(true);
            }

            /* set value subscription */
            self.value.subscribe(function(value) {
                self.setToLocalStorage('value', value);
            });

            /* cached informationBox logic */
            this.setupInformationBox();
        };

        this.save = function() {
            /*
                currently SYNCHRONOUS, however async localStore interaction is
                covered by value subscription. This should be refactored when we can.
            */
            var preSaveCallback = ko.unwrap(self.preSaveCallback);
            if (preSaveCallback) {
                preSaveCallback();
            }

            self.setToLocalStorage('value', self.value())

            var postSaveCallback = ko.unwrap(self.postSaveCallback);
            if (postSaveCallback) {
                postSaveCallback();
            }
        };

        this.clearCallback = ko.observable();

        this.clear = function() {
            if (self.hasDirtyTile()) {
                if (ko.unwrap(self.tile)) {
                    self.tile().reset();
                }

                if (ko.unwrap(self.clearCallback)) {
                    self.clearCallback()();
                }
            }
        }

        this.setToLocalStorage = function(key, value) {
            var allStepsLocalStorageData = JSON.parse(localStorage.getItem(STEPS_LABEL)) || {};

            if (!allStepsLocalStorageData[self.id()]) {
                allStepsLocalStorageData[self.id()] = {};
            }

            allStepsLocalStorageData[self.id()][key] = value;

            localStorage.setItem(
                STEPS_LABEL,
                JSON.stringify(allStepsLocalStorageData)
            );
        };

        this.getFromLocalStorage = function(key) {
            var allStepsLocalStorageData = JSON.parse(localStorage.getItem(STEPS_LABEL)) || {};

            if (allStepsLocalStorageData[self.id()]) {
                return allStepsLocalStorageData[self.id()][key];
            }
        };

        this.setStepIdToUrl = function() {
            var searchParams = new URLSearchParams(window.location.search);
            searchParams.set(STEP_ID_LABEL, self.id());

            var newRelativePathQuery = `${window.location.pathname}?${searchParams.toString()}`;
            history.pushState(null, '', newRelativePathQuery);
        };

        this.getExternalStepData = function() {
            Object.keys(self.externalStepData).forEach(function(key) {
                config.workflow.getStepData(externalStepSourceData[key]).then(function(data) {
                    self.externalStepData[key]['data'] = data;
                });
            });
        };

        this.toggleInformationBox = function() {
            var informationBoxData = self.informationBoxData();
            var isDisplayed = informationBoxData['displayed'];

            informationBoxData['displayed'] = !isDisplayed;
            self.informationBoxData(informationBoxData);

            config.informationBoxDisplayed(!isDisplayed);
        };

        this.setupInformationBox = function() {
            if (config.informationBoxDisplayed && config.informationboxdata) {
                var isDisplayed = true;
                if (config.informationBoxDisplayed() !== undefined){
                    isDisplayed = config.informationBoxDisplayed();
                }
                self.informationBoxData({
                    displayed: isDisplayed,
                    heading: config.informationboxdata['heading'],
                    text: config.informationboxdata['text'],
                })
            }
        }

        _.extend(this, config);

        this.iconClass = ko.computed(function(){
            var ret = '';
            if(this.active()){
                ret = this.classActive;
            }else if(this.complete()){
                ret = this.classComplete;
            }else {
                ret = this.classUnvisited;
            }
            return ret + ' ' + ko.unwrap(this.icon);
        }, this);

        this.initialize();
    };

    /* only register template here, params are passed at the workflow level */
    ko.components.register('workflow-step', {
        template: {
            require: 'text!templates/views/components/plugins/workflow-step.htm'
        }
    });

    return WorkflowStep;
});
<commit_msg>nit #741<commit_after>define([
    'knockout',
    'underscore',
    'knockout-mapping',
    'uuid'
], function(ko, _, koMapping, uuid) {
    STEPS_LABEL = 'workflow-steps';
    STEP_ID_LABEL = 'workflow-step-id';

    var WorkflowStep = function(config) {
        var self = this;

        this.id = ko.observable();
        this.workflowId = ko.observable(config.workflow ? config.workflow.id : null);

        this.classUnvisited = 'workflow-step-icon';
        this.classActive = 'workflow-step-icon active';
        this.classComplete = 'workflow-step-icon complete';
        this.classCanAdavance = 'workflow-step-icon can-advance';

        this.icon = 'fa-chevron-circle-right';
        this.title = '';
        this.subtitle = '';
        this.description = '';

        this.informationBoxData = ko.observable();

        this.hasDirtyTile = ko.observable(false);

        this.saving = ko.observable(false);

        this.complete = ko.observable(false);
        this.required = ko.observable(ko.unwrap(config.required));
        this.autoAdvance = ko.observable(true);

        this.preSaveCallback = ko.observable();
        this.postSaveCallback = ko.observable();

        this.externalStepData = {};

        var externalStepSourceData = ko.unwrap(config.externalstepdata) || {};
        Object.keys(externalStepSourceData).forEach(function(key) {
            if (key !== '__ko_mapping__') {
                config.workflow.getStepData(externalStepSourceData[key]).then(function(data) {
                    self.externalStepData[key] = {
                        stepName: externalStepSourceData[key],
                        data: data,
                    };
                });
            }
        });
        delete config.externalstepdata;

        this.value = ko.observable();
        this.value.subscribe(function(value) {
            var getResourceIdFromComponentData = function(componentData) {
                /* iterates over each component in layout */
                return Object.values(componentData).reduce(function(acc, componentDatum) {
                    /* most components store data for a single tile */
                    if (componentDatum instanceof Array && componentDatum.length === 1) {
                        componentDatum = componentDatum[0];
                    }

                    if (!acc && componentDatum.resourceInstanceId) {
                        return componentDatum.resourceInstanceId;
                    }

                    return acc;
                }, null);
            };

            /* if we have defined that this is part of a single-resource workflow, and that this step creates the desired resource */
            if (self.shouldtrackresource && !ko.unwrap(config.workflow.resourceId)) {
                if (value) {
                    var resourceId;

                    if (value.resourceid) {  /* legacy newTileStep */
                        resourceId = value.resourceid
                    }
                    else {  /* component-based-step */
                        resourceId = getResourceIdFromComponentData(value);
                    }

                    config.workflow.resourceId(resourceId);
                }
                else {
                    config.workflow.resourceId(null);
                }
            }
        });

        this.active = ko.computed(function() {
            return config.workflow.activeStep() === this;
        }, this);
        this.active.subscribe(function(active) {
            if (active) {
                self.setStepIdToUrl();
                self.getExternalStepData();
            }
        });

        Object.keys(config).forEach(function(prop){
            if(prop !== 'workflow') {
                config[prop] = koMapping.fromJS(config[prop]);
            }
        });

        this.initialize = function() {
            /* cached ID logic */
            var cachedId = ko.unwrap(config.id);
            if (cachedId) {
                self.id(cachedId)
            }
            else {
                self.id(uuid.generate());
            }

            /* cached value logic */
            var cachedValue = self.getFromLocalStorage('value');
            if (cachedValue) {
                self.value(cachedValue);
                self.complete(true);
            }

            /* set value subscription */
            self.value.subscribe(function(value) {
                self.setToLocalStorage('value', value);
            });

            /* cached informationBox logic */
            this.setupInformationBox();
        };

        this.save = function() {
            /*
                currently SYNCHRONOUS, however async localStore interaction is
                covered by value subscription. This should be refactored when we can.
            */
            var preSaveCallback = ko.unwrap(self.preSaveCallback);
            if (preSaveCallback) {
                preSaveCallback();
            }

            self.setToLocalStorage('value', self.value())

            var postSaveCallback = ko.unwrap(self.postSaveCallback);
            if (postSaveCallback) {
                postSaveCallback();
            }
        };

        this.clearCallback = ko.observable();

        this.clear = function() {
            if (self.hasDirtyTile()) {
                if (ko.unwrap(self.tile)) {
                    self.tile().reset();
                }

                if (ko.unwrap(self.clearCallback)) {
                    self.clearCallback()();
                }
            }
        }

        this.setToLocalStorage = function(key, value) {
            var allStepsLocalStorageData = JSON.parse(localStorage.getItem(STEPS_LABEL)) || {};

            if (!allStepsLocalStorageData[self.id()]) {
                allStepsLocalStorageData[self.id()] = {};
            }

            allStepsLocalStorageData[self.id()][key] = koMapping.toJSON(value);

            localStorage.setItem(
                STEPS_LABEL,
                JSON.stringify(allStepsLocalStorageData)
            );
        };

        this.getFromLocalStorage = function(key) {
            var allStepsLocalStorageData = JSON.parse(localStorage.getItem(STEPS_LABEL)) || {};

            if (allStepsLocalStorageData[self.id()]) {
                return JSON.parse(allStepsLocalStorageData[self.id()][key]);
            }
        };

        this.setStepIdToUrl = function() {
            var searchParams = new URLSearchParams(window.location.search);
            searchParams.set(STEP_ID_LABEL, self.id());

            var newRelativePathQuery = `${window.location.pathname}?${searchParams.toString()}`;
            history.pushState(null, '', newRelativePathQuery);
        };

        this.getExternalStepData = function() {
            Object.keys(self.externalStepData).forEach(function(key) {
                config.workflow.getStepData(externalStepSourceData[key]).then(function(data) {
                    self.externalStepData[key]['data'] = data;
                });
            });
        };

        this.toggleInformationBox = function() {
            var informationBoxData = self.informationBoxData();
            var isDisplayed = informationBoxData['displayed'];

            informationBoxData['displayed'] = !isDisplayed;
            self.informationBoxData(informationBoxData);

            config.informationBoxDisplayed(!isDisplayed);
        };

        this.setupInformationBox = function() {
            if (config.informationBoxDisplayed && config.informationboxdata) {
                var isDisplayed = true;
                if (config.informationBoxDisplayed() !== undefined){
                    isDisplayed = config.informationBoxDisplayed();
                }
                self.informationBoxData({
                    displayed: isDisplayed,
                    heading: config.informationboxdata['heading'],
                    text: config.informationboxdata['text'],
                })
            }
        }

        _.extend(this, config);

        this.iconClass = ko.computed(function(){
            var ret = '';
            if(this.active()){
                ret = this.classActive;
            }else if(this.complete()){
                ret = this.classComplete;
            }else {
                ret = this.classUnvisited;
            }
            return ret + ' ' + ko.unwrap(this.icon);
        }, this);

        this.initialize();
    };

    /* only register template here, params are passed at the workflow level */
    ko.components.register('workflow-step', {
        template: {
            require: 'text!templates/views/components/plugins/workflow-step.htm'
        }
    });

    return WorkflowStep;
});
<|endoftext|>


<commit_before>/*
 * Copyright 2008-2013 Microarray Informatics Team, EMBL-European Bioinformatics Institute
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *
 * For further details of the Gene Expression Atlas project, including source code,
 * downloads and documentation, please see:
 *
 * http://gxa.github.com/gxa
 */

/*global $,jQuery,console,loadSliderAndPlot: false */
/*jslint browser:true */
/*jslint nomen: true*/

var heatmapModule = (function ($) {

    "use strict";

    var _transcriptUrlRoot;

    function showTranscriptBreakdownFancyBox() {
        $.fancybox({
                href:'#transcript-breakdown',
                padding:0,
                openEffect:'elastic',
                closeEffect:'elastic',
                helpers:{
                    overlay:{
                        locked:false
                    }
                }
            }
        );
    }

    function showCellText(div) {
        $(div).removeClass("hide_cell").addClass("show_cell");
    }

    function hideCellText(div) {
        $(div).removeClass("show_cell").addClass("hide_cell");
    }

    function showExpressionLevels() {
        $heatmap("div[data-color]").each(function () {
            showCellText(this);
        });
        $heatmap(".gradient-level-min").attr("style", 'white-space: nowrap;');
        $heatmap(".gradient-level-max").attr("style", 'white-space: nowrap;');
    }

    function hideExpressionLevels() {
        $heatmap("div[data-color]").each(function () {
            hideCellText(this);
        });
        $heatmap(".gradient-level-min").css("display", "none");
        $heatmap(".gradient-level-max").css("display", "none");
    }

    function initGeneSetLinkOnClick() {
        $("#showGeneSetProfiles").click(function () {
            $("#heatmap-div").hide();
            $("#heatmap-profilesAsGeneSets").show();
        });
        $("#showIndividualGenes").click(function () {
            $("#heatmap-profilesAsGeneSets").hide();
            $("#heatmap-div").show();
        });
    }

    function initDisplayLevelsButtonOnClick(asGeneSets) { //binds toggle handler

        var prefFormDisplayLevels = $("#prefForm").find("#displayLevels");

        // hacky!
        function syncDisplayLevelButtonOnOtherHeatmap(syntheticEvent) {
            if (!syntheticEvent) {
                // don't want to get stuck in an infinite loop,
                // so click other button only in response to original click
                // not the synthetic event we generate here
                $('.display-levels-button').not(this).trigger("click", "syntheticEvent")
            }
        }

        $heatmap("#display-levels").button()
            .toggle(
            function (eventObject, syntheticEvent) {
                $(this).button('option', 'label', $("#buttonText").attr('pressedtext'));
                showExpressionLevels(this);
                prefFormDisplayLevels.val("true");

                syncDisplayLevelButtonOnOtherHeatmap.call(this, syntheticEvent);
            },
            function (eventObject, syntheticEvent) {
                $(this).button('option', 'label', $("#buttonText").attr('unpressedtext'));
                hideExpressionLevels(this);
                prefFormDisplayLevels.val("false");

                syncDisplayLevelButtonOnOtherHeatmap.call(this, syntheticEvent);
            }
        );

        $heatmap("#display-levels").button({ label:$("#buttonText").attr('unpressedtext') });

        if (prefFormDisplayLevels.val() === "true") {
            $heatmap("#display-levels").trigger("click", "syntheticEvent")
        }

    }

    function initTranscriptPopupOnHeatMapCellClick(experimentAccession, species, selectedFilterFactorsJson) {
        var $transcript = $('#transcript-breakdown');

        function buildPlotData(transcriptRates) {
            var data = [],
                index = 0;
            $.each(transcriptRates, function (key, value) {
                data[index++] = {label:key, data:Math.abs(value.toFixed(1)), color:(value < 0 ? 'white' : undefined)};
            });
            return data;
        }

        function paintPieChart(plotData, geneId) {

            $transcript.css('position', 'absolute').css('left', '-5000px');
            $transcript.show();

            $.plot('#transcripts-pie', plotData, {
                series:{
                    pie:{stroke:{
                        color:"#d3d3d3"
                    },
                        show:true
                    }
                },
                legend:{
                    show:true,
                    labelFormatter:function (label) {
                        return label === "Others" ? "Others" :
                            "" +
                                label + "";
                    }
                }
            });

            //next lines are required because the div is configured to stay in an invisible position (position:absolute; left:-5000px)
            //in order to make it invisible during the show-up of fancybox
            //all of this is required because of IE8 :( . It doesn' t allow painting canvas in a hidden div, so we need to first show the div, then paint in it, then reposition it, then fancybox it...
            $transcript.hide();
            $transcript.css('position', 'relative')
                .css('left', '0px');

        }

        $heatmap("#heatmap-table").find("td:has(div[data-color])").click(function () {

            //gene and factor properties are extracted from gene and factor headers in the html table
            var $queryFactorType = $("#queryFactorType");

            var factorValue = $(this).find("div").attr("data-organism-part"),
                factorType = $queryFactorType.attr("value") || $queryFactorType.attr("data-value"),
                geneId = $(this).parent().find("td a:eq(0)").attr("id") || $(this).parent().find("td div:eq(0)").attr("id"),
                geneName = $(this).parent().find("td a:eq(0)").text() || $(this).parent().find("td div:eq(0)").text() ;

            $.ajax({
                url: _transcriptUrlRoot + "/json/transcripts/" + experimentAccession,
                type:"GET",
                data:{
                    'geneId':geneId,
                    'factorType':factorType,
                    'factorValue':factorValue,
                    'selectedFilterFactorsJson':JSON.stringify(selectedFilterFactorsJson)
                },
                datatype:'json',
                success:function (data) {
                    var totalCount = data.totalTranscriptsCount,
                        expressedCount = data.expressedTranscriptsCount,
                        plotData = buildPlotData(data.transcriptExpressions);

                    species = species.replace(" ", "_");

                    paintPieChart(plotData, geneId);

                    showTranscriptBreakdownFancyBox();

                    var s = '';
                    if (totalCount > 1) {
                        s = 's';
                    }

                    var is = 'is';
                    if (totalCount > 1) {
                        is = 'are';
                    }

                    $('#transcript-breakdown-title').html("Expression Level Breakdown for " +
                        "" + geneName + " in " + factorValue +
                        "
(" + expressedCount + " out of " + totalCount + " transcript" + s +
                        " " + is + " expressed):");

                }
            }).fail(function (data) {
                    console.log("ERROR:  " + data);
                });

        });
    }

    //there must be a cleaner way to do this, but I don't know it yet!
    function buildHeatmapCellTooltip(pValue, tstatistic, foldChange) {
        return "

Adjusted p-value	" +
            (tstatistic !== undefined ? "t-statistic	" : "") +
            "Log2-fold change
" +
            "

" + pValue + "	" +
            (tstatistic !== undefined ? "" + tstatistic + "	" : "") +
            "" + foldChange + "

" +
            "
";
    }

    function initDifferentialHeatmapCellsTooltip() {
        $heatmap("#heatmap-table td:has(div[data-pValue])").attr('title', '').tooltip(
            {
                open:function (event, ui) {
                    var colour = $(this).find("div").attr("data-color");
                    ui.tooltip.css('background', colour);
                },
                tooltipClass:"help-tooltip pvalue-tooltip-styling",

                content:function () {
                    var foldChange = $(this).find("div").html(),
                        pValue = $(this).find("div").attr("data-pValue"),
                        tstatistic = $(this).find("div").attr("data-tstatistic");

                    return buildHeatmapCellTooltip(pValue, tstatistic, foldChange);
                }

            });
    }

    function initDownloadButtonTooltip() {
        $heatmap('#download-profiles-link').button().tooltip();
    }

    function restrictLabelSize(label, maxSize) {
        var result = label;
        if (result.length > maxSize) {
            result = result.substring(0, maxSize);
            if (result.lastIndexOf(" ") > maxSize - 5) {
                result = result.substring(0, result.lastIndexOf(" "));
            }
            result = result + "...";
        }
        return result;
    }

    function createHeatmapFactorHeaders() {//shorten header labels if necessary and inits tooltips

        $heatmap(".factor-header")
            .each(function () {
                if ($.browser.msie) {
                    $(this).append($(this).attr("data-organism-part"));
                    $heatmap("div", "th", "#heatmap-table").addClass('rotate_text_IE').removeClass('rotate_text');
                    $heatmap("th", "#heatmap-table").addClass('heatmap td').removeClass('rotated_cell');
                } else {
                    var organismPartName = $(this).attr("data-organism-part");
                    organismPartName = restrictLabelSize(organismPartName, 17);
                    $(this).append(organismPartName);
                }
            }).tooltip();

    }

    function insertFirstColumnHeaders(accessionHeaders) {

        var headers = "";

        $(accessionHeaders).each(function () {
            headers += "" + this + "	";
        });

        //add header cells for gene name and design element (if any)
        //NB: this is subsequently removed when the heatmap is loaded by heatmap-matrix-searchresults-diffanalytics.jsp
        $heatmap("#heatmap-table thead").append("
" + headers + "
");

        //add display levels cell colspan
        if (accessionHeaders.length === 2) {

            $heatmap("#heatmap-table thead tr th:eq(1)").remove();
            $heatmap("#heatmap-table thead tr th:eq(0)").attr("colspan", 2);

        }
        //add rowspan to factor headers
        $heatmap("#heatmap-table thead tr th:gt(0)").attr("rowspan", 2);
    }

    function initMaPlotButtons(experimentAccession) {
        var thElements = $heatmap(".factor-header").parent(),
            maPlotURL;

        thElements.css("width", "60px");
        $heatmap(".factor-header").css("transform-origin");
        $heatmap(".factor-header").css("top", "57px");

        $(thElements).each(function () {
            var contrastId = $(this).children().attr("data-contrast-id");

            var arrayDesignAccession = $(this).children().attr("data-array-design");

            maPlotURL = 'external-resources/' + experimentAccession + '/' + (arrayDesignAccession ? arrayDesignAccession + '/' : '' ) + contrastId + '/ma-plot.png';
            //append a button div now
            $(this).append("

");

        });

        $heatmap(".ma-button").tooltip().button();

        $heatmap(".ma-button").fancybox({
            padding:0,
            openEffect:'elastic',
            closeEffect:'elastic'
        });

    }

    function initTranscriptBreakdownFancyBox(experimentAccession, parameters) {
        initTranscriptPopupOnHeatMapCellClick(experimentAccession, parameters.species, parameters.selectedFilterFactorsJson);

        $('#transcript-breakdown-geneid').tooltip();
        $('#transcript-breakdown-title-help').tooltip();

    }

    function contextFactory(ctx) {
        return function(selector) {
            return $(selector, ctx);
        };
    }

    var $heatmap; // stores current heatmap element. allows us to have multiple heatmaps on the same page

    function initHeatmap(experimentAccession, parameters, heatmapElementId, isHidden) {
        var heatmapElement = $('#' + heatmapElementId);
        $heatmap = contextFactory(heatmapElement);

        $heatmap('#heatmap-table th:first').addClass('horizontal-header-cell'); //because displaytag doesn't let us configure TH cells...

        if (experimentAccession !== undefined && parameters.species && !parameters.asGeneSets) {
            initTranscriptBreakdownFancyBox(experimentAccession, parameters);
        }

        initDifferentialHeatmapCellsTooltip();
        initDownloadButtonTooltip();
        initDisplayLevelsButtonOnClick(parameters.asGeneSets);
        initGeneSetLinkOnClick();
        createHeatmapFactorHeaders();

        var geneNameHeader = parameters.asGeneSets ? "Gene set" : "Gene";
        insertFirstColumnHeaders(parameters.isMicroarray ? [geneNameHeader, "Design Element"] : [geneNameHeader]);

        if (experimentAccession !== undefined && parameters.cutoff === 0.05 && !parameters.geneQuery) {
            initMaPlotButtons(experimentAccession);
        }

        if (!isHidden) {
            heatmapElement.show();
        }
    }

    function initBaselineHeatmap(experimentAccession, species, selectedFilterFactorsJson, asGeneSets, transcriptUrlRoot, heatmapElementId, isHidden) {
        _transcriptUrlRoot = transcriptUrlRoot;

        initHeatmap(experimentAccession, {
            species:species,
            selectedFilterFactorsJson:selectedFilterFactorsJson,
            asGeneSets:asGeneSets
        }, heatmapElementId, isHidden);
    }

    function initRnaSeqHeatmap(experimentAccession, cutoff, geneQuery, heatmapElementId) {
        initHeatmap(experimentAccession, {cutoff:cutoff, geneQuery:geneQuery}, heatmapElementId);
    }

    function initMicroarrayHeatmap(experimentAccession, cutoff, geneQuery, heatmapElementId) {
        initHeatmap(experimentAccession, {cutoff:cutoff, geneQuery:geneQuery, isMicroarray:true}, heatmapElementId);
    }

    return {

        initBaselineHeatmap:initBaselineHeatmap,
        initRnaSeqHeatmap:initRnaSeqHeatmap,
        initMicroarrayHeatmap:initMicroarrayHeatmap

    };

}(jQuery));
<commit_msg>refactor<commit_after>/*
 * Copyright 2008-2013 Microarray Informatics Team, EMBL-European Bioinformatics Institute
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *
 * For further details of the Gene Expression Atlas project, including source code,
 * downloads and documentation, please see:
 *
 * http://gxa.github.com/gxa
 */

/*global $,jQuery,console,loadSliderAndPlot: false */
/*jslint browser:true */
/*jslint nomen: true*/

var heatmapModule = (function ($) {

    "use strict";

    var _transcriptUrlRoot;

    function showTranscriptBreakdownFancyBox() {
        $.fancybox({
                href:'#transcript-breakdown',
                padding:0,
                openEffect:'elastic',
                closeEffect:'elastic',
                helpers:{
                    overlay:{
                        locked:false
                    }
                }
            }
        );
    }

    function showCellText(div) {
        $(div).removeClass("hide_cell").addClass("show_cell");
    }

    function hideCellText(div) {
        $(div).removeClass("show_cell").addClass("hide_cell");
    }

    function showExpressionLevels($heatmap) {
        $heatmap("div[data-color]").each(function () {
            showCellText(this);
        });
        $heatmap(".gradient-level-min").attr("style", 'white-space: nowrap;');
        $heatmap(".gradient-level-max").attr("style", 'white-space: nowrap;');
    }

    function hideExpressionLevels($heatmap) {
        $heatmap("div[data-color]").each(function () {
            hideCellText(this);
        });
        $heatmap(".gradient-level-min").css("display", "none");
        $heatmap(".gradient-level-max").css("display", "none");
    }

    function initGeneSetLinkOnClick() {
        $("#showGeneSetProfiles").click(function () {
            $("#heatmap-div").hide();
            $("#heatmap-profilesAsGeneSets").show();
        });
        $("#showIndividualGenes").click(function () {
            $("#heatmap-profilesAsGeneSets").hide();
            $("#heatmap-div").show();
        });
    }

    function initDisplayLevelsButtonOnClick(heatmapElement) { //binds toggle handler
        var $heatmap = contextFactory(heatmapElement);
        var prefFormDisplayLevels = $("#prefForm").find("#displayLevels");

        // hacky!
        function syncDisplayLevelButtonOnOtherHeatmap(syntheticEvent) {
            if (!syntheticEvent) {
                // don't want to get stuck in an infinite loop,
                // so click other button only in response to original click
                // not the synthetic event we generate here
                $('.display-levels-button').not(this).trigger("click", "syntheticEvent")
            }
        }

        $heatmap("#display-levels").button()
            .toggle(
            function (eventObject, syntheticEvent) {
                $(this).button('option', 'label', $("#buttonText").attr('pressedtext'));
                showExpressionLevels($heatmap);
                prefFormDisplayLevels.val("true");

                syncDisplayLevelButtonOnOtherHeatmap.call(this, syntheticEvent);
            },
            function (eventObject, syntheticEvent) {
                $(this).button('option', 'label', $("#buttonText").attr('unpressedtext'));
                hideExpressionLevels($heatmap);
                prefFormDisplayLevels.val("false");

                syncDisplayLevelButtonOnOtherHeatmap.call(this, syntheticEvent);
            }
        );

        $heatmap("#display-levels").button({ label:$("#buttonText").attr('unpressedtext') });

        if (prefFormDisplayLevels.val() === "true") {
            $heatmap("#display-levels").trigger("click", "syntheticEvent")
        }

    }

    function initTranscriptPopupOnHeatMapCellClick(experimentAccession, species, selectedFilterFactorsJson) {
        var $transcript = $('#transcript-breakdown');

        function buildPlotData(transcriptRates) {
            var data = [],
                index = 0;
            $.each(transcriptRates, function (key, value) {
                data[index++] = {label:key, data:Math.abs(value.toFixed(1)), color:(value < 0 ? 'white' : undefined)};
            });
            return data;
        }

        function paintPieChart(plotData, geneId) {

            $transcript.css('position', 'absolute').css('left', '-5000px');
            $transcript.show();

            $.plot('#transcripts-pie', plotData, {
                series:{
                    pie:{stroke:{
                        color:"#d3d3d3"
                    },
                        show:true
                    }
                },
                legend:{
                    show:true,
                    labelFormatter:function (label) {
                        return label === "Others" ? "Others" :
                            "" +
                                label + "";
                    }
                }
            });

            //next lines are required because the div is configured to stay in an invisible position (position:absolute; left:-5000px)
            //in order to make it invisible during the show-up of fancybox
            //all of this is required because of IE8 :( . It doesn' t allow painting canvas in a hidden div, so we need to first show the div, then paint in it, then reposition it, then fancybox it...
            $transcript.hide();
            $transcript.css('position', 'relative')
                .css('left', '0px');

        }

        $heatmap("#heatmap-table").find("td:has(div[data-color])").click(function () {

            //gene and factor properties are extracted from gene and factor headers in the html table
            var $queryFactorType = $("#queryFactorType");

            var factorValue = $(this).find("div").attr("data-organism-part"),
                factorType = $queryFactorType.attr("value") || $queryFactorType.attr("data-value"),
                geneId = $(this).parent().find("td a:eq(0)").attr("id") || $(this).parent().find("td div:eq(0)").attr("id"),
                geneName = $(this).parent().find("td a:eq(0)").text() || $(this).parent().find("td div:eq(0)").text() ;

            $.ajax({
                url: _transcriptUrlRoot + "/json/transcripts/" + experimentAccession,
                type:"GET",
                data:{
                    'geneId':geneId,
                    'factorType':factorType,
                    'factorValue':factorValue,
                    'selectedFilterFactorsJson':JSON.stringify(selectedFilterFactorsJson)
                },
                datatype:'json',
                success:function (data) {
                    var totalCount = data.totalTranscriptsCount,
                        expressedCount = data.expressedTranscriptsCount,
                        plotData = buildPlotData(data.transcriptExpressions);

                    species = species.replace(" ", "_");

                    paintPieChart(plotData, geneId);

                    showTranscriptBreakdownFancyBox();

                    var s = '';
                    if (totalCount > 1) {
                        s = 's';
                    }

                    var is = 'is';
                    if (totalCount > 1) {
                        is = 'are';
                    }

                    $('#transcript-breakdown-title').html("Expression Level Breakdown for " +
                        "" + geneName + " in " + factorValue +
                        "
(" + expressedCount + " out of " + totalCount + " transcript" + s +
                        " " + is + " expressed):");

                }
            }).fail(function (data) {
                    console.log("ERROR:  " + data);
                });

        });
    }

    //there must be a cleaner way to do this, but I don't know it yet!
    function buildHeatmapCellTooltip(pValue, tstatistic, foldChange) {
        return "

Adjusted p-value	" +
            (tstatistic !== undefined ? "t-statistic	" : "") +
            "Log2-fold change
" +
            "

" + pValue + "	" +
            (tstatistic !== undefined ? "" + tstatistic + "	" : "") +
            "" + foldChange + "

" +
            "
";
    }

    function initDifferentialHeatmapCellsTooltip() {
        $heatmap("#heatmap-table td:has(div[data-pValue])").attr('title', '').tooltip(
            {
                open:function (event, ui) {
                    var colour = $(this).find("div").attr("data-color");
                    ui.tooltip.css('background', colour);
                },
                tooltipClass:"help-tooltip pvalue-tooltip-styling",

                content:function () {
                    var foldChange = $(this).find("div").html(),
                        pValue = $(this).find("div").attr("data-pValue"),
                        tstatistic = $(this).find("div").attr("data-tstatistic");

                    return buildHeatmapCellTooltip(pValue, tstatistic, foldChange);
                }

            });
    }

    function initDownloadButtonTooltip() {
        $heatmap('#download-profiles-link').button().tooltip();
    }

    function restrictLabelSize(label, maxSize) {
        var result = label;
        if (result.length > maxSize) {
            result = result.substring(0, maxSize);
            if (result.lastIndexOf(" ") > maxSize - 5) {
                result = result.substring(0, result.lastIndexOf(" "));
            }
            result = result + "...";
        }
        return result;
    }

    function createHeatmapFactorHeaders() {// shorten/rotate header labels

        $heatmap(".factor-header")
            .each(function () {
                if ($.browser.msie) {
                    $(this).append($(this).attr("data-organism-part"));
                    $heatmap("div", "th", "#heatmap-table").addClass('rotate_text_IE').removeClass('rotate_text');
                    $heatmap("th", "#heatmap-table").addClass('heatmap td').removeClass('rotated_cell');
                } else {
                    var organismPartName = $(this).attr("data-organism-part");
                    organismPartName = restrictLabelSize(organismPartName, 17);
                    $(this).append(organismPartName);
                }
            });

    }

    function insertFirstColumnHeaders(accessionHeaders) {

        var headers = "";

        $(accessionHeaders).each(function () {
            headers += "" + this + "	";
        });

        //add header cells for gene name and design element (if any)
        //NB: this is subsequently removed when the heatmap is loaded by heatmap-matrix-searchresults-diffanalytics.jsp
        $heatmap("#heatmap-table thead").append("
" + headers + "
");

        //add display levels cell colspan
        if (accessionHeaders.length === 2) {

            $heatmap("#heatmap-table thead tr th:eq(1)").remove();
            $heatmap("#heatmap-table thead tr th:eq(0)").attr("colspan", 2);

        }
        //add rowspan to factor headers
        $heatmap("#heatmap-table thead tr th:gt(0)").attr("rowspan", 2);
    }

    function initMaPlotButtons(experimentAccession) {
        var thElements = $heatmap(".factor-header").parent(),
            maPlotURL;

        thElements.css("width", "60px");
        $heatmap(".factor-header").css("transform-origin");
        $heatmap(".factor-header").css("top", "57px");

        $(thElements).each(function () {
            var contrastId = $(this).children().attr("data-contrast-id");

            var arrayDesignAccession = $(this).children().attr("data-array-design");

            maPlotURL = 'external-resources/' + experimentAccession + '/' + (arrayDesignAccession ? arrayDesignAccession + '/' : '' ) + contrastId + '/ma-plot.png';
            //append a button div now
            $(this).append("

");

        });

        $heatmap(".ma-button").tooltip().button();

        $heatmap(".ma-button").fancybox({
            padding:0,
            openEffect:'elastic',
            closeEffect:'elastic'
        });

    }

    function initTranscriptBreakdownFancyBox(experimentAccession, parameters) {
        initTranscriptPopupOnHeatMapCellClick(experimentAccession, parameters.species, parameters.selectedFilterFactorsJson);

        $('#transcript-breakdown-geneid').tooltip();
        $('#transcript-breakdown-title-help').tooltip();

    }

    function contextFactory(ctx) {
        return function(selector) {
            return $(selector, ctx);
        };
    }

    var $heatmap; // stores current heatmap element. allows us to have multiple heatmaps on the same page

    function initHeatmap(experimentAccession, parameters, heatmapElementId, isHidden) {
        var heatmapElement = $('#' + heatmapElementId);
        $heatmap = contextFactory(heatmapElement);

        $heatmap('#heatmap-table th:first').addClass('horizontal-header-cell'); //because displaytag doesn't let us configure TH cells...

        if (experimentAccession !== undefined && parameters.species && !parameters.asGeneSets) {
            initTranscriptBreakdownFancyBox(experimentAccession, parameters);
        }

        initDifferentialHeatmapCellsTooltip();
        initDownloadButtonTooltip();
        initDisplayLevelsButtonOnClick(heatmapElement);
        initGeneSetLinkOnClick();
        createHeatmapFactorHeaders();

        var geneNameHeader = parameters.asGeneSets ? "Gene set" : "Gene";
        insertFirstColumnHeaders(parameters.isMicroarray ? [geneNameHeader, "Design Element"] : [geneNameHeader]);

        if (experimentAccession !== undefined && parameters.cutoff === 0.05 && !parameters.geneQuery) {
            initMaPlotButtons(experimentAccession);
        }

        if (!isHidden) {
            heatmapElement.show();
        }
    }

    function initBaselineHeatmap(experimentAccession, species, selectedFilterFactorsJson, asGeneSets, transcriptUrlRoot, heatmapElementId, isHidden) {
        _transcriptUrlRoot = transcriptUrlRoot;

        initHeatmap(experimentAccession, {
            species:species,
            selectedFilterFactorsJson:selectedFilterFactorsJson,
            asGeneSets:asGeneSets
        }, heatmapElementId, isHidden);
    }

    function initRnaSeqHeatmap(experimentAccession, cutoff, geneQuery, heatmapElementId) {
        initHeatmap(experimentAccession, {cutoff:cutoff, geneQuery:geneQuery}, heatmapElementId);
    }

    function initMicroarrayHeatmap(experimentAccession, cutoff, geneQuery, heatmapElementId) {
        initHeatmap(experimentAccession, {cutoff:cutoff, geneQuery:geneQuery, isMicroarray:true}, heatmapElementId);
    }

    return {

        initBaselineHeatmap:initBaselineHeatmap,
        initRnaSeqHeatmap:initRnaSeqHeatmap,
        initMicroarrayHeatmap:initMicroarrayHeatmap,
        initDisplayLevelsButtonOnClick:initDisplayLevelsButtonOnClick

    };

}(jQuery));
<|endoftext|>


<commit_before>describe('sap.m.TableSelectDialog', function() {
    it('should open simple table select dialog', function() {
        element(by.id('tsdWithBindingInput-vhi')).click();
        var tableSelectDialog = element(by.id('TableSelectDialog2-dialog'));
        expect(takeScreenshot(tableSelectDialog)).toLookAs('simple-tableSelectDialog');
        element(by.id('TableSelectDialog2-cancel')).click();
    });

    it('should open table select dialog in multiselect mode', function() {
        element(by.id('tsdWithMultiSelectButton')).click();
        var tableSelectDialog = element(by.id('TableSelectDialog4-dialog'));
        expect(takeScreenshot(tableSelectDialog)).toLookAs('tableSelectDialog-multiselect');

        element(by.id('TableSelectDialog4-table-sa-CbBg')).click();
        expect(takeScreenshot(tableSelectDialog)).toLookAs('tableSelectDialog-multiselect-selection');

        element(by.id('TableSelectDialog4-cancel')).click();
    });

    it('should open table select dialog in multiselect mode with large data', function() {
        element(by.id('tsdWithLargeDataAndMultiSelectButton')).click();
        var tableSelectDialog = element(by.id('TableSelectDialog5-dialog'));
        expect(takeScreenshot(tableSelectDialog)).toLookAs('tableSelectDialog-multiselect-largeData');
        element(by.id('TableSelectDialog5-cancel')).click();
    });

    it('should open table select dialog in multiselect mode with very large data', function() {
        element(by.id('tsdWithVeryLargeDataButton')).click();
        var tableSelectDialog = element(by.id('TableSelectDialog6-dialog'));
        expect(takeScreenshot(tableSelectDialog)).toLookAs('tableSelectD-multiselect-veryLargeData');
        element(by.id('TableSelectDialog6-cancel')).click();

    });
});<commit_msg>[INTERNAL][TEST] sap.m.TableSelectDialog: disable checkbox validation<commit_after>describe('sap.m.TableSelectDialog', function() {
    it('should open simple table select dialog', function() {
        element(by.id('tsdWithBindingInput-vhi')).click();
        var tableSelectDialog = element(by.id('TableSelectDialog2-dialog'));
        expect(takeScreenshot(tableSelectDialog)).toLookAs('simple-tableSelectDialog');
        element(by.id('TableSelectDialog2-cancel')).click();
    });

    /*it('should open table select dialog in multiselect mode', function() {
        element(by.id('tsdWithMultiSelectButton')).click();
        var tableSelectDialog = element(by.id('TableSelectDialog4-dialog'));
        expect(takeScreenshot(tableSelectDialog)).toLookAs('tableSelectDialog-multiselect');

        element(by.id('TableSelectDialog4-table-sa-CbBg')).click();
        expect(takeScreenshot(tableSelectDialog)).toLookAs('tableSelectDialog-multiselect-selection');

        element(by.id('TableSelectDialog4-cancel')).click();
    });*/

    it('should open table select dialog in multiselect mode with large data', function() {
        element(by.id('tsdWithLargeDataAndMultiSelectButton')).click();
        var tableSelectDialog = element(by.id('TableSelectDialog5-dialog'));
        expect(takeScreenshot(tableSelectDialog)).toLookAs('tableSelectDialog-multiselect-largeData');
        element(by.id('TableSelectDialog5-cancel')).click();
    });

    it('should open table select dialog in multiselect mode with very large data', function() {
        element(by.id('tsdWithVeryLargeDataButton')).click();
        var tableSelectDialog = element(by.id('TableSelectDialog6-dialog'));
        expect(takeScreenshot(tableSelectDialog)).toLookAs('tableSelectD-multiselect-veryLargeData');
        element(by.id('TableSelectDialog6-cancel')).click();

    });
});<|endoftext|>


<commit_before>sap.ui.define([
	"sap/ui/fl/Layer",
	"sap/ui/fl/Utils",
	"sap/ui/fl/FakeLrepConnectorSessionStorage",
	"sap/ui/fl/write/api/PersistenceWriteAPI",
	"sap/ui/fl/write/api/ChangesWriteAPI",
	"sap/ui/core/Component",
	"sap/ui/core/ComponentContainer",
	"sap/ui/qunit/QUnitUtils",
	"sap/ui/events/KeyCodes",
	"sap/ui/core/util/reflection/JsControlTreeModifier"
], function(
	Layer,
	flUtils,
	FakeLrepConnectorSessionStorage,
	PersistenceWriteAPI,
	ChangesWriteAPI,
	Component,
	ComponentContainer,
	QUnitUtils,
	KeyCodes,
	JsControlTreeModifier
) {
	"use strict";

	var RtaQunitUtils = {};

	RtaQunitUtils.renderTestModuleAt = function(sNamespace, sDomId) {
		var oComp = sap.ui.getCore().createComponent({
			name : "sap.ui.rta.qunitrta",
			id : "Comp1",
			settings : {
				componentData : {
					showAdaptButton : true
				}
			}
		});

		var oCompCont = new ComponentContainer({
			component: oComp
		}).placeAt(sDomId);
		sap.ui.getCore().applyChanges();

		return oCompCont;
	};

	RtaQunitUtils.renderTestAppAt = function(sDomId) {
		FakeLrepConnectorSessionStorage.enableFakeConnector();

		var oComp = sap.ui.getCore().createComponent({
			name : "sap.ui.rta.qunitrta",
			id : "Comp1",
			settings : {
				componentData : {
					showAdaptButton : true
				}
			}
		});

		var oCompCont = new ComponentContainer({
			component: oComp
		}).placeAt(sDomId);
		sap.ui.getCore().applyChanges();

		return oCompCont;
	};

	RtaQunitUtils.clear = function (oElement, bRevert) {
		var oComponent = (oElement && flUtils.getAppComponentForControl(oElement)) || sap.ui.getCore().getComponent("Comp1");

		return Promise.all([
			PersistenceWriteAPI.save({selector: oComponent, layer: Layer.CUSTOMER}),
			PersistenceWriteAPI.save({selector: oComponent, layer: Layer.USER})
		])
			.then(function (aSavedChanges) {
				if (bRevert) {
					return aSavedChanges[0].concat(aSavedChanges[1]).reverse()
						.reduce(function (oPreviousPromise, oChange) {
							var oElementToBeReverted = JsControlTreeModifier.bySelector(oChange.getSelector(), oComponent);
							return ChangesWriteAPI.revert({
								element: oElementToBeReverted,
								change: oChange
							});
						}, new flUtils.FakePromise());
				}
			})
			.then(function () {
				return Promise.all([
					PersistenceWriteAPI.reset({
						selector: oComponent,
						layer: Layer.CUSTOMER,
						generator: "Change.createInitialFileContent"
					}),
					PersistenceWriteAPI.reset({
						selector: oComponent,
						layer: Layer.USER,
						generator: "Change.createInitialFileContent"
					})
				]);
			});
	};

	RtaQunitUtils.getNumberOfChangesForTestApp = function () {
		return FakeLrepConnectorSessionStorage.forTesting.getNumberOfChanges("sap.ui.rta.qunitrta.Component");
	};

	RtaQunitUtils.spySessionStorageWrite = function(sandbox, assert) {
		return FakeLrepConnectorSessionStorage.forTesting.spyWrite(sandbox, assert);
	};

	RtaQunitUtils.renderTestAppAtAsync = function(sDomId) {
		FakeLrepConnectorSessionStorage.enableFakeConnector();

		return Component.create({
			name : "sap.ui.rta.qunitrta",
			id : "Comp1",
			settings : {
				componentData : {
					showAdaptButton : true
				}
			}
		})
		.then(function(oComponent) {
			return new ComponentContainer({
				component : oComponent,
				async: true
			});
		})
		.then(function(oComponentContainer) {
			oComponentContainer.placeAt(sDomId);
			sap.ui.getCore().applyChanges();

			return oComponentContainer;
		});
	};

	RtaQunitUtils.renderRuntimeAuthoringAppAt = function(sDomId) {
		var oComp = sap.ui.getCore().createComponent({
			name : "sap.ui.rta.test",
			id : "Comp1",
			settings : {
				componentData : {
					showAdaptButton : true,
					useSessionStorage: true
				}
			}
		});

		var oCompCont = new ComponentContainer({
			component: oComp
		}).placeAt(sDomId);
		sap.ui.getCore().applyChanges();

		return oCompCont;
	};

	RtaQunitUtils.openContextMenuWithKeyboard = function(oTarget) {
		return new Promise(function(resolve) {
			this.oRta.getPlugins()["contextMenu"].attachEventOnce("openedContextMenu", resolve);

			var oParams = {};
			oParams.keyCode = KeyCodes.F10;
			oParams.which = oParams.keyCode;
			oParams.shiftKey = true;
			oParams.altKey = false;
			oParams.metaKey = false;
			oParams.ctrlKey = false;
			QUnitUtils.triggerEvent("keyup", oTarget.getDomRef(), oParams);
		}.bind(this));
	};

	RtaQunitUtils.openContextMenuWithClick = function(oTarget, sinon) {
		return new Promise(function(resolve) {
			this.oRta.getPlugins()["contextMenu"].attachEventOnce("openedContextMenu", resolve);

			var clock = sinon.useFakeTimers();
			QUnitUtils.triggerMouseEvent(oTarget.getDomRef(), "contextmenu");
			clock.tick(50);
			clock.restore();
		}.bind(this));
	};

	RtaQunitUtils.closeContextMenuWithKeyboard = function(oTarget) {
		return new Promise(function(resolve) {
			var oPopover = oTarget.getPopover();
			if (!oPopover.isOpen()) {
				return resolve();
			}
			oPopover.attachEventOnce("afterClose", resolve);

			oPopover.focus();
			var oParams = {};
			oParams.keyCode = KeyCodes.ESCAPE;
			QUnitUtils.triggerEvent("keyup", oPopover.getDomRef(), oParams);
		});
	};

	RtaQunitUtils.getContextMenuItemCount = function(oTarget) {
		return new Promise(function(resolve) {
			var iItemCount;
			oTarget.focus();
			oTarget.setSelected();
			RtaQunitUtils.openContextMenuWithKeyboard.call(this, oTarget)
				.then(function () {
					var oContextMenuControl = this.oRta.getPlugins()["contextMenu"].oContextMenuControl;
					iItemCount = oContextMenuControl.getButtons().length;
					return oContextMenuControl;
				}.bind(this))
				.then(RtaQunitUtils.closeContextMenuWithKeyboard)
				.then(function () {
					resolve(iItemCount);
				});
		}.bind(this));
	};

	return RtaQunitUtils;
});
<commit_msg>[INTERNAL] sap.ui.rta Avoid reverting descriptor changes in tests<commit_after>sap.ui.define([
	"sap/ui/fl/Layer",
	"sap/ui/fl/Utils",
	"sap/ui/fl/FakeLrepConnectorSessionStorage",
	"sap/ui/fl/write/api/PersistenceWriteAPI",
	"sap/ui/fl/write/api/ChangesWriteAPI",
	"sap/ui/core/Component",
	"sap/ui/core/ComponentContainer",
	"sap/ui/qunit/QUnitUtils",
	"sap/ui/events/KeyCodes",
	"sap/ui/core/util/reflection/JsControlTreeModifier"
], function(
	Layer,
	flUtils,
	FakeLrepConnectorSessionStorage,
	PersistenceWriteAPI,
	ChangesWriteAPI,
	Component,
	ComponentContainer,
	QUnitUtils,
	KeyCodes,
	JsControlTreeModifier
) {
	"use strict";

	var RtaQunitUtils = {};

	RtaQunitUtils.renderTestModuleAt = function(sNamespace, sDomId) {
		var oComp = sap.ui.getCore().createComponent({
			name : "sap.ui.rta.qunitrta",
			id : "Comp1",
			settings : {
				componentData : {
					showAdaptButton : true
				}
			}
		});

		var oCompCont = new ComponentContainer({
			component: oComp
		}).placeAt(sDomId);
		sap.ui.getCore().applyChanges();

		return oCompCont;
	};

	RtaQunitUtils.renderTestAppAt = function(sDomId) {
		FakeLrepConnectorSessionStorage.enableFakeConnector();

		var oComp = sap.ui.getCore().createComponent({
			name : "sap.ui.rta.qunitrta",
			id : "Comp1",
			settings : {
				componentData : {
					showAdaptButton : true
				}
			}
		});

		var oCompCont = new ComponentContainer({
			component: oComp
		}).placeAt(sDomId);
		sap.ui.getCore().applyChanges();

		return oCompCont;
	};

	RtaQunitUtils.clear = function (oElement, bRevert) {
		var oComponent = (oElement && flUtils.getAppComponentForControl(oElement)) || sap.ui.getCore().getComponent("Comp1");

		return Promise.all([
			PersistenceWriteAPI.save({selector: oComponent, layer: Layer.CUSTOMER}),
			PersistenceWriteAPI.save({selector: oComponent, layer: Layer.USER})
		])
			.then(function (aSavedChanges) {
				if (bRevert) {
					return aSavedChanges[0].concat(aSavedChanges[1]).reverse()
						.filter(function (oChange) {
							//skip descriptor changes
							return !oChange.getDefinition().appDescriptorChange;
						})
						.reduce(function (oPreviousPromise, oChange) {
							var oElementToBeReverted = JsControlTreeModifier.bySelector(oChange.getSelector(), oComponent);
							return ChangesWriteAPI.revert({
								element: oElementToBeReverted,
								change: oChange
							});
						}, new flUtils.FakePromise());
				}
			})
			.then(function () {
				return Promise.all([
					PersistenceWriteAPI.reset({
						selector: oComponent,
						layer: Layer.CUSTOMER,
						generator: "Change.createInitialFileContent"
					}),
					PersistenceWriteAPI.reset({
						selector: oComponent,
						layer: Layer.USER,
						generator: "Change.createInitialFileContent"
					})
				]);
			});
	};

	RtaQunitUtils.getNumberOfChangesForTestApp = function () {
		return FakeLrepConnectorSessionStorage.forTesting.getNumberOfChanges("sap.ui.rta.qunitrta.Component");
	};

	RtaQunitUtils.spySessionStorageWrite = function(sandbox, assert) {
		return FakeLrepConnectorSessionStorage.forTesting.spyWrite(sandbox, assert);
	};

	RtaQunitUtils.renderTestAppAtAsync = function(sDomId) {
		FakeLrepConnectorSessionStorage.enableFakeConnector();

		return Component.create({
			name : "sap.ui.rta.qunitrta",
			id : "Comp1",
			settings : {
				componentData : {
					showAdaptButton : true
				}
			}
		})
		.then(function(oComponent) {
			return new ComponentContainer({
				component : oComponent,
				async: true
			});
		})
		.then(function(oComponentContainer) {
			oComponentContainer.placeAt(sDomId);
			sap.ui.getCore().applyChanges();

			return oComponentContainer;
		});
	};

	RtaQunitUtils.renderRuntimeAuthoringAppAt = function(sDomId) {
		var oComp = sap.ui.getCore().createComponent({
			name : "sap.ui.rta.test",
			id : "Comp1",
			settings : {
				componentData : {
					showAdaptButton : true,
					useSessionStorage: true
				}
			}
		});

		var oCompCont = new ComponentContainer({
			component: oComp
		}).placeAt(sDomId);
		sap.ui.getCore().applyChanges();

		return oCompCont;
	};

	RtaQunitUtils.openContextMenuWithKeyboard = function(oTarget) {
		return new Promise(function(resolve) {
			this.oRta.getPlugins()["contextMenu"].attachEventOnce("openedContextMenu", resolve);

			var oParams = {};
			oParams.keyCode = KeyCodes.F10;
			oParams.which = oParams.keyCode;
			oParams.shiftKey = true;
			oParams.altKey = false;
			oParams.metaKey = false;
			oParams.ctrlKey = false;
			QUnitUtils.triggerEvent("keyup", oTarget.getDomRef(), oParams);
		}.bind(this));
	};

	RtaQunitUtils.openContextMenuWithClick = function(oTarget, sinon) {
		return new Promise(function(resolve) {
			this.oRta.getPlugins()["contextMenu"].attachEventOnce("openedContextMenu", resolve);

			var clock = sinon.useFakeTimers();
			QUnitUtils.triggerMouseEvent(oTarget.getDomRef(), "contextmenu");
			clock.tick(50);
			clock.restore();
		}.bind(this));
	};

	RtaQunitUtils.closeContextMenuWithKeyboard = function(oTarget) {
		return new Promise(function(resolve) {
			var oPopover = oTarget.getPopover();
			if (!oPopover.isOpen()) {
				return resolve();
			}
			oPopover.attachEventOnce("afterClose", resolve);

			oPopover.focus();
			var oParams = {};
			oParams.keyCode = KeyCodes.ESCAPE;
			QUnitUtils.triggerEvent("keyup", oPopover.getDomRef(), oParams);
		});
	};

	RtaQunitUtils.getContextMenuItemCount = function(oTarget) {
		return new Promise(function(resolve) {
			var iItemCount;
			oTarget.focus();
			oTarget.setSelected();
			RtaQunitUtils.openContextMenuWithKeyboard.call(this, oTarget)
				.then(function () {
					var oContextMenuControl = this.oRta.getPlugins()["contextMenu"].oContextMenuControl;
					iItemCount = oContextMenuControl.getButtons().length;
					return oContextMenuControl;
				}.bind(this))
				.then(RtaQunitUtils.closeContextMenuWithKeyboard)
				.then(function () {
					resolve(iItemCount);
				});
		}.bind(this));
	};

	return RtaQunitUtils;
});
<|endoftext|>


<commit_before>(function() {
    'use strict';
	angular.module('facetApp')
	.directive('personlink', function() {
		return {
			restrict: 	'EC',
			scope: 		{ url: '@' },
			transclude: true,
			controller: ['$scope', 'popoverService', function($scope, popoverService){
		        if (!$scope.url) return;

		        $scope.personId = { personId: ($scope.url).replace(/^.+?(p[0-9]+)$/, '$1') };
		        $scope.image = false;
		        $scope.lifespan = '';

		        popoverService.getPopover($scope.url).then(function(data) {
		        	if (data.length) data = data[0];

		        	$scope.label = data.label;
		        	$scope.color = data.hasbio ? "#337ab7" : "#222";

		        	//	check if lifespan contains any numbers
		        	if ((new RegExp(/\d/)).test(data.lifespan)) {
		        		// remove leading zeros (0800-0900) -> (800-900)
		        		data.lifespan = data.lifespan.replace(/(\D)0/g, "$1");

		        		$scope.lifespan = data.lifespan;
		        	}

		        	if (data.hasOwnProperty('image')) $scope.image = data.image;
		        });

			}],
			template: ' '
		}});
})();
<commit_msg>Removing user-icon from relatives slot<commit_after>(function() {
    'use strict';
	angular.module('facetApp')
	.directive('personlink', function() {
		return {
			restrict: 	'EC',
			scope: 		{ url: '@' },
			transclude: true,
			controller: ['$scope', 'popoverService', function($scope, popoverService){
		        if (!$scope.url) return;

		        $scope.personId = { personId: ($scope.url).replace(/^.+?(p[0-9]+)$/, '$1') };
		        $scope.image = false;
		        $scope.lifespan = '';

		        popoverService.getPopover($scope.url).then(function(data) {
		        	if (data.length) data = data[0];

		        	$scope.label = data.label;
		        	$scope.color = data.hasbio ? "#337ab7" : "#222";

		        	//	check if lifespan contains any numbers
		        	if ((new RegExp(/\d/)).test(data.lifespan)) {
		        		// remove leading zeros (0800-0900) -> (800-900)
		        		data.lifespan = data.lifespan.replace(/(\D)0/g, "$1");

		        		$scope.lifespan = data.lifespan;
		        	}

		        	if (data.hasOwnProperty('image')) $scope.image = data.image;
		        });

			}],
			template: ''
		}});
})();
<|endoftext|>


<commit_before>(function(jQuery) {
"use strict";

var $ = jQuery;

/**
 * @class Echo.StreamServer.Controls.Stream.Item.Plugins.Reply
 * Adds extra “Reply” button to each item in the Echo Stream control.
 * Integrates Echo Submit control and provides the ability to submit
 * replies to the posted items.
 *
 * 	new Echo.StreamServer.Controls.Stream({
 * 		"target": document.getElementById("echo-stream"),
 * 		"appkey": "echo.jssdk.demo.aboutecho.com",
 * 		"plugins": [{
 * 			"name": "Reply"
 * 		}]
 * 	});
 *
 * More information regarding the plugins installation can be found
 * in the [“How to initialize Echo components”](#!/guide/how_to_initialize_components-section-2) guide.
 *
 * @extends Echo.Plugin
 *
 * @package streamserver/plugins.pack.js
 * @package streamserver.pack.js
 */
var plugin = Echo.Plugin.manifest("Reply", "Echo.StreamServer.Controls.Stream.Item");

if (Echo.Plugin.isDefined(plugin)) return;

plugin.init = function() {
	var self = this, item = this.component;
	this.extendTemplate("insertAsLastChild", "content", plugin.templates.form);
	var form = Echo.Utils.get(Echo.Variables, this._getSubmitKey());
	$.each(form || {}, function(key, value) {
	    self.set(key, value);
	});
	item.addButtonSpec("Reply", this._assembleButton());
	this.set("documentClickHandler", this._getClickHandler());
	$(document).on('click', this.get("documentClickHandler"));
};

plugin.config = {
	/**
	 * @cfg {String} actionString
	 * Specifies the hint placed in the empty text area.
	 *
	 * 	new Echo.StreamServer.Controls.Stream({
	 * 		"target": document.getElementById("echo-stream"),
	 * 		"appkey": "echo.jssdk.demo.aboutecho.com",
	 * 		"plugins": [{
	 * 			"name": "Reply",
	 * 			"actionString": "Type your comment here..."
	 * 		}]
	 * 	});
	 */
	"actionString": "Write a reply..."
};

plugin.labels = {
	/**
	 * @echo_label
	 * Label for the button in the item
	 */
	"replyControl": "Reply"
};

plugin.dependencies = [{
	"control": "Echo.StreamServer.Controls.Submit",
	"url": "{config:cdnBaseURL.sdk}/streamserver.pack.js"
}];

plugin.events = {
	"Echo.StreamServer.Controls.Stream.Plugins.Reply.onFormExpand": function(topic, args) {
		var item = this.component;
		var context = item.config.get("context");
		if (this.get("expanded") && context && context !== args.context) {
			this._hideSubmit();
		}
	},
	"Echo.StreamServer.Controls.Submit.onPostComplete": function(topic, args) {
		this._hideSubmit();
	},
	"Echo.StreamServer.Controls.Stream.Item.onRender": function(topic, args) {
		if (this.get("expanded")) {
			this._showSubmit();
		}
	}
};

plugin.templates.form =
	'
' +
		'

' +
		'
' +
			'
' +
				'<input class="{plugin.class:compactField} echo-primaryFont echo-secondaryColor">' +
			'
' +
		'
' +
	'
';

/**
 * @echo_renderer
 */
plugin.component.renderers.container = function(element) {
	var item = this.component;
	var threading = item.threading;
	if (this.get("expanded")) {
		item.threading = true;
	}
	item.parentRenderer("container", arguments);
	item.threading = threading;
	return element;
};

/**
 * @echo_renderer
 */
plugin.component.renderers.children = function(element) {
	var item = this.component;
	// perform reply form rerendering *only* when we have exactly 1 item
	// (the first item is being added or the last one is being deleted)
	if (item.get("children").length === 1) {
		var child = item.get("children")[0];
		if (child.get("added") || child.get("deleted")) {
			this._itemCSS("remove", item, this.view.get("compactForm"));
			this.view.render({"name": "compactForm"});
		}
	}
	return item.parentRenderer("children", arguments);
};

/**
 * @echo_renderer
 */
plugin.renderers.submitForm = function(element) {
	element.click(function(event) {
		event.stopPropagation();
	});
	return this.get("expanded") ? element.show() : element.empty().hide();
};

/**
 * @echo_renderer
 */
plugin.renderers.compactForm = function(element) {
	var item = this.component;
	var hasChildren = !!item.children.length;
	if (!item.get("depth") && hasChildren && !this.get("expanded") && !item.get("children")[0].get("deleted")) {
		this._itemCSS("add", item, element);
		return element.show();
	}
	this._itemCSS("remove", item, this.view.get("compactForm"));
	return element.hide();
};

/**
 * @echo_renderer
 */
plugin.renderers.compactField = function(element) {
	var plugin = this, item = this.component;
	return element.focus(function() {
		plugin._showSubmit();
	}).val(this.config.get("actionString"));
};

/**
 * Method to destroy the plugin.
 */
plugin.methods.destroy = function() {
	if (this.get("submit")) {
		Echo.Utils.set(Echo.Variables, this._getSubmitKey(), {
			"expanded": this.get("expanded"),
			"data": {
				"object": this._getSubmitData()
			}
		});
	}
	$(document).off('click', this.get("documentClickHandler"));
};

plugin.methods._submitConfig = function(target) {
	var plugin = this, item = this.component;
	return plugin.config.assemble({
		"target": target,
		"targetURL": item.get("data.object.id"),
		"parent": item.config.getAsHash(),
		"data": plugin.get("data") || {},
		"targetQuery": item.config.get("query", ""),
		"ready": function() {
			plugin.set("submit", this);
			plugin._expand();
		}
	});
};

plugin.methods._showSubmit = function() {
	var item = this.component;
	var target = this.view.get("submitForm");
	this._itemCSS("add", item, this.view.get("submitForm"));
	var submit = this.get("submit");
	if (submit) {
		submit.config.set("target", target);
		submit.render();
		this._expand();
		return target;
	}
	var config = this._submitConfig(target);
	config.plugins.push({
		"name": "Reply",
		"inReplyTo": item.get("data")
	});
	new Echo.StreamServer.Controls.Submit(config);
	return target;
};

plugin.methods._hideSubmit = function() {
	var item = this.component;
	var submit = this.get("submit");
	if (submit) {
		submit.set("data", undefined);
	}
	this.set("expanded", false);
	this._itemCSS("remove", item, this.view.get("submitForm"));
	this.view.get("submitForm").empty();
	this.view.render({"name": "compactForm"});
	item.view.render({"name": "container"});
	/**
	 * @echo_event Echo.StreamServer.Controls.Stream.Item.Plugins.Reply.onCollapse
	 * Triggered when the reply form is closed.
	 */
	this.events.publish({
		"topic": "onCollapse"
	});
};

plugin.methods._expand = function() {
	var item = this.component;
	this.set("expanded", true);
	this.view.render({"name": "submitForm"});
	this.view.render({"name": "compactForm"});
	/**
	 * @echo_event Echo.StreamServer.Controls.Stream.Item.Plugins.Reply.onExpand
	 * Triggered when the reply form is expanded.
	 */
	this.events.publish({
		"topic": "onExpand",
		"data": {
			"context": item.config.get("context")
		}
	});
	item.view.render({"name": "container"});
};

plugin.methods._getClickHandler = function() {
	var plugin = this;
	return function() {
	    var submit = plugin.get("submit");
	    if (plugin.get("expanded") && submit && !submit.view.get("text").val()) {
		    plugin._hideSubmit();
	    }
	};
};

plugin.methods._assembleButton = function() {
	var plugin = this, item = this.component;
	var callback = function() {
		plugin._showSubmit();
	};
	return function() {
		var item = this;
		return {
			"name": "Reply",
			"label": plugin.labels.get("replyControl"),
			"visible": item.get("depth") < item.config.get("parent.children.maxDepth"),
			"callback": callback
		};
	};
};

plugin.methods._itemCSS = function(action, item, element) {
	$.each(["container", "container-child", "depth-" + (item.get("depth") + 1)], function(i, css) {
		element[action + "Class"](item.get("cssPrefix") + css);
	});
	element[action + "Class"]('echo-trinaryBackgroundColor');
};

plugin.methods._getSubmitKey = function() {
	var item = this.component;
	var applicationContext = item.config.get("context").split("/")[0];
	return "forms." + item.data.unique + "-" + applicationContext;
};

plugin.methods._getSubmitData = function() {
	var data = {};
	var submit = this.get("submit");
	data["content"] = submit.view.get("text").val();
	$.map(["tags", "markers"], function(field) {
		var elements = submit.view.get(field).val().split(", ");
		data[field] = elements || [];
	});
	return data;
};

plugin.css =
	".{plugin.class:compactContent} { padding: 5px 5px 5px 6px; background-color: #fff; }" +
	".{plugin.class:compactBorder} { border: 1px solid #d2d2d2; }" +
	".{plugin.class:compactContent} input.{plugin.class:compactField} { width: 100%; border: none; }" +
	'.{plugin.class:compactContent} input.{plugin.class:compactField}[type="text"] { width: 100%; border: none; margin: 0px; padding: 0px; }';

Echo.Plugin.create(plugin);

})(Echo.jQuery);

(function(jQuery) {
"use strict";

var $ = jQuery;

/**
 * @class Echo.StreamServer.Controls.Stream.Plugins.Reply
 * Proxies the "Echo.StreamServer.Controls.Stream.Item.Plugins.Reply.onExpand"
 * event on the Stream control level.
 *
 * 	new Echo.StreamServer.Controls.Stream({
 * 		"target": document.getElementById("echo-stream"),
 * 		"appkey": "echo.jssdk.demo.aboutecho.com",
 * 		"plugins": [{
 * 			"name": "Reply"
 * 		}]
 * 	});
 *
 * More information regarding the plugins installation can be found
 * in the [“How to initialize Echo components”](#!/guide/how_to_initialize_components-section-2) guide.
 *
 * @extends Echo.Plugin
 *
 * @private
 * @package streamserver/plugins.pack.js
 * @package streamserver.pack.js
 */
var plugin = Echo.Plugin.manifest("Reply", "Echo.StreamServer.Controls.Stream");

if (Echo.Plugin.isDefined(plugin)) return;

plugin.events = {
	"Echo.StreamServer.Controls.Stream.Item.Plugins.Reply.onExpand": function(topic, args) {
		/**
		 * @echo_event Echo.StreamServer.Controls.Stream.Plugins.Reply.onFormExpand
		 * Triggered if reply form is expanded.
		 */
		this.events.publish({
			"topic": "onFormExpand",
			"data": {
			    "context": args.context
			}
		});
	}
};

Echo.Plugin.create(plugin);

})(Echo.jQuery);

(function(jQuery) {
"use strict";

var $ = jQuery;

/**
 * @class Echo.StreamServer.Controls.Submit.Plugins.Reply
 * Adds internal data field "inReplyTo" for correct reply workflow.
 *
 * 	new Echo.StreamServer.Controls.Submit({
 * 		"target": document.getElementById("echo-submit"),
 * 		"appkey": "echo.jssdk.demo.aboutecho.com",
 * 		"plugins": [{
 * 			"name": "Reply",
 * 			"inReplyTo": data
 * 		}]
 * 	});
 *
 * More information regarding the plugins installation can be found
 * in the [“How to initialize Echo components”](#!/guide/how_to_initialize_components-section-2) guide.
 *
 * @extends Echo.Plugin
 *
 * @private
 * @package streamserver/plugins.pack.js
 * @package streamserver.pack.js
 */
var plugin = Echo.Plugin.manifest("Reply", "Echo.StreamServer.Controls.Submit");

if (Echo.Plugin.isDefined(plugin)) return;

plugin.init = function() {
	var plugin = this, submit = plugin.component;
	var _prepareEventParams = submit._prepareEventParams;
	submit._prepareEventParams = function(params) {
		var _params = _prepareEventParams.call(submit, params);
		_params.inReplyTo = plugin.config.get("inReplyTo");
		return _params;
	};
};

/**
 * @cfg {Object} inReplyTo
 * Entry which is the parent for the current reply.
 */

$.map(["onRender", "onRerender"], function(topic) {
	plugin.events["Echo.StreamServer.Controls.Submit." + topic] = function() {
		var submit = this.component;
		submit.config.get("target").show();
		submit.view.get("text").focus();
	};
});

Echo.Plugin.create(plugin);

})(Echo.jQuery);
<commit_msg>Fixed issue with font style in compact reply form<commit_after>(function(jQuery) {
"use strict";

var $ = jQuery;

/**
 * @class Echo.StreamServer.Controls.Stream.Item.Plugins.Reply
 * Adds extra “Reply” button to each item in the Echo Stream control.
 * Integrates Echo Submit control and provides the ability to submit
 * replies to the posted items.
 *
 * 	new Echo.StreamServer.Controls.Stream({
 * 		"target": document.getElementById("echo-stream"),
 * 		"appkey": "echo.jssdk.demo.aboutecho.com",
 * 		"plugins": [{
 * 			"name": "Reply"
 * 		}]
 * 	});
 *
 * More information regarding the plugins installation can be found
 * in the [“How to initialize Echo components”](#!/guide/how_to_initialize_components-section-2) guide.
 *
 * @extends Echo.Plugin
 *
 * @package streamserver/plugins.pack.js
 * @package streamserver.pack.js
 */
var plugin = Echo.Plugin.manifest("Reply", "Echo.StreamServer.Controls.Stream.Item");

if (Echo.Plugin.isDefined(plugin)) return;

plugin.init = function() {
	var self = this, item = this.component;
	this.extendTemplate("insertAsLastChild", "content", plugin.templates.form);
	var form = Echo.Utils.get(Echo.Variables, this._getSubmitKey());
	$.each(form || {}, function(key, value) {
	    self.set(key, value);
	});
	item.addButtonSpec("Reply", this._assembleButton());
	this.set("documentClickHandler", this._getClickHandler());
	$(document).on('click', this.get("documentClickHandler"));
};

plugin.config = {
	/**
	 * @cfg {String} actionString
	 * Specifies the hint placed in the empty text area.
	 *
	 * 	new Echo.StreamServer.Controls.Stream({
	 * 		"target": document.getElementById("echo-stream"),
	 * 		"appkey": "echo.jssdk.demo.aboutecho.com",
	 * 		"plugins": [{
	 * 			"name": "Reply",
	 * 			"actionString": "Type your comment here..."
	 * 		}]
	 * 	});
	 */
	"actionString": "Write a reply..."
};

plugin.labels = {
	/**
	 * @echo_label
	 * Label for the button in the item
	 */
	"replyControl": "Reply"
};

plugin.dependencies = [{
	"control": "Echo.StreamServer.Controls.Submit",
	"url": "{config:cdnBaseURL.sdk}/streamserver.pack.js"
}];

plugin.events = {
	"Echo.StreamServer.Controls.Stream.Plugins.Reply.onFormExpand": function(topic, args) {
		var item = this.component;
		var context = item.config.get("context");
		if (this.get("expanded") && context && context !== args.context) {
			this._hideSubmit();
		}
	},
	"Echo.StreamServer.Controls.Submit.onPostComplete": function(topic, args) {
		this._hideSubmit();
	},
	"Echo.StreamServer.Controls.Stream.Item.onRender": function(topic, args) {
		if (this.get("expanded")) {
			this._showSubmit();
		}
	}
};

plugin.templates.form =
	'
' +
		'

' +
		'
' +
			'
' +
				'<input type="text" class="{plugin.class:compactField} echo-primaryFont echo-secondaryColor">' +
			'
' +
		'
' +
	'
';

/**
 * @echo_renderer
 */
plugin.component.renderers.container = function(element) {
	var item = this.component;
	var threading = item.threading;
	if (this.get("expanded")) {
		item.threading = true;
	}
	item.parentRenderer("container", arguments);
	item.threading = threading;
	return element;
};

/**
 * @echo_renderer
 */
plugin.component.renderers.children = function(element) {
	var item = this.component;
	// perform reply form rerendering *only* when we have exactly 1 item
	// (the first item is being added or the last one is being deleted)
	if (item.get("children").length === 1) {
		var child = item.get("children")[0];
		if (child.get("added") || child.get("deleted")) {
			this._itemCSS("remove", item, this.view.get("compactForm"));
			this.view.render({"name": "compactForm"});
		}
	}
	return item.parentRenderer("children", arguments);
};

/**
 * @echo_renderer
 */
plugin.renderers.submitForm = function(element) {
	element.click(function(event) {
		event.stopPropagation();
	});
	return this.get("expanded") ? element.show() : element.empty().hide();
};

/**
 * @echo_renderer
 */
plugin.renderers.compactForm = function(element) {
	var item = this.component;
	var hasChildren = !!item.children.length;
	if (!item.get("depth") && hasChildren && !this.get("expanded") && !item.get("children")[0].get("deleted")) {
		this._itemCSS("add", item, element);
		return element.show();
	}
	this._itemCSS("remove", item, this.view.get("compactForm"));
	return element.hide();
};

/**
 * @echo_renderer
 */
plugin.renderers.compactField = function(element) {
	var plugin = this, item = this.component;
	return element.focus(function() {
		plugin._showSubmit();
	}).val(this.config.get("actionString"));
};

/**
 * Method to destroy the plugin.
 */
plugin.methods.destroy = function() {
	if (this.get("submit")) {
		Echo.Utils.set(Echo.Variables, this._getSubmitKey(), {
			"expanded": this.get("expanded"),
			"data": {
				"object": this._getSubmitData()
			}
		});
	}
	$(document).off('click', this.get("documentClickHandler"));
};

plugin.methods._submitConfig = function(target) {
	var plugin = this, item = this.component;
	return plugin.config.assemble({
		"target": target,
		"targetURL": item.get("data.object.id"),
		"parent": item.config.getAsHash(),
		"data": plugin.get("data") || {},
		"targetQuery": item.config.get("query", ""),
		"ready": function() {
			plugin.set("submit", this);
			plugin._expand();
		}
	});
};

plugin.methods._showSubmit = function() {
	var item = this.component;
	var target = this.view.get("submitForm");
	this._itemCSS("add", item, this.view.get("submitForm"));
	var submit = this.get("submit");
	if (submit) {
		submit.config.set("target", target);
		submit.render();
		this._expand();
		return target;
	}
	var config = this._submitConfig(target);
	config.plugins.push({
		"name": "Reply",
		"inReplyTo": item.get("data")
	});
	new Echo.StreamServer.Controls.Submit(config);
	return target;
};

plugin.methods._hideSubmit = function() {
	var item = this.component;
	var submit = this.get("submit");
	if (submit) {
		submit.set("data", undefined);
	}
	this.set("expanded", false);
	this._itemCSS("remove", item, this.view.get("submitForm"));
	this.view.get("submitForm").empty();
	this.view.render({"name": "compactForm"});
	item.view.render({"name": "container"});
	/**
	 * @echo_event Echo.StreamServer.Controls.Stream.Item.Plugins.Reply.onCollapse
	 * Triggered when the reply form is closed.
	 */
	this.events.publish({
		"topic": "onCollapse"
	});
};

plugin.methods._expand = function() {
	var item = this.component;
	this.set("expanded", true);
	this.view.render({"name": "submitForm"});
	this.view.render({"name": "compactForm"});
	/**
	 * @echo_event Echo.StreamServer.Controls.Stream.Item.Plugins.Reply.onExpand
	 * Triggered when the reply form is expanded.
	 */
	this.events.publish({
		"topic": "onExpand",
		"data": {
			"context": item.config.get("context")
		}
	});
	item.view.render({"name": "container"});
};

plugin.methods._getClickHandler = function() {
	var plugin = this;
	return function() {
	    var submit = plugin.get("submit");
	    if (plugin.get("expanded") && submit && !submit.view.get("text").val()) {
		    plugin._hideSubmit();
	    }
	};
};

plugin.methods._assembleButton = function() {
	var plugin = this, item = this.component;
	var callback = function() {
		plugin._showSubmit();
	};
	return function() {
		var item = this;
		return {
			"name": "Reply",
			"label": plugin.labels.get("replyControl"),
			"visible": item.get("depth") < item.config.get("parent.children.maxDepth"),
			"callback": callback
		};
	};
};

plugin.methods._itemCSS = function(action, item, element) {
	$.each(["container", "container-child", "depth-" + (item.get("depth") + 1)], function(i, css) {
		element[action + "Class"](item.get("cssPrefix") + css);
	});
	element[action + "Class"]('echo-trinaryBackgroundColor');
};

plugin.methods._getSubmitKey = function() {
	var item = this.component;
	var applicationContext = item.config.get("context").split("/")[0];
	return "forms." + item.data.unique + "-" + applicationContext;
};

plugin.methods._getSubmitData = function() {
	var data = {};
	var submit = this.get("submit");
	data["content"] = submit.view.get("text").val();
	$.map(["tags", "markers"], function(field) {
		var elements = submit.view.get(field).val().split(", ");
		data[field] = elements || [];
	});
	return data;
};

plugin.css =
	".{plugin.class:compactContent} { padding: 5px 5px 5px 6px; background-color: #fff; }" +
	".{plugin.class:compactBorder} { border: 1px solid #d2d2d2; }" +
	".{plugin.class:compactContent} input.{plugin.class:compactField}[type='text'].echo-secondaryColor { color: #C6C6C6 }" +
	".{plugin.class:compactContent} input.{plugin.class:compactField}[type='text'].echo-primaryFont { font-size: 12px; line-height: 16px; }" +
	".{plugin.class:compactContent} input.{plugin.class:compactField}[type='text'] { width: 100%; height: 16px; border: none; margin: 0px; padding: 0px; box-shadow: none; vertical-align: middle; }" +
	".{plugin.class:compactContent} input.{plugin.class:compactField}[type='text']:focus { outline: 0; box-shadow: none; }";

Echo.Plugin.create(plugin);

})(Echo.jQuery);

(function(jQuery) {
"use strict";

var $ = jQuery;

/**
 * @class Echo.StreamServer.Controls.Stream.Plugins.Reply
 * Proxies the "Echo.StreamServer.Controls.Stream.Item.Plugins.Reply.onExpand"
 * event on the Stream control level.
 *
 * 	new Echo.StreamServer.Controls.Stream({
 * 		"target": document.getElementById("echo-stream"),
 * 		"appkey": "echo.jssdk.demo.aboutecho.com",
 * 		"plugins": [{
 * 			"name": "Reply"
 * 		}]
 * 	});
 *
 * More information regarding the plugins installation can be found
 * in the [“How to initialize Echo components”](#!/guide/how_to_initialize_components-section-2) guide.
 *
 * @extends Echo.Plugin
 *
 * @private
 * @package streamserver/plugins.pack.js
 * @package streamserver.pack.js
 */
var plugin = Echo.Plugin.manifest("Reply", "Echo.StreamServer.Controls.Stream");

if (Echo.Plugin.isDefined(plugin)) return;

plugin.events = {
	"Echo.StreamServer.Controls.Stream.Item.Plugins.Reply.onExpand": function(topic, args) {
		/**
		 * @echo_event Echo.StreamServer.Controls.Stream.Plugins.Reply.onFormExpand
		 * Triggered if reply form is expanded.
		 */
		this.events.publish({
			"topic": "onFormExpand",
			"data": {
			    "context": args.context
			}
		});
	}
};

Echo.Plugin.create(plugin);

})(Echo.jQuery);

(function(jQuery) {
"use strict";

var $ = jQuery;

/**
 * @class Echo.StreamServer.Controls.Submit.Plugins.Reply
 * Adds internal data field "inReplyTo" for correct reply workflow.
 *
 * 	new Echo.StreamServer.Controls.Submit({
 * 		"target": document.getElementById("echo-submit"),
 * 		"appkey": "echo.jssdk.demo.aboutecho.com",
 * 		"plugins": [{
 * 			"name": "Reply",
 * 			"inReplyTo": data
 * 		}]
 * 	});
 *
 * More information regarding the plugins installation can be found
 * in the [“How to initialize Echo components”](#!/guide/how_to_initialize_components-section-2) guide.
 *
 * @extends Echo.Plugin
 *
 * @private
 * @package streamserver/plugins.pack.js
 * @package streamserver.pack.js
 */
var plugin = Echo.Plugin.manifest("Reply", "Echo.StreamServer.Controls.Submit");

if (Echo.Plugin.isDefined(plugin)) return;

plugin.init = function() {
	var plugin = this, submit = plugin.component;
	var _prepareEventParams = submit._prepareEventParams;
	submit._prepareEventParams = function(params) {
		var _params = _prepareEventParams.call(submit, params);
		_params.inReplyTo = plugin.config.get("inReplyTo");
		return _params;
	};
};

/**
 * @cfg {Object} inReplyTo
 * Entry which is the parent for the current reply.
 */

$.map(["onRender", "onRerender"], function(topic) {
	plugin.events["Echo.StreamServer.Controls.Submit." + topic] = function() {
		var submit = this.component;
		submit.config.get("target").show();
		submit.view.get("text").focus();
	};
});

Echo.Plugin.create(plugin);

})(Echo.jQuery);
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import Ribbon, { RibbonDataProvider } from 'gene-ontology-ribbon';
import '../../../node_modules/gene-ontology-ribbon/lib/index.css';

class GeneOntologyRibbon extends Component {
  render() {
    const {db, id} =  this.props;

    return (
      <RibbonDataProvider subject={id}>
      {({title, data, dataReceived, dataError}) => (

          {
            dataReceived ? <Ribbon data={data} title={title} /> : null
          }
          {
            dataError ? No Data Available : null
          }
          {
            dataReceived || dataError ? null : 'Loading...'
          }

        )
      }
      </RibbonDataProvider>
    );
  }
}

GeneOntologyRibbon.propTypes = {
  db: React.PropTypes.string.isRequired,
  id: React.PropTypes.string.isRequired
};

export default GeneOntologyRibbon;
<commit_msg>removed unused db prop for GeneOntologyRibbon<commit_after>import React, { Component } from 'react';
import Ribbon, { RibbonDataProvider } from 'gene-ontology-ribbon';
import '../../../node_modules/gene-ontology-ribbon/lib/index.css';

class GeneOntologyRibbon extends Component {
  render() {
    const {id} =  this.props;

    return (
      <RibbonDataProvider subject={id}>
      {({title, data, dataReceived, dataError}) => (

          {
            dataReceived ? <Ribbon data={data} title={title} /> : null
          }
          {
            dataError ? No Data Available : null
          }
          {
            dataReceived || dataError ? null : 'Loading...'
          }

        )
      }
      </RibbonDataProvider>
    );
  }
}

GeneOntologyRibbon.propTypes = {
  id: React.PropTypes.string.isRequired
};

export default GeneOntologyRibbon;
<|endoftext|>