+# custom_event_support.lua #
+
+This is a lua port of CustomEventSupport.js by @azendal. It's a
+simple implementation of the observer pattern.
+
+## Dependencies ##
+
+[Middleclass][https://github.com/kikito/middleclass]
+
+## Usage ##
+
+Step 1. Require it somewhere
+
+```lua
+CustomEvent = require('custom_event')
+CustomEventSupport = require('custom_event_support')
+```
+
+Step 2. Include it in a class
+
+```
+local MyClass = class('MyClass')
+MyClass:include(CustomEventSupport)
+```
+
+Step 3a. Bind events
+
+```lua
+-- Bind them to the class
+MyClass:bind('click', function (self, ev)
+ print("Hey, I caught the event")
+end)
+
+
+-- or bind them to an instance
+local my_instance = MyClass:new()
+my_instance:bind('click', function (self, ev)
+ print("Hey, I caught another event: "..tostring(ev.message))
+end)
+```
+
+Step 3b. Dispatch events
+
+```lua
+-- Dispatch them from the class. You can optionally pass data as a
+table.
+MyClass:dispatch('click')
+
+-- or dispatch them from an instance
+my_instance:dispatch('click', {message = "Instance event!"})
+```
+
+That's it. Enjoy :)
+local CustomEvent = class('CustomEvent')
+
+function CustomEvent:initialize(event_type, data)
+ -- defaults
+ self.bubbles = true
+ self.cancelable = true
+ self.current_target = nil
+ self.timestamp = 0
+ self.target = nil
+ self.type = ''
+ self.is_propagation_stopped = false
+ self.is_default_prevented = false
+ self.is_immediate_propagation_stopped = false
+ self.are_immediate_handlers_prevented = false
+
+ -- init
+ self.type = event_type
+ for k, v in pairs(data) do
+ self[k] = v
+ end
+end
+
+function CustomEvent:stop_propagation()
+ self.is_propagation_stopped = true
+end
+
+function CustomEvent:prevent_default()
+ self.is_default_prevented = true
+end
+
+function CustomEvent:stop_immediate_propagation()
+ self.is_immediate_propagation_stopped = true
+end
+
+function CustomEvent:prevent_immediate_handlers()
+ self.are_immediate_handlers_prevented = true
+end
+
+return CustomEvent;
+local CustomEventSupport = { static = {} }
+
+CustomEventSupport.static.event_listeners = nil
+
+function CustomEventSupport.static:bind(event_type, event_handler)
+ local found, listeners
+
+ if not self.static.event_listeners then
+ self.static.event_listeners = {}
+ end
+
+ if not self.static.event_listeners[event_type] then
+ self.static.event_listeners[event_type] = {}
+ end
+
+ found = false
+
+ listeners = self.static.event_listeners[event_type]
+ for i, v in ipairs(listeners) do
+ if v == event_handler then
+ found = true
+ break
+ end
+ end
+
+ if not found then
+ table.insert(self.static.event_listeners[event_type], event_handler)
+ end
+
+ return self.static
+
+end
+
+function CustomEventSupport.static:unbind(event_type, event_handler)
+ local found, listeners, counter
+
+ if not self.static.event_listeners then
+ self.static.event_listeners = {}
+ end
+
+ if not self.static.event_listeners[event_type] then
+ self.static.event_listeners[event_type] = {}
+ end
+
+ found = false
+
+ listeners = self.static.event_listeners[event_type]
+ for i, v in ipairs(listeners) do
+ if v == event_handler then
+ found = true
+ counter = i
+ break
+ end
+ end
+
+ if found then
+ table.remove(self.static.event_listeners[event_type], counter)
+ end
+
+ return self.static
+end
+
+function CustomEventSupport.static:dispatch(event_type, data)
+ local event, listeners, instance, i
+
+ if not self.static.event_listeners then
+ self.static.event_listeners = {}
+ end
+
+ if not data then
+ data = {}
+ end
+
+ if not data.target then
+ data.target = self
+ end
+
+ -- Create new CustomEvent
+ event = CustomEvent:new(event_type, data)
+ listeners = self.static.event_listeners[event_type] or {}
+ instance = self.static
+
+ for i, v in ipairs(listeners) do
+ v(instance, event)
+ if event.are_immediate_handlers_prevented == true then
+ break
+ end
+ end
+end
+
+CustomEventSupport.event_listeners = nil
+
+function CustomEventSupport:bind(event_type, event_handler)
+ local found, listeners
+
+ if not self.event_listeners then
+ self.event_listeners = {}
+ end
+
+ if not self.event_listeners[event_type] then
+ self.event_listeners[event_type] = {}
+ end
+
+ found = false
+
+ listeners = self.event_listeners[event_type]
+ for i, v in ipairs(listeners) do
+ if v == event_handler then
+ found = true
+ break
+ end
+ end
+
+ if not found then
+ table.insert(self.event_listeners[event_type], event_handler)
+ end
+
+ return self
+
+end
+
+function CustomEventSupport:unbind(event_type, event_handler)
+ local found, listeners, counter
+
+ if not self.event_listeners then
+ self.event_listeners = {}
+ end
+
+ if not self.event_listeners[event_type] then
+ self.event_listeners[event_type] = {}
+ end
+
+ found = false
+
+ listeners = self.event_listeners[event_type]
+ for i, v in ipairs(listeners) do
+ if v == event_handler then
+ found = true
+ counter = i
+ break
+ end
+ end
+
+ if found then
+ table.remove(self.event_listeners[event_type], counter)
+ end
+
+ return self
+end
+
+function CustomEventSupport:dispatch(event_type, data)
+ local event, listeners, instance, i
+
+ if not self.event_listeners then
+ self.event_listeners = {}
+ end
+
+ if not data then
+ data = {}
+ end
+
+ if not data.target then
+ data.target = self
+ end
+
+ -- Create new CustomEvent
+ event = CustomEvent:new(event_type, data)
+ listeners = self.event_listeners[event_type] or {}
+ instance = self
+
+ for i, v in ipairs(listeners) do
+ v(instance, event)
+ if event.are_immediate_handlers_prevented == true then
+ break
+ end
+ end
+end
+
+return CustomEventSupport