SearchResultsPane.js 5.9 KB

123456789101112131415161718192021222324
  1. export default class SearchResultsPane extends UI.VBox{constructor(searchConfig){super(true);this._searchConfig=searchConfig;this._searchResults=[];this._treeOutline=new UI.TreeOutlineInShadow();this._treeOutline.hideOverflow();this._treeOutline.registerRequiredCSS('search/searchResultsPane.css');this.contentElement.appendChild(this._treeOutline.element);this._matchesExpandedCount=0;}
  2. addSearchResult(searchResult){this._searchResults.push(searchResult);this._addTreeElement(searchResult);}
  3. _addTreeElement(searchResult){const treeElement=new Search.SearchResultsPane.SearchResultsTreeElement(this._searchConfig,searchResult);this._treeOutline.appendChild(treeElement);if(!this._treeOutline.selectedTreeElement){treeElement.select(true,true);}
  4. if(this._matchesExpandedCount<Search.SearchResultsPane._matchesExpandedByDefault){treeElement.expand();}
  5. this._matchesExpandedCount+=searchResult.matchesCount();}}
  6. export const _matchesExpandedByDefault=20;export const _matchesShownAtOnce=20;export class SearchResultsTreeElement extends UI.TreeElement{constructor(searchConfig,searchResult){super('',true);this._searchConfig=searchConfig;this._searchResult=searchResult;this._initialized=false;this.toggleOnClick=true;}
  7. onexpand(){if(this._initialized){return;}
  8. this._updateMatchesUI();this._initialized=true;}
  9. _updateMatchesUI(){this.removeChildren();const toIndex=Math.min(this._searchResult.matchesCount(),Search.SearchResultsPane._matchesShownAtOnce);if(toIndex<this._searchResult.matchesCount()){this._appendSearchMatches(0,toIndex-1);this._appendShowMoreMatchesElement(toIndex-1);}else{this._appendSearchMatches(0,toIndex);}}
  10. onattach(){this._updateSearchMatches();}
  11. _updateSearchMatches(){this.listItemElement.classList.add('search-result');const fileNameSpan=span(this._searchResult.label(),'search-result-file-name');fileNameSpan.appendChild(span('\u2014','search-result-dash'));fileNameSpan.appendChild(span(this._searchResult.description(),'search-result-qualifier'));this.tooltip=this._searchResult.description();this.listItemElement.appendChild(fileNameSpan);const matchesCountSpan=createElement('span');matchesCountSpan.className='search-result-matches-count';matchesCountSpan.textContent=`${this._searchResult.matchesCount()}`;UI.ARIAUtils.setAccessibleName(matchesCountSpan,ls`Matches Count ${this._searchResult.matchesCount()}`);this.listItemElement.appendChild(matchesCountSpan);if(this.expanded){this._updateMatchesUI();}
  12. function span(text,className){const span=createElement('span');span.className=className;span.textContent=text;return span;}}
  13. _appendSearchMatches(fromIndex,toIndex){const searchResult=this._searchResult;const queries=this._searchConfig.queries();const regexes=[];for(let i=0;i<queries.length;++i){regexes.push(createSearchRegex(queries[i],!this._searchConfig.ignoreCase(),this._searchConfig.isRegex()));}
  14. for(let i=fromIndex;i<toIndex;++i){const lineContent=searchResult.matchLineContent(i).trim();let matchRanges=[];for(let j=0;j<regexes.length;++j){matchRanges=matchRanges.concat(this._regexMatchRanges(lineContent,regexes[j]));}
  15. const anchor=Components.Linkifier.linkifyRevealable(searchResult.matchRevealable(i),'');anchor.classList.add('search-match-link');const labelSpan=createElement('span');labelSpan.classList.add('search-match-line-number');const resultLabel=searchResult.matchLabel(i);labelSpan.textContent=resultLabel;if(typeof resultLabel==='number'&&!isNaN(resultLabel)){UI.ARIAUtils.setAccessibleName(labelSpan,ls`Line ${resultLabel}`);}else{UI.ARIAUtils.setAccessibleName(labelSpan,ls`${resultLabel}`);}
  16. anchor.appendChild(labelSpan);const contentSpan=this._createContentSpan(lineContent,matchRanges);anchor.appendChild(contentSpan);const searchMatchElement=new UI.TreeElement();this.appendChild(searchMatchElement);searchMatchElement.listItemElement.className='search-match';searchMatchElement.listItemElement.appendChild(anchor);searchMatchElement.listItemElement.addEventListener('keydown',event=>{if(isEnterKey(event)){event.consume(true);Common.Revealer.reveal(searchResult.matchRevealable(i));}});searchMatchElement.tooltip=lineContent;}}
  17. _appendShowMoreMatchesElement(startMatchIndex){const matchesLeftCount=this._searchResult.matchesCount()-startMatchIndex;const showMoreMatchesText=Common.UIString('Show %d more',matchesLeftCount);const showMoreMatchesTreeElement=new UI.TreeElement(showMoreMatchesText);this.appendChild(showMoreMatchesTreeElement);showMoreMatchesTreeElement.listItemElement.classList.add('show-more-matches');showMoreMatchesTreeElement.onselect=this._showMoreMatchesElementSelected.bind(this,showMoreMatchesTreeElement,startMatchIndex);}
  18. _createContentSpan(lineContent,matchRanges){let trimBy=0;if(matchRanges.length>0&&matchRanges[0].offset>20){trimBy=15;}
  19. lineContent=lineContent.substring(trimBy,1000+trimBy);if(trimBy){matchRanges=matchRanges.map(range=>new TextUtils.SourceRange(range.offset-trimBy+1,range.length));lineContent='\u2026'+lineContent;}
  20. const contentSpan=createElement('span');contentSpan.className='search-match-content';contentSpan.textContent=lineContent;UI.ARIAUtils.setAccessibleName(contentSpan,`${lineContent} line`);UI.highlightRangesWithStyleClass(contentSpan,matchRanges,'highlighted-match');return contentSpan;}
  21. _regexMatchRanges(lineContent,regex){regex.lastIndex=0;let match;const matchRanges=[];while((regex.lastIndex<lineContent.length)&&(match=regex.exec(lineContent))){matchRanges.push(new TextUtils.SourceRange(match.index,match[0].length));}
  22. return matchRanges;}
  23. _showMoreMatchesElementSelected(showMoreMatchesTreeElement,startMatchIndex){this.removeChild(showMoreMatchesTreeElement);this._appendSearchMatches(startMatchIndex,this._searchResult.matchesCount());return false;}}
  24. self.Search=self.Search||{};Search=Search||{};Search.SearchResultsPane=SearchResultsPane;Search.SearchResultsPane._matchesExpandedByDefault=_matchesExpandedByDefault;Search.SearchResultsPane._matchesShownAtOnce=_matchesShownAtOnce;Search.SearchResultsPane.SearchResultsTreeElement=SearchResultsTreeElement;