234 lines
6.2 KiB
JavaScript
234 lines
6.2 KiB
JavaScript
import Collection from './collection';
|
|
import Super from './super';
|
|
import * as u from './utils';
|
|
|
|
///////////////////////
|
|
/// MANAGER ///
|
|
///////////////////////
|
|
|
|
function Manager (options) {
|
|
var self = this;
|
|
self.ids = {};
|
|
self.index = 0;
|
|
self.collections = [];
|
|
self.scroll = u.getScroll();
|
|
|
|
self.config(options);
|
|
self.prepareCollections();
|
|
|
|
// Listen for resize, to reposition every joysticks
|
|
var resizeHandler = function () {
|
|
var pos;
|
|
self.collections.forEach(function (collection) {
|
|
collection.forEach(function (nipple) {
|
|
pos = nipple.el.getBoundingClientRect();
|
|
nipple.position = {
|
|
x: self.scroll.x + pos.left,
|
|
y: self.scroll.y + pos.top
|
|
};
|
|
});
|
|
});
|
|
};
|
|
u.bindEvt(window, 'resize', function () {
|
|
u.throttle(resizeHandler);
|
|
});
|
|
|
|
// Listen for scrolls, so we have a global scroll value
|
|
// without having to request it all the time.
|
|
var scrollHandler = function () {
|
|
self.scroll = u.getScroll();
|
|
};
|
|
u.bindEvt(window, 'scroll', function () {
|
|
u.throttle(scrollHandler);
|
|
});
|
|
|
|
return self.collections;
|
|
}
|
|
|
|
Manager.prototype = new Super();
|
|
Manager.constructor = Manager;
|
|
|
|
Manager.prototype.prepareCollections = function () {
|
|
var self = this;
|
|
// Public API Preparation.
|
|
self.collections.create = self.create.bind(self);
|
|
// Listen to anything
|
|
self.collections.on = self.on.bind(self);
|
|
// Unbind general events
|
|
self.collections.off = self.off.bind(self);
|
|
// Destroy everything
|
|
self.collections.destroy = self.destroy.bind(self);
|
|
// Get any nipple
|
|
self.collections.get = function (id) {
|
|
var nipple;
|
|
// Use .every() to break the loop as soon as found.
|
|
self.collections.every(function (collection) {
|
|
nipple = collection.get(id);
|
|
return nipple ? false : true;
|
|
});
|
|
return nipple;
|
|
};
|
|
};
|
|
|
|
Manager.prototype.create = function (options) {
|
|
return this.createCollection(options);
|
|
};
|
|
|
|
// Collection Factory
|
|
Manager.prototype.createCollection = function (options) {
|
|
var self = this;
|
|
var collection = new Collection(self, options);
|
|
|
|
self.bindCollection(collection);
|
|
self.collections.push(collection);
|
|
|
|
return collection;
|
|
};
|
|
|
|
Manager.prototype.bindCollection = function (collection) {
|
|
var self = this;
|
|
var type;
|
|
// Bubble up identified events.
|
|
var handler = function (evt, data) {
|
|
// Identify the event type with the nipple's identifier.
|
|
type = evt.type + ' ' + data.id + ':' + evt.type;
|
|
self.trigger(type, data);
|
|
};
|
|
|
|
// When it gets destroyed we clean.
|
|
collection.on('destroyed', self.onDestroyed.bind(self));
|
|
|
|
// Other events that will get bubbled up.
|
|
collection.on('shown hidden rested dir plain', handler);
|
|
collection.on('dir:up dir:right dir:down dir:left', handler);
|
|
collection.on('plain:up plain:right plain:down plain:left', handler);
|
|
};
|
|
|
|
Manager.prototype.bindDocument = function () {
|
|
var self = this;
|
|
// Bind only if not already binded
|
|
if (!self.binded) {
|
|
self.bindEvt(document, 'move')
|
|
.bindEvt(document, 'end');
|
|
self.binded = true;
|
|
}
|
|
};
|
|
|
|
Manager.prototype.unbindDocument = function (force) {
|
|
var self = this;
|
|
// If there are no touch left
|
|
// unbind the document.
|
|
if (!Object.keys(self.ids).length || force === true) {
|
|
self.unbindEvt(document, 'move')
|
|
.unbindEvt(document, 'end');
|
|
self.binded = false;
|
|
}
|
|
};
|
|
|
|
Manager.prototype.getIdentifier = function (evt) {
|
|
var id;
|
|
// If no event, simple increment
|
|
if (!evt) {
|
|
id = this.index;
|
|
} else {
|
|
// Extract identifier from event object.
|
|
// Unavailable in mouse events so replaced by latest increment.
|
|
id = evt.identifier === undefined ? evt.pointerId : evt.identifier;
|
|
if (id === undefined) {
|
|
id = this.latest || 0;
|
|
}
|
|
}
|
|
|
|
if (this.ids[id] === undefined) {
|
|
this.ids[id] = this.index;
|
|
this.index += 1;
|
|
}
|
|
|
|
// Keep the latest id used in case we're using an unidentified mouseEvent
|
|
this.latest = id;
|
|
return this.ids[id];
|
|
};
|
|
|
|
Manager.prototype.removeIdentifier = function (identifier) {
|
|
var removed = {};
|
|
for (var id in this.ids) {
|
|
if (this.ids[id] === identifier) {
|
|
removed.id = id;
|
|
removed.identifier = this.ids[id];
|
|
delete this.ids[id];
|
|
break;
|
|
}
|
|
}
|
|
return removed;
|
|
};
|
|
|
|
Manager.prototype.onmove = function (evt) {
|
|
var self = this;
|
|
self.onAny('move', evt);
|
|
return false;
|
|
};
|
|
|
|
Manager.prototype.onend = function (evt) {
|
|
var self = this;
|
|
self.onAny('end', evt);
|
|
return false;
|
|
};
|
|
|
|
Manager.prototype.oncancel = function (evt) {
|
|
var self = this;
|
|
self.onAny('end', evt);
|
|
return false;
|
|
};
|
|
|
|
Manager.prototype.onAny = function (which, evt) {
|
|
var self = this;
|
|
var id;
|
|
var processFn = 'processOn' + which.charAt(0).toUpperCase() +
|
|
which.slice(1);
|
|
evt = u.prepareEvent(evt);
|
|
var processColl = function (e, id, coll) {
|
|
if (coll.ids.indexOf(id) >= 0) {
|
|
coll[processFn](e);
|
|
// Mark the event to avoid cleaning it later.
|
|
e._found_ = true;
|
|
}
|
|
};
|
|
var processEvt = function (e) {
|
|
id = self.getIdentifier(e);
|
|
u.map(self.collections, processColl.bind(null, e, id));
|
|
// If the event isn't handled by any collection,
|
|
// we need to clean its identifier.
|
|
if (!e._found_) {
|
|
self.removeIdentifier(id);
|
|
}
|
|
};
|
|
|
|
u.map(evt, processEvt);
|
|
|
|
return false;
|
|
};
|
|
|
|
// Cleanly destroy the manager
|
|
Manager.prototype.destroy = function () {
|
|
var self = this;
|
|
self.unbindDocument(true);
|
|
self.ids = {};
|
|
self.index = 0;
|
|
self.collections.forEach(function(collection) {
|
|
collection.destroy();
|
|
});
|
|
self.off();
|
|
};
|
|
|
|
// When a collection gets destroyed
|
|
// we clean behind.
|
|
Manager.prototype.onDestroyed = function (evt, coll) {
|
|
var self = this;
|
|
if (self.collections.indexOf(coll) < 0) {
|
|
return false;
|
|
}
|
|
self.collections.splice(self.collections.indexOf(coll), 1);
|
|
};
|
|
|
|
export default Manager;
|