Skip to content
This repository was archived by the owner on Jul 12, 2020. It is now read-only.

Organize searchbar interface results by page - #126

Merged
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization
Feb 15, 2020
Merged

Organize searchbar interface results by page#126
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization

Conversation

@ang-zeyu

@ang-zeyuang-zeyu commented Jan 31, 2020

Copy link
Copy Markdown

What is the purpose of this pull request? (put "X" next to an item, remove the rest)

• [x] Enhancement to an existing feature

ResolvesMarkBind/markbind#994
Requires MarkBind/markbind#1006

What is the rationale for this request?
Search results are not organized by page, resulting in a less pleasant user experience.

What changes did you make? (Give an overview)

  • Moved searchbarTemplate to its own seperate file for better maintainability.
  • Rewrite searchbarTemplate's template to organize results by page
  • Changed result sorting to sort first by the total number of matches in a page, then by the respective number of matches for the page's headings ( and keywords ).
  • Use the page src as a fallback title for the title, which prevents this:
    emptytitle

End result:
searchbar

Provide some example code that this change will affect:

Template of searchbarTemplate

<divv-if="item.heading" class="heading"><divclass="heading-text">{{ item.heading.text }}</div><divclass="heading-text-items"><smallv-html="highlight(item.heading.text, value)"></small><br/><smallv-for="(keyword, index) in item.keywords" :key="index"><spanv-html="highlight(keyword, value)"></span><br/></small></div></div><divv-else>
...
</div>

Is there anything you'd like reviewers to focus on?
na

Testing instructions:
The test site has a good amount of keywords / headings used to test the sorting algorithm.
This version of SearchbarPageItem displays the number of matches beside the entry, if needed

The searchbar should appear as is in the above image otherwise.

Proposed commit message: (wrap lines at 72 characters)

Organize searchbar interface results by page

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.

This can lead to a less pleasant user experience with the searchbar.

Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good change. Just a couple of comments for now!

Comment threadsrc/Searchbar.vue
.filter(searchKeyword => searchKeyword !== '')
.map(searchKeyword => searchKeyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
.map(searchKeyword => new RegExp(searchKeyword, 'i'));
.map(searchKeyword => new RegExp(searchKeyword, 'ig'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the g flag?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Comment threadsrc/Searchbar.vue Outdated
if (isMatchingPage) {
matches.push(Object.assign(entry, { totalMatches }));
}
const fallbackTitle = title || src;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term fallback feels a little misleading here, since this variable would be used as the eventual title anyway. Would something like resultTitle be more accurate?

Comment threadsrc/Searchbar.vue Outdated
const matchesKeywords = headingKeywords[id] && headingKeywords[id].some(keyword =>
regexes.some(regex => regex.test(keyword)));
if (matchesHeading || matchesKeywords) {
searchTarget = [fallbackTitle, keywords, text, ...(headingKeywords[id] || [])].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be helpful to add some comments to explain what we're trying to do when we are changing the search target here 🙂

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a more specific variable name might help too!

Comment threadsrc/Searchbar.vue Outdated
keywords,
...Object.values(headings),
...Object.values(headingKeywords),
].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like it would be nice to move the join(' ') part to getTotalMatches, so that we can just pass a list of search targets to the function instead of having to join it manually every time.

Comment threadsrc/SearchbarPageItem.vue Outdated
<span class="page-title" v-html="highlight(item.title, value)"></span>
<br v-if="item.keywords" />
<small v-if="item.keywords" v-html="highlight(item.keywords, value)"></small>
<hr class="page-headings-separator"/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ang-zeyu oops, I missed this just now. There seems to be an inconsistent spacing here between the class and the closing />

@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch 2 times, most recently from 163b1aa to a2e1daaCompareFebruary 5, 2020 05:23
@ang-zeyu

ang-zeyu commented Feb 5, 2020

Copy link
Copy Markdown
Author

Looks like a good change. Just a couple of comments for now!

Thanks for the suggestions! I've updated the relavant parts

I've updated the testing instructions with a link to a version of searchbarPageItem that displays the number of matches beside it as well, if needed

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Yup, the old algorithm pattern didn't count repeats.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes! Just a couple of follow up comments.

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Comment threadsrc/Searchbar.vue Outdated
function getTotalMatches(searchTarget, regexes) {
return regexes.reduce((total, regex) => (regex.test(searchTarget) ? total + 1 : total), 0);
// Returns the total number of matches between an array of regex patterns and string search targets.
function getTotalMatches(regexes, ...searchTargets) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if it wasn't clear before, but I was thinking of having a variable searchTargets. I don't feel that the spread operator gives us much benefit here, and makes it a little more confusing at the call site.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I'm still not so sure what you mean by "having a variable searchTargets" though;

As a guess, do you mean removing searchTarget/searchTargets as a parameter from getTotalMatches altogether, and using a variable local to primitiveData()?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking something along these lines:

function getTotalMatches(regexes, searchTargets) {
...
}
const searchTargets = [...];
const totalMatches = getTotalMatches(regexes, searchTargets);

Comment threadsrc/Searchbar.vue Outdated
}
const displayTitle = title || src;

// The total number of occurrences of all indexed words ( headings, keywords, title ) for a page

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit, but should we stick to the usual spacing conventions here for the bracket? (i.e. (headings, keywords, title))

@ang-zeyu

Copy link
Copy Markdown
Author

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Hmm, the PR's version shouldn't show the number of matches, only the template file I linked in the testing instructions, for verify the sorting algorithm. Can I confirm this?

@marvinchin

Copy link
Copy Markdown

Ah I think I misunderstood earlier that you were suggesting that we add the match counts to the production version. Yes, the number of matches don't appear in the search result in the PR version. Thanks for clarifying!

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.
This can lead to a less pleasant user experience with the searchbar.
Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.
@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch from a2e1daa to 305bc02CompareFebruary 7, 2020 06:49
@ang-zeyu

Copy link
Copy Markdown
Author

Thanks for clarifying as well!

I've updated it and removed the comments in favor of more explicit variable names

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me :)

@ang-zeyu

Copy link
Copy Markdown
Author

This looks good to me :)

Thanks a lot for reviewing this! 😄

@yamgentyamgent added this to the v2.0.1-markbind.35 milestone Feb 15, 2020
@yamgent
yamgent merged commit 400a3d6 into MarkBind:masterFeb 15, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve default search UI organization

3 participants

@ang-zeyu@marvinchin@yamgent
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all \x3Cpre>\x3Ccode> blocks (function() { function addCopyButtons() { document.querySelectorAll('pre code').forEach(function(codeBlock) { if (codeBlock.parentElement.hasAttribute('data-copy-added')) return; codeBlock.parentElement.setAttribute('data-copy-added', 'true'); var btn = document.createElement('button'); btn.textContent = 'Copy'; btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;'; btn.onmouseover = function() { this.style.opacity = '1'; }; btn.onmouseout = function() { this.style.opacity = '0.7'; }; btn.onclick = function() { navigator.clipboard.writeText(codeBlock.textContent).then(function() { btn.textContent = 'Copied!'; setTimeout(function() { btn.textContent = 'Copy'; }, 1500); }); }; codeBlock.parentElement.style.position = 'relative'; codeBlock.parentElement.appendChild(btn); }); } addCopyButtons(); // Re-run on dynamic content var observer = new MutationObserver(addCopyButtons); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + ' Organize searchbar interface results by page by ang-zeyu · Pull Request #126 · MarkBind/vue-strap · GitHub
Skip to content
This repository was archived by the owner on Jul 12, 2020. It is now read-only.

Organize searchbar interface results by page - #126

Merged
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization
Feb 15, 2020
Merged

Organize searchbar interface results by page#126
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization

Conversation

@ang-zeyu

@ang-zeyuang-zeyu commented Jan 31, 2020

Copy link
Copy Markdown

What is the purpose of this pull request? (put "X" next to an item, remove the rest)

• [x] Enhancement to an existing feature

ResolvesMarkBind/markbind#994
Requires MarkBind/markbind#1006

What is the rationale for this request?
Search results are not organized by page, resulting in a less pleasant user experience.

What changes did you make? (Give an overview)

  • Moved searchbarTemplate to its own seperate file for better maintainability.
  • Rewrite searchbarTemplate's template to organize results by page
  • Changed result sorting to sort first by the total number of matches in a page, then by the respective number of matches for the page's headings ( and keywords ).
  • Use the page src as a fallback title for the title, which prevents this:
    emptytitle

End result:
searchbar

Provide some example code that this change will affect:

Template of searchbarTemplate

<divv-if="item.heading" class="heading"><divclass="heading-text">{{ item.heading.text }}</div><divclass="heading-text-items"><smallv-html="highlight(item.heading.text, value)"></small><br/><smallv-for="(keyword, index) in item.keywords" :key="index"><spanv-html="highlight(keyword, value)"></span><br/></small></div></div><divv-else>
...
</div>

Is there anything you'd like reviewers to focus on?
na

Testing instructions:
The test site has a good amount of keywords / headings used to test the sorting algorithm.
This version of SearchbarPageItem displays the number of matches beside the entry, if needed

The searchbar should appear as is in the above image otherwise.

Proposed commit message: (wrap lines at 72 characters)

Organize searchbar interface results by page

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.

This can lead to a less pleasant user experience with the searchbar.

Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good change. Just a couple of comments for now!

Comment threadsrc/Searchbar.vue
.filter(searchKeyword => searchKeyword !== '')
.map(searchKeyword => searchKeyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
.map(searchKeyword => new RegExp(searchKeyword, 'i'));
.map(searchKeyword => new RegExp(searchKeyword, 'ig'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the g flag?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Comment threadsrc/Searchbar.vue Outdated
if (isMatchingPage) {
matches.push(Object.assign(entry, { totalMatches }));
}
const fallbackTitle = title || src;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term fallback feels a little misleading here, since this variable would be used as the eventual title anyway. Would something like resultTitle be more accurate?

Comment threadsrc/Searchbar.vue Outdated
const matchesKeywords = headingKeywords[id] && headingKeywords[id].some(keyword =>
regexes.some(regex => regex.test(keyword)));
if (matchesHeading || matchesKeywords) {
searchTarget = [fallbackTitle, keywords, text, ...(headingKeywords[id] || [])].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be helpful to add some comments to explain what we're trying to do when we are changing the search target here 🙂

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a more specific variable name might help too!

Comment threadsrc/Searchbar.vue Outdated
keywords,
...Object.values(headings),
...Object.values(headingKeywords),
].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like it would be nice to move the join(' ') part to getTotalMatches, so that we can just pass a list of search targets to the function instead of having to join it manually every time.

Comment threadsrc/SearchbarPageItem.vue Outdated
<span class="page-title" v-html="highlight(item.title, value)"></span>
<br v-if="item.keywords" />
<small v-if="item.keywords" v-html="highlight(item.keywords, value)"></small>
<hr class="page-headings-separator"/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ang-zeyu oops, I missed this just now. There seems to be an inconsistent spacing here between the class and the closing />

@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch 2 times, most recently from 163b1aa to a2e1daaCompareFebruary 5, 2020 05:23
@ang-zeyu

ang-zeyu commented Feb 5, 2020

Copy link
Copy Markdown
Author

Looks like a good change. Just a couple of comments for now!

Thanks for the suggestions! I've updated the relavant parts

I've updated the testing instructions with a link to a version of searchbarPageItem that displays the number of matches beside it as well, if needed

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Yup, the old algorithm pattern didn't count repeats.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes! Just a couple of follow up comments.

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Comment threadsrc/Searchbar.vue Outdated
function getTotalMatches(searchTarget, regexes) {
return regexes.reduce((total, regex) => (regex.test(searchTarget) ? total + 1 : total), 0);
// Returns the total number of matches between an array of regex patterns and string search targets.
function getTotalMatches(regexes, ...searchTargets) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if it wasn't clear before, but I was thinking of having a variable searchTargets. I don't feel that the spread operator gives us much benefit here, and makes it a little more confusing at the call site.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I'm still not so sure what you mean by "having a variable searchTargets" though;

As a guess, do you mean removing searchTarget/searchTargets as a parameter from getTotalMatches altogether, and using a variable local to primitiveData()?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking something along these lines:

function getTotalMatches(regexes, searchTargets) {
...
}
const searchTargets = [...];
const totalMatches = getTotalMatches(regexes, searchTargets);

Comment threadsrc/Searchbar.vue Outdated
}
const displayTitle = title || src;

// The total number of occurrences of all indexed words ( headings, keywords, title ) for a page

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit, but should we stick to the usual spacing conventions here for the bracket? (i.e. (headings, keywords, title))

@ang-zeyu

Copy link
Copy Markdown
Author

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Hmm, the PR's version shouldn't show the number of matches, only the template file I linked in the testing instructions, for verify the sorting algorithm. Can I confirm this?

@marvinchin

Copy link
Copy Markdown

Ah I think I misunderstood earlier that you were suggesting that we add the match counts to the production version. Yes, the number of matches don't appear in the search result in the PR version. Thanks for clarifying!

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.
This can lead to a less pleasant user experience with the searchbar.
Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.
@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch from a2e1daa to 305bc02CompareFebruary 7, 2020 06:49
@ang-zeyu

Copy link
Copy Markdown
Author

Thanks for clarifying as well!

I've updated it and removed the comments in favor of more explicit variable names

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me :)

@ang-zeyu

Copy link
Copy Markdown
Author

This looks good to me :)

Thanks a lot for reviewing this! 😄

@yamgentyamgent added this to the v2.0.1-markbind.35 milestone Feb 15, 2020
@yamgent
yamgent merged commit 400a3d6 into MarkBind:masterFeb 15, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve default search UI organization

3 participants

@ang-zeyu@marvinchin@yamgent
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Organize searchbar interface results by page by ang-zeyu · Pull Request #126 · MarkBind/vue-strap · GitHub
Skip to content
This repository was archived by the owner on Jul 12, 2020. It is now read-only.

Organize searchbar interface results by page - #126

Merged
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization
Feb 15, 2020
Merged

Organize searchbar interface results by page#126
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization

Conversation

@ang-zeyu

@ang-zeyuang-zeyu commented Jan 31, 2020

Copy link
Copy Markdown

What is the purpose of this pull request? (put "X" next to an item, remove the rest)

• [x] Enhancement to an existing feature

ResolvesMarkBind/markbind#994
Requires MarkBind/markbind#1006

What is the rationale for this request?
Search results are not organized by page, resulting in a less pleasant user experience.

What changes did you make? (Give an overview)

  • Moved searchbarTemplate to its own seperate file for better maintainability.
  • Rewrite searchbarTemplate's template to organize results by page
  • Changed result sorting to sort first by the total number of matches in a page, then by the respective number of matches for the page's headings ( and keywords ).
  • Use the page src as a fallback title for the title, which prevents this:
    emptytitle

End result:
searchbar

Provide some example code that this change will affect:

Template of searchbarTemplate

<divv-if="item.heading" class="heading"><divclass="heading-text">{{ item.heading.text }}</div><divclass="heading-text-items"><smallv-html="highlight(item.heading.text, value)"></small><br/><smallv-for="(keyword, index) in item.keywords" :key="index"><spanv-html="highlight(keyword, value)"></span><br/></small></div></div><divv-else>
...
</div>

Is there anything you'd like reviewers to focus on?
na

Testing instructions:
The test site has a good amount of keywords / headings used to test the sorting algorithm.
This version of SearchbarPageItem displays the number of matches beside the entry, if needed

The searchbar should appear as is in the above image otherwise.

Proposed commit message: (wrap lines at 72 characters)

Organize searchbar interface results by page

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.

This can lead to a less pleasant user experience with the searchbar.

Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good change. Just a couple of comments for now!

Comment threadsrc/Searchbar.vue
.filter(searchKeyword => searchKeyword !== '')
.map(searchKeyword => searchKeyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
.map(searchKeyword => new RegExp(searchKeyword, 'i'));
.map(searchKeyword => new RegExp(searchKeyword, 'ig'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the g flag?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Comment threadsrc/Searchbar.vue Outdated
if (isMatchingPage) {
matches.push(Object.assign(entry, { totalMatches }));
}
const fallbackTitle = title || src;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term fallback feels a little misleading here, since this variable would be used as the eventual title anyway. Would something like resultTitle be more accurate?

Comment threadsrc/Searchbar.vue Outdated
const matchesKeywords = headingKeywords[id] && headingKeywords[id].some(keyword =>
regexes.some(regex => regex.test(keyword)));
if (matchesHeading || matchesKeywords) {
searchTarget = [fallbackTitle, keywords, text, ...(headingKeywords[id] || [])].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be helpful to add some comments to explain what we're trying to do when we are changing the search target here 🙂

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a more specific variable name might help too!

Comment threadsrc/Searchbar.vue Outdated
keywords,
...Object.values(headings),
...Object.values(headingKeywords),
].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like it would be nice to move the join(' ') part to getTotalMatches, so that we can just pass a list of search targets to the function instead of having to join it manually every time.

Comment threadsrc/SearchbarPageItem.vue Outdated
<span class="page-title" v-html="highlight(item.title, value)"></span>
<br v-if="item.keywords" />
<small v-if="item.keywords" v-html="highlight(item.keywords, value)"></small>
<hr class="page-headings-separator"/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ang-zeyu oops, I missed this just now. There seems to be an inconsistent spacing here between the class and the closing />

@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch 2 times, most recently from 163b1aa to a2e1daaCompareFebruary 5, 2020 05:23
@ang-zeyu

ang-zeyu commented Feb 5, 2020

Copy link
Copy Markdown
Author

Looks like a good change. Just a couple of comments for now!

Thanks for the suggestions! I've updated the relavant parts

I've updated the testing instructions with a link to a version of searchbarPageItem that displays the number of matches beside it as well, if needed

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Yup, the old algorithm pattern didn't count repeats.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes! Just a couple of follow up comments.

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Comment threadsrc/Searchbar.vue Outdated
function getTotalMatches(searchTarget, regexes) {
return regexes.reduce((total, regex) => (regex.test(searchTarget) ? total + 1 : total), 0);
// Returns the total number of matches between an array of regex patterns and string search targets.
function getTotalMatches(regexes, ...searchTargets) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if it wasn't clear before, but I was thinking of having a variable searchTargets. I don't feel that the spread operator gives us much benefit here, and makes it a little more confusing at the call site.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I'm still not so sure what you mean by "having a variable searchTargets" though;

As a guess, do you mean removing searchTarget/searchTargets as a parameter from getTotalMatches altogether, and using a variable local to primitiveData()?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking something along these lines:

function getTotalMatches(regexes, searchTargets) {
...
}
const searchTargets = [...];
const totalMatches = getTotalMatches(regexes, searchTargets);

Comment threadsrc/Searchbar.vue Outdated
}
const displayTitle = title || src;

// The total number of occurrences of all indexed words ( headings, keywords, title ) for a page

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit, but should we stick to the usual spacing conventions here for the bracket? (i.e. (headings, keywords, title))

@ang-zeyu

Copy link
Copy Markdown
Author

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Hmm, the PR's version shouldn't show the number of matches, only the template file I linked in the testing instructions, for verify the sorting algorithm. Can I confirm this?

@marvinchin

Copy link
Copy Markdown

Ah I think I misunderstood earlier that you were suggesting that we add the match counts to the production version. Yes, the number of matches don't appear in the search result in the PR version. Thanks for clarifying!

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.
This can lead to a less pleasant user experience with the searchbar.
Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.
@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch from a2e1daa to 305bc02CompareFebruary 7, 2020 06:49
@ang-zeyu

Copy link
Copy Markdown
Author

Thanks for clarifying as well!

I've updated it and removed the comments in favor of more explicit variable names

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me :)

@ang-zeyu

Copy link
Copy Markdown
Author

This looks good to me :)

Thanks a lot for reviewing this! 😄

@yamgentyamgent added this to the v2.0.1-markbind.35 milestone Feb 15, 2020
@yamgent
yamgent merged commit 400a3d6 into MarkBind:masterFeb 15, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve default search UI organization

3 participants

@ang-zeyu@marvinchin@yamgent
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Organize searchbar interface results by page by ang-zeyu · Pull Request #126 · MarkBind/vue-strap · GitHub
Skip to content
This repository was archived by the owner on Jul 12, 2020. It is now read-only.

Organize searchbar interface results by page - #126

Merged
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization
Feb 15, 2020
Merged

Organize searchbar interface results by page#126
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization

Conversation

@ang-zeyu

@ang-zeyuang-zeyu commented Jan 31, 2020

Copy link
Copy Markdown

What is the purpose of this pull request? (put "X" next to an item, remove the rest)

• [x] Enhancement to an existing feature

ResolvesMarkBind/markbind#994
Requires MarkBind/markbind#1006

What is the rationale for this request?
Search results are not organized by page, resulting in a less pleasant user experience.

What changes did you make? (Give an overview)

  • Moved searchbarTemplate to its own seperate file for better maintainability.
  • Rewrite searchbarTemplate's template to organize results by page
  • Changed result sorting to sort first by the total number of matches in a page, then by the respective number of matches for the page's headings ( and keywords ).
  • Use the page src as a fallback title for the title, which prevents this:
    emptytitle

End result:
searchbar

Provide some example code that this change will affect:

Template of searchbarTemplate

<divv-if="item.heading" class="heading"><divclass="heading-text">{{ item.heading.text }}</div><divclass="heading-text-items"><smallv-html="highlight(item.heading.text, value)"></small><br/><smallv-for="(keyword, index) in item.keywords" :key="index"><spanv-html="highlight(keyword, value)"></span><br/></small></div></div><divv-else>
...
</div>

Is there anything you'd like reviewers to focus on?
na

Testing instructions:
The test site has a good amount of keywords / headings used to test the sorting algorithm.
This version of SearchbarPageItem displays the number of matches beside the entry, if needed

The searchbar should appear as is in the above image otherwise.

Proposed commit message: (wrap lines at 72 characters)

Organize searchbar interface results by page

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.

This can lead to a less pleasant user experience with the searchbar.

Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good change. Just a couple of comments for now!

Comment threadsrc/Searchbar.vue
.filter(searchKeyword => searchKeyword !== '')
.map(searchKeyword => searchKeyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
.map(searchKeyword => new RegExp(searchKeyword, 'i'));
.map(searchKeyword => new RegExp(searchKeyword, 'ig'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the g flag?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Comment threadsrc/Searchbar.vue Outdated
if (isMatchingPage) {
matches.push(Object.assign(entry, { totalMatches }));
}
const fallbackTitle = title || src;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term fallback feels a little misleading here, since this variable would be used as the eventual title anyway. Would something like resultTitle be more accurate?

Comment threadsrc/Searchbar.vue Outdated
const matchesKeywords = headingKeywords[id] && headingKeywords[id].some(keyword =>
regexes.some(regex => regex.test(keyword)));
if (matchesHeading || matchesKeywords) {
searchTarget = [fallbackTitle, keywords, text, ...(headingKeywords[id] || [])].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be helpful to add some comments to explain what we're trying to do when we are changing the search target here 🙂

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a more specific variable name might help too!

Comment threadsrc/Searchbar.vue Outdated
keywords,
...Object.values(headings),
...Object.values(headingKeywords),
].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like it would be nice to move the join(' ') part to getTotalMatches, so that we can just pass a list of search targets to the function instead of having to join it manually every time.

Comment threadsrc/SearchbarPageItem.vue Outdated
<span class="page-title" v-html="highlight(item.title, value)"></span>
<br v-if="item.keywords" />
<small v-if="item.keywords" v-html="highlight(item.keywords, value)"></small>
<hr class="page-headings-separator"/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ang-zeyu oops, I missed this just now. There seems to be an inconsistent spacing here between the class and the closing />

@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch 2 times, most recently from 163b1aa to a2e1daaCompareFebruary 5, 2020 05:23
@ang-zeyu

ang-zeyu commented Feb 5, 2020

Copy link
Copy Markdown
Author

Looks like a good change. Just a couple of comments for now!

Thanks for the suggestions! I've updated the relavant parts

I've updated the testing instructions with a link to a version of searchbarPageItem that displays the number of matches beside it as well, if needed

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Yup, the old algorithm pattern didn't count repeats.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes! Just a couple of follow up comments.

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Comment threadsrc/Searchbar.vue Outdated
function getTotalMatches(searchTarget, regexes) {
return regexes.reduce((total, regex) => (regex.test(searchTarget) ? total + 1 : total), 0);
// Returns the total number of matches between an array of regex patterns and string search targets.
function getTotalMatches(regexes, ...searchTargets) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if it wasn't clear before, but I was thinking of having a variable searchTargets. I don't feel that the spread operator gives us much benefit here, and makes it a little more confusing at the call site.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I'm still not so sure what you mean by "having a variable searchTargets" though;

As a guess, do you mean removing searchTarget/searchTargets as a parameter from getTotalMatches altogether, and using a variable local to primitiveData()?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking something along these lines:

function getTotalMatches(regexes, searchTargets) {
...
}
const searchTargets = [...];
const totalMatches = getTotalMatches(regexes, searchTargets);

Comment threadsrc/Searchbar.vue Outdated
}
const displayTitle = title || src;

// The total number of occurrences of all indexed words ( headings, keywords, title ) for a page

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit, but should we stick to the usual spacing conventions here for the bracket? (i.e. (headings, keywords, title))

@ang-zeyu

Copy link
Copy Markdown
Author

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Hmm, the PR's version shouldn't show the number of matches, only the template file I linked in the testing instructions, for verify the sorting algorithm. Can I confirm this?

@marvinchin

Copy link
Copy Markdown

Ah I think I misunderstood earlier that you were suggesting that we add the match counts to the production version. Yes, the number of matches don't appear in the search result in the PR version. Thanks for clarifying!

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.
This can lead to a less pleasant user experience with the searchbar.
Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.
@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch from a2e1daa to 305bc02CompareFebruary 7, 2020 06:49
@ang-zeyu

Copy link
Copy Markdown
Author

Thanks for clarifying as well!

I've updated it and removed the comments in favor of more explicit variable names

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me :)

@ang-zeyu

Copy link
Copy Markdown
Author

This looks good to me :)

Thanks a lot for reviewing this! 😄

@yamgentyamgent added this to the v2.0.1-markbind.35 milestone Feb 15, 2020
@yamgent
yamgent merged commit 400a3d6 into MarkBind:masterFeb 15, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve default search UI organization

3 participants

@ang-zeyu@marvinchin@yamgent
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Organize searchbar interface results by page by ang-zeyu · Pull Request #126 · MarkBind/vue-strap · GitHub
Skip to content
This repository was archived by the owner on Jul 12, 2020. It is now read-only.

Organize searchbar interface results by page - #126

Merged
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization
Feb 15, 2020
Merged

Organize searchbar interface results by page#126
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization

Conversation

@ang-zeyu

@ang-zeyuang-zeyu commented Jan 31, 2020

Copy link
Copy Markdown

What is the purpose of this pull request? (put "X" next to an item, remove the rest)

• [x] Enhancement to an existing feature

ResolvesMarkBind/markbind#994
Requires MarkBind/markbind#1006

What is the rationale for this request?
Search results are not organized by page, resulting in a less pleasant user experience.

What changes did you make? (Give an overview)

  • Moved searchbarTemplate to its own seperate file for better maintainability.
  • Rewrite searchbarTemplate's template to organize results by page
  • Changed result sorting to sort first by the total number of matches in a page, then by the respective number of matches for the page's headings ( and keywords ).
  • Use the page src as a fallback title for the title, which prevents this:
    emptytitle

End result:
searchbar

Provide some example code that this change will affect:

Template of searchbarTemplate

<divv-if="item.heading" class="heading"><divclass="heading-text">{{ item.heading.text }}</div><divclass="heading-text-items"><smallv-html="highlight(item.heading.text, value)"></small><br/><smallv-for="(keyword, index) in item.keywords" :key="index"><spanv-html="highlight(keyword, value)"></span><br/></small></div></div><divv-else>
...
</div>

Is there anything you'd like reviewers to focus on?
na

Testing instructions:
The test site has a good amount of keywords / headings used to test the sorting algorithm.
This version of SearchbarPageItem displays the number of matches beside the entry, if needed

The searchbar should appear as is in the above image otherwise.

Proposed commit message: (wrap lines at 72 characters)

Organize searchbar interface results by page

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.

This can lead to a less pleasant user experience with the searchbar.

Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good change. Just a couple of comments for now!

Comment threadsrc/Searchbar.vue
.filter(searchKeyword => searchKeyword !== '')
.map(searchKeyword => searchKeyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
.map(searchKeyword => new RegExp(searchKeyword, 'i'));
.map(searchKeyword => new RegExp(searchKeyword, 'ig'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the g flag?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Comment threadsrc/Searchbar.vue Outdated
if (isMatchingPage) {
matches.push(Object.assign(entry, { totalMatches }));
}
const fallbackTitle = title || src;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term fallback feels a little misleading here, since this variable would be used as the eventual title anyway. Would something like resultTitle be more accurate?

Comment threadsrc/Searchbar.vue Outdated
const matchesKeywords = headingKeywords[id] && headingKeywords[id].some(keyword =>
regexes.some(regex => regex.test(keyword)));
if (matchesHeading || matchesKeywords) {
searchTarget = [fallbackTitle, keywords, text, ...(headingKeywords[id] || [])].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be helpful to add some comments to explain what we're trying to do when we are changing the search target here 🙂

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a more specific variable name might help too!

Comment threadsrc/Searchbar.vue Outdated
keywords,
...Object.values(headings),
...Object.values(headingKeywords),
].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like it would be nice to move the join(' ') part to getTotalMatches, so that we can just pass a list of search targets to the function instead of having to join it manually every time.

Comment threadsrc/SearchbarPageItem.vue Outdated
<span class="page-title" v-html="highlight(item.title, value)"></span>
<br v-if="item.keywords" />
<small v-if="item.keywords" v-html="highlight(item.keywords, value)"></small>
<hr class="page-headings-separator"/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ang-zeyu oops, I missed this just now. There seems to be an inconsistent spacing here between the class and the closing />

@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch 2 times, most recently from 163b1aa to a2e1daaCompareFebruary 5, 2020 05:23
@ang-zeyu

ang-zeyu commented Feb 5, 2020

Copy link
Copy Markdown
Author

Looks like a good change. Just a couple of comments for now!

Thanks for the suggestions! I've updated the relavant parts

I've updated the testing instructions with a link to a version of searchbarPageItem that displays the number of matches beside it as well, if needed

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Yup, the old algorithm pattern didn't count repeats.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes! Just a couple of follow up comments.

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Comment threadsrc/Searchbar.vue Outdated
function getTotalMatches(searchTarget, regexes) {
return regexes.reduce((total, regex) => (regex.test(searchTarget) ? total + 1 : total), 0);
// Returns the total number of matches between an array of regex patterns and string search targets.
function getTotalMatches(regexes, ...searchTargets) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if it wasn't clear before, but I was thinking of having a variable searchTargets. I don't feel that the spread operator gives us much benefit here, and makes it a little more confusing at the call site.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I'm still not so sure what you mean by "having a variable searchTargets" though;

As a guess, do you mean removing searchTarget/searchTargets as a parameter from getTotalMatches altogether, and using a variable local to primitiveData()?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking something along these lines:

function getTotalMatches(regexes, searchTargets) {
...
}
const searchTargets = [...];
const totalMatches = getTotalMatches(regexes, searchTargets);

Comment threadsrc/Searchbar.vue Outdated
}
const displayTitle = title || src;

// The total number of occurrences of all indexed words ( headings, keywords, title ) for a page

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit, but should we stick to the usual spacing conventions here for the bracket? (i.e. (headings, keywords, title))

@ang-zeyu

Copy link
Copy Markdown
Author

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Hmm, the PR's version shouldn't show the number of matches, only the template file I linked in the testing instructions, for verify the sorting algorithm. Can I confirm this?

@marvinchin

Copy link
Copy Markdown

Ah I think I misunderstood earlier that you were suggesting that we add the match counts to the production version. Yes, the number of matches don't appear in the search result in the PR version. Thanks for clarifying!

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.
This can lead to a less pleasant user experience with the searchbar.
Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.
@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch from a2e1daa to 305bc02CompareFebruary 7, 2020 06:49
@ang-zeyu

Copy link
Copy Markdown
Author

Thanks for clarifying as well!

I've updated it and removed the comments in favor of more explicit variable names

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me :)

@ang-zeyu

Copy link
Copy Markdown
Author

This looks good to me :)

Thanks a lot for reviewing this! 😄

@yamgentyamgent added this to the v2.0.1-markbind.35 milestone Feb 15, 2020
@yamgent
yamgent merged commit 400a3d6 into MarkBind:masterFeb 15, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve default search UI organization

3 participants

@ang-zeyu@marvinchin@yamgent
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Organize searchbar interface results by page by ang-zeyu · Pull Request #126 · MarkBind/vue-strap · GitHub
Skip to content
This repository was archived by the owner on Jul 12, 2020. It is now read-only.

Organize searchbar interface results by page - #126

Merged
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization
Feb 15, 2020
Merged

Organize searchbar interface results by page#126
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization

Conversation

@ang-zeyu

@ang-zeyuang-zeyu commented Jan 31, 2020

Copy link
Copy Markdown

What is the purpose of this pull request? (put "X" next to an item, remove the rest)

• [x] Enhancement to an existing feature

ResolvesMarkBind/markbind#994
Requires MarkBind/markbind#1006

What is the rationale for this request?
Search results are not organized by page, resulting in a less pleasant user experience.

What changes did you make? (Give an overview)

  • Moved searchbarTemplate to its own seperate file for better maintainability.
  • Rewrite searchbarTemplate's template to organize results by page
  • Changed result sorting to sort first by the total number of matches in a page, then by the respective number of matches for the page's headings ( and keywords ).
  • Use the page src as a fallback title for the title, which prevents this:
    emptytitle

End result:
searchbar

Provide some example code that this change will affect:

Template of searchbarTemplate

<divv-if="item.heading" class="heading"><divclass="heading-text">{{ item.heading.text }}</div><divclass="heading-text-items"><smallv-html="highlight(item.heading.text, value)"></small><br/><smallv-for="(keyword, index) in item.keywords" :key="index"><spanv-html="highlight(keyword, value)"></span><br/></small></div></div><divv-else>
...
</div>

Is there anything you'd like reviewers to focus on?
na

Testing instructions:
The test site has a good amount of keywords / headings used to test the sorting algorithm.
This version of SearchbarPageItem displays the number of matches beside the entry, if needed

The searchbar should appear as is in the above image otherwise.

Proposed commit message: (wrap lines at 72 characters)

Organize searchbar interface results by page

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.

This can lead to a less pleasant user experience with the searchbar.

Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good change. Just a couple of comments for now!

Comment threadsrc/Searchbar.vue
.filter(searchKeyword => searchKeyword !== '')
.map(searchKeyword => searchKeyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
.map(searchKeyword => new RegExp(searchKeyword, 'i'));
.map(searchKeyword => new RegExp(searchKeyword, 'ig'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the g flag?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Comment threadsrc/Searchbar.vue Outdated
if (isMatchingPage) {
matches.push(Object.assign(entry, { totalMatches }));
}
const fallbackTitle = title || src;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term fallback feels a little misleading here, since this variable would be used as the eventual title anyway. Would something like resultTitle be more accurate?

Comment threadsrc/Searchbar.vue Outdated
const matchesKeywords = headingKeywords[id] && headingKeywords[id].some(keyword =>
regexes.some(regex => regex.test(keyword)));
if (matchesHeading || matchesKeywords) {
searchTarget = [fallbackTitle, keywords, text, ...(headingKeywords[id] || [])].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be helpful to add some comments to explain what we're trying to do when we are changing the search target here 🙂

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a more specific variable name might help too!

Comment threadsrc/Searchbar.vue Outdated
keywords,
...Object.values(headings),
...Object.values(headingKeywords),
].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like it would be nice to move the join(' ') part to getTotalMatches, so that we can just pass a list of search targets to the function instead of having to join it manually every time.

Comment threadsrc/SearchbarPageItem.vue Outdated
<span class="page-title" v-html="highlight(item.title, value)"></span>
<br v-if="item.keywords" />
<small v-if="item.keywords" v-html="highlight(item.keywords, value)"></small>
<hr class="page-headings-separator"/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ang-zeyu oops, I missed this just now. There seems to be an inconsistent spacing here between the class and the closing />

@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch 2 times, most recently from 163b1aa to a2e1daaCompareFebruary 5, 2020 05:23
@ang-zeyu

ang-zeyu commented Feb 5, 2020

Copy link
Copy Markdown
Author

Looks like a good change. Just a couple of comments for now!

Thanks for the suggestions! I've updated the relavant parts

I've updated the testing instructions with a link to a version of searchbarPageItem that displays the number of matches beside it as well, if needed

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Yup, the old algorithm pattern didn't count repeats.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes! Just a couple of follow up comments.

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Comment threadsrc/Searchbar.vue Outdated
function getTotalMatches(searchTarget, regexes) {
return regexes.reduce((total, regex) => (regex.test(searchTarget) ? total + 1 : total), 0);
// Returns the total number of matches between an array of regex patterns and string search targets.
function getTotalMatches(regexes, ...searchTargets) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if it wasn't clear before, but I was thinking of having a variable searchTargets. I don't feel that the spread operator gives us much benefit here, and makes it a little more confusing at the call site.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I'm still not so sure what you mean by "having a variable searchTargets" though;

As a guess, do you mean removing searchTarget/searchTargets as a parameter from getTotalMatches altogether, and using a variable local to primitiveData()?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking something along these lines:

function getTotalMatches(regexes, searchTargets) {
...
}
const searchTargets = [...];
const totalMatches = getTotalMatches(regexes, searchTargets);

Comment threadsrc/Searchbar.vue Outdated
}
const displayTitle = title || src;

// The total number of occurrences of all indexed words ( headings, keywords, title ) for a page

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit, but should we stick to the usual spacing conventions here for the bracket? (i.e. (headings, keywords, title))

@ang-zeyu

Copy link
Copy Markdown
Author

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Hmm, the PR's version shouldn't show the number of matches, only the template file I linked in the testing instructions, for verify the sorting algorithm. Can I confirm this?

@marvinchin

Copy link
Copy Markdown

Ah I think I misunderstood earlier that you were suggesting that we add the match counts to the production version. Yes, the number of matches don't appear in the search result in the PR version. Thanks for clarifying!

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.
This can lead to a less pleasant user experience with the searchbar.
Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.
@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch from a2e1daa to 305bc02CompareFebruary 7, 2020 06:49
@ang-zeyu

Copy link
Copy Markdown
Author

Thanks for clarifying as well!

I've updated it and removed the comments in favor of more explicit variable names

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me :)

@ang-zeyu

Copy link
Copy Markdown
Author

This looks good to me :)

Thanks a lot for reviewing this! 😄

@yamgentyamgent added this to the v2.0.1-markbind.35 milestone Feb 15, 2020
@yamgent
yamgent merged commit 400a3d6 into MarkBind:masterFeb 15, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve default search UI organization

3 participants

@ang-zeyu@marvinchin@yamgent
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Organize searchbar interface results by page by ang-zeyu · Pull Request #126 · MarkBind/vue-strap · GitHub
Skip to content
This repository was archived by the owner on Jul 12, 2020. It is now read-only.

Organize searchbar interface results by page - #126

Merged
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization
Feb 15, 2020
Merged

Organize searchbar interface results by page#126
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization

Conversation

@ang-zeyu

@ang-zeyuang-zeyu commented Jan 31, 2020

Copy link
Copy Markdown

What is the purpose of this pull request? (put "X" next to an item, remove the rest)

• [x] Enhancement to an existing feature

ResolvesMarkBind/markbind#994
Requires MarkBind/markbind#1006

What is the rationale for this request?
Search results are not organized by page, resulting in a less pleasant user experience.

What changes did you make? (Give an overview)

  • Moved searchbarTemplate to its own seperate file for better maintainability.
  • Rewrite searchbarTemplate's template to organize results by page
  • Changed result sorting to sort first by the total number of matches in a page, then by the respective number of matches for the page's headings ( and keywords ).
  • Use the page src as a fallback title for the title, which prevents this:
    emptytitle

End result:
searchbar

Provide some example code that this change will affect:

Template of searchbarTemplate

<divv-if="item.heading" class="heading"><divclass="heading-text">{{ item.heading.text }}</div><divclass="heading-text-items"><smallv-html="highlight(item.heading.text, value)"></small><br/><smallv-for="(keyword, index) in item.keywords" :key="index"><spanv-html="highlight(keyword, value)"></span><br/></small></div></div><divv-else>
...
</div>

Is there anything you'd like reviewers to focus on?
na

Testing instructions:
The test site has a good amount of keywords / headings used to test the sorting algorithm.
This version of SearchbarPageItem displays the number of matches beside the entry, if needed

The searchbar should appear as is in the above image otherwise.

Proposed commit message: (wrap lines at 72 characters)

Organize searchbar interface results by page

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.

This can lead to a less pleasant user experience with the searchbar.

Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good change. Just a couple of comments for now!

Comment threadsrc/Searchbar.vue
.filter(searchKeyword => searchKeyword !== '')
.map(searchKeyword => searchKeyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
.map(searchKeyword => new RegExp(searchKeyword, 'i'));
.map(searchKeyword => new RegExp(searchKeyword, 'ig'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the g flag?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Comment threadsrc/Searchbar.vue Outdated
if (isMatchingPage) {
matches.push(Object.assign(entry, { totalMatches }));
}
const fallbackTitle = title || src;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term fallback feels a little misleading here, since this variable would be used as the eventual title anyway. Would something like resultTitle be more accurate?

Comment threadsrc/Searchbar.vue Outdated
const matchesKeywords = headingKeywords[id] && headingKeywords[id].some(keyword =>
regexes.some(regex => regex.test(keyword)));
if (matchesHeading || matchesKeywords) {
searchTarget = [fallbackTitle, keywords, text, ...(headingKeywords[id] || [])].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be helpful to add some comments to explain what we're trying to do when we are changing the search target here 🙂

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a more specific variable name might help too!

Comment threadsrc/Searchbar.vue Outdated
keywords,
...Object.values(headings),
...Object.values(headingKeywords),
].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like it would be nice to move the join(' ') part to getTotalMatches, so that we can just pass a list of search targets to the function instead of having to join it manually every time.

Comment threadsrc/SearchbarPageItem.vue Outdated
<span class="page-title" v-html="highlight(item.title, value)"></span>
<br v-if="item.keywords" />
<small v-if="item.keywords" v-html="highlight(item.keywords, value)"></small>
<hr class="page-headings-separator"/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ang-zeyu oops, I missed this just now. There seems to be an inconsistent spacing here between the class and the closing />

@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch 2 times, most recently from 163b1aa to a2e1daaCompareFebruary 5, 2020 05:23
@ang-zeyu

ang-zeyu commented Feb 5, 2020

Copy link
Copy Markdown
Author

Looks like a good change. Just a couple of comments for now!

Thanks for the suggestions! I've updated the relavant parts

I've updated the testing instructions with a link to a version of searchbarPageItem that displays the number of matches beside it as well, if needed

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Yup, the old algorithm pattern didn't count repeats.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes! Just a couple of follow up comments.

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Comment threadsrc/Searchbar.vue Outdated
function getTotalMatches(searchTarget, regexes) {
return regexes.reduce((total, regex) => (regex.test(searchTarget) ? total + 1 : total), 0);
// Returns the total number of matches between an array of regex patterns and string search targets.
function getTotalMatches(regexes, ...searchTargets) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if it wasn't clear before, but I was thinking of having a variable searchTargets. I don't feel that the spread operator gives us much benefit here, and makes it a little more confusing at the call site.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I'm still not so sure what you mean by "having a variable searchTargets" though;

As a guess, do you mean removing searchTarget/searchTargets as a parameter from getTotalMatches altogether, and using a variable local to primitiveData()?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking something along these lines:

function getTotalMatches(regexes, searchTargets) {
...
}
const searchTargets = [...];
const totalMatches = getTotalMatches(regexes, searchTargets);

Comment threadsrc/Searchbar.vue Outdated
}
const displayTitle = title || src;

// The total number of occurrences of all indexed words ( headings, keywords, title ) for a page

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit, but should we stick to the usual spacing conventions here for the bracket? (i.e. (headings, keywords, title))

@ang-zeyu

Copy link
Copy Markdown
Author

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Hmm, the PR's version shouldn't show the number of matches, only the template file I linked in the testing instructions, for verify the sorting algorithm. Can I confirm this?

@marvinchin

Copy link
Copy Markdown

Ah I think I misunderstood earlier that you were suggesting that we add the match counts to the production version. Yes, the number of matches don't appear in the search result in the PR version. Thanks for clarifying!

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.
This can lead to a less pleasant user experience with the searchbar.
Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.
@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch from a2e1daa to 305bc02CompareFebruary 7, 2020 06:49
@ang-zeyu

Copy link
Copy Markdown
Author

Thanks for clarifying as well!

I've updated it and removed the comments in favor of more explicit variable names

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me :)

@ang-zeyu

Copy link
Copy Markdown
Author

This looks good to me :)

Thanks a lot for reviewing this! 😄

@yamgentyamgent added this to the v2.0.1-markbind.35 milestone Feb 15, 2020
@yamgent
yamgent merged commit 400a3d6 into MarkBind:masterFeb 15, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve default search UI organization

3 participants

@ang-zeyu@marvinchin@yamgent
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Organize searchbar interface results by page by ang-zeyu · Pull Request #126 · MarkBind/vue-strap · GitHub
Skip to content
This repository was archived by the owner on Jul 12, 2020. It is now read-only.

Organize searchbar interface results by page - #126

Merged
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization
Feb 15, 2020
Merged

Organize searchbar interface results by page#126
yamgent merged 1 commit into
MarkBind:masterfrom
ang-zeyu:searchbar-ui-organization

Conversation

@ang-zeyu

@ang-zeyuang-zeyu commented Jan 31, 2020

Copy link
Copy Markdown

What is the purpose of this pull request? (put "X" next to an item, remove the rest)

• [x] Enhancement to an existing feature

ResolvesMarkBind/markbind#994
Requires MarkBind/markbind#1006

What is the rationale for this request?
Search results are not organized by page, resulting in a less pleasant user experience.

What changes did you make? (Give an overview)

  • Moved searchbarTemplate to its own seperate file for better maintainability.
  • Rewrite searchbarTemplate's template to organize results by page
  • Changed result sorting to sort first by the total number of matches in a page, then by the respective number of matches for the page's headings ( and keywords ).
  • Use the page src as a fallback title for the title, which prevents this:
    emptytitle

End result:
searchbar

Provide some example code that this change will affect:

Template of searchbarTemplate

<divv-if="item.heading" class="heading"><divclass="heading-text">{{ item.heading.text }}</div><divclass="heading-text-items"><smallv-html="highlight(item.heading.text, value)"></small><br/><smallv-for="(keyword, index) in item.keywords" :key="index"><spanv-html="highlight(keyword, value)"></span><br/></small></div></div><divv-else>
...
</div>

Is there anything you'd like reviewers to focus on?
na

Testing instructions:
The test site has a good amount of keywords / headings used to test the sorting algorithm.
This version of SearchbarPageItem displays the number of matches beside the entry, if needed

The searchbar should appear as is in the above image otherwise.

Proposed commit message: (wrap lines at 72 characters)

Organize searchbar interface results by page

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.

This can lead to a less pleasant user experience with the searchbar.

Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good change. Just a couple of comments for now!

Comment threadsrc/Searchbar.vue
.filter(searchKeyword => searchKeyword !== '')
.map(searchKeyword => searchKeyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
.map(searchKeyword => new RegExp(searchKeyword, 'i'));
.map(searchKeyword => new RegExp(searchKeyword, 'ig'));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the g flag?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Comment threadsrc/Searchbar.vue Outdated
if (isMatchingPage) {
matches.push(Object.assign(entry, { totalMatches }));
}
const fallbackTitle = title || src;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term fallback feels a little misleading here, since this variable would be used as the eventual title anyway. Would something like resultTitle be more accurate?

Comment threadsrc/Searchbar.vue Outdated
const matchesKeywords = headingKeywords[id] && headingKeywords[id].some(keyword =>
regexes.some(regex => regex.test(keyword)));
if (matchesHeading || matchesKeywords) {
searchTarget = [fallbackTitle, keywords, text, ...(headingKeywords[id] || [])].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be helpful to add some comments to explain what we're trying to do when we are changing the search target here 🙂

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a more specific variable name might help too!

Comment threadsrc/Searchbar.vue Outdated
keywords,
...Object.values(headings),
...Object.values(headingKeywords),
].join(' ');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like it would be nice to move the join(' ') part to getTotalMatches, so that we can just pass a list of search targets to the function instead of having to join it manually every time.

Comment threadsrc/SearchbarPageItem.vue Outdated
<span class="page-title" v-html="highlight(item.title, value)"></span>
<br v-if="item.keywords" />
<small v-if="item.keywords" v-html="highlight(item.keywords, value)"></small>
<hr class="page-headings-separator"/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ang-zeyu oops, I missed this just now. There seems to be an inconsistent spacing here between the class and the closing />

@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch 2 times, most recently from 163b1aa to a2e1daaCompareFebruary 5, 2020 05:23
@ang-zeyu

ang-zeyu commented Feb 5, 2020

Copy link
Copy Markdown
Author

Looks like a good change. Just a couple of comments for now!

Thanks for the suggestions! I've updated the relavant parts

I've updated the testing instructions with a link to a version of searchbarPageItem that displays the number of matches beside it as well, if needed

I guess if the aim is to find the total number of matches (rather than the total number of regexes it matches), it seems reasonable to have it. Is that the expected behaviour here?

Yup, the old algorithm pattern didn't count repeats.

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes! Just a couple of follow up comments.

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Comment threadsrc/Searchbar.vue Outdated
function getTotalMatches(searchTarget, regexes) {
return regexes.reduce((total, regex) => (regex.test(searchTarget) ? total + 1 : total), 0);
// Returns the total number of matches between an array of regex patterns and string search targets.
function getTotalMatches(regexes, ...searchTargets) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry if it wasn't clear before, but I was thinking of having a variable searchTargets. I don't feel that the spread operator gives us much benefit here, and makes it a little more confusing at the call site.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I'm still not so sure what you mean by "having a variable searchTargets" though;

As a guess, do you mean removing searchTarget/searchTargets as a parameter from getTotalMatches altogether, and using a variable local to primitiveData()?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking something along these lines:

function getTotalMatches(regexes, searchTargets) {
...
}
const searchTargets = [...];
const totalMatches = getTotalMatches(regexes, searchTargets);

Comment threadsrc/Searchbar.vue Outdated
}
const displayTitle = title || src;

// The total number of occurrences of all indexed words ( headings, keywords, title ) for a page

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit, but should we stick to the usual spacing conventions here for the bracket? (i.e. (headings, keywords, title))

@ang-zeyu

Copy link
Copy Markdown
Author

I don't think that we should show the number of matches to the reader - that doesn't seem to add much value to the search experience and might be confusing.

Hmm, the PR's version shouldn't show the number of matches, only the template file I linked in the testing instructions, for verify the sorting algorithm. Can I confirm this?

@marvinchin

Copy link
Copy Markdown

Ah I think I misunderstood earlier that you were suggesting that we add the match counts to the production version. Yes, the number of matches don't appear in the search result in the PR version. Thanks for clarifying!

Search results belonging to the same page display as individual entries,
showing the page title multiple times.
Results are also not organized by page, but by the total number of
matches in the page title, heading and keywords with the search term.
When a page title is not specified in the site config, the search result
displays an empty block of vertical space.
This can lead to a less pleasant user experience with the searchbar.
Let’s redesign the searchbar user interface, organizing results by page.
Results belonging to the same page are sorted by the number of
matches, and pages are sorted according to the total number of its
matches in the page’s headings and keywords.
Let’s use the page’s src as a fallback title if the title is absent.
@ang-zeyu
ang-zeyuforce-pushed the searchbar-ui-organization branch from a2e1daa to 305bc02CompareFebruary 7, 2020 06:49
@ang-zeyu

Copy link
Copy Markdown
Author

Thanks for clarifying as well!

I've updated it and removed the comments in favor of more explicit variable names

@marvinchinmarvinchin left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me :)

@ang-zeyu

Copy link
Copy Markdown
Author

This looks good to me :)

Thanks a lot for reviewing this! 😄

@yamgentyamgent added this to the v2.0.1-markbind.35 milestone Feb 15, 2020
@yamgent
yamgent merged commit 400a3d6 into MarkBind:masterFeb 15, 2020
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve default search UI organization

3 participants

@ang-zeyu@marvinchin@yamgent