PluginProbe
Smart Grid-Layout Design for Contact Form 7 / 4.5
Smart Grid-Layout Design for Contact Form 7 v4.5
4.18.0 4.17.0 3.2.0 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 4.0.0 4.0.1 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10 4.11 4.12 4.13 4.14 All 119 releases
← All changes | admin/js/cf7-grid-layout-admin.js +405 -241 3.2.14.5 View file →
@@ -1,24 +1,24 @@
1 1
2 -/**
3 - Javascript to handle grid editor
4 - Event 'cf7sg-form-change' fired on #contact-form-editor element when codemirror changes occur
5 -*/
6 2 (function( $ ) {
7 - var offsets = ['offset-one','offset-two', 'offset-three', 'offset-four', 'offset-five', 'offset-six', 'offset-seven', 'offset-eight', 'offset-nine', 'offset-ten', 'offset-eleven'];
8 - var columnsizes = ['one', 'two', 'one-fourth', 'one-third', 'five', 'one-half', 'seven', 'two-thirds', 'nine', 'ten', 'eleven', 'full'];
9 - var $wpcf7Editor,$grid,$rowControl = null;
3 + 'use strict';
4 + /**
5 + * Javascript to handle grid editor
6 + * Event 'cf7sg-form-change' fired on #contact-form-editor element when codemirror changes occur
7 + */
8 + const offsets = ['offset-one','offset-two', 'offset-three', 'offset-four', 'offset-five', 'offset-six', 'offset-seven', 'offset-eight', 'offset-nine', 'offset-ten', 'offset-eleven'],
9 + columnsizes = ['one', 'two', 'one-fourth', 'one-third', 'five', 'one-half', 'seven', 'two-thirds', 'nine', 'ten', 'eleven', 'full'];
10 + let $wpcf7Editor,$grid,$rowControl = null;
10 11 //graphics UI template pattern
11 - var $pattern = $('<div>').html(cf7grid.preHTML+'\\s*(\\[.*\\s*\\].*\\s*){0,}\\s*'+cf7grid.postHTML);
12 - var required = cf7grid.requiredHTML.replace('*', '\\*');
12 + const $pattern = $('<div>').html(cf7grid.preHTML+'\\s*(\\[.*\\s*\\].*\\s*){0,}\\s*'+cf7grid.postHTML),
13 + required = cf7grid.requiredHTML.replace('*', '\\*');
13 14 // console.log('r:'+required);
14 15 $pattern.find('label').html('((\\s*.*)('+required+'){1}|(\\s*.*))');
15 16 $pattern.find('.info-tip').text('(.*\\s*)');
16 17 //console.log('p:'+$pattern.html());
17 - var templateRegex = new RegExp($pattern.html(), 'ig');
18 - var seekTemplate = false;
19 - var cssTemplate = 'div.field';
20 - var $template = $('<div id="cf7sg-dummy">').append(cf7grid.preHTML+cf7grid.postHTML);
18 + const templateRegex = new RegExp($pattern.html().replace('><','>\\s?<'), 'ig');
19 + let seekTemplate = false, cssTemplate = 'div.field',
20 + $template = $('<div id="cf7sg-dummy">').append(cf7grid.preHTML+cf7grid.postHTML);
21 21 $template = $template.children();
22 22 if(1==$template.length && $template.find('label').length>0){
23 23 seekTemplate = true;
24 24 cssTemplate = $template.prop('nodeName');
@@ -25,25 +25,21 @@
25 25 if($template.prop('class').length>0){
26 26 cssTemplate += '.'+$template.attr('class').split(' ').join('.');
27 27 }
28 28 }
29 - var wpcf7Value = '';
29 + let wpcf7Value = '';
30 30
31 31 $(document).ready( function(){
32 32 //change the form id to mimic cf7 plugin custom admin page.
33 33 /** @since 2.11.0 full screen button*/
34 - var $editor = $('#cf7sg-editor'),
35 - bodyWidth = $('#wpbody').width();
34 + let $editor = $('#cf7sg-editor') ;
36 35 $editor.css('background-color',$('body').css('background-color'));
37 36 $('#full-screen-cf7').on('click', function(){
38 37 $editor.toggleClass('full-screen');
39 38 $(this).toggleClass('full-screen');
40 - if($editor.is('.full-screen')) $editor.width(bodyWidth);
41 - else $editor.width('auto');
42 - // $oldParent = $editor.parent();
43 - // $editor.detach();
44 - // $nextParent.prepend($editor);
45 - // $nextParent = $oldParent;
39 + // if($editor.is('.full-screen')) $editor.width($('#wpbody').width());
40 + // else $editor.width('auto');
41 + $('#form-editor-tabs .ui-tabs-panel', $editor).trigger('cf7sg-screen-resize');
46 42 });
47 43 $wpcf7Editor = $('textarea#wpcf7-form-hidden');
48 44 $grid = $('#grid-form');
49 45 $rowControl = $('#top-grid-controls');
@@ -51,14 +47,14 @@
51 47 /*
52 48 Build grid from existing form------------------------- BUILD UI FORM
53 49 */
54 50 function buildGridForm(){
55 - var formhtml = $wpcf7Editor.text();
51 + let formhtml = $wpcf7Editor.text();
56 52 if(0===formhtml.length){
57 53 formhtml = '<div class="container"><div class="row"><div class="columns full"></div></div></div>';
58 54 }
59 - var $form = $('<div>').append( formhtml );
60 - var isGrid = true; //return value.
55 + const $form = $('<div>').append( formhtml );
56 + let isGrid = true; //return value.
61 57 $grid.html(''); //empty the grid.
62 58 if(0===$form.children('.container').length){
63 59 isGrid = false;
64 60 }
@@ -66,10 +62,9 @@
66 62 $('.cf7sg-external-form .cf7sg-external-form-content', $form).remove();
67 63 //replace columns content with textareas
68 64 /*--------------------------------------------------- convert columns */
69 65 $('div.columns', $form).each(function(){
70 - var $this = $(this);
71 - var $area = $($('#grid-col').html());
66 + const $this = $(this), $area = $($('#grid-col').html());
72 67 if($this.children().is('.container')){
73 68 $('textarea.grid-input', $area).remove();
74 69 $('div.cf7-field-inner', $area).remove();
75 70 }else{
@@ -85,19 +80,19 @@
85 80 $(this).append( $('#grid-row .row-controls').clone() );
86 81 });
87 82 /*--------------------------------------------------- convert collapsible sections */
88 83 $('div.container.cf7sg-collapsible', $form).each(function(){
89 - var $this = $(this);
90 - var id = $this.attr('id');
84 + const $this = $(this);
85 + let id = $this.attr('id');
91 86 if(typeof id == 'undefined'){
92 87 id = randString(6);
93 88 $this.attr('id', id); //assign a random id
94 89 }
95 - var text = $this.children('.cf7sg-collapsible-title span.cf7sg-title').text();
90 + let text = $this.children('.cf7sg-collapsible-title span.cf7sg-title').text();
96 91 if(0==text.length){ //pre v1.8 title?.
97 92 text = $this.children('.cf7sg-collapsible-title').text();
98 93 }
99 - var $toggle = $('.toggle', $this.children('.cf7sg-collapsible-title'));
94 + let $toggle = $('.toggle', $this.children('.cf7sg-collapsible-title'));
100 95 if($toggle.length>0){
101 96 $toggle = $toggle.clone();
102 97 }
103 98
@@ -107,9 +102,9 @@
107 102 if($toggle.length>0){
108 103 $this.children('.cf7sg-collapsible-title').append($toggle);
109 104 $('input[type="checkbox"]', $this.children('.cf7sg-collapsible-title') ).prop('checked', true);
110 105 }
111 - var $ctrl = $this.children('.row').children('.row-controls').find('.collapsible-row-label');
106 + const $ctrl = $this.children('.row').children('.row-controls').find('.collapsible-row-label');
112 107 $('input', $ctrl).prop('checked', true);
113 108 //toggle disable the sibling input
114 109 $('input', $ctrl.siblings('.unique-mod')).prop('disabled', function(i,v){return !v;});
115 110 });
@@ -114,18 +109,18 @@
114 109 $('input', $ctrl.siblings('.unique-mod')).prop('disabled', function(i,v){return !v;});
115 110 });
116 111 /*--------------------------------------------------- convert tables */
117 112 $('div.container.cf7-sg-table', $form).each(function(){
118 - var $this = $(this);
119 - var id = $this.attr('id');
113 + const $this = $(this);
114 + let id = $this.attr('id');
120 115 if(typeof id == 'undefined'){
121 116 id = 'cf7-sg-table-'+(new Date).getTime();
122 117 $this.attr('id', id);
123 118 }
124 - var $ctrl = $this.find('.row.cf7-sg-table > .row-controls' ).first().find('.table-row-label');
119 + let $ctrl = $this.find('.row.cf7-sg-table > .row-controls' ).first().find('.table-row-label');
125 120 $('input', $ctrl).prop('checked', true);
126 121 //set button label
127 - var text = $this.data('button');
122 + let text = $this.data('button');
128 123 if(typeof text == 'undefined'){
129 124 text = 'Add Row';
130 125 $this.attr('data-button',text);
131 126 }
@@ -132,9 +127,9 @@
132 127 $ctrl.next('.table-row-button').children('input').val(text);
133 128 //toggle disable the sibling input
134 129 $('input', $ctrl.siblings('.unique-mod')).prop('disabled', function(i,v){return !v;});
135 130 //toggle footer row
136 - var $footer = $this.next();
131 + const $footer = $this.next();
137 132 if($footer.is('.cf7-sg-table-footer')){
138 133 $ctrl = $footer.children('.row').first().find('.row-controls .footer-row-label');
139 134 $('input.footer-row', $ctrl).prop('checked', true);
140 135 $('input', $ctrl.siblings('.unique-mod')).prop('disabled', function(i,v){return !v;});
@@ -142,14 +137,14 @@
142 137 });
143 138 //tabs
144 139 /*--------------------------------------------------- convert tabs */
145 140 $('ul.cf7-sg-tabs-list li', $form).each(function(){
146 - var $this = $(this);
147 - var text = $this.children('a').text();
141 + const $this = $(this);
142 + let text = $this.children('a').text();
148 143 $this.append($('#grid-tabs ul li label').clone());
149 144 $('label input', $this).val(text);
150 145 //setup checkbox
151 - var $ctrl = $this.parent().siblings('.cf7-sg-tabs-panel');
146 + let $ctrl = $this.parent().siblings('.cf7-sg-tabs-panel');
152 147 $ctrl = $ctrl.children('.row').find('.row-controls' ).first().find('.tabs-row-label');
153 148 $('input.tabs-row', $ctrl).prop('checked', true);
154 149 $('input', $ctrl.siblings('.unique-mod')).prop('disabled', function(i,v){return !v;});
155 150 });
@@ -154,17 +149,17 @@
154 149 $('input', $ctrl.siblings('.unique-mod')).prop('disabled', function(i,v){return !v;});
155 150 });
156 151 //reinsert the external forms
157 152 $('.cf7sg-external-form', $form).each(function(){
158 - var $extform = $(this);
153 + const $extform = $(this);
159 154 $extform.append($( $('#grid-cf7-forms .cf7sg-external-form').html() ) );
160 - var id = $extform.data('form');
155 + let id = $extform.data('form');
161 156 if($('#grid-cf7-forms .form-select option[value="'+id+'"]' ).length > 0 ){
162 157 //add controls
163 158 //$extform.append($('#grid-cf7-forms .form-controls').clone());
164 159 $('.form-controls .form-select', $extform).val(id);
165 160 //check for form update.
166 - var data = {
161 + const data = {
167 162 'action' : 'get_cf7_content',
168 163 'id': $('#post_ID').val(),
169 164 'nonce' : $('#_wpcf7nonce').val(),
170 165 'cf7_key' : id,
@@ -177,8 +172,24 @@
177 172 });
178 173
179 174 }
180 175 });
176 + /** @since 3.4 enable groupings of collapsible rows */
177 + $('.cf7sg-accordion-rows.columns, .cf7sg-slider-section.columns', $form).each(function(){
178 + let $col = $(this),
179 + $control = $col.children('.grid-column').addClass('enable-grouping'); //enable checkboxes.
180 + if($col.is('.cf7sg-accordion-rows')){
181 + $('.accordion-rows:input', $control).prop('checked', true);
182 + }else{ //is .cf7sg-slider-section
183 + $('.slider-rows:input', $control).prop('checked', true);
184 + }
185 + //remove toggle checkbox.
186 + $('input[type="checkbox"]', $col.children('.cf7sg-collapsible').children('.cf7sg-collapsible-title') ).hide().next('span').hide();
187 + });
188 + //check if any columns have more than 2 collapsible sections.
189 + $('.row .cf7sg-collapsible:first-child', $form).each(function(){
190 + $(this).siblings('.cf7sg-collapsible').closest('.columns').children('.grid-column').addClass('enable-grouping');
191 + });
181 192 //add the form to the grid
182 193 if($form.children('.container').length >0 || $form.children('.cf7sg-external-form').length>0){
183 194 $grid.append($form.children());
184 195 }else{ //this is not a cf7sg form.
@@ -185,16 +196,16 @@
185 196 $grid.html($form.html());
186 197 }
187 198 //set the value of each textarea as inner text
188 199 $('textarea', $grid).each(function(){
189 - var $this = $(this);
200 + const $this = $(this);
190 201 $this.html($this.val());
191 202 });
192 203 /*--------------------------------------------------- if ui mode, then convert to gui template */
193 - var $textareaSelected='';
204 + let $textareaSelected='';
194 205 if(cf7grid.ui){
195 206 $('div.columns', $grid).each(function(){
196 - var $this = $(this);
207 + const $this = $(this);
197 208 if($this.children().is('.container')) return true;
198 209 $this.html2gui();
199 210 });
200 211 }else{
@@ -204,9 +215,9 @@
204 215 $textareaSelected.attr('id', 'wpcf7-form');
205 216 }
206 217 //change this to whichever is live
207 218 $('textarea', $grid).on('focus', function(){
208 - var $this = $(this);
219 + const $this = $(this);
209 220 if($textareaSelected.length>0 && $textareaSelected.is('#wpcf7-form')){
210 221 $textareaSelected.attr('id','');
211 222 $textareaSelected.html($textareaSelected.val()); //set its inner html
212 223 }
@@ -216,15 +227,38 @@
216 227 }
217 228 });
218 229 return isGrid;
219 230 } //end buildGridForm()
220 -
231 + /** @since 3.4.0 enalbe accordion class for containers having multiple collapsible rows */
232 + $grid.on('cf7sg-update', function(e, update){
233 + let $container = $(e.target);
234 + if(undefined !== update.add){
235 + switch(update.add){
236 + case 'collapsible-row':
237 + let $pc = $container.closest('.columns');
238 + if( $pc.children('.cf7sg-collapsible').length>1 ){
239 + //enable column accordion control.
240 + $pc.children('.grid-column').addClass('enable-grouping');
241 + }
242 + }
243 + }
244 + if(undefined !== update.remove){
245 + switch(update.remove){
246 + case 'collapsible-row':
247 + let $pc = $container.closest('.columns');
248 + if( $pc.children('.cf7sg-collapsible').length<2 ){
249 + //disable column accordion control.
250 + $pc.children('.grid-column').removeClass('enable-grouping');
251 + }
252 + }
253 + }
254 + });
221 255 //offset/size change using event delegation
222 256 /*---------------------------------------------------------------------------- ui menus */
223 257 $grid.on('change', function(event){
224 - var $target = $(event.target);
258 + const $target = $(event.target);
225 259 if($target.is('.column-setting')){ //----------- column size/offset settings
226 - var validation = ['dummy'];
260 + let validation = ['dummy'];
227 261 if( $target.is('.column-offset') ){
228 262 validation = offsets;
229 263 }else if( $target.is('.column-size') ){
230 264 validation = columnsizes;
@@ -230,12 +264,10 @@
230 264 validation = columnsizes;
231 265 }else{
232 266 return false;
233 267 }
234 - var $column = $target.closest('.columns');
235 - var classList = $column.attr('class').split(/\s+/);
236 - var idx;
237 - for(idx=0; idx<classList.length; idx++){
268 + const $column = $target.closest('.columns'), classList = $column.attr('class').split(/\s+/);
269 + for(let idx=0; idx<classList.length; idx++){
238 270 if($.inArray(classList[idx], validation) > -1){
239 271 $column.removeClass(classList[idx]);
240 272 }
241 273 }
@@ -242,11 +274,11 @@
242 274 $column.addClass($target.val());
243 275 //filter the options
244 276 $target.closest('.grid-controls').filterColumnControls();
245 277 }else if($target.is('.form-select')){ //-------------- external form selection
246 - var $container = $target.closest('.cf7sg-external-form');
278 + const $container = $target.closest('.cf7sg-external-form');
247 279 $container.attr('data-form', $target.val());
248 - var data = {
280 + const data = {
249 281 'action' : 'get_cf7_content',
250 282 'id': $('#post_ID').val(),
251 283 'nonce' : $('#_wpcf7nonce').val(),
252 284 'cf7_key' : $target.val()
@@ -260,15 +292,15 @@
260 292 */
261 293 if($target.is('.cf7sg-collapsible-title label input[type="text"]')){ //------- Collapsible title
262 294 $target.siblings('input[type="hidden"]').val($target.val());
263 295 }else if( $target.is('.cf7sg-collapsible-title label input[type="checkbox"]')){ //------- Collapsible title toggled
264 - var $title = $target.closest('.cf7sg-collapsible-title');
296 + const $title = $target.closest('.cf7sg-collapsible-title');
265 297 if($target.is(':checked')){
266 298 $title.append($('#grid-collapsible-with-toggle').html());
267 - $title.closest('.container.cf7sg-collapsible').addClass('with-toggle').attr('data-group','');
299 + $title.closest('.container.cf7sg-collapsible').addClass('with-toggle').attr('data-group','').attr('data-open','false');
268 300 }else{
269 301 $('.toggle', $title).remove();
270 - $title.closest('.container.cf7sg-collapsible').removeClass('with-toggle').removeAttr( 'data-group');
302 + $title.closest('.container.cf7sg-collapsible').removeClass('with-toggle').removeAttr( 'data-group').removeAttr( 'data-open');
271 303 }
272 304 }else if($target.is('ul.cf7-sg-tabs-list li label input[type="text"]')){ //------- Tabs title
273 305 $target.parent().siblings('a').text($target.val());
274 306 }else if($target.is('label.table-row-button input')){
@@ -275,9 +307,9 @@
275 307 $target.closest('.container.cf7-sg-table').attr('data-button',$target.val());
276 308 }
277 309 if(cf7grid.ui){
278 310 if($target.is('.cf7-field-inner textarea')){
279 - var label = $target.scanCF7Tag();
311 + let label = $target.scanCF7Tag();
280 312 $target.siblings('p.content').html(label);//.show();
281 313 $target.parent().siblings('textarea.grid-input').updateGridForm();
282 314 }else if($target.is('.cf7-field-inner input')){
283 315 $target.siblings('p.content').html($target.val());
@@ -283,13 +315,13 @@
283 315 $target.siblings('p.content').html($target.val());
284 316 $target.parent().siblings('textarea.grid-input').updateGridForm();
285 317 }
286 318 }
287 - });
319 + }); //end $grid.on('change');
288 320
289 321 //grid click event delegation
290 322 $grid.on('click', function(event){
291 - var $target = $(event.target);
323 + const $target = $(event.target);
292 324 switch(true){
293 325 case $target.is('input[type="text"]:visible'):
294 326 case $target.is('textarea:visible'): //click on a field.
295 327 case $target.is('select:visible'):
@@ -302,16 +334,16 @@
302 334 /*
303 335 Row controls
304 336 ----------------------------------------------------------ROW CONTRLS
305 337 */
306 - var $parentRow;
338 + let $parentRow,$parentContainer, $parentColumn;
307 339 if($target.is('.dashicons-trash.form-control')){ //--------TRASH included form
308 340 $target.closest('.cf7sg-external-form').remove();
309 341 }else if($target.is('.dashicons-plus.form-control') ){ //---ADD external form
310 342 $target.closest('.cf7sg-external-form').insertNewRow();
311 343 }else if($target.is('.dashicons-trash.row-control')){ //--------TRASH
312 - var $parentContainer = $target.closest('.container');
313 - var $parent = $parentContainer.parent();
344 + $parentContainer = $target.closest('.container');
345 + let $parent = $parentContainer.parent();
314 346 $parentContainer.remove();
315 347 if( $parent.is('.columns') ) { //verify is this is the last row being deleted
316 348 if( 0 == $parent.children('.container').length ){
317 349 //add a text area to the column
@@ -322,12 +354,9 @@
322 354 $target.closest('.container').insertNewRow();
323 355 }else if($target.is('.dashicons-edit.row-control')){ //-----------Show controls
324 356 //hide any other controls that might be open
325 357 //taken care by closeAllControls
326 - // $('.grid-controls', $grid).hide();
327 - // $('.dashicons-no-alt', $grid).hide();
328 - // $('.dashicons-edit', $grid).show();
329 - //now show this control
358 +
330 359 $target.siblings('.grid-controls').show();
331 360 $target.hide();
332 361 $target.siblings('.dashicons-no-alt').show();
333 362 /*
@@ -335,64 +364,84 @@
335 364 possibly introduce a boolean to check if filter has been run already on this row
336 365 */
337 366 }else if( $target.is('.dashicons-no-alt.row-control') ) { //----------------hide controls
338 367 //take care by closeAllControls
339 - // $target.siblings('.grid-controls').hide();
340 - // $target.hide();
341 - // $target.siblings('.dashicons-edit').show();
342 368 }else if($target.is('input.collapsible-row')){ //-------------checkbox collapsible row
343 - var $container = $target.closest('.container');
369 + const $container = $target.closest('.container');
344 370 if($target.is(':checked')){
345 371 $container.addClass('cf7sg-collapsible');
346 - var id = $container.attr('id');
372 + let id = $container.attr('id');
347 373 if(typeof id == 'undefined'){
348 374 id = randString(6);
349 375 $container.attr('id', id); //assign a random id
350 376 }
351 - $container.prepend($('#grid-collapsible').html());
377 + $container.prepend($('#grid-collapsible').html()).fireGridUpdate('add','collapsible-row');
352 378 }else{
353 379 $container.removeClass('cf7sg-collapsible');
354 380 $container.children('.cf7sg-collapsible-title').remove();
381 + $container.fireGridUpdate('remove','collapsible-row');
355 382 }
356 383 //toggle disable the sibling input
357 384 $target.parent().siblings('label.unique-mod').children('input').prop('disabled', function(i,v){return !v;});
358 385 }else if($target.is('input.table-row')){ //-------------checkbox table row
359 386 if($target.is(':checked')){
360 - var id = 'cf7-sg-table-'+(new Date).getTime();
387 + let id = 'cf7-sg-table-'+(new Date).getTime();
361 388 $target.closest('.row').addClass('cf7-sg-table');
362 - $target.closest('.container').addClass('cf7-sg-table').attr('id',id);
389 + $target.closest('.container').addClass('cf7-sg-table').attr('id',id).fireGridUpdate('add','table-row');
363 390 }else{
364 391 $target.closest('.row').removeClass('cf7-sg-table');
365 - $target.closest('.container').removeClass('cf7-sg-table').removeAttr('id');
392 + $target.closest('.container').removeClass('cf7-sg-table').removeAttr('id').removeAttr('data-button').fireGridUpdate('remove','table-row');
366 393 }
367 394 //toggle disable the sibling input
368 395 $target.parent().siblings('label.unique-mod').children('input').prop('disabled', function(i,v){return !v;});
369 396 }else if($target.is('input.tabs-row')){ //-------------checkbox tabbed row
370 - var $panel = $target.closest('.container');
397 + const $panel = $target.closest('.container');
371 398 if($target.is(':checked')){
372 - var id = 'cf7-sg-tab-'+(new Date).getTime();
399 + let id = 'cf7-sg-tab-'+(new Date).getTime();
373 400 $panel.addClass('cf7-sg-tabs-panel').attr('id',id);
374 401 $panel.before($('#grid-tabs').html());
375 402 $panel.closest('.columns').addClass('cf7-sg-tabs');
376 403 $('li a', $panel.siblings('ul.cf7-sg-tabs-list')).attr('href','#'+id);
404 + $panel.fireGridUpdate('add','tabbed-row');
377 405 }else{
378 406 $panel.removeClass('cf7-sg-tabs-panel');
379 407 $panel.closest('.columns').removeClass('cf7-sg-tabs');
380 408 $panel.siblings('ul.cf7-sg-tabs-list').remove();
409 + $panel.fireGridUpdate('remove','tabbed-row');
381 410 }
382 411 //toggle disable the sibling input
383 412 $target.parent().siblings('label.unique-mod').children('input').prop('disabled', function(i,v){return !v;});
384 413 }else if($target.is('input.footer-row')){ //-------------checkbox footer row
385 - var $table = $target.closest('.container').prev();
414 + const $table = $target.closest('.container').prev();
386 415 if($table.is('.container.cf7-sg-table')){
387 416 if($target.is(':checked')){
388 - $target.closest('.container').addClass('cf7-sg-table-footer');
417 + $target.closest('.container').addClass('cf7-sg-table-footer').fireGridUpdate('add','footer-row');
389 418 }else{
390 - $target.closest('.container').removeClass('cf7-sg-table-footer');
419 + $target.closest('.container').removeClass('cf7-sg-table-footer').fireGridUpdate('remove','footer-row');
391 420 }
392 421 //toggle disable the sibling input
393 422 $target.parent().siblings('label.unique-mod').children('input').prop('disabled', function(i,v){return !v;});
394 423 }
424 + }else if( $target.is('.make-grid.row-control') ){ /** @since 3.4.0--wrap row into column ->make grid*/
425 + //close the grid-control box
426 + $target.parent().hide();
427 + $target.parent().siblings('.dashicons-no-alt').hide();
428 + $target.parent().siblings('.dashicons-edit').show();
429 + //convert to grid if multiple columns
430 + $parentRow = $target.closest('.row');
431 + if($parentRow && $parentRow.children('.columns').length>1){
432 + //is row table/tab
433 + $parentContainer = $parentRow.closest('.container');
434 + const $content = $parentRow.children('.columns');
435 + $content.wrapAll('<div class="columns full"></div>');
436 + $parentColumn = $content.parent('.columns');
437 + $parentColumn.prepend( $( $('#grid-col').html() ) );
438 + //remove single cell UI content
439 + $parentColumn.children('.grid-column').children('textarea.grid-input').remove();
440 + $parentColumn.children('.grid-column').children('div.cf7-field-inner').remove();
441 + //finally insert a new row with the content moved to the new row.
442 + $parentColumn.insertNewRow($content.remove());
443 + }
395 444 }
396 445
397 446
398 447 /*
@@ -398,24 +447,13 @@
398 447 /*
399 448 Column controls, show/hide contols, add column, and refresh select dropdowns for colum size on addition
400 449 */
401 450
402 - var $parentColumn ;
403 451 if( $target.is('.columns')){
404 452 $parentColumn = $target;
405 453 }else{
406 454 $parentColumn = $target.closest('.columns');
407 455 }
408 - //let's close any column controls : taken care by closeAllControls
409 - // if(0===$target.closest('.grid-controls').length ){
410 - // $('.grid-column .grid-controls', $grid).hide();
411 - // $('.grid-column .column-control.dashicons-no-alt', $grid).hide();
412 - // $('.grid-column .column-control.dashicons-edit', $grid).show();
413 - // //close any ui fields if any
414 - // if(cf7grid.ui && !$target.is('.cf7-field-inner *')){
415 - // $('.grid-column .cf7-field-inner span.dashicons').trigger('click');
416 - // }
417 - // }
418 456 //verify which target was clicked
419 457 if( $target.is('.dashicons-edit.column-control') ){ //------------------show controls
420 458 //now show this control
421 459 $target.siblings('.grid-controls').show().filterColumnControls();
@@ -420,27 +458,58 @@
420 458 //now show this control
421 459 $target.siblings('.grid-controls').show().filterColumnControls();
422 460 $target.hide();
423 461 $target.siblings('.dashicons-no-alt').show();
424 - }else if( $target.is('.dashicons-controls-repeat.column-control') ) { //--------show hooks
425 - var $helper =$('<div class="helper-popup">').html( $('#grid-helper').html());
462 + }else if( $target.is('.php-icon.column-control') ) { //--------show hooks
463 + let $helper =$('<div class="helper-popup">').html( $('#grid-helper').html()),
464 + $copy = $('.copy-helper', $helper),
465 + field = $target.data('field'),
466 + tag = $target.data('tag'),
467 + search = $target.data('search'),
468 + $hooks = $(search, '#fieldhelperdiv').clone();
469 + $target.after($helper)
470 + $('.cf7sg-helper-list', $helper).append($hooks);
471 + $('a.helper', $helper).each(function(){
472 + new Clipboard($(this)[0], {
473 + text: function(trigger) {
474 + let $target = $(trigger);
475 + let text = $target.data('cf72post');
476 + //get post slug
477 + let key = $('#post_name').val();
478 + text = text.replace(/\{\$form_key\}/gi, key);
479 + text = text.replace(/\{\$form_key_slug\}/gi, key.replace(/\-/g,'_'));
480 + text = text.replace(/\{\$field_name\}/gi, field);
481 + text = text.replace(/\{\$field_name_slug\}/gi, field.replace(/\-/g,'_'));
482 + text = text.replace(/\{\$field_type\}/gi, tag);
483 + text = text.replace(/\[dqt\]/gi, '"');
484 + return text;
485 + }
486 + });
487 + $(this).append($copy.clone());
488 + });
489 + $helper.click('a.helper, .dashicons-no-alt', function(e){
490 + $(this).remove();
491 + });
492 + }else if( $target.is('.js-icon.column-control') ) { //--------show js hooks
493 + let $helper =$('<div class="helper-popup">').html( $('#grid-js-helper').html()),
494 + $copy = $('.copy-helper', $helper),
495 + field = $target.data('field'),
496 + tag = $target.data('tag'),
497 + search = $target.data('search'),
498 + $hooks = $(search, '#fieldhelperjs').clone();
426 499 $target.after($helper);
427 - var $copy = $('.copy-helper', $helper);
428 - var field = $target.data('field');
429 - var tag = $target.data('tag');
430 - var search = $target.data('search');
431 - var $hooks = $(search, '#fieldhelperdiv').clone();
432 500 $('.cf7sg-helper-list', $helper).append($hooks);
433 501 $('a.helper', $helper).each(function(){
434 502 new Clipboard($(this)[0], {
435 503 text: function(trigger) {
436 - var $target = $(trigger);
437 - var text = $target.data('cf72post');
504 + let $target = $(trigger);
505 + let text = $target.data('cf72post');
438 506 //get post slug
439 - var key = $('#post_name').val();
507 + let key = $('#post_name').val();
440 508 text = text.replace(/\{\$form_key\}/gi, key);
509 + text = text.replace(/\{\$form_key_slug\}/gi, key.replace(/\-/g,'_'));
441 510 text = text.replace(/\{\$field_name\}/gi, field);
442 - text = text.replace(/\{\$field_name_slug\}/gi, field.replace('-','_'));
511 + text = text.replace(/\{\$field_name_slug\}/gi, field.replace(/\-/g,'_'));
443 512 text = text.replace(/\{\$field_type\}/gi, tag);
444 513 text = text.replace(/\[dqt\]/gi, '"');
445 514 return text;
446 515 }
@@ -450,9 +519,9 @@
450 519 $helper.click('a.helper, .dashicons-no-alt', function(e){
451 520 $(this).remove();
452 521 });
453 522 }else if($target.is('.icon-code.column-control') ){
454 - var $focus = $target.closest('.columns');
523 + const $focus = $target.closest('.columns');
455 524 //toggle cf7sgfocus class on inner field to focus on.
456 525 if($focus.is('.cf7sgfocus')){
457 526 $focus.removeClass('cf7sgfocus');
458 527 }else{
@@ -460,14 +529,15 @@
460 529 $focus.addClass('cf7sgfocus');
461 530 }
462 531 //move to text editor.
463 532 $('#form-editor-tabs').tabs('option',{ active:1});
533 + $('body').addClass('disable-scroll');
464 534 }else if($target.is('.dashicons-trash.column-control') ){ //-------------------delete column
465 -
535 + $parentColumn.closest('.row').fireGridUpdate('remove','column');
466 536 $parentColumn.remove();
467 537 //refilter
468 538 //$target.siblings('.grid-controls').filterColumnControls();
469 - }else if( $target.is('.make-grid') ){ //--------------------add row/convert column to grid
539 + }else if( $target.is('.make-grid.column-control') ){ //--------------------add row/convert column to grid
470 540
471 541 //close the grid-control box
472 542 $target.parent().hide();
473 543 $target.parent().siblings('.dashicons-no-alt').hide();
@@ -472,12 +542,12 @@
472 542 $target.parent().hide();
473 543 $target.parent().siblings('.dashicons-no-alt').hide();
474 544 $target.parent().siblings('.dashicons-edit').show();
475 545 //convert to grid
476 - var $parentColumn = $target.closest('.columns');
546 + $parentColumn = $target.closest('.columns');
477 547 if($parentColumn.length > 0){
478 548 //column already has a row?
479 - var text = '';
549 + let text = '';
480 550 if(0 == $parentColumn.children('.container').length){
481 551 //keep the textarea and remove from the column
482 552 if(cf7grid.ui){
483 553 text = $('textarea.grid-input', $parentColumn).remove().text();
@@ -500,17 +570,13 @@
500 570 //replace container with form selector
501 571 $target.closest('.container').after($('#grid-cf7-forms').html());
502 572 $target.closest('.container').remove();
503 573 }else if( $target.is('.dashicons-plus.column-control') ){ //--------------------add column
504 - var $parentColumn = $target.closest('.columns');
505 - var $parentRow = $parentColumn.closest('.row');
506 - var classList, idx , columns, row;
507 - var newSize=0;
508 - var sizes = [];
509 - var $newColumn = $('<div class="columns"></div>');
510 - var createColumn = true;
574 + $parentColumn = $target.closest('.columns');
575 + $parentRow = $parentColumn.closest('.row');
576 + let classList, idx , columns, row, newSize=0, createColumn = true, total = 0;
577 + let sizes = [], $newColumn = $('<div class="columns"></div>');
511 578 //is the row filled up?
512 - var total = 0;
513 579 //first check if the current column fills the entire row
514 580 if( $parentColumn.is('.full') ){
515 581 total = 12;
516 582 columns = 1;
@@ -527,9 +593,9 @@
527 593 /*TODO: display an error message and return */
528 594 return false;
529 595 }
530 596 createColumn = false;
531 - var newClass = columnsizes[newSize];
597 + let newClass = columnsizes[newSize];
532 598 $parentRow.children('.columns').each(function(index){
533 599 //make sure the column is not size 1
534 600 if( sizes[index] > 0 ){
535 601 $(this).changeColumnSize(columnsizes[sizes[index]], newClass );
@@ -557,8 +623,35 @@
557 623 $('div.cf7-field-inner', $newColumn).hide();
558 624 }
559 625 $newColumn.changeColumnSize('',columnsizes[newSize]);
560 626 $parentColumn.after($newColumn);
627 + }else if( $target.is('.accordion-rows.column-control') ){ /** @since 3.4.0 enable accordion */
628 + if($target.is(':checked')){
629 + $parentColumn.addClass('cf7sg-accordion-rows').removeClass('cf7sg-slider-section').removeAttr("data-next data-prev data-submit");
630 + $target.parent('label').siblings('.grouping-option').children(':input').prop('checked', false);
631 + $target.fireGridUpdate('add','accordion-rows');
632 + //hide toggle checkbox.
633 + $('input[type="checkbox"]', $parentColumn.children('.cf7sg-collapsible').children('.cf7sg-collapsible-title') ).hide().next('span').hide();
634 + }else{
635 + $target.closest('.columns').removeClass('cf7sg-accordion-rows');
636 + $target.fireGridUpdate('remove','accordion-rows');
637 + //show toggle checkbox.
638 + $('input[type="checkbox"]', $parentColumn.children('.cf7sg-collapsible').children('.cf7sg-collapsible-title') ).show().next('span').show();
639 + }
640 + }else if( $target.is('.slider-rows.column-control') ) { /** @since 3.4.0 enable slider */
641 + if($target.is(':checked')){
642 + let attrs = { "data-next":"", "data-prev":"", "data-submit":""};
643 + $target.closest('.columns').addClass('cf7sg-slider-section').attr(attrs).removeClass('cf7sg-accordion-rows');
644 + $target.parent('label').siblings('.grouping-option').children(':input').prop('checked', false);
645 + $target.fireGridUpdate('add','slider-section');
646 + //hide toggle checkbox.
647 + $('input[type="checkbox"]', $parentColumn.children('.cf7sg-collapsible').children('.cf7sg-collapsible-title') ).hide().next('span').hide();
648 + }else{
649 + $target.closest('.columns').removeClass('cf7sg-slider-section').removeAttr("data-next data-prev data-submit");
650 + $target.fireGridUpdate('remove','slider-section');
651 + //show toggle checkbox.
652 + $('input[type="checkbox"]', $parentColumn.children('.cf7sg-collapsible').children('.cf7sg-collapsible-title') ).show().next('span').show();
653 + }
561 654 }
562 655 /*
563 656 Column UI fields
564 657 */
@@ -572,23 +665,26 @@
572 665 }else if('none'!==$('#wpcf7-form').css('display') && !$target.is('#wpcf7-form')){
573 666 changeTextarea();
574 667 }
575 668 }
576 - });
669 + });//end $grid.on('click').
577 670
578 - // capture tab and move to the next field
671 + // capture tab and move to the next field.
579 672 if(cf7grid.ui){
580 - $grid.keydown('div.cf7-field-inner', function(event){
581 - if(9 !== event.which ){//tab
582 - return;
583 - }
584 - $target = $(event.target);
673 + $grid.keydown('div.cf7-field-inner', function(e){
674 + if(9 !== (e.which || e.keyCode) ) return; //check for tab.
675 + let $target = $(e.target);
585 676 if($target.is('div.cf7-field-inner :input')){
586 677 $target.closeUIfield();
587 - var $next = $target.parent().next('div.cf7-field-inner');
588 - if($next.length>0){
678 + $target = $target.parent(); //switch to parent.
679 + let found = false, stopSearch = false, $next = $grid.find('div.cf7-field-inner').filter(function(i,el){
680 + if(stopSearch) return false;
681 + if(found) return (stopSearch = true) ;
682 + else if($(el).is($target) ) found = true;
683 + });
684 + if($next){
589 685 $next.showUIfield();
590 - event.preventDefault(); //stop tab focus on this element.
686 + e.preventDefault(); //stop tab focus on this element.
591 687 }
592 688 }
593 689 });
594 690
@@ -594,9 +690,9 @@
594 690
595 691 }
596 692 //general inputs into the textareas will trigger form change event
597 693 $grid.on('input selectionchange propertychange', 'textarea', function(event){
598 - var $target = $(event.target);
694 + const $target = $(event.target);
599 695 if($target.is('.cf7-field-type textarea')){
600 696 return false; //form change trigger will happen after this
601 697 }else if($target.is('textarea')){
602 698 $target.html($target.val()+'\n'); //ensure changes are capture in the codemirror editor
@@ -614,9 +710,9 @@
614 710 $grid.trigger('cf7grid-form-ready'); //codemirror initialisation
615 711 });
616 712 changeTextarea(true);
617 713 }else{
618 - var $txta = $('textarea#wpcf7-form');
714 + const $txta = $('textarea#wpcf7-form');
619 715 $txta.html($txta.val()+'\n');
620 716 $grid.trigger('cf7grid-form-ready'); //codemirror initialisation
621 717 }
622 718 });
@@ -626,11 +722,11 @@
626 722 $grid.on('build-grid', function(){
627 723 if( !buildGridForm() ){
628 724 $('#form-editor-tabs').tabs('option',{ active:1, disabled:true});
629 725 }else{
630 - var $focus = $('.cf7sgfocus', $grid);
726 + const $focus = $('.cf7sgfocus', $grid);
631 727 if($focus.length>0){
632 - var scrollPos = $focus.offset().top - $(window).height()/2 + $focus.height()/2;
728 + const scrollPos = $focus.offset().top - $(window).height()/2 + $focus.height()/2;
633 729 //console.log(scrollPos);
634 730 $(window).scrollTop(scrollPos);
635 731 $focus.removeClass('cf7sgfocus');
636 732 }
@@ -644,9 +740,9 @@
644 740 //placeholder: "ui-state-highlight",
645 741 handle:'.row-controls > .dashicons-move',
646 742 axis: 'y',
647 743 //containment:'parent',
648 - items: '> .container, > .cf7sg-external-form',
744 + items: '> .container, > .cf7sg-external-form', //.columns.cf7-sg-tabs > .row',
649 745 helper:'clone'
650 746 });
651 747 //grid is ready
652 748 $wpcf7Editor.trigger('grid-ready');
@@ -656,11 +752,11 @@
656 752 function randString(n){
657 753 if(!n){
658 754 n = 5;
659 755 }
660 - var text = '';
661 - var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
662 - for(var i=0; i < n; i++){
756 + let text = '';
757 + const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
758 + for(let i=0; i < n; i++){
663 759 text += possible.charAt(Math.floor(Math.random() * possible.length));
664 760 }
665 761 return text;
666 762 }
@@ -672,20 +768,20 @@
672 768 }
673 769 //close controls row/column
674 770 function closeAllControls(){
675 771 $('.grid-controls:visible', $grid).each(function(){
676 - var $this = $(this);
772 + const $this = $(this);
677 773 $this.hide();
678 774 $this.siblings('.dashicons-no-alt').hide();
679 775 $this.siblings('.dashicons-edit').show();
680 776 });
681 777 //close helper popups.
682 - $('.dashicons-controls-repeat.column-control+.helper-popup').remove();
778 + $('.column-control+.helper-popup').remove();
683 779 }
684 780 //trigger a change on the textarea#wpcf7-form field if its value has changed
685 781 function changeTextarea(finalise = false){
686 782 if(cf7grid.ui){
687 - var $lastTA = $('#wpcf7-form');
783 + const $lastTA = $('#wpcf7-form');
688 784 if($lastTA.length >0 && wpcf7Value !== $lastTA.val()){
689 785 wpcf7Value = '';
690 786 $lastTA.trigger('change');
691 787 }else if(finalise){
@@ -707,16 +803,14 @@
707 803 receive: function( event, ui ) {
708 804 //ui.item validate column size relative to new row columns.
709 805 //ui.sender original row. cnacel if column does not fit in new row.
710 806 //$targetRow has more than 12 columns then cancel.
711 - var $targetRow = $(event.target);//receiving row
712 - var row = $targetRow.getRowSize();
713 - //var total = row.length;
714 - //var sizes = row.cols;
715 - //var columns = sizes.length;
807 + const $targetRow = $(event.target);//receiving row
808 + let row = $targetRow.getRowSize();
809 +
716 810 if( row.length > 12){
717 811 ui.sender.sortable('cancel');
718 - var $warning = $('<span class="cf7sg-warning">Not enough space in this row to add column</span>');
812 + const $warning = $('<span class="cf7sg-warning">Not enough space in this row to add column</span>');
719 813 $targetRow.after($warning);
720 814 $warning.delay(2000).fadeOut('slow', function(){
721 815 $(this).remove();
722 816 });
@@ -721,9 +815,9 @@
721 815 $(this).remove();
722 816 });
723 817 }else{
724 818 //make sure the row controls is at the end.
725 - var control = $targetRow.children('.row-controls').remove();
819 + const control = $targetRow.children('.row-controls').remove();
726 820 $targetRow.append(control);
727 821 }
728 822 }
729 823 });
@@ -729,26 +823,30 @@
729 823 });
730 824 }
731 825 /* some function definitions...*/
732 826 $.fn.closeUIfield = function(){
733 - var $this = $(this);
734 - if(!$this.is('.cf7-field-inner :input:visible')){
735 - return $this;
736 - }
737 - if($this.parent().is('.cf7-field-type')) changeTextarea();
738 - $this.hide().attr('id', '');
739 - $this.siblings('.dashicons-no-alt').hide();
740 - $this.siblings('.content').show();
741 - return $this;
827 + let obj = this;
828 + if(!Array.isArray(this)) obj=[this];
829 + $.each(obj,function(idx, item){
830 + const $this = $(item);
831 + if(!$this.is('.cf7-field-inner :input:visible')){
832 + return $this;
833 + }
834 + if($this.parent().is('.cf7-field-type')) changeTextarea();
835 + $this.hide().attr('id', '');
836 + $this.siblings('.dashicons-no-alt').hide();
837 + $this.siblings('.content').show();
838 + });
839 + return true;
742 840 }
743 841 $.fn.showUIfield = function(){
744 - var $this = $(this);
842 + const $this = $(this);
745 843 if(!$this.is('.cf7-field-inner')){
746 844 return $this;
747 845 }
748 846 $this.find('p.content').hide();
749 847 $this.find('span.dashicons').show();
750 - var $input = $(':input', $this).show();
848 + const $input = $(':input', $this).show();
751 849 $input.focus();
752 850 if($input.is('textarea')){
753 851 $('textarea#wpcf7-form').attr('id','');
754 852 $input.attr('id', 'wpcf7-form');
@@ -758,9 +856,9 @@
758 856 }
759 857 return $this;
760 858 }
761 859 $.fn.html2gui = function(html){
762 - var $this = $(this);
860 + const $this = $(this);
763 861 if(typeof html === 'undefined') html ='';
764 862 if(html.length === 0){
765 863 //get the fields from the textarea
766 864 html = $('textarea.grid-input', $this).text();
@@ -768,25 +866,25 @@
768 866 $('textarea.grid-input', $this).hide();
769 867 return $this;
770 868 }
771 869 }
772 - var singleField = true;
773 - var search = $('<div>').append(html);
870 + let singleField = true;
871 + let search = $('<div>').append(html);
774 872
775 873 if(seekTemplate && 1==search.children(cssTemplate).length){
776 - var lines = html.split(/\r\n|\r|\n/g);
874 + const lines = html.split(/\r\n|\r|\n/g);
777 875 search = '';
778 - for(var i=0; i<lines.length; i++){
876 + for(let i=0; i<lines.length; i++){
779 877 search += lines[i].trim();
780 878 }
781 - var match = templateRegex.exec(search);
879 + const match = templateRegex.exec(search);
782 880 if(null !== match){
783 881 //populate the fields
784 - var $field = $('div.cf7-field-label', $this);
882 + let $field = $('div.cf7-field-label', $this);
785 883 $('input', $field).val(match[1]);
786 884 $('p.content', $field).html(match[1]);
787 885 $field = $('div.cf7-field-type', $this);
788 - var tag = $('textarea', $field).val(match[5]).scanCF7Tag();
886 + const tag = $('textarea', $field).val(match[5]).scanCF7Tag();
789 887 $('p.content', $field).html(tag);
790 888 $field = $('div.cf7-field-tip', $this);
791 889 $('input', $field).val(match[6]);
792 890 $('p.content', $field).html(match[6]);
@@ -802,14 +900,15 @@
802 900 }
803 901 }
804 902
805 903 $.fn.scanCF7Tag = function(){
806 - var $this = $(this);
904 + let $this = $(this);
807 905 if(!$this.is('textarea')){
808 906 return '';
809 907 }
810 - var $parent = $this.parent(); //.cf7-field-type.
811 - var $helper = $parent.siblings('.dashicons-controls-repeat');
908 + let $parent = $this.parent(), //.cf7-field-type.
909 + $helper = $parent.siblings('.php-icon'),
910 + $jshelper = $parent.siblings('.js-icon');
812 911 $helper.each(function(index){
813 912 if(index>0){
814 913 $(this).remove();
815 914 return;
@@ -816,11 +915,21 @@
816 915 }
817 916 $(this).removeAttr('data-field').removeAttr('data-tag').removeAttr('data-search');
818 917 });
819 918 //reset helper.
820 - $helper = $parent.siblings('.dashicons-controls-repeat');
919 + $helper = $parent.siblings('.php-icon');
920 + //handle jshleper
921 + $jshelper.each(function(index){
922 + if(index>0){
923 + $(this).remove();
924 + return;
925 + }
926 + $(this).removeAttr('data-field').removeAttr('data-tag').removeAttr('data-search');
927 + });
928 + //reset jshelper.
929 + $jshelper = $parent.siblings('.js-icon');
821 930
822 - var cf7TagRegexp = /\[(.[^\s]*)\s*(.[^\s\]]*)[\s\[]*(.[^\[]*\"source:([^\s]*)\"[\s^\[]*|[.^\[]*(?!\"source:)[^\[]*)\]/img,
931 + let cf7TagRegexp = /\[(.[^\s]*)\s*(.[^\s\]]*)[\s\[]*(.[^\[]*\"source:([^\s]*)\"[\s^\[]*|[.^\[]*(?!\"source:)[^\[]*)\]/img,
823 932 search = $this.val(),
824 933 match = cf7TagRegexp.exec(search),
825 934 label='',
826 935 isRequired = false,
@@ -825,14 +934,15 @@
825 934 label='',
826 935 isRequired = false,
827 936 type = [],
828 937 fields = [],
829 - hooks = [],
938 + hooks = [],jshooks=[],
830 939 tag='',
831 940 isSubmit = false, hasHidden = false,
832 941 count =0, counth = 0,
833 942 field = '',
834 - stopSearch = false;
943 + stopSearch = false, isField =true,
944 + classes = $('#grid-col div.cf7-field-type').attr('class');
835 945
836 946 while (match != null && !stopSearch) {
837 947 count++;
838 948 label+='['+match[1]+' '+match[2]+']';
@@ -837,10 +947,11 @@
837 947 count++;
838 948 label+='['+match[1]+' '+match[2]+']';
839 949 tag = match[1].replace('*','');
840 950 field = match[2];
841 - var helpers = ['cf7sg-tag-all'];
951 + let helpers = ['cf7sg-tag-all'], jsHelpers = ['cf7sg-tag-all'];
842 952 helpers[helpers.length] = 'cf7sg-tag-'+tag;
953 + jsHelpers[jsHelpers.length] = 'cf7sg-tag-'+tag;
843 954 switch(tag){
844 955 case 'submit':
845 956 case 'save':
846 957 tag +='-button';
@@ -847,9 +958,9 @@
847 958 isSubmit = true;
848 959 break;
849 960 case 'textarea':
850 961 if( match[0].search(/\s[0-9]{0,3}x[0-9]{1,3}\s?/ig) <0){
851 - var cf7sc = match[0].replace(']',' x5]');
962 + let cf7sc = match[0].replace(']',' x5]');
852 963 cf7sc = search.replace(match[0], cf7sc);
853 964 $this.val(cf7sc);
854 965 }
855 966 break;
@@ -861,20 +972,28 @@
861 972 label='[recaptcha]';
862 973 stopSearch = true;
863 974 break;
864 975 case 'dynamic_select':
865 - var source ='';
866 - switch(match.length){
867 - case 5: //match[4] exists.
868 - if('undefined' !== typeof match[4]){
869 - source = match[4].split(':');
870 - source = source[0];
871 - helpers[helpers.length] = 'cf7sg-tag-dynamic_select-'+source;
976 + let source ='';
977 + switch(true){
978 + case ( match.length > 4 && 'undefined' !== typeof match[4] ) : //match[4] exists.
979 + source = match[4].split(':');
980 + source = source[0];
981 + helpers[helpers.length] = 'cf7sg-tag-dynamic_select-'+source;
982 + case match.length > 3: //lets deal with match[3]
983 + if(0=== source.length){
984 + source="filter";
985 + switch(true){
986 + case match[3].indexOf("source:post")>0:
987 + source="post";
988 + break;
989 + case match[3].indexOf("slug:")>0:
990 + source="taxonomy";
991 + break;
992 + }
872 993 }
873 - case 4: //lets deal with match[3]
874 - if(0=== source.length && match[3].indexOf('slug:'>-1)){
875 - source = 'taxonomy';
876 - }
994 + helpers[helpers.length] = 'cf7sg-tag-dynamic_select-'+source;
995 +
877 996 if(match[3].indexOf('class:tags')>-1){
878 997 helpers[helpers.length] = 'cf7sg-tag-dynamic_select-tags';
879 998 if(source.length>0){
880 999 helpers[helpers.length] = 'cf7sg-tag-dynamic_select-'+source+'-tags';
@@ -886,23 +1005,41 @@
886 1005 case 'hidden': /** @since 3.2.1 fix hidden field class */
887 1006 tag+='-input';
888 1007 counth++;
889 1008 break;
1009 + case 'group': /** @since 4.4.3 fix conditional groups within */
1010 + isField = false;
1011 + classes += " conditional-group";
1012 + break;
1013 + case '/grou':
1014 + isField = false;
1015 + stopSearch = true;
1016 + break;
1017 + default:
1018 + break;
890 1019 }
891 - type[type.length] = tag;
892 - fields[fields.length] = field;
893 - hooks[hooks.length] = helpers;
1020 + /** @since 3.3.0 add extension classes */
1021 + if(undefined !== cf7sgCustomHelperModule[tag]){
1022 + let ch = cf7sgCustomHelperModule[tag](search);
1023 + if(Array.isArray(ch.php) && ch.php.length>0) helpers = helpers.concat(ch.php);
1024 + if(Array.isArray(ch.js) && ch.js.length>0) jsHelpers = jsHelpers.concat(ch.js);
1025 + }
1026 + if(isField){
1027 + type[type.length] = tag;
1028 + fields[fields.length] = field;
1029 + hooks[hooks.length] = helpers;
1030 + jshooks[jshooks.length] = jsHelpers;
1031 + }
894 1032 if('*' === match[1][match[1].length -1]){
895 1033 isRequired = true;
896 1034 }
897 1035 if(!stopSearch) match = cf7TagRegexp.exec(search); //get the next match.
898 1036 }
899 - var classes = $('#grid-col div.cf7-field-type').attr('class');
900 1037 classes += " "+ type.join(' ');
901 1038 field = fields.join(' ');
902 1039 // $parent.removeClass('required');
903 1040 if(isRequired) classes += ' required';//$parent.addClass('required').
904 - var $parentColumn = $parent.closest('.columns');
1041 + const $parentColumn = $parent.closest('.columns');
905 1042 if($parentColumn.is('[class*="cf7-tags-"]')){
906 1043 $parentColumn.removeClass(function (index, className) {
907 1044 return (className.match (/(^|\s)cf7-tags-\S+/g) || []).join(' ');
908 1045 });
@@ -915,20 +1052,19 @@
915 1052 /**@since 2.0.0
916 1053 * setup fields for tag specific filters/actions.
917 1054 */
918 1055 //for each tag get corresponding set of filters.
919 - var helperUsed = false;
920 - for (var i = 0, len = type.length; i < len; i++) {
921 - var search = '';
922 - var helpers = hooks[i];
923 - for (var j=0, jlen = helpers.length; j<jlen; j++){
924 - search += 'li.'+helpers[j]+',';
1056 + let helperUsed = false, jsHelperUsed=false,len = type.length, jlen=0;
1057 + search = '';
1058 + for (let i = 0; i < len; i++) {
1059 + for (let j=0, jlen = hooks[i].length; j<jlen; j++){
1060 + search += 'li.'+hooks[i][j]+',';
925 1061 }
926 1062 search = search.slice(0,-1); //remove last ','
927 1063 if($( search ,$('#fieldhelperdiv')).length>0){
928 - //this tag has soem filters.
1064 + //this tag has some filters.
929 1065 if(helperUsed){
930 - var $clone = $helper.clone();
1066 + const $clone = $helper.clone();
931 1067 $helper.after($clone);
932 1068 $helper = $clone;
933 1069 }
934 1070 helperUsed = true;
@@ -936,8 +1072,27 @@
936 1072 $helper.attr('data-tag', type[i]);
937 1073 $helper.attr('data-search', search);
938 1074 $helper.show();
939 1075 }
1076 + //js helpers.
1077 + search='', jlen = jshooks[i].length;
1078 + for (let j=0; j<jlen; j++){
1079 + search += 'li.'+jshooks[i][j]+',';
1080 + }
1081 + search = search.slice(0,-1); //remove last ','
1082 + if($( search ,$('#fieldhelperjs')).length>0){
1083 + //this tag has some filters.
1084 + if(jsHelperUsed){
1085 + const $clone = $jshelper.clone();
1086 + $jshelper.after($clone);
1087 + $jshelper = $clone;
1088 + }
1089 + jsHelperUsed = true;
1090 + $jshelper.attr('data-field', fields[i]);
1091 + $jshelper.attr('data-tag', type[i]);
1092 + $jshelper.attr('data-search', search);
1093 + $jshelper.show();
1094 + }
940 1095 }
941 1096 if(isSubmit){
942 1097 $parent.parent().addClass('submit-field');
943 1098 }
@@ -944,18 +1099,18 @@
944 1099
945 1100 return label;
946 1101 }
947 1102 $.fn.updateGridForm = function(){
948 - var $this = $(this);
1103 + const $this = $(this);
949 1104 if(!$this.is('textarea.grid-input')){
950 1105 return $this;
951 1106 }
952 1107 //label
953 - var $label = $this.siblings('div.cf7-field-label').find(':input');
954 - var label = $label.val();
1108 + const $label = $this.siblings('div.cf7-field-label').find(':input');
1109 + let label = $label.val();
955 1110 //field
956 - var field = $this.siblings('div.cf7-field-type').find('textarea').val();
957 - var idx = 0;
1111 + const field = $this.siblings('div.cf7-field-type').find('textarea.field-entry').val();
1112 + let idx = 0;
958 1113 if(cf7grid.requiredHTML.length>0) idx=label.indexOf(cf7grid.requiredHTML)
959 1114 if($this.siblings('div.cf7-field-type').is('.required')){
960 1115 /** @since 2.10.4 fix for custom manual labels, allow replacement with empty span*/
961 1116 if(idx<0) idx = label.search(/<span>[\w\W]*<\/span>/g);
@@ -971,10 +1126,10 @@
971 1126 $label.siblings('p.content').html(label);
972 1127 }
973 1128 }
974 1129 //tip
975 - var tip = $this.siblings('div.cf7-field-tip').find(':input').val();
976 - var $cell = $('<div>').append( cf7grid.preHTML + field + cf7grid.postHTML );
1130 + const tip = $this.siblings('div.cf7-field-tip').find(':input').val(),
1131 + $cell = $('<div>').append( cf7grid.preHTML + field + cf7grid.postHTML );
977 1132 $('label', $cell).html(label);
978 1133 $('.info-tip', $cell).html(tip);
979 1134 //update grid input and trigger change to udpate form
980 1135 if(cf7grid.ui) $this.html($cell.html()+'\n').trigger('change');
@@ -982,14 +1137,14 @@
982 1137 return $this;
983 1138 };
984 1139
985 1140 $.fn.toggleSiblingUIFields = function(){
986 - var $this = $(this);
1141 + const $this = $(this);
987 1142 if(!$this.is('div.cf7-field-inner')){
988 1143 return $this;
989 1144 }
990 1145 $this.siblings('div.cf7-field-inner').each(function(){
991 - var $this = $(this);
1146 + const $this = $(this);
992 1147 $('p.content', $this).show();
993 1148 $(':input', $this).hide().attr('id','');
994 1149 $('span.dashicons', $this).hide();
995 1150 });
@@ -994,11 +1149,10 @@
994 1149 $('span.dashicons', $this).hide();
995 1150 });
996 1151 }
997 1152 $.fn.getRowSize = function(){
998 - var size, off, idx, foundSize, classList;
999 - var total = 0;
1000 - var sizes = [0];
1153 + let size, off, idx, foundSize, classList,total = 0;
1154 + const sizes = [0];
1001 1155 $(this).children('.columns').each(function(index){
1002 1156 classList = $(this).attr('class').split(/\s+/);
1003 1157 foundSize = false;
1004 1158 for(idx=0;idx<classList.length; idx++){
@@ -1018,21 +1172,18 @@
1018 1172 });
1019 1173 return {'length':total, 'cols':sizes};
1020 1174 }
1021 1175 $.fn.getColumnTotalSize = function(){
1022 - var $this = $(this);
1176 + const $this = $(this);
1023 1177 if(! $this.is('.columns')){
1024 1178 return 0;
1025 1179 }
1026 - var off, foundSize, size = 0;
1027 - var total = 0;
1028 - var classList = $this.attr('class').split(/\s+/);
1029 - var $sizes = $this.find('.grid-column select.column-size');
1030 - var $offsets = $this.find('.grid-column select.column-offset');
1180 + let off, foundSize, size = 0,total = 0, classList = $this.attr('class').split(/\s+/);
1181 + const $sizes = $this.find('.grid-column select.column-size'), $offsets = $this.find('.grid-column select.column-offset');
1031 1182 $offsets.val('');
1032 1183 $sizes.val('one');
1033 1184 foundSize = false;
1034 - for(var idx=0;idx<classList.length; idx++){
1185 + for(let idx=0;idx<classList.length; idx++){
1035 1186 if(!foundSize){
1036 1187 size = $.inArray(classList[idx], columnsizes);
1037 1188 if(size > -1){
1038 1189 foundSize = true;
@@ -1054,34 +1205,34 @@
1054 1205 return {'length':total, 'size':size};
1055 1206 }
1056 1207 //add new rows
1057 1208 $.fn.insertNewRow = function(areaCode){
1058 - var $this = $(this);
1209 + const $this = $(this);
1059 1210 if(typeof areaCode === 'undefined') areaCode ='';
1060 - var append=true;
1211 + const $newRow = $( $('#grid-row').html() );
1212 + //append the column controls and textarea
1213 + $('.columns', $newRow).append( $($('#grid-col').html()) );
1214 +
1061 1215 switch(true){
1062 - case ( $this.is('.columns') || $this.is($grid)):
1063 - case $this.is('.container.cf7-sg-tabs-panel'): /* fixes rows added in panels*/
1064 - append=true;
1216 + case $this.is('.columns'):
1217 + case $this.is($grid):
1218 + case $this.is('.row'):
1219 + $this.append($newRow);
1065 1220 break;
1066 - case ($this.is('.container') || $this.is('.cf7sg-external-form') ):
1067 - append=false;
1221 + // $this.prepend($newRow);
1222 + // break;
1223 + case $this.is('.container'):
1224 + case $this.is('.cf7sg-external-form'):
1225 + $this.after($newRow);
1068 1226 break;
1069 1227 default: //unknown element, maybe an error.
1070 1228 return $this;
1071 1229 }
1072 1230
1073 - var $newRow = $( $('#grid-row').html() );
1074 - //append the column controls and textarea
1075 - $('.columns', $newRow).append( $($('#grid-col').html()) );
1076 - //append the new row to the column or container
1077 - if(append) $this.append($newRow);
1078 - else $this.after($newRow);
1079 1231 //is areaCode text or jQuery object?
1080 1232 if(areaCode instanceof jQuery){
1081 - $('.cf7-field-inner', $newRow).remove();
1082 - $('textarea.grid-input',$newRow).remove();
1083 - $('.columns', $newRow).append(areaCode);
1233 + $('.columns', $newRow).remove();
1234 + $('.row', $newRow).prepend(areaCode);
1084 1235 }else{
1085 1236 //add the code to the textarea
1086 1237 if(cf7grid.ui){
1087 1238 $('textarea.grid-input',$newRow).html(areaCode).hide();//.trigger('change');
@@ -1092,13 +1243,14 @@
1092 1243 }
1093 1244 }
1094 1245 //make new row's columns sortable.
1095 1246 sortableRows($newRow);
1247 + $newRow.fireGridUpdate('add','row');
1096 1248 return $this;
1097 1249 }
1098 1250 //refresh controls select
1099 1251 $.fn.changeColumnSize = function(oldSize, newSize){
1100 - var $this = $(this);
1252 + const $this = $(this);
1101 1253 if(oldSize.length > 0) $this.removeClass(oldSize);
1102 1254 $this.addClass(newSize);
1103 1255 $('.column-size option[value="'+newSize+'"]', $this ).prop('selected', true);
1104 1256 }
@@ -1103,9 +1255,9 @@
1103 1255 $('.column-size option[value="'+newSize+'"]', $this ).prop('selected', true);
1104 1256 }
1105 1257 //$target.closest('.grid-controls').filterColumnControls();
1106 1258 $.fn.filterColumnControls = function(){
1107 - var $this = $(this);
1259 + const $this = $(this);
1108 1260 if(!$this.is('.grid-controls')){
1109 1261 return $this;
1110 1262 }
1111 1263 //enable all options
@@ -1110,13 +1262,11 @@
1110 1262 }
1111 1263 //enable all options
1112 1264 $('.column-size option', $this ).prop('disabled', false);
1113 1265 $('.column-offset option', $this ).prop('disabled', false);
1114 - var $parentRow = $this.closest('.row');
1115 - var $parentColumn = $this.closest('.columns');
1116 - var row = $parentRow.getRowSize();
1117 - var col = $parentColumn.getColumnTotalSize();
1118 - var idx, start, free = 0;
1266 + const $parentRow = $this.closest('.row'), $parentColumn = $this.closest('.columns');
1267 + const row = $parentRow.getRowSize(), col = $parentColumn.getColumnTotalSize();
1268 + let idx, start, free = 0;
1119 1269 if(row.length < 12) free = (12 - row.length);
1120 1270 for(idx = start = col.size+1; idx < columnsizes.length; idx++){
1121 1271 if( idx > (free + start - 1) ){
1122 1272 $('.column-size option[value="'+columnsizes[idx]+'"]', $this ).prop('disabled', true);
@@ -1128,6 +1278,20 @@
1128 1278 }
1129 1279 }
1130 1280 return $this;
1131 1281 }
1282 + /** @since 3.4.0 fire grid ui update events.*/
1283 + $.fn.fireGridUpdate = function(action, element){
1284 + let e={
1285 + bubbles: true,
1286 + cancelable: true,
1287 + };
1288 + e[action]=element;
1289 + $(this).trigger('cf7sg-update',e);
1290 + }
1132 1291
1133 1292 })( jQuery );
1293 +
1294 +/** @since 3.3.0 custom helpers */
1295 +var cf7sgCustomHelperModule = (function (cch) {
1296 + return cch;
1297 +}(cf7sgCustomHelperModule || {}));