From 1b23b84f7d9d099301b757ec9d59bf254e13b837 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Thu, 10 Dec 2020 10:45:40 -0500 Subject: [PATCH] feat(filters): add auto position (left/right) to multiple-select lib - `autoAdjustDropPosition` option should not only adjust top/bottom, it should also adjust left/right --- .../examples/grid-graphql-nopage.component.ts | 90 ++++++++++++------- .../lib/multiple-select/multiple-select.js | 20 ++++- 2 files changed, 76 insertions(+), 34 deletions(-) diff --git a/src/app/examples/grid-graphql-nopage.component.ts b/src/app/examples/grid-graphql-nopage.component.ts index aed3e28a8..43c927ca4 100644 --- a/src/app/examples/grid-graphql-nopage.component.ts +++ b/src/app/examples/grid-graphql-nopage.component.ts @@ -73,36 +73,6 @@ export class GridGraphqlWithoutPaginationComponent implements OnInit { { id: 'countryPhone', field: 'phone', name: 'Phone Area Code', maxWidth: 110, sortable: true, filterable: true, columnGroup: 'Country' }, { id: 'countryCurrency', field: 'currency', name: 'Currency', maxWidth: 90, sortable: true, filterable: true, columnGroup: 'Country' }, { id: 'countryEmoji', field: 'emoji', name: 'Emoji', maxWidth: 90, sortable: true, columnGroup: 'Country' }, - { - id: 'continentCode', field: 'continent.code', name: 'Code', maxWidth: 90, - sortable: true, - filterable: true, - filter: { - model: Filters.singleSelect, - collectionAsync: this.getContinents(), - collectionOptions: { - // the data is not at the root of the array, so we must tell the Select Filter where to pull the data - collectionInsideObjectProperty: 'data.continents', - addBlankEntry: true, - separatorBetweenTextLabels: ': ', - }, - customStructure: { - value: 'code', - label: 'code', - labelSuffix: 'name', - } - }, - formatter: Formatters.complexObject, columnGroup: 'Continent', - }, - { - id: 'continentName', field: 'continent.name', name: 'Name', width: 60, sortable: true, - filterable: true, formatter: Formatters.complexObject, columnGroup: 'Continent' - }, - { - id: 'languageCode', field: 'languages.code', name: 'Codes', maxWidth: 100, - formatter: Formatters.arrayObjectToCsv, params: { propertyNames: ['code'], useFormatterOuputToFilter: true }, columnGroup: 'Language', - filterable: true, - }, { id: 'languageName', field: 'languages.name', name: 'Names', width: 60, formatter: Formatters.arrayObjectToCsv, columnGroup: 'Language', @@ -139,7 +109,63 @@ export class GridGraphqlWithoutPaginationComponent implements OnInit { }, { id: 'languageNative', field: 'languages.native', name: 'Native', width: 60, - formatter: Formatters.arrayObjectToCsv, params: { propertyNames: ['native'] }, columnGroup: 'Language', + formatter: Formatters.arrayObjectToCsv, params: { propertyNames: ['native'], useFormatterOuputToFilter: true }, columnGroup: 'Language', + filterable: true, + filter: { + model: Filters.multipleSelect, + collectionAsync: this.getLanguages(), + operator: OperatorType.inContains, + collectionOptions: { + addBlankEntry: true, + // the data is not at the root of the array, so we must tell the Select Filter where to pull the data + collectionInsideObjectProperty: 'data.languages' + }, + collectionFilterBy: [ + // filter out any empty values + { property: 'native', value: '', operator: 'NE' }, + { property: 'native', value: null, operator: 'NE' }, + ], + collectionSortBy: { + property: 'native' + }, + customStructure: { + value: 'native', + label: 'native', + }, + filterOptions: { + filter: true + } as MultipleSelectOption + }, + }, + { + id: 'languageCode', field: 'languages.code', name: 'Codes', maxWidth: 100, + formatter: Formatters.arrayObjectToCsv, params: { propertyNames: ['code'], useFormatterOuputToFilter: true }, columnGroup: 'Language', + filterable: true, + }, + { + id: 'continentName', field: 'continent.name', name: 'Name', width: 60, sortable: true, + filterable: true, formatter: Formatters.complexObject, columnGroup: 'Continent' + }, + { + id: 'continentCode', field: 'continent.code', name: 'Code', maxWidth: 90, + sortable: true, + filterable: true, + filter: { + model: Filters.singleSelect, + collectionAsync: this.getContinents(), + collectionOptions: { + // the data is not at the root of the array, so we must tell the Select Filter where to pull the data + collectionInsideObjectProperty: 'data.continents', + addBlankEntry: true, + separatorBetweenTextLabels: ': ', + }, + customStructure: { + value: 'code', + label: 'code', + labelSuffix: 'name', + } + }, + formatter: Formatters.complexObject, columnGroup: 'Continent', }, ]; @@ -212,7 +238,7 @@ export class GridGraphqlWithoutPaginationComponent implements OnInit { * We also need to resolve the data in a flat array (singleSelect/multipleSelect Filters only accept data at the root of the array) */ getLanguages() { - const languageQuery = `query { languages { code, name }}`; + const languageQuery = `query { languages { code, name, native }}`; return this.http.post>(COUNTRIES_API, { query: languageQuery }); } } diff --git a/src/assets/lib/multiple-select/multiple-select.js b/src/assets/lib/multiple-select/multiple-select.js index fc606de15..317269f6c 100644 --- a/src/assets/lib/multiple-select/multiple-select.js +++ b/src/assets/lib/multiple-select/multiple-select.js @@ -1,6 +1,6 @@ /** * @author zhixin wen - * @version 1.3.7 + * @version 1.3.9 * * http://wenzhixin.net.cn/p/multiple-select/ * @@ -14,7 +14,7 @@ * - width option was not working when using "container", added some code to support it * - "offsetLeft" (defaults to 0) if we want the drop to be offset from the select element (by default it is aligned left to the element with 0 offset) * - "autoAdjustDropHeight" (defaults to False) when set will automatically adjust the drop (up or down) height - * - "autoAdjustDropPosition" (defaults to False) when set will automatically calculate the area with the most available space and use best possible choise for the drop to show (up or down) + * - "autoAdjustDropPosition" (defaults to False) when set will automatically calculate the area with the most available space and use best possible choice for the drop to show (up/down and left/right) * - "autoDropWidth" (defaults to False) when set will automatically adjust the dropdown width with the same size as the select element width * - "autoAdjustDropWidthByTextSize" (defaults to false) when set will automatically adjust the drop (up or down) width by the text size (it will use largest text width) * - "adjustHeightPadding" (defaults to 10) when using "autoAdjustDropHeight" we might want to add a bottom (or top) padding instead of taking the entire available space @@ -629,9 +629,13 @@ adjustDropPosition: function (forceToggle) { var position = 'bottom'; var msDropHeight = this.$drop.outerHeight() || 0; + var msDropWidth = this.$drop.outerWidth() || 0; var selectOffsetTop = this.$parent.offset().top; + var selectParentWidth = this.$parent.width(); var spaceBottom = this.availableSpaceBottom(); + var spaceLeft = this.availableSpaceLeft(); var spaceTop = this.availableSpaceTop(); + var windowWidth = $(window).width(); // find the optimal position of the drop (always choose "bottom" as the default to use) if (spaceBottom > msDropHeight) { @@ -657,6 +661,12 @@ this.$drop.removeClass('bottom'); } + // auto-adjust left/right position + if ((windowWidth - msDropWidth) < spaceLeft) { + var newLeftOffset = spaceLeft - (msDropWidth - selectParentWidth); + this.$drop.offset({ left: newLeftOffset }); + } + return position; }, @@ -715,6 +725,12 @@ return windowHeight - (msDropOffsetTop - pageScroll); }, + availableSpaceLeft: function () { + var pageScrollLeft = $(window).scrollLeft() || 0; + var msDropOffsetLeft = this.$parent.offset().left; + return msDropOffsetLeft - pageScrollLeft; + }, + availableSpaceTop: function () { var pageScroll = $(window).scrollTop() || 0; var msDropOffsetTop = this.$parent.offset().top;