2 if (!CRM
.Designer
) CRM
.Designer
= {};
5 * When rendering a template with Marionette.ItemView, the list of variables is determined by
6 * serializeData(). The normal behavior is to map each property of this.model to a template
9 * This function extends that practice by exporting variables "_view", "_model", "_collection",
10 * and "_options". This makes it easier for the template to, e.g., access computed properties of
11 * a model (by calling "_model.getComputedProperty"), or to access constructor options (by
12 * calling "_options.myoption").
16 var extendedSerializeData = function() {
17 var result
= Marionette
.ItemView
.prototype.serializeData
.apply(this);
19 result
._model
= this.model
;
20 result
._collection
= this.collection
;
21 result
._options
= this.options
;
26 * Display a dialog window with an editable form for a UFGroupModel
28 * The implementation here is very "jQuery-style" and not "Backbone-style";
32 * - model: CRM.UF.UFGroupModel
34 CRM
.Designer
.DesignerDialog
= Backbone
.Marionette
.Layout
.extend({
35 serializeData
: extendedSerializeData
,
36 template
: '#designer_dialog_template',
37 className
: 'crm-designer-dialog',
39 designerRegion
: '.crm-designer'
41 /** @var bool whether this dialog is currently open */
43 /** @var bool whether any changes have been made */
45 /** @var obj handle for the CRM.alert containing undo link */
47 /** @var bool whether this dialog is being re-opened by the undo link */
50 initialize: function(options
) {
51 CRM
.designerApp
.vent
.on('ufUnsaved', this.onUfChanged
, this);
54 this.undoAlert
&& this.undoAlert
.close
&& this.undoAlert
.close();
55 CRM
.designerApp
.vent
.off('ufUnsaved', this.onUfChanged
, this);
57 onUfChanged: function(isUfUnsaved
) {
58 this.isUfUnsaved
= isUfUnsaved
;
60 onRender: function() {
61 var designerDialog
= this;
62 designerDialog
.$el
.dialog({
63 autoOpen
: true, // note: affects accordion height
64 title
: 'Edit Profile',
68 minHeight
: 600, // to allow dropping in big whitespace, coordinate with min-height of .crm-designer-fields
70 // Prevent conflicts with other onbeforeunload handlers
71 designerDialog
.oldOnBeforeUnload
= window
.onbeforeunload
;
72 // Warn of unsaved changes when navigating away from the page
73 window
.onbeforeunload = function() {
74 if (designerDialog
.isDialogOpen
&& designerDialog
.isUfUnsaved
) {
75 return ts("Your profile has not been saved.");
77 if (designerDialog
.oldOnBeforeUnload
) {
78 return designerDialog
.oldOnBeforeUnload
.apply(arguments
);
81 designerDialog
.undoAlert
&& designerDialog
.undoAlert
.close
&& designerDialog
.undoAlert
.close();
82 designerDialog
.isDialogOpen
= true;
83 // Initialize new dialog if we are not re-opening unsaved changes
84 if (designerDialog
.undoState
=== false) {
85 designerDialog
.designerRegion
&& designerDialog
.designerRegion
.close
&& designerDialog
.designerRegion
.close();
86 designerDialog
.$el
.block({message
: 'Loading...', theme
: true});
87 designerDialog
.options
.findCreateUfGroupModel({
88 onLoad: function(ufGroupModel
) {
89 designerDialog
.model
= ufGroupModel
;
90 var designerLayout
= new CRM
.Designer
.DesignerLayout({
92 el
: '<div class="full-height"></div>'
94 designerDialog
.$el
.unblock();
95 designerDialog
.designerRegion
.show(designerLayout
);
96 CRM
.designerApp
.vent
.trigger('resize');
97 designerDialog
.isUfUnsaved
= false;
101 designerDialog
.undoState
= false;
103 CRM
.designerApp
.DetachedProfiles
= [];
106 window
.onbeforeunload
= designerDialog
.oldOnBeforeUnload
;
107 designerDialog
.isDialogOpen
= false;
109 designerDialog
.undoAlert
&& designerDialog
.undoAlert
.close
&& designerDialog
.undoAlert
.close();
110 if (designerDialog
.isUfUnsaved
) {
111 designerDialog
.undoAlert
= CRM
.alert('<p>' + ts('Your changes to "%1" have not been saved.', {1: designerDialog
.model
.get('title')}) + '</p><a href="#" class="crm-undo">' + ts('Restore unsaved changes') + '</a>', ts('Unsaved Changes'), 'alert', {expires
: 60000});
112 $('.ui-notify-message a.crm-undo').click(function() {
113 designerDialog
.undoState
= true;
114 designerDialog
.$el
.dialog('open');
119 CRM
.designerApp
.restorePreviewArea();
122 CRM
.designerApp
.vent
.trigger('resize');
129 * Display a complete form-editing UI, including canvas, palette, and
133 * - model: CRM.UF.UFGroupModel
135 CRM
.Designer
.DesignerLayout
= Backbone
.Marionette
.Layout
.extend({
136 serializeData
: extendedSerializeData
,
137 template
: '#designer_template',
139 buttons
: '.crm-designer-buttonset-region',
140 palette
: '.crm-designer-palette-region',
141 form
: '.crm-designer-form-region',
142 fields
: '.crm-designer-fields-region'
144 initialize: function() {
145 CRM
.designerApp
.vent
.on('resize', this.onResize
, this);
147 onClose: function() {
148 CRM
.designerApp
.vent
.off('resize', this.onResize
, this);
150 onRender: function() {
151 this.buttons
.show(new CRM
.Designer
.ToolbarView({
154 this.palette
.show(new CRM
.Designer
.PaletteView({
157 this.form
.show(new CRM
.Designer
.UFGroupView({
160 this.fields
.show(new CRM
.Designer
.UFFieldCanvasView({
164 onResize: function() {
165 if (! this.hasResizedBefore
) {
166 this.hasResizedBefore
= true;
167 this.$('.crm-designer-toolbar').resizable({
171 resize: function(event
, ui
) {
172 $('.crm-designer-canvas').css('margin-right', (ui
.size
.width
+ 10) + 'px');
173 $(this).css({left
: '', height
: ''});
175 }).css({left
: '', height
: ''});
181 * Display toolbar with working button
184 * - model: CRM.UF.UFGroupModel
186 CRM
.Designer
.ToolbarView
= Backbone
.Marionette
.ItemView
.extend({
187 serializeData
: extendedSerializeData
,
188 template
: '#designer_buttons_template',
191 'click .crm-designer-save': 'doSave',
192 'click .crm-designer-preview': 'doPreview'
194 onRender: function() {
195 this.$('.crm-designer-save').button().attr({
196 disabled
: 'disabled',
197 style
: 'opacity:.5; box-shadow:none; cursor:default;'
199 this.$('.crm-designer-preview').button();
201 initialize: function(options
) {
202 CRM
.designerApp
.vent
.on('ufUnsaved', this.onUfChanged
, this);
204 onUfChanged: function(isUfUnsaved
) {
206 this.$('.crm-designer-save').removeAttr('style').removeAttr('disabled');
209 doSave: function(event
) {
210 var ufGroupModel
= this.model
;
211 if (ufGroupModel
.getRel('ufFieldCollection').hasDuplicates()) {
212 CRM
.alert(ts('Please correct errors before saving.'), '', 'alert');
215 var $dialog
= this.$el
.closest('.crm-designer-dialog'); // FIXME use events
216 $dialog
.block({message
: 'Saving...', theme
: true});
217 var profile
= ufGroupModel
.toStrictJSON();
218 profile
["api.UFField.replace"] = {values
: ufGroupModel
.getRel('ufFieldCollection').toSortedJSON(), 'option.autoweight': 0};
219 CRM
.api('UFGroup', 'create', profile
, {
220 success: function(data
) {
224 CRM
.alert(data
.error_message
);
227 _
.each(data
.values
, function(ufGroupResponse
) {
228 if (ufGroupResponse
['api.UFField.replace'].is_error
) {
229 CRM
.alert(ufGroupResponse
['api.UFField.replace'].error_message
);
234 if (!ufGroupModel
.get('id')) {
235 ufGroupModel
.set('id', data
.id
);
237 CRM
.designerApp
.vent
.trigger('ufUnsaved', false);
238 CRM
.designerApp
.vent
.trigger('ufSaved');
239 $dialog
.dialog('close');
245 doPreview: function(event
) {
246 this.previewMode
= !this.previewMode
;
247 if (!this.previewMode
) {
248 $('.crm-designer-preview-canvas').html('');
249 $('.crm-designer-canvas > *, .crm-designer-palette-region').show();
250 $('.crm-designer-preview span').html(ts('Preview'));
253 if (this.model
.getRel('ufFieldCollection').hasDuplicates()) {
254 CRM
.alert(ts('Please correct errors before previewing.'), '', 'alert');
257 var $dialog
= this.$el
.closest('.crm-designer-dialog'); // FIXME use events
258 $dialog
.block({message
: 'Loading...', theme
: true});
260 CRM
.designerApp
.clearPreviewArea();
262 url
: CRM
.url("civicrm/ajax/inline"),
265 'qfKey': CRM
.profilePreviewKey
,
266 'class_name': 'CRM_UF_Form_Inline_Preview',
268 'ufData': JSON
.stringify({
269 ufGroup
: this.model
.toStrictJSON(),
270 ufFieldCollection
: this.model
.getRel('ufFieldCollection').toSortedJSON()
273 }).done(function(data
) {
275 $('.crm-designer-canvas > *, .crm-designer-palette-region').hide();
276 $('.crm-designer-preview-canvas').html(data
).show();
277 $('.crm-designer-preview span').html(ts('Edit'));
284 * Display a selection of available fields
287 * - model: CRM.UF.UFGroupModel
289 CRM
.Designer
.PaletteView
= Backbone
.Marionette
.ItemView
.extend({
290 serializeData
: extendedSerializeData
,
291 template
: '#palette_template',
292 el
: '<div class="full-height"></div>',
294 'keyup .crm-designer-palette-search input': 'doSearch',
295 'click .crm-designer-palette-clear-search': 'clearSearch',
296 'click .crm-designer-palette-refresh': 'doRefresh',
297 'click .crm-designer-palette-toggle': 'toggleAll'
299 initialize: function() {
300 this.model
.getRel('ufFieldCollection')
301 .on('add', this.toggleActive
, this)
302 .on('remove', this.toggleActive
, this);
303 this.model
.getRel('paletteFieldCollection')
304 .on('reset', this.render
, this);
305 CRM
.designerApp
.vent
.on('resize', this.onResize
, this);
307 onClose: function() {
308 this.model
.getRel('ufFieldCollection')
309 .off('add', this.toggleActive
, this)
310 .off('remove', this.toggleActive
, this);
311 this.model
.getRel('paletteFieldCollection')
312 .off('reset', this.render
, this);
313 CRM
.designerApp
.vent
.off('resize', this.onResize
, this);
315 onRender: function() {
316 var paletteView
= this;
318 // Prepare data for jstree
320 var paletteFieldsByEntitySection
= this.model
.getRel('paletteFieldCollection').getFieldsByEntitySection();
322 paletteView
.model
.getRel('ufEntityCollection').each(function(ufEntityModel
){
323 _
.each(ufEntityModel
.getSections(), function(section
, sectionKey
){
324 var entitySection
= ufEntityModel
.get('entity_name') + '-' + sectionKey
;
326 if (paletteFieldsByEntitySection
[entitySection
]) {
327 _
.each(paletteFieldsByEntitySection
[entitySection
], function(paletteFieldModel
, k
) {
328 items
.push({data
: paletteFieldModel
.getLabel(), attr
: {'class': 'crm-designer-palette-field', 'data-plm-cid': paletteFieldModel
.cid
}});
331 if (section
.is_addable
) {
332 items
.push({data
: 'placeholder', attr
: {'class': 'crm-designer-palette-add', 'data-entity': ufEntityModel
.get('entity_name'), 'data-section': sectionKey
}});
334 if (items
.length
> 0) {
335 treeData
.push({data
: section
.title
, children
: items
});
340 this.$('.crm-designer-palette-tree').jstree({
341 'json_data': {data
: treeData
},
343 'case_insensitive' : true,
344 'show_only_matches': true
350 "url": CRM
.config
.resourceBase
+ 'packages/jquery/plugins/jstree/themes/classic/style.css'
352 'plugins': ['themes', 'json_data', 'ui', 'search']
353 }).bind('loaded.jstree', function () {
354 $('.crm-designer-palette-field', this).draggable({
355 appendTo
: '.crm-designer',
356 zIndex
: $(this.$el
).zIndex() + 5000,
358 connectToSortable
: '.crm-designer-fields' // FIXME: tight canvas/palette coupling
360 $('.crm-designer-palette-field', this).dblclick(function(event
){
361 var paletteFieldModel
= paletteView
.model
.getRel('paletteFieldCollection').get($(event
.currentTarget
).attr('data-plm-cid'));
362 paletteFieldModel
.addToUFCollection(paletteView
.model
.getRel('ufFieldCollection'));
363 event
.stopPropagation();
365 paletteView
.model
.getRel('ufFieldCollection').each(function(ufFieldModel
) {
366 paletteView
.toggleActive(ufFieldModel
, paletteView
.model
.getRel('ufFieldCollection'))
368 paletteView
.$('.crm-designer-palette-add a').remove();
369 paletteView
.$('.crm-designer-palette-add').append('<button>'+ts('Add Field')+'</button>');
370 paletteView
.$('.crm-designer-palette-add button').button()
371 .click(function(event
){
372 var entityKey
= $(event
.currentTarget
).closest('.crm-designer-palette-add').attr('data-entity');
373 var sectionKey
= $(event
.currentTarget
).closest('.crm-designer-palette-add').attr('data-section');
374 var ufEntityModel
= paletteView
.model
.getRel('ufEntityCollection').getByName(entityKey
);
375 var sections
= ufEntityModel
.getSections();
376 paletteView
.doAddField(sections
[sectionKey
]);
377 event
.stopPropagation();
380 }).bind("select_node.jstree", function (e
, data
) {
381 $(this).jstree("toggle_node", data
.rslt
.obj
);
382 $(this).jstree("deselect_node", data
.rslt
.obj
);
385 // FIXME: tight canvas/palette coupling
386 this.$(".crm-designer-fields").droppable({
387 activeClass
: "ui-state-default",
388 hoverClass
: "ui-state-hover",
389 accept
: ":not(.ui-sortable-helper)"
394 onResize: function() {
395 var pos
= this.$('.crm-designer-palette-tree').position();
396 var div
= this.$('.crm-designer-palette-tree').closest('.crm-container').height();
397 this.$('.crm-designer-palette-tree').css({height
: div
- pos
.top
});
399 doSearch: function(event
) {
400 $('.crm-designer-palette-tree').jstree("search", $(event
.target
).val());
402 doAddField: function(section
) {
403 var paletteView
= this;
404 var openAddNewWindow = function() {
405 var url
= CRM
.url('civicrm/admin/custom/group/field/add', {
408 gid
: section
.custom_group_id
410 window
.open(url
, '_blank');
413 if (paletteView
.hideAddFieldAlert
) {
416 CRM
.confirm(function() {
417 paletteView
.hideAddFieldAlert
= true;
420 title
: ts('Add Field'),
421 message
: ts('A new window or tab will open. Use the new window to add your field, and then return to this window and click "Refresh."')
427 doRefresh: function(event
) {
428 var ufGroupModel
= this.model
;
429 CRM
.Schema
.reloadModels()
430 .done(function(data
){
431 ufGroupModel
.resetEntities();
434 CRM
.alert(ts('Failed to retrieve schema'), ts('Error'), 'error');
438 clearSearch: function(event
) {
439 $('.crm-designer-palette-search input').val('').keyup();
442 toggleActive: function(ufFieldModel
, ufFieldCollection
, options
) {
443 var paletteFieldCollection
= this.model
.getRel('paletteFieldCollection');
444 var paletteFieldModel
= paletteFieldCollection
.getFieldByName(ufFieldModel
.get('entity_name'), ufFieldModel
.get('field_name'));
445 var isAddable
= ufFieldCollection
.isAddable(ufFieldModel
);
446 this.$('[data-plm-cid='+paletteFieldModel
.cid
+']').toggleClass('disabled', !isAddable
);
448 toggleAll: function(event
) {
449 if ($('.crm-designer-palette-search input').val() == '') {
450 $('.crm-designer-palette-tree').jstree($(event
.target
).attr('rel'));
457 * Display all UFFieldModel objects in a UFGroupModel.
460 * - model: CRM.UF.UFGroupModel
462 CRM
.Designer
.UFFieldCanvasView
= Backbone
.Marionette
.View
.extend({
463 initialize: function() {
464 this.model
.getRel('ufFieldCollection')
465 .on('add', this.updatePlaceholder
, this)
466 .on('remove', this.updatePlaceholder
, this)
467 .on('add', this.addUFFieldView
, this);
469 onClose: function() {
470 this.model
.getRel('ufFieldCollection')
471 .off('add', this.updatePlaceholder
, this)
472 .off('remove', this.updatePlaceholder
, this)
473 .off('add', this.addUFFieldView
, this);
476 var ufFieldCanvasView
= this;
477 this.$el
.html(_
.template($('#field_canvas_view_template').html()));
479 // BOTTOM: Setup field-level editing
480 var $fields
= this.$('.crm-designer-fields');
481 this.updatePlaceholder();
482 var ufFieldModels
= this.model
.getRel('ufFieldCollection').sortBy(function(ufFieldModel
) {
483 return parseInt(ufFieldModel
.get('weight'));
485 _
.each(ufFieldModels
, function(ufFieldModel
) {
486 ufFieldCanvasView
.addUFFieldView(ufFieldModel
, ufFieldCanvasView
.model
.getRel('ufFieldCollection'), {skipWeights
: true});
488 this.$(".crm-designer-fields").sortable({
489 placeholder
: 'crm-designer-row-placeholder',
490 forcePlaceholderSize
: true,
491 receive: function(event
, ui
) {
492 var paletteFieldModel
= ufFieldCanvasView
.model
.getRel('paletteFieldCollection').get(ui
.item
.attr('data-plm-cid'));
493 var ufFieldModel
= paletteFieldModel
.addToUFCollection(
494 ufFieldCanvasView
.model
.getRel('ufFieldCollection'),
497 if (null == ufFieldModel
) {
498 ufFieldCanvasView
.$('.crm-designer-fields .ui-draggable').remove();
500 // Move from end to the 'dropped' position
501 var ufFieldViewEl
= ufFieldCanvasView
.$('div[data-field-cid='+ufFieldModel
.cid
+']').parent();
502 ufFieldCanvasView
.$('.crm-designer-fields .ui-draggable').replaceWith(ufFieldViewEl
);
504 // note: the sortable() update callback will call updateWeight
507 ufFieldCanvasView
.updateWeights();
511 /** Determine visual order of fields and set the model values for "weight" */
512 updateWeights: function() {
513 var ufFieldCanvasView
= this;
515 var rows
= this.$('.crm-designer-row').each(function(key
, row
) {
516 if ($(row
).hasClass('placeholder')) {
519 var ufFieldCid
= $(row
).attr('data-field-cid');
520 var ufFieldModel
= ufFieldCanvasView
.model
.getRel('ufFieldCollection').get(ufFieldCid
);
521 ufFieldModel
.set('weight', weight
);
525 addUFFieldView: function(ufFieldModel
, ufFieldCollection
, options
) {
526 var paletteFieldModel
= this.model
.getRel('paletteFieldCollection').getFieldByName(ufFieldModel
.get('entity_name'), ufFieldModel
.get('field_name'));
527 var ufFieldView
= new CRM
.Designer
.UFFieldView({
528 el
: $("<div></div>"),
530 paletteFieldModel
: paletteFieldModel
532 ufFieldView
.render();
533 this.$('.crm-designer-fields').append(ufFieldView
.$el
);
534 if (! (options
&& options
.skipWeights
)) {
535 this.updateWeights();
538 updatePlaceholder: function() {
539 if (this.model
.getRel('ufFieldCollection').isEmpty()) {
540 this.$('.placeholder').css({display
: 'block', border
: '0 none', cursor
: 'default'});
542 this.$('.placeholder').hide();
549 * - model: CRM.UF.UFFieldModel
550 * - paletteFieldModel: CRM.Designer.PaletteFieldModel
552 CRM
.Designer
.UFFieldView
= Backbone
.Marionette
.Layout
.extend({
553 serializeData
: extendedSerializeData
,
554 template
: '#field_row_template',
557 summary
: '.crm-designer-field-summary',
558 detail
: '.crm-designer-field-detail'
561 "click .crm-designer-action-settings": 'doToggleForm',
562 "click .crm-designer-action-remove": 'doRemove'
566 "change:is_duplicate": 'onChangeIsDuplicate'
568 onRender: function() {
569 this.summary
.show(new CRM
.Designer
.UFFieldSummaryView({
571 fieldSchema
: this.model
.getFieldSchema(),
572 paletteFieldModel
: this.options
.paletteFieldModel
574 this.detail
.show(new CRM
.Designer
.UFFieldDetailView({
576 fieldSchema
: this.model
.getFieldSchema()
578 this.onChangeIsDuplicate(this.model
, this.model
.get('is_duplicate'))
579 if (!this.expanded
) {
580 this.detail
.$el
.hide();
583 CRM
.designerApp
.vent
.on('formOpened', function(event
) {
584 if (that
.expanded
&& event
!= that
.cid
) {
585 that
.doToggleForm(false);
589 doToggleForm: function(event
) {
590 this.expanded
= !this.expanded
;
591 if (this.expanded
&& event
!== false) {
592 CRM
.designerApp
.vent
.trigger('formOpened', this.cid
);
594 this.$el
.toggleClass('crm-designer-open', this.expanded
);
595 var $detail
= this.detail
.$el
;
596 if (!this.expanded
) {
597 $detail
.toggle('blind', 250);
600 var $canvas
= $('.crm-designer-canvas');
601 var top
= $canvas
.offset().top
;
604 step: function(num
, effect
) {
605 // Scroll canvas to keep field details visible
606 if (effect
.prop
== 'height') {
607 if (effect
.now
+ $detail
.offset().top
- top
> $canvas
.height() - 9) {
608 $canvas
.scrollTop($canvas
.scrollTop() + effect
.now
+ $detail
.offset().top
- top
- $canvas
.height() + 9);
615 onChangeIsDuplicate: function(model
, value
, options
) {
616 this.$el
.toggleClass('crm-designer-duplicate', value
);
618 doRemove: function(event
) {
620 this.$el
.hide(250, function() {
621 that
.model
.destroyLocal();
628 * - model: CRM.UF.UFFieldModel
629 * - fieldSchema: (Backbone.Form schema element)
630 * - paletteFieldModel: CRM.Designer.PaletteFieldModel
632 CRM
.Designer
.UFFieldSummaryView
= Backbone
.Marionette
.ItemView
.extend({
633 serializeData
: extendedSerializeData
,
634 template
: '#field_summary_template',
640 * Compose a printable string which describes the binding of this UFField to the data model
643 getBindingLabel: function() {
644 var result
= this.options
.paletteFieldModel
.getSection().title
+ ": " + this.options
.paletteFieldModel
.getLabel();
645 if (this.options
.fieldSchema
.civiIsPhone
) {
646 result
= result
+ '-' + CRM
.PseudoConstant
.phoneType
[this.model
.get('phone_type_id')];
648 if (this.options
.fieldSchema
.civiIsLocation
) {
649 var locType
= this.model
.get('location_type_id') ? CRM
.PseudoConstant
.locationType
[this.model
.get('location_type_id')] : ts('Primary');
650 result
= result
+ ' (' + locType
+ ')';
656 * Return a string marking if the field is required
659 getRequiredMarker: function() {
660 if (this.model
.get('is_required') == 1) {
661 return ' <span class="crm-marker">*</span> ';
666 onRender: function() {
667 this.$el
.toggleClass('disabled', this.model
.get('is_active') != 1);
668 if (this.model
.get("is_reserved") == 1) {
669 this.$('.crm-designer-buttons').hide();
676 * - model: CRM.UF.UFFieldModel
677 * - fieldSchema: (Backbone.Form schema element)
679 CRM
.Designer
.UFFieldDetailView
= Backbone
.View
.extend({
680 initialize: function() {
681 // FIXME: hide/display 'in_selector' if 'visibility' is one of the public options
682 var fields
= ['location_type_id', 'phone_type_id', 'label', 'is_multi_summary', 'is_required', 'is_view', 'visibility', 'in_selector', 'is_searchable', 'help_pre', 'help_post', 'is_active'];
683 if (! this.options
.fieldSchema
.civiIsLocation
) {
684 fields
= _
.without(fields
, 'location_type_id');
686 if (! this.options
.fieldSchema
.civiIsPhone
) {
687 fields
= _
.without(fields
, 'phone_type_id');
689 if (!this.options
.fieldSchema
.civiIsMultiple
) {
690 fields
= _
.without(fields
, 'is_multi_summary');
693 this.form
= new Backbone
.Form({
697 this.form
.on('change', this.onFormChange
, this);
698 this.model
.on('change', this.onModelChange
, this);
701 this.$el
.html(this.form
.render().el
);
704 onModelChange: function() {
705 $.each(this.form
.fields
, function(i
, field
) {
706 this.form
.setValue(field
.key
, this.model
.get(field
.key
));
709 onFormChange: function() {
711 this.$('.field-is_multi_summary').toggle(this.options
.fieldSchema
.civiIsMultiple
? true : false);
712 this.$('.field-in_selector').toggle(this.model
.isInSelectorAllowed());
713 // this.$(':input').attr('disabled', this.model.get("is_reserved") == 1);
715 if (!this.model
.isInSelectorAllowed() && this.model
.get('in_selector') != "0") {
716 this.model
.set('in_selector', "0");
717 this.form
.setValue('in_selector', "0");
718 // TODO: It might be nicer if we didn't completely discard in_selector -- e.g.
719 // if the value could be restored when the user isInSelectorAllowed becomes true
720 // again. However, I haven't found a simple way to do this.
727 * - model: CRM.UF.UFGroupModel
729 CRM
.Designer
.UFGroupView
= Backbone
.Marionette
.Layout
.extend({
730 serializeData
: extendedSerializeData
,
731 template
: '#form_row_template',
734 summary
: '.crm-designer-form-summary',
735 detail
: '.crm-designer-form-detail'
738 "click .crm-designer-action-settings": 'doToggleForm'
740 onRender: function() {
741 this.summary
.show(new CRM
.Designer
.UFGroupSummaryView({
744 this.detail
.show(new CRM
.Designer
.UFGroupDetailView({
747 if (!this.expanded
) {
748 this.detail
.$el
.hide();
751 CRM
.designerApp
.vent
.on('formOpened', function(event
) {
752 if (that
.expanded
&& event
!== 0) {
753 that
.doToggleForm(false);
757 doToggleForm: function(event
) {
758 this.expanded
= !this.expanded
;
759 if (this.expanded
&& event
!== false) {
760 CRM
.designerApp
.vent
.trigger('formOpened', 0);
762 this.$el
.toggleClass('crm-designer-open', this.expanded
);
763 this.detail
.$el
.toggle('blind', 250);
769 * - model: CRM.UF.UFGroupModel
771 CRM
.Designer
.UFGroupSummaryView
= Backbone
.Marionette
.ItemView
.extend({
772 serializeData
: extendedSerializeData
,
773 template
: '#form_summary_template',
777 onRender: function() {
778 this.$el
.toggleClass('disabled', this.model
.get('is_active') != 1);
779 if (this.model
.get("is_reserved") == 1) {
780 this.$('.crm-designer-buttons').hide();
787 * - model: CRM.UF.UFGroupModel
789 CRM
.Designer
.UFGroupDetailView
= Backbone
.View
.extend({
790 initialize: function() {
791 this.form
= new Backbone
.Form({
793 fields
: ['title', 'help_pre', 'help_post', 'is_active']
795 this.form
.on('change', this.form
.commit
, this.form
);
798 this.$el
.html(this.form
.render().el
);