Fixed "has changed" to work with empty wiki fields
[ajatus.git] / js / renderers / form.js
blob39778ee861069204b0b8ae4d0cbb1557ce314309
1 /*
2  * This file is part of
3  *
4  * Ajatus - Distributed CRM
5  * @requires jQuery v1.2.1
6  * 
7  * Copyright (c) 2007 Jerry Jalava <jerry.jalava@gmail.com>
8  * Copyright (c) 2007 Nemein Oy <http://nemein.com>
9  * Website: http://ajatus.info
10  * Licensed under the GPL license
11  * http://www.gnu.org/licenses/gpl.html
12  * 
13  */
15 (function($){
16     $.ajatus = $.ajatus || {};
17     $.ajatus.renderer = $.ajatus.renderer || {};
18     
19     $.ajatus.renderer.form_helpers = {
20         _add_row: function(type, holder, name, data, doc) {
21                 if (    data.hidden
22                     && data.hidden == true)
23                 {
24                     return;
25                 }
26             $.ajatus.debug("add row "+name);
28                 var widget = new $.ajatus.widget(data.widget.name, data.widget.config);
29                 
30                 var required = false;
31                 if (   typeof data.widget.required != 'undefined'
32                     || typeof data.required != 'undefined')
33                 {
34                 widget.required = data.widget.required || data.required;                    
35                 required = true;
36                 }
38                 switch (type) {
39                     case 'create':
40                     var def_val = data.def_val;
41                     if (   typeof doc == 'object'
42                         && typeof doc.value[name] != 'undefined')
43                     {
44                         def_val = doc.value[name].val;
45                     }
46                 
47                         var wdgt_tpl = widget.get_create_tpl(name, def_val);
48                     break;
49                     case 'edit':
50                     var doc_value = {};
51                     if (! doc.value[name]) {
52                         doc_value = {
53                             val: '',
54                             widget: data.widget
55                         };
56                     } else {
57                         doc_value = doc.value[name];
58                     }
59                 
60                     var edit_data = $.extend({
61                         _id: doc._id
62                     }, doc_value);
63                     
64                         var wdgt_tpl = widget.get_edit_tpl(name, edit_data);
65                     break;
66                 }
68                 if ( typeof data['read_only'] != 'undefined'
69                     && data.read_only == true)
70                 {
71                     wdgt_tpl = $.ajatus.widgets.to_readonly(type, name, data.def_val, widget);
72                 }
73                 
74             holder.createAppend(
75                 'li', { id: '_element_'+name, className: 'row' }, [
76                     'label', { id: '_element_'+name+'_label' }, $.ajatus.i10n.get(data.label) + (required ? ' *' : ''),
77                     'div', { id: '_element_'+name+'_widget', className: widget.name, style: 'width: 80%;' }, wdgt_tpl,
78                     'br', { className: 'clear_fix' }, ''
79                 ]
80             );
81             widget.init($('#_element_'+name+'_widget', holder), true);
82             
83             if (required) {
84                 $('#_element_'+name+'_label', holder).addClass('required');
85             }
86             
87             $('#_element_'+name+'_label', holder).bind('click', function(e){
88                 if ($('#_element_'+name+'_widget:visible', holder)[0]) {
89                     $('#_element_'+name+'_widget', holder).hide();
90                 } else {
91                     $('#_element_'+name+'_widget', holder).show();
92                 }
93             });
94         },
95         _add_additional_row: function(type, holder, name, data, doc) {
96             $.ajatus.debug("add additional row "+name);
98                 var widget = new $.ajatus.widget(data.widget.name, data.widget.config);
100                 var required = false;
101                 if (   typeof data.widget.required != 'undefined'
102                     || typeof data.required != 'undefined')
103                 {
104                 widget.required = data.widget.required || data.required;                    
105                 required = true;
106                 }
108                 switch (type) {
109                     case 'create':
110                         var wdgt_tpl = widget.get_create_tpl(name, data.def_val);
111                     break;
112                     case 'edit':
113                     var doc_value = {};
114                     if (! doc.value[name]) {
115                         doc_value = {
116                             val: '',
117                             widget: data.widget
118                         };
119                     } else {
120                         doc_value = doc.value[name];
121                     }
122             
123                     var edit_data = $.extend({
124                         _id: doc._id
125                     }, doc_value);
126                     
127                         var wdgt_tpl = widget.get_edit_tpl(name, edit_data);
128                     break;
129                 }
130                 
131                 var additional_actions_tpl = $.ajatus.document.additionals.generate_item_actions_tpl(name, widget, doc);
132                 
133             holder.createAppend(
134                 'li', { id: '_element_'+name, className: 'row' }, [
135                     'label', { id: '_element_'+name+'_label' }, $.ajatus.i10n.get(data.label) + (required ? ' *' : ''),
136                     'input', { type: 'hidden', name: 'widget['+name+':additional]', value: $.ajatus.converter.toJSON(data) }, '',
137                     'div', { id: '_element_'+name+'_widget', className: widget.name, style: 'width: 80%;' }, wdgt_tpl,
138                     'div', { id: '_element_'+name+'_additional_actions' }, additional_actions_tpl,
139                     'br', { className: 'clear_fix' }, ''
140                 ]
141             );
142             widget.init($('#_element_'+name+'_widget', holder), true);
144             if (required) {
145                 $('#_element_'+name+'_label', holder).addClass('required');
146             }
147             
148             $('#_element_'+name+'_label', holder).bind('click', function(e){
149                 if ($('#_element_'+name+'_widget:visible', holder)[0]) {
150                     $('#_element_'+name+'_widget', holder).hide();
151                 } else {
152                     $('#_element_'+name+'_widget', holder).show();
153                 }
154             });
155         },
156         _register_for_autosave: function(form, action) {
157             if ($.ajatus.utils.to_boolean($.ajatus.preferences.local.auto_save.enabled) == false) {
158                 return false;
159             }
160             
161             var save_interval = Number($.ajatus.preferences.local.auto_save.interval);
162             var watcher = new $.ajatus.events.watcher({
163                 auto_start: true,
164                 safety_runs: 0,
165                 interval: 200,
166                 timed: (save_interval * 1000)
167             });
168             $.ajatus.views.on_change_actions.add('$.ajatus.events.watchers.remove('+watcher._id+');');
170             var as_lc_holder = $('.form_structure .auto_save_lc span', form);
171             as_lc_holder.html('0');
172             if (typeof as_lc_holder[0] == 'undefined') {
173                 as_holder = $('<div class="auto_save_lc" />').hide().prependTo($('.form_structure', form));
174                 as_holder.html($.ajatus.i10n.get("Auto saving in")+" ");
175                 as_lc_holder = $('<span/>').appendTo(as_holder);
176             }
177             
178             watcher.element.bind('on_tick', function(e, watcher_id, data){
179                 // console.log("on_tick");
180                 // console.log(data);
181                 if (data['left_prc'] > 70) {
182                     var time_left = "0";
183                     var ls = data['left_ms'] / 1000;
184                     if (ls < 60) {
185                         time_left = parseInt(ls).toString();
186                     } else {
187                         var min = parseInt(ls/60);
188                         var sec = parseInt(ls - (min*60));
189                         
190                         if (sec < 10) {
191                             sec = "0" + sec.toString();
192                         }
193                         
194                         time_left = parseInt(min).toString() + ":" + sec;
195                     }
197                     if (as_lc_holder.parent().css('display') == 'none') {
198                         as_lc_holder.parent().fadeIn('slow', function(){
199                             as_lc_holder.html(time_left);
200                         });
201                     } else {
202                         as_lc_holder.html(time_left);
203                     }
204                 }
205             });
206             watcher.element.bind('on_stop', function(e, watcher_id){
207                 eval(action);
208                 
209                 if ($.ajatus.forms.active) {
210                     $.ajatus.renderer.form_helpers._register_for_autosave(form, action);
211                 }
212             });
213         }
214     };
215     
216     $.ajatus.renderer.form = function(content_type, doc, doc_as_defaults, latest_rev)
217     {
218         var self = this;
219         this.content_type = content_type;
220         this.doc = doc || false;
221         this.doc_as_defaults = doc_as_defaults || false;
222         this.form = null;
223         
224         $.ajatus.toolbar.show();
225         
226         if (   this.doc
227             && !this.doc_as_defaults)
228         {
229             this.form = this.edit(this.content_type, this.doc, latest_rev);
230         } else {
231             this.form = this.create(this.content_type, this.doc);
232         }
233         
234         return this;
235     }
236     $.extend($.ajatus.renderer.form.prototype, {
237         create: function(content_type, doc)
238         {
239             if (typeof content_type == 'string') {
240                 content_type = $.ajatus.preferences.client.content_types[content_type];
241             }
242             
243             var schema_fields = content_type.schema;
244             var type_name = content_type.name;
246             var form = $('<form id="create_'+type_name+'" name="create_'+type_name+'" />');
247             var form_actions = $('<div class="form_actions"><input type="submit" name="save" value="' + $.ajatus.i10n.get('Create') + '" /><input type="submit" name="cancel" value="' + $.ajatus.i10n.get('Cancel') + '" /></div>');
248             var form_struct = $('<div class="form_structure" />');
249             var form_errors = $('<div class="form_errors" />').hide();
250             var row_holder = $('<ul class="row_holder" />');
252             var type_title = content_type.title;
253             $('<h2>' + $.ajatus.i10n.get('Create %s', [type_title]) + '</h2>').appendTo(form_struct);
255             if (typeof $.ajatus.forms.process.has_errors != 'undefined') {
256                     var error_holder = $('<ul />');
257                     $.each($.ajatus.forms.process.error_fields, function(field, data){
258                         $('<li class="error" />').html(data.msg).appendTo(error_holder);
259                     });
260                     error_holder.appendTo(form_errors);
261                     form_errors.appendTo(form_struct).show();
262             }
264             $.ajatus.toolbar.add_item($.ajatus.i10n.get('Create'), {
265                 icon: 'save.png',
266                 action: function(){
267                     $('#create_'+type_name+' input[@type=submit][name*=save]').trigger("click", []);
268                 },
269                 access_key: 'Ctrl+s'
270             });
271             $.ajatus.toolbar.add_item($.ajatus.i10n.get('Cancel'), 'cancel.png', function(){
272                 $('#create_'+type_name+' input[@type=submit][name*=cancel]').trigger("click", []);
273             });
275             var hidden_data = {
276                 _type: type_name
277             };
279             var hidden_fields = function() {
280                 return [
281                     'input', { type: 'hidden', id: '_type', name: '_type', value: this._type }, ''
282                 ];
283             };
284             row_holder.tplAppend(hidden_data, hidden_fields);
285             
286             $.each(schema_fields, function(i,n){
287                 $.ajatus.renderer.form_helpers._add_row('create', row_holder, i, n, doc);
288             });
290             row_holder.appendTo(form_struct);
291             form_struct.appendTo(form);
292             form_actions.appendTo(form);
293             
294             $('li:first', row_holder).addClass('first');
295             $('li:last', row_holder).addClass('last');
296                         
297             if (   typeof(content_type['enable_additionals']) != 'undefined'
298                 && content_type.enable_additionals)
299             {
300                     var additionals_add = $('<div class="additionals_add_btn" />').html($.ajatus.i10n.get('Add field'));
301                 additionals_add.appendTo(form_struct);
302                 
303                 additionals_add.bind('click', function(e){
304                     $.ajatus.document.additionals.create(content_type, row_holder);
305                 });             
306             }
307             
308             // var save_action = "$('#create_"+type_name+" input[@type=submit][name*=save]').trigger('click', []);";
309             // $.ajatus.renderer.form_helpers._register_for_autosave(form, save_action);
310             
311             return form;
312         },
313         edit: function(content_type, doc, latest_rev)
314         {            
315             var schema_fields = content_type.schema;
316             var type_name = content_type.name;
317             var has_additionals = false;
318             
319             if (typeof doc.value._additionals != 'undefined') {
320                 has_additionals = true;
321                 $.each(doc.value._additionals, function(key,data){                    
322                     schema_fields[key] = data;
323                 });
324             }
326             var form = $('<form id="edit_'+type_name+'" name="edit_'+type_name+'" />');
327             var form_actions = $('<div class="form_actions"><input type="submit" name="save" value="' + $.ajatus.i10n.get('Save') + '" /><input type="submit" name="cancel" value="' + $.ajatus.i10n.get('Cancel') + '" /></div>');
328             var form_struct = $('<div class="form_structure" />');
329             var form_errors = $('<div class="form_errors" />').hide();
330             var row_holder = $('<ul class="row_holder" />');
332             var type_title = content_type.title;
333             $('<h2>' + $.ajatus.i10n.get('Edit %s', [type_title]) + '</h2>').appendTo(form_struct);
334             
335             if (typeof $.ajatus.forms.process.has_errors != 'undefined') {
336                     var error_holder = $('<ul />');
337                     $.each($.ajatus.forms.process.error_fields, function(field, data){
338                         $('<li class="error" />').html(data.msg).appendTo(error_holder);
339                     });
340                     error_holder.appendTo(form_errors);
341                     form_errors.appendTo(form_struct).show();
342             }
343             
344             $.ajatus.toolbar.add_item($.ajatus.i10n.get('Save'), {
345                 icon: 'save.png',
346                 action: function(){
347                     $('#edit_'+type_name+' input[@type=submit][name*=save]').trigger("click", []);
348                 },
349                 access_key: 'Ctrl+s'
350             });
351             $.ajatus.toolbar.add_item($.ajatus.i10n.get('Cancel'), 'cancel.png', function(){
352                 $('#edit_'+type_name+' input[@type=submit][name*=cancel]').trigger("click", []);
353             });
354             $.ajatus.toolbar.add_item($.ajatus.i10n.get('View'), {
355                 icon: 'view.png',
356                 action: function(){
357                     $.ajatus.views.system.item.render(doc);
358                 },
359                 access_key: 'Ctrl+v'
360             });
362             var hidden_data = {
363                 _id: doc._id,
364                 _rev: (latest_rev || doc._rev),
365                 _type: type_name
366             };
368             var hidden_fields = function() {
369                 return [
370                     'input', { type: 'hidden', id: this._id+'_id', name: '_id', value: this._id }, '',
371                     'input', { type: 'hidden', id: this._id+'_revision', name: '_rev', value: this._rev }, '',
372                     'input', { type: 'hidden', id: this._id+'_type', name: '_type', value: this._type }, ''
373                 ];
374             };
375             $(row_holder).tplAppend(hidden_data, hidden_fields);
376             
377             if (has_additionals) {
378                 var additionals_hidden = $('<input type="hidden" name="_additionals" id="' + doc._id + '_additionals" value=\'' + $.ajatus.converter.toJSON(doc.value._additionals) + '\' />');
379                 additionals_hidden.appendTo(row_holder);
380             }
381             
382             $.each(doc.value.metadata, function(k,m){                   
383                 var data = $.extend({
384                     _id: doc._id
385                 }, m);
386                 var md_field = function() {
387                     return [
388                         'input', { type: 'hidden', id: this._id+'_metadata_'+k, name: 'metadata['+k+']', value: this.val }, '',
389                     ];
390                 };            
391                 $(row_holder).tplAppend(data, md_field);
392             });
393             
394             $.each(schema_fields, function(i,n){
395                 if (   has_additionals
396                     && typeof doc.value._additionals[i] != 'undefined')
397                 {
398                     $.ajatus.renderer.form_helpers._add_additional_row('edit', row_holder, i, n, doc);
399                 } else {
400                     $.ajatus.renderer.form_helpers._add_row('edit', row_holder, i, n, doc);
401                 }
402             });
404             row_holder.appendTo(form_struct);
405             form_struct.appendTo(form);
406             form_actions.appendTo(form);
407             
408             $('<div class="clear_fix" />').appendTo(form);
409             
410             $('li:first', row_holder).addClass('first');
411             $('li:last', row_holder).addClass('last');
412             $('li:odd', row_holder).addClass('odd');
414             if (   typeof(content_type['enable_additionals']) != 'undefined'
415                 && content_type.enable_additionals)
416             {
417                     var additionals_add = $('<div class="additionals_add_btn" />').html($.ajatus.i10n.get('Add field'));
418                 additionals_add.appendTo(form_struct);
419                 
420                 additionals_add.bind('click', function(e){
421                     $.ajatus.document.additionals.create(content_type, row_holder);
422                 });             
423             }
425             var save_action = "$('#edit_"+type_name+" input[@type=submit][name*=save]').trigger('click', []);";
426             $.ajatus.renderer.form_helpers._register_for_autosave(form, save_action);
428             return form;
429         }
430     });
431     
432 })(jQuery);