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">← 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> ' + 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> ' + 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.