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') new_environ[key] = value.encode('iso-8859-1')
subprocess.call(args, env = new_environ) 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: except Exception, e:
log.critical(e) log.critical(e)
return 0 return 0
+1
View File
@@ -18,3 +18,4 @@ def index():
return jsonified({'routes': routes}) return jsonified({'routes': routes})
addApiView('', index) addApiView('', index)
addApiView('default', index)
+5 -6
View File
@@ -1,5 +1,5 @@
from couchpotato.api import addApiView 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.logger import CPLog
from couchpotato.core.plugins.base import Plugin from couchpotato.core.plugins.base import Plugin
from couchpotato.environment import Env from couchpotato.environment import Env
@@ -43,14 +43,13 @@ class Core(Plugin):
time.sleep(1) time.sleep(1)
if restart: if restart:
self.createFile(self.restartFilePath(), 'This is the most suckiest way to register if CP is restarted. Ever...') self.createFile(self.restartFilePath(), 'This is the most suckiest way to register if CP is restarted. Ever...')
func = request.environ.get('werkzeug.server.shutdown') try:
if func is None: request.environ.get('werkzeug.server.shutdown')()
except:
log.error('Failed shutting down the server') log.error('Failed shutting down the server')
func()
def removeRestartFile(self): def removeRestartFile(self):
try: try:
@@ -59,4 +58,4 @@ class Core(Plugin):
pass pass
def restartFilePath(self): 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.event import addEvent
from couchpotato.core.logger import CPLog from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin from couchpotato.core.plugins.base import Plugin
from couchpotato.environment import Env
log = CPLog(__name__) log = CPLog(__name__)
@@ -16,7 +17,10 @@ class Downloader(Plugin):
pass pass
def cpTag(self, movie): 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): def isDisabled(self):
return not self.isEnabled() return not self.isEnabled()
+5 -2
View File
@@ -8,7 +8,7 @@ log = CPLog(__name__)
events = {} events = {}
def addEvent(name, handler): def addEvent(name, handler, priority = 0):
if events.get(name): if events.get(name):
e = events[name] e = events[name]
@@ -27,7 +27,10 @@ def addEvent(name, handler):
return h return h
e += createHandle if name == 'app.initialize':
print 'test', priority
e.handle(createHandle, priority = priority)
def removeEvent(name, handler): def removeEvent(name, handler):
e = events[name] e = events[name]
+2 -2
View File
@@ -19,7 +19,7 @@ class ProfilePlugin(Plugin):
addApiView('profile.save_order', self.saveOrder) addApiView('profile.save_order', self.saveOrder)
addApiView('profile.delete', self.delete) addApiView('profile.delete', self.delete)
addEvent('app.initialize', self.fill) addEvent('app.initialize', self.fill, priority = 90)
def all(self): def all(self):
@@ -127,7 +127,7 @@ class ProfilePlugin(Plugin):
}] }]
# Create default quality profile # Create default quality profile
order = 99 order = -2
for profile in profiles: for profile in profiles:
log.info('Creating default profile: %s' % profile.get('label')) log.info('Creating default profile: %s' % profile.get('label'))
p = Profile( p = Profile(
+1 -1
View File
@@ -32,7 +32,7 @@ class QualityPlugin(Plugin):
addEvent('quality.single', self.single) addEvent('quality.single', self.single)
addEvent('quality.guess', self.guess) addEvent('quality.guess', self.guess)
addEvent('app.initialize', self.fill) addEvent('app.initialize', self.fill, priority = 10)
def all(self): def all(self):
+1 -1
View File
@@ -86,7 +86,7 @@ class Searcher(Plugin):
for info in nzb: for info in nzb:
try: try:
if not isinstance(nzb[info], (str, unicode)): if not isinstance(nzb[info], (str, unicode, int, long)):
continue continue
rls_info = ReleaseInfo( 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.event import addEvent, fireEvent
from couchpotato.core.helpers.request import jsonified
from couchpotato.core.logger import CPLog from couchpotato.core.logger import CPLog
from couchpotato.core.plugins.base import Plugin from couchpotato.core.plugins.base import Plugin
from couchpotato.environment import Env from couchpotato.environment import Env
@@ -10,14 +12,13 @@ log = CPLog(__name__)
class Updater(Plugin): class Updater(Plugin):
git = 'git://github.com/CouchPotato/CouchPotato.git' repo_name = 'RuudBurger/CouchPotatoServer'
running = False running = False
version = None version = None
updateFailed = False update_failed = False
updateAvailable = False update_version = None
updateVersion = None last_check = 0
lastCheck = 0
def __init__(self): def __init__(self):
@@ -27,6 +28,18 @@ class Updater(Plugin):
addEvent('app.load', self.check) 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): def getVersion(self):
if not self.version: if not self.version:
@@ -42,7 +55,7 @@ class Updater(Plugin):
def check(self): def check(self):
if self.updateAvailable or self.isDisabled(): if self.update_version or self.isDisabled():
return return
current_branch = self.repo.getCurrentBranch().name current_branch = self.repo.getCurrentBranch().name
@@ -54,13 +67,17 @@ class Updater(Plugin):
remote = branch.getHead() remote = branch.getHead()
if local.getDate() < remote.getDate(): if local.getDate() < remote.getDate():
if self.conf('automatic') and not self.updateFailed: if self.conf('automatic') and not self.update_failed:
self.doUpdate() self.doUpdate()
else: else:
self.updateAvailable = True self.update_version = remote.hash
self.updateVersion = remote.hash
self.lastCheck = time.time() self.last_check = time.time()
def doUpdateView(self):
return jsonified({
'success': self.doUpdate()
})
def doUpdate(self): def doUpdate(self):
try: try:
@@ -70,7 +87,7 @@ class Updater(Plugin):
except Exception, e: except Exception, e:
log.error('Failed updating via GIT: %s' % e) log.error('Failed updating via GIT: %s' % e)
self.updateFailed = True self.update_failed = True
return False 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', 'name': 'host',
'default': 'http://nzb.su', 'default': 'nzb.su',
'description': 'The hostname of your newznab provider' 'description': 'The hostname of your newznab provider'
}, },
{ {
@@ -72,7 +72,7 @@ var MultipleNewznab = new Class({
if(has_empty) return; if(has_empty) return;
self.add_empty_timeout = setTimeout(function(){ self.add_empty_timeout = setTimeout(function(){
self.createItem(false); self.createItem(false, null, null);
}, 10); }, 10);
}, },
+9 -1
View File
@@ -29,7 +29,7 @@ var CouchPotato = new Class({
else else
self.openPage(window.location.pathname); 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){ pushState: function(e){
@@ -100,6 +100,14 @@ var CouchPotato = new Class({
getPage: function(name){ getPage: function(name){
return this.pages[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); this.fireEvent('removeHighlight', this);
}, },
keyToggle: function(e) { keyToggle: function(e) {
var evt = new Event(e); var evt = (e);
if (evt.key === 'space') { this.toggle(e); } if (evt.key === 'space') { this.toggle(e); }
}, },
toggle: function(e) { toggle: function(e) {
var evt; var evt;
if (this.disabled) { return this; } if (this.disabled) { return this; }
if (e) { if (e) {
evt = new Event(e).stopPropagation(); evt = (e).stopPropagation();
if (evt.target.tagName.toLowerCase() !== 'a') { if (evt.target.tagName.toLowerCase() !== 'a') {
evt.stop(); evt.stop();
} }
@@ -117,7 +117,7 @@ Form.Dropdown = new Class({
}, },
expand: function(e) { expand: function(e) {
clearTimeout(this.collapseInterval); clearTimeout(this.collapseInterval);
var evt = e ? new Event(e).stop() : null; var evt = e ? (e).stop() : null;
this.open = true; this.open = true;
this.input.focus(); this.input.focus();
this.element.addClass('active').addClass('dropdown-active'); this.element.addClass('active').addClass('dropdown-active');
@@ -22,7 +22,7 @@ Form.Radio = new Class({
toggle: function(e) { toggle: function(e) {
if (this.element.hasClass('checked') || this.disabled) { return; } if (this.element.hasClass('checked') || this.disabled) { return; }
var evt; var evt;
if (e) { evt = new Event(e).stop(); } if (e) { evt = (e).stop(); }
if (this.checked) { if (this.checked) {
this.uncheck(); this.uncheck();
} else { } else {
+510 -310
View File
@@ -3,10 +3,10 @@
MooTools: the javascript framework MooTools: the javascript framework
web build: web build:
- http://mootools.net/core/3e4fc9be110c01367e16b46df47d66b7 - http://mootools.net/core/f42fb6d73ea1a13146c5ad9502b442f0
packager build: 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() 'text': (group.label || group.name).capitalize()
}).adopt( }).adopt(
new Element('span.hint', { 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){ indexAction: function(param){
var self = this; var self = this;
if(!self.list){ if(!self.wanted){
// Wanted movies // Wanted movies
self.wanted = new MovieList({ self.wanted = new MovieList({
'status': ['active', 'snatched'], 'status': 'active',
'actions': MovieActions 'actions': MovieActions
}); });
$(self.wanted).inject(self.el); $(self.wanted).inject(self.el);
+22
View File
@@ -1,6 +1,7 @@
/* @override /* @override
http://localhost:5000/static/style/main.css http://localhost:5000/static/style/main.css
http://192.168.1.20: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 { html {
@@ -211,6 +212,27 @@ form {
.header .navigation li a:hover, .header .navigation li a:active { .header .navigation li a:hover, .header .navigation li a:active {
color: #b1d8dc; 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 ***/ /*** Global Styles ***/
.check { .check {
+7 -4
View File
@@ -11,7 +11,10 @@
# Source: http://pypi.python.org/pypi/axel # Source: http://pypi.python.org/pypi/axel
# Docs: http://packages.python.org/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): class Event(object):
""" """
@@ -100,7 +103,7 @@ class Event(object):
self.handlers = {} self.handlers = {}
self.memoize = {} self.memoize = {}
def handle(self, handler): def handle(self, handler, priority = 0):
""" Registers a handler. The handler can be transmitted together """ Registers a handler. The handler can be transmitted together
with two arguments as a list or dictionary. The arguments are: 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} event += {'handler':handler, 'memoize':True, 'timeout':1.5}
""" """
handler_, memoize, timeout = self._extract(handler) 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 return self
def unhandle(self, handler): def unhandle(self, handler):
@@ -144,7 +147,7 @@ class Event(object):
t.daemon = True t.daemon = True
t.start() t.start()
for handler in self.handlers: for handler in sorted(self.handlers.iterkeys(), cmp = natcmp):
self.queue.put(handler) self.queue.put(handler)
if self.asynchronous: if self.asynchronous: