radiant-fabulator_exhibit-extension 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +9 -0
- data/README.markdown +3 -0
- data/Rakefile +3 -2
- data/VERSION +1 -1
- data/app/models/fabulator_exhibit.rb +4 -0
- data/fabulator_exhibit_extension.rb +11 -2
- data/lib/tasks/fabulator_exhibit_extension_tasks.rake +30 -0
- data/public/javascripts/fabulator/exhibit/data.js +745 -0
- data/public/javascripts/fabulator/exhibit/exhibit.js +160 -0
- data/public/javascripts/fabulator/exhibit/expressions.js +1028 -0
- data/public/javascripts/fabulator/exhibit/facets.js +579 -0
- data/public/javascripts/fabulator/exhibit/views.js +457 -0
- data/public/stylesheets/fabulator/exhibit/exhibit.css +109 -0
- metadata +49 -10
@@ -0,0 +1,160 @@
|
|
1
|
+
/*
|
2
|
+
* (c) Copyright Texas A&M University 2010. All rights reserved.
|
3
|
+
*
|
4
|
+
* Portions of this code are copied from The SIMILE Project:
|
5
|
+
* (c) Copyright The SIMILE Project 2006. All rights reserved.
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
8
|
+
* modification, are permitted provided that the following conditions
|
9
|
+
* are met:
|
10
|
+
*
|
11
|
+
* 1. Redistributions of source code must retain the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer.
|
13
|
+
*
|
14
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
15
|
+
* notice, this list of conditions and the following disclaimer in the
|
16
|
+
* documentation and/or other materials provided with the distribution.
|
17
|
+
*
|
18
|
+
* 3. The name of the author may not be used to endorse or promote products
|
19
|
+
* derived from this software without specific prior written permission.
|
20
|
+
*
|
21
|
+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
22
|
+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
23
|
+
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
24
|
+
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
25
|
+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
26
|
+
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
27
|
+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
28
|
+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
29
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
30
|
+
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31
|
+
*
|
32
|
+
*/
|
33
|
+
|
34
|
+
// We can assume the Infusion is loaded
|
35
|
+
|
36
|
+
/*
|
37
|
+
* An Exhibit consists of the presentation and an overlay or slide-out
|
38
|
+
* with facets
|
39
|
+
*/
|
40
|
+
|
41
|
+
/* We look for <div class="fabulator-exhibit" /> sections */
|
42
|
+
|
43
|
+
/*
|
44
|
+
* A view offers a filtered set of data from a data store
|
45
|
+
* A data store manages the actual data from the server
|
46
|
+
* An Exhibit interacts with the view to manage the data shown
|
47
|
+
*/
|
48
|
+
|
49
|
+
Fabulator.namespace('Exhibit');
|
50
|
+
|
51
|
+
(function($, Exhibit) {
|
52
|
+
|
53
|
+
var initDataView = function(that) {
|
54
|
+
that.dataView = Exhibit.DataView({ source: that.options.source });
|
55
|
+
that.dataView.events.onModelChange.addListener(that.eventModelChange);
|
56
|
+
that.registerFilter = function(filter) {
|
57
|
+
that.dataView.registerFilter(filter);
|
58
|
+
};
|
59
|
+
};
|
60
|
+
|
61
|
+
var initPresentationViews = function(that) {
|
62
|
+
$(that.container).find('.views').each(function(idx, el) {
|
63
|
+
$(el).addClass("ui-corner-all");
|
64
|
+
that.presentation = Exhibit.Presentations(el, { viewPanel: that });
|
65
|
+
});
|
66
|
+
};
|
67
|
+
|
68
|
+
var initFacetView = function(that, myid) {
|
69
|
+
$(that.container).find('.facets').each(function(idx, el) {
|
70
|
+
$(el).attr('id', myid+'-facets-' + idx);
|
71
|
+
that.facets = Exhibit.Facets(el, { viewPanel: that, trigger: '#' + myid + '-open-facets' });
|
72
|
+
});
|
73
|
+
};
|
74
|
+
|
75
|
+
Exhibit.ViewPanel = function(container, options) {
|
76
|
+
var that = fluid.initView("Fabulator.Exhibit.ViewPanel", container, options),
|
77
|
+
lenses = new Array(),
|
78
|
+
header, counters,
|
79
|
+
myid = $(container).attr('id');
|
80
|
+
|
81
|
+
options = that.options;
|
82
|
+
|
83
|
+
options.source = options.source || $(container).attr("source");
|
84
|
+
|
85
|
+
that.eventModelChange = function(model) {
|
86
|
+
|
87
|
+
that.setCount(model.size());
|
88
|
+
|
89
|
+
if(that.presentation) {
|
90
|
+
that.presentation.eventModelChange(model);
|
91
|
+
}
|
92
|
+
|
93
|
+
};
|
94
|
+
|
95
|
+
lenses.push(Exhibit.DefaultLens());
|
96
|
+
|
97
|
+
that.getLens = function(item) {
|
98
|
+
for(i = 0, n = lenses.length; i < n; i++) {
|
99
|
+
if(lenses[i].isForItem(item)) {
|
100
|
+
return lenses[i];
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
|
106
|
+
header = "<span class='title'>" + $(container).attr("ex:exhibitLabel") + "</span>";
|
107
|
+
|
108
|
+
counters = $(container).attr("ex:counters");
|
109
|
+
|
110
|
+
if( counters != null) {
|
111
|
+
counters = counters.split(':');
|
112
|
+
header += "<span class='counter' id='" + myid + "-counter'>0 " + counters[1] + "</span>";
|
113
|
+
}
|
114
|
+
|
115
|
+
if( $(that.container).find('.facets').size() > 0 ) {
|
116
|
+
header += "<span class='ui-icon ui-icon-gear' id='"+myid+"-open-facets'>facets</span>";
|
117
|
+
}
|
118
|
+
$("<div class='header ui-corner-all'>" + header + "</div>").prependTo($(container));
|
119
|
+
//$("<div class='header ui-corner-all'><span class='title'>" + $(container).attr("ex:exhibitLabel") + "</span><span class='counter' id='" + myid + "-counter'>0 Items</span><span class='ui-icon ui-icon-gear' id='"+myid+"-open-facets'>facets</span></div>").prependTo($(container));
|
120
|
+
|
121
|
+
that.setCount = function(count) {
|
122
|
+
if( counters != null ) {
|
123
|
+
$('#' + myid + '-counter').text(count + " " + (count == 1 ? counters[0] : counters[1]));
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
initDataView(that);
|
128
|
+
|
129
|
+
initPresentationViews(that);
|
130
|
+
|
131
|
+
initFacetView(that, myid);
|
132
|
+
|
133
|
+
that.dataView.dataSource.fetchData();
|
134
|
+
|
135
|
+
|
136
|
+
return that;
|
137
|
+
};
|
138
|
+
})(jQuery, Fabulator.Exhibit);
|
139
|
+
|
140
|
+
fluid.defaults("Fabulator.Exhibit.ViewPanel", {
|
141
|
+
Presentations: {
|
142
|
+
type: "Fabulator.Exhibit.Presentations",
|
143
|
+
},
|
144
|
+
Facets: {
|
145
|
+
type: "Fabulator.Exhibit.Facets",
|
146
|
+
},
|
147
|
+
events: {
|
148
|
+
onDataChange: null
|
149
|
+
}
|
150
|
+
});
|
151
|
+
|
152
|
+
/* The following is what goes into the HTML through the xslt */
|
153
|
+
jQuery(document).ready(function($){
|
154
|
+
$(".fabulator-exhibit").each(function(idx, el) {
|
155
|
+
var options = {
|
156
|
+
};
|
157
|
+
|
158
|
+
Fabulator.Exhibit.ViewPanel('#' + $(el).attr('id'), options);
|
159
|
+
});
|
160
|
+
});
|
@@ -0,0 +1,1028 @@
|
|
1
|
+
/*
|
2
|
+
* (c) Copyright Texas A&M University 2010. All rights reserved.
|
3
|
+
*
|
4
|
+
* Portions of this code are copied from The SIMILE Project:
|
5
|
+
* (c) Copyright The SIMILE Project 2006. All rights reserved.
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without
|
8
|
+
* modification, are permitted provided that the following conditions
|
9
|
+
* are met:
|
10
|
+
*
|
11
|
+
* 1. Redistributions of source code must retain the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer.
|
13
|
+
*
|
14
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
15
|
+
* notice, this list of conditions and the following disclaimer in the
|
16
|
+
* documentation and/or other materials provided with the distribution.
|
17
|
+
*
|
18
|
+
* 3. The name of the author may not be used to endorse or promote products
|
19
|
+
* derived from this software without specific prior written permission.
|
20
|
+
*
|
21
|
+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
22
|
+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
23
|
+
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
24
|
+
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
25
|
+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
26
|
+
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
27
|
+
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
28
|
+
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
29
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
30
|
+
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31
|
+
*
|
32
|
+
*/
|
33
|
+
|
34
|
+
(function($, Exhibit) {
|
35
|
+
Exhibit.Controls = {
|
36
|
+
"if": {
|
37
|
+
f: function(args, roots, rootValueTypes, defaultRootName, database) {
|
38
|
+
var conditionCollection = args[0].evaluate(roots, rootValueTypes, defaultRootName, database),
|
39
|
+
condition = false;
|
40
|
+
conditionCollection.forEachValue(function(v) {
|
41
|
+
if(v) {
|
42
|
+
condition = true;
|
43
|
+
return true;
|
44
|
+
}
|
45
|
+
});
|
46
|
+
|
47
|
+
if(condition) {
|
48
|
+
return args[1].evaluate(roots, rootValueTypes, defaultRootName, database);
|
49
|
+
}
|
50
|
+
else {
|
51
|
+
return args[2].evaluate(roots, rootValueTypes, defaultRootName, database);
|
52
|
+
}
|
53
|
+
}
|
54
|
+
},
|
55
|
+
"foreach": {
|
56
|
+
f: function(args, roots, rootValueTypes, defaultRootName, database) {
|
57
|
+
var collection = args[0].evaluate(roots, rootValueTypes, defaultRootName, database),
|
58
|
+
oldValue = roots["value"],
|
59
|
+
oldValueType = rootValueTypes["value"],
|
60
|
+
results = [ ],
|
61
|
+
valueType = "text",
|
62
|
+
collection2;
|
63
|
+
|
64
|
+
rootValueTypes["value"] = collection.valueType;
|
65
|
+
|
66
|
+
collection.forEachValue(function(element) {
|
67
|
+
roots["value"] = element;
|
68
|
+
collection2 = args[1].evaluate(roots, rootValueTypes, defaultRootName, database);
|
69
|
+
valueType = collection2.valueType;
|
70
|
+
|
71
|
+
collection2.forEachValue(function(result) {
|
72
|
+
results.push(result);
|
73
|
+
});
|
74
|
+
});
|
75
|
+
|
76
|
+
roots["value"] = oldValue;
|
77
|
+
rootValueTypes["value"] = oldValueType;
|
78
|
+
|
79
|
+
return Exhibit.Expression.Collection(results, valueType);
|
80
|
+
}
|
81
|
+
},
|
82
|
+
"default": {
|
83
|
+
f: function(args, roots, rootValueTypes, defaultRootName, database) {
|
84
|
+
var i, n, collection;
|
85
|
+
for(i = 0, n = args.length; i < n; i++) {
|
86
|
+
collection = args[i].evaluate(roots, rootValueTypes, defaultRootName, database);
|
87
|
+
if( collection.size() > 0 ) {
|
88
|
+
return collection;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
return Exhibit.Expression.Collection([], "text");
|
92
|
+
}
|
93
|
+
}
|
94
|
+
};
|
95
|
+
|
96
|
+
Exhibit.Expression = function(rootNode) {
|
97
|
+
var that = { };
|
98
|
+
|
99
|
+
that.evaluate = function(
|
100
|
+
roots,
|
101
|
+
rootValueTypes,
|
102
|
+
defaultRootName,
|
103
|
+
database
|
104
|
+
) {
|
105
|
+
var collection = rootNode.evaluate(roots, rootValueTypes, defaultRootName, database);
|
106
|
+
return {
|
107
|
+
values: collection.getSet(),
|
108
|
+
valueType: collection.valueType,
|
109
|
+
size: collection.size()
|
110
|
+
};
|
111
|
+
};
|
112
|
+
|
113
|
+
that.evaluateOneItem = function( itemID, database ) {
|
114
|
+
return this.evaluate(
|
115
|
+
{ "value" : itemID },
|
116
|
+
{ "value" : "item" },
|
117
|
+
"value",
|
118
|
+
database
|
119
|
+
);
|
120
|
+
};
|
121
|
+
|
122
|
+
that.evaluateSingle = function(
|
123
|
+
roots,
|
124
|
+
rootValueTypes,
|
125
|
+
defaultRootName,
|
126
|
+
database
|
127
|
+
) {
|
128
|
+
var collection = rootNode.evaluate(roots, rootValueTypes, defaultRootName, database),
|
129
|
+
result = { value: null, valueType: collection.valueType };
|
130
|
+
|
131
|
+
collection.forEachValue(function(v) {
|
132
|
+
result.value = v;
|
133
|
+
return true;
|
134
|
+
});
|
135
|
+
|
136
|
+
return result;
|
137
|
+
};
|
138
|
+
|
139
|
+
that.isPath = rootNode.isPath;
|
140
|
+
|
141
|
+
that.getPath = that.isPath ?
|
142
|
+
function() { return rootNode; } :
|
143
|
+
function() { return null; } ;
|
144
|
+
|
145
|
+
that.testExists = that.isPath ?
|
146
|
+
function(
|
147
|
+
roots,
|
148
|
+
rootValueTypes,
|
149
|
+
defaultRootName,
|
150
|
+
database
|
151
|
+
) {
|
152
|
+
return rootNode.testExists(roots, rootValueTypes, defaultRootName, database);
|
153
|
+
} :
|
154
|
+
function(
|
155
|
+
roots,
|
156
|
+
rootValueTypes,
|
157
|
+
defaultRootName,
|
158
|
+
database
|
159
|
+
) {
|
160
|
+
return that.evaluate(roots, rootValueTypes, defaultRootName, database).values.size() > 0;
|
161
|
+
};
|
162
|
+
|
163
|
+
that.evaluateBackward = function(
|
164
|
+
value,
|
165
|
+
valueType,
|
166
|
+
filter,
|
167
|
+
database
|
168
|
+
) {
|
169
|
+
return rootNode.walkBackward([ value ], valueType, filter, database);
|
170
|
+
};
|
171
|
+
|
172
|
+
that.walkForward = function(
|
173
|
+
values,
|
174
|
+
valueType,
|
175
|
+
database
|
176
|
+
) {
|
177
|
+
return rootNode.walkForward(values, valueType, database);
|
178
|
+
};
|
179
|
+
|
180
|
+
that.walkBackward = function(
|
181
|
+
values,
|
182
|
+
valueType,
|
183
|
+
filter,
|
184
|
+
database
|
185
|
+
) {
|
186
|
+
return rootNode.walkBackward(values, valueType, filter, database);
|
187
|
+
};
|
188
|
+
|
189
|
+
return that;
|
190
|
+
};
|
191
|
+
|
192
|
+
Exhibit.Expression.Collection = function(values, valueType) {
|
193
|
+
var that = { };
|
194
|
+
|
195
|
+
if( values instanceof Array ) {
|
196
|
+
|
197
|
+
that.forEachValue = function(f) {
|
198
|
+
var a = values,
|
199
|
+
i, n;
|
200
|
+
|
201
|
+
for(i = 0, n = a.length; i < n; i++) {
|
202
|
+
if( f(a[i]) === true ) {
|
203
|
+
break;
|
204
|
+
}
|
205
|
+
}
|
206
|
+
};
|
207
|
+
|
208
|
+
that.getSet = function() {
|
209
|
+
return Exhibit.Set(values);
|
210
|
+
};
|
211
|
+
|
212
|
+
that.contains = function(v) {
|
213
|
+
var a = values,
|
214
|
+
i, n;
|
215
|
+
|
216
|
+
for(i = 0, n = a.length; i < n; i++) {
|
217
|
+
if( a[i] == v ) { return true; }
|
218
|
+
}
|
219
|
+
return false;
|
220
|
+
};
|
221
|
+
|
222
|
+
that.size = function() { values.length; };
|
223
|
+
|
224
|
+
}
|
225
|
+
else {
|
226
|
+
|
227
|
+
that.forEachValue = function(f) {
|
228
|
+
values.visit(f);
|
229
|
+
};
|
230
|
+
|
231
|
+
that.getSet = function() {
|
232
|
+
return values;
|
233
|
+
};
|
234
|
+
|
235
|
+
that.contains = function(v) {
|
236
|
+
return values.contains(v);
|
237
|
+
};
|
238
|
+
|
239
|
+
that.size = values.size;
|
240
|
+
|
241
|
+
}
|
242
|
+
|
243
|
+
that.isPath = false;
|
244
|
+
|
245
|
+
return that;
|
246
|
+
};
|
247
|
+
|
248
|
+
Exhibit.Expression.Constant = function(value, valueType) {
|
249
|
+
var that = { };
|
250
|
+
|
251
|
+
that.evaluate = function(
|
252
|
+
roots,
|
253
|
+
rootValueTypes,
|
254
|
+
defaultRootName,
|
255
|
+
database
|
256
|
+
) {
|
257
|
+
return Exhibit.Expression.Collection([ value ], valueType);
|
258
|
+
};
|
259
|
+
|
260
|
+
that.isPath = false;
|
261
|
+
|
262
|
+
return that;
|
263
|
+
};
|
264
|
+
|
265
|
+
var _operators = {
|
266
|
+
"+" : {
|
267
|
+
argumentType: "number",
|
268
|
+
valueType: "number",
|
269
|
+
f: function(a,b) { return a+b; }
|
270
|
+
},
|
271
|
+
"-" : {
|
272
|
+
argumentType: "number",
|
273
|
+
valueType: "number",
|
274
|
+
f: function(a,b) { return a-b; }
|
275
|
+
},
|
276
|
+
"*" : {
|
277
|
+
argumentType: "number",
|
278
|
+
valueType: "number",
|
279
|
+
f: function(a,b) { return a*b; }
|
280
|
+
},
|
281
|
+
"/" : {
|
282
|
+
argumentType: "number",
|
283
|
+
valueType: "number",
|
284
|
+
f: function(a,b) { return a/b; }
|
285
|
+
},
|
286
|
+
"=" : {
|
287
|
+
valueType: "boolean",
|
288
|
+
f: function(a,b) { return a == b; }
|
289
|
+
},
|
290
|
+
"<>" : {
|
291
|
+
valueType: "boolean",
|
292
|
+
f: function(a,b) { return a != b; }
|
293
|
+
},
|
294
|
+
"><" : {
|
295
|
+
valueType: "boolean",
|
296
|
+
f: function(a,b) { return a != b; }
|
297
|
+
},
|
298
|
+
"<" : {
|
299
|
+
valueType: "boolean",
|
300
|
+
f: function(a,b) { return a < b; }
|
301
|
+
},
|
302
|
+
">" : {
|
303
|
+
valueType: "boolean",
|
304
|
+
f: function(a,b) { return a > b; }
|
305
|
+
},
|
306
|
+
"<=" : {
|
307
|
+
valueType: "boolean",
|
308
|
+
f: function(a,b) { return a <= b; }
|
309
|
+
},
|
310
|
+
">=" : {
|
311
|
+
valueType: "boolean",
|
312
|
+
f: function(a,b) { return a >= b; }
|
313
|
+
}
|
314
|
+
};
|
315
|
+
|
316
|
+
Exhibit.Expression.Operator = function(operator, args) {
|
317
|
+
var that = { },
|
318
|
+
_operator = operator,
|
319
|
+
_args = args;
|
320
|
+
|
321
|
+
that.evaluate = function(
|
322
|
+
roots,
|
323
|
+
rootValueTypes,
|
324
|
+
defaultRootName,
|
325
|
+
database
|
326
|
+
) {
|
327
|
+
var values = [ ],
|
328
|
+
args = [],
|
329
|
+
i, n, operator, f;
|
330
|
+
|
331
|
+
for(i = 0, n = _args.length; i < n; i++) {
|
332
|
+
args.push(_args[i].evaluate(roots, rootValueTypes, defaultRootName, database));
|
333
|
+
}
|
334
|
+
|
335
|
+
operator = _operators[_operator];
|
336
|
+
f = operator.f;
|
337
|
+
if(operator.argumentType == "number") {
|
338
|
+
args[0].forEachValue(function(v1) {
|
339
|
+
if( !(typeof(v1) == "number") ) {
|
340
|
+
v1 = parseFloat(v1);
|
341
|
+
}
|
342
|
+
|
343
|
+
args[1].forEachValue(function(v2) {
|
344
|
+
if( !(typeof(v2) == "number")) {
|
345
|
+
v2 = parseFloat(v2);
|
346
|
+
}
|
347
|
+
|
348
|
+
values.push(f(v1, v2));
|
349
|
+
});
|
350
|
+
});
|
351
|
+
}
|
352
|
+
else {
|
353
|
+
args[0].forEachValue(function(v1) {
|
354
|
+
args[1].forEachValue(function(v2) {
|
355
|
+
values.push(f(v1, v2));
|
356
|
+
});
|
357
|
+
});
|
358
|
+
}
|
359
|
+
|
360
|
+
return Exhibit.Expression.Collection(values, operator.valueType);
|
361
|
+
};
|
362
|
+
|
363
|
+
that.isPath = false;
|
364
|
+
|
365
|
+
return that;
|
366
|
+
};
|
367
|
+
|
368
|
+
Exhibit.Expression.FunctionCall = function(name, args) {
|
369
|
+
var that = { },
|
370
|
+
_name = name,
|
371
|
+
_args = args;
|
372
|
+
|
373
|
+
that.evaluate = function(
|
374
|
+
roots,
|
375
|
+
rootValueTypes,
|
376
|
+
defaultRootName,
|
377
|
+
database
|
378
|
+
) {
|
379
|
+
var args = [],
|
380
|
+
i, n;
|
381
|
+
|
382
|
+
for(i = 0, n = _args.length; i < n; i++) {
|
383
|
+
args.push(_args[i].evaluate(roots, rootValueTypes, defaultRootName, database));
|
384
|
+
}
|
385
|
+
|
386
|
+
if(_name in Exhibit.Functions) {
|
387
|
+
return Exhibit.Functions[_name].f(args);
|
388
|
+
}
|
389
|
+
else {
|
390
|
+
throw new Error("No such function named " + _name);
|
391
|
+
}
|
392
|
+
};
|
393
|
+
|
394
|
+
that.isPath = false;
|
395
|
+
|
396
|
+
return that;
|
397
|
+
};
|
398
|
+
|
399
|
+
Exhibit.Expression.ControlCall = function(name, args) {
|
400
|
+
var that = { },
|
401
|
+
_name = name,
|
402
|
+
_args = args;
|
403
|
+
|
404
|
+
that.evaluate = function(
|
405
|
+
roots,
|
406
|
+
rootValueTypes,
|
407
|
+
defaultRootName,
|
408
|
+
database
|
409
|
+
) {
|
410
|
+
return Exhibit.Controls[_name].f(_args, roots, rootValueTypes, defaultRootName, database);
|
411
|
+
};
|
412
|
+
|
413
|
+
that.isPath = false;
|
414
|
+
|
415
|
+
return that;
|
416
|
+
};
|
417
|
+
|
418
|
+
Exhibit.Expression.Path = function(property, forward) {
|
419
|
+
var that = { },
|
420
|
+
_rootName = null,
|
421
|
+
_segments = [ ];
|
422
|
+
|
423
|
+
if( typeof(property) != "undefined" ) {
|
424
|
+
_segments.push({ property: property, forward: forward, isArray: false });
|
425
|
+
}
|
426
|
+
|
427
|
+
that.isPath = true;
|
428
|
+
|
429
|
+
that.setRootName = function(rootName) {
|
430
|
+
_rootName = rootName;
|
431
|
+
};
|
432
|
+
|
433
|
+
that.appendSegment = function(property, hopOperator) {
|
434
|
+
_segments.push({
|
435
|
+
property: property,
|
436
|
+
forward: hopOperator.charAt(0) == ".",
|
437
|
+
isArray: hopOperator.length > 1
|
438
|
+
});
|
439
|
+
};
|
440
|
+
|
441
|
+
that.getSegment = function(index) {
|
442
|
+
var segment;
|
443
|
+
|
444
|
+
if( index < _segments.length ) {
|
445
|
+
segment = _segments[index];
|
446
|
+
return {
|
447
|
+
property: segment.property,
|
448
|
+
forward: segment.forward,
|
449
|
+
isArray: segment.isArray
|
450
|
+
};
|
451
|
+
}
|
452
|
+
else {
|
453
|
+
return null;
|
454
|
+
}
|
455
|
+
};
|
456
|
+
|
457
|
+
that.getLastSegment = function() {
|
458
|
+
return that.getSegment(_segments.length - 1);
|
459
|
+
};
|
460
|
+
|
461
|
+
that.getSegmentCount = function() { return _segments.length };
|
462
|
+
|
463
|
+
var walkForward = function(collection, database) {
|
464
|
+
var i, n, segment, a, valueType, property, values;
|
465
|
+
|
466
|
+
for(i = 0, n = _segments.length; i < n; i++) {
|
467
|
+
segment = _segments[i];
|
468
|
+
if(segment.isArray) {
|
469
|
+
a = [ ];
|
470
|
+
if( segment.forward ) {
|
471
|
+
collection.forEachValue(function(v) {
|
472
|
+
database.getObjects(v, segment.property).visit(function(v2) { a.push(v2); });
|
473
|
+
});
|
474
|
+
|
475
|
+
property = database.getProperty(segment.property);
|
476
|
+
valueType = property != null ? property.getValueType() : "text";
|
477
|
+
}
|
478
|
+
else {
|
479
|
+
collection.forEachValue(function(v) {
|
480
|
+
database.getSubjects(v, segment.property).visit(function(v2) { a.push(v2); });
|
481
|
+
});
|
482
|
+
valueType = "item";
|
483
|
+
}
|
484
|
+
collection = Exhibit.Expression.Collection(a, valueType);
|
485
|
+
}
|
486
|
+
else {
|
487
|
+
if( segment.forward ) {
|
488
|
+
values = database.getObjectsUnion(collection.getSet(), segment.property);
|
489
|
+
property = database.getProperty(segment.property);
|
490
|
+
valueType = property != null ? property.getValueType() : "text";
|
491
|
+
collection = Exhibit.Expression.Collection(values, valueType);
|
492
|
+
}
|
493
|
+
else {
|
494
|
+
values = database.getSubjectsUnion(collection.getSet(), segment.property);
|
495
|
+
collection = Exhibit.Expression.Collection(values, "item");
|
496
|
+
}
|
497
|
+
}
|
498
|
+
}
|
499
|
+
|
500
|
+
return collection;
|
501
|
+
};
|
502
|
+
|
503
|
+
var walkBackward = function(collection, filter, database) {
|
504
|
+
var i, segment, a, valueType, property, values;
|
505
|
+
|
506
|
+
if(filter instanceof Array) {
|
507
|
+
filter = Exhibit.Set(filter);
|
508
|
+
}
|
509
|
+
for(i = _segments.length - 1; i >= 0; i--) {
|
510
|
+
segment = _segments[i];
|
511
|
+
if(segment.isArray) {
|
512
|
+
a = [];
|
513
|
+
if( segment.forward ) {
|
514
|
+
collection.forEachValue(function(v) {
|
515
|
+
database.getSubjects(v, segment.property).visit(function(v2) {
|
516
|
+
if( i > 0 || filter == null || filter.contains(v2) ) {
|
517
|
+
a.push(v2);
|
518
|
+
}
|
519
|
+
});
|
520
|
+
});
|
521
|
+
|
522
|
+
property = database.getProperty(segment.property);
|
523
|
+
valueType = property != null ? property.getValueType() : "text";
|
524
|
+
}
|
525
|
+
else {
|
526
|
+
collection.forEachValue(function(v) {
|
527
|
+
database.getObjects(v, segment.property).visit(function(v2) {
|
528
|
+
if( i > 0 || filter == null || filter.contains(v2) ) {
|
529
|
+
a.push(v2);
|
530
|
+
}
|
531
|
+
});
|
532
|
+
});
|
533
|
+
valueType = "item";
|
534
|
+
}
|
535
|
+
collection = Exhibit.Expression.Collection(a, valueType);
|
536
|
+
}
|
537
|
+
else {
|
538
|
+
if( segment.forward ) {
|
539
|
+
values = database.getSubjectsUnion(collection.getSet(), segment.property, null, i == 0 ? filter : null);
|
540
|
+
collection = Exhibit.Expression.Collection(values, "item");
|
541
|
+
}
|
542
|
+
else {
|
543
|
+
values = database.getObjectsUnion(collection.getSet(), segment.property, null, i == 0 ? filter : null);
|
544
|
+
property = database.getProperty(segment.property);
|
545
|
+
valueType = property != null ? property.getValueType() : "text";
|
546
|
+
collection = Exhibit.Expression.Collection(values, valueType);
|
547
|
+
}
|
548
|
+
}
|
549
|
+
}
|
550
|
+
|
551
|
+
return collection;
|
552
|
+
};
|
553
|
+
|
554
|
+
that.rangeBackward = function(
|
555
|
+
from,
|
556
|
+
to,
|
557
|
+
filter,
|
558
|
+
database
|
559
|
+
) {
|
560
|
+
var set = Exhibit.Set(),
|
561
|
+
valueType = "item",
|
562
|
+
segment, i;
|
563
|
+
|
564
|
+
if(_segments.length > 0) {
|
565
|
+
segment = _segments[_segments.length - 1];
|
566
|
+
if(segment.forward) {
|
567
|
+
database.getSubjectsInRange(segment.property, from, to, false, set, _segments.length == 1 ? filter : null);
|
568
|
+
}
|
569
|
+
else {
|
570
|
+
throw new Error("Last path of segment must be forward");
|
571
|
+
}
|
572
|
+
|
573
|
+
for(i = _segments.length-2; i >= 0; i--) {
|
574
|
+
segment = _segments[i];
|
575
|
+
if( segment.forward ) {
|
576
|
+
set = database.getSubjectsUnion(set, segment.property, null, i == 0 ? filter : null);
|
577
|
+
valueType = "item";
|
578
|
+
}
|
579
|
+
else {
|
580
|
+
set = database.getObjectsUnion(set, segment.property, null, i == 0 ? filter : null);
|
581
|
+
property = database.getProperty(segment.property);
|
582
|
+
valueType = property != null ? property.getValueType() : "text";
|
583
|
+
}
|
584
|
+
}
|
585
|
+
}
|
586
|
+
|
587
|
+
return {
|
588
|
+
valueType: valueType,
|
589
|
+
values: set,
|
590
|
+
count: set.size()
|
591
|
+
};
|
592
|
+
};
|
593
|
+
|
594
|
+
that.evaluate = function(
|
595
|
+
roots,
|
596
|
+
rootValueTypes,
|
597
|
+
defaultRootName,
|
598
|
+
database
|
599
|
+
) {
|
600
|
+
var rootName = _rootName != null ? _rootName : defaultRootName,
|
601
|
+
valueType = rootName in rootValueTypes ? rootValueTypes[rootName] : "text",
|
602
|
+
collection = null,
|
603
|
+
root;
|
604
|
+
|
605
|
+
if( rootName in roots ) {
|
606
|
+
root = roots[rootName];
|
607
|
+
|
608
|
+
if( root.isSet || root instanceof Array) {
|
609
|
+
collection = Exhibit.Expression.Collection(root, valueType);
|
610
|
+
}
|
611
|
+
else {
|
612
|
+
collection = Exhibit.Expression.Collection([ root ], valueType);
|
613
|
+
}
|
614
|
+
|
615
|
+
return walkForward(collection, database);
|
616
|
+
}
|
617
|
+
else {
|
618
|
+
throw new Error("No such variable called " + rootName);
|
619
|
+
}
|
620
|
+
};
|
621
|
+
|
622
|
+
that.testExists = function(
|
623
|
+
roots,
|
624
|
+
rootValueTypes,
|
625
|
+
defaultRootName,
|
626
|
+
database
|
627
|
+
) {
|
628
|
+
return that.evaluate(roots, rootValueTypes, defaultRootName, database).size() > 0;
|
629
|
+
};
|
630
|
+
|
631
|
+
that.evaluateBackward = function(
|
632
|
+
value,
|
633
|
+
valueType,
|
634
|
+
filter,
|
635
|
+
database
|
636
|
+
) {
|
637
|
+
var collection = Exhibit.Expression.Collection([ value ], valueType);
|
638
|
+
return walkBackward(collection, filter, database);
|
639
|
+
};
|
640
|
+
|
641
|
+
that.walkForward = function(
|
642
|
+
values,
|
643
|
+
valueType,
|
644
|
+
database
|
645
|
+
) {
|
646
|
+
return walkForward(Exhibit.Expression.Collection(values, valueType), database);
|
647
|
+
};
|
648
|
+
|
649
|
+
that.walkBackward = function(
|
650
|
+
values,
|
651
|
+
valueType,
|
652
|
+
filter,
|
653
|
+
database
|
654
|
+
) {
|
655
|
+
return walkBackward(Exhibit.Expression.Collection(values, valueType), filter, database);
|
656
|
+
};
|
657
|
+
|
658
|
+
return that;
|
659
|
+
};
|
660
|
+
|
661
|
+
Exhibit.ExpressionParser = function() {
|
662
|
+
var that = { };
|
663
|
+
|
664
|
+
var internalParse = function(scanner, several) {
|
665
|
+
var token = scanner.token(),
|
666
|
+
roots, expressions, r, n,
|
667
|
+
Scanner = Exhibit.ExpressionScanner,
|
668
|
+
next = function() { scanner.next(); token = scanner.token(); },
|
669
|
+
makePosition = function() { return token != null ? token.start : scanner.index(); };
|
670
|
+
|
671
|
+
var parsePath = function() {
|
672
|
+
var path = Exhibit.Expression.Path(),
|
673
|
+
hopOperator;
|
674
|
+
while( token != null && token.type == Scanner.PATH_OPERATOR ) {
|
675
|
+
hopOperator = token.value;
|
676
|
+
next();
|
677
|
+
|
678
|
+
if( token != null && token.type == Scanner.IDENTIFIER ) {
|
679
|
+
path.appendSegment(token.value, hopOperator);
|
680
|
+
next();
|
681
|
+
}
|
682
|
+
else {
|
683
|
+
throw new Error("Missing property ID at position " + makePosition());
|
684
|
+
}
|
685
|
+
}
|
686
|
+
return path;
|
687
|
+
};
|
688
|
+
|
689
|
+
var parseFactor = function() {
|
690
|
+
var result = null,
|
691
|
+
identifier;
|
692
|
+
|
693
|
+
if( token == null ) {
|
694
|
+
throw new Error("Missing factor at end of expression");
|
695
|
+
}
|
696
|
+
|
697
|
+
switch(token.type) {
|
698
|
+
case Scanner.NUMBER:
|
699
|
+
result = Exhibit.Expression.Constant(token.value, "number");
|
700
|
+
next();
|
701
|
+
break;
|
702
|
+
case Scanner.STRING:
|
703
|
+
result = Exhibit.Expression.Constant(token.value, "text");
|
704
|
+
next();
|
705
|
+
break;
|
706
|
+
case Scanner.PATH_OPERATOR:
|
707
|
+
result = parsePath();
|
708
|
+
break;
|
709
|
+
case Scanner.IDENTIFIER:
|
710
|
+
identifier = token.value;
|
711
|
+
next();
|
712
|
+
|
713
|
+
if( identifier in Exhibit.Controls ) {
|
714
|
+
if( token != null && token.type == Scanner.DELIMITER && token.value == "(") {
|
715
|
+
next();
|
716
|
+
|
717
|
+
args = (token != null && token.type == Scanner.DELIMITER && token.value == ")") ?
|
718
|
+
[] : parseExpressionList();
|
719
|
+
result = Exhibit.Expression.ControlCall(identifier, args);
|
720
|
+
|
721
|
+
if( token != null && token.type == Scanner.DELIMITER && token.value == ")") {
|
722
|
+
next();
|
723
|
+
}
|
724
|
+
else {
|
725
|
+
throw new Error("Missing ) to end " + identifier + " at position " + makePosition());
|
726
|
+
}
|
727
|
+
}
|
728
|
+
else {
|
729
|
+
throw new Error("Missing ( to start " + identifier + " at position " + makePosition());
|
730
|
+
}
|
731
|
+
}
|
732
|
+
else {
|
733
|
+
if( token != null && token.type == Scanner.DELIMITER && token.value == "(") {
|
734
|
+
next();
|
735
|
+
|
736
|
+
args = (token != null && token.type == Scanner.DELIMITER && token.value == ")") ?
|
737
|
+
[] : parseExpressionList();
|
738
|
+
result = Exhibit.Expression.FunctionCall(identifier, args);
|
739
|
+
|
740
|
+
if( token != null && token.type == Scanner.DELIMITER && token.value == ")") {
|
741
|
+
next();
|
742
|
+
}
|
743
|
+
else {
|
744
|
+
throw new Error("Missing ) after function call " + identifier + " at position " + makePosition());
|
745
|
+
}
|
746
|
+
}
|
747
|
+
else {
|
748
|
+
result = parsePath();
|
749
|
+
result.setRootName(identifier);
|
750
|
+
}
|
751
|
+
}
|
752
|
+
break;
|
753
|
+
case Scanner.DELIMITER:
|
754
|
+
if( token.value == "(" ) {
|
755
|
+
next();
|
756
|
+
|
757
|
+
result = parseExpression();
|
758
|
+
if( token != null && token.type == Scanner.DELIMITER && token.value == ")") {
|
759
|
+
next();
|
760
|
+
break;
|
761
|
+
}
|
762
|
+
else {
|
763
|
+
throw new Error("Missing ) at position " + makePosition());
|
764
|
+
}
|
765
|
+
} // else, fall through
|
766
|
+
default:
|
767
|
+
throw new Error("Unexpected text " + token.value + " at position " + makePosition());
|
768
|
+
}
|
769
|
+
|
770
|
+
return result;
|
771
|
+
};
|
772
|
+
|
773
|
+
var parseTerm = function() {
|
774
|
+
var term = parseFactor(),
|
775
|
+
operator;
|
776
|
+
|
777
|
+
while( token != null && token.type == Scanner.OPERATOR &&
|
778
|
+
( token.value == "*" || token.value == "/" )) {
|
779
|
+
operator = token.value;
|
780
|
+
next();
|
781
|
+
|
782
|
+
term = Exhibit.Expression.Operator(operator, [ term, parseFactor() ]);
|
783
|
+
}
|
784
|
+
return term;
|
785
|
+
};
|
786
|
+
|
787
|
+
var parseSubExpression = function() {
|
788
|
+
var subExpression = parseTerm(),
|
789
|
+
operator;
|
790
|
+
|
791
|
+
while( token != null && token.type == Scanner.OPERATOR &&
|
792
|
+
( token.value == "+" || token.value == "-" )) {
|
793
|
+
operator = token.value;
|
794
|
+
next();
|
795
|
+
|
796
|
+
subExpression = Exhibit.Expression.Operator(operator, [ subExpression, parseTerm() ]);
|
797
|
+
}
|
798
|
+
return subExpression;
|
799
|
+
};
|
800
|
+
|
801
|
+
var parseExpression = function() {
|
802
|
+
var expression = parseSubExpression(),
|
803
|
+
operator;
|
804
|
+
|
805
|
+
while( token != null && token.type == Scanner.OPERATOR &&
|
806
|
+
( token.value == "=" || token.value == "<>" ||
|
807
|
+
token.value == "<" || token.value == "<=" ||
|
808
|
+
token.value == ">" || token.value == ">=" )) {
|
809
|
+
|
810
|
+
operator = token.value;
|
811
|
+
next();
|
812
|
+
|
813
|
+
expression = Exhibit.Expression.Operator(operator, [ expression, parseSubExpression ]);
|
814
|
+
}
|
815
|
+
return expression;
|
816
|
+
};
|
817
|
+
|
818
|
+
var parseExpressionList = function() {
|
819
|
+
var expressions = [ parseExpression() ];
|
820
|
+
while( token != null && token.type == Scanner.DELIMITER && token.value == ",") {
|
821
|
+
next();
|
822
|
+
expressions.push(parseExpression());
|
823
|
+
}
|
824
|
+
return expressions;
|
825
|
+
};
|
826
|
+
|
827
|
+
if(several) {
|
828
|
+
roots = parseExpressionList();
|
829
|
+
expressions = [ ];
|
830
|
+
for(r = 0, n = roots.length; r < n; r++) {
|
831
|
+
expressions.push(Exhibit.Expression(roots[r]));
|
832
|
+
}
|
833
|
+
return expressions;
|
834
|
+
}
|
835
|
+
else {
|
836
|
+
return Exhibit.Expression(parseExpression());
|
837
|
+
}
|
838
|
+
};
|
839
|
+
|
840
|
+
that.parse = function(s, startIndex, results) {
|
841
|
+
var scanner;
|
842
|
+
|
843
|
+
startIndex = startIndex || 0;
|
844
|
+
results = results || { };
|
845
|
+
|
846
|
+
scanner = Exhibit.ExpressionScanner(s, startIndex);
|
847
|
+
try {
|
848
|
+
return internalParse(scanner, false);
|
849
|
+
}
|
850
|
+
finally {
|
851
|
+
results.index = scanner.token() != null ? scanner.token().start : scanner.index();
|
852
|
+
}
|
853
|
+
};
|
854
|
+
|
855
|
+
|
856
|
+
return that;
|
857
|
+
};
|
858
|
+
|
859
|
+
Exhibit.ExpressionScanner = function(text, startIndex) {
|
860
|
+
var that = { },
|
861
|
+
_text = text + " ",
|
862
|
+
_maxIndex = text.length,
|
863
|
+
_index = startIndex,
|
864
|
+
_token = null;
|
865
|
+
|
866
|
+
|
867
|
+
|
868
|
+
that.token = function() { return _token; }
|
869
|
+
|
870
|
+
that.index = function() { return _index; }
|
871
|
+
|
872
|
+
var isDigit = function(c) {
|
873
|
+
return "0123456789".indexOf(c) >= 0;
|
874
|
+
};
|
875
|
+
|
876
|
+
that.next = function() {
|
877
|
+
var c1, c2, i, c;
|
878
|
+
|
879
|
+
_token = null;
|
880
|
+
|
881
|
+
while(_index < _maxIndex &&
|
882
|
+
" \t\r\n".indexOf(_text.charAt(_index)) >= 0) {
|
883
|
+
_index++;
|
884
|
+
};
|
885
|
+
|
886
|
+
if( _index < _maxIndex ) {
|
887
|
+
c1 = _text.charAt(_index);
|
888
|
+
c2 = _text.charAt(_index + 1);
|
889
|
+
|
890
|
+
if( ".!".indexOf(c1) >= 0 ) {
|
891
|
+
if( c2 == "@" ) {
|
892
|
+
_token = {
|
893
|
+
type: Exhibit.ExpressionScanner.PATH_OPERATOR,
|
894
|
+
value: c1+c2,
|
895
|
+
start: _index,
|
896
|
+
end: _index+2
|
897
|
+
};
|
898
|
+
_index += 2;
|
899
|
+
}
|
900
|
+
else {
|
901
|
+
_token = {
|
902
|
+
type: Exhibit.ExpressionScanner.PATH_OPERATOR,
|
903
|
+
value: c1,
|
904
|
+
start: _index,
|
905
|
+
end: _index+1
|
906
|
+
};
|
907
|
+
_index += 1;
|
908
|
+
}
|
909
|
+
}
|
910
|
+
else if( "<>".indexOf(c1) >= 0) {
|
911
|
+
if((c2 == "=") || ("<>".indexOf(c2) >= 0 && c1 != c2)) {
|
912
|
+
_token = {
|
913
|
+
type: Exhibit.ExpressionScanner.OPERATOR,
|
914
|
+
value: c1 + c2,
|
915
|
+
start: _index,
|
916
|
+
end: _index + 2
|
917
|
+
};
|
918
|
+
_index += 2;
|
919
|
+
}
|
920
|
+
else {
|
921
|
+
_token = {
|
922
|
+
type: Exhibit.ExpressionScanner.OPERATOR,
|
923
|
+
value: c1,
|
924
|
+
start: _index,
|
925
|
+
end: _index+1
|
926
|
+
};
|
927
|
+
_index += 1;
|
928
|
+
}
|
929
|
+
}
|
930
|
+
else if( "+-*/=".indexOf(c1) >= 0) {
|
931
|
+
_token = {
|
932
|
+
type: Exhibit.ExpressionScanner.OPERATOR,
|
933
|
+
value: c1,
|
934
|
+
start: _index,
|
935
|
+
end: _index+1
|
936
|
+
};
|
937
|
+
_index += 1;
|
938
|
+
}
|
939
|
+
else if( "()".indexOf(c1) >= 0) {
|
940
|
+
_token = {
|
941
|
+
type: Exhibit.ExpressionScanner.DELIMITER,
|
942
|
+
value: c1,
|
943
|
+
start: _index,
|
944
|
+
end: _index+1
|
945
|
+
};
|
946
|
+
_index += 1;
|
947
|
+
}
|
948
|
+
else if( "\"'".indexOf(c1) >= 0) { // quoted strings
|
949
|
+
i = _index + 1;
|
950
|
+
while( i < _maxIndex ) {
|
951
|
+
if( _text.charAt(i) == c1 && _text.charAt(i-1) != "\\") {
|
952
|
+
break;
|
953
|
+
}
|
954
|
+
i += 1;
|
955
|
+
}
|
956
|
+
|
957
|
+
if(i < _maxIndex) {
|
958
|
+
_token = {
|
959
|
+
type: Exhibit.ExpressionScanner.STRING,
|
960
|
+
value: _text.substring(_index+1, i).replace(/\\'/g, "'").replace(/\\"/g, '"'),
|
961
|
+
start: _index,
|
962
|
+
end: i+1
|
963
|
+
};
|
964
|
+
_index = i + 1;
|
965
|
+
}
|
966
|
+
else {
|
967
|
+
throw new Error("Unterminated string starting at " + _index);
|
968
|
+
}
|
969
|
+
}
|
970
|
+
else if(isDigit(c1)) { // number
|
971
|
+
i = _index;
|
972
|
+
while( i < _maxIndex && isDigit(_text.charAt(i))) {
|
973
|
+
i += 1;
|
974
|
+
}
|
975
|
+
|
976
|
+
if( i < _maxIndex && _text.charAt(i) == "." ) {
|
977
|
+
i += 1;
|
978
|
+
while( i < _maxIndex && isDigit(_text.charAt(i))) {
|
979
|
+
i += 1;
|
980
|
+
}
|
981
|
+
}
|
982
|
+
|
983
|
+
_token = {
|
984
|
+
type: Exhibit.ExpressionScanner.NUMBER,
|
985
|
+
value: parseFloat(_text.substring(_index, i)),
|
986
|
+
start: _index,
|
987
|
+
end: i
|
988
|
+
};
|
989
|
+
|
990
|
+
_index = i;
|
991
|
+
}
|
992
|
+
else { // identifier
|
993
|
+
i = _index;
|
994
|
+
|
995
|
+
while( i < _maxIndex ) {
|
996
|
+
c = _text.charAt(i);
|
997
|
+
if( "(),.!@ \t".indexOf(c) < 0 ) {
|
998
|
+
i += 1;
|
999
|
+
}
|
1000
|
+
else {
|
1001
|
+
break;
|
1002
|
+
}
|
1003
|
+
}
|
1004
|
+
|
1005
|
+
_token = {
|
1006
|
+
type: Exhibit.ExpressionScanner.IDENTIFIER,
|
1007
|
+
value: _text.substring(_index, i),
|
1008
|
+
start: _index,
|
1009
|
+
end: i
|
1010
|
+
};
|
1011
|
+
_index = i;
|
1012
|
+
}
|
1013
|
+
}
|
1014
|
+
};
|
1015
|
+
|
1016
|
+
that.next();
|
1017
|
+
|
1018
|
+
return that;
|
1019
|
+
};
|
1020
|
+
|
1021
|
+
Exhibit.ExpressionScanner.DELIMITER = 0;
|
1022
|
+
Exhibit.ExpressionScanner.NUMBER = 1;
|
1023
|
+
Exhibit.ExpressionScanner.STRING = 2;
|
1024
|
+
Exhibit.ExpressionScanner.IDENTIFIER = 3;
|
1025
|
+
Exhibit.ExpressionScanner.OPERATOR = 4;
|
1026
|
+
Exhibit.ExpressionScanner.PATH_OPERATOR = 5;
|
1027
|
+
|
1028
|
+
})(jQuery, Fabulator.Exhibit);
|