Skip to content

Commit 03efe02

Browse files
unknownunknown
unknown
authored and
unknown
committed
Implemented search filters for movie tab
1 parent 90ae8b3 commit 03efe02

File tree

8 files changed

+1178
-28
lines changed

8 files changed

+1178
-28
lines changed

app/assets/javascripts/jquery-ui-1.10.1.custom.min.js

+911-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/assets/javascripts/movies.js.coffee

+15-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,23 @@
44

55
jQuery ->
66
if $("body").data("controller") in ["movies", "genres", "actors"]
7+
$("select#actor").multiselect(
8+
selectedList: false,
9+
noneSelectedText: "Select actors",
10+
selectedText: "# actors selected"
11+
).multiselectfilter()
12+
$("select#genre").multiselect(
13+
multiple: false,
14+
selectedList: 1,
15+
header: "Select a genre",
16+
noneSelectedText: "Select a genre"
17+
)
18+
$("#filters-toggle").click( ->
19+
$("#new-filters").toggle("blind")
20+
)
721
$("#searchbar").autocomplete(
822
source: (request, response) ->
9-
$.getJSON(location.pathname + ".json", (rawdata) ->
23+
$.getJSON(location.pathname.replace(/\/$/, "") + ".json", (rawdata) ->
1024
matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "i")
1125
data = []
1226
for obj in rawdata

app/assets/stylesheets/home.css.scss

+18
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,24 @@ p.info {
224224
font-style: normal;
225225
}
226226
}
227+
.filter {
228+
background: $backblue;
229+
padding: 2px;
230+
margin-top: 5px;
231+
p {
232+
margin: 0;
233+
margin-left: 20px;
234+
display: inline-block;
235+
}
236+
a {
237+
display: inline-block;
238+
border: none;
239+
}
240+
}
241+
#filters-toggle {
242+
text-align: center;
243+
cursor: pointer;
244+
}
227245

228246
@media screen and (max-width: 650px) {
229247
hgroup {

app/assets/stylesheets/jquery-ui-1.10.1.custom.css

+28
Original file line numberDiff line numberDiff line change
@@ -1173,3 +1173,31 @@ body .ui-tooltip {
11731173
filter: Alpha(Opacity=45);
11741174
border-radius: 5px;
11751175
}
1176+
1177+
.ui-multiselect { padding:2px 0 2px 4px; text-align:left }
1178+
.ui-multiselect span.ui-icon { float:right }
1179+
.ui-multiselect-single .ui-multiselect-checkboxes input { position:absolute !important; top: auto !important; left:-9999px; }
1180+
.ui-multiselect-single .ui-multiselect-checkboxes label { padding:5px !important }
1181+
1182+
.ui-multiselect-header { margin-bottom:3px; padding:3px 0 3px 4px }
1183+
.ui-multiselect-header ul { font-size:0.9em }
1184+
.ui-multiselect-header ul li { float:left; padding:0 10px 0 0 }
1185+
.ui-multiselect-header a { text-decoration:none }
1186+
.ui-multiselect-header a:hover { text-decoration:underline }
1187+
.ui-multiselect-header span.ui-icon { float:left }
1188+
.ui-multiselect-header li.ui-multiselect-close { float:right; text-align:right; padding-right:0 }
1189+
1190+
.ui-multiselect-menu { display:none; padding:3px; position:absolute; z-index:10000; text-align: left }
1191+
.ui-multiselect-checkboxes { position:relative /* fixes bug in IE6/7 */; overflow-y:auto }
1192+
.ui-multiselect-checkboxes label { cursor:default; display:block; border:1px solid transparent; padding:3px 1px }
1193+
.ui-multiselect-checkboxes label input { position:relative; top:1px }
1194+
.ui-multiselect-checkboxes li { clear:both; font-size:0.9em; padding-right:3px }
1195+
.ui-multiselect-checkboxes li.ui-multiselect-optgroup-label { text-align:center; font-weight:bold; border-bottom:1px solid }
1196+
.ui-multiselect-checkboxes li.ui-multiselect-optgroup-label a { display:block; padding:3px; margin:1px 0; text-decoration:none }
1197+
1198+
/* remove label borders in IE6 because IE6 does not support transparency */
1199+
* html .ui-multiselect-checkboxes label { border:none }
1200+
1201+
.ui-multiselect-hasfilter ul { position:relative; top:2px }
1202+
.ui-multiselect-filter { float:left; margin-right:10px; font-size:11px }
1203+
.ui-multiselect-filter input { width:100px; font-size:10px; margin-left:5px; height:15px; padding:2px; border:1px solid #292929; -webkit-appearance:textfield; -webkit-box-sizing:content-box; }

app/controllers/movies_controller.rb

+29-19
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,39 @@ class MoviesController < ApplicationController
22
# GET /movies
33
# GET /movies.json
44
def index
5-
if params[:sort]
6-
if params[:sort] == "alphabetical"
7-
@movies = Movie.order(:title)
8-
elsif params[:sort] == "date"
9-
@movies = Movie.order('lastWatched DESC')
10-
elsif params[:sort] == "type"
11-
@movies = Movie.order(:dvd)
12-
elsif params[:sort] == "duration"
13-
@movies = Movie.order(:duration)
14-
elsif params[:sort] == "year"
15-
@movies = Movie.order(:year)
5+
# if params[:sort]
6+
# if params[:sort] == "alphabetical"
7+
# @movies = Movie.order(:title)
8+
# elsif params[:sort] == "date"
9+
# @movies = Movie.order('lastWatched DESC')
10+
# elsif params[:sort] == "type"
11+
# @movies = Movie.order(:dvd)
12+
# elsif params[:sort] == "duration"
13+
# @movies = Movie.order(:duration)
14+
# elsif params[:sort] == "year"
15+
# @movies = Movie.order(:year)
16+
# end
17+
# else
18+
# @movies = Movie.order(:title)
19+
# end
20+
@filters = []
21+
params.each do |key, value|
22+
if key != "q" and key != "sort" and key != "action" and key != "controller" and value != ""
23+
if value.kind_of? Array
24+
value.each {|val| @filters.push({:name => key, :value => val})}
25+
next
26+
end
27+
@filters.push({:name => key, :value => value})
1628
end
17-
else
18-
@movies = Movie.order(:title)
1929
end
2030

21-
if params[:q]
22-
@movies.keep_if {|movie| movie.title =~ Regexp.new(Regexp.escape(params[:q]))}
23-
end
31+
@actors = []
32+
Actor.all().each {|actor| @actors.push(actor.name)}
2433

25-
if params[:limit]
26-
@movies = @movies.limit(params[:limit])
27-
end
34+
@genres = [""]
35+
Genre.all().each {|genre| @genres.push(genre.name)}
36+
37+
@movies = Movie.search(params[:q], params[:sort], @filters)
2838

2939
@search = params[:q] || ""
3040

app/helpers/movies_helper.rb

+57
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,59 @@
11
module MoviesHelper
2+
attr_accessor :url
3+
attr_accessor :has_querystring
4+
def setupURL(url)
5+
@url = url ? url : ""
6+
if @url != ""
7+
@url.gsub! "%5B", "["
8+
@url.gsub! "%5D", "]"
9+
@url.gsub! "%20", " "
10+
@url.gsub! "+", " "
11+
end
12+
puts @url
13+
puts "<-----------------------------"
14+
@has_querystring = @url["?"] == "?"
15+
end
16+
def searchURL(category, value)
17+
"?q="
18+
end
19+
def cleanURL(url)
20+
url.sub! "&&", "&"
21+
url.sub! "?&", "?"
22+
url.sub!(/\&$/, "")
23+
return url
24+
end
25+
def removeFilter(category, value)
26+
filter = Regexp.new "#{category}(\\[\\d?\\])?=#{value}"
27+
newurl = @url.sub filter, ""
28+
puts newurl
29+
return cleanURL newurl
30+
end
31+
def addFilter(category, value, update=false)
32+
newurl = @url
33+
r = Regexp.new("(?<=#{category}=)\\w+")
34+
if update
35+
if newurl[r]
36+
newurl[r] = value
37+
return newurl
38+
end
39+
end
40+
if @has_querystring
41+
return newurl+"&#{category}=#{value}"
42+
end
43+
return newurl+"?#{category}=#{value}"
44+
end
45+
def hasFilter(category, value)
46+
r = Regexp.new("#{category}(\\[\\d?\\])?=#{value}")
47+
return @url[r]
48+
end
49+
def filterValue(category)
50+
r = Regexp.new("#{category}(\\[\\d?\\])?=(?<value>.*?(?=($|&)))")
51+
match = r.match(@url)
52+
if match
53+
match = match[:value]
54+
end
55+
puts "match for #{category}"
56+
puts match
57+
return match == "" ? "" : match
58+
end
259
end

app/models/movie.rb

+59
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,63 @@ def yearstring
1414
"(#{year})"
1515
end
1616
end
17+
18+
def self.search(q, sort, filters)
19+
if sort == "alphabetical"
20+
movies = Movie.order(:title)
21+
elsif sort == "date"
22+
movies = Movie.order('lastWatched DESC')
23+
elsif sort == "type"
24+
movies = Movie.order(:dvd)
25+
elsif sort == "duration"
26+
movies = Movie.order(:duration)
27+
elsif sort == "year"
28+
movies = Movie.order(:year)
29+
end
30+
31+
sortables = {"alphabetical" => :title,
32+
"title" => :title,
33+
nil => :title,
34+
"date" => 'lastWatched DESC',
35+
"lastWatched" => 'lastWatched DESC',
36+
"type" => :dvd,
37+
"dvd" => :dvd,
38+
"release" => :year,
39+
"year" => :year,
40+
"time" => :duration,
41+
"duration" => :duration}
42+
times = {"short" => (0..60),
43+
"normal" => (60..90),
44+
"long" => (90..120),
45+
"epic" => (120..400)}
46+
movies = Movie.includes([:actors, :genres]).order(sortables[sort])
47+
nmovies = []
48+
movies.each { |movie| nmovies.push movie }
49+
filters.each do |filter|
50+
name = filter[:name]
51+
value = filter[:value]
52+
if name == "actor"
53+
if value.kind_of? String
54+
nmovies.keep_if {|movie| movie.actors.index {|actor| actor.firstname + " " + actor.lastname == value}}
55+
elsif value.kind_of? Array
56+
value.each {|val| nmovies.keep_if {|movie| movie.actors.index {|actor| actor.firstname + " " + actor.lastname == val }}}
57+
else
58+
value.each {|i, val| nmovies.keep_if {|movie| movie.actors.index {|actor| actor.firstname + " " + actor.lastname == val }}}
59+
end
60+
elsif name == "genre"
61+
nmovies.keep_if {|movie| movie.genres.index {|genre| genre.name == value}}
62+
elsif sortables[name] == :year
63+
nmovies.keep_if {|movie| movie.year == value.to_i }
64+
elsif sortables[name] == :dvd
65+
nmovies.keep_if {|movie| movie.dvd.to_s == value }
66+
elsif sortables[name] == :duration
67+
nmovies.keep_if {|movie| times[value].include? movie.duration }
68+
end
69+
end
70+
puts nmovies
71+
if q
72+
nmovies.keep_if {|movie| movie.title.downcase =~ Regexp.new(Regexp.escape(q.downcase))}
73+
end
74+
return nmovies
75+
end
1776
end

app/views/movies/index.html.erb

+61-7
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,72 @@
77
<%= link_to 'New Movie', new_movie_path %>
88
<% end %>
99

10-
<form action="" method="GET" role="search" onsubmit="return q.value != ''">
10+
<% setupURL request.original_fullpath[/\?.+$/] %>
11+
<form action="" method="GET" role="search">
1112
<input id="searchbar" type="text" name="q" placeholder="Search..." <% if defined? @search %>value="<%= @search %>"<% end %> />
1213
<button id="searchbtn" type="submit" class="ui-button-icon-only"><span style="display: inline-block" class="ui-icon ui-icon-search"></span></button>
14+
<div id="new-filters" class="ui-accordion-content ui-helper-reset ui-widget-content ui-corner-all ui-accordion-content-active" style="display: none">
15+
<div class="field">
16+
<%= label_tag 'Actor' %>
17+
<select id='actor' multiple="multiple" name="actor[]">
18+
<% @actors.each do |name| %>
19+
<option value="<%= name %>"<%= hasFilter("actor", name) ? "selected" : ""%>><%= name %></option>
20+
<% end %>
21+
</select>
22+
</div>
23+
<div class="field">
24+
<%= label_tag 'Genre' %>
25+
<select id='genre' name="genre">
26+
<% @genres.each do |name| %>
27+
<option value="<%= name %>"<%= filterValue("genre") == name ? "selected" : ""%>><%= name %></option>
28+
<% end %>
29+
</select>
30+
</div>
31+
<div class="field">
32+
<%= label_tag 'Duration' %>
33+
<%= select_tag 'duration', options_for_select([["",""],["Short (30-60 min)", "short"], ["Normal (60-90 min)", "normal"], ["Long (90-120 min)", "long"], ["Epic (120+ min)", "epic"]], filterValue('duration')) %>
34+
</div>
35+
<div class="field">
36+
<%= label_tag 'Year' %>
37+
<%= number_field_tag 'year', filterValue("year") %>
38+
</div>
39+
<div class="field">
40+
<%= label_tag 'DVD' %>
41+
<%= select_tag 'dvd', options_for_select([["",""], ["DVD", 1], ["Video", 0]], filterValue("dvd")) %>
42+
</div>
43+
</div>
44+
<h3 id="filters-toggle" class="ui-accordion-header ui-state-default ui-corner-all ui-helper-reset">Filters</h3>
1345
<div class="sort-options">
14-
<% q = @search != "" ? "&q="+@search : ""%>
15-
<%= link_to "Date Viewed", "?sort=date"+q, :class => "sort" %>
16-
<%= link_to "Alphabetical", "?sort=alphabetical"+q, :class => "sort" %>
17-
<%= link_to "Video/DVD", "?sort=type"+q, :class => "sort" %>
18-
<%= link_to "Running Time", "?sort=duration"+q, :class => "sort" %>
19-
<%= link_to "Year", "?sort=year"+q, :class => "sort" %>
46+
<p>Sort by:
47+
<%= link_to "Date Viewed", addFilter('sort', 'date', true), :class => "sort" %>
48+
<%= link_to "Alphabetical", addFilter('sort', 'alphabetical', true), :class => "sort" %>
49+
<%= link_to "Video/DVD", addFilter('sort', 'dvd', true), :class => "sort" %>
50+
<%= link_to "Running Time", addFilter('sort', 'duration', true), :class => "sort" %>
51+
<%= link_to "Year", addFilter('sort', 'year', true), :class => "sort" %></p>
2052
</div>
53+
<!--<% @filters.each do |filter| %>
54+
<% if filter[:value].kind_of? Hash %>
55+
<% filter[:value].each do |i,subvalue| %>
56+
<%= hidden_field_tag "#{filter[:name]}[#{i}]", subvalue %>
57+
<% end %>
58+
<% else %>
59+
<%= hidden_field_tag filter[:name], filter[:value] %>
60+
<% end %>
61+
<% end %>-->
2162
</form>
63+
<% @filters.each do |filter| %>
64+
<% if filter[:value].kind_of? Hash %>
65+
<% filter[:value].each do |i,subvalue| %>
66+
<div class="filter">
67+
<a href="<%= removeFilter filter[:name]+"[#{i}]", subvalue %>" class="ui-icon ui-icon-closethick">&nbsp;</a><p><%= filter[:name].capitalize %> = <%= subvalue %></p>
68+
</div>
69+
<% end %>
70+
<% else %>
71+
<div class="filter">
72+
<a href="<%= removeFilter filter[:name], filter[:value] %>" class="ui-icon ui-icon-closethick">&nbsp;</a><p><%= filter[:name].capitalize %> = <%= filter[:value] %></p>
73+
</div>
74+
<% end %>
75+
<% end %>
2276
<% @movies.each do |movie| %>
2377
<article class="<%= movie.dvd == 1 ? "dvd" : "video" %>">
2478
<a href="<%= url_for movie %>"><h2><%= movie.title %> <%= movie.yearstring %></h2></a>

0 commit comments

Comments
 (0)