Free cookie consent management tool by TermsFeed Policy Generator

source: branches/OaaS/HeuristicLab.Services.Optimization.Web/Content/experiment.view.js @ 9324

Last change on this file since 9324 was 9324, checked in by fschoepp, 12 years ago

#1888:

  • DAL: Added a Delete method which deletes by experiment id.
  • HL DataTables will now be transposed and mapped as double[ROWS][COLUMNS] (transposed)
  • JS: Moved all classes into "modules" to prevent namespace pollution (using OAAS_MODEL for model classes, OAAS_VIEW for views and OAAS_CONTROLLER for controllers)
  • JS: Moved DatatypeMapper classes into Backbone views
  • JS: Models now correctly send DELETE requests
  • Added a new job overview page (which also renders run details) using AJAX
  • Using moment.min.js to format DateTime as string
  • Controllers now inherit from BaseController which provides a RedirectToLoginIfNecessary-method
  • Added loading animations to several AJAX bound places (loading experiments / scenarios)
  • Added a section to _Layout.cshtml which allows page-specific JavaScript includes (<script> only for a certain page)
  • Fixed Build/Edit of experiment menu redirecting to the wrong page
  • The Experiment Variation Dialog disables input fields, if the property has not been activated before
File size: 33.8 KB
Line 
1var OAAS_VIEW = (function (my, Backbone, _, $, OAAS_MODEL) {
2    // ================ VIEWS =======================
3    my.ExperimentTreeView = Backbone.View.extend({
4        renderTree: function (model) {
5            var jsonModel = model.toJSON();
6            var self = this;
7            this.tree = $('<div />').dynatree({
8                children: [jsonModel],
9                autoExpandMS: 750,
10                onActivate: function (node) {
11                    // if we are able to remove this node from the tree, enable the remove button.
12                    if (node && node.parent.parent != null) {
13                        $('.remove-button', this.$el).removeAttr("disabled");
14                    } else if (node) {
15                        $('.remove-button', this.$el).attr("disabled", "disabled");
16                    }
17
18                    var modelNode = OAAS_MODEL.ExperimentNode.lookup(node.data.key);
19                    if (modelNode && !modelNode.get('isExperiment')) {
20                        $('.variate-button', this.$el).removeAttr("disabled");
21                    } else {
22                        $('.variate-button', this.$el).attr("disabled", "disabled");
23                    }
24                },
25                dnd: {
26                    onDragStart: function (node) {
27                        return node.parent.parent != null;
28                    },
29                    onDragEnter: function (node, sourceNode) {
30                        return true;
31                    },
32                    onDragOver: function (node, sourceNode, hitMode) {
33                        return node.data.title !== "Experiment" || hitMode === "over";
34                    },
35                    onDrop: function (node, sourceNode, hitMode, ui, draggable) {
36                        if (hitMode !== 'over')
37                            return;
38                        var modelNode = OAAS_MODEL.ExperimentNode.lookup(node.data.key);
39                        if (sourceNode) {
40                            var sourceModelNode = OAAS_MODEL.ExperimentNode.lookup(sourceNode.data.key);
41                            sourceNode.move(node, hitMode);
42                            // move node into the modelNode
43                            sourceModelNode.moveNode(modelNode);
44                        }
45                        else {
46                            var elem = $(draggable.element[0]);
47                            var newNode = { nodeId: elem.attr('id'), isExperiment: elem.attr('data-isExperiment') === 'true', title: elem.attr('data-name'), key: OAAS_MODEL.ExperimentNode.nextGlobalKey() };
48                            if (hitMode == "over") {
49                                node.addChild(newNode);
50                                node.expand(true);
51                                // update the data model
52                                newNode = modelNode.addNode(newNode);
53                                self.trigger('node-added', newNode);
54                            }
55                        }
56                        self.trigger('structure-changed', modelNode);
57                    }
58                }
59            });
60            this.tree.dynatree("getRoot").visit(function (node) {
61                node.expand(true);
62            });
63        },
64        initialize: function (spec) {
65            this.renderTree(spec.model);
66        },
67        events: {
68            'click .remove-button': 'doRemove',
69            'click .variate-button': 'doVariate'
70        },
71        render: function () {
72            this.$el.empty();
73            this.renderTree(this.model);
74            var content = $(_.template($('#stepwizard_template').html(), {}));
75            this.tree.appendTo(this.$el);
76            content.appendTo(this.$el);
77        },
78        doRemove: function () {
79            var node = this.tree.dynatree('getActiveNode');
80            if (node && node.parent.parent != null) {
81                var nxt = node.getNextSibling();
82                if (nxt == null)
83                    nxt = node.getPrevSibling();
84                if (nxt == null)
85                    nxt = node.getParent();
86                node.remove();
87                OAAS_MODEL.ExperimentNode.lookup(node.data.key).remove();
88                if (nxt) {
89                    this.tree.dynatree("getTree").activateKey(nxt.data.key);
90                }
91            }
92            this.trigger('structure-changed', node);
93        },
94        doVariate: function () {
95            var node = this.tree.dynatree('getActiveNode');
96            var modelNode = OAAS_MODEL.ExperimentNode.lookup(node.data.key);
97            this.trigger('variation-request', {
98                parentNode: node.parent,
99                model: modelNode
100            });
101        }
102    });
103
104    my.ExperimentDetailsTreeView = Backbone.View.extend({
105        render: function () {
106            var jsonModel = this.model.toJSON();
107            var self = this;
108            var tree = $('<div />').dynatree({
109                children: [jsonModel],
110                autoExpandMS: 750,
111                onActivate: function (node) {
112                    // if we click a node, simply open a dialog to enter it's parameters
113                    self.trigger('node-clicked', node);
114                }
115            });
116
117            this.$el.empty();
118            tree.appendTo(this.$el);
119            tree.dynatree("getRoot").visit(function (node) {
120                node.expand(true);
121            });
122        }
123    });
124
125    my.DraggableGroup = Backbone.View.extend({
126        initialize: function () {
127            this.collection.bind('remove', this.render, this);
128            this.collection.bind('add', this.render, this);
129        },
130        render: function () {
131            var self = this;
132            var div = $('<div />');
133            if (this.collection.length == 0) {
134                $('<p></p>').text("No items found!").appendTo(div);
135            }
136            for (var i = 0; i < this.collection.length; i++) {
137                new my.DraggableView({ model: this.collection.models[i], el: div }).render();
138            }
139
140            this.$el.empty();
141            div.appendTo(this.$el);
142        }
143    });
144
145
146    my.DraggableView = Backbone.View.extend({
147        render: function () {
148            var late = _.template($("#draggable_template").html(), this.model.attributes);
149            $(late).draggable({
150                revert: true,
151                connectToDynatree: true,
152                cursorAt: { top: -5, left: -5 },
153                helper: "clone"
154            }).appendTo(this.$el);
155        }
156    });
157
158    my.SelectableGroup = Backbone.View.extend({
159        initialize: function () {
160            this.collection.bind('remove', this.render, this);
161            this.collection.bind('add', this.render, this);
162            this.collection.bind('change', this.render, this);
163        },
164        render: function () {
165            var self = this;
166            var div = $('<div />');
167            if (this.collection.length == 0) {
168                $('<p></p>').text("No experiments found!").appendTo(div);
169            }
170
171            for (var i = 0; i < this.collection.length; i++) {
172                new my.SelectableView({ model: this.collection.models[i], el: div }).render();
173            }
174            this.$el.empty();
175            div.selectable({
176                filter: 'div',
177                selected: function (event, ui) {
178                    self.selected(event, ui);
179                }
180            }).appendTo(this.$el);
181        },
182        selected: function (event, ui) {
183            var nodeId = $(ui.selected).attr('id');
184            this.trigger('node-selected', nodeId);
185        }
186    });
187
188    my.SelectableView = Backbone.View.extend({
189        render: function () {
190            var late = _.template($("#draggable_template").html(), this.model.attributes);
191            $(late).appendTo(this.$el);
192        }
193    });
194
195    my.StepWizardView = Backbone.View.extend({
196        render: function () {
197            var self = this;
198            this.$el.smartWizard({
199                onLeaveStep: function (step) {
200                    var stepNum = parseInt(step.attr("rel"));
201                    return self.validateStep(stepNum);
202                },
203                onShowStep: function (step) {
204                    var stepNum = parseInt(step.attr("rel"));
205                    return self.showStep(stepNum);
206                },
207                onFinish: function () {
208                    self.trigger('experiment-finished');
209                }
210            });
211        },
212        validateStep: function (stepNumber) {
213            var validationModel = {
214                stepNumber: stepNumber,
215                succeeded: true
216            };
217            this.trigger('step-validated', validationModel);
218            return validationModel.succeeded;
219        },
220        showStep: function (stepNumber) {
221            this.trigger('step-shown', stepNumber);
222            return true;
223        }
224    });
225
226    my.ParameterWizard = Backbone.View.extend({
227        createWizard: function (steps) {
228            // use template instead of jquery?!
229            var newWizard = $('<div />').addClass('wizard swMain');
230            var stepMenu = $('<ul />');
231            var prefix = name + '_';
232            for (var i = 0; i < steps.length; i++) {
233                var step = steps[i];
234                var a = $('<a></a>', { href: '#' + prefix + (i + 1) });
235                $('<label />').addClass("stepNumber").text((i + 1)).appendTo(a);
236                $('<span />').addClass("stepDesc").html(step.heading + '<br /><small>' + step.description + '</small>').appendTo(a);
237                var li = $('<li />').append(a);
238                li.appendTo(stepMenu);
239            }
240            stepMenu.appendTo(newWizard);
241            for (var i = 0; i < steps.length; i++) {
242                var div = $('<div />', { id: prefix + (i + 1) });
243                if (steps[i].content && steps[i].content != null)
244                    div.append(steps[i].content);
245                div.appendTo(newWizard);
246            }
247            return newWizard;
248        },
249        render: function () {
250            var self = this;
251            this.$el.empty();
252            var data = this.model.get('data');
253
254            var hasProblemParameters = typeof data.ProblemParameters !== 'undefined';
255            var dialog = $('<div />');
256            var algoDiv = $('<div />');
257            var problemDiv = $('<div />');
258
259            for (var i = 0; i < data.AlgorithmParameters.length; i++) {
260                var parameterView = new my.ParameterEditableView({ model: data.AlgorithmParameters[i] });
261                // render to dialog
262                parameterView.render();
263                parameterView.$el.appendTo(algoDiv);
264            }
265
266            if (hasProblemParameters) {
267                var problemParameters = data.ProblemParameters;
268                for (var i = 0; i < problemParameters.length; i++) {
269                    var parameterView = new my.ParameterEditableView({ model: problemParameters[i] });
270                    // render to dialog
271                    parameterView.render();
272                    parameterView.$el.appendTo(problemDiv);
273                }
274            }
275
276            var newWizard =
277          hasProblemParameters ?
278            this.createWizard([
279              { heading: "Algorithm Parameters", description: "Adjust algorithm parameters", content: algoDiv },
280              { heading: "Problem Parameters", description: "Adjust problem parameters", content: problemDiv }
281            ]) :
282            this.createWizard([
283              { heading: "Algorithm Parameters", description: "Adjust algorithm parameters", content: algoDiv }
284            ]);
285
286            newWizard.appendTo(this.$el);
287            newWizard.smartWizard({
288                onFinish: function () {
289                    self.trigger('parameters-finished');
290                }
291            });
292        }
293    });
294
295    my.ParameterEditableView = Backbone.View.extend({
296        /*events: {
297        'change': 'valueChanged'
298        },*/
299        render: function () {
300            var mapper = new my.DatatypeMapper();
301            var content = $(_.template($('#parameter_template').html(), this.model));
302            mapper.mapHtml(this.model, $('.rightEntry', content));
303            content.appendTo(this.$el);
304        } /*,
305        valueChanged: function (param) {
306            var value = $(param.target).val();
307            if (!isNaN(value))
308                value = parseFloat(value);
309            var name = $(param.target).attr("name");
310            // normally a controller would do this, just for once, let the view update the model
311            var splitted = name.split("_");
312            if (splitted.length == 1) {
313                this.model.Value = value;
314            } else if (splitted.length == 2) {
315                this.model.Value[parseInt(splitted[1])] = value;
316            } else if (splitted.length == 3) {
317                this.model.Value[parseInt(splitted[1])][parseInt(splitted[2])] = value;
318            }
319        }*/
320    });
321
322
323    my.LoadingDialog = Backbone.View.extend({
324        initialize: function () {
325            this.reset();
326        },
327        render: function () {
328            var self = this;
329            this.$el.empty();
330            var dialog = $('<div />');
331            this.content.appendTo(dialog);
332            dialog.appendTo(this.$el);
333            this.$el.dialog({
334                autoOpen: true
335            });
336        },
337        text: function (txt) {
338            $('p', this.$el).text(txt);
339        },
340        setLoading: function (isLoading) {
341            if (isLoading)
342                $('img', this.$el).show();
343            else
344                $('img', this.$el).hide();
345        },
346        reset: function () {
347            this.content = $(_.template($('#loading_template').html(), {}));
348        },
349        setContent: function (el) {
350            this.content = el;
351        },
352        close: function () {
353            this.$el.dialog("close");
354        }
355    });
356
357
358    my.ParameterDialog = Backbone.View.extend({
359        render: function () {
360            var self = this;
361
362            this.$el.empty();
363            var data = this.model.get('data');
364
365            var hasProblemParameters = typeof data.ProblemParameters !== 'undefined';
366            var dialog = $('<div />');
367
368            var parameterWizard = new my.ParameterWizard({ model: this.model, el: dialog });
369            parameterWizard.render();
370            this.listenTo(parameterWizard, 'parameters-finished', function () {
371                self.trigger('parameters-finished');
372            });
373            dialog.appendTo(this.$el);
374            this.$el.dialog({
375                autoOpen: true,
376                width: 1024,
377                height: 768
378            });
379        },
380        close: function () {
381            this.$el.dialog("close");
382        }
383    });
384
385    my.ExperimentDetailsView = Backbone.View.extend({
386        events: {
387            'change': 'valueChanged'
388        },
389        valueChanged: function (param) {
390            var value = $(param.target).val();
391            if (!isNaN(value))
392                value = parseFloat(value);
393            var name = $(param.target).attr("name");
394            if (name == 'Name')
395                this.model.set({ title: value });
396            else if (name == 'RunImmediately')
397                this.model.set({ run: $(param.target).is(':checked') });
398            else if (name == 'Repititions')
399                this.model.set({ repititions: value });
400            else if (name == 'Group')
401                this.model.set({ group: value });
402
403            if (this.model.get('run')) {
404                $('input[name="Repititions"]', this.$el).removeAttr('disabled');
405                $('input[name="Group"]', this.$el).removeAttr('disabled');
406            } else {
407                $('input[name="Repititions"]', this.$el).attr('disabled', 'disabled');
408                $('input[name="Group"]', this.$el).attr('disabled', 'disabled');
409            }
410        },
411        render: function () {
412            $('input[name="Name"]', this.$el).val(this.model.get('title'));
413            $('input[name="RunImmediately"]', this.$el).attr('checked', this.model.get('run'));
414            $('input[name="Repititions"]', this.$el).val(this.model.get('repititions'));
415            $('input[name="Group"]', this.$el).val(this.model.get('group'));
416        }
417    });
418
419    my.ValidationHintsView = Backbone.View.extend({
420        render: function () {
421            var template = _.template($('#validationhints_template').html(), this.model);
422            $(template).dialog({
423                resizable: false,
424                modal: true,
425                buttons: {
426                    "OK": function () {
427                        $(this).dialog("close");
428                    }
429                }
430            });
431        }
432    });
433
434    // ========== Variation Dialog Views ============
435
436    my.VariationDialog = Backbone.View.extend({
437        initialize: function (spec) {
438
439        },
440        events: {
441            'change': 'entrySelected'
442        },
443        render: function () {
444            var self = this;
445            var dialog = $(_.template($('#variationdialog_template').html(), {}));
446
447            var content = $('select[class="variationDialogContent"]', dialog);
448            var data = this.model.get('data');
449            for (var i = 0; i < data.AlgorithmParameters.length; i++) {
450                data.AlgorithmParameters[i].Index = i;
451                var entry = new my.VariationEntryView({ model: data.AlgorithmParameters[i], el: content });
452                entry.render();
453            }
454
455            this.details = $('div[class="variationDetails"]', dialog);
456            this.activateButton = $('input[name="active"]', dialog);
457            this.activateButton.change(function (evt) {
458                var checked = $(evt.target).is(':checked');
459                if (self.selectedModel && self.selectedModel != null) {
460                    self.selectedModel.Active = checked;
461                }
462
463                if (self.selectedModel.Active) {
464                    $('*', self.details).removeAttr('disabled');
465                }
466                else {
467                    //$('input,button,select', self.details).attr('disabled', 'disabled');
468                    $('*', self.details).attr('disabled', 'disabled');
469                }
470            });
471            dialog.dialog({
472                height: 300,
473                buttons: {
474                    "Abort": function () {
475                        $(this).dialog("close");
476                    },
477                    "OK": function () {
478                        self.generateVariations();
479                        $(this).dialog("close");
480                    }
481                }
482            });
483
484            content.change(function (evt) {
485                var optionSelected = $("option:selected", this);
486                var model = self.model.get('data').AlgorithmParameters[parseInt($(optionSelected).attr('data-index'))]
487                self.entrySelected(model);
488            });
489
490            this.variationDetails = new my.VariationContentView({ el: this.details });
491            var model = this.model.get('data').AlgorithmParameters[0];
492            this.entrySelected(model);
493        },
494        entrySelected: function (model) {
495            this.selectedModel = model;
496            this.variationDetails.model = model;
497            this.details.empty();
498            this.variationDetails.render();
499            if (model.Active) {
500                this.activateButton.attr('checked', 'checked');
501                $('*', this.details).removeAttr('disabled');
502            }
503            else {
504                this.activateButton.removeAttr('checked');
505                $('*', this.details).attr('disabled', 'disabled');
506            }
507        },
508        generateVariations: function () {
509            this.solutions = [];
510            this.exhaust(0, []);
511            this.trigger('variations-generated', this.solutions);
512        },
513        exhaust: function (index, element) {
514            if (index == this.model.get('data').AlgorithmParameters.length) {
515                // we found a solution! store it by creating a deep copy
516                this.solutions.push($.extend(true, [], element));
517                return;
518            }
519
520            var currentParameter = this.model.get('data').AlgorithmParameters[index];
521            if (currentParameter.Active && currentParameter.Generated) {
522                for (var i = 0; i < currentParameter.Generated.length; i++) {
523                    element[index] = {
524                        Name: currentParameter.Name,
525                        Value: currentParameter.Generated[i]
526                    };
527                    if (currentParameter.Options) {
528                        element[index].Options = currentParameter.Options;
529                    }
530                    this.exhaust(index + 1, element);
531                }
532            } else {
533                element[index] = {
534                    Name: currentParameter.Name,
535                    Value: currentParameter.Value
536                };
537                if (currentParameter.Options) {
538                    element[index].Options = currentParameter.Options;
539                }
540                this.exhaust(index + 1, element);
541            }
542        }
543    });
544
545    my.TableEditView = Backbone.View.extend({
546        events: {
547            'change': 'valueChanged',
548            'click button[data-operation="Add"]': 'addClicked',
549            'click button[data-operation="Remove"]': 'removeClicked'
550        },
551        render: function () {
552            this.$el.empty();
553            // http: //stackoverflow.com/questions/8749236/create-table-with-jquery-append
554            var table = $('<table></table>').addClass('editableTable');
555
556            // determine dimensions
557            var rows = this.model.length;
558            var columns = 1;
559            if ($.isArray(this.model[0])) {
560                columns = this.model[0].length;
561            }
562
563            // create head elements
564            var head = $('<thead></thead>');
565            var headerRow = $('<tr></tr>');
566            headerRow.appendTo(head);
567            if (this.options.rowNames) {
568                var rowNames = this.options.rowNames;
569                for (var i = 0; i < rowNames.length; i++) {
570                    $('<td />').text(rowNames[i]).appendTo(headerRow);
571                }
572            } else {
573                for (var i = 0; i < columns; i++) {
574                    $('<td />').text((i + 1) + '. Column').appendTo(headerRow);
575                }
576            }
577            head.appendTo(table);
578
579            // create body
580            var body = $('<tbody></tbody>');
581
582            for (var i = 0; i < rows; i++) {
583                var row = $('<tr></tr>');
584                for (var j = 0; j < columns; j++) {
585                    var rowContent = this.model[i];
586                    var columnEntry = $.isArray(rowContent) ? rowContent[j] : rowContent;
587                    var col = $('<td></td>');
588                    if (this.options.editable) {
589                        $('<input type="text" name="' + i + '_' + j + '" />').val(columnEntry).appendTo(col);
590                    } else {
591                        col.text(columnEntry);
592                    }
593                    col.appendTo(row);
594                }
595                if (this.options.editable) {
596                    $('<button data-operation="Add" name="' + i + '" />').val(columnEntry).text('+').appendTo(col);
597                    $('<button data-operation="Remove" name="' + i + '" />').val(columnEntry).text('-').appendTo(col);
598                }
599                row.appendTo(body);
600            }
601            body.appendTo(table);
602
603            table.appendTo(this.$el);
604            if (this.options.useDatatable)
605                table.dataTable();
606        },
607        valueChanged: function (evt) {
608            var target = $(evt.target);
609            var value = target.val();
610            var index = target.attr('name');
611            var splittedName = index.split('_');
612            var i = parseInt(splittedName[0]);
613            var j = parseInt(splittedName[1]);
614            if ($.isArray(this.model[i])) {
615                this.model[i][j] = parseFloat(value);
616            } else {
617                this.model[i] = parseFloat(value);
618            }
619        },
620        addClicked: function (evt) {
621            var target = $(evt.target);
622            var index = target.attr('name');
623            var i = parseInt(index);
624            if ($.isArray(this.model[i])) {
625                var cpy = [];
626                for (var j = 0; j < this.model[i].length; j++) {
627                    cpy.push(this.model[i][j]);
628                }
629                this.model.splice(i, 0, cpy);
630            } else {
631                this.model.splice(i, 0, this.model[i]);
632            }
633            // render after model changes
634            this.render();
635        },
636        removeClicked: function (evt) {
637            var target = $(evt.target);
638            var index = target.attr('name');
639            var i = parseInt(index);
640            this.model.splice(i, 1);
641            // render after model changes
642            this.render();
643        }
644    });
645
646    my.NumberEditableView = Backbone.View.extend({
647        events: {
648            'change': 'valueChanged'
649        },
650        render: function () {
651            $('<input type="text" />').val(this.model.Value).appendTo(this.$el);
652
653        },
654        valueChanged: function (evt) {
655            var value = $(evt.target).val();
656            if (!isNaN(value)) {
657                value = parseFloat(value);
658                this.model.Value = value;
659            } else {
660                $('input', this.$el).val(this.model.Value);
661            }
662        }
663    });
664
665    my.SelectionView = Backbone.View.extend({
666        events: {
667            'change': 'checked'
668        },
669        render: function () {
670            this.$el.empty();
671            var s = $('<select />').attr('data-name', this.model.Name).appendTo(this.$el);
672            for (var i = 0; i < this.model.Options.length; i++) {
673                $('<option />', { value: this.model.Options[i], text: this.model.Options[i] }).appendTo(s);
674            }
675            s.val(this.model.Value);
676        },
677        checked: function (evt) {
678            var value = $(evt.target).val();
679            var name = $(evt.target).attr('data-name')
680            this.trigger('selected', { name: name, value: value });
681        }
682    });
683
684    my.OptionSelectionView = Backbone.View.extend({
685        events: {
686            'change': 'checked'
687        },
688        render: function () {
689            this.$el.empty();
690            if ($.isArray(this.model)) {
691                for (var i = 0; i < this.model.length; i++) {
692                    $(_.template($('#checkbox_template').html(), { checked: false, name: this.model[i], text: this.model[i], hideText: this.options.hideText })).appendTo(this.$el);
693                }
694            }
695            else {
696                $(_.template($('#checkbox_template').html(), { checked: this.model, name: this.model, text: this.model, hideText: this.options.hideText })).appendTo(this.$el);
697            }
698        },
699        checked: function (evt) {
700            var checked = $(evt.target).is(':checked');
701            var name = $(evt.target).attr('name')
702            this.trigger('changed', { name: name, checked: checked });
703        }
704    });
705
706
707    my.PlotView = Backbone.View.extend({
708        render: function () {
709            this.$el.empty();
710            var plotLabels = undefined;
711            if (this.model.RowNames) {
712                plotLabels = [];
713                for (var i = 0; i < this.model.RowNames.length; i++) {
714                    plotLabels.push({ label: this.model.RowNames[i] });
715                }
716            }
717
718            var values = this.model.Value ? this.model.Value : this.model;
719
720            var plotValues = [];
721            if ($.isArray(values[0])) {
722                var columnCount = values[0].length;
723                var colVals = {};
724                for (var i = 0; i < columnCount; i++)
725                    colVals[i] = [];
726
727                for (var i = 0; i < values.length; i++) {
728                    for (var j = 0; j < columnCount; j++) {
729                        colVals[j].push(values[i][j]);
730                    }
731                }
732
733                for (var i = 0; i < columnCount; i++) {
734                    plotValues.push(colVals[i]);
735                }
736            } else {
737                plotValues.push(values);
738            }
739
740            if (!this.$el.attr('id')) {
741                this.$el.attr('id', my.PlotView.nextId());
742            }
743
744            this.$el.css('width', '500px');
745
746            this.plot = $.jqplot(this.$el.attr('id'), plotValues, {
747                cursor: {
748                    show: true,
749                    zoom: true,
750                    showTooltip: false
751                },
752                series: plotLabels,
753                seriesDefaults: {
754                    lineWidth: 1.5,
755                    markerOptions: {
756                        size: 2,
757                        lineWidth: 2
758                    }
759                },
760                legend: {
761                    show: true,
762                    placement: 'outsideGrid'
763                },
764                highlighter: {
765                    show: true,
766                    sizeAdjust: 7.5
767                }
768            });
769        },
770        refresh: function () {
771            if (this.plot)
772                this.plot.replot({ resetAxes: true });
773        }
774    },
775  {
776      plotId: 1,
777      nextId: function () {
778          return my.PlotView.plotId++;
779      }
780  });
781
782    my.VariationContentView = Backbone.View.extend({
783        render: function () {
784            var self = this;
785            if (this.model.Value === 'false' || this.model.Value === 'true' ||
786              this.model.Value === true || this.model.Value === false) {
787                $(_.template($('#variation_boolean_template').html(), {})).appendTo(this.$el);
788                this.model.Generated = [false, true];
789            }
790            else if (!isNaN(this.model.Value)) {
791                var elem = $(_.template($('#variation_number_template').html(), {}));
792                elem.appendTo(this.$el)
793                $('input[name="generate"]', elem).click(function (evt) { self.openGenerator(evt); });
794                if (!this.model.Generated) {
795                    this.model.Generated = [0, 1, 2];
796                }
797                var tev = new my.TableEditView({ model: this.model.Generated, el: $('div div', this.$el), editable: true });
798                tev.render();
799            }
800            else if (this.model.Options) {
801                var osv = new my.OptionSelectionView({ model: this.model.Options, el: this.$el });
802                this.listenTo(osv, 'changed', function (evt) {
803                    self.selectionChanged(evt);
804                });
805                if (!this.model.Generated)
806                    this.model.Generated = [];
807                osv.render();
808                for (var i = 0; i < this.model.Generated.length; i++) {
809                    $('input[name="' + this.model.Generated[i] + '"]', this.$el).attr('checked', 'checked');
810                }
811            }
812        },
813        openGenerator: function (evt) {
814            var self = this;
815            var generator = new my.GeneratorDialog();
816            this.listenTo(generator, 'success', function (data) {
817                self.doGenerate(data);
818            });
819            generator.render();
820        },
821        doGenerate: function (data) {
822            if (data.minimum > data.maximum) {
823                var tmp = data.minimum;
824                data.minimum = data.maximum;
825                data.maximum = tmp;
826            }
827            if (data.step < 0)
828                data.step *= -1;
829            if (data.step == 0)
830                data.step = 1;
831            this.model.Generated = _.range(data.minimum, data.maximum + 1, data.step);
832            var tev = new my.TableEditView({ model: this.model.Generated, el: $('div div', this.$el), editable: true });
833            tev.render();
834        },
835        selectionChanged: function (evt) {
836            if (!evt.checked) {
837                this.model.Generated = _.without(this.model.Generated, evt.name);
838            } else if (_.indexOf(this.model.Generated, evt.name) == -1) {
839                this.model.Generated.push(evt.name);
840            }
841        }
842    });
843
844    my.GeneratorDialog = Backbone.View.extend({
845        render: function () {
846            var self = this;
847            var generator = $(_.template($('#variation_generator_template').html(), {}));
848            generator.dialog({
849                buttons: {
850                    "Abort": function () {
851                        $(this).dialog("close");
852                    },
853                    "OK": function () {
854                        $(this).dialog("close");
855                        self.trigger("success", {
856                            minimum: parseInt($('input[name="minimum"]', generator).val()),
857                            maximum: parseInt($('input[name="maximum"]', generator).val()),
858                            step: parseFloat($('input[name="step"]', generator).val())
859                        });
860                    }
861                }
862            });
863        }
864    });
865
866    my.VariationEntryView = Backbone.View.extend({
867        render: function () {
868            var entryTemplate = _.template($('#variationentry_template').html(), this.model);
869            $(entryTemplate).appendTo(this.$el);
870        }
871    });
872    return my;
873} (OAAS_VIEW || {}, Backbone, _, $, OAAS_MODEL));
Note: See TracBrowser for help on using the repository browser.