diff options
author | elijahe <elijahe@ca.ibm.com> | 2014-06-26 14:06:50 -0400 |
---|---|---|
committer | elijahe <elijahe@ca.ibm.com> | 2014-06-26 14:06:50 -0400 |
commit | 9f651dfded5cf438631528a05c47f4a8d5cbc29e (patch) | |
tree | f82193a9202ea3f7deaa547832d6f2911ffa9bb3 | |
parent | ca33b4a1d9927a1a1a9d15f65c35d2366e3e094b (diff) | |
download | org.eclipse.orion.client-origin/searchInEditor.zip org.eclipse.orion.client-origin/searchInEditor.tar.gz org.eclipse.orion.client-origin/searchInEditor.tar.bz2 |
Bug 438076 - Replace Global Search Page (search.html) with Inline Search in Edit Page (edit.html)origin/searchInEditor
- Fixed a bunch of sidebar layout issues
- Modified shortcut of Ctrl+Shift+F command to Ctrl+Shift+R and made Ctrl+Shift+F open the inline search pane
- Added ability to remove a search result from the list and improved search result look and feel
- Replaced search pane toggle button with an always visible search input field
- Replaced "Search" string in search button with search icon
- Copied template from searchBuilder.html directly into InlineSearchPane.html (in preparation for deleting searchBuilder.html)
- Copied functionality from AdvSearchOptRenderer directly into InlineSearchPane.js (in preparation for deleting AdvSearchOptRenderer.js)
- Removed Search link from Navigation Bar
17 files changed, 608 insertions, 101 deletions
diff --git a/bundles/org.eclipse.orion.client.ui/web/css/layout.css b/bundles/org.eclipse.orion.client.ui/web/css/layout.css index 51644ef..ad6e6d9 100644 --- a/bundles/org.eclipse.orion.client.ui/web/css/layout.css +++ b/bundles/org.eclipse.orion.client.ui/web/css/layout.css @@ -306,8 +306,8 @@ hard-coded numbers elsewhere. .sidebarWrapper > .sidebar {
position: relative;
left: 0;
- top: 0;
- height: calc(100% - 30px);
+ top: 5px;
+ height: calc(100% - 70px);
overflow-x: visible;
}
diff --git a/bundles/org.eclipse.orion.client.ui/web/css/theme.css b/bundles/org.eclipse.orion.client.ui/web/css/theme.css index 8a0ffc6..016f01e 100644 --- a/bundles/org.eclipse.orion.client.ui/web/css/theme.css +++ b/bundles/org.eclipse.orion.client.ui/web/css/theme.css @@ -211,9 +211,9 @@ a.currentLocation:hover { }
.sidebarToolbar {
+ display: inline;
overflow: visible;
- padding-right: 4px;
- padding-left: 0;
+ padding: 0 !important;
}
/* Searchbox in the top navigation area seems a difficult thing to
diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/globalCommands.js b/bundles/org.eclipse.orion.client.ui/web/orion/globalCommands.js index 7c0dcee..c96d720 100644 --- a/bundles/org.eclipse.orion.client.ui/web/orion/globalCommands.js +++ b/bundles/org.eclipse.orion.client.ui/web/orion/globalCommands.js @@ -743,7 +743,7 @@ define([ }); commandRegistry.addCommand(openResourceCommand); - commandRegistry.registerCommandContribution("globalActions", "orion.openResource", 100, null, true, new KeyBinding.KeyBinding('f', true, true)); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$ + commandRegistry.registerCommandContribution("globalActions", "orion.openResource", 100, null, true, new KeyBinding.KeyBinding('r', true, true)); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$ var noBanner = false; var toggleBannerFunc = function () { if (noBanner) { diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/globalSearch/advSearchOptRenderer.js b/bundles/org.eclipse.orion.client.ui/web/orion/globalSearch/advSearchOptRenderer.js index a83e29e..20b6832 100644 --- a/bundles/org.eclipse.orion.client.ui/web/orion/globalSearch/advSearchOptRenderer.js +++ b/bundles/org.eclipse.orion.client.ui/web/orion/globalSearch/advSearchOptRenderer.js @@ -308,6 +308,18 @@ define([ document.getElementById("searchScopeSelectButton").title = messages["Choose a Folder"]; //$NON-NLS-1$ //$NON-NLS-0$ }, + setSearchScope: function(targetFolder) { + if (targetFolder && (targetFolder.Path || targetFolder.Location)) { + var location = targetFolder.Path || targetFolder.Location; + this._searchLocations = [location]; + } else { + this._searchLocations = [this._rootURL]; + } + + this._displaySelectedSearchScope(); + this._searcher.setLocationbyURL(this._searchLocations[0]); + }, + _initSearchScope: function() { var resource = mPageUtil.matchResourceParameters().resource; this._rootURL = this.fileClient.fileServiceRootURL(resource); @@ -323,23 +335,12 @@ define([ this._searchScopeSelectButton = lib.$("#searchScopeSelectButton", this._parentDiv); //$NON-NLS-0$ - var searchScopeDialogCallback = function(targetFolder) { - if (targetFolder && targetFolder.Location) { - this._searchLocations = [targetFolder.Location]; - } else { - this._searchLocations = [this._rootURL]; - } - - this._displaySelectedSearchScope(); - this._searcher.setLocationbyURL(this._searchLocations[0]); - }.bind(this); - this._searchScopeSelectButton.addEventListener("click", function(){ //$NON-NLS-0$ var searchScopeDialog = new DirectoryPrompterDialog.DirectoryPrompterDialog({ title: messages["Choose a Folder"], //$NON-NLS-0$ serviceRegistry: this._serviceRegistry, fileClient: this.fileClient, - func: searchScopeDialogCallback + func: this.setSearchScope.bind(this) }); searchScopeDialog.show(); }.bind(this)); diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/globalSearch/globalSearch.css b/bundles/org.eclipse.orion.client.ui/web/orion/globalSearch/globalSearch.css index 132e27d..3f9217f 100644 --- a/bundles/org.eclipse.orion.client.ui/web/orion/globalSearch/globalSearch.css +++ b/bundles/org.eclipse.orion.client.ui/web/orion/globalSearch/globalSearch.css @@ -22,6 +22,7 @@ .search_secondaryColumn{ color: #666666; + white-space: nowrap; } .search_report { diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/inlineSearchResultExplorer.js b/bundles/org.eclipse.orion.client.ui/web/orion/inlineSearchResultExplorer.js index 270374a..7ac2e31 100644 --- a/bundles/org.eclipse.orion.client.ui/web/orion/inlineSearchResultExplorer.js +++ b/bundles/org.eclipse.orion.client.ui/web/orion/inlineSearchResultExplorer.js @@ -112,6 +112,14 @@ function(messages, require, Deferred, lib, mContentTypes, i18nUtil, mExplorer, m this.explorer = explorer; } SearchResultRenderer.prototype = new mExplorer.SelectionRenderer(); + + // Overrides Explorer.SelectionRenderer.prototype.renderRow + SearchResultRenderer.prototype.renderRow = function(item, tableRow) { + mExplorer.SelectionRenderer.prototype.renderRow.call(this, item, tableRow); + if (item.type !== "file") { + tableRow.classList.add("searchDetailRow"); //$NON-NLS-0$ + } + }; // TODO: this should be handled outside of here in a common select all command // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=339500 @@ -339,6 +347,7 @@ function(messages, require, Deferred, lib, mContentTypes, i18nUtil, mExplorer, m var link = navigatorRenderer.createLink(null, {Location: item.parent.location, Name: name}, this.explorer._commandService, this.explorer._contentTypeService, this.explorer._openWithCommands, {id:this.getItemLinkId(item)}, params, {}); spanHolder.appendChild(link); + link.classList.add("searchDetailLink"); //$NON-NLS-0$ mNavUtils.addNavGrid(this.explorer.getNavDict(), item, link); _connect(link, "click", function() { //$NON-NLS-0$ @@ -416,11 +425,6 @@ function(messages, require, Deferred, lib, mContentTypes, i18nUtil, mExplorer, m } else { this.getExpandImage(tableRow, span); //$NON-NLS-0$ } - } else { - span = _createSpan(null, null, col, null); - col.noWrap = true; - col.align = "right"; //$NON-NLS-0$ - this.renderDetailLineNumber(item, span); } break; case 1: @@ -435,12 +439,29 @@ function(messages, require, Deferred, lib, mContentTypes, i18nUtil, mExplorer, m if (item.parentLocation) { this.renderLocationElement(item, span); } + var button = _createElement("button", ["imageSprite", "core-sprite-delete", "dismissButton", "deleteSearchRowButton"], null, col); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$ + button.title = messages["Remove from search results"]; //$NON-NLS-0$ + button.addEventListener("click", function(){ //$NON-NLS-0$ + var model = this.explorer.model; + model.removeChild(item.parent, item); + this.explorer.getNavHandler().refreshModel(this.explorer.getNavDict(), model, model.children); + this.explorer.getNavHandler().cursorOn(null, true); + tableRow.parentNode.removeChild(tableRow); + + if (item.children) { + item.children.forEach(function(child){ + var childRow = this.explorer.getRow(child); + childRow.parentNode.removeChild(childRow); + }, this); + } + + //TODO update match count, maybe... + }.bind(this)); } else { - this.renderDetailElement(item, span); - var iconSpan = _createSpan(null, this.getDetailIconId(item), span, null); - var icon = _createSpan(null, null, iconSpan, null); - icon.classList.add('imageSprite'); //$NON-NLS-0$ - icon.classList.add('core-sprite-none'); //$NON-NLS-0$ + this.renderDetailLineNumber(item, span); + span.classList.add("searchDetailLineNumber"); //$NON-NLS-0$ + + this.renderDetailElement(item, col); } break; } @@ -860,6 +881,7 @@ function(messages, require, Deferred, lib, mContentTypes, i18nUtil, mExplorer, m this.createTree(this._uiFactory ? this._uiFactory.getMatchDivID() : this.getParentDivId(), this.model, { selectionPolicy: "singleSelection", //$NON-NLS-0$ indent: 0, + setFocus: false, onCollapse: function(model) { that.onCollapse(model); } @@ -1243,6 +1265,7 @@ function(messages, require, Deferred, lib, mContentTypes, i18nUtil, mExplorer, m selectionPolicy: "singleSelection", //$NON-NLS-0$ indent: 0, getChildrenFunc: function(model) {return this.model.getFilteredChildren(model);}.bind(this), + setFocus: false, onCollapse: function(model) { that.onCollapse(model); } @@ -1278,6 +1301,7 @@ function(messages, require, Deferred, lib, mContentTypes, i18nUtil, mExplorer, m selectionPolicy: "singleSelection", //$NON-NLS-0$ getChildrenFunc: function(model) {return this.model.getFilteredChildren(model);}.bind(this), indent: 0, + setFocus: false, onCollapse: function(model) { that.onCollapse(model); } @@ -1347,7 +1371,7 @@ function(messages, require, Deferred, lib, mContentTypes, i18nUtil, mExplorer, m if(!modelToExpand){ modelToExpand = _validFiles(this.model).length > 0 ? _validFiles(this.model)[0] : null; } - this.getNavHandler().cursorOn(modelToExpand, true); + this.getNavHandler().cursorOn(modelToExpand, true, null, true); if (modelToExpand && detailIndex && detailIndex !== "none") { //$NON-NLS-0$ this.myTree.expand(modelToExpand, function() { this.onExpand(modelToExpand, detailIndex); @@ -1406,8 +1430,8 @@ function(messages, require, Deferred, lib, mContentTypes, i18nUtil, mExplorer, m //TODO: we need a better way to render the progress and allow user to be able to cancel the crawling search var crawling = searchParams.regEx || searchParams.caseSensitive; var crawler; - lib.empty(lib.node("pageNavigationActions")); //$NON-NLS-0$ - lib.empty(lib.node("pageActions")); //$NON-NLS-0$ +// lib.empty(lib.node("pageNavigationActions")); //$NON-NLS-0$ +// lib.empty(lib.node("pageActions")); //$NON-NLS-0$ lib.empty(resultsNode); diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/search/InlineSearchPane.css b/bundles/org.eclipse.orion.client.ui/web/orion/search/InlineSearchPane.css index 0e50a70..c8e8faf 100644 --- a/bundles/org.eclipse.orion.client.ui/web/orion/search/InlineSearchPane.css +++ b/bundles/org.eclipse.orion.client.ui/web/orion/search/InlineSearchPane.css @@ -4,20 +4,56 @@ @import "../widgets/input/ComboTextInput.css"; -#resultsinnerTree.treetable td { - padding: 5px !important; +.searchResultsWrapperDiv .treeTableRow > td { + padding: 3px; } -.replaceWrapper { +.searchResultsWrapperDiv > b { + margin-left: 10px; +} + +.searchWrapper { + border: 1px solid transparent; + border-bottom: none; + display: block; + position: relative; + z-index: 100; + white-space: nowrap; + width: calc(100% - 2px); +} + +.searchWrapperActive { + background: whitesmoke; + border-color: rgb(222, 222, 222); + padding-bottom: 5px; +} + +.searchWrapper > .comboTextInputWrapper { + margin: 5px 10px 0 10px; +} + +.searchWrapper > .searchDismissButton { + display: none; + float: right; + margin: 0; + padding: 4px; + position: relative; +} + +.searchWrapper.searchWrapperActive > .searchDismissButton { display: inline-block; +} + +.replaceWrapper { + display: block; max-height: 50px; /* for transition */ - overflow: hidden; + overflow: visible; transition: max-height 0.2s ease; } .replaceWrapperHidden { - display: block !important; /* removes the need to also set the width to 0 */ max-height: 0; /* for transition */ + overflow: hidden; } .fileNamePatternsTextInput { @@ -110,35 +146,28 @@ vertical-align: baseline; } -.commandButton.inlineSearchButton { - margin-right: 15px; - outline: none; - vertical-align: top; +.searchButton > span { + font-size: 14px; } -.inlineSearchButton > .core-sprite-search { - font-size: 14px; +.commandButton.comboTextInputButton.searchButton { + padding: 3px 5px 5px 5px; } -.commandButton.inlineSearchButton:focus { - background-color: rgb(221, 221, 221); - box-shadow: none; +.commandButton.comboTextInputButton.searchButton.isHidden { + padding: 3px 0 5px 0; } -.commandButton.orionButton.inlineSearchButtonActive { - background-color: whitesmoke; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; +.replaceWrapper > .comboTextInputWrapper > .comboTextInputButton { + padding: 7px 10px; } .inlineSearchWrapperDiv { background: whitesmoke; display: block; - height: calc(100% - 28px); opacity: 0; overflow: hidden; position: absolute; - top: 26px; transition: opacity 0.2s ease, overflow 0s ease 0.2s, visibility 0s ease 0.2s; visibility: hidden; width: calc(100% - 2px); /* subtract border width */ @@ -147,12 +176,24 @@ .isVisible { border: 1px solid rgb(222, 222, 222); + border-top: none; + height: calc(100% - 68px); /* subtract top and border */ opacity: 1; overflow: auto; + top: 67px; transition-delay: 0s; visibility: visible; } +.projectNavSidebarWrapper > .sidebarToolbar > .inlineSearchWrapperDiv.isVisible { + top: 38px; + height: calc(100% - 40px); +} + +.projectNavSidebarWrapper.sidebarWrapper > .sidebar { + height: calc(100% - 40px); +} + .fileNameSpan { display: inline-block; outline: none; @@ -170,4 +211,42 @@ -webkit-user-select: text; -moz-user-select: text; user-select: text; -}
\ No newline at end of file +} + +.deleteSearchRowButton { + margin-left: 10px !important; +} + +.searchDetailRow { + background: white !important; +} + +.searchDetailLineNumber { + margin-right: 4px; +} + +.navlink.searchDetailLink { + vertical-align: baseline; +} + +.searchWrapper:not(.searchWrapperActive) > .comboTextInputWrapper > .comboTextInputButton { + background-color: white; + border-color: white; +} + +.searchWrapper:not(.searchWrapperActive) > .comboTextInputWrapper > .comboTextInputButton > span { + color: #aaa; +} + +.searchWrapper > .comboTextInputWrapper > .recentEntryButton { + max-width: 25px; + transition: max-width 0.2s ease; +} + +.searchWrapper:not(.searchWrapperActive) > .comboTextInputWrapper > .recentEntryButton { + max-width: 0; +} + +.searchWrapperActive > .comboTextInputWrapper > .comboTextInputButton { + background-color: rgb(221, 221, 221); +} diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/search/InlineSearchPane.html b/bundles/org.eclipse.orion.client.ui/web/orion/search/InlineSearchPane.html index 2e4734a..ec05241 100644 --- a/bundles/org.eclipse.orion.client.ui/web/orion/search/InlineSearchPane.html +++ b/bundles/org.eclipse.orion.client.ui/web/orion/search/InlineSearchPane.html @@ -1,7 +1,36 @@ -<button class="commandButton orionButton layoutRight inlineSearchButton">
- <span class="core-sprite-search"></span>
-</button>
+<div class="searchWrapper">
+ <button class="imageSprite core-sprite-close dismissButton searchDismissButton"></button>
+ <!-- search box gets inserted here -->
+</div>
<div class="inlineSearchWrapperDiv">
- <div class="searchOptWrapperDiv"></div>
+ <div class="searchOptWrapperDiv">
+ <div class="searchMainOptionBlock">
+ <!-- search box gets inserted here -->
+ <div id="replaceWrapper" class="replaceWrapper replaceWrapperHidden">
+ <!-- replace box gets inserted here -->
+ </div>
+ <a id="toggleReplaceLink" class="toggleDisplayLink"></a>
+ </div>
+
+ <div class="searchOptionBlock">
+ <label id="advSearchCaseSensitiveLabel" class="searchCheckboxLabel" for="advSearchCaseSensitive"></label><input type="checkbox" id="advSearchCaseSensitive" class="searchCheckbox">
+ <span class="layoutRight">
+ <label id="advSearchRegExLabel" class="searchCheckboxLabel" for="advSearchRegEx"></label><input type="checkbox" id="advSearchRegEx" class="searchCheckbox">
+ </span>
+ </div>
+ <div class="searchOptionBlock">
+ <div id="fileNamePatternsLabel" class="searchLabel"></div>
+ <!-- file name patterns box gets inserted here -->
+ <span id="fileNamePatternsHint" class="fileNamePatternsHint"></span>
+
+ <div id="searchScope" class="searchScope">
+ <div id="searchScopeLabel" class="searchLabel"></div>
+ <span id="searchScopeInputWrapper" class="searchScopeInputWrapper">
+ <span id="searchScopeElementWrapper" class="searchScopeElementWrapper"></span>
+ <button id="searchScopeSelectButton" class="commandButton core-sprite-outline searchScopeSelectButton"></button>
+ </span>
+ </div>
+ </div>
+ </div>
<div class="searchResultsWrapperDiv"></div>
</div>
\ No newline at end of file diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/search/InlineSearchPane.js b/bundles/org.eclipse.orion.client.ui/web/orion/search/InlineSearchPane.js index 1280597..45ab7af 100644 --- a/bundles/org.eclipse.orion.client.ui/web/orion/search/InlineSearchPane.js +++ b/bundles/org.eclipse.orion.client.ui/web/orion/search/InlineSearchPane.js @@ -16,14 +16,21 @@ define([ 'text!orion/search/InlineSearchPane.html',
'orion/searchClient',
'orion/inlineSearchResultExplorer',
- 'orion/globalSearch/advSearchOptRenderer'
+ 'orion/EventTarget',
+ 'orion/searchUtils',
+ 'orion/Deferred',
+ 'orion/webui/dialogs/DirectoryPrompterDialog',
+ 'orion/widgets/input/ComboTextInput',
+ 'i18n!orion/search/nls/messages'
], function(
- objects, lib, InlineSearchPaneTemplate, mSearchClient, InlineSearchResultExplorer, mAdvSearchOptRenderer
+ objects, lib, InlineSearchPaneTemplate, mSearchClient, InlineSearchResultExplorer,
+ EventTarget, mSearchUtils, Deferred, DirectoryPrompterDialog, ComboTextInput, messages
) {
/**
* @param {DOMNode} options.parentNode
*/
function InlineSearchPane(options) {
+ EventTarget.attach(this);
this._parentNode = options.parentNode;
this._serviceRegistry = options.serviceRegistry;
this._commandRegistry = options.commandRegistry;
@@ -38,25 +45,16 @@ define([ var domNodeFragment = range.createContextualFragment(InlineSearchPaneTemplate);
this._parentNode.appendChild(domNodeFragment);
+ this._searchWrapper = lib.$(".searchWrapper", this._parentNode); //$NON-NLS-0$
this._wrapperDiv = lib.$(".inlineSearchWrapperDiv", this._parentNode); //$NON-NLS-0$
- this._displayButton = lib.$(".inlineSearchButton", this._parentNode); //$NON-NLS-0$
-
- var focusOnTextInput = function(){
- this._searchOptRenderer.getSearchTextInputBox().focus();
+ this._focusOnTextInput = function(){
+ this._searchTextInputBox.focus();
}.bind(this);
- this._displayButton.addEventListener("click", function(){ //$NON-NLS-0$
- if (this._wrapperDiv.classList.contains("isVisible")) { //$NON-NLS-0$
- // hide
- this._wrapperDiv.classList.remove("isVisible"); //$NON-NLS-0$
- this._displayButton.classList.remove("inlineSearchButtonActive"); //$NON-NLS-0$
- } else {
- // show
- this._wrapperDiv.classList.add("isVisible"); //$NON-NLS-0$
- this._displayButton.classList.add("inlineSearchButtonActive"); //$NON-NLS-0$
- window.setTimeout(focusOnTextInput, 100);
- }
+ this._dismissButton = lib.$(".dismissButton", this._parentNode); //$NON-NLS-0$
+ this._dismissButton.addEventListener("click", function(){ //$NON-NLS-0$
+ this.hide();
}.bind(this));
this._searchOptWrapperDiv = lib.$(".searchOptWrapperDiv", this._wrapperDiv); //$NON-NLS-0$
@@ -64,15 +62,360 @@ define([ this._searchResultsWrapperDiv.id = "inlineSearchResultsWrapper";
- var searcher = new mSearchClient.Searcher({serviceRegistry: this._serviceRegistry, commandService: this._commandRegistry, fileService: this._fileClient});
- this._searchOptRenderer = new mAdvSearchOptRenderer.AdvSearchOptRenderer(this._searchOptWrapperDiv, searcher, this._serviceRegistry);
- var searchResultsExplorer = new InlineSearchResultExplorer(this._serviceRegistry, this._commandRegistry);
-
- this._searchOptRenderer.setResultInfo(searchResultsExplorer, this._searchResultsWrapperDiv); //$NON-NLS-0$
+ this._searcher = new mSearchClient.Searcher({serviceRegistry: this._serviceRegistry, commandService: this._commandRegistry, fileService: this._fileClient});
+ this._searchResultExplorer = new InlineSearchResultExplorer(this._serviceRegistry, this._commandRegistry);
+ this._render();
},
isVisible: function() {
return this._wrapperDiv.classList.contains("isVisible"); //$NON-NLS-0$
+ },
+
+ show: function() {
+ this._previousActiveElement = document.activeElement;
+
+ this._searchWrapper.classList.add("searchWrapperActive"); //$NON-NLS-0$
+ this._wrapperDiv.classList.add("isVisible"); //$NON-NLS-0$
+ window.setTimeout(this._focusOnTextInput, 100);
+
+ this.dispatchEvent({type: "open"});
+ },
+
+ hide: function() {
+ this._searchWrapper.classList.remove("searchWrapperActive"); //$NON-NLS-0$
+ this._wrapperDiv.classList.remove("isVisible"); //$NON-NLS-0$
+
+ if (!this._replaceBoxIsHidden()) {
+ this._hideReplaceField();
+ }
+
+ this._previousActiveElement = null;
+ },
+
+ getOptions: function(){
+ var resource = ""; //$NON-NLS-0$
+ this._searchLocations.forEach(function(searchLocation){
+ if (resource) {
+ resource = resource.concat(","); //$NON-NLS-0$
+ }
+ resource = resource.concat(searchLocation);
+ }, this);
+
+ var fileNamePatternsArray = mSearchUtils.getFileNamePatternsArray(this._fileNamePatternsBox.getTextInputValue());
+ var replaceValue = this._replaceBox.getTextInputValue() || undefined;
+
+ return {keyword: this._searchBox.getTextInputValue(),
+ rows: 10000,
+ start: 0,
+ replace: replaceValue,
+ caseSensitive: this._caseSensitiveCB.checked,
+ regEx: this._regExCB.checked,
+ fileNamePatterns: fileNamePatternsArray,
+ resource: resource
+ };
+ },
+
+ _render: function(){
+ this._initHTMLLabels();
+ this._initControls();
+ },
+
+ _submitSearch: function(){
+ var options = this.getOptions();
+ options.replace = null;
+ if(options.keyword){
+ this._searchBox.addTextInputValueToRecentEntries();
+ this._fileNamePatternsBox.addTextInputValueToRecentEntries();
+ var searchParams = mSearchUtils.getSearchParams(this._searcher, options.keyword, options);
+ this._searchResultExplorer.runSearch(searchParams, this._searchResultsWrapperDiv, this._searcher);
+ }
+ },
+
+ _replacePreview: function(){
+ var options = this.getOptions();
+ if(!options.replace){
+ options.replace = "";
+ }
+ if(options.keyword){
+ this._searchBox.addTextInputValueToRecentEntries();
+ this._replaceBox.addTextInputValueToRecentEntries();
+ this._fileNamePatternsBox.addTextInputValueToRecentEntries();
+ var searchParams = mSearchUtils.getSearchParams(this._searcher, options.keyword, options);
+ this._searchResultExplorer.runSearch(searchParams, this._searchResultsWrapperDiv, this._searcher);
+ }
+ },
+
+ _initSearchBox: function(){
+ //Optional. Reading extended search proposals by asking plugins, if any.
+ //If there are multiple plugins then merge all the proposals and call uiCallBack.
+ //Plugins(with service id "orion.search.proposal") should define the property "filterForMe" to true or false. Which means:
+ //If true the inputCompletion class will filter the proposals returned by the plugin.
+ //If false the inputCompletion class assumes that the proposals are already filtered by hte given kerword.
+ //The false case happens when a plugin wants to use the keyword to ask for a set of filtered proposal from a web service by the keyword and Orion does not need to filter it again.
+ var exendedProposalProvider = function(keyWord, uiCallback){
+ var serviceReferences = this._serviceRegistry.getServiceReferences("orion.search.proposal"); //$NON-NLS-0$
+ if(!serviceReferences || serviceReferences.length === 0){
+ uiCallback(null);
+ return;
+ }
+ var promises = [];
+ var renderer = this;
+ serviceReferences.forEach(function(serviceRef) {
+ var filterForMe = serviceRef.getProperty("filterForMe"); //$NON-NLS-0$
+ promises.push( this._serviceRegistry.getService(serviceRef).run(keyWord).then(function(returnValue) {
+ //The return value has to be an array of {category : string, datalist: [string,string,string...]}
+ var proposalList = {filterForMe: filterForMe, proposals: []};
+ for (var i = 0; i < returnValue.length; i++) {
+ proposalList.proposals.push({type: "category", label: returnValue[i].category});//$NON-NLS-0$
+ for (var j = 0; j < returnValue[i].datalist.length; j++) {
+ proposalList.proposals.push({type: "proposal", label: returnValue[i].datalist[j], value: returnValue[i].datalist[j]});//$NON-NLS-0$
+ }
+ }
+ return proposalList;
+ }));
+ }.bind(renderer));
+ Deferred.all(promises).then(function(returnValues) {
+ //Render UI
+ uiCallback(returnValues);
+ });
+ }.bind(this);
+
+ var searchBoxParentNode = lib.$(".searchWrapper", this._parentNode);
+
+ var searchButtonListener = function() {
+ if (!this.isVisible()) {
+ this.show();
+ }
+ this._submitSearch();
+ }.bind(this);
+
+ this._searchBox = new ComboTextInput({
+ id: "advSearchInput", //$NON-NLS-0$
+ parentNode: searchBoxParentNode,
+ hasButton: true,
+ buttonClickListener: searchButtonListener,
+ hasInputCompletion: true,
+ serviceRegistry: this._serviceRegistry,
+ extendedRecentEntryProposalProvider: exendedProposalProvider
+ });
+
+ var searchButtonSpan = document.createElement("span"); //$NON-NLS-0$
+ searchButtonSpan.classList.add("core-sprite-search"); //$NON-NLS-0$
+
+ this._searchButton = this._searchBox.getButton();
+ this._searchButton.classList.add("searchButton"); //$NON-NLS-0$
+ this._searchButton.appendChild(searchButtonSpan);
+
+ this._searchTextInputBox = this._searchBox.getTextInputNode();
+ this._searchTextInputBox.placeholder = messages["Type a search term"]; //$NON-NLS-1$ //$NON-NLS-0$
+
+ this._searchBox.setRecentEntryButtonTitle(messages["Show previous search terms"]); //$NON-NLS-0$
+
+ this._searchTextInputBox.addEventListener("keydown", function(e) { //$NON-NLS-0$
+ if(e.defaultPrevented){// If the key event was handled by other listeners and preventDefault was set on(e.g. input completion handled ENTER), we do not handle it here
+ return;
+ }
+ var keyCode= e.charCode || e.keyCode;
+ if (keyCode === lib.KEY.ENTER) {
+ this._submitSearch();
+ } else if (keyCode === lib.KEY.ESCAPE) {
+ if (this._previousActiveElement) {
+ if (this._previousActiveElement === this._searchTextInputBox) {
+ this._searchTextInputBox.blur();
+ } else {
+ this._previousActiveElement.focus();
+ }
+
+ this.hide();
+ }
+ }
+ }.bind(this));
+
+ this._searchTextInputBox.addEventListener("focus", function(){
+ this.show();
+ }.bind(this));
+ },
+
+ _initReplaceBox: function() {
+ this._replaceWrapper = document.getElementById("replaceWrapper"); //$NON-NLS-0$
+
+ this._replaceBox = new ComboTextInput({
+ id: "advReplaceInput", //$NON-NLS-0$
+ parentNode: this._replaceWrapper,
+ hasButton: true,
+ buttonText: messages["Replace..."], //$NON-NLS-0$
+ buttonClickListener: this._replacePreview.bind(this),
+ hasInputCompletion: true,
+ serviceRegistry: this._serviceRegistry,
+ });
+
+ this._replaceTextInputBox = this._replaceBox.getTextInputNode();
+ this._replaceTextInputBox.placeholder = messages["Replace With"]; //$NON-NLS-0$
+
+ this._replaceButton = this._replaceBox.getButton();
+ this._replaceButton.title = messages["Show replacement preview"]; //$NON-NLS-0$
+
+ this._replaceBox.setRecentEntryButtonTitle(messages["Show previous replace terms"]); //$NON-NLS-0$
+
+ this._replaceTextInputBox.addEventListener("keydown", function(e) { //$NON-NLS-0$
+ var keyCode= e.charCode || e.keyCode;
+ if (keyCode === lib.KEY.ENTER) {
+ this._replacePreview();
+ }
+ }.bind(this));
+ },
+
+ _initFileNamePatternsBox: function() {
+ this._fileNamePatternsHint = document.getElementById("fileNamePatternsHint"); //$NON-NLS-0$
+
+ this._fileNamePatternsBox = new ComboTextInput({
+ id: "fileNamePatternsInput", //$NON-NLS-0$
+ insertBeforeNode: this._fileNamePatternsHint,
+ parentNode: this._fileNamePatternsHint.parentNode,
+ hasButton: false,
+ hasInputCompletion: true,
+ serviceRegistry: this._serviceRegistry
+ });
+
+ this._fileNamePatternsBox.getDomNode().classList.add("fileNamePatternsInput"); //$NON-NLS-0$
+
+ this._fileNamePatternsTextInput = this._fileNamePatternsBox.getTextInputNode();
+ this._fileNamePatternsTextInput.classList.add("fileNamePatternsTextInput"); //$NON-NLS-0$
+ this._fileNamePatternsTextInput.placeholder = "*.*"; //$NON-NLS-0$
+ lib.empty(this._fileNamePatternsHint);
+ this._fileNamePatternsHint.appendChild(document.createTextNode(messages["(* = any string, ? = any character)"])); //$NON-NLS-0$
+
+ this._fileNamePatternsTextInput.addEventListener("focus", function(){ //$NON-NLS-0$
+ this._fileNamePatternsHint.classList.add("fileNamePatternsHintVisible"); //$NON-NLS-0$
+ }.bind(this));
+
+ this._fileNamePatternsTextInput.addEventListener("blur", function(){ //$NON-NLS-0$
+ var inputValue = this._fileNamePatternsBox.getTextInputValue();
+ if (inputValue) {
+ var correctedPatternArray = mSearchUtils.getFileNamePatternsArray(inputValue);
+ this._fileNamePatternsBox.setTextInputValue(correctedPatternArray.join(", ")); //$NON-NLS-0$
+ }
+ this._fileNamePatternsHint.classList.remove("fileNamePatternsHintVisible"); //$NON-NLS-0$
+ }.bind(this));
+ },
+
+ _initControls: function(){
+ this._initSearchBox();
+ this._initReplaceBox();
+ this._initFileNamePatternsBox();
+
+ this._caseSensitiveCB = document.getElementById("advSearchCaseSensitive"); //$NON-NLS-0$
+ this._regExCB = document.getElementById("advSearchRegEx"); //$NON-NLS-0$
+ this._toggleReplaceLink = document.getElementById("toggleReplaceLink"); //$NON-NLS-0$
+
+ if (this._replaceBoxIsHidden()) {
+ this._toggleReplaceLink.innerHTML = messages["Show Replace"]; //$NON-NLS-0$
+ }
+ this._toggleReplaceLink.addEventListener("click", this._toggleReplaceFieldVisibility.bind(this)); //$NON-NLS-0$
+
+ this._initSearchScope();
+ },
+
+ _initHTMLLabels: function(){
+ document.getElementById("advSearchCaseSensitiveLabel").appendChild(document.createTextNode(messages["Case sensitive"])); //$NON-NLS-1$ //$NON-NLS-0$
+ document.getElementById("advSearchRegExLabel").appendChild(document.createTextNode(messages["Regular expression"])); //$NON-NLS-1$ //$NON-NLS-0$
+ document.getElementById("searchScopeLabel").appendChild(document.createTextNode(messages["Scope"])); //$NON-NLS-1$ //$NON-NLS-0$
+ document.getElementById("fileNamePatternsLabel").appendChild(document.createTextNode(messages["File name patterns (comma-separated)"])); //$NON-NLS-1$ //$NON-NLS-0$
+ document.getElementById("searchScopeSelectButton").title = messages["Choose a Folder"]; //$NON-NLS-1$ //$NON-NLS-0$
+ },
+
+ setSearchScope: function(targetFolder) {
+ if (targetFolder && (targetFolder.Path || targetFolder.Location)) {
+ var location = targetFolder.Path || targetFolder.Location;
+ this._searchLocations = [location];
+ } else {
+ this._searchLocations = [this._rootURL];
+ }
+
+ if (targetFolder.Location) {
+ this._searcher.setLocationByMetaData(targetFolder);
+ } else {
+ this._searcher.setLocationbyURL(this._searchLocations[0]);
+ }
+
+ this._displaySelectedSearchScope();
+ },
+
+ _initSearchScope: function() {
+ this._rootURL = this._fileClient.fileServiceRootURL();
+ this._searchLocations = [this._rootURL];
+
+ this._searchScopeElementWrapper = lib.$("#searchScopeElementWrapper", this._searchOptWrapperDiv); //$NON-NLS-0$
+ this._searchScopeSelectButton = lib.$("#searchScopeSelectButton", this._searchOptWrapperDiv); //$NON-NLS-0$
+
+ this._searchScopeSelectButton.addEventListener("click", function(){ //$NON-NLS-0$
+ var searchScopeDialog = new DirectoryPrompterDialog.DirectoryPrompterDialog({
+ title: messages["Choose a Folder"], //$NON-NLS-0$
+ serviceRegistry: this._serviceRegistry,
+ fileClient: this._fileClient,
+ func: this.setSearchScope.bind(this)
+ });
+ searchScopeDialog.show();
+ }.bind(this));
+ },
+
+ _replaceBoxIsHidden: function() {
+ return this._replaceWrapper.classList.contains("replaceWrapperHidden"); //$NON-NLS-0$
+ },
+
+ _toggleReplaceFieldVisibility: function () {
+ if (this._replaceBoxIsHidden()) {
+ this._showReplaceField();
+ } else {
+ this._hideReplaceField();
+ }
+ },
+
+ _showReplaceField: function() {
+ this._searchBox.hideButton();
+ this._replaceWrapper.classList.remove("replaceWrapperHidden"); //$NON-NLS-0$
+ this._toggleReplaceLink.innerHTML = messages["Hide Replace"]; //$NON-NLS-0$
+ },
+
+ _hideReplaceField: function() {
+ this._searchBox.showButton();
+ this._replaceWrapper.classList.add("replaceWrapperHidden"); //$NON-NLS-0$
+ this._toggleReplaceLink.innerHTML = messages["Show Replace"]; //$NON-NLS-0$
+ },
+
+ _displaySelectedSearchScope: function() {
+ var scopeElementWrapper = this._searchScopeElementWrapper;
+ lib.empty(scopeElementWrapper);
+
+ this._searchLocations.forEach(function(searchLocation){
+ var decodedLocation = decodeURI(searchLocation);
+ var scopeString = decodedLocation;
+ var rootName = this._fileClient.fileServiceRootURL(scopeString);
+ if (rootName === searchLocation) {
+ //replace location string with file system name
+ scopeString = this._fileClient.fileServiceName(scopeString);
+ } else {
+ //set scopeString to resource name
+ var segments = scopeString.split("/");
+ if (segments) {
+ scopeString = segments.pop();
+ if (!scopeString) {
+ // scopeString ended with '/', last element in array returned by
+ // split() was empty, pop again to get the name
+ scopeString = segments.pop();
+ }
+ }
+ }
+
+ var locationElement = document.createElement("span"); //$NON-NLS-0$
+ locationElement.classList.add("searchScopeElement"); //$NON-NLS-0$
+
+ locationElement.title = decodedLocation;
+ scopeElementWrapper.title = decodedLocation;
+
+ locationElement.appendChild(document.createTextNode(scopeString));
+ scopeElementWrapper.appendChild(locationElement);
+ }, this);
}
});
diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/search/nls/root/messages.js b/bundles/org.eclipse.orion.client.ui/web/orion/search/nls/root/messages.js index a305eac..9851ec2 100644 --- a/bundles/org.eclipse.orion.client.ui/web/orion/search/nls/root/messages.js +++ b/bundles/org.eclipse.orion.client.ui/web/orion/search/nls/root/messages.js @@ -102,5 +102,6 @@ define({ "Show replacement preview": "Show replacement preview", "File name patterns (comma-separated)": "File name patterns (comma-separated)", "(* = any string, ? = any character)": "(* = any string, ? = any character)", - "Choose a Folder": "Choose a Folder" + "Choose a Folder": "Choose a Folder", + "Remove from search results": "Remove from search results" }); diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/searchModel.js b/bundles/org.eclipse.orion.client.ui/web/orion/searchModel.js index cee1ebb..b674229 100644 --- a/bundles/org.eclipse.orion.client.ui/web/orion/searchModel.js +++ b/bundles/org.eclipse.orion.client.ui/web/orion/searchModel.js @@ -543,6 +543,14 @@ function(messages, require, Deferred, i18nUtil, mExplorer, mSearchUtils) { } return matchesReplaced; }; + + SearchResultModel.prototype.removeChild = function(model, item) { + var index = model.children.indexOf(item); + if (-1 < index) { + model.children.splice(index, 1); + item.stale = true; + } + }; SearchResultModel.prototype.constructor = SearchResultModel; diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/widgets/filesystem/filesystemSwitcher.js b/bundles/org.eclipse.orion.client.ui/web/orion/widgets/filesystem/filesystemSwitcher.js index 479b52c..000613e 100644 --- a/bundles/org.eclipse.orion.client.ui/web/orion/widgets/filesystem/filesystemSwitcher.js +++ b/bundles/org.eclipse.orion.client.ui/web/orion/widgets/filesystem/filesystemSwitcher.js @@ -37,6 +37,7 @@ define([ this.filesystemChangeDispatcher = params.filesystemChangeDispatcher; this.fileClient = params.fileClient; this.node = params.node; + this._insertBeforeNode = params.insertBeforeNode; this.serviceRegistry = params.serviceRegistry; var _self = this; this.listener = function(event) { @@ -102,7 +103,11 @@ define([ wrapper.appendChild(this.fsName); wrapper.appendChild(this.menu); - this.node.appendChild(wrapper); + if (this._insertBeforeNode) { + this.node.insertBefore(wrapper, this._insertBeforeNode); + } else { + this.node.appendChild(wrapper); + } this.registerCommands(); diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/widgets/input/ComboTextInput.css b/bundles/org.eclipse.orion.client.ui/web/orion/widgets/input/ComboTextInput.css index 99c079d..b2311a3 100644 --- a/bundles/org.eclipse.orion.client.ui/web/orion/widgets/input/ComboTextInput.css +++ b/bundles/org.eclipse.orion.client.ui/web/orion/widgets/input/ComboTextInput.css @@ -58,7 +58,7 @@ border: none;
vertical-align: middle;
border-left: 1px solid lightgray;
- border-radius: 0 3px 3px 0;
+ border-radius: 0 2px 2px 0;
font-size: 12px;
transition: all 0.1s ease;
max-width: 150px; /* for transition */
diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/widgets/nav/common-nav.js b/bundles/org.eclipse.orion.client.ui/web/orion/widgets/nav/common-nav.js index 0c57c2e..48e428d 100644 --- a/bundles/org.eclipse.orion.client.ui/web/orion/widgets/nav/common-nav.js +++ b/bundles/org.eclipse.orion.client.ui/web/orion/widgets/nav/common-nav.js @@ -26,11 +26,12 @@ define([ 'orion/URITemplate', 'orion/PageUtil', 'orion/webui/contextmenu', - 'orion/search/InlineSearchPane' + 'orion/search/InlineSearchPane', + 'orion/commands' ], function( messages, objects, lib, mExplorer, mNavigatorRenderer, mExplorerNavHandler, mKeyBinding, FileCommands, ProjectCommands, ExtensionCommands, mGlobalCommands, Selection, URITemplate, PageUtil, - mContextMenu, InlineSearchPane + mContextMenu, InlineSearchPane, mCommands ) { var FileExplorer = mExplorer.FileExplorer; var KeyBinding = mKeyBinding.KeyBinding; @@ -461,9 +462,23 @@ define([ fileClient: this.fileClient }); + // set the scope to the target folder that is selected in the navigator pane + this._inlineSearchPane.addEventListener("open", function(){ + var selectionService = this.selection; + var selections = selectionService.getSelections(); + if (selections && (1 === selections.length)) { + if (selections[0]) { + var targetFolder = selections[0].Directory ? selections[0] : selections[0].parent; + this._inlineSearchPane.setSearchScope(targetFolder); + } + } else { + // no selection or multiple selections, set the scope to the root + this._inlineSearchPane.setSearchScope(this.treeRoot); + } + }.bind(this)); + this.addEventListener("rootChanged", function(event) { //$NON-NLS-0$ - //TODO change scope in search builder -// _self.sidebarNavInputManager.dispatchEvent({type: "InputChanged", input: event.root.ChildrenLocation}); //$NON-NLS-0$ + this._inlineSearchPane.setSearchScope(event.root); }.bind(this)); this.toolbarNode.parentNode.addEventListener("scroll", function(){ @@ -471,6 +486,17 @@ define([ this.toolbarNode.parentNode.scrollTop = 0; } }.bind(this)); + + var openSearchCommand = new mCommands.Command({ + name: "open inline search pane", + id: "orion.openInlineSearchPane", //$NON-NLS-0$ + callback: function (data) { + this._inlineSearchPane.show(); + }.bind(this) + }); + + this.commandRegistry.addCommand(openSearchCommand); + this.commandRegistry.registerCommandContribution(this.additionalActionsScope, "orion.openInlineSearchPane", 100, null, true, new KeyBinding('f', true, true)); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$ } }); diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/widgets/nav/mini-nav.js b/bundles/org.eclipse.orion.client.ui/web/orion/widgets/nav/mini-nav.js index 9f43e9c..7aca98d 100644 --- a/bundles/org.eclipse.orion.client.ui/web/orion/widgets/nav/mini-nav.js +++ b/bundles/org.eclipse.orion.client.ui/web/orion/widgets/nav/mini-nav.js @@ -116,6 +116,8 @@ define([ serviceRegistry: this.serviceRegistry, toolbarNode: this.toolbarNode }); + + var searchWrapper = lib.$(".searchWrapper", this.toolbarNode); // Create switcher here this.fsSwitcher = new mFilesystemSwitcher.FilesystemSwitcher({ @@ -124,6 +126,7 @@ define([ filesystemChangeDispatcher: this.explorer.sidebarNavInputManager, fileClient: this.fileClient, node: this.toolbarNode, + insertBeforeNode: searchWrapper, serviceRegistry: this.serviceRegistry }); diff --git a/bundles/org.eclipse.orion.client.ui/web/orion/widgets/nav/project-nav.js b/bundles/org.eclipse.orion.client.ui/web/orion/widgets/nav/project-nav.js index b63c34a..e38376f 100644 --- a/bundles/org.eclipse.orion.client.ui/web/orion/widgets/nav/project-nav.js +++ b/bundles/org.eclipse.orion.client.ui/web/orion/widgets/nav/project-nav.js @@ -454,14 +454,16 @@ define([ toolbarNode: this.toolbarNode }); this.explorer.display(this.project); - this.sidebar.hideToolbar(); + //TODO do this in a less hackish way + this.toolbarNode.parentNode.classList.add("projectNavSidebarWrapper"); //$NON-NLS-0$ }, destroy: function() { if (this.explorer) { this.explorer.destroy(); } this.explorer = null; - this.sidebar.showToolbar(); + //TODO do this in a less hackish way + this.toolbarNode.parentNode.classList.remove("projectNavSidebarWrapper"); //$NON-NLS-0$ }, getProjectJson: function(metadata) { function getJson(children) { diff --git a/bundles/org.eclipse.orion.client.ui/web/plugins/pageLinksPlugin.js b/bundles/org.eclipse.orion.client.ui/web/plugins/pageLinksPlugin.js index f669b8c..14629b6 100644 --- a/bundles/org.eclipse.orion.client.ui/web/plugins/pageLinksPlugin.js +++ b/bundles/org.eclipse.orion.client.ui/web/plugins/pageLinksPlugin.js @@ -35,13 +35,6 @@ define([ order: 10 }); provider.registerService("orion.page.link.category", null, { - id: "search", - nameKey: "Search", - nls: "orion/nls/messages", - imageClass: "core-sprite-search", - order: 30 - }); - provider.registerService("orion.page.link.category", null, { id: "shell", nameKey: "Shell", nls: "orion/nls/messages", @@ -74,14 +67,6 @@ define([ order: 1000, // low priority uriTemplate: "{+OrionHome}/shell/shellPage.html" }); - provider.registerService("orion.page.link", serviceImpl, { - nameKey: "Search", - id: "orion.Search", - nls: "orion/nls/messages", - category: "search", - order: 1000, // low priority - uriTemplate: "{+OrionHome}/search/search.html", - }); provider.registerService("orion.page.link", null, { nameKey: "Settings", |