reimandlab/Visualistion-Framework-for-Genome-Mutations

View on GitHub
website/static/searchbar.js

Summary

Maintainability
D
1 day
Test Coverage
var more_icon = '<span class="glyphicon glyphicon-chevron-right more"></span>';

var SearchBar = function ()
{
    var input
    var results_div
    var current_query
    var indicator
    var initial_results_content

    function default_template_result(result)
    {
        return '<a href="' + result.url + '" class="list-group-item">' + result.name + '</a>'
    }

    var config = {
        autocomplete_url: '/search/autocomplete_all',
        template: default_template_result
    }

    function update_results(results, original_query) {

        // if we've got a result of an old query, it's not interesting anymore
        if(original_query !== current_query)
            return false

        if(!results.entries.length)
        {
            results_div.html(config.template({
                name: 'No results found',
                type: 'message'
            }))
        }
        else
        {
            var html = ''
            for(var i = 0; i < results.entries.length; i++)
            {
                html += config.template(results.entries[i])
            }
            results_div.html(html)

            add_dropdown_navigation(results_div)
            show_fake_focus_on_first(results_div)
        }
        indicator.hide()
    }

    function show_fake_focus_on_first(dropdown_element) {
        var elements = dropdown_element.find('.list-group-item')
        var first_element = $(elements[0])

        first_element.addClass('focus')
    }

    function add_dropdown_navigation(dropdown_element)
    {
        var elements = dropdown_element.find('.list-group-item')
        for(var i = 0; i < elements.length; i++)
        {
            $(elements[i]).on('keydown', {i: i}, function(e)
            {
                var i = e.data.i

                // arrow up
                if(e.which === 38)
                {
                    if(i > 0)
                        $(elements[i - 1]).focus()
                    else
                        input.focus()

                    return false
                }
                // arrow down
                else if(e.which === 40)
                {
                    if(i + 1 < elements.length)
                        $(elements[i + 1]).focus()
                    else
                        input.focus()

                    return false
                }
            })

            $(elements[i]).on('click', function(e)
            {
                e.stopPropagation()
                $(this).addClass('item-loading')
            })
        }
    }

    function search_on_type()
    {
        var query = input.val()

        // if the query has not changed, skip it
        if(current_query === query)
            return

        current_query = query

        // if the query is empty, clear up results
        if(!query)
        {
            results_div.html(initial_results_content)
            indicator.hide()
            return
        }

        $.ajax({
            url: config.autocomplete_url,
            type: 'GET',
            data: {q: encodeURIComponent(query)},
            success: function(query)
            {
                return function(result)
                {
                    return update_results(result, query)
                }
            }(query)
        })

        indicator.show()
    }


    var publicSpace = {
        init: function(data)
        {
            update_object(config, data)
            var box = $(data.box)
            input = box.find('input')
            results_div = box.find('.bar-results')
            indicator = box.find('.waiting-indicator')
            initial_results_content = results_div.html()

            input.on('change mouseup drop input', search_on_type)
            input.on('click', function(){ return false })
            input.on('focus', function(){ results_div.show() })
            input.on('keydown', function(e){
                // arrow down
                if(e.which === 40)
                {
                    var elements = results_div.find('.list-group-item')
                    var first = $(elements[0])
                    var focus_on;

                    if(first.hasClass('focus'))
                    {
                        first.removeClass('focus')
                        focus_on = 1
                    }
                    else {
                        focus_on = 0
                    }
                    elements[focus_on].focus()

                    return false
                }
                // arrow up
                else if(e.which === 38)
                {
                    var elements = results_div.find('.list-group-item')
                    elements.first().removeClass('focus')
                    elements.last().focus()

                    return false
                }
                //
                else if(e.which === 13)
                {
                    // pressing enter is equivalent to clicking on a first result,
                    // as requested in #124
                    results_div.find('.list-group-item').first().get(0).click()

                    // blur the input so user will need to click on it to type
                    // (and it will show up again in case if it was hidden due to click() action)
                    input.blur()

                    return false
                }
            })

            add_dropdown_navigation(results_div)

            $(document.body).on('click', function(){
                results_div.hide()
                indicator.hide()
            })
        }
    }

    return publicSpace
}


function badge(name) {
    return '<span class="badge">' + name + '</span>';
}


function advanced_searchbar_templator(mutation_template, protein_template)
{

    function template_mutation(result, name)
    {
        var badges = '';

        if(result.mutation.is_confirmed)
            badges += badge('known mutation');

        if(result.mutation.is_ptm)
            badges += badge('PTM mutation');

        if(result.protein.is_preferred)
            badges += badge('preferred isoform');

        return format(mutation_template, {
            name: name,
            refseq: result.protein.refseq,
            pos: result.pos,
            alt: result.alt,
            badges: badges
        });

    }

    var cancer_template = 'Did you mean somatic cancer mutations of {{ name }} ({{ code }}) from TCGA?'
    var disease_template = 'Did you mean {{ name }} mutations from ClinVar?'
    var disease_in_protein_template = '{{ name }} mutations in {{ gene }} ({{ refseq }})'

    return (
        function (result)
        {
            var link, name = ''

            if('url' in result)
                link = '<a href="' + result.url + '" class="list-group-item">'

            switch(result.type)
            {
                case 'gene':
                    var badges = '';

                    if(result.isoforms_count > 1)
                        badges += badge(result.isoforms_count + ' isoforms')

                    return format(
                        protein_template,
                        {
                            preferred_isoform: result.preferred_isoform,
                            name: result.name,
                            badges: badges
                        }
                    )

                case 'aminoacid mutation':
                    name = result.mutation.name + ' (' + result.protein.refseq + ')';
                    return template_mutation(result, name)

                case 'nucleotide mutation':
                    name = result.mutation.name + ' (' + result.protein.refseq + ')' + ', result of ' + result.input
                    return template_mutation(result, name)

                case 'message':
                    return '<button type="button" class="list-group-item">' + result.name + '</button>'

                case 'pathway':

                    link += result.name

                    if(result.gene_ontology)
                        link += badge('Gene Ontology pathway')
                    if(result.reactome)
                        link += badge('Reactome pathway')

                    return link + '</a>'

                case 'cancer':
                    return link + format(cancer_template, result) + badge('Cancer') + '</a>'

                case 'disease':
                    return link + format(disease_template, result) + badge('Disease') + '</a>'

                case 'disease_in_protein':
                    return link + format(disease_in_protein_template, result) + badge('Disease mutations') + '</a>'

                case 'see_more':
                    return link + result.name + more_icon + '</a>'

            }
        }
    )
}