Requires

Provides

Events.js

A mixin that adds support for declarative events assignment

License:
Public domain (http://unlicense.org).
Authors:
Yaroslaff Fedin

The module takes events object defined in options and binds all functions to the widget.

Ready to use event tree can be accessed via .events accessor.

  1. 35
  2. 36
  3. 37
  4. 38
  5. 39
  6. 40
  7. 41
  8. 42
  9. 43
  10. 44
  11. 45
  12. 46
  13. 47
  14. 48
  15. 49
  16. 50
  17. 51
  18. 52
  19. 53
  20. 54
  21. 55
  22. 56
  23. 57
  24. 58
  25. 59
  26. 60
  27. 61
  28. 62
  29. 63
  30. 64
  31. 65
  32. 66
  33. 67
  34. 68
  35. 69
  36. 70
  37. 71
  38. 72
  39. 73
  40. 74
  41. 75
  42. 76
  43. 77
  44. 78
  45. 79
  46. 80
  47. 81
  48. 82
  49. 83
  50. 84
  51. 85
  52. 86
  53. 87
  54. 88
  55. 89
  56. 90
  57. 91
  58. 92
  59. 93
  60. 94
  61. 95
  62. 96
  63. 97
  64. 98
  65. 99
  66. 100
  67. 101
  68. 102
  69. 103
  70. 104
  71. 105
  72. 106
  73. 107
  74. 108
  75. 109
  76. 110
LSD.Module.Events = new Class({ options: { events: {}, states: Array.fast('attached') }, initialize: function() { this.addEvents({ destroy: function() { this.detach(); }, attach: function() { if (!this.events) this.events = this.options.events ? this.bindEvents(this.options.events) : {}; this.addEvents(this.events); }, detach: function() { this.removeEvents(this.events); } }, true); this.parent.apply(this, arguments); this.attach(); }, addEvents: function(events) { return this.setEvents(events, true); }, removeEvents: function(events) { return this.setEvents(events, false); }, setEvents: function(events, state) { var convert = LSD.Module.Events.target, method = state ? 'addEvents' : 'removeEvents', old = Events.prototype[method]; for (var i in events) { if (events[i].call) { //stick to old behaviour when key: function object is passed old.call(this, events); } else { for (name in events) { var subset = events[name]; if (!subset) continue; var target = convert(this, name) if (!target) continue; if (target != this) { if (target == true) target = this; target[method](subset); } else old.call(this, subset); } }; break; } return events; }, bindEvents: function(tree) { if (!tree || tree.call) return tree; if (!this.$bound) this.$bound = {} if (tree.indexOf) { var args, self = this if (tree.map) { args = tree.splice(1); tree = tree[0]; } if (!this.$bound[tree]) { this.$bound[tree] = function() { if (self[tree]) self[tree].apply(self, args || arguments); } } return this.$bound[tree]; } var result = {} for (var i in tree) result[i] = this.bindEvents(tree[i]); return result; } });

Target system re-routes event groups to various objects.

Combine them for fun and profit.

Keyword Object that recieves events
self widget itself (no routing) |
element widget element (when built) |
parent parent widget |
document LSD document |
window window element |
State Condition
enabled widget is enabled |
disabled widget is disabled |
focused widget is focused |
blured widget is blured |
target first focusable parent is focused |
Extras Description
expected Routes events to widgets, selected |
by selectors (keys of event group).|
Provided by Expectations module |
_\w An event group which name starts |
with underscore is auto-applied |

Advanced example:

events: { self: { focus: ‘onFocus’ }, window: { resize: ‘onWindowResize’ }, parent: { element: { //event delegation ‘click:relay(.button)’: ‘onButtonClick’ } }, expected: { ‘button:first-child’: { //waits for widgets parent: {} } } }

  1. 167
  2. 168
  3. 169
  4. 170
  5. 171
  6. 172
  7. 173
  8. 174
  9. 175
  10. 176
  11. 177
  12. 178
  13. 179
  14. 180
  15. 181
  16. 182
  17. 183
  18. 184
  19. 185
  20. 186
  21. 187
  22. 188
  23. 189
  24. 190
  25. 191
  26. 192
  27. 193
  28. 194
  29. 195
  30. 196
  31. 197
  32. 198
  33. 199
  34. 200
  35. 201
  36. 202
  37. 203
  38. 204
  39. 205
  40. 206
  41. 207
  42. 208
  43. 209
  44. 210
  45. 211
  46. 212
  47. 213
  48. 214
  49. 215
  50. 216
  51. 217
  52. 218
  53. 219
  54. 220
  55. 221
  56. 222
  57. 223
  58. 224
  59. 225
  60. 226
  61. 227
  62. 228
  63. 229
  64. 230
  65. 231
  66. 232
  67. 233
  68. 234
  69. 235
  70. 236
  71. 237
  72. 238
  73. 239
  74. 240
  75. 241
  76. 242
  77. 243
  78. 244
  79. 245
  80. 246
  81. 247
  82. 248
  83. 249
  84. 250
  85. 251
  86. 252
  87. 253
  88. 254
  89. 255
  90. 256
  91. 257
  92. 258
  93. 259
  94. 260
  95. 261
  96. 262
  97. 263
  98. 264
LSD.Module.Events.Promise = function() { this.events = {} } LSD.Module.Events.Promise.prototype = { addEvents: function(events) { for (var name in events) { var group = this.events[name] if (!group) group = this.events[name] = []; group.push(events[name]); } }, removeEvents: function(events) { for (var name in events) { var group = this.events[name] if (group) group.erase(events[name]); } }, realize: function(object) { for (var name in this.events) for (var i = 0, fn; fn = this.events[name][i++];) object.addEvent(name, fn); } } LSD.Module.Events.Targets = { self: function() { return this }, element: function() { if (this.element) return this.element; var promise = this.$events.$element; if (!promise) { promise = this.$events.$element = new LSD.Module.Events.Promise this.addEvent('build', function() { promise.realize(this.element) }); } return promise; }, window: function() { return window; }, document: function() { return this.document; }, parent: function() { var self = this, watchers = this.watchers, group; var listeners = { inject: function(widget) { if (widget instanceof LSD.Widget) widget.addEvents(group); }, dispose: function(widget) { if (widget instanceof LSD.Widget) widget.removeEvents(group); } }; return { addEvents: function(events) { group = events; self.addEvents(listeners); if (self.parentNode) listeners.inject(self.parentNode); }, removeEvents: function(events) { group = events; self.removeEvents(listeners); if (self.parentNode) listeners.dispose(self.parentNode); } } }, mobile: function() { return this; } }; !function(Events, Known, Positive, Negative) { Object.each(Object.append({}, Positive, Negative), function(state, name) { var positive = !!Positive[name]; LSD.Module.Events.Targets[name] = function() { var self = this, setting = Known[state], group; var add = function() { self.addEvents(group); } var remove = function() { self.removeEvents(group) } return { addEvents: function(events) { group = events; if (positive ^ !self[state]) add.call(this); self.addEvent(setting[positive ? 'enabler' : 'disabler'], add); self.addEvent(setting[!positive ? 'enabler' : 'disabler'], remove); }, removeEvents: function(events) { group = events; if (positive ^ self[state]) remove.call(this); self.removeEvent(setting[!positive ? 'enabler' : 'disabler'], add); self.removeEvent(setting[positive ? 'enabler' : 'disabler'], remove); } } } }); }(LSD.Module.Events, LSD.States.Known, LSD.States.Positive, LSD.States.Negative)
  1. 270
  2. 271
  3. 272
  4. 273
  5. 274
  6. 275
LSD.Module.Events.target = function(self, name) { if (name.charAt(0) == "_") return true; var target = LSD.Module.Events.Targets[name]; if (!target) return; return target.call(self) }

Defines special on pseudo class for events used for event delegation. The difference between usual event delegation (which is :relay in mootools) and this, is that with :on you can use LSD selectors and it fires callbacks in context of widgets.

element.addEvent(‘mouseover:on(button)’, callback)

  1. 287
  2. 288
  3. 289
  4. 290
  5. 291
  6. 292
  7. 293
  8. 294
Event.definePseudo('on', function(split, fn, args){ var event = args[0]; var widget = Element.get(event.target, 'widget'); if (widget && widget.match(split.value)) { fn.call(widget, event, widget, event.target); return; } });