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 +5555 -458 0.9.6 → 2.2.2 View file →
@@ -8,29 +8,126 @@
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);
22 99
100 +// Function to load the codes
101 +function pagelayer_start(){
102 +
103 + pagelayer.loading = 1;
104 + console.log('['+pagelayer_brand+'] Starting Pagelayer');
105 +
106 + // Prevent the click Insite editor
107 + pagelayer_prevent_click();
108 +
109 + // Set the title of the parent window
110 + try{ pagelayer.$$('head').append(pagelayer.$('title')[0].outerHTML); }catch(e){};
111 +
112 + pagelayer.blank_img = pagelayer_url+'/images/default-image.png';
113 +
23 114 pagelayer_shortcodes['pl_inner_row'] = JSON.parse(JSON.stringify(pagelayer_shortcodes['pl_row']));
24 115 pagelayer_shortcodes['pl_inner_row']['name'] = 'Inner Row';
25 116 pagelayer_groups['grid'].push('pl_inner_row');
117 +
118 + // Removing post props options
119 + pagelayer_setting_post_props();
26 120
27 121 // Make the Topbar
28 122 pagelayer_bottombar();
29 123
30 124 // Make the Leftbar
31 - pagelayer_leftbar();
32 -
125 + pagelayer_leftbar();
126 +
127 + // Make widget list toolbar
128 + pagelayer_create_widget_tooltip();
129 +
33 130 // Add widget section
34 131 pagelayer_add_widget();
35 132
36 133 // Setup the ELPD
@@ -35,8 +132,11 @@
35 132
36 133 // Setup the ELPD
37 134 pagelayer_elpd_setup();
38 135
136 + // Dump the data we have
137 + pagelayer_element_dump_data();
138 +
39 139 // Setup the properties of the elements
40 140 pagelayer_element_setup();
41 141
42 142 // An image to show for drag
@@ -44,24 +144,331 @@
44 144
45 145 // Setup the grid drag
46 146 pagelayer_setup_drag();
47 147
148 + // Set left bar draggable
149 + pagelayer_make_leftbar_movable();
150 +
48 151 // Set to desktop
49 152 pagelayer_set_screen_mode('desktop');
50 153
154 + // Create list of fonts
155 + pagelayer_fonts = pagelayer_l('pl_fonts_list');
156 +
51 157 // Set up right click
52 158 pagelayer_left_click();
53 159 pagelayer_right_click();
54 160
55 - // Setup pagelayer history
161 + // Setup pagelayer history handle
56 162 pagelayer_history_obj['action_data'] = [];
57 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 + };
58 186
59 -});
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 +}
60 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 +
61 431 // The jQuery Object of the ELPD
62 432 var pagelayer_elpd;
63 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 +
64 471 function pagelayer_closest_corner(jEle){
65 472 var corners = [];
66 473 var w = jEle.outerWidth();
67 474 var h = jEle.outerHeight();
@@ -95,8 +502,115 @@
95 502 return corner;
96 503
97 504 };
98 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 +
99 613 // Make rows and cols draggable
100 614 function pagelayer_setup_drag(){
101 615
102 616 // The object to show as drag
@@ -214,9 +728,21 @@
214 728 var onWrap;
215 729
216 730 // If we are a column, we can be over another column or row
217 731 if(tag == 'pl_col'){
218 - 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 + }
219 745 //console.log(pagelayer_id(onWrap));
220 746
221 747 // If we are a row, we can be over another row or a column
222 748 }else if(tag == 'pl_row'){
@@ -224,11 +750,15 @@
224 750 //console.log(pagelayer_id(onWrap));
225 751
226 752 // For inner row we restrict to 1 level only
227 753 }else if(tag == 'pl_inner_row'){
228 - var ele_wrap = jQuery(ele).parents('.pagelayer-wrap-col')
229 - if(ele_wrap.length == 1){
230 - onWrap = jQuery(ele).closest('.pagelayer-wrap-ele,.pagelayer-wrap-col');
754 +
755 + var ele_wrap = jQuery(ele).parents('.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 + ){
760 + onWrap = jQuery(ele).closest('.pagelayer-wrap-ele,.pagelayer-wrap-col,.pagelayer-wrap-inner-row');
231 761 }else{
232 762 onWrap = jQuery(ele).closest('.pagelayer-wrap-inner-row');
233 763 }
234 764 // For every other element, we can be over a col or ele
@@ -233,8 +763,70 @@
233 763 }
234 764 // For every other element, we can be over a col or ele
235 765 }else{
236 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 + }
237 829 }
238 830 //console.log(onWrap);
239 831
240 832 // If we find nothing
@@ -243,21 +835,48 @@
243 835 reset_on_drag();// Also reset the last on item
244 836 return false;
245 837 }
246 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 +
247 857 // Get the ID
248 - var onId = onWrap.attr('pagelayer-wrap-id');
249 - var onEle = onWrap.children('.pagelayer-ele');
858 + var onId = pagelayer_id(onWrap);
859 + var onEle = pagelayer_ele_by_id(onId);
250 860
251 861 // Do we have a parent ?
252 - var pOnId = pagelayer_get_parent(onEle);
253 -
254 - 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 +
255 869 onId = pOnId;
256 - onEle = pagelayer_ele_by_id(onId);
257 - 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 +
258 874 }
259 875
876 + // Do we have a parent ?
877 + have_parent(onEle);
878 +
260 879 var changed = false;
261 880
262 881 // Was it the same ID like the one we were on before
263 882 if(pagelayer.drag_closest != onId){
@@ -297,10 +916,10 @@
297 916 }
298 917
299 918 //console.log(changed);
300 919
301 - // If we are on our self then clear return false
302 - 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')){
303 922 clear_prospect();// Clear existing prospects
304 923 reset_on_drag();// Also reset the last on item
305 924 return false;
306 925 }
@@ -397,10 +1016,17 @@
397 1016 e.preventDefault();
398 1017
399 1018 var wrap = pagelayer.dragging;
400 1019 var tag = pagelayer_tag(wrap);
1020 + var gId = wrap.attr('pagelayer-global-id');
401 1021 var fromEl = wrap.parent();
402 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 +
403 1029 wrap.removeClass('pagelayer-is-dragging');
404 1030
405 1031 // Find any prospect
406 1032 var prospect = jQuery('.pagelayer-drag-prospect');
@@ -414,15 +1040,25 @@
414 1040 var onTag = pagelayer_tag(onWrap);
415 1041 var dropped;
416 1042 var corner = prospect.attr('pagelayer-corner');
417 1043 var method = (corner == 'top') ? 'before' : 'after';
1044 + var before_loc; // Location before the drop
418 1045
419 1046 // Create the element if it needs to be created
420 - if(pagelayer.drag_is_new){
1047 + if(pagelayer.drag_is_new){
421 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 + }
422 1054
423 1055 // Move the object
424 1056 }else{
1057 +
1058 + // Get near by element before move
1059 + before_loc = pagelayer_near_by_ele(pagelayer_id(wrap), tag);
1060 +
425 1061 dropped = wrap;
426 1062 dropped.detach();
427 1063 }
428 1064
@@ -444,12 +1080,30 @@
444 1080
445 1081 // Trigger the onadd
446 1082 if(pagelayer.drag_is_new){
447 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 + }
448 1091
449 1092 // Existing elements
450 1093 }else{
451 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));
452 1106 }
453 1107
454 1108 // Defining the variables as needed
455 1109 var jEle = pagelayer_ele_by_id(id);
@@ -497,13 +1151,14 @@
497 1151 jQuery(document).on('dragover', ondragover);
498 1152 jQuery(document).on('drop', ondrop);
499 1153
500 1154 // For addition of new elements
501 - pagelayer.$$('[pagelayer-tag]').on('dragstart', function(e){
1155 + pagelayer.$$('.pagelayer-leftbar').on('dragstart', function(e){
502 1156 //console.log(e);
503 1157
504 1158 var tEle = jQuery(e.target);
505 1159 var jEle = tEle.closest('.pagelayer-shortcode-drag');
1160 + var global_id = jEle.attr('pagelayer-global-id');
506 1161
507 1162 // Is it an existing element ?
508 1163 if(jEle.length < 1){
509 1164 return false;
@@ -510,12 +1165,37 @@
510 1165 }
511 1166
512 1167 e.originalEvent.dataTransfer.setData('tag', pagelayer_tag(jEle));
513 1168
1169 + if(!pagelayer_empty(global_id)){
1170 + e.originalEvent.dataTransfer.setData( 'global_id', global_id );
1171 + }
1172 +
514 1173 pagelayer.dragging = jEle;
515 1174 pagelayer.drag_is_new = true;
516 1175
517 1176 });
1177 +
1178 + // Handle editable content by removing drag
1179 + var onmousedown = function(e){
1180 +
1181 + var tEle = jQuery(e.originalEvent.explicitOriginalTarget);
1182 +
1183 + if(tEle.closest('[pagelayer-editable]').length > 0){
1184 + //console.log('Is Editable MouseDown');
1185 + tEle.parents('[draggable]').attr('draggable', 'false');
1186 + }
1187 +
1188 + }
1189 +
1190 + // Handle editable content by adding drag that was removed
1191 + var onmouseup = function(e){
1192 + jQuery(document).find('[draggable=false]').attr('draggable', 'true');
1193 + }
1194 +
1195 + // Handle editable contents by temprarily removing drag
1196 + jQuery(document).on('mousedown', onmousedown);
1197 + jQuery(document).on('mouseup', onmouseup);
518 1198
519 1199 };
520 1200
521 1201 // Handle empty col
@@ -534,17 +1214,25 @@
534 1214
535 1215 // Column is becoming blank, so show add ele
536 1216 if(jEle.children().length < 1){
537 1217 //from.addClass('pagelayer-empty-col');
538 - jEle.append('<div class="pagelayer-add-ele pagelayer-ele-wrap"><i class="fa fa-plus"><br>Empty column please add something</div>');
539 - var h = jEle.parent().parent().children('.pagelayer-ele-overlay').height();
540 - jEle.children('.pagelayer-add-ele').height(h);
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>');
1219 + //var h = jEle.parent().parent().children('.pagelayer-ele-overlay').height();
1220 + //jEle.children('.pagelayer-add-ele').height(h);
541 1221
542 1222 // Any add ele sign with non-empty columns here ?
543 - }else if(jEle.children('.pagelayer-add-ele').length > 0){
1223 + }else if(jEle.children('.pagelayer-add-ele').length > 0 && jEle.children().length > 1){
544 1224 jEle.children('.pagelayer-add-ele').remove();
545 1225 }
546 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 +
547 1235 });
548 1236
549 1237 };
550 1238
@@ -573,15 +1261,112 @@
573 1261 break;
574 1262 }
575 1263 }
576 1264 jEle.addClass('pagelayer-col-'+cols);
577 - Ele.addClass('pagelayer-col-'+cols);
578 -
1265 + jEle.css({'width': ''});
1266 +
579 1267 // Set the att
580 1268 pagelayer_set_atts(Ele, obj);
1269 + pagelayer_set_atts(Ele, 'col_width','');
1270 + pagelayer_sc_render(Ele)
581 1271 });
582 1272 }
583 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 +
584 1369 // Handle addition of elements from the left
585 1370 // NOTE : At this point the addition is FINALIZED
586 1371 // The add element cannot be prevented !
587 1372 function pagelayer_onadd(jEle, toClick){
@@ -605,14 +1390,25 @@
605 1390 function pagelayer_element_added(jEle){
606 1391
607 1392 var sc = jEle.attr('pagelayer-tag');
608 1393 var id, par_id;
1394 + var gId = jEle.attr('pagelayer-global-id');
1395 + gId = gId && !pagelayer_empty(pagelayer_global_widgets[gId]) ? gId : 0;
609 1396
610 1397 // Set Pagelayer History FALSE to prevent saving attributes in action history
611 1398 pagelayer.history_action = false;
612 -
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 +
613 1406 // Generate the HTML
614 - html = pagelayer_create_sc(sc);
1407 + }else{
1408 + html = pagelayer_create_sc(sc);
1409 + }
1410 +
615 1411 id = pagelayer_assign_id(html);
616 1412 par_id = id;
617 1413
618 1414 // Insert the HTML
@@ -620,8 +1416,13 @@
620 1416
621 1417 // Setup the properties of the elements
622 1418 pagelayer_element_setup("[pagelayer-id="+par_id+"], [pagelayer-id="+par_id+"] .pagelayer-ele", true);
623 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 +
624 1425 // Any children to add ?
625 1426 if(!('widget' in pagelayer_shortcodes[sc])){
626 1427
627 1428 // The element props
@@ -628,17 +1429,29 @@
628 1429 var props = pagelayer_shortcodes[sc];
629 1430
630 1431 // Do we have to create children ?
631 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);
632 1442
633 - var has_group = props['has_group'];
634 - var gProp = props[has_group['section']][has_group['prop']];
635 -
636 - for(var i=0; i < gProp['count']; i++){
637 - var cid = pagelayer_element_add_child(jQuery("[pagelayer-id="+id+"]"), gProp['sc']);
638 - //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+'"]'));
639 1453 }
640 -
641 1454 }
642 1455
643 1456 }
644 1457
@@ -648,21 +1461,27 @@
648 1461 pagelayer_history_action_push({
649 1462 'title' : pagelayer_shortcodes[sc]['name'],
650 1463 'action' : 'Added',
651 1464 'pl_id' : id,
652 - 'html' : html[0].outerHTML,
1465 + 'html' : jQuery("[pagelayer-id="+id+"]")[0].outerHTML,
653 1466 'cEle' : cEle
654 - });
1467 + });
655 1468
656 1469 // Set pagelayer history TRUE
657 1470 pagelayer.history_action = true;
1471 + pagelayer.global_render = true;
658 1472
1473 + // To update nav item list
1474 + pagelayer_do_dirty(pagelayer_ele_by_id(id));
1475 +
659 1476 return id;
660 1477
661 1478 };
662 1479
663 1480 // Add an element
664 -function pagelayer_element_add_child(pEle, sc){
1481 +function pagelayer_element_add_child(pEle, sc, gProp){
1482 +
1483 + gProp = gProp || {};
665 1484 var child = pagelayer_create_sc(sc);
666 1485 var cid = pagelayer_assign_id(child);
667 1486 pagelayer_set_parent(child, pagelayer_assign_id(pEle));
668 1487
@@ -680,8 +1499,73 @@
680 1499 }
681 1500
682 1501 pagelayer_element_setup('[pagelayer-id='+cid+']', true);
683 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 +
684 1568 // Do we have to create children ?
685 1569 if('has_group' in pagelayer_shortcodes[sc]){
686 1570
687 1571 var has_group = pagelayer_shortcodes[sc]['has_group'];
@@ -687,9 +1571,9 @@
687 1571 var has_group = pagelayer_shortcodes[sc]['has_group'];
688 1572 var gProp = pagelayer_shortcodes[sc][has_group['section']][has_group['prop']];
689 1573
690 1574 for(var i=0; i < gProp['count']; i++){
691 - 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);
692 1576 }
693 1577
694 1578 }
695 1579
@@ -719,8 +1603,14 @@
719 1603 return id;
720 1604
721 1605 }
722 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 +
723 1613 // Assign the jQuery object an ID
724 1614 function pagelayer_assign_id(jEle){
725 1615
726 1616 // Do you have the pagelayer id
@@ -725,9 +1615,10 @@
725 1615
726 1616 // Do you have the pagelayer id
727 1617 var id = jEle.attr("pagelayer-id");
728 1618 if(!id || id.length < 1){
729 - id = pagelayer_randstr(16);
1619 + id = pagelayer_randstr(3)+pagelayer_randInt(9999).toString();
1620 + id = id.toLowerCase();
730 1621 jEle.attr("pagelayer-id", id);
731 1622 }
732 1623
733 1624 return id;
@@ -738,8 +1629,9 @@
738 1629 function pagelayer_element_clicked(selector, e){
739 1630
740 1631 var jEle = jQuery(selector);
741 1632 e = e || false;
1633 + //console.log(e);
742 1634
743 1635 // You must be a element atleast
744 1636 if(!jEle.hasClass('pagelayer-ele')){
745 1637 return false;
@@ -752,18 +1644,25 @@
752 1644 if(pId){
753 1645 jEle = pagelayer_ele_by_id(pId);
754 1646 }
755 1647
1648 + // Make the editable fields active
1649 + //pagelayer_clear_editable();// First clear
1650 + jEle.find('[pagelayer-editable]').each(function (){
1651 + pagelayer_make_editable(jQuery(this), e);
1652 + });
1653 +
1654 + // Show left bar
1655 + if(pagelayer_empty(e)){
1656 + pagelayer.$$('.pagelayer-leftbar-table').removeClass('pagelayer-leftbar-hidden pagelayer-leftbar-minimize');
1657 + }
1658 +
756 1659 // Lets not rebuild everything to make it faster
757 1660 if(pagelayer_is_active(jEle)){
758 1661 return false;
759 1662 }
760 1663
761 - // Make the editable fields active
762 - pagelayer_clear_editable();// First clear
763 - jEle.find('[pagelayer-editable]').each(function (){
764 - pagelayer_make_editable(jQuery(this), e);
765 - });
1664 + pagelayer_trigger_action('pagelayer_element_clicked', [jEle]);
766 1665
767 1666 // Set this as the active element
768 1667 pagelayer_set_active(jEle);
769 1668
@@ -771,13 +1670,69 @@
771 1670 pagelayer_elpd_open(jEle);
772 1671
773 1672 }
774 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 +
775 1720 // The edit option
776 1721 function pagelayer_edit_element(selector){
777 1722 pagelayer_element_clicked(selector);
778 1723 }
779 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 +
780 1735 // Setup the properties on a single click
781 1736 function pagelayer_element_setup(selector, render){
782 1737
783 1738 var selector = selector || ".pagelayer-ele";
@@ -783,10 +1738,10 @@
783 1738 var selector = selector || ".pagelayer-ele";
784 1739 render = render || false;
785 1740
786 1741 // Loop through
787 - jQuery(selector).each(function(){
788 -
1742 + jQuery(pagelayer_editable+' '+selector).each(function(){
1743 +
789 1744 var jEle = jQuery(this);
790 1745
791 1746 // Assign an ID if not there
792 1747 var id = pagelayer_assign_id(jEle);
@@ -792,8 +1747,13 @@
792 1747 var id = pagelayer_assign_id(jEle);
793 1748 var pId = pagelayer_get_parent(jEle) || '';// Options to show on hover
794 1749 var selector = '[pagelayer-id='+id+']';
795 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 +
796 1756 if(render){
797 1757 pagelayer_sc_render(jEle);
798 1758 }
799 1759
@@ -798,8 +1758,9 @@
798 1758 }
799 1759
800 1760 // Get the tag
801 1761 var tag = pagelayer_tag(jEle);
1762 + var props = pagelayer_get_props(jEle);
802 1763
803 1764 // Lets check if we are the child of a parent i.e. element of a group
804 1765 if(pagelayer_empty(pId)){
805 1766
@@ -826,9 +1787,14 @@
826 1787
827 1788 }
828 1789
829 1790 }
830 -
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 +
831 1797 // Make the wraps
832 1798 jEle.wrap('<div class="pagelayer-ele-wrap" pagelayer-wrap-id="'+id+'"></div>');
833 1799 var wrap = jEle.parent();
834 1800
@@ -841,15 +1807,10 @@
841 1807 col = 'pagelayer-col-'+x;
842 1808 break;
843 1809 }
844 1810 }
1811 +
845 1812
846 - var is_custom_width = pagelayer_get_att(jEle, 'col');
847 - var col_width = pagelayer_get_att(jEle, 'col_width');
848 - if(pagelayer_empty(is_custom_width) && col_width){
849 - wrap.css('width', col_width+'%');
850 - }
851 -
852 1813 wrap.addClass('pagelayer-col '+col);
853 1814 //jEle.removeClass('pagelayer-col '+col);
854 1815 wrap.addClass('pagelayer-wrap-col');
855 1816
@@ -875,11 +1836,13 @@
875 1836 pagelayer_sc_render(jEle);
876 1837 }
877 1838
878 1839 html = '<div class="pagelayer-row-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
879 - '<i class="fa fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" />'+
880 - '<i class="fa fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" />'+
881 - '<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>'+
882 1845 '</div>';
883 1846
884 1847 }else if(tag == 'pl_col'){
885 1848
@@ -885,20 +1848,25 @@
885 1848
886 1849 overlay.addClass('pagelayer-col-hover');
887 1850
888 1851 html = '<div class="pagelayer-col-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
889 - '<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>'+
890 1853 '</div>';
891 1854
892 1855 // Is it an empty col ?
893 1856 pagelayer_empty_col(jEle.children('.pagelayer-col-holder'));
1857 +
1858 + // Make col resizable
1859 + pagelayer_col_make_resizable(wrap);
894 1860
895 1861 }else{
896 1862
897 1863 html = '<div class="pagelayer-ele-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
898 - '<i class="fa fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" />'+
899 - '<i class="fa fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" />'+
900 - '<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>'+
901 1869 '</div>';
902 1870
903 1871 }
904 1872
@@ -903,10 +1871,23 @@
903 1871 }
904 1872
905 1873 // Append to the child
906 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 +
907 1881 jQuery('[pagelayer-option-id='+id+']').hide();
908 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 +
909 1890 // Setup the HOVER events ABD create WRAPS IF we dont have a parent
910 1891 if(pId.length > 0){
911 1892 return;
912 1893 }
@@ -940,12 +1921,48 @@
940 1921
941 1922 });
942 1923 }
943 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 +
944 1961 // Left Click
945 1962 function pagelayer_left_click(){
946 1963
947 - jQuery('.entry-content').on('click', function(e){
1964 + jQuery(pagelayer_editable).on('click', function(e){
948 1965
949 1966 e.preventDefault();// Added by Jivan in Actions / Revisions version
950 1967
951 1968 // Hide the context menu
@@ -971,12 +1988,15 @@
971 1988
972 1989 var html = '<div class="pagelayer-right-click-options" style="display:none;">'+
973 1990 '<ul>'+
974 1991 '<li><a class="pagelayer-right-edit">Edit</a></li>'+
975 - '<li><a class="pagelayer-right-duplicate">Duplicate</a></li>'+
976 - '<li><a class="pagelayer-right-copy">Copy</a></li>'+
977 - '<li><a class="pagelayer-right-paste">Paste</a></li>'+
978 - '<li><a class="pagelayer-right-delete">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>'+
979 1999 '</ul>'+
980 2000 '</div>';
981 2001
982 2002 jQuery('body').append(html);
@@ -982,13 +2002,18 @@
982 2002 jQuery('body').append(html);
983 2003
984 2004 var $contextMenu = jQuery('.pagelayer-right-click-options');
985 2005
986 - jQuery('.entry-content').on('contextmenu', function(e){
2006 + jQuery(pagelayer_editable).on('contextmenu', function(e){
987 2007
988 2008 var tEle = jQuery(e.target);
989 2009 var jEle = tEle.closest('.pagelayer-ele-wrap').children('.pagelayer-ele');
990 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 +
991 2016 // Get the parent
992 2017 var pId = pagelayer_get_parent(jEle);
993 2018
994 2019 // If we found a parent
@@ -999,26 +2024,89 @@
999 2024 // The basics
1000 2025 var id = pagelayer_assign_id(jEle);
1001 2026 var tag = pagelayer_tag(jEle);
1002 2027
1003 - $contextMenu.find('.pagelayer-right-edit').attr('onclick', 'pagelayer_edit_element("[pagelayer-id='+id+']")').html('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']);
1004 2029 $contextMenu.find('.pagelayer-right-duplicate').attr('onclick', 'pagelayer_copy_element("[pagelayer-id='+id+']")');
1005 2030 $contextMenu.find('.pagelayer-right-copy').attr('onclick', 'pagelayer_copy_select("[pagelayer-id='+id+']")');
1006 - $contextMenu.find('.pagelayer-right-paste').attr('onclick', 'pagelayer_paste_element("[pagelayer-id='+id+']")');
1007 2031 $contextMenu.find('.pagelayer-right-delete').attr('onclick', 'pagelayer_delete_element("[pagelayer-id='+id+']")');
1008 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 +
1009 2060 // Are we to hide the paste ?
1010 - if(!pagelayer_empty(pagelayer.copy_selected) && pagelayer_can_copy_to(jEle)){
1011 - //console.log(pagelayer_can_copy_to(jEle));
1012 - $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);
1013 2073 }else{
1014 - $contextMenu.find('.pagelayer-right-paste').parent().hide();
2074 + showPaste();
1015 2075 }
1016 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 +
1017 2105 $contextMenu.css({
1018 2106 display: "block",
1019 - left: e.pageX,
1020 - top: e.pageY
2107 + left: hPosition,
2108 + top: vPosition
1021 2109 });
1022 2110
1023 2111 return false;
1024 2112
@@ -1033,9 +2121,14 @@
1033 2121 function pagelayer_set_parent(jEle, id){
1034 2122 jEle.attr('pagelayer-parent', id);
1035 2123 };
1036 2124
1037 -// 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
1038 2131 function pagelayer_get_parent(jEle){
1039 2132 return jEle.attr('pagelayer-parent');
1040 2133 };
1041 2134
@@ -1056,10 +2149,13 @@
1056 2149 // Add the class
1057 2150 body.addClass('pagelayer-screen-'+mode);
1058 2151
1059 2152 // Add the class to the button
1060 - pagelayer.$$('.pagelayer-mode-button').removeClass('fa-'+current).addClass('fa-'+mode);
2153 + pagelayer.$$('.pagelayer-mode-button').removeClass('pli-'+current).addClass('pli-'+mode);
1061 2154
2155 + // Add the class to the button
2156 + pagelayer.$$('.pagelayer-prop-screen').removeClass('pli-'+current).addClass('pli-'+mode);
2157 +
1062 2158 // Trigger screen change if any
1063 2159 pagelayer.$$('.pagelayer-elp-screen').trigger('pagelayer-screen-changed');
1064 2160
1065 2161 };
@@ -1075,12 +2171,512 @@
1075 2171 }
1076 2172 }
1077 2173 }
1078 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 +
1079 2324 // Handle key press events
1080 -jQuery(document).keydown(function(event){
2325 +pagelayer.gDocument.keydown(function(event){
1081 2326 //alert(String.fromCharCode(event.which));
1082 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 +
1083 2679 // Delete
1084 2680 if(event.keyCode == 46){
1085 2681 pagelayer_delete_element('[pagelayer-active]');
1086 2682 }
@@ -1094,31 +2690,212 @@
1094 2690 if(event.keyCode == 89 && event.ctrlKey){
1095 2691 pagelayer_do_history('redo');
1096 2692 }
1097 2693
1098 - // ctrl+c handle
1099 - if(event.keyCode == 67 && event.ctrlKey){
2694 +});
2695 +
2696 +// Handle Copy of content
2697 +jQuery(document).on('copy', function(copyEvent){
1100 2698
1101 - // Check the active element
1102 - if(pagelayer_active.el && pagelayer_active.el.id){
1103 - 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 + }
1104 2773 }
1105 2774
2775 + pEle_target.css({'opacity': '0.33' , 'transition' : '0.1s'});
1106 2776 }
1107 2777
1108 - // ctrl+v handle
1109 - if(event.keyCode == 86 && event.ctrlKey){
2778 + // This function for ajax success call back
2779 + pagelayer_ajax_func['success'] = function(obj){
1110 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 +
1111 2872 // Check the active element
1112 - if(pagelayer_active.el && pagelayer_active.el.id){
2873 + if(pagelayer_active.el && pagelayer_active.el.id && pagelayer_active.el.tag != 'pl_post_props'){
1113 2874
1114 - var jEle = jQuery("[pagelayer-id='"+pagelayer_active.el.id+"']");
2875 + const text = clipboardData.getData('text');
2876 + var pEle = jQuery(text);
2877 + var getData = true;
1115 2878
1116 - // Check if the any element is copied
1117 - if(!pagelayer_empty(pagelayer.copy_selected) && pagelayer_can_copy_to(jEle)){
1118 - 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 +
1119 2894 }
1120 2895
2896 + }else{
2897 + pagelayer_show_msg(pagelayer_l('no_active_ele_paste'));
1121 2898 }
1122 2899 }
1123 2900 });
1124 2901
@@ -1124,8 +2901,9 @@
1124 2901
1125 2902 // Delete an element as per the selector
1126 2903 function pagelayer_delete_element(selector){
1127 2904 var jEle = jQuery(selector);
2905 + var nearBy = jEle;
1128 2906
1129 2907 // Anything found ?
1130 2908 if(jEle.length > 0){
1131 2909
@@ -1140,8 +2918,10 @@
1140 2918 // Save this element in history action
1141 2919 if(pagelayer.history_action){
1142 2920 var cEle = pagelayer_near_by_ele(id, sc);
1143 2921
2922 + nearBy = jQuery(cEle.cEle);
2923 +
1144 2924 // To save in history, we need to save only element not the wraps as we call setup if we redo or undo
1145 2925 jEle.find('style').remove();
1146 2926 jEle.find('.pagelayer-ele-overlay').remove();
1147 2927
@@ -1156,9 +2936,9 @@
1156 2936 pagelayer_history_action_push({
1157 2937 'title' : pagelayer_shortcodes[sc]['name'],
1158 2938 'action' : 'Deleted',
1159 2939 'pl_id' : id,
1160 - 'html' : jEle,
2940 + 'html' : jEle[0].outerHTML,
1161 2941 'cEle' : cEle
1162 2942 });
1163 2943 }
1164 2944
@@ -1165,22 +2945,93 @@
1165 2945 wrap.remove();
1166 2946
1167 2947 pagelayer_empty_col(par);
1168 2948
1169 - 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)){
1170 2951 pagelayer.$$('.pagelayer-elpd-close').click();
1171 2952 }
1172 2953
1173 2954 }
1174 2955
1175 - pagelayer_isDirty = true;
2956 + // Do Pagelayer dirty
2957 + pagelayer_do_dirty(nearBy);
1176 2958 };
1177 2959
1178 2960 // Select an element
1179 -function pagelayer_copy_select(selector){
1180 - 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 +
1181 2999 }
1182 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 +
1183 3034 function pagelayer_can_copy_to(to){
1184 3035 var jEle = jQuery(pagelayer.copy_selected);
1185 3036 var tEle = jQuery(to);
1186 3037
@@ -1186,8 +3037,14 @@
1186 3037
1187 3038 var eTag = pagelayer_tag(jEle);
1188 3039 var tTag = pagelayer_tag(tEle);
1189 3040 //console.log(eTag+' - '+tTag);
3041 +
3042 + // Invalid HTML copied
3043 + if(pagelayer_empty(eTag)){
3044 + return false;
3045 + }
3046 +
1190 3047 // Final to
1191 3048 var fTo;
1192 3049
1193 3050 // Selected element is a Row, can go only after a row
@@ -1213,10 +3070,26 @@
1213 3070
1214 3071 }
1215 3072
1216 3073 // Select an element
1217 -function pagelayer_paste_element(to){
3074 +function pagelayer_paste_element(to, syncClipboard = true){
1218 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 +
1219 3092 var fTo = pagelayer_can_copy_to(to);
1220 3093
1221 3094 // Is it a valid to
1222 3095 if(!fTo){
@@ -1222,35 +3095,63 @@
1222 3095 if(!fTo){
1223 3096 return false;
1224 3097 }
1225 3098
1226 - 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;
1227 3107 }
1228 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 +
1229 3144 // Copy an element
1230 3145 // Note : insertAfter should always be an pagelayer-ele
1231 3146 function pagelayer_copy_element(selector, insertAfter){
1232 3147 var src = jQuery(selector);
1233 - var html = src[0].outerHTML;
1234 3148 var tag = pagelayer_tag(src);
1235 3149 insertAfter = insertAfter || src;
1236 3150 insertAfter = insertAfter.parent();
1237 3151
1238 - var jEle = jQuery(html);
1239 - jEle.removeAttr('pagelayer-id');
1240 - jEle.find('[pagelayer-id]').removeAttr('pagelayer-id');
1241 - jEle.find('[pagelayer-parent]').removeAttr('pagelayer-parent');// Remove the parent attribute as it will be reset during pagelayer_element_setup
1242 - jEle.find('style').remove();
1243 - jEle.find('.pagelayer-ele-overlay').remove();
3152 + var jEle = pagelayer_element_unsetup(src);
1244 3153
1245 - // Unwrap the wraps
1246 - jEle.find('.pagelayer-ele').each(function (){
1247 - var ele = jQuery(this);
1248 - if(ele.parent().is('.pagelayer-ele-wrap')){
1249 - ele.unwrap();
1250 - }
1251 - });
1252 -
1253 3154 // Give it an ID
1254 3155 var id = pagelayer_assign_id(jEle);
1255 3156
1256 3157 jQuery(insertAfter).after(jEle);
@@ -1256,8 +3157,12 @@
1256 3157 jQuery(insertAfter).after(jEle);
1257 3158
1258 3159 pagelayer_element_setup('[pagelayer-id='+id+'], [pagelayer-id='+id+'] .pagelayer-ele', true);
1259 3160
3161 + if(pagelayer_is_group(tag)){
3162 + pagelayer_sc_render(jEle);
3163 + }
3164 +
1260 3165 // Save this element in history action
1261 3166 if(pagelayer.history_action){
1262 3167 var cEle = pagelayer_near_by_ele(id, tag);
1263 3168 pagelayer_history_action_push({
@@ -1263,9 +3168,9 @@
1263 3168 pagelayer_history_action_push({
1264 3169 'title' : pagelayer_shortcodes[tag]['name'],
1265 3170 'action' : 'Copied',
1266 3171 'pl_id' : id,
1267 - 'html' : jEle,
3172 + 'html' : jEle[0].outerHTML,
1268 3173 'cEle' : cEle
1269 3174 });
1270 3175 }
1271 3176
@@ -1274,18 +3179,366 @@
1274 3179 var row = src.parent().closest('.pagelayer-row');
1275 3180 pagelayer_renumber_col(row);
1276 3181 }
1277 3182
1278 - pagelayer_isDirty = true;
3183 + pagelayer_do_dirty(jEle);
1279 3184
1280 3185 return id;
1281 3186 };
1282 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 +
1283 3484 // Language key
1284 3485 function pagelayer_l(k){
3486 + if(k in pagelayer_lang){
3487 + return pagelayer_lang[k];
3488 + }
1285 3489 return k;
1286 3490 }
1287 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 +
1288 3541 // Set the given jELE as active
1289 3542 function pagelayer_set_active(jEle){
1290 3543
1291 3544 // Make all other element as inactive
@@ -1312,13 +3565,13 @@
1312 3565 function pagelayer_create_sc(sc){
1313 3566
1314 3567 var html;
1315 3568 var _sc = pagelayer_sc(sc);
1316 - var func = window['pagelayer_sc_'+sc];
3569 + var func = window['pagelayer_create_sc_'+sc];
1317 3570
1318 3571 // Generate the HTML
1319 3572 if(typeof func == 'function'){
1320 - html = window['pagelayer_sc_'+sc]();
3573 + html = window['pagelayer_create_sc_'+sc]();
1321 3574 }else{
1322 3575 html = '<div '+pagelayer_sc_atts('pagelayer-'+_sc)+'></div>';
1323 3576 }
1324 3577
@@ -1383,16 +3636,88 @@
1383 3636
1384 3637 return jEle.attr('pagelayer-tag');
1385 3638 }
1386 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 +
1387 3704 // Gets a single attribute value
1388 3705 function pagelayer_get_att(jEle, att){
1389 - 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;
1390 3711 };
1391 3712
1392 3713 // Gets a single attribute value
1393 3714 function pagelayer_get_tmp_att(jEle, att){
1394 - 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;
1395 3720 };
1396 3721
1397 3722 // This function will just set atts and not do anything else
1398 3723 // Atts can be string or object. If its string, then val is needed
@@ -1421,8 +3746,9 @@
1421 3746 var all_props = pagelayer_shortcodes[tag];//console.log(tag);console.log(jEle);
1422 3747 var trigger_props = {};
1423 3748 var no_val = {};
1424 3749 var defaults = {};
3750 + var _props = {};
1425 3751
1426 3752 // Loop through all props
1427 3753 for(var i in pagelayer_tabs){
1428 3754
@@ -1437,15 +3763,39 @@
1437 3763 if('default' in props[x]){
1438 3764 defaults[x] = 1;
1439 3765 }
1440 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 +
1441 3776 // Dont set any val, but we set temp value
1442 3777 if('no_val' in props[x]){
1443 3778 no_val[x] = 1;
1444 3779 }
1445 3780
1446 - if('req' in props[x] || 'show' in props[x]){
3781 + if('req' in props[x] || 'show' in props[x]){
1447 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 +
1448 3798 for(var showParam in show){
1449 3799 var val = show[showParam];
1450 3800 var except = showParam.substr(0, 1) == '!' ? true : false;
1451 3801 showParam = except ? showParam.substr(1) : showParam;
@@ -1459,8 +3809,10 @@
1459 3809 }
1460 3810
1461 3811 }
1462 3812
3813 + var ref_data = pagelayer_el_data_ref(jEle);
3814 +
1463 3815 for(var x in atts){
1464 3816
1465 3817 // Are we to trigger change
1466 3818 if(x in trigger_props){
@@ -1468,8 +3820,13 @@
1468 3820 }
1469 3821
1470 3822 //console.log(x+'-'+atts[x]);
1471 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 +
1472 3829 if(x in no_val){
1473 3830 pagelayer_set_tmp_atts(jEle, x, atts[x]);
1474 3831 continue;
1475 3832 }
@@ -1474,23 +3831,19 @@
1474 3831 continue;
1475 3832 }
1476 3833
1477 3834 // Record History
1478 - if(pagelayer.history_action){
1479 - var attr_label = '';
1480 - for(var section in all_props){
1481 - for(var props in all_props[section]){
1482 - if(props == x){
1483 - attr_label = all_props[section][props]['label'];
1484 - }
1485 - }
1486 -
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'];
1487 3841 }
1488 -
1489 - var old_val = pagelayer_get_att(jEle, x) || '';
3842 +
1490 3843 pagelayer_history_action_push({
1491 3844 'title' : all_props['name'],
1492 - 'subTitle' : attr_label,
3845 + 'subTitle' : label,
1493 3846 'action' : 'Edited',
1494 3847 'attrType' : 'a_attr',
1495 3848 'pl_id' : pagelayer_id(jEle),
1496 3849 'atts' : x,
@@ -1497,40 +3850,27 @@
1497 3850 'oldVal' : old_val,
1498 3851 'newVal' : atts[x]
1499 3852 });
1500 3853 }
1501 -
3854 +
1502 3855 // Remove the attribute if its BLANK and there is no default for it
1503 3856 // If there is a default, we set it to blank to keep record of the current val
1504 - if(atts[x].length < 1){
3857 + if(pagelayer_length(atts[x]) < 1){
1505 3858
1506 - // Dont remove the value as there is a default
3859 + // Remove values which are not defaults
1507 3860 if(!(x in defaults)){
1508 - jEle.removeAttr('pagelayer-a-'+x);
1509 - // Otherwise blank it
3861 + delete ref_data['attr'][x];
3862 + // Otherwise keep value set for avoiding resetting
1510 3863 }else{
1511 - jEle.attr('pagelayer-a-'+x, atts[x]);
3864 + ref_data['attr'][x] = atts[x];
1512 3865 }
1513 3866
1514 3867 // Remove the tmp atts anyway
1515 - var to_del = new Array();
1516 - var regexp = new RegExp('pagelayer\-tmp\-'+x, 'gi');
1517 -
1518 - jQuery.each(jEle[0].attributes, function(index, att){
1519 - if(!att) return;
1520 - if(att.name.match(regexp)){
1521 - to_del.push(att.name);
1522 - }
1523 - });
1524 -
1525 - //console.log(to_del);
1526 - for(var n in to_del){
1527 - jEle.removeAttr(to_del[n]);
1528 - }
3868 + pagelayer_clear_tmp_atts(jEle, x);
1529 3869
1530 3870 // Set the value
1531 3871 }else{
1532 - jEle.attr('pagelayer-a-'+x, atts[x]);
3872 + ref_data['attr'][x] = pagelayer_trim(atts[x]);
1533 3873 }
1534 3874
1535 3875 // Are you the active element
1536 3876 if(pagelayer_is_active(jEle)){
@@ -1540,14 +3880,17 @@
1540 3880 }
1541 3881
1542 3882 }
1543 3883
3884 + pagelayer_el_dump_data(jEle);
3885 +
1544 3886 // Trigger the change of the parameter and show the required properties
1545 3887 if(trigger_onchange){
1546 3888 pagelayer_elpd_show_rows();
1547 3889 }
1548 3890
1549 - pagelayer_isDirty = true;
3891 + pagelayer_do_dirty(jEle);
3892 +
1550 3893 };
1551 3894
1552 3895 // This function will just set atts and not do anything else
1553 3896 // Atts can be string or object. If its string, then val is needed
@@ -1562,10 +3905,12 @@
1562 3905 if(typeof atts != 'object'){
1563 3906 return false;
1564 3907 }
1565 3908
3909 + var ref_data = pagelayer_el_data_ref(jEle);
3910 +
1566 3911 for(var x in atts){
1567 -
3912 +
1568 3913 // Record history
1569 3914 if(pagelayer.history_action){
1570 3915
1571 3916 var old_val = pagelayer_get_tmp_att(jEle, x) || '';
@@ -1580,27 +3925,51 @@
1580 3925 'newVal' : atts[x]
1581 3926 });
1582 3927
1583 3928 }
1584 -
1585 - jEle.attr('pagelayer-tmp-'+x, atts[x]);
3929 +
3930 + ref_data['tmp'][x] = atts[x];
3931 +
1586 3932 }
1587 3933
3934 + pagelayer_el_dump_data(jEle);
3935 +
1588 3936 };
1589 3937
1590 -// Set the att and classes of an HTML which is not yet created
1591 -function pagelayer_sc_atts(classes, atts){
3938 +// This function removes the temporary attributes of an ele
3939 +function pagelayer_clear_tmp_atts(jEle, attr){
1592 3940
1593 - if(typeof atts != 'object'){
1594 - 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 + }
1595 3950 }
3951 +}
3952 +
3953 +// This function removes the temporary attributes of an ele
3954 +function pagelayer_img_tmp_atts(jEle, attr){
1596 3955
1597 - var r = new Array();
3956 + var found = {};
3957 + var regexp = new RegExp('^'+attr+'\-', 'gi');
3958 + var ref_data = pagelayer_el_data_ref(jEle);
1598 3959
1599 - for(var x in atts){
1600 - 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 + }
1601 3964 }
1602 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();
1603 3972 return 'class="'+classes+' pagelayer-ele" '+r.join(' ');
1604 3973 }
1605 3974
1606 3975 // Is the jEle the active element ?
@@ -1626,16 +3995,33 @@
1626 3995
1627 3996 // Seperator
1628 3997 seperator = seperator || ',';
1629 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 +
1630 4012 // Replace the val
1631 - css = css.split('{{val}}').join(val);
4013 + css = replaceCss(css, val, '{{val}}');
1632 4014
1633 4015 // If there is an array
1634 4016 if(css.match(/val\[\d/)){
1635 - val = val.split(seperator);
4017 +
4018 + if(typeof val != 'object' || val === null){
4019 + val = String(val).split(seperator);
4020 + }
4021 +
1636 4022 for(var i in val){
1637 - css = css.split('{{val['+i+']}}').join(val[i]);
4023 + css = replaceCss(css, val[i], '{{val['+i+']}}');
1638 4024 }
1639 4025 }
1640 4026
1641 4027 //console.log('Final CSS '+css);
@@ -1643,9 +4029,40 @@
1643 4029 return css;
1644 4030
1645 4031 };
1646 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 +
1647 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
1648 4065 function pagelayer_parse_vars(str, el){
1649 4066
1650 4067 for(var x in el.tmp){
1651 4068 str = str.split('{{{'+x+'}}}').join(el.tmp[x]);
@@ -1665,9 +4082,11 @@
1665 4082 if(!pagelayer_is_active(jEle)){
1666 4083 //return false;
1667 4084 }
1668 4085
1669 - // Handle the CSS part
4086 + //console.log('Rendering');
4087 +
4088 + // Handle the CSS part
1670 4089 // Get the id, tag, atts, data, etc
1671 4090 var el = pagelayer_data(jEle, true);
1672 4091 var all_props = pagelayer_shortcodes[el.tag];
1673 4092 var elCSS = {
@@ -1676,13 +4095,18 @@
1676 4095 attr: [],
1677 4096 remove_attr: [],
1678 4097 css: [],
1679 4098 edit: [],
1680 - sel: '[pagelayer-id="'+el.id+'"]'
4099 + cssSel: '.p-'+el.id,
4100 + sel: '[pagelayer-id="'+el.id+'"]',
4101 + wrap: '[pagelayer-wrap-id="'+el.id+'"]'
1681 4102 };
1682 4103
1683 4104 // Create a reference
1684 4105 el.CSS = elCSS;
4106 +
4107 + // Make sure if we have the class selector
4108 + el.$.addClass('p-'+el.id);
1685 4109
1686 4110 //console.log(el.atts);
1687 4111
1688 4112 for(var i in pagelayer_tabs){
@@ -1696,10 +4120,10 @@
1696 4120
1697 4121 // pagelayer_data will return attributes even if they are BLANK e.g. attr=""
1698 4122 // Render doesnt consider BLANK values as values, and we are unsetting them now
1699 4123 // If in any situation you need to consider blank values, please handle in the JS / PHP function of the Shortcode
1700 - if(x in el.atts && el.atts[x].length < 1){
1701 - delete el.atts[x];
4124 + if(x in el.atts && pagelayer_length(el.atts[x]) < 1){
4125 + delete el.atts[x];
1702 4126 }
1703 4127
1704 4128 // Any editor ?
1705 4129 if('edit' in props[x]){
@@ -1705,8 +4129,59 @@
1705 4129 if('edit' in props[x]){
1706 4130 elCSS.edit.push({prop: x, sel: props[x]['edit']});
1707 4131 }
1708 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 +
1709 4184 // Do we have a addClass ?
1710 4185 // We are checking before the element has a value so that we can add or remove the class
1711 4186 if('addClass' in props[x]){
1712 4187
@@ -1741,9 +4216,9 @@
1741 4216 }
1742 4217
1743 4218 }else{
1744 4219
1745 - var tmp = {'sel': tSel, 'val': addClasses[c]};
4220 + var tmp = {'sel': tSel, 'val': addClasses[c].replace('{{val}}', el.atts[x])};
1746 4221
1747 4222 // If the value is there
1748 4223 if(x in el.atts){
1749 4224 elCSS['classes'].push(tmp);
@@ -1796,8 +4271,9 @@
1796 4271 }
1797 4272
1798 4273 // Screen modes
1799 4274 var modes = {desktop: '', tablet: '_tablet', mobile: '_mobile'};
4275 + var desk_global = (props[x]['type'] == 'typography') ? pagelayer_is_global_typo(el.atts[x]) : '';
1800 4276
1801 4277 for(var m in modes){
1802 4278
1803 4279 var xm = x+modes[m];
@@ -1802,12 +4278,37 @@
1802 4278
1803 4279 var xm = x+modes[m];
1804 4280
1805 4281 // If the value is there
1806 - if(!(xm in el.atts)){
4282 + if(!(xm in el.atts) && pagelayer_empty(desk_global)){
1807 4283 continue;
1808 4284 }
1809 -
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 +
1810 4311 for(var c in css){
1811 4312
1812 4313 // The selector
1813 4314 var tSel = jQuery.isNumeric(c) ? '{{element}}' : c;
@@ -1812,20 +4313,20 @@
1812 4313 // The selector
1813 4314 var tSel = jQuery.isNumeric(c) ? '{{element}}' : c;
1814 4315 var tmp = {
1815 4316 sel: tSel,
1816 - val: pagelayer_css_render(css[c], el.atts[xm], (props[x].sep || ',')),
4317 + val: pagelayer_css_render(css[c], xm_val, (props[x].sep || ',')),
1817 4318 };
1818 4319
1819 4320 // Is this a tablet
1820 4321 if(m == 'tablet'){
1821 - 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;
1822 4323 tmp.val = tmp.val+'}';
1823 4324 }
1824 4325
1825 4326 // Is this a mobile mode ?
1826 4327 if(m == 'mobile'){
1827 - tmp.sel = '@media (max-width: 360px){'+tmp.sel;
4328 + tmp.sel = '@media (max-width: '+ pagelayer_settings['mobile_breakpoint'] +'px){'+tmp.sel;
1828 4329 tmp.val = tmp.val+'}';
1829 4330 }
1830 4331
1831 4332 // Push to store
@@ -1843,9 +4344,16 @@
1843 4344 }
1844 4345
1845 4346 // If there is an HTML, then process it
1846 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')];
1847 4351
4352 + if(typeof fn == 'function'){
4353 + fn(el);
4354 + }
4355 +
1848 4356 el.iHTML = jQuery('<div>'+pagelayer_shortcodes[el.tag]['html']+'</div>');
1849 4357
1850 4358 // Lets process the 'if-ext'
1851 4359 el.iHTML.find('[if-ext]').each(function (){
@@ -1873,16 +4381,9 @@
1873 4381 $j.remove();
1874 4382 }
1875 4383
1876 4384 });
1877 -
1878 - // Is there a function to render ?
1879 - var fn = window['pagelayer_render_'+jEle.attr('pagelayer-tag')];
1880 4385
1881 - if(typeof fn == 'function'){
1882 - fn(el);
1883 - }
1884 -
1885 4386 //console.log(el.atts);
1886 4387
1887 4388 // Parse the variables
1888 4389 var new_html = pagelayer_parse_vars(el.iHTML.html(), el);
@@ -1939,9 +4440,9 @@
1939 4440 for(var c in elCSS.edit){
1940 4441 var prop = elCSS.edit[c]['prop'];
1941 4442 var tSel = elCSS.edit[c]['sel'];
1942 4443 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
1943 - node.attr('pagelayer-editable', prop);
4444 + node.attr({'pagelayer-editable': prop, 'contenteditable' : 'true'});
1944 4445 }
1945 4446
1946 4447 }
1947 4448
@@ -1953,9 +4454,9 @@
1953 4454 if(elCSS.classes.length > 0){
1954 4455 //console.log(elCSS.classes);
1955 4456
1956 4457 for(var c in elCSS.classes){
1957 - var tSel = elCSS.classes[c]['sel'];
4458 + var tSel = elCSS.classes[c]['sel'].replace('{{element}}', '');
1958 4459 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
1959 4460 if(!node.hasClass(elCSS.classes[c]['val'])){
1960 4461 node.addClass(elCSS.classes[c]['val']);
1961 4462 }
@@ -1966,9 +4467,9 @@
1966 4467 if(elCSS.remove_classes.length > 0){
1967 4468 //console.log(elCSS.remove_classes);
1968 4469
1969 4470 for(var c in elCSS.remove_classes){
1970 - var tSel = elCSS.remove_classes[c]['sel'];
4471 + var tSel = elCSS.remove_classes[c]['sel'].replace('{{element}}', '');
1971 4472 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
1972 4473 if(node.hasClass(elCSS.remove_classes[c]['val'])){
1973 4474 node.removeClass(elCSS.remove_classes[c]['val']);
1974 4475 }
@@ -1985,14 +4486,14 @@
1985 4486
1986 4487 for(var c in elCSS.attr){
1987 4488 var tSel = elCSS.attr[c]['sel'].replace('{{element}}', '');
1988 4489 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
1989 - var att = elCSS.attr[c]['val'].split('=');
4490 + var att = elCSS.attr[c]['val'].split(/=(.*)/);
1990 4491 att[1] = pagelayer_parse_vars(att[1], el);
1991 4492 att[1] = pagelayer_trim(att[1], '"');
1992 4493
1993 4494 // Is it the same val ?
1994 - if(!node.attr(att[0]) != att[1]){
4495 + if(!node.attr(att[0]) !== att[1]){
1995 4496 node.attr(att[0], att[1]);
1996 4497 }
1997 4498 }
1998 4499 }
@@ -2030,15 +4531,28 @@
2030 4531 var rules = [];
2031 4532
2032 4533 // Loop
2033 4534 for(var c in elCSS.css){
2034 - var tSel = elCSS.css[c]['sel'].replace('{{element}}', elCSS.sel);
2035 - var rule = pagelayer_parse_vars(elCSS.css[c]['val'], el);
2036 - 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 + }
2037 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 + }
2038 4552
2039 4553 // Set the style
2040 - style.html(rules.join("\n"));
4554 + style.html(pagelayer_parse_vars(rules.join("\n"), el));
2041 4555 //console.log(style);
2042 4556 }else{
2043 4557 style.remove();
2044 4558 }
@@ -2051,14 +4565,150 @@
2051 4565 }
2052 4566
2053 4567 // If the element have any parent
2054 4568 var par = pagelayer_get_parent(jEle);
4569 + var eleId = el.id;
4570 +
2055 4571 if(par){
4572 + eleId = par;
2056 4573 pagelayer_sc_render(pagelayer_ele_by_id(par));
2057 4574 }
2058 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 +
2059 4595 };
2060 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 +
2061 4711 // Is the given tag a group
2062 4712 function pagelayer_is_group(tag){
2063 4713
2064 4714 if('has_group' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['has_group'])){
@@ -2068,37 +4718,308 @@
2068 4718 return false;
2069 4719
2070 4720 }
2071 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 +
2072 4910 // Save the post
2073 4911 function pagelayer_save(){
2074 4912
2075 - var post = pagelayer_generate_sc(".entry-content");//alert(post);return;
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 +
2076 4919 var pagelayerajaxurl = pagelayer_ajax_url+'&action=pagelayer_save_content&postID='+pagelayer_postID;
2077 - jQuery.ajax({
2078 - type: "POST",
2079 - url: pagelayerajaxurl,
2080 - data: {
2081 - pagelayer_update_content : post,
2082 - nonce: pagelayer_ajax_nonce
2083 - },
2084 - success: function(response, status, xhr){
2085 - //alert(data);
2086 - var obj = jQuery.parseJSON(response);
2087 - //alert(obj);
2088 - if(obj['error']){
2089 - alert(obj['error']);
2090 - }else{
2091 - pagelayer_isDirty = false;
2092 - alert(obj['success']);
2093 - pagelayer_get_revision();
4920 + var post = pagelayer_generate_sc(pagelayer_editable);//alert(post);return;
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 + }
2094 5011 }
2095 - },
2096 - error: function(errorThrown){
2097 - console.log(errorThrown);
2098 - }
2099 - });
5012 + });
5013 + }
2100 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();
2101 5022 };
2102 5023
2103 5024 //Close the Editor
2104 5025 function pagelayer_close(){
@@ -2111,18 +5032,30 @@
2111 5032 }else{
2112 5033 window.top.location.href = pagelayer_returnURL;
2113 5034 }
2114 5035 };
5036 +
5037 +function pagelayer_htmlEntities(str) {
5038 + return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
5039 +}
2115 5040
2116 -// Generate Shortcode Post to save
2117 -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){
2118 5052
5053 + selfEle = selfEle || false;
2119 5054 var txt = '';
2120 5055
2121 - jQuery(selector).children(".pagelayer-ele-wrap").each(function(){
5056 + var generate_sc_single = function(jEle){
2122 5057
2123 - var jEle = jQuery(this).children('.pagelayer-ele');
2124 -
2125 5058 // The ID
2126 5059 var id = jEle.attr('pagelayer-id');
2127 5060
2128 5061 // If there is an Add element wrapper
@@ -2132,14 +5065,29 @@
2132 5065
2133 5066 // Find the type of tag
2134 5067 var tag = jEle.attr('pagelayer-tag');
2135 5068 var final_tag = tag;
5069 + var closestEle = jEle.closest('.pagelayer-col-holder');
2136 5070
2137 - // Define inner row and inner column
2138 - if(tag == 'pl_row' && jQuery(this).closest('.pagelayer-col-holder').length > 0){
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 +
5076 + // Define inner row | Note : Commented as we now have a new widget of type inner_row
5077 + /*if(tag == 'pl_row' && closestEle.length > 0 && closestEle.closest(pagelayer_editable).length > 0){
2139 5078 final_tag = 'pl_inner_row';
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);
2140 5086 }
2141 - if(tag == 'pl_col' && jQuery(this).closest('.pagelayer-col-holder').length > 0){
5087 +
5088 + // Define inner column
5089 + if(tag == 'pl_col' && closestEle.length > 0 && closestEle.closest(pagelayer_editable).length > 0){
2142 5090 final_tag = 'pl_inner_col';
2143 5091 }
2144 5092 //console.log(tag);
2145 5093
@@ -2148,57 +5096,61 @@
2148 5096 if('innerHTML' in pagelayer_shortcodes[tag]){
2149 5097 inner = pagelayer_shortcodes[tag]['innerHTML'];
2150 5098 }
2151 5099
5100 + // Data reference
5101 + var ref_data = pagelayer_el_data_ref(jEle);
5102 +
2152 5103 // Create the tag
2153 - var data = '['+final_tag;
5104 + var data = JSON.parse(JSON.stringify(ref_data['attr']));
2154 5105
2155 - // Get the attributes to store
2156 - jQuery.each(jEle[0].attributes, function(i, attrib){
2157 - var res = attrib.name.match(/^pagelayer-a-(.+)/i);
2158 - if(res && res[1] != inner){
2159 - //console.log(attrib.name+' '+res[1]);
2160 - data += ' '+res[1]+'="'+pagelayer_escapeHTML(attrib.value)+'"';
2161 - }
2162 - });
5106 + data['pagelayer-id'] = id;
5107 + data = pagelayer_serializeAttributes(data);
5108 +
5109 + var content = '';
2163 5110
2164 - data = data+']';
2165 -
2166 - // Add to the text
2167 - txt = txt+data+"\n";
2168 -
2169 5111 // Any internal function to handle the save ?
2170 5112 var func = window['pagelayer_tag_'+tag];
2171 5113 if(typeof func == 'function'){
2172 5114
2173 - var content = '';
2174 5115 content = func(jEle);
2175 5116
2176 - if(content.length > 0){
2177 - txt = txt+content;
2178 - }
2179 -
2180 5117 // If its a Row or Column or Group then it will have children
2181 5118 }else if(jEle.hasClass('pagelayer-row') || jEle.hasClass('pagelayer-col') || jEle.hasClass('pagelayer-inner_row') || pagelayer_is_group(tag)){
2182 5119
2183 - var sel = "[pagelayer-id="+id+"]";
5120 + var sel = jEle;
2184 5121
2185 5122 // Any holder which holds children ?
2186 5123 if('holder' in pagelayer_shortcodes[tag]){
2187 - sel = sel+' '+pagelayer_shortcodes[tag]['holder'];
5124 + sel = jEle.find(pagelayer_shortcodes[tag]['holder']);
2188 5125 }
2189 5126
2190 - var childrens = pagelayer_generate_sc(jQuery(sel).first());
2191 - if(childrens.length > 0){
2192 - txt = txt+childrens;
5127 + // Select the top-most element
5128 + sel = jQuery(sel).first();
5129 +
5130 + // Any child selector - Majorly for owl carousel
5131 + // NOTE : Child selector should be very specific with immediate child selection at all levels
5132 + var child_selector = false;
5133 + if('child_selector' in pagelayer_shortcodes[tag]){
5134 + childSel = sel.find(pagelayer_shortcodes[tag]['child_selector']);
5135 +
5136 + if(childSel.length > 0){
5137 + sel = childSel;
5138 + }
2193 5139 }
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;
5146 + }
2194 5147
2195 5148 // Its a normal element so we might need to handle the content
2196 5149 }else{
2197 5150
2198 - var content = '';
2199 5151 if(inner.length > 0){
2200 - content = jEle.attr('pagelayer-a-'+inner);
5152 + content = pagelayer_get_att(jEle, inner);
2201 5153 if(!content){
2202 5154 content = '';
2203 5155 }
2204 5156 }else{
@@ -2204,100 +5156,98 @@
2204 5156 }else{
2205 5157 content = '';//jEle.html();
2206 5158 }
2207 5159
2208 - if(content.length > 0){
2209 - txt = txt+content;
2210 - }
2211 -
2212 5160 }
2213 5161
2214 - // Close the tag
2215 - 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 + }
2216 5167
2217 - });
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 + };
2218 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 +
2219 5193 return txt;
2220 5194
2221 5195 };
2222 5196
2223 -// Escape charaters in attributes
2224 -var pagelayer_escapeChars = {
2225 - '\\]' : '#93',
2226 - '\\[' : '#91',
2227 - //'=' : '#61',
2228 - '<' : 'lt',
2229 - '>' : 'gt',
2230 - '"' : 'quot',
2231 - //'&' : 'amp',
2232 - '\'' : '#39'
2233 -};
2234 -
2235 -// To unescape
2236 -var pagelayer_unescapeChars = {
2237 - '#93' : ']',
2238 - '#91' : '[',
2239 - //'#61' : '=',
2240 - 'lt' : '<',
2241 - 'gt' : '>',
2242 - 'quot' : '"',
2243 - //'amp' : '&',
2244 - '#39' : '\''
2245 -};
2246 -
2247 -var pagelayer_escaperegex_S = '[';
2248 -for(var key in pagelayer_escapeChars) {
2249 - pagelayer_escaperegex_S += key;
5197 +// Show the required leftbar tab
5198 +function pagelayer_leftbar_tab(tab){
5199 + pagelayer.$$('.pagelayer-leftbar-tab').hide();
5200 + pagelayer.$$('#'+tab).show();
2250 5201 }
2251 -pagelayer_escaperegex_S += ']';
2252 5202
2253 -var pagelayer_escaperegex = new RegExp( pagelayer_escaperegex_S, 'g');
2254 -
2255 -// The function which escapes everything
2256 -function pagelayer_escapeHTML(str) {
2257 - return str.replace(pagelayer_escaperegex, function(m) {
2258 - if(m == '[' || m == ']') m = '\\'+m;
2259 - return '&' + pagelayer_escapeChars[m] + ';';
2260 - });
2261 -};
2262 -
2263 -// This will unescape everything
2264 -function pagelayer_unescapeHTML(str){
2265 - return str.replace(/\&([^;]+);/g, function (entity, entityCode) {
2266 - if(entityCode in pagelayer_unescapeChars){
2267 - return pagelayer_unescapeChars[entityCode];
2268 - }else{
2269 - return entity;
2270 - }
2271 - });
2272 -};
2273 -
2274 5203 // Sets up the leftbar
2275 5204 function pagelayer_leftbar(){
2276 5205
2277 5206 // Toggle the holder
2278 5207 pagelayer.$$('.pagelayer-leftbar-toggle').on('click', function(){
2279 - pagelayer.$$('.pagelayer-leftbar-table').toggle();
5208 + pagelayer.$$('.pagelayer-leftbar-table').toggleClass('pagelayer-leftbar-hidden');
5209 + pagelayer_trigger_action('pagelayer-leftbar-toggle');
2280 5210 });
2281 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 +
2282 5222 var html = '<div class="pagelayer-leftbar">'+
2283 5223 '<div class="pagelayer-leftbar-scroll">'+
2284 - '<div class="pagelayer-shortcodes">'+
2285 - '<div class="pagelayer-leftbar-search">'+
2286 - '<input class="pagelayer-search-field" />'+
2287 - '</div>';
5224 + '<div id="pagelayer-shortcodes" class="pagelayer-leftbar-tab pagelayer-shortcodes">'+
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>';
2288 5234
2289 5235 for(var x in pagelayer_groups){
2290 5236
2291 5237 // Title
2292 - 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';
2293 5241
5242 + html += '<div class="pagelayer-leftbar-group pagelayer-group-name-'+x+'"><h5>'+group_title+'</h5>';
5243 +
2294 5244 // Indivdual icon
2295 5245 for(var y in pagelayer_groups[x]){
2296 5246
2297 5247 var sc = pagelayer_groups[x][y];
2298 5248
2299 - if('not_visible' in pagelayer_shortcodes[sc]){
5249 + if(!(sc in pagelayer_shortcodes) || 'not_visible' in pagelayer_shortcodes[sc]){
2300 5250 continue;
2301 5251 }
2302 5252
2303 5253 html += '<div class="pagelayer-shortcode-drag" draggable="true" pagelayer-tag="'+sc+'">'+
@@ -2304,11 +5254,11 @@
2304 5254 '<div class="pagelayer-sc">'+
2305 5255 '<center class="pagelayer-shortcode-inner">';
2306 5256
2307 5257 if('icon' in pagelayer_shortcodes[sc]){
2308 - html += '<i class="pagelayer-shortcode fa fa-'+pagelayer_shortcodes[sc]['icon']+'"></i>';
5258 + html += '<i class="pagelayer-shortcode '+pagelayer_shortcodes[sc]['icon']+'"></i>';
2309 5259 }else{
2310 - html += '<i class="pagelayer-shortcode pagelayer-'+sc+'"></i>';
5260 + html += '<i class="pagelayer-shortcode pli pagelayer-'+sc+'"></i>';
2311 5261 }
2312 5262
2313 5263 html += '</center>'+
2314 5264 '<span class="pagelayer-shortcode-text">'+pagelayer_shortcodes[sc]['name']+'</span>'+
@@ -2321,17 +5271,24 @@
2321 5271
2322 5272 }
2323 5273
2324 5274 html += '</div>'+
2325 - '<div id="pagelayer-elpd" class="pagelayer-elpd"></div>'+
2326 - '<div id="pagelayer-history" class="pagelayer-history"></div>'+
5275 + '<div id="pagelayer-global-widget" class="pagelayer-hidden pagelayer-global-widget"></div>'+
5276 + '</div>'+
5277 + '<div id="pagelayer-elpd" class="pagelayer-leftbar-tab pagelayer-elpd"></div>'+
5278 + '<div id="pagelayer-options" class="pagelayer-leftbar-tab pagelayer-options"></div>'+
5279 + '<div id="pagelayer-history" class="pagelayer-leftbar-tab pagelayer-history"></div>'+
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>'+
2327 5283 '</div>'+
2328 5284 '</div>';
2329 5285
2330 5286 pagelayer.$$('.pagelayer-leftbar-holder').prepend(html);
5287 + pagelayer_leftbar_tab('pagelayer-shortcodes');
2331 5288
2332 5289 pagelayer.$$('.pagelayer-leftbar-scroll').slimScroll({
2333 - height: '100%',
5290 + height: '100%',
2334 5291 railVisible: false,
2335 5292 alwaysVisible: true,
2336 5293 color: '#000',
2337 5294 size: '5px',
@@ -2371,10 +5328,173 @@
2371 5328
2372 5329 });
2373 5330 });
2374 5331
5332 + // On click Pagelayer setting icon
5333 + pagelayer.$$('.pagelayer-settings-icon, .pagelayer-settings').click(function(event){
5334 + pagelayer_active = {};
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 +
5341 + });
5342 +
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 +
5359 +
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>'+
5377 + '</div>'+
5378 + '<div class="pagelayer-leftbar-group"><h5>'+pagelayer_l('global_widgets')+'</h5></div>'+
5379 + '</div>';
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 + }
5411 +
5412 + pagelayer.$$('#pagelayer-global-widget').html(gHtml);
5413 + };
5414 +
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 + });
5434 +
5435 + // On click search empty
5436 + pagelayer.$$('.pagelayer-leftbar-search>.pagelayer-sf-empty').click(function(){
5437 + pagelayer.$$('.pagelayer-search-field').val('').trigger('input');
5438 + });
5439 +
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();
5444 +
5445 + // Setup General options
5446 + pagelayer_setup_general_options();
5447 +
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();
5467 +
5468 + });
2375 5469 };
2376 5470
5471 +// Post setting holder
5472 +function pagelayer_post_settings(pl_tag, to_click){
5473 +
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);
5485 +
5486 + // Dont mark as dirty as post_props is not editing anything
5487 + pagelayer_do_undirty();
5488 + }
5489 +
5490 + if(to_click){
5491 + jEle.click();
5492 + }
5493 +
5494 + return jEle;
5495 +}
5496 +
2377 5497 // Get the closest element and method
2378 5498 function pagelayer_near_by_ele(id, sc){
2379 5499
2380 5500 // Get the previous element of the id element
@@ -2390,9 +5510,9 @@
2390 5510 }else{
2391 5511
2392 5512 // If don't have previous element of the id element then get parent element
2393 5513 if(sc == "pl_row"){
2394 - args = {'method' : 'prepend', 'cEle' : '.entry-content'};
5514 + args = {'method' : 'prepend', 'cEle' : pagelayer_editable};
2395 5515 }else{
2396 5516
2397 5517 // Get the parent element
2398 5518 var pEle_id = pagelayer_id(jQuery('[pagelayer-wrap-id="'+id+'"]').closest('.pagelayer-ele'));
@@ -2398,9 +5518,9 @@
2398 5518 var pEle_id = pagelayer_id(jQuery('[pagelayer-wrap-id="'+id+'"]').closest('.pagelayer-ele'));
2399 5519
2400 5520 // Get the parent element tag
2401 5521 var pEle_tag = pagelayer_tag(jQuery('[pagelayer-id="'+pEle_id+'"]'));
2402 - var holder = pagelayer_shortcodes[pEle_tag]['holder'] || '';
5522 + var holder = '>'+ pagelayer_shortcodes[pEle_tag]['holder'] || '';
2403 5523 args = {'method' : 'prepend', 'cEle' : '[pagelayer-id="'+pEle_id+'"] '+ holder+' '};
2404 5524
2405 5525 }
2406 5526
@@ -2412,8 +5532,9 @@
2412 5532
2413 5533 // Push the action data in the pagelayer_history_obj object
2414 5534 function pagelayer_history_action_push(args){
2415 5535
5536 + var currentTime = new Date();
2416 5537 var history_obj_len = pagelayer_history_obj['action_data'].length;
2417 5538
2418 5539 // If the history_obj_len is less then 1 then set the data in array 0 position
2419 5540 if(history_obj_len < 1){
@@ -2423,8 +5544,9 @@
2423 5544
2424 5545 // Remove the second array element if the history_obj_len greater then 100
2425 5546 if(history_obj_len > 100){
2426 5547 pagelayer_history_obj['action_data'].splice(1, 1);
5548 + pagelayer_history_obj['current_active_item_id'] = pagelayer_history_obj['action_data'].length - 1;
2427 5549 }
2428 5550
2429 5551 // Get current active history action id
2430 5552 var action_id = parseInt(pagelayer_history_obj['current_active_item_id']) || 0;
@@ -2433,22 +5555,45 @@
2433 5555 var del_ele = history_obj_len - action_id - 1;
2434 5556 pagelayer_history_obj['action_data'].splice(action_id + 1, del_ele);
2435 5557
2436 5558 // Check if the same attr set as current active history
2437 - if(args.action == "Edited" && history_obj_len > 1){
5559 + if(args.action == "Edited" && history_obj_len > 1 && currentTime - pagelayer.history_lastTime < 1000){
2438 5560 var atts = pagelayer_history_obj['action_data'][action_id] || '';
2439 - if(atts['atts'] == args['atts']){
5561 + if(atts['atts'] == args['atts'] && atts['pl_id'] == args['pl_id'] && pagelayer_empty(atts['sub_actions_group']) ){
2440 5562 args['oldVal'] = atts['oldVal'];
2441 5563 pagelayer_history_obj['action_data'][action_id] = args;
2442 5564 pagelayer_history_setup();
5565 +
5566 + // Set the last history time
5567 + pagelayer.history_lastTime = currentTime;
2443 5568 return true;
2444 5569 }
2445 5570 }
2446 -
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 +
2447 5590 pagelayer_history_obj['action_data'].push(args);
2448 5591 pagelayer_history_obj['current_active_item_id'] = pagelayer_history_obj['action_data'].length - 1;
2449 5592 pagelayer_history_setup();
2450 5593
5594 + // Set the last history time
5595 + pagelayer.history_lastTime = currentTime;
2451 5596 }
2452 5597
2453 5598 // Setup pagelayer history
2454 5599 function pagelayer_history_setup(force){
@@ -2455,9 +5600,9 @@
2455 5600
2456 5601 var force = force || false;
2457 5602
2458 5603 // If the history tab is visible, only then setup
2459 - if(!pagelayer.$$('.pagelayer-history').is(':visible') && !force){
5604 + if(!pagelayer.$$('#pagelayer-history').is(':visible') && !force){
2460 5605 return;
2461 5606 }
2462 5607
2463 5608 // The current active action id
@@ -2494,9 +5639,9 @@
2494 5639 '<span class="pagelayer-history-subtitle"> '+subTitle+' </span>'+
2495 5640 '<span class="pagelayer-history-action"><i> '+action+' </i></span>'+
2496 5641 '</div>'+
2497 5642 '<div class="pagelayer-history-icon">'+
2498 - '<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>'+
2499 5644 '</div>'+
2500 5645 '</div>';
2501 5646 }
2502 5647
@@ -2524,9 +5669,9 @@
2524 5669 pagelayer_revision_obj[x]['post_author_name']+
2525 5670 '</div>'+
2526 5671 '</div>'+
2527 5672 '<div class="pagelayer-revision-icon-holder">'+
2528 - '<i class="pagelayer-revision-delete fa fa-times"></i>'+
5673 + '<i class="pagelayer-revision-delete pli pli-cross"></i>'+
2529 5674 '</div>'+
2530 5675 '</div>';
2531 5676 }
2532 5677
@@ -2558,9 +5703,9 @@
2558 5703 jQuery.ajax({
2559 5704 url: pagelayer_ajax_url+'&action=pagelayer_apply_revision&revisionID='+revision_id,
2560 5705 type: 'post',
2561 5706 data: {
2562 - nonce: pagelayer_ajax_nonce,
5707 + pagelayer_nonce: pagelayer_ajax_nonce,
2563 5708 'pagelayer-live' : 1,
2564 5709 },
2565 5710 success: function(response, status, xhr){
2566 5711
@@ -2565,14 +5710,45 @@
2565 5710 success: function(response, status, xhr){
2566 5711
2567 5712 var obj = jQuery.parseJSON(response);
2568 5713 if(obj['error']){
2569 - alert(obj['error']);
5714 + pagelayer_show_msg(obj['error'] , 'error');
2570 5715 }else{
2571 - jQuery('.entry-content').html(obj['content']);
2572 - alert(obj['success']);
2573 - pagelayer_element_setup();
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
5727 + jQuery(pagelayer_editable).html(obj['content']);
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);
2574 5749 pagelayer_add_widget();
5750 + pagelayer_show_msg(obj['success'], 'success');
2575 5751 }
2576 5752 }
2577 5753 });
2578 5754 });
@@ -2587,16 +5763,16 @@
2587 5763 if(confirm("Are you sure you want to delete the revision ?")){
2588 5764 jQuery.ajax({
2589 5765 url: pagelayer_ajax_url+'&action=pagelayer_delete_revision&revisionID='+revision_id,
2590 5766 type: 'post',
2591 - data: {nonce: pagelayer_ajax_nonce},
5767 + data: {pagelayer_nonce: pagelayer_ajax_nonce},
2592 5768 success: function(response, status, xhr){
2593 5769
2594 5770 var obj = jQuery.parseJSON(response);
2595 5771 if(obj['error']){
2596 - alert(obj['error']);
5772 + pagelayer_show_msg(obj['error'], 'error');
2597 5773 }else{
2598 - alert(obj['success']);
5774 + pagelayer_show_msg(obj['success'], 'success');
2599 5775 rEle.hide();
2600 5776 }
2601 5777
2602 5778 }
@@ -2629,9 +5805,9 @@
2629 5805 });
2630 5806 });
2631 5807 }
2632 5808
2633 -// Get evisions Handler
5809 +// Get revisions Handler
2634 5810 function pagelayer_get_revision(){
2635 5811
2636 5812 jQuery.ajax({
2637 5813 url: pagelayer_ajax_url+'&action=pagelayer_get_revision&postID='+pagelayer_postID,
@@ -2636,9 +5812,9 @@
2636 5812 jQuery.ajax({
2637 5813 url: pagelayer_ajax_url+'&action=pagelayer_get_revision&postID='+pagelayer_postID,
2638 5814 type: 'post',
2639 5815 data: {
2640 - nonce: pagelayer_ajax_nonce,
5816 + pagelayer_nonce: pagelayer_ajax_nonce,
2641 5817 },
2642 5818 //async:false,
2643 5819 success: function(response, status, xhr){
2644 5820 var obj = jQuery.parseJSON(response);
@@ -2643,9 +5819,9 @@
2643 5819 success: function(response, status, xhr){
2644 5820 var obj = jQuery.parseJSON(response);
2645 5821
2646 5822 if(!pagelayer_empty(obj['error'])){
2647 - alert(obj['error']);
5823 + pagelayer_show_msg(obj['error'], 'error');
2648 5824 }else{
2649 5825 pagelayer_revision_obj = obj;
2650 5826 pagelayer_history_setup(true);
2651 5827 }
@@ -2724,9 +5900,13 @@
2724 5900 // Re-setup the element
2725 5901 var resetup_ele = function(history_array){
2726 5902 jQuery(history_array.cEle.cEle)[history_array.cEle.method](history_array.html);
2727 5903 pagelayer_element_setup('[pagelayer-id='+history_array.pl_id+'], [pagelayer-id='+history_array.pl_id+'] .pagelayer-ele', true);
2728 - 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);
2729 5909 };
2730 5910
2731 5911 // Re-setup the element attr
2732 5912 var reset_ele_attr = function(hEle, atts, val, attrType){
@@ -2747,10 +5927,69 @@
2747 5927 pagelayer.history_action = true;
2748 5928
2749 5929 };
2750 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 +
2751 5990 if(prev_item_id > current_item_id){
2752 -
5991 +
2753 5992 // All Actions for undo here
2754 5993 var i = parseInt(prev_item_id);
2755 5994
2756 5995 for(i; i > current_item_id; i--){
@@ -2755,26 +5994,31 @@
2755 5994
2756 5995 for(i; i > current_item_id; i--){
2757 5996
2758 5997 var history_array = pagelayer_history_obj['action_data'][i];
2759 - var action = history_array.action;
2760 - var id = history_array.pl_id;
5998 + var sub_actions_group = history_array['sub_actions_group'] || '';
2761 5999
2762 - if(action == "Edited"){
2763 - hEle = jQuery('[pagelayer-id="'+id+'"]');
2764 - reset_ele_attr(hEle, history_array.atts, history_array.oldVal, history_array.attrType);
2765 - }else if(action == "Added"){
2766 - delete_ele(id);
2767 - }else if(action == "Deleted"){
2768 - resetup_ele(history_array);
2769 - }else if(action == "Copied"){
2770 - 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 + }
2771 6006 }
2772 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 + }
2773 6017 }
2774 6018
2775 6019 }else{
2776 -
6020 +
2777 6021 // All Actions for redo here
2778 6022 var i = parseInt(prev_item_id)+1;
2779 6023
2780 6024 for(i; i <= current_item_id; i++){
@@ -2779,27 +6023,25 @@
2779 6023
2780 6024 for(i; i <= current_item_id; i++){
2781 6025
2782 6026 var history_array = pagelayer_history_obj['action_data'][i];
2783 - var action = history_array.action;
2784 - 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);
2785 6030
2786 - if(action == "Edited"){
2787 - hEle = jQuery('[pagelayer-id="'+id+'"]');
2788 - reset_ele_attr(hEle, history_array.atts, history_array.newVal, history_array.attrType);
2789 - }else if(action == "Added"){
2790 - resetup_ele(history_array);
2791 -
2792 - if(history_array.tag != "pl_row" && history_array.tag != "pl_col" ){
2793 - // Ensure the column is not empty
2794 - 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]);
2795 6035 }
2796 - }else if(action == "Deleted"){
2797 - delete_ele(id);
2798 - }else if(action == "Copied"){
2799 - resetup_ele(history_array);
2800 6036 }
2801 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 + }
2802 6044 }
2803 6045 }
2804 6046
2805 6047 };
@@ -2810,26 +6052,48 @@
2810 6052 alert(prefix+error);
2811 6053 };
2812 6054
2813 6055 function pagelayer_bottombar(){
2814 - var holder = pagelayer.$$('.pagelayer-bottombar-holder');
2815 - var html = '<div class="pagelayer-bottombar">'+
2816 - '<div class="pagelayer-bottombar-rightbuttons">'+
2817 - '<button class="pagelayer-update-button">Update</button>'+
2818 - '<button class="pagelayer-close-button">Close</button>'+
2819 - '<div class="pagelayer-mode-wrapper">'+
2820 - '<i class="pagelayer-mode-button fa fa-desktop"></i>'+
2821 - '<div class="pagelayer-mode-buttons-wrapper">'+
2822 - '<i class="screen-mode fa fa-desktop" pagelayer-mode-data="desktop"></i>'+
2823 - '<i class="screen-mode fa fa-tablet" pagelayer-mode-data="tablet"></i>'+
2824 - '<i class="screen-mode fa fa-mobile" pagelayer-mode-data="mobile"></i>'+
2825 - '</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>'+
2826 6071 '</div>'+
2827 - '<i class="pagelayer-history-icon fa fa-history"></i>'+
2828 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>'+
2829 6088 '</div>';
2830 6089
2831 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 +
2832 6096 holder.find('.pagelayer-update-button').on('click', function(){
2833 6097 pagelayer_save();
2834 6098 pagelayer_history_setup();// Setup history tab after update
2835 6099 });
@@ -2836,27 +6100,79 @@
2836 6100
2837 6101 holder.find('.pagelayer-close-button').on('click', function(){
2838 6102 pagelayer_close();
2839 6103 });
6104 +
2840 6105 holder.find('.screen-mode').on('click', function(){
2841 6106 var screen_mode = jQuery(this).attr('pagelayer-mode-data');
2842 6107 pagelayer_set_screen_mode(screen_mode);
2843 - holder.find('.pagelayer-mode-buttons-wrapper').toggle();
6108 + holder.find('.screen-mode').removeClass('active');
6109 + jQuery(this).addClass('active');
2844 6110 });
2845 6111
2846 - holder.find('.pagelayer-mode-button').on('click', function(){
2847 - 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();
2848 6118 });
2849 6119
2850 - holder.find('.pagelayer-history-icon').click(function(){
2851 - pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text('Pagelayer History');
2852 - pagelayer.$$('.pagelayer-elpd').hide();
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'));
2853 6122 pagelayer.$$('.pagelayer-logo').hide();
2854 - pagelayer.$$('.pagelayer-shortcodes').hide();
2855 - pagelayer.$$('.pagelayer-history').show();
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');
2856 6130 pagelayer_active = {};
2857 - pagelayer_history_setup();
2858 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 + });
2859 6175 };
2860 6176
2861 6177
2862 6178 ///////////////////////////////
@@ -2862,89 +6178,298 @@
2862 6178 ///////////////////////////////
2863 6179 // Miscellaneuos Functions
2864 6180 ///////////////////////////////
2865 6181
2866 -// Generates a random string of "n" characters
2867 -function pagelayer_randstr(n, special){
2868 - var text = '';
2869 - var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
6182 +// Setup General options
6183 +function pagelayer_setup_general_options(){
2870 6184
2871 - special = special || 0;
2872 - if(special){
2873 - possible = possible + '&#$%@';
6185 + var holder = pagelayer.$$('.pagelayer-general-options');
6186 +
6187 + if(holder.children().length > 0){
6188 + return;
2874 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>';
2875 6225
2876 - for(var i=0; i < n; i++){
2877 - text += possible.charAt(Math.floor(Math.random() * possible.length));
2878 - }
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 + });
2879 6263
2880 - return text;
2881 -};
6264 + modal.unbind('click');
6265 + modal.on('click', function(e){
6266 +
6267 + if(e.target != this) {
6268 + return;
6269 + }
2882 6270
2883 -function pagelayer_update_site_title(val){
2884 - if(!pagelayer_empty(val)){
2885 - var site_name = jQuery('.pagelayer-wp-title').attr('pagelayer-a-site_name');
2886 - if(!pagelayer_empty(site_name)){
2887 - var site_title = jQuery.ajax({
2888 - url: pagelayer_ajax_url+'&action=pagelayer_fetch_site_title',
2889 - type: 'post',
2890 - async: false
2891 - }).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(){
2892 6289
2893 - if(site_title != site_name){
2894 - var site_title = jQuery.ajax({
2895 - url: pagelayer_ajax_url+'&action=pagelayer_update_site_title',
2896 - type: 'post',
2897 - data: {'site_title': site_name},
2898 - async: false
2899 - }).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;
2900 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+']');
2901 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();
2902 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 +
2903 6416 }
2904 6417
2905 -function pagelayer_trim(str, charlist){
2906 - // discuss at: http://locutus.io/php/trim/
6418 +// Scroll page to element view port
6419 +function pagelayer_scroll_to_viewport(jEle, timeout, parentEle){
2907 6420
2908 - if(typeof str != 'string'){
2909 - return str;
2910 - }
6421 + var scrolled = parentEle || jQuery('html, body');
6422 + timeout = timeout || 500;
6423 + parentEle = parentEle || jQuery(window);
2911 6424
2912 - var whitespace = [' ', '\n', '\r', '\t', '\f', '\x0b', '\xa0', '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u2005', '\u2006', '\u2007', '\u2008', '\u2009', '\u200a', '\u200b', '\u2028', '\u2029', '\u3000' ].join('')
2913 - var l = 0
2914 - var i = 0
2915 - 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 + }
2916 6434
2917 - if (charlist) {
2918 - whitespace = (charlist + '').replace(/([[\]().?/*{}+$^:])/g, '$1')
2919 - }
6435 + var scrolling = elementTop - parentHeight / 2;
6436 + scrolled.stop(true).animate({
6437 + scrollTop: scrolling
6438 + }, 1000);
6439 + }, timeout);
6440 +}
2920 6441
2921 - l = str.length
2922 - for (i = 0; i < l; i++) {
2923 - if (whitespace.indexOf(str.charAt(i)) === -1) {
2924 - str = str.substring(i)
2925 - break
2926 - }
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 + '&#$%@';
2927 6450 }
2928 -
2929 - l = str.length
2930 - for (i = l - 1; i >= 0; i--) {
2931 - if (whitespace.indexOf(str.charAt(i)) === -1) {
2932 - str = str.substring(0, i + 1)
2933 - break
2934 - }
6451 +
6452 + for(var i=0; i < n; i++){
6453 + text += possible.charAt(Math.floor(Math.random() * possible.length));
2935 6454 }
2936 6455
2937 - return whitespace.indexOf(str.charAt(0)) === -1 ? str : ''
6456 + return text;
2938 6457 };
2939 6458
6459 +function pagelayer_randInt(max) {
6460 + return Math.floor(Math.random() * Math.floor(max));
6461 +}
6462 +
2940 6463 // Convert the regular URL of a Video to a Embed URL
2941 -function pagelayer_video_url(src){
2942 -
6464 +function pagelayer_video_url(src, no_url){
6465 +
6466 + no_url = no_url || false;
2943 6467 var youtubeRegExp = /youtube\.com|youtu\.be/;
2944 6468 var vimeoRegExp = /vimeo\.com/;
2945 6469 var match = '';
2946 6470 var videoId = '';
6471 + var vid_params = {};
2947 6472
2948 6473 if (youtubeRegExp.exec(src)) {
2949 6474 match = 'youtube';
2950 6475 } else if (vimeoRegExp.exec(src)) {
@@ -2971,9 +6496,15 @@
2971 6496 } else if (youtube.exec(src)) {
2972 6497 videoId = src.split('.be/');
2973 6498 }
2974 6499
2975 - 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();
2976 6507
2977 6508 break;
2978 6509
2979 6510 case 'vimeo':
@@ -2986,48 +6517,88 @@
2986 6517 } else if (vimeoRegExp.exec(src)) {
2987 6518 videoId = src.split('.com/');
2988 6519 }
2989 6520
2990 - 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 + };
2991 6526
2992 6527 break;
2993 6528 default:
2994 - return src;
6529 + vid_params = {
6530 + type : 'local',
6531 + src : src
6532 + };
6533 +
2995 6534 }
6535 +
6536 + if(!no_url){
6537 + return vid_params.src;
6538 + }
6539 +
6540 + return vid_params;
2996 6541 };
2997 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 +
2998 6554 // Add widget section
2999 6555 function pagelayer_add_widget(){
3000 6556
3001 6557 html='<div class="pagelayer-add-widget-area">'+
3002 - '<i class="pagelayer-add-row fa fa-plus-circle"></i>'+
3003 - '<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>'+
3004 6564 '</div>';
3005 6565
3006 - jQuery('.entry-content').append(html);
6566 + jQuery(pagelayer_editable).append(html);
3007 6567
3008 6568 var add_area = jQuery('.pagelayer-add-widget-area');
3009 6569
3010 6570 // Add a code before this
3011 - var add_sc = function(tag){
6571 + var add_sc = function(tag, global_id = ''){
3012 6572
6573 + var attr = '';
6574 + if(!pagelayer_empty(global_id)){
6575 + attr = ' pagelayer-global-id="'+global_id+'" ';
6576 + }
6577 +
3013 6578 // Create Row
3014 - var row = jQuery('<div pagelayer-tag="pl_row"></div>');
6579 + var row = jQuery('<div pagelayer-tag="pl_row" '+((tag == 'pl_row') ? attr : '') +'></div>');
3015 6580 add_area.before(row);
3016 6581 var row_id = pagelayer_onadd(row, false);
3017 6582 var rEle = pagelayer_ele_by_id(row_id);
3018 6583
3019 - if(tag == 'pl_row'){
6584 + if(tag == 'pl_row' && !pagelayer_empty(global_id)){
3020 6585 rEle.click();
3021 6586 return row_id;
3022 6587 }
3023 6588
3024 6589 // Create Column
3025 - var col = jQuery('<div pagelayer-tag="pl_col"></div>');
6590 + var col = jQuery('<div pagelayer-tag="pl_col" '+((tag == 'pl_col') ? attr : '') +'></div>');
3026 6591 rEle.find('.pagelayer-row-holder').append(col);
3027 6592 var col_id = pagelayer_onadd(col, false);
3028 6593 var cEle = pagelayer_ele_by_id(col_id);
3029 6594
6595 +
6596 + if(tag == 'pl_row'){
6597 + rEle.click();
6598 + return row_id;
6599 + }
6600 +
3030 6601 if(tag == 'pl_col'){
3031 6602 cEle.click();
3032 6603 return col_id;
3033 6604 }
@@ -3032,24 +6603,66 @@
3032 6603 return col_id;
3033 6604 }
3034 6605
3035 6606 // Create element
3036 - var ele = jQuery('<div pagelayer-tag="'+tag+'"></div>');
6607 + var ele = jQuery('<div pagelayer-tag="'+tag+'" '+attr+'></div>');
3037 6608 cEle.find('.pagelayer-col-holder').append(ele);
6609 + //console.log(ele);
3038 6610 var id = pagelayer_onadd(ele);
3039 -
6611 + //console.log(id);
6612 + //console.log(col_id);
6613 + var eEle = pagelayer_ele_by_id(col_id);
6614 + //console.log(eEle);
3040 6615 // Ensure the column is not empty
3041 6616 pagelayer_empty_col(cEle.find('.pagelayer-col-holder'));
3042 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 +
3043 6625 return id;
3044 6626
3045 6627 }
3046 6628
3047 - // Handle Click
3048 - add_area.on('click', function(){
6629 + // Handle Click on Plus Button
6630 + add_area.find('.pagelayer-add-circle-plus').on('click', function(e){
6631 + e.stopPropagation();
3049 6632 add_sc('pl_col');
3050 6633 });
3051 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 +
3052 6665 // Handle Drag over
3053 6666 add_area.on('dragover', function(e){
3054 6667 //console.log(e)
3055 6668 add_area.addClass('pagelayer-add-widget-drag');
@@ -3069,8 +6682,9 @@
3069 6682 add_area.removeClass('pagelayer-add-widget-drag');
3070 6683 jQuery('.pagelayer-is-dragging').removeClass('pagelayer-is-dragging');
3071 6684
3072 6685 var tag = e.originalEvent.dataTransfer.getData('tag');
6686 + var global_id = e.originalEvent.dataTransfer.getData('global_id');
3073 6687
3074 6688 // Is it an existing element ?
3075 6689 if(tag.length < 1){
3076 6690 return false;
@@ -3079,7 +6693,1490 @@
3079 6693 e.preventDefault();
3080 6694
3081 6695 //console.log(tag);
3082 6696
3083 - add_sc(tag);
6697 + add_sc(tag, global_id);
3084 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 ;
3085 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 +