1 /*
  2  * SIMPLICITE - runtime & framework
  3  * http://www.simplicite.fr
  4  * Copyright (c)2006-2013 Simplicite Software. All rights reserved.
  5  */
  6 
  7 /** @ignore */
  8 Simplicite.Ajax.prototype.DEFAULT_INSTANCE_PREFIX = "ajax_";
  9 
 10 /**
 11  * Get a new business object.
 12  * <br/>Sample usage:
 13  * <pre>
 14  * // app is a Simplicite.Ajax instance
 15  * var obj = app.getBusinessObject("MyObject");
 16  * </pre>
 17  * @param objName Object name
 18  * @param objInstName Object instance name, optional (defauts to ajax_<object name>)
 19  * @param autoRefreshMetaData Automatic refresh of metadata at each call (defaults to false)
 20  * @function
 21  */
 22 Simplicite.Ajax.prototype.getBusinessObject = function(objName, objInstName, autoRefreshMetaData) {
 23 	if (!objName) return;
 24 	if (!objInstName) objInstName = this.DEFAULT_INSTANCE_PREFIX + objName;
 25 	if (!this._businessObjectsCache) this._businessObjectsCache = new Object();
 26 	var obj = this._businessObjectsCache[objName + ":" + objInstName];
 27 	if (!obj) {
 28 		obj = new Simplicite.Ajax.BusinessObject(this, objName, objInstName, autoRefreshMetaData);
 29 		this._businessObjectsCache[objName + ":" + objInstName] = obj;
 30 	}
 31 	return obj;
 32 };
 33 
 34 /**
 35  * Simplicité® business object.
 36  * <br/>Getting a new business object should use the <code>Simplicite.Ajax.getBusinessObject()</code> function instead of this constructor
 37  * @param app Application Simplicite.Ajax instance
 38  * @param objName Object name
 39  * @param objInstName Object instance name, optional (defauts to ajax_<object name>)
 40  * @param autoRefreshMetaData Automatic refresh of metadata at each call (defaults to false)
 41  * @class
 42  */
 43 Simplicite.Ajax.BusinessObject = function(app, objName, objInstName, autoRefreshMetaData) {
 44 	/** @ignore */
 45 	this._app = app;
 46 
 47 	/** @ignore */
 48 	this._autoRefreshMetaData = (autoRefreshMetaData !== undefined) ? Boolean(autoRefreshMetaData) : false;
 49 
 50 	/**
 51 	 * Current meta data.
 52 	 * <ul>
 53 	 * <li>name: object name</li>
 54 	 * <li>instance: object instance name</li>
 55 	 * <li>fields: fields definition array</li>
 56 	 * <li>TO BE COMPLETED...</li>
 57 	 * </ul>
 58 	 * @field
 59 	 */
 60 	this.metadata = {
 61 		name : objName,
 62 		instance : (objInstName ? objInstName : this.DEFAULT_INSTANCE_PREFIX + objName),
 63 		rowidfield : "row_id"
 64 	};
 65 
 66 	/**
 67 	 * Current item. Use item["<field name>"] or item.<field name> to access to the field value
 68 	 * @field
 69 	 */
 70 	this.item = new Object();
 71 
 72 	/**
 73 	 * Current search filters. Use filters["<field name>"] or filters.<field name> to access to the filter value
 74 	 * @field
 75 	 */
 76 	this.filters = new Object();
 77 
 78 	/**
 79 	 * Current search result count.
 80 	 * @field
 81 	 */
 82 	this.count = 0;
 83 
 84 	/**
 85 	 * Current search result array of items.
 86 	 * @field
 87 	 */
 88 	this.list = new Array();
 89 
 90 	/**
 91 	 * Current search result max page index (for paginated searches).
 92 	 * @field
 93 	 */
 94 	this.maxpage = 0;
 95 
 96 	/**
 97 	 * Current search result page index (for paginated searches).
 98 	 * @field
 99 	 */
100 	this.page = 0;
101 
102 	/**
103 	 * Current cross table data.
104 	 * @field
105 	 */
106 	this.crosstabdata = new Object();
107 
108 	// Initialy (and synchronously) loads meta data if auto refresh meta data is set
109 	if (this._autoRefreshMetaData)
110 		this.getMetaData(undefined, { async: false });
111 };
112 
113 /**
114  * Loads meta data for specified context.
115  * <br/>Sample usage:
116  * <pre>
117  * obj.getMetaData(function() {
118  * 	alert("Meta data loaded for update of object " + this.getName());
119  * }, { context: app.CONTEXT_UPDATE });
120  * </pre>
121  * @param callback Callback function called when loading is completed
122  * @param params Optional parameters :
123  * <ul>
124  * <li>context Context (one of Simplicite.Ajax.CONTEXT_* constants)</li>
125  * <li>contextParam Context parameter</li>
126  * <li>async Asynchronous call (use default if absent) ?</li>
127  * <li>error Custom error handler (use default error handler if absent) ?</li>
128  * </ul>
129  * @function
130  */
131 Simplicite.Ajax.BusinessObject.prototype.getMetaData = function(callback, params) {
132 	var s = this._app;
133 	var url = s._objURL + "?action=metadata&object=" + this.metadata.name + "&inst=" + this.metadata.instance;
134 	if (params === undefined)
135 		params = new Object();
136 	if (params.context !== undefined) {
137 		url += "&context=" + params.context;
138 		if (params.contextParam !== undefined)
139 			url += "&contextparam=" + encodeURIComponent(params.contextParam);
140 	}
141 	return s._call(params.async, url, undefined, function(r) {
142 		if (r.type == "error") {
143 			if (params.error !== undefined)
144 				params.error.call(this, r.response);
145 			else
146 				s.error(r.response);
147 		} else {
148 			this.metadata = r.response;
149 			if (callback !== undefined)
150 				callback.call(this, this.metadata);
151 		}
152 	}, this);
153 };
154 
155 /**
156  * Gets name from meta data.
157  * @function
158  */
159 Simplicite.Ajax.BusinessObject.prototype.getName = function() {
160 	return this.metadata.name;
161 };
162 
163 /**
164  * Gets instance name from meta data.
165  * @function
166  */
167 Simplicite.Ajax.BusinessObject.prototype.getInstance = function() {
168 	return this.metadata.instance;
169 };
170 
171 /**
172  * Gets label from meta data (is undefined as long as meta data are not loaded using <code>getMetaData</code>).
173  * @function
174  */
175 Simplicite.Ajax.BusinessObject.prototype.getLabel = function() {
176 	return this.metadata.label;
177 };
178 
179 /**
180  * Gets help from meta data (is undefined as long as meta data are not loaded using <code>getMetaData</code>).
181  * @function
182  */
183 Simplicite.Ajax.BusinessObject.prototype.getHelp = function() {
184 	return this.metadata.help;
185 };
186 
187 /**
188  * Gets fields array from meta data (is undefined as long as meta data are not loaded using <code>getMetaData</code>).
189  * @function
190  */
191 Simplicite.Ajax.BusinessObject.prototype.getFields = function() {
192 	return this.metadata.fields;
193 };
194 
195 /**
196  * Gets links array from meta data (is undefined as long as meta data are not loaded using <code>getMetaData</code>).
197  * @function
198  */
199 Simplicite.Ajax.BusinessObject.prototype.getLinks = function() {
200 	return this.metadata.links;
201 };
202 
203 /**
204  * Gets field from fields array in meta data (returns undefined if field is not found).
205  * @param name Field name
206  * @function
207  */
208 Simplicite.Ajax.BusinessObject.prototype.getField = function(name) {
209 	var n = 0;
210 	var fs = this.getFields();
211 	while (n < fs.length && fs[n].name != name) n++;
212 	return (n == fs.length ? undefined : fs[n]);
213 };
214 
215 /**
216  * Gets list of values field value from code (returns code if not found or not a list of value field)
217  * @param field Field
218  * @param code Field code
219  * @function
220  */
221 Simplicite.Ajax.BusinessObject.prototype.getValueForCode = function(field, code) {
222 	var n = 0;
223 	var l = field.listOfValues;
224 	if (l === undefined) return code;
225 	while (n < l.length && l[n].code != code) n++;
226 	return (n == l.length ? code : l[n].value);
227 };
228 
229 /**
230  * Gets row Id field name from meta data (is undefined as long as meta data are not loaded using <code>getMetaData</code>).
231  * @function
232  */
233 Simplicite.Ajax.BusinessObject.prototype.getRowIdFieldName = function() {
234 	return this.metadata.rowidfield;
235 };
236 
237 /**
238  * Gets row Id field from meta data (returns undefined if row Id field name is undefined).
239  * @function
240  */
241 Simplicite.Ajax.BusinessObject.prototype.getRowIdField = function() {
242 	return this.getField(this.getRowIdFieldName());
243 };
244 
245 /**
246  * Gets value from list for specified code (returns undefined if code is not in list).
247  * @param list List metadata (typically from a field metadata)
248  * @param code Code
249  * @function
250  */
251 Simplicite.Ajax.BusinessObject.prototype.getListValue = function(list, code) {
252 	for (var i = 0; i < list.length; i++) {
253 		var l = list[i];
254 		if (l.code == code) return l.value;
255 	}
256 	return undefined;
257 };
258 
259 /**
260  * Selects and loads an item for designated row ID (if row ID is Simplicite.Ajax.DEFAULT_ROW_ID, a defaut item for creation is returned with all default values applied).
261  * @param callback Callback function called when loading is completed
262  * @param rowId Row ID, mandatory
263  * @param params Optional parameters object may include:
264  * <ul>
265  * <li>context Init context (one of Simplicite.Ajax.CONTEXT_CREATE/UPDATE/DELETE/COPY constants)</li>
266  * <li>inlineDocs Inline documents (false if absent or undefined, can be a boolean or an array of document fields to inline) ?</li>
267  * <li>inlineThumbs Inline image documents thumbnails (false if absent or undefined, can be a boolean or an array of image document fields to inline) ?</li>
268  * <li>inlineObjs Inline objects fields items (false if absent or undefined, can be a boolean or an array of object fields to inline) ?</li>
269  * <li>fields Array of field names to retreive (if absent or undefined, all fields are retreived)</li>
270  * <li>async Asynchronous call (use default if absent or undefined) ?</li>
271  * <li>error Custom error handler (use default error handler if absent) ?</li>
272  * <ul>
273  * @function
274  */
275 Simplicite.Ajax.BusinessObject.prototype.get = function(callback, rowId, params) {
276 	var s = this._app;
277 	var url = s._objURL + "?action=get&object=" + this.metadata.name + "&inst=" + this.metadata.instance;
278 	if (params === undefined)
279 		params = new Object();
280 	if (params.context !== undefined)
281 		url += "&context=" + params.context;
282 	var id = params.inlineDocs;
283 	if (id !== undefined)
284 		url += "&inline_documents=" + (id.join ? id.join(",") : id);
285 	var it = params.inlineThumbs;
286 	if (it !== undefined)
287 		url += "&inline_thumbnails=" + (it.join ? it.join(",") : it);
288 	var io = params.inlineObjs;
289 	if (io !== undefined)
290 		url += "&inline_objects=" + (io.join ? io.join(",") : io);
291 	if (params.fields !== undefined) {
292 		for (var i = 0; i < params.fields.length; i++) {
293 			url += "&fields=" + params.fields[i].replace(".", "__");
294 		}
295 	}
296 	var p = new Object();
297 	p[this.metadata.rowidfield] = rowId ? rowId : this.item[this.metadata.rowidfield];
298 	return s._call(params.async, url, p, function(r) {
299 		if (r.type == "error") {
300 			this.item = new Object();
301 			if (params.error !== undefined)
302 				params.error.call(this, r.response);
303 			else
304 				s.error(r.response);
305 		} else {
306 			this.item = r.response;
307 			if (!this._autoRefreshMetaData) {
308 				if (callback !== undefined)
309 					callback.call(this, this.item);
310 			} else
311 				this.getMetaData(function() {
312 					if (callback !== undefined)
313 						callback.call(this, this.item);
314 				}, {
315 					context : params.context,
316 					async : params.async
317 				});
318 		}
319 	}, this);
320 };
321 
322 /**
323  * Same as get function
324  * @function
325  */
326 Simplicite.Ajax.BusinessObject.prototype.select = Simplicite.Ajax.BusinessObject.prototype.get;
327 
328 /**
329  * Loads default item for creation (equivalent to a get done on default row ID with the create init context Simplicite.Ajax.CONTEXT_CREATE).
330  * @param callback Callback function called when loading is completed
331  * @param params Optional parameters (same as for get function)
332  * @function
333  */
334 Simplicite.Ajax.BusinessObject.prototype.getForCreate = function(callback, params) {
335 	if (params === undefined)
336 		params = new Object();
337 	params.context = this._app.CONTEXT_CREATE;
338 	this.get(callback, this._app.DEFAULT_ROW_ID, params);
339 };
340 
341 /**
342  * Same as getForCreate function
343  * @function
344  */
345 Simplicite.Ajax.BusinessObject.prototype.selectForCreate = Simplicite.Ajax.BusinessObject.prototype.getForCreate;
346 
347 /**
348  * Loads item for designated row ID for update (equivalent to a get done with the update init context Simplicite.Ajax.CONTEXT_UPDATE).
349  * @param callback Callback function called when loading and context initialization is completed
350  * @param rowId Row ID, mandatory
351  * @param params Optional parameters (same as for get function)
352  * @function
353  */
354 Simplicite.Ajax.BusinessObject.prototype.getForUpdate = function(callback, rowId, params) {
355 	if (params === undefined)
356 		params = new Object();
357 	params.context = this._app.CONTEXT_UPDATE;
358 	this.get(callback, rowId, params);
359 };
360 
361 /**
362  * Same as getForUpdate function
363  * @function
364  */
365 Simplicite.Ajax.BusinessObject.prototype.selectForUpdate = Simplicite.Ajax.BusinessObject.prototype.getForUpdate;
366 
367 /**
368  * Loads item for designated row ID for copy (equivalent to a get done with the copy init context Simplicite.Ajax.CONTEXT_COPY).
369  * @param callback Callback function called when loading and context initialization is completed
370  * @param rowId Row ID, mandatory
371  * @param params Optional parameters (same as for get function)
372  * @function
373  */
374 Simplicite.Ajax.BusinessObject.prototype.getForCopy = function(callback, rowId, params) {
375 	if (params === undefined)
376 		params = new Object();
377 	params.context = this._app.CONTEXT_COPY;
378 	this.get(callback, rowId, params);
379 };
380 
381 /**
382  * Same as getForCopy function
383  * @function
384  */
385 Simplicite.Ajax.BusinessObject.prototype.selectForCopy = Simplicite.Ajax.BusinessObject.prototype.getForCopy;
386 
387 /**
388  * Loads item for designated row ID for delete (equivalent to a get done with the delete init context Simplicite.Ajax.CONTEXT_DELETE).
389  * @param callback Callback function called when loading and context initialization is completed
390  * @param rowId Row ID, mandatory
391  * @param params Optional parameters (same as for get function)
392  * @function
393  */
394 Simplicite.Ajax.BusinessObject.prototype.getForDelete = function(callback, rowId, params) {
395 	if (params === undefined)
396 		params = new Object();
397 	params.context = this._app.CONTEXT_DELETE;
398 	this.get(callback, rowId, params);
399 };
400 
401 /**
402  * Same as getForDelete function
403  * @function
404  */
405 Simplicite.Ajax.BusinessObject.prototype.selectForDelete = Simplicite.Ajax.BusinessObject.prototype.getForDelete;
406 
407 /**
408  * Gets current item row Id value (returns undefined if not current item is loaded).
409  * @function
410  */
411 Simplicite.Ajax.BusinessObject.prototype.getRowId = function() {
412 	if (this.item !== undefined)
413 		return this.item[this.getRowIdFieldName()];
414 };
415 
416 /**
417  * Populate item (e.g. after getForCreate and after having set foreign keys)
418  * @param callback Callback function called when loading is completed
419  * @param item Item to be populated, optional (if absent current item is used)
420  * @param params Optional parameters object may include:
421  * <ul>
422  * <li>inlineDocs Inline documents (false if absent or undefined, can be a boolean or an array of document fields to inline) ?</li>
423  * <li>inlineThumbs Inline image documents thumbnails (false if absent or undefined, can be a boolean or an array of image document fields to inline) ?</li>
424  * <li>inlineObjs Inline object fields items (false if absent or undefined, can be a boolean or an array of object fields to inline) ?</li>
425  * <li>async Asynchronous call (use default if absent or undefined) ?</li>
426  * <li>error Custom error handler (use default error handler if absent) ?</li>
427  * </ul>
428  * @function
429  */
430 Simplicite.Ajax.BusinessObject.prototype.populate = function(callback, item, params) {
431 	var s = this._app;
432 	if (item !== undefined)
433 		this.item = item;
434 	var url = s._objURL + "?action=populate&object=" + this.metadata.name + "&inst=" + this.metadata.instance;
435 	if (params === undefined)
436 		params = new Object();
437 	var id = params.inlineDocs;
438 	if (id !== undefined)
439 		url += "&inline_documents=" + (id.join ? id.join(",") : id);
440 	var it = params.inlineThumbs;
441 	if (it !== undefined)
442 		url += "&inline_thumbnails=" + (it.join ? it.join(",") : it);
443 	var io = params.inlineObjs;
444 	if (io !== undefined)
445 		url += "&inline_objects=" + (io.join ? io.join(",") : io);
446 	return s._call(params.async, url, this.item, function(r) {
447 		if (r.type == "error") {
448 			this.item = new Object();
449 			if (params.error !== undefined)
450 				params.error.call(this, r.response);
451 			else
452 				s.error(r.response);
453 		} else {
454 			this.item = r.response;
455 			if (callback !== undefined)
456 				callback.call(this, this.item);
457 		}
458 	}, this);
459 };
460 
461 /**
462  * Loads current filters.
463  * @param callback Callback function called when loading is completed
464  * @param params Optional parameters :
465  * <ul>
466  * <li>context Init context (normally Simplicite.Ajax.CONTEXT_SEARCH constant), optional</li>
467  * <li>reset Reset filters, optional</li>
468  * <li>async Asynchronous call (use default if absent) ?</li>
469  * <li>error Custom error handler (use default error handler if absent) ?</li>
470  * </ul>
471  * @function
472  */
473 Simplicite.Ajax.BusinessObject.prototype.getFilters = function(callback, params) {
474 	var s = this._app;
475 	var url = s._objURL + "?action=filters&object=" + this.metadata.name + "&inst=" + this.metadata.instance;
476 	if (params === undefined)
477 		params = new Object();
478 	if (params.context !== undefined)
479 		url += "&context=" + params.context;
480 	if (params.reset !== undefined)
481 		url += "&reset=" + params.reset;
482 	return s._call(params.async, url, undefined, function(r) {
483 		if (r.type == "error") {
484 			this.filters = new Object();
485 			if (params.error !== undefined)
486 				params.error.call(this, r.response);
487 			else
488 				s.error(r.response);
489 		} else {
490 			this.filters = r.response;
491 			if (!this._autoRefreshMetaData) {
492 				if (callback !== undefined)
493 					callback.call(this, this.filters);
494 			} else
495 				this.getMetaData(function() {
496 					if (callback !== undefined)
497 						callback.call(this, this.filters);
498 				}, {
499 					context : params.context,
500 					async : params.async
501 				});
502 		}
503 	}, this);
504 };
505 
506 /**
507  * Loads current filters for search (equivalent to a getFilters done with the search init context Simplicite.Ajax.CONTEXT_SEARCH).
508  * @param callback Callback function called when loading is completed
509  * @param params Optional parameters
510  * @function
511  */
512 Simplicite.Ajax.BusinessObject.prototype.getFiltersForSearch = function(callback, params) {
513 	if (params === undefined)
514 		params = new Object();
515 	params.context = this._app.CONTEXT_SEARCH;
516 	return this.getFilters(callback, params);
517 };
518 
519 /**
520  * Search and loads search result items.
521  * @param callback Callback function called when loading is completed
522  * @param filters Filters to be applied, optional (if absent, current filters are used)
523  * @param params Optional parameters :
524  * <ul>
525  * <li>context Init context (normally one of Simplicite.Ajax.CONTEXT_LIST/PANELLIST/REFSELECT/DATAMAPSELECT/EXPORT/CROSSTAB/GRAPH/PRINTTMPL constant), optional</li>
526  * <li>page Page index to retreive (must be between 1 and maxpage), optional (if absent or set to 0 no pagination will be done, for pagination a first call must be done with pageIndex set to 1)</li>
527  * <li>inlineDocs Inline documents (false if absent or undefined, can be a boolean or an array of document fields to inline) ?</li>
528  * <li>inlineThumbs Inline image documents thumbnails (false if absent or undefined) ?</li>
529  * <li>inlineObjs Inline objects fields items (false if absent or undefined, can be a boolean or an array of object fields to inline) ?</li>
530  * <li>async Asynchronous call (use default if absent) ?</li>
531  * <li>error Custom error handler (use default error handler if absent) ?</li>
532  * </ul>
533  * @function
534  */
535 Simplicite.Ajax.BusinessObject.prototype.search = function(callback, filters, params) {
536 	var s = this._app;
537 	if (filters !== undefined)
538 		this.filters = filters;
539 	var url = s._objURL + "?action=search&object=" + this.metadata.name + "&inst=" + this.metadata.instance;
540 	if (params === undefined)
541 		params = new Object();
542 	if (params.context !== undefined)
543 		url += "&context=" + params.context;
544 	if (params.page !== undefined)
545 		url += "&page=" + params.page;
546 	var id = params.inlineDocs;
547 	if (id !== undefined)
548 		url += "&inline_documents=" + (id.join ? id.join(",") : id);
549 	var it = params.inlineThumbs;
550 	if (it !== undefined)
551 		url += "&inline_thumbnails=" + (it.join ? it.join(",") : it);
552 	var io = params.inlineObjs;
553 	if (io !== undefined)
554 		url += "&inline_objects=" + (io.join ? io.join(",") : io);
555 	return s._call(params.async, url, this.filters, function(r) {
556 		if (r.type == "error") {
557 			this.count = 0;
558 			this.list = new Array();
559 			this.maxpage = 0;
560 			this.page = 0;
561 			if (params.error !== undefined)
562 				params.error.call(this, r.response);
563 			else
564 				s.error(r.response);
565 		} else {
566 			var res = r.response;
567 			this.count = res.count;
568 			if (res.count > 0) {
569 				this.list = res.list;
570 				this.maxpage = res.maxpage;
571 				this.page = res.page;
572 			} else {
573 				this.list = new Array();
574 				this.maxpage = 0;
575 				this.page = 0;
576 			}
577 			if (!this._autoRefreshMetaData) {
578 				if (callback !== undefined)
579 					callback.call(this, this.list);
580 			} else
581 				this.getMetaData(function() {
582 					if (callback !== undefined)
583 						callback.call(this, this.list);
584 				}, {
585 					context : params.context,
586 					async : params.async
587 				});
588 		}
589 	}, this);
590 };
591 
592 /**
593  * Search and loads search result items for list (equivalent to a search done with the list init context Simplicite.Ajax.CONTEXT_LIST).
594  * @param callback Callback function called when loading is completed
595  * @param filters Filters to be applied, optional (if absent, current filters are used)
596  * @param params Optional parameters
597  * @function
598  */
599 Simplicite.Ajax.BusinessObject.prototype.searchForList = function(callback, filters, params) {
600 	if (params === undefined)
601 		params = new Object();
602 	params.context = this._app.CONTEXT_LIST;
603 	this.search(callback, filters, params);
604 };
605 
606 /**
607  * Search and loads search result items for panel list (equivalent to a search done with the list init context Simplicite.Ajax.CONTEXT_PANELLIST).
608  * @param callback Callback function called when loading is completed
609  * @param filters Filters to be applied, optional (if absent, current filters are used)
610  * @param params Optional parameters
611  * @function
612  */
613 Simplicite.Ajax.BusinessObject.prototype.searchForPanelList = function(callback, filters, params) {
614 	if (params === undefined)
615 		params = new Object();
616 	params.context = this._app.CONTEXT_PANELLIST;
617 	this.search(callback, filters, params);
618 };
619 
620 /**
621  * Saves (create or update) and loads an item.
622  * @param callback Callback function called when loading is completed
623  * @param item Item to be saved, optional (if absent current item is used)
624  * @param params Optional parameters
625  * @function
626  */
627 Simplicite.Ajax.BusinessObject.prototype.save = function(callback, item, params) {
628 	if (item !== undefined)
629 		this.item = item;
630 	if (this.item[this.metadata.rowidfield] == this._app.DEFAULT_ROW_ID)
631 		this.create(callback, item, params);
632 	else
633 		this.update(callback, item, params);
634 };
635 
636 /**
637  * Creates and loads an item.
638  * @param callback Callback function called when loading is completed
639  * @param item Item to be created (row ID field of the item must be set to Simplicite.Ajax.DEFAULT_ROW_ID), optional (if absent current item is used)
640  * @param params Optional parameters :
641  * <ul>
642  * <li>async Asynchronous call (use default if absent) ?</li>
643  * <li>error Custom error handler (use default error handler if absent) ?</li>
644  * </ul>
645  * @function
646  */
647 Simplicite.Ajax.BusinessObject.prototype.create = function(callback, item, params) {
648 	var s = this._app;
649 	if (item !== undefined)
650 		this.item = item;
651 	var url = s._objURL + "?action=create&object=" + this.metadata.name + "&inst=" + this.metadata.instance;
652 	if (params === undefined)
653 		params = new Object();
654 	return s._call(params.async, url, this.item, function(r) {
655 		if (r.type == "error") {
656 			this.item = new Object();
657 			if (params.error !== undefined)
658 				params.error.call(this, r.response);
659 			else
660 				s.error(r.response);
661 		} else {
662 			this.item = r.response;
663 			if (!this._autoRefreshMetaData) {
664 				if (callback !== undefined)
665 					callback.call(this, this.item);
666 			} else
667 				this.getMetaData(function() {
668 					if (callback !== undefined)
669 						callback.call(this, this.item);
670 				}, {
671 					context : params.context,
672 					async : params.async
673 				});
674 		}
675 	}, this);
676 };
677 
678 /**
679  * Updates and loads an item.
680  * @param callback Callback function called when loading is completed
681  * @param item Item to be updated, optional (if absent current item is used)
682  * @param params Optional parameters :
683  * <ul>
684  * <li>async Asynchronous call (use default if absent) ?</li>
685  * <li>error Custom error handler (use default error handler if absent) ?</li>
686  * </li>
687  * @function
688  */
689 Simplicite.Ajax.BusinessObject.prototype.update = function(callback, item, params) {
690 	var s = this._app;
691 	if (item !== undefined)
692 		this.item = item;
693 	var url = s._objURL + "?action=update&object=" + this.metadata.name + "&inst=" + this.metadata.instance;
694 	if (params === undefined)
695 		params = new Object();
696 	return s._call(params.async, url, this.item, function(r) {
697 		if (r.type == "error") {
698 			this.item = new Object();
699 			if (params.error !== undefined)
700 				params.error.call(this, r.response);
701 			else
702 				s.error(r.response);
703 		} else {
704 			this.item = r.response;
705 			if (!this._autoRefreshMetaData) {
706 				if (callback !== undefined)
707 					callback.call(this, this.item);
708 			} else
709 				this.getMetaData(function() {
710 					if (callback !== undefined)
711 						callback.call(this, this.item);
712 				}, {
713 					context : params.context,
714 					async : params.async
715 				});
716 		}
717 	}, this);
718 };
719 
720 /**
721  * Deletes item. Current item is set to undefined.
722  * @param callback Callback function called when loading is completed
723  * @param item Item to be deleted (in fact only row ID field is used), optional (if absent current item is used)
724  * @param params Optional parameters :
725  * <ul>
726  * <li>async Asynchronous call (use default if absent) ?</li>
727  * <li>error Custom error handler (use default error handler if absent) ?</li>
728  * </ul>
729  * @function
730  */
731 Simplicite.Ajax.BusinessObject.prototype.del = function(callback, item, params) {
732 	var s = this._app;
733 	if (item !== undefined)
734 		this.item = item;
735 	var url = s._objURL + "?action=delete&object=" + this.metadata.name + "&inst=" + this.metadata.instance + "&" + this.metadata.rowidfield + "=" + this.item[this.metadata.rowidfield];
736 	if (params === undefined)
737 		params = new Object();
738 	return s._call(params.async, url, undefined, function(r) {
739 		if (r.type == "error") {
740 			if (params.error !== undefined)
741 				params.error.call(this, r.response);
742 			else
743 				s.error(r.response);
744 		} else {
745 			this.item = new Object();
746 			if (!this._autoRefreshMetaData) {
747 				if (callback !== undefined)
748 					callback.call(this);
749 			} else
750 				this.getMetaData(function() {
751 					if (callback !== undefined)
752 						callback.call(this);
753 				}, {
754 					context : params.context,
755 					async : params.async
756 				});
757 		}
758 	}, this);
759 };
760 
761 /**
762  * Loads cross table data for search filters.
763  * @param callback Callback function called when loading is completed
764  * @param ctb Cross table name
765  * @param filters Filters to be applied, optional (if absent, current filters are used)
766  * @param params Optional parameters :
767  * <ul>
768  * <li>async Asynchronous call (use default if absent) ?</li>
769  * <li>error Custom error handler (use default error handler if absent) ?</li>
770  * </ul>
771  * @function
772  */
773 Simplicite.Ajax.BusinessObject.prototype.crosstab = function(callback, ctb, filters, params) {
774 	var s = this._app;
775 	if (filters !== undefined)
776 		this.filters = filters;
777 	var url = s._objURL + "?action=crosstab&object=" + this.metadata.name + "&inst=" + this.metadata.instance + "&crosstab=" + ctb;
778 	if (params === undefined)
779 		params = new Object();
780 	return s._call(params.async, url, this.filters, function(r) {
781 		if (r.type == "error") {
782 			this.crosstabdata = new Object();
783 			if (params.error !== undefined)
784 				params.error.call(this, r.response);
785 			else
786 				s.error(r.response);
787 		} else {
788 			this.crosstabdata = r.response;
789 			if (!this._autoRefreshMetaData) {
790 				if (callback !== undefined)
791 					callback.call(this, this.crosstabdata);
792 			} else
793 				this.getMetaData(function() {
794 					if (callback !== undefined)
795 						callback.call(this, this.crosstabdata);
796 				}, {
797 					context : params.context,
798 					async : params.async
799 				});
800 		}
801 	}, this);
802 };
803 
804 /**
805  * Gets cross table data chart JPG image for search filters.
806  * @param callback Callback function called when loading is completed
807  * @param ctb Cross table name
808  * @param filters Filters to be applied, optional (if absent, current filters are used)
809  * @param params Optional parameters :
810  * <ul>
811  * <li>async Asynchronous call (use default if absent) ?</li>
812  * <li>error Custom error handler (use default error handler if absent) ?</li>
813  * <ul>
814  * @function
815  */
816 Simplicite.Ajax.BusinessObject.prototype.crosstabChartImage = function(callback, ctb, filters, params) {
817 	var s = this._app;
818 	if (filters !== undefined)
819 		this.filters = filters;
820 	var url = s._objURL + "?action=chart&object=" + this.metadata.name + "&inst=" + this.metadata.instance + "&crosstab=" + ctb;
821 	if (params === undefined)
822 		params = new Object();
823 	return s._call(params.async, url, this.filters, function(r) {
824 		if (r.type == "error") {
825 			if (params.error !== undefined)
826 				params.error.call(this, r.response);
827 			else
828 				s.error(r.response);
829 		} else {
830 			var chart = r.response.chart;
831 			if (!this._autoRefreshMetaData) {
832 				if (callback !== undefined)
833 					callback.call(this, chart);
834 			} else
835 				this.getMetaData(function() {
836 					if (callback !== undefined)
837 						callback.call(this, chart);
838 				}, {
839 					context : params.context,
840 					async : params.async
841 				});
842 		}
843 	}, this);
844 };
845 
846 /**
847  * Calls an object action and loads action result.
848  * @param callback Callback function called when loading is completed (action result is passed to this function)
849  * @param act Action name
850  * @param params Optional parameters :
851  * <ul>
852  * <li>async Asynchronous call (use default if absent) ?</li>
853  * <li>error Custom error handler (use default error handler if absent) ?</li>
854  * </ul>
855  * @function
856  */
857 Simplicite.Ajax.BusinessObject.prototype.action = function(callback, act, params) {
858 	var s = this._app;
859 	var url = s._objURL + "?action=" + act + "&object=" + this.metadata.name + "&inst=" + this.metadata.instance;
860 	if (params === undefined)
861 		params = new Object();
862 	var p = new Object();
863 	if (this.item && this.item[this.metadata.rowidfield])
864 		p[this.metadata.rowidfield] = this.item[this.metadata.rowidfield];
865 	var a = s._call(params.async, url, p, function(r) {
866 		if (r.type == "error") {
867 			if (params.error !== undefined)
868 				params.error.call(this, r.response);
869 			else
870 				s.error(r.response);
871 		} else {
872 			var res = r.response.result;
873 			if (!this._autoRefreshMetaData) {
874 				if (callback !== undefined)
875 					callback.call(this, res);
876 			} else
877 				this.getMetaData(function() {
878 					if (callback !== undefined)
879 						callback.call(this, res);
880 				}, {
881 					context : params.context,
882 					async : params.async
883 				});
884 		}
885 	}, this);
886 	if (a !== undefined && a.result !== undefined) return a.result;
887 };
888 
889 /**
890  * Calls an object publication and loads publication result.
891  * @param callback Callback function called when loading is completed (publication result is passed to this function)
892  * @param prt Print template name
893  * @param params Optional parameters :
894  * <ul>
895  * <li>all Apply template to all items matching current filters (false by default, which means apply template only to current item) ?</li>
896  * <li>mailing Apply template individually to all items matching current filter (false by default) ?</li>
897  * <li>async Asynchronous call (use default if absent) ?</li>
898  * <li>error Custom error handler (use default error handler if absent) ?</li>
899  * </ul>
900  * @function
901  */
902 Simplicite.Ajax.BusinessObject.prototype.print = function(callback, prt, params) {
903 	var s = this._app;
904 	var url = s._objURL + "?action=print&object=" + this.metadata.name + "&inst=" + this.metadata.instance + "&printtemplate=" + prt;
905 	if (params === undefined)
906 		params = new Object();
907 	if (params.all !== undefined)
908 		url += "&all=" + params.all;
909 	if (params.mailing !== undefined)
910 		url += "&mailing=" + params.mailing;
911 	var p = new Object();
912 	if (this.item && this.item[this.metadata.rowidfield])
913 		p[this.metadata.rowidfield] = + this.item[this.metadata.rowidfield];
914 	return s._call(params.async, url, p, function(r) {
915 		if (r.type == "error") {
916 			if (params.error !== undefined)
917 				params.error.call(this, r.response);
918 			else
919 				s.error(r.response);
920 		} else {
921 			var res = r.response;
922 			if (!this._autoRefreshMetaData) {
923 				if (callback !== undefined)
924 					callback.call(this, res);
925 			} else
926 				this.getMetaData(function() {
927 					if (callback !== undefined)
928 						callback.call(this, res);
929 				}, {
930 					context : params.context,
931 					async : params.async
932 				});
933 		}
934 	}, this);
935 };
936 
937 /**
938  * Sets (or remove) an object parameter and loads it back.
939  * @param callback Callback function called when loading is completed (parameter is passed to this function)
940  * @param name Parameter name
941  * @param value Parameter value (if undefined parameter is unset)
942  * @param params Optional parameters :
943  * <ul>
944  * <li>async Asynchronous call (use default if absent) ?</li>
945  * <li>error Custom error handler (use default error handler if absent) ?</li>
946  * </ul>
947  * @function
948  */
949 Simplicite.Ajax.BusinessObject.prototype.setParameter = function(callback, name, value, params) {
950 	var s = this._app;
951 	var url = s._objURL + "?action=setparameter&object=" + this.metadata.name + "&inst=" + this.metadata.instance;
952 	if (params === undefined)
953 		params = new Object();
954 	var p = { name : name };
955 	if (value !== undefined)
956 		p.value = value;
957 	var r = s._call(params.async, url, p, function(r) {
958 		if (r.type == "error") {
959 			if (params.error !== undefined)
960 				params.error.call(this, r.response);
961 			else
962 				s.error(r.response);
963 		} else {
964 			var res = r.response.result;
965 			if (callback !== undefined)
966 				callback.call(this, res);
967 		}
968 	}, this);
969 	if (r !== undefined && r.result !== undefined) return r.result;
970 };
971 
972 /**
973  * Remove an object parameter.
974  * @param callback Callback function called when completed
975  * @param name Parameter name
976  * @param params Optional parameters :
977  * <ul>
978  * <li>async Asynchronous call (use default if absent) ?</li>
979  * <li>error Custom error handler (use default error handler if absent) ?</li>
980  * </ul>
981  * @function
982  */
983 Simplicite.Ajax.BusinessObject.prototype.removeParameter = function(callback, name, params) {
984 	return this.setParameter(callback, name, undefined, params);
985 };
986 
987 /**
988  * Loads an object parameter.
989  * @param callback Callback function called when loading is completed (parameter is passed to this function)
990  * @param name Parameter name
991  * @param params Optional parameters :
992  * <ul>
993  * <li>async Asynchronous call (use default if absent) ?</li>
994  * <li>error Custom error handler (use default error handler if absent) ?</li>
995  * </ul>
996  * @function
997  */
998 Simplicite.Ajax.BusinessObject.prototype.getParameter = function(callback, name, params) {
999 	var s = this._app;
1000 	var url = s._objURL + "?action=getparameter&object=" + this.metadata.name + "&inst=" + this.metadata.instance;
1001 	if (params === undefined)
1002 		params = new Object();
1003 	var r = s._call(params.async, url, { name : name }, function(r) {
1004 		if (r.type == "error") {
1005 			if (params.error !== undefined)
1006 				params.error.call(this, r.response);
1007 			else
1008 				s.error(r.response);
1009 		} else {
1010 			var res = r.response.result;
1011 			if (callback !== undefined)
1012 				callback.call(this, res);
1013 		}
1014 	}, this);
1015 	if (r !== undefined && r.result !== undefined) return r.result;
1016 };
1017 
1018 /**
1019  * Calls an object completion for specified field and loads action result.
1020  * @param callback Callback function called when loading is completed (completion result is passed to this function)
1021  * @param field Field name
1022  * @param req Completion request
1023  * @param params Optional parameters :
1024  * <ul>
1025  * <li>async Asynchronous call (use default if absent) ?</li>
1026  * <li>error Custom error handler (use default error handler if absent) ?</li>
1027  * </ul>
1028  * @function
1029  */
1030 Simplicite.Ajax.BusinessObject.prototype.completion = function(callback, field, req, params) {
1031 	var s = this._app;
1032 	var url = s._objURL + "?action=completion&object=" + this.metadata.name + "&inst=" + this.metadata.instance + "&input=" + field;
1033 	if (params === undefined)
1034 		params = new Object();
1035 	var c = s._call(params.async, url, { query: req }, function(r) {
1036 		if (r.type == "error") {
1037 			if (params.error !== undefined)
1038 				params.error.call(this, r.response);
1039 			else
1040 				s.error(r.response);
1041 		} else {
1042 			var res = r.response.result;
1043 			if (callback !== undefined)
1044 				callback.call(this, res);
1045 		}
1046 	}, this);
1047 	if (c !== undefined && c.result !== undefined) return c.result;
1048 };
1049 
1050 /**
1051  * Checks whether a field is the row ID field.
1052  * @param f Field meta data
1053  * @function
1054  */
1055 Simplicite.Ajax.BusinessObject.prototype.isRowIdField = function(f) {
1056 	return !f.ref && f.name == this.metadata.rowidfield;
1057 };
1058 
1059 /**
1060  * Checks whether a field is a timestamp field.
1061  * @param f Field meta data
1062  * @function
1063  */
1064 Simplicite.Ajax.BusinessObject.prototype.isTimestampField = function(f) {
1065 	var n = f.name;
1066 	return !f.ref && (n == "created_by" || n == "created_dt" || n == "updated_by" || n == "updated_dt");
1067 };
1068