UNPKG

mini-event-emitter

Version:

An easy javascript EventEmitter which has no dependencies and the possibility to group events, log errors and trace events

319 lines (197 loc) 7.87 kB
class MiniEventEmitter constructor: (@mini, obj) -> # Define and store settings @mini.settings = name : obj?.name || "MiniEventEmitter" error : obj?.error || false trace : obj?.trace || false # Store all events @mini.events = {} # Store all groups @mini.groups = {} # -------------------------------------------------- # Public available # -------------------------------------------------- on: (event, group, fn) => # Make group optional [group, fn] = @optional group, fn # Check if the input is valid if not allow chaining return @mini if not @valid "on", event, group, fn # Check if the provided group exists if (groups = @mini.groups)[group] # Check if the provided event exists within this group and either push to or create an array with fns if groups[group][event] then groups[group][event].push fn else groups[group][event] = [fn] else # Create the provided group groups[group] = {} # Create an array with fn for this group and event groups[group][event] = [fn] # Either add a new event or push it to a list with others if (events = @mini.events)[event] then events[event].push fn else events[event] = [fn] # Allow chaining @mini off: (event, group, fn) => # Remove all events, groups and eventListeners return @removeAll() if arguments.length is 0 # Make group optional [group, fn] = @optional group, fn # Check if the input is valid if not allow chaining return @mini if not @valid "off", event, group, fn # Provided group does not exist if not @mini.groups[group] @error "off", 7, event, group # Allow chaining return @mini # No event (event === null) is provided so remove all events and fns from the provided group return @removeGroup group if not event # Event name does not exist for the provided group if not fns = @mini.groups[group][event] @error "off", 8, event, group # Allow chaining return @mini # If no fn to remove is provided, remove all fns of the event+group return @removeFns event, group, fns if not fn # Provided fn to remove is not found for the provided event and group if -1 is index = fns.indexOf fn @error "off", 2, event, group # Allow chaining return @mini # Remove single fn @removeFn event, group, fns, fn, index # Allow chaining @mini emitIf: => @_emit arguments, true emit: => @_emit arguments _emit: (args, skip) -> # Turn arguments into an array args = Array.from args # Retrieve event name from the provided arguments event = args.shift() # Check if the provided event exists return @mini if not fns = @validEvent event, skip # Trace the event @trace event, args # Excecute all fns of the event fn.apply fn, args for fn in fns by -1 # Allow chaining @mini # -------------------------------------------------- # Helpers # -------------------------------------------------- valid: (name, event, group, fn) -> if name is "on" # Event name MUST be a string return @error name, 1 if not @isString event # Group MUST be a string return @error name, 5 if not @isString group # Fn MUST be a function return @error name, 6, event, group if not @isFunction fn if name is "off" # Event name MUST be a string OR null return @error name, 1 if event isnt null and not @isString event # Group MUST be a string return @error name, 5 if not @isString group # Fn MAY be a function return @error name, 6, event, group if fn and not @isFunction fn true validEvent: (event, skip) -> # Event was not provided return @error "emit", 3 if not event # Event name must be a string return @error "emit", 1 if not @isString event # Event name does not exist if not fns = @mini.events[event] # Send the error with emit but not with emitIf @error "emit", 4, event if not skip return null # Return all found fn's to be excecuted fns error: (name, id, event, group) -> # Prefix all error messages with the MiniEventEmitter text msg = "#{name} ~ " if id is 1 then msg += "Event name must be a string" if id is 2 then msg += "Provided function to remove with event \"#{event}\" in group \"#{group}\" is not found" if id is 3 then msg += "Event was not provided" if id is 4 then msg += "EventListener for event \"#{event}\" does not exist" if id is 5 then msg += "Provided group must be a string" if id is 6 then msg += "The last param provided with event \"#{event}\" and group \"#{group}\" is expected to be a function" if id is 7 then msg += "Provided group \"#{group}\" is not found" if id is 8 then msg += "Event \"#{event}\" does not exist for the provided group \"#{group}\"" # Allow for external code to listen in @mini.listen "error", event, [msg, name, id, group] # Only log the message if they are required return null if not @mini.settings.error msg = "#{@mini.settings.name} ~ #{msg}" # Log the message to the console (as a warning if available) if console then (if console.warn then console.warn msg else console.log msg) null optional: (group, fn) -> # Check if the "actual" group was provided or only an event and fucntion if not fn? and @isFunction group # Group contains the fn, so correct accordingly fn = group # Set group to default group = "" else # Make sure the group is a string group = "" if not group # Return new group and fn [group, fn] removeAll: -> # Removes all MiniEventEmitter's references to events, groups and eventListeners @mini.events = {} @mini.groups = {} # Allow chaining @mini removeGroup: (group) -> # Remove all events of the provided group @removeFns event, group, fns for event, fns of @mini.groups[group] # Allow chaining @mini removeFns: (event, group, fns) => # Loop over all found fns in the group in reverse order to maintain the correct indexes after splice has been performed @removeFn event, group, fns, fn for fn in fns by -1 # Allow chaining @mini removeFn: (event, group, fns, fn, index) => # Get the index of the fn in the fns if no index is provided index = fns.indexOf fn if not index # Remove fn from groups list fns.splice index, 1 # If no fns are left within the event of a group remove it (clean up) delete @mini.groups[group][event] if fns.length is 0 # If no events are left within the group remove it (clean up) delete @mini.groups[group] if 0 is @objLength @mini.groups[group] # Get the index of the fn in the eventlist index = @mini.events[event].indexOf fn # Remove fn from the eventlist @mini.events[event].splice index, 1 # If no fns are left within the eventlist remove it (clean up) delete @mini.events[event] if @mini.events[event].length is 0 trace: (event, args) -> # Allow for external code to listen in @mini.listen "trace", event, args # If traced, all *emited* events will be loged *before* the event is actually emitted if @mini.settings.trace # The trace message msg = "#{@mini.settings.name} ~ trace ~ #{event}" # Make trace messages blue if the log.debug is available (in browser) if args.length is 0 # Log without arguments if console.debug then console.log "%c #{msg}", "color: #13d" else console.log msg else # Log arguments as well if console.debug then console.log "%c #{msg}", "color: #13d", args else console.log msg, args # Shortcuts isString: (event) -> typeof event is "string" or event instanceof String objLength: (obj) -> Object.keys(obj).length isFunction: (fn) -> typeof fn is "function" # -------------------------------------------------- # Expose # -------------------------------------------------- # Require | Browserify, Node module.exports = MiniEventEmitter # Distribution | Browser # window.MiniEventEmitter = MiniEventEmitter