This app provides monitoring and information features for the common freifunk user and the technical stuff of a freifunk community.
Code base is taken from a TUM Practical Course project and added here to see if Freifunk Altdorf can use it.
https://www.freifunk-altdorf.de
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
6.2 KiB
190 lines
6.2 KiB
/** |
|
* @author Toru Nagashima |
|
* @copyright 2015 Toru Nagashima. All rights reserved. |
|
* See LICENSE file in root directory for full license. |
|
*/ |
|
|
|
"use strict"; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Requirements |
|
//----------------------------------------------------------------------------- |
|
|
|
var Commons = require("./commons"); |
|
var CustomEventTarget = require("./custom-event-target"); |
|
var EventWrapper = require("./event-wrapper"); |
|
var LISTENERS = Commons.LISTENERS; |
|
var CAPTURE = Commons.CAPTURE; |
|
var BUBBLE = Commons.BUBBLE; |
|
var ATTRIBUTE = Commons.ATTRIBUTE; |
|
var newNode = Commons.newNode; |
|
var defineCustomEventTarget = CustomEventTarget.defineCustomEventTarget; |
|
var createEventWrapper = EventWrapper.createEventWrapper; |
|
var STOP_IMMEDIATE_PROPAGATION_FLAG = |
|
EventWrapper.STOP_IMMEDIATE_PROPAGATION_FLAG; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Constants |
|
//----------------------------------------------------------------------------- |
|
|
|
/** |
|
* A flag which shows there is the native `EventTarget` interface object. |
|
* |
|
* @type {boolean} |
|
* @private |
|
*/ |
|
var HAS_EVENTTARGET_INTERFACE = ( |
|
typeof window !== "undefined" && |
|
typeof window.EventTarget !== "undefined" |
|
); |
|
|
|
//----------------------------------------------------------------------------- |
|
// Public Interface |
|
//----------------------------------------------------------------------------- |
|
|
|
/** |
|
* An implementation for `EventTarget` interface. |
|
* |
|
* @constructor |
|
* @public |
|
*/ |
|
var EventTarget = module.exports = function EventTarget() { |
|
if (this instanceof EventTarget) { |
|
// this[LISTENERS] is a Map. |
|
// Its key is event type. |
|
// Its value is ListenerNode object or null. |
|
// |
|
// interface ListenerNode { |
|
// var listener: Function |
|
// var kind: CAPTURE|BUBBLE|ATTRIBUTE |
|
// var next: ListenerNode|null |
|
// } |
|
Object.defineProperty(this, LISTENERS, {value: Object.create(null)}); |
|
} |
|
else if (arguments.length === 1 && Array.isArray(arguments[0])) { |
|
return defineCustomEventTarget(EventTarget, arguments[0]); |
|
} |
|
else if (arguments.length > 0) { |
|
var types = Array(arguments.length); |
|
for (var i = 0; i < arguments.length; ++i) { |
|
types[i] = arguments[i]; |
|
} |
|
|
|
// To use to extend with attribute listener properties. |
|
// e.g. |
|
// class MyCustomObject extends EventTarget("message", "error") { |
|
// //... |
|
// } |
|
return defineCustomEventTarget(EventTarget, types); |
|
} |
|
else { |
|
throw new TypeError("Cannot call a class as a function"); |
|
} |
|
}; |
|
|
|
EventTarget.prototype = Object.create( |
|
(HAS_EVENTTARGET_INTERFACE ? window.EventTarget : Object).prototype, |
|
{ |
|
constructor: { |
|
value: EventTarget, |
|
writable: true, |
|
configurable: true |
|
}, |
|
|
|
addEventListener: { |
|
value: function addEventListener(type, listener, capture) { |
|
if (listener == null) { |
|
return false; |
|
} |
|
if (typeof listener !== "function" && typeof listener !== "object") { |
|
throw new TypeError("\"listener\" is not an object."); |
|
} |
|
|
|
var kind = (capture ? CAPTURE : BUBBLE); |
|
var node = this[LISTENERS][type]; |
|
if (node == null) { |
|
this[LISTENERS][type] = newNode(listener, kind); |
|
return true; |
|
} |
|
|
|
var prev = null; |
|
while (node != null) { |
|
if (node.listener === listener && node.kind === kind) { |
|
// Should ignore a duplicated listener. |
|
return false; |
|
} |
|
prev = node; |
|
node = node.next; |
|
} |
|
|
|
prev.next = newNode(listener, kind); |
|
return true; |
|
}, |
|
configurable: true, |
|
writable: true |
|
}, |
|
|
|
removeEventListener: { |
|
value: function removeEventListener(type, listener, capture) { |
|
if (listener == null) { |
|
return false; |
|
} |
|
|
|
var kind = (capture ? CAPTURE : BUBBLE); |
|
var prev = null; |
|
var node = this[LISTENERS][type]; |
|
while (node != null) { |
|
if (node.listener === listener && node.kind === kind) { |
|
if (prev == null) { |
|
this[LISTENERS][type] = node.next; |
|
} |
|
else { |
|
prev.next = node.next; |
|
} |
|
return true; |
|
} |
|
|
|
prev = node; |
|
node = node.next; |
|
} |
|
|
|
return false; |
|
}, |
|
configurable: true, |
|
writable: true |
|
}, |
|
|
|
dispatchEvent: { |
|
value: function dispatchEvent(event) { |
|
// If listeners aren't registered, terminate. |
|
var node = this[LISTENERS][event.type]; |
|
if (node == null) { |
|
return true; |
|
} |
|
|
|
// Since we cannot rewrite several properties, so wrap object. |
|
var wrapped = createEventWrapper(event, this); |
|
|
|
// This doesn't process capturing phase and bubbling phase. |
|
// This isn't participating in a tree. |
|
while (node != null) { |
|
if (typeof node.listener === "function") { |
|
node.listener.call(this, wrapped); |
|
} |
|
else if (node.kind !== ATTRIBUTE && typeof node.listener.handleEvent === "function") { |
|
node.listener.handleEvent(wrapped); |
|
} |
|
|
|
if (wrapped[STOP_IMMEDIATE_PROPAGATION_FLAG]) { |
|
break; |
|
} |
|
node = node.next; |
|
} |
|
|
|
return !wrapped.defaultPrevented; |
|
}, |
|
configurable: true, |
|
writable: true |
|
} |
|
} |
|
);
|
|
|