Event priority
Mootools defaults fixes
This commit is contained in:
Ruud
2011-09-12 21:26:38 +02:00
parent c0c0628708
commit 1effeb2134
21 changed files with 695 additions and 349 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ def start():
new_environ[key] = value.encode('iso-8859-1')
subprocess.call(args, env = new_environ)
return os.path.isfile(os.path.join(options.data_dir, 'restart'))
return os.path.isfile(os.path.join(base_path, 'restart'))
except Exception, e:
log.critical(e)
return 0
+1
View File
@@ -18,3 +18,4 @@ def index():
return jsonified({'routes': routes})
addApiView('', index)
addApiView('default', index)
+5 -6
View File
@@ -1,5 +1,5 @@
from couchpotato.api import addApiView
from couchpotato.core.event import fireEvent
from couchpotato.core.event import fireEvent, addEvent
from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
from couchpotato.environment import Env
@@ -43,14 +43,13 @@ class Core(Plugin):
time.sleep(1)
if restart:
self.createFile(self.restartFilePath(), 'This is the most suckiest way to register if CP is restarted. Ever...')
func = request.environ.get('werkzeug.server.shutdown')
if func is None:
try:
request.environ.get('werkzeug.server.shutdown')()
except:
log.error('Failed shutting down the server')
func()
def removeRestartFile(self):
try:
@@ -59,4 +58,4 @@ class Core(Plugin):
pass
def restartFilePath(self):
return os.path.join(Env.get('data_dir'), 'restart')
return os.path.join(Env.get('app_dir'), 'restart')
+5 -1
View File
@@ -1,6 +1,7 @@
from couchpotato.core.event import addEvent
from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
from couchpotato.environment import Env
log = CPLog(__name__)
@@ -16,7 +17,10 @@ class Downloader(Plugin):
pass
def cpTag(self, movie):
return '.cp(' + movie['library'].get('identifier') + ')' if movie['library'].get('identifier') else ''
if Env.setting('enabled', 'renamer'):
return '.cp(' + movie['library'].get('identifier') + ')' if movie['library'].get('identifier') else ''
return ''
def isDisabled(self):
return not self.isEnabled()
+5 -2
View File
@@ -8,7 +8,7 @@ log = CPLog(__name__)
events = {}
def addEvent(name, handler):
def addEvent(name, handler, priority = 0):
if events.get(name):
e = events[name]
@@ -27,7 +27,10 @@ def addEvent(name, handler):
return h
e += createHandle
if name == 'app.initialize':
print 'test', priority
e.handle(createHandle, priority = priority)
def removeEvent(name, handler):
e = events[name]
+2 -2
View File
@@ -19,7 +19,7 @@ class ProfilePlugin(Plugin):
addApiView('profile.save_order', self.saveOrder)
addApiView('profile.delete', self.delete)
addEvent('app.initialize', self.fill)
addEvent('app.initialize', self.fill, priority = 90)
def all(self):
@@ -127,7 +127,7 @@ class ProfilePlugin(Plugin):
}]
# Create default quality profile
order = 99
order = -2
for profile in profiles:
log.info('Creating default profile: %s' % profile.get('label'))
p = Profile(
+1 -1
View File
@@ -32,7 +32,7 @@ class QualityPlugin(Plugin):
addEvent('quality.single', self.single)
addEvent('quality.guess', self.guess)
addEvent('app.initialize', self.fill)
addEvent('app.initialize', self.fill, priority = 10)
def all(self):
+1 -1
View File
@@ -86,7 +86,7 @@ class Searcher(Plugin):
for info in nzb:
try:
if not isinstance(nzb[info], (str, unicode)):
if not isinstance(nzb[info], (str, unicode, int, long)):
continue
rls_info = ReleaseInfo(
+28 -11
View File
@@ -1,4 +1,6 @@
from couchpotato.api import addApiView
from couchpotato.core.event import addEvent, fireEvent
from couchpotato.core.helpers.request import jsonified
from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin
from couchpotato.environment import Env
@@ -10,14 +12,13 @@ log = CPLog(__name__)
class Updater(Plugin):
git = 'git://github.com/CouchPotato/CouchPotato.git'
repo_name = 'RuudBurger/CouchPotatoServer'
running = False
version = None
updateFailed = False
updateAvailable = False
updateVersion = None
lastCheck = 0
update_failed = False
update_version = None
last_check = 0
def __init__(self):
@@ -27,6 +28,18 @@ class Updater(Plugin):
addEvent('app.load', self.check)
addApiView('updater.info', self.getInfo)
addApiView('updater.update', self.doUpdateView)
def getInfo(self):
return jsonified({
'repo_name': self.repo_name,
'last_check': self.last_check,
'update_version': self.update_version,
'version': self.getVersion(),
})
def getVersion(self):
if not self.version:
@@ -42,7 +55,7 @@ class Updater(Plugin):
def check(self):
if self.updateAvailable or self.isDisabled():
if self.update_version or self.isDisabled():
return
current_branch = self.repo.getCurrentBranch().name
@@ -54,13 +67,17 @@ class Updater(Plugin):
remote = branch.getHead()
if local.getDate() < remote.getDate():
if self.conf('automatic') and not self.updateFailed:
if self.conf('automatic') and not self.update_failed:
self.doUpdate()
else:
self.updateAvailable = True
self.updateVersion = remote.hash
self.update_version = remote.hash
self.lastCheck = time.time()
self.last_check = time.time()
def doUpdateView(self):
return jsonified({
'success': self.doUpdate()
})
def doUpdate(self):
try:
@@ -70,7 +87,7 @@ class Updater(Plugin):
except Exception, e:
log.error('Failed updating via GIT: %s' % e)
self.updateFailed = True
self.update_failed = True
return False
@@ -0,0 +1,89 @@
var UpdaterBase = new Class({
initialize: function(){
var self = this;
App.addEvent('load', self.info.bind(self, 1000))
},
info: function(timeout){
var self = this;
if(self.timer) clearTimeout(self.timer);
self.timer = setTimeout(function(){
Api.request('updater.info', {
'onComplete': function(json){
if(json.update_version){
self.createMessage(json);
}
else {
if(self.message)
self.message.destroy();
}
}
})
}, (timeout || 0))
},
createMessage: function(data){
var self = this;
self.message = new Element('div.message.update').adopt(
new Element('span', {
'text': 'A new version is available'
}),
new Element('a', {
'href': 'https://github.com/'+data.repo_name+'/compare/'+data.version.substr(0, 7)+'...'+data.update_version.substr(0, 7),
'text': 'see what has changed',
'target': '_blank'
}),
new Element('span[text=or]'),
new Element('a', {
'text': 'just update, gogogo!',
'events': {
'click': self.doUpdate.bind(self)
}
})
).inject($(document.body).getElement('.header'))
},
doUpdate: function(){
var self = this;
Api.request('updater.update', {
'onComplete': function(json){
if(json.success){
App.restart();
$(document.body).set('spin', {
'message': 'Updating'
});
$(document.body).spin();
var checks = 0;
var interval = 0;
interval = setInterval(function(){
Api.request('', {
'onSuccess': function(){
if(checks > 2){
clearInterval(interval);
$(document.body).unspin();
self.info();
}
}
});
checks++;
}, 500)
}
}
});
}
});
var Updater = new UpdaterBase();
@@ -21,7 +21,7 @@ config = [{
},
{
'name': 'host',
'default': 'http://nzb.su',
'default': 'nzb.su',
'description': 'The hostname of your newznab provider'
},
{
@@ -72,7 +72,7 @@ var MultipleNewznab = new Class({
if(has_empty) return;
self.add_empty_timeout = setTimeout(function(){
self.createItem(false);
self.createItem(false, null, null);
}, 10);
},
+9 -1
View File
@@ -29,7 +29,7 @@ var CouchPotato = new Class({
else
self.openPage(window.location.pathname);
self.c.addEvent('click:relay(a)', self.pushState.bind(self));
self.c.addEvent('click:relay(a:not([target=_blank]))', self.pushState.bind(self));
},
pushState: function(e){
@@ -100,6 +100,14 @@ var CouchPotato = new Class({
getPage: function(name){
return this.pages[name]
},
shutdown: function(){
Api.request('app.shutdown');
},
restart: function(){
Api.request('app.restart');
}
});
@@ -96,14 +96,14 @@ Form.Check = new Class({
this.fireEvent('removeHighlight', this);
},
keyToggle: function(e) {
var evt = new Event(e);
var evt = (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();
evt = (e).stopPropagation();
if (evt.target.tagName.toLowerCase() !== 'a') {
evt.stop();
}
@@ -117,7 +117,7 @@ Form.Dropdown = new Class({
},
expand: function(e) {
clearTimeout(this.collapseInterval);
var evt = e ? new Event(e).stop() : null;
var evt = e ? (e).stop() : null;
this.open = true;
this.input.focus();
this.element.addClass('active').addClass('dropdown-active');
@@ -22,7 +22,7 @@ Form.Radio = new Class({
toggle: function(e) {
if (this.element.hasClass('checked') || this.disabled) { return; }
var evt;
if (e) { evt = new Event(e).stop(); }
if (e) { evt = (e).stop(); }
if (this.checked) {
this.uncheck();
} else {
+510 -310
View File
@@ -3,10 +3,10 @@
MooTools: the javascript framework
web build:
- http://mootools.net/core/3e4fc9be110c01367e16b46df47d66b7
- http://mootools.net/core/f42fb6d73ea1a13146c5ad9502b442f0
packager build:
- 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/Cookie Core/DOMReady
- packager build Core/Class Core/Class.Extras Core/Element Core/Element.Style Core/Element.Delegation Core/Element.Dimensions Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request.JSON Core/Cookie Core/DOMReady
/*
---
@@ -3608,6 +3608,514 @@ Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, bor
})();
/*
---
name: Event
description: Contains the Event Type, to make the event object cross-browser.
license: MIT-style license.
requires: [Window, Document, Array, Function, String, Object]
provides: Event
...
*/
(function() {
var _keys = {};
var DOMEvent = this.DOMEvent = new Type('DOMEvent', function(event, win){
if (!win) win = window;
event = event || win.event;
if (event.$extended) return event;
this.event = event;
this.$extended = true;
this.shift = event.shiftKey;
this.control = event.ctrlKey;
this.alt = event.altKey;
this.meta = event.metaKey;
var type = this.type = event.type;
var target = event.target || event.srcElement;
while (target && target.nodeType == 3) target = target.parentNode;
this.target = document.id(target);
if (type.indexOf('key') == 0){
var code = this.code = (event.which || event.keyCode);
this.key = _keys[code];
if (type == 'keydown'){
if (code > 111 && code < 124) this.key = 'f' + (code - 111);
else if (code > 95 && code < 106) this.key = code - 96;
}
if (this.key == null) this.key = String.fromCharCode(code).toLowerCase();
} else if (type == 'click' || type == 'dblclick' || type == 'contextmenu' || type.indexOf('mouse') == 0){
var doc = win.document;
doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
this.page = {
x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft,
y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop
};
this.client = {
x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX,
y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY
};
if (type == 'DOMMouseScroll' || type == 'mousewheel')
this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
this.rightClick = (event.which == 3 || event.button == 2);
if (type == 'mouseover' || type == 'mouseout'){
var related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element'];
while (related && related.nodeType == 3) related = related.parentNode;
this.relatedTarget = document.id(related);
}
} else if (type.indexOf('touch') == 0 || type.indexOf('gesture') == 0){
this.rotation = event.rotation;
this.scale = event.scale;
this.targetTouches = event.targetTouches;
this.changedTouches = event.changedTouches;
var touches = this.touches = event.touches;
if (touches && touches[0]){
var touch = touches[0];
this.page = {x: touch.pageX, y: touch.pageY};
this.client = {x: touch.clientX, y: touch.clientY};
}
}
if (!this.client) this.client = {};
if (!this.page) this.page = {};
});
DOMEvent.implement({
stop: function(){
return this.preventDefault().stopPropagation();
},
stopPropagation: function(){
if (this.event.stopPropagation) this.event.stopPropagation();
else this.event.cancelBubble = true;
return this;
},
preventDefault: function(){
if (this.event.preventDefault) this.event.preventDefault();
else this.event.returnValue = false;
return this;
}
});
DOMEvent.defineKey = function(code, key){
_keys[code] = key;
return this;
};
DOMEvent.defineKeys = DOMEvent.defineKey.overloadSetter(true);
DOMEvent.defineKeys({
'38': 'up', '40': 'down', '37': 'left', '39': 'right',
'27': 'esc', '32': 'space', '8': 'backspace', '9': 'tab',
'46': 'delete', '13': 'enter'
});
})();
/*
---
name: Element.Event
description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events.
license: MIT-style license.
requires: [Element, Event]
provides: Element.Event
...
*/
(function(){
Element.Properties.events = {set: function(events){
this.addEvents(events);
}};
[Element, Window, Document].invoke('implement', {
addEvent: function(type, fn){
var events = this.retrieve('events', {});
if (!events[type]) events[type] = {keys: [], values: []};
if (events[type].keys.contains(fn)) return this;
events[type].keys.push(fn);
var realType = type,
custom = Element.Events[type],
condition = fn,
self = this;
if (custom){
if (custom.onAdd) custom.onAdd.call(this, fn, type);
if (custom.condition){
condition = function(event){
if (custom.condition.call(this, event, type)) return fn.call(this, event);
return true;
};
}
if (custom.base) realType = Function.from(custom.base).call(this, type);
}
var defn = function(){
return fn.call(self);
};
var nativeEvent = Element.NativeEvents[realType];
if (nativeEvent){
if (nativeEvent == 2){
defn = function(event){
event = new DOMEvent(event, self.getWindow());
if (condition.call(self, event) === false) event.stop();
};
}
this.addListener(realType, defn, arguments[2]);
}
events[type].values.push(defn);
return this;
},
removeEvent: function(type, fn){
var events = this.retrieve('events');
if (!events || !events[type]) return this;
var list = events[type];
var index = list.keys.indexOf(fn);
if (index == -1) return this;
var value = list.values[index];
delete list.keys[index];
delete list.values[index];
var custom = Element.Events[type];
if (custom){
if (custom.onRemove) custom.onRemove.call(this, fn, type);
if (custom.base) type = Function.from(custom.base).call(this, type);
}
return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this;
},
addEvents: function(events){
for (var event in events) this.addEvent(event, events[event]);
return this;
},
removeEvents: function(events){
var type;
if (typeOf(events) == 'object'){
for (type in events) this.removeEvent(type, events[type]);
return this;
}
var attached = this.retrieve('events');
if (!attached) return this;
if (!events){
for (type in attached) this.removeEvents(type);
this.eliminate('events');
} else if (attached[events]){
attached[events].keys.each(function(fn){
this.removeEvent(events, fn);
}, this);
delete attached[events];
}
return this;
},
fireEvent: function(type, args, delay){
var events = this.retrieve('events');
if (!events || !events[type]) return this;
args = Array.from(args);
events[type].keys.each(function(fn){
if (delay) fn.delay(delay, this, args);
else fn.apply(this, args);
}, this);
return this;
},
cloneEvents: function(from, type){
from = document.id(from);
var events = from.retrieve('events');
if (!events) return this;
if (!type){
for (var eventType in events) this.cloneEvents(from, eventType);
} else if (events[type]){
events[type].keys.each(function(fn){
this.addEvent(type, fn);
}, this);
}
return this;
}
});
Element.NativeEvents = {
click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons
mousewheel: 2, DOMMouseScroll: 2, //mouse wheel
mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement
keydown: 2, keypress: 2, keyup: 2, //keyboard
orientationchange: 2, // mobile
touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch
gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture
focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, paste: 2, oninput: 2, //form elements
load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window
error: 1, abort: 1, scroll: 1 //misc
};
var check = function(event){
var related = event.relatedTarget;
if (related == null) return true;
if (!related) return false;
return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related));
};
Element.Events = {
mouseenter: {
base: 'mouseover',
condition: check
},
mouseleave: {
base: 'mouseout',
condition: check
},
mousewheel: {
base: (Browser.firefox) ? 'DOMMouseScroll' : 'mousewheel'
}
};
/*<ltIE9>*/
if (!window.addEventListener){
Element.NativeEvents.propertychange = 2;
Element.Events.change = {
base: function(){
var type = this.type;
return (this.get('tag') == 'input' && (type == 'radio' || type == 'checkbox')) ? 'propertychange' : 'change'
},
condition: function(event){
return !!(this.type != 'radio' || this.checked);
}
}
}
/*</ltIE9>*/
})();
/*
---
name: Element.Delegation
description: Extends the Element native object to include the delegate method for more efficient event management.
license: MIT-style license.
requires: [Element.Event]
provides: [Element.Delegation]
...
*/
(function(){
var eventListenerSupport = !!window.addEventListener;
Element.NativeEvents.focusin = Element.NativeEvents.focusout = 2;
var bubbleUp = function(self, match, fn, event){
var target = event.target;
while (target && target != self){
if (match(target, event)) return fn.call(target, event, target);
target = document.id(target.parentNode);
}
};
var map = {
mouseenter: {
base: 'mouseover'
},
mouseleave: {
base: 'mouseout'
},
focus: {
base: 'focus' + (eventListenerSupport ? '' : 'in'),
capture: true
},
blur: {
base: eventListenerSupport ? 'blur' : 'focusout',
capture: true
}
};
/*<ltIE9>*/
var _key = '$delegation:';
var formObserver = function(type){
return {
base: 'focusin',
remove: function(self, uid){
var list = self.retrieve(_key + type + 'listeners', {})[uid];
if (list && list.forms) for (var i = list.forms.length; i--;){
list.forms[i].removeEvent(type, list.fns[i]);
}
},
listen: function(self, match, fn, event, uid){
var target = event.target,
form = (target.get('tag') == 'form') ? target : event.target.getParent('form');
if (!form) return;
var listeners = self.retrieve(_key + type + 'listeners', {}),
listener = listeners[uid] || {forms: [], fns: []},
forms = listener.forms, fns = listener.fns;
if (forms.indexOf(form) != -1) return;
forms.push(form);
var _fn = function(event){
bubbleUp(self, match, fn, event);
};
form.addEvent(type, _fn);
fns.push(_fn);
listeners[uid] = listener;
self.store(_key + type + 'listeners', listeners);
}
};
};
var inputObserver = function(type){
return {
base: 'focusin',
listen: function(self, match, fn, event){
var events = {blur: function(){
this.removeEvents(events);
}};
events[type] = function(event){
bubbleUp(self, match, fn, event);
};
event.target.addEvents(events);
}
};
};
if (!eventListenerSupport) Object.append(map, {
submit: formObserver('submit'),
reset: formObserver('reset'),
change: inputObserver('change'),
select: inputObserver('select')
});
/*</ltIE9>*/
var proto = Element.prototype,
addEvent = proto.addEvent,
removeEvent = proto.removeEvent;
var relay = function(old, method){
return function(type, fn, useCapture){
if (type.indexOf(':relay') == -1) return old.call(this, type, fn, useCapture);
var parsed = Slick.parse(type).expressions[0][0];
if (parsed.pseudos[0].key != 'relay') return old.call(this, type, fn, useCapture);
var newType = parsed.tag;
parsed.pseudos.slice(1).each(function(pseudo){
newType += ':' + pseudo.key + (pseudo.value ? '(' + pseudo.value + ')' : '');
});
return method.call(this, newType, parsed.pseudos[0].value, fn);
};
};
var delegation = {
addEvent: function(type, match, fn){
var storage = this.retrieve('$delegates', {}), stored = storage[type];
if (stored) for (var _uid in stored){
if (stored[_uid].fn == fn && stored[_uid].match == match) return this;
}
var _type = type, _match = match, _fn = fn, _map = map[type] || {};
type = _map.base || _type;
match = function(target){
return Slick.match(target, _match);
};
var elementEvent = Element.Events[_type];
if (elementEvent && elementEvent.condition){
var __match = match, condition = elementEvent.condition;
match = function(target, event){
return __match(target, event) && condition.call(target, event, type);
};
}
var self = this, uid = String.uniqueID();
var delegator = _map.listen ? function(event){
_map.listen(self, match, fn, event, uid);
} : function(event){
bubbleUp(self, match, fn, event);
};
if (!stored) stored = {};
stored[uid] = {
match: _match,
fn: _fn,
delegator: delegator
};
storage[_type] = stored;
return addEvent.call(this, type, delegator, _map.capture);
},
removeEvent: function(type, match, fn, _uid){
var storage = this.retrieve('$delegates', {}), stored = storage[type];
if (!stored) return this;
if (_uid){
var _type = type, delegator = stored[_uid].delegator, _map = map[type] || {};
type = _map.base || _type;
if (_map.remove) _map.remove(this, _uid);
delete stored[_uid];
storage[_type] = stored;
return removeEvent.call(this, type, delegator);
}
var __uid, s;
if (fn) for (__uid in stored){
s = stored[__uid];
if (s.match == match && s.fn == fn) return delegation.removeEvent.call(this, type, match, fn, __uid);
} else for (__uid in stored){
s = stored[__uid];
if (s.match == match) delegation.removeEvent.call(this, type, match, s.fn, __uid);
}
return this;
}
};
[Element, Window, Document].invoke('implement', {
addEvent: relay(addEvent, delegation.addEvent),
removeEvent: relay(removeEvent, delegation.removeEvent)
});
})();
/*
---
@@ -4994,314 +5502,6 @@ Cookie.dispose = function(key, options){
};
/*
---
name: Event
description: Contains the Event Type, to make the event object cross-browser.
license: MIT-style license.
requires: [Window, Document, Array, Function, String, Object]
provides: Event
...
*/
(function() {
var _keys = {};
var DOMEvent = this.DOMEvent = new Type('DOMEvent', function(event, win){
if (!win) win = window;
event = event || win.event;
if (event.$extended) return event;
this.event = event;
this.$extended = true;
this.shift = event.shiftKey;
this.control = event.ctrlKey;
this.alt = event.altKey;
this.meta = event.metaKey;
var type = this.type = event.type;
var target = event.target || event.srcElement;
while (target && target.nodeType == 3) target = target.parentNode;
this.target = document.id(target);
if (type.indexOf('key') == 0){
var code = this.code = (event.which || event.keyCode);
this.key = _keys[code];
if (type == 'keydown'){
if (code > 111 && code < 124) this.key = 'f' + (code - 111);
else if (code > 95 && code < 106) this.key = code - 96;
}
if (this.key == null) this.key = String.fromCharCode(code).toLowerCase();
} else if (type == 'click' || type == 'dblclick' || type == 'contextmenu' || type.indexOf('mouse') == 0){
var doc = win.document;
doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
this.page = {
x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft,
y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop
};
this.client = {
x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX,
y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY
};
if (type == 'DOMMouseScroll' || type == 'mousewheel')
this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
this.rightClick = (event.which == 3 || event.button == 2);
if (type == 'mouseover' || type == 'mouseout'){
var related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element'];
while (related && related.nodeType == 3) related = related.parentNode;
this.relatedTarget = document.id(related);
}
} else if (type.indexOf('touch') == 0 || type.indexOf('gesture') == 0){
this.rotation = event.rotation;
this.scale = event.scale;
this.targetTouches = event.targetTouches;
this.changedTouches = event.changedTouches;
var touches = this.touches = event.touches;
if (touches && touches[0]){
var touch = touches[0];
this.page = {x: touch.pageX, y: touch.pageY};
this.client = {x: touch.clientX, y: touch.clientY};
}
}
if (!this.client) this.client = {};
if (!this.page) this.page = {};
});
DOMEvent.implement({
stop: function(){
return this.preventDefault().stopPropagation();
},
stopPropagation: function(){
if (this.event.stopPropagation) this.event.stopPropagation();
else this.event.cancelBubble = true;
return this;
},
preventDefault: function(){
if (this.event.preventDefault) this.event.preventDefault();
else this.event.returnValue = false;
return this;
}
});
DOMEvent.defineKey = function(code, key){
_keys[code] = key;
return this;
};
DOMEvent.defineKeys = DOMEvent.defineKey.overloadSetter(true);
DOMEvent.defineKeys({
'38': 'up', '40': 'down', '37': 'left', '39': 'right',
'27': 'esc', '32': 'space', '8': 'backspace', '9': 'tab',
'46': 'delete', '13': 'enter'
});
})();
/*
---
name: Element.Event
description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events.
license: MIT-style license.
requires: [Element, Event]
provides: Element.Event
...
*/
(function(){
Element.Properties.events = {set: function(events){
this.addEvents(events);
}};
[Element, Window, Document].invoke('implement', {
addEvent: function(type, fn){
var events = this.retrieve('events', {});
if (!events[type]) events[type] = {keys: [], values: []};
if (events[type].keys.contains(fn)) return this;
events[type].keys.push(fn);
var realType = type,
custom = Element.Events[type],
condition = fn,
self = this;
if (custom){
if (custom.onAdd) custom.onAdd.call(this, fn, type);
if (custom.condition){
condition = function(event){
if (custom.condition.call(this, event, type)) return fn.call(this, event);
return true;
};
}
if (custom.base) realType = Function.from(custom.base).call(this, type);
}
var defn = function(){
return fn.call(self);
};
var nativeEvent = Element.NativeEvents[realType];
if (nativeEvent){
if (nativeEvent == 2){
defn = function(event){
event = new DOMEvent(event, self.getWindow());
if (condition.call(self, event) === false) event.stop();
};
}
this.addListener(realType, defn, arguments[2]);
}
events[type].values.push(defn);
return this;
},
removeEvent: function(type, fn){
var events = this.retrieve('events');
if (!events || !events[type]) return this;
var list = events[type];
var index = list.keys.indexOf(fn);
if (index == -1) return this;
var value = list.values[index];
delete list.keys[index];
delete list.values[index];
var custom = Element.Events[type];
if (custom){
if (custom.onRemove) custom.onRemove.call(this, fn, type);
if (custom.base) type = Function.from(custom.base).call(this, type);
}
return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this;
},
addEvents: function(events){
for (var event in events) this.addEvent(event, events[event]);
return this;
},
removeEvents: function(events){
var type;
if (typeOf(events) == 'object'){
for (type in events) this.removeEvent(type, events[type]);
return this;
}
var attached = this.retrieve('events');
if (!attached) return this;
if (!events){
for (type in attached) this.removeEvents(type);
this.eliminate('events');
} else if (attached[events]){
attached[events].keys.each(function(fn){
this.removeEvent(events, fn);
}, this);
delete attached[events];
}
return this;
},
fireEvent: function(type, args, delay){
var events = this.retrieve('events');
if (!events || !events[type]) return this;
args = Array.from(args);
events[type].keys.each(function(fn){
if (delay) fn.delay(delay, this, args);
else fn.apply(this, args);
}, this);
return this;
},
cloneEvents: function(from, type){
from = document.id(from);
var events = from.retrieve('events');
if (!events) return this;
if (!type){
for (var eventType in events) this.cloneEvents(from, eventType);
} else if (events[type]){
events[type].keys.each(function(fn){
this.addEvent(type, fn);
}, this);
}
return this;
}
});
Element.NativeEvents = {
click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons
mousewheel: 2, DOMMouseScroll: 2, //mouse wheel
mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement
keydown: 2, keypress: 2, keyup: 2, //keyboard
orientationchange: 2, // mobile
touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch
gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture
focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, paste: 2, oninput: 2, //form elements
load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window
error: 1, abort: 1, scroll: 1 //misc
};
var check = function(event){
var related = event.relatedTarget;
if (related == null) return true;
if (!related) return false;
return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related));
};
Element.Events = {
mouseenter: {
base: 'mouseover',
condition: check
},
mouseleave: {
base: 'mouseout',
condition: check
},
mousewheel: {
base: (Browser.firefox) ? 'DOMMouseScroll' : 'mousewheel'
}
};
/*<ltIE9>*/
if (!window.addEventListener){
Element.NativeEvents.propertychange = 2;
Element.Events.change = {
base: function(){
var type = this.type;
return (this.get('tag') == 'input' && (type == 'radio' || type == 'checkbox')) ? 'propertychange' : 'change'
},
condition: function(event){
return !!(this.type != 'radio' || this.checked);
}
}
}
/*</ltIE9>*/
})();
/*
---
+1 -1
View File
@@ -184,7 +184,7 @@ Page.Settings = new Class({
'text': (group.label || group.name).capitalize()
}).adopt(
new Element('span.hint', {
'html': group.description
'html': group.description || ''
})
)
)
+2 -2
View File
@@ -8,11 +8,11 @@ Page.Wanted = new Class({
indexAction: function(param){
var self = this;
if(!self.list){
if(!self.wanted){
// Wanted movies
self.wanted = new MovieList({
'status': ['active', 'snatched'],
'status': 'active',
'actions': MovieActions
});
$(self.wanted).inject(self.el);
+22
View File
@@ -1,6 +1,7 @@
/* @override
http://localhost:5000/static/style/main.css
http://192.168.1.20:5000/static/style/main.css
http://127.0.0.1:5000/static/style/main.css
*/
html {
@@ -211,6 +212,27 @@ form {
.header .navigation li a:hover, .header .navigation li a:active {
color: #b1d8dc;
}
.header .message {
text-align: center;
position: relative;
top: -70px;
padding: 15px 0 20px;
background: #ff6134;
font-size: 26px;
border-radius: 0 0 5px 5px;
-moz-border-radius: 0 0 5px 5px;
-webkit-border-radius: 0 0 5px 5px;
box-shadow: 0 2px 1px rgba(0,0,0, 0.3);
-moz-box-shadow: 0 2px 1px rgba(0,0,0, 0.3);
-webkit-box-shadow: 0 2px 1px rgba(0,0,0, 0.3);
}
.header .message a {
padding: 0 10px;
}
/*** Global Styles ***/
.check {
+7 -4
View File
@@ -11,7 +11,10 @@
# Source: http://pypi.python.org/pypi/axel
# Docs: http://packages.python.org/axel
import sys, threading, Queue
from couchpotato.core.helpers.variable import natcmp
import Queue
import sys
import threading
class Event(object):
"""
@@ -100,7 +103,7 @@ class Event(object):
self.handlers = {}
self.memoize = {}
def handle(self, handler):
def handle(self, handler, priority = 0):
""" Registers a handler. The handler can be transmitted together
with two arguments as a list or dictionary. The arguments are:
@@ -118,7 +121,7 @@ class Event(object):
event += {'handler':handler, 'memoize':True, 'timeout':1.5}
"""
handler_, memoize, timeout = self._extract(handler)
self.handlers[hash(handler_)] = (handler_, memoize, timeout)
self.handlers['%s.%s' % (priority, hash(handler_))] = (handler_, memoize, timeout)
return self
def unhandle(self, handler):
@@ -144,7 +147,7 @@ class Event(object):
t.daemon = True
t.start()
for handler in self.handlers:
for handler in sorted(self.handlers.iterkeys(), cmp = natcmp):
self.queue.put(handler)
if self.asynchronous: