Skip to content
Snippets Groups Projects
Select Git revision
  • fbf008efa11f009d2b89109e99c213c44c62e024
  • main default protected
  • studip-rector
  • ci-opt
  • course-members-export-as-word
  • data-vue-app
  • pipeline-improvements
  • webpack-optimizations
  • rector
  • icon-renewal
  • http-client-and-factories
  • jsonapi-atomic-operations
  • vueify-messages
  • tic-2341
  • 135-translatable-study-areas
  • extensible-sorm-action-parameters
  • sorm-configuration-trait
  • jsonapi-mvv-routes
  • docblocks-for-magic-methods
19 results

MyRealmModel.php

Blame
  • Forked from Stud.IP / Stud.IP
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    global_search.js 9.17 KiB
    const GlobalSearch = {
        lastSearch: null,
    
        /**
         * Toggles visibility of search input field and hints.
         * @param visible boolean indicating whether shown or not
         * @param cleanup boolean whether to clear search term and results
         * @returns {boolean}
         */
        toggleSearchBar: function(visible, cleanup) {
            $('#globalsearch-searchbar').toggleClass('is-visible', visible);
            $('#globalsearch-input').attr('aria-expanded', visible ? 'true' : 'false');
            $('#globalsearch-input').toggleClass('hidden-small-down', !visible);
            $('#globalsearch-icon').toggleClass('hidden-small-down', visible);
            $('#globalsearch-clear').toggleClass('hidden-small-down', !visible);
    
            if (!visible && cleanup) {
                GlobalSearch.lastSearch = null;
                $('#globalsearch-searchbar').removeClass('has-value');
                $('#globalsearch-results').html('');
                $('#globalsearch-input').blur().val('');
            }
    
            $('html:not(.size-large)').toggleClass('globalsearch-visible', visible);
    
            return false;
        },
    
        /**
         * Performs the actual search.
         */
        doSearch: function() {
            var searchterm = $('#globalsearch-input').val().trim();
            var hasValue = searchterm.length >= 3;
            var results = $();
            var resultsDiv = $('#globalsearch-results');
            var resultsPerType = resultsDiv.data('results-per-type');
            var moreResultsText = resultsDiv.data('more-results');
            var limit = resultsPerType * 3;
            var wrapper = $('#globalsearch-searchbar');
    
            if (searchterm === '') {
                return;
            }
    
            wrapper.toggleClass('has-value', hasValue);
    
            if (!hasValue || GlobalSearch.lastSearch === searchterm) {
                return;
            }
    
            GlobalSearch.lastSearch = searchterm;
    
            // Display spinner symbol, user should always see something is happening.
            wrapper.addClass('is-searching');
    
            // Call AJAX endpoint and get search results.
            $.getJSON(STUDIP.URLHelper.getURL('dispatch.php/globalsearch/find/' + limit, {}, true), {
                search: searchterm,
                filters: '{"category":"show_all_categories","semester":"future"}'
            }).done(function(json) {
                resultsDiv.empty();
    
                // No results found...
                if (!$.isPlainObject(json) || $.isEmptyObject(json)) {
                    wrapper.removeClass('is-searching');
                    resultsDiv.html(resultsDiv.data('no-result'));
                    return;
                }
    
                // Iterate over each result category.
                $.each(json, function(name, value) {
                    // Create an <article> for category.
                    var category = $(`<article id="globalsearch-${name}" role="list">`),
                        header = $('<header>').appendTo(category),
                        counter = 0;
    
                    // Create header name
                    $('<a href="#">')
                        .text(value.name)
                        .wrap('<div class="globalsearch-category">')
                        .parent() // Element is now the wrapper
                        .data('category', name)
                        .appendTo(header);
    
                    // We have more search results than shown, provide link to
                    // full search if available.
                    if (value.more && value.fullsearch !== '') {
                        $('<a>')
                            .attr('href', value.fullsearch)
                            .text(moreResultsText)
                            .wrap('<div class="globalsearch-more-results">')
                            .parent() // Element is now the wrapper
                            .appendTo(header);
                    }
    
                    // Process results and create corresponding entries.
                    $.each(value.content, function(index, result) {
                        // Create single result entry.
                        var single = $(`<a href="${result.url}" role="listitem" ${dataDialog}>`),
                            data = $('<div class="globalsearch-result-data">'),
                            details = $('<div class="globalsearch-result-details">');
    
                        if (counter >= resultsPerType) {
                            single.addClass('globalsearch-extended-result');
                        }
    
                        // Which result types should be opened via dialog?
                        const openInDialog = ['GlobalSearchFiles', 'GlobalSearchMessages'];
                        var dataDialog = (openInDialog.indexOf(name) >= 0 ? dataDialog = 'data-dialog' : dataDialog = '');
                        //var link = $(`<a href="${result.url}" ${dataDialog}>`).appendTo(single);
    
                        // Optional image...
                        if (result.img !== null) {
                            $(`<img src="${result.img}" alt="">`)
                                .wrap('<div class="globalsearch-result-img">')
                                .parent() // Element is now the wrapper
                                .appendTo(single);
                        }
    
                        single.append(data);
    
                        // Name/title
                        $('<div class="globalsearch-result-title">')
                            .html(result.name)
                            .appendTo(data);
    
                        // Details: Descriptional text
                        if (result.description !== null) {
                            $('<div class="globalsearch-result-description">')
                                .html(result.description)
                                .appendTo(details);
                        }
    
                        // Details: Additional information
                        if (result.additional !== null) {
                            $('<div class="globalsearch-result-additional">')
                                .html(result.additional)
                                .appendTo(details);
                        }
    
                        data.append(details);
    
                        // Date/Time of entry
                        if (result.date !== null) {
                            $('<div class="globalsearch-result-time">')
                                .html(result.date)
                                .appendTo(single);
                        }
    
                        // "Expand" attribute for further, result-related search
                        // (e.g. search in course of found forum entry)
                        if (result.expand !== null && result.expand !== value.fullsearch && value.more) {
                            $(`<a href="${result.expand}" title="${result.expandtext}">`)
                                .wrap('<div class="globalsearch-result-expand">')
                                .parent() // Element is now the wrapper
                                .appendTo(single);
                        }
                        category.append(single);
    
                        counter += 1;
                    });
                    results = results.add(category);
                });
    
                resultsDiv.html(results);
                wrapper.removeClass('is-searching');
            }).fail(function(xhr, status, error) {
                if (error) {
                    window.alert(error);
                }
            });
        },
    
        /**
         * Clear search term and remove results for previous search term.
         */
        resetSearch: function() {
            GlobalSearch.lastSearch = null;
    
            $('#globalsearch-searchbar').removeClass('is-visible has-value');
            $('#globalsearch-input').attr('aria-expanded', 'false');
            $('#globalsearch-input').val('');
            $('#globalsearch-results').html('');
            $('#globalsearch-input').focus();
        },
    
        /**
         * Expand a single category, showing more results, and hide other
         * categories.
         * @param category
         * @returns {boolean}
         */
        expandCategory: function(category) {
            // Hide other categories.
            $(`#globalsearch-results article:not([id="globalsearch-${category}"])`).hide();
            // Show all results.
            $(`#globalsearch-${category} section.globalsearch-extended-result`).removeClass(
                'globalsearch-extended-result'
            );
            $(`article#globalsearch-${category}`).get(0).scrollIntoView();
            // Reassign category click to closing extended view.
            $(`#globalsearch-results article#globalsearch-${category} header div.globalsearch-category a`)
                .off('click')
                .on('click', function() {
                    GlobalSearch.showAllCategories(category);
                    return false;
                });
            return false;
        },
    
        /**
         * Close expanded view of a single category, showing normal view with
         * all categories again.
         * @param currentCategory
         */
        showAllCategories: function(currentCategory) {
            $(`#globalsearch-results article#globalsearch-${currentCategory} header div.globalsearch-category a`)
                .off('click')
                .on('click', function() {
                    GlobalSearch.expandCategory(currentCategory);
                    return false;
                });
            var resultCount = $('#globalsearch-results').data('results-per-type') - 1;
            $(`#globalsearch-${currentCategory} section:gt(${resultCount})`).addClass(
                'globalsearch-extended-result'
            );
            $('#globalsearch-results')
                .children(`article:not([id="globalsearch-${currentCategory}"])`)
                .show();
            return false;
        }
    };
    
    export default GlobalSearch;