PageSourceSearch

https://www.wabcmusicradio.com/wp-content/plugins/wpb-contest/js/views.js?dt=5_Nov_2025&ver=7.1

js wabcmusicradio.com collected 2026-09-27 04:40:33 UTC 48,101 bytes, 1,358 lines download raw bytes

1(function ($) {
2	// all of utilities functions will be put here
3	
4	// it's field view Factory function
5	var createFieldView = function(type, model){
6		// model = model || {};
7		if( type == 'text'){
8			return new TextFieldView({model:model});
9		}else if(type == 'textarea'){
10			return new TextareaFieldView({model:model});
11		}else if(type == 'radios'){
12			return new RadiosFieldView({model:model});
13		}else if(type == 'checkboxes'){
14			return new CheckboxesFieldView({model:model});
15		}else if(type == 'html'){ // WPB-4314
16			return new HTMLFieldView({model:model});
17		}else if(type == 'dropdown'){ // WPB-4314
18			return new DropDownFieldView({model:model});
19		}
20	};
21
22	// it will add option for checkboxes or radios
23	// eg:
24	// addOption('You are awesome', {4: 'you are good'})
25	// result: {4: 'you are good', 8: 'You are awesome'}
26	var addOption = function(label, obj){
27		obj = obj || {};
28		if(_.isEmpty(obj)){ return obj['1'] = label;}
29		var allKeys = _.keys(obj);
30		var maxKey = parseInt(allKeys.pop());
31		maxKey = maxKey * 2;
32		maxKey += '';
33		obj[maxKey] = label;
34	};
35
36	// define own namespace
37	if(_.isUndefined(window.cq)) window.cq = {};
38
39	// WPB-4314: Global field definitions
40    window.cq.fieldDefinitions = {
41        'text':       { label: 'Text Input',        icon: '<i class="fa-solid fa-i-cursor"></i>',
42                                                      stacked_icon: '<span class="fa-stack fa-lg"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-i-cursor fa-stack-1x fa-inverse"></i></span>' },
43        'textarea':   { label: 'Text Area',         icon: '<i class="fa-solid fa-align-left"></i>',
44                                                      stacked_icon: '<span class="fa-stack fa-lg"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-align-left fa-stack-1x fa-inverse"></i></span>' },
45        'radios':     { label: 'Radio Group',       icon: '<i class="fa-solid fa-circle-dot"></i>',
46                                                      stacked_icon: '<span class="fa-stack fa-lg"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-circle-dot fa-stack-1x fa-inverse"></i></span>' },
47        'checkboxes': { label: 'Checkbox Group',    icon: '<i class="fa-solid fa-square-check"></i>',
48                                                      stacked_icon: '<span class="fa-stack fa-lg"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-square-check fa-stack-1x fa-inverse"></i></span>' },
49        'html':       { label: 'Custom HTML',       icon: '<i class="fa-solid fa-code"></i>',
50                                                      stacked_icon: '<span class="fa-stack fa-lg"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-solid fa-code fa-stack-1x fa-inverse"></i></span>' },
51        'dropdown':   { label: 'Dropdown',          icon: '<i class="fa-regular fa-square-caret-down"></i>',
52                                                      stacked_icon: '<span class="fa-stack fa-lg"><i class="fa-solid fa-circle fa-stack-2x"></i><i class="fa-regular fa-square-caret-down fa-stack-1x fa-inverse"></i></span>' }
53    };
54
55	//generate frontend fields html code
56	window.cq.initFrontPanel = function(fields){
57		var objs = [];
58		for(var i = 0; i < fields.length; i ++){
59			var type = fields[i].type;
60			var model = new FieldModel(fields[i]);
61			
62			var temp = createFieldView(type,  model);
63			temp.renderFrontHtml();
64			$('#custom_questions_area').append(temp.$el);
65			
66			objs.push(temp);
67		}
68		var objs2 = [];
69		for(var i = 0; i < fields.length; i ++){
70			var type = fields[i].type;
71			var model = new FieldModel(fields[i]);
72			
73			var temp = createFieldView(type,  model);
74			temp.renderFrontHtml();
75			
76			$('#custom_questions_area_2').append(temp.$el);
77			objs2.push(temp);
78		}
79
80		//WPB-4323
81		window.cq.objs = objs;
82		window.cq.objs2 = objs2;
83
84		$("#contest_signup_dialog_form").submit(function(){
85			for(var i = 0; i < objs.length; i ++){
86				var temp = objs[i];
87				if(!temp.validate()) {
88					//WPB-134
89					try {
90						jQuery('#btnSignSubmit_divMsg').html('');
91					}
92					catch(e){}
93					return false;
94				}
95			}
96			return true;
97		});
98		$("#contest_update_dialog_form").submit(function(){
99			for(var i = 0; i < objs2.length; i ++){
100				var temp = objs2[i];
101				if(!temp.validate()) {
102					//WPB-134
103					try {
104						jQuery('#btnSignSubmit_divMsg').html('');
105					}
106					catch(e){}
107					return false;
108				}
109			}
110			return true;
111		});
112	};
113
114	window.cq.uniqueId = 0;
115
116	// define event object, all not-direct events will be bind on it.
117	window.cq.Events = _.extend({}, window.cq.Events, Backbone.Events);
118
119	var FieldModel = Backbone.Model.extend({
120		defaults: function () {
121			//uuid
122			var uniqueId = window.cq.uniqueId + 1;
123			var name = 'cq_field_' + uniqueId;
124			return {
125				type : '',
126				name : name,
127				label : '',
128				description: '',
129				required: 0,
130				highlight: 0,
131				uniqueId: uniqueId,
132			};
133		},
134	});
135
136	//var add_new_option_style = 'color:green;border: 1px dotted !important;';
137	//var delete_btn_style = 'color:red;border: 1px dotted !important;';
138	//var delete_btn_style_preview_section = 'color:red;text-decoration:none;padding-right:10px;padding-top:3px;';
139
140	var FieldsCollection = Backbone.Collection.extend({
141		model: FieldModel,
142
143		highlightField: function (model){
144			// reset all highlight
145			_.map(this.models, function(temp){
146				temp.set('highlight', 0);
147			});
148			model.set('highlight', 1);
149			window.cq.Events.trigger('highlightEvent', model);
150		},
151		unhighlightAll: function (){
152            _.map(this.models, function(temp){
153                temp.set('highlight', 0);
154            });
155        },
156	});
157
158	// this is collection data that will be persisted into DB
159	window.cq.fields = new FieldsCollection;
160
161	window.cq.FieldsPanel = Backbone.View.extend({
162		el: '#custom_questions_editor',
163
164		initialize: function(options){
165			this.render();
166			// load "All Fields" view and "Field Settings" view
167			this.allFieldsView = new AllFields()
168			this.fieldSettingsView = new FieldSettings()
169			window.cq.Events.on('highlightEvent', this.switchView, this); //WPB-4314
170			window.cq.Events.on('showAllFields', this.showAllFields, this); //WPB-4314
171			this.listenTo(window.cq.fields, 'add', this.addPreviewField);
172			this.listenTo(window.cq.fields, 'remove', this.onFieldRemoved); //WPB-4314
173			this.checkEmptyState(); //WPB-4314
174		},
175
176		//"Fields" "Field Settings"
177		switchView: function() {
178			this.$el.find('#all_fields').hide();
179			this.$el.find('#field_settings').show();
180		},
181
182		// WPB-4314 Handler for our "Back" button
183		showAllFields: function() {
184			this.$el.find('#field_settings').hide();
185			this.$el.find('#all_fields').show();
186			window.cq.fields.unhighlightAll(); 
187            this.fieldSettingsView.clearModel(); 
188		},
189		// WPB-4314 To revert to field listing if delete current field or last field
190        onFieldRemoved: function(removedModel) {
191            // Get the model that is currently being edited
192            var currentlyEditingModel = this.fieldSettingsView.model;
193            
194            // Check if the form will be empty AFTER this removal
195            var isNowEmpty = (window.cq.fields.length === 0);
196
197            // ONLY reset the view if...
198            // 1. The field we just deleted IS the one we were editing.
199            //    OR
200            // 2. We just deleted the last field.
201            if (removedModel === currentlyEditingModel || isNowEmpty) {
202                this.showAllFields();
203                this.fieldSettingsView.clearModel();
204            }
205
206            // Always check the empty state, regardless
207            this.checkEmptyState();
208        },
209		events: {
210			'click #form-preview>.row': 'changeCurrentFieldModel'
211		},
212
213		template: function() {
214			return '<div id="all_fields"></div>'
215				+ '<div id="field_settings" style="display: none;"></div>'; 
216		},
217
218		//WP-4314
219		checkEmptyState: function() {
220			var $emptyState = this.$el.find('#form-preview-empty-state');
221			if (window.cq.fields.length === 0) {
222				$emptyState.show();
223			} else {
224				$emptyState.hide();
225			}
226		},
227
228		// load main view
229		render: function() {
230			this.$el.find('#fields_panel').html(this.template());
231			this.makeFormPreviewDroppable();
232		},
233
234		// before you submit form, you have to generate data that will be persisted into DB.
235		returnJSON: function() {
236			return JSON.stringify(window.cq.fields);
237		},
238		
239		addPreviewFields: function(fields) {
240			fields = fields || '';
241			if(fields == ''){return;}
242			window.cq.fields.add(fields);
243		},
244
245		addPreviewField: function(model, collection, options) {
246			// we need to check every model when we get all models from database
247			// and save the max uniqueId on client.
248			// Next time we can use it when we create new model.
249			var uniqueId = model.get('uniqueId');
250			if(uniqueId > window.cq.uniqueId){
251				window.cq.uniqueId = uniqueId;
252			}
253			var view = createFieldView(model.get('type'), model);
254			view.renderFormPreview();
255			view.$el.appendTo(this.$el.find('#form-preview'));
256			// this view is preview, not included by field setting view
257			// so we bind it here, not in construct function
258			view.listenTo(model, 'change', view.renderFormPreview);
259			collection.highlightField(model);
260			//WPB-4314
261			this.checkEmptyState();
262		},
263
264		// make form-preview droppable
265		makeFormPreviewDroppable: function() {
266			var that = this;
267			this.$el.find('#form-preview').droppable({
268				activeClass: "ui-state-default",
269				hoverClass: "ui-state-hover",
270				accept: ":not(.ui-sortable-helper)",
271				drop: function( event, ui ) {
272					//create new field view
273					var temp = createFieldView(ui.draggable.attr('data-field'));
274					window.cq.fields.add(temp.model);
275					temp.remove();
276				}
277			});
278		},
279	});
280
281	var AllFields = Backbone.View.extend({
282	    el: '#all_fields',
283
284	    initialize: function(options){
285	        this.all_fields = ['text', 'textarea', 'radios', 'checkboxes', 'html', 'dropdown'];
286	        this.render();
287	    },
288
289	    render: function() {
290	        this.$el.html(this.template());
291	        this.makeComponentDraggable();
292	    },
293
294	    template: function() {
295	        var output = '';
296
297	        //WPB-4314 Define icons and display names for each field type (these show on the field "widgets")
298			var fieldDefinitions = {
299				'text':       { label: 'Text Input',        icon: '<i class="fa-solid fa-i-cursor"></i>' },
300				'textarea':   { label: 'Text Area',         icon: '<i class="fa-solid fa-align-left"></i>' },
301				'radios':     { label: 'Radio Buttons',    	icon: '<i class="fa-solid fa-circle-dot"></i>' },
302				'checkboxes': { label: 'Checkboxes', 		icon: '<i class="fa-solid fa-square-check"></i>' },
303				'html':       { label: 'Custom HTML',       icon: '<i class="fa-solid fa-code"></i>' },
304				'dropdown':   { label: 'Drop Down', 		icon: '<i class="fa-regular fa-square-caret-down"></i>' }
305			};
306
307	        for(var i = 0; i < this.all_fields.length; i ++){
308	            var fieldClass = this.all_fields[i];
309	            var fieldDef = fieldDefinitions[fieldClass];
310	            if (fieldDef) { 
311	                output += '<div class="field-widget" data-field="' + fieldClass + '">'
312	                        + '    <div class="widget-icon">' + fieldDef.icon + '</div>'
313	                        + '    <div class="widget-label">' + fieldDef.label + '</div>'
314	                        + '</div>';
315	            }
316	        }
317	        return output;
318	    },
319
320		makeComponentDraggable: function() {
321		    this.$el.find('.field-widget').draggable({//WPB-4314
322		        appendTo: "body",
323		        helper: "clone",
324				cursorAt: { top: 1, left: 1 }
325		    });
326		}
327	});
328	
329	var FieldSettings = Backbone.View.extend({
330		el: '#field_settings',
331
332		//WPB-4314
333		events: {
334			'click .back-to-fields-btn': 'showAllFields'
335		},
336
337		//WPB-4314
338		showAllFields: function(e) {
339			e.preventDefault();
340			window.cq.Events.trigger('showAllFields'); // Fire global event
341		},
342
343		initialize: function(options){
344			this.currentView = false;
345			this.$el.html(this.noModelTemplate());
346			window.cq.Events.on('highlightEvent', this.setModel, this);
347		},
348
349		setModel: function(model) {
350			this.model = model;
351			//this.listenTo(this.model, 'change', this.render);
352			this.render();
353		},
354		//WPB-4314 revert to field list after deleting open field
355		clearModel: function() {
356            this.model = null;
357            if (this.currentView) {
358                this.currentView.remove();
359                this.currentView = false;
360            }
361            this.$el.html(this.noModelTemplate());
362        },
363		render: function() {
364			if(this.currentView){
365				this.currentView.remove();
366			}
367			//load field view
368			this.currentView = createFieldView(this.model.get('type'), this.model);
369			this.currentView.render();
370		
371			//WPB-4314 Add a "Back" button wrapper
372			var backButtonHtml = '<div class="field-settings-header">'
373							+ '  <a href="#" class="back-to-fields-btn">&larr; Back to All Fields</a>'
374							+ '</div>';
375
376			this.$el.html(backButtonHtml); 
377			this.currentView.$el.addClass('field-editor-form-wrap');
378			this.$el.append(this.currentView.$el); 
379		},
380
381		noModelTemplate: function() {
382			return 'Please select a field on the right to edit its settings.';
383		}
384	});
385
386	// if you want to add new field, you have to implement the interface
387	var FieldView = Backbone.View.extend({
388		events: {
389			'click .field-form-preview': 'highlightField',
390			'click .field-delete-btn': 'removeFieldView',
391            'click select': 'stopBubble',//WPB-4314 allows user to click dropdown in form preview to see options
392		},
393		stopBubble: function(e) {
394            e.stopPropagation();
395        },
396		initialize: function(options){
397			options = options || {};
398			if( _.isUndefined(options.model) ) {
399				this.model = new FieldModel(this.getDefaultModel());
400			}
401		},
402
403		// this fucntion is using for field editor
404		render: function() {
405			this.$el.html(_.template(this.getFieldEditorTemplate())(this.model.toJSON()));
406		},
407
408		getPreviewHtml : function() {
409			return _.template(this.getPreviewTemplate())(this.model.toJSON());
410		},
411
412		renderFrontHtml : function() {
413			this.$el.html(_.template(this.getFrontTemplate())(this.model.toJSON()));
414		},
415
416		renderFormPreview: function() {
417			var highlight = (this.model.get('highlight') == 1 ? 'highlight' : '');
418			var deleteIcon = '<i class="fa-regular fa-circle-xmark" title="Delete this field"></i>'; //WPB-4314
419			this.$el.html('<div class="field-form-preview clearfix ' + highlight + '"><div class="field-actions"><a class="field-delete-btn" href="#">' + deleteIcon + '</a></div>' + this.getPreviewHtml() + '</div>');
420		},
421
422		highlightField: function() {
423			window.cq.fields.highlightField(this.model);
424		},
425
426		removeFieldView: function() {
427			// the better way is bind 'remove' event into view, but there is no internet now, I can not look manual online.
428			window.cq.fields.remove(this.model);
429			this.remove();
430			return false;
431		},
432
433		// finish the following function in your new field
434		// getDefaultModel
435		// getPreviewTemplate
436		// getFieldEditorTemplate
437		// getFrontTemplate
438		// validate
439	});
440
441	// ===========================================================================
442	var TextFieldView = FieldView.extend({
443		events: function(){
444			return _.extend({},FieldView.prototype.events,{
445				'change #label' : 'setLabel',
446				'change #placeholder' : 'setPlaceholder',
447				'change #required' : 'setRequired',
448			});
449		},
450
451		setLabel: function(el) {
452			var current = $(el.currentTarget);
453			this.model.set('label', current.val());
454		},
455
456		setPlaceholder: function(el) {
457			var current = $(el.currentTarget);
458			this.model.set('attributes', {placeholder: current.val()});
459		},
460
461		setRequired: function(el) {
462			var current = $(el.currentTarget);
463			if(current.prop('checked')){
464				this.model.set('required', 1);
465			}else{
466				this.model.set('required', 0);
467			}
468		},
469
470		getDefaultModel: function() {
471			return {
472				type: 'text',
473				label: 'Text Input',
474				attributes: {
475					placeholder: 'Placeholder',
476				},
477				description: '',
478			};
479		},
480
481        getPreviewTemplate: function() {
482            // NEW ICON LAYOUT
483            var icon = window.cq.fieldDefinitions['text'].stacked_icon;
484            var title = '<%=label%>';
485            if(this.model.get('required') == 1) { title += ' (Required)'; }
486            return '<div class="sp-row row" title="' + title + '">'
487                 + '  <div class="preview-icon">' + icon + '</div>'
488                 + '  <div class="preview-content"><label><%=label%></label>
488<input name="<%=name%>" type="text" placeholder="<%=attributes.placeholder%>" class="form-control" value="" disabled></div>'
489                 + '</div>';
490        },
491
492		getFrontTemplate: function() {
493			return '<p><%if(required == 1){%><span style="color:red;">*</span><%}%><%=label%></p><input style="" name="<%=name%>" id="<%=name%>" type="text" placeholder="<%=attributes.placeholder%>" value="">';
494		},
495
496		getFieldEditorTemplate: function() {
497			//WPB-4314 new stacked layout
498            return ''
499            + '<div class="sp-row">'
500            + '  <label for="label">Label</label>'
501            + '  <input id="label" name="label" type="text" class="form-control" value="<%=label%>">'
502            + '</div>'
503            + '<div class="sp-row">'
504            + '  <label for="placeholder">Placeholder</label>'
505            + '  <input id="placeholder" name="placeholder" type="text" class="form-control" value="<%=attributes.placeholder%>">'
506            + '</div>'
507            + '<div class="sp-row checkbox-row">' 
508            + '  <input <%if(required == 1){%>checked<%}%> type="checkbox" id="required" name="required" value="1" />'
509            + '  <label for="required">Required</label>'
510            + '</div>'
511            + '';
512        },
513
514		validate: function(){
515			if(this.model.get('required') == 1){
516				var custom_que_id = this.$el.find('input').attr('id');
517				if($.trim(this.$el.find('input').val()) == ''){
518					//WPB-134 -- textbox
519					try {
520						jQuery('#btnSignSubmit_divMsg').html('');
521					}
522					catch(e){}
523
524					//stop alert message for custom question and used span things like other fields of contest.
525					if(jQuery("#span"+custom_que_id).length == 0) {
526						jQuery('<span id="span'+custom_que_id+'"><font color="red">Please fill out the "'+this.model.get('label')+'"'+"</font></span>").insertAfter('#'+custom_que_id);
527					}
528					else {
529						jQuery("#span"+custom_que_id).show();
530					}
531					return false;
532				}
533				else {
534					jQuery("#span"+custom_que_id).remove();
535				}
536			}
537			return true;
538		}
539	});
540
541	// ===========================================================================
542	var TextareaFieldView = FieldView.extend({
543		events: function(){
544			return _.extend({},FieldView.prototype.events,{
545				'change #label' : 'setLabel',
546				'change #placeholder' : 'setPlaceholder',
547				'change #required' : 'setRequired',
548			});
549		},
550
551		setLabel: function(el) {
552			var current = $(el.currentTarget);
553			this.model.set('label', current.val());
554		},
555
556		setPlaceholder: function(el) {
557			var current = $(el.currentTarget);
558			this.model.set('attributes', {placeholder: current.val()});
559		},
560
561		setRequired: function(el) {
562			var current = $(el.currentTarget);
563			if(current.prop('checked')){
564				this.model.set('required', 1);
565			}else{
566				this.model.set('required', 0);
567			}
568		},
569
570		getDefaultModel: function() {
571			return {
572				type: 'textarea',
573				label: 'Text Area',
574				attributes: {
575					placeholder: 'Placeholder',
576				},
577				description: '',
578			};
579		},
580
581        getPreviewTemplate: function() {
582            // NEW ICON LAYOUT
583            var icon = window.cq.fieldDefinitions['textarea'].stacked_icon;
584            var title = '<%=label%>';
585            if(this.model.get('required') == 1) { title += ' (Required)'; }
586            return '<div class="sp-row row" title="' + title + '">'
587                 + '  <div class="preview-icon">' + icon + '</div>'
588                 + '  <div class="preview-content"><label><%=label%></label><textarea name="<%=name%>" placeholder="<%=attributes.placeholder%>" class="form-control" disabled></textarea></div>'
589                 + '</div>';
590        },
591
592		getFrontTemplate: function() {
593			return '<p><%if(required == 1){%><span style="color:red;">*</span><%}%><%=label%></p><textarea name="<%=name%>" id="<%=name%>" placeholder="<%=attributes.placeholder%>"></textarea>';
594		},
595
596		getFieldEditorTemplate: function() {
597			//WPB-4314 new stacked layout
598            return ''
599            + '<div class="sp-row">'
600            + '  <label for="label">Label</label>'
601            + '  <input id="label" name="label" type="text" class="form-control" value="<%=label%>">'
602            + '</div>'
603            + '<div class="sp-row">'
604            + '  <label for="placeholder">Placeholder</label>'
605            + '  <input id="placeholder" name="placeholder" type="text" class="form-control" value="<%=attributes.placeholder%>">'
606            + '</div>'
607            + '<div class="sp-row checkbox-row">'
608            + '  <input <%if(required == 1){%>checked<%}%> type="checkbox" id="required" name="required" value="1" />'
609            + '  <label for="required">Required</label>'
610            + '</div>'
611            + '';
612        },
613
614		validate: function(){
615			if(this.model.get('required') == 1){
616				var custom_que_id = this.$el.find('textarea').attr('id');
617				if($.trim(this.$el.find('textarea').val()) == ''){
618					//WPB-134 -- textarea
619					try {
620						jQuery('#btnSignSubmit_divMsg').html('');
621					}
622					catch(e){}
623
624					if(jQuery("#span"+custom_que_id).length == 0) {
625						jQuery('<span id="span'+custom_que_id+'"><font color="red">
625Please fill out the "'+this.model.get('label')+'"'+"</font></span>").insertAfter('#'+custom_que_id);
626					}
627					else {
628						jQuery("#span"+custom_que_id).show();
629					}
630					return false;
631				}
632				else {
633					jQuery("#span"+custom_que_id).remove();
634				}
635			}
636			return true;
637		}
638	});
639
640	// ===========================================================================
641	var RadiosFieldView = FieldView.extend({
642		events: function(){
643			return _.extend({},FieldView.prototype.events,{
644				'change #label' : 'setLabel',
645				'change .radio_option_input': 'setOptions',
646				'click #add_new_option': 'addNewOption',
647				'click .delete_option': 'deleteOption',
648				'change #required' : 'setRequired',
649				'change .radio_option_default' : 'setDefault',
650			});
651		},
652
653		setLabel: function(el) {
654			var current = $(el.currentTarget);
655			this.model.set('label', current.val());
656		},
657
658		setOptions: function() {
659			var options = {};
660			this.$el.find('.radio_option_input').each(function(){
661				if($(this).attr('data-index') != '0'){
662					options[$(this).attr('data-index')] = $(this).val();
663				}else{
664					addOption($(this).val(), options);
665					var allKeys = _.keys(options);
666		            var maxKey = parseInt(allKeys.pop());
667					var newDef = $(this).next().next();
668					newDef.val(maxKey);
669					$(newDef).attr('data-index',maxKey);
670				}
671			});
672
673			this.model.set('options', options);
674		},
675		setRequired: function(el) {
676			var current = $(el.currentTarget);
677			if(current.prop('checked')){
678				this.model.set('required', 1);
679			}else{
680				this.model.set('required', 0);
681			}
682		},
683
684		setDefault: function(el) {
685			var def = '';
686			var current = $(el.currentTarget);
687			if(current.attr('data-index') != '0'){
688                 def = current.val();
689			}else{
690                var options = this.model.get('options');
691                var allKeys = _.keys(options);
692				var maxKey = parseInt(allKeys.pop());
693				maxKey = maxKey * 2;
694				def=maxKey;
695			}
696			this.model.set('default', def);
697		},
698
699		addNewOption: function() {
700			//WPB-4314 use iconography instead of text
701			this.$el.find('#add_new_option_row').before('<div class="option-editor-row">'
702            +    '<input type="text" class="radio_option_input" data-index="0" value="">'
703            +    '<div class="option-actions">'
704            +      '<input name="radio_option_default" type="radio" class="radio_option_default" data-index="0" value="1"> Preselect'
705            +      '<button title="Delete Radio option" class="btn delete_option"><i class="fa-regular fa-circle-xmark"></i></button>'
706            +    '</div>'
707            +  '</div>');
708			return false;
709        },
710
711		deleteOption: function(el) {
712            var radio_button = $(el.currentTarget).siblings('input[type="radio"]');//WPB-4314
713            var def = this.model.get('default');
714            var curr = radio_button.attr('data-index');
715            
716            if(curr==def){
717                this.model.set('default', '');
718            }
719            
720            $(el.currentTarget).parent().parent().remove(); //WPB-4314
721            
722            this.setOptions();
723            return false;
724        },
725
726		getDefaultModel: function() {
727			return {
728				type: 'radios',
729				label: 'Radio Buttons',
730				attributes: {
731				},
732				options: {
733					'1': 'Option 1',
734					'2': 'Option 2',
735					'4': 'Option 3', // donot change to 3 here.
736				},
737				description: '',
738			};
739		},
740
741        getPreviewTemplate: function() {
742            // NEW ICON LAYOUT
743            var icon = window.cq.fieldDefinitions['radios'].stacked_icon;
744            var title = '<%=label%>';
745            if(this.model.get('required') == 1) { title += ' (Required)'; }
746            var optionHtml = '';
747            var options = this.model.get('options');
748            var def = this.model.get('default');
749            for( var key in options){
750                var chk='';
751                if(key==def)
752                    chk='checked';
753                optionHtml += '<div><input class="option_input" type="radio" name="<%=name%>" value="' + key + '" '+chk+' disabled>&nbsp;' + options[key] + '</div>';
754            }
755            return '<div class="sp-row row" title="' + title + '">'
756                 + '  <div class="preview-icon">' + icon + '</div>'
757                 + '  <div class="preview-content"><label><%=label%></label>' + optionHtml + '</div>'
758                 + '</div>';
759        },
760
761		getFrontTemplate: function() {
762			var optionHtml = '';
763			var options = this.model.get('options');
764			var def = this.model.get('default');
765			for( var key in options){
766				var chk='';
767				var prevVal='false';
768				if(key==def){
769					chk='checked';
770					prevVal='true';
771				}
772				optionHtml += '<p><input class="option_input" type="radio" name="<%=name%>" value="' + key + '" '+chk+' previousValue="'+prevVal+'">' + options[key] + '</p>';
773			}
774			return '<p><%if(required == 1){%><span style="color:red;">*</span><%}%><%=label%></p>' + optionHtml;
775		},
776
777		getFieldEditorTemplate: function() {
778            var options = this.model.get('options');
779            var def = this.model.get('default');
780            var optionsHtml = '';
781            for(var i in options){
782                var chk='';
783                if(i==def)
784                    chk='checked';
785                //WPB-4314 use iconography instead of text
786				optionsHtml 
787					+= '<div class="option-editor-row">'
788					+    '<input type="text" class="radio_option_input" data-index="' + i + '" value="' + options[i] + '">'
789					+    '<div class="option-actions">'
790					+      '<input name="radio_option_default" type="radio" class="radio_option_default" data-index="' + i + '" value="'+ i +'" '+chk+'> Preselect'
791					+      '<button title="Delete Radio option" class="btn delete_option"><i class="fa-regular fa-circle-xmark"></i></button>'
792					+    '</div>'
793					+  '</div>';
794            }
795            optionsHtml += '<div class="option-editor-row" id="add_new_option_row"><button id="add_new_option" title="Add New Radio Option" class="btn">+ Add new option</button></div>';
796            
797            //WPB-4314 stacked layout
798            return ''
799            + '<div class="sp-row">'
800            + '  <label for="label">Label</label>'
801            + '  <input id="label" name="label" type="text" class="form-control" value="<%=label%>">'
802            + '</div>'
803			+ '<div class="sp-row">' 
804			+ '  <label>Options</label>' 
805			+ '  <div class="options-list-container">' + optionsHtml + '</div>' 
806			+ '</div>'
807            + '<div class="sp-row checkbox-row">'
808            + '  <input <%if(required == 1){%>checked<%}%> type="checkbox" id="required" name="required" value="1" />'
809            + '  <label for="required">Required</label>'
810            + '</div>'
811            + '';
812        },
813
814		validate: function(){
815			if(this.model.get('required') == 1){
816				if(_.isUndefined(this.$el.find('input:checked').val())){
817					//WPB-134 -- radios
818					try {
819						jQuery('#btnSignSubmit_divMsg').html('');
820					}
821					catch(e){}
822					alert('Please make a selection for "' + this.model.get('label') + '".');//WPB-4314 
823					return false;
824				}
825			}
826			return true;
827		},
828
829		toggleRadio: function(el){
830              var previousValue = $(el.currentTarget).attr('previousValue');
831			  var name = $(el.currentTarget).attr('name');
832			  if (previousValue == 'true') {
833			    $(el.currentTarget).removeAttr('checked');
834			    $(el.currentTarget).attr('previousValue', 'false');
835			  }
836			  else {
837			    $("input[name="+name+"]:radio").attr('previousValue', 'false');
838			    $(el.currentTarget).attr('previousValue', 'true');
839			  }
840		}
841	});
842	
843	// ===========================================================================
844	var CheckboxesFieldView = FieldView.extend({
845		events: function(){
846			return _.extend({},FieldView.prototype.events,{
847				'change #label' : 'setLabel',
848				'change .radio_option_input': 'setOptions',
849				'click #add_new_option': 'addNewOption',
850				'change #required' : 'setRequired',
851				'click .delete_option': 'deleteOption',
852                'click .check_option_default' : 'setDefault',
853			});
854		},
855
856		setLabel: function(el) {
857			var current = $(el.currentTarget);
858			this.model.set('label', current.val());
859		},
860
861		setOptions: function() {
862			var options = {};
863			this.$el.find('.radio_option_input').each(function(){
864				if($(this).attr('data-index') != '0'){
865					options[$(this).attr('data-index')] = $(this).val();
866				}else{
867					addOption($(this).val(), options);
868					var allKeys = _.keys(options);
869		            var maxKey = parseInt(allKeys.pop());
870					var newDef = $(this).next().next();
871					newDef.val(maxKey);
872					$(newDef).attr('data-index',maxKey);
873				}
874			});
875
876			this.model.set('options', options);
877		},
878		setRequired: function(el) {
879			var current = $(el.currentTarget);
880			if(current.prop('checked')){
881				this.model.set('required', 1);
882			}else{
883				this.model.set('required', 0);
884			}
885		},
886		//WPB-4314 use iconography instead of text	
887		addNewOption: function() {
888			this.$el.find('#add_new_option_row').before('<div class="option-editor-row">'
889			+    '<input type="text" class="radio_option_input" data-index="0" value="">'
890			+    '<div class="option-actions">'
891			+      '<input type="checkbox" class="check_option_default" name="radio_option_default[]" data-index="0" value="
8910"> Preselect'
892			+      '<button class="btn delete_option"><i class="fa-regular fa-circle-xmark"></i></button>'
893			+    '</div>'
894			+  '</div>');
895			return false;
896		},
897
898		deleteOption: function(el) {
899            var checkbox = $(el.currentTarget).siblings('input[type="checkbox"]');//WPB-4314
900            var curr = checkbox.attr('data-index');//WPB-4314
901            var defCheck = this.model.get('defaultCheck');
902            
903            if(defCheck!=undefined){
904                if(defCheck.indexOf(curr)>=0){
905                    defCheck.splice(defCheck.indexOf(curr), 1);
906                    this.model.set('defaultCheck', defCheck);
907                }
908            }
909            
910            $(el.currentTarget).parent().parent().remove(); //WPB-4314
911            
912            this.setOptions();
913            return false;
914        },
915
916		getDefaultModel: function() {
917			return {
918				type: 'checkboxes',
919				label: 'Checkboxes',
920				attributes: {
921				},
922				options: {
923					'1': 'Check 1',
924					'2': 'Check 2',
925					'4': 'Check 3',  // donot change to 3 here.
926				},
927				description: '',
928			};
929		},
930
931        getPreviewTemplate: function() {
932            // NEW ICON LAYOUT
933            var icon = window.cq.fieldDefinitions['checkboxes'].stacked_icon;
934            var title = '<%=label%>';
935            if(this.model.get('required') == 1) { title += ' (Required)'; }
936            var optionHtml = '';
937            var options = this.model.get('options');
938            var defCheck = this.model.get('defaultCheck');
939            for( var key in options){
940                var chk = '';   
941                if(defCheck!=undefined){
942                    if(defCheck.indexOf(key)>=0){
943                        chk='checked';
944                    }
945                }
946                optionHtml += '<div><input type="checkbox" name="<%=name%>[]" value="' + key + '" '+chk+' disabled>&nbsp;' + options[key] + '</div>';
947            }
948            return '<div class="sp-row row" title="' + title + '">'
949                 + '  <div class="preview-icon">' + icon + '</div>'
950                 + '  <div class="preview-content"><label><%=label%></label>' + optionHtml + '</div>'
951                 + '</div>';
952        },
953
954		getFrontTemplate: function() {
955			var optionHtml = '';
956			var options = this.model.get('options');
957			var defCheck = this.model.get('defaultCheck');
958			for( var key in options){
959				var chk = '';	
960				if(defCheck!=undefined){
961					if(defCheck.indexOf(key)>=0){
962						chk='checked';
963					}
964				}
965				optionHtml += '<p><input type="checkbox" name="<%=name%>[]" value="' + key + '" '+chk+'>' + options[key] + '</p>';
966			}
967			return '<p><%if(required == 1){%><span style="color:red;">*</span><%}%><%=label%></p>' + optionHtml;
968		},
969
970		getFieldEditorTemplate: function() {
971            var options = this.model.get('options');
972            var optionsHtml = '';
973            var defCheck = this.model.get('defaultCheck');
974            for(var i in options){
975                var chk = '';   
976                if(defCheck!=undefined){
977                    if(defCheck.indexOf(i)>=0){
978                        chk='checked';
979                    }
980                }
981                optionsHtml 
982				//WPB-4314 use iconography instead of text
983                    += '<div class="option-editor-row">'
984                    +    '<input type="text" class="radio_option_input" data-index="' + i + '" value="' + options[i] + '">'
985                    +    '<div class="option-actions">'
986                    +      '<input type="checkbox" class="check_option_default" name="radio_option_default[]" data-index="' + i + '" value="' + i + '" '+chk+'> Preselect'
987                    +      '<button title="Delete Checkbox option" class="btn delete_option"><i class="fa-regular fa-circle-xmark"></i></button>'
988                    +    '</div>'
989                    +  '</div>';
990            }
991            optionsHtml += '<div class="option-editor-row" id="add_new_option_row"><button id="add_new_option" title="Add New Checkbox Option" class="btn">+ Add new option</button></div>';
992            //WPB-4314 new stacked layout
993            return ''
994            + '<div class="sp-row">'
995            + '  <label for="label">Label</label>'
996            + '  <input id="label" name="label" type="text" class="form-control" value="<%=label%>">'
997            + '</div>'
998            + '<div class="sp-row">'
999            + '  <label>Options</label>'
1000            + '  <div class="options-list-container">' + optionsHtml + '</div>'
1001            + '</div>'
1002            + '<div class="sp-row checkbox-row">'
1003            + '  <input <%if(required == 1){%>checked<%}%> type="checkbox" id="required" name="required" value="1" />'
1004            + '  <label for="required">Required</label>'
1005            + '</div>'
1006            + '';
1007        },
1008
1009		validate: function(){
1010			if(this.model.get('required') == 1){
1011				if(_.isUndefined(this.$el.find('input:checked').val())){
1012					//WPB-134 -- Checkbox
1013					try {
1014						jQuery('#btnSignSubmit_divMsg').html('');
1015					}
1016					catch(e){}
1017					alert('Please select at least one option for "' + this.model.get('label') + '".');//WPB-4314
1018					return false;
1019				}
1020			}
1021			return true;
1022		},
1023
1024		setDefault: function(el) {
1025			if(this.model.get('defaultCheck')==undefined)
1026			 var def = [];
1027			else
1028             var def = this.model.get('defaultCheck');
1029			var current = $(el.currentTarget);
1030			if(current.prop('checked')){
1031			 if(current.attr('data-index') != '0'){
1032                 def.push(current.val());
1033			 }else{
1034                var options = this.model.get('options');
1035                var allKeys = _.keys(options);
1036				var maxKey = parseInt(allKeys.pop());
1037				maxKey = maxKey * 2;
1038				def.push(maxKey);
1039			 }
1040			}else{
1041				if(current.attr('data-index') != '0'){
1042					var k = def.indexOf(current.val());
1043					def.splice(k, 1);
1044				 }else{
1045	                var options = this.model.get('options');
1046	                var allKeys = _.keys(options);
1047					var maxKey = parseInt(allKeys.pop());
1048					maxKey = maxKey * 2;
1049					var k = def.indexOf(maxKey);
1050					def.splice(k, 1);
1051				 }
1052			}
1053			this.model.set('defaultCheck', def);
1054			var uniqueId = window.cq.uniqueId-1;
1055			var name = 'cq_field_' + uniqueId;
1056			
1057			 $('.highlight').find("input").each( function () {
1058			       var val = $(this).val();
1059			       if(def.indexOf(val)>=0)
1060			       	 $(this).attr('checked',true);
1061			       else
1062			        $(this).removeAttr('checked');	
1063			 });
1064		},
1065	});
1066	
1067	// ===========================================================================
1068	// WPB-4314
1069	var HTMLFieldView = FieldView.extend({
1070		events: function(){
1071			return _.extend({}, FieldView.prototype.events, {
1072				'keyup #html_content' : 'setHTML', // change keyup etc...
1073				'click #toggle_preview' : 'togglePreview'
1074			});
1075		},
1076
1077		setHTML: function(el) {
1078			var current = $(el.currentTarget);
1079			this.model.set('html', current.val());
1080			this.$('.editor-preview').html(current.val());
1081		},
1082
1083		togglePreview: function(e) {
1084			e && e.preventDefault();
1085			this.$('.editor-preview').toggle();
1086		},
1087
1088		getDefaultModel: function() {
1089			return {
1090				type: 'html',
1091				html: '<p><b>Enter your custom text or HTML here.</b></p>',
1092				description: 'Use this field to add custom HTML, instructional text, headings, or dividers within your form.'
1093			};
1094		},
1095
1096        getPreviewTemplate: function() {
1097            // NEW ICON LAYOUT
1098            var icon = window.cq.fieldDefinitions['html'].stacked_icon;
1099            return '<div class="sp-row row" title="Custom HTML">'
1100                 + '  <div class="preview-icon">' + icon + '</div>'
1101                 + '  <div class="preview-content"><div class="html-preview-small">
1101<%= html %></div></div>'
1102                 + '</div>';       
1103        },
1104
1105		// front form render (no label, just raw HTML)
1106		getFrontTemplate: function() {
1107			return '<div class="cq-html-block"><div class="cq-html-content"><%= html %></div></div>';
1108		},
1109
1110		// editor UI: only textarea + preview
1111        getFieldEditorTemplate: function() {
1112            return ''
1113            + '<div class="sp-row">'
1114            + '  <label for="html_content">HTML / Text</label>'
1115            + '  <textarea id="html_content" class="form-control" rows="6"><%= html %></textarea>'
1116            + '  <p class="description">You can add <b>custom HTML for instructions, headings, or visual dividers.</b></p>'
1117            + '  <div style="margin-top: 10px;">' 
1118            + '    <button id="toggle_preview" class="btn">Toggle Preview</button>'
1119            + '  </div>'
1120            + '  <div class="editor-preview" style="margin-top: 10px;"><%= html %></div>' 
1121            + '</div>';
1122        },
1123
1124		render: function() {
1125			this.$el.html(_.template(this.getFieldEditorTemplate())(this.model.toJSON()));
1126			var that = this;
1127			this.listenTo(this.model, 'change:html', function(m, val){
1128				that.$('#html_content').val(val);
1129				that.$('.editor-preview').html(val);
1130			});
1131			return this;
1132		},
1133
1134		renderFrontHtml: function() {
1135			this.$el.html(_.template(this.getFrontTemplate())(this.model.toJSON()));
1136			return this;
1137		},
1138		//WPB-4314 use iconography instead of text
1139		renderFormPreview: function() {
1140			var highlight = (this.model.get('highlight') == 1 ? 'highlight' : '');
1141			this.$el.html('<div class="field-form-preview clearfix ' + highlight + '"><div class="field-actions"><a class="field-delete-btn" href="#"><i class="fa-regular fa-circle-xmark"></i></a></div>' + this.getPreviewHtml() + '</div>');
1142		},
1143
1144		validate: function(){
1145			return true;
1146		}
1147	});
1148
1149	// ===========================================================================
1150	// WPB-4314 -- copy radio field view and did chanes as per select options.
1151	var DropDownFieldView = FieldView.extend({
1152		events: function(){
1153			return _.extend({},FieldView.prototype.events,{
1154				'change #label' : 'setLabel',
1155				'change .select_option_input': 'setOptions',
1156				'click #add_new_option': 'addNewOption',
1157				'click .delete_option': 'deleteOption',
1158				'change #required' : 'setRequired',
1159				'change .select_option_default' : 'setDefault',
1160			});
1161		},
1162
1163		setLabel: function(el) {
1164			var current = $(el.currentTarget);
1165			this.model.set('label', current.val());
1166		},
1167
1168		setOptions: function() {
1169			var options = {};
1170			this.$el.find('.select_option_input').each(function(){
1171				if($(this).attr('data-index') != '0'){
1172					options[$(this).attr('data-index')] = $(this).val();
1173				}else{
1174					addOption($(this).val(), options);
1175					var allKeys = _.keys(options);
1176		            var maxKey = parseInt(allKeys.pop());
1177					var newDef = $(this).next().next();
1178
1179					newDef.val(maxKey);
1180					$(newDef).attr('data-index',maxKey);
1181				}
1182			});
1183
1184			this.model.set('options', options);
1185		},
1186		setRequired: function(el) {
1187			var current = $(el.currentTarget);
1188			if(current.prop('checked')){
1189				this.model.set('required', 1);
1190			}else{
1191				this.model.set('required', 0);
1192			}
1193		},
1194
1195		setDefault: function(el) {
1196			var def = '';
1197			var current = $(el.currentTarget);
1198			if(current.attr('data-index') != '0'){
1199                 def = current.val();
1200			}else{
1201                var options = this.model.get('options');
1202                var allKeys = _.keys(options);
1203				var maxKey = parseInt(allKeys.pop());
1204				maxKey = maxKey * 2;
1205				def=maxKey;
1206			}
1207			this.model.set('default', def);
1208		},
1209		//WPB-4314 use iconography instead of text
1210		addNewOption: function() {
1211			this.$el.find('#add_new_option_row').before('<div class="option-editor-row">'
1212			+    '<input type="text" class="select_option_input" data-index="0" value="">'
1213			+    '<div class="option-actions">'
1214			+      '<input name="select_option_default" type="radio" class="select_option_default" data-index="0" value="1"> Preselect'
1215			+      '<button class="btn delete_option"><i class="fa-regular fa-circle-xmark"></i></button>'
1216			+    '</div>'
1217			+  '</div>');
1218			return false;
1219		},
1220		deleteOption: function(el) {
1221            var radio_button = $(el.currentTarget).siblings('input[type="radio"]');//WPB-4314
1222            var def = this.model.get('default');
1223            var curr = radio_button.attr('data-index');//WPB-4314
1224            
1225            if(curr==def){
1226                this.model.set('default', '');
1227            }
1228            
1229            $(el.currentTarget).parent().parent().remove(); //WPB-4314
1230            
1231            this.setOptions();
1232            return false;
1233        },	
1234
1235		getDefaultModel: function() {
1236			return {
1237				type: 'dropdown', // select
1238				label: 'Drop Down',
1239				attributes: {
1240				},
1241				options: {
1242					'1': 'Option 1',
1243					'2': 'Option 2',
1244					'4': 'Option 3', // radios, checkboxes also 4. so, keeping 4. donot change to 3. new option will be 8
1245				},
1246				description: '',
1247			};
1248		},
1249
1250        getPreviewTemplate: function() {
1251            // NEW ICON LAYOUT
1252            var icon = window.cq.fieldDefinitions['dropdown'].stacked_icon;
1253            var title = '<%=label%>';
1254            if(this.model.get('required') == 1) { title += ' (Required)'; }
1255            var optionHtml = '';
1256            var options = this.model.get('options');
1257            var def = this.model.get('default');
1258            optionHtml = '<div><select class="select_input" name="<%=name%>">'; // REMOVED disabled
1259            for( var key in options){
1260                var chk='';
1261                if(key==def)
1262                    chk='selected';
1263                optionHtml += '<option value="' + key + '" '+chk+'>' + options[key] + '</option>';
1264            }
1265            optionHtml += '</select></div>';
1266
1267            return '<div class="sp-row row" title="' + title + '">'
1268                 + '  <div class="preview-icon">' + icon + '</div>'
1269                 + '  <div class="preview-content"><label><%=label%></label>' + optionHtml + '</div>'
1270                 + '</div>';
1271        },
1272
1273		getFrontTemplate: function() {
1274			var optionHtml = '';
1275			var options = this.model.get('options');
1276			var def = this.model.get('default');
1277			optionHtml = '<p><select class="select_input" name="<%=name%>">';
1278			for( var key in options){
1279				var chk='';
1280				var prevVal='false';
1281				if(key==def){
1282					chk='selected';
1283					prevVal='true';
1284				}
1285				optionHtml += '<option value="' + key + '" '+chk+' previousValue="'+prevVal+'">' + options[key] + '</option>';
1286			}
1287			optionHtml += '</select></p>';
1288
1289			return '<p><%if(required == 1){%><span style="color:red;">*</span><%}%><%=label%></p>' + optionHtml;
1290		},
1291
1292		getFieldEditorTemplate: function() {
1293            var options = this.model.get('options');
1294            var def = this.model.get('default');
1295            var optionsHtml = '';
1296            for(var i in options){
1297                var chk='';
1298                if(i==def)
1299                    chk='selected';
1300                //WPB-4314 Psotion field actions below input
1301                optionsHtml 
1302                    += '<div class="option-editor-row">'
1303                    +    '<input type="text" class="select_option_input" data-index="' + i + '" value="' + options[i] + '">'
1304                    +    '<div class="option-actions">'
1305                    +      '<input name="select_option_default" type="radio" class="select_option_default" data-index="' + i + '" value="'+ i +'" '+chk+'> Preselect'
1306                    +      '<button title="Delete Drop Down option" class="btn delete_option"><i class="fa-regular fa-circle-xmark"></i></button>'
1307                    +    '</div>'
1308                    +  '</div>';
1309            }
1310            optionsHtml += '<div class="option-editor-row" id="add_new_option_row"><button id="add_new_option" title="Add New Drop Down Option" class="btn">+ Add new option</button></div>';
1311			//WPB-4314 minor structural changes so everything fits on smaller screens
1312            return ''
1313            + '<div class="sp-row">'
1314            + '  <label for="label">Label</label>'
1315            + '  <input id="label" name="label" type="text" class="form-control" value="<%=label%>">'
1316            + '</div>'
1317            + '<div class="sp-row">'
1318            + '  <label>Options</label>'
1319            + '  <div class="options-list-container">' + optionsHtml + '</div>'
1320            + '</div>'
1321            + '<div class="sp-row checkbox-row">'
1322            + '  <input <%if(required == 1){%>checked<%}%> type="checkbox" id="required" name="required" value="1" />'
1323            + '  <label for="required">Required</label>'
1324            + '</div>'
1325            + '';
1326        },
1327
1328		validate: function(){
1329			if(this.model.get('required') == 1){
1330				if(this.$el.find('select').val() === ''){ // select box. so, diff here than radio checked.
1331					//WPB-134 -- dropdown/select
1332					try {
1333						jQuery('#btnSignSubmit_divMsg').html('');
1334					}
1335					catch(e){}
1336					alert('Please make a selection for "' + this.model.get('label') + '".');//WPB-4314 
1337					return false;
1338				}
1339			}
1340			return true;
1341		},
1342
1343		toggleRadio: function(el){
1344              var previousValue = $(el.currentTarget).attr('previousValue');
1345			  var name = $(el.currentTarget).attr('name');
1346			  if (previousValue == 'true') {
1347			    $(el.currentTarget).removeAttr('checked');
1348			    $(el.currentTarget).attr('previousValue', 'false');
1349			  }
1350			  else {
1351			    $("input[name="+name+"]:radio").attr('previousValue', 'false');
1352			    $(el.currentTarget).attr('previousValue', 'true');
1353			  }
1354		}
1355	});
1356	// ===========================================================================
1357
1358})(window.jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.