@@ -84,6 +84,9 @@ define(function (require, exports, module) {
8484 */
8585 var searchResults = { } ;
8686
87+ /** @type {Array.<string> } Keeps a copy of the searched files sorted by name and with the selected file first */
88+ var searchFiles = [ ] ;
89+
8790 /** @type {Panel } Bottom panel holding the search results. Initialized in htmlReady() */
8891 var searchResultsPanel ;
8992
@@ -158,6 +161,7 @@ define(function (require, exports, module) {
158161 * @private
159162 * Returns label text to indicate the search scope. Already HTML-escaped.
160163 * @param {?Entry } scope
164+ * @return {string }
161165 */
162166 function _labelForScope ( scope ) {
163167 var projName = ProjectManager . getProjectRoot ( ) . name ;
@@ -236,7 +240,7 @@ define(function (require, exports, module) {
236240 * @param {string } fullPath
237241 * @param {string } contents
238242 * @param {RegExp } queryExpr
239- * @return {boolean } True iff matches were added to the search results
243+ * @return {boolean } True iff the matches were added to the search results
240244 */
241245 function _addSearchMatches ( fullPath , contents , queryExpr ) {
242246 var matches = _getSearchMatches ( contents , queryExpr ) ;
@@ -253,7 +257,48 @@ define(function (require, exports, module) {
253257
254258 /**
255259 * @private
256- * Count the total number of matches and files
260+ * Sorts the file keys to show the results from the selected file first and the rest sorted by path
261+ */
262+ function _sortResultFiles ( ) {
263+ var selectedEntry = ProjectManager . getSelectedItem ( ) . fullPath ;
264+ searchFiles = Object . keys ( searchResults ) ;
265+
266+ searchFiles . sort ( function ( key1 , key2 ) {
267+ if ( selectedEntry === key1 ) {
268+ return - 1 ;
269+ } else if ( selectedEntry === key2 ) {
270+ return 1 ;
271+ }
272+
273+ var entryName1 , entryName2 ,
274+ pathParts1 = key1 . split ( "/" ) ,
275+ pathParts2 = key2 . split ( "/" ) ,
276+ length = Math . min ( pathParts1 . length , pathParts2 . length ) ,
277+ folders1 = pathParts1 . length - 1 ,
278+ folders2 = pathParts2 . length - 1 ,
279+ index = 0 ;
280+
281+ while ( index < length ) {
282+ entryName1 = pathParts1 [ index ] ;
283+ entryName2 = pathParts2 [ index ] ;
284+
285+ if ( entryName1 !== entryName2 ) {
286+ if ( index < folders1 && index < folders2 ) {
287+ return entryName1 . toLocaleLowerCase ( ) . localeCompare ( entryName2 . toLocaleLowerCase ( ) ) ;
288+ } else if ( index >= folders1 && index >= folders2 ) {
289+ return FileUtils . compareFilenames ( entryName1 , entryName2 ) ;
290+ }
291+ return ( index >= folders1 && index < folders2 ) ? 1 : - 1 ;
292+ }
293+ index ++ ;
294+ }
295+ return 0 ;
296+ } ) ;
297+ }
298+
299+ /**
300+ * @private
301+ * Counts the total number of matches and files
257302 * @return {{files: number, matches: number} }
258303 */
259304 function _countFilesMatches ( ) {
@@ -316,13 +361,16 @@ define(function (require, exports, module) {
316361 } ) ) ;
317362
318363 // Create the results template search list
319- var searchItems , match , i ,
364+ var searchItems , match , i , item ,
320365 searchList = [ ] ,
321366 matchesCounter = 0 ,
322367 showMatches = false ;
323368
324- _ . some ( searchResults , function ( item , fullPath ) {
369+ // Iterates throuh the files to display the results sorted by filenamess. The loop ends as soon as
370+ // we filled the results for one page
371+ searchFiles . some ( function ( fullPath ) {
325372 showMatches = true ;
373+ item = searchResults [ fullPath ] ;
326374
327375 // Since the amount of matches on this item plus the amount of matches we skipped until
328376 // now is still smaller than the first match that we want to display, skip these.
@@ -503,14 +551,15 @@ define(function (require, exports, module) {
503551 }
504552
505553 FileSystem . on ( "change" , _fileSystemChangeHandler ) ;
554+
506555 } else {
507-
508556 _hideSearchResults ( ) ;
509557
510558 if ( dialog ) {
511- dialog . getDialogTextField ( ) . addClass ( "no-results" )
512- . removeAttr ( "disabled" )
513- . get ( 0 ) . select ( ) ;
559+ dialog . getDialogTextField ( )
560+ . addClass ( "no-results" )
561+ . removeAttr ( "disabled" )
562+ . get ( 0 ) . select ( ) ;
514563 $ ( ".modal-bar .no-results-message" ) . show ( ) ;
515564 }
516565 }
@@ -666,6 +715,7 @@ define(function (require, exports, module) {
666715 }
667716 if ( updateResults ) {
668717 timeoutID = window . setTimeout ( function ( ) {
718+ _sortResultFiles ( ) ;
669719 _restoreSearchResults ( ) ;
670720 timeoutID = null ;
671721 } , UPDATE_TIMEOUT ) ;
@@ -693,9 +743,9 @@ define(function (require, exports, module) {
693743 }
694744
695745 /**
746+ * @private
696747 * Used to filter out image files when building a list of file in which to
697748 * search. Ideally this would filter out ALL binary files.
698- * @private
699749 * @param {FileSystemEntry } entry The entry to test
700750 * @return {boolean } Whether or not the entry's contents should be searched
701751 */
@@ -729,6 +779,7 @@ define(function (require, exports, module) {
729779 } )
730780 . done ( function ( ) {
731781 // Done searching all files: show results
782+ _sortResultFiles ( ) ;
732783 _showSearchResults ( ) ;
733784 StatusBar . hideBusyIndicator ( ) ;
734785 PerfUtils . addMeasurement ( perfTimer ) ;
@@ -928,6 +979,7 @@ define(function (require, exports, module) {
928979
929980 // Restore the results if needed
930981 if ( resultsChanged ) {
982+ _sortResultFiles ( ) ;
931983 _restoreSearchResults ( ) ;
932984 }
933985 }
@@ -946,7 +998,7 @@ define(function (require, exports, module) {
946998
947999 /*
9481000 * Remove existing search results that match the given entry's path
949- * @param {File|Directory }
1001+ * @param {( File|Directory) } entry
9501002 */
9511003 function _removeSearchResultsForEntry ( entry ) {
9521004 Object . keys ( searchResults ) . forEach ( function ( fullPath ) {
@@ -959,8 +1011,8 @@ define(function (require, exports, module) {
9591011
9601012 /*
9611013 * Add new search results for this entry and all of its children
962- * @param {File|Directory }
963- * @param {jQuery.Promise } Resolves when the results have been added
1014+ * @param {( File|Directory) } entry
1015+ * @return {jQuery.Promise } Resolves when the results have been added
9641016 */
9651017 function _addSearchResultsForEntry ( entry ) {
9661018 var addedFiles = [ ] ,
@@ -1025,12 +1077,13 @@ define(function (require, exports, module) {
10251077 addPromise . always ( function ( ) {
10261078 // Restore the results if needed
10271079 if ( resultsChanged ) {
1080+ _sortResultFiles ( ) ;
10281081 _restoreSearchResults ( ) ;
10291082 }
10301083 } ) ;
1031-
10321084 } ;
10331085
1086+
10341087 // Initialize items dependent on HTML DOM
10351088 AppInit . htmlReady ( function ( ) {
10361089 var panelHtml = Mustache . render ( searchPanelTemplate , Strings ) ;
0 commit comments