-
Notifications
You must be signed in to change notification settings - Fork 950
feat(treeview): add a search field to lists #13739
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
5f29930 to
e093a48
Compare
|
duplicate search field in checklists is fixed by https://gerrit.libreoffice.org/c/core/+/195719 |
e093a48 to
a36d0bf
Compare
fdced34 to
0b01557
Compare
0b01557 to
7c9696d
Compare
7c9696d to
46e7afd
Compare
|
Range diff: 1: 7c9696de43 ! 1: 46e7afdbfe feat(treeview): add a search field to lists
@@ browser/css/jsdialogs.css: algned to the bottom */
+ padding-right: 1px;
+}
+
-+#ui-treeview-search-input {
++[id^='ui-treeview-search-input'] {
+ width: 100%;
+ box-sizing: border-box;
+}
+
- .modalpopup .ui-treeview {
+ #__MENU__.ui-treeview {
min-height: min-content;
}
+ ## browser/src/canvas/sections/CommentListSection.ts ##
+@@ browser/src/canvas/sections/CommentListSection.ts: export class CommentSection extends CanvasSectionObject {
+ fireKeyEvents: true,
+ hideIfEmpty: true,
+ entries: [] as Array<TreeEntryJSON>,
++ noSearchField: true,
+ },
+ {
+ id: '',
+
+ ## browser/src/control/AutoCompletePopup.ts ##
+@@ browser/src/control/AutoCompletePopup.ts: abstract class AutoCompletePopup {
+ singleclickactivate: false,
+ fireKeyEvents: true,
+ entries: [] as Array<TreeEntryJSON>,
++ noSearchField: true,
+ } as TreeWidgetJSON;
+ }
+
+
+ ## browser/src/control/Control.QuickFindPanel.ts ##
+@@ browser/src/control/Control.QuickFindPanel.ts: class QuickFindPanel extends SidebarBase {
+ if (
+ data.control.id === 'searchfinds' &&
+ data.control.type === 'treelistbox'
+- )
++ ) {
+ e.data.control.ignoreFocus = true;
++ e.data.control.noSearchField = true;
++ }
+
+ if (!super.onJSUpdate(e)) return false;
+
+@@ browser/src/control/Control.QuickFindPanel.ts: class QuickFindPanel extends SidebarBase {
+ quickFindControls.classList.toggle('hidden', isEmpty);
+ }
+
++ removeSearchFields(quickFindData: any): any {
++ if (quickFindData.children) {
++ const modifiedData = JSON.parse(JSON.stringify(quickFindData));
++
++ const _removeSearchFields = (data: any) => {
++ for (const child of data.children) {
++ if (child.type === 'treelistbox') {
++ child.noSearchField = true;
++ }
++
++ if (child.children) {
++ _removeSearchFields(child);
++ }
++ }
++ };
++
++ _removeSearchFields(modifiedData);
++
++ return modifiedData;
++ }
++
++ return quickFindData;
++ }
++
+ addPlaceholderIfEmpty(quickFindData: any): any {
+ const hasEntries =
+ quickFindData.children &&
+@@ browser/src/control/Control.QuickFindPanel.ts: class QuickFindPanel extends SidebarBase {
+
+ this.container.innerHTML = '';
+
+- const modifiedData = this.addPlaceholderIfEmpty(quickFindData);
++ }
+
+ if (!super.onJSUpdate(e)) return false;
+
+@@ browser/src/control/Control.QuickFindPanel.ts: class QuickFindPanel extends SidebarBase {
+ quickFindControls.classList.toggle('hidden', isEmpty);
+ }
+
++ removeSearchFields(quickFindData: any): any {
++ if (quickFindData.children) {
++ const modifiedData = JSON.parse(JSON.stringify(quickFindData));
++
++ const _removeSearchFields = (data: any) => {
++ for (const child of data.children) {
++ if (child.type === 'treelistbox') {
++ child.noSearchField = true;
++ }
++
++ if (child.children) {
++ _removeSearchFields(child);
++ }
++ }
++ };
++
++ _removeSearchFields(modifiedData);
++
++ return modifiedData;
++ }
++
++ return quickFindData;
++ }
++
+ addPlaceholderIfEmpty(quickFindData: any): any {
+ const hasEntries =
+ quickFindData.children &&
+@@ browser/src/control/Control.QuickFindPanel.ts: class QuickFindPanel extends SidebarBase {
+
+ this.container.innerHTML = '';
+
+- const modifiedData = this.addPlaceholderIfEmpty(quickFindData);
-+#ui-treeview-search-input {
++[id^='ui-treeview-search-input'] {
+ width: 100%;
+ box-sizing: border-box;
+}
+
- .modalpopup .ui-treeview {
+ #__MENU__.ui-treeview {
min-height: min-content;
}
+ ## browser/src/canvas/sections/CommentListSection.ts ##
+@@ browser/src/canvas/sections/CommentListSection.ts: export class CommentSection extends CanvasSectionObject {
+ fireKeyEvents: true,
+ hideIfEmpty: true,
+ entries: [] as Array<TreeEntryJSON>,
++ noSearchField: true,
+ },
+ {
+ id: '',
+
+ ## browser/src/control/AutoCompletePopup.ts ##
+@@ browser/src/control/AutoCompletePopup.ts: abstract class AutoCompletePopup {
+ singleclickactivate: false,
+ fireKeyEvents: true,
+ entries: [] as Array<TreeEntryJSON>,
++ noSearchField: true,
+ } as TreeWidgetJSON;
+ }
+
+
+ ## browser/src/control/Control.QuickFindPanel.ts ##
+@@ browser/src/control/Control.QuickFindPanel.ts: class QuickFindPanel extends SidebarBase {
+ if (
+ data.control.id === 'searchfinds' &&
+ data.control.type === 'treelistbox'
+- )
++ ) {
+ e.data.control.ignoreFocus = true;
1: 7c9696de43 ! 1: 46e7afdbfe feat(treeview): add a search field to lists
@@ browser/css/jsdialogs.css: algned to the bottom */
+ padding-right: 1px;
+}
+
-+#ui-treeview-search-input {
++[id^='ui-treeview-search-input'] {
+ width: 100%;
+ box-sizing: border-box;
+}
+
- .modalpopup .ui-treeview {
+ #__MENU__.ui-treeview {
min-height: min-content;
}
+ ## browser/src/canvas/sections/CommentListSection.ts ##
+@@ browser/src/canvas/sections/CommentListSection.ts: export class CommentSection extends CanvasSectionObject {
+ fireKeyEvents: true,
+ hideIfEmpty: true,
+ entries: [] as Array<TreeEntryJSON>,
++ noSearchField: true,
+ },
+ {
+ id: '',
+
+ ## browser/src/control/AutoCompletePopup.ts ##
+@@ browser/src/control/AutoCompletePopup.ts: abstract class AutoCompletePopup {
+ singleclickactivate: false,
+ fireKeyEvents: true,
+ entries: [] as Array<TreeEntryJSON>,
++ noSearchField: true,
+ } as TreeWidgetJSON;
+ }
+
+
+ ## browser/src/control/Control.QuickFindPanel.ts ##
+@@ browser/src/control/Control.QuickFindPanel.ts: class QuickFindPanel extends SidebarBase {
+ if (
+ data.control.id === 'searchfinds' &&
+ data.control.type === 'treelistbox'
+- )
++ ) {
+ e.data.control.ignoreFocus = true;
++ e.data.control.noSearchField = true;
++ }
+
+ if (!super.onJSUpdate(e)) return false;
+
+@@ browser/src/control/Control.QuickFindPanel.ts: class QuickFindPanel extends SidebarBase {
+ quickFindControls.classList.toggle('hidden', isEmpty);
+ }
+
++ removeSearchFields(quickFindData: any): any {
++ if (quickFindData.children) {
++ const modifiedData = JSON.parse(JSON.stringify(quickFindData));
++
++ const _removeSearchFields = (data: any) => {
++ for (const child of data.children) {
++ if (child.type === 'treelistbox') {
++ child.noSearchField = true;
++ }
++
++ if (child.children) {
++ _removeSearchFields(child);
++ }
++ }
++ };
++
++ _removeSearchFields(modifiedData);
++
++ return modifiedData;
++ }
++
++ return quickFindData;
++ }
++
+ addPlaceholderIfEmpty(quickFindData: any): any {
+ const hasEntries =
+ quickFindData.children &&
+@@ browser/src/control/Control.QuickFindPanel.ts: class QuickFindPanel extends SidebarBase {
+
+ this.container.innerHTML = '';
+
+- const modifiedData = this.addPlaceholderIfEmpty(quickFindData);
++ let modifiedData = this.removeSearchFields(quickFindData);
++ modifiedData = this.addPlaceholderIfEmpty(modifiedData);
+
+ this.builder?.build(this.container, [modifiedData], false);
+
+
+ ## browser/src/control/jsdialog/Definitions.Types.ts ##
+@@ browser/src/control/jsdialog/Definitions.Types.ts: interface TreeWidgetJSON extends WidgetJSON {
+ highlightTerm?: string; // what, if any, entries are we highlighting?
+ ignoreFocus?: boolean; // When true, does't focus to selected item automatically.
+ customEntryRenderer?: boolean;
++ noSearchField?: boolean; // When true, the widget shouldn't have a search field added
+ }
+
+ interface IconViewEntry {
+
## browser/src/control/jsdialog/Widget.TreeView.ts ##
@@ browser/src/control/jsdialog/Widget.TreeView.ts: class TreeViewControl {
if (level === 1 && !hasSelectedEntry) this.makeTreeViewFocusable(true);
@@ browser/src/control/jsdialog/Widget.TreeView.ts: class TreeViewControl {
+ showSearchBar(parent: HTMLElement) {
+ const searchBox = document.createElement('input');
-+ searchBox.id = 'ui-treeview-search-input'; // Form fields should have either a name or an ID - using this instead of a class
++ searchBox.id = JSDialog.MakeIdUnique('ui-treeview-search-input'); // Form fields should have either a name or an ID - using this instead of a class
+ searchBox.placeholder = 'Search...';
+ searchBox.addEventListener('input', () =>
+ this.filterEntries(searchBox.value),
@@ browser/src/control/jsdialog/Widget.TreeView.ts: class TreeViewControl {
+ if (
+ this._isListbox &&
-+ this._container.id !== 'searchfinds' &&
-+ this._container.id !== 'mentionPopupList'
++ !data.noSearchField
+ ) {
+ this.showSearchBar(this._container);
+ } |
7e28adb to
d6e5f4b
Compare
eszkadev
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code looks ok
|
redraft, I've noticed an issue with treeviews with different numbers of columns -- seems that _columns isn't always quite right and since as we dynamically figure this out we can't use infinity or -1 to just go to the last column either |
|
there are icons and expanders which might occupy some place in some tables I think |
yeah, I'm going to move the search bar creation to after we fill columns, and count up what the largest column we get there is... |
d6e5f4b to
514e3cf
Compare
This change came about because of the difficulty of finding items in really long dropdown lists. We can make a fairly quick solution to this using the existing filtering functions, tied to an input element which sticks to the top of the dropdown list... I'm a little unconvinced by using position: sticky, since as overscroll will cause the search bar to move (which is cosmetically weird, though not actually a functional problem). Nevertheless, I couldn't find something obviously better without making a risky change to treeviews at large. I suspect you can do some position: absolute thing to minimize trouble, but whatever it is it won't be clean. This depends on https://gerrit.libreoffice.org/c/core/+/195719 to hide the search field with checkbox lists to avoid duplicates there We also explicitly ignore some dropdown lists - the search results and the mention popup - since as having a search there doesn't make a lot of sense... Signed-off-by: Skyler Grey <[email protected]> Change-Id: Ib8000bc3e5566993fa6eea89adcc617b6a6a6964
514e3cf to
5df6c0c
Compare
|
fixed |



This change came about because of the difficulty of finding items in really long dropdown lists. We can make a fairly quick solution to this using the existing filtering functions, tied to an input element which sticks to the top of the dropdown list...
This probably shouldn't be merged as is, in particular:
Nevertheless, hopefully it'll be useful for you to test!
Change-Id: Ib8000bc3e5566993fa6eea89adcc617b6a6a6964
Summary
TODO
Checklist
make prettier-writeand formatted the code.make checkmake runand manually verified that everything looks okay