Notifications
This commit is contained in:
@@ -34,6 +34,7 @@ Block.Search = new Class({
|
||||
self.spinner = new Spinner(self.result_container);
|
||||
|
||||
self.OuterClickStack = new EventStack.OuterClick();
|
||||
History.addEvent('change', self.hideResults.bind(self, true));
|
||||
|
||||
//debug
|
||||
//self.input.set('value', 'kick ass')
|
||||
@@ -126,16 +127,16 @@ Block.Search = new Class({
|
||||
|
||||
Object.each(json.movies, function(movie){
|
||||
|
||||
if(!movie.imdb || (movie.imdb && !self.results.getElement('#'+movie.imdb))){
|
||||
// if(!movie.imdb || (movie.imdb && !self.results.getElement('#'+movie.imdb))){
|
||||
var m = new Block.Search.Item(movie);
|
||||
$(m).inject(self.results)
|
||||
self.movies[movie.imdb || 'r-'+Math.floor(Math.random()*10000)] = m
|
||||
}
|
||||
else {
|
||||
self.movies[movie.imdb].alternativeName({
|
||||
'name': movie.name
|
||||
})
|
||||
}
|
||||
// }
|
||||
// else {
|
||||
// self.movies[movie.imdb].alternativeTitle({
|
||||
// 'title': movie.title
|
||||
// })
|
||||
// }
|
||||
|
||||
});
|
||||
|
||||
@@ -157,7 +158,7 @@ Block.Search.Item = new Class({
|
||||
var self = this;
|
||||
|
||||
self.info = info;
|
||||
self.alternative_names = [];
|
||||
self.alternative_titles = [];
|
||||
|
||||
self.create();
|
||||
|
||||
@@ -167,7 +168,7 @@ Block.Search.Item = new Class({
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
var info = self.info
|
||||
var info = self.info;
|
||||
|
||||
self.el = new Element('div.movie', {
|
||||
'id': info.imdb
|
||||
@@ -182,12 +183,12 @@ Block.Search.Item = new Class({
|
||||
'click': self.showOptions.bind(self)
|
||||
}
|
||||
}).adopt(
|
||||
self.thumbnail = info.poster ? new Element('img.thumbnail', {
|
||||
'src': info.poster
|
||||
self.thumbnail = info.images.posters.length > 0 ? new Element('img.thumbnail', {
|
||||
'src': info.images.posters[0]
|
||||
}) : null,
|
||||
new Element('div.info').adopt(
|
||||
self.name = new Element('h2', {
|
||||
'text': info.name
|
||||
self.title = new Element('h2', {
|
||||
'text': info.titles[0]
|
||||
}).adopt(
|
||||
self.year = info.year ? new Element('span', {
|
||||
'text': info.year
|
||||
@@ -214,15 +215,18 @@ Block.Search.Item = new Class({
|
||||
})
|
||||
}
|
||||
|
||||
self.alternativeName({
|
||||
'name': info.name
|
||||
});
|
||||
|
||||
info.titles.each(function(title){
|
||||
self.alternativeTitle({
|
||||
'title': title
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
alternativeName: function(alternative){
|
||||
alternativeTitle: function(alternative){
|
||||
var self = this;
|
||||
|
||||
self.alternative_names.include(alternative);
|
||||
self.alternative_titles.include(alternative);
|
||||
},
|
||||
|
||||
showOptions: function(){
|
||||
@@ -246,8 +250,8 @@ Block.Search.Item = new Class({
|
||||
Api.request('movie.add', {
|
||||
'data': {
|
||||
'identifier': self.info.imdb,
|
||||
'name': self.name_select.get('value'),
|
||||
'quality': self.quality_select.get('value')
|
||||
'title': self.title_select.get('value'),
|
||||
'profile_id': self.profile_select.get('value')
|
||||
},
|
||||
'useSpinner': true,
|
||||
'spinnerTarget': self.options,
|
||||
@@ -277,14 +281,14 @@ Block.Search.Item = new Class({
|
||||
|
||||
self.options.adopt(
|
||||
new Element('div').adopt(
|
||||
self.info.poster ? new Element('img.thumbnail', {
|
||||
'src': self.info.poster
|
||||
self.info.images.posters.length > 0 ? new Element('img.thumbnail', {
|
||||
'src': self.info.images.posters[0]
|
||||
}) : null,
|
||||
self.name_select = new Element('select', {
|
||||
'name': 'name'
|
||||
self.title_select = new Element('select', {
|
||||
'name': 'title'
|
||||
}),
|
||||
self.quality_select = new Element('select', {
|
||||
'name': 'profile_identifier'
|
||||
self.profile_select = new Element('select', {
|
||||
'name': 'profile'
|
||||
}),
|
||||
new Element('a.button', {
|
||||
'text': 'Add',
|
||||
@@ -295,17 +299,17 @@ Block.Search.Item = new Class({
|
||||
)
|
||||
);
|
||||
|
||||
Array.each(self.alternative_names, function(alt){
|
||||
Array.each(self.alternative_titles, function(alt){
|
||||
new Element('option', {
|
||||
'text': alt.name
|
||||
}).inject(self.name_select)
|
||||
'text': alt.title
|
||||
}).inject(self.title_select)
|
||||
})
|
||||
|
||||
Array.each(Quality.profiles, function(q){
|
||||
Array.each(Quality.profiles, function(profile){
|
||||
new Element('option', {
|
||||
'value': q.indentifier,
|
||||
'text': q.label
|
||||
}).inject(self.quality_select)
|
||||
'value': profile.id ? profile.id : profile.data.id,
|
||||
'text': profile.label ? profile.label : profile.data.label
|
||||
}).inject(self.profile_select)
|
||||
});
|
||||
|
||||
self.options.addClass('set');
|
||||
|
||||
@@ -114,8 +114,8 @@ var ApiClass = new Class({
|
||||
}, options)).send()
|
||||
},
|
||||
|
||||
createUrl: function(action){
|
||||
return this.options.url + (action || 'default') + '/'
|
||||
createUrl: function(action, params){
|
||||
return this.options.url + (action || 'default') + '/' + (params ? '?'+Object.toQueryString(params) : '')
|
||||
},
|
||||
|
||||
getOption: function(name){
|
||||
@@ -186,6 +186,17 @@ var p = function(){
|
||||
console.log(arguments)
|
||||
};
|
||||
|
||||
function randomString(length, extra) {
|
||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz" + (extra ? '-._!@#$%^&*()+=' : '');
|
||||
var stringLength = length || 8;
|
||||
var randomString = '';
|
||||
for (var i = 0; i < stringLength; i++) {
|
||||
var rnum = Math.floor(Math.random() * chars.length);
|
||||
randomString += chars.charAt(rnum);
|
||||
}
|
||||
return randomString;
|
||||
}
|
||||
|
||||
(function(){
|
||||
|
||||
var keyPaths = [];
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
var File = new Class({
|
||||
|
||||
initialize: function(file){
|
||||
var self = this;
|
||||
|
||||
self.data = file;
|
||||
self.type = File.Type.get(file.type_id);
|
||||
|
||||
self['create'+(self.type.type).capitalize()]()
|
||||
|
||||
},
|
||||
|
||||
createImage: function(){
|
||||
var self = this;
|
||||
|
||||
self.el = new Element('div.type_image').adopt(
|
||||
new Element('img', {
|
||||
'src': Api.createUrl('file.cache') + self.data.path.substring(1) + '/'
|
||||
})
|
||||
)
|
||||
},
|
||||
|
||||
toElement: function(){
|
||||
return this.el;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var FileSelect = new Class({
|
||||
|
||||
multiple: function(type, files, single){
|
||||
|
||||
var results = files.filter(function(file){
|
||||
return file.type_id == File.Type.get(type).id;
|
||||
});
|
||||
|
||||
if(single){
|
||||
results = new File(results.pop());
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
|
||||
return results;
|
||||
|
||||
},
|
||||
|
||||
single: function(type, files){
|
||||
return this.multiple(type, files, true);
|
||||
}
|
||||
|
||||
});
|
||||
window.File.Select = new FileSelect();
|
||||
|
||||
var FileTypeBase = new Class({
|
||||
|
||||
setup: function(types){
|
||||
var self = this;
|
||||
|
||||
self.typesById = {};
|
||||
self.typesByKey = {};
|
||||
Object.each(types, function(type){
|
||||
self.typesByKey[type.identifier] = type;
|
||||
self.typesById[type.id] = type;
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
get: function(identifier){
|
||||
if(typeOf(identifier) == 'number')
|
||||
return this.typesById[identifier]
|
||||
else
|
||||
return this.typesByKey[identifier]
|
||||
}
|
||||
|
||||
});
|
||||
window.File.Type = new FileTypeBase();
|
||||
@@ -3,10 +3,10 @@
|
||||
MooTools: the javascript framework
|
||||
|
||||
web build:
|
||||
- http://mootools.net/core/bd6349d3fbc489736e5aefb01157c8a8
|
||||
- http://mootools.net/core/c1215700e7dedaa9d48503126daf2111
|
||||
|
||||
packager build:
|
||||
- packager build Core/Class Core/Class.Extras Core/Element Core/Element.Style Core/Element.Dimensions Core/Fx.Tween Core/Fx.Transitions Core/Request.JSON Core/DOMReady
|
||||
- packager build Core/Class Core/Class.Extras Core/Element Core/Element.Style Core/Element.Dimensions Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request.JSON Core/DOMReady
|
||||
|
||||
/*
|
||||
---
|
||||
@@ -4085,6 +4085,85 @@ Element.implement({
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
---
|
||||
|
||||
name: Fx.Morph
|
||||
|
||||
description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules.
|
||||
|
||||
license: MIT-style license.
|
||||
|
||||
requires: Fx.CSS
|
||||
|
||||
provides: Fx.Morph
|
||||
|
||||
...
|
||||
*/
|
||||
|
||||
Fx.Morph = new Class({
|
||||
|
||||
Extends: Fx.CSS,
|
||||
|
||||
initialize: function(element, options){
|
||||
this.element = this.subject = document.id(element);
|
||||
this.parent(options);
|
||||
},
|
||||
|
||||
set: function(now){
|
||||
if (typeof now == 'string') now = this.search(now);
|
||||
for (var p in now) this.render(this.element, p, now[p], this.options.unit);
|
||||
return this;
|
||||
},
|
||||
|
||||
compute: function(from, to, delta){
|
||||
var now = {};
|
||||
for (var p in from) now[p] = this.parent(from[p], to[p], delta);
|
||||
return now;
|
||||
},
|
||||
|
||||
start: function(properties){
|
||||
if (!this.check(properties)) return this;
|
||||
if (typeof properties == 'string') properties = this.search(properties);
|
||||
var from = {}, to = {};
|
||||
for (var p in properties){
|
||||
var parsed = this.prepare(this.element, p, properties[p]);
|
||||
from[p] = parsed.from;
|
||||
to[p] = parsed.to;
|
||||
}
|
||||
return this.parent(from, to);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Element.Properties.morph = {
|
||||
|
||||
set: function(options){
|
||||
this.get('morph').cancel().setOptions(options);
|
||||
return this;
|
||||
},
|
||||
|
||||
get: function(){
|
||||
var morph = this.retrieve('morph');
|
||||
if (!morph){
|
||||
morph = new Fx.Morph(this, {link: 'cancel'});
|
||||
this.store('morph', morph);
|
||||
}
|
||||
return morph;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Element.implement({
|
||||
|
||||
morph: function(props){
|
||||
this.get('morph').start(props);
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// MooTools: the javascript framework.
|
||||
// Load this file's selection again by visiting: http://mootools.net/more/a6033a03c64d978cd0033a1d420e16e0
|
||||
// Or build this file again with packager using: packager build More/Element.Forms More/Element.Delegation More/Element.Shortcuts More/Request.JSONP More/Spinner
|
||||
// Load this file's selection again by visiting: http://mootools.net/more/2b832e45b9bf2f9e5fdbdafc9b16febf
|
||||
// Or build this file again with packager using: packager build More/Element.Forms More/Element.Delegation More/Element.Shortcuts More/Fx.Slide More/Sortables More/Request.JSONP More/Spinner
|
||||
/*
|
||||
---
|
||||
|
||||
@@ -767,6 +767,849 @@ Document.implement({
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
---
|
||||
|
||||
script: Fx.Slide.js
|
||||
|
||||
name: Fx.Slide
|
||||
|
||||
description: Effect to slide an element in and out of view.
|
||||
|
||||
license: MIT-style license
|
||||
|
||||
authors:
|
||||
- Valerio Proietti
|
||||
|
||||
requires:
|
||||
- Core/Fx
|
||||
- Core/Element.Style
|
||||
- /MooTools.More
|
||||
|
||||
provides: [Fx.Slide]
|
||||
|
||||
...
|
||||
*/
|
||||
|
||||
Fx.Slide = new Class({
|
||||
|
||||
Extends: Fx,
|
||||
|
||||
options: {
|
||||
mode: 'vertical',
|
||||
wrapper: false,
|
||||
hideOverflow: true,
|
||||
resetHeight: false
|
||||
},
|
||||
|
||||
initialize: function(element, options){
|
||||
element = this.element = this.subject = document.id(element);
|
||||
this.parent(options);
|
||||
options = this.options;
|
||||
|
||||
var wrapper = element.retrieve('wrapper'),
|
||||
styles = element.getStyles('margin', 'position', 'overflow');
|
||||
|
||||
if (options.hideOverflow) styles = Object.append(styles, {overflow: 'hidden'});
|
||||
if (options.wrapper) wrapper = document.id(options.wrapper).setStyles(styles);
|
||||
|
||||
if (!wrapper) wrapper = new Element('div', {
|
||||
styles: styles
|
||||
}).wraps(element);
|
||||
|
||||
element.store('wrapper', wrapper).setStyle('margin', 0);
|
||||
if (element.getStyle('overflow') == 'visible') element.setStyle('overflow', 'hidden');
|
||||
|
||||
this.now = [];
|
||||
this.open = true;
|
||||
this.wrapper = wrapper;
|
||||
|
||||
this.addEvent('complete', function(){
|
||||
this.open = (wrapper['offset' + this.layout.capitalize()] != 0);
|
||||
if (this.open && options.resetHeight) wrapper.setStyle('height', '');
|
||||
}, true);
|
||||
},
|
||||
|
||||
vertical: function(){
|
||||
this.margin = 'margin-top';
|
||||
this.layout = 'height';
|
||||
this.offset = this.element.offsetHeight;
|
||||
},
|
||||
|
||||
horizontal: function(){
|
||||
this.margin = 'margin-left';
|
||||
this.layout = 'width';
|
||||
this.offset = this.element.offsetWidth;
|
||||
},
|
||||
|
||||
set: function(now){
|
||||
this.element.setStyle(this.margin, now[0]);
|
||||
this.wrapper.setStyle(this.layout, now[1]);
|
||||
return this;
|
||||
},
|
||||
|
||||
compute: function(from, to, delta){
|
||||
return [0, 1].map(function(i){
|
||||
return Fx.compute(from[i], to[i], delta);
|
||||
});
|
||||
},
|
||||
|
||||
start: function(how, mode){
|
||||
if (!this.check(how, mode)) return this;
|
||||
this[mode || this.options.mode]();
|
||||
|
||||
var margin = this.element.getStyle(this.margin).toInt(),
|
||||
layout = this.wrapper.getStyle(this.layout).toInt(),
|
||||
caseIn = [[margin, layout], [0, this.offset]],
|
||||
caseOut = [[margin, layout], [-this.offset, 0]],
|
||||
start;
|
||||
|
||||
switch (how){
|
||||
case 'in': start = caseIn; break;
|
||||
case 'out': start = caseOut; break;
|
||||
case 'toggle': start = (layout == 0) ? caseIn : caseOut;
|
||||
}
|
||||
return this.parent(start[0], start[1]);
|
||||
},
|
||||
|
||||
slideIn: function(mode){
|
||||
return this.start('in', mode);
|
||||
},
|
||||
|
||||
slideOut: function(mode){
|
||||
return this.start('out', mode);
|
||||
},
|
||||
|
||||
hide: function(mode){
|
||||
this[mode || this.options.mode]();
|
||||
this.open = false;
|
||||
return this.set([-this.offset, 0]);
|
||||
},
|
||||
|
||||
show: function(mode){
|
||||
this[mode || this.options.mode]();
|
||||
this.open = true;
|
||||
return this.set([0, this.offset]);
|
||||
},
|
||||
|
||||
toggle: function(mode){
|
||||
return this.start('toggle', mode);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Element.Properties.slide = {
|
||||
|
||||
set: function(options){
|
||||
this.get('slide').cancel().setOptions(options);
|
||||
return this;
|
||||
},
|
||||
|
||||
get: function(){
|
||||
var slide = this.retrieve('slide');
|
||||
if (!slide){
|
||||
slide = new Fx.Slide(this, {link: 'cancel'});
|
||||
this.store('slide', slide);
|
||||
}
|
||||
return slide;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Element.implement({
|
||||
|
||||
slide: function(how, mode){
|
||||
how = how || 'toggle';
|
||||
var slide = this.get('slide'), toggle;
|
||||
switch (how){
|
||||
case 'hide': slide.hide(mode); break;
|
||||
case 'show': slide.show(mode); break;
|
||||
case 'toggle':
|
||||
var flag = this.retrieve('slide:flag', slide.open);
|
||||
slide[flag ? 'slideOut' : 'slideIn'](mode);
|
||||
this.store('slide:flag', !flag);
|
||||
toggle = true;
|
||||
break;
|
||||
default: slide.start(how, mode);
|
||||
}
|
||||
if (!toggle) this.eliminate('slide:flag');
|
||||
return this;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
---
|
||||
|
||||
script: Drag.js
|
||||
|
||||
name: Drag
|
||||
|
||||
description: The base Drag Class. Can be used to drag and resize Elements using mouse events.
|
||||
|
||||
license: MIT-style license
|
||||
|
||||
authors:
|
||||
- Valerio Proietti
|
||||
- Tom Occhinno
|
||||
- Jan Kassens
|
||||
|
||||
requires:
|
||||
- Core/Events
|
||||
- Core/Options
|
||||
- Core/Element.Event
|
||||
- Core/Element.Style
|
||||
- Core/Element.Dimensions
|
||||
- /MooTools.More
|
||||
|
||||
provides: [Drag]
|
||||
...
|
||||
|
||||
*/
|
||||
|
||||
var Drag = new Class({
|
||||
|
||||
Implements: [Events, Options],
|
||||
|
||||
options: {/*
|
||||
onBeforeStart: function(thisElement){},
|
||||
onStart: function(thisElement, event){},
|
||||
onSnap: function(thisElement){},
|
||||
onDrag: function(thisElement, event){},
|
||||
onCancel: function(thisElement){},
|
||||
onComplete: function(thisElement, event){},*/
|
||||
snap: 6,
|
||||
unit: 'px',
|
||||
grid: false,
|
||||
style: true,
|
||||
limit: false,
|
||||
handle: false,
|
||||
invert: false,
|
||||
preventDefault: false,
|
||||
stopPropagation: false,
|
||||
modifiers: {x: 'left', y: 'top'}
|
||||
},
|
||||
|
||||
initialize: function(){
|
||||
var params = Array.link(arguments, {
|
||||
'options': Type.isObject,
|
||||
'element': function(obj){
|
||||
return obj != null;
|
||||
}
|
||||
});
|
||||
|
||||
this.element = document.id(params.element);
|
||||
this.document = this.element.getDocument();
|
||||
this.setOptions(params.options || {});
|
||||
var htype = typeOf(this.options.handle);
|
||||
this.handles = ((htype == 'array' || htype == 'collection') ? $$(this.options.handle) : document.id(this.options.handle)) || this.element;
|
||||
this.mouse = {'now': {}, 'pos': {}};
|
||||
this.value = {'start': {}, 'now': {}};
|
||||
|
||||
this.selection = (Browser.ie) ? 'selectstart' : 'mousedown';
|
||||
|
||||
|
||||
if (Browser.ie && !Drag.ondragstartFixed){
|
||||
document.ondragstart = Function.from(false);
|
||||
Drag.ondragstartFixed = true;
|
||||
}
|
||||
|
||||
this.bound = {
|
||||
start: this.start.bind(this),
|
||||
check: this.check.bind(this),
|
||||
drag: this.drag.bind(this),
|
||||
stop: this.stop.bind(this),
|
||||
cancel: this.cancel.bind(this),
|
||||
eventStop: Function.from(false)
|
||||
};
|
||||
this.attach();
|
||||
},
|
||||
|
||||
attach: function(){
|
||||
this.handles.addEvent('mousedown', this.bound.start);
|
||||
return this;
|
||||
},
|
||||
|
||||
detach: function(){
|
||||
this.handles.removeEvent('mousedown', this.bound.start);
|
||||
return this;
|
||||
},
|
||||
|
||||
start: function(event){
|
||||
var options = this.options;
|
||||
|
||||
if (event.rightClick) return;
|
||||
|
||||
if (options.preventDefault) event.preventDefault();
|
||||
if (options.stopPropagation) event.stopPropagation();
|
||||
this.mouse.start = event.page;
|
||||
|
||||
this.fireEvent('beforeStart', this.element);
|
||||
|
||||
var limit = options.limit;
|
||||
this.limit = {x: [], y: []};
|
||||
|
||||
var styles = this.element.getStyles('left', 'right', 'top', 'bottom');
|
||||
this._invert = {
|
||||
x: options.modifiers.x == 'left' && styles.left == 'auto' && !isNaN(styles.right.toInt()) && (options.modifiers.x = 'right'),
|
||||
y: options.modifiers.y == 'top' && styles.top == 'auto' && !isNaN(styles.bottom.toInt()) && (options.modifiers.y = 'bottom')
|
||||
};
|
||||
|
||||
var z, coordinates;
|
||||
for (z in options.modifiers){
|
||||
if (!options.modifiers[z]) continue;
|
||||
|
||||
var style = this.element.getStyle(options.modifiers[z]);
|
||||
|
||||
// Some browsers (IE and Opera) don't always return pixels.
|
||||
if (style && !style.match(/px$/)){
|
||||
if (!coordinates) coordinates = this.element.getCoordinates(this.element.getOffsetParent());
|
||||
style = coordinates[options.modifiers[z]];
|
||||
}
|
||||
|
||||
if (options.style) this.value.now[z] = (style || 0).toInt();
|
||||
else this.value.now[z] = this.element[options.modifiers[z]];
|
||||
|
||||
if (options.invert) this.value.now[z] *= -1;
|
||||
if (this._invert[z]) this.value.now[z] *= -1;
|
||||
|
||||
this.mouse.pos[z] = event.page[z] - this.value.now[z];
|
||||
|
||||
if (limit && limit[z]){
|
||||
var i = 2;
|
||||
while (i--){
|
||||
var limitZI = limit[z][i];
|
||||
if (limitZI || limitZI === 0) this.limit[z][i] = (typeof limitZI == 'function') ? limitZI() : limitZI;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeOf(this.options.grid) == 'number') this.options.grid = {
|
||||
x: this.options.grid,
|
||||
y: this.options.grid
|
||||
};
|
||||
|
||||
var events = {
|
||||
mousemove: this.bound.check,
|
||||
mouseup: this.bound.cancel
|
||||
};
|
||||
events[this.selection] = this.bound.eventStop;
|
||||
this.document.addEvents(events);
|
||||
},
|
||||
|
||||
check: function(event){
|
||||
if (this.options.preventDefault) event.preventDefault();
|
||||
var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2)));
|
||||
if (distance > this.options.snap){
|
||||
this.cancel();
|
||||
this.document.addEvents({
|
||||
mousemove: this.bound.drag,
|
||||
mouseup: this.bound.stop
|
||||
});
|
||||
this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element);
|
||||
}
|
||||
},
|
||||
|
||||
drag: function(event){
|
||||
var options = this.options;
|
||||
|
||||
if (options.preventDefault) event.preventDefault();
|
||||
this.mouse.now = event.page;
|
||||
|
||||
for (var z in options.modifiers){
|
||||
if (!options.modifiers[z]) continue;
|
||||
this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];
|
||||
|
||||
if (options.invert) this.value.now[z] *= -1;
|
||||
if (this._invert[z]) this.value.now[z] *= -1;
|
||||
|
||||
if (options.limit && this.limit[z]){
|
||||
if ((this.limit[z][1] || this.limit[z][1] === 0) && (this.value.now[z] > this.limit[z][1])){
|
||||
this.value.now[z] = this.limit[z][1];
|
||||
} else if ((this.limit[z][0] || this.limit[z][0] === 0) && (this.value.now[z] < this.limit[z][0])){
|
||||
this.value.now[z] = this.limit[z][0];
|
||||
}
|
||||
}
|
||||
|
||||
if (options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % options.grid[z]);
|
||||
|
||||
if (options.style) this.element.setStyle(options.modifiers[z], this.value.now[z] + options.unit);
|
||||
else this.element[options.modifiers[z]] = this.value.now[z];
|
||||
}
|
||||
|
||||
this.fireEvent('drag', [this.element, event]);
|
||||
},
|
||||
|
||||
cancel: function(event){
|
||||
this.document.removeEvents({
|
||||
mousemove: this.bound.check,
|
||||
mouseup: this.bound.cancel
|
||||
});
|
||||
if (event){
|
||||
this.document.removeEvent(this.selection, this.bound.eventStop);
|
||||
this.fireEvent('cancel', this.element);
|
||||
}
|
||||
},
|
||||
|
||||
stop: function(event){
|
||||
var events = {
|
||||
mousemove: this.bound.drag,
|
||||
mouseup: this.bound.stop
|
||||
};
|
||||
events[this.selection] = this.bound.eventStop;
|
||||
this.document.removeEvents(events);
|
||||
if (event) this.fireEvent('complete', [this.element, event]);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Element.implement({
|
||||
|
||||
makeResizable: function(options){
|
||||
var drag = new Drag(this, Object.merge({
|
||||
modifiers: {
|
||||
x: 'width',
|
||||
y: 'height'
|
||||
}
|
||||
}, options));
|
||||
|
||||
this.store('resizer', drag);
|
||||
return drag.addEvent('drag', function(){
|
||||
this.fireEvent('resize', drag);
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
---
|
||||
|
||||
script: Drag.Move.js
|
||||
|
||||
name: Drag.Move
|
||||
|
||||
description: A Drag extension that provides support for the constraining of draggables to containers and droppables.
|
||||
|
||||
license: MIT-style license
|
||||
|
||||
authors:
|
||||
- Valerio Proietti
|
||||
- Tom Occhinno
|
||||
- Jan Kassens
|
||||
- Aaron Newton
|
||||
- Scott Kyle
|
||||
|
||||
requires:
|
||||
- Core/Element.Dimensions
|
||||
- /Drag
|
||||
|
||||
provides: [Drag.Move]
|
||||
|
||||
...
|
||||
*/
|
||||
|
||||
Drag.Move = new Class({
|
||||
|
||||
Extends: Drag,
|
||||
|
||||
options: {/*
|
||||
onEnter: function(thisElement, overed){},
|
||||
onLeave: function(thisElement, overed){},
|
||||
onDrop: function(thisElement, overed, event){},*/
|
||||
droppables: [],
|
||||
container: false,
|
||||
precalculate: false,
|
||||
includeMargins: true,
|
||||
checkDroppables: true
|
||||
},
|
||||
|
||||
initialize: function(element, options){
|
||||
this.parent(element, options);
|
||||
element = this.element;
|
||||
|
||||
this.droppables = $$(this.options.droppables);
|
||||
this.container = document.id(this.options.container);
|
||||
|
||||
if (this.container && typeOf(this.container) != 'element')
|
||||
this.container = document.id(this.container.getDocument().body);
|
||||
|
||||
if (this.options.style){
|
||||
if (this.options.modifiers.x == "left" && this.options.modifiers.y == "top"){
|
||||
var parentStyles,
|
||||
parent = element.getOffsetParent();
|
||||
var styles = element.getStyles('left', 'top');
|
||||
if (parent && (styles.left == 'auto' || styles.top == 'auto')){
|
||||
element.setPosition(element.getPosition(parent));
|
||||
}
|
||||
}
|
||||
|
||||
if (element.getStyle('position') == 'static') element.setStyle('position', 'absolute');
|
||||
}
|
||||
|
||||
this.addEvent('start', this.checkDroppables, true);
|
||||
this.overed = null;
|
||||
},
|
||||
|
||||
start: function(event){
|
||||
if (this.container) this.options.limit = this.calculateLimit();
|
||||
|
||||
if (this.options.precalculate){
|
||||
this.positions = this.droppables.map(function(el){
|
||||
return el.getCoordinates();
|
||||
});
|
||||
}
|
||||
|
||||
this.parent(event);
|
||||
},
|
||||
|
||||
calculateLimit: function(){
|
||||
var element = this.element,
|
||||
container = this.container,
|
||||
|
||||
offsetParent = document.id(element.getOffsetParent()) || document.body,
|
||||
containerCoordinates = container.getCoordinates(offsetParent),
|
||||
elementMargin = {},
|
||||
elementBorder = {},
|
||||
containerMargin = {},
|
||||
containerBorder = {},
|
||||
offsetParentPadding = {};
|
||||
|
||||
['top', 'right', 'bottom', 'left'].each(function(pad){
|
||||
elementMargin[pad] = element.getStyle('margin-' + pad).toInt();
|
||||
elementBorder[pad] = element.getStyle('border-' + pad).toInt();
|
||||
containerMargin[pad] = container.getStyle('margin-' + pad).toInt();
|
||||
containerBorder[pad] = container.getStyle('border-' + pad).toInt();
|
||||
offsetParentPadding[pad] = offsetParent.getStyle('padding-' + pad).toInt();
|
||||
}, this);
|
||||
|
||||
var width = element.offsetWidth + elementMargin.left + elementMargin.right,
|
||||
height = element.offsetHeight + elementMargin.top + elementMargin.bottom,
|
||||
left = 0,
|
||||
top = 0,
|
||||
right = containerCoordinates.right - containerBorder.right - width,
|
||||
bottom = containerCoordinates.bottom - containerBorder.bottom - height;
|
||||
|
||||
if (this.options.includeMargins){
|
||||
left += elementMargin.left;
|
||||
top += elementMargin.top;
|
||||
} else {
|
||||
right += elementMargin.right;
|
||||
bottom += elementMargin.bottom;
|
||||
}
|
||||
|
||||
if (element.getStyle('position') == 'relative'){
|
||||
var coords = element.getCoordinates(offsetParent);
|
||||
coords.left -= element.getStyle('left').toInt();
|
||||
coords.top -= element.getStyle('top').toInt();
|
||||
|
||||
left -= coords.left;
|
||||
top -= coords.top;
|
||||
if (container.getStyle('position') != 'relative'){
|
||||
left += containerBorder.left;
|
||||
top += containerBorder.top;
|
||||
}
|
||||
right += elementMargin.left - coords.left;
|
||||
bottom += elementMargin.top - coords.top;
|
||||
|
||||
if (container != offsetParent){
|
||||
left += containerMargin.left + offsetParentPadding.left;
|
||||
top += ((Browser.ie6 || Browser.ie7) ? 0 : containerMargin.top) + offsetParentPadding.top;
|
||||
}
|
||||
} else {
|
||||
left -= elementMargin.left;
|
||||
top -= elementMargin.top;
|
||||
if (container != offsetParent){
|
||||
left += containerCoordinates.left + containerBorder.left;
|
||||
top += containerCoordinates.top + containerBorder.top;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
x: [left, right],
|
||||
y: [top, bottom]
|
||||
};
|
||||
},
|
||||
|
||||
getDroppableCoordinates: function(element){
|
||||
var position = element.getCoordinates();
|
||||
if (element.getStyle('position') == 'fixed'){
|
||||
var scroll = window.getScroll();
|
||||
position.left += scroll.x;
|
||||
position.right += scroll.x;
|
||||
position.top += scroll.y;
|
||||
position.bottom += scroll.y;
|
||||
}
|
||||
return position;
|
||||
},
|
||||
|
||||
checkDroppables: function(){
|
||||
var overed = this.droppables.filter(function(el, i){
|
||||
el = this.positions ? this.positions[i] : this.getDroppableCoordinates(el);
|
||||
var now = this.mouse.now;
|
||||
return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);
|
||||
}, this).getLast();
|
||||
|
||||
if (this.overed != overed){
|
||||
if (this.overed) this.fireEvent('leave', [this.element, this.overed]);
|
||||
if (overed) this.fireEvent('enter', [this.element, overed]);
|
||||
this.overed = overed;
|
||||
}
|
||||
},
|
||||
|
||||
drag: function(event){
|
||||
this.parent(event);
|
||||
if (this.options.checkDroppables && this.droppables.length) this.checkDroppables();
|
||||
},
|
||||
|
||||
stop: function(event){
|
||||
this.checkDroppables();
|
||||
this.fireEvent('drop', [this.element, this.overed, event]);
|
||||
this.overed = null;
|
||||
return this.parent(event);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Element.implement({
|
||||
|
||||
makeDraggable: function(options){
|
||||
var drag = new Drag.Move(this, options);
|
||||
this.store('dragger', drag);
|
||||
return drag;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
---
|
||||
|
||||
script: Sortables.js
|
||||
|
||||
name: Sortables
|
||||
|
||||
description: Class for creating a drag and drop sorting interface for lists of items.
|
||||
|
||||
license: MIT-style license
|
||||
|
||||
authors:
|
||||
- Tom Occhino
|
||||
|
||||
requires:
|
||||
- Core/Fx.Morph
|
||||
- /Drag.Move
|
||||
|
||||
provides: [Sortables]
|
||||
|
||||
...
|
||||
*/
|
||||
|
||||
var Sortables = new Class({
|
||||
|
||||
Implements: [Events, Options],
|
||||
|
||||
options: {/*
|
||||
onSort: function(element, clone){},
|
||||
onStart: function(element, clone){},
|
||||
onComplete: function(element){},*/
|
||||
opacity: 1,
|
||||
clone: false,
|
||||
revert: false,
|
||||
handle: false,
|
||||
dragOptions: {}
|
||||
},
|
||||
|
||||
initialize: function(lists, options){
|
||||
this.setOptions(options);
|
||||
|
||||
this.elements = [];
|
||||
this.lists = [];
|
||||
this.idle = true;
|
||||
|
||||
this.addLists($$(document.id(lists) || lists));
|
||||
|
||||
if (!this.options.clone) this.options.revert = false;
|
||||
if (this.options.revert) this.effect = new Fx.Morph(null, Object.merge({
|
||||
duration: 250,
|
||||
link: 'cancel'
|
||||
}, this.options.revert));
|
||||
},
|
||||
|
||||
attach: function(){
|
||||
this.addLists(this.lists);
|
||||
return this;
|
||||
},
|
||||
|
||||
detach: function(){
|
||||
this.lists = this.removeLists(this.lists);
|
||||
return this;
|
||||
},
|
||||
|
||||
addItems: function(){
|
||||
Array.flatten(arguments).each(function(element){
|
||||
this.elements.push(element);
|
||||
var start = element.retrieve('sortables:start', function(event){
|
||||
this.start.call(this, event, element);
|
||||
}.bind(this));
|
||||
(this.options.handle ? element.getElement(this.options.handle) || element : element).addEvent('mousedown', start);
|
||||
}, this);
|
||||
return this;
|
||||
},
|
||||
|
||||
addLists: function(){
|
||||
Array.flatten(arguments).each(function(list){
|
||||
this.lists.include(list);
|
||||
this.addItems(list.getChildren());
|
||||
}, this);
|
||||
return this;
|
||||
},
|
||||
|
||||
removeItems: function(){
|
||||
return $$(Array.flatten(arguments).map(function(element){
|
||||
this.elements.erase(element);
|
||||
var start = element.retrieve('sortables:start');
|
||||
(this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent('mousedown', start);
|
||||
|
||||
return element;
|
||||
}, this));
|
||||
},
|
||||
|
||||
removeLists: function(){
|
||||
return $$(Array.flatten(arguments).map(function(list){
|
||||
this.lists.erase(list);
|
||||
this.removeItems(list.getChildren());
|
||||
|
||||
return list;
|
||||
}, this));
|
||||
},
|
||||
|
||||
getClone: function(event, element){
|
||||
if (!this.options.clone) return new Element(element.tagName).inject(document.body);
|
||||
if (typeOf(this.options.clone) == 'function') return this.options.clone.call(this, event, element, this.list);
|
||||
var clone = element.clone(true).setStyles({
|
||||
margin: 0,
|
||||
position: 'absolute',
|
||||
visibility: 'hidden',
|
||||
width: element.getStyle('width')
|
||||
}).addEvent('mousedown', function(event){
|
||||
element.fireEvent('mousedown', event);
|
||||
});
|
||||
//prevent the duplicated radio inputs from unchecking the real one
|
||||
if (clone.get('html').test('radio')){
|
||||
clone.getElements('input[type=radio]').each(function(input, i){
|
||||
input.set('name', 'clone_' + i);
|
||||
if (input.get('checked')) element.getElements('input[type=radio]')[i].set('checked', true);
|
||||
});
|
||||
}
|
||||
|
||||
return clone.inject(this.list).setPosition(element.getPosition(element.getOffsetParent()));
|
||||
},
|
||||
|
||||
getDroppables: function(){
|
||||
var droppables = this.list.getChildren().erase(this.clone).erase(this.element);
|
||||
if (!this.options.constrain) droppables.append(this.lists).erase(this.list);
|
||||
return droppables;
|
||||
},
|
||||
|
||||
insert: function(dragging, element){
|
||||
var where = 'inside';
|
||||
if (this.lists.contains(element)){
|
||||
this.list = element;
|
||||
this.drag.droppables = this.getDroppables();
|
||||
} else {
|
||||
where = this.element.getAllPrevious().contains(element) ? 'before' : 'after';
|
||||
}
|
||||
this.element.inject(element, where);
|
||||
this.fireEvent('sort', [this.element, this.clone]);
|
||||
},
|
||||
|
||||
start: function(event, element){
|
||||
if (
|
||||
!this.idle ||
|
||||
event.rightClick ||
|
||||
['button', 'input', 'a'].contains(event.target.get('tag'))
|
||||
) return;
|
||||
|
||||
this.idle = false;
|
||||
this.element = element;
|
||||
this.opacity = element.get('opacity');
|
||||
this.list = element.getParent();
|
||||
this.clone = this.getClone(event, element);
|
||||
|
||||
this.drag = new Drag.Move(this.clone, Object.merge({
|
||||
|
||||
droppables: this.getDroppables()
|
||||
}, this.options.dragOptions)).addEvents({
|
||||
onSnap: function(){
|
||||
event.stop();
|
||||
this.clone.setStyle('visibility', 'visible');
|
||||
this.element.set('opacity', this.options.opacity || 0);
|
||||
this.fireEvent('start', [this.element, this.clone]);
|
||||
}.bind(this),
|
||||
onEnter: this.insert.bind(this),
|
||||
onCancel: this.end.bind(this),
|
||||
onComplete: this.end.bind(this)
|
||||
});
|
||||
|
||||
this.clone.inject(this.element, 'before');
|
||||
this.drag.start(event);
|
||||
},
|
||||
|
||||
end: function(){
|
||||
this.drag.detach();
|
||||
this.element.set('opacity', this.opacity);
|
||||
if (this.effect){
|
||||
var dim = this.element.getStyles('width', 'height'),
|
||||
clone = this.clone,
|
||||
pos = clone.computePosition(this.element.getPosition(this.clone.getOffsetParent()));
|
||||
|
||||
var destroy = function(){
|
||||
this.removeEvent('cancel', destroy);
|
||||
clone.destroy();
|
||||
};
|
||||
|
||||
this.effect.element = clone;
|
||||
this.effect.start({
|
||||
top: pos.top,
|
||||
left: pos.left,
|
||||
width: dim.width,
|
||||
height: dim.height,
|
||||
opacity: 0.25
|
||||
}).addEvent('cancel', destroy).chain(destroy);
|
||||
} else {
|
||||
this.clone.destroy();
|
||||
}
|
||||
this.reset();
|
||||
},
|
||||
|
||||
reset: function(){
|
||||
this.idle = true;
|
||||
this.fireEvent('complete', this.element);
|
||||
},
|
||||
|
||||
serialize: function(){
|
||||
var params = Array.link(arguments, {
|
||||
modifier: Type.isFunction,
|
||||
index: function(obj){
|
||||
return obj != null;
|
||||
}
|
||||
});
|
||||
var serial = this.lists.map(function(list){
|
||||
return list.getChildren().map(params.modifier || function(element){
|
||||
return element.get('id');
|
||||
}, this);
|
||||
}, this);
|
||||
|
||||
var index = params.index;
|
||||
if (this.lists.length == 1) index = 0;
|
||||
return (index || index === 0) && index >= 0 && index < this.lists.length ? serial[index] : serial;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
---
|
||||
|
||||
|
||||
@@ -11,6 +11,12 @@ Page.Settings = new Class({
|
||||
},
|
||||
'providers': {
|
||||
'label': 'Providers'
|
||||
},
|
||||
'downloaders': {
|
||||
'label': 'Downloaders'
|
||||
},
|
||||
'notifications': {
|
||||
'label': 'Notifications'
|
||||
}
|
||||
},
|
||||
|
||||
@@ -27,13 +33,13 @@ Page.Settings = new Class({
|
||||
|
||||
openTab: function(action){
|
||||
var self = this;
|
||||
action = action || self.action
|
||||
var action = action || self.action;
|
||||
|
||||
if(self.current)
|
||||
self.toggleTab(self.current, true);
|
||||
|
||||
self.toggleTab(action)
|
||||
self.current = action;
|
||||
var tab = self.toggleTab(action)
|
||||
self.current = tab == self.tabs.general ? 'general' : action;
|
||||
|
||||
},
|
||||
|
||||
@@ -47,6 +53,7 @@ Page.Settings = new Class({
|
||||
t.tab[a](c);
|
||||
t.content[a](c);
|
||||
|
||||
return t
|
||||
},
|
||||
|
||||
getData: function(onComplete){
|
||||
@@ -121,7 +128,7 @@ Page.Settings = new Class({
|
||||
|
||||
// Add options to group
|
||||
group.options.sortBy('order').each(function(option){
|
||||
var class_name = (option.type || 'input').capitalize();
|
||||
var class_name = (option.type || 'string').capitalize();
|
||||
var input = new Option[class_name](self, section_name, option.name, option);
|
||||
input.inject(group_el);
|
||||
});
|
||||
@@ -145,13 +152,13 @@ Page.Settings = new Class({
|
||||
var tab_el = new Element('li').adopt(
|
||||
new Element('a', {
|
||||
'href': '/'+self.name+'/'+tab_name+'/',
|
||||
'text': tab.label.capitalize()
|
||||
'text': (tab.label || tab.name).capitalize()
|
||||
})
|
||||
).inject(self.tabs_container);
|
||||
|
||||
if(!self.tabs[tab_name])
|
||||
self.tabs[tab_name] = {
|
||||
'label': tab.label
|
||||
'label': tab.label || tab.name
|
||||
}
|
||||
|
||||
self.tabs[tab_name] = Object.merge(self.tabs[tab_name], {
|
||||
@@ -171,7 +178,7 @@ Page.Settings = new Class({
|
||||
'class': group.advanced ? 'inlineLabels advanced' : 'inlineLabels'
|
||||
}).adopt(
|
||||
new Element('h2', {
|
||||
'text': group.label
|
||||
'text': group.label || group.name.capitalize()
|
||||
}).adopt(
|
||||
new Element('span.hint', {
|
||||
'text': group.description
|
||||
@@ -222,6 +229,13 @@ var OptionBase = new Class({
|
||||
},
|
||||
|
||||
create: function(){},
|
||||
|
||||
createLabel: function(){
|
||||
var self = this;
|
||||
return new Element('label', {
|
||||
'text': self.options.label || self.options.name.capitalize()
|
||||
})
|
||||
},
|
||||
|
||||
setAdvanced: function(){
|
||||
this.el.addClass(this.options.advanced ? 'advanced': '')
|
||||
@@ -319,9 +333,7 @@ Option.String = new Class({
|
||||
var self = this
|
||||
|
||||
self.el.adopt(
|
||||
new Element('label', {
|
||||
'text': self.options.label
|
||||
}),
|
||||
self.createLabel(),
|
||||
self.input = new Element('input', {
|
||||
'type': 'text',
|
||||
'name': self.postName(),
|
||||
@@ -337,18 +349,17 @@ Option.Dropdown = new Class({
|
||||
create: function(){
|
||||
var self = this
|
||||
|
||||
new Element('label', {
|
||||
'text': self.options.label
|
||||
}).adopt(
|
||||
self.el.adopt(
|
||||
self.createLabel(),
|
||||
self.input = new Element('select', {
|
||||
'name': self.postName()
|
||||
})
|
||||
).inject(self.el)
|
||||
)
|
||||
|
||||
Object.each(self.options.values, function(label, value){
|
||||
Object.each(self.options.values, function(value){
|
||||
new Element('option', {
|
||||
'text': label,
|
||||
'value': value
|
||||
'text': value[0],
|
||||
'value': value[1]
|
||||
}).inject(self.input)
|
||||
})
|
||||
|
||||
@@ -366,24 +377,31 @@ Option.Checkbox = new Class({
|
||||
|
||||
var randomId = 'option-'+Math.floor(Math.random()*1000000)
|
||||
|
||||
new Element('label', {
|
||||
'text': self.options.label,
|
||||
'for': randomId
|
||||
}).inject(self.el);
|
||||
|
||||
self.input = new Element('input', {
|
||||
'type': 'checkbox',
|
||||
'value': self.getSettingValue(),
|
||||
'checked': self.getSettingValue() !== undefined,
|
||||
'id': randomId
|
||||
}).inject(self.el);
|
||||
self.el.adopt(
|
||||
self.createLabel().set('for', randomId),
|
||||
self.input = new Element('input', {
|
||||
'type': 'checkbox',
|
||||
'value': self.getSettingValue(),
|
||||
'checked': self.getSettingValue() !== undefined,
|
||||
'id': randomId
|
||||
})
|
||||
)
|
||||
}
|
||||
});
|
||||
|
||||
Option.Password = new Class({
|
||||
Extends: Option.String,
|
||||
type: 'password'
|
||||
});
|
||||
|
||||
Option.Bool = new Class({
|
||||
Extends: Option.Checkbox
|
||||
});
|
||||
|
||||
Option.Enabler = new Class({
|
||||
Extends: Option.Bool
|
||||
});
|
||||
|
||||
Option.Int = new Class({
|
||||
Extends: Option.String
|
||||
});
|
||||
@@ -401,9 +419,7 @@ Option.Directory = new Class({
|
||||
|
||||
|
||||
self.el.adopt(
|
||||
new Element('label', {
|
||||
'text': self.options.label
|
||||
}),
|
||||
self.createLabel(),
|
||||
self.input = new Element('span', {
|
||||
'text': self.getSettingValue(),
|
||||
'events': {
|
||||
|
||||
@@ -18,19 +18,28 @@ Page.Wanted = new Class({
|
||||
|
||||
if(!self.movie_container)
|
||||
self.movie_container = new Element('div.movies').inject(self.el);
|
||||
|
||||
|
||||
self.movie_container.empty();
|
||||
Object.each(self.movies, function(info){
|
||||
var m = new Movie(self, {}, info);
|
||||
$(m).inject(self.movie_container);
|
||||
});
|
||||
|
||||
self.movie_container.addEvents({
|
||||
'mouseenter:relay(.movie)': function(e, el){
|
||||
el.addClass('hover')
|
||||
},
|
||||
'mouseleave:relay(.movie)': function(e, el){
|
||||
el.removeClass('hover')
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
get: function(status, onComplete){
|
||||
var self = this
|
||||
|
||||
if(self.movies.length == 0)
|
||||
Api.request('movie', {
|
||||
Api.request('movie.list', {
|
||||
'data': {},
|
||||
'onComplete': function(json){
|
||||
self.store(json.movies);
|
||||
@@ -58,16 +67,280 @@ var Movie = new Class({
|
||||
|
||||
self.data = data;
|
||||
|
||||
self.profile = Quality.getProfile(data.profile_id);
|
||||
self.parent(self, options);
|
||||
},
|
||||
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
self.el = new Element('div.movie', {
|
||||
'text': self.data.name
|
||||
self.el = new Element('div.movie').adopt(
|
||||
self.data_container = new Element('div').adopt(
|
||||
self.thumbnail = File.Select.single('poster', self.data.library.files),
|
||||
self.title = new Element('div.title', {
|
||||
'text': self.getTitle()
|
||||
}),
|
||||
self.description = new Element('div.description', {
|
||||
'text': self.data.library.plot
|
||||
}),
|
||||
self.rating = new Element('div.rating', {
|
||||
'text': self.data.library.rating || 10
|
||||
}),
|
||||
self.year = new Element('div.year', {
|
||||
'text': self.data.library.year || 'Unknown'
|
||||
}),
|
||||
self.quality = new Element('div.quality', {
|
||||
'text': self.profile.get('label')
|
||||
}),
|
||||
self.actions = new Element('div.actions').adopt(
|
||||
self.action_imdb = new Movie.Action.IMDB(self),
|
||||
self.action_edit = new Movie.Action.Edit(self),
|
||||
self.action_refresh = new Movie.Action.Refresh(self),
|
||||
self.action_delete = new Movie.Action.Delete(self)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
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'
|
||||
},
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
Movie.Action = {}
|
||||
|
||||
Movie.Action.Edit = new Class({
|
||||
|
||||
Extends: MovieAction,
|
||||
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
self.el = new Element('a.edit', {
|
||||
'text': 'edit',
|
||||
'title': 'Refresh the movie info and do a forced search',
|
||||
'events': {
|
||||
'click': self.editMovie.bind(self)
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
editMovie: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
|
||||
self.optionContainer = new Element('div.options').adopt(
|
||||
$(self.movie.thumbnail).clone(),
|
||||
self.title_select = new Element('select', {
|
||||
'name': 'title'
|
||||
}),
|
||||
self.profile_select = new Element('select', {
|
||||
'name': 'profile'
|
||||
}),
|
||||
new Element('a.button.edit', {
|
||||
'text': 'Save',
|
||||
'events': {
|
||||
'click': self.save.bind(self)
|
||||
}
|
||||
})
|
||||
).inject(self.movie, 'top');
|
||||
},
|
||||
|
||||
save: function(){
|
||||
var self = this;
|
||||
|
||||
Api.request('movie.edit', {
|
||||
'data': {
|
||||
'default_title': self.title_select.get('value'),
|
||||
'profile_id': self.profile_select.get('value')
|
||||
},
|
||||
'useSpinner': true,
|
||||
'spinnerTarget': self.movie
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
Movie.Action.IMDB = new Class({
|
||||
|
||||
Extends: MovieAction,
|
||||
id: null,
|
||||
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
self.id = self.movie.get('identifier');
|
||||
|
||||
self.el = new Element('a.imdb', {
|
||||
'text': '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+'/');
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
Movie.Action.Refresh = new Class({
|
||||
|
||||
Extends: MovieAction,
|
||||
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
self.el = new Element('a.refresh', {
|
||||
'text': 'refresh',
|
||||
'title': 'Refresh the movie info and do a forced search',
|
||||
'events': {
|
||||
'click': self.doSearch.bind(self)
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
doSearch: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
|
||||
Api.request('movie.refresh', {
|
||||
'data': {
|
||||
'id': self.movie.get('id')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
Movie.Action.Delete = new Class({
|
||||
|
||||
Extends: MovieAction,
|
||||
|
||||
Implements: [Chain],
|
||||
|
||||
create: function(){
|
||||
var self = this;
|
||||
|
||||
self.el = new Element('a.delete', {
|
||||
'text': 'delete',
|
||||
'title': 'Remove the movie from your wanted list',
|
||||
'events': {
|
||||
'click': self.showConfirm.bind(self)
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
showConfirm: function(e){
|
||||
var self = this;
|
||||
(e).stop();
|
||||
|
||||
self.mask = $(self.movie).mask({
|
||||
'destroyOnHide': true
|
||||
});
|
||||
|
||||
$(self.mask).adopt(
|
||||
new Element('a.button.delete', {
|
||||
'text': 'Delete movie',
|
||||
'events': {
|
||||
'click': self.del.bind(self)
|
||||
}
|
||||
}),
|
||||
new Element('span', {
|
||||
'text': 'or'
|
||||
}),
|
||||
new Element('a.button.cancel', {
|
||||
'text': 'Cancel',
|
||||
'events': {
|
||||
'click': self.mask.hide.bind(self.mask)
|
||||
}
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
del: function(e){
|
||||
(e).stop()
|
||||
var self = this;
|
||||
|
||||
var movie = $(self.movie);
|
||||
|
||||
self.chain(
|
||||
function(){
|
||||
$(self.mask).empty().addClass('loading');
|
||||
self.callChain();
|
||||
},
|
||||
function(){
|
||||
Api.request('movie.delete', {
|
||||
'data': {
|
||||
'id': self.movie.get('id')
|
||||
},
|
||||
'onComplete': function(){
|
||||
p(movie, $(self.movie))
|
||||
movie.slide('in');
|
||||
}
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
self.callChain();
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
@@ -6,13 +6,19 @@ var QualityBase = new Class({
|
||||
setup: function(data){
|
||||
var self = this;
|
||||
|
||||
self.profiles = data.profiles;
|
||||
self.qualities = data.qualities;
|
||||
|
||||
self.profiles = {}
|
||||
Object.each(data.profiles, self.createProfilesClass.bind(self));
|
||||
|
||||
App.addEvent('load', self.addSettings.bind(self))
|
||||
|
||||
},
|
||||
|
||||
getProfile: function(id){
|
||||
return this.profiles[id]
|
||||
},
|
||||
|
||||
addSettings: function(){
|
||||
var self = this;
|
||||
|
||||
@@ -47,22 +53,34 @@ var QualityBase = new Class({
|
||||
new Element('a.add_new', {
|
||||
'text': 'Create a new quality profile',
|
||||
'events': {
|
||||
'click': self.createNewProfile.bind(self)
|
||||
'click': function(){
|
||||
var profile = self.createProfilesClass();
|
||||
$(profile).inject(self.profile_container, 'top')
|
||||
}
|
||||
}
|
||||
}),
|
||||
self.profile_container = new Element('div.container')
|
||||
)
|
||||
|
||||
Object.each(self.profiles, self.createNewProfile.bind(self))
|
||||
Object.each(self.profiles, function(profile){
|
||||
if(!profile.isCore())
|
||||
$(profile).inject(self.profile_container, 'top')
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
createNewProfile: function(data, nr){
|
||||
createProfilesClass: function(data){
|
||||
var self = this;
|
||||
|
||||
self.profiles[nr] = new Profile(data);
|
||||
$(self.profiles[nr]).inject(self.profile_container)
|
||||
|
||||
if(data){
|
||||
return self.profiles[data.id] = new Profile(data);
|
||||
}
|
||||
else {
|
||||
var data = {
|
||||
'id': randomString()
|
||||
}
|
||||
return self.profiles[data.id] = new Profile(data);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -95,7 +113,7 @@ var QualityBase = new Class({
|
||||
window.Quality = new QualityBase();
|
||||
|
||||
var Profile = new Class({
|
||||
|
||||
|
||||
data: {},
|
||||
types: [],
|
||||
|
||||
@@ -119,12 +137,9 @@ var Profile = new Class({
|
||||
|
||||
var data = self.data;
|
||||
|
||||
self.el = new Element('div', {
|
||||
'class': 'profile'
|
||||
}).adopt(
|
||||
new Element('h4', {'text': data.label}),
|
||||
new Element('span.delete', {
|
||||
'html': 'del',
|
||||
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)
|
||||
}
|
||||
@@ -135,25 +150,29 @@ var Profile = new Class({
|
||||
new Element('label', {'text':'Name'}),
|
||||
new Element('input.label.textInput.large', {
|
||||
'type':'text',
|
||||
'value': data.label
|
||||
'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.wait_for
|
||||
'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'}),
|
||||
self.type_container = new Element('div.types').adopt(
|
||||
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>'})
|
||||
)
|
||||
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': '#',
|
||||
@@ -164,6 +183,8 @@ var Profile = new Class({
|
||||
)
|
||||
);
|
||||
|
||||
self.makeSortable()
|
||||
|
||||
if(data.types)
|
||||
Object.each(data.types, self.addType.bind(self))
|
||||
},
|
||||
@@ -174,11 +195,19 @@ var Profile = new Class({
|
||||
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)
|
||||
@@ -194,12 +223,15 @@ var Profile = new Class({
|
||||
'wait_for' : self.el.getElement('.wait_for').get('value'),
|
||||
'types': []
|
||||
}
|
||||
|
||||
Object.each(self.types, function(type){
|
||||
if(!type.deleted)
|
||||
data.types.include(type.getData());
|
||||
|
||||
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
|
||||
},
|
||||
|
||||
@@ -208,6 +240,7 @@ var Profile = new Class({
|
||||
|
||||
var t = new Profile.Type(data);
|
||||
$(t).inject(self.type_container);
|
||||
self.sortable.addItems($(t));
|
||||
|
||||
self.types.include(t);
|
||||
|
||||
@@ -216,6 +249,8 @@ var Profile = new Class({
|
||||
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
|
||||
@@ -224,12 +259,35 @@ var Profile = new Class({
|
||||
'spinnerOptions': {
|
||||
'target': self.el
|
||||
},
|
||||
'onComplete': function(){
|
||||
self.el.destroy();
|
||||
'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
|
||||
}
|
||||
@@ -252,7 +310,7 @@ Profile.Type = Class({
|
||||
var self = this;
|
||||
var data = self.data;
|
||||
|
||||
self.el = new Element('div.type').adopt(
|
||||
self.el = new Element('li.type').adopt(
|
||||
new Element('span.quality_type').adopt(
|
||||
self.fillQualities()
|
||||
),
|
||||
@@ -263,15 +321,12 @@ Profile.Type = Class({
|
||||
'checked': data.finish
|
||||
})
|
||||
),
|
||||
new Element('span.delete', {
|
||||
'html': 'del',
|
||||
new Element('span.delete.icon', {
|
||||
'events': {
|
||||
'click': self.del.bind(self)
|
||||
}
|
||||
}),
|
||||
new Element('span', {
|
||||
'class':'handle'
|
||||
})
|
||||
new Element('span.handle')
|
||||
)
|
||||
|
||||
},
|
||||
@@ -284,21 +339,21 @@ Profile.Type = Class({
|
||||
Object.each(Quality.qualities, function(q){
|
||||
new Element('option', {
|
||||
'text': q.label,
|
||||
'value': q.identifier
|
||||
'value': q.id
|
||||
}).inject(self.qualities)
|
||||
});
|
||||
|
||||
self.qualities.set('value', self.data.quality);
|
||||
self.qualities.set('value', self.data.quality_id);
|
||||
|
||||
return self.qualities;
|
||||
|
||||
},
|
||||
|
||||
|
||||
getData: function(){
|
||||
var self = this;
|
||||
|
||||
|
||||
return {
|
||||
'quality': self.qualities.get('value'),
|
||||
'quality_id': self.qualities.get('value'),
|
||||
'finish': +self.finish.checked
|
||||
}
|
||||
},
|
||||
@@ -306,6 +361,7 @@ Profile.Type = Class({
|
||||
del: function(){
|
||||
var self = this;
|
||||
|
||||
self.el.addClass('deleted');
|
||||
self.el.hide();
|
||||
self.deleted = true;
|
||||
},
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
var StatusBase = new Class({
|
||||
|
||||
setup: function(statuses){
|
||||
var self = this;
|
||||
|
||||
self.statuses = statuses;
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
window.Status = new StatusBase();
|
||||
Reference in New Issue
Block a user