From 00b4aec60a804104b9d89d03152922e2ea8d05c9 Mon Sep 17 00:00:00 2001 From: REJack Date: Sat, 13 Jun 2020 17:32:43 +0200 Subject: [PATCH 1/6] add SidebarSearch.js --- build/js/AdminLTE.js | 2 + build/js/SidebarSearch.js | 225 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+) create mode 100644 build/js/SidebarSearch.js diff --git a/build/js/AdminLTE.js b/build/js/AdminLTE.js index cb004e543..fd709a432 100644 --- a/build/js/AdminLTE.js +++ b/build/js/AdminLTE.js @@ -6,6 +6,7 @@ import Dropdown from './Dropdown' import ExpandableTable from './ExpandableTable' import Layout from './Layout' import PushMenu from './PushMenu' +import SidebarSearch from './SidebarSearch' import Toasts from './Toasts' import TodoList from './TodoList' import Treeview from './Treeview' @@ -19,6 +20,7 @@ export { ExpandableTable, Layout, PushMenu, + SidebarSearch, Toasts, TodoList, Treeview diff --git a/build/js/SidebarSearch.js b/build/js/SidebarSearch.js new file mode 100644 index 000000000..0eacbba95 --- /dev/null +++ b/build/js/SidebarSearch.js @@ -0,0 +1,225 @@ +/** + * -------------------------------------------- + * AdminLTE SidebarSearch.js + * License MIT + * -------------------------------------------- + */ + +import $, { trim } from 'jquery' + +/** + * Constants + * ==================================================== + */ + +const NAME = 'SidebarSearch' +const DATA_KEY = 'lte.sidebar-search' +const JQUERY_NO_CONFLICT = $.fn[NAME] + +const CLASS_NAME_OPEN = 'sidebar-search-open' +const CLASS_NAME_ICON_SEARCH = 'fa-search' +const CLASS_NAME_ICON_CLOSE = 'fa-times' +const CLASS_NAME_HEADER = 'nav-header' +const CLASS_NAME_SEARCH_RESULTS = 'sidebar-search-results' +const CLASS_NAME_LIST_GROUP = 'list-group' + +const SELECTOR_DATA_WIDGET = '[data-widget="sidebar-search"]' +const SELECTOR_SIDEBAR = '.main-sidebar .nav-sidebar' +const SELECTOR_NAV_LINK = '.nav-link' +const SELECTOR_NAV_TREEVIEW = '.nav-treeview' +const SELECTOR_SEARCH_INPUT = `${SELECTOR_DATA_WIDGET} .form-control` +const SELECTOR_SEARCH_BUTTON = `${SELECTOR_DATA_WIDGET} .btn` +const SELECTOR_SEARCH_ICON = `${SELECTOR_SEARCH_BUTTON} i` +const SELECTOR_SEARCH_LIST_GROUP = `.${CLASS_NAME_LIST_GROUP}` +const SELECTOR_SEARCH_RESULTS = `.${CLASS_NAME_SEARCH_RESULTS}` +const SELECTOR_SEARCH_RESULTS_GROUP = `${SELECTOR_SEARCH_RESULTS} .${CLASS_NAME_LIST_GROUP}` + +const Default = { + arrowSign: '->', + minLength: 3, + maxResults: 7, + notFoundText: 'No element found!' +} + +const SearchItems = [] + +/** + * Class Definition + * ==================================================== + */ + +class SidebarSearch { + constructor(_element, _options) { + this.element = _element + this.options = $.extend({}, Default, _options) + this.items = [] + } + + // Public + + init() { + if ($(SELECTOR_DATA_WIDGET).next(SELECTOR_SEARCH_RESULTS).length == 0) { + $(SELECTOR_DATA_WIDGET).after( + $('
', { class: CLASS_NAME_SEARCH_RESULTS }) + ) + } + + if ($(SELECTOR_SEARCH_RESULTS).children(SELECTOR_SEARCH_LIST_GROUP).length == 0) { + $(SELECTOR_SEARCH_RESULTS).append( + $('
', { class: CLASS_NAME_LIST_GROUP }) + ) + } + + this._addNotFound() + + $(SELECTOR_SIDEBAR).children().each((i, child) => { + this._parseItem(child) + }) + } + + search() { + const searchValue = $(SELECTOR_SEARCH_INPUT).val().toLowerCase() + if (searchValue.length < this.options.minLength) { + $(SELECTOR_SEARCH_RESULTS_GROUP).empty() + this._addNotFound() + this.close() + return + } + + const searchResults = SearchItems.filter(item => (item.name).toLowerCase().includes(searchValue)) + const endResults = $(searchResults.slice(0, this.options.maxResults)) + $(SELECTOR_SEARCH_RESULTS_GROUP).empty() + + if (endResults.length === 0) { + this._addNotFound() + } else { + endResults.each((i, result) => { + $(SELECTOR_SEARCH_RESULTS_GROUP).append(this._renderItem(result.name, result.link, result.path)) + }) + } + + this.open() + } + + open() { + $(SELECTOR_DATA_WIDGET).parent().addClass(CLASS_NAME_OPEN) + $(SELECTOR_SEARCH_ICON).removeClass(CLASS_NAME_ICON_SEARCH).addClass(CLASS_NAME_ICON_CLOSE) + } + + close() { + $(SELECTOR_DATA_WIDGET).parent().removeClass(CLASS_NAME_OPEN) + $(SELECTOR_SEARCH_ICON).removeClass(CLASS_NAME_ICON_CLOSE).addClass(CLASS_NAME_ICON_SEARCH) + } + + toggle() { + if ($(SELECTOR_DATA_WIDGET).parent().hasClass(CLASS_NAME_OPEN)) { + this.close() + } else { + this.open() + } + } + + // Private + + _parseItem(item, path = []) { + if ($(item).hasClass(CLASS_NAME_HEADER)) { + return + } + + const itemObject = {} + const navLink = $(item).clone().find(`> ${SELECTOR_NAV_LINK}`) + const navTreeview = $(item).clone().find(`> ${SELECTOR_NAV_TREEVIEW}`) + + const link = navLink.attr('href') + const name = navLink.find('p').children().remove().end().text() + + itemObject.name = this._trimText(name) + itemObject.link = link + itemObject.path = path + + if (navTreeview.length === 0) { + SearchItems.push(itemObject) + } else { + const newPath = itemObject.path.concat([itemObject.name]) + navTreeview.children().each((i, child) => { + this._parseItem(child, newPath) + }) + } + } + + _trimText(text) { + return trim(text.replace(/(\r\n|\n|\r)/gm, ' ')) + } + + _renderItem(name, link, path) { + return ` +
+ ${name} +
+
+ ${path.join(` ${this.options.arrowSign} `)} +
+
` + } + + _addNotFound() { + $(SELECTOR_SEARCH_RESULTS_GROUP).append(this._renderItem(this.options.notFoundText, '#', [])) + } + + // Static + + static _jQueryInterface(config) { + let data = $(this).data(DATA_KEY) + + if (!data) { + data = $(this).data() + } + + const _options = $.extend({}, Default, typeof config === 'object' ? config : data) + const plugin = new SidebarSearch($(this), _options) + + $(this).data(DATA_KEY, typeof config === 'object' ? config : data) + + if (typeof config === 'string' && config.match(/init|toggle|close|open|search/)) { + plugin[config]() + } else { + plugin.init() + } + } +} + +/** + * Data API + * ==================================================== + */ +$(document).on('click', SELECTOR_SEARCH_BUTTON, event => { + event.preventDefault() + + SidebarSearch._jQueryInterface.call($(SELECTOR_DATA_WIDGET), 'toggle') +}) + +$(document).on('keyup', SELECTOR_SEARCH_INPUT, () => { + let timer = 0 + clearTimeout(timer) + timer = setTimeout(() => { + SidebarSearch._jQueryInterface.call($(SELECTOR_DATA_WIDGET), 'search') + }, 100) +}) + +$(window).on('load', () => { + SidebarSearch._jQueryInterface.call($(SELECTOR_DATA_WIDGET), 'init') +}) + +/** + * jQuery API + * ==================================================== + */ + +$.fn[NAME] = SidebarSearch._jQueryInterface +$.fn[NAME].Constructor = SidebarSearch +$.fn[NAME].noConflict = function () { + $.fn[NAME] = JQUERY_NO_CONFLICT + return SidebarSearch._jQueryInterface +} + +export default SidebarSearch From 30746618d001c16fa1516d7d2ae02d18c9e32ee2 Mon Sep 17 00:00:00 2001 From: REJack Date: Sat, 13 Jun 2020 17:33:02 +0200 Subject: [PATCH 2/6] add sidebar search style --- build/scss/_main-sidebar.scss | 83 +++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/build/scss/_main-sidebar.scss b/build/scss/_main-sidebar.scss index e8818adfb..fff1609ad 100644 --- a/build/scss/_main-sidebar.scss +++ b/build/scss/_main-sidebar.scss @@ -902,6 +902,24 @@ .btn-sidebar:focus { background-color: lighten($sidebar-dark-bg, 10%); } + + .list-group-item { + background-color: lighten($sidebar-dark-bg, 7.5%); + border-color: lighten($sidebar-dark-bg, 15%); + color: $sidebar-dark-color; + + &:hover { + background-color: lighten($sidebar-dark-bg, 10%); + } + + &:focus { + background-color: lighten($sidebar-dark-bg, 12.5%); + } + + .search-path { + color: $gray-500; + } + } } [class*="sidebar-light"] { @@ -924,6 +942,22 @@ .btn-sidebar:focus { background-color: darken($sidebar-light-bg, 10%); } + + .list-group-item { + border-color: darken($sidebar-light-bg, 15%); + + &:hover { + background-color: darken($sidebar-light-bg, 7.5%); + } + + &:focus { + background-color: darken($sidebar-light-bg, 10%); + } + + .search-path { + color: $gray-600; + } + } } // Sidebar inline input-group fix @@ -946,3 +980,52 @@ position: relative; } } + +// Sidebar Search +.sidebar-collapse { + .form-control-sidebar, + .form-control-sidebar ~ .input-group-append, + .sidebar-search-results { + display: none; + } +} + +.sidebar-search-results { + position: relative; + display: none; + width: 100%; + + .sidebar-search-open & { + display: inline-block; + } + + .search-title { + margin-bottom: -.1rem; + } + + .list-group { + position: absolute; + width: 100%; + z-index: $zindex-main-sidebar + 1; + + .list-group-item { + padding: $input-padding-y $input-padding-x; + } + + > .list-group-item:first-child { + border-top: 0; + @include border-top-radius(0); + } + } +} + +.sidebar-search-results .search-path { + font-size: $small-font-size; +} + +.sidebar-search-open { + .btn, + .form-control { + @include border-bottom-radius(0); + } +} From eec4fd768e5acb22f9cc7c14e6e07cad5a0898a7 Mon Sep 17 00:00:00 2001 From: REJack Date: Sat, 13 Jun 2020 17:37:06 +0200 Subject: [PATCH 3/6] add sidebar search form in all demo pages --- index.html | 12 ++++++++++++ index2.html | 12 ++++++++++++ index3.html | 12 ++++++++++++ pages/UI/buttons.html | 12 ++++++++++++ pages/UI/general.html | 12 ++++++++++++ pages/UI/icons.html | 12 ++++++++++++ pages/UI/modals.html | 12 ++++++++++++ pages/UI/navbar.html | 12 ++++++++++++ pages/UI/ribbons.html | 12 ++++++++++++ pages/UI/sliders.html | 12 ++++++++++++ pages/UI/timeline.html | 12 ++++++++++++ pages/calendar.html | 12 ++++++++++++ pages/charts/chartjs.html | 12 ++++++++++++ pages/charts/flot.html | 12 ++++++++++++ pages/charts/inline.html | 12 ++++++++++++ pages/examples/404.html | 12 ++++++++++++ pages/examples/500.html | 12 ++++++++++++ pages/examples/blank.html | 12 ++++++++++++ pages/examples/contacts.html | 12 ++++++++++++ pages/examples/e-commerce.html | 12 ++++++++++++ pages/examples/invoice.html | 12 ++++++++++++ pages/examples/language-menu.html | 12 ++++++++++++ pages/examples/legacy-user-menu.html | 12 ++++++++++++ pages/examples/pace.html | 12 ++++++++++++ pages/examples/profile.html | 12 ++++++++++++ pages/examples/project-add.html | 12 ++++++++++++ pages/examples/project-detail.html | 12 ++++++++++++ pages/examples/project-edit.html | 12 ++++++++++++ pages/examples/projects.html | 12 ++++++++++++ pages/forms/advanced.html | 12 ++++++++++++ pages/forms/editors.html | 12 ++++++++++++ pages/forms/general.html | 12 ++++++++++++ pages/forms/validation.html | 12 ++++++++++++ pages/gallery.html | 12 ++++++++++++ pages/layout/boxed.html | 12 ++++++++++++ pages/layout/collapsed-sidebar.html | 12 ++++++++++++ pages/layout/fixed-footer.html | 12 ++++++++++++ pages/layout/fixed-sidebar.html | 12 ++++++++++++ pages/layout/fixed-topnav.html | 12 ++++++++++++ pages/layout/top-nav-sidebar.html | 12 ++++++++++++ pages/mailbox/compose.html | 12 ++++++++++++ pages/mailbox/mailbox.html | 12 ++++++++++++ pages/mailbox/read-mail.html | 12 ++++++++++++ pages/tables/data.html | 12 ++++++++++++ pages/tables/jsgrid.html | 12 ++++++++++++ pages/tables/simple.html | 12 ++++++++++++ pages/widgets.html | 12 ++++++++++++ starter.html | 12 ++++++++++++ 48 files changed, 576 insertions(+) diff --git a/index.html b/index.html index 915fc9a30..18a24d410 100644 --- a/index.html +++ b/index.html @@ -172,6 +172,18 @@
+ +
+
+ +
+ +
+
+
+