MDL-75837 core_grades: Adapt the base search widget to support dropdowns
This commit is contained in:
+3
-3
@@ -1,10 +1,10 @@
|
||||
define("core_grades/searchwidget/basewidget",["exports","core/modal_factory","core/modal_events","core/utils","core/templates","core/aria"],(function(_exports,ModalFactory,ModalEvents,_utils,Templates,_aria){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}
|
||||
define("core_grades/searchwidget/basewidget",["exports","core/utils","core/templates","core/aria","core_grades/searchwidget/selectors","core/notification"],(function(_exports,_utils,Templates,_aria,Selectors,_notification){var obj;function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}
|
||||
/**
|
||||
* A small modal to search users or grade items within the gradebook.
|
||||
* A widget to search users or grade items within the gradebook.
|
||||
*
|
||||
* @module core_grades/searchwidget/basewidget
|
||||
* @copyright 2022 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.promisesAndResolvers=_exports.init=void 0,ModalFactory=_interopRequireWildcard(ModalFactory),ModalEvents=_interopRequireWildcard(ModalEvents),Templates=_interopRequireWildcard(Templates);_exports.init=function(bodyPromise,data,searchFunc,modalTitle){let unsearchableContent=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null;const modal=buildModal(bodyPromise,modalTitle);registerListenerEvents(modal,data,searchFunc,unsearchableContent)};const registerListenerEvents=(modal,data,searchFunc,unsearchableContent)=>{modal.then((modal=>{modal.getRoot().on(ModalEvents.hidden,(()=>{modal.destroy()})),modal.getBodyPromise().then((body=>body[0])).then((body=>{const searchInput=body.querySelector('input[data-action="search"]'),searchResultsContainer=body.querySelector('[data-region="search-results-container-widget"]');if(renderSearchResults(searchResultsContainer,data),unsearchableContent){body.querySelector('[data-region="unsearchable-content-container-widget"]').innerHTML+=unsearchableContent}return searchInput.addEventListener("input",(0,_utils.debounce)((async()=>{await renderSearchResults(searchResultsContainer,debounceCallee(searchInput.value,data,searchFunc()))}),300)),(0,_aria.comboBox)(searchInput),body})).catch()})).catch()},buildModal=(bodyPromise,modalTitle)=>ModalFactory.create({type:ModalFactory.types.DEFAULT,title:modalTitle,body:bodyPromise,small:!0,scrollable:!1,templateContext:{classes:"reportdatasearch modal-sm"}}).then((modal=>(modal.show(),modal))),debounceCallee=(searchValue,data,searchFunction)=>searchValue.length>0?searchFunction(data,searchValue):data,renderSearchResults=async(searchResultsContainer,searchResultsData)=>{const templateData={searchresults:searchResultsData},{html:html,js:js}=await Templates.renderForPromise("core_grades/searchwidget/searchresults",templateData);await Templates.replaceNodeContents(searchResultsContainer,html,js)};_exports.promisesAndResolvers=()=>{let bodyPromiseResolver;const bodyPromise=new Promise((resolve=>{bodyPromiseResolver=resolve}));return{bodyPromiseResolver:bodyPromiseResolver,bodyPromise:bodyPromise}}}));
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.showLoader=_exports.registerListenerEvents=_exports.promisesAndResolvers=_exports.init=void 0,Templates=_interopRequireWildcard(Templates),Selectors=_interopRequireWildcard(Selectors),_notification=(obj=_notification)&&obj.__esModule?obj:{default:obj};_exports.init=async function(widgetContentContainer,bodyPromise,data,searchFunc){let unsearchableContent=arguments.length>4&&void 0!==arguments[4]?arguments[4]:null;bodyPromise.then((async bodyContent=>{if(widgetContentContainer.innerHTML=bodyContent,unsearchableContent){widgetContentContainer.querySelector(Selectors.regions.unsearchableContent).innerHTML+=unsearchableContent}const searchResultsContainer=widgetContentContainer.querySelector(Selectors.regions.searchResults);await showLoader(searchResultsContainer),await renderSearchResults(searchResultsContainer,data),registerListenerEvents(widgetContentContainer,data,searchFunc)})).catch(_notification.default.exception)};const registerListenerEvents=(widgetContentContainer,data,searchFunc)=>{const searchResultsContainer=widgetContentContainer.querySelector(Selectors.regions.searchResults),searchInput=widgetContentContainer.querySelector(Selectors.actions.search);searchInput.addEventListener("input",(0,_utils.debounce)((async()=>{await renderSearchResults(searchResultsContainer,debounceCallee(searchInput.value,data,searchFunc()))}),300)),(0,_aria.comboBox)(searchInput)};_exports.registerListenerEvents=registerListenerEvents;const showLoader=async container=>{const{html:html,js:js}=await Templates.renderForPromise("core_grades/searchwidget/loading",{});Templates.replaceNodeContents(container,html,js)};_exports.showLoader=showLoader;const debounceCallee=(searchValue,data,searchFunction)=>searchValue.length>0?searchFunction(data,searchValue):data,renderSearchResults=async(searchResultsContainer,searchResultsData)=>{const templateData={searchresults:searchResultsData},{html:html,js:js}=await Templates.renderForPromise("core_grades/searchwidget/searchresults",templateData);await Templates.replaceNodeContents(searchResultsContainer,html,js)};_exports.promisesAndResolvers=()=>{let bodyPromiseResolver;const bodyPromise=new Promise((resolve=>{bodyPromiseResolver=resolve}));return{bodyPromiseResolver:bodyPromiseResolver,bodyPromise:bodyPromise}}}));
|
||||
|
||||
//# sourceMappingURL=basewidget.min.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -14,105 +14,87 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* A small modal to search users or grade items within the gradebook.
|
||||
* A widget to search users or grade items within the gradebook.
|
||||
*
|
||||
* @module core_grades/searchwidget/basewidget
|
||||
* @copyright 2022 Mathew May <mathew.solutions>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
import * as ModalFactory from 'core/modal_factory';
|
||||
import * as ModalEvents from 'core/modal_events';
|
||||
import {debounce} from 'core/utils';
|
||||
import * as Templates from 'core/templates';
|
||||
import {comboBox} from 'core/aria';
|
||||
import * as Selectors from 'core_grades/searchwidget/selectors';
|
||||
import Notification from 'core/notification';
|
||||
|
||||
/**
|
||||
* Build the base searching widget.
|
||||
*
|
||||
* @method init
|
||||
* @param {Promise} bodyPromise The promise from the callee of the contents to place in the modal body.
|
||||
* @param {HTMLElement} widgetContentContainer The selector for the widget container element.
|
||||
* @param {Promise} bodyPromise The promise from the callee of the contents to place in the widget container.
|
||||
* @param {Array} data An array of all the data generated by the callee.
|
||||
* @param {Function} searchFunc Partially applied function we need to manage search the passed dataset.
|
||||
* @param {string} modalTitle The name of the search widget.
|
||||
* @param {string|null} unsearchableContent The content rendered in a non-searchable area.
|
||||
*/
|
||||
export const init = (bodyPromise, data, searchFunc, modalTitle, unsearchableContent = null) => {
|
||||
const modal = buildModal(bodyPromise, modalTitle);
|
||||
registerListenerEvents(modal, data, searchFunc, unsearchableContent);
|
||||
export const init = async(widgetContentContainer, bodyPromise, data, searchFunc, unsearchableContent = null) => {
|
||||
bodyPromise.then(async(bodyContent) => {
|
||||
// Render the body content.
|
||||
widgetContentContainer.innerHTML = bodyContent;
|
||||
|
||||
// Render the unsearchable content if defined.
|
||||
if (unsearchableContent) {
|
||||
const unsearchableContentContainer = widgetContentContainer.querySelector(Selectors.regions.unsearchableContent);
|
||||
unsearchableContentContainer.innerHTML += unsearchableContent;
|
||||
}
|
||||
|
||||
const searchResultsContainer = widgetContentContainer.querySelector(Selectors.regions.searchResults);
|
||||
// Display a loader until the search results are rendered.
|
||||
await showLoader(searchResultsContainer);
|
||||
// Render the search results.
|
||||
await renderSearchResults(searchResultsContainer, data);
|
||||
|
||||
registerListenerEvents(widgetContentContainer, data, searchFunc);
|
||||
|
||||
}).catch(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Register chooser related event listeners.
|
||||
* Register the event listeners for the search widget.
|
||||
*
|
||||
* @method registerListenerEvents
|
||||
* @param {Promise} modal Our modal that we are working with.
|
||||
* @param {HTMLElement} widgetContentContainer The selector for the widget container element.
|
||||
* @param {Array} data An array of all the data generated by the callee.
|
||||
* @param {Function} searchFunc Partially applied function we need to manage search the passed dataset.
|
||||
* @param {string|null} unsearchableContent The content rendered in a non-searchable area.
|
||||
*/
|
||||
const registerListenerEvents = (modal, data, searchFunc, unsearchableContent) => {
|
||||
modal.then(modal => {
|
||||
// We want to destroy this when the dialog is closed.
|
||||
modal.getRoot().on(ModalEvents.hidden, () => {
|
||||
modal.destroy();
|
||||
});
|
||||
// Once the body of the modal has been resolved, add more features.
|
||||
modal.getBodyPromise()
|
||||
// The return value of getBodyPromise is a jquery object containing the body NodeElement.
|
||||
.then(body => body[0])
|
||||
.then(body => {
|
||||
const searchInput = body.querySelector('input[data-action="search"]');
|
||||
const searchResultsContainer = body.querySelector('[data-region="search-results-container-widget"]');
|
||||
export const registerListenerEvents = (widgetContentContainer, data, searchFunc) => {
|
||||
const searchResultsContainer = widgetContentContainer.querySelector(Selectors.regions.searchResults);
|
||||
const searchInput = widgetContentContainer.querySelector(Selectors.actions.search);
|
||||
|
||||
renderSearchResults(searchResultsContainer, data);
|
||||
|
||||
if (unsearchableContent) {
|
||||
const unsearchableContentContainer = body.querySelector(
|
||||
'[data-region="unsearchable-content-container-widget"]');
|
||||
unsearchableContentContainer.innerHTML += unsearchableContent;
|
||||
}
|
||||
|
||||
// The search input is triggered.
|
||||
searchInput.addEventListener('input', debounce(async() => {
|
||||
// Display the search results.
|
||||
await renderSearchResults(
|
||||
searchResultsContainer,
|
||||
debounceCallee(
|
||||
searchInput.value,
|
||||
data,
|
||||
searchFunc()
|
||||
)
|
||||
);
|
||||
}, 300));
|
||||
// Trigger event handling for the results in line with aria guidelines.
|
||||
comboBox(searchInput);
|
||||
return body;
|
||||
}).catch();
|
||||
}).catch();
|
||||
// The search input is triggered.
|
||||
searchInput.addEventListener('input', debounce(async() => {
|
||||
// Display the search results.
|
||||
await renderSearchResults(
|
||||
searchResultsContainer,
|
||||
debounceCallee(
|
||||
searchInput.value,
|
||||
data,
|
||||
searchFunc()
|
||||
)
|
||||
);
|
||||
}, 300));
|
||||
// Trigger event handling for the results in line with aria guidelines.
|
||||
comboBox(searchInput);
|
||||
};
|
||||
|
||||
/**
|
||||
* Given an object we want to build a modal ready to show.
|
||||
* Renders the loading placeholder for the search widget.
|
||||
*
|
||||
* @method buildModal
|
||||
* @param {Promise} bodyPromise Body promise that the caller should resolve.
|
||||
* @param {string} modalTitle The name of the search widget.
|
||||
* @return {Object} The modal ready to display immediately and render body in later.
|
||||
* @method showLoader
|
||||
* @param {HTMLElement} container The DOM node where we'll render the loading placeholder.
|
||||
*/
|
||||
const buildModal = (bodyPromise, modalTitle) => {
|
||||
return ModalFactory.create({
|
||||
type: ModalFactory.types.DEFAULT,
|
||||
title: modalTitle,
|
||||
body: bodyPromise,
|
||||
small: true,
|
||||
scrollable: false,
|
||||
templateContext: {
|
||||
classes: 'reportdatasearch modal-sm'
|
||||
}
|
||||
}).then(modal => {
|
||||
modal.show();
|
||||
return modal;
|
||||
});
|
||||
export const showLoader = async(container) => {
|
||||
const {html, js} = await Templates.renderForPromise('core_grades/searchwidget/loading', {});
|
||||
Templates.replaceNodeContents(container, html, js);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -133,7 +115,7 @@ const debounceCallee = (searchValue, data, searchFunction) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Given the output of the callers' search function, render out the results into the modal.
|
||||
* Given the output of the callers' search function, render out the results into the search results container.
|
||||
*
|
||||
* @method renderSearchResults
|
||||
* @param {HTMLElement} searchResultsContainer The DOM node of the widget where we'll render the provided results.
|
||||
@@ -149,14 +131,14 @@ const renderSearchResults = async(searchResultsContainer, searchResultsData) =>
|
||||
};
|
||||
|
||||
/**
|
||||
* We want to create the basic promises and hooks that the caller will implement, so we can build modals
|
||||
* We want to create the basic promises and hooks that the caller will implement, so we can build the search widget
|
||||
* ahead of time and allow the caller to resolve their promises once complete.
|
||||
*
|
||||
* @method promisesAndResolvers
|
||||
* @returns {{bodyPromise: Promise, bodyPromiseResolver}}
|
||||
*/
|
||||
export const promisesAndResolvers = () => {
|
||||
// We want to show the modal instantly but loading whilst waiting for our data.
|
||||
// We want to show the widget instantly but loading whilst waiting for our data.
|
||||
let bodyPromiseResolver;
|
||||
const bodyPromise = new Promise(resolve => {
|
||||
bodyPromiseResolver = resolve;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
{{!
|
||||
This file is part of Moodle - http://moodle.org/
|
||||
|
||||
Moodle is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Moodle is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@template core_grades/searchwidget/loading
|
||||
|
||||
This template renders the loading placeholder for the search widget.
|
||||
|
||||
Example context (json):
|
||||
{}
|
||||
}}
|
||||
<div class="d-flex w-100 h-100 justify-content-center align-items-center">
|
||||
{{> core/loading }}
|
||||
</div>
|
||||
@@ -27,22 +27,20 @@
|
||||
"fullname": "Cameron Greeve"
|
||||
}
|
||||
}}
|
||||
<div class="w-100 result-row" role="row" id="result-row-{{id}}">
|
||||
{{#name}}
|
||||
<a role="option" id="result-item-{{id}}x{{id}}" href="{{url}}" class="d-flex px-2 py-1">
|
||||
<span class="w-50 pull-left result-cell text-truncate text-body mr-2">
|
||||
{{name}}
|
||||
</span>
|
||||
</a>
|
||||
{{/name}}
|
||||
{{^name}}
|
||||
<a role="option" id="user-{{id}}" href="{{url}}" class="d-flex px-2 py-1">
|
||||
<span class="w-50 pull-left result-cell text-truncate text-body mr-2">
|
||||
{{fullname}}
|
||||
</span>
|
||||
<span class="w-50 pull-left result-cell text-truncate text-muted">
|
||||
<span id="email-user-{{id}}" role="gridcell">{{email}}</span>
|
||||
</span>
|
||||
</a>
|
||||
{{/name}}
|
||||
</div>
|
||||
{{#name}}
|
||||
<a role="option" href="{{url}}" class="dropdown-item d-flex px-2 py-1">
|
||||
<span class="pull-left result-cell text-truncate mr-2">
|
||||
{{name}}
|
||||
</span>
|
||||
</a>
|
||||
{{/name}}
|
||||
{{^name}}
|
||||
<a role="option" href="{{url}}" class="dropdown-item d-flex px-2 py-1 align-items-center">
|
||||
<span class="w-50 pull-left text-truncate mr-2">
|
||||
{{fullname}}
|
||||
</span>
|
||||
<span class="w-50 pull-left text-truncate small email">
|
||||
{{email}}
|
||||
</span>
|
||||
</a>
|
||||
{{/name}}
|
||||
|
||||
@@ -530,21 +530,48 @@
|
||||
}
|
||||
}
|
||||
|
||||
.searchresultitemscontainer {
|
||||
max-height: 150px;
|
||||
overflow: auto;
|
||||
.search-widget {
|
||||
.dropdown-menu {
|
||||
padding: 0.8rem 1.2rem;
|
||||
|
||||
a:hover {
|
||||
background-color: $gray-100;
|
||||
}
|
||||
&.wide {
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
.focused-cell {
|
||||
outline-style: dotted;
|
||||
outline-color: green;
|
||||
&.narrow {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
span {
|
||||
&.email {
|
||||
color: $text-muted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-item:hover,
|
||||
.dropdown-item:active {
|
||||
span {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.searchresultscontainer {
|
||||
height: 178px;
|
||||
font-size: 90%;
|
||||
|
||||
.searchresultitemscontainer {
|
||||
height: 178px;
|
||||
max-height: 178px;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.unsearchablecontentcontainer {
|
||||
border-top: 1px solid #dee2e6;
|
||||
padding-top: 10px;
|
||||
font-size: 90%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.unsearchablecontentcontainer {
|
||||
border-top: 1px solid #dee2e6;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
@@ -19747,18 +19747,28 @@ p.arrow_button {
|
||||
.path-grade-report-singleview .reporttable .dropdown-toggle::after {
|
||||
display: none; }
|
||||
|
||||
.searchresultitemscontainer {
|
||||
max-height: 150px;
|
||||
overflow: auto; }
|
||||
.searchresultitemscontainer a:hover {
|
||||
background-color: #f8f9fa; }
|
||||
.searchresultitemscontainer .focused-cell {
|
||||
outline-style: dotted;
|
||||
outline-color: green; }
|
||||
|
||||
.unsearchablecontentcontainer {
|
||||
border-top: 1px solid #dee2e6;
|
||||
padding-top: 10px; }
|
||||
.search-widget .dropdown-menu {
|
||||
padding: 0.8rem 1.2rem; }
|
||||
.search-widget .dropdown-menu.wide {
|
||||
width: 350px; }
|
||||
.search-widget .dropdown-menu.narrow {
|
||||
width: 250px; }
|
||||
.search-widget .dropdown-menu .dropdown-item span.email {
|
||||
color: #6a737b; }
|
||||
.search-widget .dropdown-menu .dropdown-item:hover span,
|
||||
.search-widget .dropdown-menu .dropdown-item:active span {
|
||||
color: #fff; }
|
||||
.search-widget .dropdown-menu .searchresultscontainer {
|
||||
height: 178px;
|
||||
font-size: 90%; }
|
||||
.search-widget .dropdown-menu .searchresultscontainer .searchresultitemscontainer {
|
||||
height: 178px;
|
||||
max-height: 178px;
|
||||
overflow: auto; }
|
||||
.search-widget .dropdown-menu .unsearchablecontentcontainer {
|
||||
border-top: 1px solid #dee2e6;
|
||||
padding-top: 10px;
|
||||
font-size: 90%; }
|
||||
|
||||
.columns-autoflow-1to1to1 {
|
||||
column-count: 3; }
|
||||
|
||||
@@ -19747,18 +19747,28 @@ p.arrow_button {
|
||||
.path-grade-report-singleview .reporttable .dropdown-toggle::after {
|
||||
display: none; }
|
||||
|
||||
.searchresultitemscontainer {
|
||||
max-height: 150px;
|
||||
overflow: auto; }
|
||||
.searchresultitemscontainer a:hover {
|
||||
background-color: #f8f9fa; }
|
||||
.searchresultitemscontainer .focused-cell {
|
||||
outline-style: dotted;
|
||||
outline-color: green; }
|
||||
|
||||
.unsearchablecontentcontainer {
|
||||
border-top: 1px solid #dee2e6;
|
||||
padding-top: 10px; }
|
||||
.search-widget .dropdown-menu {
|
||||
padding: 0.8rem 1.2rem; }
|
||||
.search-widget .dropdown-menu.wide {
|
||||
width: 350px; }
|
||||
.search-widget .dropdown-menu.narrow {
|
||||
width: 250px; }
|
||||
.search-widget .dropdown-menu .dropdown-item span.email {
|
||||
color: #6a737b; }
|
||||
.search-widget .dropdown-menu .dropdown-item:hover span,
|
||||
.search-widget .dropdown-menu .dropdown-item:active span {
|
||||
color: #fff; }
|
||||
.search-widget .dropdown-menu .searchresultscontainer {
|
||||
height: 178px;
|
||||
font-size: 90%; }
|
||||
.search-widget .dropdown-menu .searchresultscontainer .searchresultitemscontainer {
|
||||
height: 178px;
|
||||
max-height: 178px;
|
||||
overflow: auto; }
|
||||
.search-widget .dropdown-menu .unsearchablecontentcontainer {
|
||||
border-top: 1px solid #dee2e6;
|
||||
padding-top: 10px;
|
||||
font-size: 90%; }
|
||||
|
||||
.columns-autoflow-1to1to1 {
|
||||
column-count: 3; }
|
||||
|
||||
Reference in New Issue
Block a user