mindreframer-riemann-dash 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/.gitignore +8 -0
  2. data/Gemfile +7 -0
  3. data/Gemfile.lock +52 -0
  4. data/LICENSE +21 -0
  5. data/README.markdown +52 -0
  6. data/Rakefile.rb +11 -0
  7. data/bin/riemann-dash +7 -0
  8. data/example/config.rb +17 -0
  9. data/lib/riemann/dash.rb +5 -0
  10. data/lib/riemann/dash/app.rb +32 -0
  11. data/lib/riemann/dash/config.rb +154 -0
  12. data/lib/riemann/dash/controller/css.rb +5 -0
  13. data/lib/riemann/dash/controller/index.rb +20 -0
  14. data/lib/riemann/dash/public/clock.js +45 -0
  15. data/lib/riemann/dash/public/dash.js +287 -0
  16. data/lib/riemann/dash/public/format.js +24 -0
  17. data/lib/riemann/dash/public/jquery-1.7.2.min.js +4 -0
  18. data/lib/riemann/dash/public/jquery-ui-1.9.0.custom.min.js +6 -0
  19. data/lib/riemann/dash/public/jquery.json-2.2.min.js +31 -0
  20. data/lib/riemann/dash/public/jquery.quickfit.js +144 -0
  21. data/lib/riemann/dash/public/jquery.simplemodal.1.4.3.min.js +26 -0
  22. data/lib/riemann/dash/public/keys.js +46 -0
  23. data/lib/riemann/dash/public/mustache.js +597 -0
  24. data/lib/riemann/dash/public/persistence.js +30 -0
  25. data/lib/riemann/dash/public/profile.js +33 -0
  26. data/lib/riemann/dash/public/subs.js +164 -0
  27. data/lib/riemann/dash/public/toastr.css +174 -0
  28. data/lib/riemann/dash/public/toastr.js +207 -0
  29. data/lib/riemann/dash/public/toolbar.js +217 -0
  30. data/lib/riemann/dash/public/underscore-min.js +5 -0
  31. data/lib/riemann/dash/public/util.js +34 -0
  32. data/lib/riemann/dash/public/vendor/smoothie.js +374 -0
  33. data/lib/riemann/dash/public/view.js +704 -0
  34. data/lib/riemann/dash/public/views/gauge.js +76 -0
  35. data/lib/riemann/dash/public/views/grid.js +279 -0
  36. data/lib/riemann/dash/public/views/help.js +28 -0
  37. data/lib/riemann/dash/public/views/timeseries.js +107 -0
  38. data/lib/riemann/dash/public/views/title.js +35 -0
  39. data/lib/riemann/dash/public/x.png +0 -0
  40. data/lib/riemann/dash/rack/static.rb +16 -0
  41. data/lib/riemann/dash/version.rb +4 -0
  42. data/lib/riemann/dash/views/css.scss +393 -0
  43. data/lib/riemann/dash/views/index.erubis +203 -0
  44. data/lib/riemann/dash/views/layout.erubis +21 -0
  45. data/riemann-dash.gemspec +28 -0
  46. data/sh/c +1 -0
  47. data/sh/env.rb +2 -0
  48. data/sh/test +1 -0
  49. data/test/config_test.rb +106 -0
  50. data/test/fixtures/config/basic_config.rb +2 -0
  51. data/test/fixtures/config/ws_config.rb +1 -0
  52. data/test/fixtures/ws_config/dummy_config.json +1 -0
  53. data/test/fixtures/ws_config/pretty_printed_config.json +6 -0
  54. data/test/test_helper.rb +10 -0
  55. metadata +202 -0
@@ -0,0 +1,704 @@
1
+ var view = (function() {
2
+ var types = {};
3
+ var focused = null;
4
+ var focusOverlay = $('<div class="focusOverlay"></div>');
5
+ $('body').append(focusOverlay);
6
+
7
+ // Unfocus all views.
8
+ var unfocus = function() {
9
+ if (focused) {
10
+ focused.unfocus();
11
+ }
12
+ }
13
+
14
+ function createObject(parent) {
15
+ function TempClass() {}
16
+ TempClass.prototype = parent;
17
+ var child = new TempClass();
18
+ return child;
19
+ }
20
+
21
+ function inherit(sup, sub) {
22
+ var newSubPrototype = createObject(sup.prototype);
23
+ newSubPrototype.constructor = sub;
24
+ sub.prototype = newSubPrototype;
25
+ }
26
+
27
+ // Create *some* type of view from json
28
+ var reify = function(json) {
29
+ var t = types[json.type];
30
+ return(new t(json));
31
+ }
32
+
33
+ // Initialize keybindings
34
+ function setKeyBindings() {
35
+ var focusedBindings = {
36
+ // left
37
+ 37: function(ev) {
38
+ if (ev.ctrlKey === true) {
39
+ focused.split('HStack', -1);
40
+ } else {
41
+ focused.moveHorizontal(-1);
42
+ }
43
+ },
44
+
45
+ // up
46
+ 38: function(ev) {
47
+ if (ev.ctrlKey === true) {
48
+ focused.split('VStack', -1);
49
+ } else {
50
+ focused.moveVertical(-1);
51
+ }
52
+ },
53
+
54
+ // right
55
+ 39: function(ev) {
56
+ if (ev.ctrlKey === true) {
57
+ focused.split('HStack', 1);
58
+ } else {
59
+ focused.moveHorizontal(1);
60
+ }
61
+ },
62
+
63
+ // down
64
+ 40: function(ev) {
65
+ if (ev.ctrlKey === true) {
66
+ focused.split('VStack', 1);
67
+ } else {
68
+ focused.moveVertical(1);
69
+ }
70
+ },
71
+
72
+ 27: function() { focused.unfocus() }, // escape
73
+ 33: function() { if (focused.parent) { // pgup
74
+ focused.parent.focus();
75
+ } },
76
+ 46: function() { focused.delete() }, // delete
77
+ 68: function() { focused.delete() }, // d
78
+
79
+ 69: function() { focused.edit() }, // e
80
+ 86: function() { focused.split('VStack', 1) }, // v
81
+ 72: function() { focused.split('HStack', 1) }, // h
82
+
83
+ 187: function() { focused.grow(); }, // +
84
+ 189: function() { focused.shrink(); } // -
85
+
86
+ };
87
+
88
+ var bindings = {};
89
+
90
+ // Set up focused bindings.
91
+ for (code in focusedBindings) {
92
+ (function(f) {
93
+ keys.bind(code, function(ev) {
94
+ if (focused) { f(ev) }
95
+ });
96
+ })(focusedBindings[code]);
97
+ }
98
+
99
+ // Set up unfocused bindings.
100
+ for (code in bindings) {
101
+ (function(f) {
102
+ keys.bind(code, function(ev) {
103
+ if (! focused) { f(ev) }
104
+ });
105
+ })(bindings[code]);
106
+ }
107
+ }
108
+ setKeyBindings()
109
+
110
+ // View ////////////////////////////////////////////////////////////////////
111
+
112
+ var View = function(json) {
113
+ this.type = json.type;
114
+ this.el = $('<div class="view">');
115
+ this.weight = json.weight || 1;
116
+ // this.el.css('background', 'rgb(' +
117
+ // Math.floor(Math.random() * 256) + ',' +
118
+ // Math.floor(Math.random() * 256) + ',' +
119
+ // Math.floor(Math.random() * 256) + ')');
120
+
121
+ var self = this;
122
+ this.clickFocusable = true;
123
+ this.el.click(function() {
124
+ if (self.clickFocusable) {
125
+ self.focus();
126
+ }
127
+ });
128
+ };
129
+ types.View = View;
130
+
131
+ View.prototype.width = function(w) {
132
+ if (w !== undefined) {
133
+ return this.el.width(w);
134
+ } else {
135
+ return this.el.width();
136
+ }
137
+ };
138
+
139
+ View.prototype.height = function(h) {
140
+ if (h !== undefined) {
141
+ return this.el.height(h);
142
+ } else {
143
+ return this.el.height();
144
+ }
145
+ };
146
+
147
+ View.prototype.top = function(t) {
148
+ if(t !== undefined) {
149
+ return this.el.css("top", t);
150
+ } else {
151
+ return this.el.css("top");
152
+ }
153
+ };
154
+
155
+ View.prototype.left = function(l) {
156
+ if (l !== undefined) {
157
+ return this.el.css("left", l);
158
+ } else {
159
+ return this.el.css("left");
160
+ }
161
+ };
162
+
163
+ View.prototype.reflow = function() {
164
+ };
165
+
166
+ View.prototype.grow = function() {
167
+ this.weight *= 2;
168
+ this.parent.reflow();
169
+ focused.refocus();
170
+ };
171
+
172
+ View.prototype.shrink = function() {
173
+ this.weight *= 0.5;
174
+ this.parent.reflow();
175
+ focused.refocus();
176
+ };
177
+
178
+ // Replace this view with a different one. Returns replacement.
179
+ View.prototype.replace = function(replacement) {
180
+ console.log("Replacing", this, "with", replacement);
181
+ console.log("Parent is", this.parent);
182
+ var p = this.parent;
183
+
184
+ if (p == null) {
185
+ throw "Sorry, can't replace top-level views.";
186
+ }
187
+
188
+ if (p.replaceChild == null) {
189
+ throw "Sorry, can't replace unless parent can replace child.";
190
+ }
191
+
192
+ p.replaceChild(this, replacement);
193
+
194
+ return replacement;
195
+ }
196
+
197
+ // Unfocus this view and delete it permanently.
198
+ View.prototype.delete = function() {
199
+ this.unfocus();
200
+ var p = this.parent;
201
+ if (p) {
202
+ if (p.removeChild) {
203
+ p.removeChild(this);
204
+ }
205
+ p.reflow();
206
+ }
207
+ if (this.el) {
208
+ this.el.remove();
209
+ this.el = null;
210
+ }
211
+ }
212
+
213
+ // Remove us from our parent, and have them reflow.
214
+ View.prototype.removeFromParent = function() {
215
+ this.unfocus();
216
+ var oldParent = this.parent;
217
+ if (oldParent && oldParent.removeChild) {
218
+ oldParent.removeChild(this);
219
+ oldParent.reflow();
220
+ }
221
+ }
222
+
223
+ // Split in a parent stack that already exists. i is either -1 (place the
224
+ // new view before us) or +1 (place the new view after us).
225
+ View.prototype.splitParentStack = function(i) {
226
+ console.log("Split parent");
227
+ if (i === null) { i = 0 }
228
+ var index = this.parent.indexOf(this) - Math.min(i, 0);
229
+ console.log(this.parent.indexOf(this), index);
230
+ this.parent.insertChild(
231
+ index,
232
+ reify({type: 'View'})
233
+ );
234
+ this.parent.reflow();
235
+ this.refocus();
236
+ }
237
+
238
+ // Split into a stackType. i is either -1 (place the new view before us) or
239
+ // +1 (place the new view after us.
240
+ View.prototype.split = function(stackType, i) {
241
+ var parent = this.parent;
242
+ if (parent) {
243
+ if (parent.type === stackType) {
244
+ this.splitParentStack(i);
245
+ } else if (parent.replaceChild) {
246
+ // Replace self with stack
247
+ var stack = reify({
248
+ type: stackType,
249
+ weight: this.weight
250
+ });
251
+ parent.replaceChild(this, stack);
252
+
253
+ // Add self to stack
254
+ this.weight = 1;
255
+ if (i === -1) {
256
+ stack.addChild(this);
257
+ stack.addChild(new View({type: 'View'}));
258
+ } else {
259
+ stack.addChild(new View({type: 'View'}));
260
+ stack.addChild(this);
261
+ }
262
+
263
+ // Redraw
264
+ parent.reflow();
265
+ this.refocus();
266
+ } else {
267
+ console.log("Can't split: parent can't replace child.");
268
+ }
269
+ } else {
270
+ console.log("Can't split: no parent");
271
+ }
272
+ }
273
+
274
+ // Redraw the focus indicator
275
+ View.prototype.refocus = function() {
276
+ focusOverlay.width(this.el.width());
277
+ focusOverlay.height(this.el.height());
278
+ focusOverlay.css('top', this.el.offset().top);
279
+ focusOverlay.css('left', this.el.offset().left);
280
+ focusOverlay.show();
281
+ }
282
+
283
+ // Focus this view
284
+ View.prototype.focus = function() {
285
+ if (focused !== null) {
286
+ focused.unfocus();
287
+ }
288
+ this.el.addClass("focused");
289
+ this.refocus();
290
+ focused = this;
291
+ }
292
+
293
+ // Unfocus this view
294
+ View.prototype.unfocus = function() {
295
+ focusOverlay.hide();
296
+ if (this.el) {
297
+ this.el.removeClass("focused");
298
+ }
299
+ if (focused === this) {
300
+ focused = null;
301
+ }
302
+ }
303
+
304
+ // Returns the nearest parent hstack
305
+ View.prototype.enclosingHStack = function() {
306
+ try {
307
+ if (this.parent.isHStack) {
308
+ return {
309
+ i: this.parent.indexOf(this),
310
+ stack: this.parent
311
+ };
312
+ } else {
313
+ return this.parent.enclosingHStack();
314
+ }
315
+ } catch(e) {
316
+ return null;
317
+ }
318
+ }
319
+
320
+ // Returns the nearest parent vstack
321
+ View.prototype.enclosingVStack = function() {
322
+ try {
323
+ if (this.parent.isVStack) {
324
+ return {
325
+ i: this.parent.indexOf(this),
326
+ stack: this.parent
327
+ };
328
+ } else {
329
+ return this.parent.enclosingVStack();
330
+ }
331
+ } catch(e) {
332
+ return null;
333
+ }
334
+ }
335
+
336
+ // Move a view horizontally, by delta -1 = left, +1 = right).
337
+ View.prototype.move = function(parentFinder, delta) {
338
+ var enclosing = this[parentFinder]();
339
+
340
+ if (enclosing) {
341
+ // Get the stack we'll move in to, and our (possibly our parent's) index
342
+ // in it.
343
+ var stack = enclosing.stack;
344
+ var i = enclosing.i;
345
+ console.log("I am", this);
346
+ console.log("Enclosing is", stack, i);
347
+
348
+ var newI = i + delta;
349
+ if (newI < 0) {
350
+ console.log("Sorry, at start.");
351
+ newI = 0;
352
+ } else if (newI >= stack.children.length) {
353
+ console.log("Sorry, at end.");
354
+ newI = stack.children.length;
355
+ } else {
356
+ // What's there now?
357
+ var neighbor = stack.children[newI];
358
+ if (neighbor && neighbor.addChild) {
359
+ // We can enter our neighbor
360
+ this.removeFromParent();
361
+ neighbor.addChild(this);
362
+ neighbor.reflow();
363
+ this.focus();
364
+ return;
365
+ }
366
+ }
367
+
368
+ if (this.parent === stack &&
369
+ stack.children.length === 1) {
370
+ // An special case: we can't leave our parent and then re-enter it,
371
+ // because removeFromParent() would *destroy* our parent after we
372
+ // left. Nothing *needs* to happen, so we return immediately.
373
+ return;
374
+ }
375
+
376
+ // We're moving to a new position inside the enclosing stack.
377
+ this.removeFromParent();
378
+ stack.insertChild(newI, this);
379
+ stack.reflow();
380
+ this.focus();
381
+ } else {
382
+ console.log("Sorry, not yet");
383
+ }
384
+ }
385
+
386
+ View.prototype.moveHorizontal = function(delta) {
387
+ this.move('enclosingHStack', delta);
388
+ }
389
+
390
+ View.prototype.moveVertical = function(delta) {
391
+ this.move('enclosingVStack', delta);
392
+ }
393
+
394
+ // A jquery node inserted into the edit modal, for changing the
395
+ // properties of a view.
396
+ View.prototype.editForm = function() {
397
+ }
398
+
399
+ // Show a dialog for changing this view.
400
+ View.prototype.edit = function() {
401
+ var dialog = $('<div><h1></h1><form>' +
402
+ '<select name="type" />' +
403
+ '<div class="edit-form"></div>' +
404
+ '<button name="apply">Apply</button>' +
405
+ '</form></div>');
406
+ dialog.find('h1').text("Edit " + this.type);
407
+
408
+ // Build type selector.
409
+ var typeSelector = dialog.find('select[name=type]');
410
+ var editForm = dialog.find('.edit-form');
411
+ var type;
412
+ for (type in types) {
413
+ if (type == this.json().type) {
414
+ typeSelector.append("<option selected>" + type + "</option>");
415
+ } else {
416
+ typeSelector.append("<option>" + type + "</option>");
417
+ }
418
+ }
419
+
420
+ // The serialized representation of a view that we're editing.
421
+ // Carried between various view types; when Apply is clicked, projected
422
+ // into an actual view.
423
+ var replacementJson = this.json();
424
+
425
+ // Update the replacement structure with the current values.
426
+ var mergeCurrentValues = function() {
427
+ dialog.find('form').first().serializeArray().forEach(function(input) {
428
+ replacementJson[input.name] = input.value;
429
+ });
430
+ }
431
+
432
+ // Add the edit form itself.
433
+ editForm.append(reify(replacementJson).editForm());
434
+
435
+ // Handle type changes.
436
+ typeSelector.change(function() {
437
+ // Read fields
438
+ mergeCurrentValues();
439
+
440
+ // Replace edit form
441
+ editForm.empty();
442
+ editForm.append(reify(replacementJson).editForm());
443
+ });
444
+
445
+ // Apply button.
446
+ var me = this;
447
+ dialog.find('button[name=apply]').click(function(e) {
448
+ // Don't submit the form.
449
+ e.preventDefault();
450
+
451
+ // Read fields
452
+ mergeCurrentValues();
453
+
454
+ // Replace view.
455
+ replacement = me.replace(reify(replacementJson));
456
+ replacement.parent.reflow();
457
+ me.delete();
458
+ replacement.focus();
459
+
460
+ // Close dialog.
461
+ $.modal.close();
462
+ });
463
+
464
+ // Show dialog.
465
+ keys.disable();
466
+ dialog.modal({onClose: function() {
467
+ keys.enable();
468
+ $.modal.close();
469
+ }});
470
+ }
471
+
472
+ // Serialize this view to JSON.
473
+ View.prototype.json = function() {
474
+ return {type: 'View', weight: this.weight};
475
+ }
476
+
477
+ // Balloon /////////////////////////////////////////////////////////////////
478
+
479
+ var Balloon = function(json) {
480
+ View.call(this, json);
481
+ this.container = json.container;
482
+ this.clickFocusable = false;
483
+ this.el.detach();
484
+ this.el.appendTo(this.container);
485
+
486
+ this.child = reify(json.child);
487
+ this.child.parent = this;
488
+ this.el.append(this.child.el);
489
+ }
490
+ inherit(View, Balloon);
491
+ types.Balloon = Balloon;
492
+
493
+ Balloon.prototype.json = function() {
494
+ return $.extend(View.prototype.json.call(this), {
495
+ type: 'Balloon',
496
+ child: this.child.json()
497
+ });
498
+ }
499
+
500
+ Balloon.prototype.replaceChild = function(v1, v2) {
501
+ this.child.parent = null;
502
+ this.child.el.detach();
503
+
504
+ this.child = v2;
505
+ v2.parent = this;
506
+ this.el.append(this.child.el);
507
+ }
508
+
509
+ Balloon.prototype.removeChild = function(c) {
510
+ this.child = null;
511
+ }
512
+
513
+ Balloon.prototype.reflow = function() {
514
+ var p = this.container;
515
+ this.width(p.width());
516
+ this.height(p.height());
517
+ if (this.child) {
518
+ this.child.width(p.width());
519
+ this.child.height(p.height());
520
+ this.child.reflow();
521
+ }
522
+ }
523
+
524
+ Balloon.prototype.delete = function() {
525
+ this.child.delete();
526
+ View.prototype.delete.call(this);
527
+ }
528
+
529
+ // Fullscreen //////////////////////////////////////////////////////////////
530
+
531
+ var Fullscreen = function(json) {
532
+ Balloon.call(this, json);
533
+ this.el.detach();
534
+ this.el.css('position', 'fixed');
535
+ this.el.appendTo($('body'));
536
+ this.parent = null;
537
+ }
538
+ inherit(Balloon, Fullscreen);
539
+ types.Fullscreen = Fullscreen;
540
+
541
+ Fullscreen.prototype.json = function() {
542
+ return $.extend(
543
+ Balloon.prototype.json.call(this),
544
+ {type: 'Fullscreen'});
545
+ }
546
+
547
+ Fullscreen.prototype.reflow = function() {
548
+ var p = $(window);
549
+ this.width(p.width());
550
+ this.height(p.height());
551
+ this.child.width(p.width());
552
+ this.child.height(p.height());
553
+ this.child.reflow();
554
+ }
555
+
556
+ // Stack ///////////////////////////////////////////////////////////////////
557
+
558
+ var Stack = function(json) {
559
+ View.call(this, json);
560
+ this.clickFocusable = false;
561
+ this.children = [];
562
+ var self = this;
563
+ if (json.children !== undefined) {
564
+ json.children.map(reify).forEach(function(c) {
565
+ self.addChild(c);
566
+ });
567
+ }
568
+ };
569
+ inherit(View, Stack);
570
+
571
+ Stack.prototype.json = function() {
572
+ return $.extend(View.prototype.json.call(this), {
573
+ type: 'Stack',
574
+ children: $.map(this.children, function(x) { return x.json(); })
575
+ });
576
+ }
577
+
578
+ Stack.prototype.addChild = function(view) {
579
+ view.parent = this;
580
+ this.children.push(view);
581
+ this.el.append(view.el);
582
+ }
583
+
584
+ Stack.prototype.insertChild = function(i, view) {
585
+ view.parent = this;
586
+ this.children.splice(i, 0, view);
587
+ this.el.append(view.el);
588
+ }
589
+
590
+ // Replace v1 with v2
591
+ Stack.prototype.replaceChild = function(v1, v2) {
592
+ v1.parent = null;
593
+ v2.parent = this;
594
+ v1.el.detach();
595
+ var i = this.children.indexOf(v1);
596
+ this.children[i] = v2;
597
+ this.el.append(v2.el);
598
+ }
599
+
600
+ Stack.prototype.removeChild = function(view) {
601
+ view.parent = null;
602
+ var i = this.children.indexOf(view);
603
+ view.el.detach();
604
+ this.children.splice(i, 1);
605
+
606
+ // Delete self if empty
607
+ if (this.children.length === 0) {
608
+ this.delete();
609
+ }
610
+ }
611
+
612
+ Stack.prototype.indexOf = function(child) {
613
+ return this.children.indexOf(child);
614
+ }
615
+
616
+ Stack.prototype.delete = function() {
617
+ this.children.slice().forEach(function(c) {
618
+ c.delete();
619
+ });
620
+ View.prototype.delete.call(this);
621
+ }
622
+
623
+ // HStack //////////////////////////////////////////////////////////////////
624
+
625
+ var HStack = function(json) {
626
+ Stack.call(this, json);
627
+ };
628
+ inherit(Stack, HStack);
629
+ types.HStack = HStack;
630
+
631
+ HStack.prototype.json = function() {
632
+ return $.extend(Stack.prototype.json.call(this), {type: 'HStack'});
633
+ }
634
+
635
+ HStack.prototype.isHStack = true;
636
+
637
+ HStack.prototype.reflow = function() {
638
+ if (this.el === null) {
639
+ // We're gone.
640
+ return;
641
+ }
642
+
643
+ var width = this.width();
644
+ var height = this.height();
645
+ var left = 0;
646
+ var weightSum = this.children.reduce(function(acc, c) {
647
+ return acc + c.weight;
648
+ }, 0);
649
+
650
+ this.children.forEach(function(c) {
651
+ c.height(height);
652
+ c.width(width * (c.weight / weightSum));
653
+ c.top(0);
654
+ c.left(left);
655
+ left = left + c.width();
656
+ c.reflow();
657
+ });
658
+ }
659
+
660
+ // VStack //////////////////////////////////////////////////////////////////
661
+
662
+ var VStack = function(json) {
663
+ Stack.call(this, json);
664
+ };
665
+ inherit(Stack, VStack);
666
+ types.VStack = VStack;
667
+
668
+ VStack.prototype.json = function() {
669
+ return $.extend(Stack.prototype.json.call(this), {type: 'VStack'});
670
+ }
671
+
672
+ VStack.prototype.isVStack = true;
673
+
674
+ VStack.prototype.reflow = function() {
675
+ if (this.el === null) {
676
+ // We're gone.
677
+ return;
678
+ }
679
+
680
+ var width = this.width();
681
+ var height = this.height();
682
+ var top = 0;
683
+ var weightSum = this.children.reduce(function(acc, c) {
684
+ return acc + c.weight;
685
+ }, 0);
686
+
687
+ this.children.forEach(function(c) {
688
+ c.width(width);
689
+ c.height(height * (c.weight / weightSum));
690
+ c.left(0);
691
+ c.top(top);
692
+ top = top + c.height();
693
+ c.reflow();
694
+ });
695
+ };
696
+
697
+ return $.extend({
698
+ types: types,
699
+ reify: reify,
700
+ inherit: inherit,
701
+ unfocus: unfocus,
702
+ focused: function() { return focused; }
703
+ }, types);
704
+ })();