Merge pull request #12653 from owncloud/full_content_search_results
Full content width search resultsremotes/origin/fix-10825
commit
fe4592937a
@ -0,0 +1,191 @@ |
||||
/* |
||||
* Copyright (c) 2014 |
||||
* |
||||
* This file is licensed under the Affero General Public License version 3 |
||||
* or later. |
||||
* |
||||
* See the COPYING-README file. |
||||
* |
||||
*/ |
||||
(function() { |
||||
|
||||
/** |
||||
* Construct a new FileActions instance |
||||
* @constructs Files |
||||
*/ |
||||
var Files = function() { |
||||
this.initialize(); |
||||
}; |
||||
/** |
||||
* @memberof OCA.Search |
||||
*/ |
||||
Files.prototype = { |
||||
|
||||
fileList: null, |
||||
|
||||
/** |
||||
* Initialize the file search |
||||
*/ |
||||
initialize: function() { |
||||
|
||||
var self = this; |
||||
|
||||
this.fileAppLoaded = function() { |
||||
return !!OCA.Files && !!OCA.Files.App; |
||||
}; |
||||
function inFileList($row, result) { |
||||
if (! self.fileAppLoaded()) { |
||||
return false; |
||||
} |
||||
var dir = self.fileList.getCurrentDirectory().replace(/\/+$/,''); |
||||
var resultDir = OC.dirname(result.path); |
||||
return dir === resultDir && self.fileList.inList(result.name); |
||||
} |
||||
function updateLegacyMimetype(result) { |
||||
// backward compatibility:
|
||||
if (!result.mime && result.mime_type) { |
||||
result.mime = result.mime_type; |
||||
} |
||||
} |
||||
function hideNoFilterResults() { |
||||
var $nofilterresults = $('.nofilterresults'); |
||||
if ( ! $nofilterresults.hasClass('hidden') ) { |
||||
$nofilterresults.addClass('hidden'); |
||||
} |
||||
} |
||||
|
||||
this.renderFolderResult = function($row, result) { |
||||
if (inFileList($row, result)) { |
||||
return null; |
||||
} |
||||
hideNoFilterResults(); |
||||
/*render folder icon, show path beneath filename, |
||||
show size and last modified date on the right */ |
||||
this.updateLegacyMimetype(result); |
||||
|
||||
var $pathDiv = $('<div class="path"></div>').text(result.path); |
||||
$row.find('td.info div.name').after($pathDiv).text(result.name); |
||||
|
||||
$row.find('td.result a').attr('href', result.link); |
||||
$row.find('td.icon').css('background-image', 'url(' + OC.imagePath('core', 'filetypes/folder') + ')'); |
||||
return $row; |
||||
}; |
||||
|
||||
this.renderFileResult = function($row, result) { |
||||
if (inFileList($row, result)) { |
||||
return null; |
||||
} |
||||
hideNoFilterResults(); |
||||
/*render preview icon, show path beneath filename, |
||||
show size and last modified date on the right */ |
||||
this.updateLegacyMimetype(result); |
||||
|
||||
var $pathDiv = $('<div class="path"></div>').text(result.path); |
||||
$row.find('td.info div.name').after($pathDiv).text(result.name); |
||||
|
||||
$row.find('td.result a').attr('href', result.link); |
||||
|
||||
if (self.fileAppLoaded()) { |
||||
self.fileList.lazyLoadPreview({ |
||||
path: result.path, |
||||
mime: result.mime, |
||||
callback: function (url) { |
||||
$row.find('td.icon').css('background-image', 'url(' + url + ')'); |
||||
} |
||||
}); |
||||
} else { |
||||
// FIXME how to get mime icon if not in files app
|
||||
var mimeicon = result.mime.replace('/', '-'); |
||||
$row.find('td.icon').css('background-image', 'url(' + OC.imagePath('core', 'filetypes/' + mimeicon) + ')'); |
||||
var dir = OC.dirname(result.path); |
||||
if (dir === '') { |
||||
dir = '/'; |
||||
} |
||||
$row.find('td.info a').attr('href', |
||||
OC.generateUrl('/apps/files/?dir={dir}&scrollto={scrollto}', {dir: dir, scrollto: result.name}) |
||||
); |
||||
} |
||||
return $row; |
||||
}; |
||||
|
||||
this.renderAudioResult = function($row, result) { |
||||
/*render preview icon, show path beneath filename, |
||||
show size and last modified date on the right |
||||
show Artist and Album */ |
||||
$row = this.renderFileResult($row, result); |
||||
if ($row) { |
||||
$row.find('td.icon').css('background-image', 'url(' + OC.imagePath('core', 'filetypes/audio') + ')'); |
||||
} |
||||
return $row; |
||||
}; |
||||
|
||||
this.renderImageResult = function($row, result) { |
||||
/*render preview icon, show path beneath filename, |
||||
show size and last modified date on the right |
||||
show width and height */ |
||||
$row = this.renderFileResult($row, result); |
||||
if ($row && !self.fileAppLoaded()) { |
||||
$row.find('td.icon').css('background-image', 'url(' + OC.imagePath('core', 'filetypes/image') + ')'); |
||||
} |
||||
return $row; |
||||
}; |
||||
|
||||
|
||||
this.handleFolderClick = function($row, result, event) { |
||||
// open folder
|
||||
if (self.fileAppLoaded()) { |
||||
self.fileList.changeDirectory(result.path); |
||||
return false; |
||||
} else { |
||||
return true; |
||||
} |
||||
}; |
||||
|
||||
this.handleFileClick = function($row, result, event) { |
||||
if (self.fileAppLoaded()) { |
||||
self.fileList.changeDirectory(OC.dirname(result.path)); |
||||
self.fileList.scrollTo(result.name); |
||||
return false; |
||||
} else { |
||||
return true; |
||||
} |
||||
}; |
||||
|
||||
this.updateLegacyMimetype = function (result) { |
||||
// backward compatibility:
|
||||
if (!result.mime && result.mime_type) { |
||||
result.mime = result.mime_type; |
||||
} |
||||
}; |
||||
this.setFileList = function (fileList) { |
||||
this.fileList = fileList; |
||||
}; |
||||
|
||||
OC.Plugins.register('OCA.Search', this); |
||||
}, |
||||
attach: function(search) { |
||||
var self = this; |
||||
search.setFilter('files', function (query) { |
||||
if (self.fileAppLoaded()) { |
||||
self.fileList.setFilter(query); |
||||
if (query.length > 2) { |
||||
//search is not started until 500msec have passed
|
||||
window.setTimeout(function() { |
||||
$('.nofilterresults').addClass('hidden'); |
||||
}, 500); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
search.setRenderer('folder', this.renderFolderResult.bind(this)); |
||||
search.setRenderer('file', this.renderFileResult.bind(this)); |
||||
search.setRenderer('audio', this.renderAudioResult.bind(this)); |
||||
search.setRenderer('image', this.renderImageResult.bind(this)); |
||||
|
||||
search.setHandler('folder', this.handleFolderClick.bind(this)); |
||||
search.setHandler(['file', 'audio', 'image'], this.handleFileClick.bind(this)); |
||||
} |
||||
}; |
||||
OCA.Search.Files = Files; |
||||
OCA.Search.files = new Files(); |
||||
})(); |
||||
@ -0,0 +1,58 @@ |
||||
<?php |
||||
/** |
||||
* ownCloud |
||||
* |
||||
* This library is free software; you can redistribute it and/or |
||||
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE |
||||
* License as published by the Free Software Foundation; either |
||||
* version 3 of the License, or any later version. |
||||
* |
||||
* This library is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU AFFERO GENERAL PUBLIC LICENSE for more details. |
||||
* |
||||
* You should have received a copy of the GNU Affero General Public |
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>. |
||||
* |
||||
*/ |
||||
|
||||
namespace OCP\Search; |
||||
|
||||
/** |
||||
* Provides a template for search functionality throughout ownCloud; |
||||
*/ |
||||
abstract class PagedProvider extends Provider { |
||||
|
||||
/** |
||||
* show all results |
||||
*/ |
||||
const SIZE_ALL = 0; |
||||
|
||||
/** |
||||
* Constructor |
||||
* @param array $options |
||||
*/ |
||||
public function __construct($options) { |
||||
$this->options = $options; |
||||
} |
||||
|
||||
/** |
||||
* Search for $query |
||||
* @param string $query |
||||
* @return array An array of OCP\Search\Result's |
||||
*/ |
||||
public function search($query) { |
||||
// old apps might assume they get all results, so we use SIZE_ALL |
||||
$this->searchPaged($query, 1, self::SIZE_ALL); |
||||
} |
||||
|
||||
/** |
||||
* Search for $query |
||||
* @param string $query |
||||
* @param int $page pages start at page 1 |
||||
* @param int $size, 0 = SIZE_ALL |
||||
* @return array An array of OCP\Search\Result's |
||||
*/ |
||||
abstract public function searchPaged($query, $page, $size); |
||||
} |
||||
@ -1,138 +0,0 @@ |
||||
/* |
||||
* Copyright (c) 2014 |
||||
* |
||||
* This file is licensed under the Affero General Public License version 3 |
||||
* or later. |
||||
* |
||||
* See the COPYING-README file. |
||||
* |
||||
*/ |
||||
|
||||
//translations for result type ids, can be extended by apps
|
||||
OC.search.resultTypes={ |
||||
file: t('core','File'), |
||||
folder: t('core','Folder'), |
||||
image: t('core','Image'), |
||||
audio: t('core','Audio') |
||||
}; |
||||
OC.search.catagorizeResults=function(results){ |
||||
var types={}; |
||||
for(var i=0;i<results.length;i++){ |
||||
var type=results[i].type; |
||||
if(!types[type]){ |
||||
types[type]=[]; |
||||
} |
||||
types[type].push(results[i]); |
||||
} |
||||
return types; |
||||
}; |
||||
OC.search.hide=function(){ |
||||
$('#searchresults').hide(); |
||||
if($('#searchbox').val().length>2){ |
||||
$('#searchbox').val(''); |
||||
if (FileList && typeof FileList.unfilter === 'function') { //TODO add hook system
|
||||
FileList.unfilter(); |
||||
} |
||||
}; |
||||
if ($('#searchbox').val().length === 0) { |
||||
if (FileList && typeof FileList.unfilter === 'function') { //TODO add hook system
|
||||
FileList.unfilter(); |
||||
} |
||||
} |
||||
}; |
||||
OC.search.showResults=function(results){ |
||||
if(results.length === 0){ |
||||
return; |
||||
} |
||||
if(!OC.search.showResults.loaded){ |
||||
var parent=$('<div/>'); |
||||
$('body').append(parent); |
||||
parent.load(OC.filePath('search','templates','part.results.php'),function(){ |
||||
OC.search.showResults.loaded=true; |
||||
$('#searchresults').click(function(event){ |
||||
OC.search.hide(); |
||||
event.stopPropagation(); |
||||
}); |
||||
$(document).click(function(event){ |
||||
OC.search.hide(); |
||||
if (FileList && typeof FileList.unfilter === 'function') { //TODO add hook system
|
||||
FileList.unfilter(); |
||||
} |
||||
}); |
||||
OC.search.lastResults=results; |
||||
OC.search.showResults(results); |
||||
}); |
||||
}else{ |
||||
var types=OC.search.catagorizeResults(results); |
||||
$('#searchresults').show(); |
||||
$('#searchresults tr.result').remove(); |
||||
var index=0; |
||||
for(var typeid in types){ |
||||
var type=types[typeid]; |
||||
if(type.length>0){ |
||||
for(var i=0;i<type.length;i++){ |
||||
var row=$('#searchresults tr.template').clone(); |
||||
row.removeClass('template'); |
||||
row.addClass('result'); |
||||
|
||||
row.data('type', typeid); |
||||
row.data('name', type[i].name); |
||||
row.data('text', type[i].text); |
||||
row.data('index',index); |
||||
|
||||
if (i === 0){ |
||||
var typeName = OC.search.resultTypes[typeid]; |
||||
row.children('td.type').text(t('lib', typeName)); |
||||
} |
||||
row.find('td.result div.name').text(type[i].name); |
||||
row.find('td.result div.text').text(type[i].text); |
||||
|
||||
if (type[i].path) { |
||||
var parent = OC.dirname(type[i].path); |
||||
if (parent === '') { |
||||
parent = '/'; |
||||
} |
||||
var containerName = OC.basename(parent); |
||||
if (containerName === '') { |
||||
containerName = '/'; |
||||
} |
||||
var containerLink = OC.linkTo('files', 'index.php') |
||||
+'/?dir='+encodeURIComponent(parent) |
||||
+'&scrollto='+encodeURIComponent(type[i].name); |
||||
row.find('td.result a') |
||||
.attr('href', containerLink) |
||||
.attr('title', t('core', 'Show in {folder}', {folder: containerName})); |
||||
} else { |
||||
row.find('td.result a').attr('href', type[i].link); |
||||
} |
||||
|
||||
index++; |
||||
/** |
||||
* Give plugins the ability to customize the search results. For example: |
||||
* OC.search.customResults.file = function (row, item){ |
||||
* if(item.name.search('.json') >= 0) ... |
||||
* }; |
||||
*/ |
||||
if(OC.search.customResults[typeid]){ |
||||
OC.search.customResults[typeid](row, type[i]); |
||||
} |
||||
$('#searchresults tbody').append(row); |
||||
} |
||||
} |
||||
} |
||||
$('#searchresults').on('click', 'result', function () { |
||||
if ($(this).data('type') === 'Files') { |
||||
//FIXME use ajax to navigate to folder & highlight file
|
||||
} |
||||
}); |
||||
} |
||||
}; |
||||
OC.search.showResults.loaded=false; |
||||
|
||||
OC.search.renderCurrent=function(){ |
||||
if($('#searchresults tr.result')[OC.search.currentResult]){ |
||||
var result=$('#searchresults tr.result')[OC.search.currentResult]; |
||||
$('#searchresults tr.result').removeClass('current'); |
||||
$(result).addClass('current'); |
||||
} |
||||
}; |
||||
@ -0,0 +1,378 @@ |
||||
/** |
||||
* ownCloud - core |
||||
* |
||||
* This file is licensed under the Affero General Public License version 3 or |
||||
* later. See the COPYING file. |
||||
* |
||||
* @author Jörn Friedrich Dreyer <jfd@owncloud.com> |
||||
* @copyright Jörn Friedrich Dreyer 2014 |
||||
*/ |
||||
|
||||
(function () { |
||||
/** |
||||
* @class OCA.Search |
||||
* @classdesc |
||||
* |
||||
* The Search class manages a search queries and their results |
||||
* |
||||
* @param $searchBox container element with existing markup for the #searchbox form |
||||
* @param $searchResults container element for results und status message |
||||
*/ |
||||
var Search = function($searchBox, $searchResults) { |
||||
this.initialize($searchBox, $searchResults); |
||||
}; |
||||
/** |
||||
* @memberof OC |
||||
*/ |
||||
Search.prototype = { |
||||
|
||||
/** |
||||
* Initialize the search box |
||||
* |
||||
* @param $searchBox container element with existing markup for the #searchbox form |
||||
* @param $searchResults container element for results und status message |
||||
* @private |
||||
*/ |
||||
initialize: function($searchBox, $searchResults) { |
||||
|
||||
var self = this; |
||||
|
||||
/** |
||||
* contains closures that are called to filter the current content |
||||
*/ |
||||
var filters = {}; |
||||
this.setFilter = function(type, filter) { |
||||
filters[type] = filter; |
||||
}; |
||||
this.hasFilter = function(type) { |
||||
return typeof filters[type] !== 'undefined'; |
||||
}; |
||||
this.getFilter = function(type) { |
||||
return filters[type]; |
||||
}; |
||||
|
||||
/** |
||||
* contains closures that are called to render search results |
||||
*/ |
||||
var renderers = {}; |
||||
this.setRenderer = function(type, renderer) { |
||||
renderers[type] = renderer; |
||||
}; |
||||
this.hasRenderer = function(type) { |
||||
return typeof renderers[type] !== 'undefined'; |
||||
}; |
||||
this.getRenderer = function(type) { |
||||
return renderers[type]; |
||||
}; |
||||
|
||||
/** |
||||
* contains closures that are called when a search result has been clicked |
||||
*/ |
||||
var handlers = {}; |
||||
this.setHandler = function(type, handler) { |
||||
handlers[type] = handler; |
||||
}; |
||||
this.hasHandler = function(type) { |
||||
return typeof handlers[type] !== 'undefined'; |
||||
}; |
||||
this.getHandler = function(type) { |
||||
return handlers[type]; |
||||
}; |
||||
|
||||
var currentResult = -1; |
||||
var lastQuery = ''; |
||||
var lastInApps = []; |
||||
var lastPage = 0; |
||||
var lastSize = 30; |
||||
var lastResults = []; |
||||
var timeoutID = null; |
||||
|
||||
this.getLastQuery = function() { |
||||
return lastQuery; |
||||
}; |
||||
|
||||
/** |
||||
* Do a search query and display the results |
||||
* @param {string} query the search query |
||||
*/ |
||||
this.search = function(query, inApps, page, size) { |
||||
if (query) { |
||||
OC.addStyle('search','results'); |
||||
if (typeof page !== 'number') { |
||||
page = 1; |
||||
} |
||||
if (typeof size !== 'number') { |
||||
size = 30; |
||||
} |
||||
if (typeof inApps !== 'object') { |
||||
var currentApp = getCurrentApp(); |
||||
if(currentApp) { |
||||
inApps = [currentApp]; |
||||
} else { |
||||
inApps = []; |
||||
} |
||||
} |
||||
// prevent double pages
|
||||
if ($searchResults && query === lastQuery && page === lastPage && size === lastSize) { |
||||
return; |
||||
} |
||||
window.clearTimeout(timeoutID); |
||||
timeoutID = window.setTimeout(function() { |
||||
lastQuery = query; |
||||
lastInApps = inApps; |
||||
lastPage = page; |
||||
lastSize = size; |
||||
|
||||
//show spinner
|
||||
$searchResults.removeClass('hidden'); |
||||
$status.html(t('core', 'Searching other places')+'<img class="spinner" alt="search in progress" src="'+OC.webroot+'/core/img/loading.gif" />'); |
||||
|
||||
// do the actual search query
|
||||
$.getJSON(OC.generateUrl('search/ajax/search.php'), {query:query, inApps:inApps, page:page, size:size }, function(results) { |
||||
lastResults = results; |
||||
if (page === 1) { |
||||
showResults(results); |
||||
} else { |
||||
addResults(results); |
||||
} |
||||
}); |
||||
}, 500); |
||||
} |
||||
}; |
||||
|
||||
//TODO should be a core method, see https://github.com/owncloud/core/issues/12557
|
||||
function getCurrentApp() { |
||||
var content = document.getElementById('content'); |
||||
if (content) { |
||||
var classList = document.getElementById('content').className.split(/\s+/); |
||||
for (var i = 0; i < classList.length; i++) { |
||||
if (classList[i].indexOf('app-') === 0) { |
||||
return classList[i].substr(4); |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
var $status = $searchResults.find('#status'); |
||||
const summaryAndStatusHeight = 118; |
||||
|
||||
function isStatusOffScreen() { |
||||
return $searchResults.position() && ($searchResults.position().top + summaryAndStatusHeight > window.innerHeight); |
||||
} |
||||
|
||||
function placeStatus() { |
||||
if (isStatusOffScreen()) { |
||||
$status.addClass('fixed'); |
||||
} else { |
||||
$status.removeClass('fixed'); |
||||
} |
||||
} |
||||
function showResults(results) { |
||||
lastResults = results; |
||||
$searchResults.find('tr.result').remove(); |
||||
$searchResults.removeClass('hidden'); |
||||
addResults(results); |
||||
} |
||||
function addResults(results) { |
||||
var $template = $searchResults.find('tr.template'); |
||||
jQuery.each(results, function (i, result) { |
||||
var $row = $template.clone(); |
||||
$row.removeClass('template'); |
||||
$row.addClass('result'); |
||||
|
||||
$row.data('result', result); |
||||
|
||||
// generic results only have four attributes
|
||||
$row.find('td.info div.name').text(result.name); |
||||
$row.find('td.info a').attr('href', result.link); |
||||
|
||||
/** |
||||
* Give plugins the ability to customize the search results. see result.js for examples |
||||
*/ |
||||
if (self.hasRenderer(result.type)) { |
||||
$row = self.getRenderer(result.type)($row, result); |
||||
} else { |
||||
// for backward compatibility add text div
|
||||
$row.find('td.info div.name').addClass('result'); |
||||
$row.find('td.result div.name').after('<div class="text"></div>'); |
||||
$row.find('td.result div.text').text(result.name); |
||||
if (OC.search.customResults && OC.search.customResults[result.type]) { |
||||
OC.search.customResults[result.type]($row, result); |
||||
} |
||||
} |
||||
if ($row) { |
||||
$searchResults.find('tbody').append($row); |
||||
} |
||||
}); |
||||
var count = $searchResults.find('tr.result').length; |
||||
$status.data('count', count); |
||||
if (count === 0) { |
||||
$status.text(t('core', 'No search result in other places')); |
||||
} else { |
||||
$status.text(n('core', '{count} search result in other places', '{count} search results in other places', count, {count:count})); |
||||
} |
||||
} |
||||
function renderCurrent() { |
||||
var result = $searchResults.find('tr.result')[currentResult]; |
||||
if (result) { |
||||
var $result = $(result); |
||||
var currentOffset = $('#app-content').scrollTop(); |
||||
$('#app-content').animate({ |
||||
// Scrolling to the top of the new result
|
||||
scrollTop: currentOffset + $result.offset().top - $result.height() * 2 |
||||
}, { |
||||
duration: 100 |
||||
}); |
||||
$searchResults.find('tr.result.current').removeClass('current'); |
||||
$result.addClass('current'); |
||||
} |
||||
} |
||||
this.hideResults = function() { |
||||
$searchResults.addClass('hidden'); |
||||
$searchResults.find('tr.result').remove(); |
||||
lastQuery = false; |
||||
}; |
||||
this.clear = function() { |
||||
self.hideResults(); |
||||
if(self.hasFilter(getCurrentApp())) { |
||||
self.getFilter(getCurrentApp())(''); |
||||
} |
||||
$searchBox.val(''); |
||||
$searchBox.blur(); |
||||
}; |
||||
|
||||
/** |
||||
* Event handler for when scrolling the list container. |
||||
* This appends/renders the next page of entries when reaching the bottom. |
||||
*/ |
||||
function onScroll(e) { |
||||
if ($searchResults && lastQuery !== false && lastResults.length > 0) { |
||||
var resultsBottom = $searchResults.offset().top + $searchResults.height(); |
||||
var containerBottom = $searchResults.offsetParent().offset().top + $searchResults.offsetParent().height(); |
||||
if ( resultsBottom < containerBottom * 1.2 ) { |
||||
self.search(lastQuery, lastInApps, lastPage + 1); |
||||
} |
||||
placeStatus(); |
||||
} |
||||
} |
||||
|
||||
$('#app-content').on('scroll', _.bind(onScroll, this)); |
||||
|
||||
/** |
||||
* scrolls the search results to the top |
||||
*/ |
||||
function scrollToResults() { |
||||
setTimeout(function() { |
||||
if (isStatusOffScreen()) { |
||||
var newScrollTop = $('#app-content').prop('scrollHeight') - $searchResults.height(); |
||||
console.log('scrolling to ' + newScrollTop); |
||||
$('#app-content').animate({ |
||||
scrollTop: newScrollTop |
||||
}, { |
||||
duration: 100, |
||||
complete: function () { |
||||
scrollToResults(); |
||||
} |
||||
}); |
||||
} |
||||
}, 150); |
||||
} |
||||
|
||||
$('form.searchbox').submit(function(event) { |
||||
event.preventDefault(); |
||||
}); |
||||
|
||||
$searchBox.on('search', function (event) { |
||||
if($searchBox.val() === '') { |
||||
if(self.hasFilter(getCurrentApp())) { |
||||
self.getFilter(getCurrentApp())(''); |
||||
} |
||||
self.hideResults(); |
||||
} |
||||
}); |
||||
$searchBox.keyup(function(event) { |
||||
if (event.keyCode === 13) { //enter
|
||||
if(currentResult > -1) { |
||||
var result = $searchResults.find('tr.result a')[currentResult]; |
||||
window.location = $(result).attr('href'); |
||||
} |
||||
} else if(event.keyCode === 38) { //up
|
||||
if(currentResult > 0) { |
||||
currentResult--; |
||||
renderCurrent(); |
||||
} |
||||
} else if(event.keyCode === 40) { //down
|
||||
if(lastResults.length > currentResult + 1){ |
||||
currentResult++; |
||||
renderCurrent(); |
||||
} |
||||
} else { |
||||
var query = $searchBox.val(); |
||||
if (lastQuery !== query) { |
||||
currentResult = -1; |
||||
if (query.length > 2) { |
||||
self.search(query); |
||||
} else { |
||||
self.hideResults(); |
||||
} |
||||
if(self.hasFilter(getCurrentApp())) { |
||||
self.getFilter(getCurrentApp())(query); |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
$(document).keyup(function(event) { |
||||
if(event.keyCode === 27) { //esc
|
||||
$searchBox.val(''); |
||||
if(self.hasFilter(getCurrentApp())) { |
||||
self.getFilter(getCurrentApp())(''); |
||||
} |
||||
self.hideResults(); |
||||
} |
||||
}); |
||||
|
||||
$searchResults.on('click', 'tr.result', function (event) { |
||||
var $row = $(this); |
||||
var item = $row.data('result'); |
||||
if(self.hasHandler(item.type)){ |
||||
var result = self.getHandler(item.type)($row, result, event); |
||||
$searchBox.val(''); |
||||
if(self.hasFilter(getCurrentApp())) { |
||||
self.getFilter(getCurrentApp())(''); |
||||
} |
||||
self.hideResults(); |
||||
return result; |
||||
} |
||||
}); |
||||
$searchResults.on('click', '#status', function (event) { |
||||
event.preventDefault(); |
||||
scrollToResults(); |
||||
return false; |
||||
}); |
||||
placeStatus(); |
||||
|
||||
OC.Plugins.attach('OCA.Search', this); |
||||
} |
||||
}; |
||||
OCA.Search = Search; |
||||
})(); |
||||
|
||||
$(document).ready(function() { |
||||
var $searchResults = $('<div id="searchresults" class="hidden"/>'); |
||||
$('#app-content') |
||||
.append($searchResults) |
||||
.find('.viewcontainer').css('min-height', 'initial'); |
||||
$searchResults.load(OC.webroot + '/search/templates/part.results.html', function () { |
||||
OC.Search = new OCA.Search($('#searchbox'), $('#searchresults')); |
||||
}); |
||||
}); |
||||
|
||||
/** |
||||
* @deprecated use get/setRenderer() instead |
||||
*/ |
||||
OC.search.customResults = {}; |
||||
/** |
||||
* @deprecated use get/setRenderer() instead |
||||
*/ |
||||
OC.search.resultTypes = {}; |
||||
@ -0,0 +1,13 @@ |
||||
<div id="status"></div> |
||||
<table> |
||||
<tbody> |
||||
<tr class="template"> |
||||
<td class="icon"></td> |
||||
<td class="info"> |
||||
<a class="link"> |
||||
<div class="name"></div> |
||||
</a> |
||||
</td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
@ -1,15 +0,0 @@ |
||||
<div id="searchresults"> |
||||
<table> |
||||
<tbody> |
||||
<tr class="template"> |
||||
<td class="type"></td> |
||||
<td class="result"> |
||||
<a> |
||||
<div class="name"></div> |
||||
<div class="text"></div> |
||||
</a> |
||||
</td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
</div> |
||||
Loading…
Reference in new issue