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.
- data/Packages/Sheet.js/Source/SheetParser.Value.js +1 -1
- data/Packages/lsd/Source/Action/Clone.js +2 -12
- data/Packages/lsd/Source/Action/Delete.js +1 -7
- data/Packages/lsd/Source/Action/Display.js +7 -7
- data/Packages/lsd/Source/Action/Edit.js +2 -2
- data/Packages/lsd/Source/Action/Invoke.js +2 -2
- data/Packages/lsd/Source/Action/Submit.js +2 -0
- data/Packages/lsd/Source/Action/Toggle.js +4 -0
- data/Packages/lsd/Source/Action/Update.js +2 -1
- data/Packages/lsd/Source/Action.js +4 -5
- data/Packages/lsd/Source/Document.js +10 -7
- data/Packages/lsd/Source/LSD.js +22 -127
- data/Packages/lsd/Source/Layer.js +4 -4
- data/Packages/lsd/Source/Layout.js +1077 -259
- data/Packages/lsd/Source/Mixin/Animation.js +1 -1
- data/Packages/lsd/Source/Mixin/Choice.js +2 -2
- data/Packages/lsd/Source/Mixin/Command.js +26 -8
- data/Packages/lsd/Source/Mixin/ContentEditable.js +2 -1
- data/Packages/lsd/Source/{Trait → Mixin}/Date.js +21 -11
- data/Packages/lsd/Source/{Trait/Menu.js → Mixin/Details.js} +6 -1
- data/Packages/lsd/Source/Mixin/Draggable.js +1 -1
- data/Packages/lsd/Source/Mixin/Fieldset.js +51 -49
- data/Packages/lsd/Source/Mixin/Focusable.js +38 -39
- data/Packages/lsd/Source/Mixin/Invokable.js +13 -14
- data/Packages/lsd/Source/Mixin/List.js +9 -17
- data/Packages/lsd/Source/Mixin/Placeholder.js +2 -7
- data/Packages/lsd/Source/Mixin/Request.js +5 -3
- data/Packages/lsd/Source/Mixin/Resizable.js +3 -3
- data/Packages/lsd/Source/Mixin/Resource.js +1 -1
- data/Packages/lsd/Source/Mixin/Root.js +17 -1
- data/Packages/lsd/Source/Mixin/Scrollable.js +1 -1
- data/Packages/lsd/Source/{Trait → Mixin}/Slider.js +0 -0
- data/Packages/lsd/Source/Mixin/Sortable.js +2 -2
- data/Packages/lsd/Source/Mixin/Submittable.js +2 -1
- data/Packages/lsd/Source/Mixin/Target.js +11 -6
- data/Packages/lsd/Source/Mixin/Touchable.js +2 -2
- data/Packages/lsd/Source/Mixin/Unselectable.js +1 -1
- data/Packages/lsd/Source/Mixin/Uploader.js +11 -13
- data/Packages/lsd/Source/Mixin/Validity.js +35 -9
- data/Packages/lsd/Source/Mixin/Value.js +5 -3
- data/Packages/lsd/Source/Module/Accessories/Attributes.js +90 -89
- data/Packages/lsd/Source/Module/Accessories/Chain.js +40 -25
- data/Packages/lsd/Source/Module/Accessories/Element.js +59 -58
- data/Packages/lsd/Source/Module/Accessories/Events.js +25 -10
- data/Packages/lsd/Source/Module/Accessories/Options.js +11 -13
- data/Packages/lsd/Source/Module/Accessories/States.js +42 -5
- data/Packages/lsd/Source/Module/Accessories/Styles.js +1 -1
- data/Packages/lsd/Source/Module/Accessories/Tag.js +21 -7
- data/Packages/lsd/Source/Module/Ambient/Allocations.js +178 -64
- data/Packages/lsd/Source/Module/Ambient/DOM.js +98 -55
- data/Packages/lsd/Source/Module/Ambient/Expectations.js +57 -8
- data/Packages/lsd/Source/Module/Ambient/Interpolations.js +147 -0
- data/Packages/lsd/Source/Module/Ambient/Layout.js +52 -15
- data/Packages/lsd/Source/Module/Ambient/Proxies.js +44 -36
- data/Packages/lsd/Source/Module/Ambient/Relations.js +3 -1
- data/Packages/lsd/Source/Module/Ambient/Selectors.js +3 -3
- data/Packages/lsd/Source/Module/Ambient.js +2 -2
- data/Packages/lsd/Source/Module/Graphics/Layers.js +1 -1
- data/Packages/lsd/Source/Module/Graphics/Render.js +1 -1
- data/Packages/lsd/Source/Relation.js +19 -20
- data/Packages/lsd/Source/Sheet.js +4 -5
- data/Packages/lsd/Source/{Behavior.js → Tools/Behavior.js} +0 -0
- data/Packages/lsd/Source/Tools/Command.js +190 -0
- data/Packages/lsd/Source/Tools/Helpers.js +109 -0
- data/Packages/lsd/Source/Tools/Interpolation.js +351 -0
- data/Packages/lsd/Source/Tools/Microdata.js +75 -0
- data/Packages/lsd/Source/Tools/Object.js +192 -0
- data/Packages/lsd/Source/Tools/Position.js +208 -0
- data/Packages/lsd/Source/Tools/Require.js +76 -0
- data/Packages/lsd/Source/Type.js +2 -2
- data/Packages/lsd/package.yml +11 -7
- data/Packages/lsd-mobile/Source/Body/Dialog.js +2 -2
- data/Packages/lsd-mobile/Source/Input/Date.js +9 -84
- data/Packages/lsd-native/Source/Input/Checkbox.js +4 -4
- data/Packages/lsd-native/Source/Input/Date.js +46 -6
- data/Packages/lsd-native/Source/Input/Radio.js +1 -4
- data/Packages/lsd-native/Source/Input.js +5 -6
- data/Packages/lsd-widgets/Source/Body/Dialog.js +9 -6
- data/Packages/lsd-widgets/Source/Body/Page.js +1 -1
- data/Packages/lsd-widgets/Source/Body.js +1 -1
- data/Packages/lsd-widgets/Source/Button.js +1 -1
- data/Packages/lsd-widgets/Source/Form.js +1 -1
- data/Packages/lsd-widgets/Source/Input/Checkbox.js +2 -2
- data/Packages/lsd-widgets/Source/Input/Date.js +45 -16
- data/Packages/lsd-widgets/Source/Input/File.js +2 -2
- data/Packages/lsd-widgets/Source/Input/HTML.js +2 -2
- data/Packages/lsd-widgets/Source/Input/Radio.js +1 -1
- data/Packages/lsd-widgets/Source/Input/Range.js +2 -2
- data/Packages/lsd-widgets/Source/Input/Submit.js +1 -1
- data/Packages/lsd-widgets/Source/Input.js +2 -11
- data/Packages/lsd-widgets/Source/Label.js +4 -8
- data/Packages/lsd-widgets/Source/Menu/List.js +3 -3
- data/Packages/lsd-widgets/Source/Menu.js +2 -2
- data/Packages/lsd-widgets/Source/Progress.js +1 -1
- data/Packages/lsd-widgets/Source/Select.js +7 -6
- data/Packages/lsd-widgets/Source/Table/Calendar.js +41 -15
- data/Packages/lsd-widgets/Source/Table.js +7 -2
- data/Packages/mootools-ext/Source/Core/Class.Mixin.js +43 -38
- data/Packages/mootools-ext/Source/Core/Class.States.js +26 -22
- data/Packages/mootools-ext/Source/Element/Element.from.js +1 -1
- data/Packages/mootools-ext/Source/Element/Properties/Item.js +1 -2
- data/Packages/mootools-ext/Source/Request/Request.Statuses.js +9 -7
- data/Packages/mootools-ext/Source/Types/{FastArray.js → Object.Array.js} +8 -14
- data/Packages/mootools-ext/package.yml +1 -2
- data/lib/lsd.rake +28 -0
- metadata +15 -11
- data/Packages/lsd/Source/Command.js +0 -135
- data/Packages/lsd/Source/Interpolation.js +0 -103
- data/Packages/lsd/Source/Module/Ambient/Container.js +0 -56
- data/Packages/mootools-ext/Source/Element/Element.onDispose.js +0 -36
@@ -0,0 +1,190 @@
|
|
1
|
+
/*
|
2
|
+
---
|
3
|
+
|
4
|
+
script: Checkbox.js
|
5
|
+
|
6
|
+
description: A triggerable interaction abstraction
|
7
|
+
|
8
|
+
license: Public domain (http://unlicense.org).
|
9
|
+
|
10
|
+
authors: Yaroslaff Fedin
|
11
|
+
|
12
|
+
requires:
|
13
|
+
- LSD
|
14
|
+
- Ext/States
|
15
|
+
|
16
|
+
provides:
|
17
|
+
- LSD.Command
|
18
|
+
|
19
|
+
...
|
20
|
+
*/
|
21
|
+
|
22
|
+
LSD.Command = function(document, options) {
|
23
|
+
this.setOptions(options);
|
24
|
+
this.widgets = [];
|
25
|
+
this.$events = Object.clone(this.$events);
|
26
|
+
if (document) {
|
27
|
+
this.document = document;
|
28
|
+
if (!this.document.commands) this.document.commands = {};
|
29
|
+
this.document.commands[this.options.id] = this;
|
30
|
+
}
|
31
|
+
if (this.options.type) this.setType(this.options.type);
|
32
|
+
};
|
33
|
+
|
34
|
+
LSD.Command.prototype = Object.append(new Options, new Events, new States, {
|
35
|
+
options: {
|
36
|
+
id: null,
|
37
|
+
action: null
|
38
|
+
},
|
39
|
+
|
40
|
+
click: function() {
|
41
|
+
this.fireEvent('click', arguments);
|
42
|
+
},
|
43
|
+
|
44
|
+
attach: function(widget) {
|
45
|
+
widget.fireEvent('register', ['command', this]);
|
46
|
+
if (this.disabled) widget.states.add('disabled');
|
47
|
+
if (!this.bound) this.bound = {}
|
48
|
+
if (!this.bound.enable) this.bound.enable = this.enable.bind(this);
|
49
|
+
if (!this.bound.disable) this.bound.disable = this.disable.bind(this);
|
50
|
+
if (this.type && this.type != 'command') {
|
51
|
+
widget.states.set('checked');
|
52
|
+
if (this.checked) widget.states.add('checked');
|
53
|
+
if (!this.bound.check) this.bound.check = this.check.bind(this);
|
54
|
+
if (!this.bound.uncheck) this.bound.uncheck = this.uncheck.bind(this);
|
55
|
+
widget.addEvent('check', this.bound.check);
|
56
|
+
widget.addEvent('uncheck', this.bound.uncheck);
|
57
|
+
if (widget.checked) this.check();
|
58
|
+
}
|
59
|
+
widget.addEvent('disable', this.bound.disable);
|
60
|
+
widget.addEvent('enable', this.bound.enable);
|
61
|
+
if (widget.disabled) this.disable();
|
62
|
+
this.widgets.push(widget);
|
63
|
+
return this;
|
64
|
+
},
|
65
|
+
|
66
|
+
detach: function(widget) {
|
67
|
+
widget.fireEvent('unregister', ['command', this]);
|
68
|
+
if (this.disabled) widget.states.remove('disabled');
|
69
|
+
if (this.type && this.type != 'command') {
|
70
|
+
widget.states.unset('checked');
|
71
|
+
if (this.checked) widget.states.remove('checked');
|
72
|
+
widget.removeEvent('check', this.bound.check);
|
73
|
+
widget.removeEvent('uncheck', this.bound.uncheck);
|
74
|
+
}
|
75
|
+
widget.removeEvent('disable', this.bound.disable);
|
76
|
+
widget.removeEvent('enable', this.bound.enable);
|
77
|
+
this.widgets.erase(widget);
|
78
|
+
return this;
|
79
|
+
},
|
80
|
+
|
81
|
+
check: function() {
|
82
|
+
for (var i = 0, widget; widget = this.widgets[i++];) widget.states.add('checked');
|
83
|
+
},
|
84
|
+
|
85
|
+
uncheck: function() {
|
86
|
+
for (var i = 0, widget; widget = this.widgets[i++];) widget.states.remove('checked');
|
87
|
+
},
|
88
|
+
|
89
|
+
disable: function() {
|
90
|
+
for (var i = 0, widget; widget = this.widgets[i++];) widget.disable.add('disabled');
|
91
|
+
},
|
92
|
+
|
93
|
+
enable: function() {
|
94
|
+
for (var i = 0, widget; widget = this.widgets[i++];) widget.enable.remove('disabled');
|
95
|
+
},
|
96
|
+
|
97
|
+
setType: function(type, unset) {
|
98
|
+
if (this.type == type) return;
|
99
|
+
if (this.type) this.unsetType(type);
|
100
|
+
this.type = type;
|
101
|
+
switch (type) {
|
102
|
+
case "checkbox":
|
103
|
+
/*
|
104
|
+
Checkbox commands are useful when you need to track and toggle
|
105
|
+
state of some linked object.
|
106
|
+
|
107
|
+
Provide your custom logic hooking on *check* and *uncheck*
|
108
|
+
state transitions. Use *checked* property to get the current state.
|
109
|
+
|
110
|
+
Examples:
|
111
|
+
- Button that toggles visibility of a sidebar
|
112
|
+
- Context menu item that shows or hides line numbers in editor
|
113
|
+
*/
|
114
|
+
this.events = {
|
115
|
+
click: function() {
|
116
|
+
this.toggle();
|
117
|
+
}
|
118
|
+
};
|
119
|
+
break;
|
120
|
+
|
121
|
+
|
122
|
+
/*
|
123
|
+
Radio groupping is a way to links commands together to allow
|
124
|
+
only one in the group be active at the moment of time.
|
125
|
+
|
126
|
+
Activation (*check*ing) of the commands deactivates all
|
127
|
+
other commands in a radiogroup.
|
128
|
+
|
129
|
+
Examples:
|
130
|
+
- Tabs on top of a content window
|
131
|
+
- Select box with a dropdown menu
|
132
|
+
*/
|
133
|
+
case "radio":
|
134
|
+
var name = this.options.radiogroup;
|
135
|
+
if (name) {
|
136
|
+
var groups = this.document.radiogroups;
|
137
|
+
if (!groups) groups = this.document.radiogroups = {};
|
138
|
+
var group = groups[name];
|
139
|
+
if (!group) group = groups[name] = [];
|
140
|
+
group.push(this);
|
141
|
+
this.group = group;
|
142
|
+
}
|
143
|
+
this.events = {
|
144
|
+
click: function() {
|
145
|
+
this.check.apply(this, arguments);
|
146
|
+
},
|
147
|
+
check: function() {
|
148
|
+
if (group) group.each(function(sibling) {
|
149
|
+
if (sibling != this) {
|
150
|
+
sibling.uncheck();
|
151
|
+
if (sibling.widgets) sibling.widgets.each(function(widget) {
|
152
|
+
widget.unclick();
|
153
|
+
})
|
154
|
+
}
|
155
|
+
}, this);
|
156
|
+
}
|
157
|
+
};
|
158
|
+
}
|
159
|
+
if (this.events) {
|
160
|
+
this.addEvents(this.events);
|
161
|
+
if (!this.bound) this.bound = {};
|
162
|
+
if (!this.bound.check) this.bound.check = this.check.bind(this);
|
163
|
+
if (!this.bound.uncheck) this.bound.uncheck = this.uncheck.bind(this);
|
164
|
+
for (var i = 0, widget; widget = this.widgets[i++];) {
|
165
|
+
widget.states.set('checked');
|
166
|
+
if (this.checked) widget.states.add('checked');
|
167
|
+
widget.addEvent('check', this.bound.check);
|
168
|
+
widget.addEvent('uncheck', this.bound.uncheck);
|
169
|
+
}
|
170
|
+
}
|
171
|
+
},
|
172
|
+
|
173
|
+
unsetType: function() {
|
174
|
+
if (this.events) {
|
175
|
+
if (this.type != 'command') {
|
176
|
+
for (var i = 0, widget; widget = this.widgets[i++];) {
|
177
|
+
widget.states.unset('checked');
|
178
|
+
if (this.checked) widget.states.remove('checked');
|
179
|
+
widget.removeEvent('check', this.bound.check);
|
180
|
+
widget.removeEvent('uncheck', this.bound.uncheck);
|
181
|
+
}
|
182
|
+
}
|
183
|
+
this.removeEvents(this.events);
|
184
|
+
delete this.events;
|
185
|
+
}
|
186
|
+
delete this.type;
|
187
|
+
}
|
188
|
+
});
|
189
|
+
|
190
|
+
LSD.Command.prototype.addStates('disabled', 'checked');
|
@@ -0,0 +1,109 @@
|
|
1
|
+
/*
|
2
|
+
---
|
3
|
+
|
4
|
+
script: Helpers.js
|
5
|
+
|
6
|
+
description: Some useful functions that are used internally
|
7
|
+
|
8
|
+
license: Public domain (http://unlicense.org).
|
9
|
+
|
10
|
+
authors: Yaroslaff Fedin
|
11
|
+
|
12
|
+
requires:
|
13
|
+
- LSD
|
14
|
+
|
15
|
+
provides:
|
16
|
+
- LSD.Helpers
|
17
|
+
|
18
|
+
...
|
19
|
+
*/
|
20
|
+
|
21
|
+
Object.append(LSD, {
|
22
|
+
toLowerCase: function(lowercased) {
|
23
|
+
return function(string) {
|
24
|
+
return (lowercased[string]) || (lowercased[string] = string.toLowerCase())
|
25
|
+
}
|
26
|
+
}(LSD.lowercased = {}),
|
27
|
+
|
28
|
+
capitalize: function(capitalized) {
|
29
|
+
return function(string) {
|
30
|
+
return (capitalized[string]) || (capitalized[string] = string.capitalize())
|
31
|
+
}
|
32
|
+
}(LSD.capitalized = {}),
|
33
|
+
|
34
|
+
toClassName: function(classnamed) {
|
35
|
+
return function(string) {
|
36
|
+
return (classnamed[string]) || (classnamed[string] = string.replace(/(^|-|_)([a-z])/g, function(a, b, c) { return (b == '-' ? '.' : '') + c.toUpperCase()}))
|
37
|
+
}
|
38
|
+
}(LSD.classnamed = {}),
|
39
|
+
|
40
|
+
uid: function(object) {
|
41
|
+
if (object.lsd) return object.lsd;
|
42
|
+
if (object.localName) return $uid(object);
|
43
|
+
return (object.lsd = ++LSD.UID);
|
44
|
+
},
|
45
|
+
|
46
|
+
position: function(box, size, x, y) {
|
47
|
+
var position = {x: 0, y: 0};
|
48
|
+
|
49
|
+
switch (x) {
|
50
|
+
case "left":
|
51
|
+
position.x = 0;
|
52
|
+
case "right":
|
53
|
+
position.x = box.width - size.width;
|
54
|
+
case "center":
|
55
|
+
position.x = (box.width - size.width) / 2;
|
56
|
+
}
|
57
|
+
switch (y) {
|
58
|
+
case "top":
|
59
|
+
position.y = 0;
|
60
|
+
case "bottom":
|
61
|
+
position.y = box.height - size.height;
|
62
|
+
case "center":
|
63
|
+
position.y = (box.height- size.height) / 2;
|
64
|
+
}
|
65
|
+
return position;
|
66
|
+
},
|
67
|
+
|
68
|
+
UID: 0,
|
69
|
+
|
70
|
+
slice: (Browser.ie ? function(list, start) {
|
71
|
+
for (var i = start || 0, j = list.length, ary = []; i < j; i++) ary.push(list[i]);
|
72
|
+
return ary;
|
73
|
+
} : function(list, start) {
|
74
|
+
return Array.prototype.slice.call(list, start || 0);
|
75
|
+
}),
|
76
|
+
|
77
|
+
reverseMerge: function(object, another) {
|
78
|
+
for (var name in another) {
|
79
|
+
var old = object[name], value = another[name];
|
80
|
+
if (old !== value) {
|
81
|
+
if (typeof old == 'undefined') {
|
82
|
+
if (!value.nodeType && !value.$family) value = Object.clone(value)
|
83
|
+
object[name] = value;
|
84
|
+
} else if (!old.nodeType && !old.$family) {
|
85
|
+
LSD.reverseMerge(old, value);
|
86
|
+
}
|
87
|
+
}
|
88
|
+
}
|
89
|
+
return object;
|
90
|
+
}
|
91
|
+
});
|
92
|
+
|
93
|
+
if (!window.console) window.console = {};
|
94
|
+
if (!window.console.log) window.console.log = function() {};
|
95
|
+
['log', 'error', 'warn', 'info', 'dir'].each(function(method) {
|
96
|
+
try {
|
97
|
+
LSD[method] = function() {
|
98
|
+
try {
|
99
|
+
(console[method] || console.log).apply(console.arguments);
|
100
|
+
} catch(e){}
|
101
|
+
}
|
102
|
+
} catch(e) {};
|
103
|
+
});
|
104
|
+
|
105
|
+
(function(toString) {
|
106
|
+
Type.isEnumerable = function(item){
|
107
|
+
return (item != null && !item.localName && !item.nodeType && toString.call(item) != '[object Function]' && typeof item.length == 'number');
|
108
|
+
};
|
109
|
+
})(Object.prototype.toString);
|
@@ -0,0 +1,351 @@
|
|
1
|
+
/*
|
2
|
+
---
|
3
|
+
|
4
|
+
script: Interpolation.js
|
5
|
+
|
6
|
+
description: Variable piece of html that can be asynchronously replaced with content
|
7
|
+
|
8
|
+
license: Public domain (http://unlicense.org).
|
9
|
+
|
10
|
+
authors: Yaroslaff Fedin
|
11
|
+
|
12
|
+
requires:
|
13
|
+
- LSD
|
14
|
+
- Sheet/SheetParser.Value
|
15
|
+
|
16
|
+
provides:
|
17
|
+
- LSD.Interpolation
|
18
|
+
|
19
|
+
...
|
20
|
+
*/
|
21
|
+
|
22
|
+
!function() {
|
23
|
+
LSD.Interpolation = function(input, output, source) {
|
24
|
+
this.input = input;
|
25
|
+
this.output = output;
|
26
|
+
this.source = source;
|
27
|
+
};
|
28
|
+
|
29
|
+
LSD.Interpolation.Function = function(input, output, source, name) {
|
30
|
+
this.input = input;
|
31
|
+
this.output = output;
|
32
|
+
this.source = source;
|
33
|
+
this.name = name;
|
34
|
+
this.args = Array.prototype.slice.call(input, 0);
|
35
|
+
};
|
36
|
+
|
37
|
+
LSD.Interpolation.Selector = function(input, output, source) {
|
38
|
+
this.input = input;
|
39
|
+
this.output = output;
|
40
|
+
this.source = source;
|
41
|
+
this.input = input.replace(R_SELECTOR_CONTEXT, function(whole, match) {
|
42
|
+
switch (match) {
|
43
|
+
case "$":
|
44
|
+
this.element = this.source.toElement();
|
45
|
+
return '';
|
46
|
+
case "$$":
|
47
|
+
this.element = this.source.toElement().ownerDocument.body;
|
48
|
+
return '';
|
49
|
+
}
|
50
|
+
}.bind(this));
|
51
|
+
this.collection = [];
|
52
|
+
if (!source || !source.lsd) throw "Selector should be applied on widgets";
|
53
|
+
};
|
54
|
+
|
55
|
+
LSD.Interpolation.prototype = {
|
56
|
+
interpolation: true,
|
57
|
+
|
58
|
+
set: function(value) {
|
59
|
+
this.value = this.process ? this.process(value) : value;
|
60
|
+
this.onSet(this.value);
|
61
|
+
},
|
62
|
+
|
63
|
+
onSet: function(value) {
|
64
|
+
if (value == null && this.placeholder) value = this.placeholder;
|
65
|
+
if (this.output) this.update(value);
|
66
|
+
if (this.parent) this.parent.set();
|
67
|
+
},
|
68
|
+
|
69
|
+
attach: function() {
|
70
|
+
return this.fetch(true);
|
71
|
+
},
|
72
|
+
|
73
|
+
detach: function() {
|
74
|
+
return this.fetch(false);
|
75
|
+
},
|
76
|
+
|
77
|
+
fetch: function(state) {
|
78
|
+
if (!this.setter) this.setter = this.set.bind(this);
|
79
|
+
(this.source.call ? this.source : this.request).call(this, this.input, this.setter, this.source, state);
|
80
|
+
return this;
|
81
|
+
},
|
82
|
+
|
83
|
+
request: function(input, callback, source, state) {
|
84
|
+
return this.source[state ? 'addInterpolation' : 'removeInterpolation'](input, callback);
|
85
|
+
},
|
86
|
+
|
87
|
+
update: function(value) {
|
88
|
+
var output = this.output;
|
89
|
+
if (!output) return;
|
90
|
+
if (output.branch) {
|
91
|
+
output.set(value);
|
92
|
+
} else if (output.call) {
|
93
|
+
output(value !== null);
|
94
|
+
} else {
|
95
|
+
if (value == null) value = '';
|
96
|
+
switch (output.nodeType) {
|
97
|
+
case 1:
|
98
|
+
if (output.lsd) output.write(value)
|
99
|
+
else output.innerHTML = value;
|
100
|
+
break;
|
101
|
+
case 3:
|
102
|
+
output.nodeValue = value;
|
103
|
+
break;
|
104
|
+
case 8:
|
105
|
+
}
|
106
|
+
}
|
107
|
+
}
|
108
|
+
};
|
109
|
+
|
110
|
+
LSD.Interpolation.Function.prototype = Object.append({}, LSD.Interpolation.prototype, {
|
111
|
+
fetch: function(state) {
|
112
|
+
for (var i = 0, j = this.args.length, arg; i < j; i++) {
|
113
|
+
if ((arg = this.args[i]) == null) continue;
|
114
|
+
if (!arg.interpolation) {
|
115
|
+
arg = LSD.Interpolation.compile(this.args[i], null, this.source);
|
116
|
+
if (!arg.parent) {
|
117
|
+
arg.parent = this;
|
118
|
+
if (arg.value == null) var stop = true;
|
119
|
+
}
|
120
|
+
}
|
121
|
+
this.args[i] = arg;
|
122
|
+
if (arg.interpolation) arg.fetch(state);
|
123
|
+
}
|
124
|
+
if (!stop) this.set();
|
125
|
+
return this;
|
126
|
+
},
|
127
|
+
|
128
|
+
execute: function() {
|
129
|
+
for (var i = 0, args = [], j = this.args.length, arg; i < j; i++)
|
130
|
+
if ((arg = this.args[i]) && arg.interpolation && arg.value == null) return null;
|
131
|
+
else args[i] = (arg && typeof arg.value != 'undefined') ? arg.value : arg;
|
132
|
+
if (this.name) {
|
133
|
+
return functions[this.name].apply(functions, args)
|
134
|
+
} else {
|
135
|
+
return args[0];
|
136
|
+
}
|
137
|
+
},
|
138
|
+
|
139
|
+
process: function() {
|
140
|
+
return this.execute();
|
141
|
+
}
|
142
|
+
});
|
143
|
+
|
144
|
+
LSD.Interpolation.Selector.prototype = Object.append({}, LSD.Interpolation.prototype, {
|
145
|
+
request: function(input, callback, state) {
|
146
|
+
return (this.element || this.source)[state ? 'watch' : 'unwatch'](input, callback);
|
147
|
+
},
|
148
|
+
|
149
|
+
set: function(node, state) {
|
150
|
+
if (this.filter && !this.filter(node)) return;
|
151
|
+
if (state) {
|
152
|
+
this.collection.push(node);
|
153
|
+
} else {
|
154
|
+
var index = this.collection.indexOf(node);
|
155
|
+
if (index > -1) this.collection.splice(index, 1);
|
156
|
+
}
|
157
|
+
this.value = this.collection.length ? this.collection : 0;
|
158
|
+
this.onSet(this.value);
|
159
|
+
}
|
160
|
+
});
|
161
|
+
|
162
|
+
// Set up helpers
|
163
|
+
var functions = LSD.Interpolation.Functions = {
|
164
|
+
count: function(elements) {
|
165
|
+
return elements.push ? elements.length : +!!elements
|
166
|
+
},
|
167
|
+
|
168
|
+
pluralize: function(count, singular, plural) {
|
169
|
+
var value = (count == 1) ? singular : (plural || (singular.pluralize()));
|
170
|
+
var index = value.indexOf('%');
|
171
|
+
if (index > -1) {
|
172
|
+
return value.substr(0, index) + count + value.substr(index + 1, value.length - index - 1);
|
173
|
+
} else {
|
174
|
+
return count + ' ' + value;
|
175
|
+
}
|
176
|
+
}
|
177
|
+
};
|
178
|
+
|
179
|
+
// Import all string prototype methods as helpers (first argument is translates to string)
|
180
|
+
for (var name in String.prototype)
|
181
|
+
if (!functions[name] && String.prototype[name].call && name.charAt(0) != '$')
|
182
|
+
functions[name] = (function(name) {
|
183
|
+
return function(a, b) {
|
184
|
+
return String(a)[name](b);
|
185
|
+
}
|
186
|
+
})(name);
|
187
|
+
|
188
|
+
// Import all number prototype methods as helpers (first argument is translates to number)
|
189
|
+
for (var name in Number.prototype)
|
190
|
+
if (!functions[name] && Number.prototype[name].call && name.charAt(0) != '$')
|
191
|
+
functions[name] = (function(name) {
|
192
|
+
return function(a, b) {
|
193
|
+
return Number(a)[name](b);
|
194
|
+
}
|
195
|
+
})(name);
|
196
|
+
|
197
|
+
var operators = {
|
198
|
+
'*': 1,
|
199
|
+
'/': 1,
|
200
|
+
'+': 2,
|
201
|
+
'-': 2,
|
202
|
+
'>': 4,
|
203
|
+
'<': 4,
|
204
|
+
'^': 4,
|
205
|
+
'&': 4,
|
206
|
+
'|': 4,
|
207
|
+
'>=': 4,
|
208
|
+
'<=': 4,
|
209
|
+
'==': 4,
|
210
|
+
'!=': 4,
|
211
|
+
'===': 4,
|
212
|
+
'!==': 4,
|
213
|
+
'&&': 5,
|
214
|
+
'||': 5
|
215
|
+
};
|
216
|
+
for (var operator in operators)
|
217
|
+
functions[operator] = new Function('left', 'right', 'return left ' + operator + ' right');
|
218
|
+
|
219
|
+
var R_TRANSLATE = SheetParser.Value.tokenize;
|
220
|
+
var R_FIND = /\\?\{([^{}]+)\}/g;
|
221
|
+
var R_VARIABLE = /^[a-z0-9][a-z_\-0-9.\[\]]*$/ig;
|
222
|
+
var R_SELECTOR_CONTEXT = /^\s*([$]+)\s*/
|
223
|
+
var parsed = {};
|
224
|
+
var combinators = Array.object('+', '>', '!+', '++', '!~', '~~', '&', '&&', '$', '$$');
|
225
|
+
|
226
|
+
Object.append(LSD.Interpolation, {
|
227
|
+
translate: function(value) {
|
228
|
+
var cached = parsed[name];
|
229
|
+
if (cached) return cached;
|
230
|
+
var found, result = [], matched = [], scope = result, text, stack = [], operator, selector;
|
231
|
+
var names = R_TRANSLATE.names;
|
232
|
+
while (found = R_TRANSLATE.exec(value)) matched.push(found);
|
233
|
+
for (var i = 0, last = matched.length - 1; found = matched[i]; i++) {
|
234
|
+
if ((text = found[names._arguments])) {
|
235
|
+
var args = LSD.Interpolation.translate(text);
|
236
|
+
for (var j = 0, bit; bit = args[j]; j++) if (bit && bit.length == 1) args[j] = bit[0];
|
237
|
+
if ((text = found[names['function']])) {
|
238
|
+
scope.push({type: 'function', name: text, value: args.push ? args : [args]});
|
239
|
+
} else {
|
240
|
+
scope.push(args);
|
241
|
+
}
|
242
|
+
} else if ((text = (found[names.dstring] || found[names.sstring]))) {
|
243
|
+
scope.push(text);
|
244
|
+
} else if ((text = (found[names.number]))) {
|
245
|
+
scope.push(parseFloat(text));
|
246
|
+
} else if ((text = found[names.operator])) {
|
247
|
+
if (!selector) {
|
248
|
+
previous = stack[stack.length - 1];
|
249
|
+
if (left) left = null;
|
250
|
+
if (previous) {
|
251
|
+
operator = {type: 'function', name: text, index: i, scope: scope, precedence: operators[text]};
|
252
|
+
stack.push(operator);
|
253
|
+
if (previous.precedence > operator.precedence) {
|
254
|
+
scope = previous.scope;
|
255
|
+
var left = scope[scope.length - 1];
|
256
|
+
if (left.value) {
|
257
|
+
if (left.value[1] != null) {
|
258
|
+
scope = operator.value = [left.value[1]];
|
259
|
+
left.value[1] = operator;
|
260
|
+
}
|
261
|
+
} else throw "Right part is missing for " + left.name + " operator";
|
262
|
+
}
|
263
|
+
}
|
264
|
+
if (!left) {
|
265
|
+
var left = scope.pop();
|
266
|
+
if (left == null) {
|
267
|
+
if (combinators[text]) {
|
268
|
+
selector = {type: 'selector', value: text};
|
269
|
+
scope.push(selector);
|
270
|
+
} else throw "Left part is missing for " + text + " operator";
|
271
|
+
} else {
|
272
|
+
var operator = {type: 'function', name: text, index: i, scope: scope, precedence: operators[text]};
|
273
|
+
operator.value = [left];
|
274
|
+
stack.push(operator);
|
275
|
+
scope.push(operator);
|
276
|
+
scope = operator.value;
|
277
|
+
}
|
278
|
+
}
|
279
|
+
} else {
|
280
|
+
selector.value += ' ' + text;
|
281
|
+
text = null;
|
282
|
+
}
|
283
|
+
} else if ((text = found[names.token])) {
|
284
|
+
if (!selector && text.match(R_VARIABLE)) {
|
285
|
+
scope.push({type: 'token', name: text});
|
286
|
+
} else {
|
287
|
+
if (!selector) {
|
288
|
+
selector = {type: 'selector', value: text};
|
289
|
+
scope.push(selector);
|
290
|
+
} else {
|
291
|
+
selector.value += ' ' + text;
|
292
|
+
text = null;
|
293
|
+
}
|
294
|
+
}
|
295
|
+
}
|
296
|
+
if (!operator && text && stack.length) {
|
297
|
+
var pop = stack[stack.length - 1]
|
298
|
+
if (pop && pop.scope) scope = pop.scope;
|
299
|
+
}
|
300
|
+
operator = null;
|
301
|
+
};
|
302
|
+
return (parsed[value] = (result.length == 1 ? result[0] : result));
|
303
|
+
},
|
304
|
+
|
305
|
+
compile: function(object, output, source, translate) {
|
306
|
+
if (translate) object = LSD.Interpolation.translate(object);
|
307
|
+
switch (object.type) {
|
308
|
+
case 'token':
|
309
|
+
var Klass = LSD.Interpolation;
|
310
|
+
var value = object.name;
|
311
|
+
break;
|
312
|
+
case 'function':
|
313
|
+
var Klass = LSD.Interpolation.Function;
|
314
|
+
var name = object.name;
|
315
|
+
var value = object.value;
|
316
|
+
break;
|
317
|
+
case 'selector':
|
318
|
+
var Klass = LSD.Interpolation.Selector;
|
319
|
+
var value = object.value;
|
320
|
+
break;
|
321
|
+
default:
|
322
|
+
if (object.push) {
|
323
|
+
var Klass = LSD.Interpolation.Function
|
324
|
+
var value = object;
|
325
|
+
} else {
|
326
|
+
return object;
|
327
|
+
}
|
328
|
+
}
|
329
|
+
return new Klass(value, output, source, name);
|
330
|
+
},
|
331
|
+
|
332
|
+
textnode: function(textnode, widget, callback) {
|
333
|
+
var node = textnode, content = node.textContent, finder, length = content.length;
|
334
|
+
for (var match, index, last, next, compiled; match = R_FIND.exec(content);) {
|
335
|
+
last = index || 0
|
336
|
+
var index = match.index + match[0].length;
|
337
|
+
expression = node;
|
338
|
+
var cut = index - last;
|
339
|
+
if (cut < node.textContent.length) node = node.splitText(index - last);
|
340
|
+
if ((cut = (match.index - last))) expression = expression.splitText(cut);
|
341
|
+
if (!callback || callback === true) callback = widget;
|
342
|
+
compiled = LSD.Interpolation.compile(match[1], expression, callback, true);
|
343
|
+
compiled.placeholder = match[0];
|
344
|
+
compiled.attach();
|
345
|
+
Element.store(expression, 'interpolation', compiled);
|
346
|
+
last = index;
|
347
|
+
}
|
348
|
+
}
|
349
|
+
})
|
350
|
+
|
351
|
+
}();
|