Skip to content

Commit

Permalink
Make Class.Pseudos to work with Core/Element.Delegation
Browse files Browse the repository at this point in the history
  • Loading branch information
Arian committed Aug 3, 2011
1 parent e34f032 commit db04736
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 338 deletions.
95 changes: 37 additions & 58 deletions Source/Class/Events.Pseudos.js
Expand Up @@ -17,22 +17,24 @@ provides: [Events.Pseudos]
...
*/

(function(){

Events.Pseudos = function(pseudos, addEvent, removeEvent){

var storeKey = 'monitorEvents:';
var storeKey = '_monitorEvents:';

var storageOf = function(object){
return {
store: object.store ? function(key, value){
object.store(storeKey + key, value);
} : function(key, value){
(object.$monitorEvents || (object.$monitorEvents = {}))[key] = value;
(object._monitorEvents || (object._monitorEvents = {}))[key] = value;
},
retrieve: object.retrieve ? function(key, dflt){
return object.retrieve(storeKey + key, dflt);
} : function(key, dflt){
if (!object.$monitorEvents) return dflt;
return object.$monitorEvents[key] || dflt;
if (!object._monitorEvents) return dflt;
return object._monitorEvents[key] || dflt;
}
};
};
Expand All @@ -45,24 +47,20 @@ Events.Pseudos = function(pseudos, addEvent, removeEvent){
l = parsedPseudos.length,
splits = [];

while (l--) if (pseudos[parsedPseudos[l].key]){
splits.push({
while (l--){
var pseudo = parsedPseudos[l].key,
listener = pseudos[pseudo];
if (listener != null) splits.push({
event: parsed.tag,
value: parsedPseudos[l].value,
pseudo: parsedPseudos[l].key,
original: type
pseudo: pseudo,
original: type,
listener: listener
});
}

return splits.length ? splits : null;
};

var mergePseudoOptions = function(split){
return Object.merge.apply(this, split.map(function(item){
return pseudos[item.pseudo].options || {};
}));
};

return {

addEvent: function(type, fn, internal){
Expand All @@ -72,29 +70,25 @@ Events.Pseudos = function(pseudos, addEvent, removeEvent){
var storage = storageOf(this),
events = storage.retrieve(type, []),
eventType = split[0].event,
options = mergePseudoOptions(split),
stack = fn,
eventOptions = options[eventType] || {},
args = Array.slice(arguments, 2),
stack = fn,
self = this,
monitor;

if (eventOptions.args) args.append(Array.from(eventOptions.args));
if (eventOptions.base) eventType = eventOptions.base;
if (eventOptions.onAdd) eventOptions.onAdd(this);

split.each(function(item){
var stackFn = stack;
stack = function(){
(eventOptions.listener || pseudos[item.pseudo].listener).call(self, item, stackFn, arguments, monitor, options);
var listener = item.listener,
stackFn = stack;
if (listener == false) eventType += ':' + item.pseudo + '(' + item.value + ')';
else stack = function(){
listener.call(self, item, stackFn, arguments, monitor);
};
});
monitor = stack.bind(this);

events.include({event: fn, monitor: monitor});
events.include({type: eventType, event: fn, monitor: monitor});
storage.store(type, events);

addEvent.apply(this, [type, fn].concat(args));
if (type != eventType) addEvent.apply(this, [type, fn].concat(args));
return addEvent.apply(this, [eventType, monitor].concat(args));
},

Expand All @@ -106,18 +100,11 @@ Events.Pseudos = function(pseudos, addEvent, removeEvent){
events = storage.retrieve(type);
if (!events) return this;

var eventType = split[0].event,
options = mergePseudoOptions(split),
eventOptions = options[eventType] || {},
args = Array.slice(arguments, 2);

if (eventOptions.args) args.append(Array.from(eventOptions.args));
if (eventOptions.base) eventType = eventOptions.base;
if (eventOptions.onRemove) eventOptions.onRemove(this);
var args = Array.slice(arguments, 2);

removeEvent.apply(this, [type, fn].concat(args));
events.each(function(monitor, i){
if (!fn || monitor.event == fn) removeEvent.apply(this, [eventType, monitor.monitor].concat(args));
if (!fn || monitor.event == fn) removeEvent.apply(this, [monitor.type, monitor.monitor].concat(args));
delete events[i];
}, this);

Expand All @@ -129,40 +116,32 @@ Events.Pseudos = function(pseudos, addEvent, removeEvent){

};

(function(){

var pseudos = {

once: {
listener: function(split, fn, args, monitor){
fn.apply(this, args);
this.removeEvent(split.event, monitor)
.removeEvent(split.original, fn);
}
once: function(split, fn, args, monitor){
fn.apply(this, args);
this.removeEvent(split.event, monitor)
.removeEvent(split.original, fn);
},

throttle: {
listener: function(split, fn, args){
if (!fn._throttled){
fn.apply(this, args);
fn._throttled = setTimeout(function(){
fn._throttled = false;
}, split.value || 250);
}
throttle: function(split, fn, args){
if (!fn._throttled){
fn.apply(this, args);
fn._throttled = setTimeout(function(){
fn._throttled = false;
}, split.value || 250);
}
},

pause: {
listener: function(split, fn, args){
clearTimeout(fn._pause);
fn._pause = fn.delay(split.value || 250, this, args);
}
pause: function(split, fn, args){
clearTimeout(fn._pause);
fn._pause = fn.delay(split.value || 250, this, args);
}

};

Events.definePseudo = function(key, listener){
pseudos[key] = Type.isFunction(listener) ? {listener: listener} : listener;
pseudos[key] = listener;
return this;
};

Expand Down
118 changes: 2 additions & 116 deletions Source/Element/Element.Delegation.js
Expand Up @@ -16,125 +16,11 @@ authors:
- Aaron Newton
- Daniel Steigerwald
requires: [/MooTools.More, Element.Event.Pseudos]
requires: [Core/Element.Delegation, /MooTools.More, Element.Event.Pseudos]
provides: [Element.Delegation]
...
*/

(function(){

var eventListenerSupport = !(window.attachEvent && !window.addEventListener),
nativeEvents = Element.NativeEvents;

nativeEvents.focusin = 2;
nativeEvents.focusout = 2;

var check = function(split, target, event){
var elementEvent = Element.Events[split.event], condition;
if (elementEvent) condition = elementEvent.condition;
return Slick.match(target, split.value) && (!condition || condition.call(target, event));
};

var bubbleUp = function(split, event, fn){
for (var target = event.target; target && target != this; target = document.id(target.parentNode)){
if (target && check(split, target, event)) return fn.call(target, event, target);
}
};

var formObserver = function(eventName){

var $delegationKey = '$delegation:';

return {
base: 'focusin',

onRemove: function(element){
element.retrieve($delegationKey + 'forms', []).each(function(el){
el.retrieve($delegationKey + 'listeners', []).each(function(listener){
el.removeEvent(eventName, listener);
});
el.eliminate($delegationKey + eventName + 'listeners')
.eliminate($delegationKey + eventName + 'originalFn');
});
},

listener: function(split, fn, args, monitor, options){
var event = args[0],
forms = this.retrieve($delegationKey + 'forms', []),
target = event.target,
form = (target.get('tag') == 'form') ? target : event.target.getParent('form');

if (!form) return;

var formEvents = form.retrieve($delegationKey + 'originalFn', []),
formListeners = form.retrieve($delegationKey + 'listeners', []),
self = this;

forms.include(form);
this.store($delegationKey + 'forms', forms);

if (!formEvents.contains(fn)){
var formListener = function(event){
bubbleUp.call(self, split, event, fn);
};
form.addEvent(eventName, formListener);

formEvents.push(fn);
formListeners.push(formListener);

form.store($delegationKey + eventName + 'originalFn', formEvents)
.store($delegationKey + eventName + 'listeners', formListeners);
}
}
};
};

var inputObserver = function(eventName){
return {
base: 'focusin',
listener: function(split, fn, args){
var events = {blur: function(){
this.removeEvents(events);
}}, self = this;
events[eventName] = function(event){
bubbleUp.call(self, split, event, fn);
};
args[0].target.addEvents(events);
}
};
};

var eventOptions = {
mouseenter: {
base: 'mouseover'
},
mouseleave: {
base: 'mouseout'
},
focus: {
base: 'focus' + (eventListenerSupport ? '' : 'in'),
args: [true]
},
blur: {
base: eventListenerSupport ? 'blur' : 'focusout',
args: [true]
}
};

if (!eventListenerSupport) Object.append(eventOptions, {
submit: formObserver('submit'),
reset: formObserver('reset'),
change: inputObserver('change'),
select: inputObserver('select')
});

Event.definePseudo('relay', {
listener: function(split, fn, args){
bubbleUp.call(this, split, args[0], fn);
},
options: eventOptions
});

})();
Event.definePseudo('relay', false);
2 changes: 1 addition & 1 deletion Source/Element/Element.Event.Pseudos.js
Expand Up @@ -26,7 +26,7 @@ var pseudos = {},
while (count--) pseudos[copyFromEvents[count]] = Events.lookupPseudo(copyFromEvents[count]);

Event.definePseudo = function(key, listener){
pseudos[key] = Type.isFunction(listener) ? {listener: listener} : listener;
pseudos[key] = listener;
return this;
};

Expand Down
20 changes: 10 additions & 10 deletions Tests/Interactive/Element/Element.Event.Pseudos.html
Expand Up @@ -12,13 +12,13 @@
Press shift+a and there should appear some text below. Pressing it once again should not fire the event because of the <code>:once</code> pseudo.
</p>

<div id="result"><h3>keydown:keys(shift+a):once</h3></div>
<div id="result1"><h3>keydown:keys(shift+a):once</h3></div>

<h3>click:relay(p.clickmeOnce):once</h3>
<p class="clickme once">Clickme :once</p>
<div id="result2"></div>

<h3>click:relay(p.clickmethrottle):throttle(1000)</h3>
<h3>click:throttle(1000)</h3>
<p id="throttle" class="clickme">:throttle(1000) - Click me quickly after each other. Event should fire 1 time / second</p>
<div id="result3"></div>

Expand All @@ -28,29 +28,29 @@ <h3>keydown:pause(300)</h3>
<div id="result4"></div>


<script src="/depender/build?require=More/Element.Event.Pseudos.Keys,More/Element.Delegation"></script>
<script src="/depender/build?require=Core/Element.Delegation,More/Element.Delegation,More/Element.Event.Pseudos.Keys"></script>

<script>

var result = $('result'),
var result1 = $('result1'),
result2 = $('result2'),
result3 = $('result2'),
result4 = $('result2');
result3 = $('result3'),
result4 = $('result4');

document.addEvent('keydown:keys(shift+a):once', function(){
result.set('html', result.get('html') + 'succes :keydown:keys(shift+a)!<br>');
result1.set('html', result1.get('html') + 'succes keydown:keys(shift+a):once!<br>');
});

document.addEvent('click:relay(p.once):once', function(event){
result2.set('html', result2.get('html') + 'succes :relay(p):once!<br>');
result2.set('html', result2.get('html') + 'succes click:relay(p):once!<br>');
});

document.id('throttle').addEvent('click:throttle(1000)', function(event){
result3.set('html', result3.get('html') + 'succes :relay(p):throttle!<br>');
result3.set('html', result3.get('html') + 'succes click:throttle(1000)!<br>');
});

document.id('pause').addEvent('keydown:pause(300)', function(event){
result4.set('html', result4.get('html') + 'succes :pause(300)!<br>');
result4.set('html', result4.get('html') + 'succes keydown:pause(300)!<br>');
});

</script>

0 comments on commit db04736

Please sign in to comment.