lsd_rails 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/Packages/Sheet.js/Source/SheetParser.Value.js +1 -1
  2. data/Packages/lsd/Source/Action/Clone.js +2 -12
  3. data/Packages/lsd/Source/Action/Delete.js +1 -7
  4. data/Packages/lsd/Source/Action/Display.js +7 -7
  5. data/Packages/lsd/Source/Action/Edit.js +2 -2
  6. data/Packages/lsd/Source/Action/Invoke.js +2 -2
  7. data/Packages/lsd/Source/Action/Submit.js +2 -0
  8. data/Packages/lsd/Source/Action/Toggle.js +4 -0
  9. data/Packages/lsd/Source/Action/Update.js +2 -1
  10. data/Packages/lsd/Source/Action.js +4 -5
  11. data/Packages/lsd/Source/Document.js +10 -7
  12. data/Packages/lsd/Source/LSD.js +22 -127
  13. data/Packages/lsd/Source/Layer.js +4 -4
  14. data/Packages/lsd/Source/Layout.js +1077 -259
  15. data/Packages/lsd/Source/Mixin/Animation.js +1 -1
  16. data/Packages/lsd/Source/Mixin/Choice.js +2 -2
  17. data/Packages/lsd/Source/Mixin/Command.js +26 -8
  18. data/Packages/lsd/Source/Mixin/ContentEditable.js +2 -1
  19. data/Packages/lsd/Source/{Trait → Mixin}/Date.js +21 -11
  20. data/Packages/lsd/Source/{Trait/Menu.js → Mixin/Details.js} +6 -1
  21. data/Packages/lsd/Source/Mixin/Draggable.js +1 -1
  22. data/Packages/lsd/Source/Mixin/Fieldset.js +51 -49
  23. data/Packages/lsd/Source/Mixin/Focusable.js +38 -39
  24. data/Packages/lsd/Source/Mixin/Invokable.js +13 -14
  25. data/Packages/lsd/Source/Mixin/List.js +9 -17
  26. data/Packages/lsd/Source/Mixin/Placeholder.js +2 -7
  27. data/Packages/lsd/Source/Mixin/Request.js +5 -3
  28. data/Packages/lsd/Source/Mixin/Resizable.js +3 -3
  29. data/Packages/lsd/Source/Mixin/Resource.js +1 -1
  30. data/Packages/lsd/Source/Mixin/Root.js +17 -1
  31. data/Packages/lsd/Source/Mixin/Scrollable.js +1 -1
  32. data/Packages/lsd/Source/{Trait → Mixin}/Slider.js +0 -0
  33. data/Packages/lsd/Source/Mixin/Sortable.js +2 -2
  34. data/Packages/lsd/Source/Mixin/Submittable.js +2 -1
  35. data/Packages/lsd/Source/Mixin/Target.js +11 -6
  36. data/Packages/lsd/Source/Mixin/Touchable.js +2 -2
  37. data/Packages/lsd/Source/Mixin/Unselectable.js +1 -1
  38. data/Packages/lsd/Source/Mixin/Uploader.js +11 -13
  39. data/Packages/lsd/Source/Mixin/Validity.js +35 -9
  40. data/Packages/lsd/Source/Mixin/Value.js +5 -3
  41. data/Packages/lsd/Source/Module/Accessories/Attributes.js +90 -89
  42. data/Packages/lsd/Source/Module/Accessories/Chain.js +40 -25
  43. data/Packages/lsd/Source/Module/Accessories/Element.js +59 -58
  44. data/Packages/lsd/Source/Module/Accessories/Events.js +25 -10
  45. data/Packages/lsd/Source/Module/Accessories/Options.js +11 -13
  46. data/Packages/lsd/Source/Module/Accessories/States.js +42 -5
  47. data/Packages/lsd/Source/Module/Accessories/Styles.js +1 -1
  48. data/Packages/lsd/Source/Module/Accessories/Tag.js +21 -7
  49. data/Packages/lsd/Source/Module/Ambient/Allocations.js +178 -64
  50. data/Packages/lsd/Source/Module/Ambient/DOM.js +98 -55
  51. data/Packages/lsd/Source/Module/Ambient/Expectations.js +57 -8
  52. data/Packages/lsd/Source/Module/Ambient/Interpolations.js +147 -0
  53. data/Packages/lsd/Source/Module/Ambient/Layout.js +52 -15
  54. data/Packages/lsd/Source/Module/Ambient/Proxies.js +44 -36
  55. data/Packages/lsd/Source/Module/Ambient/Relations.js +3 -1
  56. data/Packages/lsd/Source/Module/Ambient/Selectors.js +3 -3
  57. data/Packages/lsd/Source/Module/Ambient.js +2 -2
  58. data/Packages/lsd/Source/Module/Graphics/Layers.js +1 -1
  59. data/Packages/lsd/Source/Module/Graphics/Render.js +1 -1
  60. data/Packages/lsd/Source/Relation.js +19 -20
  61. data/Packages/lsd/Source/Sheet.js +4 -5
  62. data/Packages/lsd/Source/{Behavior.js → Tools/Behavior.js} +0 -0
  63. data/Packages/lsd/Source/Tools/Command.js +190 -0
  64. data/Packages/lsd/Source/Tools/Helpers.js +109 -0
  65. data/Packages/lsd/Source/Tools/Interpolation.js +351 -0
  66. data/Packages/lsd/Source/Tools/Microdata.js +75 -0
  67. data/Packages/lsd/Source/Tools/Object.js +192 -0
  68. data/Packages/lsd/Source/Tools/Position.js +208 -0
  69. data/Packages/lsd/Source/Tools/Require.js +76 -0
  70. data/Packages/lsd/Source/Type.js +2 -2
  71. data/Packages/lsd/package.yml +11 -7
  72. data/Packages/lsd-mobile/Source/Body/Dialog.js +2 -2
  73. data/Packages/lsd-mobile/Source/Input/Date.js +9 -84
  74. data/Packages/lsd-native/Source/Input/Checkbox.js +4 -4
  75. data/Packages/lsd-native/Source/Input/Date.js +46 -6
  76. data/Packages/lsd-native/Source/Input/Radio.js +1 -4
  77. data/Packages/lsd-native/Source/Input.js +5 -6
  78. data/Packages/lsd-widgets/Source/Body/Dialog.js +9 -6
  79. data/Packages/lsd-widgets/Source/Body/Page.js +1 -1
  80. data/Packages/lsd-widgets/Source/Body.js +1 -1
  81. data/Packages/lsd-widgets/Source/Button.js +1 -1
  82. data/Packages/lsd-widgets/Source/Form.js +1 -1
  83. data/Packages/lsd-widgets/Source/Input/Checkbox.js +2 -2
  84. data/Packages/lsd-widgets/Source/Input/Date.js +45 -16
  85. data/Packages/lsd-widgets/Source/Input/File.js +2 -2
  86. data/Packages/lsd-widgets/Source/Input/HTML.js +2 -2
  87. data/Packages/lsd-widgets/Source/Input/Radio.js +1 -1
  88. data/Packages/lsd-widgets/Source/Input/Range.js +2 -2
  89. data/Packages/lsd-widgets/Source/Input/Submit.js +1 -1
  90. data/Packages/lsd-widgets/Source/Input.js +2 -11
  91. data/Packages/lsd-widgets/Source/Label.js +4 -8
  92. data/Packages/lsd-widgets/Source/Menu/List.js +3 -3
  93. data/Packages/lsd-widgets/Source/Menu.js +2 -2
  94. data/Packages/lsd-widgets/Source/Progress.js +1 -1
  95. data/Packages/lsd-widgets/Source/Select.js +7 -6
  96. data/Packages/lsd-widgets/Source/Table/Calendar.js +41 -15
  97. data/Packages/lsd-widgets/Source/Table.js +7 -2
  98. data/Packages/mootools-ext/Source/Core/Class.Mixin.js +43 -38
  99. data/Packages/mootools-ext/Source/Core/Class.States.js +26 -22
  100. data/Packages/mootools-ext/Source/Element/Element.from.js +1 -1
  101. data/Packages/mootools-ext/Source/Element/Properties/Item.js +1 -2
  102. data/Packages/mootools-ext/Source/Request/Request.Statuses.js +9 -7
  103. data/Packages/mootools-ext/Source/Types/{FastArray.js → Object.Array.js} +8 -14
  104. data/Packages/mootools-ext/package.yml +1 -2
  105. data/lib/lsd.rake +28 -0
  106. metadata +15 -11
  107. data/Packages/lsd/Source/Command.js +0 -135
  108. data/Packages/lsd/Source/Interpolation.js +0 -103
  109. data/Packages/lsd/Source/Module/Ambient/Container.js +0 -56
  110. data/Packages/mootools-ext/Source/Element/Element.onDispose.js +0 -36
@@ -60,10 +60,12 @@ LSD.Module.Chain = new Class({
60
60
 
61
61
  eachLink: function(filter, args, ahead, revert, target) {
62
62
  if (filter && filter.indexOf) filter = Iterators[filter];
63
- if (args != null && !args.push) args = LSD.slice(args);
64
-
63
+ if (args != null && !args.push) args = LSD.slice(args);
65
64
  var chain = this.currentChain || (this.currentChain = this.getActionChain.apply(this, args));
66
- if (!chain.length) return this.clearChain();
65
+ if (!chain.length) {
66
+ if (this.chainPhase > -1) this.clearChain();
67
+ return false;
68
+ }
67
69
  var index = this.chainPhase;
68
70
  if (ahead) index += +ahead;
69
71
  if (ahead == 1 && index == chain.length) {
@@ -80,7 +82,7 @@ LSD.Module.Chain = new Class({
80
82
  };
81
83
  if (action) {
82
84
  if (revert) {
83
- var last = phases.getLast();
85
+ var last = phases[phases.length - 1];
84
86
  if (last && last.asynchronous && last.index < this.chainPhase) break;
85
87
  phases.pop();
86
88
  if (!phases.length) revert = true;
@@ -113,44 +115,47 @@ LSD.Module.Chain = new Class({
113
115
  if (command.call && (!(command = command.apply(this, args))));
114
116
  else if (command.indexOf) command = {action: command}
115
117
  var action = this.getAction(command.action);
116
- var targets = command.target;
117
- if (targets && targets.call && (!(targets = targets.call(this)) || (targets.length === 0))) return true;
118
- if (command.arguments != null) {
119
- var cargs = command.arguments && command.arguments.call ? command.arguments.call(this) : command.arguments;
120
- args = [].concat(cargs == null ? [] : cargs, args || []);
121
- }
122
118
  if (state == null && command.state != null) state = command.state;
123
- var promised = [], succeed = [], failed = [], self = this;
124
- var perform = function(target) {
125
- var value = self.getActionState(action, [target].concat(args), state, revert);
119
+ var promised, succeed, failed, cargs;
120
+ var perform = function(target, targetstate) {
121
+ if (targetstate !== true || targetstate !== false) targetstate = state;
122
+ var value = this.getActionState(action, [target].concat(args), targetstate, revert);
126
123
  var method = value ? 'commit' : 'revert';
124
+ if (!cargs && command.arguments != null) {
125
+ cargs = command.arguments && command.arguments.call ? command.arguments.call(this) : command.arguments;
126
+ args = [].concat(cargs == null ? [] : cargs, args || []);
127
+ }
127
128
  var result = action[method](target, args);
128
129
  if (result && result.callChain && (command.promise !== false)) {
129
- if (value) var phases = self.eachLink('success', arguments, ahead + 1);
130
+ // Execute onSuccess callbacks ahead (to be possibly unrolled on failure)
131
+ if (value) var phases = this.eachLink('success', arguments, ahead + 1);
132
+ if (!promised) promised = [], succeed = [], failed = [];
130
133
  promised.push(result);
131
134
  // waits for completion
132
135
  var callback = function(args, state) {
133
136
  (state ? succeed : failed).push([target, args]);
134
137
  result.removeEvents(events);
135
138
  // Try to fork off execution if action lets so
136
- if (state && (self != target) && command.fork) {
139
+ if (state && (this != target) && command.fork) {
137
140
  if (target.chainPhase == -1) target.callChain.apply(target, args);
138
141
  else target.eachLink('optional', args, true);
139
142
  };
140
143
  if (failed.length + succeed.length != promised.length) return;
141
- if (failed.length) self.eachLink('alternative', args, true, false, succeed);
142
- if (self.currentChain && self.chainPhase < self.currentChain.length - 1)
143
- if (succeed.length) self.eachLink('regular', args, true, false, succeed);
144
+ if (failed.length) this.eachLink('alternative', args, true, false, succeed);
145
+ if (this.currentChain && this.chainPhase < this.currentChain.length - 1)
146
+ if (succeed.length) this.eachLink('regular', args, true, false, succeed);
144
147
  }
145
148
  var events = {
146
149
  complete: function() {
147
- callback(arguments, true);
148
- },
150
+ callback.call(this, arguments, true);
151
+ }.bind(this),
149
152
  cancel: function() {
150
- self.eachLink('success', arguments, ahead + phases.length - 1, phases || true);
151
- self.eachLink('failure', arguments, ahead + 1);
152
- callback(arguments, false);
153
- }
153
+ // Unroll onSuccess callbacks
154
+ this.eachLink('success', arguments, ahead + phases.length - 1, phases || true);
155
+ // Then execute onFailure
156
+ this.eachLink('failure', arguments, ahead + 1);
157
+ callback.call(this, arguments, false);
158
+ }.bind(this)
154
159
  }
155
160
  // If it may fail, we should not simply wait for completion
156
161
  if (result.onFailure) {
@@ -162,7 +167,13 @@ LSD.Module.Chain = new Class({
162
167
  return;
163
168
  } else if (result === false) return;
164
169
  return value;
165
- };
170
+ }.bind(this);
171
+
172
+ var targets = command.target;
173
+ if (targets && targets.call) {
174
+ targets = targets.call(this, perform, state, revert);
175
+ if (targets === true || targets === false || targets == null) return targets;
176
+ }
166
177
  action.invoker = this;
167
178
  var ret = (targets) ? (targets.map ? targets.map(perform) : perform(targets)) : perform(this);
168
179
  delete action.invoker;
@@ -220,6 +231,10 @@ var Iterators = LSD.Module.Chain.Iterators = {
220
231
  default: return;
221
232
  }
222
233
  }
234
+ },
235
+
236
+ quickstart: function(link) {
237
+ return link.action && (link.keyword == 'do');
223
238
  }
224
239
  }
225
240
 
@@ -12,6 +12,7 @@ authors: Yaroslaff Fedin
12
12
  requires:
13
13
  - LSD.Module
14
14
  - LSD.Module.Events
15
+ - LSD.Layout
15
16
 
16
17
  provides:
17
18
  - LSD.Module.Element
@@ -46,6 +47,13 @@ LSD.Module.Element = new Class({
46
47
  if (!this.built) this.build();
47
48
  this.fireEvent('register', ['element', this.element]);
48
49
  if (this.options.key) this.element.store(this.options.key, this).fireEvent('attach', this);
50
+ /*
51
+ Extracts and sets layout options from attached element
52
+ */
53
+ if (!this.extracted && this.options.extract !== false && (!this.built || this.origin)) {
54
+ this.extracted = LSD.Module.Element.extract(element, this);
55
+ this.setOptions(this.extracted);
56
+ }
49
57
  return this.element;
50
58
  },
51
59
 
@@ -53,6 +61,13 @@ LSD.Module.Element = new Class({
53
61
  this.fireEvent('unregister', ['element', this.element]);
54
62
  if (this.options.key) this.element.eliminate(this.options.key, this).fireEvent('detach', this)
55
63
  delete this.element;
64
+ /*
65
+ Unsets options previously extracted from the detached element
66
+ */
67
+ if (this.extracted) {
68
+ this.unsetOptions(this.extracted);
69
+ delete this.extracted, delete this.origin;
70
+ }
56
71
  },
57
72
 
58
73
  toElement: function(){
@@ -70,31 +85,41 @@ LSD.Module.Element = new Class({
70
85
  element = query.element = element || this.element;
71
86
  var options = this.options;
72
87
  this.fireEvent('beforeBuild', query);
88
+ if (element) LSD.Module.Element.validate(this, query);
73
89
  if (this.parentNode) this.parentNode.dispatchEvent('beforeNodeBuild', [query, this]);
74
90
  var build = query.build;
75
91
  delete query.element, delete query.build;
76
- var attrs = Object.merge({}, this.attributes, options.element, query.attributes);
92
+ var attrs = {}
93
+ for (var attribute in this.attributes)
94
+ if (this.attributes.has(attribute))
95
+ attrs[attribute] = this.attributes[attribute];
96
+ Object.merge(attrs, options.element, query.attributes);
77
97
  var tag = query.tag || attrs.tag || this.getElementTag();
78
98
  delete attrs.tag; delete query.tag;
79
- if (query.attributes || query.classes || query.pseudos) this.setOptions(query);
80
99
  if (!element || build) {
81
100
  this.element = new Element(tag, attrs);
82
- } else var element = this.element = document.id(element).set(attrs);
83
- var classes = new FastArray;
84
- if (this.tagName != tag) classes.push('lsd', this.tagName);
85
- classes.concat(this.classes);
86
- if (Object.getLength(classes)) this.element.className = classes.join(' ');
87
-
101
+ } else {
102
+ var element = this.element = document.id(element);
103
+ for (var name in attrs)
104
+ if (name != 'type' || tag != 'input')
105
+ element.setAttribute(name, attrs[name] === true ? name : attrs[name]);
106
+ }
107
+ var classes = [];
108
+ if (this.tagName != tag) classes.push('lsd ', this.tagName);
109
+ for (var name in this.classes) if (this.classes.has(name)) classes.include(name);
110
+ if (classes.length) this.element.className = classes.join(' ');
88
111
  if (this.style) for (var property in this.style.element) this.element.setStyle(property, this.style.element[property]);
112
+ this.attach(this.element);
89
113
  return this.element;
90
114
  },
91
115
 
92
116
  getElementTag: function(soft) {
117
+ if (this.element) return LSD.toLowerCase(this.element.tagName);
93
118
  var options = this.options, element = options.element;
94
119
  if (element && element.tag) return element.tag;
95
120
  if (!soft) switch (options.inline) {
96
121
  case null:
97
- return this.tagName;
122
+ return LSD.Layout.NodeNames[this.tagName] ? this.tagName : "div";
98
123
  case true:
99
124
  return "span";
100
125
  case false:
@@ -106,7 +131,9 @@ LSD.Module.Element = new Class({
106
131
 
107
132
  destroy: function() {
108
133
  this.fireEvent('beforeDestroy');
134
+ if (this.parentNode) this.dispose();
109
135
  this.element.destroy();
136
+ this.detach();
110
137
  return this;
111
138
  },
112
139
 
@@ -125,7 +152,7 @@ LSD.Module.Element.extract = function(element, widget) {
125
152
  }, attrs = options.attributes;
126
153
  for (var i = 0, attribute, name; attribute = element.attributes[i++];) {
127
154
  name = attribute.name;
128
- attrs[name] = LSD.Attributes.Boolean[name] || attribute.value || "";
155
+ attrs[name] = LSD.Attributes[name] == 'boolean' || attribute.value || "";
129
156
  }
130
157
  var klass = attrs['class'];
131
158
  if (klass) {
@@ -155,61 +182,35 @@ LSD.Module.Element.extract = function(element, widget) {
155
182
  }
156
183
  if (i == 1) delete options.attributes;
157
184
  return options;
158
- }
185
+ };
186
+
187
+ /*
188
+ Extract options off from widget and makes it rebuild element if it doesnt fit.
189
+ */
190
+ LSD.Module.Element.validate = function(widget, query) {
191
+ if (widget.options.extract !== false || widget.options.clone) {
192
+ widget.extracted = LSD.Module.Element.extract(query.element, widget);
193
+ widget.setOptions(widget.extracted);
194
+ Object.merge(query, widget.extracted);
195
+ }
196
+ var tag = widget.getElementTag(true);
197
+ if (widget.options.clone || (tag && LSD.toLowerCase(query.element.tagName) != tag)) {
198
+ widget.origin = query.element;
199
+ query.tag = tag;
200
+ query.build = true;
201
+ }
202
+ };
159
203
 
160
204
  LSD.Module.Element.events = {
161
205
  /*
162
- A lazy widget will not attach to element until it's built or attached
206
+ Preparation happens when widget is initialized. If element was passed into
207
+ constructor, it will go through a build/attach routine from the start.
208
+
209
+ A widget may be set to defer the attachment with a `lazy` option set to true.
163
210
  */
164
211
  prepare: function(options, element) {
165
212
  if (options.lazy) this.origin = element;
166
213
  else if (element) this.build(element);
167
- },
168
- /*
169
- If a the widget was built before it was attached, attach it after the build
170
- */
171
- build: function() {
172
- this.attach.apply(this, arguments);
173
- },
174
- /*
175
- Detaches element when it's destroyed
176
- */
177
- destroy: function() {
178
- this.detach.apply(this, arguments);
179
- },
180
- /*
181
- Extracts and sets layout options from attached element
182
- */
183
- attach: function(element) {
184
- if (!this.extracted && this.options.extract !== false) {
185
- this.extracted = LSD.Module.Element.extract(element, this);
186
- this.setOptions(this.extracted);
187
- }
188
- },
189
- /*
190
- Unsets options previously extracted from the detached element
191
- */
192
- detach: function() {
193
- if (!this.extracted) return;
194
- this.unsetOptions(this.extracted);
195
- delete this.extracted, delete this.origin;
196
- },
197
- /*
198
- Extract options off from widget and makes it rebuild element if it doesnt fit.
199
- */
200
- beforeBuild: function(query) {
201
- if (!query.element) return;
202
- if (this.options.extract !== false || this.options.clone) {
203
- this.extracted = LSD.Module.Element.extract(query.element, this);
204
- this.setOptions(this.extracted);
205
- Object.merge(query, this.extracted);
206
- }
207
- var tag = this.getElementTag(true);
208
- if (this.options.clone || (tag && LSD.toLowerCase(query.element.tagName) != tag)) {
209
- this.origin = query.element;
210
- query.tag = tag;
211
- query.build = true;
212
- }
213
214
  }
214
215
  };
215
216
 
@@ -90,7 +90,7 @@ var Events = Object.append(LSD.Module.Events, {
90
90
  var events = this.events[name], initial = !events;
91
91
  if (!events) events = this.events[name] = {};
92
92
  var bound = this.lsd ? this.bindEvents(fn) : fn;
93
- for (event in bound) {
93
+ for (var event in bound) {
94
94
  var group = (events[event] || (events[event] = []));
95
95
  if (revert) {
96
96
  var i = group.indexOf(bound[event]);
@@ -102,11 +102,14 @@ var Events = Object.append(LSD.Module.Events, {
102
102
  if (target.call) {
103
103
  if ((target = target.call(this)))
104
104
  for (var event in bound) Events.setEvent.call(target, event, bound[event], revert);
105
- } else if (initial) {
106
- Events.watchEventTarget.call(this, name, function(object, state) {
107
- Events.setStoredEvents.call(object, events, state, this);
108
- })
109
- } else if (target.getter && this[target.getter]) this[target.getter][revert ? 'removeEvents' : 'addEvents'](bound)
105
+ } else {
106
+ if (initial && !target.registers) {
107
+ Events.watchEventTarget.call(this, name, function(object, state) {
108
+ Events.setStoredEvents.call(object, events, state, this);
109
+ })
110
+ }
111
+ if (target.getter && this[target.getter]) this[target.getter][revert ? 'removeEvents' : 'addEvents'](bound);
112
+ }
110
113
  return this;
111
114
  }
112
115
  },
@@ -182,7 +185,7 @@ var Events = Object.append(LSD.Module.Events, {
182
185
  if (!(event = events[i])) continue;
183
186
  if (!method) var method = Type.isEnumerable(args) ? 'apply' : 'call';
184
187
  var result = event[method](this, args);
185
- if (result) return result;
188
+ if (result != null) return result;
186
189
  }
187
190
  },
188
191
 
@@ -286,6 +289,18 @@ Events.Targets = {
286
289
  }
287
290
  }
288
291
  };
292
+
293
+ Events.States = {
294
+ Positive: {
295
+ disabled: 'disabled',
296
+ focused: 'focused'
297
+ },
298
+ Negative: {
299
+ enabled: 'disabled',
300
+ blured: 'focused'
301
+ }
302
+ };
303
+
289
304
  !function(Known, Positive, Negative) {
290
305
  Object.each(Object.append({}, Positive, Negative), function(name, condition) {
291
306
  var events = {}, positive = !!Positive[name], state = Known[name];
@@ -299,7 +314,7 @@ Events.Targets = {
299
314
  events: events
300
315
  }
301
316
  });
302
- }(LSD.States.Known, LSD.States.Positive, LSD.States.Negative)
317
+ }(LSD.States, Events.States.Positive, Events.States.Negative);
303
318
 
304
319
 
305
320
  /*
@@ -329,7 +344,7 @@ LSD.Options.events = {
329
344
 
330
345
  Class.Mutators.$events = function(events) {
331
346
  var category = this.prototype.$events || (this.prototype.$events = {});
332
- for (name in events) {
347
+ for (var name in events) {
333
348
  var type = category[name] || (category[name] = []);
334
349
  type.push.apply(type, events[name]);
335
350
  }
@@ -337,7 +352,7 @@ Class.Mutators.$events = function(events) {
337
352
 
338
353
  Class.Mutators.events = function(events) {
339
354
  var category = this.prototype.events || (this.prototype.events = {});
340
- for (label in events) {
355
+ for (var label in events) {
341
356
  var group = events[label];
342
357
  var type = category[label] || (category[label] = {});
343
358
  for (var name in group) {
@@ -31,16 +31,16 @@ LSD.Module.Options = new Class({
31
31
  return this;
32
32
  },
33
33
 
34
- construct: function(object) {
34
+ construct: function(object, set) {
35
35
  if (!object) object = this;
36
36
  var initialized = object.$initialized = [];
37
37
  /*
38
38
  Run module constructors and keep returned values
39
39
  */
40
40
  for (var name in object.constructors) {
41
- var initializer = object.constructors[name];
42
- if (initializer) {
43
- var result = initializer.call(this, object.options);
41
+ var constructor = object.constructors[name];
42
+ if (constructor) {
43
+ var result = constructor.call(this, object.options);
44
44
  if (result) initialized.push(result);
45
45
  }
46
46
  }
@@ -48,6 +48,10 @@ LSD.Module.Options = new Class({
48
48
  Set options returned from constructors
49
49
  */
50
50
  for (var i = 0, value; value = initialized[i++];) this.setOptions(value);
51
+ /*
52
+ Set options from the object
53
+ */
54
+ if (set) this.setOptions(object.options);
51
55
  return object.options;
52
56
  },
53
57
 
@@ -61,7 +65,7 @@ LSD.Module.Options = new Class({
61
65
  });
62
66
 
63
67
  LSD.Module.Options.setOption = function(name, value, unset, context) {
64
- setter = (context || LSD.Options)[name];
68
+ var setter = (context || LSD.Options)[name];
65
69
  if (!setter) {
66
70
  Object.merge(this.options, name, value);
67
71
  return this;
@@ -92,14 +96,8 @@ LSD.Module.Options.initialize = function(element, options) {
92
96
  // Merge given options object into this.options
93
97
  if (options) Object.merge(this.options, options);
94
98
 
95
- // Collection options off constructors
96
- options = this.construct();
97
-
98
- // Call parent class initializer (if set)
99
- if (Class.hasParent(this)) this.parent(element, options);
100
-
101
- // Run callbacks for all the options set
102
- this.setOptions(options);
99
+ // Run constructors and set options
100
+ options = this.construct(this, true);
103
101
 
104
102
  // Indicate readiness to start
105
103
  this.fireEvent('boot', [options, element]);
@@ -9,9 +9,10 @@ license: Public domain (http://unlicense.org).
9
9
 
10
10
  authors: Yaroslaff Fedin
11
11
 
12
- requires:
13
- - Ext/States
12
+ requires:
14
13
  - LSD.Module
14
+ - LSD.Object
15
+ - Ext/States
15
16
 
16
17
  provides:
17
18
  - LSD.Module.States
@@ -19,10 +20,46 @@ provides:
19
20
  ...
20
21
  */
21
22
 
22
- LSD.Module.States = States;
23
+ LSD.Module.States = new Class({
24
+ Implements: States,
25
+
26
+ constructors: {
27
+ states: function() {
28
+ this.states = (new LSD.Object.Stack).addEvent('change', function(name, value, state, old, quiet) {
29
+ var known = LSD.States[name];
30
+ var method = value && state ? 'add' : 'remove';
31
+ if (known && state && (old == null || value != null)) this.addState(name);
32
+ if (!(old == null && value == null)) {
33
+ if (LSD.Attributes[name] != 'boolean') {
34
+ if (quiet != 'classes') this.classes[method](LSD.States[name] ? name : 'is-' + name, true);
35
+ } else {
36
+ if (quiet != 'attributes') this.attributes[method](name, true);
37
+ }
38
+ if (quiet != 'pseudos') this.pseudos[method](name, true);
39
+ }
40
+ if (known) {
41
+ this.setStateTo(name, value && state, null, false);
42
+ if (!state) this.removeState(name);
43
+ }
44
+ }.bind(this))
45
+ }
46
+ },
47
+
48
+ onStateChange: function(state, value, args, callback) {
49
+ var args = Array.prototype.slice.call(arguments, 0);
50
+ args.slice(1, 2); //state + args
51
+ if (callback !== false) this.states[value ? 'add' : 'remove'](state);
52
+ this.fireEvent('stateChange', [state, args]);
53
+ return true;
54
+ }
55
+ });
23
56
 
24
57
  LSD.Options.states = {
25
- add: 'addState',
26
- remove: 'removeState',
58
+ add: function(name, value) {
59
+ this.states.set(name);
60
+ },
61
+ remove: function(name, value) {
62
+ this.states.unset(name);
63
+ },
27
64
  iterate: true
28
65
  };
@@ -13,7 +13,7 @@ requires:
13
13
  - LSD.Module
14
14
  - LSD.Module.Events
15
15
  - Core/Element.Style
16
- - Ext/FastArray
16
+ - Ext/Object.Array
17
17
  - Sheet/SheetParser.Styles
18
18
 
19
19
  provides:
@@ -30,6 +30,14 @@ LSD.Module.Tag = new Class({
30
30
  tag: function(options) {
31
31
  if (options.context) this.setContext(options.context)
32
32
  this.nodeType = options.nodeType;
33
+ var self = this;
34
+ this.mixins = (new LSD.Object.Stack).addEvent('change', function(name, value, state, old) {
35
+ if (state) {
36
+ if (old == null) self.mixin(LSD.Mixin[LSD.toClassName(name)], true);
37
+ } else {
38
+ self.unmix(LSD.Mixin[LSD.toClassName(name)], true);
39
+ }
40
+ })
33
41
  }
34
42
  },
35
43
 
@@ -42,7 +50,7 @@ LSD.Module.Tag = new Class({
42
50
 
43
51
  setSource: function(source) {
44
52
  if (!source) source = this.getSource(true);
45
- if (this.source != source) {
53
+ if (this.source != (source && source.join ? source.join('-') : source)) {
46
54
  if (source.length) {
47
55
  var role = this.context.find(source);
48
56
  if (role && role != this.role) {
@@ -99,16 +107,22 @@ LSD.Module.Tag = new Class({
99
107
  },
100
108
 
101
109
  mixin: function(mixin, light) {
102
- if (typeof mixin == 'string') mixin = LSD.Mixin[LSD.capitalize(mixin)];
103
- Class.mixin(this, mixin, light);
104
- this.setOptions(this.construct(mixin.prototype));
110
+ if (typeof mixin == 'string') {
111
+ this.mixins.add(mixin);
112
+ } else {
113
+ var options = Class.mixin(this, mixin, light);
114
+ this.setOptions(this.construct(mixin.prototype));
115
+ }
105
116
  return this;
106
117
  },
107
118
 
108
119
  unmix: function(mixin, light) {
109
- if (typeof mixin == 'string') mixin = LSD.Mixin[LSD.capitalize(mixin)];
110
- this.unsetOptions(this.destruct(mixin.prototype));
111
- Class.unmix(this, mixin, light);
120
+ if (typeof mixin == 'string') {
121
+ this.mixins.remove(mixin);
122
+ } else {
123
+ this.unsetOptions(this.destruct(mixin.prototype));
124
+ Class.unmix(this, mixin, light);
125
+ }
112
126
  return this;
113
127
  }
114
128