37 changed files with 2405 additions and 867 deletions
@ -0,0 +1,95 @@ |
|||||
|
var MovieList = new Class({ |
||||
|
|
||||
|
Implements: [Options], |
||||
|
|
||||
|
options: { |
||||
|
navigation: true |
||||
|
}, |
||||
|
|
||||
|
movies: [], |
||||
|
|
||||
|
initialize: function(options){ |
||||
|
var self = this; |
||||
|
self.setOptions(options); |
||||
|
|
||||
|
self.el = new Element('div.movies'); |
||||
|
self.getMovies(); |
||||
|
}, |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
// Create the alphabet nav
|
||||
|
if(self.options.navigation) |
||||
|
self.createNavigation(); |
||||
|
|
||||
|
Object.each(self.movies, function(info){ |
||||
|
var m = new Movie(self, { |
||||
|
'actions': self.options.actions |
||||
|
}, info); |
||||
|
$(m).inject(self.el); |
||||
|
m.fireEvent('injected'); |
||||
|
}); |
||||
|
|
||||
|
self.el.addEvents({ |
||||
|
'mouseenter:relay(.movie)': function(e, el){ |
||||
|
el.addClass('hover') |
||||
|
}, |
||||
|
'mouseleave:relay(.movie)': function(e, el){ |
||||
|
el.removeClass('hover') |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
createNavigation: function(){ |
||||
|
var self = this; |
||||
|
var chars = '#ABCDEFGHIJKLMNOPQRSTUVWXYZ'; |
||||
|
var selected = 'Z'; |
||||
|
|
||||
|
self.navigation = new Element('div.alph_nav').adopt( |
||||
|
self.alpha = new Element('ul.inlay'), |
||||
|
self.input = new Element('input.inlay'), |
||||
|
self.view = new Element('ul.inlay').adopt( |
||||
|
new Element('li.list'), |
||||
|
new Element('li.thumbnails'), |
||||
|
new Element('li.text') |
||||
|
) |
||||
|
).inject(this.el, 'top') |
||||
|
|
||||
|
chars.split('').each(function(c){ |
||||
|
new Element('li', { |
||||
|
'text': c, |
||||
|
'class': c == selected ? 'selected' : '' |
||||
|
}).inject(self.alpha) |
||||
|
}) |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
getMovies: function(status, onComplete){ |
||||
|
var self = this |
||||
|
|
||||
|
if(self.movies.length == 0) |
||||
|
Api.request('movie.list', { |
||||
|
'data': { |
||||
|
'status': self.options.status |
||||
|
}, |
||||
|
'onComplete': function(json){ |
||||
|
self.store(json.movies); |
||||
|
self.create(); |
||||
|
} |
||||
|
}) |
||||
|
else |
||||
|
self.list() |
||||
|
}, |
||||
|
|
||||
|
store: function(movies){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.movies = movies; |
||||
|
}, |
||||
|
|
||||
|
toElement: function(){ |
||||
|
return this.el; |
||||
|
} |
||||
|
|
||||
|
}); |
@ -0,0 +1,166 @@ |
|||||
|
/* @override http://localhost:5000/static/movie_plugin/movie.css */ |
||||
|
|
||||
|
.movies { |
||||
|
padding: 20px 0; |
||||
|
} |
||||
|
|
||||
|
.movies .movie { |
||||
|
overflow: hidden; |
||||
|
position: relative; |
||||
|
|
||||
|
border-radius: 4px; |
||||
|
-moz-border-radius: 4px; |
||||
|
-webkit-border-radius: 4px; |
||||
|
margin: 10px 0; |
||||
|
} |
||||
|
.movies .movie:hover { |
||||
|
border-color: #ddd #fff #fff #ddd; |
||||
|
} |
||||
|
.movies .movie:hover .data { |
||||
|
} |
||||
|
.movies .data { |
||||
|
padding: 2%; |
||||
|
position: absolute; |
||||
|
width: 96.1%; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
|
||||
|
border-radius: 4px; |
||||
|
-moz-border-radius: 4px; |
||||
|
-webkit-border-radius: 4px; |
||||
|
} |
||||
|
.movies .data:after { |
||||
|
content: ""; |
||||
|
display: block; |
||||
|
height: 0; |
||||
|
clear: both; |
||||
|
visibility: hidden; |
||||
|
} |
||||
|
.movies .data .poster, .options .poster { |
||||
|
overflow: hidden; |
||||
|
float: left; |
||||
|
max-width: 10%; |
||||
|
margin: 0 2% 0 0; |
||||
|
border-radius:3px; |
||||
|
-moz-border-radius: 3px; |
||||
|
-webkit-border-radius: 3px; |
||||
|
box-shadow: 0 0 10px rgba(0,0,0,0.35); |
||||
|
-moz-box-shadow: 0 0 10px rgba(0,0,0,0.35); |
||||
|
-webkit-box-shadow: 0 0 10px rgba(0,0,0,0.35); |
||||
|
line-height: 0; |
||||
|
} |
||||
|
|
||||
|
.movies .info { |
||||
|
float: right; |
||||
|
width: 88%; |
||||
|
} |
||||
|
|
||||
|
.movies .info .title { |
||||
|
font-size: 30px; |
||||
|
font-weight: bold; |
||||
|
margin-bottom: 10px; |
||||
|
float: left; |
||||
|
width: 80%; |
||||
|
} |
||||
|
|
||||
|
.movies .info .year { |
||||
|
font-size: 30px; |
||||
|
margin-bottom: 10px; |
||||
|
float: right; |
||||
|
color: #bbb; |
||||
|
width: 10%; |
||||
|
text-align: right; |
||||
|
} |
||||
|
|
||||
|
.movies .info .rating { |
||||
|
font-size: 30px; |
||||
|
margin-bottom: 10px; |
||||
|
color: #444; |
||||
|
float: left; |
||||
|
width: 5%; |
||||
|
padding: 0 0 0 3%; |
||||
|
background: url('../images/rating.png') no-repeat left center; |
||||
|
} |
||||
|
|
||||
|
.movies .info .description { |
||||
|
clear: both; |
||||
|
width: 95%; |
||||
|
} |
||||
|
.movies .data .actions { |
||||
|
position: absolute; |
||||
|
right: 15px; |
||||
|
bottom: 15px; |
||||
|
line-height: 0; |
||||
|
} |
||||
|
.movies .data:hover .action { opacity: 0.6; } |
||||
|
.movies .data:hover .action:hover { opacity: 1; } |
||||
|
|
||||
|
.movies .data .action { |
||||
|
background: no-repeat center; |
||||
|
display: inline-block; |
||||
|
width: 20px; |
||||
|
height: 20px; |
||||
|
padding: 3px; |
||||
|
opacity: 0; |
||||
|
} |
||||
|
.movies .data .action.refresh { background-image: url('../images/reload.png'); } |
||||
|
.movies .data .action.delete { background-image: url('../images/delete.png'); } |
||||
|
.movies .data .action.edit { background-image: url('../images/edit.png'); } |
||||
|
.movies .data .action.imdb { background-image: url('../images/imdb.png'); } |
||||
|
|
||||
|
.movies .delete_container { |
||||
|
clear: both; |
||||
|
text-align: center; |
||||
|
font-size: 20px; |
||||
|
position: relative; |
||||
|
} |
||||
|
.movies .delete_container .cancel { |
||||
|
} |
||||
|
.movies .delete_container .or { |
||||
|
padding: 10px; |
||||
|
} |
||||
|
.movies .delete_container .delete { |
||||
|
background-color: #ff321c; |
||||
|
font-weight: normal; |
||||
|
} |
||||
|
.movies .delete_container .delete:hover { |
||||
|
color: #fff; |
||||
|
background-color: #d32917; |
||||
|
} |
||||
|
|
||||
|
.movies .options .form { |
||||
|
margin-top: -2%; |
||||
|
float: left; |
||||
|
font-size: 20px; |
||||
|
} |
||||
|
|
||||
|
.movies .options .form select { |
||||
|
margin-right: 20px; |
||||
|
} |
||||
|
|
||||
|
.movies .options { |
||||
|
padding: 2%; |
||||
|
} |
||||
|
|
||||
|
.movies .alph_nav ul { |
||||
|
list-style: none; |
||||
|
padding: 0; |
||||
|
margin: 0; |
||||
|
|
||||
|
display: inline-block; |
||||
|
} |
||||
|
|
||||
|
.movies .alph_nav li { |
||||
|
display: inline-block; |
||||
|
vertical-align: top; |
||||
|
width: 24px; |
||||
|
height: 24px; |
||||
|
line-height: 26px; |
||||
|
text-align: center; |
||||
|
cursor: pointer; |
||||
|
margin: 0 -1px 0 0; |
||||
|
} |
||||
|
|
||||
|
.movies .alph_nav li:hover, .movies .alph_nav li.onlay { |
||||
|
font-weight: bold; |
||||
|
} |
@ -0,0 +1,176 @@ |
|||||
|
var Movie = new Class({ |
||||
|
|
||||
|
Extends: BlockBase, |
||||
|
|
||||
|
action: {}, |
||||
|
|
||||
|
initialize: function(self, options, data){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.data = data; |
||||
|
|
||||
|
self.profile = Quality.getProfile(data.profile_id); |
||||
|
self.parent(self, options); |
||||
|
self.addEvent('injected', self.afterInject.bind(self)) |
||||
|
}, |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.el = new Element('div.movie.inlay').adopt( |
||||
|
self.data_container = new Element('div.data.inlay.light', { |
||||
|
'tween': { |
||||
|
duration: 400, |
||||
|
transition: 'quint:in:out' |
||||
|
} |
||||
|
}).adopt( |
||||
|
self.thumbnail = File.Select.single('poster', self.data.library.files), |
||||
|
self.info_container = new Element('div.info').adopt( |
||||
|
self.title = new Element('div.title', { |
||||
|
'text': self.getTitle() |
||||
|
}), |
||||
|
self.year = new Element('div.year', { |
||||
|
'text': self.data.library.year || 'Unknown' |
||||
|
}), |
||||
|
self.rating = new Element('div.rating', { |
||||
|
'text': self.data.library.rating |
||||
|
}), |
||||
|
self.description = new Element('div.description', { |
||||
|
'text': self.data.library.plot |
||||
|
}), |
||||
|
self.quality = new Element('div.quality', { |
||||
|
'text': self.profile ? self.profile.get('label') : '' |
||||
|
}) |
||||
|
), |
||||
|
self.actions = new Element('div.actions') |
||||
|
) |
||||
|
); |
||||
|
|
||||
|
Object.each(self.options.actions, function(action, key){ |
||||
|
self.actions.adopt( |
||||
|
self.action[key.toLowerCase()] = new self.options.actions[key](self) |
||||
|
) |
||||
|
}); |
||||
|
|
||||
|
if(!self.data.library.rating) |
||||
|
self.rating.hide(); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
afterInject: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
var height = self.getHeight(); |
||||
|
self.el.setStyle('height', height); |
||||
|
}, |
||||
|
|
||||
|
getTitle: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
var titles = self.data.library.titles; |
||||
|
|
||||
|
var title = titles.filter(function(title){ |
||||
|
return title['default'] |
||||
|
}).pop() |
||||
|
|
||||
|
if(title) |
||||
|
return title.title |
||||
|
else if(titles.length > 0) |
||||
|
return titles[0].title |
||||
|
|
||||
|
return 'Unknown movie' |
||||
|
}, |
||||
|
|
||||
|
slide: function(direction){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(direction == 'in'){ |
||||
|
self.el.addEvent('outerClick', self.slide.bind(self, 'out')) |
||||
|
self.data_container.tween('left', 0, self.getWidth()); |
||||
|
} |
||||
|
else { |
||||
|
self.el.removeEvents('outerClick') |
||||
|
self.data_container.tween('left', self.getWidth(), 0); |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
getHeight: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(!self.height) |
||||
|
self.height = self.data_container.getCoordinates().height; |
||||
|
|
||||
|
return self.height; |
||||
|
}, |
||||
|
|
||||
|
getWidth: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(!self.width) |
||||
|
self.width = self.data_container.getCoordinates().width; |
||||
|
|
||||
|
return self.width; |
||||
|
}, |
||||
|
|
||||
|
get: function(attr){ |
||||
|
return this.data[attr] || this.data.library[attr] |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
var MovieAction = new Class({ |
||||
|
|
||||
|
class_name: 'action', |
||||
|
|
||||
|
initialize: function(movie){ |
||||
|
var self = this; |
||||
|
self.movie = movie; |
||||
|
|
||||
|
self.create(); |
||||
|
self.el.addClass(self.class_name) |
||||
|
}, |
||||
|
|
||||
|
create: function(){}, |
||||
|
|
||||
|
disable: function(){ |
||||
|
this.el.addClass('disable') |
||||
|
}, |
||||
|
|
||||
|
enable: function(){ |
||||
|
this.el.removeClass('disable') |
||||
|
}, |
||||
|
|
||||
|
toElement: function(){ |
||||
|
return this.el |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
var IMDBAction = new Class({ |
||||
|
|
||||
|
Extends: MovieAction, |
||||
|
id: null, |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.id = self.movie.get('identifier'); |
||||
|
|
||||
|
self.el = new Element('a.imdb', { |
||||
|
'title': 'Go to the IMDB page of ' + self.movie.getTitle(), |
||||
|
'events': { |
||||
|
'click': self.gotoIMDB.bind(self) |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
if(!self.id) self.disable(); |
||||
|
}, |
||||
|
|
||||
|
gotoIMDB: function(e){ |
||||
|
var self = this; |
||||
|
(e).stop(); |
||||
|
|
||||
|
window.open('http://www.imdb.com/title/'+self.id+'/'); |
||||
|
} |
||||
|
|
||||
|
}) |
@ -0,0 +1,18 @@ |
|||||
|
.profile > .delete { |
||||
|
background-position: center; |
||||
|
height: 20px; |
||||
|
width: 20px; |
||||
|
} |
||||
|
|
||||
|
.profile .types .type .handle { |
||||
|
background: url('../../images/handle.png') center; |
||||
|
display: inline-block; |
||||
|
height: 20px; |
||||
|
width: 20px; |
||||
|
} |
||||
|
|
||||
|
.profile .types .type .delete { |
||||
|
background-position: center; |
||||
|
height: 20px; |
||||
|
width: 20px; |
||||
|
} |
@ -0,0 +1,259 @@ |
|||||
|
var Profile = new Class({ |
||||
|
|
||||
|
data: {}, |
||||
|
types: [], |
||||
|
|
||||
|
initialize: function(data){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.data = data; |
||||
|
self.types = []; |
||||
|
|
||||
|
self.create(); |
||||
|
|
||||
|
self.el.addEvents({ |
||||
|
'change:relay(select, input[type=checkbox])': self.save.bind(self, 0), |
||||
|
'keyup:relay(input[type=text])': self.save.bind(self, [300]) |
||||
|
}); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
var data = self.data; |
||||
|
|
||||
|
self.el = new Element('div.profile').adopt( |
||||
|
self.header = new Element('h4', {'text': data.label}), |
||||
|
new Element('span.delete.icon', { |
||||
|
'events': { |
||||
|
'click': self.del.bind(self) |
||||
|
} |
||||
|
}), |
||||
|
new Element('div', { |
||||
|
'class': 'ctrlHolder' |
||||
|
}).adopt( |
||||
|
new Element('label', {'text':'Name'}), |
||||
|
new Element('input.label.textInput.large', { |
||||
|
'type':'text', |
||||
|
'value': data.label, |
||||
|
'events': { |
||||
|
'keyup': function(){ |
||||
|
self.header.set('text', this.get('value')) |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
), |
||||
|
new Element('div.ctrlHolder').adopt( |
||||
|
new Element('label', {'text':'Wait'}), |
||||
|
new Element('input.wait_for.textInput.xsmall', { |
||||
|
'type':'text', |
||||
|
'value': data.types && data.types.length > 0 ? data.types[0].wait_for : 0 |
||||
|
}), |
||||
|
new Element('span', {'text':' day(s) for better quality.'}) |
||||
|
), |
||||
|
new Element('div.ctrlHolder').adopt( |
||||
|
new Element('label', {'text': 'Qualities'}), |
||||
|
new Element('div.head').adopt( |
||||
|
new Element('span.quality_type', {'text': 'Search for'}), |
||||
|
new Element('span.finish', {'html': '<acronym title="Won\'t download anything else if it has found this quality.">Finish</acronym>'}) |
||||
|
), |
||||
|
self.type_container = new Element('ol.types'), |
||||
|
new Element('a.addType', { |
||||
|
'text': 'Add another quality to search for.', |
||||
|
'href': '#', |
||||
|
'events': { |
||||
|
'click': self.addType.bind(self) |
||||
|
} |
||||
|
}) |
||||
|
) |
||||
|
); |
||||
|
|
||||
|
self.makeSortable() |
||||
|
|
||||
|
if(data.types) |
||||
|
Object.each(data.types, self.addType.bind(self)) |
||||
|
}, |
||||
|
|
||||
|
save: function(delay){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(self.save_timer) clearTimeout(self.save_timer); |
||||
|
self.save_timer = (function(){ |
||||
|
|
||||
|
var data = self.getData(); |
||||
|
if(data.types.length < 2) return; |
||||
|
|
||||
|
Api.request('profile.save', { |
||||
|
'data': self.getData(), |
||||
|
'useSpinner': true, |
||||
|
'spinnerOptions': { |
||||
|
'target': self.el |
||||
|
}, |
||||
|
'onComplete': function(json){ |
||||
|
if(json.success){ |
||||
|
self.data = json.profile |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
}).delay(delay, self) |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
getData: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
var data = { |
||||
|
'id' : self.data.id, |
||||
|
'label' : self.el.getElement('.label').get('value'), |
||||
|
'wait_for' : self.el.getElement('.wait_for').get('value'), |
||||
|
'types': [] |
||||
|
} |
||||
|
|
||||
|
Array.each(self.type_container.getElements('.type'), function(type){ |
||||
|
if(!type.hasClass('deleted')) |
||||
|
data.types.include({ |
||||
|
'quality_id': type.getElement('select').get('value'), |
||||
|
'finish': +type.getElement('input[type=checkbox]').checked |
||||
|
}); |
||||
|
}) |
||||
|
|
||||
|
return data |
||||
|
}, |
||||
|
|
||||
|
addType: function(data){ |
||||
|
var self = this; |
||||
|
|
||||
|
var t = new Profile.Type(data); |
||||
|
$(t).inject(self.type_container); |
||||
|
self.sortable.addItems($(t)); |
||||
|
|
||||
|
self.types.include(t); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
del: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
if(!confirm('Are you sure you want to delete this profile?')) return |
||||
|
|
||||
|
Api.request('profile.delete', { |
||||
|
'data': { |
||||
|
'id': self.data.id |
||||
|
}, |
||||
|
'useSpinner': true, |
||||
|
'spinnerOptions': { |
||||
|
'target': self.el |
||||
|
}, |
||||
|
'onComplete': function(json){ |
||||
|
if(json.success) |
||||
|
self.el.destroy(); |
||||
|
else |
||||
|
alert(json.message) |
||||
|
} |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
makeSortable: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.sortable = new Sortables(self.type_container, { |
||||
|
'revert': true, |
||||
|
//'clone': true,
|
||||
|
'handle': '.handle', |
||||
|
'opacity': 0.5, |
||||
|
'onComplete': self.save.bind(self, 300) |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
get: function(attr){ |
||||
|
return this.data[attr] |
||||
|
}, |
||||
|
|
||||
|
isCore: function(){ |
||||
|
return this.data.core |
||||
|
}, |
||||
|
|
||||
|
toElement: function(){ |
||||
|
return this.el |
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
Profile.Type = Class({ |
||||
|
|
||||
|
deleted: false, |
||||
|
|
||||
|
initialize: function(data){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.data = data; |
||||
|
self.create(); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
create: function(){ |
||||
|
var self = this; |
||||
|
var data = self.data; |
||||
|
|
||||
|
self.el = new Element('li.type').adopt( |
||||
|
new Element('span.quality_type').adopt( |
||||
|
self.fillQualities() |
||||
|
), |
||||
|
new Element('span.finish').adopt( |
||||
|
self.finish = new Element('input', { |
||||
|
'type':'checkbox', |
||||
|
'class':'finish', |
||||
|
'checked': data.finish |
||||
|
}) |
||||
|
), |
||||
|
new Element('span.delete.icon', { |
||||
|
'events': { |
||||
|
'click': self.del.bind(self) |
||||
|
} |
||||
|
}), |
||||
|
new Element('span.handle') |
||||
|
) |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
fillQualities: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.qualities = new Element('select'); |
||||
|
|
||||
|
Object.each(Quality.qualities, function(q){ |
||||
|
new Element('option', { |
||||
|
'text': q.label, |
||||
|
'value': q.id |
||||
|
}).inject(self.qualities) |
||||
|
}); |
||||
|
|
||||
|
self.qualities.set('value', self.data.quality_id); |
||||
|
|
||||
|
return self.qualities; |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
getData: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
return { |
||||
|
'quality_id': self.qualities.get('value'), |
||||
|
'finish': +self.finish.checked |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
del: function(){ |
||||
|
var self = this; |
||||
|
|
||||
|
self.el.addClass('deleted'); |
||||
|
self.el.hide(); |
||||
|
self.deleted = true; |
||||
|
}, |
||||
|
|
||||
|
toElement: function(){ |
||||
|
return this.el; |
||||
|
} |
||||
|
|
||||
|
}) |
@ -1,21 +0,0 @@ |
|||||
/* @override http://localhost:5000/static/style/plugin/quality.css */ |
|
||||
|
|
||||
|
|
||||
.profile > .delete { |
|
||||
background-position: center; |
|
||||
height: 20px; |
|
||||
width: 20px; |
|
||||
} |
|
||||
|
|
||||
.profile .types .type .handle { |
|
||||
background: url('../../images/handle.png') center; |
|
||||
display: inline-block; |
|
||||
height: 20px; |
|
||||
width: 20px; |
|
||||
} |
|
||||
|
|
||||
.profile .types .type .delete { |
|
||||
background-position: center; |
|
||||
height: 20px; |
|
||||
width: 20px; |
|
||||
} |
|
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB |
@ -0,0 +1,51 @@ |
|||||
|
/* |
||||
|
--- |
||||
|
name: Form.CheckGroup |
||||
|
description: Class to represent a group of Form.Check wrapped checkboxes |
||||
|
authors: Bryan J Swift (@bryanjswift) |
||||
|
license: MIT-style license. |
||||
|
requires: [Core/Class.Extras, Core/Element, Core/Element.Event, Form-Replacement/Form.Check] |
||||
|
provides: Form.CheckGroup |
||||
|
... |
||||
|
*/ |
||||
|
if (typeof window.Form === 'undefined') { window.Form = {}; } |
||||
|
|
||||
|
Form.CheckGroup = new Class({ |
||||
|
Implements: [Events,Options], |
||||
|
options: { |
||||
|
checkOptions: {}, |
||||
|
initialValues: {} |
||||
|
}, |
||||
|
checks: [], |
||||
|
initialize: function(group,options) { |
||||
|
if (!Form.Check) { throw 'required Class Form.Check not found'; } |
||||
|
this.setOptions(options); |
||||
|
group = $(group); |
||||
|
if (!group) { return this; } |
||||
|
var checkboxes = group.getElements('input[type=checkbox]'); |
||||
|
checkboxes.each(this.addCheck,this); |
||||
|
}, |
||||
|
addCheck: function(checkbox) { |
||||
|
var initialValues = this.options.initialValues[checkbox.get('name')]; |
||||
|
var checkOptions = {}; |
||||
|
checkOptions.checked = initialValues ? initialValues.contains(checkbox.get('value')) : checkbox.get('checked'); |
||||
|
checkOptions.disabled = checkbox.get('disabled'); |
||||
|
checkbox.store('Form.CheckGroup::data',this); |
||||
|
var check = checkbox.retrieve('Form.Check::data') || new Form.Check(checkbox, Object.append(checkOptions,this.options.checkOptions)); |
||||
|
this.checks.push(check); |
||||
|
}, |
||||
|
checkAll: function() { |
||||
|
this.checks.each(function(check) { if (!check.checked) { check.toggle(); } }); |
||||
|
}, |
||||
|
disable: function() { |
||||
|
this.checks.each(function(check) { check.disable(); }); |
||||
|
this.fireEvent('disable',this); |
||||
|
}, |
||||
|
enable: function() { |
||||
|
this.checks.each(function(check) { check.enable(); }); |
||||
|
this.fireEvent('enable',this); |
||||
|
}, |
||||
|
uncheckAll: function() { |
||||
|
this.checks.each(function(check) { if (check.checked) { check.toggle(); } }); |
||||
|
} |
||||
|
}); |
@ -0,0 +1,59 @@ |
|||||
|
/* |
||||
|
--- |
||||
|
name: Form.RadioGroup |
||||
|
description: Class to represent a group of Form.Radio buttons |
||||
|
authors: Bryan J Swift (@bryanjswift) |
||||
|
license: MIT-style license. |
||||
|
requires: [Core/Class.Extras, Core/Element, Core/Element.Event, Form-Replacement/Form.Radio] |
||||
|
provides: Form.RadioGroup |
||||
|
... |
||||
|
*/ |
||||
|
if (typeof window.Form === 'undefined') { window.Form = {}; } |
||||
|
|
||||
|
Form.RadioGroup = new Class({ |
||||
|
Implements: [Events,Options], |
||||
|
options: { |
||||
|
radioOptions: {}, |
||||
|
initialValues: {} |
||||
|
}, |
||||
|
bound: {}, |
||||
|
radios: [], |
||||
|
value: null, |
||||
|
initialize: function(group,options) { |
||||
|
if (!Form.Radio) { throw 'required Class Form.Radio not found'; } |
||||
|
this.setOptions(options); |
||||
|
this.bound = { select: this.select.bind(this) }; |
||||
|
group = $(group); |
||||
|
if (!group) { return this; } |
||||
|
var radios = group.getElements('input[type=radio]'); |
||||
|
radios.each(this.addCheck,this); |
||||
|
}, |
||||
|
addCheck: function(radio,i) { |
||||
|
var initialValues = this.options.initialValues[radio.get('name')]; |
||||
|
var radioOptions = {}; |
||||
|
radioOptions.checked = initialValues ? initialValues.contains(radio.get('value')) : radio.get('checked'); |
||||
|
radioOptions.disabled = radio.get('disabled'); |
||||
|
var check = (radio.retrieve('Form.Radio::data') |
||||
|
|| new Form.Radio(radio,Object.append(radioOptions,this.options.radioOptions))); |
||||
|
check.addEvent('onCheck',this.bound.select); |
||||
|
if (check.checked) { i ? this.changed(check) : this.value = check.value; } |
||||
|
radio.store('Form.RadioGroup::data',this); |
||||
|
this.radios.push(check); |
||||
|
}, |
||||
|
changed: function(radio) { |
||||
|
this.value = radio.value; |
||||
|
this.fireEvent('onChange',this); |
||||
|
}, |
||||
|
disable: function() { |
||||
|
this.radios.each(function(radio) { radio.disable(); }); |
||||
|
}, |
||||
|
enable: function() { |
||||
|
this.radios.each(function(radio) { radio.enable(); }); |
||||
|
}, |
||||
|
select: function(checkedRadio) { |
||||
|
this.radios.each(function(radio) { |
||||
|
if (radio.checked && radio.value !== checkedRadio.value) { radio.uncheck(); } |
||||
|
}); |
||||
|
if (checkedRadio.value !== this.value) { this.changed(checkedRadio); } |
||||
|
} |
||||
|
}); |
@ -0,0 +1,125 @@ |
|||||
|
/* |
||||
|
--- |
||||
|
name: Form.Check |
||||
|
description: Class to represent a checkbox |
||||
|
authors: Bryan J Swift (@bryanjswift) |
||||
|
license: MIT-style license. |
||||
|
requires: [Core/Class.Extras, Core/Element, Core/Element.Event] |
||||
|
provides: Form.Check |
||||
|
... |
||||
|
*/ |
||||
|
if (typeof window.Form === 'undefined') { window.Form = {}; } |
||||
|
|
||||
|
Form.Check = new Class({ |
||||
|
Implements: [Events, Options], |
||||
|
options: { |
||||
|
checked: false, |
||||
|
disabled: false |
||||
|
}, |
||||
|
bound: {}, |
||||
|
checked: false, |
||||
|
config: { |
||||
|
checkedClass: 'checked', |
||||
|
disabledClass: 'disabled', |
||||
|
elementClass: 'check', |
||||
|
highlightedClass: 'highlighted', |
||||
|
storage: 'Form.Check::data' |
||||
|
}, |
||||
|
disabled: false, |
||||
|
element: null, |
||||
|
input: null, |
||||
|
label: null, |
||||
|
value: null, |
||||
|
initialize: function(input, options) { |
||||
|
this.setOptions(options); |
||||
|
this.bound = { |
||||
|
disable: this.disable.bind(this), |
||||
|
enable: this.enable.bind(this), |
||||
|
highlight: this.highlight.bind(this), |
||||
|
removeHighlight: this.removeHighlight.bind(this), |
||||
|
keyToggle: this.keyToggle.bind(this), |
||||
|
toggle: this.toggle.bind(this) |
||||
|
}; |
||||
|
var bound = this.bound; |
||||
|
input = this.input = $(input); |
||||
|
var id = input.get('id'); |
||||
|
this.label = document.getElement('label[for=' + id + ']'); |
||||
|
this.element = new Element('div', { |
||||
|
'class': input.get('class') + ' ' + this.config.elementClass, |
||||
|
id: id ? id + 'Check' : '', |
||||
|
events: { |
||||
|
click: bound.toggle, |
||||
|
mouseenter: bound.highlight, |
||||
|
mouseleave: bound.removeHighlight |
||||
|
} |
||||
|
}); |
||||
|
this.input.addEvents({ |
||||
|
keypress: bound.keyToggle, |
||||
|
keydown: bound.keyToggle, |
||||
|
keyup: bound.keyToggle |
||||
|
}); |
||||
|
if (this.label) { this.label.addEvent('click', bound.toggle); } |
||||
|
this.element.wraps(input); |
||||
|
this.value = input.get('value'); |
||||
|
if (this.input.checked) { this.check(); } else { this.uncheck(); } |
||||
|
if (this.input.disabled) { this.disable(); } else { this.enable(); } |
||||
|
input.store(this.config.storage, this).addEvents({ |
||||
|
blur: bound.removeHighlight, |
||||
|
focus: bound.highlight |
||||
|
}); |
||||
|
this.fireEvent('create', this); |
||||
|
}, |
||||
|
check: function() { |
||||
|
this.element.addClass(this.config.checkedClass); |
||||
|
this.input.set('checked', 'checked').focus(); |
||||
|
this.checked = true; |
||||
|
this.fireEvent('check', this); |
||||
|
}, |
||||
|
disable: function() { |
||||
|
this.element.addClass(this.config.disabledClass); |
||||
|
this.input.set('disabled', 'disabled'); |
||||
|
this.disabled = true; |
||||
|
this.fireEvent('disable', this); |
||||
|
}, |
||||
|
enable: function() { |
||||
|
this.element.removeClass(this.config.disabledClass); |
||||
|
this.input.erase('disabled'); |
||||
|
this.disabled = false; |
||||
|
this.fireEvent('enable', this); |
||||
|
}, |
||||
|
highlight: function() { |
||||
|
this.element.addClass(this.config.highlightedClass); |
||||
|
this.fireEvent('highlight', this); |
||||
|
}, |
||||
|
removeHighlight: function() { |
||||
|
this.element.removeClass(this.config.highlightedClass); |
||||
|
this.fireEvent('removeHighlight', this); |
||||
|
}, |
||||
|
keyToggle: function(e) { |
||||
|
var evt = new Event(e); |
||||
|
if (evt.key === 'space') { this.toggle(e); } |
||||
|
}, |
||||
|
toggle: function(e) { |
||||
|
var evt; |
||||
|
if (this.disabled) { return this; } |
||||
|
if (e) { |
||||
|
evt = new Event(e).stopPropagation(); |
||||
|
if (evt.target.tagName.toLowerCase() !== 'a') { |
||||
|
evt.stop(); |
||||
|
} |
||||
|
} |
||||
|
if (this.checked) { |
||||
|
this.uncheck(); |
||||
|
} else { |
||||
|
this.check(); |
||||
|
} |
||||
|
this.fireEvent('change', this); |
||||
|
return this; |
||||
|
}, |
||||
|
uncheck: function() { |
||||
|
this.element.removeClass(this.config.checkedClass); |
||||
|
this.input.erase('checked'); |
||||
|
this.checked = false; |
||||
|
this.fireEvent('uncheck', this); |
||||
|
} |
||||
|
}); |
@ -0,0 +1,325 @@ |
|||||
|
/* |
||||
|
--- |
||||
|
name: Form.Dropdown |
||||
|
description: Class to represent a select input |
||||
|
authors: Bryan J Swift (@bryanjswift) |
||||
|
license: MIT-style license. |
||||
|
requires: [Core/Class.Extras, Core/Element, Core/Element.Event, Form-Replacement/Form.SelectOption] |
||||
|
provides: Form.Dropdown |
||||
|
... |
||||
|
*/ |
||||
|
if (typeof window.Form === 'undefined') { window.Form = {}; } |
||||
|
|
||||
|
Form.Dropdown = new Class({ |
||||
|
Implements: [Events,Options], |
||||
|
options: { |
||||
|
excludedValues: [], |
||||
|
initialValue: null, |
||||
|
mouseLeaveDelay: 350, |
||||
|
selectOptions: {}, |
||||
|
typeDelay: 500 |
||||
|
}, |
||||
|
bound: {}, |
||||
|
dropdownOptions: [], |
||||
|
element: null, |
||||
|
events: {}, |
||||
|
highlighted: null, |
||||
|
input: null, |
||||
|
open: true, |
||||
|
selected: null, |
||||
|
selection: null, |
||||
|
typed: { lastKey: null, value: null, timer: null, pressed: null, shortlist: [], startkey: null }, |
||||
|
value: null, |
||||
|
initialize: function(select,options) { |
||||
|
this.setOptions(options); |
||||
|
select = $(select); |
||||
|
this.bound = { |
||||
|
collapse: this.collapse.bind(this), |
||||
|
expand: this.expand.bind(this), |
||||
|
focus: this.focus.bind(this), |
||||
|
highlightOption: this.highlightOption.bind(this), |
||||
|
keydown: this.keydown.bind(this), |
||||
|
keypress: this.keypress.bind(this), |
||||
|
mouseenterDropdown: this.mouseenterDropdown.bind(this), |
||||
|
mouseleaveDropdown: this.mouseleaveDropdown.bind(this), |
||||
|
mousemove: this.mousemove.bind(this), |
||||
|
removeHighlightOption: this.removeHighlightOption.bind(this), |
||||
|
select: this.select.bind(this), |
||||
|
toggle: this.toggle.bind(this) |
||||
|
}; |
||||
|
this.events = { mouseenter: this.bound.mouseenterDropdown, mouseleave: this.bound.mouseleaveDropdown }; |
||||
|
this.value = this.options.initialValue; |
||||
|
this.initializeCreateElements(select); |
||||
|
var optionElements = select.getElements('option'); |
||||
|
this.updateOptions(optionElements); |
||||
|
this.element.replaces(select); |
||||
|
document.addEvent('click', this.bound.collapse); |
||||
|
var eventName = Browser.ie || Browser.webkit ? 'keydown' : 'keypress'; |
||||
|
var target = Browser.ie ? $(document.body) : window; |
||||
|
target.addEvent('keydown',this.bound.keydown).addEvent(eventName,this.bound.keypress); |
||||
|
}, |
||||
|
initializeCreateElements: function(select) { |
||||
|
var id = select.get('id'); |
||||
|
var dropdown = new Element('div', { |
||||
|
'class': (select.get('class') + ' select').trim(), |
||||
|
'id': (id && id !== '') ? id + 'Dropdown' : '' |
||||
|
}); |
||||
|
var menu = new Element('div', {'class': 'menu'}); |
||||
|
var list = new Element('div', {'class': 'list'}); |
||||
|
var options = new Element('ul', {'class': 'options'}); |
||||
|
dropdown.adopt(menu.adopt(list.adopt(options))); |
||||
|
var dropdownSelection = new Element('div', { |
||||
|
'class': 'selection', |
||||
|
events: {click: this.bound.toggle} |
||||
|
}); |
||||
|
var dropdownBackground = new Element('div', { 'class': 'dropdownBackground' }); |
||||
|
var selection = new Element('span', { 'class': 'selectionDisplay' }); |
||||
|
var input = new Element('input', { |
||||
|
type:'text', |
||||
|
id: id, |
||||
|
name: select.get('name'), |
||||
|
events: { |
||||
|
focus: this.bound.focus |
||||
|
} |
||||
|
}); |
||||
|
dropdownSelection.adopt(dropdownBackground, selection, input); |
||||
|
dropdown.adopt(dropdownSelection); |
||||
|
this.element = dropdown; |
||||
|
this.selection = selection; |
||||
|
this.input = input; |
||||
|
return options; |
||||
|
}, |
||||
|
collapse: function(e) { |
||||
|
this.open = false; |
||||
|
this.element.removeClass('active').removeClass('dropdown-active'); |
||||
|
if (this.selected) { this.selected.removeHighlight(); } |
||||
|
this.element.removeEvents(this.events); |
||||
|
this.fireEvent('collapse', [this, e]); |
||||
|
}, |
||||
|
deselect: function(option) { |
||||
|
option.deselect(); |
||||
|
}, |
||||
|
destroy: function() { |
||||
|
this.element = null; |
||||
|
this.selection = null; |
||||
|
this.input = null; |
||||
|
}, |
||||
|
disable: function() { |
||||
|
this.collapse(); |
||||
|
this.input.set('disabled', 'disabled').removeEvents({blur:this.bound.blur, focus:this.bound.focus}); |
||||
|
this.selection.getParent().removeEvent('click', this.bound.toggle); |
||||
|
this.fireEvent('disable', this); |
||||
|
}, |
||||
|
enable: function() { |
||||
|
this.input.erase('disabled').addEvents({blur:this.bound.blur, focus:this.bound.focus}); |
||||
|
this.selection.getParent().addEvent('click', this.bound.toggle); |
||||
|
this.fireEvent('enable', this); |
||||
|
}, |
||||
|
expand: function(e) { |
||||
|
clearTimeout(this.collapseInterval); |
||||
|
var evt = e ? new Event(e).stop() : null; |
||||
|
this.open = true; |
||||
|
this.input.focus(); |
||||
|
this.element.addClass('active').addClass('dropdown-active'); |
||||
|
if (this.selected) { this.selected.highlight(); } |
||||
|
this.element.addEvents(this.events); |
||||
|
this.fireEvent('expand', [this, e]); |
||||
|
}, |
||||
|
focus: function(e) { |
||||
|
this.expand(); |
||||
|
}, |
||||
|
foundMatch: function(e) { |
||||
|
var typed = this.typed; |
||||
|
var shortlist = typed.shortlist; |
||||
|
var value = typed.value; |
||||
|
var i = 0; |
||||
|
var optionsLength = shortlist.length; |
||||
|
var excludedValues = this.options.excludedValues; |
||||
|
var found = false; |
||||
|
if (!optionsLength) { return; } |
||||
|
var option; |
||||
|
do { |
||||
|
option = shortlist[i]; |
||||
|
if (option.text.toLowerCase().indexOf(value) === 0 && !excludedValues.contains(option.value)) { |
||||
|
found = true; |
||||
|
option.highlight(e); |
||||
|
typed.pressed = i + 1; |
||||
|
i = optionsLength; |
||||
|
} |
||||
|
i = i + 1; |
||||
|
} while(i < optionsLength); |
||||
|
return found; |
||||
|
}, |
||||
|
highlightOption: function(option) { |
||||
|
if (this.highlighted) { this.highlighted.removeHighlight(); } |
||||
|
this.highlighted = option; |
||||
|
}, |
||||
|
isOpen: function() { |
||||
|
return this.open; |
||||
|
}, |
||||
|
keydown: function(e) { |
||||
|
if (!this.open) { return; } |
||||
|
this.dropdownOptions.each(function(option) { option.disable(); }); |
||||
|
document.addEvent('mousemove', this.bound.mousemove); |
||||
|
}, |
||||
|
keypress: function(e) { |
||||
|
if (!this.open) { return; } |
||||
|
(e).stop(); |
||||
|
|
||||
|
var code = e.code, key = e.key; |
||||
|
|
||||
|
var typed = this.typed; |
||||
|
var match, i, options, option, optionsLength, found, first, excludedValues, shortlist; |
||||
|
switch(code) { |
||||
|
case 38: // up
|
||||
|
case 37: // left
|
||||
|
if (typed.pressed > 0) { typed.pressed = typed.pressed - 1; } |
||||
|
if (!this.highlighted) { this.dropdownOptions.getLast().highlight(e); break; } |
||||
|
match = this.highlighted.element.getPrevious(); |
||||
|
match = match ? match.retrieve('Form.SelectOption::data') : this.dropdownOptions.getLast(); |
||||
|
match.highlight(e); |
||||
|
break; |
||||
|
case 40: // down
|
||||
|
case 39: // right
|
||||
|
if (typed.shortlist.length > 0) { typed.pressed = typed.pressed + 1; } |
||||
|
if (!this.highlighted) { this.dropdownOptions[0].highlight(e); break; } |
||||
|
match = this.highlighted.element.getNext(); |
||||
|
match = match ? match.retrieve('Form.SelectOption::data') : this.dropdownOptions[0]; |
||||
|
match.highlight(e); |
||||
|
break; |
||||
|
case 13: // enter
|
||||
|
e.stop(); |
||||
|
case 9: // tab - skips the stop event but selects the item
|
||||
|
this.highlighted.select(); |
||||
|
break; |
||||
|
case 27: // esc
|
||||
|
e.stop(); |
||||
|
this.toggle(); |
||||
|
break; |
||||
|
case 32: // space
|
||||
|
default: // anything else
|
||||
|
if (!(code >= 48 && code <= 122 && (code <= 57 || (code >= 65 && code <= 90) || code >=97) || code === 32)) { |
||||
|
break; |
||||
|
} |
||||
|
if (evt.control || evt.alt || evt.meta) { return; } |
||||
|
// alphanumeric or space
|
||||
|
key = code === 32 ? ' ' : key; |
||||
|
clearTimeout(typed.timer); |
||||
|
options = this.dropdownOptions; |
||||
|
optionsLength = options.length; |
||||
|
excludedValues = this.options.excludedValues; |
||||
|
if (typed.timer === null) { // timer is expired
|
||||
|
typed.shortlist = []; |
||||
|
if (key === typed.lastKey || key === typed.startkey) { // get next
|
||||
|
typed.pressed = typed.pressed + 1; |
||||
|
typed.value = key; |
||||
|
} else { // get first
|
||||
|
typed = this.resetTyped(); |
||||
|
typed.value = key; |
||||
|
typed.startkey = key; |
||||
|
typed.pressed = 1; |
||||
|
} |
||||
|
typed.timer = this.resetTyped.delay(500, this); |
||||
|
} else { |
||||
|
if (key === typed.lastKey) { // check for match, if no match get next
|
||||
|
typed.value = typed.value + key; |
||||
|
if (this.foundMatch(e)) { // got a match so break
|
||||
|
typed.timer = this.resetTyped.delay(500, this); |
||||
|
break; |
||||
|
} else { // no match fall through
|
||||
|
typed.shortlist = []; |
||||
|
typed.value = key; |
||||
|
typed.pressed = typed.pressed + 1; |
||||
|
typed.timer = null; |
||||
|
} |
||||
|
} else { // reset timer, get first match, set pressed to found position
|
||||
|
typed.timer = this.resetTyped.delay(500, this); |
||||
|
typed.value = typed.value + key; |
||||
|
typed.startkey = typed.value.substring(0, 1); |
||||
|
typed.lastKey = key; |
||||
|
this.foundMatch(e); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
typed.lastKey = key; |
||||
|
shortlist = typed.shortlist; |
||||
|
i = 0; |
||||
|
found = 0; |
||||
|
do { |
||||
|
option = options[i]; |
||||
|
if (option.text.toLowerCase().indexOf(key) === 0 && !excludedValues.contains(option.value)) { |
||||
|
if (found === 0) { first = option; } |
||||
|
found = found + 1; |
||||
|
if (found === typed.pressed) { option.highlight(e); } |
||||
|
shortlist.push(option); |
||||
|
} |
||||
|
i = i + 1; |
||||
|
} while(i < optionsLength); |
||||
|
if (typed.pressed > found) { |
||||
|
first.highlight(e); |
||||
|
typed.pressed = 1; |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
}, |
||||
|
mouseenterDropdown: function() { |
||||
|
clearTimeout(this.collapseInterval); |
||||
|
}, |
||||
|
mouseleaveDropdown: function() { |
||||
|
this.collapseInterval = this.options.mouseLeaveDelay ? this.collapse.delay(this.options.mouseLeaveDelay,this) : null; |
||||
|
}, |
||||
|
mousemove: function() { |
||||
|
this.dropdownOptions.each(function(option) { option.enable(); }); |
||||
|
document.removeEvent('mousemove', this.bound.mousemove); |
||||
|
}, |
||||
|
removeHighlightOption: function(option) { |
||||
|
this.highlighted = null; |
||||
|
}, |
||||
|
reset: function() { |
||||
|
if (this.options.initialValue) { |
||||
|
this.dropdownOptions.each(function(o) { |
||||
|
if (o.value === this.options.initialValue) { o.select(); } |
||||
|
}, this); |
||||
|
} else { |
||||
|
this.dropdownOptions[0].select(); |
||||
|
} |
||||
|
}, |
||||
|
resetTyped: function() { |
||||
|
var typed = this.typed; |
||||
|
typed.value = null; |
||||
|
typed.timer = null; |
||||
|
return typed; |
||||
|
}, |
||||
|
select: function(option, e) { |
||||
|
this.dropdownOptions.each(this.deselect); |
||||
|
this.selection.set('html', option.element.get('html')); |
||||
|
var oldValue = this.value; |
||||
|
this.value = option.value; |
||||
|
this.input.set('value', option.value); |
||||
|
this.selected = option; |
||||
|
this.fireEvent('select', [this, e]); |
||||
|
if (oldValue && oldValue !== this.value) { this.fireEvent('change', [this, e]); } |
||||
|
this.collapse(e); |
||||
|
}, |
||||
|
toggle: function(e) { |
||||
|
if (this.open) { this.collapse(e); } |
||||
|
else { this.expand(e); } |
||||
|
}, |
||||
|
updateOptions: function(optionElements) { |
||||
|
var optionsList = this.element.getElement('ul').empty(), |
||||
|
dropdownOptions = this.dropdownOptions.empty(), |
||||
|
selectOptions = this.options.selectOptions; |
||||
|
optionElements.each(function(opt) { |
||||
|
var option = new Form.SelectOption(opt, selectOptions); |
||||
|
option.addEvents({ |
||||
|
'onHighlight':this.bound.highlightOption, |
||||
|
'onRemoveHighlight':this.bound.removeHighlightOption, |
||||
|
'onSelect':this.bound.select |
||||
|
}).owner = this; |
||||
|
if (option.value === this.options.initialValue || opt.get('selected')) { this.select(option); } |
||||
|
dropdownOptions.push(option); |
||||
|
optionsList.adopt(option.element); |
||||
|
}, this); |
||||
|
if (!this.selected && optionElements[0]) { optionElements[0].retrieve('Form.SelectOption::data').select(); } |
||||
|
} |
||||
|
}); |
@ -0,0 +1,34 @@ |
|||||
|
/* |
||||
|
--- |
||||
|
name: Form.Radio |
||||
|
description: Class to represent a radio button |
||||
|
authors: Bryan J Swift (@bryanjswift) |
||||
|
license: MIT-style license. |
||||
|
requires: [Core/Class.Extras, Core/Element, Core/Element.Event, Form-Replacement/Form.Check] |
||||
|
provides: Form.Radio |
||||
|
... |
||||
|
*/ |
||||
|
if (typeof window.Form === 'undefined') { window.Form = {}; } |
||||
|
|
||||
|
Form.Radio = new Class({ |
||||
|
Extends: Form.Check, |
||||
|
config: { |
||||
|
elementClass: 'radio', |
||||
|
storage: 'Form.Radio::data' |
||||
|
}, |
||||
|
initialize: function(input,options) { |
||||
|
this.parent(input,options); |
||||
|
}, |
||||
|
toggle: function(e) { |
||||
|
if (this.element.hasClass('checked') || this.disabled) { return; } |
||||
|
var evt; |
||||
|
if (e) { evt = new Event(e).stop(); } |
||||
|
if (this.checked) { |
||||
|
this.uncheck(); |
||||
|
} else { |
||||
|
this.check(); |
||||
|
} |
||||
|
this.fireEvent(this.checked ? 'onCheck' : 'onUncheck',this); |
||||
|
this.fireEvent('onChange',this); |
||||
|
} |
||||
|
}); |
@ -0,0 +1,93 @@ |
|||||
|
/* |
||||
|
--- |
||||
|
name: Form.SelectOption |
||||
|
description: Class to represent an option for Form.Dropdown |
||||
|
authors: Bryan J Swift (@bryanjswift) |
||||
|
license: MIT-style license. |
||||
|
requires: [Core/Class.Extras, Core/Element, Core/Element.Event] |
||||
|
provides: Form.SelectOption |
||||
|
... |
||||
|
*/ |
||||
|
if (typeof window.Form === 'undefined') { window.Form = {}; } |
||||
|
|
||||
|
Form.SelectOption = new Class({ |
||||
|
Implements: [Events, Options], |
||||
|
options: { |
||||
|
optionTag: 'li', |
||||
|
selected: false |
||||
|
}, |
||||
|
config: { |
||||
|
highlightedClass: 'highlighted', |
||||
|
optionClass: 'option', |
||||
|
selectedClass: 'selected' |
||||
|
}, |
||||
|
element: null, |
||||
|
bound: {}, |
||||
|
option: null, |
||||
|
selected: false, |
||||
|
text: null, |
||||
|
value: null, |
||||
|
initialize: function(option, options) { |
||||
|
this.setOptions(options); |
||||
|
option = $(option); |
||||
|
this.option = option; |
||||
|
this.bound = { |
||||
|
deselect: this.deselect.bind(this), |
||||
|
highlight: this.highlight.bind(this), |
||||
|
removeHighlight: this.removeHighlight.bind(this), |
||||
|
select: this.select.bind(this) |
||||
|
}; |
||||
|
this.text = option.get('text'); |
||||
|
this.value = option.get('value'); |
||||
|
this.element = new Element(this.options.optionTag, { |
||||
|
'class': (option.get('class') + ' ' + this.config.optionClass).trim(), |
||||
|
'html': option.get('html'), |
||||
|
'events': { |
||||
|
click: this.bound.select, |
||||
|
mouseenter: this.bound.highlight, |
||||
|
mouseleave: this.bound.removeHighlight |
||||
|
} |
||||
|
}); |
||||
|
this.element.store('Form.SelectOption::data', this); |
||||
|
option.store('Form.SelectOption::data', this); |
||||
|
}, |
||||
|
deselect: function(e) { |
||||
|
this.fireEvent('onDeselect', [this, e]); |
||||
|
this.element.removeClass(this.config.selectedClass).addEvent('click', this.bound.select); |
||||
|
this.selected = false; |
||||
|
}, |
||||
|
destroy: function() { |
||||
|
this.element = null; |
||||
|
this.bound = null; |
||||
|
this.option = null; |
||||
|
}, |
||||
|
disable: function() { |
||||
|
this.element.removeEvents({ |
||||
|
mouseenter: this.bound.highlight, |
||||
|
mouseleave: this.bound.removeHighlight |
||||
|
}); |
||||
|
this.fireEvent('onDisable', this); |
||||
|
}, |
||||
|
enable: function() { |
||||
|
this.element.addEvents({ |
||||
|
mouseenter: this.bound.highlight, |
||||
|
mouseleave: this.bound.removeHighlight |
||||
|
}); |
||||
|
this.fireEvent('onEnable', this); |
||||
|
}, |
||||
|
highlight: function(e) { |
||||
|
this.fireEvent('onHighlight', [this, e]); |
||||
|
this.element.addClass(this.config.highlightedClass); |
||||
|
return this; |
||||
|
}, |
||||
|
removeHighlight: function(e) { |
||||
|
this.fireEvent('onRemoveHighlight', [this, e]); |
||||
|
this.element.removeClass(this.config.highlightedClass); |
||||
|
return this; |
||||
|
}, |
||||
|
select: function(e) { |
||||
|
this.fireEvent('onSelect', [this, e]); |
||||
|
this.element.addClass(this.config.selectedClass).removeEvent('click', this.bound.select); |
||||
|
this.selected = true; |
||||
|
} |
||||
|
}); |
@ -1,134 +0,0 @@ |
|||||
/* @override http://localhost:5000/static/style/page/wanted.css */ |
|
||||
|
|
||||
.page.wanted .movies { |
|
||||
padding: 20px 0; |
|
||||
} |
|
||||
|
|
||||
.page.wanted .movie { |
|
||||
overflow: hidden; |
|
||||
position: relative; |
|
||||
background: #999; |
|
||||
|
|
||||
border-radius: 4px; |
|
||||
-moz-border-radius: 4px; |
|
||||
-webkit-border-radius: 4px; |
|
||||
margin: 10px 0; |
|
||||
border: 1px solid #fff; |
|
||||
border-color: #eee #fff #fff #eee; |
|
||||
background: #ddd; |
|
||||
} |
|
||||
.page.wanted .movie:hover { |
|
||||
border-color: #ddd #fff #fff #ddd; |
|
||||
} |
|
||||
.page.wanted .movie:hover .data { |
|
||||
background: #f5f5f5; |
|
||||
} |
|
||||
.page.wanted .data { |
|
||||
padding: 2%; |
|
||||
position: absolute; |
|
||||
width: 96.1%; |
|
||||
top: 0; |
|
||||
left: 0; |
|
||||
background: #f9f9f9; |
|
||||
} |
|
||||
.page.wanted .data:after { |
|
||||
content: ""; |
|
||||
display: block; |
|
||||
height: 0; |
|
||||
clear: both; |
|
||||
visibility: hidden; |
|
||||
} |
|
||||
.page.wanted .data .poster, .page.wanted .options .poster { |
|
||||
overflow: hidden; |
|
||||
float: left; |
|
||||
max-width: 10%; |
|
||||
margin: 0 2% 0 0; |
|
||||
border-radius:3px; |
|
||||
-moz-border-radius: 3px; |
|
||||
-webkit-border-radius: 3px; |
|
||||
-moz-box-shadow: 0 0 10px rgba(0,0,0,0.35); |
|
||||
-webkit-box-shadow: 0 0 10px rgba(0,0,0,0.35); |
|
||||
line-height: 0; |
|
||||
} |
|
||||
|
|
||||
.page.wanted .info { |
|
||||
float: right; |
|
||||
width: 88%; |
|
||||
} |
|
||||
|
|
||||
.page.wanted .info .title { |
|
||||
font-size: 30px; |
|
||||
font-weight: bold; |
|
||||
margin-bottom: 10px; |
|
||||
float: left; |
|
||||
width: 80%; |
|
||||
} |
|
||||
|
|
||||
.page.wanted .info .year { |
|
||||
font-size: 30px; |
|
||||
margin-bottom: 10px; |
|
||||
float: right; |
|
||||
color: #bbb; |
|
||||
width: 10%; |
|
||||
text-align: right; |
|
||||
} |
|
||||
|
|
||||
.page.wanted .info .rating { |
|
||||
font-size: 30px; |
|
||||
margin-bottom: 10px; |
|
||||
color: #444; |
|
||||
float: left; |
|
||||
width: 5%; |
|
||||
padding: 0 0 0 3%; |
|
||||
background: url('../../images/rating.png') no-repeat left center; |
|
||||
} |
|
||||
|
|
||||
.page.wanted .info .description { |
|
||||
clear: both; |
|
||||
width: 95%; |
|
||||
} |
|
||||
.page.wanted .data .actions { |
|
||||
position: absolute; |
|
||||
right: 15px; |
|
||||
bottom: 15px; |
|
||||
line-height: 0; |
|
||||
} |
|
||||
.page.wanted .data:hover .action { opacity: 0.6; } |
|
||||
.page.wanted .data:hover .action:hover { opacity: 1; } |
|
||||
|
|
||||
.page.wanted .data .action { |
|
||||
background: no-repeat center; |
|
||||
display: inline-block; |
|
||||
width: 20px; |
|
||||
height: 20px; |
|
||||
padding: 3px; |
|
||||
opacity: 0; |
|
||||
} |
|
||||
.page.wanted .data .action.refresh { background-image: url('../../images/reload.png'); } |
|
||||
.page.wanted .data .action.delete { background-image: url('../../images/delete.png'); } |
|
||||
.page.wanted .data .action.edit { background-image: url('../../images/edit.png'); } |
|
||||
.page.wanted .data .action.imdb { background-image: url('../../images/imdb.png'); } |
|
||||
|
|
||||
.page.wanted .delete_container { |
|
||||
clear: both; |
|
||||
text-align: center; |
|
||||
font-size: 20px; |
|
||||
position: relative; |
|
||||
} |
|
||||
.page.wanted .delete_container .cancel { |
|
||||
} |
|
||||
.page.wanted .delete_container .or { |
|
||||
padding: 10px; |
|
||||
} |
|
||||
.page.wanted .delete_container .delete { |
|
||||
background-color: #ff321c; |
|
||||
font-weight: normal; |
|
||||
} |
|
||||
.page.wanted .delete_container .delete:hover { |
|
||||
color: #fff; |
|
||||
background-color: #d32917; |
|
||||
} |
|
||||
|
|
||||
.page.wanted .options { |
|
||||
padding: 2%; |
|
||||
} |
|
Loading…
Reference in new issue