vis-rails 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.gitmodules +3 -0
- data/.project +11 -0
- data/Gemfile +4 -0
- data/LICENSE +202 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/vis/rails/engine.rb +6 -0
- data/lib/vis/rails/version.rb +5 -0
- data/lib/vis/rails.rb +7 -0
- data/vendor/assets/javascripts/vis.js +1 -0
- data/vendor/assets/stylesheets/vis.css +3 -0
- data/vendor/assets/vis/DataSet.js +936 -0
- data/vendor/assets/vis/DataView.js +281 -0
- data/vendor/assets/vis/EventBus.js +89 -0
- data/vendor/assets/vis/events.js +116 -0
- data/vendor/assets/vis/graph/ClusterMixin.js +1019 -0
- data/vendor/assets/vis/graph/Edge.js +620 -0
- data/vendor/assets/vis/graph/Graph.js +2111 -0
- data/vendor/assets/vis/graph/Groups.js +80 -0
- data/vendor/assets/vis/graph/Images.js +41 -0
- data/vendor/assets/vis/graph/NavigationMixin.js +245 -0
- data/vendor/assets/vis/graph/Node.js +978 -0
- data/vendor/assets/vis/graph/Popup.js +105 -0
- data/vendor/assets/vis/graph/SectorsMixin.js +547 -0
- data/vendor/assets/vis/graph/SelectionMixin.js +515 -0
- data/vendor/assets/vis/graph/dotparser.js +829 -0
- data/vendor/assets/vis/graph/img/downarrow.png +0 -0
- data/vendor/assets/vis/graph/img/leftarrow.png +0 -0
- data/vendor/assets/vis/graph/img/minus.png +0 -0
- data/vendor/assets/vis/graph/img/plus.png +0 -0
- data/vendor/assets/vis/graph/img/rightarrow.png +0 -0
- data/vendor/assets/vis/graph/img/uparrow.png +0 -0
- data/vendor/assets/vis/graph/img/zoomExtends.png +0 -0
- data/vendor/assets/vis/graph/shapes.js +225 -0
- data/vendor/assets/vis/module/exports.js +68 -0
- data/vendor/assets/vis/module/header.js +24 -0
- data/vendor/assets/vis/module/imports.js +32 -0
- data/vendor/assets/vis/shim.js +252 -0
- data/vendor/assets/vis/timeline/Controller.js +172 -0
- data/vendor/assets/vis/timeline/Range.js +553 -0
- data/vendor/assets/vis/timeline/Stack.js +192 -0
- data/vendor/assets/vis/timeline/TimeStep.js +449 -0
- data/vendor/assets/vis/timeline/Timeline.js +476 -0
- data/vendor/assets/vis/timeline/component/Component.js +148 -0
- data/vendor/assets/vis/timeline/component/ContentPanel.js +113 -0
- data/vendor/assets/vis/timeline/component/CurrentTime.js +101 -0
- data/vendor/assets/vis/timeline/component/CustomTime.js +255 -0
- data/vendor/assets/vis/timeline/component/Group.js +129 -0
- data/vendor/assets/vis/timeline/component/GroupSet.js +546 -0
- data/vendor/assets/vis/timeline/component/ItemSet.js +612 -0
- data/vendor/assets/vis/timeline/component/Panel.js +112 -0
- data/vendor/assets/vis/timeline/component/RootPanel.js +215 -0
- data/vendor/assets/vis/timeline/component/TimeAxis.js +522 -0
- data/vendor/assets/vis/timeline/component/css/currenttime.css +5 -0
- data/vendor/assets/vis/timeline/component/css/customtime.css +6 -0
- data/vendor/assets/vis/timeline/component/css/groupset.css +59 -0
- data/vendor/assets/vis/timeline/component/css/item.css +93 -0
- data/vendor/assets/vis/timeline/component/css/itemset.css +17 -0
- data/vendor/assets/vis/timeline/component/css/panel.css +14 -0
- data/vendor/assets/vis/timeline/component/css/timeaxis.css +41 -0
- data/vendor/assets/vis/timeline/component/css/timeline.css +2 -0
- data/vendor/assets/vis/timeline/component/item/Item.js +81 -0
- data/vendor/assets/vis/timeline/component/item/ItemBox.js +302 -0
- data/vendor/assets/vis/timeline/component/item/ItemPoint.js +237 -0
- data/vendor/assets/vis/timeline/component/item/ItemRange.js +251 -0
- data/vendor/assets/vis/timeline/component/item/ItemRangeOverflow.js +91 -0
- data/vendor/assets/vis/util.js +673 -0
- data/vis-rails.gemspec +47 -0
- metadata +142 -0
@@ -0,0 +1,515 @@
|
|
1
|
+
|
2
|
+
var SelectionMixin = {
|
3
|
+
|
4
|
+
/**
|
5
|
+
* This function can be called from the _doInAllSectors function
|
6
|
+
*
|
7
|
+
* @param object
|
8
|
+
* @param overlappingNodes
|
9
|
+
* @private
|
10
|
+
*/
|
11
|
+
_getNodesOverlappingWith : function(object, overlappingNodes) {
|
12
|
+
var nodes = this.nodes;
|
13
|
+
for (var nodeId in nodes) {
|
14
|
+
if (nodes.hasOwnProperty(nodeId)) {
|
15
|
+
if (nodes[nodeId].isOverlappingWith(object)) {
|
16
|
+
overlappingNodes.push(nodeId);
|
17
|
+
}
|
18
|
+
}
|
19
|
+
}
|
20
|
+
},
|
21
|
+
|
22
|
+
/**
|
23
|
+
* retrieve all nodes overlapping with given object
|
24
|
+
* @param {Object} object An object with parameters left, top, right, bottom
|
25
|
+
* @return {Number[]} An array with id's of the overlapping nodes
|
26
|
+
* @private
|
27
|
+
*/
|
28
|
+
_getAllNodesOverlappingWith : function (object) {
|
29
|
+
var overlappingNodes = [];
|
30
|
+
this._doInAllActiveSectors("_getNodesOverlappingWith",object,overlappingNodes);
|
31
|
+
return overlappingNodes;
|
32
|
+
},
|
33
|
+
|
34
|
+
|
35
|
+
/**
|
36
|
+
* retrieve all nodes in the navigation controls overlapping with given object
|
37
|
+
* @param {Object} object An object with parameters left, top, right, bottom
|
38
|
+
* @return {Number[]} An array with id's of the overlapping nodes
|
39
|
+
* @private
|
40
|
+
*/
|
41
|
+
_getAllNavigationNodesOverlappingWith : function (object) {
|
42
|
+
var overlappingNodes = [];
|
43
|
+
this._doInNavigationSector("_getNodesOverlappingWith",object,overlappingNodes);
|
44
|
+
return overlappingNodes;
|
45
|
+
},
|
46
|
+
|
47
|
+
/**
|
48
|
+
* Return a position object in canvasspace from a single point in screenspace
|
49
|
+
*
|
50
|
+
* @param pointer
|
51
|
+
* @returns {{left: number, top: number, right: number, bottom: number}}
|
52
|
+
* @private
|
53
|
+
*/
|
54
|
+
_pointerToPositionObject : function(pointer) {
|
55
|
+
var x = this._canvasToX(pointer.x);
|
56
|
+
var y = this._canvasToY(pointer.y);
|
57
|
+
|
58
|
+
return {left: x,
|
59
|
+
top: y,
|
60
|
+
right: x,
|
61
|
+
bottom: y};
|
62
|
+
},
|
63
|
+
|
64
|
+
/**
|
65
|
+
* Return a position object in canvasspace from a single point in screenspace
|
66
|
+
*
|
67
|
+
* @param pointer
|
68
|
+
* @returns {{left: number, top: number, right: number, bottom: number}}
|
69
|
+
* @private
|
70
|
+
*/
|
71
|
+
_pointerToScreenPositionObject : function(pointer) {
|
72
|
+
var x = pointer.x;
|
73
|
+
var y = pointer.y;
|
74
|
+
|
75
|
+
return {left: x,
|
76
|
+
top: y,
|
77
|
+
right: x,
|
78
|
+
bottom: y};
|
79
|
+
},
|
80
|
+
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Get the top navigation controls node at the a specific point (like a click)
|
84
|
+
*
|
85
|
+
* @param {{x: Number, y: Number}} pointer
|
86
|
+
* @return {Node | null} node
|
87
|
+
* @private
|
88
|
+
*/
|
89
|
+
_getNavigationNodeAt : function (pointer) {
|
90
|
+
var screenPositionObject = this._pointerToScreenPositionObject(pointer);
|
91
|
+
var overlappingNodes = this._getAllNavigationNodesOverlappingWith(screenPositionObject);
|
92
|
+
if (overlappingNodes.length > 0) {
|
93
|
+
return this.sectors["navigation"]["nodes"][overlappingNodes[overlappingNodes.length - 1]];
|
94
|
+
}
|
95
|
+
else {
|
96
|
+
return null;
|
97
|
+
}
|
98
|
+
},
|
99
|
+
|
100
|
+
|
101
|
+
/**
|
102
|
+
* Get the top node at the a specific point (like a click)
|
103
|
+
*
|
104
|
+
* @param {{x: Number, y: Number}} pointer
|
105
|
+
* @return {Node | null} node
|
106
|
+
* @private
|
107
|
+
*/
|
108
|
+
_getNodeAt : function (pointer) {
|
109
|
+
// we first check if this is an navigation controls element
|
110
|
+
var positionObject = this._pointerToPositionObject(pointer);
|
111
|
+
overlappingNodes = this._getAllNodesOverlappingWith(positionObject);
|
112
|
+
|
113
|
+
// if there are overlapping nodes, select the last one, this is the
|
114
|
+
// one which is drawn on top of the others
|
115
|
+
if (overlappingNodes.length > 0) {
|
116
|
+
return this.nodes[overlappingNodes[overlappingNodes.length - 1]];
|
117
|
+
}
|
118
|
+
else {
|
119
|
+
return null;
|
120
|
+
}
|
121
|
+
},
|
122
|
+
|
123
|
+
|
124
|
+
/**
|
125
|
+
* Place holder. To implement change the _getNodeAt to a _getObjectAt. Have the _getObjectAt call
|
126
|
+
* _getNodeAt and _getEdgesAt, then priortize the selection to user preferences.
|
127
|
+
*
|
128
|
+
* @param pointer
|
129
|
+
* @returns {null}
|
130
|
+
* @private
|
131
|
+
*/
|
132
|
+
_getEdgeAt : function(pointer) {
|
133
|
+
return null;
|
134
|
+
},
|
135
|
+
|
136
|
+
|
137
|
+
/**
|
138
|
+
* Add object to the selection array. The this.selection id array may not be needed.
|
139
|
+
*
|
140
|
+
* @param obj
|
141
|
+
* @private
|
142
|
+
*/
|
143
|
+
_addToSelection : function(obj) {
|
144
|
+
this.selection.push(obj.id);
|
145
|
+
this.selectionObj[obj.id] = obj;
|
146
|
+
},
|
147
|
+
|
148
|
+
|
149
|
+
/**
|
150
|
+
* Remove a single option from selection.
|
151
|
+
*
|
152
|
+
* @param obj
|
153
|
+
* @private
|
154
|
+
*/
|
155
|
+
_removeFromSelection : function(obj) {
|
156
|
+
for (var i = 0; i < this.selection.length; i++) {
|
157
|
+
if (obj.id == this.selection[i]) {
|
158
|
+
this.selection.splice(i,1);
|
159
|
+
break;
|
160
|
+
}
|
161
|
+
}
|
162
|
+
delete this.selectionObj[obj.id];
|
163
|
+
},
|
164
|
+
|
165
|
+
|
166
|
+
/**
|
167
|
+
* Unselect all. The selectionObj is useful for this.
|
168
|
+
*
|
169
|
+
* @param {Boolean} [doNotTrigger] | ignore trigger
|
170
|
+
* @private
|
171
|
+
*/
|
172
|
+
_unselectAll : function(doNotTrigger) {
|
173
|
+
if (doNotTrigger === undefined) {
|
174
|
+
doNotTrigger = false;
|
175
|
+
}
|
176
|
+
|
177
|
+
this.selection = [];
|
178
|
+
for (var objId in this.selectionObj) {
|
179
|
+
if (this.selectionObj.hasOwnProperty(objId)) {
|
180
|
+
this.selectionObj[objId].unselect();
|
181
|
+
}
|
182
|
+
}
|
183
|
+
this.selectionObj = {};
|
184
|
+
|
185
|
+
if (doNotTrigger == false) {
|
186
|
+
this._trigger('select', {
|
187
|
+
nodes: this.getSelection()
|
188
|
+
});
|
189
|
+
}
|
190
|
+
},
|
191
|
+
|
192
|
+
|
193
|
+
/**
|
194
|
+
* Check if anything is selected
|
195
|
+
*
|
196
|
+
* @returns {boolean}
|
197
|
+
* @private
|
198
|
+
*/
|
199
|
+
_selectionIsEmpty : function() {
|
200
|
+
if (this.selection.length == 0) {
|
201
|
+
return true;
|
202
|
+
}
|
203
|
+
else {
|
204
|
+
return false;
|
205
|
+
}
|
206
|
+
},
|
207
|
+
|
208
|
+
|
209
|
+
/**
|
210
|
+
* This is called when someone clicks on a node. either select or deselect it.
|
211
|
+
* If there is an existing selection and we don't want to append to it, clear the existing selection
|
212
|
+
*
|
213
|
+
* @param {Node} node
|
214
|
+
* @param {Boolean} append
|
215
|
+
* @param {Boolean} [doNotTrigger] | ignore trigger
|
216
|
+
* @private
|
217
|
+
*/
|
218
|
+
_selectNode : function(node, append, doNotTrigger) {
|
219
|
+
if (doNotTrigger === undefined) {
|
220
|
+
doNotTrigger = false;
|
221
|
+
}
|
222
|
+
|
223
|
+
if (this._selectionIsEmpty() == false && append == false) {
|
224
|
+
this._unselectAll(true);
|
225
|
+
}
|
226
|
+
|
227
|
+
|
228
|
+
if (node.selected == false) {
|
229
|
+
node.select();
|
230
|
+
this._addToSelection(node);
|
231
|
+
}
|
232
|
+
else {
|
233
|
+
node.unselect();
|
234
|
+
this._removeFromSelection(node);
|
235
|
+
}
|
236
|
+
if (doNotTrigger == false) {
|
237
|
+
this._trigger('select', {
|
238
|
+
nodes: this.getSelection()
|
239
|
+
});
|
240
|
+
}
|
241
|
+
},
|
242
|
+
|
243
|
+
|
244
|
+
/**
|
245
|
+
* handles the selection part of the touch, only for navigation controls elements;
|
246
|
+
* Touch is triggered before tap, also before hold. Hold triggers after a while.
|
247
|
+
* This is the most responsive solution
|
248
|
+
*
|
249
|
+
* @param {Object} pointer
|
250
|
+
* @private
|
251
|
+
*/
|
252
|
+
_handleTouch : function(pointer) {
|
253
|
+
if (this.constants.navigation.enabled == true) {
|
254
|
+
var node = this._getNavigationNodeAt(pointer);
|
255
|
+
if (node != null) {
|
256
|
+
if (this[node.triggerFunction] !== undefined) {
|
257
|
+
this[node.triggerFunction]();
|
258
|
+
}
|
259
|
+
}
|
260
|
+
}
|
261
|
+
},
|
262
|
+
|
263
|
+
|
264
|
+
/**
|
265
|
+
* handles the selection part of the tap;
|
266
|
+
*
|
267
|
+
* @param {Object} pointer
|
268
|
+
* @private
|
269
|
+
*/
|
270
|
+
_handleTap : function(pointer) {
|
271
|
+
var node = this._getNodeAt(pointer);
|
272
|
+
if (node != null) {
|
273
|
+
this._selectNode(node,false);
|
274
|
+
}
|
275
|
+
else {
|
276
|
+
this._unselectAll();
|
277
|
+
}
|
278
|
+
this._redraw();
|
279
|
+
},
|
280
|
+
|
281
|
+
|
282
|
+
/**
|
283
|
+
* handles the selection part of the double tap and opens a cluster if needed
|
284
|
+
*
|
285
|
+
* @param {Object} pointer
|
286
|
+
* @private
|
287
|
+
*/
|
288
|
+
_handleDoubleTap : function(pointer) {
|
289
|
+
var node = this._getNodeAt(pointer);
|
290
|
+
if (node != null && node !== undefined) {
|
291
|
+
// we reset the areaCenter here so the opening of the node will occur
|
292
|
+
this.areaCenter = {"x" : this._canvasToX(pointer.x),
|
293
|
+
"y" : this._canvasToY(pointer.y)};
|
294
|
+
this.openCluster(node);
|
295
|
+
}
|
296
|
+
},
|
297
|
+
|
298
|
+
|
299
|
+
/**
|
300
|
+
* Handle the onHold selection part
|
301
|
+
*
|
302
|
+
* @param pointer
|
303
|
+
* @private
|
304
|
+
*/
|
305
|
+
_handleOnHold : function(pointer) {
|
306
|
+
var node = this._getNodeAt(pointer);
|
307
|
+
if (node != null) {
|
308
|
+
this._selectNode(node,true);
|
309
|
+
}
|
310
|
+
this._redraw();
|
311
|
+
},
|
312
|
+
|
313
|
+
|
314
|
+
/**
|
315
|
+
* handle the onRelease event. These functions are here for the navigation controls module.
|
316
|
+
*
|
317
|
+
* @private
|
318
|
+
*/
|
319
|
+
_handleOnRelease : function() {
|
320
|
+
this.xIncrement = 0;
|
321
|
+
this.yIncrement = 0;
|
322
|
+
this.zoomIncrement = 0;
|
323
|
+
this._unHighlightAll();
|
324
|
+
},
|
325
|
+
|
326
|
+
|
327
|
+
|
328
|
+
/**
|
329
|
+
*
|
330
|
+
* retrieve the currently selected nodes
|
331
|
+
* @return {Number[] | String[]} selection An array with the ids of the
|
332
|
+
* selected nodes.
|
333
|
+
*/
|
334
|
+
getSelection : function() {
|
335
|
+
return this.selection.concat([]);
|
336
|
+
},
|
337
|
+
|
338
|
+
/**
|
339
|
+
*
|
340
|
+
* retrieve the currently selected nodes as objects
|
341
|
+
* @return {Objects} selection An array with the ids of the
|
342
|
+
* selected nodes.
|
343
|
+
*/
|
344
|
+
getSelectionObjects : function() {
|
345
|
+
return this.selectionObj;
|
346
|
+
},
|
347
|
+
|
348
|
+
/**
|
349
|
+
* // TODO: rework this function, it is from the old system
|
350
|
+
*
|
351
|
+
* select zero or more nodes
|
352
|
+
* @param {Number[] | String[]} selection An array with the ids of the
|
353
|
+
* selected nodes.
|
354
|
+
*/
|
355
|
+
setSelection : function(selection) {
|
356
|
+
var i, iMax, id;
|
357
|
+
|
358
|
+
if (!selection || (selection.length == undefined))
|
359
|
+
throw 'Selection must be an array with ids';
|
360
|
+
|
361
|
+
// first unselect any selected node
|
362
|
+
this._unselectAll(true);
|
363
|
+
|
364
|
+
for (i = 0, iMax = selection.length; i < iMax; i++) {
|
365
|
+
id = selection[i];
|
366
|
+
|
367
|
+
var node = this.nodes[id];
|
368
|
+
if (!node) {
|
369
|
+
throw new RangeError('Node with id "' + id + '" not found');
|
370
|
+
}
|
371
|
+
this._selectNode(node,true,true);
|
372
|
+
}
|
373
|
+
|
374
|
+
this.redraw();
|
375
|
+
},
|
376
|
+
|
377
|
+
|
378
|
+
/**
|
379
|
+
* TODO: rework this function, it is from the old system
|
380
|
+
*
|
381
|
+
* Validate the selection: remove ids of nodes which no longer exist
|
382
|
+
* @private
|
383
|
+
*/
|
384
|
+
_updateSelection : function () {
|
385
|
+
var i = 0;
|
386
|
+
while (i < this.selection.length) {
|
387
|
+
var nodeId = this.selection[i];
|
388
|
+
if (!this.nodes.hasOwnProperty(nodeId)) {
|
389
|
+
this.selection.splice(i, 1);
|
390
|
+
delete this.selectionObj[nodeId];
|
391
|
+
}
|
392
|
+
else {
|
393
|
+
i++;
|
394
|
+
}
|
395
|
+
}
|
396
|
+
}
|
397
|
+
|
398
|
+
|
399
|
+
/**
|
400
|
+
* Unselect selected nodes. If no selection array is provided, all nodes
|
401
|
+
* are unselected
|
402
|
+
* @param {Object[]} selection Array with selection objects, each selection
|
403
|
+
* object has a parameter row. Optional
|
404
|
+
* @param {Boolean} triggerSelect If true (default), the select event
|
405
|
+
* is triggered when nodes are unselected
|
406
|
+
* @return {Boolean} changed True if the selection is changed
|
407
|
+
* @private
|
408
|
+
*/
|
409
|
+
/* _unselectNodes : function(selection, triggerSelect) {
|
410
|
+
var changed = false;
|
411
|
+
var i, iMax, id;
|
412
|
+
|
413
|
+
if (selection) {
|
414
|
+
// remove provided selections
|
415
|
+
for (i = 0, iMax = selection.length; i < iMax; i++) {
|
416
|
+
id = selection[i];
|
417
|
+
if (this.nodes.hasOwnProperty(id)) {
|
418
|
+
this.nodes[id].unselect();
|
419
|
+
}
|
420
|
+
var j = 0;
|
421
|
+
while (j < this.selection.length) {
|
422
|
+
if (this.selection[j] == id) {
|
423
|
+
this.selection.splice(j, 1);
|
424
|
+
changed = true;
|
425
|
+
}
|
426
|
+
else {
|
427
|
+
j++;
|
428
|
+
}
|
429
|
+
}
|
430
|
+
}
|
431
|
+
}
|
432
|
+
else if (this.selection && this.selection.length) {
|
433
|
+
// remove all selections
|
434
|
+
for (i = 0, iMax = this.selection.length; i < iMax; i++) {
|
435
|
+
id = this.selection[i];
|
436
|
+
if (this.nodes.hasOwnProperty(id)) {
|
437
|
+
this.nodes[id].unselect();
|
438
|
+
}
|
439
|
+
changed = true;
|
440
|
+
}
|
441
|
+
this.selection = [];
|
442
|
+
}
|
443
|
+
|
444
|
+
if (changed && (triggerSelect == true || triggerSelect == undefined)) {
|
445
|
+
// fire the select event
|
446
|
+
this._trigger('select', {
|
447
|
+
nodes: this.getSelection()
|
448
|
+
});
|
449
|
+
}
|
450
|
+
|
451
|
+
return changed;
|
452
|
+
},
|
453
|
+
*/
|
454
|
+
/**
|
455
|
+
* select all nodes on given location x, y
|
456
|
+
* @param {Array} selection an array with node ids
|
457
|
+
* @param {boolean} append If true, the new selection will be appended to the
|
458
|
+
* current selection (except for duplicate entries)
|
459
|
+
* @return {Boolean} changed True if the selection is changed
|
460
|
+
* @private
|
461
|
+
*/
|
462
|
+
/* _selectNodes : function(selection, append) {
|
463
|
+
var changed = false;
|
464
|
+
var i, iMax;
|
465
|
+
|
466
|
+
// TODO: the selectNodes method is a little messy, rework this
|
467
|
+
|
468
|
+
// check if the current selection equals the desired selection
|
469
|
+
var selectionAlreadyThere = true;
|
470
|
+
if (selection.length != this.selection.length) {
|
471
|
+
selectionAlreadyThere = false;
|
472
|
+
}
|
473
|
+
else {
|
474
|
+
for (i = 0, iMax = Math.min(selection.length, this.selection.length); i < iMax; i++) {
|
475
|
+
if (selection[i] != this.selection[i]) {
|
476
|
+
selectionAlreadyThere = false;
|
477
|
+
break;
|
478
|
+
}
|
479
|
+
}
|
480
|
+
}
|
481
|
+
if (selectionAlreadyThere) {
|
482
|
+
return changed;
|
483
|
+
}
|
484
|
+
|
485
|
+
if (append == undefined || append == false) {
|
486
|
+
// first deselect any selected node
|
487
|
+
var triggerSelect = false;
|
488
|
+
changed = this._unselectNodes(undefined, triggerSelect);
|
489
|
+
}
|
490
|
+
|
491
|
+
for (i = 0, iMax = selection.length; i < iMax; i++) {
|
492
|
+
// add each of the new selections, but only when they are not duplicate
|
493
|
+
var id = selection[i];
|
494
|
+
var isDuplicate = (this.selection.indexOf(id) != -1);
|
495
|
+
if (!isDuplicate) {
|
496
|
+
this.nodes[id].select();
|
497
|
+
this.selection.push(id);
|
498
|
+
changed = true;
|
499
|
+
}
|
500
|
+
}
|
501
|
+
|
502
|
+
if (changed) {
|
503
|
+
// fire the select event
|
504
|
+
this._trigger('select', {
|
505
|
+
nodes: this.getSelection()
|
506
|
+
});
|
507
|
+
}
|
508
|
+
|
509
|
+
return changed;
|
510
|
+
},
|
511
|
+
*/
|
512
|
+
};
|
513
|
+
|
514
|
+
|
515
|
+
|