1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-17 15:53:28 +00:00

[search] added 'advanced search' for top-search-form and search-result page

This commit is contained in:
llj
2013-05-20 15:03:55 +08:00
committed by lins05
parent 0fbc6cd0f2
commit 7f1ccc52e3
6 changed files with 232 additions and 98 deletions

View File

@@ -90,6 +90,7 @@ button {
} }
input[type=radio] { input[type=radio] {
height:auto; height:auto;
border:0;/*for ie*/
} }
input::-webkit-outer-spin-button, input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {/*for input type="number" in chrome: to hide up/download arrow*/ input::-webkit-inner-spin-button {/*for input type="number" in chrome: to hide up/download arrow*/
@@ -2222,13 +2223,13 @@ textarea:-moz-placeholder {/* for FF */
} }
/* search */ /* search */
.search-form { .search-form,
#search-form .input_and_submit {
padding-left:5px; padding-left:5px;
height:24px; height:24px;
border:1px solid #ddd; border:1px solid #ddd;
border-radius:3px; border-radius:3px;
background:#fff; background:#fff;
/*overflow:hidden;for some chromium*/
position:relative; position:relative;
} }
#top-search-form { #top-search-form {
@@ -2250,25 +2251,46 @@ textarea:-moz-placeholder {/* for FF */
cursor:pointer; cursor:pointer;
line-height:24px; line-height:24px;
} }
.search-scales { #advanced-search-form {
position:absolute; position:absolute;
padding:2px 0; width:500px;
padding:18px;
height:auto;
font-weight:normal; font-weight:normal;
background:#fff; box-shadow:0 0 10px #ddd;
z-index:100;/* for pages with jquery tabs*/
}
#advanced-search-form .search-input {
width:98%;
padding:0 3px;
border:1px solid #ddd; border:1px solid #ddd;
border-radius:3px; border-radius:3px;
box-shadow:0 0 10px #ddd; }
#advanced-search-form .submit {
margin-bottom:0;
}
.search-scales {
margin-top:8px;
} }
.search-scales .item { .search-scales .item {
padding:2px 6px; width:48%;
} }
.search-scales .item-hover { .search-repos {
color:#fff; border-bottom:1px dotted #ddd;
background:#666; margin-bottom:3px;
cursor:pointer;
} }
.search-scales [class^="icon-"] { .custom-ftype-options {
margin-right:5px; font-size:13px;
padding:2px 0;
background:#fafafa;
}
.custom-ftype-options .checkbox-label {
display:inline-block;
margin:0 10px 0 0;
}
.custom-ftype-options .fileext-input {
padding:0 3px;
width:70%;
} }
.search-form .search-submit { .search-form .search-submit {
width:30px; width:30px;
@@ -2279,17 +2301,26 @@ textarea:-moz-placeholder {/* for FF */
color:#aaa; color:#aaa;
} }
#search-form { #search-form {
padding:7px 5px;
height:auto;
background:#f7f7f8;
border:0;
border-radius:2px;
}
#search-form .input_and_submit {
display:inline-block;
width:426px; width:426px;
*width:430px; *width:430px;
} }
#search-form .advanced-search {
color:#666;
font-size:16px;
cursor:pointer;
margin-left:4px;
}
#search-form .search-input { #search-form .search-input {
width:392px; width:392px;
} }
#search-form-container {
padding:7px 5px;
background:#f7f7f8;
border-radius:2px;
}
#search-results { #search-results {
padding-top:15px; padding-top:15px;
} }

View File

@@ -362,3 +362,15 @@ function disable(btn) {
function enable(btn) { function enable(btn) {
btn.removeAttr('disabled').removeClass('btn-disabled'); btn.removeAttr('disabled').removeClass('btn-disabled');
} }
// for browsers don't support array.indexOf
if (!Array.indexOf) {
Array.prototype.indexOf = function(obj){
for(var i = 0; i < this.length; i++){
if(this[i] == obj){
return i;
}
}
return -1;
}
}

View File

@@ -71,24 +71,61 @@
{% if enable_file_search and request.user.is_authenticated %} {% if enable_file_search and request.user.is_authenticated %}
<form id="top-search-form" method="get" action="{% url 'search' %}" class="search-form fright"> <form id="top-search-form" method="get" action="{% url 'search' %}" class="search-form fright">
<input class="search-input" name="q" placeholder="{% trans 'Search Files' %}" value="{{ keyword }}" />
<input type="hidden" name="scale" value="all" />
{% if search_repo_id %} {% if search_repo_id %}
<input type="hidden" name="search_repo_id" value="{{ search_repo_id }}" /> <input class="search-input" name="q" placeholder="{% if search_wiki %}{% trans "Search files in this wiki" %}{% else %}{% trans "Search files in this library" %}{% endif %}" value="{{ keyword }}" />
{% endif %} <input type="hidden" name="search_repo" value="{{ search_repo_id }}" />
<span class="icon-caret-down" title="{% trans "choose search scale" %}"></span><button type="submit" class="search-submit"><span class="icon-search"></span></button>
<ul class="search-scales hide">
<li class="item" data-value="all"><span class="icon-ok"></span>{% trans "In all libraries" %}</li>
{% if search_repo_id %}
<li class="item" data-value="current"><span class="icon-"></span>
{% if search_wiki %}
{% trans "In this wiki" %}
{% else %} {% else %}
{% trans "In this library" %} <input class="search-input" name="q" placeholder="{% trans 'Search Files' %}" value="{{ keyword }}" />
{% endif %} {% endif %}
</li> <span class="icon-caret-down" title="{% trans "advanced" %}"></span><button type="submit" class="search-submit"><span class="icon-search"></span></button>
</form>
<form id="advanced-search-form" method="get" action="{% url 'search' %}" class="search-form hide">
<input class="search-input" name="q" placeholder="{% trans 'Search Files' %}" value="{{ keyword }}" />
<div class="search-scales">
<div class="search-repos">
{% if search_repo_id %}
<label class="item"><input type="radio" name="search_repo" value="all" class="vam" /> <span class="vam">{% trans "In all libraries" %}</span></label>
<label class="item"><input type="radio" name="search_repo" checked="checked" value="{{ search_repo_id }}" class="vam" /> <span class="vam">{% if search_wiki %}{% trans "In this wiki" %}{% else %}{% trans "In this library" %}{% endif %}</span></label>
{% else %}
{% if search_repo and repo %}
<label class="item"><input type="radio" name="search_repo" value="all" class="vam" /> <span class="vam">{% trans "In all libraries" %}</span></label>
<label class="item"><input type="radio" name="search_repo" value="{{repo.id}}" checked="checked" class="vam" /> <span class="vam">{% blocktrans with name=repo.name %}in {{name }}{% endblocktrans %}</span></label>
{% else %}
<label class="item"><input type="radio" name="search_repo" value="all" checked="checked" class="vam" /> <span class="vam">{% trans "In all libraries" %}</span></label>
{% endif %} {% endif %}
</ul> {% endif %}
</div>
<div class="search-filetypes">
{% if search_ftypes != 'custom' %}
<label class="item"><input type="radio" name="search_ftypes" value="all" checked="checked" class="vam" /> <span class="vam">{% trans "All file types" %}</span></label>
<label class="item"><input type="radio" name="search_ftypes" value="custom" class="vam" id="custom-search-ftypes" /> <span class="vam">{% trans "Custom file types" %}</span></label>
{% else %}
<label class="item"><input type="radio" name="search_ftypes" value="all" class="vam" /> <span class="vam">{% trans "All file types" %}</span></label>
<label class="item"><input type="radio" name="search_ftypes" value="custom" checked="checked" class="vam" id="custom-search-ftypes" /> <span class="vam">{% trans "Custom file types" %}</span></label>
{% endif %}
</div>
{% if search_ftypes != 'custom' %}
<div class="custom-ftype-options hide">
{% else %}
<div class="custom-ftype-options">
{% endif %}
{# ftype value should be the same with utils/file_types.py #}
<label class="checkbox-label"><span class="checkbox"><input type="checkbox" name="ftype" value="Text" class="checkbox-orig" /></span><span class="checkbox-option">{% trans "Text files" %}</span></label>
<label class="checkbox-label"><span class="checkbox"><input type="checkbox" name="ftype" value="Document" class="checkbox-orig" /></span><span class="checkbox-option">{% trans "Documents" %}</span></label>
<label class="checkbox-label"><span class="checkbox"><input type="checkbox" name="ftype" value="Image" class="checkbox-orig" /></span><span class="checkbox-option">{% trans "Images" %}</span></label>
<label class="checkbox-label"><span class="checkbox"><input type="checkbox" name="ftype" value="Video" class="checkbox-orig" /></span><span class="checkbox-option">{% trans "Video" %}</span></label>
<label class="checkbox-label"><span class="checkbox"><input type="checkbox" name="ftype" value="Audio" class="checkbox-orig" /></span><span class="checkbox-option">{% trans "Audio" %}</span></label>
<label class="checkbox-label"><span class="checkbox"><input type="checkbox" name="ftype" value="SVG" class="checkbox-orig" /></span><span class="checkbox-option">{% trans "svg" %}</span></label>
<label class="checkbox-label"><span class="checkbox"><input type="checkbox" name="ftype" value="PDF" class="checkbox-orig" /></span><span class="checkbox-option">{% trans "pdf" %}</span></label>
<label class="checkbox-label"><span class="checkbox"><input type="checkbox" name="ftype" value="Sf" class="checkbox-orig" /></span><span class="checkbox-option">{% trans "seaf" %}</span></label>
<label class="checkbox-label"><span class="checkbox"><input type="checkbox" name="ftype" value="Markdown" class="checkbox-orig" /></span><span class="checkbox-option">{% trans "markdown" %}</span></label>
<br/>
<input type="text" value="{{ input_fileexts }}" name="input_fexts" placeholder="{% trans "Input file extensions here, separate with ','" %}" class="fileext-input" />
<p class="error hide">{% trans "Please select at least 1 file type or input at least 1 file extension" %}</p>
</div>
</div>
<input type="submit" value="{% trans "Submit" %}" class="submit" />
</form> </form>
{% endif %} {% endif %}
</div> </div>
@@ -204,40 +241,41 @@ $(document).ready(function(){
}); });
{% if enable_file_search %} {% if enable_file_search %}
$('#top-search-form .icon-caret-down').click(function() { // search-form: top-search-form, advanced-search-form, search-form in search result page
var form = $(this).parent(); $('.search-form').submit(function() {
form.find('.search-scales').css({'right':form.find('.search-submit').outerWidth(true), 'top':form.outerHeight()}).toggleClass('hide'); if (!$.trim($(this).find('.search-input').val())) {
return false;
}
}); });
$('.search-scales li').hover( $('#top-search-form .icon-caret-down').click(function() {
function() { var form = $(this).parent(),
$(this).addClass('item-hover'); q = form.find('[name="q"]').val(),
}, advanced_form = $('#advanced-search-form');
function() { $('#header-inner').css({'position':'relative'});
$(this).removeClass('item-hover'); advanced_form.css({'right': 0, 'top':form.outerHeight(true)}).toggleClass('hide');
} if (!advanced_form.hasClass('hide') && q) {
).click(function() { advanced_form.find('.search-input').val(q);
$(this).parent().find('span').attr('class', 'icon-');
$(this).children('span').attr('class', 'icon-ok');
if (!pseudo_support) {
$(this).parent().find('span').html('');
setCon($(this).children('span'), 'icon-', fa_icons);
}
$('#top-search-form [name="scale"]').val($(this).data('value'));
$(this).parent().addClass('hide');
var search_input = $('#top-search-form .search-input');
if ($.trim(search_input.val())) {
$('#top-search-form').submit();
} else {
search_input.attr('placeholder', $(this).text().replace(/^&#x\w+;$/,'')); // replace(...) to rm icon text for some browsers
if (!('placeholder' in document.createElement('input'))) { // for browsers which don't natively support 'placeholder' attr
search_input.attr('value', search_input.attr('placeholder'));
} }
});
$('.search-filetypes .item:first-child').click(function() {
$(this).parents('.search-form').find('.custom-ftype-options').addClass('hide');
});
$('.search-filetypes .item:last-child').click(function() {
$(this).parents('.search-form').find('.custom-ftype-options').removeClass('hide');
});
$('#advanced-search-form').submit(function() {
if ($('#custom-search-ftypes').attr('checked') &&
$('.custom-ftype-options .checkbox-checked').length == 0 &&
!$.trim($('.custom-ftype-options .fileext-input').val())) {
$(this).find('.error').removeClass('hide');
return false;
} }
}); });
$(document).click(function(e) { $(document).click(function(e) {
var target = e.target || event.srcElement; var target = e.target || event.srcElement;
if (!$('.search-scales, #top-search-form .icon-caret-down').is(target) && !($('.search-scales').find('*').is(target))) { var popup = $('#advanced-search-form');
$('.search-scales').addClass('hide'); if (!popup.is(target) && !popup.find('*').is(target) && !$('#top-search-form .icon-caret-down').is(target)) {
popup.addClass('hide');
} }
}); });
{% endif %} {% endif %}
@@ -282,7 +320,9 @@ $(document).click(function(e) {
{'name':'star', 'con':'f005'}, {'name':'star', 'con':'f005'},
{'name':'star-empty', 'con':'f006'}, {'name':'star-empty', 'con':'f006'},
{'name':'caret-down', 'con':'f0d7'}, {'name':'caret-down', 'con':'f0d7'},
{'name':'ok', 'con':'f00c'} {'name':'ok', 'con':'f00c'},
{'name':'double-angle-up', 'con':'f102'},
{'name':'double-angle-down', 'con':'f103'}
]; ];
function setCon(icon, icon_class_prefix, icon_list) { function setCon(icon, icon_class_prefix, icon_list) {
for (var i = 0, len = icon_list.length; i < len; i++) { for (var i = 0, len = icon_list.length; i < len; i++) {

View File

@@ -4,26 +4,20 @@
{% load url from future %} {% load url from future %}
{% block right_panel %} {% block right_panel %}
<div id="search-form-container">
<form method="get" action="{% url 'search' %}" class="search-form" id="search-form"> <form method="get" action="{% url 'search' %}" class="search-form" id="search-form">
<div class="input_and_submit">
<input class="search-input" name="q" placeholder="{% trans 'Search Files' %}" value="{{ keyword }}" /> <input class="search-input" name="q" placeholder="{% trans 'Search Files' %}" value="{{ keyword }}" />
<button type="submit" class="search-submit"><span class="icon-search"></span></button> <button type="submit" class="search-submit"><span class="icon-search"></span></button>
</form>
</div> </div>
<span class="advanced-search vam icon-double-angle-{% if not search_repo and not search_ftypes %}down{% else %}up{% endif %}" title="{% trans "advanced" %}"></span>
</form>
<div id="search-results"> <div id="search-results">
{% if not error %}
{% if not results %} {% if not results %}
<p>{% trans 'No result found' %} <p>{% trans 'No result found' %}</p>
{% if repo %}
{% trans 'in repo' %} <a href="{% url 'repo' repo_id=repo.id %}">{{ repo.name }}</a>
{% endif %}
</p>
{% else %} {% else %}
<p class="tip">{% blocktrans count counter=total %}{{ total }} result{% plural %}{{ total }} results{% endblocktrans%} <p class="tip">{% blocktrans count counter=total %}{{ total }} result{% plural %}{{ total }} results{% endblocktrans%}</p>
{% if repo %}
{% trans 'found in repo' %} <a href="{% url 'repo' repo_id=repo.id %}">{{ repo.name }}</a>
{% endif %}
</p>
<ul id="search-results-list"> <ul id="search-results-list">
{% for file in results %} {% for file in results %}
<li class="search-results-item ovhd"> <li class="search-results-item ovhd">
@@ -78,5 +72,44 @@
</div> </div>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% endif %}
</div> </div>
{% endblock %} {% endblock %}
{% block extra_script %}
<script type="text/javascript">
(function() {
var form = $('#search-form');
{% if search_repo or search_ftypes %}
form.append($('#advanced-search-form .search-scales').clone(true));
{% endif %}
form.find('.advanced-search').click(function() {
if (form.find('.search-scales').length == 0) {
form.append($('#advanced-search-form .search-scales').clone(true));
} else {
form.find('.search-scales').toggleClass('hide');
}
var it = $(this),
str = 'icon-double-angle-';
if (it.hasClass(str + 'down')) {
it.removeClass(str + 'down').addClass(str + 'up');
} else {
it.removeClass(str + 'up').addClass(str + 'down');
}
return false;
});
{% if custom_ftypes %}
var custom_ftypes = [];
{% for f in custom_ftypes %}
custom_ftypes.push("{{f}}");
{% endfor %}
var ftype_options = form.find('[name="ftype"]');
ftype_options.each(function() {
if (custom_ftypes.indexOf($(this).val()) != -1) {
$(this).attr('checked', true);
$(this).parent().addClass('checkbox-checked');
}
});
{% endif %}
})();
</script>
{% endblock %}

View File

@@ -53,7 +53,7 @@ EMPTY_SHA1 = '0000000000000000000000000000000000000000'
MAX_INT = 2147483647 MAX_INT = 2147483647
PREVIEW_FILEEXT = { PREVIEW_FILEEXT = {
TEXT: ('ac', 'am', 'bat', 'c', 'cc', 'cmake', 'cpp', 'cs', 'css', 'diff', 'el', 'h', 'html', 'htm', 'java', 'js', 'json', 'less', 'make', 'org', 'php', 'pl', 'properties', 'py', 'rb', 'scala', 'script', 'sh', 'sql', 'txt', 'text', 'tex', 'vi', 'vim', 'xhtml', 'xml', 'log', 'csv', 'groovy', 'rst', 'patch', ), TEXT: ('ac', 'am', 'bat', 'c', 'cc', 'cmake', 'cpp', 'cs', 'css', 'diff', 'el', 'h', 'html', 'htm', 'java', 'js', 'json', 'less', 'make', 'org', 'php', 'pl', 'properties', 'py', 'rb', 'scala', 'script', 'sh', 'sql', 'txt', 'text', 'tex', 'vi', 'vim', 'xhtml', 'xml', 'log', 'csv', 'groovy', 'rst', 'patch'),
IMAGE: ('gif', 'jpeg', 'jpg', 'png', 'ico'), IMAGE: ('gif', 'jpeg', 'jpg', 'png', 'ico'),
DOCUMENT: ('doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx'), DOCUMENT: ('doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx'),
SVG: ('svg',), SVG: ('svg',),

View File

@@ -3,27 +3,41 @@ from django.template import RequestContext
from seaserv import get_repo from seaserv import get_repo
from seahub.auth.decorators import login_required from seahub.auth.decorators import login_required
from seahub.utils import PREVIEW_FILEEXT
from seahub.utils.search import search_file_by_name, search_repo_file_by_name from seahub.utils.search import search_file_by_name, search_repo_file_by_name
def parse_suffixes(suffixes):
if not suffixes:
return None
l = []
for suffix in suffixes.split(','):
suffix = suffix.strip()
if suffix:
l.append(suffix)
print l
return l
@login_required @login_required
def search(request): def search(request):
keyword = request.GET['q'] template = 'search_results.html'
suffixes = parse_suffixes(request.GET.get('suffixes', None)) error = False
keyword = request.GET.get('q', None)
if not keyword:
return render_to_response(template, {
'error': True,
}, context_instance=RequestContext(request))
# advanced search
search_repo = request.GET.get('search_repo', None) # val: 'all' or 'search_repo_id'
search_ftypes = request.GET.get('search_ftypes', None) # val: 'all' or 'custom'
custom_ftypes = request.GET.getlist('ftype') # types like 'Image', 'Video'... same in utils/file_types.py
input_fileexts = request.GET.get('input_fexts', '') # file extension input by the user
suffixes = None
if search_ftypes == 'custom':
suffixes = []
if len(custom_ftypes) > 0:
for ftp in custom_ftypes:
if PREVIEW_FILEEXT.has_key(ftp):
for ext in PREVIEW_FILEEXT[ftp]:
suffixes.append(ext)
if input_fileexts:
input_fexts = input_fileexts.split(',')
for i_ext in input_fexts:
i_ext = i_ext.strip()
if i_ext:
suffixes.append(i_ext)
current_page = int(request.GET.get('page', '1')) current_page = int(request.GET.get('page', '1'))
per_page= int(request.GET.get('per_page', '25')) per_page= int(request.GET.get('per_page', '25'))
@@ -31,10 +45,9 @@ def search(request):
start = (current_page - 1) * per_page start = (current_page - 1) * per_page
size = per_page size = per_page
scale = request.GET.get('scale', None)
repo_id = request.GET.get('search_repo_id', None)
repo = None repo = None
if scale == 'current' and repo_id: if search_repo and search_repo != 'all':
repo_id = search_repo
repo = get_repo(repo_id) repo = get_repo(repo_id)
if repo: if repo:
results, total = search_repo_file_by_name(request, repo, keyword, suffixes, start, size) results, total = search_repo_file_by_name(request, repo, keyword, suffixes, start, size)
@@ -48,7 +61,7 @@ def search(request):
else: else:
has_more = False has_more = False
return render_to_response('search_results.html', { return render_to_response(template, {
'repo': repo, 'repo': repo,
'keyword': keyword, 'keyword': keyword,
'results': results, 'results': results,
@@ -58,4 +71,9 @@ def search(request):
'prev_page': current_page - 1, 'prev_page': current_page - 1,
'next_page': current_page + 1, 'next_page': current_page + 1,
'per_page': per_page, 'per_page': per_page,
'search_repo': search_repo,
'search_ftypes': search_ftypes,
'custom_ftypes': custom_ftypes,
'input_fileexts': input_fileexts,
'error': error,
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))