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 +5226 -590 1.0.0 → 2.2.2 View file →
@@ -8,19 +8,105 @@
8 8 $: jQuery,
9 9 $$ : function(select){
10 10 return jQuery(select, window.parent.document);
11 11 },
12 + gDocument : jQuery(window.parent.document).add(document),
12 13 p : this,
13 14 copy_selected: '',
14 15 mouse: {x: -1, y: -1},
15 16 history_action : true,
17 + global_render : true,
18 + history_lastTime : new Date(),
19 + props_ref : {},
20 + pro_txt : '',
21 + loaded : 0,
22 + post_status : '',
23 + el: {},// All elements data
16 24 }
17 25
18 26 var pagelayer_history_obj = {}, pagelayer_revision_obj = {};
27 +var pagelayer_add_section_data = {};
19 28
29 +// Console error manager
30 +window.onerror = function (msg, url, lineNo, columnNo, error) {
31 +
32 + if (typeof pagelayer_doc_width === 'undefined') {
33 + var test_giver = -1;
34 +
35 + jQuery.ajax({
36 + url: pagelayer_url+'/js/givejs.php?test=1',
37 + type: "GET",
38 + dataType: "text",
39 + success: function(data){
40 +
41 + if(data != 1){
42 + return;
43 + }
44 +
45 + test_giver = 1;
46 + },
47 + complete: function(data){
48 + jQuery.ajax({
49 + type: "POST",
50 + url: pagelayer_ajax_url+"&action=pagelayer_set_jscss_giver",
51 + data: {
52 + pagelayer_nonce: pagelayer_ajax_nonce,
53 + set : test_giver
54 + },
55 + error: function(errorThrown){
56 + console.log("Error saving giver data");
57 + console.log(errorThrown);
58 + }
59 + });
60 + }
61 + });
62 + }
63 +
64 + var string = msg.toLowerCase();
65 + var substring = "script error";
66 +
67 + if(pagelayer.loaded > 0){
68 + return;
69 + }
70 +
71 + if (string.indexOf(substring) > -1){
72 + return;
73 + }
74 +
75 + if(url.indexOf('pagelayer')=== -1){
76 + return;
77 + }
78 +
79 + var message = [
80 + "Message: " + msg,
81 + "\r\n<br>URL: " + url,
82 + "\r\n<br>Line: " + lineNo,
83 + "\r\n<br>Column: "+ columnNo,
84 + "\r\n<br>Error object: " + error
85 + ].join('\n');
86 + //alert("Script Error: See browser console for details");
87 +
88 + pagelayer.$$('.pagelayer-errorBox-content').html(message);
89 + pagelayer.$$('.pagelayer-errorBox-close').on('click', function(){
90 + pagelayer.$$('.pagelayer-errorBox').fadeOut();
91 + });
92 + pagelayer.$$('.pagelayer-errorBox').fadeIn();
93 +
94 + return false;
95 +};
96 +
20 97 // Lets start
21 -jQuery(document).ready(function(){
98 +jQuery(document).ready(pagelayer_start);
99 +
100 +// Function to load the codes
101 +function pagelayer_start(){
22 102
103 + pagelayer.loading = 1;
104 + console.log('['+pagelayer_brand+'] Starting Pagelayer');
105 +
106 + // Prevent the click Insite editor
107 + pagelayer_prevent_click();
108 +
23 109 // Set the title of the parent window
24 110 try{ pagelayer.$$('head').append(pagelayer.$('title')[0].outerHTML); }catch(e){};
25 111
26 112 pagelayer.blank_img = pagelayer_url+'/images/default-image.png';
@@ -27,15 +113,21 @@
27 113
28 114 pagelayer_shortcodes['pl_inner_row'] = JSON.parse(JSON.stringify(pagelayer_shortcodes['pl_row']));
29 115 pagelayer_shortcodes['pl_inner_row']['name'] = 'Inner Row';
30 116 pagelayer_groups['grid'].push('pl_inner_row');
117 +
118 + // Removing post props options
119 + pagelayer_setting_post_props();
31 120
32 121 // Make the Topbar
33 122 pagelayer_bottombar();
34 123
35 124 // Make the Leftbar
36 - pagelayer_leftbar();
37 -
125 + pagelayer_leftbar();
126 +
127 + // Make widget list toolbar
128 + pagelayer_create_widget_tooltip();
129 +
38 130 // Add widget section
39 131 pagelayer_add_widget();
40 132
41 133 // Setup the ELPD
@@ -40,8 +132,11 @@
40 132
41 133 // Setup the ELPD
42 134 pagelayer_elpd_setup();
43 135
136 + // Dump the data we have
137 + pagelayer_element_dump_data();
138 +
44 139 // Setup the properties of the elements
45 140 pagelayer_element_setup();
46 141
47 142 // An image to show for drag
@@ -49,11 +144,17 @@
49 144
50 145 // Setup the grid drag
51 146 pagelayer_setup_drag();
52 147
148 + // Set left bar draggable
149 + pagelayer_make_leftbar_movable();
150 +
53 151 // Set to desktop
54 152 pagelayer_set_screen_mode('desktop');
55 153
154 + // Create list of fonts
155 + pagelayer_fonts = pagelayer_l('pl_fonts_list');
156 +
56 157 // Set up right click
57 158 pagelayer_left_click();
58 159 pagelayer_right_click();
59 160
@@ -59,14 +160,315 @@
59 160
60 161 // Setup pagelayer history handle
61 162 pagelayer_history_obj['action_data'] = [];
62 163 pagelayer_history_setup(true);
164 +
165 + // Make a quick access of the props
166 + pagelayer_make_props_ref();
167 +
168 + // Post props exported defaults need to be updated
169 + pagelayer_set_exported_defaults();
170 +
171 + // Do any actions here
172 + pagelayer_trigger_action('pagelayer_setup_history');
173 +
174 + // Editor Tooltips
175 + pagelayer_tooltip_setup();
176 +
177 + // Load Fonts
178 + for(var x in pagelayer_loaded_icons){
179 + var item = pagelayer_loaded_icons[x];
180 + jQuery.when(
181 + pagelayer_get_stored_data(pagelayer_url+'/fonts/'+item+'.json', pagelayer_ver)
182 + ).then(function(){
183 + pagelayer_icons[item] = JSON.parse(pagelayer_get_stored_data(pagelayer_url+'/fonts/'+item+'.json', pagelayer_ver));
184 + });
185 + };
63 186
64 -});
187 + // Set row-option top zero(0) of the first row
188 + pagelayer_set_row_option_position();
189 +
190 + // Just the txt
191 + pagelayer.pro_txt = pagelayer_pro_txt;
192 +
193 + // Open post props on document load
194 + pagelayer.$$('.pagelayer-settings').click();
195 +
196 + // Open post props and Make elements editable to edit post props data
197 + pagelayer_setup_props_editable();
198 +
199 + // Make elements editable
200 + jQuery(pagelayer_editable+' [pagelayer-editable]').attr('contenteditable', 'true');
201 +
202 + // Use text widget for search widget
203 + pagelayer_search_widgets();
204 +
205 + // Hide the loader
206 + pagelayer_loader_hide();
207 +
208 + // ON comment mode
209 + const urlParams = new URLSearchParams(window.location.search);
210 + pagelayer.cmode = urlParams.get('cmode');
211 +
212 + // Start custom UX Improvements engine
213 + setTimeout(pagelayer_ux_improvements_init, 200);
214 +}
65 215
216 +// Post props attribute
217 +function pagelayer_post_props_atts(prop, val, temp){
218 +
219 + val = val || null;
220 + temp = temp || false;
221 +
222 + var proEle = jQuery(pagelayer_editable+' .pagelayer-post_props.pagelayer-ele').first();
223 +
224 + if(!pagelayer_empty(temp)){
225 + if(val === null){
226 + return pagelayer_get_tmp_att(proEle, prop);
227 + }
228 +
229 + // Set the temp property as well
230 + pagelayer_set_tmp_atts(proEle, prop, val);
231 + return true;
232 + }
233 +
234 + if(val === null){
235 + return pagelayer_get_att(proEle, prop);
236 + }
237 +
238 + // Set the property as well
239 + pagelayer_set_atts(proEle, prop, val);
240 + return true;
241 +}
242 +
243 +// Open post props and Make elements editable to edit post props data
244 +function pagelayer_setup_props_editable(){
245 +
246 + jQuery('[pagelayer-props-editable]').each(function(){
247 + var jEle = jQuery(this);
248 +
249 + // Skip element under the editable area
250 + if (jEle.closest(pagelayer_editable).length > 0) {
251 + return;
252 + }
253 +
254 + var prop = jEle.attr('pagelayer-props-editable');
255 +
256 + // Make editable
257 + jEle.attr('contenteditable', 'true');
258 +
259 + // Reverse setup the event
260 + jEle.on('focus', function(){
261 + // Set the property as well
262 + var data = pagelayer_post_props_atts(prop);
263 + jEle.html(data);
264 + });
265 +
266 + // Reverse setup the event
267 + jEle.on('input', function(){
268 +
269 + var val = pagelayer_trim(jEle.html());
270 +
271 + // Set the property as well
272 + pagelayer_post_props_atts(prop, val);
273 +
274 + // Update the property
275 + var input = pagelayer.$$('[pagelayer-elp-name='+prop+']').find('input,textarea,.trumbowyg-editor');
276 + //console.log(input);
277 +
278 + if(input.length > 0){
279 + if(input.hasClass('trumbowyg-editor')){
280 + input.html(val);
281 + }else{
282 + input.val(val);
283 + }
284 + }
285 +
286 + });
287 +
288 + });
289 +
290 +}
291 +
292 +// Prevent the click Insite editor
293 +function pagelayer_prevent_click(){
294 + jQuery(document).on('submit', function(event){
295 + var target = jQuery(event.target);
296 + if (target.closest(pagelayer_editable).length < 1) {
297 + event.preventDefault();
298 + }
299 + });
300 +
301 + jQuery(document).on('click', function(event){
302 + var target = jQuery(event.target);
303 + if (target.closest('a').length > 0 && target.closest(pagelayer_editable).length < 1) {
304 + event.preventDefault()
305 + }
306 + });
307 +}
308 +
309 +// Removing post props options from the editor
310 +function pagelayer_setting_post_props(){
311 +
312 + if(pagelayer_empty(pagelayer_post_categories)){
313 + delete pagelayer_shortcodes.pl_post_props.postCategory;
314 + }
315 +
316 + if(pagelayer_empty(pagelayer_post_tags)){
317 + delete pagelayer_shortcodes.pl_post_props.postTags;
318 + }
319 +
320 + if(pagelayer_empty(pagelayer_shortcodes.pl_post_props.pageParent.post_parent.list)){
321 + delete pagelayer_shortcodes.pl_post_props.pageParent;
322 + }
323 +
324 + if(pagelayer_post.post_type != 'post'){
325 + delete pagelayer_shortcodes.pl_post_props.params.post_sticky;
326 + }
327 +
328 + if(pagelayer_empty(pagelayer_post_type_features['comments'])){
329 + delete pagelayer_shortcodes.pl_post_props.postDiscussion.comment_status;
330 + }
331 +
332 + if(pagelayer_empty(pagelayer_post_type_features['trackbacks'])){
333 + delete pagelayer_shortcodes.pl_post_props.postDiscussion.ping_status;
334 + }
335 +
336 + if(pagelayer_empty(pagelayer_shortcodes.pl_post_props.postDiscussion)){
337 + delete pagelayer_shortcodes.pl_post_props.postDiscussion;
338 + }
339 +
340 + if(pagelayer_empty(pagelayer_post_type_features['excerpt'])){
341 + delete pagelayer_shortcodes.pl_post_props.postExcerpt;
342 + }
343 +
344 + if(pagelayer_empty(pagelayer_post_type_features['thumbnail'])){
345 + delete pagelayer_shortcodes.pl_post_props.postFeaturedImage;
346 + }
347 +
348 + if(pagelayer_empty(pagelayer_post_type_features['author'])){
349 + delete pagelayer_shortcodes.pl_post_props.params.post_author;
350 + }
351 +}
352 +
353 +// Set the default values of all default exported codes
354 +function pagelayer_set_exported_defaults(){
355 +
356 + // Set defaults for the exported variety
357 + if(pagelayer_empty(pagelayer_default_params)){
358 + return;
359 + }
360 +
361 + for(var tag in pagelayer_default_params){
362 +
363 + for(var x in pagelayer_default_params[tag]){
364 +
365 + if(x in pagelayer.props_ref[tag]){
366 + pagelayer.props_ref[tag][x]['default'] = pagelayer_default_params[tag][x];
367 + }
368 +
369 + }
370 +
371 + }
372 +
373 +}
374 +
375 +// Do pagelayer Dirty
376 +function pagelayer_do_dirty(jEle){
377 +
378 + pagelayer_isDirty = true;
379 +
380 + if (!window.onbeforeunload) {
381 + window.onbeforeunload = function(){
382 + return true;
383 + };
384 + }
385 +
386 + pagelayer_trigger_action('pagelayer_do_dirty', [jEle]);
387 +}
388 +
389 +function pagelayer_do_undirty(){
390 +
391 + pagelayer_isDirty = false;
392 +
393 + if (window.onbeforeunload) {
394 + window.onbeforeunload = null;
395 + }
396 +
397 +}
398 +
399 +// Executes when pagelayer is fully loaded
400 +function pagelayer_loader_hide(){
401 + var inner = pagelayer.$$('.pagelayer-percent');
402 + inner.attr('loaded', 1);
403 + var w = parseInt(inner.text());
404 + var t = setInterval(function() {
405 + w = w + 1;
406 + inner.html(w +'<sup>%</sup>');
407 + if (w >= 100){
408 + clearInterval(t);
409 + w = 0;
410 + var loaderWrapper = pagelayer.$$('#pagelayer-loader-wrapper');
411 + loaderWrapper.addClass('pagelayer-loaded');
412 + loaderWrapper.animate({opacity:0}, function(){
413 + loaderWrapper.remove();
414 + });
415 + }
416 + }, 1);
417 + pagelayer.loaded = 1;
418 +}
419 +
420 +// Set row-option top zero(0) of the first row
421 +function pagelayer_set_row_option_position(){
422 + try{
423 + if(jQuery(pagelayer_editable).offset().top < 20){
424 + jQuery(pagelayer_editable).addClass('pagelayer-row-option-zero');
425 + }
426 + }catch(e){
427 + console.log(pagelayer_editable+" not found and hence Pagelayer wont work on this page !");
428 + }
429 +}
430 +
66 431 // The jQuery Object of the ELPD
67 432 var pagelayer_elpd;
68 433
434 +// Store data values
435 +function pagelayer_get_stored_data(url, version){
436 + var name = 'pagelayer_'+url;
437 + var data = {};
438 + var force = false;
439 +
440 + // Try to parse the data
441 + try{
442 + data = JSON.parse(localStorage.getItem(name));
443 +
444 + if(data['version'] !== version){
445 + force = true;
446 + }
447 +
448 + }catch(e){
449 + force = true;
450 + }
451 +
452 + // Force download
453 + if(force){
454 + return jQuery.ajax({
455 + url: url,
456 + type: 'GET',
457 + dataType: 'text',
458 + success:function(newData){
459 + var data = {};
460 + data['version'] = version;
461 + data['val'] = newData;
462 + localStorage.setItem(name, JSON.stringify(data));
463 + }
464 + });
465 + }
466 +
467 + return data['val'];
468 +
469 +}
470 +
69 471 function pagelayer_closest_corner(jEle){
70 472 var corners = [];
71 473 var w = jEle.outerWidth();
72 474 var h = jEle.outerHeight();
@@ -100,8 +502,115 @@
100 502 return corner;
101 503
102 504 };
103 505
506 +// Make left bar draggable
507 +function pagelayer_make_leftbar_movable(){
508 + var pl_iframe = pagelayer.$$('.pagelayer-iframe'),
509 + pl_leftbar = pagelayer.$$('.pagelayer-leftbar-table');
510 +
511 + // On mouse down in pagelayer-topbar-holder
512 + pagelayer.$$('.pagelayer-topbar-mover').on('mousedown', function(e){
513 + e = e || window.event;
514 + e.preventDefault();
515 +
516 + // Get leftbar position
517 + var orig_eleX = pl_leftbar.offset().left;
518 + var orig_eleY = pl_leftbar.offset().top;
519 +
520 + // Get the mouse cursor position at startup:
521 + var posX = e.clientX;
522 + var posY = e.clientY;
523 +
524 + // The variable needs to be empty.
525 + var newMethod = '',
526 + change = true;
527 +
528 + var leftbar_mousemove = function(e){
529 + e = e || window.event;
530 +
531 + if(change){
532 + // Add class to leftbar
533 + pl_leftbar.addClass('pagelayer-leftbar-moving');
534 +
535 + // Add left-right overlay
536 + pl_iframe.before('<div class="pagelayer-leftbar-move pagelayer-moveto-left"></div>');
537 + pl_iframe.after('<div class="pagelayer-leftbar-move pagelayer-moveto-right"></div>');
538 + pagelayer.$$('body').addClass('pagelayer-overflow-hidden');
539 + change = false;
540 + }
541 +
542 + // calculate the new cursor position and set the element left-top position
543 + var top = orig_eleY + (e.clientY - posY);
544 + var left = orig_eleX + (e.clientX - posX);
545 +
546 + // set the element's new position:
547 + pl_leftbar.css({'top': top +'px','left': left +'px'});
548 + pagelayer.$$('.pagelayer-leftbar-toggle').hide();
549 +
550 + // Make a copy of new method
551 + var _newMethod = newMethod;
552 + newMethod = '';
553 +
554 + // Get near by corner
555 + var offleft = pl_iframe.offset().left;
556 +
557 + if(offleft + 100 > e.clientX){
558 + newMethod = 'before';
559 + }else if(offleft+pl_iframe.outerWidth()- 100 < e.clientX){
560 + newMethod = 'after';
561 + }
562 +
563 + if(_newMethod != newMethod){
564 + pagelayer.$$('.pagelayer-leftbar-move').css({'width' :'', 'opacity': '0.33'});
565 +
566 + if(newMethod == 'after'){
567 + pagelayer.$$('.pagelayer-moveto-right').animate({'width' :'60px', 'opacity': '0.66'}, 200);
568 + pl_leftbar.addClass('pagelayer-rightbar');
569 + }else if(newMethod == 'before'){
570 + pagelayer.$$('.pagelayer-moveto-left').animate({'width' : '60px', 'opacity': '0.66'}, 200);
571 + pl_leftbar.removeClass('pagelayer-rightbar');
572 + }
573 + }
574 +
575 + };
576 +
577 + var leftbar_mouseup = function(e){
578 +
579 + // Remove events
580 + pagelayer.gDocument.off('mousemove', leftbar_mousemove);
581 + pagelayer.gDocument.off('mouseup', leftbar_mouseup);
582 +
583 + // Remove class to leftbar
584 + pagelayer.$$('.pagelayer-leftbar-move').remove();
585 +
586 + var windowHeight = jQuery(window).height();
587 +
588 + if(pl_leftbar.offset().top < 0){
589 + pl_leftbar.css({'top': '10px'});
590 + }else if( (windowHeight - e.clientY) < 10){
591 + pl_leftbar.css({'top': ''+windowHeight - 40+'px'});
592 + }
593 +
594 + if( !pagelayer_empty(newMethod)){
595 + pl_leftbar.removeClass('pagelayer-leftbar-moving');
596 + pl_leftbar.removeAttr('style');
597 + pagelayer.$$('.pagelayer-leftbar-toggle').show();
598 + pagelayer.$$('body').removeClass('pagelayer-overflow-hidden');
599 + pl_iframe[newMethod](pl_leftbar);
600 + }
601 +
602 + // make change true
603 + change = true;
604 + };
605 +
606 + pagelayer.gDocument.on('mouseup', leftbar_mouseup);
607 + pagelayer.gDocument.on('mousemove', leftbar_mousemove);
608 +
609 + });
610 +
611 +}
612 +
104 613 // Make rows and cols draggable
105 614 function pagelayer_setup_drag(){
106 615
107 616 // The object to show as drag
@@ -219,9 +728,21 @@
219 728 var onWrap;
220 729
221 730 // If we are a column, we can be over another column or row
222 731 if(tag == 'pl_col'){
223 - onWrap = jQuery(ele).closest('.pagelayer-wrap-col,.pagelayer-wrap-row,.pagelayer-wrap-inner-row');
732 +
733 + // Prevent column in inner-row and it's columns, if the draged column have inner-rows
734 + if(wrap.find('.pagelayer-wrap-inner-row').length > 0){
735 + onWrap = jQuery(ele).closest('.pagelayer-wrap-col,.pagelayer-wrap-row');
736 +
737 + var innerRow = onWrap.closest(pagelayer_editable +' .pagelayer-wrap-inner-row');
738 + if( onWrap.length < 1 || innerRow.length > 0){
739 + onWrap = jQuery(innerRow).closest('.pagelayer-wrap-col,.pagelayer-wrap-row');
740 + }
741 +
742 + }else{
743 + onWrap = jQuery(ele).closest('.pagelayer-wrap-col,.pagelayer-wrap-row,.pagelayer-wrap-inner-row');
744 + }
224 745 //console.log(pagelayer_id(onWrap));
225 746
226 747 // If we are a row, we can be over another row or a column
227 748 }else if(tag == 'pl_row'){
@@ -229,10 +750,14 @@
229 750 //console.log(pagelayer_id(onWrap));
230 751
231 752 // For inner row we restrict to 1 level only
232 753 }else if(tag == 'pl_inner_row'){
754 +
233 755 var ele_wrap = jQuery(ele).parents('.pagelayer-wrap-col');
234 - if(ele_wrap.length == 1 && !jQuery(ele).hasClass('pagelayer-wrap-col')){
756 + if(
757 + (ele_wrap.length == 1 && !jQuery(ele).hasClass('pagelayer-wrap-col')) ||
758 + (ele_wrap.length == 0 && jQuery(ele).hasClass('pagelayer-wrap-col'))
759 + ){
235 760 onWrap = jQuery(ele).closest('.pagelayer-wrap-ele,.pagelayer-wrap-col,.pagelayer-wrap-inner-row');
236 761 }else{
237 762 onWrap = jQuery(ele).closest('.pagelayer-wrap-inner-row');
238 763 }
@@ -238,8 +763,70 @@
238 763 }
239 764 // For every other element, we can be over a col or ele
240 765 }else{
241 766 onWrap = jQuery(ele).closest('.pagelayer-wrap-ele,.pagelayer-wrap-col,.pagelayer-wrap-inner-row');
767 +
768 + // If we are inside the same widget tag
769 + // We are allowing for now, hence the following is commented
770 + /*var sameTag = onWrap.closest(pagelayer_editable +' [pagelayer-tag="'+tag+'"]');
771 + if(sameTag.length > 0){
772 + onWrap = sameTag.closest('.pagelayer-wrap-ele');
773 + }*/
774 +
775 + // Is prevent to go inside any widget?
776 + if('prevent_inside' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['prevent_inside'])){
777 +
778 + var preTags = pagelayer_shortcodes[tag]['prevent_inside'];
779 + var prevent_inside = false;
780 + var preEle = onWrap;
781 +
782 + if(typeof preTags === 'string'){
783 + preTags = [preTags];
784 + }
785 +
786 + for(var toFind in preTags){
787 + preEle = onWrap.closest(pagelayer_editable +' [pagelayer-tag="'+preTags[toFind]+'"]');
788 + if (preEle.length > 0) {
789 + prevent_inside = true;
790 + break;
791 + }
792 + }
793 +
794 + // If we find
795 + if(prevent_inside){
796 + onWrap = preEle.closest('.pagelayer-wrap-ele');
797 + }
798 + }
799 +
800 + var widGroup = onWrap.closest('.pagelayer-ele-widget-group');
801 +
802 + // If we are inside the group widget
803 + if(widGroup.length > 0 && widGroup.closest(pagelayer_editable).length > 0){
804 +
805 + var wGroupTag = pagelayer_tag(widGroup);
806 + var use_inside = false;
807 +
808 + // If defined use inside only
809 + if('use_inside' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['use_inside'])){
810 +
811 + var inTags = pagelayer_shortcodes[tag]['use_inside'];
812 +
813 + if(typeof inTags === 'string'){
814 + inTags = [inTags];
815 + }
816 +
817 + for(var toFind in inTags){
818 + if (wGroupTag == inTags[toFind]) {
819 + use_inside = true;
820 + }
821 + }
822 + }
823 +
824 + // If we find nothing
825 + if(!use_inside){
826 + onWrap = widGroup.parent('.pagelayer-wrap-ele');
827 + }
828 + }
242 829 }
243 830 //console.log(onWrap);
244 831
245 832 // If we find nothing
@@ -267,20 +854,29 @@
267 854 }
268 855 }*/
269 856
270 857 // Get the ID
271 - var onId = onWrap.attr('pagelayer-wrap-id');
272 - var onEle = onWrap.children('.pagelayer-ele');
858 + var onId = pagelayer_id(onWrap);
859 + var onEle = pagelayer_ele_by_id(onId);
273 860
274 861 // Do we have a parent ?
275 - var pOnId = pagelayer_get_parent(onEle);
276 -
277 - 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 +
278 869 onId = pOnId;
279 - onEle = pagelayer_ele_by_id(onId);
280 - 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 +
281 874 }
282 875
876 + // Do we have a parent ?
877 + have_parent(onEle);
878 +
283 879 var changed = false;
284 880
285 881 // Was it the same ID like the one we were on before
286 882 if(pagelayer.drag_closest != onId){
@@ -320,10 +916,10 @@
320 916 }
321 917
322 918 //console.log(changed);
323 919
324 - // If we are on our self then clear return false
325 - 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')){
326 922 clear_prospect();// Clear existing prospects
327 923 reset_on_drag();// Also reset the last on item
328 924 return false;
329 925 }
@@ -420,10 +1016,17 @@
420 1016 e.preventDefault();
421 1017
422 1018 var wrap = pagelayer.dragging;
423 1019 var tag = pagelayer_tag(wrap);
1020 + var gId = wrap.attr('pagelayer-global-id');
424 1021 var fromEl = wrap.parent();
425 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 +
426 1029 wrap.removeClass('pagelayer-is-dragging');
427 1030
428 1031 // Find any prospect
429 1032 var prospect = jQuery('.pagelayer-drag-prospect');
@@ -437,15 +1040,25 @@
437 1040 var onTag = pagelayer_tag(onWrap);
438 1041 var dropped;
439 1042 var corner = prospect.attr('pagelayer-corner');
440 1043 var method = (corner == 'top') ? 'before' : 'after';
1044 + var before_loc; // Location before the drop
441 1045
442 1046 // Create the element if it needs to be created
443 - if(pagelayer.drag_is_new){
1047 + if(pagelayer.drag_is_new){
444 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 + }
445 1054
446 1055 // Move the object
447 1056 }else{
1057 +
1058 + // Get near by element before move
1059 + before_loc = pagelayer_near_by_ele(pagelayer_id(wrap), tag);
1060 +
448 1061 dropped = wrap;
449 1062 dropped.detach();
450 1063 }
451 1064
@@ -467,12 +1080,30 @@
467 1080
468 1081 // Trigger the onadd
469 1082 if(pagelayer.drag_is_new){
470 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 + }
471 1091
472 1092 // Existing elements
473 1093 }else{
474 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));
475 1106 }
476 1107
477 1108 // Defining the variables as needed
478 1109 var jEle = pagelayer_ele_by_id(id);
@@ -520,13 +1151,14 @@
520 1151 jQuery(document).on('dragover', ondragover);
521 1152 jQuery(document).on('drop', ondrop);
522 1153
523 1154 // For addition of new elements
524 - pagelayer.$$('[pagelayer-tag]').on('dragstart', function(e){
1155 + pagelayer.$$('.pagelayer-leftbar').on('dragstart', function(e){
525 1156 //console.log(e);
526 1157
527 1158 var tEle = jQuery(e.target);
528 1159 var jEle = tEle.closest('.pagelayer-shortcode-drag');
1160 + var global_id = jEle.attr('pagelayer-global-id');
529 1161
530 1162 // Is it an existing element ?
531 1163 if(jEle.length < 1){
532 1164 return false;
@@ -533,8 +1165,12 @@
533 1165 }
534 1166
535 1167 e.originalEvent.dataTransfer.setData('tag', pagelayer_tag(jEle));
536 1168
1169 + if(!pagelayer_empty(global_id)){
1170 + e.originalEvent.dataTransfer.setData( 'global_id', global_id );
1171 + }
1172 +
537 1173 pagelayer.dragging = jEle;
538 1174 pagelayer.drag_is_new = true;
539 1175
540 1176 });
@@ -578,17 +1214,25 @@
578 1214
579 1215 // Column is becoming blank, so show add ele
580 1216 if(jEle.children().length < 1){
581 1217 //from.addClass('pagelayer-empty-col');
582 - jEle.append('<div class="pagelayer-add-ele pagelayer-ele-wrap"><i class="fa fa-plus"><br /><span>Empty column please Drag Widgets</span></i></div>');
1218 + jEle.append('<div class="pagelayer-add-ele pagelayer-ele-wrap"><i class="fas fa-plus"></i><br /><span>Empty column please Drag Widgets</span></div>');
583 1219 //var h = jEle.parent().parent().children('.pagelayer-ele-overlay').height();
584 1220 //jEle.children('.pagelayer-add-ele').height(h);
585 1221
586 1222 // Any add ele sign with non-empty columns here ?
587 - }else if(jEle.children('.pagelayer-add-ele').length > 0){
1223 + }else if(jEle.children('.pagelayer-add-ele').length > 0 && jEle.children().length > 1){
588 1224 jEle.children('.pagelayer-add-ele').remove();
589 1225 }
590 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 +
591 1235 });
592 1236
593 1237 };
594 1238
@@ -618,13 +1262,13 @@
618 1262 }
619 1263 }
620 1264 jEle.addClass('pagelayer-col-'+cols);
621 1265 jEle.css({'width': ''});
622 - Ele.addClass('pagelayer-col-'+cols);
623 - Ele.css({'width': ''});
624 1266
625 1267 // Set the att
626 1268 pagelayer_set_atts(Ele, obj);
1269 + pagelayer_set_atts(Ele, 'col_width','');
1270 + pagelayer_sc_render(Ele)
627 1271 });
628 1272 }
629 1273
630 1274 // Make column resizable handler
@@ -631,13 +1275,9 @@
631 1275 function pagelayer_col_make_resizable(wrap){
632 1276
633 1277 // Resize handler element
634 1278 var rHandler = jQuery('<div class="pagelayer-resize-handler"><div class="pagelayer-resize-icon"></div></div>');
635 -
636 - if( wrap.is(":last-child") ){
637 - wrap = wrap.prev();
638 - }
639 -
1279 +
640 1280 var pResize = wrap.children('.pagelayer-ele-overlay').find('.pagelayer-resize-handler');
641 1281
642 1282 if(pResize.length > 0){
643 1283 return;
@@ -654,13 +1294,16 @@
654 1294 var rHolder_width = wrap.closest('.pagelayer-row-holder').width();
655 1295 var new_width, nEle_new_width;
656 1296
657 1297 // Original width
658 - var original_width = wrap.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'));
659 1300 var original_mouse_x = e.pageX;
660 1301
1302 + var both_width = parseInt(original_width + next_ele_width);
1303 +
661 1304 // Add the element width and next element width
662 - both_width = (original_width / rHolder_width *100) + (next_ele.width() / rHolder_width *100);
1305 + both_width = ((both_width / rHolder_width) *100);
663 1306
664 1307 if(both_width > 100){
665 1308 return false;
666 1309 }
@@ -665,11 +1308,15 @@
665 1308 return false;
666 1309 }
667 1310
668 1311 jQuery('body').css({'cursor': 'ew-resize'});
669 - rHandler.show();
1312 + rHandler.css({'display': 'block'});
670 1313
1314 + var mousemoved = false;
1315 +
671 1316 var r_mousemove = function(e){
1317 + mousemoved = true;
1318 +
672 1319 var width = original_width + (e.pageX - original_mouse_x);
673 1320
674 1321 // Covert width in percentage
675 1322 new_width = (width / rHolder_width *100).toFixed(2);
@@ -686,19 +1333,31 @@
686 1333
687 1334 var r_mouseup = function(e){
688 1335
689 1336 jQuery(document).off('mousemove', r_mousemove);
1337 + jQuery(document).off('mouseup', r_mouseup);
690 1338 jQuery('body').css({'cursor': ''});
691 1339 rHandler.removeAttr('style pre-width next-width');
692 1340
1341 + // IF mouseMoved
1342 + if(!mousemoved) return;
1343 +
693 1344 // find real element and next real element
694 1345 var jEle = wrap.find('>.pagelayer-ele');
695 1346 var nEle = next_ele.find('>.pagelayer-ele');
696 -
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 +
697 1355 // Set the element attrs
698 - jEle.attr({'pagelayer-a-col_width': new_width, 'pagelayer-a-col': ''});
699 - nEle.attr({'pagelayer-a-col_width': nEle_new_width, 'pagelayer-a-col': ''});
700 - jQuery(document).off('mouseup', r_mouseup);
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', '');
701 1360
702 1361 };
703 1362
704 1363 // Resize start
@@ -731,14 +1390,25 @@
731 1390 function pagelayer_element_added(jEle){
732 1391
733 1392 var sc = jEle.attr('pagelayer-tag');
734 1393 var id, par_id;
1394 + var gId = jEle.attr('pagelayer-global-id');
1395 + gId = gId && !pagelayer_empty(pagelayer_global_widgets[gId]) ? gId : 0;
735 1396
736 1397 // Set Pagelayer History FALSE to prevent saving attributes in action history
737 1398 pagelayer.history_action = false;
738 -
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 +
739 1406 // Generate the HTML
740 - html = pagelayer_create_sc(sc);
1407 + }else{
1408 + html = pagelayer_create_sc(sc);
1409 + }
1410 +
741 1411 id = pagelayer_assign_id(html);
742 1412 par_id = id;
743 1413
744 1414 // Insert the HTML
@@ -746,8 +1416,13 @@
746 1416
747 1417 // Setup the properties of the elements
748 1418 pagelayer_element_setup("[pagelayer-id="+par_id+"], [pagelayer-id="+par_id+"] .pagelayer-ele", true);
749 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 +
750 1425 // Any children to add ?
751 1426 if(!('widget' in pagelayer_shortcodes[sc])){
752 1427
753 1428 // The element props
@@ -754,17 +1429,29 @@
754 1429 var props = pagelayer_shortcodes[sc];
755 1430
756 1431 // Do we have to create children ?
757 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);
758 1442
759 - var has_group = props['has_group'];
760 - var gProp = props[has_group['section']][has_group['prop']];
761 -
762 - for(var i=0; i < gProp['count']; i++){
763 - var cid = pagelayer_element_add_child(jQuery("[pagelayer-id="+id+"]"), gProp['sc']);
764 - //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+'"]'));
765 1453 }
766 -
767 1454 }
768 1455
769 1456 }
770 1457
@@ -774,21 +1461,27 @@
774 1461 pagelayer_history_action_push({
775 1462 'title' : pagelayer_shortcodes[sc]['name'],
776 1463 'action' : 'Added',
777 1464 'pl_id' : id,
778 - 'html' : jQuery("[pagelayer-id="+id+"]"),
1465 + 'html' : jQuery("[pagelayer-id="+id+"]")[0].outerHTML,
779 1466 'cEle' : cEle
780 - });
1467 + });
781 1468
782 1469 // Set pagelayer history TRUE
783 1470 pagelayer.history_action = true;
1471 + pagelayer.global_render = true;
784 1472
1473 + // To update nav item list
1474 + pagelayer_do_dirty(pagelayer_ele_by_id(id));
1475 +
785 1476 return id;
786 1477
787 1478 };
788 1479
789 1480 // Add an element
790 -function pagelayer_element_add_child(pEle, sc){
1481 +function pagelayer_element_add_child(pEle, sc, gProp){
1482 +
1483 + gProp = gProp || {};
791 1484 var child = pagelayer_create_sc(sc);
792 1485 var cid = pagelayer_assign_id(child);
793 1486 pagelayer_set_parent(child, pagelayer_assign_id(pEle));
794 1487
@@ -806,8 +1499,73 @@
806 1499 }
807 1500
808 1501 pagelayer_element_setup('[pagelayer-id='+cid+']', true);
809 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 +
810 1568 // Do we have to create children ?
811 1569 if('has_group' in pagelayer_shortcodes[sc]){
812 1570
813 1571 var has_group = pagelayer_shortcodes[sc]['has_group'];
@@ -813,9 +1571,9 @@
813 1571 var has_group = pagelayer_shortcodes[sc]['has_group'];
814 1572 var gProp = pagelayer_shortcodes[sc][has_group['section']][has_group['prop']];
815 1573
816 1574 for(var i=0; i < gProp['count']; i++){
817 - 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);
818 1576 }
819 1577
820 1578 }
821 1579
@@ -845,8 +1603,14 @@
845 1603 return id;
846 1604
847 1605 }
848 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 +
849 1613 // Assign the jQuery object an ID
850 1614 function pagelayer_assign_id(jEle){
851 1615
852 1616 // Do you have the pagelayer id
@@ -851,9 +1615,10 @@
851 1615
852 1616 // Do you have the pagelayer id
853 1617 var id = jEle.attr("pagelayer-id");
854 1618 if(!id || id.length < 1){
855 - id = pagelayer_randstr(16);
1619 + id = pagelayer_randstr(3)+pagelayer_randInt(9999).toString();
1620 + id = id.toLowerCase();
856 1621 jEle.attr("pagelayer-id", id);
857 1622 }
858 1623
859 1624 return id;
@@ -884,8 +1649,13 @@
884 1649 //pagelayer_clear_editable();// First clear
885 1650 jEle.find('[pagelayer-editable]').each(function (){
886 1651 pagelayer_make_editable(jQuery(this), e);
887 1652 });
1653 +
1654 + // Show left bar
1655 + if(pagelayer_empty(e)){
1656 + pagelayer.$$('.pagelayer-leftbar-table').removeClass('pagelayer-leftbar-hidden pagelayer-leftbar-minimize');
1657 + }
888 1658
889 1659 // Lets not rebuild everything to make it faster
890 1660 if(pagelayer_is_active(jEle)){
891 1661 return false;
@@ -890,8 +1660,10 @@
890 1660 if(pagelayer_is_active(jEle)){
891 1661 return false;
892 1662 }
893 1663
1664 + pagelayer_trigger_action('pagelayer_element_clicked', [jEle]);
1665 +
894 1666 // Set this as the active element
895 1667 pagelayer_set_active(jEle);
896 1668
897 1669 // Show the properties
@@ -898,13 +1670,69 @@
898 1670 pagelayer_elpd_open(jEle);
899 1671
900 1672 }
901 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 +
902 1720 // The edit option
903 1721 function pagelayer_edit_element(selector){
904 1722 pagelayer_element_clicked(selector);
905 1723 }
906 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 +
907 1735 // Setup the properties on a single click
908 1736 function pagelayer_element_setup(selector, render){
909 1737
910 1738 var selector = selector || ".pagelayer-ele";
@@ -911,9 +1739,9 @@
911 1739 render = render || false;
912 1740
913 1741 // Loop through
914 1742 jQuery(pagelayer_editable+' '+selector).each(function(){
915 -
1743 +
916 1744 var jEle = jQuery(this);
917 1745
918 1746 // Assign an ID if not there
919 1747 var id = pagelayer_assign_id(jEle);
@@ -919,8 +1747,13 @@
919 1747 var id = pagelayer_assign_id(jEle);
920 1748 var pId = pagelayer_get_parent(jEle) || '';// Options to show on hover
921 1749 var selector = '[pagelayer-id='+id+']';
922 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 +
923 1756 if(render){
924 1757 pagelayer_sc_render(jEle);
925 1758 }
926 1759
@@ -925,8 +1758,9 @@
925 1758 }
926 1759
927 1760 // Get the tag
928 1761 var tag = pagelayer_tag(jEle);
1762 + var props = pagelayer_get_props(jEle);
929 1763
930 1764 // Lets check if we are the child of a parent i.e. element of a group
931 1765 if(pagelayer_empty(pId)){
932 1766
@@ -953,9 +1787,14 @@
953 1787
954 1788 }
955 1789
956 1790 }
957 -
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 +
958 1797 // Make the wraps
959 1798 jEle.wrap('<div class="pagelayer-ele-wrap" pagelayer-wrap-id="'+id+'"></div>');
960 1799 var wrap = jEle.parent();
961 1800
@@ -968,15 +1807,10 @@
968 1807 col = 'pagelayer-col-'+x;
969 1808 break;
970 1809 }
971 1810 }
1811 +
972 1812
973 - var is_custom_width = pagelayer_get_att(jEle, 'col');
974 - var col_width = pagelayer_get_att(jEle, 'col_width');
975 - if(pagelayer_empty(is_custom_width) && col_width){
976 - wrap.css('width', col_width+'%');
977 - }
978 -
979 1813 wrap.addClass('pagelayer-col '+col);
980 1814 //jEle.removeClass('pagelayer-col '+col);
981 1815 wrap.addClass('pagelayer-wrap-col');
982 1816
@@ -1002,11 +1836,13 @@
1002 1836 pagelayer_sc_render(jEle);
1003 1837 }
1004 1838
1005 1839 html = '<div class="pagelayer-row-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
1006 - '<i class="fa fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" />'+
1007 - '<i class="fa fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" />'+
1008 - '<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>'+
1009 1845 '</div>';
1010 1846
1011 1847 }else if(tag == 'pl_col'){
1012 1848
@@ -1012,9 +1848,9 @@
1012 1848
1013 1849 overlay.addClass('pagelayer-col-hover');
1014 1850
1015 1851 html = '<div class="pagelayer-col-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
1016 - '<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>'+
1017 1853 '</div>';
1018 1854
1019 1855 // Is it an empty col ?
1020 1856 pagelayer_empty_col(jEle.children('.pagelayer-col-holder'));
@@ -1024,11 +1860,13 @@
1024 1860
1025 1861 }else{
1026 1862
1027 1863 html = '<div class="pagelayer-ele-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
1028 - '<i class="fa fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" />'+
1029 - '<i class="fa fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" />'+
1030 - '<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>'+
1031 1869 '</div>';
1032 1870
1033 1871 }
1034 1872
@@ -1033,10 +1871,23 @@
1033 1871 }
1034 1872
1035 1873 // Append to the child
1036 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 +
1037 1881 jQuery('[pagelayer-option-id='+id+']').hide();
1038 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 +
1039 1890 // Setup the HOVER events ABD create WRAPS IF we dont have a parent
1040 1891 if(pId.length > 0){
1041 1892 return;
1042 1893 }
@@ -1070,8 +1921,44 @@
1070 1921
1071 1922 });
1072 1923 }
1073 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 +
1074 1961 // Left Click
1075 1962 function pagelayer_left_click(){
1076 1963
1077 1964 jQuery(pagelayer_editable).on('click', function(e){
@@ -1101,12 +1988,15 @@
1101 1988
1102 1989 var html = '<div class="pagelayer-right-click-options" style="display:none;">'+
1103 1990 '<ul>'+
1104 1991 '<li><a class="pagelayer-right-edit">Edit</a></li>'+
1105 - '<li><a class="pagelayer-right-duplicate"><i class="fa fa-clone" /> Duplicate</a></li>'+
1106 - '<li><a class="pagelayer-right-copy"><i class="fa fa-files-o" /> Copy</a></li>'+
1107 - '<li><a class="pagelayer-right-paste"><i class="fa fa-clipboard" /> Paste</a></li>'+
1108 - '<li><a class="pagelayer-right-delete"><i class="fa fa-trash-o" /> Delete</a></li>'+
1992 + '<li><a class="pagelayer-right-duplicate"><i class="far fa-clone" ></i> '+pagelayer_l('Duplicate')+'</a></li>'+
1993 + '<li><a class="pagelayer-right-copy"><i class="far fa-copy" ></i> '+pagelayer_l('Copy')+' <span style="margin-left:10px;opacity:0.6">Ctrl+c</span></a></li>'+
1994 + '<li><a class="pagelayer-right-paste pagelayer-context-disable" title="If the paste is not done correctly then use Ctrl+V"><i class="far fa-clipboard" ></i> '+pagelayer_l('Paste')+' <span style="margin-left:10px;opacity:0.6">Ctrl+v</span></a></li>'+
1995 + '<li><a class="pagelayer-right-delete"><i class="far fa-trash-alt" ></i> '+pagelayer_l('Delete')+'</a></li>'+
1996 + '<li><a class="pagelayer-right-save-global-widget" pro="1"><i class="far fa-save" ></i> '+pagelayer_l('save_global')+'</a></li>'+
1997 + '<li><a class="pagelayer-right-save-section" pro="1"><i class="far fa-heart" ></i> '+pagelayer_l('save_as_section')+'</a></li>'+
1998 + '<li><a class="pagelayer-right-save-global-section" pro="1"><i class="fas fa-globe" ></i> '+pagelayer_l('save_as_global_section')+'</a></li>'+
1109 1999 '</ul>'+
1110 2000 '</div>';
1111 2001
1112 2002 jQuery('body').append(html);
@@ -1117,8 +2007,13 @@
1117 2007
1118 2008 var tEle = jQuery(e.target);
1119 2009 var jEle = tEle.closest('.pagelayer-ele-wrap').children('.pagelayer-ele');
1120 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 +
1121 2016 // Get the parent
1122 2017 var pId = pagelayer_get_parent(jEle);
1123 2018
1124 2019 // If we found a parent
@@ -1129,26 +2024,89 @@
1129 2024 // The basics
1130 2025 var id = pagelayer_assign_id(jEle);
1131 2026 var tag = pagelayer_tag(jEle);
1132 2027
1133 - $contextMenu.find('.pagelayer-right-edit').attr('onclick', 'pagelayer_edit_element("[pagelayer-id='+id+']")').html('<i class="fa fa-pencil-square-o" /> Edit '+pagelayer_shortcodes[tag]['name']);
2028 + $contextMenu.find('.pagelayer-right-edit').attr('onclick', 'pagelayer_edit_element("[pagelayer-id='+id+']")').html('<i class="far fa-edit" ></i> Edit '+pagelayer_shortcodes[tag]['name']);
1134 2029 $contextMenu.find('.pagelayer-right-duplicate').attr('onclick', 'pagelayer_copy_element("[pagelayer-id='+id+']")');
1135 2030 $contextMenu.find('.pagelayer-right-copy').attr('onclick', 'pagelayer_copy_select("[pagelayer-id='+id+']")');
1136 - $contextMenu.find('.pagelayer-right-paste').attr('onclick', 'pagelayer_paste_element("[pagelayer-id='+id+']")');
1137 2031 $contextMenu.find('.pagelayer-right-delete').attr('onclick', 'pagelayer_delete_element("[pagelayer-id='+id+']")');
1138 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 +
1139 2060 // Are we to hide the paste ?
1140 - if(!pagelayer_empty(pagelayer.copy_selected) && pagelayer_can_copy_to(jEle)){
1141 - //console.log(pagelayer_can_copy_to(jEle));
1142 - $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);
1143 2073 }else{
1144 - $contextMenu.find('.pagelayer-right-paste').parent().hide();
2074 + showPaste();
1145 2075 }
1146 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 +
1147 2105 $contextMenu.css({
1148 2106 display: "block",
1149 - left: e.pageX,
1150 - top: e.pageY
2107 + left: hPosition,
2108 + top: vPosition
1151 2109 });
1152 2110
1153 2111 return false;
1154 2112
@@ -1163,9 +2121,14 @@
1163 2121 function pagelayer_set_parent(jEle, id){
1164 2122 jEle.attr('pagelayer-parent', id);
1165 2123 };
1166 2124
1167 -// 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
1168 2131 function pagelayer_get_parent(jEle){
1169 2132 return jEle.attr('pagelayer-parent');
1170 2133 };
1171 2134
@@ -1186,12 +2149,12 @@
1186 2149 // Add the class
1187 2150 body.addClass('pagelayer-screen-'+mode);
1188 2151
1189 2152 // Add the class to the button
1190 - pagelayer.$$('.pagelayer-mode-button').removeClass('fa-'+current).addClass('fa-'+mode);
2153 + pagelayer.$$('.pagelayer-mode-button').removeClass('pli-'+current).addClass('pli-'+mode);
1191 2154
1192 2155 // Add the class to the button
1193 - pagelayer.$$('.pagelayer-prop-screen').removeClass('fa-'+current).addClass('fa-'+mode);
2156 + pagelayer.$$('.pagelayer-prop-screen').removeClass('pli-'+current).addClass('pli-'+mode);
1194 2157
1195 2158 // Trigger screen change if any
1196 2159 pagelayer.$$('.pagelayer-elp-screen').trigger('pagelayer-screen-changed');
1197 2160
@@ -1208,12 +2171,512 @@
1208 2171 }
1209 2172 }
1210 2173 }
1211 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 +
1212 2324 // Handle key press events
1213 -jQuery(document).keydown(function(event){
2325 +pagelayer.gDocument.keydown(function(event){
1214 2326 //alert(String.fromCharCode(event.which));
1215 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 +
1216 2679 // Delete
1217 2680 if(event.keyCode == 46){
1218 2681 pagelayer_delete_element('[pagelayer-active]');
1219 2682 }
@@ -1226,40 +2689,67 @@
1226 2689 // ctrl+y handle
1227 2690 if(event.keyCode == 89 && event.ctrlKey){
1228 2691 pagelayer_do_history('redo');
1229 2692 }
2693 +
1230 2694 });
1231 2695
1232 2696 // Handle Copy of content
1233 2697 jQuery(document).on('copy', function(copyEvent){
2698 +
2699 + // Is Selected string?
2700 + var selectedText = "";
2701 + if (window.getSelection){ // all modern browsers and IE9+
2702 + selectedText = window.getSelection().toString();
2703 + }
1234 2704
1235 - // Check the active element
2705 + if(selectedText.length > 0){
2706 + return;
2707 + }
2708 +
1236 2709 if(pagelayer_active.el && pagelayer_active.el.id){
1237 -
1238 2710 copyEvent.preventDefault();
1239 2711
1240 - var eHtml = jQuery("[pagelayer-id='"+pagelayer_active.el.id+"']")[0].outerHTML;
1241 -
1242 - // We need to do Empty clipboard
1243 - (copyEvent.originalEvent || copyEvent).clipboardData.setData('pagelayer_ele', eHtml);
1244 -
1245 2712 // Save the active element id
1246 - //pagelayer_copy_select("[pagelayer-id='"+pagelayer_active.el.id+"']");
2713 + pagelayer_copy_select("[pagelayer-id='"+pagelayer_active.el.id+"']", copyEvent);
1247 2714
1248 2715 }
1249 2716
1250 2717 });
1251 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 +
1252 2733 // Handle Paste in the editor
1253 2734 jQuery(document).on('paste', function(pasteEvent){
1254 -
2735 +
1255 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 +
1256 2741 var pagelayer_ajax_func = {};
1257 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 + }
1258 2749
1259 - if(pEle_target.closest('[contenteditable]').length > 0){
1260 - pEle_target = pEle_target.closest('[contenteditable]');
1261 - contenteditable = true;
2750 + if( items.length < 1 || (items.length == 1 && pagelayer_empty(clipboardData.getData(items[0].type))) ){
2751 + pasteWidget = true;
1262 2752 }
1263 2753
1264 2754 // This function for ajax before send call back
1265 2755 pagelayer_ajax_func['beforeSend'] = function(xhr){
@@ -1268,8 +2758,9 @@
1268 2758 if( pagelayer_empty(contenteditable) ){
1269 2759
1270 2760 // If we dont have an active element then return false and stop ajax
1271 2761 if( !(pagelayer_active.el && pagelayer_active.el.id) ){
2762 + pagelayer_show_msg(pagelayer_l('active_ele_paste_msg'));
1272 2763 return false;
1273 2764 }
1274 2765
1275 2766 pagelayer.copy_selected = jQuery('<div pagelayer-tag="pl_image"></div>');
@@ -1295,25 +2786,77 @@
1295 2786 document.execCommand('insertImage', false, obj['data']['url']);
1296 2787
1297 2788 // For our widgets
1298 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 +
1299 2796 var fTo = pagelayer_can_copy_to('[pagelayer-id="'+pagelayer_active.el.id+'"]');
1300 2797 // We need to empty pagelayer.copy_selected
1301 2798 pagelayer.copy_selected = '';
1302 -
1303 - // Create image html
1304 - var html = jQuery( pagelayer_create_sc('pl_image') );
1305 - html.attr('pagelayer-a-id', obj['data']['id']);
1306 - html.attr('pagelayer-tmp-id-url', obj['data']['url']);
1307 2799
1308 - // Copy the element
1309 - var id = pagelayer_copy_element(html, fTo);
1310 - jQuery('[pagelayer-id="'+id+'"]').click();
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 + }
1311 2854 }
1312 2855
1313 2856 // Some error occured
1314 2857 }else{
1315 - alert(obj['data']['message']);
2858 + pagelayer_show_msg(obj['data']['message'], 'error', 10000);
1316 2859 }
1317 2860 }
1318 2861
1319 2862 // This function for ajax complete call back
@@ -1323,23 +2866,36 @@
1323 2866 }
1324 2867
1325 2868 var findImg = pagelayer_editable_paste_handler(pasteEvent, pagelayer_ajax_func);
1326 2869
1327 - if(pagelayer_empty(findImg)){
2870 + if(pagelayer_empty(findImg) || pasteWidget){
1328 2871
1329 2872 // Check the active element
1330 - if(pagelayer_active.el && pagelayer_active.el.id){
2873 + if(pagelayer_active.el && pagelayer_active.el.id && pagelayer_active.el.tag != 'pl_post_props'){
1331 2874
1332 - var jEle = jQuery("[pagelayer-id='"+pagelayer_active.el.id+"']");
2875 + const text = clipboardData.getData('text');
2876 + var pEle = jQuery(text);
2877 + var getData = true;
1333 2878
1334 - var copy_ele = jQuery((pasteEvent.originalEvent || pasteEvent).clipboardData.getData('pagelayer_ele'));
1335 -
1336 - // Check if the any element is copied
1337 - if(copy_ele.length > 0 && pagelayer_can_copy_to(jEle)){
1338 - pagelayer.copy_selected = copy_ele;
1339 - 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 +
1340 2894 }
1341 2895
2896 + }else{
2897 + pagelayer_show_msg(pagelayer_l('no_active_ele_paste'));
1342 2898 }
1343 2899 }
1344 2900 });
1345 2901
@@ -1345,8 +2901,9 @@
1345 2901
1346 2902 // Delete an element as per the selector
1347 2903 function pagelayer_delete_element(selector){
1348 2904 var jEle = jQuery(selector);
2905 + var nearBy = jEle;
1349 2906
1350 2907 // Anything found ?
1351 2908 if(jEle.length > 0){
1352 2909
@@ -1361,8 +2918,10 @@
1361 2918 // Save this element in history action
1362 2919 if(pagelayer.history_action){
1363 2920 var cEle = pagelayer_near_by_ele(id, sc);
1364 2921
2922 + nearBy = jQuery(cEle.cEle);
2923 +
1365 2924 // To save in history, we need to save only element not the wraps as we call setup if we redo or undo
1366 2925 jEle.find('style').remove();
1367 2926 jEle.find('.pagelayer-ele-overlay').remove();
1368 2927
@@ -1377,9 +2936,9 @@
1377 2936 pagelayer_history_action_push({
1378 2937 'title' : pagelayer_shortcodes[sc]['name'],
1379 2938 'action' : 'Deleted',
1380 2939 'pl_id' : id,
1381 - 'html' : jEle,
2940 + 'html' : jEle[0].outerHTML,
1382 2941 'cEle' : cEle
1383 2942 });
1384 2943 }
1385 2944
@@ -1386,22 +2945,93 @@
1386 2945 wrap.remove();
1387 2946
1388 2947 pagelayer_empty_col(par);
1389 2948
1390 - 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)){
1391 2951 pagelayer.$$('.pagelayer-elpd-close').click();
1392 2952 }
1393 2953
1394 2954 }
1395 2955
1396 - pagelayer_isDirty = true;
2956 + // Do Pagelayer dirty
2957 + pagelayer_do_dirty(nearBy);
1397 2958 };
1398 2959
1399 2960 // Select an element
1400 -function pagelayer_copy_select(selector){
1401 - 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 +
1402 2999 }
1403 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 +
1404 3034 function pagelayer_can_copy_to(to){
1405 3035 var jEle = jQuery(pagelayer.copy_selected);
1406 3036 var tEle = jQuery(to);
1407 3037
@@ -1407,8 +3037,14 @@
1407 3037
1408 3038 var eTag = pagelayer_tag(jEle);
1409 3039 var tTag = pagelayer_tag(tEle);
1410 3040 //console.log(eTag+' - '+tTag);
3041 +
3042 + // Invalid HTML copied
3043 + if(pagelayer_empty(eTag)){
3044 + return false;
3045 + }
3046 +
1411 3047 // Final to
1412 3048 var fTo;
1413 3049
1414 3050 // Selected element is a Row, can go only after a row
@@ -1434,10 +3070,26 @@
1434 3070
1435 3071 }
1436 3072
1437 3073 // Select an element
1438 -function pagelayer_paste_element(to){
3074 +function pagelayer_paste_element(to, syncClipboard = true){
1439 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 +
1440 3092 var fTo = pagelayer_can_copy_to(to);
1441 3093
1442 3094 // Is it a valid to
1443 3095 if(!fTo){
@@ -1443,35 +3095,63 @@
1443 3095 if(!fTo){
1444 3096 return false;
1445 3097 }
1446 3098
1447 - 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;
1448 3107 }
1449 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 +
1450 3144 // Copy an element
1451 3145 // Note : insertAfter should always be an pagelayer-ele
1452 3146 function pagelayer_copy_element(selector, insertAfter){
1453 3147 var src = jQuery(selector);
1454 - var html = src[0].outerHTML;
1455 3148 var tag = pagelayer_tag(src);
1456 3149 insertAfter = insertAfter || src;
1457 3150 insertAfter = insertAfter.parent();
1458 3151
1459 - var jEle = jQuery(html);
1460 - jEle.removeAttr('pagelayer-id');
1461 - jEle.find('[pagelayer-id]').removeAttr('pagelayer-id');
1462 - jEle.find('[pagelayer-parent]').removeAttr('pagelayer-parent');// Remove the parent attribute as it will be reset during pagelayer_element_setup
1463 - jEle.find('style').remove();
1464 - jEle.find('.pagelayer-ele-overlay').remove();
3152 + var jEle = pagelayer_element_unsetup(src);
1465 3153
1466 - // Unwrap the wraps
1467 - jEle.find('.pagelayer-ele').each(function (){
1468 - var ele = jQuery(this);
1469 - if(ele.parent().is('.pagelayer-ele-wrap')){
1470 - ele.unwrap();
1471 - }
1472 - });
1473 -
1474 3154 // Give it an ID
1475 3155 var id = pagelayer_assign_id(jEle);
1476 3156
1477 3157 jQuery(insertAfter).after(jEle);
@@ -1477,8 +3157,12 @@
1477 3157 jQuery(insertAfter).after(jEle);
1478 3158
1479 3159 pagelayer_element_setup('[pagelayer-id='+id+'], [pagelayer-id='+id+'] .pagelayer-ele', true);
1480 3160
3161 + if(pagelayer_is_group(tag)){
3162 + pagelayer_sc_render(jEle);
3163 + }
3164 +
1481 3165 // Save this element in history action
1482 3166 if(pagelayer.history_action){
1483 3167 var cEle = pagelayer_near_by_ele(id, tag);
1484 3168 pagelayer_history_action_push({
@@ -1484,9 +3168,9 @@
1484 3168 pagelayer_history_action_push({
1485 3169 'title' : pagelayer_shortcodes[tag]['name'],
1486 3170 'action' : 'Copied',
1487 3171 'pl_id' : id,
1488 - 'html' : jEle,
3172 + 'html' : jEle[0].outerHTML,
1489 3173 'cEle' : cEle
1490 3174 });
1491 3175 }
1492 3176
@@ -1495,18 +3179,366 @@
1495 3179 var row = src.parent().closest('.pagelayer-row');
1496 3180 pagelayer_renumber_col(row);
1497 3181 }
1498 3182
1499 - pagelayer_isDirty = true;
3183 + pagelayer_do_dirty(jEle);
1500 3184
1501 3185 return id;
1502 3186 };
1503 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 +
1504 3484 // Language key
1505 3485 function pagelayer_l(k){
3486 + if(k in pagelayer_lang){
3487 + return pagelayer_lang[k];
3488 + }
1506 3489 return k;
1507 3490 }
1508 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 +
1509 3541 // Set the given jELE as active
1510 3542 function pagelayer_set_active(jEle){
1511 3543
1512 3544 // Make all other element as inactive
@@ -1533,13 +3565,13 @@
1533 3565 function pagelayer_create_sc(sc){
1534 3566
1535 3567 var html;
1536 3568 var _sc = pagelayer_sc(sc);
1537 - var func = window['pagelayer_sc_'+sc];
3569 + var func = window['pagelayer_create_sc_'+sc];
1538 3570
1539 3571 // Generate the HTML
1540 3572 if(typeof func == 'function'){
1541 - html = window['pagelayer_sc_'+sc]();
3573 + html = window['pagelayer_create_sc_'+sc]();
1542 3574 }else{
1543 3575 html = '<div '+pagelayer_sc_atts('pagelayer-'+_sc)+'></div>';
1544 3576 }
1545 3577
@@ -1604,16 +3636,88 @@
1604 3636
1605 3637 return jEle.attr('pagelayer-tag');
1606 3638 }
1607 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 +
1608 3704 // Gets a single attribute value
1609 3705 function pagelayer_get_att(jEle, att){
1610 - 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;
1611 3711 };
1612 3712
1613 3713 // Gets a single attribute value
1614 3714 function pagelayer_get_tmp_att(jEle, att){
1615 - 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;
1616 3720 };
1617 3721
1618 3722 // This function will just set atts and not do anything else
1619 3723 // Atts can be string or object. If its string, then val is needed
@@ -1642,8 +3746,9 @@
1642 3746 var all_props = pagelayer_shortcodes[tag];//console.log(tag);console.log(jEle);
1643 3747 var trigger_props = {};
1644 3748 var no_val = {};
1645 3749 var defaults = {};
3750 + var _props = {};
1646 3751
1647 3752 // Loop through all props
1648 3753 for(var i in pagelayer_tabs){
1649 3754
@@ -1658,15 +3763,39 @@
1658 3763 if('default' in props[x]){
1659 3764 defaults[x] = 1;
1660 3765 }
1661 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 +
1662 3776 // Dont set any val, but we set temp value
1663 3777 if('no_val' in props[x]){
1664 3778 no_val[x] = 1;
1665 3779 }
1666 3780
1667 - if('req' in props[x] || 'show' in props[x]){
3781 + if('req' in props[x] || 'show' in props[x]){
1668 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 +
1669 3798 for(var showParam in show){
1670 3799 var val = show[showParam];
1671 3800 var except = showParam.substr(0, 1) == '!' ? true : false;
1672 3801 showParam = except ? showParam.substr(1) : showParam;
@@ -1680,8 +3809,10 @@
1680 3809 }
1681 3810
1682 3811 }
1683 3812
3813 + var ref_data = pagelayer_el_data_ref(jEle);
3814 +
1684 3815 for(var x in atts){
1685 3816
1686 3817 // Are we to trigger change
1687 3818 if(x in trigger_props){
@@ -1689,8 +3820,13 @@
1689 3820 }
1690 3821
1691 3822 //console.log(x+'-'+atts[x]);
1692 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 +
1693 3829 if(x in no_val){
1694 3830 pagelayer_set_tmp_atts(jEle, x, atts[x]);
1695 3831 continue;
1696 3832 }
@@ -1695,23 +3831,19 @@
1695 3831 continue;
1696 3832 }
1697 3833
1698 3834 // Record History
1699 - if(pagelayer.history_action){
1700 - var attr_label = '';
1701 - for(var section in all_props){
1702 - for(var props in all_props[section]){
1703 - if(props == x){
1704 - attr_label = all_props[section][props]['label'];
1705 - }
1706 - }
1707 -
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'];
1708 3841 }
1709 -
1710 - var old_val = pagelayer_get_att(jEle, x) || '';
3842 +
1711 3843 pagelayer_history_action_push({
1712 3844 'title' : all_props['name'],
1713 - 'subTitle' : attr_label,
3845 + 'subTitle' : label,
1714 3846 'action' : 'Edited',
1715 3847 'attrType' : 'a_attr',
1716 3848 'pl_id' : pagelayer_id(jEle),
1717 3849 'atts' : x,
@@ -1718,40 +3850,27 @@
1718 3850 'oldVal' : old_val,
1719 3851 'newVal' : atts[x]
1720 3852 });
1721 3853 }
1722 -
3854 +
1723 3855 // Remove the attribute if its BLANK and there is no default for it
1724 3856 // If there is a default, we set it to blank to keep record of the current val
1725 - if(atts[x].length < 1){
3857 + if(pagelayer_length(atts[x]) < 1){
1726 3858
1727 - // Dont remove the value as there is a default
3859 + // Remove values which are not defaults
1728 3860 if(!(x in defaults)){
1729 - jEle.removeAttr('pagelayer-a-'+x);
1730 - // Otherwise blank it
3861 + delete ref_data['attr'][x];
3862 + // Otherwise keep value set for avoiding resetting
1731 3863 }else{
1732 - jEle.attr('pagelayer-a-'+x, atts[x]);
3864 + ref_data['attr'][x] = atts[x];
1733 3865 }
1734 3866
1735 3867 // Remove the tmp atts anyway
1736 - var to_del = new Array();
1737 - var regexp = new RegExp('pagelayer\-tmp\-'+x, 'gi');
1738 -
1739 - jQuery.each(jEle[0].attributes, function(index, att){
1740 - if(!att) return;
1741 - if(att.name.match(regexp)){
1742 - to_del.push(att.name);
1743 - }
1744 - });
1745 -
1746 - //console.log(to_del);
1747 - for(var n in to_del){
1748 - jEle.removeAttr(to_del[n]);
1749 - }
3868 + pagelayer_clear_tmp_atts(jEle, x);
1750 3869
1751 3870 // Set the value
1752 3871 }else{
1753 - jEle.attr('pagelayer-a-'+x, atts[x]);
3872 + ref_data['attr'][x] = pagelayer_trim(atts[x]);
1754 3873 }
1755 3874
1756 3875 // Are you the active element
1757 3876 if(pagelayer_is_active(jEle)){
@@ -1761,14 +3880,17 @@
1761 3880 }
1762 3881
1763 3882 }
1764 3883
3884 + pagelayer_el_dump_data(jEle);
3885 +
1765 3886 // Trigger the change of the parameter and show the required properties
1766 3887 if(trigger_onchange){
1767 3888 pagelayer_elpd_show_rows();
1768 3889 }
1769 3890
1770 - pagelayer_isDirty = true;
3891 + pagelayer_do_dirty(jEle);
3892 +
1771 3893 };
1772 3894
1773 3895 // This function will just set atts and not do anything else
1774 3896 // Atts can be string or object. If its string, then val is needed
@@ -1783,10 +3905,12 @@
1783 3905 if(typeof atts != 'object'){
1784 3906 return false;
1785 3907 }
1786 3908
3909 + var ref_data = pagelayer_el_data_ref(jEle);
3910 +
1787 3911 for(var x in atts){
1788 -
3912 +
1789 3913 // Record history
1790 3914 if(pagelayer.history_action){
1791 3915
1792 3916 var old_val = pagelayer_get_tmp_att(jEle, x) || '';
@@ -1801,27 +3925,51 @@
1801 3925 'newVal' : atts[x]
1802 3926 });
1803 3927
1804 3928 }
1805 -
1806 - jEle.attr('pagelayer-tmp-'+x, atts[x]);
3929 +
3930 + ref_data['tmp'][x] = atts[x];
3931 +
1807 3932 }
1808 3933
3934 + pagelayer_el_dump_data(jEle);
3935 +
1809 3936 };
1810 3937
1811 -// Set the att and classes of an HTML which is not yet created
1812 -function pagelayer_sc_atts(classes, atts){
3938 +// This function removes the temporary attributes of an ele
3939 +function pagelayer_clear_tmp_atts(jEle, attr){
1813 3940
1814 - if(typeof atts != 'object'){
1815 - 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 + }
1816 3950 }
3951 +}
3952 +
3953 +// This function removes the temporary attributes of an ele
3954 +function pagelayer_img_tmp_atts(jEle, attr){
1817 3955
1818 - var r = new Array();
3956 + var found = {};
3957 + var regexp = new RegExp('^'+attr+'\-', 'gi');
3958 + var ref_data = pagelayer_el_data_ref(jEle);
1819 3959
1820 - for(var x in atts){
1821 - 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 + }
1822 3964 }
1823 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();
1824 3972 return 'class="'+classes+' pagelayer-ele" '+r.join(' ');
1825 3973 }
1826 3974
1827 3975 // Is the jEle the active element ?
@@ -1847,16 +3995,33 @@
1847 3995
1848 3996 // Seperator
1849 3997 seperator = seperator || ',';
1850 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 +
1851 4012 // Replace the val
1852 - css = css.split('{{val}}').join(val);
4013 + css = replaceCss(css, val, '{{val}}');
1853 4014
1854 4015 // If there is an array
1855 4016 if(css.match(/val\[\d/)){
1856 - val = val.split(seperator);
4017 +
4018 + if(typeof val != 'object' || val === null){
4019 + val = String(val).split(seperator);
4020 + }
4021 +
1857 4022 for(var i in val){
1858 - css = css.split('{{val['+i+']}}').join(val[i]);
4023 + css = replaceCss(css, val[i], '{{val['+i+']}}');
1859 4024 }
1860 4025 }
1861 4026
1862 4027 //console.log('Final CSS '+css);
@@ -1864,9 +4029,40 @@
1864 4029 return css;
1865 4030
1866 4031 };
1867 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 +
1868 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
1869 4065 function pagelayer_parse_vars(str, el){
1870 4066
1871 4067 for(var x in el.tmp){
1872 4068 str = str.split('{{{'+x+'}}}').join(el.tmp[x]);
@@ -1886,11 +4082,11 @@
1886 4082 if(!pagelayer_is_active(jEle)){
1887 4083 //return false;
1888 4084 }
1889 4085
1890 - //console.log('Rendering');
4086 + //console.log('Rendering');
1891 4087
1892 - // Handle the CSS part
4088 + // Handle the CSS part
1893 4089 // Get the id, tag, atts, data, etc
1894 4090 var el = pagelayer_data(jEle, true);
1895 4091 var all_props = pagelayer_shortcodes[el.tag];
1896 4092 var elCSS = {
@@ -1899,13 +4095,18 @@
1899 4095 attr: [],
1900 4096 remove_attr: [],
1901 4097 css: [],
1902 4098 edit: [],
1903 - sel: '[pagelayer-id="'+el.id+'"]'
4099 + cssSel: '.p-'+el.id,
4100 + sel: '[pagelayer-id="'+el.id+'"]',
4101 + wrap: '[pagelayer-wrap-id="'+el.id+'"]'
1904 4102 };
1905 4103
1906 4104 // Create a reference
1907 4105 el.CSS = elCSS;
4106 +
4107 + // Make sure if we have the class selector
4108 + el.$.addClass('p-'+el.id);
1908 4109
1909 4110 //console.log(el.atts);
1910 4111
1911 4112 for(var i in pagelayer_tabs){
@@ -1919,10 +4120,10 @@
1919 4120
1920 4121 // pagelayer_data will return attributes even if they are BLANK e.g. attr=""
1921 4122 // Render doesnt consider BLANK values as values, and we are unsetting them now
1922 4123 // If in any situation you need to consider blank values, please handle in the JS / PHP function of the Shortcode
1923 - if(x in el.atts && el.atts[x].length < 1){
1924 - delete el.atts[x];
4124 + if(x in el.atts && pagelayer_length(el.atts[x]) < 1){
4125 + delete el.atts[x];
1925 4126 }
1926 4127
1927 4128 // Any editor ?
1928 4129 if('edit' in props[x]){
@@ -1928,8 +4129,59 @@
1928 4129 if('edit' in props[x]){
1929 4130 elCSS.edit.push({prop: x, sel: props[x]['edit']});
1930 4131 }
1931 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 +
1932 4184 // Do we have a addClass ?
1933 4185 // We are checking before the element has a value so that we can add or remove the class
1934 4186 if('addClass' in props[x]){
1935 4187
@@ -1964,9 +4216,9 @@
1964 4216 }
1965 4217
1966 4218 }else{
1967 4219
1968 - var tmp = {'sel': tSel, 'val': addClasses[c]};
4220 + var tmp = {'sel': tSel, 'val': addClasses[c].replace('{{val}}', el.atts[x])};
1969 4221
1970 4222 // If the value is there
1971 4223 if(x in el.atts){
1972 4224 elCSS['classes'].push(tmp);
@@ -2019,8 +4271,9 @@
2019 4271 }
2020 4272
2021 4273 // Screen modes
2022 4274 var modes = {desktop: '', tablet: '_tablet', mobile: '_mobile'};
4275 + var desk_global = (props[x]['type'] == 'typography') ? pagelayer_is_global_typo(el.atts[x]) : '';
2023 4276
2024 4277 for(var m in modes){
2025 4278
2026 4279 var xm = x+modes[m];
@@ -2025,12 +4278,37 @@
2025 4278
2026 4279 var xm = x+modes[m];
2027 4280
2028 4281 // If the value is there
2029 - if(!(xm in el.atts)){
4282 + if(!(xm in el.atts) && pagelayer_empty(desk_global)){
2030 4283 continue;
2031 4284 }
2032 -
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 +
2033 4311 for(var c in css){
2034 4312
2035 4313 // The selector
2036 4314 var tSel = jQuery.isNumeric(c) ? '{{element}}' : c;
@@ -2035,20 +4313,20 @@
2035 4313 // The selector
2036 4314 var tSel = jQuery.isNumeric(c) ? '{{element}}' : c;
2037 4315 var tmp = {
2038 4316 sel: tSel,
2039 - val: pagelayer_css_render(css[c], el.atts[xm], (props[x].sep || ',')),
4317 + val: pagelayer_css_render(css[c], xm_val, (props[x].sep || ',')),
2040 4318 };
2041 4319
2042 4320 // Is this a tablet
2043 4321 if(m == 'tablet'){
2044 - 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;
2045 4323 tmp.val = tmp.val+'}';
2046 4324 }
2047 4325
2048 4326 // Is this a mobile mode ?
2049 4327 if(m == 'mobile'){
2050 - tmp.sel = '@media (max-width: 360px){'+tmp.sel;
4328 + tmp.sel = '@media (max-width: '+ pagelayer_settings['mobile_breakpoint'] +'px){'+tmp.sel;
2051 4329 tmp.val = tmp.val+'}';
2052 4330 }
2053 4331
2054 4332 // Push to store
@@ -2066,9 +4344,16 @@
2066 4344 }
2067 4345
2068 4346 // If there is an HTML, then process it
2069 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')];
2070 4351
4352 + if(typeof fn == 'function'){
4353 + fn(el);
4354 + }
4355 +
2071 4356 el.iHTML = jQuery('<div>'+pagelayer_shortcodes[el.tag]['html']+'</div>');
2072 4357
2073 4358 // Lets process the 'if-ext'
2074 4359 el.iHTML.find('[if-ext]').each(function (){
@@ -2096,16 +4381,9 @@
2096 4381 $j.remove();
2097 4382 }
2098 4383
2099 4384 });
2100 -
2101 - // Is there a function to render ?
2102 - var fn = window['pagelayer_render_'+jEle.attr('pagelayer-tag')];
2103 4385
2104 - if(typeof fn == 'function'){
2105 - fn(el);
2106 - }
2107 -
2108 4386 //console.log(el.atts);
2109 4387
2110 4388 // Parse the variables
2111 4389 var new_html = pagelayer_parse_vars(el.iHTML.html(), el);
@@ -2162,9 +4440,9 @@
2162 4440 for(var c in elCSS.edit){
2163 4441 var prop = elCSS.edit[c]['prop'];
2164 4442 var tSel = elCSS.edit[c]['sel'];
2165 4443 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2166 - node.attr('pagelayer-editable', prop);
4444 + node.attr({'pagelayer-editable': prop, 'contenteditable' : 'true'});
2167 4445 }
2168 4446
2169 4447 }
2170 4448
@@ -2176,9 +4454,9 @@
2176 4454 if(elCSS.classes.length > 0){
2177 4455 //console.log(elCSS.classes);
2178 4456
2179 4457 for(var c in elCSS.classes){
2180 - var tSel = elCSS.classes[c]['sel'];
4458 + var tSel = elCSS.classes[c]['sel'].replace('{{element}}', '');
2181 4459 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2182 4460 if(!node.hasClass(elCSS.classes[c]['val'])){
2183 4461 node.addClass(elCSS.classes[c]['val']);
2184 4462 }
@@ -2189,9 +4467,9 @@
2189 4467 if(elCSS.remove_classes.length > 0){
2190 4468 //console.log(elCSS.remove_classes);
2191 4469
2192 4470 for(var c in elCSS.remove_classes){
2193 - var tSel = elCSS.remove_classes[c]['sel'];
4471 + var tSel = elCSS.remove_classes[c]['sel'].replace('{{element}}', '');
2194 4472 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2195 4473 if(node.hasClass(elCSS.remove_classes[c]['val'])){
2196 4474 node.removeClass(elCSS.remove_classes[c]['val']);
2197 4475 }
@@ -2208,14 +4486,14 @@
2208 4486
2209 4487 for(var c in elCSS.attr){
2210 4488 var tSel = elCSS.attr[c]['sel'].replace('{{element}}', '');
2211 4489 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2212 - var att = elCSS.attr[c]['val'].split('=');
4490 + var att = elCSS.attr[c]['val'].split(/=(.*)/);
2213 4491 att[1] = pagelayer_parse_vars(att[1], el);
2214 4492 att[1] = pagelayer_trim(att[1], '"');
2215 4493
2216 4494 // Is it the same val ?
2217 - if(!node.attr(att[0]) != att[1]){
4495 + if(!node.attr(att[0]) !== att[1]){
2218 4496 node.attr(att[0], att[1]);
2219 4497 }
2220 4498 }
2221 4499 }
@@ -2253,15 +4531,28 @@
2253 4531 var rules = [];
2254 4532
2255 4533 // Loop
2256 4534 for(var c in elCSS.css){
2257 - var tSel = elCSS.css[c]['sel'].replace('{{element}}', elCSS.sel);
2258 - var rule = pagelayer_parse_vars(elCSS.css[c]['val'], el);
2259 - 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 + }
2260 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 + }
2261 4552
2262 4553 // Set the style
2263 - style.html(rules.join("\n"));
4554 + style.html(pagelayer_parse_vars(rules.join("\n"), el));
2264 4555 //console.log(style);
2265 4556 }else{
2266 4557 style.remove();
2267 4558 }
@@ -2274,14 +4565,150 @@
2274 4565 }
2275 4566
2276 4567 // If the element have any parent
2277 4568 var par = pagelayer_get_parent(jEle);
4569 + var eleId = el.id;
4570 +
2278 4571 if(par){
4572 + eleId = par;
2279 4573 pagelayer_sc_render(pagelayer_ele_by_id(par));
2280 4574 }
2281 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 +
2282 4595 };
2283 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 +
2284 4711 // Is the given tag a group
2285 4712 function pagelayer_is_group(tag){
2286 4713
2287 4714 if('has_group' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['has_group'])){
@@ -2291,37 +4718,308 @@
2291 4718 return false;
2292 4719
2293 4720 }
2294 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 +
2295 4910 // Save the post
2296 4911 function pagelayer_save(){
2297 4912
4913 + // hiding and showing loading animation
4914 + pagelayer.$$('.pagelayer-update-text').hide();
4915 + pagelayer.$$('.pagelayer-update-loader').show();
4916 +
4917 + pagelayer_trigger_action('pagelayer_save');
4918 +
4919 + var pagelayerajaxurl = pagelayer_ajax_url+'&action=pagelayer_save_content&postID='+pagelayer_postID;
2298 4920 var post = pagelayer_generate_sc(pagelayer_editable);//alert(post);return;
2299 - var pagelayerajaxurl = pagelayer_ajax_url+'&action=pagelayer_save_content&postID='+pagelayer_postID;
2300 - jQuery.ajax({
2301 - type: "POST",
2302 - url: pagelayerajaxurl,
2303 - data: {
2304 - pagelayer_update_content : post,
2305 - pagelayer_nonce: pagelayer_ajax_nonce
2306 - },
2307 - success: function(response, status, xhr){
2308 - //alert(data);
2309 - var obj = jQuery.parseJSON(response);
2310 - //alert(obj);
2311 - if(obj['error']){
2312 - alert(obj['error']);
2313 - }else{
2314 - pagelayer_isDirty = false;
2315 - alert(obj['success']);
2316 - pagelayer_get_revision();
4921 +
4922 + // Update data or meta of the post
4923 + pagelayer_update_post_data();
4924 +
4925 + // Update Customizer Settings
4926 + pagelayer_update_customizer_settings();
4927 +
4928 + // Update nav menu
4929 + pagelayer_update_nav_menu_data();
4930 +
4931 + if(pagelayer_empty(pagelayer.post_status) && !pagelayer_empty(pagelayer_ajax_post_data['post_status'])){
4932 + pagelayer.post_status = pagelayer_ajax_post_data['post_status'];
4933 + }
4934 +
4935 + // Do we have contact templates ?
4936 + var contacts_props = pagelayer_get_contact_templates();
4937 +
4938 + // Do we have any global widget to save ?
4939 + var global_data = {};
4940 +
4941 + if(!pagelayer_empty(pagelayer_global_widgets)){
4942 + global_data = pagelayer_generate_sc_global_widget();
4943 + }
4944 +
4945 + var cancel = function(){
4946 + pagelayer.$$('.pagelayer-update-text').show();
4947 + pagelayer.$$('.pagelayer-update-loader').hide();
4948 + }
4949 +
4950 + var save = function(){
4951 + var post_data = {
4952 + pagelayer_update_content : pagelayer_Base64.encode(post),
4953 + pagelayer_nonce: pagelayer_ajax_nonce,
4954 + global_widgets: global_data,
4955 + contacts: contacts_props,
4956 + post_status: pagelayer.post_status,
4957 + copyright: pagelayer_copyright
4958 + }
4959 +
4960 + if(!pagelayer_empty(pagelayer.cmode)){
4961 + post_data.cmode = pagelayer.cmode;
4962 + }
4963 +
4964 + post_data = Object.assign(pagelayer_ajax_post_data, post_data);
4965 +
4966 + jQuery.ajax({
4967 + type: "POST",
4968 + url: pagelayerajaxurl,
4969 + data: post_data,
4970 + success: function(response, status, xhr){
4971 + //alert(data);
4972 + var obj = jQuery.parseJSON(response);
4973 + //alert(obj);
4974 +
4975 + if('comment_alerts' in obj){
4976 + console.log("Alerts:", obj['comment_alerts']);
4977 + }
4978 +
4979 + if(obj['error']){
4980 + pagelayer_show_msg(obj['error'], 'error', 10000);
4981 + if('comment_errors' in obj){
4982 + console.log("Errors:", obj['comment_errors']);
4983 + }
4984 + }else{
4985 + pagelayer_show_msg(obj['success'], 'success', 10000);
4986 + pagelayer_get_revision();
4987 +
4988 + // Update the post status in the post_props, but first find if its actually there !
4989 + var jEle = jQuery(pagelayer_editable).find("[pagelayer-tag=pl_post_props]");
4990 + if(jEle.length > 0){
4991 + var id = pagelayer_id(jEle);
4992 + pagelayer_set_atts(jEle, 'post_status', obj['post_status']);
4993 + pagelayer_trigger_action('pagelayer_save_success', obj['post_status']);
4994 + }
4995 +
4996 + pagelayer_do_undirty();
4997 + }
4998 + },
4999 + error: function(jqXHR, textStatus, errorThrown){
5000 + console.log(errorThrown);
5001 + pagelayer_show_msg('An error occured while saving ! Status : '+textStatus+' and Error : '+errorThrown, 'error', 10000);
5002 + },
5003 + complete: function(xhr,status){
5004 + pagelayer.$$('.pagelayer-update-text').show();
5005 + pagelayer.$$('.pagelayer-update-loader').hide();
5006 +
5007 + if(!pagelayer_empty(pagelayer.post_status)){
5008 + pagelayer.$$('.pagelayer-props-modal .pagelayer-meta-iframe').attr('src', pagelayer_post_props );
5009 + pagelayer.post_status = '';
5010 + }
2317 5011 }
2318 - },
2319 - error: function(errorThrown){
2320 - console.log(errorThrown);
2321 - }
2322 - });
5012 + });
5013 + }
2323 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();
2324 5022 };
2325 5023
2326 5024 //Close the Editor
2327 5025 function pagelayer_close(){
@@ -2334,18 +5032,30 @@
2334 5032 }else{
2335 5033 window.top.location.href = pagelayer_returnURL;
2336 5034 }
2337 5035 };
5036 +
5037 +function pagelayer_htmlEntities(str) {
5038 + return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
5039 +}
2338 5040
2339 -// Generate Shortcode Post to save
2340 -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){
2341 5052
5053 + selfEle = selfEle || false;
2342 5054 var txt = '';
2343 5055
2344 - jQuery(selector).children(".pagelayer-ele-wrap").each(function(){
5056 + var generate_sc_single = function(jEle){
2345 5057
2346 - var jEle = jQuery(this).children('.pagelayer-ele');
2347 -
2348 5058 // The ID
2349 5059 var id = jEle.attr('pagelayer-id');
2350 5060
2351 5061 // If there is an Add element wrapper
@@ -2355,14 +5065,26 @@
2355 5065
2356 5066 // Find the type of tag
2357 5067 var tag = jEle.attr('pagelayer-tag');
2358 5068 var final_tag = tag;
2359 - var closestEle = jQuery(this).closest('.pagelayer-col-holder');
5069 + var closestEle = jEle.closest('.pagelayer-col-holder');
2360 5070
5071 + // Skip to create shortcode to prevent save, allowed by tag
5072 + if('skip_save' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['skip_save'])){
5073 + return;
5074 + }
5075 +
2361 5076 // Define inner row | Note : Commented as we now have a new widget of type inner_row
2362 5077 /*if(tag == 'pl_row' && closestEle.length > 0 && closestEle.closest(pagelayer_editable).length > 0){
2363 5078 final_tag = 'pl_inner_row';
2364 5079 }*/
5080 +
5081 + if(pagelayer_empty(tag)){
5082 + var err = 'Found an error in the content as the TAG was missing. The console will have more details.';
5083 + pagelayer_show_msg(err, 'error');
5084 + console.log(err);
5085 + console.log(jEle);
5086 + }
2365 5087
2366 5088 // Define inner column
2367 5089 if(tag == 'pl_col' && closestEle.length > 0 && closestEle.closest(pagelayer_editable).length > 0){
2368 5090 final_tag = 'pl_inner_col';
@@ -2374,44 +5096,33 @@
2374 5096 if('innerHTML' in pagelayer_shortcodes[tag]){
2375 5097 inner = pagelayer_shortcodes[tag]['innerHTML'];
2376 5098 }
2377 5099
5100 + // Data reference
5101 + var ref_data = pagelayer_el_data_ref(jEle);
5102 +
2378 5103 // Create the tag
2379 - var data = '['+final_tag;
5104 + var data = JSON.parse(JSON.stringify(ref_data['attr']));
2380 5105
2381 - // Get the attributes to store
2382 - jQuery.each(jEle[0].attributes, function(i, attrib){
2383 - var res = attrib.name.match(/^pagelayer-a-(.+)/i);
2384 - if(res && res[1] != inner){
2385 - //console.log(attrib.name+' '+res[1]);
2386 - data += ' '+res[1]+'="'+pagelayer_escapeHTML(attrib.value)+'"';
2387 - }
2388 - });
5106 + data['pagelayer-id'] = id;
5107 + data = pagelayer_serializeAttributes(data);
5108 +
5109 + var content = '';
2389 5110
2390 - data = data+']';
2391 -
2392 - // Add to the text
2393 - txt = txt+data+"\n";
2394 -
2395 5111 // Any internal function to handle the save ?
2396 5112 var func = window['pagelayer_tag_'+tag];
2397 5113 if(typeof func == 'function'){
2398 5114
2399 - var content = '';
2400 5115 content = func(jEle);
2401 5116
2402 - if(content.length > 0){
2403 - txt = txt+content;
2404 - }
2405 -
2406 5117 // If its a Row or Column or Group then it will have children
2407 5118 }else if(jEle.hasClass('pagelayer-row') || jEle.hasClass('pagelayer-col') || jEle.hasClass('pagelayer-inner_row') || pagelayer_is_group(tag)){
2408 5119
2409 - var sel = "[pagelayer-id="+id+"]";
5120 + var sel = jEle;
2410 5121
2411 5122 // Any holder which holds children ?
2412 5123 if('holder' in pagelayer_shortcodes[tag]){
2413 - sel = sel+' '+pagelayer_shortcodes[tag]['holder'];
5124 + sel = jEle.find(pagelayer_shortcodes[tag]['holder']);
2414 5125 }
2415 5126
2416 5127 // Select the top-most element
2417 5128 sel = jQuery(sel).first();
@@ -2419,22 +5130,27 @@
2419 5130 // Any child selector - Majorly for owl carousel
2420 5131 // NOTE : Child selector should be very specific with immediate child selection at all levels
2421 5132 var child_selector = false;
2422 5133 if('child_selector' in pagelayer_shortcodes[tag]){
2423 - sel = sel.find(pagelayer_shortcodes[tag]['child_selector']);
5134 + childSel = sel.find(pagelayer_shortcodes[tag]['child_selector']);
5135 +
5136 + if(childSel.length > 0){
5137 + sel = childSel;
5138 + }
2424 5139 }
2425 -
2426 - var childrens = pagelayer_generate_sc(sel);
2427 - if(childrens.length > 0){
2428 - txt = txt+childrens;
5140 +
5141 + if(jQuery(sel).children(".pagelayer-ele-wrap").length < 1){
5142 + content = jQuery(sel).html(); // Backward Compatibility
5143 + }else{
5144 + content = pagelayer_generate_sc(sel);
5145 + content = "\n"+content;
2429 5146 }
2430 5147
2431 5148 // Its a normal element so we might need to handle the content
2432 5149 }else{
2433 5150
2434 - var content = '';
2435 5151 if(inner.length > 0){
2436 - content = jEle.attr('pagelayer-a-'+inner);
5152 + content = pagelayer_get_att(jEle, inner);
2437 5153 if(!content){
2438 5154 content = '';
2439 5155 }
2440 5156 }else{
@@ -2440,74 +5156,45 @@
2440 5156 }else{
2441 5157 content = '';//jEle.html();
2442 5158 }
2443 5159
2444 - if(content.length > 0){
2445 - txt = txt+content;
2446 - }
2447 -
2448 5160 }
2449 5161
2450 - // Close the tag
2451 - 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 + }
2452 5167
2453 - });
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 + };
2454 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 +
2455 5193 return txt;
2456 5194
2457 5195 };
2458 5196
2459 -// Escape charaters in attributes
2460 -var pagelayer_escapeChars = {
2461 - '\\]' : '#93',
2462 - '\\[' : '#91',
2463 - //'=' : '#61',
2464 - '<' : 'lt',
2465 - '>' : 'gt',
2466 - '"' : 'quot',
2467 - //'&' : 'amp',
2468 - '\'' : '#39'
2469 -};
2470 -
2471 -// To unescape
2472 -var pagelayer_unescapeChars = {
2473 - '#93' : ']',
2474 - '#91' : '[',
2475 - //'#61' : '=',
2476 - 'lt' : '<',
2477 - 'gt' : '>',
2478 - 'quot' : '"',
2479 - //'amp' : '&',
2480 - '#39' : '\''
2481 -};
2482 -
2483 -var pagelayer_escaperegex_S = '[';
2484 -for(var key in pagelayer_escapeChars) {
2485 - pagelayer_escaperegex_S += key;
2486 -}
2487 -pagelayer_escaperegex_S += ']';
2488 -
2489 -var pagelayer_escaperegex = new RegExp( pagelayer_escaperegex_S, 'g');
2490 -
2491 -// The function which escapes everything
2492 -function pagelayer_escapeHTML(str) {
2493 - return str.replace(pagelayer_escaperegex, function(m) {
2494 - if(m == '[' || m == ']') m = '\\'+m;
2495 - return '&' + pagelayer_escapeChars[m] + ';';
2496 - });
2497 -};
2498 -
2499 -// This will unescape everything
2500 -function pagelayer_unescapeHTML(str){
2501 - return str.replace(/\&([^;]+);/g, function (entity, entityCode) {
2502 - if(entityCode in pagelayer_unescapeChars){
2503 - return pagelayer_unescapeChars[entityCode];
2504 - }else{
2505 - return entity;
2506 - }
2507 - });
2508 -};
2509 -
2510 5197 // Show the required leftbar tab
2511 5198 function pagelayer_leftbar_tab(tab){
2512 5199 pagelayer.$$('.pagelayer-leftbar-tab').hide();
2513 5200 pagelayer.$$('#'+tab).show();
@@ -2517,23 +5204,44 @@
2517 5204 function pagelayer_leftbar(){
2518 5205
2519 5206 // Toggle the holder
2520 5207 pagelayer.$$('.pagelayer-leftbar-toggle').on('click', function(){
2521 - pagelayer.$$('.pagelayer-leftbar-table').toggle();
5208 + pagelayer.$$('.pagelayer-leftbar-table').toggleClass('pagelayer-leftbar-hidden');
5209 + pagelayer_trigger_action('pagelayer-leftbar-toggle');
2522 5210 });
2523 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 +
2524 5222 var html = '<div class="pagelayer-leftbar">'+
2525 5223 '<div class="pagelayer-leftbar-scroll">'+
2526 5224 '<div id="pagelayer-shortcodes" class="pagelayer-leftbar-tab pagelayer-shortcodes">'+
2527 - '<div class="pagelayer-leftbar-search">'+
2528 - '<i class="fa fa-search" /><input class="pagelayer-search-field" />'+
2529 - '</div>';
5225 + '<div class="pagelayer-widget-tabs">'+
5226 + '<div class="pagelayer-widget-tab" pagelayer-widget-tab="widgets" pagelayer-elpd-active-tab=1>Widgets</div>'+
5227 + '<div class="pagelayer-widget-tab pagelayer-settings" pagelayer-widget-tab="settings">Settings</div>'+
5228 + '<div class="pagelayer-widget-tab" pagelayer-widget-tab="global">Globals</div>'+
5229 + '</div>'+
5230 + '<div class="pagelayer-shortcodes-widget">'+
5231 + '<div class="pagelayer-leftbar-search">'+
5232 + '<i class="pli pli-search" ></i><input class="pagelayer-search-field" placeholder="Search Widget..." /><span class="pagelayer-sf-empty pli">&times;</span>'+
5233 + '</div>';
2530 5234
2531 5235 for(var x in pagelayer_groups){
2532 5236
2533 5237 // Title
2534 - 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';
2535 5241
5242 + html += '<div class="pagelayer-leftbar-group pagelayer-group-name-'+x+'"><h5>'+group_title+'</h5>';
5243 +
2536 5244 // Indivdual icon
2537 5245 for(var y in pagelayer_groups[x]){
2538 5246
2539 5247 var sc = pagelayer_groups[x][y];
@@ -2546,11 +5254,11 @@
2546 5254 '<div class="pagelayer-sc">'+
2547 5255 '<center class="pagelayer-shortcode-inner">';
2548 5256
2549 5257 if('icon' in pagelayer_shortcodes[sc]){
2550 - html += '<i class="pagelayer-shortcode fa fa-'+pagelayer_shortcodes[sc]['icon']+'"></i>';
5258 + html += '<i class="pagelayer-shortcode '+pagelayer_shortcodes[sc]['icon']+'"></i>';
2551 5259 }else{
2552 - html += '<i class="pagelayer-shortcode pagelayer-'+sc+'"></i>';
5260 + html += '<i class="pagelayer-shortcode pli pagelayer-'+sc+'"></i>';
2553 5261 }
2554 5262
2555 5263 html += '</center>'+
2556 5264 '<span class="pagelayer-shortcode-text">'+pagelayer_shortcodes[sc]['name']+'</span>'+
@@ -2563,11 +5271,16 @@
2563 5271
2564 5272 }
2565 5273
2566 5274 html += '</div>'+
5275 + '<div id="pagelayer-global-widget" class="pagelayer-hidden pagelayer-global-widget"></div>'+
5276 + '</div>'+
2567 5277 '<div id="pagelayer-elpd" class="pagelayer-leftbar-tab pagelayer-elpd"></div>'+
5278 + '<div id="pagelayer-options" class="pagelayer-leftbar-tab pagelayer-options"></div>'+
2568 5279 '<div id="pagelayer-history" class="pagelayer-leftbar-tab pagelayer-history"></div>'+
2569 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>'+
2570 5283 '</div>'+
2571 5284 '</div>';
2572 5285
2573 5286 pagelayer.$$('.pagelayer-leftbar-holder').prepend(html);
@@ -2616,108 +5329,170 @@
2616 5329 });
2617 5330 });
2618 5331
2619 5332 // On click Pagelayer setting icon
2620 - pagelayer.$$('.pagelayer-settings-icon').click(function(){
2621 - pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text('Post Settings');
2622 - pagelayer.$$('.pagelayer-logo').hide();
2623 - pagelayer_leftbar_tab('pagelayer-post-settings');
5333 + pagelayer.$$('.pagelayer-settings-icon, .pagelayer-settings').click(function(event){
2624 5334 pagelayer_active = {};
2625 - pagelayer_post_settings();
5335 +
5336 + var pl_tag = jQuery(this).attr('pagelayer-tag') || 'pl_post_props';
5337 + var nModal = jQuery(this).attr('pagelayer-modal-none');
5338 +
5339 + pagelayer_post_settings(pl_tag);
5340 +
2626 5341 });
2627 5342
2628 -};
2629 -
2630 -// Post setting holder
2631 -function pagelayer_post_settings(){
5343 + // Pagelayer post advance setting modal handler
5344 + var propsModal = pagelayer.$$('.pagelayer-props-modal');
5345 + propsModal.find('.pagelayer-props-modal-close').on('click', function(event){
5346 + propsModal.hide();
5347 + });
5348 +
5349 + propsModal.on('click', function(event){
5350 + var target = jQuery(event.target);
5351 +
5352 + if(target.closest('.pagelayer-props-modal-wrap').length > 0){
5353 + return;
5354 + }
5355 +
5356 + propsModal.hide();
5357 + });
5358 +
2632 5359
2633 - // Start pagelayer settings holder
2634 - var setting_holder = '<div class="pagelayer-post-settings-holder">';
2635 -
2636 - // Start pagelayer settings content body
2637 - setting_holder += '<div class="pagelayer-post-settings-acc">'+
2638 - '<div class="pagelayer-post-settings-lable"><span>Title</span><i class="pagelayer-toggle fa"></i></div>'+
2639 - '<div class="pagelayer-post-settings-fields">'+
2640 - '<label for="post_title">Post Title</label> '+
2641 - '<input type="text" name="post_title" value="'+ pagelayer_postTitle +'" id="title" spellcheck="true" autocomplete="off">'+
2642 - '<button class="pagelayer-post-settings-apply pagelayer-success-btn" disabled>Apply</button>'+
2643 - '</div>'+
2644 - '</div>';
2645 -
2646 - /*if(pagelayer_postType == pagelayer_cpt['name']){
2647 - setting_holder += '<div class="pagelayer-post-settings-acc">'+
2648 - '<div class="pagelayer-post-settings-lable"><span>Custom Template type</span><i class="pagelayer-toggle fa"></i></div>'+
2649 - '<div class="pagelayer-post-settings-fields">'+ pagelayer_CPT_condi +
5360 + // On click Pagelayer setting icon
5361 + var global_widget_list = function(){
5362 +
5363 + var gHtml = '';
5364 +
5365 + if(pagelayer_empty(pagelayer_pro)){
5366 + gHtml += '<div class="pagelayer-global-widget-pro">'+pagelayer.pro_txt+
5367 + '<p>Using this feature, you can save the widgets globally and use them on the entire site. The global widget will be editable from one place.</p>'+
5368 + '</div>';
5369 +
5370 + pagelayer.$$('#pagelayer-global-widget').html(gHtml);
5371 + return;
5372 + }
5373 +
5374 + gHtml += '<div class="pagelayer-global-widget-shortcodes">'+
5375 + '<div class="pagelayer-leftbar-search">'+
5376 + '<i class="pli pli-search" ></i><input class="pagelayer-search-field" /><i class="pagelayer-sf-empty pli">&times;</i>'+
2650 5377 '</div>'+
5378 + '<div class="pagelayer-leftbar-group"><h5>'+pagelayer_l('global_widgets')+'</h5></div>'+
2651 5379 '</div>';
2652 - }*/
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 + }
2653 5411
2654 - /* if(pagelayer_support_FI){
2655 - setting_holder += '<div class="pagelayer-post-settings-acc">'+
2656 - '<div class="pagelayer-post-settings-lable"><span>Featured Image</span><i class="pagelayer-toggle fa"></i></div>'+
2657 - '<div class="pagelayer-post-settings-fields">Featured Image'+
2658 - '</div>'+
2659 - '</div>';
2660 - } */
5412 + pagelayer.$$('#pagelayer-global-widget').html(gHtml);
5413 + };
2661 5414
2662 - // End pagelayer settings content body
5415 + // The widget tabs
5416 + pagelayer.$$('.pagelayer-widget-tab').on('click', function(){
5417 + var attr = 'pagelayer-elpd-active-tab';
5418 + pagelayer.$$('.pagelayer-widget-tab').each(function(){
5419 + jQuery(this).removeAttr(attr);
5420 + });
5421 + var cEle = jQuery(this);
5422 + cEle.attr(attr, 1);
5423 +
5424 + if(cEle.attr('pagelayer-widget-tab') == 'global'){
5425 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-shortcodes-widget').addClass('pagelayer-hidden');
5426 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-global-widget').removeClass('pagelayer-hidden');
5427 + // Trigger create global widgets
5428 + global_widget_list();
5429 + }else{
5430 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-shortcodes-widget').removeClass('pagelayer-hidden');
5431 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-global-widget').addClass('pagelayer-hidden');
5432 + }
5433 + });
2663 5434
2664 - // End pagelayer settings holder
2665 - setting_holder += '</div>';
2666 - var holder = pagelayer.$$('#pagelayer-post-settings');
2667 - holder.html(setting_holder);
2668 -
2669 - // On change input fields enable the apply button
2670 - holder.find('input, select, textarea').on('change input', function(){
2671 - jQuery(this).closest('.pagelayer-post-settings-fields').find('.pagelayer-post-settings-apply').removeAttr('disabled');
5435 + // On click search empty
5436 + pagelayer.$$('.pagelayer-leftbar-search>.pagelayer-sf-empty').click(function(){
5437 + pagelayer.$$('.pagelayer-search-field').val('').trigger('input');
2672 5438 });
2673 5439
2674 - // On click the label toggle the setting field holder
2675 - holder.find('.pagelayer-post-settings-lable').on('click', function(){
5440 + // Pagelayer General options
5441 + pagelayer.$$('.pagelayer-options-icon ').click(function(){
5442 + pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text(pagelayer_l('general_options'));
5443 + pagelayer.$$('.pagelayer-logo').hide();
2676 5444
2677 - var lEle = jQuery(this);
2678 - var lEle_next = lEle.next('.pagelayer-post-settings-fields');
5445 + // Setup General options
5446 + pagelayer_setup_general_options();
2679 5447
2680 - holder.find('.pagelayer-post-settings-fields').each(function(){
2681 - var fEle = jQuery(this);
2682 - if(!fEle.is(lEle_next)){
2683 - fEle.hide().prev('.pagelayer-post-settings-lable').find('.pagelayer-toggle').removeClass('pagelayer-open');
2684 - }
2685 - });
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();
2686 5467
2687 - lEle.next('.pagelayer-post-settings-fields').toggle();
2688 - lEle.find('.pagelayer-toggle').toggleClass('pagelayer-open');
2689 -
2690 5468 });
5469 +};
5470 +
5471 +// Post setting holder
5472 +function pagelayer_post_settings(pl_tag, to_click){
2691 5473
2692 - // On click apply button
2693 - holder.find('.pagelayer-post-settings-apply').click(function(){
2694 - var fEle = jQuery(this).closest('.pagelayer-post-settings-fields');
2695 - var data = fEle.find('input, select, textarea').serialize();
5474 + to_click = to_click == -1 ? false : true;
5475 +
5476 + // Is there a post settings ?
5477 + var jEle = jQuery(pagelayer_editable+' [pagelayer-tag="'+ pl_tag +'"]');
5478 +
5479 + // Could not find
5480 + if(jEle.length < 1){
5481 + jEle = pagelayer_create_sc(pl_tag);
5482 + var id = pagelayer_id(jEle);
5483 + jQuery(pagelayer_editable).prepend(jEle);
5484 + pagelayer_element_setup('[pagelayer-id='+id+']', true);
2696 5485
2697 - jQuery.ajax({
2698 - url: pagelayer_ajax_url+'action=pagelayer_save_settings&postID='+pagelayer_postID,
2699 - type: 'post',
2700 - data : 'pagelayer_nonce='+ pagelayer_ajax_nonce +'&'+ data,
2701 - success: function(response, status, xhr){
2702 - //alert(data);
2703 - var obj = jQuery.parseJSON(response);
2704 - //alert(obj);
2705 - if(obj['error']){
2706 - alert(obj['error']);
2707 - }else{
2708 - alert(obj['success']);
2709 - window.location.reload();
2710 - }
2711 - },
2712 - error: function(errorThrown){
2713 - console.log(errorThrown);
2714 - }
2715 - });
2716 -
2717 - });
5486 + // Dont mark as dirty as post_props is not editing anything
5487 + pagelayer_do_undirty();
5488 + }
2718 5489
2719 - return;
5490 + if(to_click){
5491 + jEle.click();
5492 + }
5493 +
5494 + return jEle;
2720 5495 }
2721 5496
2722 5497 // Get the closest element and method
2723 5498 function pagelayer_near_by_ele(id, sc){
@@ -2743,9 +5518,9 @@
2743 5518 var pEle_id = pagelayer_id(jQuery('[pagelayer-wrap-id="'+id+'"]').closest('.pagelayer-ele'));
2744 5519
2745 5520 // Get the parent element tag
2746 5521 var pEle_tag = pagelayer_tag(jQuery('[pagelayer-id="'+pEle_id+'"]'));
2747 - var holder = pagelayer_shortcodes[pEle_tag]['holder'] || '';
5522 + var holder = '>'+ pagelayer_shortcodes[pEle_tag]['holder'] || '';
2748 5523 args = {'method' : 'prepend', 'cEle' : '[pagelayer-id="'+pEle_id+'"] '+ holder+' '};
2749 5524
2750 5525 }
2751 5526
@@ -2757,8 +5532,9 @@
2757 5532
2758 5533 // Push the action data in the pagelayer_history_obj object
2759 5534 function pagelayer_history_action_push(args){
2760 5535
5536 + var currentTime = new Date();
2761 5537 var history_obj_len = pagelayer_history_obj['action_data'].length;
2762 5538
2763 5539 // If the history_obj_len is less then 1 then set the data in array 0 position
2764 5540 if(history_obj_len < 1){
@@ -2768,8 +5544,9 @@
2768 5544
2769 5545 // Remove the second array element if the history_obj_len greater then 100
2770 5546 if(history_obj_len > 100){
2771 5547 pagelayer_history_obj['action_data'].splice(1, 1);
5548 + pagelayer_history_obj['current_active_item_id'] = pagelayer_history_obj['action_data'].length - 1;
2772 5549 }
2773 5550
2774 5551 // Get current active history action id
2775 5552 var action_id = parseInt(pagelayer_history_obj['current_active_item_id']) || 0;
@@ -2778,22 +5555,45 @@
2778 5555 var del_ele = history_obj_len - action_id - 1;
2779 5556 pagelayer_history_obj['action_data'].splice(action_id + 1, del_ele);
2780 5557
2781 5558 // Check if the same attr set as current active history
2782 - if(args.action == "Edited" && history_obj_len > 1){
5559 + if(args.action == "Edited" && history_obj_len > 1 && currentTime - pagelayer.history_lastTime < 1000){
2783 5560 var atts = pagelayer_history_obj['action_data'][action_id] || '';
2784 - if(atts['atts'] == args['atts']){
5561 + if(atts['atts'] == args['atts'] && atts['pl_id'] == args['pl_id'] && pagelayer_empty(atts['sub_actions_group']) ){
2785 5562 args['oldVal'] = atts['oldVal'];
2786 5563 pagelayer_history_obj['action_data'][action_id] = args;
2787 5564 pagelayer_history_setup();
5565 +
5566 + // Set the last history time
5567 + pagelayer.history_lastTime = currentTime;
2788 5568 return true;
2789 5569 }
2790 5570 }
2791 -
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 +
2792 5590 pagelayer_history_obj['action_data'].push(args);
2793 5591 pagelayer_history_obj['current_active_item_id'] = pagelayer_history_obj['action_data'].length - 1;
2794 5592 pagelayer_history_setup();
2795 5593
5594 + // Set the last history time
5595 + pagelayer.history_lastTime = currentTime;
2796 5596 }
2797 5597
2798 5598 // Setup pagelayer history
2799 5599 function pagelayer_history_setup(force){
@@ -2839,9 +5639,9 @@
2839 5639 '<span class="pagelayer-history-subtitle"> '+subTitle+' </span>'+
2840 5640 '<span class="pagelayer-history-action"><i> '+action+' </i></span>'+
2841 5641 '</div>'+
2842 5642 '<div class="pagelayer-history-icon">'+
2843 - '<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>'+
2844 5644 '</div>'+
2845 5645 '</div>';
2846 5646 }
2847 5647
@@ -2869,9 +5669,9 @@
2869 5669 pagelayer_revision_obj[x]['post_author_name']+
2870 5670 '</div>'+
2871 5671 '</div>'+
2872 5672 '<div class="pagelayer-revision-icon-holder">'+
2873 - '<i class="pagelayer-revision-delete fa fa-times"></i>'+
5673 + '<i class="pagelayer-revision-delete pli pli-cross"></i>'+
2874 5674 '</div>'+
2875 5675 '</div>';
2876 5676 }
2877 5677
@@ -2910,14 +5710,45 @@
2910 5710 success: function(response, status, xhr){
2911 5711
2912 5712 var obj = jQuery.parseJSON(response);
2913 5713 if(obj['error']){
2914 - alert(obj['error']);
5714 + pagelayer_show_msg(obj['error'] , 'error');
2915 5715 }else{
5716 +
5717 + // Get the current post_name and post_status
5718 + var props = jQuery(pagelayer_editable).find('.pagelayer-post_props');
5719 + var post_name = '', post_status = '';
5720 +
5721 + if(props.length > 0){
5722 + post_name = pagelayer_get_att(props, 'post_name');
5723 + post_status = pagelayer_get_att(props, 'post_status');
5724 + }
5725 +
5726 + // Set content
2916 5727 jQuery(pagelayer_editable).html(obj['content']);
2917 - alert(obj['success']);
2918 - pagelayer_element_setup();
5728 +
5729 + // Add previous post_name and post_status
5730 + var props_new = jQuery(pagelayer_editable).find('.pagelayer-post_props');
5731 + if(props_new.length > 0){
5732 +
5733 + if(pagelayer_empty(post_name)){
5734 + post_name = pagelayer_default_params.pl_post_props.post_name;
5735 + }
5736 +
5737 + if(pagelayer_empty(post_status)){
5738 + post_status = pagelayer_default_params.pl_post_props.post_status;
5739 + }
5740 +
5741 + var tmp = {};
5742 + tmp['post_name'] = post_name;
5743 + tmp['post_status'] = post_status;
5744 + pagelayer_set_atts(props_new, tmp);
5745 + }
5746 +
5747 + // Need to pass true to render table
5748 + pagelayer_element_setup('.pagelayer-ele', true);
2919 5749 pagelayer_add_widget();
5750 + pagelayer_show_msg(obj['success'], 'success');
2920 5751 }
2921 5752 }
2922 5753 });
2923 5754 });
@@ -2937,11 +5768,11 @@
2937 5768 success: function(response, status, xhr){
2938 5769
2939 5770 var obj = jQuery.parseJSON(response);
2940 5771 if(obj['error']){
2941 - alert(obj['error']);
5772 + pagelayer_show_msg(obj['error'], 'error');
2942 5773 }else{
2943 - alert(obj['success']);
5774 + pagelayer_show_msg(obj['success'], 'success');
2944 5775 rEle.hide();
2945 5776 }
2946 5777
2947 5778 }
@@ -2974,9 +5805,9 @@
2974 5805 });
2975 5806 });
2976 5807 }
2977 5808
2978 -// Get evisions Handler
5809 +// Get revisions Handler
2979 5810 function pagelayer_get_revision(){
2980 5811
2981 5812 jQuery.ajax({
2982 5813 url: pagelayer_ajax_url+'&action=pagelayer_get_revision&postID='+pagelayer_postID,
@@ -2988,9 +5819,9 @@
2988 5819 success: function(response, status, xhr){
2989 5820 var obj = jQuery.parseJSON(response);
2990 5821
2991 5822 if(!pagelayer_empty(obj['error'])){
2992 - alert(obj['error']);
5823 + pagelayer_show_msg(obj['error'], 'error');
2993 5824 }else{
2994 5825 pagelayer_revision_obj = obj;
2995 5826 pagelayer_history_setup(true);
2996 5827 }
@@ -3069,9 +5900,13 @@
3069 5900 // Re-setup the element
3070 5901 var resetup_ele = function(history_array){
3071 5902 jQuery(history_array.cEle.cEle)[history_array.cEle.method](history_array.html);
3072 5903 pagelayer_element_setup('[pagelayer-id='+history_array.pl_id+'], [pagelayer-id='+history_array.pl_id+'] .pagelayer-ele', true);
3073 - 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);
3074 5909 };
3075 5910
3076 5911 // Re-setup the element attr
3077 5912 var reset_ele_attr = function(hEle, atts, val, attrType){
@@ -3092,10 +5927,69 @@
3092 5927 pagelayer.history_action = true;
3093 5928
3094 5929 };
3095 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 +
3096 5990 if(prev_item_id > current_item_id){
3097 -
5991 +
3098 5992 // All Actions for undo here
3099 5993 var i = parseInt(prev_item_id);
3100 5994
3101 5995 for(i; i > current_item_id; i--){
@@ -3100,26 +5994,31 @@
3100 5994
3101 5995 for(i; i > current_item_id; i--){
3102 5996
3103 5997 var history_array = pagelayer_history_obj['action_data'][i];
3104 - var action = history_array.action;
3105 - var id = history_array.pl_id;
5998 + var sub_actions_group = history_array['sub_actions_group'] || '';
3106 5999
3107 - if(action == "Edited"){
3108 - hEle = jQuery('[pagelayer-id="'+id+'"]');
3109 - reset_ele_attr(hEle, history_array.atts, history_array.oldVal, history_array.attrType);
3110 - }else if(action == "Added"){
3111 - delete_ele(id);
3112 - }else if(action == "Deleted"){
3113 - resetup_ele(history_array);
3114 - }else if(action == "Copied"){
3115 - 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 + }
3116 6006 }
3117 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 + }
3118 6017 }
3119 6018
3120 6019 }else{
3121 -
6020 +
3122 6021 // All Actions for redo here
3123 6022 var i = parseInt(prev_item_id)+1;
3124 6023
3125 6024 for(i; i <= current_item_id; i++){
@@ -3124,27 +6023,25 @@
3124 6023
3125 6024 for(i; i <= current_item_id; i++){
3126 6025
3127 6026 var history_array = pagelayer_history_obj['action_data'][i];
3128 - var action = history_array.action;
3129 - 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);
3130 6030
3131 - if(action == "Edited"){
3132 - hEle = jQuery('[pagelayer-id="'+id+'"]');
3133 - reset_ele_attr(hEle, history_array.atts, history_array.newVal, history_array.attrType);
3134 - }else if(action == "Added"){
3135 - resetup_ele(history_array);
3136 -
3137 - if(history_array.tag != "pl_row" && history_array.tag != "pl_col" ){
3138 - // Ensure the column is not empty
3139 - 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]);
3140 6035 }
3141 - }else if(action == "Deleted"){
3142 - delete_ele(id);
3143 - }else if(action == "Copied"){
3144 - resetup_ele(history_array);
3145 6036 }
3146 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 + }
3147 6044 }
3148 6045 }
3149 6046
3150 6047 };
@@ -3155,26 +6052,48 @@
3155 6052 alert(prefix+error);
3156 6053 };
3157 6054
3158 6055 function pagelayer_bottombar(){
3159 - var holder = pagelayer.$$('.pagelayer-bottombar-holder');
3160 - var html = '<div class="pagelayer-bottombar">'+
3161 - '<div class="pagelayer-bottombar-rightbuttons">'+
3162 - '<button class="pagelayer-update-button pagelayer-success-btn">Update</button>'+
3163 - '<button class="pagelayer-close-button">Close</button>'+
3164 - '<div class="pagelayer-mode-wrapper">'+
3165 - '<i class="pagelayer-mode-button fa fa-desktop"></i>'+
3166 - '<div class="pagelayer-mode-buttons-wrapper">'+
3167 - '<i class="screen-mode fa fa-desktop" pagelayer-mode-data="desktop"></i>'+
3168 - '<i class="screen-mode fa fa-tablet" pagelayer-mode-data="tablet"></i>'+
3169 - '<i class="screen-mode fa fa-mobile" pagelayer-mode-data="mobile"></i>'+
3170 - '</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>'+
3171 6071 '</div>'+
3172 - '<i class="pagelayer-history-icon fa fa-history"></i>'+
3173 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>'+
3174 6088 '</div>';
3175 6089
3176 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 +
3177 6096 holder.find('.pagelayer-update-button').on('click', function(){
3178 6097 pagelayer_save();
3179 6098 pagelayer_history_setup();// Setup history tab after update
3180 6099 });
@@ -3181,25 +6100,79 @@
3181 6100
3182 6101 holder.find('.pagelayer-close-button').on('click', function(){
3183 6102 pagelayer_close();
3184 6103 });
6104 +
3185 6105 holder.find('.screen-mode').on('click', function(){
3186 6106 var screen_mode = jQuery(this).attr('pagelayer-mode-data');
3187 6107 pagelayer_set_screen_mode(screen_mode);
3188 - holder.find('.pagelayer-mode-buttons-wrapper').toggle();
6108 + holder.find('.screen-mode').removeClass('active');
6109 + jQuery(this).addClass('active');
3189 6110 });
3190 6111
3191 - holder.find('.pagelayer-mode-button').on('click', function(){
3192 - 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();
3193 6118 });
3194 6119
3195 - holder.find('.pagelayer-history-icon').click(function(){
3196 - pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text('Pagelayer History');
6120 + holder.find('.pagelayer-navigator-icon').closest('.pagelayer-header-icon-wrap').click(function(){
6121 + pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text(pagelayer_l('pagelayer_navigator'));
3197 6122 pagelayer.$$('.pagelayer-logo').hide();
3198 - pagelayer_leftbar_tab('pagelayer-history');
6123 +
6124 + // If the navigator tab visible, then don't setup
6125 + if(!pagelayer.$$('#pagelayer-navigator').is(':visible')){
6126 + pagelayer_navigator_setup();
6127 + }
6128 +
6129 + pagelayer_leftbar_tab('pagelayer-navigator');
3199 6130 pagelayer_active = {};
3200 - pagelayer_history_setup();
3201 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 + });
3202 6175 };
3203 6176
3204 6177
3205 6178 ///////////////////////////////
@@ -3205,89 +6178,298 @@
3205 6178 ///////////////////////////////
3206 6179 // Miscellaneuos Functions
3207 6180 ///////////////////////////////
3208 6181
3209 -// Generates a random string of "n" characters
3210 -function pagelayer_randstr(n, special){
3211 - var text = '';
3212 - var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
6182 +// Setup General options
6183 +function pagelayer_setup_general_options(){
3213 6184
3214 - special = special || 0;
3215 - if(special){
3216 - possible = possible + '&#$%@';
6185 + var holder = pagelayer.$$('.pagelayer-general-options');
6186 +
6187 + if(holder.children().length > 0){
6188 + return;
3217 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>';
3218 6225
3219 - for(var i=0; i < n; i++){
3220 - text += possible.charAt(Math.floor(Math.random() * possible.length));
3221 - }
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 + });
3222 6263
3223 - return text;
3224 -};
6264 + modal.unbind('click');
6265 + modal.on('click', function(e){
6266 +
6267 + if(e.target != this) {
6268 + return;
6269 + }
3225 6270
3226 -function pagelayer_update_site_title(val){
3227 - if(!pagelayer_empty(val)){
3228 - var site_name = jQuery('.pagelayer-wp-title').attr('pagelayer-a-site_name');
3229 - if(!pagelayer_empty(site_name)){
3230 - var site_title = jQuery.ajax({
3231 - url: pagelayer_ajax_url+'&action=pagelayer_fetch_site_title',
3232 - type: 'post',
3233 - async: false
3234 - }).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(){
3235 6289
3236 - if(site_title != site_name){
3237 - var site_title = jQuery.ajax({
3238 - url: pagelayer_ajax_url+'&action=pagelayer_update_site_title',
3239 - type: 'post',
3240 - data: {'site_title': site_name},
3241 - async: false
3242 - }).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;
3243 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+']');
3244 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();
3245 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 +
3246 6416 }
3247 6417
3248 -function pagelayer_trim(str, charlist){
3249 - // discuss at: http://locutus.io/php/trim/
6418 +// Scroll page to element view port
6419 +function pagelayer_scroll_to_viewport(jEle, timeout, parentEle){
3250 6420
3251 - if(typeof str != 'string'){
3252 - return str;
3253 - }
6421 + var scrolled = parentEle || jQuery('html, body');
6422 + timeout = timeout || 500;
6423 + parentEle = parentEle || jQuery(window);
3254 6424
3255 - var whitespace = [' ', '\n', '\r', '\t', '\f', '\x0b', '\xa0', '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u2005', '\u2006', '\u2007', '\u2008', '\u2009', '\u200a', '\u200b', '\u2028', '\u2029', '\u3000' ].join('')
3256 - var l = 0
3257 - var i = 0
3258 - 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 + }
3259 6434
3260 - if (charlist) {
3261 - whitespace = (charlist + '').replace(/([[\]().?/*{}+$^:])/g, '$1')
3262 - }
6435 + var scrolling = elementTop - parentHeight / 2;
6436 + scrolled.stop(true).animate({
6437 + scrollTop: scrolling
6438 + }, 1000);
6439 + }, timeout);
6440 +}
3263 6441
3264 - l = str.length
3265 - for (i = 0; i < l; i++) {
3266 - if (whitespace.indexOf(str.charAt(i)) === -1) {
3267 - str = str.substring(i)
3268 - break
3269 - }
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 + '&#$%@';
3270 6450 }
3271 -
3272 - l = str.length
3273 - for (i = l - 1; i >= 0; i--) {
3274 - if (whitespace.indexOf(str.charAt(i)) === -1) {
3275 - str = str.substring(0, i + 1)
3276 - break
3277 - }
6451 +
6452 + for(var i=0; i < n; i++){
6453 + text += possible.charAt(Math.floor(Math.random() * possible.length));
3278 6454 }
3279 6455
3280 - return whitespace.indexOf(str.charAt(0)) === -1 ? str : ''
6456 + return text;
3281 6457 };
3282 6458
6459 +function pagelayer_randInt(max) {
6460 + return Math.floor(Math.random() * Math.floor(max));
6461 +}
6462 +
3283 6463 // Convert the regular URL of a Video to a Embed URL
3284 -function pagelayer_video_url(src){
3285 -
6464 +function pagelayer_video_url(src, no_url){
6465 +
6466 + no_url = no_url || false;
3286 6467 var youtubeRegExp = /youtube\.com|youtu\.be/;
3287 6468 var vimeoRegExp = /vimeo\.com/;
3288 6469 var match = '';
3289 6470 var videoId = '';
6471 + var vid_params = {};
3290 6472
3291 6473 if (youtubeRegExp.exec(src)) {
3292 6474 match = 'youtube';
3293 6475 } else if (vimeoRegExp.exec(src)) {
@@ -3314,9 +6496,15 @@
3314 6496 } else if (youtube.exec(src)) {
3315 6497 videoId = src.split('.be/');
3316 6498 }
3317 6499
3318 - 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();
3319 6507
3320 6508 break;
3321 6509
3322 6510 case 'vimeo':
@@ -3329,22 +6517,51 @@
3329 6517 } else if (vimeoRegExp.exec(src)) {
3330 6518 videoId = src.split('.com/');
3331 6519 }
3332 6520
3333 - 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 + };
3334 6526
3335 6527 break;
3336 6528 default:
3337 - return src;
6529 + vid_params = {
6530 + type : 'local',
6531 + src : src
6532 + };
6533 +
3338 6534 }
6535 +
6536 + if(!no_url){
6537 + return vid_params.src;
6538 + }
6539 +
6540 + return vid_params;
3339 6541 };
3340 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 +
3341 6554 // Add widget section
3342 6555 function pagelayer_add_widget(){
3343 6556
3344 6557 html='<div class="pagelayer-add-widget-area">'+
3345 - '<i class="pagelayer-add-row fa fa-plus-circle"></i>'+
3346 - '<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>'+
3347 6564 '</div>';
3348 6565
3349 6566 jQuery(pagelayer_editable).append(html);
3350 6567
@@ -3350,27 +6567,38 @@
3350 6567
3351 6568 var add_area = jQuery('.pagelayer-add-widget-area');
3352 6569
3353 6570 // Add a code before this
3354 - var add_sc = function(tag){
6571 + var add_sc = function(tag, global_id = ''){
3355 6572
6573 + var attr = '';
6574 + if(!pagelayer_empty(global_id)){
6575 + attr = ' pagelayer-global-id="'+global_id+'" ';
6576 + }
6577 +
3356 6578 // Create Row
3357 - var row = jQuery('<div pagelayer-tag="pl_row"></div>');
6579 + var row = jQuery('<div pagelayer-tag="pl_row" '+((tag == 'pl_row') ? attr : '') +'></div>');
3358 6580 add_area.before(row);
3359 6581 var row_id = pagelayer_onadd(row, false);
3360 6582 var rEle = pagelayer_ele_by_id(row_id);
3361 6583
3362 - if(tag == 'pl_row'){
6584 + if(tag == 'pl_row' && !pagelayer_empty(global_id)){
3363 6585 rEle.click();
3364 6586 return row_id;
3365 6587 }
3366 6588
3367 6589 // Create Column
3368 - var col = jQuery('<div pagelayer-tag="pl_col"></div>');
6590 + var col = jQuery('<div pagelayer-tag="pl_col" '+((tag == 'pl_col') ? attr : '') +'></div>');
3369 6591 rEle.find('.pagelayer-row-holder').append(col);
3370 6592 var col_id = pagelayer_onadd(col, false);
3371 6593 var cEle = pagelayer_ele_by_id(col_id);
3372 6594
6595 +
6596 + if(tag == 'pl_row'){
6597 + rEle.click();
6598 + return row_id;
6599 + }
6600 +
3373 6601 if(tag == 'pl_col'){
3374 6602 cEle.click();
3375 6603 return col_id;
3376 6604 }
@@ -3375,25 +6603,66 @@
3375 6603 return col_id;
3376 6604 }
3377 6605
3378 6606 // Create element
3379 - var ele = jQuery('<div pagelayer-tag="'+tag+'"></div>');
6607 + var ele = jQuery('<div pagelayer-tag="'+tag+'" '+attr+'></div>');
3380 6608 cEle.find('.pagelayer-col-holder').append(ele);
6609 + //console.log(ele);
3381 6610 var id = pagelayer_onadd(ele);
3382 -
6611 + //console.log(id);
6612 + //console.log(col_id);
6613 + var eEle = pagelayer_ele_by_id(col_id);
6614 + //console.log(eEle);
3383 6615 // Ensure the column is not empty
3384 6616 pagelayer_empty_col(cEle.find('.pagelayer-col-holder'));
3385 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 +
3386 6625 return id;
3387 6626
3388 6627 }
3389 6628
3390 - // Handle Click
3391 - add_area.on('click', function(e){
6629 + // Handle Click on Plus Button
6630 + add_area.find('.pagelayer-add-circle-plus').on('click', function(e){
3392 6631 e.stopPropagation();
3393 6632 add_sc('pl_col');
3394 6633 });
3395 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 +
3396 6665 // Handle Drag over
3397 6666 add_area.on('dragover', function(e){
3398 6667 //console.log(e)
3399 6668 add_area.addClass('pagelayer-add-widget-drag');
@@ -3413,8 +6682,9 @@
3413 6682 add_area.removeClass('pagelayer-add-widget-drag');
3414 6683 jQuery('.pagelayer-is-dragging').removeClass('pagelayer-is-dragging');
3415 6684
3416 6685 var tag = e.originalEvent.dataTransfer.getData('tag');
6686 + var global_id = e.originalEvent.dataTransfer.getData('global_id');
3417 6687
3418 6688 // Is it an existing element ?
3419 6689 if(tag.length < 1){
3420 6690 return false;
@@ -3423,19 +6693,482 @@
3423 6693 e.preventDefault();
3424 6694
3425 6695 //console.log(tag);
3426 6696
3427 - add_sc(tag);
6697 + add_sc(tag, global_id);
3428 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 ;
3429 6716 }
3430 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 +
3431 7158 // On editable area image paste handler
3432 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;
3433 7164
3434 7165 try {
3435 - var items = (pasteEvent.originalEvent || pasteEvent).clipboardData.items,
3436 - mustPreventDefault = false,
3437 - reader;
7166 + if(is_Paste){
7167 + items = (pasteEvent.originalEvent || pasteEvent).clipboardData.items;
7168 + }else{
7169 + items = [pasteEvent];
7170 + }
3438 7171
3439 7172 for (var i = items.length - 1; i >= 0; i -= 1) {
3440 7173
3441 7174 if (items[i].type.match(/^image\//)) {
@@ -3441,71 +7174,49 @@
3441 7174 if (items[i].type.match(/^image\//)) {
3442 7175
3443 7176 reader = new FileReader();
3444 7177 /* jshint -W083 */
3445 - reader.onloadend = function (event) {
7178 + reader.onloadend = function(event) {
3446 7179
3447 7180 var src = event.target.result;
3448 7181
3449 - if( src.indexOf('data:image') === 0 ) {
7182 + if(src.indexOf('data:image') === 0 ) {
3450 7183
3451 7184 var block = src.split(";");
3452 7185 var contentType = block[0].split(":")[1];
3453 7186 var realData = block[1].split(",")[1];
3454 - var fileName = "image."+contentType.split("/")[1];
7187 + if(is_Paste){
7188 + var fileName = "image."+contentType.split("/")[1];
7189 + }else{
7190 + var fileName = items[0]['name'];
7191 + }
3455 7192
3456 7193 // Convert it to a blob to upload
3457 7194 var blob = pagelayer_b64toBlob(realData, contentType);
3458 7195
3459 - var formData = new FormData();
3460 - formData.append('action', 'upload-attachment');
3461 - formData.append('_ajax_nonce', pagelayer_media_ajax_nonce);
3462 - formData.append('async-upload', blob, fileName);
7196 + pagelayer_upload_image(fileName, blob, pagelayer_ajax_func);
3463 7197
3464 - $.ajax({
3465 - url:pagelayer_ajax_url,
3466 - data: formData,// the formData function is available in almost all new browsers.
3467 - type:"post",
3468 - contentType:false,
3469 - processData:false,
3470 - cache:false,
3471 - beforeSend: function( xhr ) {
3472 - if(typeof pagelayer_ajax_func.beforeSend == 'function'){
3473 - pagelayer_ajax_func.beforeSend(xhr);
3474 - }
3475 - },
3476 - error:function(err){
3477 - //console.error(err);
3478 - alert("Unable to upload image for some reason.");
3479 - },
3480 - success:function(response){
3481 - var obj = jQuery.parseJSON(response);
3482 - if(typeof pagelayer_ajax_func.success == 'function'){
3483 - pagelayer_ajax_func.success(obj);
3484 - }
3485 - },
3486 - complete:function(xhr){
3487 - if(typeof pagelayer_ajax_func.complete == 'function'){
3488 - pagelayer_ajax_func.complete(xhr);
3489 - }
3490 - }
3491 - });
3492 -
3493 7198 }
3494 7199
3495 7200 };
3496 7201 /* jshint +W083 */
3497 - reader.readAsDataURL(items[i].getAsFile());
7202 + if(is_Paste){
7203 + reader.readAsDataURL(items[i].getAsFile());
7204 + }else{
7205 + reader.readAsDataURL(items[i]);
7206 + }
3498 7207 mustPreventDefault = true;
3499 7208 }
3500 7209 }
3501 7210
3502 - if(mustPreventDefault){
7211 + if(mustPreventDefault && is_Paste){
3503 7212 pasteEvent.stopPropagation();
3504 7213 pasteEvent.preventDefault();
3505 7214 }
3506 7215
3507 - }catch(err){}
7216 + }catch(err){
7217 + console.log(err);
7218 + }
3508 7219
3509 7220 return mustPreventDefault;
3510 7221
3511 7222 }
@@ -3542,5 +7253,930 @@
3542 7253 img_url = img_url.replace(x, pagelayer_theme_vars[x]);
3543 7254 }
3544 7255
3545 7256 return img_url;
3546 -};
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 +