PluginProbe
Page Builder: Pagelayer – Drag and Drop website builder / 2.2.2
Page Builder: Pagelayer – Drag and Drop website builder v2.2.2
2.2.2 2.2.1 2.2.0 2.1.9 2.1.8 2.1.7 2.1.6 2.1.5 2.1.4 2.1.3 trunk 0.9.0 0.9.1 0.9.2 0.9.3 0.9.4 0.9.5 0.9.6 0.9.7 0.9.8 0.9.9 1.0.0 1.0.2 1.0.3 1.0.4 All 130 releases
← All changes | js/pagelayer-editor.js +5463 -519 0.9.9 → 2.2.2 View file →
@@ -8,21 +8,107 @@
8 8 $: jQuery,
9 9 $$ : function(select){
10 10 return jQuery(select, window.parent.document);
11 11 },
12 + gDocument : jQuery(window.parent.document).add(document),
12 13 p : this,
13 14 copy_selected: '',
14 15 mouse: {x: -1, y: -1},
15 16 history_action : true,
17 + global_render : true,
18 + history_lastTime : new Date(),
19 + props_ref : {},
20 + pro_txt : '',
21 + loaded : 0,
22 + post_status : '',
23 + el: {},// All elements data
16 24 }
17 25
18 26 var pagelayer_history_obj = {}, pagelayer_revision_obj = {};
27 +var pagelayer_add_section_data = {};
19 28
29 +// Console error manager
30 +window.onerror = function (msg, url, lineNo, columnNo, error) {
31 +
32 + if (typeof pagelayer_doc_width === 'undefined') {
33 + var test_giver = -1;
34 +
35 + jQuery.ajax({
36 + url: pagelayer_url+'/js/givejs.php?test=1',
37 + type: "GET",
38 + dataType: "text",
39 + success: function(data){
40 +
41 + if(data != 1){
42 + return;
43 + }
44 +
45 + test_giver = 1;
46 + },
47 + complete: function(data){
48 + jQuery.ajax({
49 + type: "POST",
50 + url: pagelayer_ajax_url+"&action=pagelayer_set_jscss_giver",
51 + data: {
52 + pagelayer_nonce: pagelayer_ajax_nonce,
53 + set : test_giver
54 + },
55 + error: function(errorThrown){
56 + console.log("Error saving giver data");
57 + console.log(errorThrown);
58 + }
59 + });
60 + }
61 + });
62 + }
63 +
64 + var string = msg.toLowerCase();
65 + var substring = "script error";
66 +
67 + if(pagelayer.loaded > 0){
68 + return;
69 + }
70 +
71 + if (string.indexOf(substring) > -1){
72 + return;
73 + }
74 +
75 + if(url.indexOf('pagelayer')=== -1){
76 + return;
77 + }
78 +
79 + var message = [
80 + "Message: " + msg,
81 + "\r\n<br>URL: " + url,
82 + "\r\n<br>Line: " + lineNo,
83 + "\r\n<br>Column: "+ columnNo,
84 + "\r\n<br>Error object: " + error
85 + ].join('\n');
86 + //alert("Script Error: See browser console for details");
87 +
88 + pagelayer.$$('.pagelayer-errorBox-content').html(message);
89 + pagelayer.$$('.pagelayer-errorBox-close').on('click', function(){
90 + pagelayer.$$('.pagelayer-errorBox').fadeOut();
91 + });
92 + pagelayer.$$('.pagelayer-errorBox').fadeIn();
93 +
94 + return false;
95 +};
96 +
20 97 // Lets start
21 -jQuery(document).ready(function(){
98 +jQuery(document).ready(pagelayer_start);
99 +
100 +// Function to load the codes
101 +function pagelayer_start(){
22 102
103 + pagelayer.loading = 1;
104 + console.log('['+pagelayer_brand+'] Starting Pagelayer');
105 +
106 + // Prevent the click Insite editor
107 + pagelayer_prevent_click();
108 +
23 109 // Set the title of the parent window
24 - pagelayer.$$('head').append(pagelayer.$('title')[0].outerHTML);
110 + try{ pagelayer.$$('head').append(pagelayer.$('title')[0].outerHTML); }catch(e){};
25 111
26 112 pagelayer.blank_img = pagelayer_url+'/images/default-image.png';
27 113
28 114 pagelayer_shortcodes['pl_inner_row'] = JSON.parse(JSON.stringify(pagelayer_shortcodes['pl_row']));
@@ -27,15 +113,21 @@
27 113
28 114 pagelayer_shortcodes['pl_inner_row'] = JSON.parse(JSON.stringify(pagelayer_shortcodes['pl_row']));
29 115 pagelayer_shortcodes['pl_inner_row']['name'] = 'Inner Row';
30 116 pagelayer_groups['grid'].push('pl_inner_row');
117 +
118 + // Removing post props options
119 + pagelayer_setting_post_props();
31 120
32 121 // Make the Topbar
33 122 pagelayer_bottombar();
34 123
35 124 // Make the Leftbar
36 - pagelayer_leftbar();
37 -
125 + pagelayer_leftbar();
126 +
127 + // Make widget list toolbar
128 + pagelayer_create_widget_tooltip();
129 +
38 130 // Add widget section
39 131 pagelayer_add_widget();
40 132
41 133 // Setup the ELPD
@@ -40,8 +132,11 @@
40 132
41 133 // Setup the ELPD
42 134 pagelayer_elpd_setup();
43 135
136 + // Dump the data we have
137 + pagelayer_element_dump_data();
138 +
44 139 // Setup the properties of the elements
45 140 pagelayer_element_setup();
46 141
47 142 // An image to show for drag
@@ -49,24 +144,331 @@
49 144
50 145 // Setup the grid drag
51 146 pagelayer_setup_drag();
52 147
148 + // Set left bar draggable
149 + pagelayer_make_leftbar_movable();
150 +
53 151 // Set to desktop
54 152 pagelayer_set_screen_mode('desktop');
55 153
154 + // Create list of fonts
155 + pagelayer_fonts = pagelayer_l('pl_fonts_list');
156 +
56 157 // Set up right click
57 158 pagelayer_left_click();
58 159 pagelayer_right_click();
59 160
60 - // Setup pagelayer history
161 + // Setup pagelayer history handle
61 162 pagelayer_history_obj['action_data'] = [];
62 163 pagelayer_history_setup(true);
164 +
165 + // Make a quick access of the props
166 + pagelayer_make_props_ref();
167 +
168 + // Post props exported defaults need to be updated
169 + pagelayer_set_exported_defaults();
170 +
171 + // Do any actions here
172 + pagelayer_trigger_action('pagelayer_setup_history');
173 +
174 + // Editor Tooltips
175 + pagelayer_tooltip_setup();
176 +
177 + // Load Fonts
178 + for(var x in pagelayer_loaded_icons){
179 + var item = pagelayer_loaded_icons[x];
180 + jQuery.when(
181 + pagelayer_get_stored_data(pagelayer_url+'/fonts/'+item+'.json', pagelayer_ver)
182 + ).then(function(){
183 + pagelayer_icons[item] = JSON.parse(pagelayer_get_stored_data(pagelayer_url+'/fonts/'+item+'.json', pagelayer_ver));
184 + });
185 + };
63 186
64 -});
187 + // Set row-option top zero(0) of the first row
188 + pagelayer_set_row_option_position();
189 +
190 + // Just the txt
191 + pagelayer.pro_txt = pagelayer_pro_txt;
192 +
193 + // Open post props on document load
194 + pagelayer.$$('.pagelayer-settings').click();
195 +
196 + // Open post props and Make elements editable to edit post props data
197 + pagelayer_setup_props_editable();
198 +
199 + // Make elements editable
200 + jQuery(pagelayer_editable+' [pagelayer-editable]').attr('contenteditable', 'true');
201 +
202 + // Use text widget for search widget
203 + pagelayer_search_widgets();
204 +
205 + // Hide the loader
206 + pagelayer_loader_hide();
207 +
208 + // ON comment mode
209 + const urlParams = new URLSearchParams(window.location.search);
210 + pagelayer.cmode = urlParams.get('cmode');
211 +
212 + // Start custom UX Improvements engine
213 + setTimeout(pagelayer_ux_improvements_init, 200);
214 +}
65 215
216 +// Post props attribute
217 +function pagelayer_post_props_atts(prop, val, temp){
218 +
219 + val = val || null;
220 + temp = temp || false;
221 +
222 + var proEle = jQuery(pagelayer_editable+' .pagelayer-post_props.pagelayer-ele').first();
223 +
224 + if(!pagelayer_empty(temp)){
225 + if(val === null){
226 + return pagelayer_get_tmp_att(proEle, prop);
227 + }
228 +
229 + // Set the temp property as well
230 + pagelayer_set_tmp_atts(proEle, prop, val);
231 + return true;
232 + }
233 +
234 + if(val === null){
235 + return pagelayer_get_att(proEle, prop);
236 + }
237 +
238 + // Set the property as well
239 + pagelayer_set_atts(proEle, prop, val);
240 + return true;
241 +}
242 +
243 +// Open post props and Make elements editable to edit post props data
244 +function pagelayer_setup_props_editable(){
245 +
246 + jQuery('[pagelayer-props-editable]').each(function(){
247 + var jEle = jQuery(this);
248 +
249 + // Skip element under the editable area
250 + if (jEle.closest(pagelayer_editable).length > 0) {
251 + return;
252 + }
253 +
254 + var prop = jEle.attr('pagelayer-props-editable');
255 +
256 + // Make editable
257 + jEle.attr('contenteditable', 'true');
258 +
259 + // Reverse setup the event
260 + jEle.on('focus', function(){
261 + // Set the property as well
262 + var data = pagelayer_post_props_atts(prop);
263 + jEle.html(data);
264 + });
265 +
266 + // Reverse setup the event
267 + jEle.on('input', function(){
268 +
269 + var val = pagelayer_trim(jEle.html());
270 +
271 + // Set the property as well
272 + pagelayer_post_props_atts(prop, val);
273 +
274 + // Update the property
275 + var input = pagelayer.$$('[pagelayer-elp-name='+prop+']').find('input,textarea,.trumbowyg-editor');
276 + //console.log(input);
277 +
278 + if(input.length > 0){
279 + if(input.hasClass('trumbowyg-editor')){
280 + input.html(val);
281 + }else{
282 + input.val(val);
283 + }
284 + }
285 +
286 + });
287 +
288 + });
289 +
290 +}
291 +
292 +// Prevent the click Insite editor
293 +function pagelayer_prevent_click(){
294 + jQuery(document).on('submit', function(event){
295 + var target = jQuery(event.target);
296 + if (target.closest(pagelayer_editable).length < 1) {
297 + event.preventDefault();
298 + }
299 + });
300 +
301 + jQuery(document).on('click', function(event){
302 + var target = jQuery(event.target);
303 + if (target.closest('a').length > 0 && target.closest(pagelayer_editable).length < 1) {
304 + event.preventDefault()
305 + }
306 + });
307 +}
308 +
309 +// Removing post props options from the editor
310 +function pagelayer_setting_post_props(){
311 +
312 + if(pagelayer_empty(pagelayer_post_categories)){
313 + delete pagelayer_shortcodes.pl_post_props.postCategory;
314 + }
315 +
316 + if(pagelayer_empty(pagelayer_post_tags)){
317 + delete pagelayer_shortcodes.pl_post_props.postTags;
318 + }
319 +
320 + if(pagelayer_empty(pagelayer_shortcodes.pl_post_props.pageParent.post_parent.list)){
321 + delete pagelayer_shortcodes.pl_post_props.pageParent;
322 + }
323 +
324 + if(pagelayer_post.post_type != 'post'){
325 + delete pagelayer_shortcodes.pl_post_props.params.post_sticky;
326 + }
327 +
328 + if(pagelayer_empty(pagelayer_post_type_features['comments'])){
329 + delete pagelayer_shortcodes.pl_post_props.postDiscussion.comment_status;
330 + }
331 +
332 + if(pagelayer_empty(pagelayer_post_type_features['trackbacks'])){
333 + delete pagelayer_shortcodes.pl_post_props.postDiscussion.ping_status;
334 + }
335 +
336 + if(pagelayer_empty(pagelayer_shortcodes.pl_post_props.postDiscussion)){
337 + delete pagelayer_shortcodes.pl_post_props.postDiscussion;
338 + }
339 +
340 + if(pagelayer_empty(pagelayer_post_type_features['excerpt'])){
341 + delete pagelayer_shortcodes.pl_post_props.postExcerpt;
342 + }
343 +
344 + if(pagelayer_empty(pagelayer_post_type_features['thumbnail'])){
345 + delete pagelayer_shortcodes.pl_post_props.postFeaturedImage;
346 + }
347 +
348 + if(pagelayer_empty(pagelayer_post_type_features['author'])){
349 + delete pagelayer_shortcodes.pl_post_props.params.post_author;
350 + }
351 +}
352 +
353 +// Set the default values of all default exported codes
354 +function pagelayer_set_exported_defaults(){
355 +
356 + // Set defaults for the exported variety
357 + if(pagelayer_empty(pagelayer_default_params)){
358 + return;
359 + }
360 +
361 + for(var tag in pagelayer_default_params){
362 +
363 + for(var x in pagelayer_default_params[tag]){
364 +
365 + if(x in pagelayer.props_ref[tag]){
366 + pagelayer.props_ref[tag][x]['default'] = pagelayer_default_params[tag][x];
367 + }
368 +
369 + }
370 +
371 + }
372 +
373 +}
374 +
375 +// Do pagelayer Dirty
376 +function pagelayer_do_dirty(jEle){
377 +
378 + pagelayer_isDirty = true;
379 +
380 + if (!window.onbeforeunload) {
381 + window.onbeforeunload = function(){
382 + return true;
383 + };
384 + }
385 +
386 + pagelayer_trigger_action('pagelayer_do_dirty', [jEle]);
387 +}
388 +
389 +function pagelayer_do_undirty(){
390 +
391 + pagelayer_isDirty = false;
392 +
393 + if (window.onbeforeunload) {
394 + window.onbeforeunload = null;
395 + }
396 +
397 +}
398 +
399 +// Executes when pagelayer is fully loaded
400 +function pagelayer_loader_hide(){
401 + var inner = pagelayer.$$('.pagelayer-percent');
402 + inner.attr('loaded', 1);
403 + var w = parseInt(inner.text());
404 + var t = setInterval(function() {
405 + w = w + 1;
406 + inner.html(w +'<sup>%</sup>');
407 + if (w >= 100){
408 + clearInterval(t);
409 + w = 0;
410 + var loaderWrapper = pagelayer.$$('#pagelayer-loader-wrapper');
411 + loaderWrapper.addClass('pagelayer-loaded');
412 + loaderWrapper.animate({opacity:0}, function(){
413 + loaderWrapper.remove();
414 + });
415 + }
416 + }, 1);
417 + pagelayer.loaded = 1;
418 +}
419 +
420 +// Set row-option top zero(0) of the first row
421 +function pagelayer_set_row_option_position(){
422 + try{
423 + if(jQuery(pagelayer_editable).offset().top < 20){
424 + jQuery(pagelayer_editable).addClass('pagelayer-row-option-zero');
425 + }
426 + }catch(e){
427 + console.log(pagelayer_editable+" not found and hence Pagelayer wont work on this page !");
428 + }
429 +}
430 +
66 431 // The jQuery Object of the ELPD
67 432 var pagelayer_elpd;
68 433
434 +// Store data values
435 +function pagelayer_get_stored_data(url, version){
436 + var name = 'pagelayer_'+url;
437 + var data = {};
438 + var force = false;
439 +
440 + // Try to parse the data
441 + try{
442 + data = JSON.parse(localStorage.getItem(name));
443 +
444 + if(data['version'] !== version){
445 + force = true;
446 + }
447 +
448 + }catch(e){
449 + force = true;
450 + }
451 +
452 + // Force download
453 + if(force){
454 + return jQuery.ajax({
455 + url: url,
456 + type: 'GET',
457 + dataType: 'text',
458 + success:function(newData){
459 + var data = {};
460 + data['version'] = version;
461 + data['val'] = newData;
462 + localStorage.setItem(name, JSON.stringify(data));
463 + }
464 + });
465 + }
466 +
467 + return data['val'];
468 +
469 +}
470 +
69 471 function pagelayer_closest_corner(jEle){
70 472 var corners = [];
71 473 var w = jEle.outerWidth();
72 474 var h = jEle.outerHeight();
@@ -100,8 +502,115 @@
100 502 return corner;
101 503
102 504 };
103 505
506 +// Make left bar draggable
507 +function pagelayer_make_leftbar_movable(){
508 + var pl_iframe = pagelayer.$$('.pagelayer-iframe'),
509 + pl_leftbar = pagelayer.$$('.pagelayer-leftbar-table');
510 +
511 + // On mouse down in pagelayer-topbar-holder
512 + pagelayer.$$('.pagelayer-topbar-mover').on('mousedown', function(e){
513 + e = e || window.event;
514 + e.preventDefault();
515 +
516 + // Get leftbar position
517 + var orig_eleX = pl_leftbar.offset().left;
518 + var orig_eleY = pl_leftbar.offset().top;
519 +
520 + // Get the mouse cursor position at startup:
521 + var posX = e.clientX;
522 + var posY = e.clientY;
523 +
524 + // The variable needs to be empty.
525 + var newMethod = '',
526 + change = true;
527 +
528 + var leftbar_mousemove = function(e){
529 + e = e || window.event;
530 +
531 + if(change){
532 + // Add class to leftbar
533 + pl_leftbar.addClass('pagelayer-leftbar-moving');
534 +
535 + // Add left-right overlay
536 + pl_iframe.before('<div class="pagelayer-leftbar-move pagelayer-moveto-left"></div>');
537 + pl_iframe.after('<div class="pagelayer-leftbar-move pagelayer-moveto-right"></div>');
538 + pagelayer.$$('body').addClass('pagelayer-overflow-hidden');
539 + change = false;
540 + }
541 +
542 + // calculate the new cursor position and set the element left-top position
543 + var top = orig_eleY + (e.clientY - posY);
544 + var left = orig_eleX + (e.clientX - posX);
545 +
546 + // set the element's new position:
547 + pl_leftbar.css({'top': top +'px','left': left +'px'});
548 + pagelayer.$$('.pagelayer-leftbar-toggle').hide();
549 +
550 + // Make a copy of new method
551 + var _newMethod = newMethod;
552 + newMethod = '';
553 +
554 + // Get near by corner
555 + var offleft = pl_iframe.offset().left;
556 +
557 + if(offleft + 100 > e.clientX){
558 + newMethod = 'before';
559 + }else if(offleft+pl_iframe.outerWidth()- 100 < e.clientX){
560 + newMethod = 'after';
561 + }
562 +
563 + if(_newMethod != newMethod){
564 + pagelayer.$$('.pagelayer-leftbar-move').css({'width' :'', 'opacity': '0.33'});
565 +
566 + if(newMethod == 'after'){
567 + pagelayer.$$('.pagelayer-moveto-right').animate({'width' :'60px', 'opacity': '0.66'}, 200);
568 + pl_leftbar.addClass('pagelayer-rightbar');
569 + }else if(newMethod == 'before'){
570 + pagelayer.$$('.pagelayer-moveto-left').animate({'width' : '60px', 'opacity': '0.66'}, 200);
571 + pl_leftbar.removeClass('pagelayer-rightbar');
572 + }
573 + }
574 +
575 + };
576 +
577 + var leftbar_mouseup = function(e){
578 +
579 + // Remove events
580 + pagelayer.gDocument.off('mousemove', leftbar_mousemove);
581 + pagelayer.gDocument.off('mouseup', leftbar_mouseup);
582 +
583 + // Remove class to leftbar
584 + pagelayer.$$('.pagelayer-leftbar-move').remove();
585 +
586 + var windowHeight = jQuery(window).height();
587 +
588 + if(pl_leftbar.offset().top < 0){
589 + pl_leftbar.css({'top': '10px'});
590 + }else if( (windowHeight - e.clientY) < 10){
591 + pl_leftbar.css({'top': ''+windowHeight - 40+'px'});
592 + }
593 +
594 + if( !pagelayer_empty(newMethod)){
595 + pl_leftbar.removeClass('pagelayer-leftbar-moving');
596 + pl_leftbar.removeAttr('style');
597 + pagelayer.$$('.pagelayer-leftbar-toggle').show();
598 + pagelayer.$$('body').removeClass('pagelayer-overflow-hidden');
599 + pl_iframe[newMethod](pl_leftbar);
600 + }
601 +
602 + // make change true
603 + change = true;
604 + };
605 +
606 + pagelayer.gDocument.on('mouseup', leftbar_mouseup);
607 + pagelayer.gDocument.on('mousemove', leftbar_mousemove);
608 +
609 + });
610 +
611 +}
612 +
104 613 // Make rows and cols draggable
105 614 function pagelayer_setup_drag(){
106 615
107 616 // The object to show as drag
@@ -219,9 +728,21 @@
219 728 var onWrap;
220 729
221 730 // If we are a column, we can be over another column or row
222 731 if(tag == 'pl_col'){
223 - onWrap = jQuery(ele).closest('.pagelayer-wrap-col,.pagelayer-wrap-row,.pagelayer-wrap-inner-row');
732 +
733 + // Prevent column in inner-row and it's columns, if the draged column have inner-rows
734 + if(wrap.find('.pagelayer-wrap-inner-row').length > 0){
735 + onWrap = jQuery(ele).closest('.pagelayer-wrap-col,.pagelayer-wrap-row');
736 +
737 + var innerRow = onWrap.closest(pagelayer_editable +' .pagelayer-wrap-inner-row');
738 + if( onWrap.length < 1 || innerRow.length > 0){
739 + onWrap = jQuery(innerRow).closest('.pagelayer-wrap-col,.pagelayer-wrap-row');
740 + }
741 +
742 + }else{
743 + onWrap = jQuery(ele).closest('.pagelayer-wrap-col,.pagelayer-wrap-row,.pagelayer-wrap-inner-row');
744 + }
224 745 //console.log(pagelayer_id(onWrap));
225 746
226 747 // If we are a row, we can be over another row or a column
227 748 }else if(tag == 'pl_row'){
@@ -229,10 +750,14 @@
229 750 //console.log(pagelayer_id(onWrap));
230 751
231 752 // For inner row we restrict to 1 level only
232 753 }else if(tag == 'pl_inner_row'){
754 +
233 755 var ele_wrap = jQuery(ele).parents('.pagelayer-wrap-col');
234 - if(ele_wrap.length == 1 && !jQuery(ele).hasClass('pagelayer-wrap-col')){
756 + if(
757 + (ele_wrap.length == 1 && !jQuery(ele).hasClass('pagelayer-wrap-col')) ||
758 + (ele_wrap.length == 0 && jQuery(ele).hasClass('pagelayer-wrap-col'))
759 + ){
235 760 onWrap = jQuery(ele).closest('.pagelayer-wrap-ele,.pagelayer-wrap-col,.pagelayer-wrap-inner-row');
236 761 }else{
237 762 onWrap = jQuery(ele).closest('.pagelayer-wrap-inner-row');
238 763 }
@@ -238,8 +763,70 @@
238 763 }
239 764 // For every other element, we can be over a col or ele
240 765 }else{
241 766 onWrap = jQuery(ele).closest('.pagelayer-wrap-ele,.pagelayer-wrap-col,.pagelayer-wrap-inner-row');
767 +
768 + // If we are inside the same widget tag
769 + // We are allowing for now, hence the following is commented
770 + /*var sameTag = onWrap.closest(pagelayer_editable +' [pagelayer-tag="'+tag+'"]');
771 + if(sameTag.length > 0){
772 + onWrap = sameTag.closest('.pagelayer-wrap-ele');
773 + }*/
774 +
775 + // Is prevent to go inside any widget?
776 + if('prevent_inside' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['prevent_inside'])){
777 +
778 + var preTags = pagelayer_shortcodes[tag]['prevent_inside'];
779 + var prevent_inside = false;
780 + var preEle = onWrap;
781 +
782 + if(typeof preTags === 'string'){
783 + preTags = [preTags];
784 + }
785 +
786 + for(var toFind in preTags){
787 + preEle = onWrap.closest(pagelayer_editable +' [pagelayer-tag="'+preTags[toFind]+'"]');
788 + if (preEle.length > 0) {
789 + prevent_inside = true;
790 + break;
791 + }
792 + }
793 +
794 + // If we find
795 + if(prevent_inside){
796 + onWrap = preEle.closest('.pagelayer-wrap-ele');
797 + }
798 + }
799 +
800 + var widGroup = onWrap.closest('.pagelayer-ele-widget-group');
801 +
802 + // If we are inside the group widget
803 + if(widGroup.length > 0 && widGroup.closest(pagelayer_editable).length > 0){
804 +
805 + var wGroupTag = pagelayer_tag(widGroup);
806 + var use_inside = false;
807 +
808 + // If defined use inside only
809 + if('use_inside' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['use_inside'])){
810 +
811 + var inTags = pagelayer_shortcodes[tag]['use_inside'];
812 +
813 + if(typeof inTags === 'string'){
814 + inTags = [inTags];
815 + }
816 +
817 + for(var toFind in inTags){
818 + if (wGroupTag == inTags[toFind]) {
819 + use_inside = true;
820 + }
821 + }
822 + }
823 +
824 + // If we find nothing
825 + if(!use_inside){
826 + onWrap = widGroup.parent('.pagelayer-wrap-ele');
827 + }
828 + }
242 829 }
243 830 //console.log(onWrap);
244 831
245 832 // If we find nothing
@@ -248,21 +835,48 @@
248 835 reset_on_drag();// Also reset the last on item
249 836 return false;
250 837 }
251 838
839 + /*// If the columns more than 12 inside the row then return - As of now not enabled the below code
840 + if(tag == 'pl_col'){
841 + var _onTag = pagelayer_tag(onWrap);
842 + var colEles;
843 +
844 + // Is on col
845 + if(_onTag == 'pl_col'){
846 + colEles = onWrap.closest('.pagelayer-row-holder').children('.pagelayer-ele-wrap');
847 + }else{
848 + colEles = onWrap.find('.pagelayer-row-holder').first().children('.pagelayer-ele-wrap');
849 + }
850 +
851 + // If the columns more than 12
852 + if(colEles.length >= 12){
853 + return false;
854 + }
855 + }*/
856 +
252 857 // Get the ID
253 - var onId = onWrap.attr('pagelayer-wrap-id');
254 - var onEle = onWrap.children('.pagelayer-ele');
858 + var onId = pagelayer_id(onWrap);
859 + var onEle = pagelayer_ele_by_id(onId);
255 860
256 861 // Do we have a parent ?
257 - var pOnId = pagelayer_get_parent(onEle);
258 -
259 - if(pOnId){
862 + var have_parent = function(Ele){
863 + var pOnId = pagelayer_get_parent(Ele);
864 +
865 + if(pagelayer_empty(pOnId) || tag == 'pl_col'){
866 + return;
867 + }
868 +
260 869 onId = pOnId;
261 - onEle = pagelayer_ele_by_id(onId);
262 - onWrap = pagelayer_wrap_by_id(onId);
870 + onEle = pagelayer_ele_by_id(pOnId);
871 + onWrap = pagelayer_wrap_by_id(pOnId);
872 + have_parent(onEle);
873 +
263 874 }
264 875
876 + // Do we have a parent ?
877 + have_parent(onEle);
878 +
265 879 var changed = false;
266 880
267 881 // Was it the same ID like the one we were on before
268 882 if(pagelayer.drag_closest != onId){
@@ -302,10 +916,10 @@
302 916 }
303 917
304 918 //console.log(changed);
305 919
306 - // If we are on our self then clear return false
307 - if(onId == id){
920 + // If we are on our self then clear return false and we are on hide active widget
921 + if(onId == id || onWrap.hasClass('pagelayer-hide-active')){
308 922 clear_prospect();// Clear existing prospects
309 923 reset_on_drag();// Also reset the last on item
310 924 return false;
311 925 }
@@ -402,10 +1016,17 @@
402 1016 e.preventDefault();
403 1017
404 1018 var wrap = pagelayer.dragging;
405 1019 var tag = pagelayer_tag(wrap);
1020 + var gId = wrap.attr('pagelayer-global-id');
406 1021 var fromEl = wrap.parent();
407 1022 var id;
1023 +
1024 + // Global ID is there for sure ?
1025 + if(pagelayer_empty(gId) || pagelayer_empty(pagelayer_global_widgets[gId])){
1026 + gId = 0;
1027 + }
1028 +
408 1029 wrap.removeClass('pagelayer-is-dragging');
409 1030
410 1031 // Find any prospect
411 1032 var prospect = jQuery('.pagelayer-drag-prospect');
@@ -419,15 +1040,25 @@
419 1040 var onTag = pagelayer_tag(onWrap);
420 1041 var dropped;
421 1042 var corner = prospect.attr('pagelayer-corner');
422 1043 var method = (corner == 'top') ? 'before' : 'after';
1044 + var before_loc; // Location before the drop
423 1045
424 1046 // Create the element if it needs to be created
425 - if(pagelayer.drag_is_new){
1047 + if(pagelayer.drag_is_new){
426 1048 dropped = jQuery('<div pagelayer-tag="'+tag+'"></div>');
1049 +
1050 + // Is there a global ID
1051 + if(!pagelayer_empty(gId)){
1052 + dropped.attr('pagelayer-global-id', gId);
1053 + }
427 1054
428 1055 // Move the object
429 1056 }else{
1057 +
1058 + // Get near by element before move
1059 + before_loc = pagelayer_near_by_ele(pagelayer_id(wrap), tag);
1060 +
430 1061 dropped = wrap;
431 1062 dropped.detach();
432 1063 }
433 1064
@@ -449,12 +1080,30 @@
449 1080
450 1081 // Trigger the onadd
451 1082 if(pagelayer.drag_is_new){
452 1083 id = pagelayer_onadd(dropped);
1084 +
1085 + // Create Column
1086 + if((tag == 'pl_row' || tag == 'pl_inner_row') && pagelayer_empty( dropped.attr('pagelayer-global-id') )){
1087 + var col = jQuery('<div pagelayer-tag="pl_col"></div>');
1088 + jQuery('[pagelayer-id="'+id+'"]').find('.pagelayer-row-holder').append(col);
1089 + var col_id = pagelayer_onadd(col, false);
1090 + }
453 1091
454 1092 // Existing elements
455 1093 }else{
456 1094 id = pagelayer_id(wrap);
1095 +
1096 + // Save in action history
1097 + pagelayer_history_action_push({
1098 + 'title' : pagelayer_shortcodes[tag]['name'],
1099 + 'action' : 'Moved',
1100 + 'pl_id' : id,
1101 + 'before_loc' : before_loc,
1102 + 'after_loc' : {'method' : method, 'cEle' : onWrap}
1103 + });
1104 +
1105 + pagelayer_do_dirty(pagelayer_ele_by_id(id));
457 1106 }
458 1107
459 1108 // Defining the variables as needed
460 1109 var jEle = pagelayer_ele_by_id(id);
@@ -502,13 +1151,14 @@
502 1151 jQuery(document).on('dragover', ondragover);
503 1152 jQuery(document).on('drop', ondrop);
504 1153
505 1154 // For addition of new elements
506 - pagelayer.$$('[pagelayer-tag]').on('dragstart', function(e){
1155 + pagelayer.$$('.pagelayer-leftbar').on('dragstart', function(e){
507 1156 //console.log(e);
508 1157
509 1158 var tEle = jQuery(e.target);
510 1159 var jEle = tEle.closest('.pagelayer-shortcode-drag');
1160 + var global_id = jEle.attr('pagelayer-global-id');
511 1161
512 1162 // Is it an existing element ?
513 1163 if(jEle.length < 1){
514 1164 return false;
@@ -515,8 +1165,12 @@
515 1165 }
516 1166
517 1167 e.originalEvent.dataTransfer.setData('tag', pagelayer_tag(jEle));
518 1168
1169 + if(!pagelayer_empty(global_id)){
1170 + e.originalEvent.dataTransfer.setData( 'global_id', global_id );
1171 + }
1172 +
519 1173 pagelayer.dragging = jEle;
520 1174 pagelayer.drag_is_new = true;
521 1175
522 1176 });
@@ -560,17 +1214,25 @@
560 1214
561 1215 // Column is becoming blank, so show add ele
562 1216 if(jEle.children().length < 1){
563 1217 //from.addClass('pagelayer-empty-col');
564 - jEle.append('<div class="pagelayer-add-ele pagelayer-ele-wrap"><i class="fa fa-plus"><br /><span>Empty column please Drag Widgets</span></i></div>');
1218 + jEle.append('<div class="pagelayer-add-ele pagelayer-ele-wrap"><i class="fas fa-plus"></i><br /><span>Empty column please Drag Widgets</span></div>');
565 1219 //var h = jEle.parent().parent().children('.pagelayer-ele-overlay').height();
566 1220 //jEle.children('.pagelayer-add-ele').height(h);
567 1221
568 1222 // Any add ele sign with non-empty columns here ?
569 - }else if(jEle.children('.pagelayer-add-ele').length > 0){
1223 + }else if(jEle.children('.pagelayer-add-ele').length > 0 && jEle.children().length > 1){
570 1224 jEle.children('.pagelayer-add-ele').remove();
571 1225 }
572 1226
1227 + jEle.find('>.pagelayer-add-ele .fas').unbind('click');
1228 + jEle.find('>.pagelayer-add-ele .fas').on('click', function(event){
1229 + event.stopPropagation();
1230 + pagelayer.$$('.pagelayer-elpd-close').click();
1231 +
1232 + pagelayer_show_widget_list(jQuery(this));
1233 + });
1234 +
573 1235 });
574 1236
575 1237 };
576 1238
@@ -599,15 +1261,112 @@
599 1261 break;
600 1262 }
601 1263 }
602 1264 jEle.addClass('pagelayer-col-'+cols);
603 - Ele.addClass('pagelayer-col-'+cols);
604 -
1265 + jEle.css({'width': ''});
1266 +
605 1267 // Set the att
606 1268 pagelayer_set_atts(Ele, obj);
1269 + pagelayer_set_atts(Ele, 'col_width','');
1270 + pagelayer_sc_render(Ele)
607 1271 });
608 1272 }
609 1273
1274 +// Make column resizable handler
1275 +function pagelayer_col_make_resizable(wrap){
1276 +
1277 + // Resize handler element
1278 + var rHandler = jQuery('<div class="pagelayer-resize-handler"><div class="pagelayer-resize-icon"></div></div>');
1279 +
1280 + var pResize = wrap.children('.pagelayer-ele-overlay').find('.pagelayer-resize-handler');
1281 +
1282 + if(pResize.length > 0){
1283 + return;
1284 + }
1285 +
1286 + // Append it
1287 + wrap.children('.pagelayer-ele-overlay').append(rHandler);
1288 +
1289 + // Resize start
1290 + rHandler.on('mousedown', function(e) {
1291 + e.preventDefault();
1292 +
1293 + var next_ele = wrap.next();
1294 + var rHolder_width = wrap.closest('.pagelayer-row-holder').width();
1295 + var new_width, nEle_new_width;
1296 +
1297 + // Original width
1298 + var original_width = parseFloat(window.getComputedStyle(wrap[0]).getPropertyValue('width'));
1299 + var next_ele_width = parseFloat(window.getComputedStyle(next_ele[0]).getPropertyValue('width'));
1300 + var original_mouse_x = e.pageX;
1301 +
1302 + var both_width = parseInt(original_width + next_ele_width);
1303 +
1304 + // Add the element width and next element width
1305 + both_width = ((both_width / rHolder_width) *100);
1306 +
1307 + if(both_width > 100){
1308 + return false;
1309 + }
1310 +
1311 + jQuery('body').css({'cursor': 'ew-resize'});
1312 + rHandler.css({'display': 'block'});
1313 +
1314 + var mousemoved = false;
1315 +
1316 + var r_mousemove = function(e){
1317 + mousemoved = true;
1318 +
1319 + var width = original_width + (e.pageX - original_mouse_x);
1320 +
1321 + // Covert width in percentage
1322 + new_width = (width / rHolder_width *100).toFixed(2);
1323 +
1324 + if(both_width > new_width && new_width > 0){
1325 + nEle_new_width = (both_width - new_width).toFixed(2);
1326 + wrap.css({'width': new_width+'%'});
1327 + next_ele.css({'width': nEle_new_width+'%'});
1328 +
1329 + rHandler.attr({'pre-width': new_width+'%', 'next-width': nEle_new_width+'%'});
1330 + }
1331 +
1332 + };
1333 +
1334 + var r_mouseup = function(e){
1335 +
1336 + jQuery(document).off('mousemove', r_mousemove);
1337 + jQuery(document).off('mouseup', r_mouseup);
1338 + jQuery('body').css({'cursor': ''});
1339 + rHandler.removeAttr('style pre-width next-width');
1340 +
1341 + // IF mouseMoved
1342 + if(!mousemoved) return;
1343 +
1344 + // find real element and next real element
1345 + var jEle = wrap.find('>.pagelayer-ele');
1346 + var nEle = next_ele.find('>.pagelayer-ele');
1347 + var mode = pagelayer_get_screen_mode();
1348 + var col_width = 'col_width';
1349 +
1350 + // Do we have screen ?
1351 + if(mode != 'desktop'){
1352 + col_width = col_width +'_'+mode;
1353 + }
1354 +
1355 + // Set the element attrs
1356 + pagelayer_set_atts(jEle, col_width, new_width);
1357 + pagelayer_set_atts(jEle, 'col', '');
1358 + pagelayer_set_atts(nEle, col_width, nEle_new_width);
1359 + pagelayer_set_atts(nEle, 'col', '');
1360 +
1361 + };
1362 +
1363 + // Resize start
1364 + jQuery(document).on('mousemove', r_mousemove);
1365 + jQuery(document).on('mouseup', r_mouseup);
1366 + });
1367 +}
1368 +
610 1369 // Handle addition of elements from the left
611 1370 // NOTE : At this point the addition is FINALIZED
612 1371 // The add element cannot be prevented !
613 1372 function pagelayer_onadd(jEle, toClick){
@@ -631,14 +1390,25 @@
631 1390 function pagelayer_element_added(jEle){
632 1391
633 1392 var sc = jEle.attr('pagelayer-tag');
634 1393 var id, par_id;
1394 + var gId = jEle.attr('pagelayer-global-id');
1395 + gId = gId && !pagelayer_empty(pagelayer_global_widgets[gId]) ? gId : 0;
635 1396
636 1397 // Set Pagelayer History FALSE to prevent saving attributes in action history
637 1398 pagelayer.history_action = false;
638 -
1399 + pagelayer.global_render = false;
1400 +
1401 + // Is this a global widget ?
1402 + if(!pagelayer_empty(gId)){
1403 +
1404 + html = pagelayer_element_unsetup(pagelayer_global_widgets[gId].$);
1405 +
639 1406 // Generate the HTML
640 - html = pagelayer_create_sc(sc);
1407 + }else{
1408 + html = pagelayer_create_sc(sc);
1409 + }
1410 +
641 1411 id = pagelayer_assign_id(html);
642 1412 par_id = id;
643 1413
644 1414 // Insert the HTML
@@ -646,8 +1416,13 @@
646 1416
647 1417 // Setup the properties of the elements
648 1418 pagelayer_element_setup("[pagelayer-id="+par_id+"], [pagelayer-id="+par_id+"] .pagelayer-ele", true);
649 1419
1420 + // Is this a global widget ? Then set this as global element
1421 + if(!pagelayer_empty(gId)){
1422 + html = pagelayer_set_ele_global(jQuery('[pagelayer-id="'+par_id+'"]'), gId);
1423 + }
1424 +
650 1425 // Any children to add ?
651 1426 if(!('widget' in pagelayer_shortcodes[sc])){
652 1427
653 1428 // The element props
@@ -654,17 +1429,29 @@
654 1429 var props = pagelayer_shortcodes[sc];
655 1430
656 1431 // Do we have to create children ?
657 1432 if('has_group' in props){
1433 +
1434 + // Is this not a global widget ?
1435 + if(pagelayer_empty(gId)){
1436 + var has_group = props['has_group'];
1437 + var gProp = props[has_group['section']][has_group['prop']];
1438 +
1439 + for(var i=0; i < gProp['count']; i++){
1440 + var cid = pagelayer_element_add_child(jQuery("[pagelayer-id="+id+"]"), gProp['sc'], gProp);
1441 + //pagelayer_element_setup('[pagelayer-id='+cid+']', true);
658 1442
659 - var has_group = props['has_group'];
660 - var gProp = props[has_group['section']][has_group['prop']];
661 -
662 - for(var i=0; i < gProp['count']; i++){
663 - var cid = pagelayer_element_add_child(jQuery("[pagelayer-id="+id+"]"), gProp['sc']);
664 - //pagelayer_element_setup('[pagelayer-id='+cid+']', true);
1443 + var cEle = pagelayer_ele_by_id(cid);
1444 +
1445 + // Set default
1446 + if( 'item_atts' in gProp && i in gProp['item_atts'] && !pagelayer_empty(gProp['item_atts'][i]) ){
1447 + pagelayer_set_atts(cEle, gProp['item_atts'][i]);
1448 + pagelayer_sc_render(cEle);
1449 + }
1450 + }
1451 + }else{
1452 + pagelayer_sc_render(jQuery('[pagelayer-id="'+par_id+'"]'));
665 1453 }
666 -
667 1454 }
668 1455
669 1456 }
670 1457
@@ -674,21 +1461,27 @@
674 1461 pagelayer_history_action_push({
675 1462 'title' : pagelayer_shortcodes[sc]['name'],
676 1463 'action' : 'Added',
677 1464 'pl_id' : id,
678 - 'html' : html[0].outerHTML,
1465 + 'html' : jQuery("[pagelayer-id="+id+"]")[0].outerHTML,
679 1466 'cEle' : cEle
680 - });
1467 + });
681 1468
682 1469 // Set pagelayer history TRUE
683 1470 pagelayer.history_action = true;
1471 + pagelayer.global_render = true;
684 1472
1473 + // To update nav item list
1474 + pagelayer_do_dirty(pagelayer_ele_by_id(id));
1475 +
685 1476 return id;
686 1477
687 1478 };
688 1479
689 1480 // Add an element
690 -function pagelayer_element_add_child(pEle, sc){
1481 +function pagelayer_element_add_child(pEle, sc, gProp){
1482 +
1483 + gProp = gProp || {};
691 1484 var child = pagelayer_create_sc(sc);
692 1485 var cid = pagelayer_assign_id(child);
693 1486 pagelayer_set_parent(child, pagelayer_assign_id(pEle));
694 1487
@@ -706,8 +1499,73 @@
706 1499 }
707 1500
708 1501 pagelayer_element_setup('[pagelayer-id='+cid+']', true);
709 1502
1503 + // Certain element have editable areas which are inner rows. For UX we need to add columns for the users
1504 + if(sc == 'pl_inner_row'){
1505 +
1506 + var rHolder = pagelayer_ele_by_id(cid).find('.pagelayer-row-holder');
1507 +
1508 + if( !pagelayer_empty(gProp) && 'inner_content' in gProp){
1509 +
1510 + var inner_content = gProp['inner_content'];
1511 +
1512 + // Add default element
1513 + if(!pagelayer_empty(inner_content)){
1514 +
1515 + var add_sc = function(hEle, _tag, content){
1516 +
1517 + var dEle = jQuery('<div pagelayer-tag="'+_tag+'"></div>');
1518 +
1519 + if(_tag == 'pl_col'){
1520 + hEle = hEle.closest('.pagelayer-row-holder');
1521 + }else{
1522 + hEle = hEle.find('.pagelayer-col-holder');
1523 + }
1524 +
1525 + hEle.append(dEle);
1526 + var curID = pagelayer_onadd(dEle, false);
1527 + var curEle = pagelayer_ele_by_id(curID);
1528 +
1529 + // Set default
1530 + if('atts' in content[_tag]){
1531 + pagelayer_set_atts(curEle, content[_tag]['atts']);
1532 + pagelayer_sc_render(curEle);
1533 + }
1534 +
1535 + // Set inner content
1536 + if('inner_content' in content[_tag]){
1537 + for( var key in content[_tag]['inner_content'] ){
1538 + for( var _key in content[_tag]['inner_content'][key] ){
1539 + add_sc(curEle, _key, content[_tag]['inner_content'][key]);
1540 + }
1541 + }
1542 + }
1543 +
1544 + if(_tag == 'pl_col'){
1545 + // TODO: unable to set col width
1546 + pagelayer_renumber_col(hEle);
1547 + }else{
1548 + pagelayer_empty_col(hEle);
1549 + }
1550 + };
1551 +
1552 + for( var key in inner_content ){
1553 + for( var tag in inner_content[key] ){
1554 + add_sc(rHolder, tag, inner_content[key]);
1555 + }
1556 + }
1557 + }
1558 +
1559 + pagelayer_empty_col(jQuery('[pagelayer-id="'+cid+'"]').find('.pagelayer-col-holder'));
1560 +
1561 + }else{
1562 + var col = jQuery('<div pagelayer-tag="pl_col"></div>');
1563 + rHolder.append(col);
1564 + pagelayer_onadd(col, false);
1565 + }
1566 + }
1567 +
710 1568 // Do we have to create children ?
711 1569 if('has_group' in pagelayer_shortcodes[sc]){
712 1570
713 1571 var has_group = pagelayer_shortcodes[sc]['has_group'];
@@ -713,9 +1571,9 @@
713 1571 var has_group = pagelayer_shortcodes[sc]['has_group'];
714 1572 var gProp = pagelayer_shortcodes[sc][has_group['section']][has_group['prop']];
715 1573
716 1574 for(var i=0; i < gProp['count']; i++){
717 - var in_cid = pagelayer_element_add_child(jQuery("[pagelayer-id="+cid+"]"), gProp['sc']);
1575 + var in_cid = pagelayer_element_add_child(jQuery("[pagelayer-id="+cid+"]"), gProp['sc'], gProp);
718 1576 }
719 1577
720 1578 }
721 1579
@@ -745,8 +1603,14 @@
745 1603 return id;
746 1604
747 1605 }
748 1606
1607 +// Remove Pagelayer ID class
1608 +function pagelayer_remove_id_class(jEle){
1609 + var id = jEle.attr('pagelayer-id');
1610 + jEle.removeClass('p-'+id);
1611 +}
1612 +
749 1613 // Assign the jQuery object an ID
750 1614 function pagelayer_assign_id(jEle){
751 1615
752 1616 // Do you have the pagelayer id
@@ -751,9 +1615,10 @@
751 1615
752 1616 // Do you have the pagelayer id
753 1617 var id = jEle.attr("pagelayer-id");
754 1618 if(!id || id.length < 1){
755 - id = pagelayer_randstr(16);
1619 + id = pagelayer_randstr(3)+pagelayer_randInt(9999).toString();
1620 + id = id.toLowerCase();
756 1621 jEle.attr("pagelayer-id", id);
757 1622 }
758 1623
759 1624 return id;
@@ -784,8 +1649,13 @@
784 1649 //pagelayer_clear_editable();// First clear
785 1650 jEle.find('[pagelayer-editable]').each(function (){
786 1651 pagelayer_make_editable(jQuery(this), e);
787 1652 });
1653 +
1654 + // Show left bar
1655 + if(pagelayer_empty(e)){
1656 + pagelayer.$$('.pagelayer-leftbar-table').removeClass('pagelayer-leftbar-hidden pagelayer-leftbar-minimize');
1657 + }
788 1658
789 1659 // Lets not rebuild everything to make it faster
790 1660 if(pagelayer_is_active(jEle)){
791 1661 return false;
@@ -790,8 +1660,10 @@
790 1660 if(pagelayer_is_active(jEle)){
791 1661 return false;
792 1662 }
793 1663
1664 + pagelayer_trigger_action('pagelayer_element_clicked', [jEle]);
1665 +
794 1666 // Set this as the active element
795 1667 pagelayer_set_active(jEle);
796 1668
797 1669 // Show the properties
@@ -798,13 +1670,69 @@
798 1670 pagelayer_elpd_open(jEle);
799 1671
800 1672 }
801 1673
1674 +// Use text widget for search widget
1675 +function pagelayer_search_widgets(hEle){
1676 +
1677 + hEle = hEle || jQuery(pagelayer_editable +' [pagelayer-tag="pl_text"], '+pagelayer_editable +' [pagelayer-tag="pl_heading"]');
1678 +
1679 + hEle.each(function(){
1680 +
1681 + var jEle = jQuery(this);
1682 + var tEle = jEle.find('[pagelayer-editable="text"]');
1683 +
1684 + var addPlaceholder = function(ele){
1685 +
1686 + var tVal = ele.text();
1687 +
1688 + if(pagelayer_empty(tVal)){
1689 + ele.attr('data-placeholder-text', 'Type / to open widget list');
1690 + }else if(ele.attr('data-placeholder-text')){
1691 + ele.removeAttr('data-placeholder-text');
1692 + }
1693 + }
1694 +
1695 + // Add placeholder text
1696 + addPlaceholder(tEle);
1697 +
1698 + tEle.off('input.search_widgets');
1699 + tEle.on('input.search_widgets', function(){
1700 +
1701 + var val = tEle.text();
1702 +
1703 + // Add placeholder text
1704 + addPlaceholder(tEle);
1705 +
1706 + if(val.charAt(0) == "/"){
1707 + val = val.replace('/', '');
1708 + pagelayer_show_widget_list(tEle, val);
1709 + }else if(pagelayer.$$('.pagelayer-widget-tooltip').is(':visible')){
1710 + // Hide Widget list
1711 + pagelayer.gDocument.trigger('mousedown.pagelayer_wdlist');
1712 + }
1713 +
1714 + });
1715 +
1716 + });
1717 +
1718 +}
1719 +
802 1720 // The edit option
803 1721 function pagelayer_edit_element(selector){
804 1722 pagelayer_element_clicked(selector);
805 1723 }
806 1724
1725 +// Dump the data from the el to the elements
1726 +function pagelayer_element_dump_data(){
1727 + for(var x in pagelayer.el){
1728 + var jEle = pagelayer_ele_by_id(x);
1729 + if(jEle.length > 0){
1730 + pagelayer_el_dump_data(jEle);
1731 + }
1732 + }
1733 +}
1734 +
807 1735 // Setup the properties on a single click
808 1736 function pagelayer_element_setup(selector, render){
809 1737
810 1738 var selector = selector || ".pagelayer-ele";
@@ -811,9 +1739,9 @@
811 1739 render = render || false;
812 1740
813 1741 // Loop through
814 1742 jQuery(pagelayer_editable+' '+selector).each(function(){
815 -
1743 +
816 1744 var jEle = jQuery(this);
817 1745
818 1746 // Assign an ID if not there
819 1747 var id = pagelayer_assign_id(jEle);
@@ -819,8 +1747,13 @@
819 1747 var id = pagelayer_assign_id(jEle);
820 1748 var pId = pagelayer_get_parent(jEle) || '';// Options to show on hover
821 1749 var selector = '[pagelayer-id='+id+']';
822 1750
1751 + // Get data part
1752 + pagelayer.el[id] = pagelayer_el_get_data(jEle);
1753 + //console.log(jEle[0].outerHTML);
1754 + //console.log(pagelayer.el[id]);
1755 +
823 1756 if(render){
824 1757 pagelayer_sc_render(jEle);
825 1758 }
826 1759
@@ -825,8 +1758,9 @@
825 1758 }
826 1759
827 1760 // Get the tag
828 1761 var tag = pagelayer_tag(jEle);
1762 + var props = pagelayer_get_props(jEle);
829 1763
830 1764 // Lets check if we are the child of a parent i.e. element of a group
831 1765 if(pagelayer_empty(pId)){
832 1766
@@ -853,9 +1787,14 @@
853 1787
854 1788 }
855 1789
856 1790 }
857 -
1791 +
1792 + // If is group of widget?
1793 + if('widget_group' in props && !pagelayer_empty(props['widget_group'])){
1794 + pagelayer_set_widget_group(jEle);
1795 + }
1796 +
858 1797 // Make the wraps
859 1798 jEle.wrap('<div class="pagelayer-ele-wrap" pagelayer-wrap-id="'+id+'"></div>');
860 1799 var wrap = jEle.parent();
861 1800
@@ -868,15 +1807,10 @@
868 1807 col = 'pagelayer-col-'+x;
869 1808 break;
870 1809 }
871 1810 }
1811 +
872 1812
873 - var is_custom_width = pagelayer_get_att(jEle, 'col');
874 - var col_width = pagelayer_get_att(jEle, 'col_width');
875 - if(pagelayer_empty(is_custom_width) && col_width){
876 - wrap.css('width', col_width+'%');
877 - }
878 -
879 1813 wrap.addClass('pagelayer-col '+col);
880 1814 //jEle.removeClass('pagelayer-col '+col);
881 1815 wrap.addClass('pagelayer-wrap-col');
882 1816
@@ -902,11 +1836,13 @@
902 1836 pagelayer_sc_render(jEle);
903 1837 }
904 1838
905 1839 html = '<div class="pagelayer-row-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
906 - '<i class="fa fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" />'+
907 - '<i class="fa fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" />'+
908 - '<i class="fa fa-pencil pagelayer-eoi" onclick="pagelayer_edit_element(\''+selector+'\', event)" />'+
1840 + '<i class="fas fa-caret-up pagelayer-eoi pagelayer-move-up" onclick="pagelayer_move_element_up(\''+selector+'\')" ></i>'+
1841 + '<i class="far fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" ></i>'+
1842 + '<i class="fas fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" ></i>'+
1843 + '<i class="fas fa-pencil-alt pagelayer-eoi" onclick="pagelayer_edit_element(\''+selector+'\', event)" ></i>'+
1844 + '<i class="fas fa-caret-down pagelayer-eoi pagelayer-move-down" onclick="pagelayer_move_element_down(\''+selector+'\')" ></i>'+
909 1845 '</div>';
910 1846
911 1847 }else if(tag == 'pl_col'){
912 1848
@@ -912,20 +1848,25 @@
912 1848
913 1849 overlay.addClass('pagelayer-col-hover');
914 1850
915 1851 html = '<div class="pagelayer-col-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
916 - '<i class="fa fa-columns pagelayer-eoi" onclick="pagelayer_edit_element(\''+selector+'\', event)" />'+
1852 + '<i class="fas fa-columns pagelayer-eoi" onclick="pagelayer_edit_element(\''+selector+'\', event)" ></i>'+
917 1853 '</div>';
918 1854
919 1855 // Is it an empty col ?
920 1856 pagelayer_empty_col(jEle.children('.pagelayer-col-holder'));
1857 +
1858 + // Make col resizable
1859 + pagelayer_col_make_resizable(wrap);
921 1860
922 1861 }else{
923 1862
924 1863 html = '<div class="pagelayer-ele-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
925 - '<i class="fa fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" />'+
926 - '<i class="fa fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" />'+
927 - '<i class="fa fa-pencil pagelayer-eoi" onclick="pagelayer_edit_element(\''+selector+'\', event)" />'+
1864 + '<i class="fas fa-caret-up pagelayer-eoi pagelayer-move-up" onclick="pagelayer_move_element_up(\''+selector+'\')" ></i>'+
1865 + '<i class="far fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" ></i>'+
1866 + '<i class="fas fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" ></i>'+
1867 + '<i class="fas fa-pencil-alt pagelayer-eoi" onclick="pagelayer_edit_element(\''+selector+'\', event)" ></i>'+
1868 + '<i class="fas fa-caret-down pagelayer-eoi pagelayer-move-down" onclick="pagelayer_move_element_down(\''+selector+'\')" ></i>'+
928 1869 '</div>';
929 1870
930 1871 }
931 1872
@@ -930,10 +1871,23 @@
930 1871 }
931 1872
932 1873 // Append to the child
933 1874 overlay.append(html);
1875 +
1876 + // Add shortcode icon
1877 + if(tag != 'pl_row' && tag != 'pl_col'){
1878 + overlay.append('<span class="pagelayer-shortcode-plus" onclick="event.stopPropagation();pagelayer_show_widget_list(this);"><i class="fas fa-plus"></i></span>');
1879 + }
1880 +
934 1881 jQuery('[pagelayer-option-id='+id+']').hide();
935 1882
1883 + // Hide active when not supported by tag
1884 + if(!pagelayer_empty(props['hide_active'])){
1885 + wrap.addClass('pagelayer-hide-active');
1886 + }
1887 +
1888 + pagelayer_trigger_action('pagelayer_element_setup', [jEle]);
1889 +
936 1890 // Setup the HOVER events ABD create WRAPS IF we dont have a parent
937 1891 if(pId.length > 0){
938 1892 return;
939 1893 }
@@ -967,8 +1921,44 @@
967 1921
968 1922 });
969 1923 }
970 1924
1925 +// Unsetup element for restup
1926 +function pagelayer_element_unsetup(selector, id){
1927 +
1928 + id = id || false;
1929 +
1930 + var src = jQuery(selector);
1931 + var html = src[0].outerHTML;
1932 +
1933 + var jEle = jQuery(html);
1934 + pagelayer_remove_id_class(jEle);
1935 + jEle.removeAttr('pagelayer-id');
1936 + jEle.removeAttr('pagelayer-active');
1937 + jEle.find('[pagelayer-id]').each(function(){
1938 + pagelayer_remove_id_class(jQuery(this));
1939 + jQuery(this).removeAttr('pagelayer-id');
1940 + });
1941 + jEle.find('[pagelayer-parent]').removeAttr('pagelayer-parent');// Remove the parent attribute as it will be reset during pagelayer_element_setup
1942 + jEle.find('style').remove();
1943 + jEle.find('.pagelayer-ele-overlay').remove();
1944 +
1945 + // Unwrap the wraps
1946 + jEle.find('.pagelayer-ele').each(function (){
1947 + var ele = jQuery(this);
1948 + if(ele.parent().is('.pagelayer-ele-wrap')){
1949 + ele.unwrap();
1950 + }
1951 + });
1952 +
1953 + // Assign id
1954 + if(!pagelayer_empty(id)){
1955 + jEle.attr('pagelayer-id', id);
1956 + }
1957 +
1958 + return jEle;
1959 +}
1960 +
971 1961 // Left Click
972 1962 function pagelayer_left_click(){
973 1963
974 1964 jQuery(pagelayer_editable).on('click', function(e){
@@ -998,12 +1988,15 @@
998 1988
999 1989 var html = '<div class="pagelayer-right-click-options" style="display:none;">'+
1000 1990 '<ul>'+
1001 1991 '<li><a class="pagelayer-right-edit">Edit</a></li>'+
1002 - '<li><a class="pagelayer-right-duplicate"><i class="fa fa-clone" /> Duplicate</a></li>'+
1003 - '<li><a class="pagelayer-right-copy"><i class="fa fa-files-o" /> Copy</a></li>'+
1004 - '<li><a class="pagelayer-right-paste"><i class="fa fa-clipboard" /> Paste</a></li>'+
1005 - '<li><a class="pagelayer-right-delete"><i class="fa fa-trash-o" /> Delete</a></li>'+
1992 + '<li><a class="pagelayer-right-duplicate"><i class="far fa-clone" ></i> '+pagelayer_l('Duplicate')+'</a></li>'+
1993 + '<li><a class="pagelayer-right-copy"><i class="far fa-copy" ></i> '+pagelayer_l('Copy')+' <span style="margin-left:10px;opacity:0.6">Ctrl+c</span></a></li>'+
1994 + '<li><a class="pagelayer-right-paste pagelayer-context-disable" title="If the paste is not done correctly then use Ctrl+V"><i class="far fa-clipboard" ></i> '+pagelayer_l('Paste')+' <span style="margin-left:10px;opacity:0.6">Ctrl+v</span></a></li>'+
1995 + '<li><a class="pagelayer-right-delete"><i class="far fa-trash-alt" ></i> '+pagelayer_l('Delete')+'</a></li>'+
1996 + '<li><a class="pagelayer-right-save-global-widget" pro="1"><i class="far fa-save" ></i> '+pagelayer_l('save_global')+'</a></li>'+
1997 + '<li><a class="pagelayer-right-save-section" pro="1"><i class="far fa-heart" ></i> '+pagelayer_l('save_as_section')+'</a></li>'+
1998 + '<li><a class="pagelayer-right-save-global-section" pro="1"><i class="fas fa-globe" ></i> '+pagelayer_l('save_as_global_section')+'</a></li>'+
1006 1999 '</ul>'+
1007 2000 '</div>';
1008 2001
1009 2002 jQuery('body').append(html);
@@ -1014,8 +2007,13 @@
1014 2007
1015 2008 var tEle = jQuery(e.target);
1016 2009 var jEle = tEle.closest('.pagelayer-ele-wrap').children('.pagelayer-ele');
1017 2010
2011 + // If copy_selected is empty then copy data from localStorage
2012 + if(pagelayer_empty(pagelayer.copy_selected)){
2013 + pagelayer_copy_from_clipboard();
2014 + }
2015 +
1018 2016 // Get the parent
1019 2017 var pId = pagelayer_get_parent(jEle);
1020 2018
1021 2019 // If we found a parent
@@ -1026,26 +2024,89 @@
1026 2024 // The basics
1027 2025 var id = pagelayer_assign_id(jEle);
1028 2026 var tag = pagelayer_tag(jEle);
1029 2027
1030 - $contextMenu.find('.pagelayer-right-edit').attr('onclick', 'pagelayer_edit_element("[pagelayer-id='+id+']")').html('<i class="fa fa-pencil-square-o" /> Edit '+pagelayer_shortcodes[tag]['name']);
2028 + $contextMenu.find('.pagelayer-right-edit').attr('onclick', 'pagelayer_edit_element("[pagelayer-id='+id+']")').html('<i class="far fa-edit" ></i> Edit '+pagelayer_shortcodes[tag]['name']);
1031 2029 $contextMenu.find('.pagelayer-right-duplicate').attr('onclick', 'pagelayer_copy_element("[pagelayer-id='+id+']")');
1032 2030 $contextMenu.find('.pagelayer-right-copy').attr('onclick', 'pagelayer_copy_select("[pagelayer-id='+id+']")');
1033 - $contextMenu.find('.pagelayer-right-paste').attr('onclick', 'pagelayer_paste_element("[pagelayer-id='+id+']")');
1034 2031 $contextMenu.find('.pagelayer-right-delete').attr('onclick', 'pagelayer_delete_element("[pagelayer-id='+id+']")');
1035 2032
2033 + // If is pagelayer pro
2034 + if(!pagelayer_empty(pagelayer_pro)){
2035 + $contextMenu.find('.pagelayer-right-save-global-widget').attr('onclick', 'pagelayer_save_sections("[pagelayer-id='+id+']", "global_widget")');
2036 + $contextMenu.find('.pagelayer-right-save-section').attr('onclick', 'pagelayer_save_sections("[pagelayer-id='+id+']", "section")');
2037 + $contextMenu.find('.pagelayer-right-save-global-section').attr('onclick', 'pagelayer_save_sections("[pagelayer-id='+id+']", "global_section")');
2038 + }else{
2039 + var pro = $contextMenu.find('[pro="1"]');
2040 +
2041 + if(pro.find('.pagelayer-pro-req').length < 1){
2042 + pro.append('<span class="pagelayer-pro-req">Pro</span>');
2043 + }
2044 +
2045 + pro.css({'color': '#a7a7a7'});
2046 +
2047 + // To stopPropagation
2048 + pro.parent().on('click', function(e){
2049 + e.stopPropagation();
2050 + });
2051 + }
2052 +
2053 + var showPaste = function(){
2054 + if(!pagelayer_empty(pagelayer.copy_selected) && pagelayer_can_copy_to(jEle)){
2055 + $contextMenu.find('.pagelayer-right-paste').removeClass('pagelayer-context-disable');
2056 + $contextMenu.find('.pagelayer-right-paste').attr('onclick', 'pagelayer_paste_element("[pagelayer-id='+id+']")');
2057 + }
2058 + }
2059 +
1036 2060 // Are we to hide the paste ?
1037 - if(!pagelayer_empty(pagelayer.copy_selected) && pagelayer_can_copy_to(jEle)){
1038 - //console.log(pagelayer_can_copy_to(jEle));
1039 - $contextMenu.find('.pagelayer-right-paste').parent().show();
2061 + if(pagelayerClipboardLoading){
2062 + var clipboardLoading = {};
2063 + clipboardLoading = setInterval(function(){
2064 +
2065 + if(pagelayerClipboardLoading){
2066 + return;
2067 + }
2068 +
2069 + clearInterval(clipboardLoading);
2070 + showPaste();
2071 +
2072 + }, 100);
1040 2073 }else{
1041 - $contextMenu.find('.pagelayer-right-paste').parent().hide();
2074 + showPaste();
1042 2075 }
1043 2076
2077 + var gId = pagelayer_get_global_id(jEle);
2078 +
2079 + // Are we to hide the global widget ?
2080 + if(!pagelayer_empty(gId) || tag == 'pl_row' || tag == 'pl_inner_row'|| tag == 'pl_col'){
2081 + $contextMenu.find('.pagelayer-right-save-global-widget').parent().hide();
2082 + }else{
2083 + $contextMenu.find('.pagelayer-right-save-global-widget').parent().show();
2084 + }
2085 +
2086 + var sId = pagelayer_get_att(jEle, 'global-section-id');
2087 +
2088 + // Are we to hide the save as global section ?
2089 + if( tag == 'pl_row' && pagelayer_empty(sId)){
2090 + $contextMenu.find('.pagelayer-right-save-global-section').parent().show();
2091 + }else{
2092 + $contextMenu.find('.pagelayer-right-save-global-section').parent().hide();
2093 + }
2094 +
2095 + // Are we to hide the save as section ?
2096 + if( tag == 'pl_row' ){
2097 + $contextMenu.find('.pagelayer-right-save-section').parent().show();
2098 + }else{
2099 + $contextMenu.find('.pagelayer-right-save-section').parent().hide();
2100 + }
2101 +
2102 + var hPosition = (e.pageX+$contextMenu.width()>jQuery(window).width()) ? (e.pageX-$contextMenu.width()) : e.pageX;
2103 + var vPosition = (e.pageY+$contextMenu.height()>jQuery(document).scrollTop()+jQuery(window).height()) ? (e.pageY-$contextMenu.height()) : e.pageY;
2104 +
1044 2105 $contextMenu.css({
1045 2106 display: "block",
1046 - left: e.pageX,
1047 - top: e.pageY
2107 + left: hPosition,
2108 + top: vPosition
1048 2109 });
1049 2110
1050 2111 return false;
1051 2112
@@ -1060,9 +2121,14 @@
1060 2121 function pagelayer_set_parent(jEle, id){
1061 2122 jEle.attr('pagelayer-parent', id);
1062 2123 };
1063 2124
1064 -// Set the parent for the group
2125 +// Set the widget group
2126 +function pagelayer_set_widget_group(jEle){
2127 + jEle.addClass('pagelayer-ele-widget-group');
2128 +};
2129 +
2130 +// Get the parent for the group
1065 2131 function pagelayer_get_parent(jEle){
1066 2132 return jEle.attr('pagelayer-parent');
1067 2133 };
1068 2134
@@ -1083,12 +2149,12 @@
1083 2149 // Add the class
1084 2150 body.addClass('pagelayer-screen-'+mode);
1085 2151
1086 2152 // Add the class to the button
1087 - pagelayer.$$('.pagelayer-mode-button').removeClass('fa-'+current).addClass('fa-'+mode);
2153 + pagelayer.$$('.pagelayer-mode-button').removeClass('pli-'+current).addClass('pli-'+mode);
1088 2154
1089 2155 // Add the class to the button
1090 - pagelayer.$$('.pagelayer-prop-screen').removeClass('fa-'+current).addClass('fa-'+mode);
2156 + pagelayer.$$('.pagelayer-prop-screen').removeClass('pli-'+current).addClass('pli-'+mode);
1091 2157
1092 2158 // Trigger screen change if any
1093 2159 pagelayer.$$('.pagelayer-elp-screen').trigger('pagelayer-screen-changed');
1094 2160
@@ -1105,12 +2171,512 @@
1105 2171 }
1106 2172 }
1107 2173 }
1108 2174
2175 +var pagelayer_keydown_data = {};
2176 +pagelayer_add_action('pagelayer_do_dirty', function(){
2177 + pagelayer_keydown_data = {};
2178 +});
2179 +
2180 +var pagelayer_active_ele_timmer = {};
2181 +// Handle widget selecttion and move cursor in editable areas on key press events
2182 +jQuery(document).keydown(function(e){
2183 + //alert(String.fromCharCode(e.which));
2184 +
2185 + var tEle = jQuery(e.target);
2186 + var editable = tEle.closest('[contenteditable="true"]');
2187 + var tooltip = pagelayer.$$('.pagelayer-widget-tooltip');
2188 +
2189 + // If ArrowDown and ArrowUp key not pressed
2190 + if(!(e.key == 'ArrowDown' || e.key == 'ArrowUp') || tooltip.is(':visible')){
2191 + pagelayer_keydown_data = {};
2192 + return;
2193 + }
2194 +
2195 + var findEles = jQuery(pagelayer_editable+' .pagelayer-ele,'+pagelayer_editable+' [contenteditable="true"]');
2196 + var activeEle = findEles.first();
2197 +
2198 + if(editable.length > 0){
2199 + activeEle = editable;
2200 + }else if( '$' in pagelayer_keydown_data ){
2201 + activeEle = pagelayer_keydown_data.$;
2202 + }else if( pagelayer_active.el && 'id' in pagelayer_active.el ){
2203 + activeEle = pagelayer_active.el.$;
2204 + }
2205 +
2206 + if(pagelayer_empty(activeEle) || activeEle.length < 1){
2207 + return;
2208 + }
2209 +
2210 + // Make element active
2211 + var makeEleActive = function(index, next){
2212 +
2213 + next = next || false;
2214 + var cursorPos = 0, focusEle;
2215 +
2216 + // We are editable area
2217 + if(editable.length > 0){
2218 +
2219 + var lines = pagelayer_content_line(editable.get(0));
2220 + var cursorPos = pagelayer_getCaretCharacterOffsetWithin(editable.get(0));
2221 +
2222 + if((next && lines[lines.length - 1].start > cursorPos) || (!next && lines[0].end < cursorPos)){
2223 + return;
2224 + }
2225 +
2226 + e.preventDefault();
2227 +
2228 + var lastLineStart = lines[lines.length - 1]['start'];
2229 +
2230 + // We are on the last line
2231 + if(next && lastLineStart <= cursorPos){
2232 + cursorPos = cursorPos - lastLineStart;
2233 + }
2234 +
2235 + }
2236 +
2237 + // Search for next/previous element
2238 + var searchEle = function(indexEle){
2239 +
2240 + indexEle = next ? ++indexEle : --indexEle;
2241 + var sIndex = findEles.eq(indexEle);
2242 +
2243 + if(sIndex.length < 1){
2244 + return sIndex;
2245 + }
2246 +
2247 + var sEle = sIndex.closest('.pagelayer-ele');
2248 + var tag = pagelayer_tag(sEle);
2249 +
2250 + if(tag == 'pl_row' || tag == 'pl_inner_row' || tag == 'pl_col' || sEle.parent().hasClass('pagelayer-hide-active') || !pagelayer_empty(sIndex.attr('pagelayer-parent'))){
2251 + sIndex = searchEle(indexEle);
2252 + }
2253 +
2254 + return sIndex;
2255 + }
2256 +
2257 + var ele = searchEle(index);
2258 +
2259 + // If ArrowUp and we are come from editable area and previous element is not editable
2260 + if(ele.length > 0 && !next && ele.attr('contenteditable') != 'true'){
2261 + ele = searchEle(findEles.index( ele ));
2262 + }
2263 +
2264 + if(ele.length < 1){
2265 + return;
2266 + }
2267 +
2268 + // Save in global variable
2269 + pagelayer_keydown_data.$ = ele;
2270 + jQuery(':focus').blur();
2271 +
2272 + var jEle = ele.closest('.pagelayer-ele');
2273 + var tag = pagelayer_tag(jEle);
2274 +
2275 + if(ele.attr('contenteditable') == 'true'){
2276 + focusEle = ele;
2277 + }else if(tag != 'pl_row' && tag != 'pl_inner_row' && tag != 'pl_col'){
2278 +
2279 + var focusAble = ele.find('[contenteditable="true"]');
2280 + var isfocusAble = focusAble.closest('.pagelayer-ele').is(jEle);
2281 +
2282 + if(isfocusAble && next){
2283 + focusEle = focusAble.first();
2284 + }else if(isfocusAble){
2285 + focusEle = focusAble.last();
2286 + }
2287 + }
2288 +
2289 + if(!pagelayer_empty(focusEle) && focusEle.length > 0){
2290 + focusEle.focus();
2291 +
2292 + var focusLine = pagelayer_content_line(focusEle.get(0));
2293 + var fLine = next ? focusLine[0] : focusLine[focusLine.length -1];
2294 +
2295 + cursorPos = (fLine['start'] + cursorPos > fLine['end'] ? fLine['end'] : fLine['start'] + cursorPos);
2296 +
2297 + pagelayer_setCaret(focusEle.get(0), cursorPos);
2298 + }
2299 +
2300 + pagelayer_set_active(jEle);
2301 + ele[0].scrollIntoView({behavior: "smooth", block: "nearest"});
2302 +
2303 + clearTimeout(pagelayer_active_ele_timmer);
2304 + pagelayer_active_ele_timmer = setTimeout(function(){
2305 + pagelayer_keydown_data = {};
2306 + ele.closest('.pagelayer-ele').click();
2307 + }, 1000);
2308 + }
2309 +
2310 + // If cursor on first line & up arrow key
2311 + var currentIndex = findEles.index( activeEle );
2312 + pagelayer_keydown_data.$ = activeEle;
2313 +
2314 + // Move active element and cursor arround editor
2315 + if(e.key == 'ArrowDown'){
2316 + makeEleActive(currentIndex, true);
2317 + }
2318 +
2319 + if(e.key == 'ArrowUp'){
2320 + makeEleActive(currentIndex, false);
2321 + }
2322 +});
2323 +
1109 2324 // Handle key press events
1110 -jQuery(document).keydown(function(event){
2325 +pagelayer.gDocument.keydown(function(event){
1111 2326 //alert(String.fromCharCode(event.which));
1112 2327
2328 + var tEle = jQuery(event.target);
2329 + var editable = tEle.closest('[contenteditable="true"]');
2330 + var tooltip = pagelayer.$$('.pagelayer-widget-tooltip');
2331 +
2332 + // Enter handle
2333 + if(event.keyCode == 13){
2334 +
2335 + var jEle = tEle.closest('.pagelayer-ele');
2336 + var tag = pagelayer_tag(jEle);
2337 +
2338 + // Add selected widget from widget list
2339 + if(tooltip.is(':visible')){
2340 + tooltip.find('.pagelayer-list-widget-active:visible').click();
2341 + return;
2342 + }
2343 +
2344 + if( pagelayer_empty(pagelayer_active.el) || !('id' in pagelayer_active.el) ){
2345 + return;
2346 + }
2347 +
2348 + var active_el_par = pagelayer_active.el.$.parent();
2349 +
2350 + // Create and add text widget
2351 + var addTitle = function(insertAfter){
2352 + var ele = jQuery('<div pagelayer-tag="pl_text"></div>');
2353 + insertAfter.after(ele);
2354 + return pagelayer_ele_by_id( pagelayer_onadd(ele) );
2355 + }
2356 +
2357 + // If we have an active element then add text widget
2358 + if(!(tEle.is('input, textarea') || editable.length > 0)){
2359 +
2360 + event.preventDefault();
2361 +
2362 + var activeTag = pagelayer_active.el.tag;
2363 +
2364 + // If is row or column ?
2365 + if(activeTag == 'pl_row' || activeTag == 'pl_col'){
2366 + return;
2367 + }
2368 +
2369 + var hEle = addTitle(active_el_par);
2370 + hEle.click();
2371 + hEle.find('[pagelayer-editable]').focus();
2372 +
2373 + // Ensure the column is not empty
2374 + pagelayer_empty_col(hEle.closest('.pagelayer-col-holder'));
2375 + return;
2376 + }
2377 +
2378 + if( (tag != 'pl_text' && tag != 'pl_heading') || editable.length < 1 || event.shiftKey){
2379 + return;
2380 + }
2381 +
2382 + var selection = window.getSelection();
2383 + var range = selection.getRangeAt(0);
2384 +
2385 + // We are within the list tag
2386 + if(jQuery(range.startContainer).closest('[pagelayer-editable] li').length > 0){
2387 + return;
2388 + }
2389 +
2390 + event.preventDefault();
2391 +
2392 + var lastChild = editable[0].lastChild;
2393 + var startContainer = range.startContainer;
2394 +
2395 + if(startContainer.nodeType == Node.TEXT_NODE && startContainer.parentNode != editable[0]){
2396 + startContainer = startContainer.parentNode;
2397 + }
2398 +
2399 + range.setEndAfter(lastChild);
2400 +
2401 + var val = range.cloneContents();
2402 + var selfEle = jQuery('<div>').append(val);
2403 + var selContent = selfEle.html();
2404 + var selfFC = selfEle[0].firstChild;
2405 + var emptyContent = false;
2406 +
2407 + if(selfFC == null || pagelayer_empty(selContent)){
2408 + selContent = '<p><br></p>';
2409 + emptyContent = true;
2410 + }else if(selfFC.nodeType == Node.TEXT_NODE){
2411 + selContent = '<p>'+selContent+'</p>';
2412 + }else if(selfEle.text() == '' && selfEle.find('br').length < 1){
2413 + selContent = '<p><br></p>';
2414 + emptyContent = true;
2415 + }else if(selfEle.text().trim() == ''){
2416 + selContent = selContent.replace(/\s+/, "\u00A0");
2417 + emptyContent = true;
2418 + }
2419 +
2420 + range.deleteContents();
2421 +
2422 + if( jQuery(startContainer).is(':first-child') && jQuery(startContainer).is(':empty') ){
2423 + jQuery(startContainer).html('<br>');
2424 + }else if( jQuery(startContainer).is(':empty') ){
2425 + jQuery(startContainer).remove();
2426 + }
2427 +
2428 + // If editor is empty
2429 + if( editable.is(':empty') ){
2430 + editable.html('<p><br></p>');
2431 + }
2432 +
2433 + editable.trigger('input');
2434 + editable.blur();
2435 +
2436 + // Create and add text widget
2437 + var ele;
2438 + if(emptyContent){
2439 + ele = addTitle(jEle.parent());
2440 + }else{
2441 + var id = pagelayer_copy_element(jEle);
2442 + ele = pagelayer_ele_by_id(id);
2443 + }
2444 +
2445 + ele.click();
2446 + var editorArea = ele.find('[pagelayer-editable]');
2447 + editorArea.html(selContent);
2448 + editorArea.find('p:empty').remove();
2449 + editorArea.focus().trigger('input');
2450 + }
2451 +
2452 + // ctrl+s handle
2453 + if(event.keyCode == 83 && event.ctrlKey){
2454 + event.preventDefault();
2455 + pagelayer.$$('.pagelayer-iframe-top-bar').find('.pagelayer-update-button').click();
2456 + }
2457 +
2458 + // ctrl+d handle
2459 + if(event.keyCode == 68 && event.ctrlKey){
2460 +
2461 + // If we have an active element
2462 + if( pagelayer_active.el && pagelayer_active.el.id ){
2463 + event.preventDefault();
2464 + pagelayer_copy_element('[pagelayer-id='+pagelayer_active.el.id+']');
2465 + }
2466 +
2467 + }
2468 +
2469 + // Delete handler for text widget
2470 + if(event.keyCode == 46 && editable.length > 0){
2471 + var jEle = tEle.closest('.pagelayer-ele-wrap');
2472 + var tag = pagelayer_tag(jEle);
2473 + var next = jEle.next();
2474 + var pTag = pagelayer_tag(next);
2475 +
2476 + var selection = window.getSelection();
2477 + var orgRange = selection.getRangeAt(0);
2478 + var cloneRange = orgRange.cloneRange();
2479 +
2480 + if((tag != 'pl_text' && tag != 'pl_heading') || next.length < 1 || pTag != tag || !cloneRange.collapsed ){
2481 + return;
2482 + }
2483 +
2484 + var currentOffset = pagelayer_getCaretCharacterOffsetWithin(editable[0]);
2485 + cloneRange.selectNodeContents(editable[0]);
2486 + var caretOffset = cloneRange.toString().length;
2487 +
2488 + if(currentOffset != caretOffset){
2489 + return;
2490 + }
2491 +
2492 + var nextHtml = next.find('[pagelayer-editable="text"]').html();
2493 + editable.append(nextHtml);
2494 + pagelayer_delete_element(next.children('.pagelayer-ele'));
2495 + }
2496 +
2497 + // Backspace handler
2498 + if(event.keyCode == 8 && editable.length > 0){
2499 + var jEle = tEle.closest('.pagelayer-ele-wrap');
2500 + var tag = pagelayer_tag(jEle);
2501 + var prev = jEle.prev();
2502 +
2503 + if((tag != 'pl_text' && tag != 'pl_heading') || prev.length < 1){
2504 + return;
2505 + }
2506 +
2507 + var pTag = pagelayer_tag(prev);
2508 + var selection = window.getSelection();
2509 +
2510 + if (selection == null || selection.rangeCount <= 0) return null;
2511 +
2512 + var range1 = selection.getRangeAt(0);
2513 +
2514 + if(pTag != tag || range1.startOffset != 0){
2515 + return;
2516 + }
2517 +
2518 + var prevArea = prev.find('[pagelayer-editable="text"]');
2519 +
2520 + if( pagelayer_getCaretCharacterOffsetWithin(editable[0]) != 0 || prevArea.length < 1){
2521 + return;
2522 + }
2523 +
2524 + //event.preventDefault();
2525 + var html = editable.html();
2526 + editable.blur();
2527 + prev.children('.pagelayer-ele').click();
2528 + prevArea.click();
2529 +
2530 + var newSel = window.getSelection();
2531 + var newRange = newSel.getRangeAt(0);
2532 + var lastChild = jQuery(prevArea[0].lastChild);
2533 +
2534 + prevArea.append(html);
2535 + prevArea.trigger('input');
2536 +
2537 + if(lastChild.length > 0){
2538 + if(lastChild[0].nextSibling != null){
2539 + newRange.setStart(lastChild[0].nextSibling, 0);
2540 + }else{
2541 + newRange.setStartAfter(lastChild[0]);
2542 + }
2543 + }
2544 +
2545 + newRange.collapse(true);
2546 + newSel.removeAllRanges();
2547 + newSel.addRange(newRange);
2548 +
2549 + pagelayer_delete_element(jEle.children('.pagelayer-ele'));
2550 +
2551 + }
2552 +
2553 + if(tooltip.is(':visible')){
2554 +
2555 + // Select previous widget in widget tooltip
2556 + if(event.key == 'ArrowUp' || event.key == 'ArrowLeft' || (event.key == 'Tab' && event.shiftKey)){
2557 +
2558 + event.preventDefault();
2559 +
2560 + var current = tooltip.find('.pagelayer-list-widget-active:visible'),
2561 + prev = current.prevAll('.pagelayer-shortcode-holder:visible');
2562 +
2563 + if(event.key == 'ArrowUp'){
2564 + var _prev = prev,
2565 + cOffset = current.offset();
2566 + findNext = false;
2567 +
2568 + var searchNext = function(nEle){
2569 +
2570 + var nOffset = nEle.offset();
2571 + var nBottom = nOffset.top + nEle.height();
2572 +
2573 + if(nBottom > cOffset.top){
2574 + return true;
2575 + }
2576 +
2577 + prev = nEle;
2578 + findNext = true;
2579 +
2580 + // Current element left set +20 to manager previous scale (css) element on hover
2581 + if(cOffset.left + 20 >= nOffset.left){
2582 + return false;
2583 + }
2584 +
2585 + return true;
2586 + }
2587 +
2588 + _prev.each(function(){
2589 + return searchNext(jQuery(this));
2590 + });
2591 +
2592 + if(!findNext){
2593 + var gNext = current.parent().prevAll('.pagelayer-widget-group:visible').first();
2594 + _prev = gNext.children('.pagelayer-shortcode-holder:visible');
2595 +
2596 + jQuery(_prev.get().reverse()).each(function(){
2597 + return searchNext(jQuery(this));
2598 + });
2599 + }
2600 +
2601 + }
2602 +
2603 + if(prev.length < 1){
2604 + prev = current.parent().prevAll('.pagelayer-widget-group:visible').first().find('.pagelayer-shortcode-holder:visible').last();
2605 + }
2606 +
2607 + if(prev.length < 1){
2608 + return;
2609 + }
2610 +
2611 + prev.first().trigger('widget_active');
2612 + }
2613 +
2614 + // Select next widget in widget tooltip
2615 + if(event.key == 'ArrowDown' || event.key == 'ArrowRight' || (event.key == 'Tab' && !event.shiftKey)){
2616 +
2617 + event.preventDefault();
2618 +
2619 + var current = tooltip.find('.pagelayer-list-widget-active:visible');
2620 + next = current.nextAll('.pagelayer-shortcode-holder:visible');
2621 +
2622 + if(event.key == 'ArrowDown'){
2623 +
2624 + var _next = next,
2625 + cOffset = current.offset(),
2626 + findNext = false;
2627 +
2628 + var searchNext = function(nEle){
2629 + var nOffset = nEle.offset();
2630 + var cBottom = cOffset.top + current.height();
2631 +
2632 + if(cBottom > nOffset.top){
2633 + return true;
2634 + }
2635 +
2636 + next = nEle;
2637 + findNext = true;
2638 +
2639 + // Current element left set -20 to manager next scale (css) element on hover
2640 + if(cOffset.left - 20 <= nOffset.left){
2641 + return false;
2642 + }
2643 +
2644 + return true;
2645 + }
2646 +
2647 + _next.each(function(){
2648 + return searchNext(jQuery(this));
2649 + });
2650 +
2651 + if(!findNext){
2652 + var gNext = current.parent().nextAll('.pagelayer-widget-group:visible').first();
2653 + _next = gNext.children('.pagelayer-shortcode-holder:visible');
2654 + _next.each(function(){
2655 + return searchNext(jQuery(this));
2656 + });
2657 + }
2658 +
2659 + }
2660 +
2661 + if(next.length < 1){
2662 + next = current.parent().nextAll('.pagelayer-widget-group:visible').first().find('.pagelayer-shortcode-holder:visible');
2663 + }
2664 +
2665 + if(next.length < 1){
2666 + return;
2667 + }
2668 +
2669 + next.first().trigger('widget_active');
2670 +
2671 + }
2672 + }
2673 +
2674 + // Is this in the editable area ?
2675 + if (tEle.is('input, textarea') || editable.length > 0) {
2676 + return;
2677 + }
2678 +
1113 2679 // Delete
1114 2680 if(event.keyCode == 46){
1115 2681 pagelayer_delete_element('[pagelayer-active]');
1116 2682 }
@@ -1124,31 +2690,212 @@
1124 2690 if(event.keyCode == 89 && event.ctrlKey){
1125 2691 pagelayer_do_history('redo');
1126 2692 }
1127 2693
1128 - // ctrl+c handle
1129 - if(event.keyCode == 67 && event.ctrlKey){
2694 +});
2695 +
2696 +// Handle Copy of content
2697 +jQuery(document).on('copy', function(copyEvent){
1130 2698
1131 - // Check the active element
1132 - if(pagelayer_active.el && pagelayer_active.el.id){
1133 - pagelayer_copy_select("[pagelayer-id='"+pagelayer_active.el.id+"']");
2699 + // Is Selected string?
2700 + var selectedText = "";
2701 + if (window.getSelection){ // all modern browsers and IE9+
2702 + selectedText = window.getSelection().toString();
2703 + }
2704 +
2705 + if(selectedText.length > 0){
2706 + return;
2707 + }
2708 +
2709 + if(pagelayer_active.el && pagelayer_active.el.id){
2710 + copyEvent.preventDefault();
2711 +
2712 + // Save the active element id
2713 + pagelayer_copy_select("[pagelayer-id='"+pagelayer_active.el.id+"']", copyEvent);
2714 +
2715 + }
2716 +
2717 +});
2718 +
2719 +// This is for preload clipboard data
2720 +// Content can be copied from outside
2721 +var pagelayerIsParentBlured = true;
2722 +jQuery(window).on('focus', function(e){
2723 + if(pagelayerIsParentBlured){
2724 + pagelayer_copy_from_clipboard();
2725 + }
2726 + pagelayerIsParentBlured = true;
2727 +});
2728 +
2729 +jQuery(window.parent).on('focus', function(){
2730 + pagelayerIsParentBlured = false;
2731 +});
2732 +
2733 +// Handle Paste in the editor
2734 +jQuery(document).on('paste', function(pasteEvent){
2735 +
2736 + var pEle_target = jQuery((pasteEvent.originalEvent || pasteEvent).target);
2737 + var tag = pagelayer_tag(pEle_target.closest('[pagelayer-id]'));
2738 + var clipboardData = (pasteEvent.originalEvent || pasteEvent).clipboardData;
2739 + var items = clipboardData.items;
2740 +
2741 + var pagelayer_ajax_func = {};
2742 + var contenteditable = false;
2743 + var pasteWidget = false;
2744 +
2745 + if( pEle_target.closest('[contenteditable="true"]').length > 0 || pEle_target.is('input, textarea') ){
2746 + pEle_target = pEle_target.closest('[contenteditable="true"], input, textarea');
2747 + contenteditable = true;
2748 + }
2749 +
2750 + if( items.length < 1 || (items.length == 1 && pagelayer_empty(clipboardData.getData(items[0].type))) ){
2751 + pasteWidget = true;
2752 + }
2753 +
2754 + // This function for ajax before send call back
2755 + pagelayer_ajax_func['beforeSend'] = function(xhr){
2756 +
2757 + // If target is not content editable
2758 + if( pagelayer_empty(contenteditable) ){
2759 +
2760 + // If we dont have an active element then return false and stop ajax
2761 + if( !(pagelayer_active.el && pagelayer_active.el.id) ){
2762 + pagelayer_show_msg(pagelayer_l('active_ele_paste_msg'));
2763 + return false;
2764 + }
2765 +
2766 + pagelayer.copy_selected = jQuery('<div pagelayer-tag="pl_image"></div>');
2767 +
2768 + // Is it to be pastable
2769 + if(!pagelayer_can_copy_to('[pagelayer-id="'+pagelayer_active.el.id+'"]')){
2770 + pagelayer.copy_selected = '';
2771 + return false;
2772 + }
1134 2773 }
1135 2774
2775 + pEle_target.css({'opacity': '0.33' , 'transition' : '0.1s'});
1136 2776 }
1137 2777
1138 - // ctrl+v handle
1139 - if(event.keyCode == 86 && event.ctrlKey){
2778 + // This function for ajax success call back
2779 + pagelayer_ajax_func['success'] = function(obj){
1140 2780
2781 + // Successfully Uploaded
2782 + if(obj['success']){
2783 +
2784 + // For content editable e.g. Rich Text
2785 + if( !pagelayer_empty(contenteditable) ){
2786 + document.execCommand('insertImage', false, obj['data']['url']);
2787 +
2788 + // For our widgets
2789 + }else{
2790 +
2791 + if(pagelayer_empty(pagelayer_active.el) || pagelayer_empty(pagelayer_active.el.id)){
2792 + pagelayer_show_msg('active_ele_paste_msg');
2793 + return;
2794 + }
2795 +
2796 + var fTo = pagelayer_can_copy_to('[pagelayer-id="'+pagelayer_active.el.id+'"]');
2797 + // We need to empty pagelayer.copy_selected
2798 + pagelayer.copy_selected = '';
2799 +
2800 + var pasteAfter = function(){
2801 +
2802 + // Prevent to add action history
2803 + pagelayer.history_action = false;
2804 +
2805 + // Create image html
2806 + var html = pagelayer_create_sc('pl_image');
2807 +
2808 + pagelayer_set_atts(html, 'id', obj['data']['id']);
2809 + pagelayer_set_tmp_atts(html, 'id-url', obj['data']['url']);
2810 +
2811 + // Allow to add action history
2812 + pagelayer.history_action = true;
2813 +
2814 + // Copy the element
2815 + var id = pagelayer_copy_element(html, fTo);
2816 + jQuery('[pagelayer-id="'+id+'"]').click();
2817 +
2818 + };
2819 +
2820 + var replaceURL = function(){
2821 +
2822 + // Finding widget image setting using id of jEle. Finding image editor setting from all of the other settings.
2823 + var row = pagelayer.$$('[pagelayer-element-id='+pagelayer_active.el.id+']').find('.pagelayer-elp-image').eq(0).parent().parent();
2824 +
2825 + row.find('.pagelayer-elp-image').css('background-image', 'url(\''+obj['data']['url']+'\')');
2826 +
2827 + // To remove past temp attr so that they are not involve in future temp values
2828 + var cname = row.attr('pagelayer-elp-name');
2829 + var old = _pagelayer_img_tmp_atts(row);
2830 + delete old[cname+'-url'];
2831 +
2832 + for(var x in obj['data']['sizes']){
2833 + _pagelayer_set_tmp_atts(row, x+'-url', obj['data']['sizes'][x]['url']);
2834 + delete old[cname+'-'+x+'-url'];
2835 + }
2836 +
2837 + for(var x in old){
2838 + _pagelayer_set_tmp_atts(row, x+'-url', '');
2839 + }
2840 +
2841 + // Save and render
2842 + _pagelayer_set_tmp_atts(row, 'url', obj['data']['url']);
2843 + _pagelayer_set_atts(row, obj['data']['id']);
2844 + };
2845 +
2846 + // Image paste confirmation.
2847 + if(!pagelayer_empty(pagelayer_active.el.tag) && pagelayer_active.el.tag == 'pl_image'){
2848 +
2849 + pagelayer_confirmation_box(pagelayer_l('img_paste_conf'), replaceURL, pasteAfter, pagelayer_l('replace_img'), pagelayer_l('paste_after'));
2850 +
2851 + }else{
2852 + pasteAfter();
2853 + }
2854 + }
2855 +
2856 + // Some error occured
2857 + }else{
2858 + pagelayer_show_msg(obj['data']['message'], 'error', 10000);
2859 + }
2860 + }
2861 +
2862 + // This function for ajax complete call back
2863 + pagelayer_ajax_func['complete'] = function(xhr){
2864 + //console.log(xhr);
2865 + pEle_target.css({'opacity': '1' , 'transition' : '0.1s'});
2866 + }
2867 +
2868 + var findImg = pagelayer_editable_paste_handler(pasteEvent, pagelayer_ajax_func);
2869 +
2870 + if(pagelayer_empty(findImg) || pasteWidget){
2871 +
1141 2872 // Check the active element
1142 - if(pagelayer_active.el && pagelayer_active.el.id){
2873 + if(pagelayer_active.el && pagelayer_active.el.id && pagelayer_active.el.tag != 'pl_post_props'){
1143 2874
1144 - var jEle = jQuery("[pagelayer-id='"+pagelayer_active.el.id+"']");
2875 + const text = clipboardData.getData('text');
2876 + var pEle = jQuery(text);
2877 + var getData = true;
1145 2878
1146 - // Check if the any element is copied
1147 - if(!pagelayer_empty(pagelayer.copy_selected) && pagelayer_can_copy_to(jEle)){
1148 - pagelayer_paste_element("[pagelayer-id='"+pagelayer_active.el.id+"']");
2879 + if(pEle.length > 0 && !pagelayer_empty(pagelayer_tag(pEle)) ){
2880 +
2881 + // Cache pEle to make contextmenu paste faster
2882 + pagelayer.copy_selected = pEle;
2883 + getData = false;
2884 +
2885 + // Is it to be pastable
2886 + if(pagelayer_can_copy_to('[pagelayer-id="'+pagelayer_active.el.id+'"]')){
2887 + pasteEvent.preventDefault();
2888 + var jEle = jQuery("[pagelayer-id='"+pagelayer_active.el.id+"']");
2889 +
2890 + // Check if the any element is copied
2891 + pagelayer_paste_element(jEle, false);
2892 + }
2893 +
1149 2894 }
1150 2895
2896 + }else{
2897 + pagelayer_show_msg(pagelayer_l('no_active_ele_paste'));
1151 2898 }
1152 2899 }
1153 2900 });
1154 2901
@@ -1154,8 +2901,9 @@
1154 2901
1155 2902 // Delete an element as per the selector
1156 2903 function pagelayer_delete_element(selector){
1157 2904 var jEle = jQuery(selector);
2905 + var nearBy = jEle;
1158 2906
1159 2907 // Anything found ?
1160 2908 if(jEle.length > 0){
1161 2909
@@ -1170,8 +2918,10 @@
1170 2918 // Save this element in history action
1171 2919 if(pagelayer.history_action){
1172 2920 var cEle = pagelayer_near_by_ele(id, sc);
1173 2921
2922 + nearBy = jQuery(cEle.cEle);
2923 +
1174 2924 // To save in history, we need to save only element not the wraps as we call setup if we redo or undo
1175 2925 jEle.find('style').remove();
1176 2926 jEle.find('.pagelayer-ele-overlay').remove();
1177 2927
@@ -1186,9 +2936,9 @@
1186 2936 pagelayer_history_action_push({
1187 2937 'title' : pagelayer_shortcodes[sc]['name'],
1188 2938 'action' : 'Deleted',
1189 2939 'pl_id' : id,
1190 - 'html' : jEle,
2940 + 'html' : jEle[0].outerHTML,
1191 2941 'cEle' : cEle
1192 2942 });
1193 2943 }
1194 2944
@@ -1195,22 +2945,93 @@
1195 2945 wrap.remove();
1196 2946
1197 2947 pagelayer_empty_col(par);
1198 2948
1199 - if(pagelayer_active.el && pagelayer_active.el.id == id){
2949 + if( (pagelayer_active.el && pagelayer_active.el.id == id) ||
2950 + (pagelayer_active.el && pagelayer_active.el.id && jQuery('[pagelayer-id="'+pagelayer_active.el.id+'"]').length < 1)){
1200 2951 pagelayer.$$('.pagelayer-elpd-close').click();
1201 2952 }
1202 2953
1203 2954 }
1204 2955
1205 - pagelayer_isDirty = true;
2956 + // Do Pagelayer dirty
2957 + pagelayer_do_dirty(nearBy);
1206 2958 };
1207 2959
1208 2960 // Select an element
1209 -function pagelayer_copy_select(selector){
1210 - pagelayer.copy_selected = selector;
2961 +function pagelayer_copy_select(selector, copyEvent = false){
2962 +
2963 + var sEle = jQuery(selector);
2964 +
2965 + if(sEle.length < 1){
2966 + pagelayer_show_msg( pagelayer_l('invalid_copy_ele_msg'));
2967 + return;
2968 + }
2969 +
2970 + var tag = pagelayer_tag(sEle);
2971 +
2972 + if(
2973 + pagelayer_empty(tag) ||
2974 + pagelayer_empty(pagelayer_shortcodes[tag]) ||
2975 + !pagelayer_empty(pagelayer_shortcodes[tag]['not_visible'])
2976 + ){
2977 + pagelayer_show_msg( pagelayer_l('invalid_copy_ele_msg'));
2978 + return;
2979 + }
2980 +
2981 + var eHtml = sEle[0].outerHTML;
2982 +
2983 + pagelayer.copy_selected = eHtml;
2984 +
2985 + // To hide Cliboard warning while pasting
2986 + pagelayerClipboardReadable = true;
2987 +
2988 + if(copyEvent){
2989 + // set clipbord data
2990 + (copyEvent.originalEvent || copyEvent).clipboardData.setData('text/plain', eHtml);
2991 + pagelayer_show_msg(pagelayer_l('copied_msg'));
2992 +
2993 + return;
2994 + }
2995 +
2996 + // Copy element to clipboard
2997 + pagelayer_copy_ele_to_clipboard(eHtml);
2998 +
1211 2999 }
1212 3000
3001 +// Select an element
3002 +function pagelayer_copy_ele_to_clipboard(eHtml){
3003 +
3004 + var fallbackCopy = function(text){
3005 + const textarea = document.createElement("textarea");
3006 + textarea.value = text;
3007 + textarea.style.position = "fixed"; // avoid scrolling
3008 + textarea.style.opacity = 0;
3009 + document.body.appendChild(textarea);
3010 + textarea.focus();
3011 + textarea.select();
3012 + try {
3013 + document.execCommand('copy');
3014 + pagelayer_show_msg( pagelayer_l('copied_msg'));
3015 + }catch(err){
3016 + //console.error("Copy failed", err);
3017 + pagelayer_show_msg( pagelayer_l('Copy failed'));
3018 + }
3019 + document.body.removeChild(textarea);
3020 + }
3021 +
3022 + // Modern clipboard API
3023 + if(navigator.clipboard && window.isSecureContext) {
3024 + navigator.clipboard.writeText(eHtml).then(() => {
3025 + pagelayer_show_msg( pagelayer_l('copied_msg'));
3026 + }).catch(() => {
3027 + fallbackCopy(eHtml);
3028 + });
3029 + }else{
3030 + fallbackCopy(eHtml);
3031 + }
3032 +}
3033 +
1213 3034 function pagelayer_can_copy_to(to){
1214 3035 var jEle = jQuery(pagelayer.copy_selected);
1215 3036 var tEle = jQuery(to);
1216 3037
@@ -1216,8 +3037,14 @@
1216 3037
1217 3038 var eTag = pagelayer_tag(jEle);
1218 3039 var tTag = pagelayer_tag(tEle);
1219 3040 //console.log(eTag+' - '+tTag);
3041 +
3042 + // Invalid HTML copied
3043 + if(pagelayer_empty(eTag)){
3044 + return false;
3045 + }
3046 +
1220 3047 // Final to
1221 3048 var fTo;
1222 3049
1223 3050 // Selected element is a Row, can go only after a row
@@ -1243,10 +3070,26 @@
1243 3070
1244 3071 }
1245 3072
1246 3073 // Select an element
1247 -function pagelayer_paste_element(to){
3074 +function pagelayer_paste_element(to, syncClipboard = true){
1248 3075
3076 + // Wait for clipboard sync
3077 + // This is for context paste
3078 + if(syncClipboard){
3079 + if(pagelayerClipboardLoading){
3080 + setTimeout(function(){
3081 + pagelayer_paste_element(to);
3082 + }, 200);
3083 + return false;
3084 + }
3085 +
3086 + // There may be some problems reading the clipboard
3087 + if(pagelayerClipboardReadable !== true){
3088 + pagelayer_show_msg('If the paste is not done correctly then use Ctrl+V', 'warning');
3089 + }
3090 + }
3091 +
1249 3092 var fTo = pagelayer_can_copy_to(to);
1250 3093
1251 3094 // Is it a valid to
1252 3095 if(!fTo){
@@ -1252,35 +3095,63 @@
1252 3095 if(!fTo){
1253 3096 return false;
1254 3097 }
1255 3098
1256 - pagelayer_copy_element(pagelayer.copy_selected, fTo);
3099 + if(!pagelayer_empty(pagelayer.copy_selected)){
3100 + pagelayer_copy_element(pagelayer.copy_selected, fTo);
3101 + return true;
3102 + }
3103 +
3104 + pagelayer_show_msg(pagelayer_l('no_copied'));
3105 +
3106 + return false;
1257 3107 }
1258 3108
3109 +var pagelayerClipboardLoading = false;
3110 +var pagelayerClipboardReadable = true;
3111 +// If copy_selected is empty then copy data from localStorage
3112 +async function pagelayer_copy_from_clipboard(){
3113 +
3114 + if(pagelayerClipboardLoading){
3115 + return;
3116 + }
3117 +
3118 + if (navigator.clipboard && window.isSecureContext) {
3119 + try {
3120 +
3121 + pagelayerClipboardLoading = true;
3122 +
3123 + const text = await navigator.clipboard.readText();
3124 + var pEle = jQuery(text);
3125 +
3126 + if(pEle.length > 0 && !pagelayer_empty(pagelayer_tag(pEle)) ){
3127 + pagelayer.copy_selected = pEle;
3128 + }
3129 +
3130 + pagelayerClipboardLoading = false;
3131 + pagelayerClipboardReadable = true;
3132 +
3133 + } catch (err) {
3134 + pagelayerClipboardLoading = false;
3135 + pagelayerClipboardReadable = 'Clipboard readText failed';
3136 + //console.warn("Clipboard readText failed", err);
3137 + }
3138 + } else {
3139 + pagelayerClipboardReadable = 'Clipboard API not available or insecure context.';
3140 + // console.warn("Clipboard API not available or insecure context.");
3141 + }
3142 +}
3143 +
1259 3144 // Copy an element
1260 3145 // Note : insertAfter should always be an pagelayer-ele
1261 3146 function pagelayer_copy_element(selector, insertAfter){
1262 3147 var src = jQuery(selector);
1263 - var html = src[0].outerHTML;
1264 3148 var tag = pagelayer_tag(src);
1265 3149 insertAfter = insertAfter || src;
1266 3150 insertAfter = insertAfter.parent();
1267 3151
1268 - var jEle = jQuery(html);
1269 - jEle.removeAttr('pagelayer-id');
1270 - jEle.find('[pagelayer-id]').removeAttr('pagelayer-id');
1271 - jEle.find('[pagelayer-parent]').removeAttr('pagelayer-parent');// Remove the parent attribute as it will be reset during pagelayer_element_setup
1272 - jEle.find('style').remove();
1273 - jEle.find('.pagelayer-ele-overlay').remove();
3152 + var jEle = pagelayer_element_unsetup(src);
1274 3153
1275 - // Unwrap the wraps
1276 - jEle.find('.pagelayer-ele').each(function (){
1277 - var ele = jQuery(this);
1278 - if(ele.parent().is('.pagelayer-ele-wrap')){
1279 - ele.unwrap();
1280 - }
1281 - });
1282 -
1283 3154 // Give it an ID
1284 3155 var id = pagelayer_assign_id(jEle);
1285 3156
1286 3157 jQuery(insertAfter).after(jEle);
@@ -1286,8 +3157,12 @@
1286 3157 jQuery(insertAfter).after(jEle);
1287 3158
1288 3159 pagelayer_element_setup('[pagelayer-id='+id+'], [pagelayer-id='+id+'] .pagelayer-ele', true);
1289 3160
3161 + if(pagelayer_is_group(tag)){
3162 + pagelayer_sc_render(jEle);
3163 + }
3164 +
1290 3165 // Save this element in history action
1291 3166 if(pagelayer.history_action){
1292 3167 var cEle = pagelayer_near_by_ele(id, tag);
1293 3168 pagelayer_history_action_push({
@@ -1293,9 +3168,9 @@
1293 3168 pagelayer_history_action_push({
1294 3169 'title' : pagelayer_shortcodes[tag]['name'],
1295 3170 'action' : 'Copied',
1296 3171 'pl_id' : id,
1297 - 'html' : jEle,
3172 + 'html' : jEle[0].outerHTML,
1298 3173 'cEle' : cEle
1299 3174 });
1300 3175 }
1301 3176
@@ -1304,18 +3179,366 @@
1304 3179 var row = src.parent().closest('.pagelayer-row');
1305 3180 pagelayer_renumber_col(row);
1306 3181 }
1307 3182
1308 - pagelayer_isDirty = true;
3183 + pagelayer_do_dirty(jEle);
1309 3184
1310 3185 return id;
1311 3186 };
1312 3187
3188 +// Traversing up one step an element
3189 +function pagelayer_move_element_up(selector){
3190 +
3191 + var src = jQuery(selector);
3192 + var srcParent = src.parent();
3193 +
3194 + var srcParentPrev = srcParent.prev('.pagelayer-wrap-row, .pagelayer-wrap-inner-row, .pagelayer-wrap-ele');
3195 +
3196 + if(srcParentPrev.length<=0){
3197 + return;
3198 + }
3199 +
3200 + var srcTopValue = srcParent.offset().top;
3201 +
3202 + if(srcParentPrev.hasClass('pagelayer-wrap-ele')){
3203 +
3204 + var animUpCalc = srcTopValue-srcParentPrev.offset().top;
3205 +
3206 + srcParent.animate({top:-animUpCalc}, 200, function(){
3207 + srcParent.css('top', '');
3208 + srcParentPrev.css('top', '');
3209 + srcParentPrev.before(srcParent.detach());
3210 + });
3211 +
3212 + srcParentPrev.animate({top:(srcParent.height()+srcParentPrev.height())-animUpCalc}, 200, function(){
3213 + srcParentPrev.css('top', '');
3214 + });
3215 +
3216 + // Traverse window scroll with the element
3217 + jQuery('html, body').animate({scrollTop:('-='+(srcTopValue-(srcParentPrev.offset().top)))},200);
3218 + }else{
3219 + srcParentPrev.before(srcParent.detach());
3220 +
3221 + // Traverse window scroll with the element
3222 + jQuery('html, body').animate({scrollTop:('-='+(srcTopValue-(src.parent().offset().top)))},200);
3223 + }
3224 +
3225 + pagelayer_do_dirty(src);
3226 +}
3227 +
3228 +// Traversing down one step an element
3229 +function pagelayer_move_element_down(selector){
3230 +
3231 + var src = jQuery(selector);
3232 + var srcParent = src.parent();
3233 +
3234 + var srcParentNext = srcParent.next('.pagelayer-wrap-row, .pagelayer-wrap-inner-row, .pagelayer-wrap-ele');
3235 +
3236 + if(srcParentNext.length<=0){
3237 + return;
3238 + }
3239 +
3240 + var srcTopValue = srcParent.offset().top;
3241 +
3242 + if(srcParentNext.hasClass('pagelayer-wrap-ele')){
3243 +
3244 + var animDownCalc = srcParentNext.offset().top-srcTopValue;
3245 +
3246 + srcParent.animate({top:(animDownCalc-(srcParent.height()-srcParentNext.height()))}, 200, function(){
3247 + srcParent.css('top', '');
3248 + srcParentNext.css('top', '');
3249 + srcParentNext.after(srcParent.detach());
3250 + });
3251 +
3252 + srcParentNext.animate({top:-animDownCalc}, 200, function(){
3253 + srcParentNext.css('top', '');
3254 + });
3255 +
3256 + // Traverse window scroll with the element
3257 + jQuery('html, body').animate({scrollTop:('+='+(animDownCalc-(srcParent.height()-srcParentNext.height())))},200);
3258 + }else{
3259 + srcParentNext.after(srcParent.detach());
3260 +
3261 + // Traverse window scroll with the element
3262 + jQuery('html, body').animate({scrollTop:('+='+((src.parent().offset().top)-srcTopValue))},200);
3263 + }
3264 +
3265 + pagelayer_do_dirty(src);
3266 +}
3267 +
3268 +// Save sections as template
3269 +function pagelayer_ajax_save_template(data, ajax_call_back = ''){
3270 +
3271 + if(pagelayer_empty(data)){
3272 + return;
3273 + }
3274 +
3275 + //save global sections and widgets
3276 + jQuery.ajax({
3277 + type: "POST",
3278 + url: pagelayer_ajax_url+'&action=pagelayer_save_templ_content&postID='+pagelayer_postID,
3279 + data: {
3280 + pagelayer_nonce: pagelayer_ajax_nonce,
3281 + global_widgets : data
3282 + },
3283 + success: function(response, status, xhr){
3284 + //alert(data);
3285 + var obj = jQuery.parseJSON(response);
3286 + if(!pagelayer_empty(ajax_call_back) || typeof ajax_call_back == 'function'){
3287 + ajax_call_back(obj);
3288 + }
3289 + },
3290 + error: function(errorThrown){
3291 + console.log(errorThrown);
3292 + }
3293 + });
3294 +
3295 +}
3296 +
3297 +// Get global id of the element
3298 +function pagelayer_get_global_id(jEle){
3299 + return pagelayer_get_att(jEle, 'global_id');
3300 +}
3301 +
3302 +// Set element as a global widget
3303 +function pagelayer_set_ele_global(jEle, post_id){
3304 +
3305 + // Add attribute for global ID
3306 + jEle.attr('pagelayer-global-id', post_id);
3307 + pagelayer.history_action = false;
3308 + pagelayer_set_atts(jEle, 'global_id', post_id);
3309 + pagelayer.history_action = true;
3310 +
3311 + return jEle;
3312 +}
3313 +
3314 +// Save widgets as a global widget
3315 +function pagelayer_save_sections(sel, section = 'section'){
3316 +
3317 + var jEle = jQuery(sel);
3318 +
3319 + var pagelayer_ajax_func = {};
3320 + var label = 'Please enter the title';
3321 + var content = pagelayer_generate_sc(jEle, true);
3322 + var data = {};// create array for template data
3323 + data[0] = {};
3324 +
3325 + switch(section){
3326 +
3327 + case 'global_widget' :
3328 + var title = prompt(label, 'Global Widget');
3329 + if (title == null) return;
3330 +
3331 + // Save the widget data in global widget array
3332 + if(pagelayer_empty(pagelayer_global_widgets)){
3333 + pagelayer_global_widgets = {};
3334 + }
3335 +
3336 + break;
3337 +
3338 + case'global_section' :
3339 + var title = prompt(label, 'Global Section');
3340 + if (title == null) return;
3341 +
3342 + break;
3343 +
3344 + case 'section':
3345 + var title = prompt(label, 'Section');
3346 + if (title == null) return;
3347 +
3348 + break;
3349 +
3350 + }
3351 +
3352 + // Add Data
3353 + data[0]['title'] = title;
3354 + data[0]['post_type'] = 'pagelayer-template';
3355 + data[0]['type'] = section;
3356 + data[0]['content'] = content.replace(/pagelayer-id="(.*?)"/g, ""); // Need to remove pagelayer id,
3357 + data[0]['content'] = pagelayer_Base64.encode(data[0]['content']);
3358 +
3359 + // This function for ajax success call back of global widget
3360 + pagelayer_ajax_func['global_widget'] = function(obj){
3361 +
3362 + if(pagelayer_empty(obj['success'])){
3363 + return;
3364 + }
3365 +
3366 + for(var post_id in obj['success']){
3367 +
3368 + pagelayer_set_ele_global(jEle, post_id);
3369 +
3370 + // Add global
3371 + jData = {};
3372 + jData['post_id'] = post_id;
3373 + jData['title'] = title; // TODO : create modal to input title
3374 + jData['$'] = jEle;
3375 + jData['is_dirty'] = true;
3376 +
3377 + // Add the array in global widgets array
3378 + pagelayer_global_widgets[post_id] = jData;
3379 +
3380 + pagelayer.$$('.pagelayer-elpd-close').click();
3381 + pagelayer.$$('.pagelayer-widget-tab').click();
3382 + break;
3383 + }
3384 +
3385 + }
3386 +
3387 + // This function for ajax success call back of global sections
3388 + pagelayer_ajax_func['global_section'] = function(obj){
3389 + // TODO: For global Sections
3390 + //console.log(obj);
3391 + }
3392 +
3393 + // This function for ajax success call back of section s
3394 + pagelayer_ajax_func['section'] = function(obj){
3395 + //console.log(obj);
3396 + }
3397 +
3398 + pagelayer_ajax_save_template(data, pagelayer_ajax_func[section]);
3399 +
3400 +}
3401 +
3402 +// Genrate sc for global widgets
3403 +function pagelayer_generate_sc_global_widget(){
3404 +
3405 + var global_widgets = {};
3406 +
3407 + // Create shortcode for all the global widgets
3408 + for(var y in pagelayer_global_widgets){
3409 + var cWidget = pagelayer_global_widgets[y];
3410 +
3411 + // If is_dirty empty then continue the loop
3412 + if(pagelayer_empty(cWidget['is_dirty'])){
3413 + continue;
3414 + }
3415 +
3416 + global_widgets[y] = {};
3417 + global_widgets[y]['title'] = cWidget['title'];
3418 + global_widgets[y]['post_id'] = pagelayer_empty(cWidget['post_id']) ? 0 : cWidget['post_id'];
3419 + global_widgets[y]['post_type'] = 'pagelayer-template';
3420 + global_widgets[y]['type'] = 'global_widget';
3421 +
3422 + var content = pagelayer_generate_sc(jQuery(cWidget.$), true);
3423 + var tag = pagelayer_tag(jQuery(cWidget.$));
3424 +
3425 + // IF is group then need to remove pagelayer id,
3426 + if(!pagelayer_empty(tag) && pagelayer_is_group(tag)){
3427 + content = content.replace(/pagelayer-id="(.*?)"/g, "");
3428 + }
3429 +
3430 + global_widgets[y]['content'] = pagelayer_Base64.encode(content);
3431 + pagelayer_global_widgets[y]['is_dirty'] = false;
3432 + }
3433 +
3434 + return global_widgets;
3435 +}
3436 +
3437 +var pagelayer_set_global_timmer = {};
3438 +
3439 +// If you edit one Global widget it should be copied to other instances of the same global widget
3440 +function pagelayer_setup_global_widgets(id, jEle){
3441 +
3442 + if(pagelayer_empty(id) || pagelayer_empty(pagelayer_global_widgets[id])){
3443 + return;
3444 + }
3445 +
3446 + var elData = pagelayer_global_widgets[id];
3447 +
3448 + clearTimeout(pagelayer_set_global_timmer);
3449 + pagelayer_set_global_timmer = setTimeout(function(){
3450 + // Set attrs for all the global widgets
3451 + jQuery(pagelayer_editable+' [pagelayer-global-id='+ id +']').each(function(){
3452 +
3453 + var cEle = jQuery(this);
3454 + var cEleID = pagelayer_id(cEle);
3455 +
3456 + if( jEle.length > 0 && jEle.is(cEle)){
3457 + return true;
3458 + }
3459 +
3460 + pagelayer.history_action = false;
3461 + pagelayer.global_render = false;
3462 +
3463 + // Get HTML form global array
3464 + var html = pagelayer_element_unsetup(elData.$, cEleID);
3465 +
3466 + if(cEle.parent().is('.pagelayer-ele-wrap')){
3467 + cEle.parent().children('.pagelayer-ele-overlay').remove();
3468 + cEle.unwrap();
3469 + }
3470 +
3471 + cEle[0].outerHTML = html[0].outerHTML;
3472 +
3473 + pagelayer_element_setup('[pagelayer-id='+cEleID+'], [pagelayer-id='+cEleID+'] .pagelayer-ele');
3474 + pagelayer_sc_render(jQuery('[pagelayer-id="'+cEleID+'"]'));
3475 +
3476 + pagelayer.history_action = true;
3477 + pagelayer.global_render = true;
3478 + });
3479 +
3480 + }, 3000);
3481 +
3482 +}
3483 +
1313 3484 // Language key
1314 3485 function pagelayer_l(k){
3486 + if(k in pagelayer_lang){
3487 + return pagelayer_lang[k];
3488 + }
1315 3489 return k;
1316 3490 }
1317 3491
3492 +// Get props based on the tag
3493 +function pagelayer_get_props(jEle){
3494 + var props = pagelayer_shortcodes[pagelayer_tag(jEle)];
3495 + return props;
3496 +}
3497 +
3498 +// Get all props based on the tag but in a single structure
3499 +function pagelayer_make_props_ref(){
3500 +
3501 + // Loop through pagelayer_shortcodes
3502 + for(var tag in pagelayer_shortcodes){
3503 +
3504 + var all_props = pagelayer_shortcodes[tag];
3505 + pagelayer.props_ref[tag] = {};
3506 +
3507 + // Loop through all props
3508 + for(var i in pagelayer_tabs){
3509 +
3510 + var tab = pagelayer_tabs[i];
3511 +
3512 + for(var section in all_props[tab]){
3513 +
3514 + var props = section in pagelayer_shortcodes[tag] ? pagelayer_shortcodes[tag][section] : pagelayer_styles[section];
3515 +
3516 + // In case of widgets its possible !
3517 + if(pagelayer_empty(props)){
3518 + continue;
3519 + }
3520 +
3521 + for(var x in props){
3522 +
3523 + // Create an easy REFERENCE for access
3524 + pagelayer.props_ref[tag][x] = props[x];
3525 +
3526 + // Screen option REFERENCE is also needed for lookup
3527 + if('screen' in props[x]){
3528 + pagelayer.props_ref[tag][x+'_tablet'] = props[x];
3529 + pagelayer.props_ref[tag][x+'_mobile'] = props[x];
3530 + }
3531 +
3532 + }
3533 + }
3534 +
3535 + }
3536 +
3537 + }
3538 +
3539 +}
3540 +
1318 3541 // Set the given jELE as active
1319 3542 function pagelayer_set_active(jEle){
1320 3543
1321 3544 // Make all other element as inactive
@@ -1342,13 +3565,13 @@
1342 3565 function pagelayer_create_sc(sc){
1343 3566
1344 3567 var html;
1345 3568 var _sc = pagelayer_sc(sc);
1346 - var func = window['pagelayer_sc_'+sc];
3569 + var func = window['pagelayer_create_sc_'+sc];
1347 3570
1348 3571 // Generate the HTML
1349 3572 if(typeof func == 'function'){
1350 - html = window['pagelayer_sc_'+sc]();
3573 + html = window['pagelayer_create_sc_'+sc]();
1351 3574 }else{
1352 3575 html = '<div '+pagelayer_sc_atts('pagelayer-'+_sc)+'></div>';
1353 3576 }
1354 3577
@@ -1413,16 +3636,88 @@
1413 3636
1414 3637 return jEle.attr('pagelayer-tag');
1415 3638 }
1416 3639
3640 +function pagelayer_el_data_ref(jEle){
3641 + var id = pagelayer_id(jEle);
3642 +
3643 + if(!(id in pagelayer.el)){
3644 + pagelayer.el[id] = {};
3645 + }
3646 +
3647 + if(typeof pagelayer.el[id] !== 'object'){
3648 + pagelayer.el[id] = {};
3649 + }
3650 +
3651 + if(!('attr' in pagelayer.el[id])){
3652 + pagelayer.el[id]['attr'] = {};
3653 + }
3654 +
3655 + if(Array.isArray(pagelayer.el[id]['attr'])){
3656 + pagelayer.el[id]['attr'] = {};
3657 + }
3658 +
3659 + if(!('tmp' in pagelayer.el[id])){
3660 + pagelayer.el[id]['tmp'] = {};
3661 + }
3662 +
3663 + if(Array.isArray(pagelayer.el[id]['tmp'])){
3664 + pagelayer.el[id]['tmp'] = {};
3665 + }
3666 +
3667 + return pagelayer.el[id];
3668 +};
3669 +
3670 +// Gets the data node which can be position 0 or 1
3671 +function pagelayer_el_get_data_node(jEle){
3672 + var node = jEle[0].childNodes[0];
3673 + if(node && node.nodeType === 8){
3674 + return node;
3675 + }
3676 + node = jEle[0].childNodes[1];
3677 + if(node && node.nodeType === 8){
3678 + return node;
3679 + }
3680 + return false;
3681 +}
3682 +
3683 +// Get the data
3684 +function pagelayer_el_get_data(jEle){
3685 + var node = pagelayer_el_get_data_node(jEle);
3686 + if(node){
3687 + return JSON.parse(node.nodeValue);
3688 + }
3689 + return false;
3690 +};
3691 +
3692 +// Add the data back again
3693 +function pagelayer_el_dump_data(jEle){
3694 + var node = pagelayer_el_get_data_node(jEle);
3695 + var d = pagelayer_serializeAttributes(pagelayer_el_data_ref(jEle));
3696 +
3697 + if(node){
3698 + node.nodeValue = d;
3699 + }else{
3700 + jEle.prepend('<!-- '+d+' -->');
3701 + }
3702 +};
3703 +
1417 3704 // Gets a single attribute value
1418 3705 function pagelayer_get_att(jEle, att){
1419 - return jEle.attr('pagelayer-a-'+att);
3706 + var ref_data = pagelayer_el_data_ref(jEle);
3707 + if(att in ref_data['attr']){
3708 + return ref_data['attr'][att];
3709 + }
3710 + return;
1420 3711 };
1421 3712
1422 3713 // Gets a single attribute value
1423 3714 function pagelayer_get_tmp_att(jEle, att){
1424 - return jEle.attr('pagelayer-tmp-'+att);
3715 + var ref_data = pagelayer_el_data_ref(jEle);
3716 + if(att in ref_data['tmp']){
3717 + return ref_data['tmp'][att];
3718 + }
3719 + return;
1425 3720 };
1426 3721
1427 3722 // This function will just set atts and not do anything else
1428 3723 // Atts can be string or object. If its string, then val is needed
@@ -1451,8 +3746,9 @@
1451 3746 var all_props = pagelayer_shortcodes[tag];//console.log(tag);console.log(jEle);
1452 3747 var trigger_props = {};
1453 3748 var no_val = {};
1454 3749 var defaults = {};
3750 + var _props = {};
1455 3751
1456 3752 // Loop through all props
1457 3753 for(var i in pagelayer_tabs){
1458 3754
@@ -1467,15 +3763,39 @@
1467 3763 if('default' in props[x]){
1468 3764 defaults[x] = 1;
1469 3765 }
1470 3766
3767 + // Create an easy REFERENCE for access
3768 + _props[x] = props[x];
3769 +
3770 + // Screen option REFERENCE is also needed for lookup
3771 + if('screen' in _props[x]){
3772 + _props[x+'_tablet'] = props[x];
3773 + _props[x+'_mobile'] = props[x];
3774 + }
3775 +
1471 3776 // Dont set any val, but we set temp value
1472 3777 if('no_val' in props[x]){
1473 3778 no_val[x] = 1;
1474 3779 }
1475 3780
1476 - if('req' in props[x] || 'show' in props[x]){
3781 + if('req' in props[x] || 'show' in props[x]){
1477 3782 var show = 'req' in props[x] ? props[x]['req'] : props[x]['show'];
3783 +
3784 + // We have both req and show, so lets just combine the values and then show
3785 + // NOTE : We need to make an array and not just merge the 2 as they are references
3786 + if('req' in props[x] && 'show' in props[x]){
3787 +
3788 + // Add the req values
3789 + show = JSON.parse(JSON.stringify(props[x]['req']));
3790 +
3791 + // Now the show values need to be looped
3792 + for(var t in props[x]['show']){
3793 + show[t] = props[x]['show'][t];
3794 + }
3795 +
3796 + }
3797 +
1478 3798 for(var showParam in show){
1479 3799 var val = show[showParam];
1480 3800 var except = showParam.substr(0, 1) == '!' ? true : false;
1481 3801 showParam = except ? showParam.substr(1) : showParam;
@@ -1489,8 +3809,10 @@
1489 3809 }
1490 3810
1491 3811 }
1492 3812
3813 + var ref_data = pagelayer_el_data_ref(jEle);
3814 +
1493 3815 for(var x in atts){
1494 3816
1495 3817 // Are we to trigger change
1496 3818 if(x in trigger_props){
@@ -1498,8 +3820,13 @@
1498 3820 }
1499 3821
1500 3822 //console.log(x+'-'+atts[x]);
1501 3823
3824 + // Is this a pro feature and we are not pro ? Then we dont do anything and continue !
3825 + if(!pagelayer_empty(_props[x]) && 'pro' in _props[x] && pagelayer_empty(pagelayer_pro)){
3826 + continue;
3827 + }
3828 +
1502 3829 if(x in no_val){
1503 3830 pagelayer_set_tmp_atts(jEle, x, atts[x]);
1504 3831 continue;
1505 3832 }
@@ -1504,23 +3831,19 @@
1504 3831 continue;
1505 3832 }
1506 3833
1507 3834 // Record History
1508 - if(pagelayer.history_action){
1509 - var attr_label = '';
1510 - for(var section in all_props){
1511 - for(var props in all_props[section]){
1512 - if(props == x){
1513 - attr_label = all_props[section][props]['label'];
1514 - }
1515 - }
1516 -
3835 + if(pagelayer.history_action){
3836 + var old_val = pagelayer_get_att(jEle, x) || '';
3837 + var label = x;
3838 +
3839 + if(x in _props && 'label' in _props[x]){
3840 + label = _props[x]['label'];
1517 3841 }
1518 -
1519 - var old_val = pagelayer_get_att(jEle, x) || '';
3842 +
1520 3843 pagelayer_history_action_push({
1521 3844 'title' : all_props['name'],
1522 - 'subTitle' : attr_label,
3845 + 'subTitle' : label,
1523 3846 'action' : 'Edited',
1524 3847 'attrType' : 'a_attr',
1525 3848 'pl_id' : pagelayer_id(jEle),
1526 3849 'atts' : x,
@@ -1527,40 +3850,27 @@
1527 3850 'oldVal' : old_val,
1528 3851 'newVal' : atts[x]
1529 3852 });
1530 3853 }
1531 -
3854 +
1532 3855 // Remove the attribute if its BLANK and there is no default for it
1533 3856 // If there is a default, we set it to blank to keep record of the current val
1534 - if(atts[x].length < 1){
3857 + if(pagelayer_length(atts[x]) < 1){
1535 3858
1536 - // Dont remove the value as there is a default
3859 + // Remove values which are not defaults
1537 3860 if(!(x in defaults)){
1538 - jEle.removeAttr('pagelayer-a-'+x);
1539 - // Otherwise blank it
3861 + delete ref_data['attr'][x];
3862 + // Otherwise keep value set for avoiding resetting
1540 3863 }else{
1541 - jEle.attr('pagelayer-a-'+x, atts[x]);
3864 + ref_data['attr'][x] = atts[x];
1542 3865 }
1543 3866
1544 3867 // Remove the tmp atts anyway
1545 - var to_del = new Array();
1546 - var regexp = new RegExp('pagelayer\-tmp\-'+x, 'gi');
1547 -
1548 - jQuery.each(jEle[0].attributes, function(index, att){
1549 - if(!att) return;
1550 - if(att.name.match(regexp)){
1551 - to_del.push(att.name);
1552 - }
1553 - });
1554 -
1555 - //console.log(to_del);
1556 - for(var n in to_del){
1557 - jEle.removeAttr(to_del[n]);
1558 - }
3868 + pagelayer_clear_tmp_atts(jEle, x);
1559 3869
1560 3870 // Set the value
1561 3871 }else{
1562 - jEle.attr('pagelayer-a-'+x, atts[x]);
3872 + ref_data['attr'][x] = pagelayer_trim(atts[x]);
1563 3873 }
1564 3874
1565 3875 // Are you the active element
1566 3876 if(pagelayer_is_active(jEle)){
@@ -1570,14 +3880,17 @@
1570 3880 }
1571 3881
1572 3882 }
1573 3883
3884 + pagelayer_el_dump_data(jEle);
3885 +
1574 3886 // Trigger the change of the parameter and show the required properties
1575 3887 if(trigger_onchange){
1576 3888 pagelayer_elpd_show_rows();
1577 3889 }
1578 3890
1579 - pagelayer_isDirty = true;
3891 + pagelayer_do_dirty(jEle);
3892 +
1580 3893 };
1581 3894
1582 3895 // This function will just set atts and not do anything else
1583 3896 // Atts can be string or object. If its string, then val is needed
@@ -1592,10 +3905,12 @@
1592 3905 if(typeof atts != 'object'){
1593 3906 return false;
1594 3907 }
1595 3908
3909 + var ref_data = pagelayer_el_data_ref(jEle);
3910 +
1596 3911 for(var x in atts){
1597 -
3912 +
1598 3913 // Record history
1599 3914 if(pagelayer.history_action){
1600 3915
1601 3916 var old_val = pagelayer_get_tmp_att(jEle, x) || '';
@@ -1610,27 +3925,51 @@
1610 3925 'newVal' : atts[x]
1611 3926 });
1612 3927
1613 3928 }
1614 -
1615 - jEle.attr('pagelayer-tmp-'+x, atts[x]);
3929 +
3930 + ref_data['tmp'][x] = atts[x];
3931 +
1616 3932 }
1617 3933
3934 + pagelayer_el_dump_data(jEle);
3935 +
1618 3936 };
1619 3937
1620 -// Set the att and classes of an HTML which is not yet created
1621 -function pagelayer_sc_atts(classes, atts){
3938 +// This function removes the temporary attributes of an ele
3939 +function pagelayer_clear_tmp_atts(jEle, attr){
1622 3940
1623 - if(typeof atts != 'object'){
1624 - atts = new Object();
3941 + var to_del = new Array();
3942 + var regexp = new RegExp('^'+attr+'\-', 'gi');
3943 + var ref_data = pagelayer_el_data_ref(jEle);
3944 +
3945 + //console.log(to_del);
3946 + for(var n in ref_data['tmp']){
3947 + if(n.match(regexp)){
3948 + delete ref_data['tmp'][n];
3949 + }
1625 3950 }
3951 +}
3952 +
3953 +// This function removes the temporary attributes of an ele
3954 +function pagelayer_img_tmp_atts(jEle, attr){
1626 3955
1627 - var r = new Array();
3956 + var found = {};
3957 + var regexp = new RegExp('^'+attr+'\-', 'gi');
3958 + var ref_data = pagelayer_el_data_ref(jEle);
1628 3959
1629 - for(var x in atts){
1630 - r.push('pagelayer-a-'+x+'="'+atts[x]+'"');
3960 + for(var n in ref_data['tmp']){
3961 + if(n.match(regexp)){
3962 + found[n] = 1;
3963 + }
1631 3964 }
1632 3965
3966 + return found;
3967 +}
3968 +
3969 +// Set the att and classes of an HTML which is not yet created
3970 +function pagelayer_sc_atts(classes){
3971 + var r = new Array();
1633 3972 return 'class="'+classes+' pagelayer-ele" '+r.join(' ');
1634 3973 }
1635 3974
1636 3975 // Is the jEle the active element ?
@@ -1656,16 +3995,33 @@
1656 3995
1657 3996 // Seperator
1658 3997 seperator = seperator || ',';
1659 3998
3999 + var replaceCss = function(rule, value, toreplace){
4000 +
4001 + value = pagelayer_hex8_to_rgba(value);
4002 +
4003 + // If value has css var then we remove units
4004 + if(value.match(/var\(/)){
4005 + var toreplace = toreplace.replace(/[-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
4006 + toreplace = new RegExp( toreplace+'?[^\\s|;]+', 'ig');
4007 + }
4008 +
4009 + return rule.split(toreplace).join(value);
4010 + }
4011 +
1660 4012 // Replace the val
1661 - css = css.split('{{val}}').join(val);
4013 + css = replaceCss(css, val, '{{val}}');
1662 4014
1663 4015 // If there is an array
1664 4016 if(css.match(/val\[\d/)){
1665 - val = val.split(seperator);
4017 +
4018 + if(typeof val != 'object' || val === null){
4019 + val = String(val).split(seperator);
4020 + }
4021 +
1666 4022 for(var i in val){
1667 - css = css.split('{{val['+i+']}}').join(val[i]);
4023 + css = replaceCss(css, val[i], '{{val['+i+']}}');
1668 4024 }
1669 4025 }
1670 4026
1671 4027 //console.log('Final CSS '+css);
@@ -1673,9 +4029,40 @@
1673 4029 return css;
1674 4030
1675 4031 };
1676 4032
4033 +// Handle hexa to rgba and also remove alpha which is ff
4034 +function pagelayer_hex8_to_rgba(val){
4035 +
4036 + val = String(val);
4037 +
4038 + // If opacity is ff then discard ff
4039 + if(val.match(/^#([a-f0-9]{6})ff$/)){
4040 + return val.substr(0,7);
4041 + }
4042 +
4043 + // Lets handle the RGB+opacity
4044 + if(val.match(/^#([a-f0-9]{8})$/)){
4045 + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(val);
4046 + val = 'rgba('+parseInt(result[1], 16)+', '+parseInt(result[2], 16)+', '+parseInt(result[3], 16)+', '+(parseInt(result[4], 16)/255).toFixed(2)+')';
4047 + }
4048 +
4049 + return val;
4050 +
4051 +};
4052 +
1677 4053 // Replace the variables
4054 +function pagelayer_parse_el_vars(str, el){
4055 +
4056 + str = str.split('{{element}}').join(el.CSS.cssSel);
4057 + str = str.split('{{wrap}}').join(el.CSS.wrap);
4058 + str = str.split('{{ele_id}}').join(el.id);
4059 +
4060 + return str;
4061 +
4062 +}
4063 +
4064 +// Replace the variables
1678 4065 function pagelayer_parse_vars(str, el){
1679 4066
1680 4067 for(var x in el.tmp){
1681 4068 str = str.split('{{{'+x+'}}}').join(el.tmp[x]);
@@ -1695,11 +4082,11 @@
1695 4082 if(!pagelayer_is_active(jEle)){
1696 4083 //return false;
1697 4084 }
1698 4085
1699 - //console.log('Rendering');
4086 + //console.log('Rendering');
1700 4087
1701 - // Handle the CSS part
4088 + // Handle the CSS part
1702 4089 // Get the id, tag, atts, data, etc
1703 4090 var el = pagelayer_data(jEle, true);
1704 4091 var all_props = pagelayer_shortcodes[el.tag];
1705 4092 var elCSS = {
@@ -1708,13 +4095,18 @@
1708 4095 attr: [],
1709 4096 remove_attr: [],
1710 4097 css: [],
1711 4098 edit: [],
1712 - sel: '[pagelayer-id="'+el.id+'"]'
4099 + cssSel: '.p-'+el.id,
4100 + sel: '[pagelayer-id="'+el.id+'"]',
4101 + wrap: '[pagelayer-wrap-id="'+el.id+'"]'
1713 4102 };
1714 4103
1715 4104 // Create a reference
1716 4105 el.CSS = elCSS;
4106 +
4107 + // Make sure if we have the class selector
4108 + el.$.addClass('p-'+el.id);
1717 4109
1718 4110 //console.log(el.atts);
1719 4111
1720 4112 for(var i in pagelayer_tabs){
@@ -1728,10 +4120,10 @@
1728 4120
1729 4121 // pagelayer_data will return attributes even if they are BLANK e.g. attr=""
1730 4122 // Render doesnt consider BLANK values as values, and we are unsetting them now
1731 4123 // If in any situation you need to consider blank values, please handle in the JS / PHP function of the Shortcode
1732 - if(x in el.atts && el.atts[x].length < 1){
1733 - delete el.atts[x];
4124 + if(x in el.atts && pagelayer_length(el.atts[x]) < 1){
4125 + delete el.atts[x];
1734 4126 }
1735 4127
1736 4128 // Any editor ?
1737 4129 if('edit' in props[x]){
@@ -1737,8 +4129,59 @@
1737 4129 if('edit' in props[x]){
1738 4130 elCSS.edit.push({prop: x, sel: props[x]['edit']});
1739 4131 }
1740 4132
4133 + // Load permalink values
4134 + if(props[x]['type'] == 'link'){
4135 +
4136 + if('selector' in props[x] && typeof el.atts[x] == 'object'){
4137 + var tmp = {};
4138 +
4139 + // Link is required for check IF and IF-EXT in html
4140 + if(pagelayer_length(el.atts[x]['link']) < 1){
4141 + delete el.atts[x];
4142 + continue;
4143 + }
4144 +
4145 + if( 'target' in el.atts[x] && !pagelayer_empty(el.atts[x]['target']) ){
4146 + tmp = {'sel': props[x]['selector'], 'val': 'target="_blank"'};
4147 + elCSS['attr'].push(tmp);
4148 + }
4149 +
4150 + if( 'rel' in el.atts[x] && !pagelayer_empty(el.atts[x]['rel']) ){
4151 + tmp = {'sel': props[x]['selector'], 'val': 'rel="nofollow"'};
4152 + elCSS['attr'].push(tmp);
4153 + }
4154 +
4155 + if( 'attrs' in el.atts[x] && !pagelayer_empty(el.atts[x]['attrs']) ){
4156 +
4157 + var attrsVal = pagelayer_trim(el.atts[x]['attrs'].split(';'));
4158 +
4159 + attrsVal.forEach(function(item, index){
4160 +
4161 + var splitValue = item.split(/=(.*)/);
4162 + var attKey = pagelayer_trim(splitValue[0]);
4163 + var setAtt = '';
4164 +
4165 + // Validate the attrs name
4166 + if(attKey.length < 1 || pagelayer_empty(attKey.match(/^[a-z_]+[\w:.-]*$/i))){
4167 + return;
4168 + }
4169 +
4170 + if(splitValue.length < 2){
4171 + setAtt = attKey+'=""';
4172 + }else{
4173 + setAtt = attKey+'="'+splitValue[1]+'"';
4174 + }
4175 +
4176 + tmp = {'sel': props[x]['selector'], 'val': setAtt};
4177 + elCSS['attr'].push(tmp);
4178 +
4179 + });
4180 + }
4181 + }
4182 + }
4183 +
1741 4184 // Do we have a addClass ?
1742 4185 // We are checking before the element has a value so that we can add or remove the class
1743 4186 if('addClass' in props[x]){
1744 4187
@@ -1773,9 +4216,9 @@
1773 4216 }
1774 4217
1775 4218 }else{
1776 4219
1777 - var tmp = {'sel': tSel, 'val': addClasses[c]};
4220 + var tmp = {'sel': tSel, 'val': addClasses[c].replace('{{val}}', el.atts[x])};
1778 4221
1779 4222 // If the value is there
1780 4223 if(x in el.atts){
1781 4224 elCSS['classes'].push(tmp);
@@ -1828,8 +4271,9 @@
1828 4271 }
1829 4272
1830 4273 // Screen modes
1831 4274 var modes = {desktop: '', tablet: '_tablet', mobile: '_mobile'};
4275 + var desk_global = (props[x]['type'] == 'typography') ? pagelayer_is_global_typo(el.atts[x]) : '';
1832 4276
1833 4277 for(var m in modes){
1834 4278
1835 4279 var xm = x+modes[m];
@@ -1834,12 +4278,37 @@
1834 4278
1835 4279 var xm = x+modes[m];
1836 4280
1837 4281 // If the value is there
1838 - if(!(xm in el.atts)){
4282 + if(!(xm in el.atts) && pagelayer_empty(desk_global)){
1839 4283 continue;
1840 4284 }
1841 -
4285 +
4286 + var xm_val = el.atts[xm];
4287 +
4288 + // If is global color
4289 + if(props[x]['type'] == 'color'){
4290 + xm_val = pagelayer_parse_color(el.atts[xm]);
4291 + }
4292 +
4293 + // If is global font
4294 + if(props[x]['type'] == 'typography'){
4295 + xm_val = pagelayer_parse_typo(xm_val, false, desk_global, m);
4296 + }
4297 +
4298 + // If there is global gradient color
4299 + if(props[x]['type'] == 'gradient'){
4300 +
4301 + if(pagelayer_is_string(xm_val)){
4302 + xm_val = xm_val.split(',');
4303 + }
4304 +
4305 + for(key in xm_val){
4306 + xm_val[key] = pagelayer_parse_color(xm_val[key]);
4307 + }
4308 +
4309 + }
4310 +
1842 4311 for(var c in css){
1843 4312
1844 4313 // The selector
1845 4314 var tSel = jQuery.isNumeric(c) ? '{{element}}' : c;
@@ -1844,20 +4313,20 @@
1844 4313 // The selector
1845 4314 var tSel = jQuery.isNumeric(c) ? '{{element}}' : c;
1846 4315 var tmp = {
1847 4316 sel: tSel,
1848 - val: pagelayer_css_render(css[c], el.atts[xm], (props[x].sep || ',')),
4317 + val: pagelayer_css_render(css[c], xm_val, (props[x].sep || ',')),
1849 4318 };
1850 4319
1851 4320 // Is this a tablet
1852 4321 if(m == 'tablet'){
1853 - tmp.sel = '@media (max-width: 768px) and (min-width: 361px){'+tmp.sel;
4322 + tmp.sel = '@media (max-width: '+ pagelayer_settings['tablet_breakpoint'] +'px) and (min-width: '+ (pagelayer_settings['mobile_breakpoint'] +1) +'px){'+tmp.sel;
1854 4323 tmp.val = tmp.val+'}';
1855 4324 }
1856 4325
1857 4326 // Is this a mobile mode ?
1858 4327 if(m == 'mobile'){
1859 - tmp.sel = '@media (max-width: 360px){'+tmp.sel;
4328 + tmp.sel = '@media (max-width: '+ pagelayer_settings['mobile_breakpoint'] +'px){'+tmp.sel;
1860 4329 tmp.val = tmp.val+'}';
1861 4330 }
1862 4331
1863 4332 // Push to store
@@ -1875,9 +4344,16 @@
1875 4344 }
1876 4345
1877 4346 // If there is an HTML, then process it
1878 4347 if('html' in pagelayer_shortcodes[el.tag]){
4348 +
4349 + // Is there a function to render ?
4350 + var fn = window['pagelayer_render_'+jEle.attr('pagelayer-tag')];
1879 4351
4352 + if(typeof fn == 'function'){
4353 + fn(el);
4354 + }
4355 +
1880 4356 el.iHTML = jQuery('<div>'+pagelayer_shortcodes[el.tag]['html']+'</div>');
1881 4357
1882 4358 // Lets process the 'if-ext'
1883 4359 el.iHTML.find('[if-ext]').each(function (){
@@ -1905,16 +4381,9 @@
1905 4381 $j.remove();
1906 4382 }
1907 4383
1908 4384 });
1909 -
1910 - // Is there a function to render ?
1911 - var fn = window['pagelayer_render_'+jEle.attr('pagelayer-tag')];
1912 4385
1913 - if(typeof fn == 'function'){
1914 - fn(el);
1915 - }
1916 -
1917 4386 //console.log(el.atts);
1918 4387
1919 4388 // Parse the variables
1920 4389 var new_html = pagelayer_parse_vars(el.iHTML.html(), el);
@@ -1971,9 +4440,9 @@
1971 4440 for(var c in elCSS.edit){
1972 4441 var prop = elCSS.edit[c]['prop'];
1973 4442 var tSel = elCSS.edit[c]['sel'];
1974 4443 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
1975 - node.attr('pagelayer-editable', prop);
4444 + node.attr({'pagelayer-editable': prop, 'contenteditable' : 'true'});
1976 4445 }
1977 4446
1978 4447 }
1979 4448
@@ -1985,9 +4454,9 @@
1985 4454 if(elCSS.classes.length > 0){
1986 4455 //console.log(elCSS.classes);
1987 4456
1988 4457 for(var c in elCSS.classes){
1989 - var tSel = elCSS.classes[c]['sel'];
4458 + var tSel = elCSS.classes[c]['sel'].replace('{{element}}', '');
1990 4459 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
1991 4460 if(!node.hasClass(elCSS.classes[c]['val'])){
1992 4461 node.addClass(elCSS.classes[c]['val']);
1993 4462 }
@@ -1998,9 +4467,9 @@
1998 4467 if(elCSS.remove_classes.length > 0){
1999 4468 //console.log(elCSS.remove_classes);
2000 4469
2001 4470 for(var c in elCSS.remove_classes){
2002 - var tSel = elCSS.remove_classes[c]['sel'];
4471 + var tSel = elCSS.remove_classes[c]['sel'].replace('{{element}}', '');
2003 4472 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2004 4473 if(node.hasClass(elCSS.remove_classes[c]['val'])){
2005 4474 node.removeClass(elCSS.remove_classes[c]['val']);
2006 4475 }
@@ -2017,14 +4486,14 @@
2017 4486
2018 4487 for(var c in elCSS.attr){
2019 4488 var tSel = elCSS.attr[c]['sel'].replace('{{element}}', '');
2020 4489 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2021 - var att = elCSS.attr[c]['val'].split('=');
4490 + var att = elCSS.attr[c]['val'].split(/=(.*)/);
2022 4491 att[1] = pagelayer_parse_vars(att[1], el);
2023 4492 att[1] = pagelayer_trim(att[1], '"');
2024 4493
2025 4494 // Is it the same val ?
2026 - if(!node.attr(att[0]) != att[1]){
4495 + if(!node.attr(att[0]) !== att[1]){
2027 4496 node.attr(att[0], att[1]);
2028 4497 }
2029 4498 }
2030 4499 }
@@ -2062,15 +4531,28 @@
2062 4531 var rules = [];
2063 4532
2064 4533 // Loop
2065 4534 for(var c in elCSS.css){
2066 - var tSel = elCSS.css[c]['sel'].replace('{{element}}', elCSS.sel);
2067 - var rule = pagelayer_parse_vars(elCSS.css[c]['val'], el);
2068 - rules.push(tSel+'{'+rule+'}');
4535 + var tSel = pagelayer_parse_el_vars(elCSS.css[c]['sel'], el);
4536 + var rule = elCSS.css[c]['val'];
4537 + if(tSel.length > 0){
4538 + rules.push(tSel+'{'+rule+'}');
4539 + }else{
4540 + rules.push(pagelayer_parse_el_vars(rule, el));
4541 + }
2069 4542 }
4543 +
4544 + // CSS Selector overide
4545 + if(!pagelayer_empty(all_props['overide_css_selector'])){
4546 + for(var r in rules){
4547 + var overide_css_selector = pagelayer_parse_el_vars(all_props['overide_css_selector'], el);
4548 + rules[r] = rules[r].split(el.CSS.cssSel).join(overide_css_selector);
4549 + rules[r] = rules[r].split(el.CSS.wrap).join(overide_css_selector);
4550 + }
4551 + }
2070 4552
2071 4553 // Set the style
2072 - style.html(rules.join("\n"));
4554 + style.html(pagelayer_parse_vars(rules.join("\n"), el));
2073 4555 //console.log(style);
2074 4556 }else{
2075 4557 style.remove();
2076 4558 }
@@ -2083,14 +4565,150 @@
2083 4565 }
2084 4566
2085 4567 // If the element have any parent
2086 4568 var par = pagelayer_get_parent(jEle);
4569 + var eleId = el.id;
4570 +
2087 4571 if(par){
4572 + eleId = par;
2088 4573 pagelayer_sc_render(pagelayer_ele_by_id(par));
2089 4574 }
2090 4575
4576 + // Render End trigger
4577 + pagelayer_trigger_action('pagelayer_sc_render_end', [el]);
4578 +
4579 + var gEle = pagelayer_ele_by_id(eleId);
4580 + var gId = pagelayer_get_global_id(gEle);
4581 +
4582 + pagelayer_el_dump_data(jEle);
4583 +
4584 + // If global id exist then update the global array and restup the all global element
4585 + if(!pagelayer_empty(gId) && !pagelayer_empty(pagelayer.global_render)){
4586 + if(!pagelayer_empty(pagelayer_global_widgets[gId])){
4587 + pagelayer_global_widgets[gId].$ = gEle[0].outerHTML;
4588 + pagelayer_global_widgets[gId]['is_dirty'] = true;
4589 + pagelayer_setup_global_widgets(gId, pagelayer_ele_by_id(eleId), true);
4590 + }else{
4591 + pagelayer_set_atts(gEle, 'global_id', '');
4592 + }
4593 + };
4594 +
2091 4595 };
2092 4596
4597 +// Is the given global color
4598 +function pagelayer_is_global_color(color){
4599 +
4600 + var color_key = color.substr(0, 1) == '$' ? color.substr(1) : '';
4601 +
4602 + // If global color not exist
4603 + if(!pagelayer_empty(color_key)){
4604 +
4605 + if(!(color_key in pagelayer_global_colors)){
4606 + color_key = 'primary';
4607 + }
4608 +
4609 + return color_key;
4610 + }
4611 +
4612 + return false;
4613 +
4614 +}
4615 +
4616 +// Is the given global color
4617 +function pagelayer_is_global_typo(value){
4618 +
4619 + var typo_key = '';
4620 +
4621 + // Backward compatibility
4622 + if(pagelayer_is_string(value) && value.substr(0, 1) == '$'){
4623 + typo_key = value.substr(1);
4624 + }
4625 +
4626 + if(typeof value == 'object' && 'global-font' in value){
4627 + typo_key = value['global-font'];
4628 + }
4629 +
4630 + // If global color not exist
4631 + if(!pagelayer_empty(typo_key) && !(typo_key in pagelayer_global_fonts)){
4632 + typo_key = 'primary';
4633 + }
4634 +
4635 + return typo_key;
4636 +
4637 +}
4638 +
4639 +// Parse typography and handle Backward compatibility
4640 +function pagelayer_parse_typo(value, noglobal, desk_global, mode){
4641 +
4642 + noglobal = noglobal || false;
4643 + mode = mode || 'desktop';
4644 + desk_global = desk_global || '';
4645 +
4646 + if(pagelayer_empty(value)){
4647 + value = {};
4648 + }
4649 +
4650 + // Backward compatibility for comma seperated val
4651 + if(pagelayer_is_string(value) && value.substr(0, 1) != '$'){
4652 + return value.split(',');
4653 + }
4654 +
4655 + var val = ['','','','','','','','','','',''];
4656 + var typos = ['font-family', 'font-size', 'font-style', 'font-weight', 'font-variant', 'text-decoration-line', 'text-decoration-style', 'line-height', 'text-transform', 'letter-spacing', 'word-spacing'];
4657 +
4658 + var global_typo = pagelayer_is_global_typo(value);
4659 + var _desk_global = false;
4660 +
4661 + if(pagelayer_empty(global_typo)){
4662 + global_typo = desk_global;
4663 + _desk_global = true;
4664 + }
4665 +
4666 + // Apply global typo
4667 + for(var typo in typos){
4668 +
4669 + var typoKey = typos[typo];
4670 +
4671 + // Backspace compatibility for normal array
4672 + if(typeof value == 'object' && !pagelayer_empty(value[typo])){
4673 + val[typo] = value[typo];
4674 + }
4675 +
4676 + if(!pagelayer_empty(value[typoKey])){
4677 + val[typo] = value[typoKey];
4678 + }
4679 +
4680 + if(pagelayer_empty(global_typo) || !pagelayer_empty(val[typo]) || noglobal){
4681 + continue;
4682 + }
4683 +
4684 + var globalVal = pagelayer_global_fonts[global_typo]['value'];
4685 +
4686 + if( !(typoKey in globalVal) || pagelayer_empty(globalVal[typoKey]) || (typeof globalVal[typoKey] == 'object' && pagelayer_empty(globalVal[typoKey][mode])) || (typeof globalVal[typoKey] != 'object' && !pagelayer_empty(_desk_global) && mode != 'desktop') ){
4687 + continue;
4688 + }
4689 +
4690 + val[typo] = 'var(--pagelayer-font-'+global_typo+'-'+typoKey+')';
4691 + }
4692 +
4693 + return val;
4694 +}
4695 +
4696 +// Parse color for global color
4697 +function pagelayer_parse_color(value, glob_var = true){
4698 +
4699 + var is_global = pagelayer_is_global_color(value);
4700 + if(pagelayer_empty(is_global)){
4701 + return value;
4702 + }
4703 +
4704 + if(pagelayer_empty(glob_var)){
4705 + return pagelayer_global_colors[is_global]['value'];
4706 + }
4707 +
4708 + return 'var(--pagelayer-color-'+is_global+')';
4709 +}
4710 +
2093 4711 // Is the given tag a group
2094 4712 function pagelayer_is_group(tag){
2095 4713
2096 4714 if('has_group' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['has_group'])){
@@ -2100,37 +4718,308 @@
2100 4718 return false;
2101 4719
2102 4720 }
2103 4721
4722 +// Do action / event
4723 +function pagelayer_trigger_action(act, param = []){
4724 + jQuery(document).trigger(act, param);
4725 +}
4726 +
4727 +// Perform a function on an action / event
4728 +function pagelayer_add_action(act, func){
4729 + jQuery(document).on(act, func);
4730 +}
4731 +
4732 +// Create array of the contact from template params
4733 +function pagelayer_get_contact_templates(){
4734 +
4735 + var contacts = jQuery(pagelayer_editable+' [pagelayer-tag=pl_contact]');
4736 + var contacts_props = {};
4737 + if(contacts.length > 0){
4738 +
4739 + contacts.each(function(){
4740 +
4741 + var tmp = pagelayer_data(jQuery(this));
4742 + var con_allowed = ['to_email', 'from_email', 'cont_subject', 'cont_header', 'cont_body', 'cont_use_html'];
4743 +
4744 + if(pagelayer_empty(tmp.atts['contact_custom_templ'])) return true;
4745 +
4746 + // Define blank array
4747 + contacts_props[tmp.id] = {};
4748 +
4749 + for(var x in con_allowed){
4750 + var key = con_allowed[x];
4751 + if(!pagelayer_empty(tmp.atts[key])){
4752 + contacts_props[tmp.id][key] = tmp.atts[key];
4753 + }
4754 + }
4755 +
4756 + });
4757 + }
4758 +
4759 + return contacts_props;
4760 +}
4761 +
4762 +// Save data or meta of the post
4763 +function pagelayer_update_post_data(){
4764 +
4765 + var tag = 'pl_post_props';
4766 + var jEle = jQuery(pagelayer_editable+' [pagelayer-tag="'+tag+'"]');
4767 +
4768 + if(jEle.length < 1){
4769 + return;
4770 + }
4771 +
4772 + var tmp = pagelayer_data(jEle, true);
4773 + var all_props = pagelayer_shortcodes[tag];
4774 +
4775 + // Loop through all props
4776 + for(var i in pagelayer_tabs){
4777 +
4778 + var tab = pagelayer_tabs[i];
4779 +
4780 + for(var section in all_props[tab]){
4781 +
4782 + var props = section in pagelayer_shortcodes[tag] ? pagelayer_shortcodes[tag][section] : pagelayer_styles[section];
4783 +
4784 + for(var x in props){
4785 + //Set pagelayer POST data to send with save ajax
4786 + if(x in tmp['atts']){
4787 + pagelayer_ajax_post_data[x] = tmp['atts'][x];
4788 + }else if(x in pagelayer_ajax_post_data){
4789 + delete pagelayer_ajax_post_data[x];
4790 + }
4791 + }
4792 + }
4793 + }
4794 +}
4795 +
4796 +// Get the nav menu updated data
4797 +function pagelayer_get_nav_items(jEle, _content){
4798 +
4799 + _content = _content || false;
4800 +
4801 + var pagelayer_nav_items = {};
4802 +
4803 + jEle.find('[pagelayer-tag="pl_nav_menu_item"]').each(function(){
4804 + var cEle = jQuery(this),
4805 + postID = pagelayer_get_att(cEle, 'ID');
4806 +
4807 + if(!(postID in pagelayer_menus_items_ref)){
4808 + return;
4809 + }
4810 +
4811 + var ref_data = pagelayer_menus_items_ref[postID];
4812 +
4813 + if(!('pagelayer_content' in ref_data) && pagelayer_empty(ref_data['pagelayer_content'])){
4814 + ref_data['pagelayer_content'] = cEle;
4815 + }
4816 +
4817 + if(!('is_dirty' in ref_data) || pagelayer_empty(ref_data['is_dirty'])){
4818 + return;
4819 + }
4820 +
4821 + var content = '',
4822 + tmp = {};
4823 + tmp = Object.assign(tmp, ref_data);
4824 + pagelayer_nav_items[postID] = {};
4825 +
4826 + // Update Mega menu content
4827 + if(!pagelayer_empty(_content)){
4828 + var navItem = jQuery(ref_data['pagelayer_content'])[0].outerHTML;
4829 + var _navItem = jQuery(navItem);
4830 +
4831 + // If is not mega menu
4832 + if('menu_type' in tmp && tmp['menu_type'] != 'mega'){
4833 + _navItem.find('.pagelayer-menu-item-holder').empty();
4834 + }
4835 +
4836 + content = pagelayer_generate_sc(_navItem, true);
4837 + content = pagelayer_Base64.encode(content);
4838 +
4839 + // Send data to save
4840 + var allowed_post = ['title'];
4841 +
4842 + for(var key in allowed_post){
4843 +
4844 + var post_prop = allowed_post[key];
4845 +
4846 + if(!(post_prop in tmp)){
4847 + continue;
4848 + }
4849 +
4850 + pagelayer_nav_items[postID][post_prop] = tmp[post_prop]
4851 + }
4852 +
4853 + }else{
4854 + pagelayer_nav_items[postID] = tmp;
4855 + }
4856 +
4857 + // Delete the html content
4858 + delete tmp['pagelayer_content'];
4859 +
4860 + pagelayer_nav_items[postID]['_pagelayer_content'] = content;
4861 +
4862 + });
4863 +
4864 + return pagelayer_nav_items;
4865 +}
4866 +
4867 +// Save data or meta of the nav post
4868 +function pagelayer_update_nav_menu_data(){
4869 +
4870 + var tag = 'pl_wp_menu';
4871 +
4872 + pagelayer_ajax_post_data['pagelayer_nav_items'] = {};
4873 +
4874 + jQuery(pagelayer_editable+' [pagelayer-tag="'+tag+'"]').each(function(){
4875 +
4876 + var jEle = jQuery(this);
4877 + var menu_ID = pagelayer_get_att(jEle, 'nav_list');
4878 +
4879 + if(!pagelayer_empty(pagelayer_ajax_post_data['pagelayer_nav_items'][menu_ID])){
4880 + return;
4881 + }
4882 +
4883 + // Get the Current menu items
4884 + var items = pagelayer_get_nav_items(jEle, true);
4885 +
4886 + if(pagelayer_empty(items)){
4887 + return;
4888 + }
4889 +
4890 + pagelayer_ajax_post_data['pagelayer_nav_items'][menu_ID] = items;
4891 +
4892 + });
4893 +}
4894 +
4895 +// Save the customizer settings
4896 +function pagelayer_update_customizer_settings(){
4897 +
4898 + var tag = 'pl_customizer';
4899 + var jEle = jQuery(pagelayer_editable+' [pagelayer-tag="'+tag+'"]');
4900 +
4901 + if(jEle.length < 1){
4902 + return;
4903 + }
4904 +
4905 + var tmp = pagelayer_data(jEle, true);
4906 + pagelayer_ajax_post_data['pagelayer_customizer_options'] = JSON.stringify(tmp['atts']);
4907 +
4908 +}
4909 +
2104 4910 // Save the post
2105 4911 function pagelayer_save(){
2106 4912
4913 + // hiding and showing loading animation
4914 + pagelayer.$$('.pagelayer-update-text').hide();
4915 + pagelayer.$$('.pagelayer-update-loader').show();
4916 +
4917 + pagelayer_trigger_action('pagelayer_save');
4918 +
4919 + var pagelayerajaxurl = pagelayer_ajax_url+'&action=pagelayer_save_content&postID='+pagelayer_postID;
2107 4920 var post = pagelayer_generate_sc(pagelayer_editable);//alert(post);return;
2108 - var pagelayerajaxurl = pagelayer_ajax_url+'&action=pagelayer_save_content&postID='+pagelayer_postID;
2109 - jQuery.ajax({
2110 - type: "POST",
2111 - url: pagelayerajaxurl,
2112 - data: {
2113 - pagelayer_update_content : post,
2114 - pagelayer_nonce: pagelayer_ajax_nonce
2115 - },
2116 - success: function(response, status, xhr){
2117 - //alert(data);
2118 - var obj = jQuery.parseJSON(response);
2119 - //alert(obj);
2120 - if(obj['error']){
2121 - alert(obj['error']);
2122 - }else{
2123 - pagelayer_isDirty = false;
2124 - alert(obj['success']);
2125 - pagelayer_get_revision();
4921 +
4922 + // Update data or meta of the post
4923 + pagelayer_update_post_data();
4924 +
4925 + // Update Customizer Settings
4926 + pagelayer_update_customizer_settings();
4927 +
4928 + // Update nav menu
4929 + pagelayer_update_nav_menu_data();
4930 +
4931 + if(pagelayer_empty(pagelayer.post_status) && !pagelayer_empty(pagelayer_ajax_post_data['post_status'])){
4932 + pagelayer.post_status = pagelayer_ajax_post_data['post_status'];
4933 + }
4934 +
4935 + // Do we have contact templates ?
4936 + var contacts_props = pagelayer_get_contact_templates();
4937 +
4938 + // Do we have any global widget to save ?
4939 + var global_data = {};
4940 +
4941 + if(!pagelayer_empty(pagelayer_global_widgets)){
4942 + global_data = pagelayer_generate_sc_global_widget();
4943 + }
4944 +
4945 + var cancel = function(){
4946 + pagelayer.$$('.pagelayer-update-text').show();
4947 + pagelayer.$$('.pagelayer-update-loader').hide();
4948 + }
4949 +
4950 + var save = function(){
4951 + var post_data = {
4952 + pagelayer_update_content : pagelayer_Base64.encode(post),
4953 + pagelayer_nonce: pagelayer_ajax_nonce,
4954 + global_widgets: global_data,
4955 + contacts: contacts_props,
4956 + post_status: pagelayer.post_status,
4957 + copyright: pagelayer_copyright
4958 + }
4959 +
4960 + if(!pagelayer_empty(pagelayer.cmode)){
4961 + post_data.cmode = pagelayer.cmode;
4962 + }
4963 +
4964 + post_data = Object.assign(pagelayer_ajax_post_data, post_data);
4965 +
4966 + jQuery.ajax({
4967 + type: "POST",
4968 + url: pagelayerajaxurl,
4969 + data: post_data,
4970 + success: function(response, status, xhr){
4971 + //alert(data);
4972 + var obj = jQuery.parseJSON(response);
4973 + //alert(obj);
4974 +
4975 + if('comment_alerts' in obj){
4976 + console.log("Alerts:", obj['comment_alerts']);
4977 + }
4978 +
4979 + if(obj['error']){
4980 + pagelayer_show_msg(obj['error'], 'error', 10000);
4981 + if('comment_errors' in obj){
4982 + console.log("Errors:", obj['comment_errors']);
4983 + }
4984 + }else{
4985 + pagelayer_show_msg(obj['success'], 'success', 10000);
4986 + pagelayer_get_revision();
4987 +
4988 + // Update the post status in the post_props, but first find if its actually there !
4989 + var jEle = jQuery(pagelayer_editable).find("[pagelayer-tag=pl_post_props]");
4990 + if(jEle.length > 0){
4991 + var id = pagelayer_id(jEle);
4992 + pagelayer_set_atts(jEle, 'post_status', obj['post_status']);
4993 + pagelayer_trigger_action('pagelayer_save_success', obj['post_status']);
4994 + }
4995 +
4996 + pagelayer_do_undirty();
4997 + }
4998 + },
4999 + error: function(jqXHR, textStatus, errorThrown){
5000 + console.log(errorThrown);
5001 + pagelayer_show_msg('An error occured while saving ! Status : '+textStatus+' and Error : '+errorThrown, 'error', 10000);
5002 + },
5003 + complete: function(xhr,status){
5004 + pagelayer.$$('.pagelayer-update-text').show();
5005 + pagelayer.$$('.pagelayer-update-loader').hide();
5006 +
5007 + if(!pagelayer_empty(pagelayer.post_status)){
5008 + pagelayer.$$('.pagelayer-props-modal .pagelayer-meta-iframe').attr('src', pagelayer_post_props );
5009 + pagelayer.post_status = '';
5010 + }
2126 5011 }
2127 - },
2128 - error: function(errorThrown){
2129 - console.log(errorThrown);
2130 - }
2131 - });
5012 + });
5013 + }
2132 5014
5015 + // If the content is empty
5016 + if(pagelayer_empty(post)){
5017 + pagelayer_confirmation_box(pagelayer_l('empty_post_content'), save, cancel);
5018 + return;
5019 + }
5020 +
5021 + save();
2133 5022 };
2134 5023
2135 5024 //Close the Editor
2136 5025 function pagelayer_close(){
@@ -2143,18 +5032,30 @@
2143 5032 }else{
2144 5033 window.top.location.href = pagelayer_returnURL;
2145 5034 }
2146 5035 };
5036 +
5037 +function pagelayer_htmlEntities(str) {
5038 + return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
5039 +}
2147 5040
2148 -// Generate Shortcode Post to save
2149 -function pagelayer_generate_sc(selector){
5041 +function pagelayer_serializeAttributes(attributes) {
5042 + return JSON.stringify(attributes) // Don't break HTML comments.
5043 + .replace(/--/g, "\\u002d\\u002d") // Don't break non-standard-compliant tools.
5044 + .replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026") // Bypass server stripslashes behavior which would unescape stringify's
5045 + // escaping of quotation mark.
5046 + // See: https://developer.wordpress.org/reference/functions/wp_kses_stripslashes/
5047 + .replace(/\\"/g, "\\u0022");
5048 +}
5049 +
5050 +// Generate blocks Post to save
5051 +function pagelayer_generate_sc(selector, selfEle){
2150 5052
5053 + selfEle = selfEle || false;
2151 5054 var txt = '';
2152 5055
2153 - jQuery(selector).children(".pagelayer-ele-wrap").each(function(){
5056 + var generate_sc_single = function(jEle){
2154 5057
2155 - var jEle = jQuery(this).children('.pagelayer-ele');
2156 -
2157 5058 // The ID
2158 5059 var id = jEle.attr('pagelayer-id');
2159 5060
2160 5061 // If there is an Add element wrapper
@@ -2164,14 +5065,26 @@
2164 5065
2165 5066 // Find the type of tag
2166 5067 var tag = jEle.attr('pagelayer-tag');
2167 5068 var final_tag = tag;
2168 - var closestEle = jQuery(this).closest('.pagelayer-col-holder');
5069 + var closestEle = jEle.closest('.pagelayer-col-holder');
2169 5070
5071 + // Skip to create shortcode to prevent save, allowed by tag
5072 + if('skip_save' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['skip_save'])){
5073 + return;
5074 + }
5075 +
2170 5076 // Define inner row | Note : Commented as we now have a new widget of type inner_row
2171 5077 /*if(tag == 'pl_row' && closestEle.length > 0 && closestEle.closest(pagelayer_editable).length > 0){
2172 5078 final_tag = 'pl_inner_row';
2173 5079 }*/
5080 +
5081 + if(pagelayer_empty(tag)){
5082 + var err = 'Found an error in the content as the TAG was missing. The console will have more details.';
5083 + pagelayer_show_msg(err, 'error');
5084 + console.log(err);
5085 + console.log(jEle);
5086 + }
2174 5087
2175 5088 // Define inner column
2176 5089 if(tag == 'pl_col' && closestEle.length > 0 && closestEle.closest(pagelayer_editable).length > 0){
2177 5090 final_tag = 'pl_inner_col';
@@ -2183,44 +5096,33 @@
2183 5096 if('innerHTML' in pagelayer_shortcodes[tag]){
2184 5097 inner = pagelayer_shortcodes[tag]['innerHTML'];
2185 5098 }
2186 5099
5100 + // Data reference
5101 + var ref_data = pagelayer_el_data_ref(jEle);
5102 +
2187 5103 // Create the tag
2188 - var data = '['+final_tag;
5104 + var data = JSON.parse(JSON.stringify(ref_data['attr']));
2189 5105
2190 - // Get the attributes to store
2191 - jQuery.each(jEle[0].attributes, function(i, attrib){
2192 - var res = attrib.name.match(/^pagelayer-a-(.+)/i);
2193 - if(res && res[1] != inner){
2194 - //console.log(attrib.name+' '+res[1]);
2195 - data += ' '+res[1]+'="'+pagelayer_escapeHTML(attrib.value)+'"';
2196 - }
2197 - });
5106 + data['pagelayer-id'] = id;
5107 + data = pagelayer_serializeAttributes(data);
5108 +
5109 + var content = '';
2198 5110
2199 - data = data+']';
2200 -
2201 - // Add to the text
2202 - txt = txt+data+"\n";
2203 -
2204 5111 // Any internal function to handle the save ?
2205 5112 var func = window['pagelayer_tag_'+tag];
2206 5113 if(typeof func == 'function'){
2207 5114
2208 - var content = '';
2209 5115 content = func(jEle);
2210 5116
2211 - if(content.length > 0){
2212 - txt = txt+content;
2213 - }
2214 -
2215 5117 // If its a Row or Column or Group then it will have children
2216 5118 }else if(jEle.hasClass('pagelayer-row') || jEle.hasClass('pagelayer-col') || jEle.hasClass('pagelayer-inner_row') || pagelayer_is_group(tag)){
2217 5119
2218 - var sel = "[pagelayer-id="+id+"]";
5120 + var sel = jEle;
2219 5121
2220 5122 // Any holder which holds children ?
2221 5123 if('holder' in pagelayer_shortcodes[tag]){
2222 - sel = sel+' '+pagelayer_shortcodes[tag]['holder'];
5124 + sel = jEle.find(pagelayer_shortcodes[tag]['holder']);
2223 5125 }
2224 5126
2225 5127 // Select the top-most element
2226 5128 sel = jQuery(sel).first();
@@ -2228,22 +5130,27 @@
2228 5130 // Any child selector - Majorly for owl carousel
2229 5131 // NOTE : Child selector should be very specific with immediate child selection at all levels
2230 5132 var child_selector = false;
2231 5133 if('child_selector' in pagelayer_shortcodes[tag]){
2232 - sel = sel.find(pagelayer_shortcodes[tag]['child_selector']);
5134 + childSel = sel.find(pagelayer_shortcodes[tag]['child_selector']);
5135 +
5136 + if(childSel.length > 0){
5137 + sel = childSel;
5138 + }
2233 5139 }
2234 -
2235 - var childrens = pagelayer_generate_sc(sel);
2236 - if(childrens.length > 0){
2237 - txt = txt+childrens;
5140 +
5141 + if(jQuery(sel).children(".pagelayer-ele-wrap").length < 1){
5142 + content = jQuery(sel).html(); // Backward Compatibility
5143 + }else{
5144 + content = pagelayer_generate_sc(sel);
5145 + content = "\n"+content;
2238 5146 }
2239 5147
2240 5148 // Its a normal element so we might need to handle the content
2241 5149 }else{
2242 5150
2243 - var content = '';
2244 5151 if(inner.length > 0){
2245 - content = jEle.attr('pagelayer-a-'+inner);
5152 + content = pagelayer_get_att(jEle, inner);
2246 5153 if(!content){
2247 5154 content = '';
2248 5155 }
2249 5156 }else{
@@ -2249,74 +5156,45 @@
2249 5156 }else{
2250 5157 content = '';//jEle.html();
2251 5158 }
2252 5159
2253 - if(content.length > 0){
2254 - txt = txt+content;
2255 - }
2256 -
2257 5160 }
2258 5161
2259 - // Close the tag
2260 - txt = txt+"[/"+final_tag+"]\n";
5162 + // Leaving HTML and non-pagelayer supported content intact
5163 + if(final_tag == 'pl_missing'){
5164 + txt += content;
5165 + return;
5166 + }
2261 5167
2262 - });
5168 + if (pagelayer_empty(content)) {
5169 + txt += "<!-- ".concat(pagelayer_block_prefix, ":pagelayer/").concat(final_tag, " ").concat(data, " /-->\n");
5170 + }else{
5171 + txt += "<!-- ".concat(pagelayer_block_prefix, ":pagelayer/").concat(final_tag, " ").concat(data, " -->").concat(content, "<!-- /").concat(pagelayer_block_prefix, ":pagelayer/").concat(final_tag, " -->\n");
5172 + }
5173 +
5174 + };
2263 5175
5176 + // Are you an element for which to generate the codes ?
5177 + if(jQuery(selector).hasClass('pagelayer-ele') && selfEle){
5178 +
5179 + generate_sc_single(jQuery(selector));
5180 +
5181 + // The selector is the holder, so loop thru
5182 + }else{
5183 +
5184 + jQuery(selector).children(".pagelayer-ele-wrap").each(function(){
5185 +
5186 + var jEle = jQuery(this).children('.pagelayer-ele');
5187 + generate_sc_single(jEle);
5188 +
5189 + });
5190 +
5191 + }
5192 +
2264 5193 return txt;
2265 5194
2266 5195 };
2267 5196
2268 -// Escape charaters in attributes
2269 -var pagelayer_escapeChars = {
2270 - '\\]' : '#93',
2271 - '\\[' : '#91',
2272 - //'=' : '#61',
2273 - '<' : 'lt',
2274 - '>' : 'gt',
2275 - '"' : 'quot',
2276 - //'&' : 'amp',
2277 - '\'' : '#39'
2278 -};
2279 -
2280 -// To unescape
2281 -var pagelayer_unescapeChars = {
2282 - '#93' : ']',
2283 - '#91' : '[',
2284 - //'#61' : '=',
2285 - 'lt' : '<',
2286 - 'gt' : '>',
2287 - 'quot' : '"',
2288 - //'amp' : '&',
2289 - '#39' : '\''
2290 -};
2291 -
2292 -var pagelayer_escaperegex_S = '[';
2293 -for(var key in pagelayer_escapeChars) {
2294 - pagelayer_escaperegex_S += key;
2295 -}
2296 -pagelayer_escaperegex_S += ']';
2297 -
2298 -var pagelayer_escaperegex = new RegExp( pagelayer_escaperegex_S, 'g');
2299 -
2300 -// The function which escapes everything
2301 -function pagelayer_escapeHTML(str) {
2302 - return str.replace(pagelayer_escaperegex, function(m) {
2303 - if(m == '[' || m == ']') m = '\\'+m;
2304 - return '&' + pagelayer_escapeChars[m] + ';';
2305 - });
2306 -};
2307 -
2308 -// This will unescape everything
2309 -function pagelayer_unescapeHTML(str){
2310 - return str.replace(/\&([^;]+);/g, function (entity, entityCode) {
2311 - if(entityCode in pagelayer_unescapeChars){
2312 - return pagelayer_unescapeChars[entityCode];
2313 - }else{
2314 - return entity;
2315 - }
2316 - });
2317 -};
2318 -
2319 5197 // Show the required leftbar tab
2320 5198 function pagelayer_leftbar_tab(tab){
2321 5199 pagelayer.$$('.pagelayer-leftbar-tab').hide();
2322 5200 pagelayer.$$('#'+tab).show();
@@ -2326,23 +5204,44 @@
2326 5204 function pagelayer_leftbar(){
2327 5205
2328 5206 // Toggle the holder
2329 5207 pagelayer.$$('.pagelayer-leftbar-toggle').on('click', function(){
2330 - pagelayer.$$('.pagelayer-leftbar-table').toggle();
5208 + pagelayer.$$('.pagelayer-leftbar-table').toggleClass('pagelayer-leftbar-hidden');
5209 + pagelayer_trigger_action('pagelayer-leftbar-toggle');
2331 5210 });
2332 5211
5212 + // Close leftbar
5213 + pagelayer.$$('.pagelayer-leftbar-close').on('click', function(){
5214 + pagelayer.$$('.pagelayer-leftbar-toggle').click();
5215 + });
5216 +
5217 + // Minimize leftbar
5218 + pagelayer.$$('.pagelayer-leftbar-minimize').on('click', function(){
5219 + pagelayer.$$('.pagelayer-leftbar-table').toggleClass('pagelayer-leftbar-minimize');
5220 + });
5221 +
2333 5222 var html = '<div class="pagelayer-leftbar">'+
2334 5223 '<div class="pagelayer-leftbar-scroll">'+
2335 5224 '<div id="pagelayer-shortcodes" class="pagelayer-leftbar-tab pagelayer-shortcodes">'+
2336 - '<div class="pagelayer-leftbar-search">'+
2337 - '<i class="fa fa-search" /><input class="pagelayer-search-field" />'+
2338 - '</div>';
5225 + '<div class="pagelayer-widget-tabs">'+
5226 + '<div class="pagelayer-widget-tab" pagelayer-widget-tab="widgets" pagelayer-elpd-active-tab=1>Widgets</div>'+
5227 + '<div class="pagelayer-widget-tab pagelayer-settings" pagelayer-widget-tab="settings">Settings</div>'+
5228 + '<div class="pagelayer-widget-tab" pagelayer-widget-tab="global">Globals</div>'+
5229 + '</div>'+
5230 + '<div class="pagelayer-shortcodes-widget">'+
5231 + '<div class="pagelayer-leftbar-search">'+
5232 + '<i class="pli pli-search" ></i><input class="pagelayer-search-field" placeholder="Search Widget..." /><span class="pagelayer-sf-empty pli">&times;</span>'+
5233 + '</div>';
2339 5234
2340 5235 for(var x in pagelayer_groups){
2341 5236
2342 5237 // Title
2343 - html += '<div class="pagelayer-leftbar-group"><h5>'+x+'</h5>';
5238 + var group_title = x;
5239 + if (x === 'Basic') group_title = 'Atomic Elements';
5240 + else if (x === 'Common') group_title = 'General';
2344 5241
5242 + html += '<div class="pagelayer-leftbar-group pagelayer-group-name-'+x+'"><h5>'+group_title+'</h5>';
5243 +
2345 5244 // Indivdual icon
2346 5245 for(var y in pagelayer_groups[x]){
2347 5246
2348 5247 var sc = pagelayer_groups[x][y];
@@ -2355,11 +5254,11 @@
2355 5254 '<div class="pagelayer-sc">'+
2356 5255 '<center class="pagelayer-shortcode-inner">';
2357 5256
2358 5257 if('icon' in pagelayer_shortcodes[sc]){
2359 - html += '<i class="pagelayer-shortcode fa fa-'+pagelayer_shortcodes[sc]['icon']+'"></i>';
5258 + html += '<i class="pagelayer-shortcode '+pagelayer_shortcodes[sc]['icon']+'"></i>';
2360 5259 }else{
2361 - html += '<i class="pagelayer-shortcode pagelayer-'+sc+'"></i>';
5260 + html += '<i class="pagelayer-shortcode pli pagelayer-'+sc+'"></i>';
2362 5261 }
2363 5262
2364 5263 html += '</center>'+
2365 5264 '<span class="pagelayer-shortcode-text">'+pagelayer_shortcodes[sc]['name']+'</span>'+
@@ -2372,11 +5271,16 @@
2372 5271
2373 5272 }
2374 5273
2375 5274 html += '</div>'+
5275 + '<div id="pagelayer-global-widget" class="pagelayer-hidden pagelayer-global-widget"></div>'+
5276 + '</div>'+
2376 5277 '<div id="pagelayer-elpd" class="pagelayer-leftbar-tab pagelayer-elpd"></div>'+
5278 + '<div id="pagelayer-options" class="pagelayer-leftbar-tab pagelayer-options"></div>'+
2377 5279 '<div id="pagelayer-history" class="pagelayer-leftbar-tab pagelayer-history"></div>'+
2378 5280 '<div id="pagelayer-post-settings" class="pagelayer-leftbar-tab pagelayer-post-settings"></div>'+
5281 + '<div id="pagelayer-navigator" class="pagelayer-leftbar-tab pagelayer-navigator"></div>'+
5282 + '<div id="pagelayer-general-options" class="pagelayer-leftbar-tab pagelayer-general-options"></div>'+
2379 5283 '</div>'+
2380 5284 '</div>';
2381 5285
2382 5286 pagelayer.$$('.pagelayer-leftbar-holder').prepend(html);
@@ -2425,108 +5329,170 @@
2425 5329 });
2426 5330 });
2427 5331
2428 5332 // On click Pagelayer setting icon
2429 - pagelayer.$$('.pagelayer-settings-icon').click(function(){
2430 - pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text('Post Settings');
2431 - pagelayer.$$('.pagelayer-logo').hide();
2432 - pagelayer_leftbar_tab('pagelayer-post-settings');
5333 + pagelayer.$$('.pagelayer-settings-icon, .pagelayer-settings').click(function(event){
2433 5334 pagelayer_active = {};
2434 - pagelayer_post_settings();
5335 +
5336 + var pl_tag = jQuery(this).attr('pagelayer-tag') || 'pl_post_props';
5337 + var nModal = jQuery(this).attr('pagelayer-modal-none');
5338 +
5339 + pagelayer_post_settings(pl_tag);
5340 +
2435 5341 });
2436 5342
2437 -};
2438 -
2439 -// Post setting holder
2440 -function pagelayer_post_settings(){
5343 + // Pagelayer post advance setting modal handler
5344 + var propsModal = pagelayer.$$('.pagelayer-props-modal');
5345 + propsModal.find('.pagelayer-props-modal-close').on('click', function(event){
5346 + propsModal.hide();
5347 + });
5348 +
5349 + propsModal.on('click', function(event){
5350 + var target = jQuery(event.target);
5351 +
5352 + if(target.closest('.pagelayer-props-modal-wrap').length > 0){
5353 + return;
5354 + }
5355 +
5356 + propsModal.hide();
5357 + });
5358 +
2441 5359
2442 - // Start pagelayer settings holder
2443 - var setting_holder = '<div class="pagelayer-post-settings-holder">';
2444 -
2445 - // Start pagelayer settings content body
2446 - setting_holder += '<div class="pagelayer-post-settings-acc">'+
2447 - '<div class="pagelayer-post-settings-lable"><span>Title</span><i class="pagelayer-toggle fa"></i></div>'+
2448 - '<div class="pagelayer-post-settings-fields">'+
2449 - '<label for="post_title">Post Title</label> '+
2450 - '<input type="text" name="post_title" value="'+ pagelayer_postTitle +'" id="title" spellcheck="true" autocomplete="off">'+
2451 - '<button class="pagelayer-post-settings-apply pagelayer-success-btn" disabled>Apply</button>'+
2452 - '</div>'+
2453 - '</div>';
2454 -
2455 - /*if(pagelayer_postType == pagelayer_cpt['name']){
2456 - setting_holder += '<div class="pagelayer-post-settings-acc">'+
2457 - '<div class="pagelayer-post-settings-lable"><span>Custom Template type</span><i class="pagelayer-toggle fa"></i></div>'+
2458 - '<div class="pagelayer-post-settings-fields">'+ pagelayer_CPT_condi +
5360 + // On click Pagelayer setting icon
5361 + var global_widget_list = function(){
5362 +
5363 + var gHtml = '';
5364 +
5365 + if(pagelayer_empty(pagelayer_pro)){
5366 + gHtml += '<div class="pagelayer-global-widget-pro">'+pagelayer.pro_txt+
5367 + '<p>Using this feature, you can save the widgets globally and use them on the entire site. The global widget will be editable from one place.</p>'+
5368 + '</div>';
5369 +
5370 + pagelayer.$$('#pagelayer-global-widget').html(gHtml);
5371 + return;
5372 + }
5373 +
5374 + gHtml += '<div class="pagelayer-global-widget-shortcodes">'+
5375 + '<div class="pagelayer-leftbar-search">'+
5376 + '<i class="pli pli-search" ></i><input class="pagelayer-search-field" /><i class="pagelayer-sf-empty pli">&times;</i>'+
2459 5377 '</div>'+
5378 + '<div class="pagelayer-leftbar-group"><h5>'+pagelayer_l('global_widgets')+'</h5></div>'+
2460 5379 '</div>';
2461 - }*/
5380 +
5381 + if(pagelayer_empty(pagelayer_global_widgets)){
5382 + pagelayer_global_widgets = [];
5383 + gHtml += '<div class="pagelayer-leftbar-group"><h5>No global widgets found</h5></div>';
5384 + }
5385 +
5386 + // Indivdual icon
5387 + for(var y in pagelayer_global_widgets){
5388 + var wEle = jQuery(pagelayer_global_widgets[y]['$']);
5389 + var sc = pagelayer_tag( wEle );
5390 +
5391 + if(!(sc in pagelayer_shortcodes) || 'not_visible' in pagelayer_shortcodes[sc]){
5392 + continue;
5393 + }
5394 +
5395 + gHtml += '<div class="pagelayer-shortcode-drag" draggable="true" pagelayer-tag="'+sc+'" pagelayer-global-id="'+y+'">'+
5396 + '<div class="pagelayer-sc">'+
5397 + '<center class="pagelayer-shortcode-inner">';
5398 +
5399 + if('icon' in pagelayer_shortcodes[sc]){
5400 + gHtml += '<i class="pagelayer-shortcode '+pagelayer_shortcodes[sc]['icon']+'"></i>';
5401 + }else{
5402 + gHtml += '<i class="pagelayer-shortcode pli pagelayer-'+sc+'"></i>';
5403 + }
5404 +
5405 + gHtml += '</center>'+
5406 + '<span class="pagelayer-shortcode-text">'+pagelayer_global_widgets[y]['title']+'</span>'+
5407 + '</div>'+
5408 + '</div>';
5409 +
5410 + }
2462 5411
2463 - /* if(pagelayer_support_FI){
2464 - setting_holder += '<div class="pagelayer-post-settings-acc">'+
2465 - '<div class="pagelayer-post-settings-lable"><span>Featured Image</span><i class="pagelayer-toggle fa"></i></div>'+
2466 - '<div class="pagelayer-post-settings-fields">Featured Image'+
2467 - '</div>'+
2468 - '</div>';
2469 - } */
5412 + pagelayer.$$('#pagelayer-global-widget').html(gHtml);
5413 + };
2470 5414
2471 - // End pagelayer settings content body
5415 + // The widget tabs
5416 + pagelayer.$$('.pagelayer-widget-tab').on('click', function(){
5417 + var attr = 'pagelayer-elpd-active-tab';
5418 + pagelayer.$$('.pagelayer-widget-tab').each(function(){
5419 + jQuery(this).removeAttr(attr);
5420 + });
5421 + var cEle = jQuery(this);
5422 + cEle.attr(attr, 1);
5423 +
5424 + if(cEle.attr('pagelayer-widget-tab') == 'global'){
5425 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-shortcodes-widget').addClass('pagelayer-hidden');
5426 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-global-widget').removeClass('pagelayer-hidden');
5427 + // Trigger create global widgets
5428 + global_widget_list();
5429 + }else{
5430 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-shortcodes-widget').removeClass('pagelayer-hidden');
5431 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-global-widget').addClass('pagelayer-hidden');
5432 + }
5433 + });
2472 5434
2473 - // End pagelayer settings holder
2474 - setting_holder += '</div>';
2475 - var holder = pagelayer.$$('#pagelayer-post-settings');
2476 - holder.html(setting_holder);
2477 -
2478 - // On change input fields enable the apply button
2479 - holder.find('input, select, textarea').on('change input', function(){
2480 - jQuery(this).closest('.pagelayer-post-settings-fields').find('.pagelayer-post-settings-apply').removeAttr('disabled');
5435 + // On click search empty
5436 + pagelayer.$$('.pagelayer-leftbar-search>.pagelayer-sf-empty').click(function(){
5437 + pagelayer.$$('.pagelayer-search-field').val('').trigger('input');
2481 5438 });
2482 5439
2483 - // On click the label toggle the setting field holder
2484 - holder.find('.pagelayer-post-settings-lable').on('click', function(){
5440 + // Pagelayer General options
5441 + pagelayer.$$('.pagelayer-options-icon ').click(function(){
5442 + pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text(pagelayer_l('general_options'));
5443 + pagelayer.$$('.pagelayer-logo').hide();
2485 5444
2486 - var lEle = jQuery(this);
2487 - var lEle_next = lEle.next('.pagelayer-post-settings-fields');
5445 + // Setup General options
5446 + pagelayer_setup_general_options();
2488 5447
2489 - holder.find('.pagelayer-post-settings-fields').each(function(){
2490 - var fEle = jQuery(this);
2491 - if(!fEle.is(lEle_next)){
2492 - fEle.hide().prev('.pagelayer-post-settings-lable').find('.pagelayer-toggle').removeClass('pagelayer-open');
2493 - }
2494 - });
5448 + pagelayer_leftbar_tab('pagelayer-general-options');
5449 + pagelayer_active = {};
5450 + });
5451 +
5452 + // Hide color and typography global list
5453 + pagelayer.$$('.pagelayer-leftbar-table').on('click', function(e){
5454 +
5455 + var closest = jQuery(e.target).closest('.pagelayer-elp-color-global, .pagelayer-elp-global-icon, .pagelayer-global-color-list, .pagelayer-global-font-list');
5456 + var list = pagelayer.$$('.pagelayer-global-color-list, .pagelayer-global-font-list');
5457 +
5458 + if(closest.length > 0 ){
5459 + var lEle = closest.closest('.pagelayer-elp-color-div-holder').find('.pagelayer-global-color-list');
5460 + var lFont = closest.closest('.pagelayer-form-item').find('.pagelayer-global-font-list');
5461 +
5462 + list = list.not(lFont);
5463 + list = list.not(lEle);
5464 + }
5465 +
5466 + list.not(closest).slideUp();
2495 5467
2496 - lEle.next('.pagelayer-post-settings-fields').toggle();
2497 - lEle.find('.pagelayer-toggle').toggleClass('pagelayer-open');
2498 -
2499 5468 });
5469 +};
5470 +
5471 +// Post setting holder
5472 +function pagelayer_post_settings(pl_tag, to_click){
2500 5473
2501 - // On click apply button
2502 - holder.find('.pagelayer-post-settings-apply').click(function(){
2503 - var fEle = jQuery(this).closest('.pagelayer-post-settings-fields');
2504 - var data = fEle.find('input, select, textarea').serialize();
5474 + to_click = to_click == -1 ? false : true;
5475 +
5476 + // Is there a post settings ?
5477 + var jEle = jQuery(pagelayer_editable+' [pagelayer-tag="'+ pl_tag +'"]');
5478 +
5479 + // Could not find
5480 + if(jEle.length < 1){
5481 + jEle = pagelayer_create_sc(pl_tag);
5482 + var id = pagelayer_id(jEle);
5483 + jQuery(pagelayer_editable).prepend(jEle);
5484 + pagelayer_element_setup('[pagelayer-id='+id+']', true);
2505 5485
2506 - jQuery.ajax({
2507 - url: pagelayer_ajax_url+'action=pagelayer_save_settings&postID='+pagelayer_postID,
2508 - type: 'post',
2509 - data : 'pagelayer_nonce='+ pagelayer_ajax_nonce +'&'+ data,
2510 - success: function(response, status, xhr){
2511 - //alert(data);
2512 - var obj = jQuery.parseJSON(response);
2513 - //alert(obj);
2514 - if(obj['error']){
2515 - alert(obj['error']);
2516 - }else{
2517 - alert(obj['success']);
2518 - window.location.reload();
2519 - }
2520 - },
2521 - error: function(errorThrown){
2522 - console.log(errorThrown);
2523 - }
2524 - });
2525 -
2526 - });
5486 + // Dont mark as dirty as post_props is not editing anything
5487 + pagelayer_do_undirty();
5488 + }
2527 5489
2528 - return;
5490 + if(to_click){
5491 + jEle.click();
5492 + }
5493 +
5494 + return jEle;
2529 5495 }
2530 5496
2531 5497 // Get the closest element and method
2532 5498 function pagelayer_near_by_ele(id, sc){
@@ -2552,9 +5518,9 @@
2552 5518 var pEle_id = pagelayer_id(jQuery('[pagelayer-wrap-id="'+id+'"]').closest('.pagelayer-ele'));
2553 5519
2554 5520 // Get the parent element tag
2555 5521 var pEle_tag = pagelayer_tag(jQuery('[pagelayer-id="'+pEle_id+'"]'));
2556 - var holder = pagelayer_shortcodes[pEle_tag]['holder'] || '';
5522 + var holder = '>'+ pagelayer_shortcodes[pEle_tag]['holder'] || '';
2557 5523 args = {'method' : 'prepend', 'cEle' : '[pagelayer-id="'+pEle_id+'"] '+ holder+' '};
2558 5524
2559 5525 }
2560 5526
@@ -2566,8 +5532,9 @@
2566 5532
2567 5533 // Push the action data in the pagelayer_history_obj object
2568 5534 function pagelayer_history_action_push(args){
2569 5535
5536 + var currentTime = new Date();
2570 5537 var history_obj_len = pagelayer_history_obj['action_data'].length;
2571 5538
2572 5539 // If the history_obj_len is less then 1 then set the data in array 0 position
2573 5540 if(history_obj_len < 1){
@@ -2577,8 +5544,9 @@
2577 5544
2578 5545 // Remove the second array element if the history_obj_len greater then 100
2579 5546 if(history_obj_len > 100){
2580 5547 pagelayer_history_obj['action_data'].splice(1, 1);
5548 + pagelayer_history_obj['current_active_item_id'] = pagelayer_history_obj['action_data'].length - 1;
2581 5549 }
2582 5550
2583 5551 // Get current active history action id
2584 5552 var action_id = parseInt(pagelayer_history_obj['current_active_item_id']) || 0;
@@ -2587,22 +5555,45 @@
2587 5555 var del_ele = history_obj_len - action_id - 1;
2588 5556 pagelayer_history_obj['action_data'].splice(action_id + 1, del_ele);
2589 5557
2590 5558 // Check if the same attr set as current active history
2591 - if(args.action == "Edited" && history_obj_len > 1){
5559 + if(args.action == "Edited" && history_obj_len > 1 && currentTime - pagelayer.history_lastTime < 1000){
2592 5560 var atts = pagelayer_history_obj['action_data'][action_id] || '';
2593 - if(atts['atts'] == args['atts']){
5561 + if(atts['atts'] == args['atts'] && atts['pl_id'] == args['pl_id'] && pagelayer_empty(atts['sub_actions_group']) ){
2594 5562 args['oldVal'] = atts['oldVal'];
2595 5563 pagelayer_history_obj['action_data'][action_id] = args;
2596 5564 pagelayer_history_setup();
5565 +
5566 + // Set the last history time
5567 + pagelayer.history_lastTime = currentTime;
2597 5568 return true;
2598 5569 }
2599 5570 }
2600 -
5571 +
5572 + // If the action time within 200 millisecond then it count as sub-actions
5573 + if(currentTime - pagelayer.history_lastTime < 200 && history_obj_len > 1){
5574 +
5575 + var cur_action_data = pagelayer_history_obj['action_data'][action_id];
5576 + var sub_actions_len = cur_action_data['sub_actions_group'] || '';
5577 +
5578 + if( !('attrType' in cur_action_data && cur_action_data['attrType'] == 'tmp_attr' && 'attrType' in args && args['attrType'] == 'a_attr') ) {
5579 + // If the sub_actions_len is less then 1 then set the data in array 0 position
5580 + if(sub_actions_len.length < 1){
5581 + pagelayer_history_obj['action_data'][action_id]['sub_actions_group'] = [args];
5582 + }else{
5583 + pagelayer_history_obj['action_data'][action_id]['sub_actions_group'].push(args);
5584 + }
5585 +
5586 + return true;
5587 + }
5588 + }
5589 +
2601 5590 pagelayer_history_obj['action_data'].push(args);
2602 5591 pagelayer_history_obj['current_active_item_id'] = pagelayer_history_obj['action_data'].length - 1;
2603 5592 pagelayer_history_setup();
2604 5593
5594 + // Set the last history time
5595 + pagelayer.history_lastTime = currentTime;
2605 5596 }
2606 5597
2607 5598 // Setup pagelayer history
2608 5599 function pagelayer_history_setup(force){
@@ -2648,9 +5639,9 @@
2648 5639 '<span class="pagelayer-history-subtitle"> '+subTitle+' </span>'+
2649 5640 '<span class="pagelayer-history-action"><i> '+action+' </i></span>'+
2650 5641 '</div>'+
2651 5642 '<div class="pagelayer-history-icon">'+
2652 - '<span class="pagelayer-history-check fa fa-check" aria-hidden="true"></span>'+
5643 + '<span class="pagelayer-history-check pli pli-checkmark" aria-hidden="true"></span>'+
2653 5644 '</div>'+
2654 5645 '</div>';
2655 5646 }
2656 5647
@@ -2678,9 +5669,9 @@
2678 5669 pagelayer_revision_obj[x]['post_author_name']+
2679 5670 '</div>'+
2680 5671 '</div>'+
2681 5672 '<div class="pagelayer-revision-icon-holder">'+
2682 - '<i class="pagelayer-revision-delete fa fa-times"></i>'+
5673 + '<i class="pagelayer-revision-delete pli pli-cross"></i>'+
2683 5674 '</div>'+
2684 5675 '</div>';
2685 5676 }
2686 5677
@@ -2719,14 +5710,45 @@
2719 5710 success: function(response, status, xhr){
2720 5711
2721 5712 var obj = jQuery.parseJSON(response);
2722 5713 if(obj['error']){
2723 - alert(obj['error']);
5714 + pagelayer_show_msg(obj['error'] , 'error');
2724 5715 }else{
5716 +
5717 + // Get the current post_name and post_status
5718 + var props = jQuery(pagelayer_editable).find('.pagelayer-post_props');
5719 + var post_name = '', post_status = '';
5720 +
5721 + if(props.length > 0){
5722 + post_name = pagelayer_get_att(props, 'post_name');
5723 + post_status = pagelayer_get_att(props, 'post_status');
5724 + }
5725 +
5726 + // Set content
2725 5727 jQuery(pagelayer_editable).html(obj['content']);
2726 - alert(obj['success']);
2727 - pagelayer_element_setup();
5728 +
5729 + // Add previous post_name and post_status
5730 + var props_new = jQuery(pagelayer_editable).find('.pagelayer-post_props');
5731 + if(props_new.length > 0){
5732 +
5733 + if(pagelayer_empty(post_name)){
5734 + post_name = pagelayer_default_params.pl_post_props.post_name;
5735 + }
5736 +
5737 + if(pagelayer_empty(post_status)){
5738 + post_status = pagelayer_default_params.pl_post_props.post_status;
5739 + }
5740 +
5741 + var tmp = {};
5742 + tmp['post_name'] = post_name;
5743 + tmp['post_status'] = post_status;
5744 + pagelayer_set_atts(props_new, tmp);
5745 + }
5746 +
5747 + // Need to pass true to render table
5748 + pagelayer_element_setup('.pagelayer-ele', true);
2728 5749 pagelayer_add_widget();
5750 + pagelayer_show_msg(obj['success'], 'success');
2729 5751 }
2730 5752 }
2731 5753 });
2732 5754 });
@@ -2746,11 +5768,11 @@
2746 5768 success: function(response, status, xhr){
2747 5769
2748 5770 var obj = jQuery.parseJSON(response);
2749 5771 if(obj['error']){
2750 - alert(obj['error']);
5772 + pagelayer_show_msg(obj['error'], 'error');
2751 5773 }else{
2752 - alert(obj['success']);
5774 + pagelayer_show_msg(obj['success'], 'success');
2753 5775 rEle.hide();
2754 5776 }
2755 5777
2756 5778 }
@@ -2783,9 +5805,9 @@
2783 5805 });
2784 5806 });
2785 5807 }
2786 5808
2787 -// Get evisions Handler
5809 +// Get revisions Handler
2788 5810 function pagelayer_get_revision(){
2789 5811
2790 5812 jQuery.ajax({
2791 5813 url: pagelayer_ajax_url+'&action=pagelayer_get_revision&postID='+pagelayer_postID,
@@ -2797,9 +5819,9 @@
2797 5819 success: function(response, status, xhr){
2798 5820 var obj = jQuery.parseJSON(response);
2799 5821
2800 5822 if(!pagelayer_empty(obj['error'])){
2801 - alert(obj['error']);
5823 + pagelayer_show_msg(obj['error'], 'error');
2802 5824 }else{
2803 5825 pagelayer_revision_obj = obj;
2804 5826 pagelayer_history_setup(true);
2805 5827 }
@@ -2878,9 +5900,13 @@
2878 5900 // Re-setup the element
2879 5901 var resetup_ele = function(history_array){
2880 5902 jQuery(history_array.cEle.cEle)[history_array.cEle.method](history_array.html);
2881 5903 pagelayer_element_setup('[pagelayer-id='+history_array.pl_id+'], [pagelayer-id='+history_array.pl_id+'] .pagelayer-ele', true);
2882 - pagelayer_empty_col(jQuery('[pagelayer-id="'+history_array.pl_id+'"]').closest('.pagelayer-col-holder'));
5904 +
5905 + var rEle = jQuery('[pagelayer-id="'+history_array.pl_id+'"]');
5906 + pagelayer_empty_col(rEle.closest('.pagelayer-col-holder'));
5907 +
5908 + pagelayer_do_dirty(rEle);
2883 5909 };
2884 5910
2885 5911 // Re-setup the element attr
2886 5912 var reset_ele_attr = function(hEle, atts, val, attrType){
@@ -2901,10 +5927,69 @@
2901 5927 pagelayer.history_action = true;
2902 5928
2903 5929 };
2904 5930
5931 + // Move element
5932 + var pagelayer_move_ele = function(id, move_loc){
5933 + var eWrap = pagelayer_wrap_by_id(id);
5934 + var pCol = eWrap.closest('.pagelayer-col-holder') || '';
5935 +
5936 + jQuery(move_loc.cEle)[move_loc.method](eWrap);
5937 +
5938 + // Ensure the column is not empty
5939 + if(!pagelayer_empty(pCol)){
5940 + pagelayer_empty_col(pCol);
5941 + pagelayer_empty_col(pagelayer_wrap_by_id(id).closest('.pagelayer-col-holder'));
5942 + }
5943 +
5944 + pagelayer_do_dirty(eWrap);
5945 + };
5946 +
5947 + // Undo actions
5948 + var pagelayer_undo_action = function(history_array){
5949 + var action = history_array.action;
5950 + var id = history_array.pl_id;
5951 +
5952 + if(action == "Edited"){
5953 + hEle = jQuery('[pagelayer-id="'+id+'"]');
5954 + reset_ele_attr(hEle, history_array.atts, history_array.oldVal, history_array.attrType);
5955 + }else if(action == "Added"){
5956 + delete_ele(id);
5957 + }else if(action == "Deleted"){
5958 + resetup_ele(history_array);
5959 + }else if(action == "Copied"){
5960 + delete_ele(id);
5961 + }else if(action == "Moved"){
5962 + pagelayer_move_ele(id, history_array.before_loc);
5963 + }
5964 + };
5965 +
5966 + // Redo actions
5967 + var pagelayer_redo_action = function(history_array){
5968 + var action = history_array.action;
5969 + var id = history_array.pl_id;
5970 +
5971 + if(action == "Edited"){
5972 + hEle = jQuery('[pagelayer-id="'+id+'"]');
5973 + reset_ele_attr(hEle, history_array.atts, history_array.newVal, history_array.attrType);
5974 + }else if(action == "Added"){
5975 + resetup_ele(history_array);
5976 +
5977 + if(history_array.tag != "pl_row" && history_array.tag != "pl_col" ){
5978 + // Ensure the column is not empty
5979 + pagelayer_empty_col(history_array.cEle.cEle);
5980 + }
5981 + }else if(action == "Deleted"){
5982 + delete_ele(id);
5983 + }else if(action == "Copied"){
5984 + resetup_ele(history_array);
5985 + }else if(action == "Moved"){
5986 + pagelayer_move_ele(id, history_array.after_loc);
5987 + }
5988 + };
5989 +
2905 5990 if(prev_item_id > current_item_id){
2906 -
5991 +
2907 5992 // All Actions for undo here
2908 5993 var i = parseInt(prev_item_id);
2909 5994
2910 5995 for(i; i > current_item_id; i--){
@@ -2909,26 +5994,31 @@
2909 5994
2910 5995 for(i; i > current_item_id; i--){
2911 5996
2912 5997 var history_array = pagelayer_history_obj['action_data'][i];
2913 - var action = history_array.action;
2914 - var id = history_array.pl_id;
5998 + var sub_actions_group = history_array['sub_actions_group'] || '';
2915 5999
2916 - if(action == "Edited"){
2917 - hEle = jQuery('[pagelayer-id="'+id+'"]');
2918 - reset_ele_attr(hEle, history_array.atts, history_array.oldVal, history_array.attrType);
2919 - }else if(action == "Added"){
2920 - delete_ele(id);
2921 - }else if(action == "Deleted"){
2922 - resetup_ele(history_array);
2923 - }else if(action == "Copied"){
2924 - delete_ele(id);
6000 + // If it has sub-actions
6001 + if(!pagelayer_empty(sub_actions_group)){
6002 + var j = sub_actions_group.length;
6003 + for(j--; j >= 0; j--){
6004 + pagelayer_undo_action(sub_actions_group[j]);
6005 + }
2925 6006 }
2926 6007
6008 + // Main action
6009 + pagelayer_undo_action(history_array);
6010 +
6011 + // Activate the current element and scroll it into viewport
6012 + var jEle = jQuery('[pagelayer-id="'+history_array.pl_id+'"]');
6013 + if(jEle.length > 0){
6014 + pagelayer_set_active(jEle);
6015 + pagelayer_scroll_to_viewport(jEle, 0);
6016 + }
2927 6017 }
2928 6018
2929 6019 }else{
2930 -
6020 +
2931 6021 // All Actions for redo here
2932 6022 var i = parseInt(prev_item_id)+1;
2933 6023
2934 6024 for(i; i <= current_item_id; i++){
@@ -2933,27 +6023,25 @@
2933 6023
2934 6024 for(i; i <= current_item_id; i++){
2935 6025
2936 6026 var history_array = pagelayer_history_obj['action_data'][i];
2937 - var action = history_array.action;
2938 - var id = history_array.pl_id;
6027 + var sub_actions_group = history_array['sub_actions_group'] || '';
6028 + // Main action
6029 + pagelayer_redo_action(history_array);
2939 6030
2940 - if(action == "Edited"){
2941 - hEle = jQuery('[pagelayer-id="'+id+'"]');
2942 - reset_ele_attr(hEle, history_array.atts, history_array.newVal, history_array.attrType);
2943 - }else if(action == "Added"){
2944 - resetup_ele(history_array);
2945 -
2946 - if(history_array.tag != "pl_row" && history_array.tag != "pl_col" ){
2947 - // Ensure the column is not empty
2948 - pagelayer_empty_col(history_array.cEle.cEle);
6031 + // If it has sub-actions
6032 + if(!pagelayer_empty(sub_actions_group)){
6033 + for(var x in sub_actions_group){
6034 + pagelayer_redo_action(sub_actions_group[x]);
2949 6035 }
2950 - }else if(action == "Deleted"){
2951 - delete_ele(id);
2952 - }else if(action == "Copied"){
2953 - resetup_ele(history_array);
2954 6036 }
2955 6037
6038 + // Activate the current element and scroll it into viewport
6039 + var jEle = jQuery('[pagelayer-id="'+history_array.pl_id+'"]');
6040 + if(jEle.length > 0){
6041 + pagelayer_set_active(jEle);
6042 + pagelayer_scroll_to_viewport(jEle, 0);
6043 + }
2956 6044 }
2957 6045 }
2958 6046
2959 6047 };
@@ -2964,26 +6052,48 @@
2964 6052 alert(prefix+error);
2965 6053 };
2966 6054
2967 6055 function pagelayer_bottombar(){
2968 - var holder = pagelayer.$$('.pagelayer-bottombar-holder');
2969 - var html = '<div class="pagelayer-bottombar">'+
2970 - '<div class="pagelayer-bottombar-rightbuttons">'+
2971 - '<button class="pagelayer-update-button pagelayer-success-btn">Update</button>'+
2972 - '<button class="pagelayer-close-button">Close</button>'+
2973 - '<div class="pagelayer-mode-wrapper">'+
2974 - '<i class="pagelayer-mode-button fa fa-desktop"></i>'+
2975 - '<div class="pagelayer-mode-buttons-wrapper">'+
2976 - '<i class="screen-mode fa fa-desktop" pagelayer-mode-data="desktop"></i>'+
2977 - '<i class="screen-mode fa fa-tablet" pagelayer-mode-data="tablet"></i>'+
2978 - '<i class="screen-mode fa fa-mobile" pagelayer-mode-data="mobile"></i>'+
2979 - '</div>'+
6056 + var holder = pagelayer.$$('.pagelayer-iframe-top-bar');
6057 + pagelayer.$$('.pagelayer-iframe-top-bar').show();
6058 +
6059 + // Get post title
6060 + var post_title = (typeof pagelayer_post !== 'undefined' && pagelayer_post.post_title) ? pagelayer_post.post_title : 'Page';
6061 +
6062 + var html = '<div class="pagelayer-top-header-bar">'+
6063 + '<div class="pagelayer-header-left">'+
6064 + '<span class="pagelayer-header-document-title">Editing: <span class="pagelayer-header-post-name">' + post_title + '</span></span>'+
6065 + '</div>'+
6066 + '<div class="pagelayer-header-center">'+
6067 + '<div class="pagelayer-device-selectors">'+
6068 + '<i class="screen-mode pli pli-desktop" pagelayer-mode-data="desktop" data-tlite="Desktop View"></i>'+
6069 + '<i class="screen-mode pli pli-tablet" pagelayer-mode-data="tablet" data-tlite="Tablet View"></i>'+
6070 + '<i class="screen-mode pli pli-mobile" pagelayer-mode-data="mobile" data-tlite="Mobile View"></i>'+
2980 6071 '</div>'+
2981 - '<i class="pagelayer-history-icon fa fa-history"></i>'+
2982 6072 '</div>'+
6073 + '<div class="pagelayer-header-right">'+
6074 + '<span data-tlite="'+pagelayer_l('preview_changes')+'" class="pagelayer-header-icon-wrap"><i class="pagelayer-preview pli pli-eye"></i></span>'+
6075 + '<span data-tlite="'+pagelayer_l('historyand_revisions')+'" class="pagelayer-header-icon-wrap"><i class="pagelayer-history-icon pli pli-history"></i></span>'+
6076 + '<span data-tlite="'+pagelayer_l('navigator')+'" class="pagelayer-header-icon-wrap"><i class="pagelayer-navigator-icon pli pli-tree"></i></span>'+
6077 + '<div class="pagelayer-header-divider"></div>'+
6078 + '<button data-tlite="Save Changes" class="pagelayer-update-button pagelayer-success-btn">'+
6079 + '<span class="pagelayer-update-loader">'+
6080 + '<span></span>'+
6081 + '<span></span>'+
6082 + '<span></span>'+
6083 + '</span>'+
6084 + '<span class="pagelayer-update-text">Update</span>'+
6085 + '</button>'+
6086 + '<button data-tlite="Close Editor" class="pagelayer-close-button"><i class="pli pli-cross"></i></button>'+
6087 + '</div>'+
2983 6088 '</div>';
2984 6089
2985 6090 holder.html(html);
6091 +
6092 + // Add active class on load
6093 + var current_mode = pagelayer.screen_mode || 'desktop';
6094 + holder.find('.screen-mode[pagelayer-mode-data="' + current_mode + '"]').addClass('active');
6095 +
2986 6096 holder.find('.pagelayer-update-button').on('click', function(){
2987 6097 pagelayer_save();
2988 6098 pagelayer_history_setup();// Setup history tab after update
2989 6099 });
@@ -2990,25 +6100,79 @@
2990 6100
2991 6101 holder.find('.pagelayer-close-button').on('click', function(){
2992 6102 pagelayer_close();
2993 6103 });
6104 +
2994 6105 holder.find('.screen-mode').on('click', function(){
2995 6106 var screen_mode = jQuery(this).attr('pagelayer-mode-data');
2996 6107 pagelayer_set_screen_mode(screen_mode);
2997 - holder.find('.pagelayer-mode-buttons-wrapper').toggle();
6108 + holder.find('.screen-mode').removeClass('active');
6109 + jQuery(this).addClass('active');
2998 6110 });
2999 6111
3000 - holder.find('.pagelayer-mode-button').on('click', function(){
3001 - holder.find('.pagelayer-mode-buttons-wrapper').toggle();
6112 + holder.find('.pagelayer-history-icon').closest('.pagelayer-header-icon-wrap').click(function(){
6113 + pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text(pagelayer_l('pagelayer_history'));
6114 + pagelayer.$$('.pagelayer-logo').hide();
6115 + pagelayer_leftbar_tab('pagelayer-history');
6116 + pagelayer_active = {};
6117 + pagelayer_history_setup();
3002 6118 });
3003 6119
3004 - holder.find('.pagelayer-history-icon').click(function(){
3005 - pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text('Pagelayer History');
6120 + holder.find('.pagelayer-navigator-icon').closest('.pagelayer-header-icon-wrap').click(function(){
6121 + pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text(pagelayer_l('pagelayer_navigator'));
3006 6122 pagelayer.$$('.pagelayer-logo').hide();
3007 - pagelayer_leftbar_tab('pagelayer-history');
6123 +
6124 + // If the navigator tab visible, then don't setup
6125 + if(!pagelayer.$$('#pagelayer-navigator').is(':visible')){
6126 + pagelayer_navigator_setup();
6127 + }
6128 +
6129 + pagelayer_leftbar_tab('pagelayer-navigator');
3008 6130 pagelayer_active = {};
3009 - pagelayer_history_setup();
3010 6131 });
6132 +
6133 + holder.find('.pagelayer-preview').click(function(){
6134 +
6135 + // If the page is not dirty
6136 + if(!pagelayer_isDirty){
6137 +
6138 + // Open in new tab the existing page itself
6139 + window.open(pagelayer_post_permalink, '_blank');
6140 + return;
6141 +
6142 + }
6143 +
6144 + // Get post content
6145 + var post = pagelayer_generate_sc(pagelayer_editable);//alert(post);return;
6146 +
6147 + pagelayer.$$('.pagelayer-body').css({'opacity' : '0.33'});
6148 + jQuery.ajax({
6149 + url: pagelayer_ajax_url+'&action=pagelayer_create_post_autosave&postID='+pagelayer_postID,
6150 + type: 'POST',
6151 + data: {
6152 + 'pagelayer_nonce': pagelayer_ajax_nonce,
6153 + 'pagelayer_post_content': pagelayer_Base64.encode(post)
6154 + },
6155 + success: function(data) {
6156 + var data = JSON.parse(data);
6157 +
6158 + // If there is some error
6159 + if(!pagelayer_empty(data['error']) || pagelayer_empty(data['id'])){
6160 + pagelayer_show_msg('Unable to set preview for some reason', 'error');
6161 + return;
6162 + }
6163 +
6164 + var url = data['url']+'&preview_id='+pagelayer_postID+'&preview_nonce='+
6165 + pagelayer_preview_nonce;
6166 +
6167 + // Open in new tab
6168 + window.open(url, '_blank');
6169 + },
6170 + complete: function(){
6171 + pagelayer.$$('.pagelayer-body').css({'opacity' : '1'});
6172 + }
6173 + });
6174 + });
3011 6175 };
3012 6176
3013 6177
3014 6178 ///////////////////////////////
@@ -3014,89 +6178,298 @@
3014 6178 ///////////////////////////////
3015 6179 // Miscellaneuos Functions
3016 6180 ///////////////////////////////
3017 6181
3018 -// Generates a random string of "n" characters
3019 -function pagelayer_randstr(n, special){
3020 - var text = '';
3021 - var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
6182 +// Setup General options
6183 +function pagelayer_setup_general_options(){
3022 6184
3023 - special = special || 0;
3024 - if(special){
3025 - possible = possible + '&#$%@';
6185 + var holder = pagelayer.$$('.pagelayer-general-options');
6186 +
6187 + if(holder.children().length > 0){
6188 + return;
3026 6189 }
6190 +
6191 + // TODO: To create this HTML get Array form php
6192 + var html = '<div class="pagelayer-options-sections">'+
6193 + '<h5>'+ pagelayer_l('general_options') +'</h5>'+
6194 + '<div class="pagelayer-option-holder pagelayer-open-customizer">'+
6195 + '<i class="fas fa-paint-brush"></i>'+
6196 + '<span>'+ pagelayer_l('customize') +'</span>'+
6197 + '</div>'+
6198 + '</div>'+
6199 + '<div class="pagelayer-options-sections">'+
6200 + '<h5>'+ pagelayer_l('navigator_options') +'</h5>'+
6201 + '<div class="pagelayer-option-holder pagelayer-options-history-icon">'+
6202 + '<i class="pli pli-history"></i>'+
6203 + '<span>'+ pagelayer_l('historyand_revisions') +'</span>'+
6204 + '</div>'+
6205 + '<div class="pagelayer-option-holder pagelayer-options-navigator-icon">'+
6206 + '<i class="pli pli-tree"></i>'+
6207 + '<span>'+ pagelayer_l('navigator') +'</span>'+
6208 + '</div>'+
6209 + '<div class="pagelayer-option-holder pagelayer-options-preview">'+
6210 + '<i class="pli pli-eye"></i>'+
6211 + '<span>'+ pagelayer_l('preview_changes') +'</span>'+
6212 + '</div>'+
6213 + '</div>'+
6214 + '<div class="pagelayer-options-sections">'+
6215 + '<h5>'+ pagelayer_l('tools') +'</h5>'+
6216 + '<div class="pagelayer-option-holder pagelayer-open-help">'+
6217 + '<i class="fas fa-question"></i>'+
6218 + '<span>'+ pagelayer_l('help') +'</span>'+
6219 + '</div>'+
6220 + '<div class="pagelayer-option-holder pagelayer-open-keyboard-shortcuts">'+
6221 + '<i class="far fa-keyboard"></i>'+
6222 + '<span>'+ pagelayer_l('keyboard_shortcuts') +'</span>'+
6223 + '</div>'+
6224 + '</div>';
3027 6225
3028 - for(var i=0; i < n; i++){
3029 - text += possible.charAt(Math.floor(Math.random() * possible.length));
3030 - }
6226 + holder.html(html);
6227 +
6228 + // Open customizer settings
6229 + holder.find('.pagelayer-open-customizer').click(function(){
6230 + window.open(pagelayer_customizer_url+'&autofocus%5Bpanel%5D=pagelayer_settings', '_blank');
6231 + });
6232 +
6233 + // Open help / support link
6234 + holder.find('.pagelayer-open-help').click(function(){
6235 + window.open(pagelayer_support_url, '_blank');
6236 + });
6237 +
6238 + // Show Pagelayer History
6239 + holder.find('.pagelayer-options-history-icon').click(function(){
6240 + pagelayer.$$('.pagelayer-iframe-top-bar .pagelayer-history-icon').click();
6241 + });
6242 +
6243 + // Show Pagelayer Navigator
6244 + holder.find('.pagelayer-options-navigator-icon').click(function(){
6245 + pagelayer.$$('.pagelayer-iframe-top-bar .pagelayer-navigator-icon').click();
6246 + });
6247 +
6248 + // Show Pagelayer Preview
6249 + holder.find('.pagelayer-options-preview').click(function(){
6250 + pagelayer.$$('.pagelayer-iframe-top-bar .pagelayer-preview').click();
6251 + });
6252 +
6253 + // Show keyboard shortcut modal
6254 + holder.find('.pagelayer-open-keyboard-shortcuts').click(function() {
6255 +
6256 + var modal = pagelayer.$$('.pagelayer-shortcuts-modal');
6257 + modal.css('display','flex');
6258 +
6259 + modal.find('.pagelayer-editor-modal-close-icon').unbind('click');
6260 + modal.find('.pagelayer-editor-modal-close-icon').click(function(){
6261 + modal.hide();
6262 + });
3031 6263
3032 - return text;
3033 -};
6264 + modal.unbind('click');
6265 + modal.on('click', function(e){
6266 +
6267 + if(e.target != this) {
6268 + return;
6269 + }
3034 6270
3035 -function pagelayer_update_site_title(val){
3036 - if(!pagelayer_empty(val)){
3037 - var site_name = jQuery('.pagelayer-wp-title').attr('pagelayer-a-site_name');
3038 - if(!pagelayer_empty(site_name)){
3039 - var site_title = jQuery.ajax({
3040 - url: pagelayer_ajax_url+'&action=pagelayer_fetch_site_title',
3041 - type: 'post',
3042 - async: false
3043 - }).responseText;
6271 + modal.hide();
6272 + });
6273 + });
6274 +}
6275 +
6276 +// Setup navigator
6277 +function pagelayer_navigator_setup(){
6278 +
6279 + var navigator_ele = pagelayer.$$('#pagelayer-navigator'),
6280 + navigator_padding = 10,
6281 + navigator_html = '';
6282 +
6283 + // Get the child elements list
6284 + var pagelayer_create_navi_list = function(selector){
6285 +
6286 + var navigator_list = '';
6287 +
6288 + selector.children('.pagelayer-ele-wrap, .pagelayer-ele').each(function(){
3044 6289
3045 - if(site_title != site_name){
3046 - var site_title = jQuery.ajax({
3047 - url: pagelayer_ajax_url+'&action=pagelayer_update_site_title',
3048 - type: 'post',
3049 - data: {'site_title': site_name},
3050 - async: false
3051 - }).responseText;
6290 + var cEle = jQuery(this),
6291 + tag = pagelayer_tag(cEle),
6292 + id = pagelayer_id(cEle),
6293 + child_ele = false,
6294 + ele_class = '';
6295 +
6296 + // If tag is not found then return
6297 + if(pagelayer_empty(tag)){
6298 + return;
3052 6299 }
6300 +
6301 + // if is row or col or inner-row
6302 + if(tag == 'pl_row' || tag == 'pl_col' || tag == 'pl_inner_row'){
6303 + ele_class = 'pagelayer-navigator-toggle';
6304 + child_ele = true;
6305 + }
6306 +
6307 + navigator_list += '<div class="pagelayer-navigetor-ele" pagelayer-id="'+id+'">'+
6308 + '<div class="pagelayer-ele-name '+ ele_class +'" pagelayer-tag="'+tag+'" style="padding-left:'+navigator_padding+'px">'+
6309 + '<i class="fa pagalayer-arrow"></i><i class="fa pagelayer-'+tag+'"></i>'+
6310 + pagelayer_shortcodes[tag]['name']+
6311 + '<span class="pagelayer-navigator-options"><i class="pli pli-pencil" data-action="edit"></i><i class="pli pli-trashcan" data-action="delete"></i></span>'+
6312 + '</div>';
6313 +
6314 + // Create the list of child element
6315 + if(child_ele){
6316 + navigator_padding += 15; // Increment padding left for widget
6317 + navigator_list += pagelayer_create_navi_list( cEle.find(pagelayer_shortcodes[tag]['holder']).first() );
6318 + navigator_padding -= 15; // Decrement padding left for widget
6319 + }
6320 +
6321 + navigator_list += '</div>';
6322 + });
6323 +
6324 + return navigator_list;
6325 + }
6326 +
6327 + // Create list of all rows and their child widgets
6328 + jQuery(pagelayer_editable).children('.pagelayer-wrap-row').each(function(){
6329 + navigator_html += pagelayer_create_navi_list(jQuery(this));
6330 + });
6331 +
6332 + // Put the navigator list
6333 + navigator_ele.html('<div class="pagelayer-leftbar-prop-body">'+navigator_html+'</div>');
6334 +
6335 + // edit and delete element click handler
6336 + navigator_ele.find('.pagelayer-navigator-options .pli').on('click', function(event){
6337 +
6338 + var sEle = jQuery(this).closest('.pagelayer-navigetor-ele');
6339 + var sId = sEle.attr('pagelayer-id');
6340 + var action = jQuery(this).data('action');
6341 + if( action == 'edit'){
6342 + pagelayer_edit_element('[pagelayer-id = '+sId+']', event);
6343 + }else if(action == 'delete'){
6344 + sEle.find('.pagelayer-ele-name').css({'background':'rgb(255, 114, 114)','opacity':'0.5'});
6345 + pagelayer_delete_element('[pagelayer-id = '+sId+']');
3053 6346 }
6347 +
6348 + });
6349 +
6350 + // On click toggle the element
6351 + navigator_ele.find('.pagelayer-ele-name').on('click', function(){
6352 +
6353 + var tEle = jQuery(this);
6354 + var pl_id = tEle.parent().attr('pagelayer-id'); // Get Pagelayer id
6355 + var jEle = pagelayer_ele_by_id(pl_id);
6356 +
6357 + // If the class "pagelayer-navigator-toggle" exist then toggle
6358 + if(tEle.hasClass('pagelayer-navigator-toggle')){
6359 + tEle.parent().toggleClass('pagelayer-navigator-open');
6360 + }
6361 +
6362 + // Also open all parents
6363 + tEle.parent().parents('.pagelayer-navigetor-ele').addClass('pagelayer-navigator-open');
6364 +
6365 + // Set the click element active
6366 + navigator_ele.find('.pagelayer-ele-name').removeClass('pagelayer-navi-active');
6367 + tEle.addClass('pagelayer-navi-active')
6368 +
6369 + // Set the element active
6370 + if(jEle.length > 0){
6371 + //pagelayer_active.el = pagelayer_data(jEle);
6372 + pagelayer_set_active(jEle);
6373 + pagelayer_scroll_to_viewport(jEle);
6374 + }
6375 +
6376 + });
6377 +
6378 + // Do active ele tab open
6379 + if( pagelayer_active.el && pagelayer_active.el.id ){
6380 + navigator_ele.find('[pagelayer-id="'+pagelayer_active.el.id+'"]').children('.pagelayer-ele-name').click();
3054 6381 }
6382 +
6383 + /* var posY = 0, orig_eleY= 0;
6384 +
6385 + // On mouse down in pagelayer-ele-name
6386 + navigator_ele.find('.pagelayer-ele-name').on('mousedown', function(e){
6387 + e = e || window.event;
6388 + e.preventDefault();
6389 +
6390 + // Get ele position
6391 + orig_eleY = jQuery(this).offset().top;
6392 +
6393 + // Get the mouse cursor at startup:
6394 + posY = e.clientY;
6395 +
6396 + // The variable needs to be empty.
6397 + newMethod = '';
6398 +
6399 + // Mouse up handler
6400 + var ele_mousemove = function(){
6401 +
6402 + }
6403 +
6404 + // Mouse move handler
6405 + var ele_mouseup = function(){
6406 + pagelayer.$$(document).off('mouseup', ele_mouseup);
6407 + pagelayer.$$(document).off('mousemove', ele_mousemove);
6408 + }
6409 +
6410 + pagelayer.$$(document).on('mouseup', ele_mouseup);
6411 + pagelayer.$$(document).on('mousemove', ele_mousemove);
6412 +
6413 + }); */
6414 +
6415 +
3055 6416 }
3056 6417
3057 -function pagelayer_trim(str, charlist){
3058 - // discuss at: http://locutus.io/php/trim/
6418 +// Scroll page to element view port
6419 +function pagelayer_scroll_to_viewport(jEle, timeout, parentEle){
3059 6420
3060 - if(typeof str != 'string'){
3061 - return str;
3062 - }
6421 + var scrolled = parentEle || jQuery('html, body');
6422 + timeout = timeout || 500;
6423 + parentEle = parentEle || jQuery(window);
3063 6424
3064 - var whitespace = [' ', '\n', '\r', '\t', '\f', '\x0b', '\xa0', '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u2005', '\u2006', '\u2007', '\u2008', '\u2009', '\u200a', '\u200b', '\u2028', '\u2029', '\u3000' ].join('')
3065 - var l = 0
3066 - var i = 0
3067 - str += ''
6425 + setTimeout(function(){
6426 + var parentHeight = parentEle.height(),
6427 + parentScrollTop = parentEle.scrollTop(),
6428 + elementTop = jEle.offset().top,
6429 + topToCheck = elementTop - parentScrollTop;
6430 +
6431 + if (topToCheck > 0 && topToCheck < parentHeight) {
6432 + return;
6433 + }
3068 6434
3069 - if (charlist) {
3070 - whitespace = (charlist + '').replace(/([[\]().?/*{}+$^:])/g, '$1')
3071 - }
6435 + var scrolling = elementTop - parentHeight / 2;
6436 + scrolled.stop(true).animate({
6437 + scrollTop: scrolling
6438 + }, 1000);
6439 + }, timeout);
6440 +}
3072 6441
3073 - l = str.length
3074 - for (i = 0; i < l; i++) {
3075 - if (whitespace.indexOf(str.charAt(i)) === -1) {
3076 - str = str.substring(i)
3077 - break
3078 - }
6442 +// Generates a random string of "n" characters
6443 +function pagelayer_randstr(n, special){
6444 + var text = '';
6445 + var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
6446 +
6447 + special = special || 0;
6448 + if(special){
6449 + possible = possible + '&#$%@';
3079 6450 }
3080 -
3081 - l = str.length
3082 - for (i = l - 1; i >= 0; i--) {
3083 - if (whitespace.indexOf(str.charAt(i)) === -1) {
3084 - str = str.substring(0, i + 1)
3085 - break
3086 - }
6451 +
6452 + for(var i=0; i < n; i++){
6453 + text += possible.charAt(Math.floor(Math.random() * possible.length));
3087 6454 }
3088 6455
3089 - return whitespace.indexOf(str.charAt(0)) === -1 ? str : ''
6456 + return text;
3090 6457 };
3091 6458
6459 +function pagelayer_randInt(max) {
6460 + return Math.floor(Math.random() * Math.floor(max));
6461 +}
6462 +
3092 6463 // Convert the regular URL of a Video to a Embed URL
3093 -function pagelayer_video_url(src){
3094 -
6464 +function pagelayer_video_url(src, no_url){
6465 +
6466 + no_url = no_url || false;
3095 6467 var youtubeRegExp = /youtube\.com|youtu\.be/;
3096 6468 var vimeoRegExp = /vimeo\.com/;
3097 6469 var match = '';
3098 6470 var videoId = '';
6471 + var vid_params = {};
3099 6472
3100 6473 if (youtubeRegExp.exec(src)) {
3101 6474 match = 'youtube';
3102 6475 } else if (vimeoRegExp.exec(src)) {
@@ -3123,9 +6496,15 @@
3123 6496 } else if (youtube.exec(src)) {
3124 6497 videoId = src.split('.be/');
3125 6498 }
3126 6499
3127 - return '//youtube.com/embed/'+videoId[1];
6500 + vid_params = {
6501 + type : 'youtube',
6502 + src : '//www.youtube.com/embed/'+videoId[1],
6503 + id : videoId[1]
6504 + };
6505 +
6506 + pagelayer_yt_api_register();
3128 6507
3129 6508 break;
3130 6509
3131 6510 case 'vimeo':
@@ -3138,22 +6517,51 @@
3138 6517 } else if (vimeoRegExp.exec(src)) {
3139 6518 videoId = src.split('.com/');
3140 6519 }
3141 6520
3142 - return '//player.vimeo.com/video/'+videoId[1];
6521 + vid_params = {
6522 + type : 'vimeo',
6523 + src : '//player.vimeo.com/video/'+videoId[1],
6524 + id : videoId[1]
6525 + };
3143 6526
3144 6527 break;
3145 6528 default:
3146 - return src;
6529 + vid_params = {
6530 + type : 'local',
6531 + src : src
6532 + };
6533 +
3147 6534 }
6535 +
6536 + if(!no_url){
6537 + return vid_params.src;
6538 + }
6539 +
6540 + return vid_params;
3148 6541 };
3149 6542
6543 +// Youtube API Register
6544 +function pagelayer_yt_api_register(){
6545 +
6546 + if(jQuery('#pagelayer-youtube-script-js').length > 0){
6547 + return;
6548 + }
6549 +
6550 + jQuery('body').append('<script src="https://www.youtube.com/iframe_api" id="pagelayer-youtube-script-js"></script>');
6551 +
6552 +}
6553 +
3150 6554 // Add widget section
3151 6555 function pagelayer_add_widget(){
3152 6556
3153 6557 html='<div class="pagelayer-add-widget-area">'+
3154 - '<i class="pagelayer-add-row fa fa-plus-circle"></i>'+
3155 - '<p>Click here to add new row OR drag widgets</p>'+
6558 + '<div class="pagelayer-add-buttons-container">'+
6559 + '<button type="button" class="pagelayer-add-circle-btn pagelayer-add-circle-plus" title="Add New Row"><i class="fas fa-plus"></i></button>'+
6560 + '<button type="button" class="pagelayer-add-circle-btn pagelayer-add-circle-folder pagelayer-add-section" title="Add Template"><i class="fas fa-folder"></i></button>'+
6561 + '<button type="button" class="pagelayer-add-circle-btn pagelayer-add-circle-ai pagelayer-add-ai" title="Build with AI"><i class="fas fa-magic"></i></button>'+
6562 + '</div>'+
6563 + '<p class="pagelayer-add-widget-text">Click here to add new row OR drag widgets</p>'+
3156 6564 '</div>';
3157 6565
3158 6566 jQuery(pagelayer_editable).append(html);
3159 6567
@@ -3159,27 +6567,38 @@
3159 6567
3160 6568 var add_area = jQuery('.pagelayer-add-widget-area');
3161 6569
3162 6570 // Add a code before this
3163 - var add_sc = function(tag){
6571 + var add_sc = function(tag, global_id = ''){
3164 6572
6573 + var attr = '';
6574 + if(!pagelayer_empty(global_id)){
6575 + attr = ' pagelayer-global-id="'+global_id+'" ';
6576 + }
6577 +
3165 6578 // Create Row
3166 - var row = jQuery('<div pagelayer-tag="pl_row"></div>');
6579 + var row = jQuery('<div pagelayer-tag="pl_row" '+((tag == 'pl_row') ? attr : '') +'></div>');
3167 6580 add_area.before(row);
3168 6581 var row_id = pagelayer_onadd(row, false);
3169 6582 var rEle = pagelayer_ele_by_id(row_id);
3170 6583
3171 - if(tag == 'pl_row'){
6584 + if(tag == 'pl_row' && !pagelayer_empty(global_id)){
3172 6585 rEle.click();
3173 6586 return row_id;
3174 6587 }
3175 6588
3176 6589 // Create Column
3177 - var col = jQuery('<div pagelayer-tag="pl_col"></div>');
6590 + var col = jQuery('<div pagelayer-tag="pl_col" '+((tag == 'pl_col') ? attr : '') +'></div>');
3178 6591 rEle.find('.pagelayer-row-holder').append(col);
3179 6592 var col_id = pagelayer_onadd(col, false);
3180 6593 var cEle = pagelayer_ele_by_id(col_id);
3181 6594
6595 +
6596 + if(tag == 'pl_row'){
6597 + rEle.click();
6598 + return row_id;
6599 + }
6600 +
3182 6601 if(tag == 'pl_col'){
3183 6602 cEle.click();
3184 6603 return col_id;
3185 6604 }
@@ -3184,25 +6603,66 @@
3184 6603 return col_id;
3185 6604 }
3186 6605
3187 6606 // Create element
3188 - var ele = jQuery('<div pagelayer-tag="'+tag+'"></div>');
6607 + var ele = jQuery('<div pagelayer-tag="'+tag+'" '+attr+'></div>');
3189 6608 cEle.find('.pagelayer-col-holder').append(ele);
6609 + //console.log(ele);
3190 6610 var id = pagelayer_onadd(ele);
3191 -
6611 + //console.log(id);
6612 + //console.log(col_id);
6613 + var eEle = pagelayer_ele_by_id(col_id);
6614 + //console.log(eEle);
3192 6615 // Ensure the column is not empty
3193 6616 pagelayer_empty_col(cEle.find('.pagelayer-col-holder'));
3194 6617
6618 + if(tag == 'pl_inner_row' && pagelayer_empty(global_id)){
6619 + // Create Column
6620 + var in_col = jQuery('<div pagelayer-tag="pl_col"></div>');
6621 + eEle.find('.pagelayer-row-holder').append(in_col);
6622 + var in_col_id = pagelayer_onadd(in_col, false);
6623 + }
6624 +
3195 6625 return id;
3196 6626
3197 6627 }
3198 6628
3199 - // Handle Click
3200 - add_area.on('click', function(e){
6629 + // Handle Click on Plus Button
6630 + add_area.find('.pagelayer-add-circle-plus').on('click', function(e){
3201 6631 e.stopPropagation();
3202 6632 add_sc('pl_col');
3203 6633 });
3204 6634
6635 + // Handle Click on Template/Folder Button
6636 + add_area.find('.pagelayer-add-section').on('click', function(e){
6637 + e.stopPropagation();
6638 + pagelayer_add_section_area();// Setup and show sections modal
6639 + });
6640 +
6641 + // Handle Click on Build with AI Button
6642 + add_area.find('.pagelayer-add-ai, .pagelayer-add-circle-ai').on('click', function(e){
6643 + e.stopPropagation();
6644 + if(typeof PagelayerAI !== 'undefined' && PagelayerAI.showPanel){
6645 + PagelayerAI.showPanel();
6646 + } else if(typeof window.parent !== 'undefined' && typeof window.parent.PagelayerAI !== 'undefined' && window.parent.PagelayerAI.showPanel){
6647 + window.parent.PagelayerAI.showPanel();
6648 + } else if(jQuery('.pagelayer-ai-topbar-btn').length > 0){
6649 + jQuery('.pagelayer-ai-topbar-btn').trigger('click');
6650 + } else if(window.parent && window.parent.jQuery && window.parent.jQuery('.pagelayer-ai-topbar-btn').length > 0){
6651 + window.parent.jQuery('.pagelayer-ai-topbar-btn').trigger('click');
6652 + }
6653 + });
6654 +
6655 +
6656 +
6657 + // Background click fallback (adds column if clicked outside circles)
6658 + add_area.on('click', function(e){
6659 + if(e.target === this || jQuery(e.target).hasClass('pagelayer-add-widget-text')){
6660 + e.stopPropagation();
6661 + add_sc('pl_col');
6662 + }
6663 + });
6664 +
3205 6665 // Handle Drag over
3206 6666 add_area.on('dragover', function(e){
3207 6667 //console.log(e)
3208 6668 add_area.addClass('pagelayer-add-widget-drag');
@@ -3222,8 +6682,9 @@
3222 6682 add_area.removeClass('pagelayer-add-widget-drag');
3223 6683 jQuery('.pagelayer-is-dragging').removeClass('pagelayer-is-dragging');
3224 6684
3225 6685 var tag = e.originalEvent.dataTransfer.getData('tag');
6686 + var global_id = e.originalEvent.dataTransfer.getData('global_id');
3226 6687
3227 6688 // Is it an existing element ?
3228 6689 if(tag.length < 1){
3229 6690 return false;
@@ -3232,7 +6693,1490 @@
3232 6693 e.preventDefault();
3233 6694
3234 6695 //console.log(tag);
3235 6696
3236 - add_sc(tag);
6697 + add_sc(tag, global_id);
3237 6698 });
6699 +};
6700 +
6701 +// Is the element in view while scrolling
6702 +function pagelayer_isElementInView(elem, holder, partial) {
6703 + partial = partial || true;
6704 + var container = jQuery(holder);
6705 + var contHeight = container.height();
6706 + var contTop = container.scrollTop();
6707 + var contBottom = contTop + contHeight ;
6708 +
6709 + var elemTop = jQuery(elem).offset().top - container.offset().top;
6710 + var elemBottom = elemTop + jQuery(elem).height();
6711 +
6712 + var isTotal = (elemTop >= 0 && elemBottom <=contHeight);
6713 + var isPart = ((elemTop < 0 && elemBottom > 0 ) || (elemTop > 0 && elemTop <= container.height())) && partial;
6714 +
6715 + return isTotal || isPart ;
3238 6716 }
6717 +
6718 +// Append section modal into body
6719 +function pagelayer_add_section_area(){
6720 +
6721 + var body = pagelayer.$$('body');
6722 + var mEle = body.find('.pagelayer-add-section-modal-container');
6723 +
6724 + if(mEle.length > 0){
6725 + mEle.show();
6726 + return;
6727 + }
6728 +
6729 + var section_modal = '<div class="pagelayer-add-section-modal-container">'+
6730 + '<div class="pagelayer-add-section-modal-holder">'+
6731 + '<div class="pagelayer-add-section-modal">'+
6732 + '<div class="pagelayer-add-section-modal-header">'+
6733 + '<div>Add Sections</div>'+
6734 + '<div class="pagelayer-section-type-div">Type : '+
6735 + '<select name="type" id="pagelayer-section-type">'+
6736 + '<option value="section">Sections</option>'+
6737 + '<option value="header">Headers</option>'+
6738 + '<option value="footer">Footers</option>'+
6739 + '<option value="page">Pages</option>'+
6740 + '</select>'+
6741 + '</div>'+
6742 + '<div class="pagelayer-add-section-modal-close">&times;</div>'+
6743 + '</div>'+
6744 + '<div class="pagelayer-add-section-modal-row">'+
6745 + '<div class="pagelayer-add-section-modal-left">'+
6746 + '<div class="pagelayer-section-search-div">'+
6747 + '<i class="pli pli-search" ></i><input class="pagelayer-section-search" /><span class="pagelayer-sf-empty pli">&times;</span>'+
6748 + '</div>'+
6749 + '<div class="pagelayer-section-tags-holder"></div>'+
6750 + '</div>'+
6751 + '<div class="pagelayer-section-modal-body-holder">'+
6752 + '<div class="pagelayer-add-section-modal-body"></div>'+
6753 + '</div>'+
6754 + '</div>'+
6755 + '<div class="pagelayer-add-section-modal-overlay" style="display:none;">'+
6756 + '<div class="pagelayer-section-wait">'+
6757 + '<div class="pagelayer-loader">'+
6758 + '<div class="pagelayer-percent-parent"></div>'+
6759 + '</div><br/>'+
6760 + '<span>Please wait a moment</span>'+
6761 + '</div>'+
6762 + '</div>'+
6763 + '</div>'+
6764 + '</div>'+
6765 + '</div>';
6766 +
6767 + mEle = jQuery(section_modal);
6768 +
6769 + // Append the element in the body
6770 + body.append(mEle);
6771 +
6772 + // On click close modal
6773 + mEle.find('.pagelayer-add-section-modal-close').on('click', function(){
6774 + mEle.hide();
6775 + });
6776 +
6777 + // Search Empty
6778 + mEle.find('.pagelayer-sf-empty').on('click', function(){
6779 + mEle.find('.pagelayer-section-search').val('');
6780 + });
6781 +
6782 + // On select section type
6783 + mEle.find('#pagelayer-section-type').on('change', function(){
6784 + var val = jQuery(this).val();
6785 + pagelayer_add_sections_list_setup(val);
6786 + });
6787 +
6788 + // Append the list items into modal body
6789 + pagelayer_add_sections_list_setup();
6790 +
6791 + mEle.show();// Show the modal
6792 +
6793 +};
6794 +
6795 +// Append section list into modal body
6796 +function pagelayer_add_sections_list_setup(type){
6797 +
6798 + var mEle = pagelayer.$$('.pagelayer-add-section-modal-container');
6799 + var body = mEle.find('.pagelayer-add-section-modal-body');
6800 + var add_area = jQuery('.pagelayer-add-widget-area');
6801 + type = type || 'section';
6802 +
6803 + // Find the number of cols
6804 + var body_width = jQuery(window.parent).width();
6805 + var num_cols = 3;
6806 + if(body_width >= 1500){
6807 + num_cols = 4;
6808 + }else if(body_width >= 992){
6809 + num_cols = 3;
6810 + }else if(body_width >= 768){
6811 + num_cols = 2;
6812 + }else if(body_width >= 360){
6813 + num_cols = 1;
6814 + }
6815 + //console.log(num_cols+' - '+body_width);
6816 +
6817 + var viewer = '<div class="pagelayer-section-is-visible"></div>';
6818 + var selected_tags = {};
6819 + var result_set = {};
6820 +
6821 + // Setup the scroll
6822 + mEle.find('.pagelayer-section-tags-holder').slimScroll({
6823 + height: 'calc(100vh - 150px)',
6824 + railVisible: false,
6825 + alwaysVisible: true,
6826 + color: '#000',
6827 + size: '5px',
6828 + });
6829 +
6830 + // Create list of items
6831 + var pagelayer_section_list = function(){
6832 +
6833 + // List the tags
6834 + if(!pagelayer_empty(pagelayer_add_section_data[type]['tags'])){
6835 + var tags_html = '';
6836 + var tags = pagelayer_add_section_data[type]['tags'];
6837 + for(var k in tags){
6838 + tags_html += '<span class="pagelayer-section-tags" tag="'+k+'">'+k+' ('+tags[k].length+')</span>';
6839 + }
6840 + mEle.find('.pagelayer-section-tags-holder').html(tags_html);
6841 +
6842 + // Handle tag click
6843 + mEle.find('.pagelayer-section-tags').unbind('click');
6844 + mEle.find('.pagelayer-section-tags').on('click', function(e){
6845 +
6846 + var search = mEle.find('.pagelayer-section-search');
6847 +
6848 + // Blank the search
6849 + if(search.val().length > 0){
6850 + search.val('');
6851 + selected_tags = {};
6852 + }
6853 +
6854 + // Fill the selected_tags
6855 + tEle = jQuery(this);
6856 + var tag = tEle.attr('tag')
6857 +
6858 + if(tEle.attr('on') == '1'){
6859 + delete selected_tags[tag];
6860 + tEle.removeAttr('on');
6861 + }else{
6862 + tEle.attr('on', 1);
6863 + selected_tags[tag] = 1;
6864 + }
6865 +
6866 + // Filter
6867 + pagelayer_section_filter(false, 1);
6868 +
6869 + });
6870 + }
6871 +
6872 + // Fill in the result
6873 + result_set = { ...pagelayer_add_section_data[type]['list']};
6874 +
6875 + show_result();
6876 +
6877 + };
6878 +
6879 + // How the result and setup scroll
6880 + var show_result = function(){
6881 +
6882 + var html = '';
6883 + for(var i = 0; i < num_cols; i++){
6884 + html += '<div class="pagelayer-section-holder" pagelayer-section-type="'+type+'" num="'+i+'"></div>';
6885 + }
6886 +
6887 + // Blank the body
6888 + body.html(html+viewer);
6889 +
6890 + mEle.find('.pagelayer-section-modal-body-holder').unbind('scroll');
6891 + mEle.find('.pagelayer-section-modal-body-holder').on('scroll', pagelayer_section_body_scroll);
6892 + pagelayer_section_body_scroll();
6893 + }
6894 +
6895 + var scroll_accessed = false;
6896 +
6897 + // Section body ON scroll
6898 + var pagelayer_section_body_scroll = function(){
6899 +
6900 + // Check if there is anything to display in the first place, as we do delete pagelayer_add_section_data
6901 + if(pagelayer_empty(result_set)){
6902 + return;
6903 + }
6904 +
6905 + var tester = mEle.find('.pagelayer-section-is-visible');
6906 + var modal = mEle.find('.pagelayer-section-modal-body-holder');
6907 +
6908 + // If we have scroll
6909 + if(!pagelayer_isElementInView(tester, modal) || scroll_accessed){
6910 + return;
6911 + }
6912 +
6913 + scroll_accessed = true;
6914 +
6915 + var html = '';
6916 + var i = 0;
6917 +
6918 + // Loop result_set
6919 + for(var id in result_set){
6920 +
6921 + if(i >= (num_cols * 5)){
6922 + break;
6923 + }
6924 +
6925 + var col = i % num_cols;
6926 + //console.log(col);
6927 +
6928 + i++;
6929 +
6930 + var pro = 0;
6931 +
6932 + // Is it pro ?
6933 + if(!pagelayer_empty(result_set[id]) && pagelayer_empty(pagelayer_pro)){
6934 + pro = 1;
6935 + }
6936 +
6937 + html = '<div class="pagelayer-section-item" pagelayer-section-type="'+type+'" pagelayer-add-section-id="'+id+'">'+
6938 + '<img src="'+ pagelayer_add_section_data[type]['image_url'] + id +'/screenshot.jpg" alt="Pagelayer code screenshot" />'+
6939 + (pro ? '<div class="pagelayer-section-pro-req">Pro</div><div class="pagelayer-section-pro-txt">'+pagelayer.pro_txt+'</div>' : '')+
6940 + '</div>';
6941 +
6942 + body.find('.pagelayer-section-holder[num='+col+']').append(html);
6943 +
6944 + delete result_set[id];
6945 +
6946 + }
6947 +
6948 + //console.log(result_set);
6949 +
6950 + mEle.find('.pagelayer-section-item').unbind('click');
6951 + mEle.find('.pagelayer-section-item').on('click', function(e){
6952 + pagelayer_section_item_clickable(jQuery(this));
6953 + });
6954 +
6955 + scroll_accessed = false;
6956 +
6957 + }
6958 +
6959 + // If we have searched something / or clicked tags
6960 + var pagelayer_section_filter = function(event, not_input){
6961 +
6962 + var txt = mEle.find('.pagelayer-section-search').val();
6963 + var tags = pagelayer_add_section_data[type]['tags'];
6964 +
6965 + // Searched anything
6966 + if(!pagelayer_empty(txt) || pagelayer_empty(not_input)){
6967 +
6968 + // Blank the tags
6969 + selected_tags = {};
6970 +
6971 + mEle.find('.pagelayer-section-tags').removeAttr('on');
6972 +
6973 + for(var k in tags){
6974 + if(k.search(txt) >= 0){
6975 + selected_tags[k] = 1;
6976 + mEle.find('.pagelayer-section-tags[tag="'+k+'"]').attr('on', 1);
6977 + }
6978 + }
6979 +
6980 + }
6981 +
6982 + var new_result = {};
6983 + var new_length = 0;
6984 +
6985 + // Filter the content
6986 + for(var t in selected_tags){
6987 +
6988 + for(var i in tags[t]){
6989 + new_length++;
6990 + new_result[tags[t][i]] = tags[t][i];
6991 + }
6992 +
6993 + }
6994 +
6995 + // Copy the result
6996 + result_set = {...new_result};
6997 + //console.log(type);console.log(selected_tags);console.log(result_set);
6998 +
6999 + show_result();
7000 +
7001 + }
7002 +
7003 + // On search change
7004 + mEle.find('.pagelayer-section-search').unbind('input');
7005 + mEle.find('.pagelayer-section-search').on('input', pagelayer_section_filter);
7006 +
7007 + // On click items
7008 + var pagelayer_section_item_clickable = function(jEle){
7009 +
7010 + var section_id = jEle.attr('pagelayer-add-section-id');
7011 +
7012 + // IF section id not found
7013 + if(pagelayer_empty(section_id)){
7014 + return false;
7015 + }
7016 +
7017 + if(jEle.find('.pagelayer-section-pro-req').length > 0){
7018 + return false;
7019 + }
7020 +
7021 + // Show the overlay
7022 + mEle.find('.pagelayer-add-section-modal-overlay').show();
7023 +
7024 + // Do shortcode the content
7025 + jQuery.ajax({
7026 + url: pagelayer_ajax_url+'&action=pagelayer_get_section_shortcodes&postID='+pagelayer_postID,
7027 + type: 'POST',
7028 + data: {
7029 + 'pagelayer_nonce': pagelayer_ajax_nonce,
7030 + 'pagelayer_section_id': section_id,
7031 + 'pagelayer-live': 1
7032 + },
7033 + success: function(data) {
7034 +
7035 + try{
7036 +
7037 + var data = JSON.parse(data);
7038 +
7039 + if(!pagelayer_empty(data['error'])){
7040 + pagelayer_show_msg('Error getting the section', 'error');
7041 + mEle.find('.pagelayer-add-section-modal-overlay').hide();
7042 + mEle.hide();
7043 + return;
7044 + }
7045 +
7046 + var cEle = jQuery(data['code']);
7047 +
7048 + // Add section before add widget area
7049 + add_area.before(cEle);
7050 +
7051 + // We need to it setup
7052 + cEle.each(function(){
7053 + var pl_id = pagelayer_id(jQuery(this));
7054 +
7055 + if(!pagelayer_empty(pl_id)){
7056 + pagelayer_element_setup('[pagelayer-id="'+pl_id+'"], [pagelayer-id='+pl_id+'] .pagelayer-ele', true);
7057 + }
7058 + });
7059 +
7060 + }catch(e){
7061 + pagelayer_show_msg('Error getting the section', 'error');
7062 + mEle.find('.pagelayer-add-section-modal-overlay').hide();
7063 + mEle.hide();
7064 + return;
7065 + }
7066 +
7067 + },
7068 + complete: function(){
7069 + mEle.find('.pagelayer-add-section-modal-overlay').hide();
7070 + mEle.hide();
7071 + }
7072 + });
7073 + }
7074 +
7075 + // Load the data if not there
7076 + if(!(type in pagelayer_add_section_data)){
7077 +
7078 + // Show the loading
7079 + mEle.find('.pagelayer-add-section-modal-overlay').show();
7080 +
7081 + // Get the sections list data and append it
7082 + jQuery.ajax({
7083 + url: pagelayer_api_url+'/library.php?give='+type,
7084 + type: 'post',
7085 + success: function(response){
7086 + var tmp = JSON.parse(response);
7087 +
7088 + // Is the list there ?
7089 + if( !('list' in tmp && !pagelayer_empty(tmp['list'])) ){
7090 + return;
7091 + }
7092 +
7093 + pagelayer_add_section_data[type] = tmp;
7094 +
7095 + // Create the Type
7096 + pagelayer_section_list(type);
7097 +
7098 + // Hide the loading
7099 + mEle.find('.pagelayer-add-section-modal-overlay').hide();
7100 +
7101 + },
7102 + complete: function(){
7103 + mEle.find('.pagelayer-add-section-modal-overlay').hide();
7104 + }
7105 + });
7106 +
7107 + // We have the data, so show it
7108 + }else{
7109 + pagelayer_section_list(type);
7110 + }
7111 +}
7112 +
7113 +// Upload an image
7114 +function pagelayer_upload_image(fileName, blob, pagelayer_ajax_func){
7115 +
7116 + var formData = new FormData();
7117 + formData.append('action', 'upload-attachment');
7118 + formData.append('_ajax_nonce', pagelayer_media_ajax_nonce);
7119 + formData.append('async-upload', blob, fileName);
7120 +
7121 + jQuery.ajax({
7122 + url:pagelayer_ajax_url,
7123 + data: formData,// the formData function is available in almost all new browsers.
7124 + type:"post",
7125 + contentType:false,
7126 + processData:false,
7127 + cache:false,
7128 + beforeSend: function( xhr ) {
7129 + if(typeof pagelayer_ajax_func.beforeSend == 'function'){
7130 + pagelayer_ajax_func.beforeSend(xhr);
7131 + }
7132 + },
7133 + xhr: function() {
7134 + var xhr = new window.XMLHttpRequest();
7135 + if(typeof pagelayer_ajax_func.uploadProgress == 'function'){
7136 + xhr = pagelayer_ajax_func.uploadProgress(xhr);
7137 + }
7138 + return xhr;
7139 + },
7140 + error:function(err){
7141 + //console.error(err);
7142 + pagelayer_show_msg('Unable to upload image for some reason.', 'error');
7143 + },
7144 + success:function(response){
7145 + var obj = jQuery.parseJSON(response);
7146 + if(typeof pagelayer_ajax_func.success == 'function'){
7147 + pagelayer_ajax_func.success(obj);
7148 + }
7149 + },
7150 + complete:function(xhr){
7151 + if(typeof pagelayer_ajax_func.complete == 'function'){
7152 + pagelayer_ajax_func.complete(xhr);
7153 + }
7154 + }
7155 + });
7156 +};
7157 +
7158 +// On editable area image paste handler
7159 +function pagelayer_editable_paste_handler(pasteEvent, pagelayer_ajax_func){
7160 + var items,
7161 + is_Paste = (pasteEvent.type == 'paste' ? true : false),
7162 + mustPreventDefault = false,
7163 + reader;
7164 +
7165 + try {
7166 + if(is_Paste){
7167 + items = (pasteEvent.originalEvent || pasteEvent).clipboardData.items;
7168 + }else{
7169 + items = [pasteEvent];
7170 + }
7171 +
7172 + for (var i = items.length - 1; i >= 0; i -= 1) {
7173 +
7174 + if (items[i].type.match(/^image\//)) {
7175 +
7176 + reader = new FileReader();
7177 + /* jshint -W083 */
7178 + reader.onloadend = function(event) {
7179 +
7180 + var src = event.target.result;
7181 +
7182 + if(src.indexOf('data:image') === 0 ) {
7183 +
7184 + var block = src.split(";");
7185 + var contentType = block[0].split(":")[1];
7186 + var realData = block[1].split(",")[1];
7187 + if(is_Paste){
7188 + var fileName = "image."+contentType.split("/")[1];
7189 + }else{
7190 + var fileName = items[0]['name'];
7191 + }
7192 +
7193 + // Convert it to a blob to upload
7194 + var blob = pagelayer_b64toBlob(realData, contentType);
7195 +
7196 + pagelayer_upload_image(fileName, blob, pagelayer_ajax_func);
7197 +
7198 + }
7199 +
7200 + };
7201 + /* jshint +W083 */
7202 + if(is_Paste){
7203 + reader.readAsDataURL(items[i].getAsFile());
7204 + }else{
7205 + reader.readAsDataURL(items[i]);
7206 + }
7207 + mustPreventDefault = true;
7208 + }
7209 + }
7210 +
7211 + if(mustPreventDefault && is_Paste){
7212 + pasteEvent.stopPropagation();
7213 + pasteEvent.preventDefault();
7214 + }
7215 +
7216 + }catch(err){
7217 + console.log(err);
7218 + }
7219 +
7220 + return mustPreventDefault;
7221 +
7222 +}
7223 +
7224 +// Convert base64 to Blob
7225 +function pagelayer_b64toBlob(b64Data, contentType, sliceSize) {
7226 + contentType = contentType || '';
7227 + sliceSize = sliceSize || 512;
7228 +
7229 + var byteCharacters = atob(b64Data);
7230 + var byteArrays = [];
7231 +
7232 + for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
7233 + var slice = byteCharacters.slice(offset, offset + sliceSize);
7234 +
7235 + var byteNumbers = new Array(slice.length);
7236 + for (var i = 0; i < slice.length; i++) {
7237 + byteNumbers[i] = slice.charCodeAt(i);
7238 + }
7239 +
7240 + var byteArray = new Uint8Array(byteNumbers);
7241 +
7242 + byteArrays.push(byteArray);
7243 + }
7244 +
7245 + var blob = new Blob(byteArrays, {type: contentType});
7246 + return blob;
7247 +}
7248 +
7249 +// Function to check if the URL is external
7250 +function pagelayer_parse_theme_vars(img_url){
7251 +
7252 + for(x in pagelayer_theme_vars){
7253 + img_url = img_url.replace(x, pagelayer_theme_vars[x]);
7254 + }
7255 +
7256 + return img_url;
7257 +};
7258 +
7259 +// Tooltip Setup for Editor
7260 +function pagelayer_tooltip_setup(){
7261 + //pagelayer.$$('[data-tlite]').each(function(){pagelayer_tlite.show(jQuery(this).get(0));});return;
7262 + pagelayer.$$('[data-tlite]').hover(function(){
7263 + pagelayer_tlite.show(jQuery(this).get(0));
7264 + }, function(){
7265 + pagelayer_tlite.hide(jQuery(this).get(0));
7266 + });
7267 +
7268 +};
7269 +
7270 +// Pagelayer Messages
7271 +function pagelayer_show_msg(msg, state, time){
7272 +
7273 + time = time || 5000;
7274 + state = !pagelayer_empty(state) ? 'pagelayer-editor-msg-state-'+state : '';
7275 + var nholder = pagelayer.$$('.pagelayer-editor-notice');
7276 + var mEle = jQuery('<div class="pagelayer-editor-msg '+state+'">'+msg+' <span class="pli pli-cross pagelayer-notice-x"></span></div>');
7277 +
7278 + nholder.append(mEle);
7279 +
7280 + mEle.find('.pagelayer-notice-x').on('click', function(){
7281 + mEle.css({opacity: 0});
7282 + setTimeout(function(){
7283 + mEle.css({transition: 'none'});
7284 + mEle.slideUp(function(){
7285 + mEle.remove();
7286 + });
7287 + }, 900);
7288 + });
7289 +
7290 + setTimeout(function(){
7291 + mEle.find('.pagelayer-notice-x').click();
7292 + }, time);
7293 +
7294 +}
7295 +
7296 +// Pagelayer confirmation box
7297 +function pagelayer_confirmation_box(message, yesCallback, noCallback, yesText, noText) {
7298 +
7299 + yesText = yesText || pagelayer_l('Yes');
7300 + noText = noText || pagelayer_l('No');
7301 +
7302 + var dialog = jQuery('<div class="pagelayer-confirm-box-holder">'+
7303 + '<div class="pagelayer-confirm-box" style="border-radius:5px">'+
7304 + '<div class="pagelayer-confirmation-msg">'+ message +'</div>'+
7305 + '<center>'+
7306 + '<span class="pagelayer-btnyes button button-pagelayer">'+ yesText +'</span>&nbsp;&nbsp;&nbsp;'+
7307 + '<span class="pagelayer-btnno button button-pagelayer">'+ noText +'</span>'+
7308 + '</center>'+
7309 + '</div>'+
7310 + '</div>');
7311 +
7312 + pagelayer.$$('body').append(dialog);
7313 +
7314 + dialog.find('.pagelayer-btnyes').on('click', function() {
7315 + dialog.remove();
7316 + if(typeof yesCallback == 'function'){
7317 + yesCallback();
7318 + }
7319 + });
7320 + dialog.find('.pagelayer-btnno').on('click', function() {
7321 + dialog.remove();
7322 + if(typeof noCallback == 'function'){
7323 + noCallback();
7324 + }
7325 + });
7326 + dialog.show();
7327 +}
7328 +
7329 +function pagelayer_trim(str, charlist){
7330 + // discuss at: http://locutus.io/php/trim/
7331 +
7332 + if(typeof str != 'string'){
7333 + return str;
7334 + }
7335 +
7336 + var whitespace = [' ', '\n', '\r', '\t', '\f', '\x0b', '\xa0', '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u2005', '\u2006', '\u2007', '\u2008', '\u2009', '\u200a', '\u200b', '\u2028', '\u2029', '\u3000' ].join('');
7337 + var l = 0;
7338 + var i = 0;
7339 + str += '';
7340 +
7341 + if (charlist) {
7342 + whitespace = (charlist + '').replace(/([[\]().?/*{}+$^:])/g, '$1');
7343 + }
7344 +
7345 + l = str.length;
7346 + for (i = 0; i < l; i++) {
7347 + if (whitespace.indexOf(str.charAt(i)) === -1) {
7348 + str = str.substring(i);
7349 + break;
7350 + }
7351 + }
7352 +
7353 + l = str.length;
7354 + for (i = l - 1; i >= 0; i--) {
7355 + if (whitespace.indexOf(str.charAt(i)) === -1) {
7356 + str = str.substring(0, i + 1);
7357 + break;
7358 + }
7359 + }
7360 +
7361 + return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
7362 +};
7363 +
7364 +function pagelayer_ucwords(str) {
7365 + return (str + '').replace(/^([a-z])|\s+([a-z])/g, function ($1) {
7366 + return $1.toUpperCase();
7367 + });
7368 +}
7369 +
7370 +// Check length for string and object
7371 +function pagelayer_length(mixed_var) {
7372 +
7373 + var length = 0;
7374 + var undef, key, i, len;
7375 + var emptyValues = [undef, null, false];
7376 +
7377 + for(i = 0, len = emptyValues.length; i < len; i++) {
7378 + if (mixed_var === emptyValues[i]) {
7379 + return length;
7380 + }
7381 + }
7382 +
7383 + // Is array, object or jQuery object?
7384 + if(typeof mixed_var === 'object'){
7385 +
7386 + // If is jQuery object
7387 + if( mixed_var.hasOwnProperty('length')){
7388 + return mixed_var.length;
7389 + }
7390 +
7391 + for (key in mixed_var) {
7392 + // TODO: should we check for own properties only?
7393 + //if ( .hasOwnProperty(key)) {
7394 + length++;
7395 + //}
7396 + }
7397 +
7398 + return length;
7399 + }
7400 +
7401 + length = String(mixed_var).length;
7402 +
7403 + return length;
7404 +};
7405 +
7406 +// Create Widget list dropdown
7407 +function pagelayer_create_widget_tooltip(){
7408 +
7409 + var html = '<div class="pagelayer-widget-tooltip">'+
7410 + '<div class="pagelayer-widget-search-holder">'+
7411 + '<div class="pagelayer-widget-search">'+
7412 + '<i class="pli pli-search" ></i><input class="pagelayer-search-field" /><span class="pagelayer-sf-empty pli">&times;</span>'+
7413 + '</div>'+
7414 + '</div>';
7415 +
7416 + for(var x in pagelayer_groups){
7417 +
7418 + // Title
7419 + html += '<div class="pagelayer-widget-group pagelayer-group-name-'+x+'"><h5>'+x+'</h5>';
7420 +
7421 + // Indivdual icon
7422 + for(var y in pagelayer_groups[x]){
7423 +
7424 + var sc = pagelayer_groups[x][y];
7425 +
7426 + if(!(sc in pagelayer_shortcodes) || 'not_visible' in pagelayer_shortcodes[sc]){
7427 + continue;
7428 + }
7429 +
7430 + html += '<div class="pagelayer-shortcode-holder" pagelayer-tag="'+sc+'">'+
7431 + '<div class="pagelayer-pointer pagelayer-sc">'+
7432 + '<center class="pagelayer-shortcode-inner">';
7433 +
7434 + if('icon' in pagelayer_shortcodes[sc]){
7435 + html += '<i class="pagelayer-shortcode '+pagelayer_shortcodes[sc]['icon']+'"></i>';
7436 + }else{
7437 + html += '<i class="pagelayer-shortcode pli pagelayer-'+sc+'"></i>';
7438 + }
7439 +
7440 + html += '</center>'+
7441 + '<span class="pagelayer-pointer pagelayer-shortcode-text">'+pagelayer_shortcodes[sc]['name']+'</span>'+
7442 + '</div>'+
7443 + '</div>';
7444 +
7445 + }
7446 +
7447 + html += '</div>';
7448 +
7449 + }
7450 +
7451 + html += '</div>';
7452 +
7453 + pagelayer.$$('body').append(html);
7454 +
7455 + var wdHolder = pagelayer.$$('.pagelayer-widget-tooltip');
7456 +
7457 + // Hide the ones which are not supposed to be shown
7458 + wdHolder.find('.pagelayer-search-field').on('input', function(){
7459 +
7460 + var val = jQuery(this).val();
7461 + var re = new RegExp(val, 'i');
7462 +
7463 + // Show only the required tags
7464 + wdHolder.find('.pagelayer-widget-group').each(function(){
7465 +
7466 + var group = jQuery(this);
7467 + var res = group.find('[pagelayer-tag]');
7468 + var hidden = 0;
7469 +
7470 + res.each(function(){
7471 +
7472 + var tEle = jQuery(this);
7473 + if(tEle.find('.pagelayer-shortcode-text').html().match(re)){
7474 + tEle.show();
7475 + }else{
7476 + hidden += 1;
7477 + tEle.hide();
7478 + }
7479 +
7480 + });
7481 +
7482 + // Hide the whole group
7483 + if(hidden == res.length){
7484 + group.hide();
7485 + }else{
7486 + group.show();
7487 + }
7488 +
7489 + });
7490 +
7491 + wdHolder.find('.pagelayer-shortcode-holder:visible').first().trigger('widget_active');
7492 +
7493 + });
7494 +
7495 + // On click search empty
7496 + wdHolder.find('.pagelayer-widget-search>.pagelayer-sf-empty').click(function(){
7497 + wdHolder.find('.pagelayer-search-field').val('').trigger('input');
7498 + });
7499 +
7500 + // Register widget active event
7501 + wdHolder.find('.pagelayer-shortcode-holder').on('widget_active', function(){
7502 + var activeEle = jQuery(this);
7503 + wdHolder.find('.pagelayer-list-widget-active').removeClass('pagelayer-list-widget-active');
7504 +
7505 + if(!activeEle.hasClass('pagelayer-list-widget-active')){
7506 + activeEle.addClass('pagelayer-list-widget-active');
7507 + }
7508 +
7509 + activeEle[0].scrollIntoView({behavior: "smooth", block: "end"});
7510 + });
7511 +
7512 + pagelayer.gDocument.on('mousedown.pagelayer_wdlist', function(e){
7513 + var target = jQuery(e.target);
7514 +
7515 + if(target.closest('.pagelayer-widget-tooltip').is(wdHolder)){
7516 + return;
7517 + }
7518 +
7519 + wdHolder.find('.pagelayer-shortcode-holder:visible').first().trigger('widget_active');
7520 +
7521 + wdHolder.hide();
7522 + jQuery('.pagelayer-show-wiget-list').removeClass('pagelayer-show-wiget-list');
7523 + jQuery(window).off('scroll.pagelayer_wdlist resize.pagelayer_wdlist');
7524 + });
7525 +
7526 +}
7527 +
7528 +// Show Widget list dropdown
7529 +function pagelayer_show_widget_list(jEle, val){
7530 +
7531 + val = val || '';
7532 + jEle = jQuery(jEle);
7533 +
7534 + var wEle = pagelayer.$$('.pagelayer-widget-tooltip'),
7535 + winH = jQuery(window).height(),
7536 + iframe = pagelayer.$$('#pagelayer-iframe'),
7537 + iframeTop = iframe.offset().top,
7538 + iframeLeft = iframe.offset().left,
7539 + style = {},
7540 + wTop = 'auto',
7541 + wBottom = 'auto',
7542 + wLeft = '';
7543 + wHeight = '';
7544 +
7545 + searchField = wEle.find('.pagelayer-search-field');
7546 + searchField.val(val);
7547 + searchField.trigger('input');
7548 +
7549 + // Add widget show class
7550 + if(jEle.hasClass('pagelayer-shortcode-plus')){
7551 + jEle.parent('.pagelayer-ele-overlay').addClass('pagelayer-show-wiget-list');
7552 + }
7553 +
7554 + var bounds = jEle[0].getBoundingClientRect();
7555 +
7556 + wEle.removeClass('pagelayer-widget-list-tooltip');
7557 + wLeft = (bounds.left + iframeLeft) - wEle.width() / 2;
7558 +
7559 + // In list view?
7560 + if(jEle.closest('[pagelayer-editable]').length > 0){
7561 + wEle.addClass('pagelayer-widget-list-tooltip');
7562 + var selection = window.getSelection();
7563 + var range = selection.getRangeAt(0);
7564 + wLeft = (range.getBoundingClientRect().left + iframeLeft) - wEle.width() / 2;
7565 + }
7566 +
7567 + wEle.closest('.pagelayer-widget-tooltip').show();
7568 + wEle.find('.pagelayer-shortcode-holder:visible').first().trigger('widget_active');
7569 +
7570 + // Hide Widget list
7571 + if(jEle.closest('[pagelayer-editable]').length > 0 && wEle.find('.pagelayer-widget-group:visible').length < 1){
7572 + pagelayer.gDocument.trigger('mousedown.pagelayer_wdlist');
7573 + return;
7574 + }else{
7575 + searchField.focus().select();
7576 + }
7577 +
7578 + var docW = iframeLeft + iframe.width() - 30;
7579 +
7580 + // Prevent to hide on left or right
7581 + if(docW < wLeft + wEle.width()){
7582 + wLeft = docW - wEle.width();
7583 + }else if(iframeLeft > wLeft){
7584 + wLeft = iframeLeft;
7585 + }
7586 +
7587 + if(winH / 2 < bounds.top + 10){
7588 + wBottom = winH - bounds.top + 10;
7589 + wHeight = bounds.top - 10;
7590 + }else{
7591 + wTop = bounds.bottom + iframeTop + 10;
7592 + wHeight = winH - bounds.bottom - 10;
7593 + }
7594 +
7595 + style['left'] = wLeft;
7596 + style['top'] = wTop;
7597 + style['bottom'] = wBottom;
7598 + style['max-height'] = '';
7599 +
7600 + if(wHeight < 350){
7601 + style['max-height'] = wHeight;
7602 + }
7603 +
7604 + wEle.css(style);
7605 +
7606 + jQuery(window).off('scroll.pagelayer_wdlist resize.pagelayer_wdlist');
7607 + jQuery(window).on('scroll.pagelayer_wdlist resize.pagelayer_wdlist', function(){
7608 + var _val = wEle.find('.pagelayer-search-field').val();
7609 + pagelayer_show_widget_list(jEle, _val);
7610 + });
7611 +
7612 + wEle.find('.pagelayer-shortcode-holder').off('click');
7613 + wEle.find('.pagelayer-shortcode-holder').on('click', function(e){
7614 +
7615 + var tag = jQuery(this).attr('pagelayer-tag');
7616 + var mWrap = jEle.closest('.pagelayer-ele-wrap[pagelayer-wrap-id]');
7617 + var mTag = pagelayer_tag(mWrap);
7618 +
7619 + var ele = jQuery('<div pagelayer-tag="'+tag+'"></div>');
7620 +
7621 + // Is col?
7622 + if(mTag == 'pl_col'){
7623 + var colHolder = mWrap.find('>.pagelayer-col > .pagelayer-col-holder');
7624 + colHolder.append(ele);
7625 + pagelayer_empty_col(colHolder);
7626 + }else{
7627 + mWrap.after(ele);
7628 + }
7629 +
7630 + // Replace widget
7631 + if(jEle.closest('[pagelayer-editable]').length > 0){
7632 + pagelayer_delete_element(mWrap.find('>.pagelayer-ele'));
7633 + }
7634 +
7635 + var eleId = pagelayer_onadd(ele, false);
7636 + var eEle = pagelayer_ele_by_id(eleId);
7637 +
7638 + // Create Column
7639 + if( tag == 'pl_inner_row' ){
7640 + var in_col = jQuery('<div pagelayer-tag="pl_col"></div>');
7641 + eEle.find('>.pagelayer-row-holder').append(in_col);
7642 + var in_col_id = pagelayer_onadd(in_col, false);
7643 + }
7644 +
7645 + eEle.click();
7646 +
7647 + // Hide Widget list
7648 + pagelayer.gDocument.trigger('mousedown.pagelayer_wdlist');
7649 + });
7650 +
7651 +}
7652 +
7653 +// Set Selection By Character Offsets
7654 +function pagelayer_setCaret(containerEl, start, end){
7655 +
7656 + end = end || start;
7657 +
7658 + // Refered from http://jsfiddle.net/zQUhV/47/
7659 + if(window.getSelection && document.createRange){
7660 +
7661 + var charIndex = 0, range = document.createRange();
7662 + range.setStart(containerEl, 0);
7663 + range.collapse(true);
7664 + var nodeStack = [containerEl], node, foundStart = false, stop = false;
7665 +
7666 + while (!stop && (node = nodeStack.pop())) {
7667 + if (node.nodeType == 3) {
7668 + var nextCharIndex = charIndex + node.length;
7669 + if (!foundStart && start >= charIndex && start <= nextCharIndex) {
7670 + range.setStart(node, start - charIndex);
7671 + foundStart = true;
7672 + }
7673 + if (foundStart && end >= charIndex && end <= nextCharIndex) {
7674 + range.setEnd(node, end - charIndex);
7675 + stop = true;
7676 + }
7677 + charIndex = nextCharIndex;
7678 + } else {
7679 + var i = node.childNodes.length;
7680 + while (i--) {
7681 + nodeStack.push(node.childNodes[i]);
7682 + }
7683 + }
7684 + }
7685 +
7686 + var sel = window.getSelection();
7687 + sel.removeAllRanges();
7688 + sel.addRange(range);
7689 +
7690 + } else if (document.selection) {
7691 + var textRange = document.body.createTextRange();
7692 + textRange.moveToElementText(containerEl);
7693 + textRange.collapse(true);
7694 + textRange.moveEnd("character", end);
7695 + textRange.moveStart("character", start);
7696 + textRange.select();
7697 + }
7698 +}
7699 +
7700 +// Set Selection By Character Offsets
7701 +function pagelayer_content_line(containerEl){
7702 +
7703 + var lines = [], charIndex = 0, range = document.createRange();
7704 + range.setStart(containerEl, 0);
7705 + range.collapse(true);
7706 + var bounding = range.getBoundingClientRect();
7707 + var nodeStack = [containerEl], node, prevX = bounding.x, nextStart = 0;
7708 +
7709 + while(node = nodeStack.pop()){
7710 + if (node.nodeType == 3) {
7711 + for(var i = 1; i <= node.length; i++){
7712 + range.setStart(node, i);
7713 + range.setEnd(node, i);
7714 + bounding = range.getBoundingClientRect();
7715 + charIndex ++;
7716 +
7717 + if(prevX > bounding.x){
7718 + lines.push({start:nextStart, end:charIndex - 1});
7719 + nextStart = charIndex;
7720 + }
7721 + prevX = bounding.x;
7722 + }
7723 + } else {
7724 + var i = node.childNodes.length;
7725 + while(i--){
7726 + nodeStack.push(node.childNodes[i]);
7727 + }
7728 + }
7729 + }
7730 +
7731 + // Push last line
7732 + if(nextStart != charIndex || nextStart == 0){
7733 + lines.push({start:nextStart, end:charIndex});
7734 + }
7735 +
7736 + return lines;
7737 +}
7738 +
7739 +//http://jsfiddle.net/TjXEG/900/
7740 +function pagelayer_getCaretCharacterOffsetWithin(element){
7741 + var caretOffset = 0;
7742 + var doc = element.ownerDocument || element.document;
7743 + var win = doc.defaultView || doc.parentWindow;
7744 + var sel;
7745 + if( typeof win.getSelection != "undefined" ){
7746 + sel = win.getSelection();
7747 + if (sel.rangeCount > 0) {
7748 + var range = win.getSelection().getRangeAt(0);
7749 + var preCaretRange = range.cloneRange();
7750 + preCaretRange.selectNodeContents(element);
7751 + preCaretRange.setEnd(range.endContainer, range.endOffset);
7752 + caretOffset = preCaretRange.toString().length;
7753 + }
7754 + }else if( (sel = doc.selection) && sel.type != "Control" ){
7755 + var textRange = sel.createRange();
7756 + var preCaretTextRange = doc.body.createTextRange();
7757 + preCaretTextRange.moveToElementText(element);
7758 + preCaretTextRange.setEndPoint("EndToEnd", textRange);
7759 + caretOffset = preCaretTextRange.text.length;
7760 + }
7761 + return caretOffset;
7762 +}
7763 +
7764 +// ==========================================================================
7765 +// PAGELAYER UX IMPROVEMENTS
7766 +// ==========================================================================
7767 +
7768 +var pagelayer_is_command_palette_open = false;
7769 +
7770 +function pagelayer_ux_improvements_init() {
7771 + // Setup global shortcuts inside Parent Window and Iframe Document
7772 + var setupShortcuts = function(doc) {
7773 + jQuery(doc).on('keydown', function(e) {
7774 + // Command Palette: Ctrl+K
7775 + if (e.key === 'k' && (e.ctrlKey || e.metaKey)) {
7776 + e.preventDefault();
7777 + pagelayer_toggle_command_palette();
7778 + }
7779 + });
7780 + };
7781 +
7782 + setupShortcuts(document);
7783 + if (pagelayer.gDocument) {
7784 + setupShortcuts(pagelayer.gDocument);
7785 + }
7786 +
7787 + // Hook selection callback to refresh Navigator if it is open in the right sidebar
7788 + pagelayer_add_action('pagelayer_element_clicked', function(jEle) {
7789 + if (jEle && jEle.length > 0) {
7790 + var isNavigatorOpen = pagelayer.$$('body').hasClass('pagelayer-right-sidebar-open') && pagelayer.$$('#pagelayer-navigator').is(':visible');
7791 + if (isNavigatorOpen) {
7792 + var newId = pagelayer_id(jEle);
7793 + if (newId) {
7794 + pagelayer_active.el = pagelayer_active.el || {};
7795 + pagelayer_active.el.id = newId;
7796 + }
7797 + pagelayer_navigator_setup();
7798 + }
7799 + }
7800 + });
7801 +
7802 + // Redirect Navigator & History/Revisions tabs to a new small right sidebar
7803 + window.pagelayer_close_right_sidebar = function() {
7804 + var sidebar = pagelayer.$$('.pagelayer-right-sidebar');
7805 + if (sidebar.length > 0) {
7806 + sidebar.css('right', '-300px');
7807 + pagelayer.$$('body').removeClass('pagelayer-right-sidebar-open');
7808 + pagelayer.$$('.pagelayer-navigator-icon, .pagelayer-history-icon').closest('.pagelayer-header-icon-wrap').removeClass('active');
7809 + pagelayer.$$('#pagelayer-navigator').hide();
7810 + pagelayer.$$('#pagelayer-history').hide();
7811 + }
7812 + };
7813 +
7814 + window.pagelayer_open_right_sidebar = function(tab) {
7815 + var sidebar = pagelayer.$$('.pagelayer-right-sidebar');
7816 + if (sidebar.length === 0) {
7817 + var sidebarHtml =
7818 + '<div class="pagelayer-right-sidebar">' +
7819 + '<div class="pagelayer-right-sidebar-header">' +
7820 + '<h4 class="pagelayer-right-sidebar-title"></h4>' +
7821 + '<button class="pagelayer-right-sidebar-close"><i class="pli pli-cross"></i></button>' +
7822 + '</div>' +
7823 + '<div class="pagelayer-right-sidebar-content">' +
7824 + '</div>' +
7825 + '</div>';
7826 + pagelayer.$$('body').append(sidebarHtml);
7827 + sidebar = pagelayer.$$('.pagelayer-right-sidebar');
7828 +
7829 + sidebar.find('.pagelayer-right-sidebar-close').on('click', function() {
7830 + window.pagelayer_close_right_sidebar();
7831 + });
7832 + }
7833 +
7834 + var isDark = pagelayer.$$('body').hasClass('pagelayer-dark');
7835 + if (isDark) {
7836 + sidebar.addClass('pagelayer-dark');
7837 + } else {
7838 + sidebar.removeClass('pagelayer-dark');
7839 + }
7840 +
7841 + pagelayer.$$('.pagelayer-navigator-icon, .pagelayer-history-icon').closest('.pagelayer-header-icon-wrap').removeClass('active');
7842 +
7843 + var title = '';
7844 + var iconClass = '';
7845 + if (tab === 'pagelayer-navigator') {
7846 + title = pagelayer_l('pagelayer_navigator') || 'Navigator';
7847 + iconClass = '.pagelayer-navigator-icon';
7848 + } else {
7849 + title = pagelayer_l('pagelayer_history') || 'History & Revisions';
7850 + iconClass = '.pagelayer-history-icon';
7851 + }
7852 +
7853 + sidebar.find('.pagelayer-right-sidebar-title').text(title);
7854 +
7855 + var isVisible = pagelayer.$$('body').hasClass('pagelayer-right-sidebar-open');
7856 + var targetContainer = pagelayer.$$('#' + tab);
7857 + if (isVisible && targetContainer.length > 0 && targetContainer.is(':visible')) {
7858 + window.pagelayer_close_right_sidebar();
7859 + return;
7860 + }
7861 +
7862 + pagelayer.$$(iconClass).closest('.pagelayer-header-icon-wrap').addClass('active');
7863 + sidebar.find('.pagelayer-right-sidebar-content').children().hide();
7864 +
7865 + if (targetContainer.parent().hasClass('pagelayer-right-sidebar-content') === false) {
7866 + sidebar.find('.pagelayer-right-sidebar-content').append(targetContainer);
7867 + }
7868 +
7869 + targetContainer.show().css({'height': '100%', 'position': 'static'});
7870 + sidebar.css('right', '0px');
7871 + pagelayer.$$('body').addClass('pagelayer-right-sidebar-open');
7872 + };
7873 +
7874 + var original_pagelayer_leftbar_tab = window.pagelayer_leftbar_tab;
7875 + window.pagelayer_leftbar_tab = function(tab) {
7876 + if (tab === 'pagelayer-navigator' || tab === 'pagelayer-history') {
7877 + window.pagelayer_open_right_sidebar(tab);
7878 + } else {
7879 + // Do not hide navigator or history tab if they are in the right sidebar
7880 + pagelayer.$$('.pagelayer-leftbar-tab').not('#pagelayer-navigator, #pagelayer-history').hide();
7881 + pagelayer.$$('#'+tab).show();
7882 + }
7883 + };
7884 +
7885 + var bindIcons = function() {
7886 + var $historyIcon = pagelayer.$$('.pagelayer-history-icon');
7887 + $historyIcon.off('click');
7888 + $historyIcon.closest('.pagelayer-header-icon-wrap').off('click').on('click', function(e) {
7889 + e.stopPropagation();
7890 + window.pagelayer_open_right_sidebar('pagelayer-history');
7891 + pagelayer_history_setup();
7892 + });
7893 +
7894 + var $navigatorIcon = pagelayer.$$('.pagelayer-navigator-icon');
7895 + $navigatorIcon.off('click');
7896 + $navigatorIcon.closest('.pagelayer-header-icon-wrap').off('click').on('click', function(e) {
7897 + e.stopPropagation();
7898 + var targetContainer = pagelayer.$$('#pagelayer-navigator');
7899 + if (!targetContainer.is(':visible')) {
7900 + pagelayer_navigator_setup();
7901 + }
7902 + window.pagelayer_open_right_sidebar('pagelayer-navigator');
7903 + });
7904 + };
7905 +
7906 + bindIcons();
7907 + setInterval(bindIcons, 3000);
7908 +}
7909 +
7910 +// Toggle Command Palette Modal (Figma / Bricks style search palette)
7911 +function pagelayer_toggle_command_palette() {
7912 + var modal = pagelayer.$$('.pagelayer-command-palette-modal');
7913 + if (modal.length > 0) {
7914 + if (modal.is(':visible')) {
7915 + modal.hide();
7916 + pagelayer_is_command_palette_open = false;
7917 + } else {
7918 + modal.show().find('.pagelayer-cmd-input').focus().val('');
7919 + pagelayer_is_command_palette_open = true;
7920 + pagelayer_render_command_palette_results('');
7921 + }
7922 + return;
7923 + }
7924 +
7925 + // Create modal in parent window
7926 + var modalHtml = '<div class="pagelayer-command-palette-modal" style="position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(15, 23, 42, 0.4); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); z-index: 99999; display: flex; align-items: center; justify-content: center; font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;">' +
7927 + '<div class="pagelayer-cmd-container" style="width: 550px; background: #ffffff; border-radius: 12px; box-shadow: 0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04); display: flex; flex-direction: column; overflow: hidden; border: 1px solid #e2e8f0; max-height: 450px;">' +
7928 + '<div class="pagelayer-cmd-search-bar" style="display: flex; align-items: center; padding: 14px 18px; border-bottom: 1px solid #f1f5f9; gap: 12px;">' +
7929 + '<i class="fas fa-search" style="color: #64748b; font-size: 16px;"></i>' +
7930 + '<input type="text" class="pagelayer-cmd-input" placeholder="Search widgets, actions, settings..." style="flex: 1; border: none; outline: none; font-size: 15px; color: #0f172a; padding: 0; background: transparent;" />' +
7931 + '<span style="font-size: 11px; background: #f1f5f9; color: #64748b; padding: 2px 6px; border-radius: 4px; border: 1px solid #cbd5e1;">ESC</span>' +
7932 + '</div>' +
7933 + '<div class="pagelayer-cmd-results" style="flex: 1; overflow-y: auto; padding: 8px 0; max-height: 380px;">' +
7934 + '</div>' +
7935 + '</div>' +
7936 + '</div>';
7937 +
7938 + pagelayer.$$('body').append(modalHtml);
7939 + modal = pagelayer.$$('.pagelayer-command-palette-modal');
7940 + pagelayer_is_command_palette_open = true;
7941 +
7942 + // Add dark mode support to command palette
7943 + if (pagelayer.$$('body').hasClass('pagelayer-dark')) {
7944 + modal.find('.pagelayer-cmd-container').css({ 'background': '#0b0f19', 'border-color': '#1e293b', 'color': '#f8fafc' });
7945 + modal.find('.pagelayer-cmd-search-bar').css({ 'border-bottom-color': '#1e293b' });
7946 + modal.find('.pagelayer-cmd-input').css({ 'color': '#f8fafc' });
7947 + modal.find('span').css({ 'background': '#1e293b', 'color': '#cbd5e1', 'border-color': '#334155' });
7948 + }
7949 +
7950 + modal.on('click', function(e) {
7951 + if (e.target === this) {
7952 + modal.hide();
7953 + pagelayer_is_command_palette_open = false;
7954 + }
7955 + });
7956 +
7957 + modal.find('.pagelayer-cmd-input').on('input', function() {
7958 + var q = jQuery(this).val();
7959 + pagelayer_render_command_palette_results(q);
7960 + });
7961 +
7962 + modal.find('.pagelayer-cmd-input').on('keydown', function(e) {
7963 + var results = modal.find('.pagelayer-cmd-item');
7964 + var active = modal.find('.pagelayer-cmd-item.active');
7965 +
7966 + if (e.key === 'ArrowDown') {
7967 + e.preventDefault();
7968 + if (active.length === 0 || active.is(':last-child')) {
7969 + results.removeClass('active').first().addClass('active').get(0).scrollIntoView({ block: 'nearest' });
7970 + } else {
7971 + active.removeClass('active').next().addClass('active').get(0).scrollIntoView({ block: 'nearest' });
7972 + }
7973 + } else if (e.key === 'ArrowUp') {
7974 + e.preventDefault();
7975 + if (active.length === 0 || active.is(':first-child')) {
7976 + results.removeClass('active').last().addClass('active').get(0).scrollIntoView({ block: 'nearest' });
7977 + } else {
7978 + active.removeClass('active').prev().addClass('active').get(0).scrollIntoView({ block: 'nearest' });
7979 + }
7980 + } else if (e.key === 'Enter') {
7981 + e.preventDefault();
7982 + if (active.length > 0) {
7983 + active.click();
7984 + }
7985 + } else if (e.key === 'Escape') {
7986 + modal.hide();
7987 + pagelayer_is_command_palette_open = false;
7988 + }
7989 + });
7990 +
7991 + modal.find('.pagelayer-cmd-input').focus();
7992 + pagelayer_render_command_palette_results('');
7993 +}
7994 +
7995 +function pagelayer_render_command_palette_results(query) {
7996 + var modal = pagelayer.$$('.pagelayer-command-palette-modal');
7997 + var resultsContainer = modal.find('.pagelayer-cmd-results');
7998 + resultsContainer.empty();
7999 +
8000 + query = query.toLowerCase().trim();
8001 + var items = [];
8002 +
8003 + // 1. Gather all shortcodes/widgets
8004 + var addedWidgets = {};
8005 +
8006 + // First, gather from pagelayer_groups to prioritize standard draggable widgets
8007 + for (var group in pagelayer_groups) {
8008 + for (var index in pagelayer_groups[group]) {
8009 + var key = pagelayer_groups[group][index];
8010 + if (addedWidgets[key]) continue;
8011 +
8012 + var sc = pagelayer_shortcodes[key];
8013 + if (!sc || !sc.name || 'not_visible' in sc) continue;
8014 +
8015 + if (query === '' || sc.name.toLowerCase().indexOf(query) > -1 || key.toLowerCase().indexOf(query) > -1) {
8016 + items.push({
8017 + type: 'widget',
8018 + title: sc.name,
8019 + subtitle: 'Add Widget',
8020 + key: key,
8021 + icon: sc.icon || '',
8022 + action: (function(k) {
8023 + return function() {
8024 + pagelayer_insert_widget(k);
8025 + };
8026 + })(key)
8027 + });
8028 + addedWidgets[key] = true;
8029 + }
8030 + }
8031 + }
8032 +
8033 + // Fallback to scan raw shortcodes to capture any miscellaneous widgets not categorized in sidebar groups
8034 + for (var key in pagelayer_shortcodes) {
8035 + if (addedWidgets[key]) continue;
8036 +
8037 + var sc = pagelayer_shortcodes[key];
8038 + if (!sc || !sc.name || 'not_visible' in sc) continue;
8039 +
8040 + if (query === '' || sc.name.toLowerCase().indexOf(query) > -1 || key.toLowerCase().indexOf(query) > -1) {
8041 + items.push({
8042 + type: 'widget',
8043 + title: sc.name,
8044 + subtitle: 'Add Widget',
8045 + key: key,
8046 + icon: sc.icon || '',
8047 + action: (function(k) {
8048 + return function() {
8049 + pagelayer_insert_widget(k);
8050 + };
8051 + })(key)
8052 + });
8053 + addedWidgets[key] = true;
8054 + }
8055 + }
8056 +
8057 + // 2. Gather editor actions
8058 + var actions = [
8059 + { title: 'Undo Last Edit', subtitle: 'History Action', icon: 'fas fa-undo', search: 'undo ctrl+z back', action: function() { pagelayer_do_history('undo'); } },
8060 + { title: 'Redo Edit', subtitle: 'History Action', icon: 'fas fa-redo', search: 'redo ctrl+y', action: function() { pagelayer_do_history('redo'); } },
8061 + { title: 'Switch to Desktop View', subtitle: 'Screen Mode', icon: 'fas fa-desktop', search: 'desktop screen responsive preview', action: function() { pagelayer_set_screen_mode('desktop'); } },
8062 + { title: 'Switch to Tablet View', subtitle: 'Screen Mode', icon: 'fas fa-tablet-alt', search: 'tablet screen responsive preview', action: function() { pagelayer_set_screen_mode('tablet'); } },
8063 + { title: 'Switch to Mobile View', subtitle: 'Screen Mode', icon: 'fas fa-mobile-alt', search: 'mobile screen responsive preview phone', action: function() { pagelayer_set_screen_mode('mobile'); } },
8064 + { title: 'Open Revisions & History', subtitle: 'Revision History', icon: 'fas fa-history', search: 'history revisions undo changes', action: function() { pagelayer.$$('.pagelayer-history-icon').click(); } },
8065 + { title: 'Save Page Changes', subtitle: 'Update Page', icon: 'fas fa-save', search: 'save update publish commit ctrl+s', action: function() { pagelayer.$$('.pagelayer-update-button').click(); } },
8066 + { title: 'Open Navigator / Elements Tree', subtitle: 'Navigator Panel', icon: 'fas fa-sitemap', search: 'navigator tree hierarchy layers structure outline', action: function() { pagelayer.$$('.pagelayer-navigator-icon').click(); } }
8067 + ];
8068 +
8069 + actions.forEach(function(act) {
8070 + if (query === '' || act.title.toLowerCase().indexOf(query) > -1 || act.search.indexOf(query) > -1) {
8071 + items.push({
8072 + type: 'action',
8073 + title: act.title,
8074 + subtitle: act.subtitle,
8075 + icon: act.icon,
8076 + action: act.action
8077 + });
8078 + }
8079 + });
8080 +
8081 + if (items.length === 0) {
8082 + resultsContainer.html('<div style="text-align: center; color: #64748b; padding: 24px 0; font-size: 14px;">No results found. Try another query.</div>');
8083 + return;
8084 + }
8085 +
8086 + var slice = items.slice(0, 100);
8087 + var isDark = pagelayer.$$('body').hasClass('pagelayer-dark');
8088 +
8089 + slice.forEach(function(item, idx) {
8090 + var iconClass = '';
8091 + if (item.type === 'widget') {
8092 + if (item.icon) {
8093 + iconClass = 'pagelayer-shortcode ' + item.icon;
8094 + } else {
8095 + iconClass = 'pagelayer-shortcode pli pagelayer-' + item.key;
8096 + }
8097 + } else {
8098 + iconClass = item.icon;
8099 + }
8100 + var itemHtml = jQuery('<div class="pagelayer-cmd-item ' + (idx === 0 ? 'active' : '') + '" style="display: flex; align-items: center; padding: 10px 18px; cursor: pointer; transition: background 0.15s, color 0.15s; gap: 14px; font-size: 14px;">' +
8101 + '<div class="pagelayer-cmd-icon" style="width: 28px; height: 28px; background: ' + (isDark ? '#1e293b' : '#f1f5f9') + '; border-radius: 6px; display: flex; align-items: center; justify-content: center; color: #2563eb; font-size: 16px;"><i class="' + iconClass + '"></i></div>' +
8102 + '<div style="flex: 1; display: flex; flex-direction: column;">' +
8103 + '<span style="font-weight: 500; color: ' + (isDark ? '#f8fafc' : '#0f172a') + ';">' + item.title + '</span>' +
8104 + '<span style="font-size: 11px; color: #64748b;">' + item.subtitle + '</span>' +
8105 + '</div>' +
8106 + '</div>');
8107 +
8108 + var hoverBg = isDark ? '#1e293b' : '#f8fafc';
8109 +
8110 + itemHtml.hover(function() {
8111 + modal.find('.pagelayer-cmd-item').removeClass('active');
8112 + jQuery(this).addClass('active');
8113 + });
8114 +
8115 + itemHtml.on('click', function() {
8116 + modal.hide();
8117 + pagelayer_is_command_palette_open = false;
8118 + item.action();
8119 + });
8120 +
8121 + resultsContainer.append(itemHtml);
8122 + });
8123 +
8124 + var styleTag = pagelayer.$$('head #pagelayer-cmd-palette-styles');
8125 + if (styleTag.length === 0) {
8126 + pagelayer.$$('head').append('<style id="pagelayer-cmd-palette-styles">' +
8127 + '.pagelayer-cmd-item.active { background: ' + (isDark ? '#1e293b !important' : '#f1f5f9 !important') + '; }' +
8128 + '</style>');
8129 + }
8130 +}
8131 +
8132 +// Programmatic widget placement
8133 +function pagelayer_insert_widget(tag) {
8134 + var active = pagelayer_active.el;
8135 + var parentCol = null;
8136 + var target = null;
8137 + var method = 'append';
8138 +
8139 + if (active && active.$) {
8140 + var tag_active = pagelayer_tag(active.$);
8141 + if (tag_active === 'pl_col') {
8142 + parentCol = active.$.find('>.pagelayer-col-holder');
8143 + method = 'append';
8144 + } else if (tag_active === 'pl_row' || tag_active === 'pl_inner_row') {
8145 + parentCol = active.$.find('.pagelayer-col-holder').first();
8146 + method = 'append';
8147 + } else {
8148 + target = active.$.closest('.pagelayer-ele-wrap');
8149 + method = 'after';
8150 + }
8151 + } else {
8152 + parentCol = jQuery(pagelayer_editable).find('.pagelayer-col-holder').first();
8153 + method = 'append';
8154 + }
8155 +
8156 + if ((!parentCol || parentCol.length === 0) && (!target || target.length === 0)) {
8157 + var row = jQuery('<div pagelayer-tag="pl_row"></div>');
8158 + jQuery(pagelayer_editable).append(row);
8159 + var rowId = pagelayer_onadd(row, false);
8160 + var rEle = pagelayer_ele_by_id(rowId);
8161 +
8162 + var col = jQuery('<div pagelayer-tag="pl_col"></div>');
8163 + rEle.find('.pagelayer-row-holder').append(col);
8164 + var colId = pagelayer_onadd(col, false);
8165 + var cEle = pagelayer_ele_by_id(colId);
8166 + parentCol = cEle.find('.pagelayer-col-holder');
8167 + method = 'append';
8168 + }
8169 +
8170 + var ele = jQuery('<div pagelayer-tag="' + tag + '"></div>');
8171 + if (method === 'append') {
8172 + parentCol.append(ele);
8173 + pagelayer_empty_col(parentCol);
8174 + } else {
8175 + target.after(ele);
8176 + pagelayer_empty_col(target.closest('.pagelayer-col-holder'));
8177 + }
8178 +
8179 + var newId = pagelayer_onadd(ele, true);
8180 + pagelayer_do_dirty(ele);
8181 +}
8182 +