5 changed files with 2169 additions and 1 deletions
@ -0,0 +1,635 @@ |
|||||
|
var ShowList = new Class({ |
||||
|
|
||||
|
Implements: [Events, Options], |
||||
|
|
||||
|
options: { |
||||
|
navigation: true, |
||||
|
limit: 50, |
||||
|
load_more: true, |
||||
|
loader: true, |
||||
|
menu: [], |
||||
|
add_new: false, |
||||
|
force_view: false |
||||
|
}, |
||||
|
|
||||
|
movies: [], |
||||
|
movies_added: {}, |
||||
|
total_movies: 0, |
||||
|
letters: {}, |
||||
|
filter: null, |
||||
|
|
||||
|
initialize: function(options){ |
||||
|
var self = this; |
||||
|
self.setOptions(options); |
||||
|
|
||||
|
self.offset = 0; |
||||
|
self.filter = self.options.filter || { |
||||
|
'starts_with': null, |
||||
|
'search': null |
||||
|
}; |
||||
|
|
||||
|
self.el = new Element('div.shows').adopt( |
||||
|
self.title = self.options.title ? new Element('h2', { |
||||
|
'text': self.options.title, |
||||
|
'styles': {'display': 'none'} |
||||
|
}) : null, |
||||
|
self.description = self.options.description ? new Element('div.description', { |
||||
|
'html': self.options.description, |
||||
|
'styles': {'display': 'none'} |
||||
|
}) : null, |
||||
|
self.movie_list = new Element('div'), |
||||
|
self.load_more = self.options.load_more ? new Element('a.load_more', { |
||||
|
'events': { |
||||
|
'click': self.loadMore.bind(self) |
||||
|
} |
||||
|
}) : null |
||||
|
); |
||||
|
|
||||
|
if($(window).getSize().x <= 480 && !self.options.force_view) |
||||
|
self.changeView('list'); |
||||
|
else |
||||
|
self.changeView(self.getSavedView() || self.options.view || 'details'); |
||||
|
|
||||
|
self.getMovies(); |
||||
|
|
||||
|
App.on('movie.added', self.movieAdded.bind(self)); |
||||
|
App.on('movie.deleted', self.movieDeleted.bind(self)) |
||||
|
}, |
||||
|
|
||||
|
movieDeleted: function(notification){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(self.movies_added[notification.data._id]){ |
||||
|
self.movies.each(function(movie){ |
||||
|
if(movie.get('_id') == notification.data._id){ |
||||
|
movie.destroy(); |
||||
|
delete self.movies_added[notification.data._id]; |
||||
|
self.setCounter(self.counter_count-1); |
||||
|
self.total_movies--; |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
self.checkIfEmpty(); |
||||
|
}, |
||||
|
|
||||
|
movieAdded: function(notification){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.fireEvent('movieAdded', notification); |
||||
|
if(self.options.add_new && !self.movies_added[notification.data._id] && notification.data.status == self.options.status){ |
||||
|
window.scroll(0,0); |
||||
|
self.createMovie(notification.data, 'top'); |
||||
|
self.setCounter(self.counter_count+1); |
||||
|
|
||||
|
self.checkIfEmpty(); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
// Create the alphabet nav
|
||||
|
if(self.options.navigation) |
||||
|
self.createNavigation(); |
||||
|
|
||||
|
if(self.options.load_more) |
||||
|
self.scrollspy = new ScrollSpy({ |
||||
|
min: function(){ |
||||
|
var c = self.load_more.getCoordinates(); |
||||
|
return c.top - window.document.getSize().y - 300 |
||||
|
}, |
||||
|
onEnter: self.loadMore.bind(self) |
||||
|
}); |
||||
|
|
||||
|
self.created = true; |
||||
|
}, |
||||
|
|
||||
|
addMovies: function(movies, total){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(!self.created) self.create(); |
||||
|
|
||||
|
// do scrollspy
|
||||
|
if(movies.length < self.options.limit && self.scrollspy){ |
||||
|
self.load_more.hide(); |
||||
|
self.scrollspy.stop(); |
||||
|
} |
||||
|
|
||||
|
Object.each(movies, function(movie){ |
||||
|
self.createMovie(movie); |
||||
|
}); |
||||
|
|
||||
|
self.total_movies += total; |
||||
|
self.setCounter(total); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
setCounter: function(count){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(!self.navigation_counter) return; |
||||
|
|
||||
|
self.counter_count = count; |
||||
|
self.navigation_counter.set('text', (count || 0) + ' movies'); |
||||
|
|
||||
|
if (self.empty_message) { |
||||
|
self.empty_message.destroy(); |
||||
|
self.empty_message = null; |
||||
|
} |
||||
|
|
||||
|
if(self.total_movies && count == 0 && !self.empty_message){ |
||||
|
var message = (self.filter.search ? 'for "'+self.filter.search+'"' : '') + |
||||
|
(self.filter.starts_with ? ' in <strong>'+self.filter.starts_with+'</strong>' : ''); |
||||
|
|
||||
|
self.empty_message = new Element('.message', { |
||||
|
'html': 'No movies found ' + message + '.<br/>' |
||||
|
}).grab( |
||||
|
new Element('a', { |
||||
|
'text': 'Reset filter', |
||||
|
'events': { |
||||
|
'click': function(){ |
||||
|
self.filter = { |
||||
|
'starts_with': null, |
||||
|
'search': null |
||||
|
}; |
||||
|
self.navigation_search_input.set('value', ''); |
||||
|
self.reset(); |
||||
|
self.activateLetter(); |
||||
|
self.getMovies(true); |
||||
|
self.last_search_value = ''; |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
).inject(self.movie_list); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
createMovie: function(movie, inject_at){ |
||||
|
var self = this; |
||||
|
var m = new Show(self, { |
||||
|
'actions': self.options.actions, |
||||
|
'view': self.current_view, |
||||
|
'onSelect': self.calculateSelected.bind(self) |
||||
|
}, movie); |
||||
|
|
||||
|
$(m).inject(self.movie_list, inject_at || 'bottom'); |
||||
|
|
||||
|
m.fireEvent('injected'); |
||||
|
|
||||
|
self.movies.include(m); |
||||
|
self.movies_added[movie._id] = true; |
||||
|
}, |
||||
|
|
||||
|
createNavigation: function(){ |
||||
|
var self = this; |
||||
|
var chars = '#ABCDEFGHIJKLMNOPQRSTUVWXYZ'; |
||||
|
|
||||
|
self.el.addClass('with_navigation'); |
||||
|
|
||||
|
self.navigation = new Element('div.alph_nav').adopt( |
||||
|
self.mass_edit_form = new Element('div.mass_edit_form').adopt( |
||||
|
new Element('span.select').adopt( |
||||
|
self.mass_edit_select = new Element('input[type=checkbox].inlay', { |
||||
|
'events': { |
||||
|
'change': self.massEditToggleAll.bind(self) |
||||
|
} |
||||
|
}), |
||||
|
self.mass_edit_selected = new Element('span.count', {'text': 0}), |
||||
|
self.mass_edit_selected_label = new Element('span', {'text': 'selected'}) |
||||
|
), |
||||
|
new Element('div.quality').adopt( |
||||
|
self.mass_edit_quality = new Element('select'), |
||||
|
new Element('a.button.orange', { |
||||
|
'text': 'Change quality', |
||||
|
'events': { |
||||
|
'click': self.changeQualitySelected.bind(self) |
||||
|
} |
||||
|
}) |
||||
|
), |
||||
|
new Element('div.delete').adopt( |
||||
|
new Element('span[text=or]'), |
||||
|
new Element('a.button.red', { |
||||
|
'text': 'Delete', |
||||
|
'events': { |
||||
|
'click': self.deleteSelected.bind(self) |
||||
|
} |
||||
|
}) |
||||
|
), |
||||
|
new Element('div.refresh').adopt( |
||||
|
new Element('span[text=or]'), |
||||
|
new Element('a.button.green', { |
||||
|
'text': 'Refresh', |
||||
|
'events': { |
||||
|
'click': self.refreshSelected.bind(self) |
||||
|
} |
||||
|
}) |
||||
|
) |
||||
|
), |
||||
|
new Element('div.menus').adopt( |
||||
|
self.navigation_counter = new Element('span.counter[title=Total]'), |
||||
|
self.filter_menu = new Block.Menu(self, { |
||||
|
'class': 'filter' |
||||
|
}), |
||||
|
self.navigation_actions = new Element('ul.actions', { |
||||
|
'events': { |
||||
|
'click:relay(li)': function(e, el){ |
||||
|
var a = 'active'; |
||||
|
self.navigation_actions.getElements('.'+a).removeClass(a); |
||||
|
self.changeView(el.get('data-view')); |
||||
|
this.addClass(a); |
||||
|
|
||||
|
el.inject(el.getParent(), 'top'); |
||||
|
el.getSiblings().hide(); |
||||
|
setTimeout(function(){ |
||||
|
el.getSiblings().setStyle('display', null); |
||||
|
}, 100) |
||||
|
} |
||||
|
} |
||||
|
}), |
||||
|
self.navigation_menu = new Block.Menu(self, { |
||||
|
'class': 'extra' |
||||
|
}) |
||||
|
) |
||||
|
).inject(self.el, 'top'); |
||||
|
|
||||
|
// Mass edit
|
||||
|
self.mass_edit_select_class = new Form.Check(self.mass_edit_select); |
||||
|
Quality.getActiveProfiles().each(function(profile){ |
||||
|
new Element('option', { |
||||
|
'value': profile.get('_id'), |
||||
|
'text': profile.get('label') |
||||
|
}).inject(self.mass_edit_quality) |
||||
|
}); |
||||
|
|
||||
|
self.filter_menu.addLink( |
||||
|
self.navigation_search_input = new Element('input', { |
||||
|
'title': 'Search through ' + self.options.identifier, |
||||
|
'placeholder': 'Search through ' + self.options.identifier, |
||||
|
'events': { |
||||
|
'keyup': self.search.bind(self), |
||||
|
'change': self.search.bind(self) |
||||
|
} |
||||
|
}) |
||||
|
).addClass('search'); |
||||
|
|
||||
|
var available_chars; |
||||
|
self.filter_menu.addEvent('open', function(){ |
||||
|
self.navigation_search_input.focus(); |
||||
|
|
||||
|
// Get available chars and highlight
|
||||
|
if(!available_chars && (self.navigation.isDisplayed() || self.navigation.isVisible())) |
||||
|
Api.request('media.available_chars', { |
||||
|
'data': Object.merge({ |
||||
|
'status': self.options.status |
||||
|
}, self.filter), |
||||
|
'onSuccess': function(json){ |
||||
|
available_chars = json.chars; |
||||
|
|
||||
|
available_chars.each(function(c){ |
||||
|
self.letters[c.capitalize()].addClass('available') |
||||
|
}) |
||||
|
|
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
self.filter_menu.addLink( |
||||
|
self.navigation_alpha = new Element('ul.numbers', { |
||||
|
'events': { |
||||
|
'click:relay(li.available)': function(e, el){ |
||||
|
self.activateLetter(el.get('data-letter')); |
||||
|
self.getMovies(true) |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
); |
||||
|
|
||||
|
// Actions
|
||||
|
['mass_edit', 'details', 'list'].each(function(view){ |
||||
|
var current = self.current_view == view; |
||||
|
new Element('li', { |
||||
|
'class': 'icon2 ' + view + (current ? ' active ' : ''), |
||||
|
'data-view': view |
||||
|
}).inject(self.navigation_actions, current ? 'top' : 'bottom'); |
||||
|
}); |
||||
|
|
||||
|
// All
|
||||
|
self.letters['all'] = new Element('li.letter_all.available.active', { |
||||
|
'text': 'ALL' |
||||
|
}).inject(self.navigation_alpha); |
||||
|
|
||||
|
// Chars
|
||||
|
chars.split('').each(function(c){ |
||||
|
self.letters[c] = new Element('li', { |
||||
|
'text': c, |
||||
|
'class': 'letter_'+c, |
||||
|
'data-letter': c |
||||
|
}).inject(self.navigation_alpha); |
||||
|
}); |
||||
|
|
||||
|
// Add menu or hide
|
||||
|
if (self.options.menu.length > 0) |
||||
|
self.options.menu.each(function(menu_item){ |
||||
|
self.navigation_menu.addLink(menu_item); |
||||
|
}); |
||||
|
else |
||||
|
self.navigation_menu.hide(); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
calculateSelected: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
var selected = 0, |
||||
|
movies = self.movies.length; |
||||
|
self.movies.each(function(movie){ |
||||
|
selected += movie.isSelected() ? 1 : 0 |
||||
|
}); |
||||
|
|
||||
|
var indeterminate = selected > 0 && selected < movies, |
||||
|
checked = selected == movies && selected > 0; |
||||
|
|
||||
|
self.mass_edit_select.set('indeterminate', indeterminate); |
||||
|
|
||||
|
self.mass_edit_select_class[checked ? 'check' : 'uncheck'](); |
||||
|
self.mass_edit_select_class.element[indeterminate ? 'addClass' : 'removeClass']('indeterminate'); |
||||
|
|
||||
|
self.mass_edit_selected.set('text', selected); |
||||
|
}, |
||||
|
|
||||
|
deleteSelected: function(){ |
||||
|
var self = this, |
||||
|
ids = self.getSelectedMovies(), |
||||
|
help_msg = self.identifier == 'wanted' ? 'If you do, you won\'t be able to watch them, as they won\'t get downloaded!' : 'Your files will be safe, this will only delete the reference from the CouchPotato manage list'; |
||||
|
|
||||
|
var qObj = new Question('Are you sure you want to delete '+ids.length+' movie'+ (ids.length != 1 ? 's' : '') +'?', help_msg, [{ |
||||
|
'text': 'Yes, delete '+(ids.length != 1 ? 'them' : 'it'), |
||||
|
'class': 'delete', |
||||
|
'events': { |
||||
|
'click': function(e){ |
||||
|
(e).preventDefault(); |
||||
|
this.set('text', 'Deleting..'); |
||||
|
Api.request('media.delete', { |
||||
|
'method': 'post', |
||||
|
'data': { |
||||
|
'id': ids.join(','), |
||||
|
'delete_from': self.options.identifier |
||||
|
}, |
||||
|
'onSuccess': function(){ |
||||
|
qObj.close(); |
||||
|
|
||||
|
var erase_movies = []; |
||||
|
self.movies.each(function(movie){ |
||||
|
if (movie.isSelected()){ |
||||
|
$(movie).destroy(); |
||||
|
erase_movies.include(movie); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
erase_movies.each(function(movie){ |
||||
|
self.movies.erase(movie); |
||||
|
movie.destroy(); |
||||
|
self.setCounter(self.counter_count-1); |
||||
|
self.total_movies--; |
||||
|
}); |
||||
|
|
||||
|
self.calculateSelected(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
}, { |
||||
|
'text': 'Cancel', |
||||
|
'cancel': true |
||||
|
}]); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
changeQualitySelected: function(){ |
||||
|
var self = this; |
||||
|
var ids = self.getSelectedMovies(); |
||||
|
|
||||
|
Api.request('movie.edit', { |
||||
|
'method': 'post', |
||||
|
'data': { |
||||
|
'id': ids.join(','), |
||||
|
'profile_id': self.mass_edit_quality.get('value') |
||||
|
}, |
||||
|
'onSuccess': self.search.bind(self) |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
refreshSelected: function(){ |
||||
|
var self = this; |
||||
|
var ids = self.getSelectedMovies(); |
||||
|
|
||||
|
Api.request('media.refresh', { |
||||
|
'method': 'post', |
||||
|
'data': { |
||||
|
'id': ids.join(',') |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
getSelectedMovies: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
var ids = []; |
||||
|
self.movies.each(function(movie){ |
||||
|
if (movie.isSelected()) |
||||
|
ids.include(movie.get('_id')) |
||||
|
}); |
||||
|
|
||||
|
return ids |
||||
|
}, |
||||
|
|
||||
|
massEditToggleAll: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
var select = self.mass_edit_select.get('checked'); |
||||
|
|
||||
|
self.movies.each(function(movie){ |
||||
|
movie.select(select) |
||||
|
}); |
||||
|
|
||||
|
self.calculateSelected() |
||||
|
}, |
||||
|
|
||||
|
reset: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.movies = []; |
||||
|
if(self.mass_edit_select) |
||||
|
self.calculateSelected(); |
||||
|
if(self.navigation_alpha) |
||||
|
self.navigation_alpha.getElements('.active').removeClass('active'); |
||||
|
|
||||
|
self.offset = 0; |
||||
|
if(self.scrollspy){ |
||||
|
//self.load_more.show();
|
||||
|
self.scrollspy.start(); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
activateLetter: function(letter){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.reset(); |
||||
|
|
||||
|
self.letters[letter || 'all'].addClass('active'); |
||||
|
self.filter.starts_with = letter; |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
changeView: function(new_view){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.el |
||||
|
.removeClass(self.current_view+'_list') |
||||
|
.addClass(new_view+'_list'); |
||||
|
|
||||
|
self.current_view = new_view; |
||||
|
Cookie.write(self.options.identifier+'_view2', new_view, {duration: 1000}); |
||||
|
}, |
||||
|
|
||||
|
getSavedView: function(){ |
||||
|
var self = this; |
||||
|
return Cookie.read(self.options.identifier+'_view2'); |
||||
|
}, |
||||
|
|
||||
|
search: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(self.search_timer) clearTimeout(self.search_timer); |
||||
|
self.search_timer = (function(){ |
||||
|
var search_value = self.navigation_search_input.get('value'); |
||||
|
if (search_value == self.last_search_value) return; |
||||
|
|
||||
|
self.reset(); |
||||
|
|
||||
|
self.activateLetter(); |
||||
|
self.filter.search = search_value; |
||||
|
|
||||
|
self.getMovies(true); |
||||
|
|
||||
|
self.last_search_value = search_value; |
||||
|
|
||||
|
}).delay(250); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
update: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.reset(); |
||||
|
self.getMovies(true); |
||||
|
}, |
||||
|
|
||||
|
getMovies: function(reset){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(self.scrollspy){ |
||||
|
self.scrollspy.stop(); |
||||
|
self.load_more.set('text', 'loading...'); |
||||
|
} |
||||
|
|
||||
|
if(self.movies.length == 0 && self.options.loader){ |
||||
|
|
||||
|
self.loader_first = new Element('div.loading').adopt( |
||||
|
new Element('div.message', {'text': self.options.title ? 'Loading \'' + self.options.title + '\'' : 'Loading...'}) |
||||
|
).inject(self.el, 'top'); |
||||
|
|
||||
|
createSpinner(self.loader_first, { |
||||
|
radius: 4, |
||||
|
length: 4, |
||||
|
width: 1 |
||||
|
}); |
||||
|
|
||||
|
self.el.setStyle('min-height', 93); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
Api.request(self.options.api_call || 'media.list', { |
||||
|
'data': Object.merge({ |
||||
|
'type': self.options.type || 'movie', |
||||
|
'status': self.options.status, |
||||
|
'limit_offset': self.options.limit ? self.options.limit + ',' + self.offset : null |
||||
|
}, self.filter), |
||||
|
'onSuccess': function(json){ |
||||
|
|
||||
|
if(reset) |
||||
|
self.movie_list.empty(); |
||||
|
|
||||
|
if(self.loader_first){ |
||||
|
var lf = self.loader_first; |
||||
|
self.loader_first.addClass('hide'); |
||||
|
self.loader_first = null; |
||||
|
setTimeout(function(){ |
||||
|
lf.destroy(); |
||||
|
}, 20000); |
||||
|
self.el.setStyle('min-height', null); |
||||
|
} |
||||
|
|
||||
|
self.store(json.movies); |
||||
|
self.addMovies(json.movies, json.total || json.movies.length); |
||||
|
if(self.scrollspy) { |
||||
|
self.load_more.set('text', 'load more movies'); |
||||
|
self.scrollspy.start(); |
||||
|
} |
||||
|
|
||||
|
self.checkIfEmpty(); |
||||
|
self.fireEvent('loaded'); |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
loadMore: function(){ |
||||
|
var self = this; |
||||
|
if(self.offset >= self.options.limit) |
||||
|
self.getMovies() |
||||
|
}, |
||||
|
|
||||
|
store: function(movies){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.offset += movies.length; |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
checkIfEmpty: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
var is_empty = self.movies.length == 0 && (self.total_movies == 0 || self.total_movies === undefined); |
||||
|
|
||||
|
if(self.title) |
||||
|
self.title[is_empty ? 'hide' : 'show'](); |
||||
|
|
||||
|
if(self.description) |
||||
|
self.description.setStyle('display', [is_empty ? 'none' : '']); |
||||
|
|
||||
|
if(is_empty && self.options.on_empty_element){ |
||||
|
self.options.on_empty_element.inject(self.loader_first || self.title || self.movie_list, 'after'); |
||||
|
|
||||
|
if(self.navigation) |
||||
|
self.navigation.hide(); |
||||
|
|
||||
|
self.empty_element = self.options.on_empty_element; |
||||
|
} |
||||
|
else if(self.empty_element){ |
||||
|
self.empty_element.destroy(); |
||||
|
|
||||
|
if(self.navigation) |
||||
|
self.navigation.show(); |
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
toElement: function(){ |
||||
|
return this.el; |
||||
|
} |
||||
|
|
||||
|
}); |
File diff suppressed because it is too large
@ -0,0 +1,109 @@ |
|||||
|
var Episodes = new Class({ |
||||
|
initialize: function(show) { |
||||
|
var self = this; |
||||
|
|
||||
|
self.show = show; |
||||
|
}, |
||||
|
|
||||
|
open: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(!self.container){ |
||||
|
self.container = new Element('div.options').grab( |
||||
|
self.episodes_container = new Element('div.episodes.table') |
||||
|
); |
||||
|
|
||||
|
self.container.inject(self.show, 'top'); |
||||
|
|
||||
|
Api.request('library.tree', { |
||||
|
'data': { |
||||
|
'media_id': self.show.data._id |
||||
|
}, |
||||
|
'onComplete': function(json){ |
||||
|
self.data = json.result; |
||||
|
|
||||
|
self.createEpisodes(); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
self.show.slide('in', self.container); |
||||
|
}, |
||||
|
|
||||
|
createEpisodes: function() { |
||||
|
var self = this; |
||||
|
|
||||
|
self.data.seasons.sort(function(a, b) { |
||||
|
var an = a.info.number || 0; |
||||
|
var bn = b.info.number || 0; |
||||
|
|
||||
|
if(an < bn) |
||||
|
return -1; |
||||
|
|
||||
|
if(an > bn) |
||||
|
return 1; |
||||
|
|
||||
|
return 0; |
||||
|
}); |
||||
|
|
||||
|
self.data.seasons.each(function(season) { |
||||
|
season['el'] = new Element('div', { |
||||
|
'class': 'item head', |
||||
|
'id': 'season_'+season._id |
||||
|
}).adopt( |
||||
|
new Element('span.name', {'text': 'Season ' + (season.info.number || 0)}) |
||||
|
).inject(self.episodes_container); |
||||
|
|
||||
|
season.episodes.sort(function(a, b) { |
||||
|
var an = a.info.number || 0; |
||||
|
var bn = b.info.number || 0; |
||||
|
|
||||
|
if(an < bn) |
||||
|
return -1; |
||||
|
|
||||
|
if(an > bn) |
||||
|
return 1; |
||||
|
|
||||
|
return 0; |
||||
|
}); |
||||
|
|
||||
|
season.episodes.each(function(episode) { |
||||
|
var title = ''; |
||||
|
|
||||
|
if(episode.info.titles && episode.info.titles.length > 0) { |
||||
|
title = episode.info.titles[0]; |
||||
|
} |
||||
|
|
||||
|
episode['el'] = new Element('div', { |
||||
|
'class': 'item', |
||||
|
'id': 'episode_'+episode._id |
||||
|
}).adopt( |
||||
|
new Element('span.episode', {'text': (episode.info.number || 0)}), |
||||
|
new Element('span.name', {'text': title}), |
||||
|
new Element('span.firstaired', {'text': episode.info.firstaired}) |
||||
|
).inject(self.episodes_container); |
||||
|
|
||||
|
episode['el_actions'] = new Element('div.actions').inject(episode['el']); |
||||
|
|
||||
|
if(episode.identifiers && episode.identifiers.imdb) { |
||||
|
new Element('a.imdb.icon2', { |
||||
|
'title': 'Go to the IMDB page of ' + self.show.getTitle(), |
||||
|
'href': 'http://www.imdb.com/title/' + episode.identifiers.imdb + '/', |
||||
|
'target': '_blank' |
||||
|
}).inject(episode['el_actions']); |
||||
|
} |
||||
|
|
||||
|
new Element('a.refresh.icon2', { |
||||
|
'title': 'Refresh the episode info and do a forced search', |
||||
|
'events': { |
||||
|
'click': self.doRefresh.bind(self) |
||||
|
} |
||||
|
}).inject(episode['el_actions']); |
||||
|
}); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
doRefresh: function() { |
||||
|
|
||||
|
} |
||||
|
}); |
@ -0,0 +1,347 @@ |
|||||
|
var Show = new Class({ |
||||
|
|
||||
|
Extends: BlockBase, |
||||
|
|
||||
|
action: {}, |
||||
|
|
||||
|
initialize: function(list, options, data){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.data = data; |
||||
|
self.view = options.view || 'details'; |
||||
|
self.list = list; |
||||
|
|
||||
|
self.el = new Element('div.show'); |
||||
|
|
||||
|
self.episodes = new Episodes(self); |
||||
|
|
||||
|
self.profile = Quality.getProfile(data.profile_id) || {}; |
||||
|
self.category = CategoryList.getCategory(data.category_id) || {}; |
||||
|
self.parent(self, options); |
||||
|
|
||||
|
self.addEvents(); |
||||
|
}, |
||||
|
|
||||
|
addEvents: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.global_events = {}; |
||||
|
|
||||
|
// Do refresh with new data
|
||||
|
self.global_events['movie.update'] = function(notification){ |
||||
|
if(self.data._id != notification.data._id) return; |
||||
|
|
||||
|
self.busy(false); |
||||
|
self.removeView(); |
||||
|
self.update.delay(2000, self, notification); |
||||
|
}; |
||||
|
App.on('movie.update', self.global_events['movie.update']); |
||||
|
|
||||
|
// Add spinner on load / search
|
||||
|
['media.busy', 'movie.searcher.started'].each(function(listener){ |
||||
|
self.global_events[listener] = function(notification){ |
||||
|
if(notification.data && (self.data._id == notification.data._id || (typeOf(notification.data._id) == 'array' && notification.data._id.indexOf(self.data._id) > -1))) |
||||
|
self.busy(true); |
||||
|
}; |
||||
|
App.on(listener, self.global_events[listener]); |
||||
|
}); |
||||
|
|
||||
|
// Remove spinner
|
||||
|
self.global_events['movie.searcher.ended'] = function(notification){ |
||||
|
if(notification.data && self.data._id == notification.data._id) |
||||
|
self.busy(false) |
||||
|
}; |
||||
|
App.on('movie.searcher.ended', self.global_events['movie.searcher.ended']); |
||||
|
|
||||
|
// Reload when releases have updated
|
||||
|
self.global_events['release.update_status'] = function(notification){ |
||||
|
var data = notification.data; |
||||
|
if(data && self.data._id == data.movie_id){ |
||||
|
|
||||
|
if(!self.data.releases) |
||||
|
self.data.releases = []; |
||||
|
|
||||
|
self.data.releases.push({'quality': data.quality, 'status': data.status}); |
||||
|
self.updateReleases(); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
App.on('release.update_status', self.global_events['release.update_status']); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
destroy: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.el.destroy(); |
||||
|
delete self.list.movies_added[self.get('id')]; |
||||
|
self.list.movies.erase(self); |
||||
|
|
||||
|
self.list.checkIfEmpty(); |
||||
|
|
||||
|
// Remove events
|
||||
|
Object.each(self.global_events, function(handle, listener){ |
||||
|
App.off(listener, handle); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
busy: function(set_busy, timeout){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(!set_busy){ |
||||
|
setTimeout(function(){ |
||||
|
if(self.spinner){ |
||||
|
self.mask.fade('out'); |
||||
|
setTimeout(function(){ |
||||
|
if(self.mask) |
||||
|
self.mask.destroy(); |
||||
|
if(self.spinner) |
||||
|
self.spinner.el.destroy(); |
||||
|
self.spinner = null; |
||||
|
self.mask = null; |
||||
|
}, timeout || 400); |
||||
|
} |
||||
|
}, timeout || 1000) |
||||
|
} |
||||
|
else if(!self.spinner) { |
||||
|
self.createMask(); |
||||
|
self.spinner = createSpinner(self.mask); |
||||
|
self.mask.fade('in'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
createMask: function(){ |
||||
|
var self = this; |
||||
|
self.mask = new Element('div.mask', { |
||||
|
'styles': { |
||||
|
'z-index': 4 |
||||
|
} |
||||
|
}).inject(self.el, 'top').fade('hide'); |
||||
|
}, |
||||
|
|
||||
|
update: function(notification){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.data = notification.data; |
||||
|
self.el.empty(); |
||||
|
self.removeView(); |
||||
|
|
||||
|
self.profile = Quality.getProfile(self.data.profile_id) || {}; |
||||
|
self.category = CategoryList.getCategory(self.data.category_id) || {}; |
||||
|
self.create(); |
||||
|
|
||||
|
self.busy(false); |
||||
|
}, |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.el.addClass('status_'+self.get('status')); |
||||
|
|
||||
|
self.el.adopt( |
||||
|
self.select_checkbox = new Element('input[type=checkbox].inlay', { |
||||
|
'events': { |
||||
|
'change': function(){ |
||||
|
self.fireEvent('select') |
||||
|
} |
||||
|
} |
||||
|
}), |
||||
|
self.thumbnail = (self.data.files && self.data.files.image_poster) ? new Element('img', { |
||||
|
'class': 'type_image poster', |
||||
|
'src': Api.createUrl('file.cache') + self.data.files.image_poster[0].split(Api.getOption('path_sep')).pop() |
||||
|
}): null, |
||||
|
self.data_container = new Element('div.data.inlay.light').adopt( |
||||
|
self.info_container = new Element('div.info').adopt( |
||||
|
new Element('div.title').adopt( |
||||
|
self.title = new Element('a', { |
||||
|
'events': { |
||||
|
'click': function(e){ |
||||
|
self.episodes.open(); |
||||
|
} |
||||
|
}, |
||||
|
'text': self.getTitle() || 'n/a' |
||||
|
}), |
||||
|
self.year = new Element('div.year', { |
||||
|
'text': self.data.info.year || 'n/a' |
||||
|
}) |
||||
|
), |
||||
|
self.description = new Element('div.description.tiny_scroll', { |
||||
|
'text': self.data.info.plot |
||||
|
}), |
||||
|
self.quality = new Element('div.quality', { |
||||
|
'events': { |
||||
|
'click': function(e){ |
||||
|
var releases = self.el.getElement('.actions .releases'); |
||||
|
if(releases.isVisible()) |
||||
|
releases.fireEvent('click', [e]) |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
), |
||||
|
self.actions = new Element('div.actions') |
||||
|
) |
||||
|
); |
||||
|
|
||||
|
if(!self.thumbnail) |
||||
|
self.el.addClass('no_thumbnail'); |
||||
|
|
||||
|
//self.changeView(self.view);
|
||||
|
self.select_checkbox_class = new Form.Check(self.select_checkbox); |
||||
|
|
||||
|
// Add profile
|
||||
|
if(self.profile.data) |
||||
|
self.profile.getTypes().each(function(type){ |
||||
|
|
||||
|
var q = self.addQuality(type.get('quality'), type.get('3d')); |
||||
|
if((type.finish == true || type.get('finish')) && !q.hasClass('finish')){ |
||||
|
q.addClass('finish'); |
||||
|
q.set('title', q.get('title') + ' Will finish searching for this movie if this quality is found.') |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
// Add releases
|
||||
|
self.updateReleases(); |
||||
|
|
||||
|
Object.each(self.options.actions, function(action, key){ |
||||
|
self.action[key.toLowerCase()] = action = new self.options.actions[key](self); |
||||
|
if(action.el) |
||||
|
self.actions.adopt(action) |
||||
|
}); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
updateReleases: function(){ |
||||
|
var self = this; |
||||
|
if(!self.data.releases || self.data.releases.length == 0) return; |
||||
|
|
||||
|
self.data.releases.each(function(release){ |
||||
|
|
||||
|
var q = self.quality.getElement('.q_'+ release.quality+(release.is_3d ? '.is_3d' : ':not(.is_3d)')), |
||||
|
status = release.status; |
||||
|
|
||||
|
if(!q && (status == 'snatched' || status == 'seeding' || status == 'done')) |
||||
|
q = self.addQuality(release.quality, release.is_3d || false); |
||||
|
|
||||
|
if (q && !q.hasClass(status)){ |
||||
|
q.addClass(status); |
||||
|
q.set('title', (q.get('title') ? q.get('title') : '') + ' status: '+ status) |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
addQuality: function(quality, is_3d){ |
||||
|
var self = this; |
||||
|
|
||||
|
var q = Quality.getQuality(quality); |
||||
|
return new Element('span', { |
||||
|
'text': q.label + (is_3d ? ' 3D' : ''), |
||||
|
'class': 'q_'+q.identifier + (is_3d ? ' is_3d' : ''), |
||||
|
'title': '' |
||||
|
}).inject(self.quality); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
getTitle: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(self.data.title) |
||||
|
return self.getUnprefixedTitle(self.data.title); |
||||
|
else if(self.data.info.titles.length > 0) |
||||
|
return self.getUnprefixedTitle(self.data.info.titles[0]); |
||||
|
|
||||
|
return 'Unknown movie' |
||||
|
}, |
||||
|
|
||||
|
getUnprefixedTitle: function(t){ |
||||
|
if(t.substr(0, 4).toLowerCase() == 'the ') |
||||
|
t = t.substr(4) + ', The'; |
||||
|
else if(t.substr(0, 3).toLowerCase() == 'an ') |
||||
|
t = t.substr(3) + ', An'; |
||||
|
else if(t.substr(0, 2).toLowerCase() == 'a ') |
||||
|
t = t.substr(2) + ', A'; |
||||
|
return t; |
||||
|
}, |
||||
|
|
||||
|
slide: function(direction, el){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(direction == 'in'){ |
||||
|
self.temp_view = self.view; |
||||
|
self.changeView('details'); |
||||
|
|
||||
|
self.el.addEvent('outerClick', function(){ |
||||
|
self.removeView(); |
||||
|
self.slide('out') |
||||
|
}); |
||||
|
el.show(); |
||||
|
|
||||
|
|
||||
|
self.el.addClass('expanded'); |
||||
|
self.el.getElements('.table').addClass('expanded'); |
||||
|
|
||||
|
self.data_container.addClass('hide_right'); |
||||
|
} |
||||
|
else { |
||||
|
self.el.removeEvents('outerClick'); |
||||
|
|
||||
|
setTimeout(function(){ |
||||
|
if(self.el) |
||||
|
{ |
||||
|
self.el.getElements('> :not(.data):not(.poster):not(.movie_container)').hide(); |
||||
|
self.el.getElements('.table').removeClass('expanded'); |
||||
|
} |
||||
|
}, 600); |
||||
|
|
||||
|
self.el.removeClass('expanded'); |
||||
|
self.data_container.removeClass('hide_right'); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
changeView: function(new_view){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(self.el) |
||||
|
self.el |
||||
|
.removeClass(self.view+'_view') |
||||
|
.addClass(new_view+'_view'); |
||||
|
|
||||
|
self.view = new_view; |
||||
|
}, |
||||
|
|
||||
|
removeView: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.el.removeClass(self.view+'_view') |
||||
|
}, |
||||
|
|
||||
|
getIdentifier: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
try { |
||||
|
return self.get('identifiers').imdb; |
||||
|
} |
||||
|
catch (e){ } |
||||
|
|
||||
|
return self.get('imdb'); |
||||
|
}, |
||||
|
|
||||
|
get: function(attr){ |
||||
|
return this.data[attr] || this.data.info[attr] |
||||
|
}, |
||||
|
|
||||
|
select: function(bool){ |
||||
|
var self = this; |
||||
|
self.select_checkbox_class[bool ? 'check' : 'uncheck']() |
||||
|
}, |
||||
|
|
||||
|
isSelected: function(){ |
||||
|
return this.select_checkbox.get('checked'); |
||||
|
}, |
||||
|
|
||||
|
toElement: function(){ |
||||
|
return this.el; |
||||
|
} |
||||
|
|
||||
|
}); |
Loading…
Reference in new issue