JavaScript event framework