master merge
[auf_rh_dae.git] / src / qbe / django_qbe / static / django_qbe / js / qbe.core.js
1 if (!window.qbe) {
2 var qbe = {};
3 }
4 qbe.CurrentModels = [];
5 qbe.CurrentRelations = [];
6 qbe.Core = function() {};
7
8 (function($) {
9 $(document).ready(function() {
10 /**
11 * Handle the loading initial data blocking process
12 */
13 var _loadingData = false;
14
15 /**
16 * Load initial data to edit query
17 */
18 qbe.Core.loadData = function(data) {
19 var initialForms, maxForms, totalForms;
20 _loadingData = true;
21 initialForms = parseInt(data["form-INITIAL_FORMS"]);
22 maxForms = parseInt(data["form-MAX_NUM_FORMS"]);
23 totalForms = parseInt(data["form-TOTAL_FORMS"]);
24 for(var i=initialForms; i<totalForms; i++) {
25 var appModel, splits, show, model, field, sorted;
26 appModel = data["form-"+ i +"-model"];
27 if (!(appModel in qbe.CurrentModels)) {
28 splits = appModel.split(".");
29 app = splits[0];
30 model = splits[1];
31 qbe.Core.addModule(app, model);
32 }
33 qbe.Core.updateModels();
34 $("#id_form-"+ i +"-model").val(appModel);
35 $("#id_form-"+ i +"-model").change();
36 field = data["form-"+ i +"-field"];
37 $("#id_form-"+ i +"-field").val(field);
38 $("#id_form-"+ i +"-field").change();
39 sorted = data["form-"+ i +"-sort"];
40 $("#id_form-"+ i +"-sort").val(sorted);
41 $("#id_form-"+ i +"-show").remove("checked");
42 if (data["form-"+ i +"-show"]) {
43 show = data["form-"+ i +"-show"];
44 if (show && show == "on") {
45 $("#id_form-"+ i +"-show").attr("checked", "checked");
46 }
47 }
48 c = 0;
49 criteria = data["form-"+ i +"-criteria_"+ c];
50 while(criteria) {
51 $("#id_form-"+ i +"-criteria_"+ c).val(criteria);
52 criteria = data["form-"+ i +"-criteria_"+ ++c];
53 }
54 }
55 $("#id_form_limit").val(data["limit"]);
56 var positions, positionSplits, splits, appModel, appName, modelName;
57 positions = data["positions"].split("|");
58 for(var i=0; i<positions.length; i++) {
59 splits = positions[i].split("@");
60 appModel = splits[0].split(".");
61 appName = appModel[0];
62 modelName = appModel[1];
63 positionSplits = splits[1].split(";");
64 if (!(appModel in qbe.CurrentModels)) {
65 $("#qbeModelItem_"+ modelName).toggleClass("selected");
66 qbe.Core.addModule(appName, modelName);
67 }
68 $("#qbeBox_"+ modelName).css({
69 left: positionSplits[0],
70 top: positionSplits[1]
71 });
72 }
73 $("#id_positions").val(data["positions"]);
74 _loadingData = false;
75 };
76
77 /**
78 * Toggle visibility of models
79 */
80 qbe.Core.toggleModel = function () {
81 var id, appName, modelName, idSplits, splits, $this;
82 $this = $(this);
83 idSplits = $this.attr("id").split("qbeModelAnchor_");
84 splits = idSplits[1].split(".");
85 appName = splits[0];
86 modelName = splits[1];
87 $("#qbeModelItem_"+ modelName).toggleClass("selected");
88 if ($("#qbeModelItem_"+ modelName).hasClass("selected")) {
89 qbe.Core.addModule(appName, modelName);
90 } else {
91 qbe.Core.removeModule(appName, modelName);
92 }
93 qbe.Core.updateModels();
94 return false;
95 }
96
97 /**
98 * Invokes the update of the each row
99 */
100 qbe.Core.updateModels = function() {
101 $(this).each(qbe.Core.updateRow);
102 };
103
104 /**
105 * Update the rows with the new models added
106 */
107 qbe.Core.updateRow = function(row) {
108 var options = ['<option value="">----</option>'];
109 for(i=0; i<qbe.CurrentModels.length; i++) {
110 var appModel = qbe.CurrentModels[i];
111 var key = appModel;
112 var value = appModel.replace(".", ": ");
113 options.push('<option value="'+ key +'">'+ value +'</option>');
114 }
115 $(".qbeFillModels").each(function() {
116 var val = $(this).val();
117 $(this).html(options.join(""));
118 $(this).val(val);
119 });
120 qbe.Core.alternatingRows();
121 };
122
123 /**
124 * Set a CSS class for alterned rows
125 */
126 qbe.Core.alternatingRows = function() {
127 var rows = "#qbeConditionsTable tbody tr";
128 $(rows).not(".add-row").removeClass("row1 row2");
129 $(rows +":even").not(".add-row").addClass("row1");
130 $(rows +":odd").not(".add-row").addClass("row2");
131 $(rows +":last").addClass("add-row");
132 };
133
134 /**
135 * Add rows per new relation with the models list hyphen separated
136 */
137 qbe.Core.addRelationsFrom = function(through) {
138 var appModels
139 appModels = through.split("-");
140 for(var i=0; i<appModels.length; i++) {
141 var appModel = appModels[i];
142 var splits = appModel.split(".");
143 qbe.Core.addModule(splits[0], splits[1]);
144 $("#qbeModelItem_"+ splits[1]).addClass("selected");
145 $("#qbeForm .add-row").click();
146 $(".qbeFillModels:last").val(splits[0] +"."+ splits[1]);
147 $(".qbeFillModels:last").change();
148 $(".qbeFillFields:last").val(splits[2]);
149 $(".qbeFillFields:last").change();
150 }
151 };
152
153 /**
154 * Event triggered when the SELECT tag for fill models is changed
155 */
156 qbe.Core.fillModelsEvent = function() {
157 var appModel, key, fields, splits, appModelSplits, allowed_fields, prefix, css, cssSplit, domTo, option, optFields, optPrimaries, optForeigns, optManies, style, value;
158 appModel = $(this).val();
159 if (appModel) {
160 appModelSplits = appModel.split(".");
161 fields = qbe.Models[appModelSplits[0]][appModelSplits[1]].fields;
162 allowed_fields = null;
163 if (qbe.AllowedFields !== null) {
164 try {
165 allowed_fields = qbe.AllowedFields[appModelSplits[0]][appModelSplits[1]];
166 } catch(e) {}
167 }
168 splits = $(this).attr("id").split("-");
169 prefix = splits.splice(0, splits.length-1).join("-");
170 css = $(this).attr("class");
171 cssSplit = css.split("to:")
172 domTo = prefix +"-"+ cssSplit[cssSplit.length-1];
173 optFields = [];
174 optPrimaries = [];
175 optForeigns = [];
176 optManies = [];
177 for(key_num in fields) {
178 // We can't jump fields with no target 'cause they are
179 // ManyToManyField and ForeignKey fields!
180 key = fields[key_num][0];
181 value = fields[key_num][1].label;
182 if (fields[key_num][1].type == "ForeignKey") {
183 style = "foreign";
184 option = '<option class="'+ style +'" value="'+ key +'">'+ value +'</option>'
185 optForeigns.push(option);
186 } else if (fields[key_num][1].type == "ManyToManyField") {
187 style = "many";
188 option = '<option class="'+ style +'" value="'+ key +'">'+ value +'</option>'
189 optManies.push(option);
190 } else if (fields[key_num][1].primary) {
191 style = "primary";
192 option = '<option class="'+ style +'" value="'+ key +'">'+ value +'</option>'
193 optPrimaries.push(option);
194 } else {
195 if (allowed_fields && allowed_fields.indexOf(key) < 0)
196 continue;
197 style = "";
198 option = '<option class="'+ style +'" value="'+ key +'">'+ value +'</option>'
199 optFields.push(option);
200 }
201 }
202 $("#"+ domTo).html('<option value="">*</option>' + optPrimaries.join("") + optForeigns.join("") + optManies.join("") + optFields.join(""));
203 // We need to raise change event
204 $("#"+ domTo).change();
205 }
206 };
207
208 /**
209 * Event triggered when the SELECT tag for fill fields is changed
210 */
211 qbe.Core.fillFieldsEvent = function() {
212 var field, splits, prefix, css, cssSplit, inputs, input, domTo, appModel, appModelSplits, fields, primary, target, targetRel, targetModel, targetStrings, targetString, relations;
213 field = $(this).val();
214 splits = $(this).attr("id").split("-");
215 prefix = splits.splice(0, splits.length-1).join("-");
216 css = $(this).attr("class");
217 cssSplit = css.split("enable:")
218 inputs = cssSplit[cssSplit.length-1].split(",");
219 for(var i=0; i<inputs.length; i++) {
220 input = inputs[i];
221 domTo = prefix +"-"+ input;
222 if (field) {
223 $("#"+ domTo).removeAttr("disabled");
224 } else {
225 $("#"+ domTo).attr("disabled", "disabled");
226 $("#"+ domTo).val("");
227 }
228 if ($("#"+ domTo).is('input[type="text"]')) {
229 appModel = $("#"+ prefix +"-model").val();
230 appModelSplits = appModel.split(".");
231 fields = qbe.Models[appModelSplits[0]][appModelSplits[1]].fields;
232 var found = false;
233 for (key_num in fields) {
234 key = fields[key_num][0];
235 if (field == key && fields[key_num][1].target) {
236 target = fields[key_num][1].target;
237 found = true;
238 break;
239 }
240
241 }
242 if (found && !_loadingData) {
243 if (target.through) {
244 $(this).parent().parent().children("td:last").children("a").click();
245 targetModel = qbe.Models[target.through.name][target.through.model];
246 targetsString = [];
247 relations = targetModel.relations;
248 for(var r=0; r<targetModel.relations.length; r++) {
249 targetRel = targetModel.relations[r];
250 targetString = target.through.name +"."+ target.through.model +"."+ targetRel.source;
251 targetsString.push(targetString);
252 }
253 qbe.Core.addRelationsFrom(targetsString.join("-"));
254 } else {
255 targetString = target.name +"."+ target.model +"."+ target.field;
256 $("#"+ domTo).val(targetString);
257 $("#"+ domTo).prev().val("join");
258 qbe.Core.addRelationsFrom(targetString);
259 }
260 } else {
261 $("#"+ domTo).val("");
262 }
263 }
264 }
265 };
266
267 /**
268 * Adds a model to the layer
269 */
270 qbe.Core.addModule = function (appName, modelName) {
271 var appModel, model, target1, target2;
272 model = qbe.Models[appName][modelName];
273 appModel = appName +"."+ modelName;
274 if (qbe.CurrentModels.indexOf(appModel) < 0) {
275 qbe.CurrentModels.push(appModel);
276 if (model.is_auto) {
277 target1 = model.relations[0].target;
278 target2 = model.relations[1].target;
279 qbe.Core.addModule(target1.name, target1.model);
280 qbe.Core.addModule(target2.name, target2.model);
281 } else {
282 qbe.Diagram.addBox(appName, modelName);
283 }
284 qbe.Core.updateRelations();
285 }
286 };
287
288 /*
289 * Removes a model from the layer
290 */
291 qbe.Core.removeModule = function(appName, modelName) {
292 var appModel = appName +"."+ modelName;
293 var pos = qbe.CurrentModels.indexOf(appModel);
294 if (pos >= 0) {
295 qbe.CurrentModels.splice(pos, 1);
296 var model = qbe.Models[appName][modelName];
297 qbe.Diagram.removeBox(appName, modelName)
298 qbe.Diagram.removeRelations(appName, modelName);
299 }
300 };
301
302 /*
303 * Update relations among models
304 */
305 qbe.Core.updateRelations = function () {
306 var label, labelStyle, paintStyle, backgroundPaintStyle, makeOverlay;
307 var relations, relation, mediumHeight, connections;
308 var sourceAppModel, sourceModelName, sourceAppName, sourceModel, sourceFieldName, sourceId, sourceField, sourceSplits, divSource;
309 var targetModel, targetAppName, targetModelName, targetFieldName, targetId, targetField, divTarget;
310 for(var i=0; i<qbe.CurrentModels.length; i++) {
311 sourceAppModel = qbe.CurrentModels[i];
312 sourceSplits = sourceAppModel.split(".");
313 sourceAppName = sourceSplits[0];
314 sourceModelName = sourceSplits[1];
315 sourceModel = qbe.Models[sourceAppName][sourceModelName];
316 relations = sourceModel.relations;
317 for(var j=0; j<relations.length; j++) {
318 relation = relations[j];
319 sourceFieldName = relation.source;
320 label = qbe.Diagram.Defaults["foreign"].label;
321 labelStyle = qbe.Diagram.Defaults["foreign"].labelStyle;
322 paintStyle = qbe.Diagram.Defaults["foreign"].paintStyle;
323 makeOverlays = qbe.Diagram.Defaults["foreign"].makeOverlays;
324 backgroundPaintStyle = qbe.Diagram.Defaults["foreign"].backgroundPaintStyle;
325 if (relation.target.through) {
326 if (qbe.Models[relation.target.through.name][relation.target.through.model].is_auto) {
327 targetModel = relation.target;
328 label = relation.target.through.model;
329 labelStyle = qbe.Diagram.Defaults["many"].labelStyle;
330 paintStyle = qbe.Diagram.Defaults["many"].paintStyle;
331 makeOverlays = qbe.Diagram.Defaults["many"].makeOverlays;
332 backgroundPaintStyle = qbe.Diagram.Defaults["many"].backgroundPaintStyle;
333 } else {
334 targetModel = relation.target.through;
335 }
336 } else {
337 targetModel = relation.target;
338 }
339 targetAppName = targetModel.name;
340 targetModelName = targetModel.model;
341 targetFieldName = targetModel.field;
342 sourceField = $("#qbeBoxField_"+ sourceAppName +"\\."+ sourceModelName +"\\."+ sourceFieldName);
343 targetField = $("#qbeBoxField_"+ targetAppName +"\\."+ targetModelName +"\\."+ targetFieldName);
344 if (sourceField.length && targetField.length
345 && !qbe.Diagram.hasConnection(sourceField, targetField)) {
346 sourceId = "qbeBox_"+ sourceModelName;
347 targetId = "qbeBox_"+ targetModelName;
348 divSource = document.getElementById(sourceId);
349 divTarget = document.getElementById(targetId);
350 if (divSource && divTarget) {
351 qbe.Diagram.addRelation(sourceId, sourceField, targetId, targetField, label, labelStyle, paintStyle, backgroundPaintStyle, makeOverlays());
352 }
353 }
354 }
355 }
356 }
357
358 });
359 })(jQuery.noConflict());