PluginProbe
Smart Grid-Layout Design for Contact Form 7 / 3.3.2
Smart Grid-Layout Design for Contact Form 7 v3.3.2
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
cf7-grid-layout / admin / js / cf7-grid-codemirror.js

cf7-grid-codemirror.js in Smart Grid-Layout Design for Contact Form 7 3.3.2, at admin/js/cf7-grid-codemirror.js

410 lines 16.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 Javascript to handle Codemirror editor
3 Event 'cf7sg-form-change' fired on #contact-form-editor element when codemirror changes occur
4 @since 3.1.2 introduce instaiated cm editor as attribute in anonymous function.
5 */
6 (function( $, cme ) {
7
8 $(document).ready( function(){
9 var $codemirror = $('#cf7-codemirror');
10 var $wpcf7Editor = $('textarea#wpcf7-form-hidden');
11 var codemirrorUpdated = false;
12 var $grid = $('#grid-form');
13 var gridTab = '#cf7-editor-grid'; //default at load time.
14 //set codemirror editor value;
15 cme.setValue($wpcf7Editor.text());
16
17 $wpcf7Editor.on('grid-ready', function(){ //------ setup the codemirror editor
18 //codemirror editor
19 CodeMirror.defineMode("shortcode", function(config, parserConfig) {
20 var cf7Overlay = {
21 token: function(stream, state) {
22 var ch;
23 if (stream.match(/^\[([a-zA-Z0-9_]+)\*?\s?/)) {
24 while ((ch = stream.next()) != null)
25 if (ch == "]" ) {
26 //stream.eat("]");
27 return "shortcode";
28 }
29 }
30 while (stream.next() != null && !stream.match(/^\[([a-zA-Z0-9_]+)\*?\s?/, false)) {}
31 return null;
32 }
33 };
34 return CodeMirror.overlayMode(CodeMirror.getMode(config, parserConfig.backdrop || "htmlmixed"), cf7Overlay);
35 });
36 // var cmConfig =
37 if(cf7sgeditor.mode.length>0) cme.setOption('mode',cf7sgeditor.mode);
38 if(cf7sgeditor.theme.length>0) cme.setOption('theme',cf7sgeditor.theme);
39 // cmEditor = CodeMirror( $codemirror.get(0), cmConfig);
40
41 /* TODO: enable shortcode edit at a future date
42 $('.cm-shortcode',$codemirror).each(function(){
43 $(this).append('<span class="dashicons dashicons-edit"></span>');
44 });
45 $('.dashicons-edit', $codemirror).on('click', function(){
46 alert('shortcode '+ $(this).parent().text());
47 });
48 */
49 $.fn.beautify = function(cursor){
50 cme.setSelection({
51 'line':cme.firstLine(),
52 'ch':0,
53 'sticky':null
54 },{
55 'line':cme.lastLine(),
56 'ch':0,
57 'sticky':null
58 },
59 {scroll: false});
60 cme.indentSelection("smart");
61 cme.setCursor(cme.firstLine(),0);
62 if('undefined' != typeof cursor && cursor.find(false)){
63 var from = cursor.from();
64 var to = cursor.to();
65 cme.setSelection(CodeMirror.Pos(from.line, 0), to);
66 cme.scrollIntoView({from: from, to: CodeMirror.Pos(to.line + 10, 0)});
67 }
68 }
69 $codemirror.beautify();
70
71 //var cur = cme.getCursor();
72 //cme.setCursor(99, cur.ch);
73
74 cme.on('changes', function(){
75 codemirrorUpdated = true;
76 var disabled = $('#form-editor-tabs').tabs('option','disabled');
77
78 if(true===disabled){
79 var changes = $('<div>').append(cme.getValue());
80 if(0===changes.children().length || changes.children('.container').length>0){
81 $('#form-editor-tabs').tabs('option',{disabled:false});
82 /**
83 * @since 1.2.3 disable cf7sg styling/js for non-cf7sg forms.
84 */
85 $('#is-cf7sg-form').val('true');
86 }
87 }
88
89 $('#contact-form-editor').trigger('cf7sg-form-change');
90 });
91
92 //create tabs
93 $('#form-editor-tabs').tabs({
94 beforeActivate: function (event, ui){
95 //update the codemirror panel
96 if('#cf7-codemirror' == ui.newPanel.selector){
97 //finalise any changes in the grid form editor
98 $grid.on('cf7grid-form-ready', function(){
99 var code = $grid.CF7FormHTML();
100 if($grid.children('.container').length > 0){ //beautify.
101 code = html_beautify(code ,
102 {
103 'indent_size': 2,
104 'wrap_line_length': 0
105 });
106 }
107 cme.setValue(code);
108 //reset the codemirror change flag
109 codemirrorUpdated = false;
110 //remove id from textarea
111 $('textarea#wpcf7-form').attr('id', '');
112 //change the wpcf7 textarea
113 $('textarea.codemirror-cf7-update', $codemirror).attr('id', 'wpcf7-form');
114 //setup the form code in the hidden textarea
115 $wpcf7Editor.html(code);
116 });
117 /** @since 2.8.3 clear the codemirror textarea##wpcf7-form */
118 $('textarea.codemirror-cf7-update', $codemirror).val('');
119 $grid.trigger('cf7grid-form-finalise');
120 }else{
121 //remove id from textarea
122 $('textarea#wpcf7-form').attr('id', '');
123 }
124 },
125 activate: function( event, ui ) {
126 gridTab = ui.newPanel.selector;
127 if('#cf7-editor-grid' == ui.newPanel.selector){
128 if(codemirrorUpdated){
129 //update the hidden textarea
130 $wpcf7Editor.text(cme.getValue());
131 //trigger rebuild grid event
132 $grid.trigger('build-grid');
133 }else{ //try to set the focus on the 'cf7sgfocus element'
134 var $focus = $('.cf7sgfocus', $grid);
135 if($focus.length>0){
136 var scrollPos = $focus.offset().top - $(window).height()/2 + $focus.height()/2;
137 //console.log(scrollPos);
138 $(window).scrollTop(scrollPos);
139 $focus.removeClass('cf7sgfocus');
140 }
141 }
142 }else if('#cf7-codemirror' == ui.newPanel.selector){
143 var cursor = cme.getSearchCursor('cf7sgfocus', CodeMirror.Pos(cme.firstLine(), 0), {caseFold: true, multiline: true});
144
145 $codemirror.beautify(cursor);
146
147 if($grid.children('.container').length>0){
148 var scrollPos = $('#form-panel').offset().top;
149 $(window).scrollTop(scrollPos);
150 }
151 }
152 }
153 });
154 /*@since 1.1.1 disable grid editor for existing cf7 forms*/
155 if(0==$grid.children('.container').length){
156 $('#form-editor-tabs').tabs('option',{ active:1, disabled:true});
157 /**
158 * @since 1.2.3 disable cf7sg styling/js for non-cf7sg forms.
159 */
160 $('#is-cf7sg-form').val('false');
161 }
162
163 //update the codemirror when tags are inserted
164 $('form.tag-generator-panel .button.insert-tag').on('click', function(){
165 var $textarea = $('textarea#wpcf7-form');
166 if($textarea.is('.codemirror-cf7-update')){
167 var tag = $textarea.delay(100).val();
168 cme.replaceSelection(tag);
169 //update codemirror.
170 $textarea.val(''); //clear.
171 }
172 });
173 }); //-----------end codemirror editor setup
174
175 $('form#post').submit(function(event) {
176 var $this = $(this);
177 $( window ).off( 'beforeunload' ); //remove event to stop cf7 script from warning on save
178 event.preventDefault(); //this will prevent the default submit
179 var $embdedForms = '';
180 var $formNoEmbeds = '';
181 var codeMirror ='';
182 if('#cf7-editor-grid' == gridTab){ //set up the code in the cf7 textarea
183 var $txta = $('textarea#wpcf7-form');
184 $txta.html($txta.val()+'\n');
185 codeMirror = html_beautify(
186 $grid.CF7FormHTML(),
187 {
188 'indent_size': 2,
189 'wrap_line_length': 0
190 }
191 );
192 $('textarea#wpcf7-form-hidden').html(codeMirror);
193 $formNoEmbeds = $('<div>').append(codeMirror);
194 }else{//we are in text mode.
195 codeMirror = cme.getValue();
196 $('textarea#wpcf7-form-hidden').html(codeMirror).val(codeMirror);
197 $formNoEmbeds = $('<div>').append(codeMirror);
198 }
199 //since 1.8 remove cf7sgfocus class if present.
200 $('.cf7sgfocus', $formNoEmbeds).removeClass('cf7sgfocus');
201 $embdedForms = $formNoEmbeds.find('.cf7sg-external-form').remove();
202 //setup sub-forms hidden field.
203 var embeds = [];
204 var hasTables = false, hasTabs = false, hasToggles=false;
205 if($embdedForms.length>0){
206 $embdedForms.each(function(){
207 embeds[embeds.length] = $(this).data('form');
208 });
209 }
210 $('#cf7sg-embeded-forms').val(JSON.stringify(embeds));
211 var cf7TagRegexp = /\[(.[^\s]*)\s*(.[^\s]*)(|\s*(.[^\[]*))\]/img;
212 /** @since 3.0.0 determine scripts required */
213 var scriptClass ="";
214 if(codeMirror.indexOf("class:sgv-")>0) scriptClass += "has-validation,";
215 if(codeMirror.indexOf("class:select2")>0) scriptClass += "has-select2,";
216 if(codeMirror.indexOf("class:nice-select")>0) scriptClass += "has-nice-select,";
217 if($('.cf7sg-collapsible', $formNoEmbeds).length>0) scriptClass += "has-accordion,";
218 if(codeMirror.indexOf("[benchmark")>0) scriptClass += "has-benchmark,";
219 if(codeMirror.indexOf("[date")>0 || 0<codeMirror.search(/\[text([^\]]+?)class:datepicker/ig)) scriptClass += "has-date,";
220
221 //scan and submit tabs & tables fields.
222 var tableFields = [];
223 $('.row.cf7-sg-table', $formNoEmbeds).each(function(){
224 /**@since 2.4.2 track each tables with unique ids and their fields*/
225 var unique = $(this).closest('.container.cf7-sg-table').attr('id');
226 var fields = {};
227 fields[unique]=[];
228 var search = $(this).html();
229 var match = cf7TagRegexp.exec(search);
230 //console.log('search:'+search);
231 while (match != null) {
232 //ttFields[ match[2] ] = match[1];
233 fields[unique][fields[unique].length] = match[2];
234 //console.log('match'+match[2]);
235 match = cf7TagRegexp.exec(search); //get the next match.
236 }
237 tableFields[tableFields.length] = fields;
238 hasTables = true;
239 });
240 //var cf7TagRegexp = /\[(.[^\s]*)\s*(.[^\s]*)\s*(.[^\[]*)\]/img;
241 var tabFields = [];
242 $('.container.cf7-sg-tabs-panel', $formNoEmbeds).each(function(){
243 /**@since 2.4.2 track each tables with unique ids and their fields*/
244 var unique = $(this).attr('id');
245 var fields = {};
246 fields[unique]=[];
247 var search = $(this).html();
248 var match = cf7TagRegexp.exec(search);
249 while (match != null) {
250 //if( -1 === tableFields.indexOf(match[2]) ) /*removed as now want to idenify fields which are both tabs and table fields*/
251 fields[unique][fields[unique].length] = match[2];
252 //ttFields[match[2]] = match[1];
253 match = cf7TagRegexp.exec(search); //get the next match.
254 }
255 tabFields[tabFields.length] = fields;
256 hasTabs = true;
257 });
258 /**
259 * Track toggled fields to see if they are submitted or not.
260 * @since 2.5 */
261
262 var toggledFields = [];
263 $('.container.cf7sg-collapsible.with-toggle', $formNoEmbeds).each(function(){
264 /**@since 2.4.2 track each tables with unique ids and their fields*/
265 var unique = $(this).attr('id');
266 var fields = {};
267 fields[unique]=[];
268 var search = $(this).html();
269 var match = cf7TagRegexp.exec(search);
270 while (match != null) {
271 //if( -1 === tableFields.indexOf(match[2]) ) /*removed as now want to idenify fields which are both tabs and table fields*/
272 fields[unique][fields[unique].length] = match[2];
273 //ttFields[match[2]] = match[1];
274 match = cf7TagRegexp.exec(search); //get the next match.
275 }
276 toggledFields[toggledFields.length] = fields;
277 hasToggles = true;
278 });
279 //append hidden fields
280 $this.append('<input type="hidden" name="cf7sg-has-tabs" value="'+hasTabs+'" /> ');
281 $this.append('<input type="hidden" name="cf7sg-has-tables" value="'+hasTables+'" /> ');
282 $this.append('<input type="hidden" name="cf7sg-has-toggles" value="'+hasToggles+'" /> ');
283 var disabled = $('#form-editor-tabs').tabs('option','disabled');
284 $this.append('<input type="hidden" name="cf7sg-has-grid" value="'+disabled+'" /> ');
285 //update script classes since v3.
286 if(hasTabs) scriptClass+="has-tabs,";
287 if(hasTables) scriptClass+="has-table,";
288 if(hasToggles) scriptClass+="has-toggles,";
289 if(!disabled) scriptClass+="has-grid,";
290 $this.append('<input type="hidden" name="cf7sg-script-classes" value="'+scriptClass+'" />');
291
292 $('#cf7sg-tabs-fields').val(JSON.stringify(tabFields));
293 $('#cf7sg-table-fields').val(JSON.stringify(tableFields));
294 $('#cf7sg-toggle-fields').val(JSON.stringify(toggledFields));
295
296 //alert(ttFields);
297 // continue the submit unbind preventDefault.
298 $this.unbind('submit').submit();
299 });
300 /*
301 Function to convert the UI form into its html final form for editing in the codemirror and/or saving to the CF7 plugin.
302 */
303 $.fn.CF7FormHTML = function(){
304 var $this = $(this);
305 if( !$this.is('#grid-form') ){
306 return '';
307 }
308 var $form = $('<div>').append( $this.html() );
309 var text='';
310 //remove the external forms
311 var external = {};
312 $('.cf7sg-external-form', $form).each(function(){
313 var $exform = $(this);
314 var id = $exform.data('form');
315 external[id] = $exform.children('.cf7sg-external-form-content').remove();
316 $exform.children('.form-controls').remove();
317 });
318 //remove the row controls
319 $('.row', $form).removeClass('ui-sortable').children('.row-controls').remove();
320
321 //remove the collapsible input
322 $('.container.cf7sg-collapsible', $form).each(function(){
323 var $this = $(this);
324 var cid = $this.attr('id');
325 var $title = $this.children('.cf7sg-collapsible-title');
326 var text = $title.children('label').children('input[type="hidden"]').val();
327 $title.children('label').remove();
328 var toggle = '';
329 if($this.is('.with-toggle')){
330 toggle=' toggled';
331 }
332 text = '<span class="cf7sg-title'+toggle+'">'+text+'</span>';
333 $title.html(text + $title.html());
334 });
335 //remove tabs inputs
336 $('ul.cf7-sg-tabs-list li label', $form).remove();
337
338 var cf7TagRegexp = /\[(.[^\s]*)\s*(.[^\s]*)(|\s*(.[^\[]*))\]/img;
339 var cf7sgToggleRegex = /class:cf7sg-toggle-(.[^\s]+)/i;
340 //remove textarea and embed its content
341 $('.columns', $form).each(function(){
342 var $this = $(this);
343 $this.removeClass('ui-sortable');
344 var $gridCol = $this.children('.grid-column');
345 var $text = $('textarea.grid-input', $gridCol);
346 if($text.length>0){
347 text = $text.text();
348 //verify if this column is within a toggled section.
349 var $toggle = $this.closest('.container.cf7sg-collapsible.with-toggle');
350 if($toggle.length>0){
351 var cid = $toggle.attr('id');
352 /**
353 * track toggled checkbox/radio fields, because they are not submitted when not filled.
354 *@since 2.1.5
355 */
356 var $field = $text.siblings('div.cf7-field-type');
357 var isToggled = false;
358 if($field.length>0){
359 if($field.is('.checkbox.required') || $field.is('.radio') || $field.is('.file.required')) isToggled = true;
360 }else isToggled = true; //custom column, needs checking.
361 if(isToggled){
362 var search = text;
363 var match = cf7TagRegexp.exec(search);
364 //var hasRadios = false;
365 while (match != null) {
366 switch(match[1]){
367 case 'checkbox*':
368 case 'radio':
369 case 'file*':
370 var options = '';
371 if(match.length>4){
372 var tglmatch = cf7sgToggleRegex.exec(match[4]);
373 if(tglmatch != null){
374 if(tglmatch[1] == cid) break;
375 options =match[4].replace(tglmatch[0],'class:cf7sg-toggle-'+cid);
376 }else{
377 options = 'class:cf7sg-toggle-'+cid+' '+match[4];
378 }
379 }else{
380 options = 'class:cf7sg-toggle-'+cid;
381 }
382 text = text.replace(match[0], '['+match[1]+' '+match[2]+' '+options+']');
383 //hasRadios = true;
384 break;
385 }
386 //console.log('match'+match[2]);
387 match = cf7TagRegexp.exec(search); //get the next match.
388 }
389 }//end isToggled.
390 }
391 $this.html('\n'+text);
392 }//else this column is a grid.
393 $gridCol.remove();
394 });
395 //reinsert the external forms
396 $('.cf7sg-external-form', $form).each(function(){
397 var $this = $(this);
398 var id = $this.data('form');
399 $this.append( external[id] );
400 });
401 text = $form.html();
402 if($grid.children('.container').length > 0){ //strip tabs/newlines
403 text = text.replace(/^(?:[\t ]*(?:\r?\n|\r))+/gm, "");
404 }
405 return text;
406 }
407 });//dcoument ready end
408
409 })( jQuery, codeMirror_5_32);
410