mirror of
https://github.com/neocities/neocities.git
synced 2025-04-24 17:22:35 +02:00
tag autocomplete and better browsing
This commit is contained in:
parent
581398f826
commit
1ac9cdf606
9 changed files with 1956 additions and 96 deletions
4
app.rb
4
app.rb
|
@ -266,6 +266,10 @@ post '/tags/remove' do
|
|||
redirect request.referer
|
||||
end
|
||||
|
||||
get '/tags/suggestions/:name.json' do |name|
|
||||
Tag.suggestions(name).collect {|t| t.name}.to_json
|
||||
end
|
||||
|
||||
get '/browse' do
|
||||
@current_page = params[:current_page]
|
||||
@current_page = @current_page.to_i
|
||||
|
|
|
@ -11,4 +11,15 @@ class Tag < Sequel::Model
|
|||
def self.create_unless_exists(name)
|
||||
dataset.filter(name: name).first || create(name: name)
|
||||
end
|
||||
|
||||
def self.suggestions(name, limit=3)
|
||||
Tag.filter(name: /^#{name}/).
|
||||
order(:name).
|
||||
limit(limit).
|
||||
all
|
||||
end
|
||||
|
||||
def self.popular_names(limit=10)
|
||||
DB["select tags.name,count(*) as c from sites_tags inner join tags on tags.id=sites_tags.tag_id where tags.name != '' group by tags.name having count(*) > 1 order by c desc LIMIT ?", limit].all
|
||||
end
|
||||
end
|
||||
|
|
|
@ -771,4 +771,14 @@ a.tag:hover {
|
|||
}
|
||||
.selected {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
max-height: 800px;
|
||||
overflow-y: visible;
|
||||
}
|
||||
|
||||
.tt-dropdown-menu {
|
||||
padding: 0px 10px 0px 10px;
|
||||
background: #FFFFFF;
|
||||
}
|
|
@ -2009,6 +2009,14 @@ a.tag:hover {
|
|||
.selected {
|
||||
font-weight: bold; }
|
||||
|
||||
.modal-body {
|
||||
max-height: 800px;
|
||||
overflow-y: visible; }
|
||||
|
||||
.tt-dropdown-menu {
|
||||
padding: 0px 10px 0px 10px;
|
||||
background: #FFFFFF; }
|
||||
|
||||
.footer-Base {
|
||||
color: #5e5b56;
|
||||
float: left;
|
||||
|
|
4
public/assets/css/neo.min.css
vendored
4
public/assets/css/neo.min.css
vendored
|
@ -841,6 +841,10 @@ a.tag:hover { text-decoration: none; background: #FFEE8A; }
|
|||
|
||||
.selected { font-weight: bold; }
|
||||
|
||||
.modal-body { max-height: 800px; overflow-y: visible; }
|
||||
|
||||
.tt-dropdown-menu { padding: 0px 10px 0px 10px; background: #FFFFFF; }
|
||||
|
||||
.footer-Base { color: #5e5b56; float: left; width: 100%; }
|
||||
.footer-Base h1, .footer-Base h2, .footer-Base h3, .footer-Base h4 { color: #8b9a7a; }
|
||||
|
||||
|
|
1782
public/js/typeahead.bundle.js
Normal file
1782
public/js/typeahead.bundle.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -29,7 +29,7 @@
|
|||
A tag can only be a single word, and can only contain letters and numbers.
|
||||
</p>
|
||||
<p>Tag:</p>
|
||||
<input type="text" name="tags">
|
||||
<input type="text" name="tags" class="typeahead">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
|
||||
|
|
211
views/browse.erb
211
views/browse.erb
|
@ -4,102 +4,123 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div class="header-Outro">
|
||||
<div class="row content">
|
||||
<% if params[:tag] %>
|
||||
<h1>Sites tagged <%= params[:tag] %>
|
||||
<% else %>
|
||||
<h1>Sites on Neocities</h1>
|
||||
<% end %>
|
||||
<h3 class="subtitle"></h3>
|
||||
</div>
|
||||
<div class="header-Outro">
|
||||
<div class="row content">
|
||||
<% if params[:tag] %>
|
||||
<h1>Sites tagged <%= params[:tag] %>
|
||||
<% else %>
|
||||
<h1>Sites on Neocities</h1>
|
||||
<% end %>
|
||||
<h3 class="subtitle"></h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row content">
|
||||
<div class="col col-50">
|
||||
<form id="search_criteria" action="/browse" method="GET">
|
||||
<fieldset class="grouping">
|
||||
<% if params[:tag] %>
|
||||
<input name="tag" type="hidden" value="<%= params[:tag] %>">
|
||||
<% end %>
|
||||
<label class="text-Label" for="sort_by">Sort By:</label>
|
||||
<div class="select-Container">
|
||||
<select name="sort_by" id="sort_by" class="input-Select">
|
||||
<option value="last_updated" <%= params[:sort_by] == 'last_updated' ? 'selected' : '' %>>Last Updated</option>
|
||||
<option value="views" <%= params[:sort_by] == 'views' ? 'selected' : '' %>>Most Views</option>
|
||||
<option value="hits" <%= params[:sort_by] == 'hits' ? 'selected' : '' %>>Most Hits</option>
|
||||
<option value="newest" <%= params[:sort_by] == 'newest' ? 'selected' : '' %>>Newest</option>
|
||||
<option value="oldest" <%= params[:sort_by] == 'oldest' ? 'selected' : '' %>>Oldest</option>
|
||||
<option value="random" <%= params[:sort_by] == 'random' ? 'selected' : '' %>>Random</option>
|
||||
</select>
|
||||
</div>
|
||||
<!--
|
||||
<div>
|
||||
<input name="is_nsfw" type="checkbox" value="true" <%= params[:is_nsfw].to_s == 'true' ? 'checked' : '' %>> Show 18+ content
|
||||
</div>
|
||||
-->
|
||||
<div style="margin-top: 10px">
|
||||
<input class="btn-Action" type="submit" value="Update">
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="row content">
|
||||
<div class="col col-50">
|
||||
<form id="search_criteria" action="/browse" method="GET">
|
||||
<fieldset class="grouping">
|
||||
<% if params[:tag] %>
|
||||
<input name="tag" type="hidden" value="<%= params[:tag] %>">
|
||||
<% end %>
|
||||
<label class="text-Label" for="sort_by">Sort By:</label>
|
||||
<div class="select-Container">
|
||||
<select name="sort_by" id="sort_by" class="input-Select">
|
||||
<option value="last_updated" <%= params[:sort_by] == 'last_updated' ? 'selected' : '' %>>Last Updated</option>
|
||||
<option value="hits" <%= params[:sort_by] == 'hits' ? 'selected' : '' %>>Most Hits</option>
|
||||
<option value="newest" <%= params[:sort_by] == 'newest' ? 'selected' : '' %>>Newest</option>
|
||||
<option value="oldest" <%= params[:sort_by] == 'oldest' ? 'selected' : '' %>>Oldest</option>
|
||||
<option value="random" <%= params[:sort_by] == 'random' ? 'selected' : '' %>>Random</option>
|
||||
</select>
|
||||
</div>
|
||||
<!--
|
||||
<div>
|
||||
<input name="is_nsfw" type="checkbox" value="true" <%= params[:is_nsfw].to_s == 'true' ? 'checked' : '' %>> Show 18+ content
|
||||
</div>
|
||||
-->
|
||||
<div style="margin-top: 10px">
|
||||
<input class="btn-Action" type="submit" value="Update">
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col col-50">
|
||||
<p>If you like a site, don't forget to follow it!<br>Visitor counts are updated hourly.</p>
|
||||
<% unless signed_in? %>
|
||||
<a class="btn-Action" href="/new" title="create a Neocities.org site today!">Create your Neocities site now</a>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
</div> <!-- end .row.content -->
|
||||
<br />
|
||||
<% if @sites.length == 0 %>
|
||||
<div class="row content single-Col">
|
||||
<h2>No active sites found.<br>Try another search!</h2>
|
||||
</div>
|
||||
<% else %>
|
||||
<ul class="row website-Gallery content int-Gall">
|
||||
<% @sites.each do |site| %>
|
||||
<li>
|
||||
<a href="//<%= site.host %>" class="neo-Screen-Shot" target="_blank" title="<%= site.title %>">
|
||||
<span class="img-Holder" style="background:url(<%= site.screenshot_url('index.html', '270x162') %>) no-repeat;">
|
||||
<img src="/img/placeholder.png" alt="<%= site.title %>" />
|
||||
</span>
|
||||
</a>
|
||||
<div>
|
||||
<span>
|
||||
<center><a href="//<%= site.host %>" title="<%= site.title %>"><%= site.title.shorten(35) %></a>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span style="float: left">
|
||||
<a href="/site/<%= site.username %>">Profile</a>
|
||||
</span>
|
||||
<span style="float: right">
|
||||
<a href="/site/<%= site.username %>">
|
||||
<%= site.hits %> hit<%= site.hits == 1 ? '' : 's' %>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
|
||||
<% if params[:sort_by] != 'random' %>
|
||||
<% if @page_count > 1 %>
|
||||
<div class="txt-Center content eps">
|
||||
<% if @current_page != 1 %>
|
||||
<a href="#" onclick="getPage(<%= @current_page - 1 %>); return false"><i class="icon-arrow-left" style="text-decoration: none"></i></a>
|
||||
<% end %>
|
||||
|
||||
<% 1.upto(@page_count) do |num| %>
|
||||
<a href="#" onclick="getPage(<%= num %>); return false" style="<%= num == @current_page ? 'text-decoration: none' : '' %>"><%= num %></a>
|
||||
<% end %>
|
||||
|
||||
<% if @current_page != @page_count %>
|
||||
<a href="#" onclick="getPage(<%= @current_page + 1 %>); return false"><i class="icon-arrow-right" style="text-decoration: none"></i></a>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="col col-50">
|
||||
<p>If you like a site, don't forget to follow it!<br>Visitor counts are updated hourly.</p>
|
||||
<% unless signed_in? %>
|
||||
<a class="btn-Action" href="/new" title="create a Neocities.org site today!">Create your Neocities site now</a>
|
||||
<% end %>
|
||||
</div>
|
||||
</div> <!-- end .row.content -->
|
||||
|
||||
<br />
|
||||
<% if @sites.length == 0 %>
|
||||
<div class="row content single-Col">
|
||||
<h2>No active sites found.<br>Try another search!</h2>
|
||||
</div>
|
||||
<% else %>
|
||||
<ul class="row website-Gallery content int-Gall">
|
||||
<% @sites.each do |site| %>
|
||||
<li>
|
||||
<a href="//<%= site.host %>" class="neo-Screen-Shot" target="_blank" title="<%= site.title %>">
|
||||
<span class="img-Holder" style="background:url(<%= site.screenshot_url('index.html', '270x162') %>) no-repeat;">
|
||||
<img src="/img/placeholder.png" alt="<%= site.title %>" />
|
||||
</span>
|
||||
</a>
|
||||
<div>
|
||||
<span>
|
||||
<center><a href="//<%= site.host %>" title="<%= site.title %>"><%= site.title.shorten(35) %></a>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span style="float: left">
|
||||
<a href="/site/<%= site.username %>">Profile</a>
|
||||
</span>
|
||||
<span style="float: right">
|
||||
<a href="/site/<%= site.username %>">
|
||||
<%= site.hits %> hit<%= site.hits == 1 ? '' : 's' %>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
|
||||
<% if params[:sort_by] != 'random' %>
|
||||
<% if @page_count > 1 %>
|
||||
<div class="txt-Center content eps">
|
||||
<% if @current_page != 1 %>
|
||||
<a href="#" onclick="getPage(<%= @current_page - 1 %>); return false"><i class="icon-arrow-left" style="text-decoration: none"></i></a>
|
||||
<% end %>
|
||||
|
||||
<% 1.upto(@page_count) do |num| %>
|
||||
<a href="#" onclick="getPage(<%= num %>); return false" style="<%= num == @current_page ? 'text-decoration: none' : '' %>"><%= num %></a>
|
||||
<% end %>
|
||||
|
||||
<% if @current_page != @page_count %>
|
||||
<a href="#" onclick="getPage(<%= @current_page + 1 %>); return false"><i class="icon-arrow-right" style="text-decoration: none"></i></a>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<div class="row content">
|
||||
<div class="col col-100">
|
||||
<h3>
|
||||
<% Tag.popular_names.each do |tag| %>
|
||||
<a href="/browse?tag=<%= Rack::Utils.escape tag[:name] %>"><%= tag[:name] %></a>
|
||||
<% end %>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row content">
|
||||
<div class="col col-20">
|
||||
<h4>Search by tag:</h4>
|
||||
<form method="GET" action="browse">
|
||||
<input class="input-Area typeahead" name="tag" placeholder="pokemon">
|
||||
<input type="submit" class="btn-Action" value="Search" style="width: 100px">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
|
@ -54,11 +54,31 @@
|
|||
<script src="/assets/scripts/underscore-min.js"></script>
|
||||
<script src="/assets/scripts/nav.min.js"></script>
|
||||
<script src="/js/bootstrap.min.js"></script>
|
||||
<script src="/js/typeahead.bundle.js"></script>
|
||||
|
||||
<script>
|
||||
$("a#like").tooltip({html: true})
|
||||
$("a.comment_like").tooltip({html: true})
|
||||
$('#shareButton').popover({html: true})
|
||||
|
||||
$('.typeahead').typeahead({
|
||||
minLength: 3,
|
||||
highlight: true
|
||||
}, {
|
||||
name: 'tags',
|
||||
source: function(query, callback) {
|
||||
$.get('/tags/suggestions/'+query+'.json', function(data) {
|
||||
console.log(data)
|
||||
|
||||
var suggestions = JSON.parse(data)
|
||||
var suggestionObjects = []
|
||||
for(var i=0; i<suggestions.length; i++)
|
||||
suggestionObjects.push({value: suggestions[i]})
|
||||
|
||||
callback(suggestionObjects)
|
||||
})
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Add table
Reference in a new issue