- Timestamp:
- 03/20/13 16:56:28 (12 years ago)
- Location:
- branches/OaaS/HeuristicLab.Services.Optimization.Web/Content
- Files:
-
- 7 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/OaaS/HeuristicLab.Services.Optimization.Web/Content/Datatypemapping.js
r9227 r9324 1 function DatatypeMapper() { 2 } 1 var OAAS_VIEW = (function (my, _, $, Backbone) { 2 my.DatatypeMapper = function () { 3 this.cb = {}; 4 _.extend(this.cb, Backbone.Events); 3 5 4 DatatypeMapper.prototype.mapHtml = function (property) { 5 var parameter = property.Value; 6 var key = property.Name; 7 if (property.Options) { 8 return DatatypeMapper_mapStrings(property.Name, property.Options, property.Value); 9 } 10 else if (parameter instanceof Array) { 11 // parameter is a vector of strings 12 if (parameter[0] instanceof String || typeof (parameter[0]) == 'string') { 13 return DatatypeMapper_mapStrings(key, parameter); 6 this.mapHtml = function (property, el) { 7 var parameter = property.Value; 8 var key = property.Name; 9 if (property.Options) { 10 var osv = new OAAS_VIEW.SelectionView({ model: property, el: el }); 11 this.cb.listenTo(osv, 'selected', function (model) { 12 property.Value = model.value; 13 }); 14 osv.render(); 15 return osv; 16 } 17 else if (parameter instanceof Array) { 18 // parameter is a matrix or vector of numbers 19 var tev = new OAAS_VIEW.TableEditView({ model: parameter, el: el, editable: true }); 20 tev.render(); 21 return tev; 22 } 23 else if (typeof (parameter) == 'boolean') { 24 var osv = new OAAS_VIEW.OptionSelectionView({ model: parameter, el: el, hideText: true }); 25 this.cb.listenTo(osv, 'changed', function (model) { 26 property.Value = model.checked; 27 }); 28 osv.render(); 29 return osv; 30 } 31 // parameter is a number 32 else if (!isNaN(parameter)) { 33 var nev = new OAAS_VIEW.NumberEditableView({ model: property, el: el }); 34 nev.render(); 35 return nev; 36 } 37 return 'No mapping for ' + typeof (parameter) + ' (Key: ' + key + ')'; 38 }; 14 39 15 }16 // parameter is a vector of numbers17 else if (!isNaN(parameter[0])) {18 return DatatypeMapper_mapNumbers(key, parameter);19 }20 // parameter is a matrix of numbers21 else {22 return DatatypeMapper_mapMatrix(key, parameter);23 }24 40 25 41 } 26 else if (typeof (parameter) == 'boolean') {27 return DatatypeMapper_mapBoolean(key, parameter);28 }29 // parameter is a number30 else if (!isNaN(parameter)) {31 return DatatypeMapper_mapNumber(key, parameter);32 }33 return 'No mapping for ' + typeof (parameter) + ' (Key: ' + key + ')';34 }35 42 36 43 37 function DatatypeMapper_mapStrings(key, param, selected) {38 // http://stackoverflow.com/questions/4814512/how-to-create-dropdown-list-dynamically-using-jquery39 var s = $('<select name="' + key + '"/>');40 for (var i = 0; i < param.length; i++) {41 $('<option />', { value: param[i], text: param[i] }).appendTo(s);42 }43 s.val(selected);44 return s;45 }44 function DatatypeMapper_mapStrings(key, param, selected) { 45 // http://stackoverflow.com/questions/4814512/how-to-create-dropdown-list-dynamically-using-jquery 46 var s = $('<select name="' + key + '"/>'); 47 for (var i = 0; i < param.length; i++) { 48 $('<option />', { value: param[i], text: param[i] }).appendTo(s); 49 } 50 s.val(selected); 51 return s; 52 } 46 53 47 function DatatypeMapper_mapNumber(key, param) {48 return $('<input type="text" name="' + key + '" />').val(param);49 }54 function DatatypeMapper_mapNumber(key, param) { 55 return $('<input type="text" name="' + key + '" />').val(param); 56 } 50 57 51 function DatatypeMapper_mapBoolean(key, param) {52 var s = $('<select name="' + key + '"/>');53 $('<option />', { value: 'true', text: 'true' }).appendTo(s);54 $('<option />', { value: 'false', text: 'false' }).appendTo(s);55 return s;56 }58 function DatatypeMapper_mapBoolean(key, param) { 59 var s = $('<select name="' + key + '"/>'); 60 $('<option />', { value: 'true', text: 'true' }).appendTo(s); 61 $('<option />', { value: 'false', text: 'false' }).appendTo(s); 62 return s; 63 } 57 64 58 function DatatypeMapper_mapNumbers(key, param) {59 // http: //stackoverflow.com/questions/8749236/create-table-with-jquery-append60 var table = $('<table></table>').addClass('editableTable');61 var head = $('<thead></thead>');62 // create head elements63 var headerRow = $('<tr></tr>');64 $('<td />').text(key + ' Column').appendTo(headerRow);65 headerRow.appendTo(head);66 head.appendTo(table);67 var body = $('<tbody></tbody>');68 for (var i = 0; i < param.length; i++) {69 var row = $('<tr></tr>');70 var td = $('<td />').appendTo(row);71 $('<input type="text" name="' + key + '_' + i + '" />').val(param[i]).appendTo(td);72 row.appendTo(body);73 }74 body.appendTo(table);75 return table;76 }65 function DatatypeMapper_mapNumbers(key, param) { 66 // http: //stackoverflow.com/questions/8749236/create-table-with-jquery-append 67 var table = $('<table></table>').addClass('editableTable'); 68 var head = $('<thead></thead>'); 69 // create head elements 70 var headerRow = $('<tr></tr>'); 71 $('<td />').text(key + ' Column').appendTo(headerRow); 72 headerRow.appendTo(head); 73 head.appendTo(table); 74 var body = $('<tbody></tbody>'); 75 for (var i = 0; i < param.length; i++) { 76 var row = $('<tr></tr>'); 77 var td = $('<td />').appendTo(row); 78 $('<input type="text" name="' + key + '_' + i + '" />').val(param[i]).appendTo(td); 79 row.appendTo(body); 80 } 81 body.appendTo(table); 82 return table; 83 } 77 84 78 function DatatypeMapper_mapMatrix(key, param) { 79 // http: //stackoverflow.com/questions/8749236/create-table-with-jquery-append 80 var table = $('<table></table>').addClass('editableTable'); 81 var head = $('<thead></thead>'); 82 // create head elements 83 var headerRow = $('<tr></tr>'); 84 for (var i = 0; i < param[0].length; i++) { 85 $('<td />').text(key + ' Column ' + i).appendTo(headerRow); 86 } 87 headerRow.appendTo(head); 88 head.appendTo(table); 89 var body = $('<tbody></tbody>'); 90 for (var i = 0; i < param.length; i++) { 91 var row = $('<tr></tr>'); 92 for (var j = 0; j < param[i].length; j++) { 93 var td = $('<td />').appendTo(row); 94 $('<input type="text" name="' + key + '_' + i + '_' + j + '" />').val(param[i][j]).appendTo(td); 85 function DatatypeMapper_mapMatrix(key, param) { 86 // http: //stackoverflow.com/questions/8749236/create-table-with-jquery-append 87 var table = $('<table></table>').addClass('editableTable'); 88 var head = $('<thead></thead>'); 89 // create head elements 90 var headerRow = $('<tr></tr>'); 91 for (var i = 0; i < param[0].length; i++) { 92 $('<td />').text(key + ' Column ' + i).appendTo(headerRow); 93 } 94 headerRow.appendTo(head); 95 head.appendTo(table); 96 var body = $('<tbody></tbody>'); 97 for (var i = 0; i < param.length; i++) { 98 var row = $('<tr></tr>'); 99 for (var j = 0; j < param[i].length; j++) { 100 var td = $('<td />').appendTo(row); 101 $('<input type="text" name="' + key + '_' + i + '_' + j + '" />').val(param[i][j]).appendTo(td); 102 } 103 row.appendTo(body); 104 } 105 body.appendTo(table); 106 return table; 107 108 /*var table = '<table class="editableTable"><thead><tr>'; 109 for (var i = 0; i < param[0].length; i++) { 110 table += '<th>' + key + ' Column ' + (i + 1) + '</th>'; 111 } 112 table += '</tr>'; 113 // foreach value entry (2d entry) 114 for (var i = 0; i < param.length; i++) { 115 table += '<tr>'; 116 for (var j = 0; j < param[i].length; j++) { 117 table += '<td><input type="text" name="' + key + '_' + i + '_' + j + '" /></td>'; 118 } 119 table += '</tr>'; 120 } 121 return $*/ 95 122 } 96 row.appendTo(body);97 }98 body.appendTo(table);99 return table;100 123 101 /*var table = '<table class="editableTable"><thead><tr>'; 102 for (var i = 0; i < param[0].length; i++) { 103 table += '<th>' + key + ' Column ' + (i + 1) + '</th>'; 104 } 105 table += '</tr>'; 106 // foreach value entry (2d entry) 107 for (var i = 0; i < param.length; i++) { 108 table += '<tr>'; 109 for (var j = 0; j < param[i].length; j++) { 110 table += '<td><input type="text" name="' + key + '_' + i + '_' + j + '" /></td>'; 124 /* 125 DatatypeMapper.prototype.mapString = function (value) { 126 if (value == "true") return true; 127 else if (value == "false") return false; 128 else if (!isNaN(value)) return parseFloat(value.replace(',', '.')); 129 return value; 111 130 } 112 table += '</tr>';113 }114 return $*/115 }116 131 117 DatatypeMapper.prototype.mapString = function (value) { 118 if (value == "true") return true; 119 else if (value == "false") return false; 120 else if (!isNaN(value)) return parseFloat(value.replace(',', '.')); 121 return value; 122 } 123 124 DatatypeMapper.prototype.aggregateTables = function (data) { 132 DatatypeMapper.prototype.aggregateTables = function (data) { 125 133 // aggregate tables: 126 134 for (var dataKey in data) { 127 128 129 130 131 132 133 134 135 136 137 135 var entry = data[dataKey]; 136 var tableEntries = {}; 137 var toRemove = []; 138 for (var key in entry) { 139 if (key.indexOf('_') != -1) { 140 var splitted = key.split('_'); 141 var name = splitted[0]; 142 var row = parseInt(splitted[1]); 143 if (!(name in tableEntries)) { 144 tableEntries[name] = [] 145 } 138 146 139 140 141 142 143 144 145 146 147 148 149 147 if (splitted.length == 2) { // its a vector of elements 148 tableEntries[name].push(entry[key]) 149 } else if (splitted.length == 3) { // its a matrix of elements 150 column = parseInt(splitted[2]); 151 if (tableEntries[name].length < row + 1) 152 tableEntries[name].push([]); 153 tableEntries[name][row][column] = entry[key]; 154 } 155 toRemove.push(key); 156 } 157 } 150 158 151 152 153 159 for (var i = 0; i < toRemove.length; i++) { 160 delete entry[toRemove[i]]; 161 } 154 162 155 for (var key in tableEntries) { 156 entry[key] = tableEntries[key]; 157 } 163 for (var key in tableEntries) { 164 entry[key] = tableEntries[key]; 158 165 } 159 } 166 } 167 }*/ 168 return my; 169 } (OAAS_VIEW || {}, _, $, Backbone)); -
branches/OaaS/HeuristicLab.Services.Optimization.Web/Content/experiment.controller.js
r9305 r9324 1 function GeneralController() { 2 this.variationRequestHandler = function (evt) { 3 var self = this; 4 var dialog = new VariationDialog({ model: evt.model }); 5 var dialogController = {}; 6 _.extend(dialogController, Backbone.Events); 7 dialogController.listenTo(dialog, 'variations-generated', function (variations) { 8 var parent = evt.model.get('parent'); 9 for (var i = 0; i < variations.length; i++) { 10 var title = evt.model.get('title'); 11 var offset = title.indexOf('(') 12 if (offset != -1) { 13 title = title.substring(0, offset); 14 } 15 title += '('; 16 for (var j = 0; j < variations[i].length; j++) { 17 title += variations[i][j].Name + " = " + variations[i][j].Value + "; "; 18 } 19 title += ')'; 20 var data = { AlgorithmParameters: variations[i] }; 21 if (evt.model.attributes.data.ProblemParameters) { 22 data.ProblemParameters = evt.model.attributes.data.ProblemParameters; 23 } 24 parent.addNode({ title: title, nodeId: evt.model.get('nodeId'), data: data }); 25 } 26 self.model.trigger('change'); 27 }); 28 dialog.render(); 29 }, 30 this.experimentFinishedHandler = function (experimentModel, availableExperiments, selectableGroup) { 31 var loadingDialog = new LoadingDialog({ el: $('#loadingDialog') }); 32 // start the loading dialog 33 loadingDialog.setLoading(true); 34 loadingDialog.text('Saving experiment ' + experimentModel.get('title') + '...'); 35 loadingDialog.render(); 36 // send experiment to server 37 experimentModel.save({}, { success: function () { 38 loadingDialog.setLoading(false); 39 loadingDialog.text('Experiment successfully saved!'); 40 loadingDialog.render(); 41 if (availableExperiments) 42 availableExperiments.fetch({ cache: false, success: function (itm) { 43 selectableGroup.render(); 44 } 45 }); 46 } 47 }); 48 //loadingDialog.close(); 49 } 50 } 51 52 function ExperimentPageController() { 53 this.refreshExperiments = function () { 54 var availableExperiments = new ExperimentList(); 55 availableExperiments.fetch({ cache: false, success: function (itm) { 56 $('#experiments').empty(); 57 for (var i = 0; i < availableExperiments.length; i++) { 58 new DraggableView({ model: availableExperiments.models[i], el: $('#experiments') }).render(); 59 } 60 } 61 }); 62 }, 63 this.refreshScenarios = function () { 64 var availableScenarios = new ScenarioList(); 65 availableScenarios.fetch({ cache: false, success: function (itm) { 66 var group = new DraggableGroup({ model: availableScenarios, el: $('#algorithms') }); 67 group.render(); 68 } 69 }); 70 }, 71 this.create = function () { 72 var self = this; 73 var generalController = new GeneralController(); 74 // create all models + required view for the experiment page 75 var model = new ExperimentNode({ 76 title: 'Experiment', 77 key: 0, 78 isExperiment: true 79 }, { parse: true }); 80 generalController.model = model; 81 var experimentModel = new Experiment({ experiment: model }); 82 83 var view = new ExperimentTreeView({ model: model, el: $('#container') }); 84 view.render(); 85 86 this.refreshScenarios(); 87 88 this.refreshExperiments(); 89 90 var wizard = new StepWizardView({ el: $('#stepWizard') }); 91 wizard.render(); 92 93 var detailsView = new ExperimentDetailsTreeView({ model: model, el: $('#container2') }); 94 var validationView = new ValidationHintsView({ model: { header: "Validation failed!", text: ""} }); 95 var parameterDialog = new ParameterDialog({ model: model, el: $('#parameterDialog') }); 96 97 var wizardController = {}; 98 _.extend(wizardController, Backbone.Events); 99 100 wizardController.listenTo(model, 'change', function () { 101 // update the details view, when the model changes 102 view.render(); 103 detailsView.render(); 104 }); 105 106 107 wizardController.listenTo(wizard, 'experiment-finished', function () { 108 generalController.experimentFinishedHandler(experimentModel, null, null); 109 self.refreshExperiments(); 110 /*// start the loading dialog 1 var OAAS_CONTROLLER = (function (my, Backbone, OAAS_VIEW, OAAS_MODEL, _, $) { 2 my.GeneralController = function () { 3 this.variationRequestHandler = function (evt) { 4 var self = this; 5 var dialog = new OAAS_VIEW.VariationDialog({ model: evt.model }); 6 var dialogController = {}; 7 _.extend(dialogController, Backbone.Events); 8 dialogController.listenTo(dialog, 'variations-generated', function (variations) { 9 var parent = evt.model.get('parent'); 10 for (var i = 0; i < variations.length; i++) { 11 var title = evt.model.get('title'); 12 var offset = title.indexOf('(') 13 if (offset != -1) { 14 title = title.substring(0, offset); 15 } 16 title += '('; 17 for (var j = 0; j < variations[i].length; j++) { 18 title += variations[i][j].Name + " = " + variations[i][j].Value + "; "; 19 } 20 title += ')'; 21 var data = { AlgorithmParameters: variations[i] }; 22 if (evt.model.attributes.data.ProblemParameters) { 23 data.ProblemParameters = evt.model.attributes.data.ProblemParameters; 24 } 25 parent.addNode({ title: title, nodeId: evt.model.get('nodeId'), data: data }); 26 } 27 self.model.trigger('change'); 28 }); 29 dialog.render(); 30 }, 31 this.experimentFinishedHandler = function (experimentModel, availableExperiments, selectableGroup) { 32 var loadingDialog = new OAAS_VIEW.LoadingDialog({ el: $('#loadingDialog') }); 33 // start the loading dialog 111 34 loadingDialog.setLoading(true); 112 35 loadingDialog.text('Saving experiment ' + experimentModel.get('title') + '...'); … … 114 37 // send experiment to server 115 38 experimentModel.save({}, { success: function () { 116 loadingDialog.setLoading(false); 117 loadingDialog.text('Experiment successfully saved!'); 118 loadingDialog.render(); 119 self.refreshExperiments(); 120 } 121 });*/ 39 loadingDialog.setLoading(false); 40 loadingDialog.text('Experiment successfully saved!'); 41 loadingDialog.render(); 42 if (availableExperiments) 43 availableExperiments.fetch({ cache: false, success: function (itm) { 44 selectableGroup.render(); 45 } 46 }); 47 } 48 }); 122 49 //loadingDialog.close(); 123 }); 124 125 wizardController.listenTo(view, 'structure-changed', function (node) { 50 } 51 } 52 53 my.ExperimentPageController = function () { 54 this.refreshExperiments = function () { 55 var availableExperiments = new OAAS_MODEL.ExperimentList(); 56 availableExperiments.fetch({ cache: false, success: function (itm) { 57 var group = new OAAS_VIEW.DraggableGroup({ collection: availableExperiments, el: $('#experiments') }); 58 group.render(); 59 } 60 }); 61 }, 62 this.refreshScenarios = function () { 63 var availableScenarios = new OAAS_MODEL.ScenarioList(); 64 availableScenarios.fetch({ cache: false, success: function (itm) { 65 var group = new OAAS_VIEW.DraggableGroup({ collection: availableScenarios, el: $('#algorithms') }); 66 group.render(); 67 } 68 }); 69 }, 70 this.create = function () { 71 var self = this; 72 var generalController = new my.GeneralController(); 73 // create all models + required view for the experiment page 74 var model = new OAAS_MODEL.ExperimentNode({ 75 title: 'Experiment', 76 key: 0, 77 isExperiment: true 78 }, { parse: true }); 79 generalController.model = model; 80 var experimentModel = new OAAS_MODEL.Experiment({ experiment: model }); 81 82 var view = new OAAS_VIEW.ExperimentTreeView({ model: model, el: $('#container') }); 126 83 view.render(); 127 detailsView.render(); 128 }); 129 130 wizardController.listenTo(view, 'node-added', function (node) { 131 // get details about the node 132 node.fetch({ success: function (itm) { 133 model.trigger('change', {}); 134 } 135 }); 136 }); 137 138 wizardController.listenTo(detailsView, 'node-clicked', function (node) { 139 // get details about the node 140 var modelNode = ExperimentNode.lookup(node.data.key); 141 if (!modelNode.get('isExperiment')) { 142 parameterDialog.model = modelNode; 143 parameterDialog.render(); 144 } 145 }); 146 147 wizardController.listenTo(parameterDialog, 'parameters-finished', function (node) { 148 parameterDialog.close(); 149 }); 150 151 wizardController.listenTo(view, 'variation-request', function (evt) { 152 generalController.variationRequestHandler(evt); 153 }); 154 155 var experimentDetailsView = new ExperimentDetailsView({ el: $('#step3'), model: experimentModel }); 84 85 this.refreshScenarios(); 86 87 this.refreshExperiments(); 88 89 var wizard = new OAAS_VIEW.StepWizardView({ el: $('#stepWizard') }); 90 wizard.render(); 91 92 var detailsView = new OAAS_VIEW.ExperimentDetailsTreeView({ model: model, el: $('#container2') }); 93 var validationView = new OAAS_VIEW.ValidationHintsView({ model: { header: "Validation failed!", text: ""} }); 94 var parameterDialog = new OAAS_VIEW.ParameterDialog({ model: model, el: $('#parameterDialog') }); 95 96 var wizardController = {}; 97 _.extend(wizardController, Backbone.Events); 98 99 wizardController.listenTo(model, 'change', function () { 100 // update the details view, when the model changes 101 view.render(); 102 detailsView.render(); 103 }); 104 105 106 wizardController.listenTo(wizard, 'experiment-finished', function () { 107 generalController.experimentFinishedHandler(experimentModel, null, null); 108 self.refreshExperiments(); 109 }); 110 111 wizardController.listenTo(view, 'structure-changed', function (node) { 112 view.render(); 113 detailsView.render(); 114 }); 115 116 wizardController.listenTo(view, 'node-added', function (node) { 117 // get details about the node 118 node.fetch({ success: function (itm) { 119 model.trigger('change', {}); 120 } 121 }); 122 }); 123 124 wizardController.listenTo(detailsView, 'node-clicked', function (node) { 125 // get details about the node 126 var modelNode = OAAS_MODEL.ExperimentNode.lookup(node.data.key); 127 if (!modelNode.get('isExperiment')) { 128 parameterDialog.model = modelNode; 129 parameterDialog.render(); 130 } 131 }); 132 133 wizardController.listenTo(parameterDialog, 'parameters-finished', function (node) { 134 parameterDialog.close(); 135 }); 136 137 wizardController.listenTo(view, 'variation-request', function (evt) { 138 generalController.variationRequestHandler(evt); 139 }); 140 141 var experimentDetailsView = new OAAS_VIEW.ExperimentDetailsView({ el: $('#step3'), model: experimentModel }); 142 143 144 } 156 145 } 157 } 158 159 160 161 /// ==================== EDIT PAGE ========================= 162 /// ==================== EDIT PAGE ========================= 163 /// ==================== EDIT PAGE ========================= 164 165 function ExperimentEditPageController() { 166 this.refreshScenarios = function () { 167 var availableScenarios = new ScenarioList(); 168 availableScenarios.fetch({ cache: false, success: function (itm) { 169 var group = new DraggableGroup({ model: availableScenarios, el: $('#draggableAlgorithms') }); 170 group.render(); 171 /*$('#algorithms').empty(); 172 for (var i = 0; i < availableScenarios.length; i++) { 173 new DraggableView({ model: availableScenarios.models[i], el: $('#algorithms') }).render(); 174 }*/ 146 147 148 149 /// ==================== EDIT PAGE ========================= 150 /// ==================== EDIT PAGE ========================= 151 /// ==================== EDIT PAGE ========================= 152 153 my.ExperimentEditPageController = function () { 154 this.refreshScenarios = function () { 155 var availableScenarios = new OAAS_MODEL.ScenarioList(); 156 availableScenarios.fetch({ cache: false, success: function (itm) { 157 var group = new OAAS_VIEW.DraggableGroup({ collection: availableScenarios, el: $('#draggableAlgorithms') }); 158 group.render(); 159 } 160 }); 161 }, 162 this.create = function () { 163 var generalController = new my.GeneralController(); 164 165 var self = this; 166 // create all models + required view for the experiment page 167 var controllerModel = new OAAS_MODEL.ControllerModel(); 168 var model = new OAAS_MODEL.ExperimentNode({ 169 title: 'Experiment', 170 key: 0, 171 isExperiment: true 172 }, { parse: true }); 173 174 generalController.model = model; 175 var experimentModel = new OAAS_MODEL.Experiment({ experiment: model }); 176 var experimentDetailsView = new OAAS_VIEW.ExperimentDetailsView({ el: $('#step4'), model: experimentModel }); 177 experimentDetailsView.render(); 178 179 var availableExperiments = new OAAS_MODEL.ExperimentList(); 180 181 var wizardController = {}; 182 _.extend(wizardController, Backbone.Events); 183 184 this.refreshScenarios(); 185 186 var selectableGroup = new OAAS_VIEW.SelectableGroup({ collection: availableExperiments, el: $('#experiments') }); 187 //selectableGroup.render(); 188 var draggableExperiments = new OAAS_VIEW.DraggableGroup({ collection: availableExperiments, el: $('#draggableExperiments') }); 189 availableExperiments.fetch({ cache: false, success: function (itm) { 190 // selectableGroup = new OAAS_VIEW.SelectableGroup({ collection: availableExperiments, el: $('#experiments') }); 191 selectableGroup.render(); 192 193 wizardController.listenTo(selectableGroup, 'node-selected', function (nodeId) { 194 var node = availableExperiments.find(function (itm) { return itm.get('nodeId') == nodeId; }); 195 196 var newNode = new OAAS_MODEL.ExperimentNode(node.attributes); 197 newNode.fetch({ success: function () { 198 experimentModel.set({ 199 experiment: newNode, 200 title: node.get('title'), 201 nodeId: node.get('nodeId'), 202 run: node.get('run'), 203 repititions: node.get('repititions'), 204 group: node.get('group') 205 }); 206 controllerModel.set({ selectedNode: newNode }); 207 $('#deleteExperimentButton').removeAttr('disabled'); 208 detailsView.model = newNode; 209 detailsView.render(); 210 view.model = newNode; 211 view.render(); 212 experimentDetailsView.render(); 213 } 214 }); 215 } 216 ); 217 } 218 }); 219 220 // create wizard with 4 steps 221 var wizard = new OAAS_VIEW.StepWizardView({ el: $('#stepWizard') }); 222 wizard.render(); 223 224 var view = new OAAS_VIEW.ExperimentTreeView({ model: model, el: $('#container') }); 225 view.render(); 226 var validationView = new OAAS_VIEW.ValidationHintsView({ model: { header: "Validation failed!", text: ""} }); 227 228 var detailsView = new OAAS_VIEW.ExperimentDetailsTreeView({ model: model, el: $('#container2') }); 229 230 var parameterDialog = new OAAS_VIEW.ParameterDialog({ model: model, el: $('#parameterDialog') }); 231 var loadingDialog = new OAAS_VIEW.LoadingDialog({ el: $('#loadingDialog') }); 232 233 wizardController.listenTo(wizard, 'step-validated', function (validationModel) { 234 // update the details view 235 if (validationModel.stepNumber == 1) { 236 if (controllerModel.get('selectedNode') == null) { 237 validationView.model["text"] = 'Please select an experiment to continue!'; 238 validationView.render(); 239 validationModel.succeeded = false; 240 } 241 } 242 detailsView.render(); 243 }); 244 245 wizardController.listenTo(model, 'change', function () { 246 // update the details view, when the model changes 247 view.render(); 248 detailsView.render(); 249 }); 250 251 wizardController.listenTo(view, 'structure-changed', function (node) { 252 view.render(); 253 }); 254 255 wizardController.listenTo(view, 'node-added', function (node) { 256 // get details about the node 257 //if (!node.get('isExperiment')) 258 node.fetch({ success: function (itm) { 259 model.trigger('change', {}); 260 } 261 }); 262 }); 263 264 wizardController.listenTo(wizard, 'experiment-finished', function () { 265 generalController.experimentFinishedHandler(experimentModel, availableExperiments, selectableGroup); 266 }); 267 268 wizardController.listenTo(detailsView, 'node-clicked', function (node) { 269 // get details about the node 270 var modelNode = OAAS_MODEL.ExperimentNode.lookup(node.data.key); 271 if (!modelNode.get('isExperiment')) { 272 parameterDialog.model = modelNode; 273 parameterDialog.render(); 274 } 275 }); 276 277 wizardController.listenTo(view, 'variation-request', function (evt) { 278 generalController.variationRequestHandler(evt); 279 }); 280 281 wizardController.listenTo(parameterDialog, 'parameters-finished', function (node) { 282 parameterDialog.close(); 283 }); 284 285 $('#deleteExperimentButton').click(function (evt) { 286 var node = controllerModel.get('selectedNode'); 287 var nodes = availableExperiments.where({ nodeId: node.get('nodeId') }); 288 if (nodes.length == 1) { 289 nodes[0].destroy(); 290 $('#deleteExperimentButton').attr('disabled', 'disabled'); 291 controllerModel.set('selectedNode', null); 292 } 293 }); 175 294 } 176 });177 },178 this.create = function () {179 var generalController = new GeneralController();180 181 var self = this;182 // create all models + required view for the experiment page183 var controllerModel = new ControllerModel();184 var model = new ExperimentNode({185 title: 'Experiment',186 key: 0,187 isExperiment: true188 }, { parse: true });189 190 generalController.model = model;191 var experimentModel = new Experiment({ experiment: model });192 var experimentDetailsView = new ExperimentDetailsView({ el: $('#step4'), model: experimentModel });193 experimentDetailsView.render();194 195 var availableExperiments = new ExperimentList();196 var selectableGroup = null;197 var wizardController = {};198 _.extend(wizardController, Backbone.Events);199 200 this.refreshScenarios();201 202 availableExperiments.fetch({ cache: false, success: function (itm) {203 selectableGroup = new SelectableGroup({ model: availableExperiments, el: $('#experiments') });204 selectableGroup.render();205 var draggableExperiments = new DraggableGroup({ model: availableExperiments, el: $('#draggableExperiments') });206 draggableExperiments.render();207 208 wizardController.listenTo(selectableGroup, 'node-selected', function (nodeId) {209 var node = availableExperiments.find(function (itm) { return itm.get('nodeId') == nodeId; });210 var newNode = new ExperimentNode(node.attributes);211 experimentModel.set({212 experiment: newNode,213 title: node.get('title'),214 nodeId: node.get('nodeId'),215 run: node.get('run'),216 repititions: node.get('repititions'),217 group: node.get('group')218 });219 controllerModel.set({ selectedNode: newNode });220 detailsView.model = newNode;221 detailsView.render();222 view.model = newNode;223 view.render();224 experimentDetailsView.render();225 }226 );227 }228 });229 230 // create wizard with 4 steps231 var wizard = new StepWizardView({ el: $('#stepWizard') });232 wizard.render();233 234 var view = new ExperimentTreeView({ model: model, el: $('#container') });235 view.render();236 var validationView = new ValidationHintsView({ model: { header: "Validation failed!", text: ""} });237 238 var detailsView = new ExperimentDetailsTreeView({ model: model, el: $('#container2') });239 240 var parameterDialog = new ParameterDialog({ model: model, el: $('#parameterDialog') });241 var loadingDialog = new LoadingDialog({ el: $('#loadingDialog') });242 243 wizardController.listenTo(wizard, 'step-validated', function (validationModel) {244 // update the details view245 if (validationModel.stepNumber == 1) {246 if (controllerModel.get('selectedNode') == null) {247 validationView.model["text"] = 'Please select an experiment to continue!';248 validationView.render();249 validationModel.succeeded = false;250 }251 }252 detailsView.render();253 });254 255 wizardController.listenTo(model, 'change', function () {256 // update the details view, when the model changes257 view.render();258 detailsView.render();259 });260 261 wizardController.listenTo(view, 'structure-changed', function (node) {262 view.render();263 });264 265 wizardController.listenTo(view, 'node-added', function (node) {266 // get details about the node267 //if (!node.get('isExperiment'))268 node.fetch({ success: function (itm) {269 model.trigger('change', {});270 }271 });272 });273 274 wizardController.listenTo(wizard, 'experiment-finished', function () {275 generalController.experimentFinishedHandler(experimentModel, availableExperiments, selectableGroup);276 });277 278 wizardController.listenTo(detailsView, 'node-clicked', function (node) {279 // get details about the node280 var modelNode = ExperimentNode.lookup(node.data.key);281 if (!modelNode.get('isExperiment')) {282 parameterDialog.model = modelNode;283 parameterDialog.render();284 }285 });286 287 wizardController.listenTo(view, 'variation-request', function (evt) {288 generalController.variationRequestHandler(evt);289 });290 291 wizardController.listenTo(parameterDialog, 'parameters-finished', function (node) {292 parameterDialog.close();293 });294 295 } 295 } 296 296 return my; 297 } (OAAS_CONTROLLER || {}, Backbone, OAAS_VIEW, OAAS_MODEL, _, $)); 297 298 298 299 -
branches/OaaS/HeuristicLab.Services.Optimization.Web/Content/experiment.model.js
r9305 r9324 1 1 //================== MODELS ===================== 2 var ControllerModel = Backbone.Model.extend({ 3 defaults: { 4 selectedNode: null 2 var OAAS_MODEL = (function (my, Backbone) { 3 Backbone.Relational.store.addModelScope(my); 4 5 my.ControllerModel = Backbone.Model.extend({ 6 defaults: { 7 selectedNode: null 8 } 9 }); 10 11 my.Experiment = Backbone.RelationalModel.extend({ 12 url: function () { 13 return '/Experiment/Experiment?nodeId=' + this.get('nodeId'); 14 }, 15 isNew: function () { return false; }, 16 defaults: { 17 title: 'My Experiment', 18 isExperiment: true, 19 run: false, 20 nodeId: null, 21 repititions: 1, 22 group: 'TESTAZURE' 23 }, 24 relations: [{ 25 key: 'experiment', 26 relatedModel: 'ExperimentNode' 27 }] 28 }); 29 30 my.ExperimentNode = Backbone.RelationalModel.extend({ 31 defaults: { 32 title: 'Experiment', 33 key: -1, 34 data: {}, 35 parent: null, 36 isExperiment: false, 37 nodeId: null 38 }, 39 relations: [{ 40 type: Backbone.HasMany, 41 key: 'children', 42 relatedModel: 'ExperimentNode', 43 collectionType: 'AlgorithmList', 44 reverseRelation: { 45 key: 'parent' 46 } 47 }], 48 url: function () { 49 return this.get('isExperiment') ? '/Experiment/Experiment?nodeId=' + this.get('nodeId') : '/Experiment/Scenario?nodeId=' + this.get('nodeId'); 50 }, 51 initialize: function (spec) { 52 if (typeof spec.key === 'undefined' || spec.key == -1) { 53 spec.key = my.ExperimentNode.globalKeyCount; 54 this.set({ key: spec.key }); 55 my.ExperimentNode.globalKeyCount++; 56 } 57 else if (spec.key >= my.ExperimentNode.globalKeyCount) 58 my.ExperimentNode.globalKeyCount = spec.key + 1; 59 60 my.ExperimentNode.globalNodeMap[spec.key] = this; 61 }, 62 // adds a new experimentNode to this node 63 addNode: function (experimentNode) { 64 if (!(experimentNode instanceof my.ExperimentNode)) { 65 experimentNode = new my.ExperimentNode(experimentNode); 66 } 67 this.get('children').add(experimentNode); 68 experimentNode.set({ parent: this }); 69 this.trigger('node-added', experimentNode); 70 return experimentNode; 71 }, 72 // moves an experimentNode into this node 73 moveNode: function (experimentNode) { 74 var parent = experimentNode.get('parent'); 75 if (parent != null) { 76 // remove from parent 77 parent.get('children').remove(experimentNode); 78 } 79 this.addNode(experimentNode); 80 }, 81 // delete this node 82 remove: function () { 83 var parent = this.get('parent'); 84 if (parent != null) { 85 parent.get('children').remove(this); 86 this.set({ parent: null }); 87 // simply replace it with 'undefined' 88 delete my.ExperimentNode.globalNodeMap[this.get('key')]; 89 } 90 }, 91 lookup: function (key) { 92 return my.ExperimentNode.globalNodeMap[key]; 93 } 94 }, 95 { 96 globalKeyCount: 0, 97 globalNodeMap: {}, 98 lookup: function (key) { 99 return my.ExperimentNode.globalNodeMap[key]; 100 }, 101 nextGlobalKey: function () { 102 var key = my.ExperimentNode.globalKeyCount; 103 my.ExperimentNode.globalKeyCount++; 104 return key; 105 } 5 106 } 6 });107 ); 7 108 8 var Experiment = Backbone.RelationalModel.extend({ 9 url: function () { 10 return '/Experiment/Experiment?nodeId=' + this.get('nodeId'); 11 }, 12 defaults: { 13 title: 'My Experiment', 14 isExperiment: true, 15 run: false, 16 nodeId: null, 17 repititions: 1, 18 group: 'TESTAZURE' 19 }, 20 isNew: function() { return this.get('nodeId') == null; }, 21 relations: [{ 22 key: 'experiment', 23 relatedModel: 'ExperimentNode' 24 }] 25 }); 109 my.ExperimentList = Backbone.Collection.extend({ 110 url: function () { 111 return "/Experiment/ExperimentList"; 112 }, 113 model: my.Experiment 114 }); 26 115 27 var ExperimentNode = Backbone.RelationalModel.extend({ 28 defaults: { 29 title: 'Experiment', 30 key: -1, 31 data: {}, 32 parent: null, 33 isExperiment: false, 34 nodeId: null 35 }, 36 relations: [{ 37 type: Backbone.HasMany, 38 key: 'children', 39 relatedModel: 'ExperimentNode', 40 collectionType: 'ScenarioList', 41 reverseRelation: { 42 key: 'parent' 43 } 44 }], 45 url: function () { 46 return this.get('isExperiment') ? '/Experiment/Experiment?nodeId=' + this.get('nodeId') : '/Experiment/Scenario?nodeId=' + this.get('nodeId'); 47 }, 48 initialize: function (spec) { 49 if (typeof spec.key === 'undefined' || spec.key == -1) { 50 spec.key = ExperimentNode.globalKeyCount; 51 this.set({ key: spec.key }); 52 ExperimentNode.globalKeyCount++; 53 } 54 else if (spec.key >= ExperimentNode.globalKeyCount) 55 ExperimentNode.globalKeyCount = spec.key + 1; 116 my.AlgorithmList = Backbone.Collection.extend({ 117 url: function () { 118 return "/Experiment/AlgorithmList"; 119 }, 120 model: my.ExperimentNode 121 }); 56 122 57 ExperimentNode.globalNodeMap[spec.key] = this; 58 }, 59 // adds a new experimentNode to this node 60 addNode: function (experimentNode) { 61 if (!(experimentNode instanceof ExperimentNode)) { 62 experimentNode = new ExperimentNode(experimentNode); 63 } 64 this.get('children').add(experimentNode); 65 experimentNode.set({ parent: this }); 66 this.trigger('node-added', experimentNode); 67 return experimentNode; 68 }, 69 // moves an experimentNode into this node 70 moveNode: function (experimentNode) { 71 var parent = experimentNode.get('parent'); 72 if (parent != null) { 73 // remove from parent 74 parent.get('children').remove(experimentNode); 75 } 76 this.addNode(experimentNode); 77 }, 78 // delete this node 79 remove: function () { 80 var parent = this.get('parent'); 81 if (parent != null) { 82 parent.get('children').remove(this); 83 this.set({ parent: null }); 84 // simply replace it with 'undefined' 85 delete ExperimentNode.globalNodeMap[this.get('key')]; 86 } 87 this.trigger('node-removed', this); 88 }, 89 lookup: function (key) { 90 return ExperimentNode.globalNodeMap[key]; 91 } 92 }, 93 { 94 globalKeyCount: 0, 95 globalNodeMap: {}, 96 lookup: function (key) { 97 return ExperimentNode.globalNodeMap[key]; 98 }, 99 nextGlobalKey: function () { 100 var key = ExperimentNode.globalKeyCount; 101 ExperimentNode.globalKeyCount++; 102 return key; 103 } 104 } 105 ); 106 107 var ExperimentList = Backbone.Collection.extend({ 108 url: function () { 109 return "/Experiment/ExperimentList"; 110 }, 111 model: Experiment 112 }); 113 114 var ScenarioList = Backbone.Collection.extend({ 115 url: function () { 116 return "/Experiment/ScenarioList"; 117 }, 118 model: ExperimentNode 119 }); 123 my.ScenarioList = Backbone.Collection.extend({ 124 url: function () { 125 return "/Experiment/ScenarioList"; 126 }, 127 model: my.ExperimentNode 128 }); 129 return my; 130 } (OAAS_MODEL || {}, Backbone)); -
branches/OaaS/HeuristicLab.Services.Optimization.Web/Content/experiment.view.js
r9305 r9324 1 // ================ VIEWS ======================= 2 var ExperimentTreeView = Backbone.View.extend({ 3 renderTree: function (model) { 4 var jsonModel = model.toJSON(); 5 var self = this; 6 this.tree = $('<div />').dynatree({ 7 children: [jsonModel], 8 autoExpandMS: 750, 9 onActivate: function (node) { 10 // if we are able to remove this node from the tree, enable the remove button. 11 if (node && node.parent.parent != null) { 12 $('.remove-button', this.$el).removeAttr("disabled"); 13 } else if (node) { 14 $('.remove-button', this.$el).attr("disabled", "disabled"); 15 } 16 17 var modelNode = ExperimentNode.lookup(node.data.key); 18 if (modelNode && !modelNode.get('isExperiment')) { 19 $('.variate-button', this.$el).removeAttr("disabled"); 20 } else { 21 $('.variate-button', this.$el).attr("disabled", "disabled"); 22 } 23 }, 24 dnd: { 25 onDragStart: function (node) { 26 return node.parent.parent != null; 1 var 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 } 27 24 }, 28 onDragEnter: function (node, sourceNode) { 29 return true; 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); 30 202 }, 31 onDragOver: function (node, sourceNode, hitMode) { 32 return node.data.title !== "Experiment" || hitMode === "over"; 203 onShowStep: function (step) { 204 var stepNum = parseInt(step.attr("rel")); 205 return self.showStep(stepNum); 33 206 }, 34 onDrop: function (node, sourceNode, hitMode, ui, draggable) { 35 if (hitMode !== 'over') 36 return; 37 var modelNode = ExperimentNode.lookup(node.data.key); 38 if (sourceNode) { 39 var sourceModelNode = ExperimentNode.lookup(sourceNode.data.key); 40 sourceNode.move(node, hitMode); 41 // move node into the modelNode 42 sourceModelNode.moveNode(modelNode); 43 } 44 else { 45 var elem = $(draggable.element[0]); 46 var newNode = { nodeId: elem.attr('id'), isExperiment: elem.attr('data-isExperiment') === 'true', title: elem.attr('data-name'), key: ExperimentNode.nextGlobalKey() }; 47 if (hitMode == "over") { 48 node.addChild(newNode); 49 node.expand(true); 50 // update the data model 51 newNode = modelNode.addNode(newNode); 52 self.trigger('node-added', newNode); 53 } 54 } 55 self.trigger('structure-changed', modelNode); 56 } 57 } 58 }); 59 this.tree.dynatree("getRoot").visit(function (node) { 60 node.expand(true); 61 }); 62 }, 63 initialize: function (spec) { 64 this.renderTree(spec.model); 65 }, 66 events: { 67 'click .remove-button': 'doRemove', 68 'click .variate-button': 'doVariate' 69 }, 70 render: function () { 71 this.$el.empty(); 72 this.renderTree(this.model); 73 var content = $(_.template($('#stepwizard_template').html(), {})); 74 this.tree.appendTo(this.$el); 75 content.appendTo(this.$el); 76 }, 77 doRemove: function () { 78 var node = this.tree.dynatree('getActiveNode'); 79 if (node && node.parent.parent != null) { 80 var nxt = node.getNextSibling(); 81 if (nxt == null) 82 nxt = node.getPrevSibling(); 83 if (nxt == null) 84 nxt = node.getParent(); 85 node.remove(); 86 ExperimentNode.lookup(node.data.key).remove(); 87 if (nxt) { 88 this.tree.dynatree("getTree").activateKey(nxt.data.key); 89 } 90 } 91 this.trigger('structure-changed', node); 92 }, 93 doVariate: function () { 94 var node = this.tree.dynatree('getActiveNode'); 95 var modelNode = ExperimentNode.lookup(node.data.key); 96 this.trigger('variation-request', { 97 parentNode: node.parent, 98 model: modelNode 99 }); 100 } 101 }); 102 103 var ExperimentDetailsTreeView = Backbone.View.extend({ 104 render: function () { 105 var jsonModel = this.model.toJSON(); 106 var self = this; 107 var tree = $('<div />').dynatree({ 108 children: [jsonModel], 109 autoExpandMS: 750, 110 onActivate: function (node) { 111 // if we click a node, simply open a dialog to enter it's parameters 112 self.trigger('node-clicked', node); 113 } 114 }); 115 116 this.$el.empty(); 117 tree.appendTo(this.$el); 118 tree.dynatree("getRoot").visit(function (node) { 119 node.expand(true); 120 }); 121 } 122 }); 123 124 var DraggableGroup = Backbone.View.extend({ 125 render: function () { 126 var self = this; 127 var div = $('<div />'); 128 129 for (var i = 0; i < this.model.length; i++) { 130 new DraggableView({ model: this.model.models[i], el: div }).render(); 131 } 132 133 this.$el.empty(); 134 div.appendTo(this.$el); 135 } 136 }); 137 138 139 var DraggableView = Backbone.View.extend({ 140 render: function () { 141 var late = _.template($("#draggable_template").html(), this.model.attributes); 142 $(late).draggable({ 143 revert: true, 144 connectToDynatree: true, 145 cursorAt: { top: -5, left: -5 }, 146 helper: "clone" 147 }).appendTo(this.$el); 148 } 149 }); 150 151 var SelectableGroup = Backbone.View.extend({ 152 render: function () { 153 var self = this; 154 var div = $('<div />'); 155 for (var i = 0; i < this.model.length; i++) { 156 new SelectableView({ model: this.model.models[i], el: div }).render(); 157 } 158 this.$el.empty(); 159 div.selectable({ 160 filter: 'div', 161 selected: function (event, ui) { 162 self.selected(event, ui); 163 } 164 }).appendTo(this.$el); 165 }, 166 selected: function (event, ui) { 167 var nodeId = $(ui.selected).attr('id'); 168 this.trigger('node-selected', nodeId); 169 } 170 }); 171 172 var SelectableView = Backbone.View.extend({ 173 render: function () { 174 var late = _.template($("#draggable_template").html(), this.model.attributes); 175 $(late).appendTo(this.$el); 176 } 177 }); 178 179 var StepWizardView = Backbone.View.extend({ 180 render: function () { 181 var self = this; 182 this.$el.smartWizard({ 183 onLeaveStep: function (step) { 184 var stepNum = parseInt(step.attr("rel")); 185 return self.validateStep(stepNum); 186 }, 187 onShowStep: function (step) { 188 var stepNum = parseInt(step.attr("rel")); 189 return self.showStep(stepNum); 190 }, 191 onFinish: function () { 192 self.trigger('experiment-finished'); 193 } 194 }); 195 }, 196 validateStep: function (stepNumber) { 197 var validationModel = { 198 stepNumber: stepNumber, 199 succeeded: true 200 }; 201 this.trigger('step-validated', validationModel); 202 return validationModel.succeeded; 203 }, 204 showStep: function (stepNumber) { 205 this.trigger('step-shown', stepNumber); 206 return true; 207 } 208 }); 209 210 var ParameterWizard = Backbone.View.extend({ 211 createWizard: function (steps) { 212 // use template instead of jquery?! 213 var newWizard = $('<div />').addClass('wizard swMain'); 214 var stepMenu = $('<ul />'); 215 var prefix = name + '_'; 216 for (var i = 0; i < steps.length; i++) { 217 var step = steps[i]; 218 var a = $('<a></a>', { href: '#' + prefix + (i + 1) }); 219 $('<label />').addClass("stepNumber").text((i + 1)).appendTo(a); 220 $('<span />').addClass("stepDesc").html(step.heading + '<br /><small>' + step.description + '</small>').appendTo(a); 221 var li = $('<li />').append(a); 222 li.appendTo(stepMenu); 223 } 224 stepMenu.appendTo(newWizard); 225 for (var i = 0; i < steps.length; i++) { 226 var div = $('<div />', { id: prefix + (i + 1) }); 227 if (steps[i].content && steps[i].content != null) 228 div.append(steps[i].content); 229 div.appendTo(newWizard); 230 } 231 return newWizard; 232 }, 233 render: function () { 234 var self = this; 235 this.$el.empty(); 236 var data = this.model.get('data'); 237 238 var hasProblemParameters = typeof data.ProblemParameters !== 'undefined'; 239 var dialog = $('<div />'); 240 var algoDiv = $('<div />'); 241 var problemDiv = $('<div />'); 242 243 for (var i = 0; i < data.AlgorithmParameters.length; i++) { 244 var parameterView = new ParameterEditableView({ model: data.AlgorithmParameters[i] }); 245 // render to dialog 246 parameterView.render(); 247 parameterView.$el.appendTo(algoDiv); 248 } 249 250 if (hasProblemParameters) { 251 var problemParameters = data.ProblemParameters; 252 for (var i = 0; i < problemParameters.length; i++) { 253 var parameterView = new ParameterEditableView({ model: problemParameters[i] }); 254 // render to dialog 255 parameterView.render(); 256 parameterView.$el.appendTo(problemDiv); 257 } 258 } 259 260 var newWizard = 261 hasProblemParameters ? 262 this.createWizard([ 263 { heading: "Algorithm Parameters", description: "Adjust algorithm parameters", content: algoDiv }, 264 { heading: "Problem Parameters", description: "Adjust problem parameters", content: problemDiv } 265 ]) : 266 this.createWizard([ 267 { heading: "Algorithm Parameters", description: "Adjust algorithm parameters", content: algoDiv } 268 ]); 269 270 newWizard.appendTo(this.$el); 271 newWizard.smartWizard({ 272 onFinish: function () { 273 self.trigger('parameters-finished'); 274 } 275 }); 276 } 277 }); 278 279 var ParameterEditableView = Backbone.View.extend({ 280 events: { 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: { 281 297 'change': 'valueChanged' 282 }, 283 render: function () { 284 var mapper = new DatatypeMapper(); 285 var content = $(_.template($('#parameter_template').html(), this.model)); 286 mapper.mapHtml(this.model).appendTo($('.rightEntry', content)); 287 content.appendTo(this.$el); 288 }, 289 valueChanged: function (param) { 290 var value = $(param.target).val(); 291 if (!isNaN(value)) 292 value = parseFloat(value); 293 var name = $(param.target).attr("name"); 294 // normally a controller would do this, just for once, let the view update the model 295 var splitted = name.split("_"); 296 if (splitted.length == 1) { 297 this.model.Value = value; 298 } else if (splitted.length == 2) { 299 this.model.Value[parseInt(splitted[1])] = value; 300 } else if (splitted.length == 3) { 301 this.model.Value[parseInt(splitted[1])][parseInt(splitted[2])] = value; 302 } 303 } 304 }); 305 306 307 var LoadingDialog = Backbone.View.extend({ 308 initialize: function () { 309 this.reset(); 310 }, 311 render: function () { 312 var self = this; 313 this.$el.empty(); 314 var dialog = $('<div />'); 315 this.content.appendTo(dialog); 316 dialog.appendTo(this.$el); 317 this.$el.dialog({ 318 autoOpen: true 319 }); 320 }, 321 text: function (txt) { 322 $('p', this.$el).text(txt); 323 }, 324 setLoading: function(isLoading) { 325 if (isLoading) 326 $('img', this.$el).show(); 327 else 328 $('img', this.$el).hide(); 329 }, 330 reset: function () { 331 this.content = $(_.template($('#loading_template').html(), {})); 332 }, 333 setContent: function (el) { 334 this.content = el; 335 }, 336 close: function () { 337 this.$el.dialog("close"); 338 } 339 }); 340 341 342 var ParameterDialog = Backbone.View.extend({ 343 render: function () { 344 var self = this; 345 346 this.$el.empty(); 347 var data = this.model.get('data'); 348 349 var hasProblemParameters = typeof data.ProblemParameters !== 'undefined'; 350 var dialog = $('<div />'); 351 352 var parameterWizard = new ParameterWizard({ model: this.model, el: dialog }); 353 parameterWizard.render(); 354 this.listenTo(parameterWizard, 'parameters-finished', function () { 355 self.trigger('parameters-finished'); 356 }); 357 dialog.appendTo(this.$el); 358 this.$el.dialog({ 359 autoOpen: true, 360 width: 1024, 361 height: 768 362 }); 363 }, 364 close: function () { 365 this.$el.dialog("close"); 366 } 367 }); 368 369 var ExperimentDetailsView = Backbone.View.extend({ 370 events: { 371 'change': 'valueChanged' 372 }, 373 valueChanged: function (param) { 374 var value = $(param.target).val(); 375 if (!isNaN(value)) 376 value = parseFloat(value); 377 var name = $(param.target).attr("name"); 378 if (name == 'Name') 379 this.model.set({ title: value }); 380 else if (name == 'RunImmediately') 381 this.model.set({ run: $(param.target).is(':checked') }); 382 else if (name == 'Repititions') 383 this.model.set({ repititions: value }); 384 else if (name == 'Group') 385 this.model.set({ group: value }); 386 387 if (this.model.get('run')) { 388 $('input[name="Repititions"]', this.$el).removeAttr('disabled'); 389 $('input[name="Group"]', this.$el).removeAttr('disabled'); 390 } else { 391 $('input[name="Repititions"]', this.$el).attr('disabled', 'disabled'); 392 $('input[name="Group"]', this.$el).attr('disabled', 'disabled'); 393 } 394 }, 395 render: function () { 396 $('input[name="Name"]', this.$el).val(this.model.get('title')); 397 $('input[name="RunImmediately"]', this.$el).attr('checked', this.model.get('run')); 398 $('input[name="Repititions"]', this.$el).val(this.model.get('repititions')); 399 $('input[name="Group"]', this.$el).val(this.model.get('group')); 400 } 401 }); 402 403 var ValidationHintsView = Backbone.View.extend({ 404 render: function () { 405 var template = _.template($('#validationhints_template').html(), this.model); 406 $(template).dialog({ 407 resizable: false, 408 modal: true, 409 buttons: { 410 "OK": function () { 411 $(this).dialog("close"); 412 } 413 } 414 }); 415 } 416 }); 417 418 // ========== Variation Dialog Views ============ 419 420 var VariationDialog = Backbone.View.extend({ 421 initialize: function (spec) { 422 423 }, 424 events: { 425 'change': 'entrySelected' 426 }, 427 render: function () { 428 var self = this; 429 var dialog = $(_.template($('#variationdialog_template').html(), {})); 430 431 var content = $('select[class="variationDialogContent"]', dialog); 432 var data = this.model.get('data'); 433 for (var i = 0; i < data.AlgorithmParameters.length; i++) { 434 data.AlgorithmParameters[i].Index = i; 435 var entry = new VariationEntryView({ model: data.AlgorithmParameters[i], el: content }); 436 entry.render(); 437 } 438 439 this.details = $('div[class="variationDetails"]', dialog); 440 this.activateButton = $('input[name="active"]', dialog); 441 this.activateButton.change(function (evt) { 442 var checked = $(evt.target).is(':checked'); 443 if (self.selectedModel && self.selectedModel != null) { 444 self.selectedModel.Active = checked; 445 } 446 }); 447 dialog.dialog({ 448 height: 300, 449 buttons: { 450 "Abort": function () { 451 $(this).dialog("close"); 452 }, 453 "OK": function () { 454 self.generateVariations(); 455 $(this).dialog("close"); 456 } 457 } 458 }); 459 460 content.change(function (evt) { 461 var optionSelected = $("option:selected", this); 462 var model = self.model.get('data').AlgorithmParameters[parseInt($(optionSelected).attr('data-index'))] 463 self.entrySelected(model); 464 }); 465 466 this.variationDetails = new VariationContentView({ el: this.details }); 467 var model = this.model.get('data').AlgorithmParameters[0]; 468 this.entrySelected(model); 469 }, 470 entrySelected: function (model) { 471 this.selectedModel = model; 472 if (model.Active) 473 this.activateButton.attr('checked', 'checked'); 474 else 475 this.activateButton.removeAttr('checked'); 476 this.variationDetails.model = model; 477 this.details.empty(); 478 this.variationDetails.render(); 479 }, 480 generateVariations: function () { 481 this.solutions = []; 482 this.exhaust(0, []); 483 this.trigger('variations-generated', this.solutions); 484 }, 485 exhaust: function (index, element) { 486 if (index == this.model.get('data').AlgorithmParameters.length) { 487 // we found a solution! store it by creating a deep copy 488 this.solutions.push($.extend(true, [], element)); 489 return; 490 } 491 492 var currentParameter = this.model.get('data').AlgorithmParameters[index]; 493 if (currentParameter.Active && currentParameter.Generated) { 494 for (var i = 0; i < currentParameter.Generated.length; i++) { 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 { 495 533 element[index] = { 496 534 Name: currentParameter.Name, 497 Value: currentParameter. Generated[i]535 Value: currentParameter.Value 498 536 }; 499 537 if (currentParameter.Options) { … … 502 540 this.exhaust(index + 1, element); 503 541 } 504 } else { 505 element[index] = { 506 Name: currentParameter.Name, 507 Value: currentParameter.Value 508 }; 509 if (currentParameter.Options) { 510 element[index].Options = currentParameter.Options; 511 } 512 this.exhaust(index + 1, element); 513 } 514 } 515 }); 516 517 var TableEditView = Backbone.View.extend({ 518 events: { 519 'change': 'valueChanged', 520 'click button[data-operation="Add"]': 'addClicked', 521 'click button[data-operation="Remove"]': 'removeClicked' 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 } 522 774 }, 523 render: function () { 524 this.$el.empty(); 525 // http: //stackoverflow.com/questions/8749236/create-table-with-jquery-append 526 var table = $('<table></table>').addClass('editableTable'); 527 528 // determine dimensions 529 var rows = this.model.length; 530 var columns = 1; 531 if ($.isArray(this.model[0])) { 532 columns = this.model[0].length; 533 } 534 535 // create head elements 536 var head = $('<thead></thead>'); 537 var headerRow = $('<tr></tr>'); 538 headerRow.appendTo(head); 539 for (var i = 0; i < columns; i++) { 540 $('<td />').text((i + 1) + '. Column').appendTo(headerRow); 541 } 542 head.appendTo(table); 543 544 // create body 545 var body = $('<tbody></tbody>'); 546 547 for (var i = 0; i < rows; i++) { 548 var row = $('<tr></tr>'); 549 for (var j = 0; j < columns; j++) { 550 var rowContent = this.model[i]; 551 var columnEntry = $.isArray(rowContent) ? rowContent[j] : rowContent; 552 var col = $('<td></td>'); 553 $('<input type="text" name="' + i + '_' + j + '" />').val(columnEntry).appendTo(col); 554 col.appendTo(row); 555 } 556 if (this.options.editable) { 557 $('<button data-operation="Add" name="' + i + '" />').val(columnEntry).text('+').appendTo(col); 558 $('<button data-operation="Remove" name="' + i + '" />').val(columnEntry).text('-').appendTo(col); 559 } 560 row.appendTo(body); 561 } 562 body.appendTo(table); 563 table.appendTo(this.$el); 564 }, 565 valueChanged: function (evt) { 566 var target = $(evt.target); 567 var value = target.val(); 568 var index = target.getattr('name'); 569 var splittedName = index.split('_'); 570 var i = parseInt(splittedName[0]); 571 var j = parseInt(splittedName[1]); 572 if ($.isArray(this.model[i])) { 573 this.model[i][j] = parseFloat(value); 574 } else { 575 this.model[i] = parseFloat(value); 576 } 577 }, 578 addClicked: function (evt) { 579 var target = $(evt.target); 580 var index = target.attr('name'); 581 var i = parseInt(index); 582 if ($.isArray(this.model[i])) { 583 var cpy = []; 584 for (var j = 0; j < this.model[i].length; j++) { 585 cpy.push(this.model[i][j]); 586 } 587 this.model.splice(i, 0, cpy); 588 } else { 589 this.model.splice(i, 0, this.model[i]); 590 } 591 // render after model changes 592 this.render(); 593 }, 594 removeClicked: function (evt) { 595 var target = $(evt.target); 596 var index = target.attr('name'); 597 var i = parseInt(index); 598 this.model.splice(i, 1); 599 // render after model changes 600 this.render(); 601 } 602 }); 603 604 var OptionSelectionView = Backbone.View.extend({ 605 events: { 606 'change': 'checked' 607 }, 608 render: function () { 609 this.$el.empty(); 610 611 for (var i = 0; i < this.model.length; i++) { 612 $(_.template($('#checkbox_template').html(), { name: this.model[i], text: this.model[i] })).appendTo(this.$el); 613 } 614 }, 615 checked: function (evt) { 616 var checked = $(evt.target).is(':checked'); 617 var name = $(evt.target).attr('name') 618 this.trigger('changed', { name: name, checked: checked }); 619 } 620 }); 621 622 var VariationContentView = Backbone.View.extend({ 623 render: function () { 624 var self = this; 625 if (this.model.Value === 'false' || this.model.Value === 'true' || 626 this.model.Value === true || this.model.Value === false) { 627 $(_.template($('#variation_boolean_template').html(), {})).appendTo(this.$el); 628 this.model.Generated = [false, true]; 629 } 630 else if (!isNaN(this.model.Value)) { 631 var elem = $(_.template($('#variation_number_template').html(), {})); 632 elem.appendTo(this.$el) 633 $('input[name="generate"]', elem).click(function (evt) { self.openGenerator(evt); }); 634 if (!this.model.Generated) { 635 this.model.Generated = [0, 1, 2]; 636 } 637 var tev = new TableEditView({ model: this.model.Generated, el: $('div div', this.$el), editable: true }); 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 }); 638 833 tev.render(); 639 } 640 else if (this.model.Options) { 641 var osv = new OptionSelectionView({ model: this.model.Options, el: this.$el }); 642 this.listenTo(osv, 'changed', function (evt) { 643 self.selectionChanged(evt); 644 }); 645 if (!this.model.Generated) 646 this.model.Generated = []; 647 osv.render(); 648 for (var i = 0; i < this.model.Generated.length; i++) { 649 $('input[name="' + this.model.Generated[i] + '"]', this.$el).attr('checked', 'checked'); 650 } 651 } 652 }, 653 openGenerator: function (evt) { 654 var self = this; 655 var generator = new GeneratorDialog(); 656 this.listenTo(generator, 'success', function (data) { 657 self.doGenerate(data); 658 }); 659 generator.render(); 660 }, 661 doGenerate: function (data) { 662 if (data.minimum > data.maximum) { 663 var tmp = data.minimum; 664 data.minimum = data.maximum; 665 data.maximum = tmp; 666 } 667 if (data.step < 0) 668 data.step *= -1; 669 if (data.step == 0) 670 data.step = 1; 671 this.model.Generated = _.range(data.minimum, data.maximum + 1, data.step); 672 var tev = new TableEditView({ model: this.model.Generated, el: $('div div', this.$el), editable: true }); 673 tev.render(); 674 }, 675 selectionChanged: function (evt) { 676 if (!evt.checked) { 677 this.model.Generated = _.without(this.model.Generated, evt.name); 678 } else if (_.indexOf(this.model.Generated, evt.name) == -1) { 679 this.model.Generated.push(evt.name); 680 } 681 } 682 }); 683 684 var GeneratorDialog = Backbone.View.extend({ 685 render: function() { 686 var self = this; 687 var generator = $(_.template($('#variation_generator_template').html(),{})); 688 generator.dialog({ 689 buttons: { 690 "Abort": function () { 691 $(this).dialog("close"); 692 }, 693 "OK": function () { 694 $(this).dialog("close"); 695 self.trigger("success", { 696 minimum: parseInt($('input[name="minimum"]', generator).val()), 697 maximum: parseInt($('input[name="maximum"]', generator).val()), 698 step: parseFloat($('input[name="step"]', generator).val()) 699 }); 700 } 701 } 702 }); 703 } 704 }); 705 706 var VariationEntryView = Backbone.View.extend({ 707 render: function () { 708 var entryTemplate = _.template($('#variationentry_template').html(), this.model); 709 $(entryTemplate).appendTo(this.$el); 710 } 711 }); 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)); -
branches/OaaS/HeuristicLab.Services.Optimization.Web/Content/hl/Site.css
r9305 r9324 447 447 background: #EA8511; 448 448 } 449 450 .loader 451 { 452 width: 24px; 453 height: 24px; 454 } 455 456 .bigImage 457 { 458 text-align: center; 459 display: block; 460 margin-left: auto; 461 margin-right: auto; 462 } 463 464 .selectedRow 465 { 466 font-weight: bolder; 467 } 468 469 .experimentMenu 470 { 471 clear: left; 472 float: left; 473 display: inline; 474 }
Note: See TracChangeset
for help on using the changeset viewer.