Use ajax to improve some functionalities

master
Guillaume Dott 2015-10-22 12:58:43 +02:00
parent 7925becdfb
commit 1bdd77ea23
9 changed files with 147 additions and 49 deletions

View File

@ -17,8 +17,19 @@ module Librarix
end end
get '/search' do get '/search' do
movies = params.key?('search') ? Tmdb::Movie.find(params['search']) : Tmdb::Movie.popular.map { |m| Tmdb::Movie.new(m) } movies = if params['search'].nil?
slim :search, locals: {movies: movies, conf: Tmdb::Configuration.new} Tmdb::Movie.popular.map { |m| Tmdb::Movie.new(m) }
elsif params['search'] == ''
[]
else
Tmdb::Movie.find(params['search'])
end
if request.xhr?
slim :list, layout: false, locals: {movies: movies}
else
slim :search, locals: {movies: movies}
end
end end
post '/add' do post '/add' do
@ -36,7 +47,11 @@ module Librarix
post '/remove' do post '/remove' do
Librarix::Redis::Movie.new(params[:id]).remove Librarix::Redis::Movie.new(params[:id]).remove
if request.xhr?
""
else
redirect to('/') redirect to('/')
end end
end end
end
end end

View File

@ -1,19 +1,45 @@
body { body {
margin: 0; margin: 10px;
} }
h2 { h2 {
margin-top: 0; margin-top: 0;
} }
#search {
display: flex;
input {
border-radius: 0.4em;
border: solid 3px #f4f4f4;
}
input[type="submit"] {
background-color: #f4f4f4;
}
input[type="text"] {
flex-grow: 1;
font-size: 1.4em;
padding: 5px;
}
}
ul { ul {
list-style-type: none; list-style-type: none;
margin: 0; margin: 0;
padding: 0; padding: 0;
li { li {
padding: 10px; padding: 10px 0;
}
li:nth-child(even) {
background-color: #f4f4f4;
}
}
.movie {
display: flex; display: flex;
flex-flow: row wrap; flex-flow: row wrap;
align-items: center; align-items: center;
@ -27,9 +53,4 @@ ul {
align-self: flex-start; align-self: flex-start;
flex: 1 1 300px; flex: 1 1 300px;
} }
}
li:nth-child(even) {
background-color: #f4f4f4;
}
} }

View File

@ -1 +1 @@
body{margin:0}h2{margin-top:0}ul{list-style-type:none;margin:0;padding:0}ul li{padding:10px;display:flex;flex-flow:row wrap;align-items:center;justify-content:center}ul li .poster{margin-right:10px}ul li .informations{align-self:flex-start;flex:1 1 300px}ul li:nth-child(even){background-color:#f4f4f4} body{margin:10px}h2{margin-top:0}#search{display:flex}#search input{border-radius:0.4em;border:solid 3px #f4f4f4}#search input[type="submit"]{background-color:#f4f4f4}#search input[type="text"]{flex-grow:1;font-size:1.4em;padding:5px}ul{list-style-type:none;margin:0;padding:0}ul li{padding:10px 0}ul li:nth-child(even){background-color:#f4f4f4}.movie{display:flex;flex-flow:row wrap;align-items:center;justify-content:center}.movie .poster{margin-right:10px}.movie .informations{align-self:flex-start;flex:1 1 300px}

View File

@ -1,2 +1,65 @@
function initButtons() {
var buttons = document.querySelectorAll('button[data-action=remove-movie]');
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function(event) {
event.preventDefault();
removeMovie(this.previousElementSibling.value)
});
}
}
function initSearch() {
var typing_timer;
var typing_interval = 300;
document.querySelector('#search > input[type="text"]').addEventListener('input', function(event) {
var value = this.value;
clearTimeout(typing_timer);
typing_timer = setTimeout(function() { search(value); }, typing_interval);
});
document.querySelector('#search > input[type="submit"]').style.display = 'none';
window.addEventListener('popstate', function(event) {
document.querySelector('#search > input[type="text"]').value = event.state.value;
search(event.state.value);
});
}
function search(value) {
var url = '/search?search=' + encodeURIComponent(value)
window.history.pushState({value: value}, "", url);
var req = new XMLHttpRequest();
req.open('GET', url);
req.setRequestHeader("X-Requested-With", "XMLHttpRequest");
req.addEventListener('load', function(e) {
document.getElementById('movies').parentNode.innerHTML = this.responseText;
});
req.send()
}
function removeMovie(id) {
var data = new FormData();
data.append('id', id);
var req = new XMLHttpRequest();
req.open('POST', '/remove');
req.setRequestHeader("X-Requested-With", "XMLHttpRequest");
req.addEventListener('load', function(e) {
document.querySelector('.movie[data-id="' + id + '"]').parentNode.remove();
});
req.send(data)
}
document.addEventListener('DOMContentLoaded', function(event) { document.addEventListener('DOMContentLoaded', function(event) {
initButtons();
if(document.querySelector('#search') != null) {
initSearch();
}
}); });

View File

@ -1,6 +1,3 @@
- content_for(:title) { 'Index' } - content_for(:title) { 'Index' }
ul == slim :list, locals: {movies: movies}
- movies.each do |movie|
li
== slim :movie, locals: {movie: movie}

View File

@ -7,5 +7,4 @@ html
link rel="stylesheet" media="all" href="/application.css" link rel="stylesheet" media="all" href="/application.css"
script type="text/javascript" src="/application.js" script type="text/javascript" src="/application.js"
body body
div#main
== yield == yield

View File

@ -0,0 +1,4 @@
ul#movies
- movies.each do |movie|
li
== slim :movie, locals: {movie: movie}

View File

@ -1,16 +1,17 @@
.poster .movie data-id="#{movie.id}"
.poster
- if movie.poster_path - if movie.poster_path
img src="#{poster_url(movie.poster_path, 'w154')}" img src="#{poster_url(movie.poster_path, 'w154')}"
.informations .informations
h2 h2
a href="https://www.themoviedb.org/movie/#{movie.id}" #{movie.original_title} (#{movie.release_year}) a href="https://www.themoviedb.org/movie/#{movie.id}" #{movie.original_title} (#{movie.release_year})
p = movie.overview p = movie.overview
.actions .actions
- if movie.added? - if movie.added?
form method="post" action="/remove" form method="post" action="/remove"
input type="hidden" name="id" value="#{movie.id}" input type="hidden" name="id" value="#{movie.id}"
button type="submit" Remove button type="submit" data-action="remove-movie" Remove
- else - else
form method="post" action="/add" form method="post" action="/add"
input type="hidden" name="id" value="#{movie.id}" input type="hidden" name="id" value="#{movie.id}"
button type="submit" Add button type="submit" data-action="add-movie" Add

View File

@ -1,10 +1,8 @@
- content_for(:title) { 'Search' } - content_for(:title) { 'Search' }
form method="get" action="/search" form method="get" action="/search" id="search"
input type="text" name="search" value="#{params['search']}" input type="text" name="search" value="#{params['search']}" autocomplete="off" autofocus="on"
input type="submit" input type="submit" value="Search"
ul div
- movies.each do |movie| == slim :list, locals: {movies: movies}
li
== slim :movie, locals: {movie: movie}