mindreframer-riemann-dash 0.2.3

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.
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
+ })();