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 +4607 -609 1.0.2 → 2.2.2 View file →
@@ -8,20 +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 = {};
19 27 var pagelayer_add_section_data = {};
20 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 +
21 97 // Lets start
22 -jQuery(document).ready(function(){
98 +jQuery(document).ready(pagelayer_start);
99 +
100 +// Function to load the codes
101 +function pagelayer_start(){
23 102
103 + pagelayer.loading = 1;
104 + console.log('['+pagelayer_brand+'] Starting Pagelayer');
105 +
106 + // Prevent the click Insite editor
107 + pagelayer_prevent_click();
108 +
24 109 // Set the title of the parent window
25 110 try{ pagelayer.$$('head').append(pagelayer.$('title')[0].outerHTML); }catch(e){};
26 111
27 112 pagelayer.blank_img = pagelayer_url+'/images/default-image.png';
@@ -28,15 +113,21 @@
28 113
29 114 pagelayer_shortcodes['pl_inner_row'] = JSON.parse(JSON.stringify(pagelayer_shortcodes['pl_row']));
30 115 pagelayer_shortcodes['pl_inner_row']['name'] = 'Inner Row';
31 116 pagelayer_groups['grid'].push('pl_inner_row');
117 +
118 + // Removing post props options
119 + pagelayer_setting_post_props();
32 120
33 121 // Make the Topbar
34 122 pagelayer_bottombar();
35 123
36 124 // Make the Leftbar
37 - pagelayer_leftbar();
38 -
125 + pagelayer_leftbar();
126 +
127 + // Make widget list toolbar
128 + pagelayer_create_widget_tooltip();
129 +
39 130 // Add widget section
40 131 pagelayer_add_widget();
41 132
42 133 // Setup the ELPD
@@ -41,8 +132,11 @@
41 132
42 133 // Setup the ELPD
43 134 pagelayer_elpd_setup();
44 135
136 + // Dump the data we have
137 + pagelayer_element_dump_data();
138 +
45 139 // Setup the properties of the elements
46 140 pagelayer_element_setup();
47 141
48 142 // An image to show for drag
@@ -56,8 +150,11 @@
56 150
57 151 // Set to desktop
58 152 pagelayer_set_screen_mode('desktop');
59 153
154 + // Create list of fonts
155 + pagelayer_fonts = pagelayer_l('pl_fonts_list');
156 +
60 157 // Set up right click
61 158 pagelayer_left_click();
62 159 pagelayer_right_click();
63 160
@@ -64,8 +161,14 @@
64 161 // Setup pagelayer history handle
65 162 pagelayer_history_obj['action_data'] = [];
66 163 pagelayer_history_setup(true);
67 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 +
68 171 // Do any actions here
69 172 pagelayer_trigger_action('pagelayer_setup_history');
70 173
71 174 // Editor Tooltips
@@ -80,10 +183,252 @@
80 183 pagelayer_icons[item] = JSON.parse(pagelayer_get_stored_data(pagelayer_url+'/fonts/'+item+'.json', pagelayer_ver));
81 184 });
82 185 };
83 186
84 -});
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 +}
85 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 +
86 431 // The jQuery Object of the ELPD
87 432 var pagelayer_elpd;
88 433
89 434 // Store data values
@@ -163,9 +508,9 @@
163 508 var pl_iframe = pagelayer.$$('.pagelayer-iframe'),
164 509 pl_leftbar = pagelayer.$$('.pagelayer-leftbar-table');
165 510
166 511 // On mouse down in pagelayer-topbar-holder
167 - pagelayer.$$('.pagelayer-topbar-holder').on('mousedown', function(e){
512 + pagelayer.$$('.pagelayer-topbar-mover').on('mousedown', function(e){
168 513 e = e || window.event;
169 514 e.preventDefault();
170 515
171 516 // Get leftbar position
@@ -177,9 +522,8 @@
177 522 var posY = e.clientY;
178 523
179 524 // The variable needs to be empty.
180 525 var newMethod = '',
181 - par_doc = jQuery(window.parent.document).add(document),
182 526 change = true;
183 527
184 528 var leftbar_mousemove = function(e){
185 529 e = e || window.event;
@@ -232,10 +576,10 @@
232 576
233 577 var leftbar_mouseup = function(e){
234 578
235 579 // Remove events
236 - par_doc.off('mousemove', leftbar_mousemove);
237 - par_doc.off('mouseup', leftbar_mouseup);
580 + pagelayer.gDocument.off('mousemove', leftbar_mousemove);
581 + pagelayer.gDocument.off('mouseup', leftbar_mouseup);
238 582
239 583 // Remove class to leftbar
240 584 pagelayer.$$('.pagelayer-leftbar-move').remove();
241 585
@@ -258,10 +602,10 @@
258 602 // make change true
259 603 change = true;
260 604 };
261 605
262 - par_doc.on('mouseup', leftbar_mouseup);
263 - par_doc.on('mousemove', leftbar_mousemove);
606 + pagelayer.gDocument.on('mouseup', leftbar_mouseup);
607 + pagelayer.gDocument.on('mousemove', leftbar_mousemove);
264 608
265 609 });
266 610
267 611 }
@@ -384,9 +728,21 @@
384 728 var onWrap;
385 729
386 730 // If we are a column, we can be over another column or row
387 731 if(tag == 'pl_col'){
388 - 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 + }
389 745 //console.log(pagelayer_id(onWrap));
390 746
391 747 // If we are a row, we can be over another row or a column
392 748 }else if(tag == 'pl_row'){
@@ -394,10 +750,14 @@
394 750 //console.log(pagelayer_id(onWrap));
395 751
396 752 // For inner row we restrict to 1 level only
397 753 }else if(tag == 'pl_inner_row'){
754 +
398 755 var ele_wrap = jQuery(ele).parents('.pagelayer-wrap-col');
399 - 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 + ){
400 760 onWrap = jQuery(ele).closest('.pagelayer-wrap-ele,.pagelayer-wrap-col,.pagelayer-wrap-inner-row');
401 761 }else{
402 762 onWrap = jQuery(ele).closest('.pagelayer-wrap-inner-row');
403 763 }
@@ -403,8 +763,70 @@
403 763 }
404 764 // For every other element, we can be over a col or ele
405 765 }else{
406 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 + }
407 829 }
408 830 //console.log(onWrap);
409 831
410 832 // If we find nothing
@@ -432,20 +854,29 @@
432 854 }
433 855 }*/
434 856
435 857 // Get the ID
436 - var onId = onWrap.attr('pagelayer-wrap-id');
437 - var onEle = onWrap.children('.pagelayer-ele');
858 + var onId = pagelayer_id(onWrap);
859 + var onEle = pagelayer_ele_by_id(onId);
438 860
439 861 // Do we have a parent ?
440 - var pOnId = pagelayer_get_parent(onEle);
441 -
442 - 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 +
443 869 onId = pOnId;
444 - onEle = pagelayer_ele_by_id(onId);
445 - 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 +
446 874 }
447 875
876 + // Do we have a parent ?
877 + have_parent(onEle);
878 +
448 879 var changed = false;
449 880
450 881 // Was it the same ID like the one we were on before
451 882 if(pagelayer.drag_closest != onId){
@@ -485,10 +916,10 @@
485 916 }
486 917
487 918 //console.log(changed);
488 919
489 - // If we are on our self then clear return false
490 - 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')){
491 922 clear_prospect();// Clear existing prospects
492 923 reset_on_drag();// Also reset the last on item
493 924 return false;
494 925 }
@@ -585,10 +1016,17 @@
585 1016 e.preventDefault();
586 1017
587 1018 var wrap = pagelayer.dragging;
588 1019 var tag = pagelayer_tag(wrap);
1020 + var gId = wrap.attr('pagelayer-global-id');
589 1021 var fromEl = wrap.parent();
590 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 +
591 1029 wrap.removeClass('pagelayer-is-dragging');
592 1030
593 1031 // Find any prospect
594 1032 var prospect = jQuery('.pagelayer-drag-prospect');
@@ -605,10 +1043,15 @@
605 1043 var method = (corner == 'top') ? 'before' : 'after';
606 1044 var before_loc; // Location before the drop
607 1045
608 1046 // Create the element if it needs to be created
609 - if(pagelayer.drag_is_new){
1047 + if(pagelayer.drag_is_new){
610 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 + }
611 1054
612 1055 // Move the object
613 1056 }else{
614 1057
@@ -637,8 +1080,15 @@
637 1080
638 1081 // Trigger the onadd
639 1082 if(pagelayer.drag_is_new){
640 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 + }
641 1091
642 1092 // Existing elements
643 1093 }else{
644 1094 id = pagelayer_id(wrap);
@@ -650,8 +1100,10 @@
650 1100 'pl_id' : id,
651 1101 'before_loc' : before_loc,
652 1102 'after_loc' : {'method' : method, 'cEle' : onWrap}
653 1103 });
1104 +
1105 + pagelayer_do_dirty(pagelayer_ele_by_id(id));
654 1106 }
655 1107
656 1108 // Defining the variables as needed
657 1109 var jEle = pagelayer_ele_by_id(id);
@@ -699,13 +1151,14 @@
699 1151 jQuery(document).on('dragover', ondragover);
700 1152 jQuery(document).on('drop', ondrop);
701 1153
702 1154 // For addition of new elements
703 - pagelayer.$$('[pagelayer-tag]').on('dragstart', function(e){
1155 + pagelayer.$$('.pagelayer-leftbar').on('dragstart', function(e){
704 1156 //console.log(e);
705 1157
706 1158 var tEle = jQuery(e.target);
707 1159 var jEle = tEle.closest('.pagelayer-shortcode-drag');
1160 + var global_id = jEle.attr('pagelayer-global-id');
708 1161
709 1162 // Is it an existing element ?
710 1163 if(jEle.length < 1){
711 1164 return false;
@@ -712,8 +1165,12 @@
712 1165 }
713 1166
714 1167 e.originalEvent.dataTransfer.setData('tag', pagelayer_tag(jEle));
715 1168
1169 + if(!pagelayer_empty(global_id)){
1170 + e.originalEvent.dataTransfer.setData( 'global_id', global_id );
1171 + }
1172 +
716 1173 pagelayer.dragging = jEle;
717 1174 pagelayer.drag_is_new = true;
718 1175
719 1176 });
@@ -757,20 +1214,11 @@
757 1214
758 1215 // Column is becoming blank, so show add ele
759 1216 if(jEle.children().length < 1){
760 1217 //from.addClass('pagelayer-empty-col');
761 - 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>');
762 1219 //var h = jEle.parent().parent().children('.pagelayer-ele-overlay').height();
763 1220 //jEle.children('.pagelayer-add-ele').height(h);
764 - jEle.find('>.pagelayer-add-ele .fa').unbind('click');
765 - jEle.find('>.pagelayer-add-ele .fa').on('click', function(event){
766 - event.stopPropagation();
767 - pagelayer.$$('.pagelayer-elpd-close').click();
768 -
769 - // Show left bar
770 - pagelayer.$$('.pagelayer-leftbar-table').removeClass('pagelayer-leftbar-hidden pagelayer-leftbar-minimize');
771 -
772 - });
773 1221
774 1222 // Any add ele sign with non-empty columns here ?
775 1223 }else if(jEle.children('.pagelayer-add-ele').length > 0 && jEle.children().length > 1){
776 1224 jEle.children('.pagelayer-add-ele').remove();
@@ -775,8 +1223,16 @@
775 1223 }else if(jEle.children('.pagelayer-add-ele').length > 0 && jEle.children().length > 1){
776 1224 jEle.children('.pagelayer-add-ele').remove();
777 1225 }
778 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 +
779 1235 });
780 1236
781 1237 };
782 1238
@@ -806,13 +1262,13 @@
806 1262 }
807 1263 }
808 1264 jEle.addClass('pagelayer-col-'+cols);
809 1265 jEle.css({'width': ''});
810 - Ele.addClass('pagelayer-col-'+cols);
811 - Ele.css({'width': ''});
812 1266
813 1267 // Set the att
814 1268 pagelayer_set_atts(Ele, obj);
1269 + pagelayer_set_atts(Ele, 'col_width','');
1270 + pagelayer_sc_render(Ele)
815 1271 });
816 1272 }
817 1273
818 1274 // Make column resizable handler
@@ -838,13 +1294,16 @@
838 1294 var rHolder_width = wrap.closest('.pagelayer-row-holder').width();
839 1295 var new_width, nEle_new_width;
840 1296
841 1297 // Original width
842 - 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'));
843 1300 var original_mouse_x = e.pageX;
844 1301
1302 + var both_width = parseInt(original_width + next_ele_width);
1303 +
845 1304 // Add the element width and next element width
846 - both_width = (original_width / rHolder_width *100) + (next_ele.width() / rHolder_width *100);
1305 + both_width = ((both_width / rHolder_width) *100);
847 1306
848 1307 if(both_width > 100){
849 1308 return false;
850 1309 }
@@ -851,9 +1310,13 @@
851 1310
852 1311 jQuery('body').css({'cursor': 'ew-resize'});
853 1312 rHandler.css({'display': 'block'});
854 1313
1314 + var mousemoved = false;
1315 +
855 1316 var r_mousemove = function(e){
1317 + mousemoved = true;
1318 +
856 1319 var width = original_width + (e.pageX - original_mouse_x);
857 1320
858 1321 // Covert width in percentage
859 1322 new_width = (width / rHolder_width *100).toFixed(2);
@@ -870,19 +1333,31 @@
870 1333
871 1334 var r_mouseup = function(e){
872 1335
873 1336 jQuery(document).off('mousemove', r_mousemove);
1337 + jQuery(document).off('mouseup', r_mouseup);
874 1338 jQuery('body').css({'cursor': ''});
875 1339 rHandler.removeAttr('style pre-width next-width');
876 1340
1341 + // IF mouseMoved
1342 + if(!mousemoved) return;
1343 +
877 1344 // find real element and next real element
878 1345 var jEle = wrap.find('>.pagelayer-ele');
879 1346 var nEle = next_ele.find('>.pagelayer-ele');
880 -
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 +
881 1355 // Set the element attrs
882 - jEle.attr({'pagelayer-a-col_width': new_width, 'pagelayer-a-col': ''});
883 - nEle.attr({'pagelayer-a-col_width': nEle_new_width, 'pagelayer-a-col': ''});
884 - 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', '');
885 1360
886 1361 };
887 1362
888 1363 // Resize start
@@ -915,14 +1390,25 @@
915 1390 function pagelayer_element_added(jEle){
916 1391
917 1392 var sc = jEle.attr('pagelayer-tag');
918 1393 var id, par_id;
1394 + var gId = jEle.attr('pagelayer-global-id');
1395 + gId = gId && !pagelayer_empty(pagelayer_global_widgets[gId]) ? gId : 0;
919 1396
920 1397 // Set Pagelayer History FALSE to prevent saving attributes in action history
921 1398 pagelayer.history_action = false;
922 -
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 +
923 1406 // Generate the HTML
924 - html = pagelayer_create_sc(sc);
1407 + }else{
1408 + html = pagelayer_create_sc(sc);
1409 + }
1410 +
925 1411 id = pagelayer_assign_id(html);
926 1412 par_id = id;
927 1413
928 1414 // Insert the HTML
@@ -930,8 +1416,13 @@
930 1416
931 1417 // Setup the properties of the elements
932 1418 pagelayer_element_setup("[pagelayer-id="+par_id+"], [pagelayer-id="+par_id+"] .pagelayer-ele", true);
933 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 +
934 1425 // Any children to add ?
935 1426 if(!('widget' in pagelayer_shortcodes[sc])){
936 1427
937 1428 // The element props
@@ -938,17 +1429,29 @@
938 1429 var props = pagelayer_shortcodes[sc];
939 1430
940 1431 // Do we have to create children ?
941 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);
942 1442
943 - var has_group = props['has_group'];
944 - var gProp = props[has_group['section']][has_group['prop']];
945 -
946 - for(var i=0; i < gProp['count']; i++){
947 - var cid = pagelayer_element_add_child(jQuery("[pagelayer-id="+id+"]"), gProp['sc']);
948 - //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+'"]'));
949 1453 }
950 -
951 1454 }
952 1455
953 1456 }
954 1457
@@ -958,21 +1461,27 @@
958 1461 pagelayer_history_action_push({
959 1462 'title' : pagelayer_shortcodes[sc]['name'],
960 1463 'action' : 'Added',
961 1464 'pl_id' : id,
962 - 'html' : jQuery("[pagelayer-id="+id+"]"),
1465 + 'html' : jQuery("[pagelayer-id="+id+"]")[0].outerHTML,
963 1466 'cEle' : cEle
964 - });
1467 + });
965 1468
966 1469 // Set pagelayer history TRUE
967 1470 pagelayer.history_action = true;
1471 + pagelayer.global_render = true;
968 1472
1473 + // To update nav item list
1474 + pagelayer_do_dirty(pagelayer_ele_by_id(id));
1475 +
969 1476 return id;
970 1477
971 1478 };
972 1479
973 1480 // Add an element
974 -function pagelayer_element_add_child(pEle, sc){
1481 +function pagelayer_element_add_child(pEle, sc, gProp){
1482 +
1483 + gProp = gProp || {};
975 1484 var child = pagelayer_create_sc(sc);
976 1485 var cid = pagelayer_assign_id(child);
977 1486 pagelayer_set_parent(child, pagelayer_assign_id(pEle));
978 1487
@@ -990,8 +1499,73 @@
990 1499 }
991 1500
992 1501 pagelayer_element_setup('[pagelayer-id='+cid+']', true);
993 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 +
994 1568 // Do we have to create children ?
995 1569 if('has_group' in pagelayer_shortcodes[sc]){
996 1570
997 1571 var has_group = pagelayer_shortcodes[sc]['has_group'];
@@ -997,9 +1571,9 @@
997 1571 var has_group = pagelayer_shortcodes[sc]['has_group'];
998 1572 var gProp = pagelayer_shortcodes[sc][has_group['section']][has_group['prop']];
999 1573
1000 1574 for(var i=0; i < gProp['count']; i++){
1001 - 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);
1002 1576 }
1003 1577
1004 1578 }
1005 1579
@@ -1029,8 +1603,14 @@
1029 1603 return id;
1030 1604
1031 1605 }
1032 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 +
1033 1613 // Assign the jQuery object an ID
1034 1614 function pagelayer_assign_id(jEle){
1035 1615
1036 1616 // Do you have the pagelayer id
@@ -1035,9 +1615,10 @@
1035 1615
1036 1616 // Do you have the pagelayer id
1037 1617 var id = jEle.attr("pagelayer-id");
1038 1618 if(!id || id.length < 1){
1039 - id = pagelayer_randstr(16);
1619 + id = pagelayer_randstr(3)+pagelayer_randInt(9999).toString();
1620 + id = id.toLowerCase();
1040 1621 jEle.attr("pagelayer-id", id);
1041 1622 }
1042 1623
1043 1624 return id;
@@ -1068,11 +1649,13 @@
1068 1649 //pagelayer_clear_editable();// First clear
1069 1650 jEle.find('[pagelayer-editable]').each(function (){
1070 1651 pagelayer_make_editable(jQuery(this), e);
1071 1652 });
1072 -
1653 +
1073 1654 // Show left bar
1074 - pagelayer.$$('.pagelayer-leftbar-table').removeClass('pagelayer-leftbar-hidden pagelayer-leftbar-minimize');
1655 + if(pagelayer_empty(e)){
1656 + pagelayer.$$('.pagelayer-leftbar-table').removeClass('pagelayer-leftbar-hidden pagelayer-leftbar-minimize');
1657 + }
1075 1658
1076 1659 // Lets not rebuild everything to make it faster
1077 1660 if(pagelayer_is_active(jEle)){
1078 1661 return false;
@@ -1077,8 +1660,10 @@
1077 1660 if(pagelayer_is_active(jEle)){
1078 1661 return false;
1079 1662 }
1080 1663
1664 + pagelayer_trigger_action('pagelayer_element_clicked', [jEle]);
1665 +
1081 1666 // Set this as the active element
1082 1667 pagelayer_set_active(jEle);
1083 1668
1084 1669 // Show the properties
@@ -1085,13 +1670,69 @@
1085 1670 pagelayer_elpd_open(jEle);
1086 1671
1087 1672 }
1088 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 +
1089 1720 // The edit option
1090 1721 function pagelayer_edit_element(selector){
1091 1722 pagelayer_element_clicked(selector);
1092 1723 }
1093 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 +
1094 1735 // Setup the properties on a single click
1095 1736 function pagelayer_element_setup(selector, render){
1096 1737
1097 1738 var selector = selector || ".pagelayer-ele";
@@ -1098,9 +1739,9 @@
1098 1739 render = render || false;
1099 1740
1100 1741 // Loop through
1101 1742 jQuery(pagelayer_editable+' '+selector).each(function(){
1102 -
1743 +
1103 1744 var jEle = jQuery(this);
1104 1745
1105 1746 // Assign an ID if not there
1106 1747 var id = pagelayer_assign_id(jEle);
@@ -1106,8 +1747,13 @@
1106 1747 var id = pagelayer_assign_id(jEle);
1107 1748 var pId = pagelayer_get_parent(jEle) || '';// Options to show on hover
1108 1749 var selector = '[pagelayer-id='+id+']';
1109 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 +
1110 1756 if(render){
1111 1757 pagelayer_sc_render(jEle);
1112 1758 }
1113 1759
@@ -1112,8 +1758,9 @@
1112 1758 }
1113 1759
1114 1760 // Get the tag
1115 1761 var tag = pagelayer_tag(jEle);
1762 + var props = pagelayer_get_props(jEle);
1116 1763
1117 1764 // Lets check if we are the child of a parent i.e. element of a group
1118 1765 if(pagelayer_empty(pId)){
1119 1766
@@ -1140,9 +1787,14 @@
1140 1787
1141 1788 }
1142 1789
1143 1790 }
1144 -
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 +
1145 1797 // Make the wraps
1146 1798 jEle.wrap('<div class="pagelayer-ele-wrap" pagelayer-wrap-id="'+id+'"></div>');
1147 1799 var wrap = jEle.parent();
1148 1800
@@ -1155,15 +1807,10 @@
1155 1807 col = 'pagelayer-col-'+x;
1156 1808 break;
1157 1809 }
1158 1810 }
1811 +
1159 1812
1160 - var is_custom_width = pagelayer_get_att(jEle, 'col');
1161 - var col_width = pagelayer_get_att(jEle, 'col_width');
1162 - if(pagelayer_empty(is_custom_width) && col_width){
1163 - wrap.css('width', col_width+'%');
1164 - }
1165 -
1166 1813 wrap.addClass('pagelayer-col '+col);
1167 1814 //jEle.removeClass('pagelayer-col '+col);
1168 1815 wrap.addClass('pagelayer-wrap-col');
1169 1816
@@ -1189,11 +1836,13 @@
1189 1836 pagelayer_sc_render(jEle);
1190 1837 }
1191 1838
1192 1839 html = '<div class="pagelayer-row-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
1193 - '<i class="fa fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" />'+
1194 - '<i class="fa fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" />'+
1195 - '<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>'+
1196 1845 '</div>';
1197 1846
1198 1847 }else if(tag == 'pl_col'){
1199 1848
@@ -1199,9 +1848,9 @@
1199 1848
1200 1849 overlay.addClass('pagelayer-col-hover');
1201 1850
1202 1851 html = '<div class="pagelayer-col-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
1203 - '<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>'+
1204 1853 '</div>';
1205 1854
1206 1855 // Is it an empty col ?
1207 1856 pagelayer_empty_col(jEle.children('.pagelayer-col-holder'));
@@ -1211,11 +1860,13 @@
1211 1860
1212 1861 }else{
1213 1862
1214 1863 html = '<div class="pagelayer-ele-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
1215 - '<i class="fa fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" />'+
1216 - '<i class="fa fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" />'+
1217 - '<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>'+
1218 1869 '</div>';
1219 1870
1220 1871 }
1221 1872
@@ -1220,10 +1871,23 @@
1220 1871 }
1221 1872
1222 1873 // Append to the child
1223 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 +
1224 1881 jQuery('[pagelayer-option-id='+id+']').hide();
1225 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 +
1226 1890 // Setup the HOVER events ABD create WRAPS IF we dont have a parent
1227 1891 if(pId.length > 0){
1228 1892 return;
1229 1893 }
@@ -1257,8 +1921,44 @@
1257 1921
1258 1922 });
1259 1923 }
1260 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 +
1261 1961 // Left Click
1262 1962 function pagelayer_left_click(){
1263 1963
1264 1964 jQuery(pagelayer_editable).on('click', function(e){
@@ -1288,12 +1988,15 @@
1288 1988
1289 1989 var html = '<div class="pagelayer-right-click-options" style="display:none;">'+
1290 1990 '<ul>'+
1291 1991 '<li><a class="pagelayer-right-edit">Edit</a></li>'+
1292 - '<li><a class="pagelayer-right-duplicate"><i class="fa fa-clone" /> Duplicate</a></li>'+
1293 - '<li><a class="pagelayer-right-copy"><i class="fa fa-files-o" /> Copy</a></li>'+
1294 - '<li><a class="pagelayer-right-paste"><i class="fa fa-clipboard" /> Paste</a></li>'+
1295 - '<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>'+
1296 1999 '</ul>'+
1297 2000 '</div>';
1298 2001
1299 2002 jQuery('body').append(html);
@@ -1304,8 +2007,13 @@
1304 2007
1305 2008 var tEle = jQuery(e.target);
1306 2009 var jEle = tEle.closest('.pagelayer-ele-wrap').children('.pagelayer-ele');
1307 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 +
1308 2016 // Get the parent
1309 2017 var pId = pagelayer_get_parent(jEle);
1310 2018
1311 2019 // If we found a parent
@@ -1316,31 +2024,89 @@
1316 2024 // The basics
1317 2025 var id = pagelayer_assign_id(jEle);
1318 2026 var tag = pagelayer_tag(jEle);
1319 2027
1320 - $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']);
1321 2029 $contextMenu.find('.pagelayer-right-duplicate').attr('onclick', 'pagelayer_copy_element("[pagelayer-id='+id+']")');
1322 2030 $contextMenu.find('.pagelayer-right-copy').attr('onclick', 'pagelayer_copy_select("[pagelayer-id='+id+']")');
1323 - $contextMenu.find('.pagelayer-right-paste').attr('onclick', 'pagelayer_paste_element("[pagelayer-id='+id+']")');
1324 2031 $contextMenu.find('.pagelayer-right-delete').attr('onclick', 'pagelayer_delete_element("[pagelayer-id='+id+']")');
1325 2032
1326 - // If copy_selected is empty then copy data from localStorage
1327 - if(pagelayer_empty(pagelayer.copy_selected)){
1328 - pagelayer_copy_from_localStorage();
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 + });
1329 2051 }
1330 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 +
1331 2060 // Are we to hide the paste ?
1332 - if(!pagelayer_empty(pagelayer.copy_selected) && pagelayer_can_copy_to(jEle)){
1333 - //console.log(pagelayer_can_copy_to(jEle));
1334 - $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);
1335 2073 }else{
1336 - $contextMenu.find('.pagelayer-right-paste').parent().hide();
2074 + showPaste();
1337 2075 }
1338 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 +
1339 2105 $contextMenu.css({
1340 2106 display: "block",
1341 - left: e.pageX,
1342 - top: e.pageY
2107 + left: hPosition,
2108 + top: vPosition
1343 2109 });
1344 2110
1345 2111 return false;
1346 2112
@@ -1355,9 +2121,14 @@
1355 2121 function pagelayer_set_parent(jEle, id){
1356 2122 jEle.attr('pagelayer-parent', id);
1357 2123 };
1358 2124
1359 -// 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
1360 2131 function pagelayer_get_parent(jEle){
1361 2132 return jEle.attr('pagelayer-parent');
1362 2133 };
1363 2134
@@ -1400,31 +2171,289 @@
1400 2171 }
1401 2172 }
1402 2173 }
1403 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 +
1404 2324 // Handle key press events
1405 -jQuery(document).keydown(function(event){
2325 +pagelayer.gDocument.keydown(function(event){
1406 2326 //alert(String.fromCharCode(event.which));
1407 2327
1408 - // Delete
1409 - if(event.keyCode == 46){
1410 - var tEle = jQuery(event.target);
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);
1411 2337
1412 - // Is this a delete call in the editable area ?
1413 - if (!tEle.is('input, textarea') && tEle.closest('[contenteditable]').length < 1) {
1414 - pagelayer_delete_element('[pagelayer-active]');
2338 + // Add selected widget from widget list
2339 + if(tooltip.is(':visible')){
2340 + tooltip.find('.pagelayer-list-widget-active:visible').click();
2341 + return;
1415 2342 }
1416 2343
1417 - }
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 + }
1418 2377
1419 - // ctrl+z handle
1420 - if(event.keyCode == 90 && event.ctrlKey){
1421 - pagelayer_do_history('undo');
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');
1422 2450 }
1423 2451
1424 - // ctrl+y handle
1425 - if(event.keyCode == 89 && event.ctrlKey){
1426 - pagelayer_do_history('redo');
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();
1427 2456 }
1428 2457
1429 2458 // ctrl+d handle
1430 2459 if(event.keyCode == 68 && event.ctrlKey){
@@ -1435,33 +2464,292 @@
1435 2464 pagelayer_copy_element('[pagelayer-id='+pagelayer_active.el.id+']');
1436 2465 }
1437 2466
1438 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 +
2679 + // Delete
2680 + if(event.keyCode == 46){
2681 + pagelayer_delete_element('[pagelayer-active]');
2682 + }
2683 +
2684 + // ctrl+z handle
2685 + if(event.keyCode == 90 && event.ctrlKey){
2686 + pagelayer_do_history('undo');
2687 + }
2688 +
2689 + // ctrl+y handle
2690 + if(event.keyCode == 89 && event.ctrlKey){
2691 + pagelayer_do_history('redo');
2692 + }
2693 +
1439 2694 });
1440 2695
1441 2696 // Handle Copy of content
1442 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 + }
1443 2704
1444 - // Check the active element
2705 + if(selectedText.length > 0){
2706 + return;
2707 + }
2708 +
1445 2709 if(pagelayer_active.el && pagelayer_active.el.id){
1446 -
2710 + copyEvent.preventDefault();
2711 +
1447 2712 // Save the active element id
1448 - pagelayer_copy_select("[pagelayer-id='"+pagelayer_active.el.id+"']");
2713 + pagelayer_copy_select("[pagelayer-id='"+pagelayer_active.el.id+"']", copyEvent);
1449 2714
1450 2715 }
1451 2716
1452 2717 });
1453 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 +
1454 2733 // Handle Paste in the editor
1455 2734 jQuery(document).on('paste', function(pasteEvent){
1456 -
2735 +
1457 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 +
1458 2741 var pagelayer_ajax_func = {};
1459 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 + }
1460 2749
1461 - if(pEle_target.closest('[contenteditable]').length > 0 || pEle_target.is('input, textarea')){
1462 - pEle_target = pEle_target.closest('[contenteditable]');
1463 - contenteditable = true;
2750 + if( items.length < 1 || (items.length == 1 && pagelayer_empty(clipboardData.getData(items[0].type))) ){
2751 + pasteWidget = true;
1464 2752 }
1465 2753
1466 2754 // This function for ajax before send call back
1467 2755 pagelayer_ajax_func['beforeSend'] = function(xhr){
@@ -1470,8 +2758,9 @@
1470 2758 if( pagelayer_empty(contenteditable) ){
1471 2759
1472 2760 // If we dont have an active element then return false and stop ajax
1473 2761 if( !(pagelayer_active.el && pagelayer_active.el.id) ){
2762 + pagelayer_show_msg(pagelayer_l('active_ele_paste_msg'));
1474 2763 return false;
1475 2764 }
1476 2765
1477 2766 pagelayer.copy_selected = jQuery('<div pagelayer-tag="pl_image"></div>');
@@ -1497,25 +2786,77 @@
1497 2786 document.execCommand('insertImage', false, obj['data']['url']);
1498 2787
1499 2788 // For our widgets
1500 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 +
1501 2796 var fTo = pagelayer_can_copy_to('[pagelayer-id="'+pagelayer_active.el.id+'"]');
1502 2797 // We need to empty pagelayer.copy_selected
1503 2798 pagelayer.copy_selected = '';
1504 -
1505 - // Create image html
1506 - var html = jQuery( pagelayer_create_sc('pl_image') );
1507 - html.attr('pagelayer-a-id', obj['data']['id']);
1508 - html.attr('pagelayer-tmp-id-url', obj['data']['url']);
1509 2799
1510 - // Copy the element
1511 - var id = pagelayer_copy_element(html, fTo);
1512 - 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 + }
1513 2854 }
1514 2855
1515 2856 // Some error occured
1516 2857 }else{
1517 - alert(obj['data']['message']);
2858 + pagelayer_show_msg(obj['data']['message'], 'error', 10000);
1518 2859 }
1519 2860 }
1520 2861
1521 2862 // This function for ajax complete call back
@@ -1525,20 +2866,36 @@
1525 2866 }
1526 2867
1527 2868 var findImg = pagelayer_editable_paste_handler(pasteEvent, pagelayer_ajax_func);
1528 2869
1529 - if(pagelayer_empty(findImg) && pagelayer_empty(contenteditable)){
2870 + if(pagelayer_empty(findImg) || pasteWidget){
1530 2871
1531 2872 // Check the active element
1532 - if(pagelayer_active.el && pagelayer_active.el.id){
2873 + if(pagelayer_active.el && pagelayer_active.el.id && pagelayer_active.el.tag != 'pl_post_props'){
1533 2874
1534 - var jEle = jQuery("[pagelayer-id='"+pagelayer_active.el.id+"']");
1535 -
1536 - // Check if the any element is copied
1537 - if(pagelayer_can_copy_to(jEle)){
1538 - pagelayer_paste_element("[pagelayer-id='"+pagelayer_active.el.id+"']");
2875 + const text = clipboardData.getData('text');
2876 + var pEle = jQuery(text);
2877 + var getData = true;
2878 +
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 +
1539 2894 }
1540 2895
2896 + }else{
2897 + pagelayer_show_msg(pagelayer_l('no_active_ele_paste'));
1541 2898 }
1542 2899 }
1543 2900 });
1544 2901
@@ -1544,8 +2901,9 @@
1544 2901
1545 2902 // Delete an element as per the selector
1546 2903 function pagelayer_delete_element(selector){
1547 2904 var jEle = jQuery(selector);
2905 + var nearBy = jEle;
1548 2906
1549 2907 // Anything found ?
1550 2908 if(jEle.length > 0){
1551 2909
@@ -1560,8 +2918,10 @@
1560 2918 // Save this element in history action
1561 2919 if(pagelayer.history_action){
1562 2920 var cEle = pagelayer_near_by_ele(id, sc);
1563 2921
2922 + nearBy = jQuery(cEle.cEle);
2923 +
1564 2924 // To save in history, we need to save only element not the wraps as we call setup if we redo or undo
1565 2925 jEle.find('style').remove();
1566 2926 jEle.find('.pagelayer-ele-overlay').remove();
1567 2927
@@ -1576,9 +2936,9 @@
1576 2936 pagelayer_history_action_push({
1577 2937 'title' : pagelayer_shortcodes[sc]['name'],
1578 2938 'action' : 'Deleted',
1579 2939 'pl_id' : id,
1580 - 'html' : jEle,
2940 + 'html' : jEle[0].outerHTML,
1581 2941 'cEle' : cEle
1582 2942 });
1583 2943 }
1584 2944
@@ -1585,28 +2945,93 @@
1585 2945 wrap.remove();
1586 2946
1587 2947 pagelayer_empty_col(par);
1588 2948
1589 - 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)){
1590 2951 pagelayer.$$('.pagelayer-elpd-close').click();
1591 2952 }
1592 2953
1593 2954 }
1594 2955
1595 - pagelayer_isDirty = true;
2956 + // Do Pagelayer dirty
2957 + pagelayer_do_dirty(nearBy);
1596 2958 };
1597 2959
1598 2960 // Select an element
1599 -function pagelayer_copy_select(selector){
2961 +function pagelayer_copy_select(selector, copyEvent = false){
1600 2962
1601 - var eHtml = jQuery(selector)[0].outerHTML;
2963 + var sEle = jQuery(selector);
1602 2964
1603 - // Copy data on localStorage
1604 - localStorage.setItem("pagelayer_ele", eHtml);
2965 + if(sEle.length < 1){
2966 + pagelayer_show_msg( pagelayer_l('invalid_copy_ele_msg'));
2967 + return;
2968 + }
1605 2969
1606 - pagelayer.copy_selected = selector;
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 +
1607 2999 }
1608 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 +
1609 3034 function pagelayer_can_copy_to(to){
1610 3035 var jEle = jQuery(pagelayer.copy_selected);
1611 3036 var tEle = jQuery(to);
1612 3037
@@ -1612,8 +3037,14 @@
1612 3037
1613 3038 var eTag = pagelayer_tag(jEle);
1614 3039 var tTag = pagelayer_tag(tEle);
1615 3040 //console.log(eTag+' - '+tTag);
3041 +
3042 + // Invalid HTML copied
3043 + if(pagelayer_empty(eTag)){
3044 + return false;
3045 + }
3046 +
1616 3047 // Final to
1617 3048 var fTo;
1618 3049
1619 3050 // Selected element is a Row, can go only after a row
@@ -1639,12 +3070,25 @@
1639 3070
1640 3071 }
1641 3072
1642 3073 // Select an element
1643 -function pagelayer_paste_element(to){
3074 +function pagelayer_paste_element(to, syncClipboard = true){
1644 3075
1645 - // Copy data from localStorage
1646 - pagelayer_copy_from_localStorage();
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 + }
1647 3091
1648 3092 var fTo = pagelayer_can_copy_to(to);
1649 3093
1650 3094 // Is it a valid to
@@ -1653,20 +3097,49 @@
1653 3097 }
1654 3098
1655 3099 if(!pagelayer_empty(pagelayer.copy_selected)){
1656 3100 pagelayer_copy_element(pagelayer.copy_selected, fTo);
3101 + return true;
1657 3102 }
1658 3103
3104 + pagelayer_show_msg(pagelayer_l('no_copied'));
3105 +
1659 3106 return false;
1660 -
1661 3107 }
1662 3108
3109 +var pagelayerClipboardLoading = false;
3110 +var pagelayerClipboardReadable = true;
1663 3111 // If copy_selected is empty then copy data from localStorage
1664 -function pagelayer_copy_from_localStorage(){
1665 - if(!pagelayer_empty(localStorage.getItem("pagelayer_ele"))){
1666 - // Set copy data from localStorage
1667 - pagelayer.copy_selected = localStorage.getItem("pagelayer_ele");
3112 +async function pagelayer_copy_from_clipboard(){
3113 +
3114 + if(pagelayerClipboardLoading){
3115 + return;
1668 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 + }
1669 3142 }
1670 3143
1671 3144 // Copy an element
1672 3145 // Note : insertAfter should always be an pagelayer-ele
@@ -1671,28 +3144,14 @@
1671 3144 // Copy an element
1672 3145 // Note : insertAfter should always be an pagelayer-ele
1673 3146 function pagelayer_copy_element(selector, insertAfter){
1674 3147 var src = jQuery(selector);
1675 - var html = src[0].outerHTML;
1676 3148 var tag = pagelayer_tag(src);
1677 3149 insertAfter = insertAfter || src;
1678 3150 insertAfter = insertAfter.parent();
1679 3151
1680 - var jEle = jQuery(html);
1681 - jEle.removeAttr('pagelayer-id');
1682 - jEle.find('[pagelayer-id]').removeAttr('pagelayer-id');
1683 - jEle.find('[pagelayer-parent]').removeAttr('pagelayer-parent');// Remove the parent attribute as it will be reset during pagelayer_element_setup
1684 - jEle.find('style').remove();
1685 - jEle.find('.pagelayer-ele-overlay').remove();
3152 + var jEle = pagelayer_element_unsetup(src);
1686 3153
1687 - // Unwrap the wraps
1688 - jEle.find('.pagelayer-ele').each(function (){
1689 - var ele = jQuery(this);
1690 - if(ele.parent().is('.pagelayer-ele-wrap')){
1691 - ele.unwrap();
1692 - }
1693 - });
1694 -
1695 3154 // Give it an ID
1696 3155 var id = pagelayer_assign_id(jEle);
1697 3156
1698 3157 jQuery(insertAfter).after(jEle);
@@ -1698,8 +3157,12 @@
1698 3157 jQuery(insertAfter).after(jEle);
1699 3158
1700 3159 pagelayer_element_setup('[pagelayer-id='+id+'], [pagelayer-id='+id+'] .pagelayer-ele', true);
1701 3160
3161 + if(pagelayer_is_group(tag)){
3162 + pagelayer_sc_render(jEle);
3163 + }
3164 +
1702 3165 // Save this element in history action
1703 3166 if(pagelayer.history_action){
1704 3167 var cEle = pagelayer_near_by_ele(id, tag);
1705 3168 pagelayer_history_action_push({
@@ -1705,9 +3168,9 @@
1705 3168 pagelayer_history_action_push({
1706 3169 'title' : pagelayer_shortcodes[tag]['name'],
1707 3170 'action' : 'Copied',
1708 3171 'pl_id' : id,
1709 - 'html' : jEle,
3172 + 'html' : jEle[0].outerHTML,
1710 3173 'cEle' : cEle
1711 3174 });
1712 3175 }
1713 3176
@@ -1716,15 +3179,314 @@
1716 3179 var row = src.parent().closest('.pagelayer-row');
1717 3180 pagelayer_renumber_col(row);
1718 3181 }
1719 3182
1720 - pagelayer_isDirty = true;
3183 + pagelayer_do_dirty(jEle);
1721 3184
1722 3185 return id;
1723 3186 };
1724 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 +
1725 3484 // Language key
1726 3485 function pagelayer_l(k){
3486 + if(k in pagelayer_lang){
3487 + return pagelayer_lang[k];
3488 + }
1727 3489 return k;
1728 3490 }
1729 3491
1730 3492 // Get props based on the tag
@@ -1732,8 +3494,51 @@
1732 3494 var props = pagelayer_shortcodes[pagelayer_tag(jEle)];
1733 3495 return props;
1734 3496 }
1735 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 +
1736 3541 // Set the given jELE as active
1737 3542 function pagelayer_set_active(jEle){
1738 3543
1739 3544 // Make all other element as inactive
@@ -1748,14 +3553,8 @@
1748 3553 jQuery('.pagelayer-active').removeClass('pagelayer-active');
1749 3554
1750 3555 jEle.parent().children('.pagelayer-ele-overlay').addClass('pagelayer-active');
1751 3556
1752 - // Hide active when not supported by tag
1753 - var props = pagelayer_get_props(jEle);
1754 - if(!pagelayer_empty(props['hide_active'])){
1755 - jEle.parent().children('.pagelayer-ele-overlay').addClass('pagelayer-hide-active');
1756 - }
1757 -
1758 3557 }
1759 3558
1760 3559 function pagelayer_sc(sc){
1761 3560 return sc.replace('pl_', '');
@@ -1837,16 +3636,88 @@
1837 3636
1838 3637 return jEle.attr('pagelayer-tag');
1839 3638 }
1840 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 +
1841 3704 // Gets a single attribute value
1842 3705 function pagelayer_get_att(jEle, att){
1843 - 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;
1844 3711 };
1845 3712
1846 3713 // Gets a single attribute value
1847 3714 function pagelayer_get_tmp_att(jEle, att){
1848 - 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;
1849 3720 };
1850 3721
1851 3722 // This function will just set atts and not do anything else
1852 3723 // Atts can be string or object. If its string, then val is needed
@@ -1906,10 +3777,25 @@
1906 3777 if('no_val' in props[x]){
1907 3778 no_val[x] = 1;
1908 3779 }
1909 3780
1910 - if('req' in props[x] || 'show' in props[x]){
3781 + if('req' in props[x] || 'show' in props[x]){
1911 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 +
1912 3798 for(var showParam in show){
1913 3799 var val = show[showParam];
1914 3800 var except = showParam.substr(0, 1) == '!' ? true : false;
1915 3801 showParam = except ? showParam.substr(1) : showParam;
@@ -1923,8 +3809,10 @@
1923 3809 }
1924 3810
1925 3811 }
1926 3812
3813 + var ref_data = pagelayer_el_data_ref(jEle);
3814 +
1927 3815 for(var x in atts){
1928 3816
1929 3817 // Are we to trigger change
1930 3818 if(x in trigger_props){
@@ -1933,9 +3821,9 @@
1933 3821
1934 3822 //console.log(x+'-'+atts[x]);
1935 3823
1936 3824 // Is this a pro feature and we are not pro ? Then we dont do anything and continue !
1937 - if('pro' in _props[x] && pagelayer_empty(pagelayer_pro)){
3825 + if(!pagelayer_empty(_props[x]) && 'pro' in _props[x] && pagelayer_empty(pagelayer_pro)){
1938 3826 continue;
1939 3827 }
1940 3828
1941 3829 if(x in no_val){
@@ -1945,11 +3833,17 @@
1945 3833
1946 3834 // Record History
1947 3835 if(pagelayer.history_action){
1948 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'];
3841 + }
3842 +
1949 3843 pagelayer_history_action_push({
1950 3844 'title' : all_props['name'],
1951 - 'subTitle' : _props[x]['label'],
3845 + 'subTitle' : label,
1952 3846 'action' : 'Edited',
1953 3847 'attrType' : 'a_attr',
1954 3848 'pl_id' : pagelayer_id(jEle),
1955 3849 'atts' : x,
@@ -1956,40 +3850,27 @@
1956 3850 'oldVal' : old_val,
1957 3851 'newVal' : atts[x]
1958 3852 });
1959 3853 }
1960 -
3854 +
1961 3855 // Remove the attribute if its BLANK and there is no default for it
1962 3856 // If there is a default, we set it to blank to keep record of the current val
1963 - if(atts[x].length < 1){
3857 + if(pagelayer_length(atts[x]) < 1){
1964 3858
1965 - // Dont remove the value as there is a default
3859 + // Remove values which are not defaults
1966 3860 if(!(x in defaults)){
1967 - jEle.removeAttr('pagelayer-a-'+x);
1968 - // Otherwise blank it
3861 + delete ref_data['attr'][x];
3862 + // Otherwise keep value set for avoiding resetting
1969 3863 }else{
1970 - jEle.attr('pagelayer-a-'+x, atts[x]);
3864 + ref_data['attr'][x] = atts[x];
1971 3865 }
1972 3866
1973 3867 // Remove the tmp atts anyway
1974 - var to_del = new Array();
1975 - var regexp = new RegExp('pagelayer\-tmp\-'+x, 'gi');
1976 -
1977 - jQuery.each(jEle[0].attributes, function(index, att){
1978 - if(!att) return;
1979 - if(att.name.match(regexp)){
1980 - to_del.push(att.name);
1981 - }
1982 - });
1983 -
1984 - //console.log(to_del);
1985 - for(var n in to_del){
1986 - jEle.removeAttr(to_del[n]);
1987 - }
3868 + pagelayer_clear_tmp_atts(jEle, x);
1988 3869
1989 3870 // Set the value
1990 3871 }else{
1991 - jEle.attr('pagelayer-a-'+x, atts[x]);
3872 + ref_data['attr'][x] = pagelayer_trim(atts[x]);
1992 3873 }
1993 3874
1994 3875 // Are you the active element
1995 3876 if(pagelayer_is_active(jEle)){
@@ -1999,14 +3880,17 @@
1999 3880 }
2000 3881
2001 3882 }
2002 3883
3884 + pagelayer_el_dump_data(jEle);
3885 +
2003 3886 // Trigger the change of the parameter and show the required properties
2004 3887 if(trigger_onchange){
2005 3888 pagelayer_elpd_show_rows();
2006 3889 }
2007 3890
2008 - pagelayer_isDirty = true;
3891 + pagelayer_do_dirty(jEle);
3892 +
2009 3893 };
2010 3894
2011 3895 // This function will just set atts and not do anything else
2012 3896 // Atts can be string or object. If its string, then val is needed
@@ -2021,10 +3905,12 @@
2021 3905 if(typeof atts != 'object'){
2022 3906 return false;
2023 3907 }
2024 3908
3909 + var ref_data = pagelayer_el_data_ref(jEle);
3910 +
2025 3911 for(var x in atts){
2026 -
3912 +
2027 3913 // Record history
2028 3914 if(pagelayer.history_action){
2029 3915
2030 3916 var old_val = pagelayer_get_tmp_att(jEle, x) || '';
@@ -2039,27 +3925,51 @@
2039 3925 'newVal' : atts[x]
2040 3926 });
2041 3927
2042 3928 }
2043 -
2044 - jEle.attr('pagelayer-tmp-'+x, atts[x]);
3929 +
3930 + ref_data['tmp'][x] = atts[x];
3931 +
2045 3932 }
2046 3933
3934 + pagelayer_el_dump_data(jEle);
3935 +
2047 3936 };
2048 3937
2049 -// Set the att and classes of an HTML which is not yet created
2050 -function pagelayer_sc_atts(classes, atts){
3938 +// This function removes the temporary attributes of an ele
3939 +function pagelayer_clear_tmp_atts(jEle, attr){
2051 3940
2052 - if(typeof atts != 'object'){
2053 - 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 + }
2054 3950 }
3951 +}
3952 +
3953 +// This function removes the temporary attributes of an ele
3954 +function pagelayer_img_tmp_atts(jEle, attr){
2055 3955
2056 - var r = new Array();
3956 + var found = {};
3957 + var regexp = new RegExp('^'+attr+'\-', 'gi');
3958 + var ref_data = pagelayer_el_data_ref(jEle);
2057 3959
2058 - for(var x in atts){
2059 - 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 + }
2060 3964 }
2061 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();
2062 3972 return 'class="'+classes+' pagelayer-ele" '+r.join(' ');
2063 3973 }
2064 3974
2065 3975 // Is the jEle the active element ?
@@ -2085,16 +3995,33 @@
2085 3995
2086 3996 // Seperator
2087 3997 seperator = seperator || ',';
2088 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 +
2089 4012 // Replace the val
2090 - css = css.split('{{val}}').join(val);
4013 + css = replaceCss(css, val, '{{val}}');
2091 4014
2092 4015 // If there is an array
2093 4016 if(css.match(/val\[\d/)){
2094 - val = val.split(seperator);
4017 +
4018 + if(typeof val != 'object' || val === null){
4019 + val = String(val).split(seperator);
4020 + }
4021 +
2095 4022 for(var i in val){
2096 - css = css.split('{{val['+i+']}}').join(val[i]);
4023 + css = replaceCss(css, val[i], '{{val['+i+']}}');
2097 4024 }
2098 4025 }
2099 4026
2100 4027 //console.log('Final CSS '+css);
@@ -2102,12 +4029,32 @@
2102 4029 return css;
2103 4030
2104 4031 };
2105 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 +
2106 4053 // Replace the variables
2107 4054 function pagelayer_parse_el_vars(str, el){
2108 4055
2109 - str = str.split('{{element}}').join(el.CSS.sel);
4056 + str = str.split('{{element}}').join(el.CSS.cssSel);
2110 4057 str = str.split('{{wrap}}').join(el.CSS.wrap);
2111 4058 str = str.split('{{ele_id}}').join(el.id);
2112 4059
2113 4060 return str;
@@ -2148,8 +4095,9 @@
2148 4095 attr: [],
2149 4096 remove_attr: [],
2150 4097 css: [],
2151 4098 edit: [],
4099 + cssSel: '.p-'+el.id,
2152 4100 sel: '[pagelayer-id="'+el.id+'"]',
2153 4101 wrap: '[pagelayer-wrap-id="'+el.id+'"]'
2154 4102 };
2155 4103
@@ -2154,8 +4102,11 @@
2154 4102 };
2155 4103
2156 4104 // Create a reference
2157 4105 el.CSS = elCSS;
4106 +
4107 + // Make sure if we have the class selector
4108 + el.$.addClass('p-'+el.id);
2158 4109
2159 4110 //console.log(el.atts);
2160 4111
2161 4112 for(var i in pagelayer_tabs){
@@ -2169,10 +4120,10 @@
2169 4120
2170 4121 // pagelayer_data will return attributes even if they are BLANK e.g. attr=""
2171 4122 // Render doesnt consider BLANK values as values, and we are unsetting them now
2172 4123 // If in any situation you need to consider blank values, please handle in the JS / PHP function of the Shortcode
2173 - if(x in el.atts && el.atts[x].length < 1){
2174 - delete el.atts[x];
4124 + if(x in el.atts && pagelayer_length(el.atts[x]) < 1){
4125 + delete el.atts[x];
2175 4126 }
2176 4127
2177 4128 // Any editor ?
2178 4129 if('edit' in props[x]){
@@ -2178,8 +4129,59 @@
2178 4129 if('edit' in props[x]){
2179 4130 elCSS.edit.push({prop: x, sel: props[x]['edit']});
2180 4131 }
2181 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 +
2182 4184 // Do we have a addClass ?
2183 4185 // We are checking before the element has a value so that we can add or remove the class
2184 4186 if('addClass' in props[x]){
2185 4187
@@ -2214,9 +4216,9 @@
2214 4216 }
2215 4217
2216 4218 }else{
2217 4219
2218 - var tmp = {'sel': tSel, 'val': addClasses[c]};
4220 + var tmp = {'sel': tSel, 'val': addClasses[c].replace('{{val}}', el.atts[x])};
2219 4221
2220 4222 // If the value is there
2221 4223 if(x in el.atts){
2222 4224 elCSS['classes'].push(tmp);
@@ -2269,8 +4271,9 @@
2269 4271 }
2270 4272
2271 4273 // Screen modes
2272 4274 var modes = {desktop: '', tablet: '_tablet', mobile: '_mobile'};
4275 + var desk_global = (props[x]['type'] == 'typography') ? pagelayer_is_global_typo(el.atts[x]) : '';
2273 4276
2274 4277 for(var m in modes){
2275 4278
2276 4279 var xm = x+modes[m];
@@ -2275,12 +4278,37 @@
2275 4278
2276 4279 var xm = x+modes[m];
2277 4280
2278 4281 // If the value is there
2279 - if(!(xm in el.atts)){
4282 + if(!(xm in el.atts) && pagelayer_empty(desk_global)){
2280 4283 continue;
2281 4284 }
2282 -
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 +
2283 4311 for(var c in css){
2284 4312
2285 4313 // The selector
2286 4314 var tSel = jQuery.isNumeric(c) ? '{{element}}' : c;
@@ -2285,20 +4313,20 @@
2285 4313 // The selector
2286 4314 var tSel = jQuery.isNumeric(c) ? '{{element}}' : c;
2287 4315 var tmp = {
2288 4316 sel: tSel,
2289 - val: pagelayer_css_render(css[c], el.atts[xm], (props[x].sep || ',')),
4317 + val: pagelayer_css_render(css[c], xm_val, (props[x].sep || ',')),
2290 4318 };
2291 4319
2292 4320 // Is this a tablet
2293 4321 if(m == 'tablet'){
2294 - 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;
2295 4323 tmp.val = tmp.val+'}';
2296 4324 }
2297 4325
2298 4326 // Is this a mobile mode ?
2299 4327 if(m == 'mobile'){
2300 - tmp.sel = '@media (max-width: 360px){'+tmp.sel;
4328 + tmp.sel = '@media (max-width: '+ pagelayer_settings['mobile_breakpoint'] +'px){'+tmp.sel;
2301 4329 tmp.val = tmp.val+'}';
2302 4330 }
2303 4331
2304 4332 // Push to store
@@ -2316,9 +4344,16 @@
2316 4344 }
2317 4345
2318 4346 // If there is an HTML, then process it
2319 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')];
2320 4351
4352 + if(typeof fn == 'function'){
4353 + fn(el);
4354 + }
4355 +
2321 4356 el.iHTML = jQuery('<div>'+pagelayer_shortcodes[el.tag]['html']+'</div>');
2322 4357
2323 4358 // Lets process the 'if-ext'
2324 4359 el.iHTML.find('[if-ext]').each(function (){
@@ -2346,16 +4381,9 @@
2346 4381 $j.remove();
2347 4382 }
2348 4383
2349 4384 });
2350 -
2351 - // Is there a function to render ?
2352 - var fn = window['pagelayer_render_'+jEle.attr('pagelayer-tag')];
2353 4385
2354 - if(typeof fn == 'function'){
2355 - fn(el);
2356 - }
2357 -
2358 4386 //console.log(el.atts);
2359 4387
2360 4388 // Parse the variables
2361 4389 var new_html = pagelayer_parse_vars(el.iHTML.html(), el);
@@ -2412,9 +4440,9 @@
2412 4440 for(var c in elCSS.edit){
2413 4441 var prop = elCSS.edit[c]['prop'];
2414 4442 var tSel = elCSS.edit[c]['sel'];
2415 4443 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2416 - node.attr('pagelayer-editable', prop);
4444 + node.attr({'pagelayer-editable': prop, 'contenteditable' : 'true'});
2417 4445 }
2418 4446
2419 4447 }
2420 4448
@@ -2426,9 +4454,9 @@
2426 4454 if(elCSS.classes.length > 0){
2427 4455 //console.log(elCSS.classes);
2428 4456
2429 4457 for(var c in elCSS.classes){
2430 - var tSel = elCSS.classes[c]['sel'];
4458 + var tSel = elCSS.classes[c]['sel'].replace('{{element}}', '');
2431 4459 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2432 4460 if(!node.hasClass(elCSS.classes[c]['val'])){
2433 4461 node.addClass(elCSS.classes[c]['val']);
2434 4462 }
@@ -2439,9 +4467,9 @@
2439 4467 if(elCSS.remove_classes.length > 0){
2440 4468 //console.log(elCSS.remove_classes);
2441 4469
2442 4470 for(var c in elCSS.remove_classes){
2443 - var tSel = elCSS.remove_classes[c]['sel'];
4471 + var tSel = elCSS.remove_classes[c]['sel'].replace('{{element}}', '');
2444 4472 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2445 4473 if(node.hasClass(elCSS.remove_classes[c]['val'])){
2446 4474 node.removeClass(elCSS.remove_classes[c]['val']);
2447 4475 }
@@ -2458,9 +4486,9 @@
2458 4486
2459 4487 for(var c in elCSS.attr){
2460 4488 var tSel = elCSS.attr[c]['sel'].replace('{{element}}', '');
2461 4489 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2462 - var att = elCSS.attr[c]['val'].split('=');
4490 + var att = elCSS.attr[c]['val'].split(/=(.*)/);
2463 4491 att[1] = pagelayer_parse_vars(att[1], el);
2464 4492 att[1] = pagelayer_trim(att[1], '"');
2465 4493
2466 4494 // Is it the same val ?
@@ -2504,9 +4532,9 @@
2504 4532
2505 4533 // Loop
2506 4534 for(var c in elCSS.css){
2507 4535 var tSel = pagelayer_parse_el_vars(elCSS.css[c]['sel'], el);
2508 - var rule = pagelayer_parse_vars(elCSS.css[c]['val'], el);
4536 + var rule = elCSS.css[c]['val'];
2509 4537 if(tSel.length > 0){
2510 4538 rules.push(tSel+'{'+rule+'}');
2511 4539 }else{
2512 4540 rules.push(pagelayer_parse_el_vars(rule, el));
@@ -2515,15 +4543,16 @@
2515 4543
2516 4544 // CSS Selector overide
2517 4545 if(!pagelayer_empty(all_props['overide_css_selector'])){
2518 4546 for(var r in rules){
2519 - rules[r] = rules[r].split(el.CSS.sel).join(all_props['overide_css_selector']);
2520 - rules[r] = rules[r].split(el.CSS.wrap).join(all_props['overide_css_selector']);
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);
2521 4550 }
2522 4551 }
2523 4552
2524 4553 // Set the style
2525 - style.html(rules.join("\n"));
4554 + style.html(pagelayer_parse_vars(rules.join("\n"), el));
2526 4555 //console.log(style);
2527 4556 }else{
2528 4557 style.remove();
2529 4558 }
@@ -2536,14 +4565,150 @@
2536 4565 }
2537 4566
2538 4567 // If the element have any parent
2539 4568 var par = pagelayer_get_parent(jEle);
4569 + var eleId = el.id;
4570 +
2540 4571 if(par){
4572 + eleId = par;
2541 4573 pagelayer_sc_render(pagelayer_ele_by_id(par));
2542 4574 }
2543 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 +
2544 4595 };
2545 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 +
2546 4711 // Is the given tag a group
2547 4712 function pagelayer_is_group(tag){
2548 4713
2549 4714 if('has_group' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['has_group'])){
@@ -2554,10 +4719,10 @@
2554 4719
2555 4720 }
2556 4721
2557 4722 // Do action / event
2558 -function pagelayer_trigger_action(act){
2559 - jQuery(document).trigger(act);
4723 +function pagelayer_trigger_action(act, param = []){
4724 + jQuery(document).trigger(act, param);
2560 4725 }
2561 4726
2562 4727 // Perform a function on an action / event
2563 4728 function pagelayer_add_action(act, func){
@@ -2563,50 +4728,298 @@
2563 4728 function pagelayer_add_action(act, func){
2564 4729 jQuery(document).on(act, func);
2565 4730 }
2566 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 +
2567 4910 // Save the post
2568 4911 function pagelayer_save(){
2569 4912
4913 + // hiding and showing loading animation
4914 + pagelayer.$$('.pagelayer-update-text').hide();
4915 + pagelayer.$$('.pagelayer-update-loader').show();
4916 +
2570 4917 pagelayer_trigger_action('pagelayer_save');
2571 4918
2572 4919 var pagelayerajaxurl = pagelayer_ajax_url+'&action=pagelayer_save_content&postID='+pagelayer_postID;
2573 4920 var post = pagelayer_generate_sc(pagelayer_editable);//alert(post);return;
2574 4921
2575 - // Do we have page properties ?
2576 - var jEle = jQuery(pagelayer_editable+' [pagelayer-tag=pl_post_props]');
2577 - var props = {};
2578 - if(jEle.length > 0){
2579 - var tmp = pagelayer_data(jEle);
2580 - //console.log(props);
2581 - props = tmp.atts;
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'];
2582 4933 }
4934 +
4935 + // Do we have contact templates ?
4936 + var contacts_props = pagelayer_get_contact_templates();
2583 4937
2584 - jQuery.ajax({
2585 - type: "POST",
2586 - url: pagelayerajaxurl,
2587 - data: {
2588 - pagelayer_update_content : post,
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),
2589 4953 pagelayer_nonce: pagelayer_ajax_nonce,
2590 - page_props: props
2591 - },
2592 - success: function(response, status, xhr){
2593 - //alert(data);
2594 - var obj = jQuery.parseJSON(response);
2595 - //alert(obj);
2596 - if(obj['error']){
2597 - alert(obj['error']);
2598 - }else{
2599 - pagelayer_isDirty = false;
2600 - alert(obj['success']);
2601 - pagelayer_get_revision();
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 + }
2602 5011 }
2603 - },
2604 - error: function(errorThrown){
2605 - console.log(errorThrown);
2606 - }
2607 - });
5012 + });
5013 + }
2608 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();
2609 5022 };
2610 5023
2611 5024 //Close the Editor
2612 5025 function pagelayer_close(){
@@ -2619,18 +5032,30 @@
2619 5032 }else{
2620 5033 window.top.location.href = pagelayer_returnURL;
2621 5034 }
2622 5035 };
5036 +
5037 +function pagelayer_htmlEntities(str) {
5038 + return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
5039 +}
2623 5040
2624 -// Generate Shortcode Post to save
2625 -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){
2626 5052
5053 + selfEle = selfEle || false;
2627 5054 var txt = '';
2628 5055
2629 - jQuery(selector).children(".pagelayer-ele-wrap").each(function(){
5056 + var generate_sc_single = function(jEle){
2630 5057
2631 - var jEle = jQuery(this).children('.pagelayer-ele');
2632 -
2633 5058 // The ID
2634 5059 var id = jEle.attr('pagelayer-id');
2635 5060
2636 5061 // If there is an Add element wrapper
@@ -2640,14 +5065,26 @@
2640 5065
2641 5066 // Find the type of tag
2642 5067 var tag = jEle.attr('pagelayer-tag');
2643 5068 var final_tag = tag;
2644 - var closestEle = jQuery(this).closest('.pagelayer-col-holder');
5069 + var closestEle = jEle.closest('.pagelayer-col-holder');
2645 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 +
2646 5076 // Define inner row | Note : Commented as we now have a new widget of type inner_row
2647 5077 /*if(tag == 'pl_row' && closestEle.length > 0 && closestEle.closest(pagelayer_editable).length > 0){
2648 5078 final_tag = 'pl_inner_row';
2649 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 + }
2650 5087
2651 5088 // Define inner column
2652 5089 if(tag == 'pl_col' && closestEle.length > 0 && closestEle.closest(pagelayer_editable).length > 0){
2653 5090 final_tag = 'pl_inner_col';
@@ -2659,44 +5096,33 @@
2659 5096 if('innerHTML' in pagelayer_shortcodes[tag]){
2660 5097 inner = pagelayer_shortcodes[tag]['innerHTML'];
2661 5098 }
2662 5099
5100 + // Data reference
5101 + var ref_data = pagelayer_el_data_ref(jEle);
5102 +
2663 5103 // Create the tag
2664 - var data = '['+final_tag;
5104 + var data = JSON.parse(JSON.stringify(ref_data['attr']));
2665 5105
2666 - // Get the attributes to store
2667 - jQuery.each(jEle[0].attributes, function(i, attrib){
2668 - var res = attrib.name.match(/^pagelayer-a-(.+)/i);
2669 - if(res && res[1] != inner){
2670 - //console.log(attrib.name+' '+res[1]);
2671 - data += ' '+res[1]+'="'+pagelayer_escapeHTML(attrib.value)+'"';
2672 - }
2673 - });
5106 + data['pagelayer-id'] = id;
5107 + data = pagelayer_serializeAttributes(data);
5108 +
5109 + var content = '';
2674 5110
2675 - data = data+']';
2676 -
2677 - // Add to the text
2678 - txt = txt+data+"\n";
2679 -
2680 5111 // Any internal function to handle the save ?
2681 5112 var func = window['pagelayer_tag_'+tag];
2682 5113 if(typeof func == 'function'){
2683 5114
2684 - var content = '';
2685 5115 content = func(jEle);
2686 5116
2687 - if(content.length > 0){
2688 - txt = txt+content;
2689 - }
2690 -
2691 5117 // If its a Row or Column or Group then it will have children
2692 5118 }else if(jEle.hasClass('pagelayer-row') || jEle.hasClass('pagelayer-col') || jEle.hasClass('pagelayer-inner_row') || pagelayer_is_group(tag)){
2693 5119
2694 - var sel = "[pagelayer-id="+id+"]";
5120 + var sel = jEle;
2695 5121
2696 5122 // Any holder which holds children ?
2697 5123 if('holder' in pagelayer_shortcodes[tag]){
2698 - sel = sel+' '+pagelayer_shortcodes[tag]['holder'];
5124 + sel = jEle.find(pagelayer_shortcodes[tag]['holder']);
2699 5125 }
2700 5126
2701 5127 // Select the top-most element
2702 5128 sel = jQuery(sel).first();
@@ -2704,22 +5130,27 @@
2704 5130 // Any child selector - Majorly for owl carousel
2705 5131 // NOTE : Child selector should be very specific with immediate child selection at all levels
2706 5132 var child_selector = false;
2707 5133 if('child_selector' in pagelayer_shortcodes[tag]){
2708 - 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 + }
2709 5139 }
2710 -
2711 - var childrens = pagelayer_generate_sc(sel);
2712 - if(childrens.length > 0){
2713 - 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;
2714 5146 }
2715 5147
2716 5148 // Its a normal element so we might need to handle the content
2717 5149 }else{
2718 5150
2719 - var content = '';
2720 5151 if(inner.length > 0){
2721 - content = jEle.attr('pagelayer-a-'+inner);
5152 + content = pagelayer_get_att(jEle, inner);
2722 5153 if(!content){
2723 5154 content = '';
2724 5155 }
2725 5156 }else{
@@ -2725,74 +5156,45 @@
2725 5156 }else{
2726 5157 content = '';//jEle.html();
2727 5158 }
2728 5159
2729 - if(content.length > 0){
2730 - txt = txt+content;
2731 - }
2732 -
2733 5160 }
2734 5161
2735 - // Close the tag
2736 - 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 + }
2737 5167
2738 - });
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 + };
2739 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 +
2740 5193 return txt;
2741 5194
2742 5195 };
2743 5196
2744 -// Escape charaters in attributes
2745 -var pagelayer_escapeChars = {
2746 - '\\]' : '#93',
2747 - '\\[' : '#91',
2748 - //'=' : '#61',
2749 - '<' : 'lt',
2750 - '>' : 'gt',
2751 - '"' : 'quot',
2752 - //'&' : 'amp',
2753 - '\'' : '#39'
2754 -};
2755 -
2756 -// To unescape
2757 -var pagelayer_unescapeChars = {
2758 - '#93' : ']',
2759 - '#91' : '[',
2760 - //'#61' : '=',
2761 - 'lt' : '<',
2762 - 'gt' : '>',
2763 - 'quot' : '"',
2764 - //'amp' : '&',
2765 - '#39' : '\''
2766 -};
2767 -
2768 -var pagelayer_escaperegex_S = '[';
2769 -for(var key in pagelayer_escapeChars) {
2770 - pagelayer_escaperegex_S += key;
2771 -}
2772 -pagelayer_escaperegex_S += ']';
2773 -
2774 -var pagelayer_escaperegex = new RegExp( pagelayer_escaperegex_S, 'g');
2775 -
2776 -// The function which escapes everything
2777 -function pagelayer_escapeHTML(str) {
2778 - return str.replace(pagelayer_escaperegex, function(m) {
2779 - if(m == '[' || m == ']') m = '\\'+m;
2780 - return '&' + pagelayer_escapeChars[m] + ';';
2781 - });
2782 -};
2783 -
2784 -// This will unescape everything
2785 -function pagelayer_unescapeHTML(str){
2786 - return str.replace(/\&([^;]+);/g, function (entity, entityCode) {
2787 - if(entityCode in pagelayer_unescapeChars){
2788 - return pagelayer_unescapeChars[entityCode];
2789 - }else{
2790 - return entity;
2791 - }
2792 - });
2793 -};
2794 -
2795 5197 // Show the required leftbar tab
2796 5198 function pagelayer_leftbar_tab(tab){
2797 5199 pagelayer.$$('.pagelayer-leftbar-tab').hide();
2798 5200 pagelayer.$$('#'+tab).show();
@@ -2819,17 +5221,27 @@
2819 5221
2820 5222 var html = '<div class="pagelayer-leftbar">'+
2821 5223 '<div class="pagelayer-leftbar-scroll">'+
2822 5224 '<div id="pagelayer-shortcodes" class="pagelayer-leftbar-tab pagelayer-shortcodes">'+
2823 - '<div class="pagelayer-leftbar-search">'+
2824 - '<i class="pli pli-search" /><input class="pagelayer-search-field" /><i class="pagelayer-sf-empty pli">&times;</i>'+
2825 - '</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>';
2826 5234
2827 5235 for(var x in pagelayer_groups){
2828 5236
2829 5237 // Title
2830 - 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';
2831 5241
5242 + html += '<div class="pagelayer-leftbar-group pagelayer-group-name-'+x+'"><h5>'+group_title+'</h5>';
5243 +
2832 5244 // Indivdual icon
2833 5245 for(var y in pagelayer_groups[x]){
2834 5246
2835 5247 var sc = pagelayer_groups[x][y];
@@ -2859,13 +5271,16 @@
2859 5271
2860 5272 }
2861 5273
2862 5274 html += '</div>'+
5275 + '<div id="pagelayer-global-widget" class="pagelayer-hidden pagelayer-global-widget"></div>'+
5276 + '</div>'+
2863 5277 '<div id="pagelayer-elpd" class="pagelayer-leftbar-tab pagelayer-elpd"></div>'+
2864 5278 '<div id="pagelayer-options" class="pagelayer-leftbar-tab pagelayer-options"></div>'+
2865 5279 '<div id="pagelayer-history" class="pagelayer-leftbar-tab pagelayer-history"></div>'+
2866 5280 '<div id="pagelayer-post-settings" class="pagelayer-leftbar-tab pagelayer-post-settings"></div>'+
2867 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>'+
2868 5283 '</div>'+
2869 5284 '</div>';
2870 5285
2871 5286 pagelayer.$$('.pagelayer-leftbar-holder').prepend(html);
@@ -2914,40 +5329,170 @@
2914 5329 });
2915 5330 });
2916 5331
2917 5332 // On click Pagelayer setting icon
2918 - pagelayer.$$('.pagelayer-settings-icon').click(function(){
2919 - pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text('Post Settings');
2920 - pagelayer.$$('.pagelayer-logo').hide();
2921 - pagelayer_leftbar_tab('pagelayer-post-settings');
5333 + pagelayer.$$('.pagelayer-settings-icon, .pagelayer-settings').click(function(event){
2922 5334 pagelayer_active = {};
2923 - 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 +
2924 5341 });
2925 5342
5343 + // Pagelayer post advance setting modal handler
5344 + var propsModal = pagelayer.$$('.pagelayer-props-modal');
5345 + propsModal.find('.pagelayer-props-modal-close').on('click', function(event){
5346 + propsModal.hide();
5347 + });
5348 +
5349 + propsModal.on('click', function(event){
5350 + var target = jQuery(event.target);
5351 +
5352 + if(target.closest('.pagelayer-props-modal-wrap').length > 0){
5353 + return;
5354 + }
5355 +
5356 + propsModal.hide();
5357 + });
5358 +
5359 +
5360 + // On click Pagelayer setting icon
5361 + var global_widget_list = function(){
5362 +
5363 + var gHtml = '';
5364 +
5365 + if(pagelayer_empty(pagelayer_pro)){
5366 + gHtml += '<div class="pagelayer-global-widget-pro">'+pagelayer.pro_txt+
5367 + '<p>Using this feature, you can save the widgets globally and use them on the entire site. The global widget will be editable from one place.</p>'+
5368 + '</div>';
5369 +
5370 + pagelayer.$$('#pagelayer-global-widget').html(gHtml);
5371 + return;
5372 + }
5373 +
5374 + gHtml += '<div class="pagelayer-global-widget-shortcodes">'+
5375 + '<div class="pagelayer-leftbar-search">'+
5376 + '<i class="pli pli-search" ></i><input class="pagelayer-search-field" /><i class="pagelayer-sf-empty pli">&times;</i>'+
5377 + '</div>'+
5378 + '<div class="pagelayer-leftbar-group"><h5>'+pagelayer_l('global_widgets')+'</h5></div>'+
5379 + '</div>';
5380 +
5381 + if(pagelayer_empty(pagelayer_global_widgets)){
5382 + pagelayer_global_widgets = [];
5383 + gHtml += '<div class="pagelayer-leftbar-group"><h5>No global widgets found</h5></div>';
5384 + }
5385 +
5386 + // Indivdual icon
5387 + for(var y in pagelayer_global_widgets){
5388 + var wEle = jQuery(pagelayer_global_widgets[y]['$']);
5389 + var sc = pagelayer_tag( wEle );
5390 +
5391 + if(!(sc in pagelayer_shortcodes) || 'not_visible' in pagelayer_shortcodes[sc]){
5392 + continue;
5393 + }
5394 +
5395 + gHtml += '<div class="pagelayer-shortcode-drag" draggable="true" pagelayer-tag="'+sc+'" pagelayer-global-id="'+y+'">'+
5396 + '<div class="pagelayer-sc">'+
5397 + '<center class="pagelayer-shortcode-inner">';
5398 +
5399 + if('icon' in pagelayer_shortcodes[sc]){
5400 + gHtml += '<i class="pagelayer-shortcode '+pagelayer_shortcodes[sc]['icon']+'"></i>';
5401 + }else{
5402 + gHtml += '<i class="pagelayer-shortcode pli pagelayer-'+sc+'"></i>';
5403 + }
5404 +
5405 + gHtml += '</center>'+
5406 + '<span class="pagelayer-shortcode-text">'+pagelayer_global_widgets[y]['title']+'</span>'+
5407 + '</div>'+
5408 + '</div>';
5409 +
5410 + }
5411 +
5412 + pagelayer.$$('#pagelayer-global-widget').html(gHtml);
5413 + };
5414 +
5415 + // The widget tabs
5416 + pagelayer.$$('.pagelayer-widget-tab').on('click', function(){
5417 + var attr = 'pagelayer-elpd-active-tab';
5418 + pagelayer.$$('.pagelayer-widget-tab').each(function(){
5419 + jQuery(this).removeAttr(attr);
5420 + });
5421 + var cEle = jQuery(this);
5422 + cEle.attr(attr, 1);
5423 +
5424 + if(cEle.attr('pagelayer-widget-tab') == 'global'){
5425 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-shortcodes-widget').addClass('pagelayer-hidden');
5426 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-global-widget').removeClass('pagelayer-hidden');
5427 + // Trigger create global widgets
5428 + global_widget_list();
5429 + }else{
5430 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-shortcodes-widget').removeClass('pagelayer-hidden');
5431 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-global-widget').addClass('pagelayer-hidden');
5432 + }
5433 + });
5434 +
2926 5435 // On click search empty
2927 5436 pagelayer.$$('.pagelayer-leftbar-search>.pagelayer-sf-empty').click(function(){
2928 5437 pagelayer.$$('.pagelayer-search-field').val('').trigger('input');
2929 5438 });
2930 5439
5440 + // Pagelayer General options
5441 + pagelayer.$$('.pagelayer-options-icon ').click(function(){
5442 + pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text(pagelayer_l('general_options'));
5443 + pagelayer.$$('.pagelayer-logo').hide();
5444 +
5445 + // Setup General options
5446 + pagelayer_setup_general_options();
5447 +
5448 + pagelayer_leftbar_tab('pagelayer-general-options');
5449 + pagelayer_active = {};
5450 + });
5451 +
5452 + // Hide color and typography global list
5453 + pagelayer.$$('.pagelayer-leftbar-table').on('click', function(e){
5454 +
5455 + var closest = jQuery(e.target).closest('.pagelayer-elp-color-global, .pagelayer-elp-global-icon, .pagelayer-global-color-list, .pagelayer-global-font-list');
5456 + var list = pagelayer.$$('.pagelayer-global-color-list, .pagelayer-global-font-list');
5457 +
5458 + if(closest.length > 0 ){
5459 + var lEle = closest.closest('.pagelayer-elp-color-div-holder').find('.pagelayer-global-color-list');
5460 + var lFont = closest.closest('.pagelayer-form-item').find('.pagelayer-global-font-list');
5461 +
5462 + list = list.not(lFont);
5463 + list = list.not(lEle);
5464 + }
5465 +
5466 + list.not(closest).slideUp();
5467 +
5468 + });
2931 5469 };
2932 5470
2933 5471 // Post setting holder
2934 -function pagelayer_post_settings(){
5472 +function pagelayer_post_settings(pl_tag, to_click){
2935 5473
5474 + to_click = to_click == -1 ? false : true;
5475 +
2936 5476 // Is there a post settings ?
2937 - var jEle = jQuery(pagelayer_editable+' [pagelayer-tag=pl_post_props]');
5477 + var jEle = jQuery(pagelayer_editable+' [pagelayer-tag="'+ pl_tag +'"]');
2938 5478
2939 5479 // Could not find
2940 5480 if(jEle.length < 1){
2941 - jEle = pagelayer_create_sc('pl_post_props');
5481 + jEle = pagelayer_create_sc(pl_tag);
2942 5482 var id = pagelayer_id(jEle);
2943 5483 jQuery(pagelayer_editable).prepend(jEle);
2944 - pagelayer_element_setup('[pagelayer-id='+id+']');
5484 + pagelayer_element_setup('[pagelayer-id='+id+']', true);
5485 +
5486 + // Dont mark as dirty as post_props is not editing anything
5487 + pagelayer_do_undirty();
2945 5488 }
2946 5489
2947 - jEle.click();
5490 + if(to_click){
5491 + jEle.click();
5492 + }
2948 5493
2949 - return;
5494 + return jEle;
2950 5495 }
2951 5496
2952 5497 // Get the closest element and method
2953 5498 function pagelayer_near_by_ele(id, sc){
@@ -2973,9 +5518,9 @@
2973 5518 var pEle_id = pagelayer_id(jQuery('[pagelayer-wrap-id="'+id+'"]').closest('.pagelayer-ele'));
2974 5519
2975 5520 // Get the parent element tag
2976 5521 var pEle_tag = pagelayer_tag(jQuery('[pagelayer-id="'+pEle_id+'"]'));
2977 - var holder = pagelayer_shortcodes[pEle_tag]['holder'] || '';
5522 + var holder = '>'+ pagelayer_shortcodes[pEle_tag]['holder'] || '';
2978 5523 args = {'method' : 'prepend', 'cEle' : '[pagelayer-id="'+pEle_id+'"] '+ holder+' '};
2979 5524
2980 5525 }
2981 5526
@@ -2987,8 +5532,9 @@
2987 5532
2988 5533 // Push the action data in the pagelayer_history_obj object
2989 5534 function pagelayer_history_action_push(args){
2990 5535
5536 + var currentTime = new Date();
2991 5537 var history_obj_len = pagelayer_history_obj['action_data'].length;
2992 5538
2993 5539 // If the history_obj_len is less then 1 then set the data in array 0 position
2994 5540 if(history_obj_len < 1){
@@ -2998,8 +5544,9 @@
2998 5544
2999 5545 // Remove the second array element if the history_obj_len greater then 100
3000 5546 if(history_obj_len > 100){
3001 5547 pagelayer_history_obj['action_data'].splice(1, 1);
5548 + pagelayer_history_obj['current_active_item_id'] = pagelayer_history_obj['action_data'].length - 1;
3002 5549 }
3003 5550
3004 5551 // Get current active history action id
3005 5552 var action_id = parseInt(pagelayer_history_obj['current_active_item_id']) || 0;
@@ -3008,22 +5555,45 @@
3008 5555 var del_ele = history_obj_len - action_id - 1;
3009 5556 pagelayer_history_obj['action_data'].splice(action_id + 1, del_ele);
3010 5557
3011 5558 // Check if the same attr set as current active history
3012 - if(args.action == "Edited" && history_obj_len > 1){
5559 + if(args.action == "Edited" && history_obj_len > 1 && currentTime - pagelayer.history_lastTime < 1000){
3013 5560 var atts = pagelayer_history_obj['action_data'][action_id] || '';
3014 - if(atts['atts'] == args['atts']){
5561 + if(atts['atts'] == args['atts'] && atts['pl_id'] == args['pl_id'] && pagelayer_empty(atts['sub_actions_group']) ){
3015 5562 args['oldVal'] = atts['oldVal'];
3016 5563 pagelayer_history_obj['action_data'][action_id] = args;
3017 5564 pagelayer_history_setup();
5565 +
5566 + // Set the last history time
5567 + pagelayer.history_lastTime = currentTime;
3018 5568 return true;
3019 5569 }
3020 5570 }
3021 -
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 +
3022 5590 pagelayer_history_obj['action_data'].push(args);
3023 5591 pagelayer_history_obj['current_active_item_id'] = pagelayer_history_obj['action_data'].length - 1;
3024 5592 pagelayer_history_setup();
3025 5593
5594 + // Set the last history time
5595 + pagelayer.history_lastTime = currentTime;
3026 5596 }
3027 5597
3028 5598 // Setup pagelayer history
3029 5599 function pagelayer_history_setup(force){
@@ -3140,14 +5710,45 @@
3140 5710 success: function(response, status, xhr){
3141 5711
3142 5712 var obj = jQuery.parseJSON(response);
3143 5713 if(obj['error']){
3144 - alert(obj['error']);
5714 + pagelayer_show_msg(obj['error'] , 'error');
3145 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
3146 5727 jQuery(pagelayer_editable).html(obj['content']);
3147 - alert(obj['success']);
3148 - 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);
3149 5749 pagelayer_add_widget();
5750 + pagelayer_show_msg(obj['success'], 'success');
3150 5751 }
3151 5752 }
3152 5753 });
3153 5754 });
@@ -3167,11 +5768,11 @@
3167 5768 success: function(response, status, xhr){
3168 5769
3169 5770 var obj = jQuery.parseJSON(response);
3170 5771 if(obj['error']){
3171 - alert(obj['error']);
5772 + pagelayer_show_msg(obj['error'], 'error');
3172 5773 }else{
3173 - alert(obj['success']);
5774 + pagelayer_show_msg(obj['success'], 'success');
3174 5775 rEle.hide();
3175 5776 }
3176 5777
3177 5778 }
@@ -3204,9 +5805,9 @@
3204 5805 });
3205 5806 });
3206 5807 }
3207 5808
3208 -// Get evisions Handler
5809 +// Get revisions Handler
3209 5810 function pagelayer_get_revision(){
3210 5811
3211 5812 jQuery.ajax({
3212 5813 url: pagelayer_ajax_url+'&action=pagelayer_get_revision&postID='+pagelayer_postID,
@@ -3218,9 +5819,9 @@
3218 5819 success: function(response, status, xhr){
3219 5820 var obj = jQuery.parseJSON(response);
3220 5821
3221 5822 if(!pagelayer_empty(obj['error'])){
3222 - alert(obj['error']);
5823 + pagelayer_show_msg(obj['error'], 'error');
3223 5824 }else{
3224 5825 pagelayer_revision_obj = obj;
3225 5826 pagelayer_history_setup(true);
3226 5827 }
@@ -3299,9 +5900,13 @@
3299 5900 // Re-setup the element
3300 5901 var resetup_ele = function(history_array){
3301 5902 jQuery(history_array.cEle.cEle)[history_array.cEle.method](history_array.html);
3302 5903 pagelayer_element_setup('[pagelayer-id='+history_array.pl_id+'], [pagelayer-id='+history_array.pl_id+'] .pagelayer-ele', true);
3303 - 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);
3304 5909 };
3305 5910
3306 5911 // Re-setup the element attr
3307 5912 var reset_ele_attr = function(hEle, atts, val, attrType){
@@ -3334,12 +5939,57 @@
3334 5939 if(!pagelayer_empty(pCol)){
3335 5940 pagelayer_empty_col(pCol);
3336 5941 pagelayer_empty_col(pagelayer_wrap_by_id(id).closest('.pagelayer-col-holder'));
3337 5942 }
3338 - }
5943 +
5944 + pagelayer_do_dirty(eWrap);
5945 + };
3339 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 +
3340 5990 if(prev_item_id > current_item_id){
3341 -
5991 +
3342 5992 // All Actions for undo here
3343 5993 var i = parseInt(prev_item_id);
3344 5994
3345 5995 for(i; i > current_item_id; i--){
@@ -3344,28 +5994,31 @@
3344 5994
3345 5995 for(i; i > current_item_id; i--){
3346 5996
3347 5997 var history_array = pagelayer_history_obj['action_data'][i];
3348 - var action = history_array.action;
3349 - var id = history_array.pl_id;
5998 + var sub_actions_group = history_array['sub_actions_group'] || '';
3350 5999
3351 - if(action == "Edited"){
3352 - hEle = jQuery('[pagelayer-id="'+id+'"]');
3353 - reset_ele_attr(hEle, history_array.atts, history_array.oldVal, history_array.attrType);
3354 - }else if(action == "Added"){
3355 - delete_ele(id);
3356 - }else if(action == "Deleted"){
3357 - resetup_ele(history_array);
3358 - }else if(action == "Copied"){
3359 - delete_ele(id);
3360 - }else if(action == "Moved"){
3361 - pagelayer_move_ele(id, history_array.before_loc);
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 + }
3362 6006 }
3363 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 + }
3364 6017 }
3365 6018
3366 6019 }else{
3367 -
6020 +
3368 6021 // All Actions for redo here
3369 6022 var i = parseInt(prev_item_id)+1;
3370 6023
3371 6024 for(i; i <= current_item_id; i++){
@@ -3370,29 +6023,25 @@
3370 6023
3371 6024 for(i; i <= current_item_id; i++){
3372 6025
3373 6026 var history_array = pagelayer_history_obj['action_data'][i];
3374 - var action = history_array.action;
3375 - 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);
3376 6030
3377 - if(action == "Edited"){
3378 - hEle = jQuery('[pagelayer-id="'+id+'"]');
3379 - reset_ele_attr(hEle, history_array.atts, history_array.newVal, history_array.attrType);
3380 - }else if(action == "Added"){
3381 - resetup_ele(history_array);
3382 -
3383 - if(history_array.tag != "pl_row" && history_array.tag != "pl_col" ){
3384 - // Ensure the column is not empty
3385 - 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]);
3386 6035 }
3387 - }else if(action == "Deleted"){
3388 - delete_ele(id);
3389 - }else if(action == "Copied"){
3390 - resetup_ele(history_array);
3391 - }else if(action == "Moved"){
3392 - pagelayer_move_ele(id, history_array.after_loc);
3393 6036 }
3394 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 + }
3395 6044 }
3396 6045 }
3397 6046
3398 6047 };
@@ -3403,29 +6052,48 @@
3403 6052 alert(prefix+error);
3404 6053 };
3405 6054
3406 6055 function pagelayer_bottombar(){
3407 - var holder = pagelayer.$$('.pagelayer-bottombar-holder');
3408 - var html = '<div class="pagelayer-bottombar">'+
3409 - '<div class="pagelayer-bottombar-rightbuttons">'+
3410 - '<button data-tlite="Save Changes" class="pagelayer-update-button pagelayer-success-btn">Update</button>'+
3411 - '<button data-tlite="Close and Return to Admin Panel" class="pagelayer-close-button">Close</button>'+
3412 - '<div class="pagelayer-mode-wrapper">'+
3413 - '<div class="pagelayer-mode-buttons-wrapper">'+
3414 - '<i class="screen-mode pli pli-desktop" pagelayer-mode-data="desktop"></i>'+
3415 - '<i class="screen-mode pli pli-tablet" pagelayer-mode-data="tablet"></i>'+
3416 - '<i class="screen-mode pli pli-mobile" pagelayer-mode-data="mobile"></i>'+
3417 - '</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>'+
3418 6071 '</div>'+
3419 - '<i class="pagelayer-mode-button pli pli-desktop"></i>'+
3420 - '<span data-tlite="Preview Changes"><i class="pagelayer-preview pli pli-eye"></i></span>'+
3421 - '<span data-tlite="History and Revisions"><i class="pagelayer-history-icon pli pli-history"></i></span>'+
3422 - '<span data-tlite="navigator"><i class="pagelayer-navigator-icon pli pli-tree"></i></span>'+
3423 - //'<span data-tlite="Close and Return to Admin Panel"><i class="pagelayer-close-button fa fa-close"></i></span>'+
3424 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>'+
3425 6088 '</div>';
3426 6089
3427 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 +
3428 6096 holder.find('.pagelayer-update-button').on('click', function(){
3429 6097 pagelayer_save();
3430 6098 pagelayer_history_setup();// Setup history tab after update
3431 6099 });
@@ -3432,20 +6100,18 @@
3432 6100
3433 6101 holder.find('.pagelayer-close-button').on('click', function(){
3434 6102 pagelayer_close();
3435 6103 });
6104 +
3436 6105 holder.find('.screen-mode').on('click', function(){
3437 6106 var screen_mode = jQuery(this).attr('pagelayer-mode-data');
3438 6107 pagelayer_set_screen_mode(screen_mode);
3439 - holder.find('.pagelayer-mode-buttons-wrapper').toggle();
6108 + holder.find('.screen-mode').removeClass('active');
6109 + jQuery(this).addClass('active');
3440 6110 });
3441 6111
3442 - holder.find('.pagelayer-mode-button').on('click', function(){
3443 - holder.find('.pagelayer-mode-buttons-wrapper').toggle();
3444 - });
3445 -
3446 - holder.find('.pagelayer-history-icon').click(function(){
3447 - pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text('Pagelayer History');
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'));
3448 6114 pagelayer.$$('.pagelayer-logo').hide();
3449 6115 pagelayer_leftbar_tab('pagelayer-history');
3450 6116 pagelayer_active = {};
3451 6117 pagelayer_history_setup();
@@ -3450,10 +6116,10 @@
3450 6116 pagelayer_active = {};
3451 6117 pagelayer_history_setup();
3452 6118 });
3453 6119
3454 - holder.find('.pagelayer-navigator-icon').click(function(){
3455 - pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text('Pagelayer Navigator');
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'));
3456 6122 pagelayer.$$('.pagelayer-logo').hide();
3457 6123
3458 6124 // If the navigator tab visible, then don't setup
3459 6125 if(!pagelayer.$$('#pagelayer-navigator').is(':visible')){
@@ -3483,9 +6149,9 @@
3483 6149 url: pagelayer_ajax_url+'&action=pagelayer_create_post_autosave&postID='+pagelayer_postID,
3484 6150 type: 'POST',
3485 6151 data: {
3486 6152 'pagelayer_nonce': pagelayer_ajax_nonce,
3487 - 'pagelayer_post_content': post
6153 + 'pagelayer_post_content': pagelayer_Base64.encode(post)
3488 6154 },
3489 6155 success: function(data) {
3490 6156 var data = JSON.parse(data);
3491 6157
@@ -3490,9 +6156,9 @@
3490 6156 var data = JSON.parse(data);
3491 6157
3492 6158 // If there is some error
3493 6159 if(!pagelayer_empty(data['error']) || pagelayer_empty(data['id'])){
3494 - alert('Unable to set preview for some reason');
6160 + pagelayer_show_msg('Unable to set preview for some reason', 'error');
3495 6161 return;
3496 6162 }
3497 6163
3498 6164 var url = data['url']+'&preview_id='+pagelayer_postID+'&preview_nonce='+
@@ -3512,8 +6178,102 @@
3512 6178 ///////////////////////////////
3513 6179 // Miscellaneuos Functions
3514 6180 ///////////////////////////////
3515 6181
6182 +// Setup General options
6183 +function pagelayer_setup_general_options(){
6184 +
6185 + var holder = pagelayer.$$('.pagelayer-general-options');
6186 +
6187 + if(holder.children().length > 0){
6188 + return;
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>';
6225 +
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 + });
6263 +
6264 + modal.unbind('click');
6265 + modal.on('click', function(e){
6266 +
6267 + if(e.target != this) {
6268 + return;
6269 + }
6270 +
6271 + modal.hide();
6272 + });
6273 + });
6274 +}
6275 +
3516 6276 // Setup navigator
3517 6277 function pagelayer_navigator_setup(){
3518 6278
3519 6279 var navigator_ele = pagelayer.$$('#pagelayer-navigator'),
@@ -3547,8 +6307,9 @@
3547 6307 navigator_list += '<div class="pagelayer-navigetor-ele" pagelayer-id="'+id+'">'+
3548 6308 '<div class="pagelayer-ele-name '+ ele_class +'" pagelayer-tag="'+tag+'" style="padding-left:'+navigator_padding+'px">'+
3549 6309 '<i class="fa pagalayer-arrow"></i><i class="fa pagelayer-'+tag+'"></i>'+
3550 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>'+
3551 6312 '</div>';
3552 6313
3553 6314 // Create the list of child element
3554 6315 if(child_ele){
@@ -3570,8 +6331,23 @@
3570 6331
3571 6332 // Put the navigator list
3572 6333 navigator_ele.html('<div class="pagelayer-leftbar-prop-body">'+navigator_html+'</div>');
3573 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+']');
6346 + }
6347 +
6348 + });
6349 +
3574 6350 // On click toggle the element
3575 6351 navigator_ele.find('.pagelayer-ele-name').on('click', function(){
3576 6352
3577 6353 var tEle = jQuery(this);
@@ -3645,29 +6421,29 @@
3645 6421 var scrolled = parentEle || jQuery('html, body');
3646 6422 timeout = timeout || 500;
3647 6423 parentEle = parentEle || jQuery(window);
3648 6424
3649 - setTimeout(function () {
3650 - var parentHeight = parentEle.height(),
3651 - parentScrollTop = parentEle.scrollTop(),
3652 - elementTop = jEle.offset().top,
3653 - topToCheck = elementTop - parentScrollTop;
6425 + setTimeout(function(){
6426 + var parentHeight = parentEle.height(),
6427 + parentScrollTop = parentEle.scrollTop(),
6428 + elementTop = jEle.offset().top,
6429 + topToCheck = elementTop - parentScrollTop;
3654 6430
3655 - if (topToCheck > 0 && topToCheck < parentHeight) {
3656 - return;
3657 - }
6431 + if (topToCheck > 0 && topToCheck < parentHeight) {
6432 + return;
6433 + }
3658 6434
3659 - var scrolling = elementTop - parentHeight / 2;
3660 - scrolled.stop(true).animate({
3661 - scrollTop: scrolling
3662 - }, 1000);
3663 - }, timeout);
6435 + var scrolling = elementTop - parentHeight / 2;
6436 + scrolled.stop(true).animate({
6437 + scrollTop: scrolling
6438 + }, 1000);
6439 + }, timeout);
3664 6440 }
3665 6441
3666 6442 // Generates a random string of "n" characters
3667 6443 function pagelayer_randstr(n, special){
3668 - var text = '';
3669 - var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
6444 + var text = '';
6445 + var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
3670 6446
3671 6447 special = special || 0;
3672 6448 if(special){
3673 6449 possible = possible + '&#$%@';
@@ -3672,79 +6448,28 @@
3672 6448 if(special){
3673 6449 possible = possible + '&#$%@';
3674 6450 }
3675 6451
3676 - for(var i=0; i < n; i++){
3677 - text += possible.charAt(Math.floor(Math.random() * possible.length));
3678 - }
6452 + for(var i=0; i < n; i++){
6453 + text += possible.charAt(Math.floor(Math.random() * possible.length));
6454 + }
3679 6455
3680 - return text;
6456 + return text;
3681 6457 };
3682 6458
3683 -function pagelayer_update_site_title(val){
3684 - if(!pagelayer_empty(val)){
3685 - var site_name = jQuery('.pagelayer-wp-title').attr('pagelayer-a-site_name');
3686 - if(!pagelayer_empty(site_name)){
3687 - var site_title = jQuery.ajax({
3688 - url: pagelayer_ajax_url+'&action=pagelayer_fetch_site_title',
3689 - type: 'post',
3690 - async: false
3691 - }).responseText;
3692 -
3693 - if(site_title != site_name){
3694 - var site_title = jQuery.ajax({
3695 - url: pagelayer_ajax_url+'&action=pagelayer_update_site_title',
3696 - type: 'post',
3697 - data: {'site_title': site_name},
3698 - async: false
3699 - }).responseText;
3700 - }
3701 - }
3702 - }
6459 +function pagelayer_randInt(max) {
6460 + return Math.floor(Math.random() * Math.floor(max));
3703 6461 }
3704 6462
3705 -function pagelayer_trim(str, charlist){
3706 - // discuss at: http://locutus.io/php/trim/
3707 -
3708 - if(typeof str != 'string'){
3709 - return str;
3710 - }
3711 -
3712 - var whitespace = [' ', '\n', '\r', '\t', '\f', '\x0b', '\xa0', '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u2005', '\u2006', '\u2007', '\u2008', '\u2009', '\u200a', '\u200b', '\u2028', '\u2029', '\u3000' ].join('')
3713 - var l = 0
3714 - var i = 0
3715 - str += ''
3716 -
3717 - if (charlist) {
3718 - whitespace = (charlist + '').replace(/([[\]().?/*{}+$^:])/g, '$1')
3719 - }
3720 -
3721 - l = str.length
3722 - for (i = 0; i < l; i++) {
3723 - if (whitespace.indexOf(str.charAt(i)) === -1) {
3724 - str = str.substring(i)
3725 - break
3726 - }
3727 - }
3728 -
3729 - l = str.length
3730 - for (i = l - 1; i >= 0; i--) {
3731 - if (whitespace.indexOf(str.charAt(i)) === -1) {
3732 - str = str.substring(0, i + 1)
3733 - break
3734 - }
3735 - }
3736 -
3737 - return whitespace.indexOf(str.charAt(0)) === -1 ? str : ''
3738 -};
3739 -
3740 6463 // Convert the regular URL of a Video to a Embed URL
3741 -function pagelayer_video_url(src){
3742 -
6464 +function pagelayer_video_url(src, no_url){
6465 +
6466 + no_url = no_url || false;
3743 6467 var youtubeRegExp = /youtube\.com|youtu\.be/;
3744 6468 var vimeoRegExp = /vimeo\.com/;
3745 6469 var match = '';
3746 6470 var videoId = '';
6471 + var vid_params = {};
3747 6472
3748 6473 if (youtubeRegExp.exec(src)) {
3749 6474 match = 'youtube';
3750 6475 } else if (vimeoRegExp.exec(src)) {
@@ -3771,9 +6496,15 @@
3771 6496 } else if (youtube.exec(src)) {
3772 6497 videoId = src.split('.be/');
3773 6498 }
3774 6499
3775 - 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();
3776 6507
3777 6508 break;
3778 6509
3779 6510 case 'vimeo':
@@ -3786,23 +6517,51 @@
3786 6517 } else if (vimeoRegExp.exec(src)) {
3787 6518 videoId = src.split('.com/');
3788 6519 }
3789 6520
3790 - 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 + };
3791 6526
3792 6527 break;
3793 6528 default:
3794 - return src;
6529 + vid_params = {
6530 + type : 'local',
6531 + src : src
6532 + };
6533 +
3795 6534 }
6535 +
6536 + if(!no_url){
6537 + return vid_params.src;
6538 + }
6539 +
6540 + return vid_params;
3796 6541 };
3797 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 +
3798 6554 // Add widget section
3799 6555 function pagelayer_add_widget(){
3800 6556
3801 6557 html='<div class="pagelayer-add-widget-area">'+
3802 - '<button class="pagelayer-add-button pagelayer-add-section"><i class="pagelayer-add-row fa fa-file-text"></i> &nbsp;Add New Section</button>'+
3803 - '<button class="pagelayer-add-button pagelayer-add-row"><i class="pagelayer-add-row fa fa-plus-circle"></i> &nbsp;Add New Row</button>'+
3804 - '<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>'+
3805 6564 '</div>';
3806 6565
3807 6566 jQuery(pagelayer_editable).append(html);
3808 6567
@@ -3808,27 +6567,38 @@
3808 6567
3809 6568 var add_area = jQuery('.pagelayer-add-widget-area');
3810 6569
3811 6570 // Add a code before this
3812 - var add_sc = function(tag){
6571 + var add_sc = function(tag, global_id = ''){
3813 6572
6573 + var attr = '';
6574 + if(!pagelayer_empty(global_id)){
6575 + attr = ' pagelayer-global-id="'+global_id+'" ';
6576 + }
6577 +
3814 6578 // Create Row
3815 - var row = jQuery('<div pagelayer-tag="pl_row"></div>');
6579 + var row = jQuery('<div pagelayer-tag="pl_row" '+((tag == 'pl_row') ? attr : '') +'></div>');
3816 6580 add_area.before(row);
3817 6581 var row_id = pagelayer_onadd(row, false);
3818 6582 var rEle = pagelayer_ele_by_id(row_id);
3819 6583
3820 - if(tag == 'pl_row'){
6584 + if(tag == 'pl_row' && !pagelayer_empty(global_id)){
3821 6585 rEle.click();
3822 6586 return row_id;
3823 6587 }
3824 6588
3825 6589 // Create Column
3826 - var col = jQuery('<div pagelayer-tag="pl_col"></div>');
6590 + var col = jQuery('<div pagelayer-tag="pl_col" '+((tag == 'pl_col') ? attr : '') +'></div>');
3827 6591 rEle.find('.pagelayer-row-holder').append(col);
3828 6592 var col_id = pagelayer_onadd(col, false);
3829 6593 var cEle = pagelayer_ele_by_id(col_id);
3830 6594
6595 +
6596 + if(tag == 'pl_row'){
6597 + rEle.click();
6598 + return row_id;
6599 + }
6600 +
3831 6601 if(tag == 'pl_col'){
3832 6602 cEle.click();
3833 6603 return col_id;
3834 6604 }
@@ -3833,31 +6603,66 @@
3833 6603 return col_id;
3834 6604 }
3835 6605
3836 6606 // Create element
3837 - var ele = jQuery('<div pagelayer-tag="'+tag+'"></div>');
6607 + var ele = jQuery('<div pagelayer-tag="'+tag+'" '+attr+'></div>');
3838 6608 cEle.find('.pagelayer-col-holder').append(ele);
6609 + //console.log(ele);
3839 6610 var id = pagelayer_onadd(ele);
3840 -
6611 + //console.log(id);
6612 + //console.log(col_id);
6613 + var eEle = pagelayer_ele_by_id(col_id);
6614 + //console.log(eEle);
3841 6615 // Ensure the column is not empty
3842 6616 pagelayer_empty_col(cEle.find('.pagelayer-col-holder'));
3843 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 +
3844 6625 return id;
3845 6626
3846 6627 }
3847 6628
3848 - // Handle Click
3849 - add_area.on('click', function(e){
6629 + // Handle Click on Plus Button
6630 + add_area.find('.pagelayer-add-circle-plus').on('click', function(e){
3850 6631 e.stopPropagation();
3851 6632 add_sc('pl_col');
3852 6633 });
3853 6634
3854 - // Handle Click
6635 + // Handle Click on Template/Folder Button
3855 6636 add_area.find('.pagelayer-add-section').on('click', function(e){
3856 6637 e.stopPropagation();
3857 6638 pagelayer_add_section_area();// Setup and show sections modal
3858 6639 });
3859 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 +
3860 6665 // Handle Drag over
3861 6666 add_area.on('dragover', function(e){
3862 6667 //console.log(e)
3863 6668 add_area.addClass('pagelayer-add-widget-drag');
@@ -3877,8 +6682,9 @@
3877 6682 add_area.removeClass('pagelayer-add-widget-drag');
3878 6683 jQuery('.pagelayer-is-dragging').removeClass('pagelayer-is-dragging');
3879 6684
3880 6685 var tag = e.originalEvent.dataTransfer.getData('tag');
6686 + var global_id = e.originalEvent.dataTransfer.getData('global_id');
3881 6687
3882 6688 // Is it an existing element ?
3883 6689 if(tag.length < 1){
3884 6690 return false;
@@ -3887,12 +6693,29 @@
3887 6693 e.preventDefault();
3888 6694
3889 6695 //console.log(tag);
3890 6696
3891 - add_sc(tag);
6697 + add_sc(tag, global_id);
3892 6698 });
3893 6699 };
3894 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 ;
6716 +}
6717 +
3895 6718 // Append section modal into body
3896 6719 function pagelayer_add_section_area(){
3897 6720
3898 6721 var body = pagelayer.$$('body');
@@ -3906,16 +6729,36 @@
3906 6729 var section_modal = '<div class="pagelayer-add-section-modal-container">'+
3907 6730 '<div class="pagelayer-add-section-modal-holder">'+
3908 6731 '<div class="pagelayer-add-section-modal">'+
3909 6732 '<div class="pagelayer-add-section-modal-header">'+
3910 - '<i class="pagelayer-add-section-modal-close">&times;</i>'+
3911 - '<span>Add Sections</span>'+
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>'+
3912 6743 '</div>'+
3913 - '<div class="pagelayer-add-section-modal-body">'+
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>'+
3914 6754 '</div>'+
3915 6755 '<div class="pagelayer-add-section-modal-overlay" style="display:none;">'+
3916 6756 '<div class="pagelayer-section-wait">'+
3917 - '<i class="fa fa-spinner fa-spin"></i><br/><span>Please wait a moment</span>'+
6757 + '<div class="pagelayer-loader">'+
6758 + '<div class="pagelayer-percent-parent"></div>'+
6759 + '</div><br/>'+
6760 + '<span>Please wait a moment</span>'+
3918 6761 '</div>'+
3919 6762 '</div>'+
3920 6763 '</div>'+
3921 6764 '</div>'+
@@ -3930,8 +6773,19 @@
3930 6773 mEle.find('.pagelayer-add-section-modal-close').on('click', function(){
3931 6774 mEle.hide();
3932 6775 });
3933 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 +
3934 6788 // Append the list items into modal body
3935 6789 pagelayer_add_sections_list_setup();
3936 6790
3937 6791 mEle.show();// Show the modal
@@ -3941,45 +6795,216 @@
3941 6795 // Append section list into modal body
3942 6796 function pagelayer_add_sections_list_setup(type){
3943 6797
3944 6798 var mEle = pagelayer.$$('.pagelayer-add-section-modal-container');
6799 + var body = mEle.find('.pagelayer-add-section-modal-body');
3945 6800 var add_area = jQuery('.pagelayer-add-widget-area');
3946 6801 type = type || 'section';
3947 6802
3948 - var default_content = '<div style="display:inline-block;position:absolute;top:0;left:0;right:0;text-align:center;"><h1>Coming Soon</h1>'+
3949 - '<span>We will soon add some pre-defined '+type+' layouts which you can add to your post with just one click !</span>'+
3950 - '</div>';
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);
3951 6816
3952 - // Set coming soon
3953 - mEle.find('.pagelayer-add-section-modal-body').html(default_content);
3954 - return;
6817 + var viewer = '<div class="pagelayer-section-is-visible"></div>';
6818 + var selected_tags = {};
6819 + var result_set = {};
3955 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 +
3956 6830 // Create list of items
3957 6831 var pagelayer_section_list = function(){
3958 6832
3959 - var section_html = '';
3960 - var data = pagelayer_add_section_data[type];
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 + }
3961 6871
3962 - // Get data form pagelayer_add_section_data object to create list
3963 - for(var section in data['list']){
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){
3964 6920
3965 - var id = data['list'][section];
6921 + if(i >= (num_cols * 5)){
6922 + break;
6923 + }
3966 6924
3967 - section_html += '<div class="pagelayer-section-item" pagelayer-add-section-id="'+ id +'">'+
3968 - '<img src="'+ data['image_url'] + id +'.png" alt="Pagelayer code screenshot">'+
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>' : '')+
3969 6940 '</div>';
3970 6941
6942 + body.find('.pagelayer-section-holder[num='+col+']').append(html);
6943 +
6944 + delete result_set[id];
6945 +
3971 6946 }
3972 -
3973 - // Create items list
3974 - mEle.find('.pagelayer-add-section-modal-body').html(section_html);
6947 +
6948 + //console.log(result_set);
6949 +
3975 6950 mEle.find('.pagelayer-section-item').unbind('click');
3976 6951 mEle.find('.pagelayer-section-item').on('click', function(e){
3977 6952 pagelayer_section_item_clickable(jQuery(this));
3978 6953 });
3979 6954
3980 - };
6955 + scroll_accessed = false;
6956 +
6957 + }
3981 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 +
3982 7007 // On click items
3983 7008 var pagelayer_section_item_clickable = function(jEle){
3984 7009
3985 7010 var section_id = jEle.attr('pagelayer-add-section-id');
@@ -3988,8 +7013,12 @@
3988 7013 if(pagelayer_empty(section_id)){
3989 7014 return false;
3990 7015 }
3991 7016
7017 + if(jEle.find('.pagelayer-section-pro-req').length > 0){
7018 + return false;
7019 + }
7020 +
3992 7021 // Show the overlay
3993 7022 mEle.find('.pagelayer-add-section-modal-overlay').show();
3994 7023
3995 7024 // Do shortcode the content
@@ -4000,25 +7029,42 @@
4000 7029 'pagelayer_nonce': pagelayer_ajax_nonce,
4001 7030 'pagelayer_section_id': section_id,
4002 7031 'pagelayer-live': 1
4003 7032 },
4004 - success: function(data) {
7033 + success: function(data) {
4005 7034
4006 - var data = JSON.parse(data);
4007 - var cEle = jQuery(data['code']);
4008 -
4009 - // Add section before add widget area
4010 - add_area.before(cEle);
4011 -
4012 - // We need to it setup
4013 - cEle.each(function(){
4014 - var pl_id = pagelayer_id(jQuery(this));
7035 + try{
4015 7036
4016 - if(!pagelayer_empty(pl_id)){
4017 - pagelayer_element_setup('[pagelayer-id="'+pl_id+'"], [pagelayer-id='+pl_id+'] .pagelayer-ele', true);
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;
4018 7044 }
4019 - });
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 + });
4020 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 +
4021 7067 },
4022 7068 complete: function(){
4023 7069 mEle.find('.pagelayer-add-section-modal-overlay').hide();
4024 7070 mEle.hide();
@@ -4027,9 +7073,12 @@
4027 7073 }
4028 7074
4029 7075 // Load the data if not there
4030 7076 if(!(type in pagelayer_add_section_data)){
4031 -
7077 +
7078 + // Show the loading
7079 + mEle.find('.pagelayer-add-section-modal-overlay').show();
7080 +
4032 7081 // Get the sections list data and append it
4033 7082 jQuery.ajax({
4034 7083 url: pagelayer_api_url+'/library.php?give='+type,
4035 7084 type: 'post',
@@ -4045,8 +7094,14 @@
4045 7094
4046 7095 // Create the Type
4047 7096 pagelayer_section_list(type);
4048 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();
4049 7104 }
4050 7105 });
4051 7106
4052 7107 // We have the data, so show it
@@ -4054,15 +7109,66 @@
4054 7109 pagelayer_section_list(type);
4055 7110 }
4056 7111 }
4057 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 +
4058 7158 // On editable area image paste handler
4059 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;
4060 7164
4061 7165 try {
4062 - var items = (pasteEvent.originalEvent || pasteEvent).clipboardData.items,
4063 - mustPreventDefault = false,
4064 - reader;
7166 + if(is_Paste){
7167 + items = (pasteEvent.originalEvent || pasteEvent).clipboardData.items;
7168 + }else{
7169 + items = [pasteEvent];
7170 + }
4065 7171
4066 7172 for (var i = items.length - 1; i >= 0; i -= 1) {
4067 7173
4068 7174 if (items[i].type.match(/^image\//)) {
@@ -4068,71 +7174,49 @@
4068 7174 if (items[i].type.match(/^image\//)) {
4069 7175
4070 7176 reader = new FileReader();
4071 7177 /* jshint -W083 */
4072 - reader.onloadend = function (event) {
7178 + reader.onloadend = function(event) {
4073 7179
4074 7180 var src = event.target.result;
4075 7181
4076 - if( src.indexOf('data:image') === 0 ) {
7182 + if(src.indexOf('data:image') === 0 ) {
4077 7183
4078 7184 var block = src.split(";");
4079 7185 var contentType = block[0].split(":")[1];
4080 7186 var realData = block[1].split(",")[1];
4081 - 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 + }
4082 7192
4083 7193 // Convert it to a blob to upload
4084 7194 var blob = pagelayer_b64toBlob(realData, contentType);
4085 7195
4086 - var formData = new FormData();
4087 - formData.append('action', 'upload-attachment');
4088 - formData.append('_ajax_nonce', pagelayer_media_ajax_nonce);
4089 - formData.append('async-upload', blob, fileName);
7196 + pagelayer_upload_image(fileName, blob, pagelayer_ajax_func);
4090 7197
4091 - $.ajax({
4092 - url:pagelayer_ajax_url,
4093 - data: formData,// the formData function is available in almost all new browsers.
4094 - type:"post",
4095 - contentType:false,
4096 - processData:false,
4097 - cache:false,
4098 - beforeSend: function( xhr ) {
4099 - if(typeof pagelayer_ajax_func.beforeSend == 'function'){
4100 - pagelayer_ajax_func.beforeSend(xhr);
4101 - }
4102 - },
4103 - error:function(err){
4104 - //console.error(err);
4105 - alert("Unable to upload image for some reason.");
4106 - },
4107 - success:function(response){
4108 - var obj = jQuery.parseJSON(response);
4109 - if(typeof pagelayer_ajax_func.success == 'function'){
4110 - pagelayer_ajax_func.success(obj);
4111 - }
4112 - },
4113 - complete:function(xhr){
4114 - if(typeof pagelayer_ajax_func.complete == 'function'){
4115 - pagelayer_ajax_func.complete(xhr);
4116 - }
4117 - }
4118 - });
4119 -
4120 7198 }
4121 7199
4122 7200 };
4123 7201 /* jshint +W083 */
4124 - reader.readAsDataURL(items[i].getAsFile());
7202 + if(is_Paste){
7203 + reader.readAsDataURL(items[i].getAsFile());
7204 + }else{
7205 + reader.readAsDataURL(items[i]);
7206 + }
4125 7207 mustPreventDefault = true;
4126 7208 }
4127 7209 }
4128 7210
4129 - if(mustPreventDefault){
7211 + if(mustPreventDefault && is_Paste){
4130 7212 pasteEvent.stopPropagation();
4131 7213 pasteEvent.preventDefault();
4132 7214 }
4133 7215
4134 - }catch(err){}
7216 + }catch(err){
7217 + console.log(err);
7218 + }
4135 7219
4136 7220 return mustPreventDefault;
4137 7221
4138 7222 }
@@ -4174,11 +7258,925 @@
4174 7258
4175 7259 // Tooltip Setup for Editor
4176 7260 function pagelayer_tooltip_setup(){
4177 7261 //pagelayer.$$('[data-tlite]').each(function(){pagelayer_tlite.show(jQuery(this).get(0));});return;
4178 - pagelayer.$$('[data-tlite]').on('hover', function(){
7262 + pagelayer.$$('[data-tlite]').hover(function(){
4179 7263 pagelayer_tlite.show(jQuery(this).get(0));
4180 - }).on('mouseleave', function(){
7264 + }, function(){
4181 7265 pagelayer_tlite.hide(jQuery(this).get(0));
4182 7266 });
4183 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 +
4184 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 +