diff --git a/web/src/search.js b/web/src/search.js index 6c23036969..d6cfc9be52 100644 --- a/web/src/search.js +++ b/web/src/search.js @@ -90,7 +90,7 @@ export function initialize() { search_map = suggestions.lookup_table; return suggestions.strings; }, - fixed: true, + parentElement: "#searchbox_legacy", items: search_suggestion.max_num_of_search_results, helpOnEmptyStrings: true, naturalSearch: true, diff --git a/web/styles/search.css b/web/styles/search.css index 42b06e0d92..a0eadae079 100644 --- a/web/styles/search.css +++ b/web/styles/search.css @@ -15,14 +15,8 @@ width: calc(100% - 2px); position: absolute; - @media (width < $xl_min) { - width: calc(100% - 84px); - } - @media (width < $md_min) { - /* todo: Figure out why this has to be different - from top-navbar-border at this width and resolve it */ - width: calc(100% - 123px); + width: calc(100% - 42px); } .search_close_button { @@ -35,6 +29,15 @@ } } + .typeahead.dropdown-menu { + /* Match the typeahead's width to its parent container. */ + right: 0; + + @media (width < $md_min) { + margin-left: 40px; + } + } + .input-append { position: relative; width: 100%; diff --git a/web/styles/zulip.css b/web/styles/zulip.css index 9711503534..302fb34e4e 100644 --- a/web/styles/zulip.css +++ b/web/styles/zulip.css @@ -2742,8 +2742,8 @@ select.invite-as { margin-right: 7px; } - .top-navbar-container { - width: calc(100% - 84px); + #navbar-middle { + margin-right: 87px; } .search_closed .zulip-icon-search { @@ -2803,7 +2803,6 @@ select.invite-as { .column-middle-inner { margin-left: 0; - margin-right: 15px; } .app-main .column-middle .column-middle-inner { @@ -2816,7 +2815,6 @@ select.invite-as { .top-navbar-border { margin-left: 40px; - width: calc(100% - 108px); } .search_closed .zulip-icon-search { diff --git a/web/tests/search_future.test.js b/web/tests/search_future.test.js index 51dd1b8129..b7265977cc 100644 --- a/web/tests/search_future.test.js +++ b/web/tests/search_future.test.js @@ -103,7 +103,6 @@ test("initialize", ({mock_template}) => { search_suggestion.max_num_of_search_results = 99; $search_query_box.typeahead = (opts) => { - assert.equal(opts.fixed, true); assert.equal(opts.items, 99); assert.equal(opts.naturalSearch, true); assert.equal(opts.helpOnEmptyStrings, true); diff --git a/web/tests/search_now.test.js b/web/tests/search_now.test.js index 0ae5990155..715460196c 100644 --- a/web/tests/search_now.test.js +++ b/web/tests/search_now.test.js @@ -86,7 +86,6 @@ run_test("initialize", ({mock_template}) => { search_suggestion.max_num_of_search_results = 999; $search_query_box.typeahead = (opts) => { - assert.equal(opts.fixed, true); assert.equal(opts.items, 999); assert.equal(opts.naturalSearch, true); assert.equal(opts.helpOnEmptyStrings, true); diff --git a/web/third/bootstrap-typeahead/typeahead.js b/web/third/bootstrap-typeahead/typeahead.js index b1ff246c5c..eb5120499d 100644 --- a/web/third/bootstrap-typeahead/typeahead.js +++ b/web/third/bootstrap-typeahead/typeahead.js @@ -98,6 +98,13 @@ * We add a new event handler, resizeHandler, for window.on('resize', ...) * that calls this.show to re-render the typeahead in the correct position. * + * 10. Allow typeahead to be located next to its input field in the DOM + * + * We add a new `parentElement` option which the typeahead can + * append to, where before it could only be appended to `body`. + * Since it's in the right part of the DOM, we don't need to do + * the manual positioning in the show() function. + * * ============================================================ */ import {insert} from "text-field-edit"; @@ -126,7 +133,7 @@ import {get_string_diff} from "../../src/util"; this.sorter = this.options.sorter || this.sorter this.highlighter = this.options.highlighter || this.highlighter this.updater = this.options.updater || this.updater - this.$container = $(this.options.container).appendTo('body') + this.$container = $(this.options.container).appendTo(this.options.parentElement || 'body') this.$menu = $(this.options.menu).appendTo(this.$container) this.$header = $(this.options.header_html).appendTo(this.$container) this.source = this.options.source @@ -207,37 +214,41 @@ import {get_string_diff} from "../../src/util"; this.$header.hide(); } + // If a parent element was specified, we shouldn't manually + // position the element, since it's already in the right place. + if (!this.options.parentElement) { var pos; - if (this.fixed) { - // Relative to screen instead of to page - pos = this.$element[0].getBoundingClientRect(); - } else { - pos = this.$element.offset(); + if (this.fixed) { + // Relative to screen instead of to page + pos = this.$element[0].getBoundingClientRect(); + } else { + pos = this.$element.offset(); + } + + pos = $.extend({}, pos, { + height: this.$element[0].offsetHeight + }) + + // Zulip patch: Workaround for iOS safari problems + pos.top = this.$element.offset().top; + + var top_pos = pos.top + pos.height + if (this.dropup) { + top_pos = pos.top - this.$container.outerHeight() + } + + // Zulip patch: Avoid typeahead going off top of screen. + if (top_pos < 0) { + top_pos = 0; + } + + this.$container.css({ + top: top_pos + , left: pos.left + }) } - pos = $.extend({}, pos, { - height: this.$element[0].offsetHeight - }) - - // Zulip patch: Workaround for iOS safari problems - pos.top = this.$element.offset().top; - - var top_pos = pos.top + pos.height - if (this.dropup) { - top_pos = pos.top - this.$container.outerHeight() - } - - // Zulip patch: Avoid typeahead going off top of screen. - if (top_pos < 0) { - top_pos = 0; - } - - this.$container.css({ - top: top_pos - , left: pos.left - }) - this.$container.show() this.shown = true this.mouse_moved_since_typeahead = false