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 +6057 -372 0.9.4 → 2.2.2 View file →
@@ -8,26 +8,126 @@
8 8 $: jQuery,
9 9 $$ : function(select){
10 10 return jQuery(select, window.parent.document);
11 11 },
12 + gDocument : jQuery(window.parent.document).add(document),
12 13 p : this,
13 14 copy_selected: '',
14 - mouse: {x: -1, y: -1}
15 + mouse: {x: -1, y: -1},
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
15 24 }
16 25
26 +var pagelayer_history_obj = {}, pagelayer_revision_obj = {};
27 +var pagelayer_add_section_data = {};
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 +
17 97 // Lets start
18 -jQuery(document).ready(function(){
98 +jQuery(document).ready(pagelayer_start);
19 99
100 +// Function to load the codes
101 +function pagelayer_start(){
102 +
103 + pagelayer.loading = 1;
104 + console.log('['+pagelayer_brand+'] Starting Pagelayer');
105 +
106 + // Prevent the click Insite editor
107 + pagelayer_prevent_click();
108 +
109 + // Set the title of the parent window
110 + try{ pagelayer.$$('head').append(pagelayer.$('title')[0].outerHTML); }catch(e){};
111 +
112 + pagelayer.blank_img = pagelayer_url+'/images/default-image.png';
113 +
20 114 pagelayer_shortcodes['pl_inner_row'] = JSON.parse(JSON.stringify(pagelayer_shortcodes['pl_row']));
21 115 pagelayer_shortcodes['pl_inner_row']['name'] = 'Inner Row';
22 116 pagelayer_groups['grid'].push('pl_inner_row');
117 +
118 + // Removing post props options
119 + pagelayer_setting_post_props();
23 120
24 121 // Make the Topbar
25 122 pagelayer_bottombar();
26 123
27 124 // Make the Leftbar
28 - pagelayer_leftbar();
29 -
125 + pagelayer_leftbar();
126 +
127 + // Make widget list toolbar
128 + pagelayer_create_widget_tooltip();
129 +
30 130 // Add widget section
31 131 pagelayer_add_widget();
32 132
33 133 // Setup the ELPD
@@ -32,8 +132,11 @@
32 132
33 133 // Setup the ELPD
34 134 pagelayer_elpd_setup();
35 135
136 + // Dump the data we have
137 + pagelayer_element_dump_data();
138 +
36 139 // Setup the properties of the elements
37 140 pagelayer_element_setup();
38 141
39 142 // An image to show for drag
@@ -41,20 +144,331 @@
41 144
42 145 // Setup the grid drag
43 146 pagelayer_setup_drag();
44 147
148 + // Set left bar draggable
149 + pagelayer_make_leftbar_movable();
150 +
45 151 // Set to desktop
46 152 pagelayer_set_screen_mode('desktop');
47 153
154 + // Create list of fonts
155 + pagelayer_fonts = pagelayer_l('pl_fonts_list');
156 +
48 157 // Set up right click
49 158 pagelayer_left_click();
50 159 pagelayer_right_click();
160 +
161 + // Setup pagelayer history handle
162 + pagelayer_history_obj['action_data'] = [];
163 + pagelayer_history_setup(true);
164 +
165 + // Make a quick access of the props
166 + pagelayer_make_props_ref();
167 +
168 + // Post props exported defaults need to be updated
169 + pagelayer_set_exported_defaults();
170 +
171 + // Do any actions here
172 + pagelayer_trigger_action('pagelayer_setup_history');
173 +
174 + // Editor Tooltips
175 + pagelayer_tooltip_setup();
176 +
177 + // Load Fonts
178 + for(var x in pagelayer_loaded_icons){
179 + var item = pagelayer_loaded_icons[x];
180 + jQuery.when(
181 + pagelayer_get_stored_data(pagelayer_url+'/fonts/'+item+'.json', pagelayer_ver)
182 + ).then(function(){
183 + pagelayer_icons[item] = JSON.parse(pagelayer_get_stored_data(pagelayer_url+'/fonts/'+item+'.json', pagelayer_ver));
184 + });
185 + };
51 186
52 -});
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 +}
53 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 +
54 431 // The jQuery Object of the ELPD
55 432 var pagelayer_elpd;
56 433
434 +// Store data values
435 +function pagelayer_get_stored_data(url, version){
436 + var name = 'pagelayer_'+url;
437 + var data = {};
438 + var force = false;
439 +
440 + // Try to parse the data
441 + try{
442 + data = JSON.parse(localStorage.getItem(name));
443 +
444 + if(data['version'] !== version){
445 + force = true;
446 + }
447 +
448 + }catch(e){
449 + force = true;
450 + }
451 +
452 + // Force download
453 + if(force){
454 + return jQuery.ajax({
455 + url: url,
456 + type: 'GET',
457 + dataType: 'text',
458 + success:function(newData){
459 + var data = {};
460 + data['version'] = version;
461 + data['val'] = newData;
462 + localStorage.setItem(name, JSON.stringify(data));
463 + }
464 + });
465 + }
466 +
467 + return data['val'];
468 +
469 +}
470 +
57 471 function pagelayer_closest_corner(jEle){
58 472 var corners = [];
59 473 var w = jEle.outerWidth();
60 474 var h = jEle.outerHeight();
@@ -88,8 +502,115 @@
88 502 return corner;
89 503
90 504 };
91 505
506 +// Make left bar draggable
507 +function pagelayer_make_leftbar_movable(){
508 + var pl_iframe = pagelayer.$$('.pagelayer-iframe'),
509 + pl_leftbar = pagelayer.$$('.pagelayer-leftbar-table');
510 +
511 + // On mouse down in pagelayer-topbar-holder
512 + pagelayer.$$('.pagelayer-topbar-mover').on('mousedown', function(e){
513 + e = e || window.event;
514 + e.preventDefault();
515 +
516 + // Get leftbar position
517 + var orig_eleX = pl_leftbar.offset().left;
518 + var orig_eleY = pl_leftbar.offset().top;
519 +
520 + // Get the mouse cursor position at startup:
521 + var posX = e.clientX;
522 + var posY = e.clientY;
523 +
524 + // The variable needs to be empty.
525 + var newMethod = '',
526 + change = true;
527 +
528 + var leftbar_mousemove = function(e){
529 + e = e || window.event;
530 +
531 + if(change){
532 + // Add class to leftbar
533 + pl_leftbar.addClass('pagelayer-leftbar-moving');
534 +
535 + // Add left-right overlay
536 + pl_iframe.before('<div class="pagelayer-leftbar-move pagelayer-moveto-left"></div>');
537 + pl_iframe.after('<div class="pagelayer-leftbar-move pagelayer-moveto-right"></div>');
538 + pagelayer.$$('body').addClass('pagelayer-overflow-hidden');
539 + change = false;
540 + }
541 +
542 + // calculate the new cursor position and set the element left-top position
543 + var top = orig_eleY + (e.clientY - posY);
544 + var left = orig_eleX + (e.clientX - posX);
545 +
546 + // set the element's new position:
547 + pl_leftbar.css({'top': top +'px','left': left +'px'});
548 + pagelayer.$$('.pagelayer-leftbar-toggle').hide();
549 +
550 + // Make a copy of new method
551 + var _newMethod = newMethod;
552 + newMethod = '';
553 +
554 + // Get near by corner
555 + var offleft = pl_iframe.offset().left;
556 +
557 + if(offleft + 100 > e.clientX){
558 + newMethod = 'before';
559 + }else if(offleft+pl_iframe.outerWidth()- 100 < e.clientX){
560 + newMethod = 'after';
561 + }
562 +
563 + if(_newMethod != newMethod){
564 + pagelayer.$$('.pagelayer-leftbar-move').css({'width' :'', 'opacity': '0.33'});
565 +
566 + if(newMethod == 'after'){
567 + pagelayer.$$('.pagelayer-moveto-right').animate({'width' :'60px', 'opacity': '0.66'}, 200);
568 + pl_leftbar.addClass('pagelayer-rightbar');
569 + }else if(newMethod == 'before'){
570 + pagelayer.$$('.pagelayer-moveto-left').animate({'width' : '60px', 'opacity': '0.66'}, 200);
571 + pl_leftbar.removeClass('pagelayer-rightbar');
572 + }
573 + }
574 +
575 + };
576 +
577 + var leftbar_mouseup = function(e){
578 +
579 + // Remove events
580 + pagelayer.gDocument.off('mousemove', leftbar_mousemove);
581 + pagelayer.gDocument.off('mouseup', leftbar_mouseup);
582 +
583 + // Remove class to leftbar
584 + pagelayer.$$('.pagelayer-leftbar-move').remove();
585 +
586 + var windowHeight = jQuery(window).height();
587 +
588 + if(pl_leftbar.offset().top < 0){
589 + pl_leftbar.css({'top': '10px'});
590 + }else if( (windowHeight - e.clientY) < 10){
591 + pl_leftbar.css({'top': ''+windowHeight - 40+'px'});
592 + }
593 +
594 + if( !pagelayer_empty(newMethod)){
595 + pl_leftbar.removeClass('pagelayer-leftbar-moving');
596 + pl_leftbar.removeAttr('style');
597 + pagelayer.$$('.pagelayer-leftbar-toggle').show();
598 + pagelayer.$$('body').removeClass('pagelayer-overflow-hidden');
599 + pl_iframe[newMethod](pl_leftbar);
600 + }
601 +
602 + // make change true
603 + change = true;
604 + };
605 +
606 + pagelayer.gDocument.on('mouseup', leftbar_mouseup);
607 + pagelayer.gDocument.on('mousemove', leftbar_mousemove);
608 +
609 + });
610 +
611 +}
612 +
92 613 // Make rows and cols draggable
93 614 function pagelayer_setup_drag(){
94 615
95 616 // The object to show as drag
@@ -207,9 +728,21 @@
207 728 var onWrap;
208 729
209 730 // If we are a column, we can be over another column or row
210 731 if(tag == 'pl_col'){
211 - 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 + }
212 745 //console.log(pagelayer_id(onWrap));
213 746
214 747 // If we are a row, we can be over another row or a column
215 748 }else if(tag == 'pl_row'){
@@ -217,17 +750,83 @@
217 750 //console.log(pagelayer_id(onWrap));
218 751
219 752 // For inner row we restrict to 1 level only
220 753 }else if(tag == 'pl_inner_row'){
221 - var ele_wrap = jQuery(ele).parents('.pagelayer-wrap-col')
222 - if(ele_wrap.length == 1){
223 - onWrap = jQuery(ele).closest('.pagelayer-wrap-ele,.pagelayer-wrap-col');
754 +
755 + var ele_wrap = jQuery(ele).parents('.pagelayer-wrap-col');
756 + if(
757 + (ele_wrap.length == 1 && !jQuery(ele).hasClass('pagelayer-wrap-col')) ||
758 + (ele_wrap.length == 0 && jQuery(ele).hasClass('pagelayer-wrap-col'))
759 + ){
760 + onWrap = jQuery(ele).closest('.pagelayer-wrap-ele,.pagelayer-wrap-col,.pagelayer-wrap-inner-row');
224 761 }else{
225 - onWrap = jQuery(ele).closest('.pagelayer-wrap-ele,.pagelayer-wrap-inner-row');
762 + onWrap = jQuery(ele).closest('.pagelayer-wrap-inner-row');
226 763 }
227 764 // For every other element, we can be over a col or ele
228 765 }else{
229 - onWrap = jQuery(ele).closest('.pagelayer-wrap-ele,.pagelayer-wrap-col');
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 + }
230 829 }
231 830 //console.log(onWrap);
232 831
233 832 // If we find nothing
@@ -236,21 +835,48 @@
236 835 reset_on_drag();// Also reset the last on item
237 836 return false;
238 837 }
239 838
839 + /*// If the columns more than 12 inside the row then return - As of now not enabled the below code
840 + if(tag == 'pl_col'){
841 + var _onTag = pagelayer_tag(onWrap);
842 + var colEles;
843 +
844 + // Is on col
845 + if(_onTag == 'pl_col'){
846 + colEles = onWrap.closest('.pagelayer-row-holder').children('.pagelayer-ele-wrap');
847 + }else{
848 + colEles = onWrap.find('.pagelayer-row-holder').first().children('.pagelayer-ele-wrap');
849 + }
850 +
851 + // If the columns more than 12
852 + if(colEles.length >= 12){
853 + return false;
854 + }
855 + }*/
856 +
240 857 // Get the ID
241 - var onId = onWrap.attr('pagelayer-wrap-id');
242 - var onEle = onWrap.children('.pagelayer-ele');
858 + var onId = pagelayer_id(onWrap);
859 + var onEle = pagelayer_ele_by_id(onId);
243 860
244 861 // Do we have a parent ?
245 - var pOnId = pagelayer_get_parent(onEle);
246 -
247 - 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 +
248 869 onId = pOnId;
249 - onEle = pagelayer_ele_by_id(onId);
250 - 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 +
251 874 }
252 875
876 + // Do we have a parent ?
877 + have_parent(onEle);
878 +
253 879 var changed = false;
254 880
255 881 // Was it the same ID like the one we were on before
256 882 if(pagelayer.drag_closest != onId){
@@ -290,10 +916,10 @@
290 916 }
291 917
292 918 //console.log(changed);
293 919
294 - // If we are on our self then clear return false
295 - 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')){
296 922 clear_prospect();// Clear existing prospects
297 923 reset_on_drag();// Also reset the last on item
298 924 return false;
299 925 }
@@ -390,10 +1016,17 @@
390 1016 e.preventDefault();
391 1017
392 1018 var wrap = pagelayer.dragging;
393 1019 var tag = pagelayer_tag(wrap);
1020 + var gId = wrap.attr('pagelayer-global-id');
394 1021 var fromEl = wrap.parent();
395 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 +
396 1029 wrap.removeClass('pagelayer-is-dragging');
397 1030
398 1031 // Find any prospect
399 1032 var prospect = jQuery('.pagelayer-drag-prospect');
@@ -407,15 +1040,25 @@
407 1040 var onTag = pagelayer_tag(onWrap);
408 1041 var dropped;
409 1042 var corner = prospect.attr('pagelayer-corner');
410 1043 var method = (corner == 'top') ? 'before' : 'after';
1044 + var before_loc; // Location before the drop
411 1045
412 1046 // Create the element if it needs to be created
413 - if(pagelayer.drag_is_new){
1047 + if(pagelayer.drag_is_new){
414 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 + }
415 1054
416 1055 // Move the object
417 1056 }else{
1057 +
1058 + // Get near by element before move
1059 + before_loc = pagelayer_near_by_ele(pagelayer_id(wrap), tag);
1060 +
418 1061 dropped = wrap;
419 1062 dropped.detach();
420 1063 }
421 1064
@@ -437,12 +1080,30 @@
437 1080
438 1081 // Trigger the onadd
439 1082 if(pagelayer.drag_is_new){
440 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 + }
441 1091
442 1092 // Existing elements
443 1093 }else{
444 1094 id = pagelayer_id(wrap);
1095 +
1096 + // Save in action history
1097 + pagelayer_history_action_push({
1098 + 'title' : pagelayer_shortcodes[tag]['name'],
1099 + 'action' : 'Moved',
1100 + 'pl_id' : id,
1101 + 'before_loc' : before_loc,
1102 + 'after_loc' : {'method' : method, 'cEle' : onWrap}
1103 + });
1104 +
1105 + pagelayer_do_dirty(pagelayer_ele_by_id(id));
445 1106 }
446 1107
447 1108 // Defining the variables as needed
448 1109 var jEle = pagelayer_ele_by_id(id);
@@ -490,13 +1151,14 @@
490 1151 jQuery(document).on('dragover', ondragover);
491 1152 jQuery(document).on('drop', ondrop);
492 1153
493 1154 // For addition of new elements
494 - pagelayer.$$('[pagelayer-tag]').on('dragstart', function(e){
1155 + pagelayer.$$('.pagelayer-leftbar').on('dragstart', function(e){
495 1156 //console.log(e);
496 1157
497 1158 var tEle = jQuery(e.target);
498 1159 var jEle = tEle.closest('.pagelayer-shortcode-drag');
1160 + var global_id = jEle.attr('pagelayer-global-id');
499 1161
500 1162 // Is it an existing element ?
501 1163 if(jEle.length < 1){
502 1164 return false;
@@ -503,12 +1165,37 @@
503 1165 }
504 1166
505 1167 e.originalEvent.dataTransfer.setData('tag', pagelayer_tag(jEle));
506 1168
1169 + if(!pagelayer_empty(global_id)){
1170 + e.originalEvent.dataTransfer.setData( 'global_id', global_id );
1171 + }
1172 +
507 1173 pagelayer.dragging = jEle;
508 1174 pagelayer.drag_is_new = true;
509 1175
510 1176 });
1177 +
1178 + // Handle editable content by removing drag
1179 + var onmousedown = function(e){
1180 +
1181 + var tEle = jQuery(e.originalEvent.explicitOriginalTarget);
1182 +
1183 + if(tEle.closest('[pagelayer-editable]').length > 0){
1184 + //console.log('Is Editable MouseDown');
1185 + tEle.parents('[draggable]').attr('draggable', 'false');
1186 + }
1187 +
1188 + }
1189 +
1190 + // Handle editable content by adding drag that was removed
1191 + var onmouseup = function(e){
1192 + jQuery(document).find('[draggable=false]').attr('draggable', 'true');
1193 + }
1194 +
1195 + // Handle editable contents by temprarily removing drag
1196 + jQuery(document).on('mousedown', onmousedown);
1197 + jQuery(document).on('mouseup', onmouseup);
511 1198
512 1199 };
513 1200
514 1201 // Handle empty col
@@ -527,17 +1214,25 @@
527 1214
528 1215 // Column is becoming blank, so show add ele
529 1216 if(jEle.children().length < 1){
530 1217 //from.addClass('pagelayer-empty-col');
531 - jEle.append('<div class="pagelayer-add-ele pagelayer-ele-wrap"><i class="fa fa-plus"><br>Empty column please add something</div>');
532 - var h = jEle.parent().parent().children('.pagelayer-ele-overlay').height();
533 - jEle.children('.pagelayer-add-ele').height(h);
1218 + jEle.append('<div class="pagelayer-add-ele pagelayer-ele-wrap"><i class="fas fa-plus"></i><br /><span>Empty column please Drag Widgets</span></div>');
1219 + //var h = jEle.parent().parent().children('.pagelayer-ele-overlay').height();
1220 + //jEle.children('.pagelayer-add-ele').height(h);
534 1221
535 1222 // Any add ele sign with non-empty columns here ?
536 - }else if(jEle.children('.pagelayer-add-ele').length > 0){
1223 + }else if(jEle.children('.pagelayer-add-ele').length > 0 && jEle.children().length > 1){
537 1224 jEle.children('.pagelayer-add-ele').remove();
538 1225 }
539 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 +
540 1235 });
541 1236
542 1237 };
543 1238
@@ -566,15 +1261,112 @@
566 1261 break;
567 1262 }
568 1263 }
569 1264 jEle.addClass('pagelayer-col-'+cols);
570 - Ele.addClass('pagelayer-col-'+cols);
571 -
1265 + jEle.css({'width': ''});
1266 +
572 1267 // Set the att
573 1268 pagelayer_set_atts(Ele, obj);
1269 + pagelayer_set_atts(Ele, 'col_width','');
1270 + pagelayer_sc_render(Ele)
574 1271 });
575 1272 }
576 1273
1274 +// Make column resizable handler
1275 +function pagelayer_col_make_resizable(wrap){
1276 +
1277 + // Resize handler element
1278 + var rHandler = jQuery('<div class="pagelayer-resize-handler"><div class="pagelayer-resize-icon"></div></div>');
1279 +
1280 + var pResize = wrap.children('.pagelayer-ele-overlay').find('.pagelayer-resize-handler');
1281 +
1282 + if(pResize.length > 0){
1283 + return;
1284 + }
1285 +
1286 + // Append it
1287 + wrap.children('.pagelayer-ele-overlay').append(rHandler);
1288 +
1289 + // Resize start
1290 + rHandler.on('mousedown', function(e) {
1291 + e.preventDefault();
1292 +
1293 + var next_ele = wrap.next();
1294 + var rHolder_width = wrap.closest('.pagelayer-row-holder').width();
1295 + var new_width, nEle_new_width;
1296 +
1297 + // Original width
1298 + var original_width = parseFloat(window.getComputedStyle(wrap[0]).getPropertyValue('width'));
1299 + var next_ele_width = parseFloat(window.getComputedStyle(next_ele[0]).getPropertyValue('width'));
1300 + var original_mouse_x = e.pageX;
1301 +
1302 + var both_width = parseInt(original_width + next_ele_width);
1303 +
1304 + // Add the element width and next element width
1305 + both_width = ((both_width / rHolder_width) *100);
1306 +
1307 + if(both_width > 100){
1308 + return false;
1309 + }
1310 +
1311 + jQuery('body').css({'cursor': 'ew-resize'});
1312 + rHandler.css({'display': 'block'});
1313 +
1314 + var mousemoved = false;
1315 +
1316 + var r_mousemove = function(e){
1317 + mousemoved = true;
1318 +
1319 + var width = original_width + (e.pageX - original_mouse_x);
1320 +
1321 + // Covert width in percentage
1322 + new_width = (width / rHolder_width *100).toFixed(2);
1323 +
1324 + if(both_width > new_width && new_width > 0){
1325 + nEle_new_width = (both_width - new_width).toFixed(2);
1326 + wrap.css({'width': new_width+'%'});
1327 + next_ele.css({'width': nEle_new_width+'%'});
1328 +
1329 + rHandler.attr({'pre-width': new_width+'%', 'next-width': nEle_new_width+'%'});
1330 + }
1331 +
1332 + };
1333 +
1334 + var r_mouseup = function(e){
1335 +
1336 + jQuery(document).off('mousemove', r_mousemove);
1337 + jQuery(document).off('mouseup', r_mouseup);
1338 + jQuery('body').css({'cursor': ''});
1339 + rHandler.removeAttr('style pre-width next-width');
1340 +
1341 + // IF mouseMoved
1342 + if(!mousemoved) return;
1343 +
1344 + // find real element and next real element
1345 + var jEle = wrap.find('>.pagelayer-ele');
1346 + var nEle = next_ele.find('>.pagelayer-ele');
1347 + var mode = pagelayer_get_screen_mode();
1348 + var col_width = 'col_width';
1349 +
1350 + // Do we have screen ?
1351 + if(mode != 'desktop'){
1352 + col_width = col_width +'_'+mode;
1353 + }
1354 +
1355 + // Set the element attrs
1356 + pagelayer_set_atts(jEle, col_width, new_width);
1357 + pagelayer_set_atts(jEle, 'col', '');
1358 + pagelayer_set_atts(nEle, col_width, nEle_new_width);
1359 + pagelayer_set_atts(nEle, 'col', '');
1360 +
1361 + };
1362 +
1363 + // Resize start
1364 + jQuery(document).on('mousemove', r_mousemove);
1365 + jQuery(document).on('mouseup', r_mouseup);
1366 + });
1367 +}
1368 +
577 1369 // Handle addition of elements from the left
578 1370 // NOTE : At this point the addition is FINALIZED
579 1371 // The add element cannot be prevented !
580 1372 function pagelayer_onadd(jEle, toClick){
@@ -598,11 +1390,25 @@
598 1390 function pagelayer_element_added(jEle){
599 1391
600 1392 var sc = jEle.attr('pagelayer-tag');
601 1393 var id, par_id;
1394 + var gId = jEle.attr('pagelayer-global-id');
1395 + gId = gId && !pagelayer_empty(pagelayer_global_widgets[gId]) ? gId : 0;
602 1396
1397 + // Set Pagelayer History FALSE to prevent saving attributes in action history
1398 + pagelayer.history_action = false;
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 +
603 1406 // Generate the HTML
604 - html = pagelayer_create_sc(sc);
1407 + }else{
1408 + html = pagelayer_create_sc(sc);
1409 + }
1410 +
605 1411 id = pagelayer_assign_id(html);
606 1412 par_id = id;
607 1413
608 1414 // Insert the HTML
@@ -610,8 +1416,13 @@
610 1416
611 1417 // Setup the properties of the elements
612 1418 pagelayer_element_setup("[pagelayer-id="+par_id+"], [pagelayer-id="+par_id+"] .pagelayer-ele", true);
613 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 +
614 1425 // Any children to add ?
615 1426 if(!('widget' in pagelayer_shortcodes[sc])){
616 1427
617 1428 // The element props
@@ -618,27 +1429,59 @@
618 1429 var props = pagelayer_shortcodes[sc];
619 1430
620 1431 // Do we have to create children ?
621 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);
622 1442
623 - var has_group = props['has_group'];
624 - var gProp = props[has_group['section']][has_group['prop']];
625 -
626 - for(var i=0; i < gProp['count']; i++){
627 - var cid = pagelayer_element_add_child(jQuery("[pagelayer-id="+id+"]"), gProp['sc']);
628 - //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+'"]'));
629 1453 }
630 -
631 1454 }
632 1455
633 1456 }
634 1457
1458 + // Save in action history
1459 + var cEle = pagelayer_near_by_ele(id, sc);
1460 +
1461 + pagelayer_history_action_push({
1462 + 'title' : pagelayer_shortcodes[sc]['name'],
1463 + 'action' : 'Added',
1464 + 'pl_id' : id,
1465 + 'html' : jQuery("[pagelayer-id="+id+"]")[0].outerHTML,
1466 + 'cEle' : cEle
1467 + });
1468 +
1469 + // Set pagelayer history TRUE
1470 + pagelayer.history_action = true;
1471 + pagelayer.global_render = true;
1472 +
1473 + // To update nav item list
1474 + pagelayer_do_dirty(pagelayer_ele_by_id(id));
1475 +
635 1476 return id;
636 1477
637 1478 };
638 1479
639 1480 // Add an element
640 -function pagelayer_element_add_child(pEle, sc){
1481 +function pagelayer_element_add_child(pEle, sc, gProp){
1482 +
1483 + gProp = gProp || {};
641 1484 var child = pagelayer_create_sc(sc);
642 1485 var cid = pagelayer_assign_id(child);
643 1486 pagelayer_set_parent(child, pagelayer_assign_id(pEle));
644 1487
@@ -656,8 +1499,73 @@
656 1499 }
657 1500
658 1501 pagelayer_element_setup('[pagelayer-id='+cid+']', true);
659 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 +
660 1568 // Do we have to create children ?
661 1569 if('has_group' in pagelayer_shortcodes[sc]){
662 1570
663 1571 var has_group = pagelayer_shortcodes[sc]['has_group'];
@@ -663,9 +1571,9 @@
663 1571 var has_group = pagelayer_shortcodes[sc]['has_group'];
664 1572 var gProp = pagelayer_shortcodes[sc][has_group['section']][has_group['prop']];
665 1573
666 1574 for(var i=0; i < gProp['count']; i++){
667 - 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);
668 1576 }
669 1577
670 1578 }
671 1579
@@ -695,8 +1603,14 @@
695 1603 return id;
696 1604
697 1605 }
698 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 +
699 1613 // Assign the jQuery object an ID
700 1614 function pagelayer_assign_id(jEle){
701 1615
702 1616 // Do you have the pagelayer id
@@ -701,9 +1615,10 @@
701 1615
702 1616 // Do you have the pagelayer id
703 1617 var id = jEle.attr("pagelayer-id");
704 1618 if(!id || id.length < 1){
705 - id = pagelayer_randstr(16);
1619 + id = pagelayer_randstr(3)+pagelayer_randInt(9999).toString();
1620 + id = id.toLowerCase();
706 1621 jEle.attr("pagelayer-id", id);
707 1622 }
708 1623
709 1624 return id;
@@ -714,8 +1629,9 @@
714 1629 function pagelayer_element_clicked(selector, e){
715 1630
716 1631 var jEle = jQuery(selector);
717 1632 e = e || false;
1633 + //console.log(e);
718 1634
719 1635 // You must be a element atleast
720 1636 if(!jEle.hasClass('pagelayer-ele')){
721 1637 return false;
@@ -728,18 +1644,25 @@
728 1644 if(pId){
729 1645 jEle = pagelayer_ele_by_id(pId);
730 1646 }
731 1647
1648 + // Make the editable fields active
1649 + //pagelayer_clear_editable();// First clear
1650 + jEle.find('[pagelayer-editable]').each(function (){
1651 + pagelayer_make_editable(jQuery(this), e);
1652 + });
1653 +
1654 + // Show left bar
1655 + if(pagelayer_empty(e)){
1656 + pagelayer.$$('.pagelayer-leftbar-table').removeClass('pagelayer-leftbar-hidden pagelayer-leftbar-minimize');
1657 + }
1658 +
732 1659 // Lets not rebuild everything to make it faster
733 1660 if(pagelayer_is_active(jEle)){
734 1661 return false;
735 1662 }
736 1663
737 - // Make the editable fields active
738 - pagelayer_clear_editable();// First clear
739 - jEle.find('[pagelayer-editable]').each(function (){
740 - pagelayer_make_editable(jQuery(this), e);
741 - });
1664 + pagelayer_trigger_action('pagelayer_element_clicked', [jEle]);
742 1665
743 1666 // Set this as the active element
744 1667 pagelayer_set_active(jEle);
745 1668
@@ -747,13 +1670,69 @@
747 1670 pagelayer_elpd_open(jEle);
748 1671
749 1672 }
750 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 +
751 1720 // The edit option
752 1721 function pagelayer_edit_element(selector){
753 1722 pagelayer_element_clicked(selector);
754 1723 }
755 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 +
756 1735 // Setup the properties on a single click
757 1736 function pagelayer_element_setup(selector, render){
758 1737
759 1738 var selector = selector || ".pagelayer-ele";
@@ -759,10 +1738,10 @@
759 1738 var selector = selector || ".pagelayer-ele";
760 1739 render = render || false;
761 1740
762 1741 // Loop through
763 - jQuery(selector).each(function(){
764 -
1742 + jQuery(pagelayer_editable+' '+selector).each(function(){
1743 +
765 1744 var jEle = jQuery(this);
766 1745
767 1746 // Assign an ID if not there
768 1747 var id = pagelayer_assign_id(jEle);
@@ -768,8 +1747,13 @@
768 1747 var id = pagelayer_assign_id(jEle);
769 1748 var pId = pagelayer_get_parent(jEle) || '';// Options to show on hover
770 1749 var selector = '[pagelayer-id='+id+']';
771 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 +
772 1756 if(render){
773 1757 pagelayer_sc_render(jEle);
774 1758 }
775 1759
@@ -774,8 +1758,9 @@
774 1758 }
775 1759
776 1760 // Get the tag
777 1761 var tag = pagelayer_tag(jEle);
1762 + var props = pagelayer_get_props(jEle);
778 1763
779 1764 // Lets check if we are the child of a parent i.e. element of a group
780 1765 if(pagelayer_empty(pId)){
781 1766
@@ -802,9 +1787,14 @@
802 1787
803 1788 }
804 1789
805 1790 }
806 -
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 +
807 1797 // Make the wraps
808 1798 jEle.wrap('<div class="pagelayer-ele-wrap" pagelayer-wrap-id="'+id+'"></div>');
809 1799 var wrap = jEle.parent();
810 1800
@@ -817,15 +1807,10 @@
817 1807 col = 'pagelayer-col-'+x;
818 1808 break;
819 1809 }
820 1810 }
1811 +
821 1812
822 - var is_custom_width = pagelayer_get_att(jEle, 'col');
823 - var col_width = pagelayer_get_att(jEle, 'col_width');
824 - if(pagelayer_empty(is_custom_width) && col_width){
825 - wrap.css('width', col_width+'%');
826 - }
827 -
828 1813 wrap.addClass('pagelayer-col '+col);
829 1814 //jEle.removeClass('pagelayer-col '+col);
830 1815 wrap.addClass('pagelayer-wrap-col');
831 1816
@@ -851,11 +1836,13 @@
851 1836 pagelayer_sc_render(jEle);
852 1837 }
853 1838
854 1839 html = '<div class="pagelayer-row-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
855 - '<i class="fa fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" />'+
856 - '<i class="fa fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" />'+
857 - '<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>'+
858 1845 '</div>';
859 1846
860 1847 }else if(tag == 'pl_col'){
861 1848
@@ -861,20 +1848,25 @@
861 1848
862 1849 overlay.addClass('pagelayer-col-hover');
863 1850
864 1851 html = '<div class="pagelayer-col-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
865 - '<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>'+
866 1853 '</div>';
867 1854
868 1855 // Is it an empty col ?
869 1856 pagelayer_empty_col(jEle.children('.pagelayer-col-holder'));
1857 +
1858 + // Make col resizable
1859 + pagelayer_col_make_resizable(wrap);
870 1860
871 1861 }else{
872 1862
873 1863 html = '<div class="pagelayer-ele-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
874 - '<i class="fa fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" />'+
875 - '<i class="fa fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" />'+
876 - '<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>'+
877 1869 '</div>';
878 1870
879 1871 }
880 1872
@@ -879,10 +1871,23 @@
879 1871 }
880 1872
881 1873 // Append to the child
882 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 +
883 1881 jQuery('[pagelayer-option-id='+id+']').hide();
884 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 +
885 1890 // Setup the HOVER events ABD create WRAPS IF we dont have a parent
886 1891 if(pId.length > 0){
887 1892 return;
888 1893 }
@@ -916,13 +1921,51 @@
916 1921
917 1922 });
918 1923 }
919 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 +
920 1961 // Left Click
921 1962 function pagelayer_left_click(){
922 1963
923 - jQuery('.entry-content').on('click', function(e){
1964 + jQuery(pagelayer_editable).on('click', function(e){
924 1965
1966 + e.preventDefault();// Added by Jivan in Actions / Revisions version
1967 +
925 1968 // Hide the context menu
926 1969 jQuery('.pagelayer-right-click-options').hide();
927 1970
928 1971 // Target
@@ -945,12 +1988,15 @@
945 1988
946 1989 var html = '<div class="pagelayer-right-click-options" style="display:none;">'+
947 1990 '<ul>'+
948 1991 '<li><a class="pagelayer-right-edit">Edit</a></li>'+
949 - '<li><a class="pagelayer-right-duplicate">Duplicate</a></li>'+
950 - '<li><a class="pagelayer-right-copy">Copy</a></li>'+
951 - '<li><a class="pagelayer-right-paste">Paste</a></li>'+
952 - '<li><a class="pagelayer-right-delete">Delete</a></li>'+
1992 + '<li><a class="pagelayer-right-duplicate"><i class="far fa-clone" ></i> '+pagelayer_l('Duplicate')+'</a></li>'+
1993 + '<li><a class="pagelayer-right-copy"><i class="far fa-copy" ></i> '+pagelayer_l('Copy')+' <span style="margin-left:10px;opacity:0.6">Ctrl+c</span></a></li>'+
1994 + '<li><a class="pagelayer-right-paste pagelayer-context-disable" title="If the paste is not done correctly then use Ctrl+V"><i class="far fa-clipboard" ></i> '+pagelayer_l('Paste')+' <span style="margin-left:10px;opacity:0.6">Ctrl+v</span></a></li>'+
1995 + '<li><a class="pagelayer-right-delete"><i class="far fa-trash-alt" ></i> '+pagelayer_l('Delete')+'</a></li>'+
1996 + '<li><a class="pagelayer-right-save-global-widget" pro="1"><i class="far fa-save" ></i> '+pagelayer_l('save_global')+'</a></li>'+
1997 + '<li><a class="pagelayer-right-save-section" pro="1"><i class="far fa-heart" ></i> '+pagelayer_l('save_as_section')+'</a></li>'+
1998 + '<li><a class="pagelayer-right-save-global-section" pro="1"><i class="fas fa-globe" ></i> '+pagelayer_l('save_as_global_section')+'</a></li>'+
953 1999 '</ul>'+
954 2000 '</div>';
955 2001
956 2002 jQuery('body').append(html);
@@ -956,13 +2002,18 @@
956 2002 jQuery('body').append(html);
957 2003
958 2004 var $contextMenu = jQuery('.pagelayer-right-click-options');
959 2005
960 - jQuery('.entry-content').on('contextmenu', function(e){
2006 + jQuery(pagelayer_editable).on('contextmenu', function(e){
961 2007
962 2008 var tEle = jQuery(e.target);
963 2009 var jEle = tEle.closest('.pagelayer-ele-wrap').children('.pagelayer-ele');
964 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 +
965 2016 // Get the parent
966 2017 var pId = pagelayer_get_parent(jEle);
967 2018
968 2019 // If we found a parent
@@ -973,26 +2024,89 @@
973 2024 // The basics
974 2025 var id = pagelayer_assign_id(jEle);
975 2026 var tag = pagelayer_tag(jEle);
976 2027
977 - $contextMenu.find('.pagelayer-right-edit').attr('onclick', 'pagelayer_edit_element("[pagelayer-id='+id+']")').html('Edit '+pagelayer_shortcodes[tag]['name']);
2028 + $contextMenu.find('.pagelayer-right-edit').attr('onclick', 'pagelayer_edit_element("[pagelayer-id='+id+']")').html('<i class="far fa-edit" ></i> Edit '+pagelayer_shortcodes[tag]['name']);
978 2029 $contextMenu.find('.pagelayer-right-duplicate').attr('onclick', 'pagelayer_copy_element("[pagelayer-id='+id+']")');
979 2030 $contextMenu.find('.pagelayer-right-copy').attr('onclick', 'pagelayer_copy_select("[pagelayer-id='+id+']")');
980 - $contextMenu.find('.pagelayer-right-paste').attr('onclick', 'pagelayer_paste_element("[pagelayer-id='+id+']")');
981 2031 $contextMenu.find('.pagelayer-right-delete').attr('onclick', 'pagelayer_delete_element("[pagelayer-id='+id+']")');
982 2032
2033 + // If is pagelayer pro
2034 + if(!pagelayer_empty(pagelayer_pro)){
2035 + $contextMenu.find('.pagelayer-right-save-global-widget').attr('onclick', 'pagelayer_save_sections("[pagelayer-id='+id+']", "global_widget")');
2036 + $contextMenu.find('.pagelayer-right-save-section').attr('onclick', 'pagelayer_save_sections("[pagelayer-id='+id+']", "section")');
2037 + $contextMenu.find('.pagelayer-right-save-global-section').attr('onclick', 'pagelayer_save_sections("[pagelayer-id='+id+']", "global_section")');
2038 + }else{
2039 + var pro = $contextMenu.find('[pro="1"]');
2040 +
2041 + if(pro.find('.pagelayer-pro-req').length < 1){
2042 + pro.append('<span class="pagelayer-pro-req">Pro</span>');
2043 + }
2044 +
2045 + pro.css({'color': '#a7a7a7'});
2046 +
2047 + // To stopPropagation
2048 + pro.parent().on('click', function(e){
2049 + e.stopPropagation();
2050 + });
2051 + }
2052 +
2053 + var showPaste = function(){
2054 + if(!pagelayer_empty(pagelayer.copy_selected) && pagelayer_can_copy_to(jEle)){
2055 + $contextMenu.find('.pagelayer-right-paste').removeClass('pagelayer-context-disable');
2056 + $contextMenu.find('.pagelayer-right-paste').attr('onclick', 'pagelayer_paste_element("[pagelayer-id='+id+']")');
2057 + }
2058 + }
2059 +
983 2060 // Are we to hide the paste ?
984 - if(!pagelayer_empty(pagelayer.copy_selected) && pagelayer_can_copy_to(jEle)){
985 - //console.log(pagelayer_can_copy_to(jEle));
986 - $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);
987 2073 }else{
988 - $contextMenu.find('.pagelayer-right-paste').parent().hide();
2074 + showPaste();
989 2075 }
990 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 +
991 2105 $contextMenu.css({
992 2106 display: "block",
993 - left: e.pageX,
994 - top: e.pageY
2107 + left: hPosition,
2108 + top: vPosition
995 2109 });
996 2110
997 2111 return false;
998 2112
@@ -1007,9 +2121,14 @@
1007 2121 function pagelayer_set_parent(jEle, id){
1008 2122 jEle.attr('pagelayer-parent', id);
1009 2123 };
1010 2124
1011 -// 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
1012 2131 function pagelayer_get_parent(jEle){
1013 2132 return jEle.attr('pagelayer-parent');
1014 2133 };
1015 2134
@@ -1030,10 +2149,13 @@
1030 2149 // Add the class
1031 2150 body.addClass('pagelayer-screen-'+mode);
1032 2151
1033 2152 // Add the class to the button
1034 - pagelayer.$$('.pagelayer-mode-button').removeClass('fa-'+current).addClass('fa-'+mode);
2153 + pagelayer.$$('.pagelayer-mode-button').removeClass('pli-'+current).addClass('pli-'+mode);
1035 2154
2155 + // Add the class to the button
2156 + pagelayer.$$('.pagelayer-prop-screen').removeClass('pli-'+current).addClass('pli-'+mode);
2157 +
1036 2158 // Trigger screen change if any
1037 2159 pagelayer.$$('.pagelayer-elp-screen').trigger('pagelayer-screen-changed');
1038 2160
1039 2161 };
@@ -1049,27 +2171,745 @@
1049 2171 }
1050 2172 }
1051 2173 }
1052 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 +
1053 2324 // Handle key press events
1054 -jQuery(document).keydown(function(event){
2325 +pagelayer.gDocument.keydown(function(event){
1055 2326 //alert(String.fromCharCode(event.which));
1056 2327
2328 + var tEle = jQuery(event.target);
2329 + var editable = tEle.closest('[contenteditable="true"]');
2330 + var tooltip = pagelayer.$$('.pagelayer-widget-tooltip');
2331 +
2332 + // Enter handle
2333 + if(event.keyCode == 13){
2334 +
2335 + var jEle = tEle.closest('.pagelayer-ele');
2336 + var tag = pagelayer_tag(jEle);
2337 +
2338 + // Add selected widget from widget list
2339 + if(tooltip.is(':visible')){
2340 + tooltip.find('.pagelayer-list-widget-active:visible').click();
2341 + return;
2342 + }
2343 +
2344 + if( pagelayer_empty(pagelayer_active.el) || !('id' in pagelayer_active.el) ){
2345 + return;
2346 + }
2347 +
2348 + var active_el_par = pagelayer_active.el.$.parent();
2349 +
2350 + // Create and add text widget
2351 + var addTitle = function(insertAfter){
2352 + var ele = jQuery('<div pagelayer-tag="pl_text"></div>');
2353 + insertAfter.after(ele);
2354 + return pagelayer_ele_by_id( pagelayer_onadd(ele) );
2355 + }
2356 +
2357 + // If we have an active element then add text widget
2358 + if(!(tEle.is('input, textarea') || editable.length > 0)){
2359 +
2360 + event.preventDefault();
2361 +
2362 + var activeTag = pagelayer_active.el.tag;
2363 +
2364 + // If is row or column ?
2365 + if(activeTag == 'pl_row' || activeTag == 'pl_col'){
2366 + return;
2367 + }
2368 +
2369 + var hEle = addTitle(active_el_par);
2370 + hEle.click();
2371 + hEle.find('[pagelayer-editable]').focus();
2372 +
2373 + // Ensure the column is not empty
2374 + pagelayer_empty_col(hEle.closest('.pagelayer-col-holder'));
2375 + return;
2376 + }
2377 +
2378 + if( (tag != 'pl_text' && tag != 'pl_heading') || editable.length < 1 || event.shiftKey){
2379 + return;
2380 + }
2381 +
2382 + var selection = window.getSelection();
2383 + var range = selection.getRangeAt(0);
2384 +
2385 + // We are within the list tag
2386 + if(jQuery(range.startContainer).closest('[pagelayer-editable] li').length > 0){
2387 + return;
2388 + }
2389 +
2390 + event.preventDefault();
2391 +
2392 + var lastChild = editable[0].lastChild;
2393 + var startContainer = range.startContainer;
2394 +
2395 + if(startContainer.nodeType == Node.TEXT_NODE && startContainer.parentNode != editable[0]){
2396 + startContainer = startContainer.parentNode;
2397 + }
2398 +
2399 + range.setEndAfter(lastChild);
2400 +
2401 + var val = range.cloneContents();
2402 + var selfEle = jQuery('<div>').append(val);
2403 + var selContent = selfEle.html();
2404 + var selfFC = selfEle[0].firstChild;
2405 + var emptyContent = false;
2406 +
2407 + if(selfFC == null || pagelayer_empty(selContent)){
2408 + selContent = '<p><br></p>';
2409 + emptyContent = true;
2410 + }else if(selfFC.nodeType == Node.TEXT_NODE){
2411 + selContent = '<p>'+selContent+'</p>';
2412 + }else if(selfEle.text() == '' && selfEle.find('br').length < 1){
2413 + selContent = '<p><br></p>';
2414 + emptyContent = true;
2415 + }else if(selfEle.text().trim() == ''){
2416 + selContent = selContent.replace(/\s+/, "\u00A0");
2417 + emptyContent = true;
2418 + }
2419 +
2420 + range.deleteContents();
2421 +
2422 + if( jQuery(startContainer).is(':first-child') && jQuery(startContainer).is(':empty') ){
2423 + jQuery(startContainer).html('<br>');
2424 + }else if( jQuery(startContainer).is(':empty') ){
2425 + jQuery(startContainer).remove();
2426 + }
2427 +
2428 + // If editor is empty
2429 + if( editable.is(':empty') ){
2430 + editable.html('<p><br></p>');
2431 + }
2432 +
2433 + editable.trigger('input');
2434 + editable.blur();
2435 +
2436 + // Create and add text widget
2437 + var ele;
2438 + if(emptyContent){
2439 + ele = addTitle(jEle.parent());
2440 + }else{
2441 + var id = pagelayer_copy_element(jEle);
2442 + ele = pagelayer_ele_by_id(id);
2443 + }
2444 +
2445 + ele.click();
2446 + var editorArea = ele.find('[pagelayer-editable]');
2447 + editorArea.html(selContent);
2448 + editorArea.find('p:empty').remove();
2449 + editorArea.focus().trigger('input');
2450 + }
2451 +
2452 + // ctrl+s handle
2453 + if(event.keyCode == 83 && event.ctrlKey){
2454 + event.preventDefault();
2455 + pagelayer.$$('.pagelayer-iframe-top-bar').find('.pagelayer-update-button').click();
2456 + }
2457 +
2458 + // ctrl+d handle
2459 + if(event.keyCode == 68 && event.ctrlKey){
2460 +
2461 + // If we have an active element
2462 + if( pagelayer_active.el && pagelayer_active.el.id ){
2463 + event.preventDefault();
2464 + pagelayer_copy_element('[pagelayer-id='+pagelayer_active.el.id+']');
2465 + }
2466 +
2467 + }
2468 +
2469 + // Delete handler for text widget
2470 + if(event.keyCode == 46 && editable.length > 0){
2471 + var jEle = tEle.closest('.pagelayer-ele-wrap');
2472 + var tag = pagelayer_tag(jEle);
2473 + var next = jEle.next();
2474 + var pTag = pagelayer_tag(next);
2475 +
2476 + var selection = window.getSelection();
2477 + var orgRange = selection.getRangeAt(0);
2478 + var cloneRange = orgRange.cloneRange();
2479 +
2480 + if((tag != 'pl_text' && tag != 'pl_heading') || next.length < 1 || pTag != tag || !cloneRange.collapsed ){
2481 + return;
2482 + }
2483 +
2484 + var currentOffset = pagelayer_getCaretCharacterOffsetWithin(editable[0]);
2485 + cloneRange.selectNodeContents(editable[0]);
2486 + var caretOffset = cloneRange.toString().length;
2487 +
2488 + if(currentOffset != caretOffset){
2489 + return;
2490 + }
2491 +
2492 + var nextHtml = next.find('[pagelayer-editable="text"]').html();
2493 + editable.append(nextHtml);
2494 + pagelayer_delete_element(next.children('.pagelayer-ele'));
2495 + }
2496 +
2497 + // Backspace handler
2498 + if(event.keyCode == 8 && editable.length > 0){
2499 + var jEle = tEle.closest('.pagelayer-ele-wrap');
2500 + var tag = pagelayer_tag(jEle);
2501 + var prev = jEle.prev();
2502 +
2503 + if((tag != 'pl_text' && tag != 'pl_heading') || prev.length < 1){
2504 + return;
2505 + }
2506 +
2507 + var pTag = pagelayer_tag(prev);
2508 + var selection = window.getSelection();
2509 +
2510 + if (selection == null || selection.rangeCount <= 0) return null;
2511 +
2512 + var range1 = selection.getRangeAt(0);
2513 +
2514 + if(pTag != tag || range1.startOffset != 0){
2515 + return;
2516 + }
2517 +
2518 + var prevArea = prev.find('[pagelayer-editable="text"]');
2519 +
2520 + if( pagelayer_getCaretCharacterOffsetWithin(editable[0]) != 0 || prevArea.length < 1){
2521 + return;
2522 + }
2523 +
2524 + //event.preventDefault();
2525 + var html = editable.html();
2526 + editable.blur();
2527 + prev.children('.pagelayer-ele').click();
2528 + prevArea.click();
2529 +
2530 + var newSel = window.getSelection();
2531 + var newRange = newSel.getRangeAt(0);
2532 + var lastChild = jQuery(prevArea[0].lastChild);
2533 +
2534 + prevArea.append(html);
2535 + prevArea.trigger('input');
2536 +
2537 + if(lastChild.length > 0){
2538 + if(lastChild[0].nextSibling != null){
2539 + newRange.setStart(lastChild[0].nextSibling, 0);
2540 + }else{
2541 + newRange.setStartAfter(lastChild[0]);
2542 + }
2543 + }
2544 +
2545 + newRange.collapse(true);
2546 + newSel.removeAllRanges();
2547 + newSel.addRange(newRange);
2548 +
2549 + pagelayer_delete_element(jEle.children('.pagelayer-ele'));
2550 +
2551 + }
2552 +
2553 + if(tooltip.is(':visible')){
2554 +
2555 + // Select previous widget in widget tooltip
2556 + if(event.key == 'ArrowUp' || event.key == 'ArrowLeft' || (event.key == 'Tab' && event.shiftKey)){
2557 +
2558 + event.preventDefault();
2559 +
2560 + var current = tooltip.find('.pagelayer-list-widget-active:visible'),
2561 + prev = current.prevAll('.pagelayer-shortcode-holder:visible');
2562 +
2563 + if(event.key == 'ArrowUp'){
2564 + var _prev = prev,
2565 + cOffset = current.offset();
2566 + findNext = false;
2567 +
2568 + var searchNext = function(nEle){
2569 +
2570 + var nOffset = nEle.offset();
2571 + var nBottom = nOffset.top + nEle.height();
2572 +
2573 + if(nBottom > cOffset.top){
2574 + return true;
2575 + }
2576 +
2577 + prev = nEle;
2578 + findNext = true;
2579 +
2580 + // Current element left set +20 to manager previous scale (css) element on hover
2581 + if(cOffset.left + 20 >= nOffset.left){
2582 + return false;
2583 + }
2584 +
2585 + return true;
2586 + }
2587 +
2588 + _prev.each(function(){
2589 + return searchNext(jQuery(this));
2590 + });
2591 +
2592 + if(!findNext){
2593 + var gNext = current.parent().prevAll('.pagelayer-widget-group:visible').first();
2594 + _prev = gNext.children('.pagelayer-shortcode-holder:visible');
2595 +
2596 + jQuery(_prev.get().reverse()).each(function(){
2597 + return searchNext(jQuery(this));
2598 + });
2599 + }
2600 +
2601 + }
2602 +
2603 + if(prev.length < 1){
2604 + prev = current.parent().prevAll('.pagelayer-widget-group:visible').first().find('.pagelayer-shortcode-holder:visible').last();
2605 + }
2606 +
2607 + if(prev.length < 1){
2608 + return;
2609 + }
2610 +
2611 + prev.first().trigger('widget_active');
2612 + }
2613 +
2614 + // Select next widget in widget tooltip
2615 + if(event.key == 'ArrowDown' || event.key == 'ArrowRight' || (event.key == 'Tab' && !event.shiftKey)){
2616 +
2617 + event.preventDefault();
2618 +
2619 + var current = tooltip.find('.pagelayer-list-widget-active:visible');
2620 + next = current.nextAll('.pagelayer-shortcode-holder:visible');
2621 +
2622 + if(event.key == 'ArrowDown'){
2623 +
2624 + var _next = next,
2625 + cOffset = current.offset(),
2626 + findNext = false;
2627 +
2628 + var searchNext = function(nEle){
2629 + var nOffset = nEle.offset();
2630 + var cBottom = cOffset.top + current.height();
2631 +
2632 + if(cBottom > nOffset.top){
2633 + return true;
2634 + }
2635 +
2636 + next = nEle;
2637 + findNext = true;
2638 +
2639 + // Current element left set -20 to manager next scale (css) element on hover
2640 + if(cOffset.left - 20 <= nOffset.left){
2641 + return false;
2642 + }
2643 +
2644 + return true;
2645 + }
2646 +
2647 + _next.each(function(){
2648 + return searchNext(jQuery(this));
2649 + });
2650 +
2651 + if(!findNext){
2652 + var gNext = current.parent().nextAll('.pagelayer-widget-group:visible').first();
2653 + _next = gNext.children('.pagelayer-shortcode-holder:visible');
2654 + _next.each(function(){
2655 + return searchNext(jQuery(this));
2656 + });
2657 + }
2658 +
2659 + }
2660 +
2661 + if(next.length < 1){
2662 + next = current.parent().nextAll('.pagelayer-widget-group:visible').first().find('.pagelayer-shortcode-holder:visible');
2663 + }
2664 +
2665 + if(next.length < 1){
2666 + return;
2667 + }
2668 +
2669 + next.first().trigger('widget_active');
2670 +
2671 + }
2672 + }
2673 +
2674 + // Is this in the editable area ?
2675 + if (tEle.is('input, textarea') || editable.length > 0) {
2676 + return;
2677 + }
2678 +
1057 2679 // Delete
1058 2680 if(event.keyCode == 46){
1059 2681 pagelayer_delete_element('[pagelayer-active]');
1060 2682 }
1061 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 +
1062 2694 });
1063 2695
2696 +// Handle Copy of content
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 + }
2704 +
2705 + if(selectedText.length > 0){
2706 + return;
2707 + }
2708 +
2709 + if(pagelayer_active.el && pagelayer_active.el.id){
2710 + copyEvent.preventDefault();
2711 +
2712 + // Save the active element id
2713 + pagelayer_copy_select("[pagelayer-id='"+pagelayer_active.el.id+"']", copyEvent);
2714 +
2715 + }
2716 +
2717 +});
2718 +
2719 +// This is for preload clipboard data
2720 +// Content can be copied from outside
2721 +var pagelayerIsParentBlured = true;
2722 +jQuery(window).on('focus', function(e){
2723 + if(pagelayerIsParentBlured){
2724 + pagelayer_copy_from_clipboard();
2725 + }
2726 + pagelayerIsParentBlured = true;
2727 +});
2728 +
2729 +jQuery(window.parent).on('focus', function(){
2730 + pagelayerIsParentBlured = false;
2731 +});
2732 +
2733 +// Handle Paste in the editor
2734 +jQuery(document).on('paste', function(pasteEvent){
2735 +
2736 + var pEle_target = jQuery((pasteEvent.originalEvent || pasteEvent).target);
2737 + var tag = pagelayer_tag(pEle_target.closest('[pagelayer-id]'));
2738 + var clipboardData = (pasteEvent.originalEvent || pasteEvent).clipboardData;
2739 + var items = clipboardData.items;
2740 +
2741 + var pagelayer_ajax_func = {};
2742 + var contenteditable = false;
2743 + var pasteWidget = false;
2744 +
2745 + if( pEle_target.closest('[contenteditable="true"]').length > 0 || pEle_target.is('input, textarea') ){
2746 + pEle_target = pEle_target.closest('[contenteditable="true"], input, textarea');
2747 + contenteditable = true;
2748 + }
2749 +
2750 + if( items.length < 1 || (items.length == 1 && pagelayer_empty(clipboardData.getData(items[0].type))) ){
2751 + pasteWidget = true;
2752 + }
2753 +
2754 + // This function for ajax before send call back
2755 + pagelayer_ajax_func['beforeSend'] = function(xhr){
2756 +
2757 + // If target is not content editable
2758 + if( pagelayer_empty(contenteditable) ){
2759 +
2760 + // If we dont have an active element then return false and stop ajax
2761 + if( !(pagelayer_active.el && pagelayer_active.el.id) ){
2762 + pagelayer_show_msg(pagelayer_l('active_ele_paste_msg'));
2763 + return false;
2764 + }
2765 +
2766 + pagelayer.copy_selected = jQuery('<div pagelayer-tag="pl_image"></div>');
2767 +
2768 + // Is it to be pastable
2769 + if(!pagelayer_can_copy_to('[pagelayer-id="'+pagelayer_active.el.id+'"]')){
2770 + pagelayer.copy_selected = '';
2771 + return false;
2772 + }
2773 + }
2774 +
2775 + pEle_target.css({'opacity': '0.33' , 'transition' : '0.1s'});
2776 + }
2777 +
2778 + // This function for ajax success call back
2779 + pagelayer_ajax_func['success'] = function(obj){
2780 +
2781 + // Successfully Uploaded
2782 + if(obj['success']){
2783 +
2784 + // For content editable e.g. Rich Text
2785 + if( !pagelayer_empty(contenteditable) ){
2786 + document.execCommand('insertImage', false, obj['data']['url']);
2787 +
2788 + // For our widgets
2789 + }else{
2790 +
2791 + if(pagelayer_empty(pagelayer_active.el) || pagelayer_empty(pagelayer_active.el.id)){
2792 + pagelayer_show_msg('active_ele_paste_msg');
2793 + return;
2794 + }
2795 +
2796 + var fTo = pagelayer_can_copy_to('[pagelayer-id="'+pagelayer_active.el.id+'"]');
2797 + // We need to empty pagelayer.copy_selected
2798 + pagelayer.copy_selected = '';
2799 +
2800 + var pasteAfter = function(){
2801 +
2802 + // Prevent to add action history
2803 + pagelayer.history_action = false;
2804 +
2805 + // Create image html
2806 + var html = pagelayer_create_sc('pl_image');
2807 +
2808 + pagelayer_set_atts(html, 'id', obj['data']['id']);
2809 + pagelayer_set_tmp_atts(html, 'id-url', obj['data']['url']);
2810 +
2811 + // Allow to add action history
2812 + pagelayer.history_action = true;
2813 +
2814 + // Copy the element
2815 + var id = pagelayer_copy_element(html, fTo);
2816 + jQuery('[pagelayer-id="'+id+'"]').click();
2817 +
2818 + };
2819 +
2820 + var replaceURL = function(){
2821 +
2822 + // Finding widget image setting using id of jEle. Finding image editor setting from all of the other settings.
2823 + var row = pagelayer.$$('[pagelayer-element-id='+pagelayer_active.el.id+']').find('.pagelayer-elp-image').eq(0).parent().parent();
2824 +
2825 + row.find('.pagelayer-elp-image').css('background-image', 'url(\''+obj['data']['url']+'\')');
2826 +
2827 + // To remove past temp attr so that they are not involve in future temp values
2828 + var cname = row.attr('pagelayer-elp-name');
2829 + var old = _pagelayer_img_tmp_atts(row);
2830 + delete old[cname+'-url'];
2831 +
2832 + for(var x in obj['data']['sizes']){
2833 + _pagelayer_set_tmp_atts(row, x+'-url', obj['data']['sizes'][x]['url']);
2834 + delete old[cname+'-'+x+'-url'];
2835 + }
2836 +
2837 + for(var x in old){
2838 + _pagelayer_set_tmp_atts(row, x+'-url', '');
2839 + }
2840 +
2841 + // Save and render
2842 + _pagelayer_set_tmp_atts(row, 'url', obj['data']['url']);
2843 + _pagelayer_set_atts(row, obj['data']['id']);
2844 + };
2845 +
2846 + // Image paste confirmation.
2847 + if(!pagelayer_empty(pagelayer_active.el.tag) && pagelayer_active.el.tag == 'pl_image'){
2848 +
2849 + pagelayer_confirmation_box(pagelayer_l('img_paste_conf'), replaceURL, pasteAfter, pagelayer_l('replace_img'), pagelayer_l('paste_after'));
2850 +
2851 + }else{
2852 + pasteAfter();
2853 + }
2854 + }
2855 +
2856 + // Some error occured
2857 + }else{
2858 + pagelayer_show_msg(obj['data']['message'], 'error', 10000);
2859 + }
2860 + }
2861 +
2862 + // This function for ajax complete call back
2863 + pagelayer_ajax_func['complete'] = function(xhr){
2864 + //console.log(xhr);
2865 + pEle_target.css({'opacity': '1' , 'transition' : '0.1s'});
2866 + }
2867 +
2868 + var findImg = pagelayer_editable_paste_handler(pasteEvent, pagelayer_ajax_func);
2869 +
2870 + if(pagelayer_empty(findImg) || pasteWidget){
2871 +
2872 + // Check the active element
2873 + if(pagelayer_active.el && pagelayer_active.el.id && pagelayer_active.el.tag != 'pl_post_props'){
2874 +
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 +
2894 + }
2895 +
2896 + }else{
2897 + pagelayer_show_msg(pagelayer_l('no_active_ele_paste'));
2898 + }
2899 + }
2900 +});
2901 +
1064 2902 // Delete an element as per the selector
1065 2903 function pagelayer_delete_element(selector){
1066 2904 var jEle = jQuery(selector);
2905 + var nearBy = jEle;
1067 2906
1068 2907 // Anything found ?
1069 2908 if(jEle.length > 0){
1070 2909
1071 2910 var id = pagelayer_assign_id(jEle);
2911 + var sc = pagelayer_tag(jEle);
1072 2912
1073 2913 // Is there a wrap
1074 2914 var wrap = jQuery('[pagelayer-wrap-id="'+id+'"]');
1075 2915
@@ -1074,25 +2914,124 @@
1074 2914 var wrap = jQuery('[pagelayer-wrap-id="'+id+'"]');
1075 2915
1076 2916 var par = wrap.parent();
1077 2917
2918 + // Save this element in history action
2919 + if(pagelayer.history_action){
2920 + var cEle = pagelayer_near_by_ele(id, sc);
2921 +
2922 + nearBy = jQuery(cEle.cEle);
2923 +
2924 + // To save in history, we need to save only element not the wraps as we call setup if we redo or undo
2925 + jEle.find('style').remove();
2926 + jEle.find('.pagelayer-ele-overlay').remove();
2927 +
2928 + // Unwrap the wraps
2929 + jEle.find('.pagelayer-ele').each(function (){
2930 + var ele = jQuery(this);
2931 + if(ele.parent().is('.pagelayer-ele-wrap')){
2932 + ele.unwrap();
2933 + }
2934 + });
2935 +
2936 + pagelayer_history_action_push({
2937 + 'title' : pagelayer_shortcodes[sc]['name'],
2938 + 'action' : 'Deleted',
2939 + 'pl_id' : id,
2940 + 'html' : jEle[0].outerHTML,
2941 + 'cEle' : cEle
2942 + });
2943 + }
2944 +
1078 2945 wrap.remove();
1079 2946
1080 2947 pagelayer_empty_col(par);
1081 2948
1082 - 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)){
1083 2951 pagelayer.$$('.pagelayer-elpd-close').click();
1084 2952 }
1085 2953
1086 2954 }
1087 - pagelayer_isDirty = true;
2955 +
2956 + // Do Pagelayer dirty
2957 + pagelayer_do_dirty(nearBy);
1088 2958 };
1089 2959
1090 2960 // Select an element
1091 -function pagelayer_copy_select(selector){
1092 - pagelayer.copy_selected = selector;
2961 +function pagelayer_copy_select(selector, copyEvent = false){
2962 +
2963 + var sEle = jQuery(selector);
2964 +
2965 + if(sEle.length < 1){
2966 + pagelayer_show_msg( pagelayer_l('invalid_copy_ele_msg'));
2967 + return;
2968 + }
2969 +
2970 + var tag = pagelayer_tag(sEle);
2971 +
2972 + if(
2973 + pagelayer_empty(tag) ||
2974 + pagelayer_empty(pagelayer_shortcodes[tag]) ||
2975 + !pagelayer_empty(pagelayer_shortcodes[tag]['not_visible'])
2976 + ){
2977 + pagelayer_show_msg( pagelayer_l('invalid_copy_ele_msg'));
2978 + return;
2979 + }
2980 +
2981 + var eHtml = sEle[0].outerHTML;
2982 +
2983 + pagelayer.copy_selected = eHtml;
2984 +
2985 + // To hide Cliboard warning while pasting
2986 + pagelayerClipboardReadable = true;
2987 +
2988 + if(copyEvent){
2989 + // set clipbord data
2990 + (copyEvent.originalEvent || copyEvent).clipboardData.setData('text/plain', eHtml);
2991 + pagelayer_show_msg(pagelayer_l('copied_msg'));
2992 +
2993 + return;
2994 + }
2995 +
2996 + // Copy element to clipboard
2997 + pagelayer_copy_ele_to_clipboard(eHtml);
2998 +
1093 2999 }
1094 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 +
1095 3034 function pagelayer_can_copy_to(to){
1096 3035 var jEle = jQuery(pagelayer.copy_selected);
1097 3036 var tEle = jQuery(to);
1098 3037
@@ -1098,8 +3037,14 @@
1098 3037
1099 3038 var eTag = pagelayer_tag(jEle);
1100 3039 var tTag = pagelayer_tag(tEle);
1101 3040 //console.log(eTag+' - '+tTag);
3041 +
3042 + // Invalid HTML copied
3043 + if(pagelayer_empty(eTag)){
3044 + return false;
3045 + }
3046 +
1102 3047 // Final to
1103 3048 var fTo;
1104 3049
1105 3050 // Selected element is a Row, can go only after a row
@@ -1125,10 +3070,26 @@
1125 3070
1126 3071 }
1127 3072
1128 3073 // Select an element
1129 -function pagelayer_paste_element(to){
3074 +function pagelayer_paste_element(to, syncClipboard = true){
1130 3075
3076 + // Wait for clipboard sync
3077 + // This is for context paste
3078 + if(syncClipboard){
3079 + if(pagelayerClipboardLoading){
3080 + setTimeout(function(){
3081 + pagelayer_paste_element(to);
3082 + }, 200);
3083 + return false;
3084 + }
3085 +
3086 + // There may be some problems reading the clipboard
3087 + if(pagelayerClipboardReadable !== true){
3088 + pagelayer_show_msg('If the paste is not done correctly then use Ctrl+V', 'warning');
3089 + }
3090 + }
3091 +
1131 3092 var fTo = pagelayer_can_copy_to(to);
1132 3093
1133 3094 // Is it a valid to
1134 3095 if(!fTo){
@@ -1134,35 +3095,63 @@
1134 3095 if(!fTo){
1135 3096 return false;
1136 3097 }
1137 3098
1138 - pagelayer_copy_element(pagelayer.copy_selected, fTo);
3099 + if(!pagelayer_empty(pagelayer.copy_selected)){
3100 + pagelayer_copy_element(pagelayer.copy_selected, fTo);
3101 + return true;
3102 + }
3103 +
3104 + pagelayer_show_msg(pagelayer_l('no_copied'));
3105 +
3106 + return false;
1139 3107 }
1140 3108
3109 +var pagelayerClipboardLoading = false;
3110 +var pagelayerClipboardReadable = true;
3111 +// If copy_selected is empty then copy data from localStorage
3112 +async function pagelayer_copy_from_clipboard(){
3113 +
3114 + if(pagelayerClipboardLoading){
3115 + return;
3116 + }
3117 +
3118 + if (navigator.clipboard && window.isSecureContext) {
3119 + try {
3120 +
3121 + pagelayerClipboardLoading = true;
3122 +
3123 + const text = await navigator.clipboard.readText();
3124 + var pEle = jQuery(text);
3125 +
3126 + if(pEle.length > 0 && !pagelayer_empty(pagelayer_tag(pEle)) ){
3127 + pagelayer.copy_selected = pEle;
3128 + }
3129 +
3130 + pagelayerClipboardLoading = false;
3131 + pagelayerClipboardReadable = true;
3132 +
3133 + } catch (err) {
3134 + pagelayerClipboardLoading = false;
3135 + pagelayerClipboardReadable = 'Clipboard readText failed';
3136 + //console.warn("Clipboard readText failed", err);
3137 + }
3138 + } else {
3139 + pagelayerClipboardReadable = 'Clipboard API not available or insecure context.';
3140 + // console.warn("Clipboard API not available or insecure context.");
3141 + }
3142 +}
3143 +
1141 3144 // Copy an element
1142 3145 // Note : insertAfter should always be an pagelayer-ele
1143 3146 function pagelayer_copy_element(selector, insertAfter){
1144 3147 var src = jQuery(selector);
1145 - var html = src[0].outerHTML;
1146 3148 var tag = pagelayer_tag(src);
1147 3149 insertAfter = insertAfter || src;
1148 3150 insertAfter = insertAfter.parent();
1149 3151
1150 - var jEle = jQuery(html);
1151 - jEle.removeAttr('pagelayer-id');
1152 - jEle.find('[pagelayer-id]').removeAttr('pagelayer-id');
1153 - jEle.find('[pagelayer-parent]').removeAttr('pagelayer-parent');// Remove the parent attribute as it will be reset during pagelayer_element_setup
1154 - jEle.find('style').remove();
1155 - jEle.find('.pagelayer-ele-overlay').remove();
3152 + var jEle = pagelayer_element_unsetup(src);
1156 3153
1157 - // Unwrap the wraps
1158 - jEle.find('.pagelayer-ele').each(function (){
1159 - var ele = jQuery(this);
1160 - if(ele.parent().is('.pagelayer-ele-wrap')){
1161 - ele.unwrap();
1162 - }
1163 - });
1164 -
1165 3154 // Give it an ID
1166 3155 var id = pagelayer_assign_id(jEle);
1167 3156
1168 3157 jQuery(insertAfter).after(jEle);
@@ -1168,8 +3157,24 @@
1168 3157 jQuery(insertAfter).after(jEle);
1169 3158
1170 3159 pagelayer_element_setup('[pagelayer-id='+id+'], [pagelayer-id='+id+'] .pagelayer-ele', true);
1171 3160
3161 + if(pagelayer_is_group(tag)){
3162 + pagelayer_sc_render(jEle);
3163 + }
3164 +
3165 + // Save this element in history action
3166 + if(pagelayer.history_action){
3167 + var cEle = pagelayer_near_by_ele(id, tag);
3168 + pagelayer_history_action_push({
3169 + 'title' : pagelayer_shortcodes[tag]['name'],
3170 + 'action' : 'Copied',
3171 + 'pl_id' : id,
3172 + 'html' : jEle[0].outerHTML,
3173 + 'cEle' : cEle
3174 + });
3175 + }
3176 +
1172 3177 //If column then renumber columns
1173 3178 if(tag == 'pl_col'){
1174 3179 var row = src.parent().closest('.pagelayer-row');
1175 3180 pagelayer_renumber_col(row);
@@ -1174,18 +3179,366 @@
1174 3179 var row = src.parent().closest('.pagelayer-row');
1175 3180 pagelayer_renumber_col(row);
1176 3181 }
1177 3182
1178 - pagelayer_isDirty = true;
3183 + pagelayer_do_dirty(jEle);
1179 3184
1180 3185 return id;
1181 3186 };
1182 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 +
1183 3484 // Language key
1184 3485 function pagelayer_l(k){
3486 + if(k in pagelayer_lang){
3487 + return pagelayer_lang[k];
3488 + }
1185 3489 return k;
1186 3490 }
1187 3491
3492 +// Get props based on the tag
3493 +function pagelayer_get_props(jEle){
3494 + var props = pagelayer_shortcodes[pagelayer_tag(jEle)];
3495 + return props;
3496 +}
3497 +
3498 +// Get all props based on the tag but in a single structure
3499 +function pagelayer_make_props_ref(){
3500 +
3501 + // Loop through pagelayer_shortcodes
3502 + for(var tag in pagelayer_shortcodes){
3503 +
3504 + var all_props = pagelayer_shortcodes[tag];
3505 + pagelayer.props_ref[tag] = {};
3506 +
3507 + // Loop through all props
3508 + for(var i in pagelayer_tabs){
3509 +
3510 + var tab = pagelayer_tabs[i];
3511 +
3512 + for(var section in all_props[tab]){
3513 +
3514 + var props = section in pagelayer_shortcodes[tag] ? pagelayer_shortcodes[tag][section] : pagelayer_styles[section];
3515 +
3516 + // In case of widgets its possible !
3517 + if(pagelayer_empty(props)){
3518 + continue;
3519 + }
3520 +
3521 + for(var x in props){
3522 +
3523 + // Create an easy REFERENCE for access
3524 + pagelayer.props_ref[tag][x] = props[x];
3525 +
3526 + // Screen option REFERENCE is also needed for lookup
3527 + if('screen' in props[x]){
3528 + pagelayer.props_ref[tag][x+'_tablet'] = props[x];
3529 + pagelayer.props_ref[tag][x+'_mobile'] = props[x];
3530 + }
3531 +
3532 + }
3533 + }
3534 +
3535 + }
3536 +
3537 + }
3538 +
3539 +}
3540 +
1188 3541 // Set the given jELE as active
1189 3542 function pagelayer_set_active(jEle){
1190 3543
1191 3544 // Make all other element as inactive
@@ -1212,13 +3565,13 @@
1212 3565 function pagelayer_create_sc(sc){
1213 3566
1214 3567 var html;
1215 3568 var _sc = pagelayer_sc(sc);
1216 - var func = window['pagelayer_sc_'+sc];
3569 + var func = window['pagelayer_create_sc_'+sc];
1217 3570
1218 3571 // Generate the HTML
1219 3572 if(typeof func == 'function'){
1220 - html = window['pagelayer_sc_'+sc]();
3573 + html = window['pagelayer_create_sc_'+sc]();
1221 3574 }else{
1222 3575 html = '<div '+pagelayer_sc_atts('pagelayer-'+_sc)+'></div>';
1223 3576 }
1224 3577
@@ -1283,16 +3636,88 @@
1283 3636
1284 3637 return jEle.attr('pagelayer-tag');
1285 3638 }
1286 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 +
1287 3704 // Gets a single attribute value
1288 3705 function pagelayer_get_att(jEle, att){
1289 - 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;
1290 3711 };
1291 3712
1292 3713 // Gets a single attribute value
1293 3714 function pagelayer_get_tmp_att(jEle, att){
1294 - 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;
1295 3720 };
1296 3721
1297 3722 // This function will just set atts and not do anything else
1298 3723 // Atts can be string or object. If its string, then val is needed
@@ -1321,8 +3746,9 @@
1321 3746 var all_props = pagelayer_shortcodes[tag];//console.log(tag);console.log(jEle);
1322 3747 var trigger_props = {};
1323 3748 var no_val = {};
1324 3749 var defaults = {};
3750 + var _props = {};
1325 3751
1326 3752 // Loop through all props
1327 3753 for(var i in pagelayer_tabs){
1328 3754
@@ -1337,15 +3763,39 @@
1337 3763 if('default' in props[x]){
1338 3764 defaults[x] = 1;
1339 3765 }
1340 3766
3767 + // Create an easy REFERENCE for access
3768 + _props[x] = props[x];
3769 +
3770 + // Screen option REFERENCE is also needed for lookup
3771 + if('screen' in _props[x]){
3772 + _props[x+'_tablet'] = props[x];
3773 + _props[x+'_mobile'] = props[x];
3774 + }
3775 +
1341 3776 // Dont set any val, but we set temp value
1342 3777 if('no_val' in props[x]){
1343 3778 no_val[x] = 1;
1344 3779 }
1345 3780
1346 - if('req' in props[x] || 'show' in props[x]){
3781 + if('req' in props[x] || 'show' in props[x]){
1347 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 +
1348 3798 for(var showParam in show){
1349 3799 var val = show[showParam];
1350 3800 var except = showParam.substr(0, 1) == '!' ? true : false;
1351 3801 showParam = except ? showParam.substr(1) : showParam;
@@ -1359,8 +3809,10 @@
1359 3809 }
1360 3810
1361 3811 }
1362 3812
3813 + var ref_data = pagelayer_el_data_ref(jEle);
3814 +
1363 3815 for(var x in atts){
1364 3816
1365 3817 // Are we to trigger change
1366 3818 if(x in trigger_props){
@@ -1368,44 +3820,57 @@
1368 3820 }
1369 3821
1370 3822 //console.log(x+'-'+atts[x]);
1371 3823
3824 + // Is this a pro feature and we are not pro ? Then we dont do anything and continue !
3825 + if(!pagelayer_empty(_props[x]) && 'pro' in _props[x] && pagelayer_empty(pagelayer_pro)){
3826 + continue;
3827 + }
3828 +
1372 3829 if(x in no_val){
1373 3830 pagelayer_set_tmp_atts(jEle, x, atts[x]);
1374 3831 continue;
1375 3832 }
1376 3833
3834 + // Record History
3835 + if(pagelayer.history_action){
3836 + var old_val = pagelayer_get_att(jEle, x) || '';
3837 + var label = x;
3838 +
3839 + if(x in _props && 'label' in _props[x]){
3840 + label = _props[x]['label'];
3841 + }
3842 +
3843 + pagelayer_history_action_push({
3844 + 'title' : all_props['name'],
3845 + 'subTitle' : label,
3846 + 'action' : 'Edited',
3847 + 'attrType' : 'a_attr',
3848 + 'pl_id' : pagelayer_id(jEle),
3849 + 'atts' : x,
3850 + 'oldVal' : old_val,
3851 + 'newVal' : atts[x]
3852 + });
3853 + }
3854 +
1377 3855 // Remove the attribute if its BLANK and there is no default for it
1378 3856 // If there is a default, we set it to blank to keep record of the current val
1379 - if(atts[x].length < 1){
3857 + if(pagelayer_length(atts[x]) < 1){
1380 3858
1381 - // Dont remove the value as there is a default
3859 + // Remove values which are not defaults
1382 3860 if(!(x in defaults)){
1383 - jEle.removeAttr('pagelayer-a-'+x);
1384 - // Otherwise blank it
3861 + delete ref_data['attr'][x];
3862 + // Otherwise keep value set for avoiding resetting
1385 3863 }else{
1386 - jEle.attr('pagelayer-a-'+x, atts[x]);
3864 + ref_data['attr'][x] = atts[x];
1387 3865 }
1388 3866
1389 3867 // Remove the tmp atts anyway
1390 - var to_del = new Array();
1391 - var regexp = new RegExp('pagelayer\-tmp\-'+x, 'gi');
1392 -
1393 - jQuery.each(jEle[0].attributes, function(index, att){
1394 - if(!att) return;
1395 - if(att.name.match(regexp)){
1396 - to_del.push(att.name);
1397 - }
1398 - });
1399 -
1400 - //console.log(to_del);
1401 - for(var n in to_del){
1402 - jEle.removeAttr(to_del[n]);
1403 - }
3868 + pagelayer_clear_tmp_atts(jEle, x);
1404 3869
1405 3870 // Set the value
1406 3871 }else{
1407 - jEle.attr('pagelayer-a-'+x, atts[x]);
3872 + ref_data['attr'][x] = pagelayer_trim(atts[x]);
1408 3873 }
1409 3874
1410 3875 // Are you the active element
1411 3876 if(pagelayer_is_active(jEle)){
@@ -1415,14 +3880,17 @@
1415 3880 }
1416 3881
1417 3882 }
1418 3883
3884 + pagelayer_el_dump_data(jEle);
3885 +
1419 3886 // Trigger the change of the parameter and show the required properties
1420 3887 if(trigger_onchange){
1421 3888 pagelayer_elpd_show_rows();
1422 3889 }
1423 3890
1424 - pagelayer_isDirty = true;
3891 + pagelayer_do_dirty(jEle);
3892 +
1425 3893 };
1426 3894
1427 3895 // This function will just set atts and not do anything else
1428 3896 // Atts can be string or object. If its string, then val is needed
@@ -1437,27 +3905,71 @@
1437 3905 if(typeof atts != 'object'){
1438 3906 return false;
1439 3907 }
1440 3908
3909 + var ref_data = pagelayer_el_data_ref(jEle);
3910 +
1441 3911 for(var x in atts){
1442 - jEle.attr('pagelayer-tmp-'+x, atts[x]);
3912 +
3913 + // Record history
3914 + if(pagelayer.history_action){
3915 +
3916 + var old_val = pagelayer_get_tmp_att(jEle, x) || '';
3917 + pagelayer_history_action_push({
3918 + 'title' : pagelayer_shortcodes[pagelayer_tag(jEle)]['name'],
3919 + 'subTitle' : x,
3920 + 'action' : 'Edited',
3921 + 'attrType' : 'tmp_attr',
3922 + 'pl_id' : pagelayer_id(jEle),
3923 + 'atts' : x,
3924 + 'oldVal' : old_val,
3925 + 'newVal' : atts[x]
3926 + });
3927 +
3928 + }
3929 +
3930 + ref_data['tmp'][x] = atts[x];
3931 +
1443 3932 }
1444 3933
3934 + pagelayer_el_dump_data(jEle);
3935 +
1445 3936 };
1446 3937
1447 -// Set the att and classes of an HTML which is not yet created
1448 -function pagelayer_sc_atts(classes, atts){
3938 +// This function removes the temporary attributes of an ele
3939 +function pagelayer_clear_tmp_atts(jEle, attr){
1449 3940
1450 - if(typeof atts != 'object'){
1451 - 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 + }
1452 3950 }
3951 +}
3952 +
3953 +// This function removes the temporary attributes of an ele
3954 +function pagelayer_img_tmp_atts(jEle, attr){
1453 3955
1454 - var r = new Array();
3956 + var found = {};
3957 + var regexp = new RegExp('^'+attr+'\-', 'gi');
3958 + var ref_data = pagelayer_el_data_ref(jEle);
1455 3959
1456 - for(var x in atts){
1457 - 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 + }
1458 3964 }
1459 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();
1460 3972 return 'class="'+classes+' pagelayer-ele" '+r.join(' ');
1461 3973 }
1462 3974
1463 3975 // Is the jEle the active element ?
@@ -1483,16 +3995,33 @@
1483 3995
1484 3996 // Seperator
1485 3997 seperator = seperator || ',';
1486 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 +
1487 4012 // Replace the val
1488 - css = css.split('{{val}}').join(val);
4013 + css = replaceCss(css, val, '{{val}}');
1489 4014
1490 4015 // If there is an array
1491 4016 if(css.match(/val\[\d/)){
1492 - val = val.split(seperator);
4017 +
4018 + if(typeof val != 'object' || val === null){
4019 + val = String(val).split(seperator);
4020 + }
4021 +
1493 4022 for(var i in val){
1494 - css = css.split('{{val['+i+']}}').join(val[i]);
4023 + css = replaceCss(css, val[i], '{{val['+i+']}}');
1495 4024 }
1496 4025 }
1497 4026
1498 4027 //console.log('Final CSS '+css);
@@ -1500,9 +4029,40 @@
1500 4029 return css;
1501 4030
1502 4031 };
1503 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 +
1504 4053 // Replace the variables
4054 +function pagelayer_parse_el_vars(str, el){
4055 +
4056 + str = str.split('{{element}}').join(el.CSS.cssSel);
4057 + str = str.split('{{wrap}}').join(el.CSS.wrap);
4058 + str = str.split('{{ele_id}}').join(el.id);
4059 +
4060 + return str;
4061 +
4062 +}
4063 +
4064 +// Replace the variables
1505 4065 function pagelayer_parse_vars(str, el){
1506 4066
1507 4067 for(var x in el.tmp){
1508 4068 str = str.split('{{{'+x+'}}}').join(el.tmp[x]);
@@ -1522,9 +4082,11 @@
1522 4082 if(!pagelayer_is_active(jEle)){
1523 4083 //return false;
1524 4084 }
1525 4085
1526 - // Handle the CSS part
4086 + //console.log('Rendering');
4087 +
4088 + // Handle the CSS part
1527 4089 // Get the id, tag, atts, data, etc
1528 4090 var el = pagelayer_data(jEle, true);
1529 4091 var all_props = pagelayer_shortcodes[el.tag];
1530 4092 var elCSS = {
@@ -1533,13 +4095,18 @@
1533 4095 attr: [],
1534 4096 remove_attr: [],
1535 4097 css: [],
1536 4098 edit: [],
1537 - sel: '[pagelayer-id="'+el.id+'"]'
4099 + cssSel: '.p-'+el.id,
4100 + sel: '[pagelayer-id="'+el.id+'"]',
4101 + wrap: '[pagelayer-wrap-id="'+el.id+'"]'
1538 4102 };
1539 4103
1540 4104 // Create a reference
1541 4105 el.CSS = elCSS;
4106 +
4107 + // Make sure if we have the class selector
4108 + el.$.addClass('p-'+el.id);
1542 4109
1543 4110 //console.log(el.atts);
1544 4111
1545 4112 for(var i in pagelayer_tabs){
@@ -1553,10 +4120,10 @@
1553 4120
1554 4121 // pagelayer_data will return attributes even if they are BLANK e.g. attr=""
1555 4122 // Render doesnt consider BLANK values as values, and we are unsetting them now
1556 4123 // If in any situation you need to consider blank values, please handle in the JS / PHP function of the Shortcode
1557 - if(x in el.atts && el.atts[x].length < 1){
1558 - delete el.atts[x];
4124 + if(x in el.atts && pagelayer_length(el.atts[x]) < 1){
4125 + delete el.atts[x];
1559 4126 }
1560 4127
1561 4128 // Any editor ?
1562 4129 if('edit' in props[x]){
@@ -1562,8 +4129,59 @@
1562 4129 if('edit' in props[x]){
1563 4130 elCSS.edit.push({prop: x, sel: props[x]['edit']});
1564 4131 }
1565 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 +
1566 4184 // Do we have a addClass ?
1567 4185 // We are checking before the element has a value so that we can add or remove the class
1568 4186 if('addClass' in props[x]){
1569 4187
@@ -1598,9 +4216,9 @@
1598 4216 }
1599 4217
1600 4218 }else{
1601 4219
1602 - var tmp = {'sel': tSel, 'val': addClasses[c]};
4220 + var tmp = {'sel': tSel, 'val': addClasses[c].replace('{{val}}', el.atts[x])};
1603 4221
1604 4222 // If the value is there
1605 4223 if(x in el.atts){
1606 4224 elCSS['classes'].push(tmp);
@@ -1653,8 +4271,9 @@
1653 4271 }
1654 4272
1655 4273 // Screen modes
1656 4274 var modes = {desktop: '', tablet: '_tablet', mobile: '_mobile'};
4275 + var desk_global = (props[x]['type'] == 'typography') ? pagelayer_is_global_typo(el.atts[x]) : '';
1657 4276
1658 4277 for(var m in modes){
1659 4278
1660 4279 var xm = x+modes[m];
@@ -1659,12 +4278,37 @@
1659 4278
1660 4279 var xm = x+modes[m];
1661 4280
1662 4281 // If the value is there
1663 - if(!(xm in el.atts)){
4282 + if(!(xm in el.atts) && pagelayer_empty(desk_global)){
1664 4283 continue;
1665 4284 }
1666 -
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 +
1667 4311 for(var c in css){
1668 4312
1669 4313 // The selector
1670 4314 var tSel = jQuery.isNumeric(c) ? '{{element}}' : c;
@@ -1669,20 +4313,20 @@
1669 4313 // The selector
1670 4314 var tSel = jQuery.isNumeric(c) ? '{{element}}' : c;
1671 4315 var tmp = {
1672 4316 sel: tSel,
1673 - val: pagelayer_css_render(css[c], el.atts[xm], (props[x].sep || ',')),
4317 + val: pagelayer_css_render(css[c], xm_val, (props[x].sep || ',')),
1674 4318 };
1675 4319
1676 4320 // Is this a tablet
1677 4321 if(m == 'tablet'){
1678 - 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;
1679 4323 tmp.val = tmp.val+'}';
1680 4324 }
1681 4325
1682 4326 // Is this a mobile mode ?
1683 4327 if(m == 'mobile'){
1684 - tmp.sel = '@media (max-width: 360px){'+tmp.sel;
4328 + tmp.sel = '@media (max-width: '+ pagelayer_settings['mobile_breakpoint'] +'px){'+tmp.sel;
1685 4329 tmp.val = tmp.val+'}';
1686 4330 }
1687 4331
1688 4332 // Push to store
@@ -1700,9 +4344,16 @@
1700 4344 }
1701 4345
1702 4346 // If there is an HTML, then process it
1703 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')];
1704 4351
4352 + if(typeof fn == 'function'){
4353 + fn(el);
4354 + }
4355 +
1705 4356 el.iHTML = jQuery('<div>'+pagelayer_shortcodes[el.tag]['html']+'</div>');
1706 4357
1707 4358 // Lets process the 'if-ext'
1708 4359 el.iHTML.find('[if-ext]').each(function (){
@@ -1730,16 +4381,9 @@
1730 4381 $j.remove();
1731 4382 }
1732 4383
1733 4384 });
1734 -
1735 - // Is there a function to render ?
1736 - var fn = window['pagelayer_render_'+jEle.attr('pagelayer-tag')];
1737 4385
1738 - if(typeof fn == 'function'){
1739 - fn(el);
1740 - }
1741 -
1742 4386 //console.log(el.atts);
1743 4387
1744 4388 // Parse the variables
1745 4389 var new_html = pagelayer_parse_vars(el.iHTML.html(), el);
@@ -1796,9 +4440,9 @@
1796 4440 for(var c in elCSS.edit){
1797 4441 var prop = elCSS.edit[c]['prop'];
1798 4442 var tSel = elCSS.edit[c]['sel'];
1799 4443 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
1800 - node.attr('pagelayer-editable', prop);
4444 + node.attr({'pagelayer-editable': prop, 'contenteditable' : 'true'});
1801 4445 }
1802 4446
1803 4447 }
1804 4448
@@ -1810,9 +4454,9 @@
1810 4454 if(elCSS.classes.length > 0){
1811 4455 //console.log(elCSS.classes);
1812 4456
1813 4457 for(var c in elCSS.classes){
1814 - var tSel = elCSS.classes[c]['sel'];
4458 + var tSel = elCSS.classes[c]['sel'].replace('{{element}}', '');
1815 4459 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
1816 4460 if(!node.hasClass(elCSS.classes[c]['val'])){
1817 4461 node.addClass(elCSS.classes[c]['val']);
1818 4462 }
@@ -1823,9 +4467,9 @@
1823 4467 if(elCSS.remove_classes.length > 0){
1824 4468 //console.log(elCSS.remove_classes);
1825 4469
1826 4470 for(var c in elCSS.remove_classes){
1827 - var tSel = elCSS.remove_classes[c]['sel'];
4471 + var tSel = elCSS.remove_classes[c]['sel'].replace('{{element}}', '');
1828 4472 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
1829 4473 if(node.hasClass(elCSS.remove_classes[c]['val'])){
1830 4474 node.removeClass(elCSS.remove_classes[c]['val']);
1831 4475 }
@@ -1842,14 +4486,14 @@
1842 4486
1843 4487 for(var c in elCSS.attr){
1844 4488 var tSel = elCSS.attr[c]['sel'].replace('{{element}}', '');
1845 4489 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
1846 - var att = elCSS.attr[c]['val'].split('=');
4490 + var att = elCSS.attr[c]['val'].split(/=(.*)/);
1847 4491 att[1] = pagelayer_parse_vars(att[1], el);
1848 4492 att[1] = pagelayer_trim(att[1], '"');
1849 4493
1850 4494 // Is it the same val ?
1851 - if(!node.attr(att[0]) != att[1]){
4495 + if(!node.attr(att[0]) !== att[1]){
1852 4496 node.attr(att[0], att[1]);
1853 4497 }
1854 4498 }
1855 4499 }
@@ -1887,15 +4531,28 @@
1887 4531 var rules = [];
1888 4532
1889 4533 // Loop
1890 4534 for(var c in elCSS.css){
1891 - var tSel = elCSS.css[c]['sel'].replace('{{element}}', elCSS.sel);
1892 - var rule = pagelayer_parse_vars(elCSS.css[c]['val'], el);
1893 - rules.push(tSel+'{'+rule+'}');
4535 + var tSel = pagelayer_parse_el_vars(elCSS.css[c]['sel'], el);
4536 + var rule = elCSS.css[c]['val'];
4537 + if(tSel.length > 0){
4538 + rules.push(tSel+'{'+rule+'}');
4539 + }else{
4540 + rules.push(pagelayer_parse_el_vars(rule, el));
4541 + }
1894 4542 }
4543 +
4544 + // CSS Selector overide
4545 + if(!pagelayer_empty(all_props['overide_css_selector'])){
4546 + for(var r in rules){
4547 + var overide_css_selector = pagelayer_parse_el_vars(all_props['overide_css_selector'], el);
4548 + rules[r] = rules[r].split(el.CSS.cssSel).join(overide_css_selector);
4549 + rules[r] = rules[r].split(el.CSS.wrap).join(overide_css_selector);
4550 + }
4551 + }
1895 4552
1896 4553 // Set the style
1897 - style.html(rules.join("\n"));
4554 + style.html(pagelayer_parse_vars(rules.join("\n"), el));
1898 4555 //console.log(style);
1899 4556 }else{
1900 4557 style.remove();
1901 4558 }
@@ -1908,14 +4565,150 @@
1908 4565 }
1909 4566
1910 4567 // If the element have any parent
1911 4568 var par = pagelayer_get_parent(jEle);
4569 + var eleId = el.id;
4570 +
1912 4571 if(par){
4572 + eleId = par;
1913 4573 pagelayer_sc_render(pagelayer_ele_by_id(par));
1914 4574 }
1915 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 +
1916 4595 };
1917 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 +
1918 4711 // Is the given tag a group
1919 4712 function pagelayer_is_group(tag){
1920 4713
1921 4714 if('has_group' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['has_group'])){
@@ -1925,36 +4718,308 @@
1925 4718 return false;
1926 4719
1927 4720 }
1928 4721
4722 +// Do action / event
4723 +function pagelayer_trigger_action(act, param = []){
4724 + jQuery(document).trigger(act, param);
4725 +}
4726 +
4727 +// Perform a function on an action / event
4728 +function pagelayer_add_action(act, func){
4729 + jQuery(document).on(act, func);
4730 +}
4731 +
4732 +// Create array of the contact from template params
4733 +function pagelayer_get_contact_templates(){
4734 +
4735 + var contacts = jQuery(pagelayer_editable+' [pagelayer-tag=pl_contact]');
4736 + var contacts_props = {};
4737 + if(contacts.length > 0){
4738 +
4739 + contacts.each(function(){
4740 +
4741 + var tmp = pagelayer_data(jQuery(this));
4742 + var con_allowed = ['to_email', 'from_email', 'cont_subject', 'cont_header', 'cont_body', 'cont_use_html'];
4743 +
4744 + if(pagelayer_empty(tmp.atts['contact_custom_templ'])) return true;
4745 +
4746 + // Define blank array
4747 + contacts_props[tmp.id] = {};
4748 +
4749 + for(var x in con_allowed){
4750 + var key = con_allowed[x];
4751 + if(!pagelayer_empty(tmp.atts[key])){
4752 + contacts_props[tmp.id][key] = tmp.atts[key];
4753 + }
4754 + }
4755 +
4756 + });
4757 + }
4758 +
4759 + return contacts_props;
4760 +}
4761 +
4762 +// Save data or meta of the post
4763 +function pagelayer_update_post_data(){
4764 +
4765 + var tag = 'pl_post_props';
4766 + var jEle = jQuery(pagelayer_editable+' [pagelayer-tag="'+tag+'"]');
4767 +
4768 + if(jEle.length < 1){
4769 + return;
4770 + }
4771 +
4772 + var tmp = pagelayer_data(jEle, true);
4773 + var all_props = pagelayer_shortcodes[tag];
4774 +
4775 + // Loop through all props
4776 + for(var i in pagelayer_tabs){
4777 +
4778 + var tab = pagelayer_tabs[i];
4779 +
4780 + for(var section in all_props[tab]){
4781 +
4782 + var props = section in pagelayer_shortcodes[tag] ? pagelayer_shortcodes[tag][section] : pagelayer_styles[section];
4783 +
4784 + for(var x in props){
4785 + //Set pagelayer POST data to send with save ajax
4786 + if(x in tmp['atts']){
4787 + pagelayer_ajax_post_data[x] = tmp['atts'][x];
4788 + }else if(x in pagelayer_ajax_post_data){
4789 + delete pagelayer_ajax_post_data[x];
4790 + }
4791 + }
4792 + }
4793 + }
4794 +}
4795 +
4796 +// Get the nav menu updated data
4797 +function pagelayer_get_nav_items(jEle, _content){
4798 +
4799 + _content = _content || false;
4800 +
4801 + var pagelayer_nav_items = {};
4802 +
4803 + jEle.find('[pagelayer-tag="pl_nav_menu_item"]').each(function(){
4804 + var cEle = jQuery(this),
4805 + postID = pagelayer_get_att(cEle, 'ID');
4806 +
4807 + if(!(postID in pagelayer_menus_items_ref)){
4808 + return;
4809 + }
4810 +
4811 + var ref_data = pagelayer_menus_items_ref[postID];
4812 +
4813 + if(!('pagelayer_content' in ref_data) && pagelayer_empty(ref_data['pagelayer_content'])){
4814 + ref_data['pagelayer_content'] = cEle;
4815 + }
4816 +
4817 + if(!('is_dirty' in ref_data) || pagelayer_empty(ref_data['is_dirty'])){
4818 + return;
4819 + }
4820 +
4821 + var content = '',
4822 + tmp = {};
4823 + tmp = Object.assign(tmp, ref_data);
4824 + pagelayer_nav_items[postID] = {};
4825 +
4826 + // Update Mega menu content
4827 + if(!pagelayer_empty(_content)){
4828 + var navItem = jQuery(ref_data['pagelayer_content'])[0].outerHTML;
4829 + var _navItem = jQuery(navItem);
4830 +
4831 + // If is not mega menu
4832 + if('menu_type' in tmp && tmp['menu_type'] != 'mega'){
4833 + _navItem.find('.pagelayer-menu-item-holder').empty();
4834 + }
4835 +
4836 + content = pagelayer_generate_sc(_navItem, true);
4837 + content = pagelayer_Base64.encode(content);
4838 +
4839 + // Send data to save
4840 + var allowed_post = ['title'];
4841 +
4842 + for(var key in allowed_post){
4843 +
4844 + var post_prop = allowed_post[key];
4845 +
4846 + if(!(post_prop in tmp)){
4847 + continue;
4848 + }
4849 +
4850 + pagelayer_nav_items[postID][post_prop] = tmp[post_prop]
4851 + }
4852 +
4853 + }else{
4854 + pagelayer_nav_items[postID] = tmp;
4855 + }
4856 +
4857 + // Delete the html content
4858 + delete tmp['pagelayer_content'];
4859 +
4860 + pagelayer_nav_items[postID]['_pagelayer_content'] = content;
4861 +
4862 + });
4863 +
4864 + return pagelayer_nav_items;
4865 +}
4866 +
4867 +// Save data or meta of the nav post
4868 +function pagelayer_update_nav_menu_data(){
4869 +
4870 + var tag = 'pl_wp_menu';
4871 +
4872 + pagelayer_ajax_post_data['pagelayer_nav_items'] = {};
4873 +
4874 + jQuery(pagelayer_editable+' [pagelayer-tag="'+tag+'"]').each(function(){
4875 +
4876 + var jEle = jQuery(this);
4877 + var menu_ID = pagelayer_get_att(jEle, 'nav_list');
4878 +
4879 + if(!pagelayer_empty(pagelayer_ajax_post_data['pagelayer_nav_items'][menu_ID])){
4880 + return;
4881 + }
4882 +
4883 + // Get the Current menu items
4884 + var items = pagelayer_get_nav_items(jEle, true);
4885 +
4886 + if(pagelayer_empty(items)){
4887 + return;
4888 + }
4889 +
4890 + pagelayer_ajax_post_data['pagelayer_nav_items'][menu_ID] = items;
4891 +
4892 + });
4893 +}
4894 +
4895 +// Save the customizer settings
4896 +function pagelayer_update_customizer_settings(){
4897 +
4898 + var tag = 'pl_customizer';
4899 + var jEle = jQuery(pagelayer_editable+' [pagelayer-tag="'+tag+'"]');
4900 +
4901 + if(jEle.length < 1){
4902 + return;
4903 + }
4904 +
4905 + var tmp = pagelayer_data(jEle, true);
4906 + pagelayer_ajax_post_data['pagelayer_customizer_options'] = JSON.stringify(tmp['atts']);
4907 +
4908 +}
4909 +
1929 4910 // Save the post
1930 4911 function pagelayer_save(){
1931 4912
1932 - var post = pagelayer_generate_sc(".entry-content");//alert(post);return;
4913 + // hiding and showing loading animation
4914 + pagelayer.$$('.pagelayer-update-text').hide();
4915 + pagelayer.$$('.pagelayer-update-loader').show();
4916 +
4917 + pagelayer_trigger_action('pagelayer_save');
4918 +
1933 4919 var pagelayerajaxurl = pagelayer_ajax_url+'&action=pagelayer_save_content&postID='+pagelayer_postID;
1934 - jQuery.ajax({
1935 - type: "POST",
1936 - url: pagelayerajaxurl,
1937 - data: {
1938 - pagelayer_update_content : post,
1939 - nonce: pagelayer_ajax_nonce
1940 - },
1941 - success: function(response, status, xhr){
1942 - //alert(data);
1943 - var obj = jQuery.parseJSON(response);
1944 - //alert(obj);
1945 - if(obj['error']){
1946 - alert(obj['error']);
1947 - }else{
1948 - pagelayer_isDirty = false;
1949 - alert(obj['success']);
4920 + var post = pagelayer_generate_sc(pagelayer_editable);//alert(post);return;
4921 +
4922 + // Update data or meta of the post
4923 + pagelayer_update_post_data();
4924 +
4925 + // Update Customizer Settings
4926 + pagelayer_update_customizer_settings();
4927 +
4928 + // Update nav menu
4929 + pagelayer_update_nav_menu_data();
4930 +
4931 + if(pagelayer_empty(pagelayer.post_status) && !pagelayer_empty(pagelayer_ajax_post_data['post_status'])){
4932 + pagelayer.post_status = pagelayer_ajax_post_data['post_status'];
4933 + }
4934 +
4935 + // Do we have contact templates ?
4936 + var contacts_props = pagelayer_get_contact_templates();
4937 +
4938 + // Do we have any global widget to save ?
4939 + var global_data = {};
4940 +
4941 + if(!pagelayer_empty(pagelayer_global_widgets)){
4942 + global_data = pagelayer_generate_sc_global_widget();
4943 + }
4944 +
4945 + var cancel = function(){
4946 + pagelayer.$$('.pagelayer-update-text').show();
4947 + pagelayer.$$('.pagelayer-update-loader').hide();
4948 + }
4949 +
4950 + var save = function(){
4951 + var post_data = {
4952 + pagelayer_update_content : pagelayer_Base64.encode(post),
4953 + pagelayer_nonce: pagelayer_ajax_nonce,
4954 + global_widgets: global_data,
4955 + contacts: contacts_props,
4956 + post_status: pagelayer.post_status,
4957 + copyright: pagelayer_copyright
4958 + }
4959 +
4960 + if(!pagelayer_empty(pagelayer.cmode)){
4961 + post_data.cmode = pagelayer.cmode;
4962 + }
4963 +
4964 + post_data = Object.assign(pagelayer_ajax_post_data, post_data);
4965 +
4966 + jQuery.ajax({
4967 + type: "POST",
4968 + url: pagelayerajaxurl,
4969 + data: post_data,
4970 + success: function(response, status, xhr){
4971 + //alert(data);
4972 + var obj = jQuery.parseJSON(response);
4973 + //alert(obj);
4974 +
4975 + if('comment_alerts' in obj){
4976 + console.log("Alerts:", obj['comment_alerts']);
4977 + }
4978 +
4979 + if(obj['error']){
4980 + pagelayer_show_msg(obj['error'], 'error', 10000);
4981 + if('comment_errors' in obj){
4982 + console.log("Errors:", obj['comment_errors']);
4983 + }
4984 + }else{
4985 + pagelayer_show_msg(obj['success'], 'success', 10000);
4986 + pagelayer_get_revision();
4987 +
4988 + // Update the post status in the post_props, but first find if its actually there !
4989 + var jEle = jQuery(pagelayer_editable).find("[pagelayer-tag=pl_post_props]");
4990 + if(jEle.length > 0){
4991 + var id = pagelayer_id(jEle);
4992 + pagelayer_set_atts(jEle, 'post_status', obj['post_status']);
4993 + pagelayer_trigger_action('pagelayer_save_success', obj['post_status']);
4994 + }
4995 +
4996 + pagelayer_do_undirty();
4997 + }
4998 + },
4999 + error: function(jqXHR, textStatus, errorThrown){
5000 + console.log(errorThrown);
5001 + pagelayer_show_msg('An error occured while saving ! Status : '+textStatus+' and Error : '+errorThrown, 'error', 10000);
5002 + },
5003 + complete: function(xhr,status){
5004 + pagelayer.$$('.pagelayer-update-text').show();
5005 + pagelayer.$$('.pagelayer-update-loader').hide();
5006 +
5007 + if(!pagelayer_empty(pagelayer.post_status)){
5008 + pagelayer.$$('.pagelayer-props-modal .pagelayer-meta-iframe').attr('src', pagelayer_post_props );
5009 + pagelayer.post_status = '';
5010 + }
1950 5011 }
1951 - },
1952 - error: function(errorThrown){
1953 - console.log(errorThrown);
1954 - }
1955 - });
5012 + });
5013 + }
1956 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();
1957 5022 };
1958 5023
1959 5024 //Close the Editor
1960 5025 function pagelayer_close(){
@@ -1967,18 +5032,30 @@
1967 5032 }else{
1968 5033 window.top.location.href = pagelayer_returnURL;
1969 5034 }
1970 5035 };
5036 +
5037 +function pagelayer_htmlEntities(str) {
5038 + return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
5039 +}
1971 5040
1972 -// Generate Shortcode Post to save
1973 -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){
1974 5052
5053 + selfEle = selfEle || false;
1975 5054 var txt = '';
1976 5055
1977 - jQuery(selector).children(".pagelayer-ele-wrap").each(function(){
5056 + var generate_sc_single = function(jEle){
1978 5057
1979 - var jEle = jQuery(this).children('.pagelayer-ele');
1980 -
1981 5058 // The ID
1982 5059 var id = jEle.attr('pagelayer-id');
1983 5060
1984 5061 // If there is an Add element wrapper
@@ -1988,14 +5065,29 @@
1988 5065
1989 5066 // Find the type of tag
1990 5067 var tag = jEle.attr('pagelayer-tag');
1991 5068 var final_tag = tag;
5069 + var closestEle = jEle.closest('.pagelayer-col-holder');
1992 5070
1993 - // Define inner row and inner column
1994 - if(tag == 'pl_row' && jQuery(this).closest('.pagelayer-col-holder').length > 0){
5071 + // Skip to create shortcode to prevent save, allowed by tag
5072 + if('skip_save' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['skip_save'])){
5073 + return;
5074 + }
5075 +
5076 + // Define inner row | Note : Commented as we now have a new widget of type inner_row
5077 + /*if(tag == 'pl_row' && closestEle.length > 0 && closestEle.closest(pagelayer_editable).length > 0){
1995 5078 final_tag = 'pl_inner_row';
5079 + }*/
5080 +
5081 + if(pagelayer_empty(tag)){
5082 + var err = 'Found an error in the content as the TAG was missing. The console will have more details.';
5083 + pagelayer_show_msg(err, 'error');
5084 + console.log(err);
5085 + console.log(jEle);
1996 5086 }
1997 - if(tag == 'pl_col' && jQuery(this).closest('.pagelayer-col-holder').length > 0){
5087 +
5088 + // Define inner column
5089 + if(tag == 'pl_col' && closestEle.length > 0 && closestEle.closest(pagelayer_editable).length > 0){
1998 5090 final_tag = 'pl_inner_col';
1999 5091 }
2000 5092 //console.log(tag);
2001 5093
@@ -2004,57 +5096,61 @@
2004 5096 if('innerHTML' in pagelayer_shortcodes[tag]){
2005 5097 inner = pagelayer_shortcodes[tag]['innerHTML'];
2006 5098 }
2007 5099
5100 + // Data reference
5101 + var ref_data = pagelayer_el_data_ref(jEle);
5102 +
2008 5103 // Create the tag
2009 - var data = '['+final_tag;
5104 + var data = JSON.parse(JSON.stringify(ref_data['attr']));
2010 5105
2011 - // Get the attributes to store
2012 - jQuery.each(jEle[0].attributes, function(i, attrib){
2013 - var res = attrib.name.match(/^pagelayer-a-(.+)/i);
2014 - if(res && res[1] != inner){
2015 - //console.log(attrib.name+' '+res[1]);
2016 - data += ' '+res[1]+'="'+pagelayer_escapeHTML(attrib.value)+'"';
2017 - }
2018 - });
5106 + data['pagelayer-id'] = id;
5107 + data = pagelayer_serializeAttributes(data);
5108 +
5109 + var content = '';
2019 5110
2020 - data = data+']';
2021 -
2022 - // Add to the text
2023 - txt = txt+data+"\n";
2024 -
2025 5111 // Any internal function to handle the save ?
2026 5112 var func = window['pagelayer_tag_'+tag];
2027 5113 if(typeof func == 'function'){
2028 5114
2029 - var content = '';
2030 5115 content = func(jEle);
2031 5116
2032 - if(content.length > 0){
2033 - txt = txt+content;
2034 - }
2035 -
2036 5117 // If its a Row or Column or Group then it will have children
2037 5118 }else if(jEle.hasClass('pagelayer-row') || jEle.hasClass('pagelayer-col') || jEle.hasClass('pagelayer-inner_row') || pagelayer_is_group(tag)){
2038 5119
2039 - var sel = "[pagelayer-id="+id+"]";
5120 + var sel = jEle;
2040 5121
2041 5122 // Any holder which holds children ?
2042 5123 if('holder' in pagelayer_shortcodes[tag]){
2043 - sel = sel+' '+pagelayer_shortcodes[tag]['holder'];
5124 + sel = jEle.find(pagelayer_shortcodes[tag]['holder']);
2044 5125 }
2045 5126
2046 - var childrens = pagelayer_generate_sc(jQuery(sel).first());
2047 - if(childrens.length > 0){
2048 - txt = txt+childrens;
5127 + // Select the top-most element
5128 + sel = jQuery(sel).first();
5129 +
5130 + // Any child selector - Majorly for owl carousel
5131 + // NOTE : Child selector should be very specific with immediate child selection at all levels
5132 + var child_selector = false;
5133 + if('child_selector' in pagelayer_shortcodes[tag]){
5134 + childSel = sel.find(pagelayer_shortcodes[tag]['child_selector']);
5135 +
5136 + if(childSel.length > 0){
5137 + sel = childSel;
5138 + }
2049 5139 }
5140 +
5141 + if(jQuery(sel).children(".pagelayer-ele-wrap").length < 1){
5142 + content = jQuery(sel).html(); // Backward Compatibility
5143 + }else{
5144 + content = pagelayer_generate_sc(sel);
5145 + content = "\n"+content;
5146 + }
2050 5147
2051 5148 // Its a normal element so we might need to handle the content
2052 5149 }else{
2053 5150
2054 - var content = '';
2055 5151 if(inner.length > 0){
2056 - content = jEle.attr('pagelayer-a-'+inner);
5152 + content = pagelayer_get_att(jEle, inner);
2057 5153 if(!content){
2058 5154 content = '';
2059 5155 }
2060 5156 }else{
@@ -2060,100 +5156,98 @@
2060 5156 }else{
2061 5157 content = '';//jEle.html();
2062 5158 }
2063 5159
2064 - if(content.length > 0){
2065 - txt = txt+content;
2066 - }
2067 -
2068 5160 }
2069 5161
2070 - // Close the tag
2071 - 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 + }
2072 5167
2073 - });
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 + };
2074 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 +
2075 5193 return txt;
2076 5194
2077 5195 };
2078 5196
2079 -// Escape charaters in attributes
2080 -var pagelayer_escapeChars = {
2081 - '\\]' : '#93',
2082 - '\\[' : '#91',
2083 - //'=' : '#61',
2084 - '<' : 'lt',
2085 - '>' : 'gt',
2086 - '"' : 'quot',
2087 - //'&' : 'amp',
2088 - '\'' : '#39'
2089 -};
2090 -
2091 -// To unescape
2092 -var pagelayer_unescapeChars = {
2093 - '#93' : ']',
2094 - '#91' : '[',
2095 - //'#61' : '=',
2096 - 'lt' : '<',
2097 - 'gt' : '>',
2098 - 'quot' : '"',
2099 - //'amp' : '&',
2100 - '#39' : '\''
2101 -};
2102 -
2103 -var pagelayer_escaperegex_S = '[';
2104 -for(var key in pagelayer_escapeChars) {
2105 - pagelayer_escaperegex_S += key;
5197 +// Show the required leftbar tab
5198 +function pagelayer_leftbar_tab(tab){
5199 + pagelayer.$$('.pagelayer-leftbar-tab').hide();
5200 + pagelayer.$$('#'+tab).show();
2106 5201 }
2107 -pagelayer_escaperegex_S += ']';
2108 5202
2109 -var pagelayer_escaperegex = new RegExp( pagelayer_escaperegex_S, 'g');
2110 -
2111 -// The function which escapes everything
2112 -function pagelayer_escapeHTML(str) {
2113 - return str.replace(pagelayer_escaperegex, function(m) {
2114 - if(m == '[' || m == ']') m = '\\'+m;
2115 - return '&' + pagelayer_escapeChars[m] + ';';
2116 - });
2117 -};
2118 -
2119 -// This will unescape everything
2120 -function pagelayer_unescapeHTML(str){
2121 - return str.replace(/\&([^;]+);/g, function (entity, entityCode) {
2122 - if(entityCode in pagelayer_unescapeChars){
2123 - return pagelayer_unescapeChars[entityCode];
2124 - }else{
2125 - return entity;
2126 - }
2127 - });
2128 -};
2129 -
2130 5203 // Sets up the leftbar
2131 5204 function pagelayer_leftbar(){
2132 5205
2133 5206 // Toggle the holder
2134 5207 pagelayer.$$('.pagelayer-leftbar-toggle').on('click', function(){
2135 - pagelayer.$$('.pagelayer-leftbar-table').toggle();
5208 + pagelayer.$$('.pagelayer-leftbar-table').toggleClass('pagelayer-leftbar-hidden');
5209 + pagelayer_trigger_action('pagelayer-leftbar-toggle');
2136 5210 });
2137 5211
5212 + // Close leftbar
5213 + pagelayer.$$('.pagelayer-leftbar-close').on('click', function(){
5214 + pagelayer.$$('.pagelayer-leftbar-toggle').click();
5215 + });
5216 +
5217 + // Minimize leftbar
5218 + pagelayer.$$('.pagelayer-leftbar-minimize').on('click', function(){
5219 + pagelayer.$$('.pagelayer-leftbar-table').toggleClass('pagelayer-leftbar-minimize');
5220 + });
5221 +
2138 5222 var html = '<div class="pagelayer-leftbar">'+
2139 5223 '<div class="pagelayer-leftbar-scroll">'+
2140 - '<div class="pagelayer-shortcodes">'+
2141 - '<div class="pagelayer-leftbar-search">'+
2142 - '<input class="pagelayer-search-field" />'+
2143 - '</div>';
5224 + '<div id="pagelayer-shortcodes" class="pagelayer-leftbar-tab pagelayer-shortcodes">'+
5225 + '<div class="pagelayer-widget-tabs">'+
5226 + '<div class="pagelayer-widget-tab" pagelayer-widget-tab="widgets" pagelayer-elpd-active-tab=1>Widgets</div>'+
5227 + '<div class="pagelayer-widget-tab pagelayer-settings" pagelayer-widget-tab="settings">Settings</div>'+
5228 + '<div class="pagelayer-widget-tab" pagelayer-widget-tab="global">Globals</div>'+
5229 + '</div>'+
5230 + '<div class="pagelayer-shortcodes-widget">'+
5231 + '<div class="pagelayer-leftbar-search">'+
5232 + '<i class="pli pli-search" ></i><input class="pagelayer-search-field" placeholder="Search Widget..." /><span class="pagelayer-sf-empty pli">&times;</span>'+
5233 + '</div>';
2144 5234
2145 5235 for(var x in pagelayer_groups){
2146 5236
2147 5237 // Title
2148 - 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';
2149 5241
5242 + html += '<div class="pagelayer-leftbar-group pagelayer-group-name-'+x+'"><h5>'+group_title+'</h5>';
5243 +
2150 5244 // Indivdual icon
2151 5245 for(var y in pagelayer_groups[x]){
2152 5246
2153 5247 var sc = pagelayer_groups[x][y];
2154 5248
2155 - if('not_visible' in pagelayer_shortcodes[sc]){
5249 + if(!(sc in pagelayer_shortcodes) || 'not_visible' in pagelayer_shortcodes[sc]){
2156 5250 continue;
2157 5251 }
2158 5252
2159 5253 html += '<div class="pagelayer-shortcode-drag" draggable="true" pagelayer-tag="'+sc+'">'+
@@ -2160,11 +5254,11 @@
2160 5254 '<div class="pagelayer-sc">'+
2161 5255 '<center class="pagelayer-shortcode-inner">';
2162 5256
2163 5257 if('icon' in pagelayer_shortcodes[sc]){
2164 - html += '<i class="pagelayer-shortcode fa fa-'+pagelayer_shortcodes[sc]['icon']+'"></i>';
5258 + html += '<i class="pagelayer-shortcode '+pagelayer_shortcodes[sc]['icon']+'"></i>';
2165 5259 }else{
2166 - html += '<i class="pagelayer-shortcode pagelayer-'+sc+'"></i>';
5260 + html += '<i class="pagelayer-shortcode pli pagelayer-'+sc+'"></i>';
2167 5261 }
2168 5262
2169 5263 html += '</center>'+
2170 5264 '<span class="pagelayer-shortcode-text">'+pagelayer_shortcodes[sc]['name']+'</span>'+
@@ -2177,16 +5271,24 @@
2177 5271
2178 5272 }
2179 5273
2180 5274 html += '</div>'+
2181 - '<div id="pagelayer-elpd" class="pagelayer-elpd"></div>'+
5275 + '<div id="pagelayer-global-widget" class="pagelayer-hidden pagelayer-global-widget"></div>'+
5276 + '</div>'+
5277 + '<div id="pagelayer-elpd" class="pagelayer-leftbar-tab pagelayer-elpd"></div>'+
5278 + '<div id="pagelayer-options" class="pagelayer-leftbar-tab pagelayer-options"></div>'+
5279 + '<div id="pagelayer-history" class="pagelayer-leftbar-tab pagelayer-history"></div>'+
5280 + '<div id="pagelayer-post-settings" class="pagelayer-leftbar-tab pagelayer-post-settings"></div>'+
5281 + '<div id="pagelayer-navigator" class="pagelayer-leftbar-tab pagelayer-navigator"></div>'+
5282 + '<div id="pagelayer-general-options" class="pagelayer-leftbar-tab pagelayer-general-options"></div>'+
2182 5283 '</div>'+
2183 5284 '</div>';
2184 5285
2185 5286 pagelayer.$$('.pagelayer-leftbar-holder').prepend(html);
5287 + pagelayer_leftbar_tab('pagelayer-shortcodes');
2186 5288
2187 5289 pagelayer.$$('.pagelayer-leftbar-scroll').slimScroll({
2188 - height: '100%',
5290 + height: '100%',
2189 5291 railVisible: false,
2190 5292 alwaysVisible: true,
2191 5293 color: '#000',
2192 5294 size: '5px',
@@ -2226,10 +5328,725 @@
2226 5328
2227 5329 });
2228 5330 });
2229 5331
5332 + // On click Pagelayer setting icon
5333 + pagelayer.$$('.pagelayer-settings-icon, .pagelayer-settings').click(function(event){
5334 + pagelayer_active = {};
5335 +
5336 + var pl_tag = jQuery(this).attr('pagelayer-tag') || 'pl_post_props';
5337 + var nModal = jQuery(this).attr('pagelayer-modal-none');
5338 +
5339 + pagelayer_post_settings(pl_tag);
5340 +
5341 + });
5342 +
5343 + // Pagelayer post advance setting modal handler
5344 + var propsModal = pagelayer.$$('.pagelayer-props-modal');
5345 + propsModal.find('.pagelayer-props-modal-close').on('click', function(event){
5346 + propsModal.hide();
5347 + });
5348 +
5349 + propsModal.on('click', function(event){
5350 + var target = jQuery(event.target);
5351 +
5352 + if(target.closest('.pagelayer-props-modal-wrap').length > 0){
5353 + return;
5354 + }
5355 +
5356 + propsModal.hide();
5357 + });
5358 +
5359 +
5360 + // On click Pagelayer setting icon
5361 + var global_widget_list = function(){
5362 +
5363 + var gHtml = '';
5364 +
5365 + if(pagelayer_empty(pagelayer_pro)){
5366 + gHtml += '<div class="pagelayer-global-widget-pro">'+pagelayer.pro_txt+
5367 + '<p>Using this feature, you can save the widgets globally and use them on the entire site. The global widget will be editable from one place.</p>'+
5368 + '</div>';
5369 +
5370 + pagelayer.$$('#pagelayer-global-widget').html(gHtml);
5371 + return;
5372 + }
5373 +
5374 + gHtml += '<div class="pagelayer-global-widget-shortcodes">'+
5375 + '<div class="pagelayer-leftbar-search">'+
5376 + '<i class="pli pli-search" ></i><input class="pagelayer-search-field" /><i class="pagelayer-sf-empty pli">&times;</i>'+
5377 + '</div>'+
5378 + '<div class="pagelayer-leftbar-group"><h5>'+pagelayer_l('global_widgets')+'</h5></div>'+
5379 + '</div>';
5380 +
5381 + if(pagelayer_empty(pagelayer_global_widgets)){
5382 + pagelayer_global_widgets = [];
5383 + gHtml += '<div class="pagelayer-leftbar-group"><h5>No global widgets found</h5></div>';
5384 + }
5385 +
5386 + // Indivdual icon
5387 + for(var y in pagelayer_global_widgets){
5388 + var wEle = jQuery(pagelayer_global_widgets[y]['$']);
5389 + var sc = pagelayer_tag( wEle );
5390 +
5391 + if(!(sc in pagelayer_shortcodes) || 'not_visible' in pagelayer_shortcodes[sc]){
5392 + continue;
5393 + }
5394 +
5395 + gHtml += '<div class="pagelayer-shortcode-drag" draggable="true" pagelayer-tag="'+sc+'" pagelayer-global-id="'+y+'">'+
5396 + '<div class="pagelayer-sc">'+
5397 + '<center class="pagelayer-shortcode-inner">';
5398 +
5399 + if('icon' in pagelayer_shortcodes[sc]){
5400 + gHtml += '<i class="pagelayer-shortcode '+pagelayer_shortcodes[sc]['icon']+'"></i>';
5401 + }else{
5402 + gHtml += '<i class="pagelayer-shortcode pli pagelayer-'+sc+'"></i>';
5403 + }
5404 +
5405 + gHtml += '</center>'+
5406 + '<span class="pagelayer-shortcode-text">'+pagelayer_global_widgets[y]['title']+'</span>'+
5407 + '</div>'+
5408 + '</div>';
5409 +
5410 + }
5411 +
5412 + pagelayer.$$('#pagelayer-global-widget').html(gHtml);
5413 + };
5414 +
5415 + // The widget tabs
5416 + pagelayer.$$('.pagelayer-widget-tab').on('click', function(){
5417 + var attr = 'pagelayer-elpd-active-tab';
5418 + pagelayer.$$('.pagelayer-widget-tab').each(function(){
5419 + jQuery(this).removeAttr(attr);
5420 + });
5421 + var cEle = jQuery(this);
5422 + cEle.attr(attr, 1);
5423 +
5424 + if(cEle.attr('pagelayer-widget-tab') == 'global'){
5425 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-shortcodes-widget').addClass('pagelayer-hidden');
5426 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-global-widget').removeClass('pagelayer-hidden');
5427 + // Trigger create global widgets
5428 + global_widget_list();
5429 + }else{
5430 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-shortcodes-widget').removeClass('pagelayer-hidden');
5431 + cEle.closest('#pagelayer-shortcodes').find('.pagelayer-global-widget').addClass('pagelayer-hidden');
5432 + }
5433 + });
5434 +
5435 + // On click search empty
5436 + pagelayer.$$('.pagelayer-leftbar-search>.pagelayer-sf-empty').click(function(){
5437 + pagelayer.$$('.pagelayer-search-field').val('').trigger('input');
5438 + });
5439 +
5440 + // Pagelayer General options
5441 + pagelayer.$$('.pagelayer-options-icon ').click(function(){
5442 + pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text(pagelayer_l('general_options'));
5443 + pagelayer.$$('.pagelayer-logo').hide();
5444 +
5445 + // Setup General options
5446 + pagelayer_setup_general_options();
5447 +
5448 + pagelayer_leftbar_tab('pagelayer-general-options');
5449 + pagelayer_active = {};
5450 + });
5451 +
5452 + // Hide color and typography global list
5453 + pagelayer.$$('.pagelayer-leftbar-table').on('click', function(e){
5454 +
5455 + var closest = jQuery(e.target).closest('.pagelayer-elp-color-global, .pagelayer-elp-global-icon, .pagelayer-global-color-list, .pagelayer-global-font-list');
5456 + var list = pagelayer.$$('.pagelayer-global-color-list, .pagelayer-global-font-list');
5457 +
5458 + if(closest.length > 0 ){
5459 + var lEle = closest.closest('.pagelayer-elp-color-div-holder').find('.pagelayer-global-color-list');
5460 + var lFont = closest.closest('.pagelayer-form-item').find('.pagelayer-global-font-list');
5461 +
5462 + list = list.not(lFont);
5463 + list = list.not(lEle);
5464 + }
5465 +
5466 + list.not(closest).slideUp();
5467 +
5468 + });
2230 5469 };
2231 5470
5471 +// Post setting holder
5472 +function pagelayer_post_settings(pl_tag, to_click){
5473 +
5474 + to_click = to_click == -1 ? false : true;
5475 +
5476 + // Is there a post settings ?
5477 + var jEle = jQuery(pagelayer_editable+' [pagelayer-tag="'+ pl_tag +'"]');
5478 +
5479 + // Could not find
5480 + if(jEle.length < 1){
5481 + jEle = pagelayer_create_sc(pl_tag);
5482 + var id = pagelayer_id(jEle);
5483 + jQuery(pagelayer_editable).prepend(jEle);
5484 + pagelayer_element_setup('[pagelayer-id='+id+']', true);
5485 +
5486 + // Dont mark as dirty as post_props is not editing anything
5487 + pagelayer_do_undirty();
5488 + }
5489 +
5490 + if(to_click){
5491 + jEle.click();
5492 + }
5493 +
5494 + return jEle;
5495 +}
5496 +
5497 +// Get the closest element and method
5498 +function pagelayer_near_by_ele(id, sc){
5499 +
5500 + // Get the previous element of the id element
5501 + var prevEle_id = jQuery('[pagelayer-wrap-id="'+id+'"]').prev().attr('pagelayer-wrap-id') || '';
5502 + var method, cEle, args = {};
5503 +
5504 + if(prevEle_id.length > 0){
5505 +
5506 + // If have previous element of the id element
5507 + // Set the method and previous element selector
5508 + args = {'method' : 'after', 'cEle' : '[pagelayer-wrap-id="'+prevEle_id+'"]'};
5509 +
5510 + }else{
5511 +
5512 + // If don't have previous element of the id element then get parent element
5513 + if(sc == "pl_row"){
5514 + args = {'method' : 'prepend', 'cEle' : pagelayer_editable};
5515 + }else{
5516 +
5517 + // Get the parent element
5518 + var pEle_id = pagelayer_id(jQuery('[pagelayer-wrap-id="'+id+'"]').closest('.pagelayer-ele'));
5519 +
5520 + // Get the parent element tag
5521 + var pEle_tag = pagelayer_tag(jQuery('[pagelayer-id="'+pEle_id+'"]'));
5522 + var holder = '>'+ pagelayer_shortcodes[pEle_tag]['holder'] || '';
5523 + args = {'method' : 'prepend', 'cEle' : '[pagelayer-id="'+pEle_id+'"] '+ holder+' '};
5524 +
5525 + }
5526 +
5527 + }
5528 +
5529 + return args;
5530 +
5531 +};
5532 +
5533 +// Push the action data in the pagelayer_history_obj object
5534 +function pagelayer_history_action_push(args){
5535 +
5536 + var currentTime = new Date();
5537 + var history_obj_len = pagelayer_history_obj['action_data'].length;
5538 +
5539 + // If the history_obj_len is less then 1 then set the data in array 0 position
5540 + if(history_obj_len < 1){
5541 + pagelayer_history_obj['action_data'][0] = {'title' : 'Start Editing', 'action' : 'Start' };
5542 + pagelayer_history_obj['current_active_item_id'] = 0;
5543 + }
5544 +
5545 + // Remove the second array element if the history_obj_len greater then 100
5546 + if(history_obj_len > 100){
5547 + pagelayer_history_obj['action_data'].splice(1, 1);
5548 + pagelayer_history_obj['current_active_item_id'] = pagelayer_history_obj['action_data'].length - 1;
5549 + }
5550 +
5551 + // Get current active history action id
5552 + var action_id = parseInt(pagelayer_history_obj['current_active_item_id']) || 0;
5553 +
5554 + // Remove the all array element after the active array element
5555 + var del_ele = history_obj_len - action_id - 1;
5556 + pagelayer_history_obj['action_data'].splice(action_id + 1, del_ele);
5557 +
5558 + // Check if the same attr set as current active history
5559 + if(args.action == "Edited" && history_obj_len > 1 && currentTime - pagelayer.history_lastTime < 1000){
5560 + var atts = pagelayer_history_obj['action_data'][action_id] || '';
5561 + if(atts['atts'] == args['atts'] && atts['pl_id'] == args['pl_id'] && pagelayer_empty(atts['sub_actions_group']) ){
5562 + args['oldVal'] = atts['oldVal'];
5563 + pagelayer_history_obj['action_data'][action_id] = args;
5564 + pagelayer_history_setup();
5565 +
5566 + // Set the last history time
5567 + pagelayer.history_lastTime = currentTime;
5568 + return true;
5569 + }
5570 + }
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 +
5590 + pagelayer_history_obj['action_data'].push(args);
5591 + pagelayer_history_obj['current_active_item_id'] = pagelayer_history_obj['action_data'].length - 1;
5592 + pagelayer_history_setup();
5593 +
5594 + // Set the last history time
5595 + pagelayer.history_lastTime = currentTime;
5596 +}
5597 +
5598 +// Setup pagelayer history
5599 +function pagelayer_history_setup(force){
5600 +
5601 + var force = force || false;
5602 +
5603 + // If the history tab is visible, only then setup
5604 + if(!pagelayer.$$('#pagelayer-history').is(':visible') && !force){
5605 + return;
5606 + }
5607 +
5608 + // The current active action id
5609 + var current_id = pagelayer_history_obj['current_active_item_id'];
5610 +
5611 + // pagelayer-HISTORY - Element Properties Dialog
5612 + var pagelayer_history_html = '<div class="pagelayer-history-tabs">'+
5613 + '<div class="pagelayer-history-tab" pagelayer-history-tab="actions" pagelayer-history-active-tab="1">Actions</div>'+
5614 + '<div class="pagelayer-history-tab" pagelayer-history-tab="revisions">Revisions</div>'+
5615 + '</div>'+
5616 + '<div class="pagelayer-history-body">'+
5617 + '<div class="pagelayer-history-section active" pagelayer-show-tab="actions">';
5618 +
5619 + // Any actions
5620 + if(pagelayer_history_obj['action_data'].length > 0){
5621 +
5622 + for(var x in pagelayer_history_obj['action_data']){
5623 +
5624 + if(pagelayer_empty(pagelayer_history_obj['action_data'][x])){continue;}
5625 +
5626 + var title = pagelayer_history_obj['action_data'][x]['title'] || '';
5627 + var subTitle = pagelayer_history_obj['action_data'][x]['subTitle'] || '';
5628 + var action = pagelayer_history_obj['action_data'][x]['action'] || '';
5629 + var tmp_attr = pagelayer_history_obj['action_data'][x]['attrType'] || '';
5630 + var eAttr = '';
5631 +
5632 + if(!pagelayer_empty(tmp_attr) && tmp_attr == "tmp_attr"){
5633 + eAttr = "pagelayer-history-hidden";
5634 + }
5635 +
5636 + pagelayer_history_html += '<div class="pagelayer-history-holder '+((current_id == x) ? 'current_active_item' : '' )+' '+eAttr+'" history-action-id="'+x+'" >'+
5637 + '<div class="pagelayer-history-detail-holder">'+
5638 + '<span class="pagelayer-history-title"><b> '+title+' </b></span>'+
5639 + '<span class="pagelayer-history-subtitle"> '+subTitle+' </span>'+
5640 + '<span class="pagelayer-history-action"><i> '+action+' </i></span>'+
5641 + '</div>'+
5642 + '<div class="pagelayer-history-icon">'+
5643 + '<span class="pagelayer-history-check pli pli-checkmark" aria-hidden="true"></span>'+
5644 + '</div>'+
5645 + '</div>';
5646 + }
5647 +
5648 + }else{
5649 + pagelayer_history_html += 'No Actions history available yet';
5650 + }
5651 +
5652 + pagelayer_history_html += '</div>'+
5653 + '<div class="pagelayer-history-section" pagelayer-show-tab="revisions">';
5654 +
5655 + // Any revisions ?
5656 + if(pagelayer_revision_obj){
5657 + for(var x in pagelayer_revision_obj){
5658 + pagelayer_history_html += '<div class="pagelayer-revision-holder" revision-id="'+pagelayer_revision_obj[x]['ID']+'">'+
5659 + '<div class="pagelayer-revision-img-holder">'+
5660 + '<img src="'+pagelayer_revision_obj[x]['post_author_url']+'" />'+
5661 + '</div>'+
5662 + '<div class="pagelayer-revision-detail-holder">'+
5663 + '<div class="pagelayer-revision-date">'+
5664 + pagelayer_revision_obj[x]['post_date_ago']+
5665 + '('+pagelayer_revision_obj[x]['post_date']+')'+
5666 + '</div>'+
5667 + '<div class="pagelayer-revision-author">'+
5668 + pagelayer_revision_obj[x]['post_type'] +' by '+
5669 + pagelayer_revision_obj[x]['post_author_name']+
5670 + '</div>'+
5671 + '</div>'+
5672 + '<div class="pagelayer-revision-icon-holder">'+
5673 + '<i class="pagelayer-revision-delete pli pli-cross"></i>'+
5674 + '</div>'+
5675 + '</div>';
5676 + }
5677 +
5678 + }else{
5679 + pagelayer_history_html += 'No Revisions history available';
5680 + }
5681 +
5682 + pagelayer_history_html += '</div>'+
5683 + '</div>';
5684 +
5685 + // Create the dialog box
5686 + pagelayer.$$('#pagelayer-history').html(pagelayer_history_html);
5687 + var holder = pagelayer.$$('#pagelayer-history');
5688 +
5689 + // Set active history holder
5690 + holder.find('.pagelayer-history-holder').on('click', function(){
5691 + var hEle = jQuery(this);
5692 + var prev_item_id = pagelayer_history_obj['current_active_item_id'];
5693 + hEle.parent().children().removeClass('current_active_item');
5694 + hEle.addClass('current_active_item');
5695 + var do_item_id = parseInt(hEle.attr('history-action-id'));
5696 + pagelayer_history_action_setup(do_item_id, prev_item_id);
5697 + });
5698 +
5699 + // Apply revision
5700 + holder.find('.pagelayer-revision-holder').on('click', function(){
5701 + var revision_id = jQuery(this).attr('revision-id');
5702 +
5703 + jQuery.ajax({
5704 + url: pagelayer_ajax_url+'&action=pagelayer_apply_revision&revisionID='+revision_id,
5705 + type: 'post',
5706 + data: {
5707 + pagelayer_nonce: pagelayer_ajax_nonce,
5708 + 'pagelayer-live' : 1,
5709 + },
5710 + success: function(response, status, xhr){
5711 +
5712 + var obj = jQuery.parseJSON(response);
5713 + if(obj['error']){
5714 + pagelayer_show_msg(obj['error'] , 'error');
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
5727 + jQuery(pagelayer_editable).html(obj['content']);
5728 +
5729 + // Add previous post_name and post_status
5730 + var props_new = jQuery(pagelayer_editable).find('.pagelayer-post_props');
5731 + if(props_new.length > 0){
5732 +
5733 + if(pagelayer_empty(post_name)){
5734 + post_name = pagelayer_default_params.pl_post_props.post_name;
5735 + }
5736 +
5737 + if(pagelayer_empty(post_status)){
5738 + post_status = pagelayer_default_params.pl_post_props.post_status;
5739 + }
5740 +
5741 + var tmp = {};
5742 + tmp['post_name'] = post_name;
5743 + tmp['post_status'] = post_status;
5744 + pagelayer_set_atts(props_new, tmp);
5745 + }
5746 +
5747 + // Need to pass true to render table
5748 + pagelayer_element_setup('.pagelayer-ele', true);
5749 + pagelayer_add_widget();
5750 + pagelayer_show_msg(obj['success'], 'success');
5751 + }
5752 + }
5753 + });
5754 + });
5755 +
5756 + // Delete the revision
5757 + holder.find('.pagelayer-revision-delete').click(function(e){
5758 +
5759 + e.stopPropagation();
5760 + var rEle = jQuery(this).closest('.pagelayer-revision-holder');
5761 + var revision_id = rEle.attr('revision-id');
5762 +
5763 + if(confirm("Are you sure you want to delete the revision ?")){
5764 + jQuery.ajax({
5765 + url: pagelayer_ajax_url+'&action=pagelayer_delete_revision&revisionID='+revision_id,
5766 + type: 'post',
5767 + data: {pagelayer_nonce: pagelayer_ajax_nonce},
5768 + success: function(response, status, xhr){
5769 +
5770 + var obj = jQuery.parseJSON(response);
5771 + if(obj['error']){
5772 + pagelayer_show_msg(obj['error'], 'error');
5773 + }else{
5774 + pagelayer_show_msg(obj['success'], 'success');
5775 + rEle.hide();
5776 + }
5777 +
5778 + }
5779 + });
5780 + }
5781 +
5782 + });
5783 +
5784 + // The tabs
5785 + holder.find('.pagelayer-history-tab').on('click', function(){
5786 + var attr = 'pagelayer-history-active-tab';
5787 + holder.find('.pagelayer-history-tab').each(function(){
5788 + jQuery(this).removeAttr(attr);
5789 + });
5790 + jQuery(this).attr(attr, 1);
5791 +
5792 + // Get the active tab
5793 + var active_tab = holder.find('[pagelayer-history-active-tab]').attr('pagelayer-history-tab');
5794 +
5795 + // Trigger the showing of rows
5796 + holder.find('[pagelayer-show-tab]').each(function(){
5797 + var sec = jQuery(this);
5798 +
5799 + // Is it the active tab ?
5800 + if(sec.attr('pagelayer-show-tab') != active_tab){
5801 + sec.hide();
5802 + }else{
5803 + sec.show();
5804 + }
5805 + });
5806 + });
5807 +}
5808 +
5809 +// Get revisions Handler
5810 +function pagelayer_get_revision(){
5811 +
5812 + jQuery.ajax({
5813 + url: pagelayer_ajax_url+'&action=pagelayer_get_revision&postID='+pagelayer_postID,
5814 + type: 'post',
5815 + data: {
5816 + pagelayer_nonce: pagelayer_ajax_nonce,
5817 + },
5818 + //async:false,
5819 + success: function(response, status, xhr){
5820 + var obj = jQuery.parseJSON(response);
5821 +
5822 + if(!pagelayer_empty(obj['error'])){
5823 + pagelayer_show_msg(obj['error'], 'error');
5824 + }else{
5825 + pagelayer_revision_obj = obj;
5826 + pagelayer_history_setup(true);
5827 + }
5828 + }
5829 + });
5830 +};
5831 +
5832 +// Do the history action - use for ctrl-z and ctrl-y
5833 +function pagelayer_do_history(action){
5834 +
5835 + var cur_id = pagelayer_history_obj['current_active_item_id'];
5836 + var new_id = cur_id;
5837 + var action_data_len = pagelayer_history_obj['action_data'].length;
5838 +
5839 +
5840 + if(action == 'undo'){
5841 +
5842 + // You cannot undo from the first movement
5843 + if(cur_id == 0){
5844 + return true;
5845 + }
5846 +
5847 + for(var i = (cur_id - 1); i => 0; i--){
5848 +
5849 + var action = pagelayer_history_obj['action_data'][i];
5850 +
5851 + if('attrType' in action && action['attrType'] == 'tmp_attr'){
5852 + continue;
5853 + }
5854 +
5855 + new_id = i;
5856 + break;
5857 +
5858 + }
5859 +
5860 + }else if(action == 'redo'){
5861 + for(var i = cur_id + 1; i < action_data_len; i++){
5862 +
5863 + var action = pagelayer_history_obj['action_data'][i];
5864 +
5865 + if('attrType' in action && action['attrType'] == 'tmp_attr'){
5866 + continue;
5867 + }
5868 +
5869 + new_id = i;
5870 + break;
5871 +
5872 + }
5873 + }
5874 +
5875 + // Do the action
5876 + pagelayer_history_action_setup(new_id, cur_id);
5877 + pagelayer_history_setup();
5878 +
5879 +};
5880 +
5881 +// Action setup handle on ctrl-z and ctrl-y
5882 +function pagelayer_history_action_setup(current_item_id, prev_item_id){
5883 +
5884 + // Set this as the current active
5885 + pagelayer_history_obj['current_active_item_id'] = current_item_id;
5886 +
5887 + // Delete the element
5888 + var delete_ele = function(id){
5889 +
5890 + // Set Pagelayer History FALSE to prevent saving delete action in action history
5891 + pagelayer.history_action = false;
5892 +
5893 + pagelayer_delete_element('[pagelayer-id='+id+']');
5894 +
5895 + // Set Pagelayer History TRUE
5896 + pagelayer.history_action = true;
5897 +
5898 + };
5899 +
5900 + // Re-setup the element
5901 + var resetup_ele = function(history_array){
5902 + jQuery(history_array.cEle.cEle)[history_array.cEle.method](history_array.html);
5903 + pagelayer_element_setup('[pagelayer-id='+history_array.pl_id+'], [pagelayer-id='+history_array.pl_id+'] .pagelayer-ele', true);
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);
5909 + };
5910 +
5911 + // Re-setup the element attr
5912 + var reset_ele_attr = function(hEle, atts, val, attrType){
5913 +
5914 + // Set Pagelayer History FALSE to prevent saving attributes in action history
5915 + pagelayer.history_action = false;
5916 + if(attrType == "tmp_attr"){
5917 + pagelayer_set_tmp_atts(hEle, atts, val);
5918 + }else{
5919 + pagelayer_set_atts(hEle, atts, val);
5920 + }
5921 +
5922 + // The property holder
5923 + var holder = pagelayer.$$('.pagelayer-elpd-body');
5924 + holder.html(' ');
5925 + pagelayer_sc_render(hEle);
5926 + pagelayer_elpd_generate(hEle, holder);
5927 + pagelayer.history_action = true;
5928 +
5929 + };
5930 +
5931 + // Move element
5932 + var pagelayer_move_ele = function(id, move_loc){
5933 + var eWrap = pagelayer_wrap_by_id(id);
5934 + var pCol = eWrap.closest('.pagelayer-col-holder') || '';
5935 +
5936 + jQuery(move_loc.cEle)[move_loc.method](eWrap);
5937 +
5938 + // Ensure the column is not empty
5939 + if(!pagelayer_empty(pCol)){
5940 + pagelayer_empty_col(pCol);
5941 + pagelayer_empty_col(pagelayer_wrap_by_id(id).closest('.pagelayer-col-holder'));
5942 + }
5943 +
5944 + pagelayer_do_dirty(eWrap);
5945 + };
5946 +
5947 + // Undo actions
5948 + var pagelayer_undo_action = function(history_array){
5949 + var action = history_array.action;
5950 + var id = history_array.pl_id;
5951 +
5952 + if(action == "Edited"){
5953 + hEle = jQuery('[pagelayer-id="'+id+'"]');
5954 + reset_ele_attr(hEle, history_array.atts, history_array.oldVal, history_array.attrType);
5955 + }else if(action == "Added"){
5956 + delete_ele(id);
5957 + }else if(action == "Deleted"){
5958 + resetup_ele(history_array);
5959 + }else if(action == "Copied"){
5960 + delete_ele(id);
5961 + }else if(action == "Moved"){
5962 + pagelayer_move_ele(id, history_array.before_loc);
5963 + }
5964 + };
5965 +
5966 + // Redo actions
5967 + var pagelayer_redo_action = function(history_array){
5968 + var action = history_array.action;
5969 + var id = history_array.pl_id;
5970 +
5971 + if(action == "Edited"){
5972 + hEle = jQuery('[pagelayer-id="'+id+'"]');
5973 + reset_ele_attr(hEle, history_array.atts, history_array.newVal, history_array.attrType);
5974 + }else if(action == "Added"){
5975 + resetup_ele(history_array);
5976 +
5977 + if(history_array.tag != "pl_row" && history_array.tag != "pl_col" ){
5978 + // Ensure the column is not empty
5979 + pagelayer_empty_col(history_array.cEle.cEle);
5980 + }
5981 + }else if(action == "Deleted"){
5982 + delete_ele(id);
5983 + }else if(action == "Copied"){
5984 + resetup_ele(history_array);
5985 + }else if(action == "Moved"){
5986 + pagelayer_move_ele(id, history_array.after_loc);
5987 + }
5988 + };
5989 +
5990 + if(prev_item_id > current_item_id){
5991 +
5992 + // All Actions for undo here
5993 + var i = parseInt(prev_item_id);
5994 +
5995 + for(i; i > current_item_id; i--){
5996 +
5997 + var history_array = pagelayer_history_obj['action_data'][i];
5998 + var sub_actions_group = history_array['sub_actions_group'] || '';
5999 +
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 + }
6006 + }
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 + }
6017 + }
6018 +
6019 + }else{
6020 +
6021 + // All Actions for redo here
6022 + var i = parseInt(prev_item_id)+1;
6023 +
6024 + for(i; i <= current_item_id; i++){
6025 +
6026 + var history_array = pagelayer_history_obj['action_data'][i];
6027 + var sub_actions_group = history_array['sub_actions_group'] || '';
6028 + // Main action
6029 + pagelayer_redo_action(history_array);
6030 +
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]);
6035 + }
6036 + }
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 + }
6044 + }
6045 + }
6046 +
6047 +};
6048 +
2232 6049 // Report an error
2233 6050 function pagelayer_error(error, func){
2234 6051 var prefix = func || '';
2235 6052 alert(prefix+error);
@@ -2235,41 +6052,128 @@
2235 6052 alert(prefix+error);
2236 6053 };
2237 6054
2238 6055 function pagelayer_bottombar(){
2239 - var holder = pagelayer.$$('.pagelayer-bottombar-holder');
2240 - var html = '<div class="pagelayer-bottombar">'+
2241 - '<div class="pagelayer-bottombar-rightbuttons">'+
2242 - '<button class="pagelayer-update-button">Update</button>'+
2243 - '<button class="pagelayer-close-button">Close</button>'+
2244 - '<div class="pagelayer-mode-wrapper">'+
2245 - '<i class="pagelayer-mode-button fa fa-desktop"></i>'+
2246 - '<div class="pagelayer-mode-buttons-wrapper">'+
2247 - '<i class="screen-mode fa fa-desktop" pagelayer-mode-data="desktop"></i>'+
2248 - '<i class="screen-mode fa fa-tablet" pagelayer-mode-data="tablet"></i>'+
2249 - '<i class="screen-mode fa fa-mobile" pagelayer-mode-data="mobile"></i>'+
2250 - '</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>'+
2251 6071 '</div>'+
2252 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>'+
2253 6088 '</div>';
2254 6089
2255 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 +
2256 6096 holder.find('.pagelayer-update-button').on('click', function(){
2257 6097 pagelayer_save();
6098 + pagelayer_history_setup();// Setup history tab after update
2258 6099 });
6100 +
2259 6101 holder.find('.pagelayer-close-button').on('click', function(){
2260 6102 pagelayer_close();
2261 6103 });
6104 +
2262 6105 holder.find('.screen-mode').on('click', function(){
2263 6106 var screen_mode = jQuery(this).attr('pagelayer-mode-data');
2264 6107 pagelayer_set_screen_mode(screen_mode);
2265 - holder.find('.pagelayer-mode-buttons-wrapper').toggle();
6108 + holder.find('.screen-mode').removeClass('active');
6109 + jQuery(this).addClass('active');
2266 6110 });
2267 6111
2268 - holder.find('.pagelayer-mode-button').on('click', function(){
2269 - holder.find('.pagelayer-mode-buttons-wrapper').toggle();
6112 + holder.find('.pagelayer-history-icon').closest('.pagelayer-header-icon-wrap').click(function(){
6113 + pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text(pagelayer_l('pagelayer_history'));
6114 + pagelayer.$$('.pagelayer-logo').hide();
6115 + pagelayer_leftbar_tab('pagelayer-history');
6116 + pagelayer_active = {};
6117 + pagelayer_history_setup();
2270 6118 });
2271 -}
6119 +
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'));
6122 + pagelayer.$$('.pagelayer-logo').hide();
6123 +
6124 + // If the navigator tab visible, then don't setup
6125 + if(!pagelayer.$$('#pagelayer-navigator').is(':visible')){
6126 + pagelayer_navigator_setup();
6127 + }
6128 +
6129 + pagelayer_leftbar_tab('pagelayer-navigator');
6130 + pagelayer_active = {};
6131 + });
6132 +
6133 + holder.find('.pagelayer-preview').click(function(){
6134 +
6135 + // If the page is not dirty
6136 + if(!pagelayer_isDirty){
6137 +
6138 + // Open in new tab the existing page itself
6139 + window.open(pagelayer_post_permalink, '_blank');
6140 + return;
6141 +
6142 + }
6143 +
6144 + // Get post content
6145 + var post = pagelayer_generate_sc(pagelayer_editable);//alert(post);return;
6146 +
6147 + pagelayer.$$('.pagelayer-body').css({'opacity' : '0.33'});
6148 + jQuery.ajax({
6149 + url: pagelayer_ajax_url+'&action=pagelayer_create_post_autosave&postID='+pagelayer_postID,
6150 + type: 'POST',
6151 + data: {
6152 + 'pagelayer_nonce': pagelayer_ajax_nonce,
6153 + 'pagelayer_post_content': pagelayer_Base64.encode(post)
6154 + },
6155 + success: function(data) {
6156 + var data = JSON.parse(data);
6157 +
6158 + // If there is some error
6159 + if(!pagelayer_empty(data['error']) || pagelayer_empty(data['id'])){
6160 + pagelayer_show_msg('Unable to set preview for some reason', 'error');
6161 + return;
6162 + }
6163 +
6164 + var url = data['url']+'&preview_id='+pagelayer_postID+'&preview_nonce='+
6165 + pagelayer_preview_nonce;
6166 +
6167 + // Open in new tab
6168 + window.open(url, '_blank');
6169 + },
6170 + complete: function(){
6171 + pagelayer.$$('.pagelayer-body').css({'opacity' : '1'});
6172 + }
6173 + });
6174 + });
6175 +};
2272 6176
2273 6177
2274 6178 ///////////////////////////////
2275 6179 // Miscellaneuos Functions
@@ -2274,89 +6178,298 @@
2274 6178 ///////////////////////////////
2275 6179 // Miscellaneuos Functions
2276 6180 ///////////////////////////////
2277 6181
2278 -// Generates a random string of "n" characters
2279 -function pagelayer_randstr(n, special){
2280 - var text = '';
2281 - var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
6182 +// Setup General options
6183 +function pagelayer_setup_general_options(){
2282 6184
2283 - special = special || 0;
2284 - if(special){
2285 - possible = possible + '&#$%@';
6185 + var holder = pagelayer.$$('.pagelayer-general-options');
6186 +
6187 + if(holder.children().length > 0){
6188 + return;
2286 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>';
2287 6225
2288 - for(var i=0; i < n; i++){
2289 - text += possible.charAt(Math.floor(Math.random() * possible.length));
2290 - }
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 + });
2291 6263
2292 - return text;
2293 -};
6264 + modal.unbind('click');
6265 + modal.on('click', function(e){
6266 +
6267 + if(e.target != this) {
6268 + return;
6269 + }
2294 6270
2295 -function pagelayer_update_site_title(val){
2296 - if(!pagelayer_empty(val)){
2297 - var site_name = jQuery('.pagelayer-wp-title').attr('pagelayer-a-site_name');
2298 - if(!pagelayer_empty(site_name)){
2299 - var site_title = jQuery.ajax({
2300 - url: pagelayer_ajax_url+'&action=pagelayer_fetch_site_title',
2301 - type: 'post',
2302 - async: false
2303 - }).responseText;
6271 + modal.hide();
6272 + });
6273 + });
6274 +}
6275 +
6276 +// Setup navigator
6277 +function pagelayer_navigator_setup(){
6278 +
6279 + var navigator_ele = pagelayer.$$('#pagelayer-navigator'),
6280 + navigator_padding = 10,
6281 + navigator_html = '';
6282 +
6283 + // Get the child elements list
6284 + var pagelayer_create_navi_list = function(selector){
6285 +
6286 + var navigator_list = '';
6287 +
6288 + selector.children('.pagelayer-ele-wrap, .pagelayer-ele').each(function(){
2304 6289
2305 - if(site_title != site_name){
2306 - var site_title = jQuery.ajax({
2307 - url: pagelayer_ajax_url+'&action=pagelayer_update_site_title',
2308 - type: 'post',
2309 - data: {'site_title': site_name},
2310 - async: false
2311 - }).responseText;
6290 + var cEle = jQuery(this),
6291 + tag = pagelayer_tag(cEle),
6292 + id = pagelayer_id(cEle),
6293 + child_ele = false,
6294 + ele_class = '';
6295 +
6296 + // If tag is not found then return
6297 + if(pagelayer_empty(tag)){
6298 + return;
2312 6299 }
6300 +
6301 + // if is row or col or inner-row
6302 + if(tag == 'pl_row' || tag == 'pl_col' || tag == 'pl_inner_row'){
6303 + ele_class = 'pagelayer-navigator-toggle';
6304 + child_ele = true;
6305 + }
6306 +
6307 + navigator_list += '<div class="pagelayer-navigetor-ele" pagelayer-id="'+id+'">'+
6308 + '<div class="pagelayer-ele-name '+ ele_class +'" pagelayer-tag="'+tag+'" style="padding-left:'+navigator_padding+'px">'+
6309 + '<i class="fa pagalayer-arrow"></i><i class="fa pagelayer-'+tag+'"></i>'+
6310 + pagelayer_shortcodes[tag]['name']+
6311 + '<span class="pagelayer-navigator-options"><i class="pli pli-pencil" data-action="edit"></i><i class="pli pli-trashcan" data-action="delete"></i></span>'+
6312 + '</div>';
6313 +
6314 + // Create the list of child element
6315 + if(child_ele){
6316 + navigator_padding += 15; // Increment padding left for widget
6317 + navigator_list += pagelayer_create_navi_list( cEle.find(pagelayer_shortcodes[tag]['holder']).first() );
6318 + navigator_padding -= 15; // Decrement padding left for widget
6319 + }
6320 +
6321 + navigator_list += '</div>';
6322 + });
6323 +
6324 + return navigator_list;
6325 + }
6326 +
6327 + // Create list of all rows and their child widgets
6328 + jQuery(pagelayer_editable).children('.pagelayer-wrap-row').each(function(){
6329 + navigator_html += pagelayer_create_navi_list(jQuery(this));
6330 + });
6331 +
6332 + // Put the navigator list
6333 + navigator_ele.html('<div class="pagelayer-leftbar-prop-body">'+navigator_html+'</div>');
6334 +
6335 + // edit and delete element click handler
6336 + navigator_ele.find('.pagelayer-navigator-options .pli').on('click', function(event){
6337 +
6338 + var sEle = jQuery(this).closest('.pagelayer-navigetor-ele');
6339 + var sId = sEle.attr('pagelayer-id');
6340 + var action = jQuery(this).data('action');
6341 + if( action == 'edit'){
6342 + pagelayer_edit_element('[pagelayer-id = '+sId+']', event);
6343 + }else if(action == 'delete'){
6344 + sEle.find('.pagelayer-ele-name').css({'background':'rgb(255, 114, 114)','opacity':'0.5'});
6345 + pagelayer_delete_element('[pagelayer-id = '+sId+']');
2313 6346 }
6347 +
6348 + });
6349 +
6350 + // On click toggle the element
6351 + navigator_ele.find('.pagelayer-ele-name').on('click', function(){
6352 +
6353 + var tEle = jQuery(this);
6354 + var pl_id = tEle.parent().attr('pagelayer-id'); // Get Pagelayer id
6355 + var jEle = pagelayer_ele_by_id(pl_id);
6356 +
6357 + // If the class "pagelayer-navigator-toggle" exist then toggle
6358 + if(tEle.hasClass('pagelayer-navigator-toggle')){
6359 + tEle.parent().toggleClass('pagelayer-navigator-open');
6360 + }
6361 +
6362 + // Also open all parents
6363 + tEle.parent().parents('.pagelayer-navigetor-ele').addClass('pagelayer-navigator-open');
6364 +
6365 + // Set the click element active
6366 + navigator_ele.find('.pagelayer-ele-name').removeClass('pagelayer-navi-active');
6367 + tEle.addClass('pagelayer-navi-active')
6368 +
6369 + // Set the element active
6370 + if(jEle.length > 0){
6371 + //pagelayer_active.el = pagelayer_data(jEle);
6372 + pagelayer_set_active(jEle);
6373 + pagelayer_scroll_to_viewport(jEle);
6374 + }
6375 +
6376 + });
6377 +
6378 + // Do active ele tab open
6379 + if( pagelayer_active.el && pagelayer_active.el.id ){
6380 + navigator_ele.find('[pagelayer-id="'+pagelayer_active.el.id+'"]').children('.pagelayer-ele-name').click();
2314 6381 }
6382 +
6383 + /* var posY = 0, orig_eleY= 0;
6384 +
6385 + // On mouse down in pagelayer-ele-name
6386 + navigator_ele.find('.pagelayer-ele-name').on('mousedown', function(e){
6387 + e = e || window.event;
6388 + e.preventDefault();
6389 +
6390 + // Get ele position
6391 + orig_eleY = jQuery(this).offset().top;
6392 +
6393 + // Get the mouse cursor at startup:
6394 + posY = e.clientY;
6395 +
6396 + // The variable needs to be empty.
6397 + newMethod = '';
6398 +
6399 + // Mouse up handler
6400 + var ele_mousemove = function(){
6401 +
6402 + }
6403 +
6404 + // Mouse move handler
6405 + var ele_mouseup = function(){
6406 + pagelayer.$$(document).off('mouseup', ele_mouseup);
6407 + pagelayer.$$(document).off('mousemove', ele_mousemove);
6408 + }
6409 +
6410 + pagelayer.$$(document).on('mouseup', ele_mouseup);
6411 + pagelayer.$$(document).on('mousemove', ele_mousemove);
6412 +
6413 + }); */
6414 +
6415 +
2315 6416 }
2316 6417
2317 -function pagelayer_trim(str, charlist){
2318 - // discuss at: http://locutus.io/php/trim/
6418 +// Scroll page to element view port
6419 +function pagelayer_scroll_to_viewport(jEle, timeout, parentEle){
2319 6420
2320 - if(typeof str != 'string'){
2321 - return str;
2322 - }
6421 + var scrolled = parentEle || jQuery('html, body');
6422 + timeout = timeout || 500;
6423 + parentEle = parentEle || jQuery(window);
2323 6424
2324 - var whitespace = [' ', '\n', '\r', '\t', '\f', '\x0b', '\xa0', '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u2005', '\u2006', '\u2007', '\u2008', '\u2009', '\u200a', '\u200b', '\u2028', '\u2029', '\u3000' ].join('')
2325 - var l = 0
2326 - var i = 0
2327 - str += ''
6425 + setTimeout(function(){
6426 + var parentHeight = parentEle.height(),
6427 + parentScrollTop = parentEle.scrollTop(),
6428 + elementTop = jEle.offset().top,
6429 + topToCheck = elementTop - parentScrollTop;
6430 +
6431 + if (topToCheck > 0 && topToCheck < parentHeight) {
6432 + return;
6433 + }
2328 6434
2329 - if (charlist) {
2330 - whitespace = (charlist + '').replace(/([[\]().?/*{}+$^:])/g, '$1')
2331 - }
6435 + var scrolling = elementTop - parentHeight / 2;
6436 + scrolled.stop(true).animate({
6437 + scrollTop: scrolling
6438 + }, 1000);
6439 + }, timeout);
6440 +}
2332 6441
2333 - l = str.length
2334 - for (i = 0; i < l; i++) {
2335 - if (whitespace.indexOf(str.charAt(i)) === -1) {
2336 - str = str.substring(i)
2337 - break
2338 - }
6442 +// Generates a random string of "n" characters
6443 +function pagelayer_randstr(n, special){
6444 + var text = '';
6445 + var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
6446 +
6447 + special = special || 0;
6448 + if(special){
6449 + possible = possible + '&#$%@';
2339 6450 }
2340 -
2341 - l = str.length
2342 - for (i = l - 1; i >= 0; i--) {
2343 - if (whitespace.indexOf(str.charAt(i)) === -1) {
2344 - str = str.substring(0, i + 1)
2345 - break
2346 - }
6451 +
6452 + for(var i=0; i < n; i++){
6453 + text += possible.charAt(Math.floor(Math.random() * possible.length));
2347 6454 }
2348 6455
2349 - return whitespace.indexOf(str.charAt(0)) === -1 ? str : ''
6456 + return text;
2350 6457 };
2351 6458
6459 +function pagelayer_randInt(max) {
6460 + return Math.floor(Math.random() * Math.floor(max));
6461 +}
6462 +
2352 6463 // Convert the regular URL of a Video to a Embed URL
2353 -function pagelayer_video_url(src){
2354 -
6464 +function pagelayer_video_url(src, no_url){
6465 +
6466 + no_url = no_url || false;
2355 6467 var youtubeRegExp = /youtube\.com|youtu\.be/;
2356 6468 var vimeoRegExp = /vimeo\.com/;
2357 6469 var match = '';
2358 6470 var videoId = '';
6471 + var vid_params = {};
2359 6472
2360 6473 if (youtubeRegExp.exec(src)) {
2361 6474 match = 'youtube';
2362 6475 } else if (vimeoRegExp.exec(src)) {
@@ -2383,9 +6496,15 @@
2383 6496 } else if (youtube.exec(src)) {
2384 6497 videoId = src.split('.be/');
2385 6498 }
2386 6499
2387 - 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();
2388 6507
2389 6508 break;
2390 6509
2391 6510 case 'vimeo':
@@ -2398,48 +6517,88 @@
2398 6517 } else if (vimeoRegExp.exec(src)) {
2399 6518 videoId = src.split('.com/');
2400 6519 }
2401 6520
2402 - 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 + };
2403 6526
2404 6527 break;
2405 6528 default:
2406 - return src;
6529 + vid_params = {
6530 + type : 'local',
6531 + src : src
6532 + };
6533 +
2407 6534 }
6535 +
6536 + if(!no_url){
6537 + return vid_params.src;
6538 + }
6539 +
6540 + return vid_params;
2408 6541 };
2409 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 +
2410 6554 // Add widget section
2411 6555 function pagelayer_add_widget(){
2412 6556
2413 6557 html='<div class="pagelayer-add-widget-area">'+
2414 - '<i class="pagelayer-add-row fa fa-plus-circle"></i>'+
2415 - '<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>'+
2416 6564 '</div>';
2417 6565
2418 - jQuery('.entry-content').append(html);
6566 + jQuery(pagelayer_editable).append(html);
2419 6567
2420 6568 var add_area = jQuery('.pagelayer-add-widget-area');
2421 6569
2422 6570 // Add a code before this
2423 - var add_sc = function(tag){
6571 + var add_sc = function(tag, global_id = ''){
2424 6572
6573 + var attr = '';
6574 + if(!pagelayer_empty(global_id)){
6575 + attr = ' pagelayer-global-id="'+global_id+'" ';
6576 + }
6577 +
2425 6578 // Create Row
2426 - var row = jQuery('<div pagelayer-tag="pl_row"></div>');
6579 + var row = jQuery('<div pagelayer-tag="pl_row" '+((tag == 'pl_row') ? attr : '') +'></div>');
2427 6580 add_area.before(row);
2428 6581 var row_id = pagelayer_onadd(row, false);
2429 6582 var rEle = pagelayer_ele_by_id(row_id);
2430 6583
2431 - if(tag == 'pl_row'){
6584 + if(tag == 'pl_row' && !pagelayer_empty(global_id)){
2432 6585 rEle.click();
2433 6586 return row_id;
2434 6587 }
2435 6588
2436 6589 // Create Column
2437 - var col = jQuery('<div pagelayer-tag="pl_col"></div>');
6590 + var col = jQuery('<div pagelayer-tag="pl_col" '+((tag == 'pl_col') ? attr : '') +'></div>');
2438 6591 rEle.find('.pagelayer-row-holder').append(col);
2439 6592 var col_id = pagelayer_onadd(col, false);
2440 6593 var cEle = pagelayer_ele_by_id(col_id);
2441 6594
6595 +
6596 + if(tag == 'pl_row'){
6597 + rEle.click();
6598 + return row_id;
6599 + }
6600 +
2442 6601 if(tag == 'pl_col'){
2443 6602 cEle.click();
2444 6603 return col_id;
2445 6604 }
@@ -2444,24 +6603,66 @@
2444 6603 return col_id;
2445 6604 }
2446 6605
2447 6606 // Create element
2448 - var ele = jQuery('<div pagelayer-tag="'+tag+'"></div>');
6607 + var ele = jQuery('<div pagelayer-tag="'+tag+'" '+attr+'></div>');
2449 6608 cEle.find('.pagelayer-col-holder').append(ele);
6609 + //console.log(ele);
2450 6610 var id = pagelayer_onadd(ele);
2451 -
6611 + //console.log(id);
6612 + //console.log(col_id);
6613 + var eEle = pagelayer_ele_by_id(col_id);
6614 + //console.log(eEle);
2452 6615 // Ensure the column is not empty
2453 6616 pagelayer_empty_col(cEle.find('.pagelayer-col-holder'));
2454 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 +
2455 6625 return id;
2456 6626
2457 6627 }
2458 6628
2459 - // Handle Click
2460 - add_area.on('click', function(){
6629 + // Handle Click on Plus Button
6630 + add_area.find('.pagelayer-add-circle-plus').on('click', function(e){
6631 + e.stopPropagation();
2461 6632 add_sc('pl_col');
2462 6633 });
2463 6634
6635 + // Handle Click on Template/Folder Button
6636 + add_area.find('.pagelayer-add-section').on('click', function(e){
6637 + e.stopPropagation();
6638 + pagelayer_add_section_area();// Setup and show sections modal
6639 + });
6640 +
6641 + // Handle Click on Build with AI Button
6642 + add_area.find('.pagelayer-add-ai, .pagelayer-add-circle-ai').on('click', function(e){
6643 + e.stopPropagation();
6644 + if(typeof PagelayerAI !== 'undefined' && PagelayerAI.showPanel){
6645 + PagelayerAI.showPanel();
6646 + } else if(typeof window.parent !== 'undefined' && typeof window.parent.PagelayerAI !== 'undefined' && window.parent.PagelayerAI.showPanel){
6647 + window.parent.PagelayerAI.showPanel();
6648 + } else if(jQuery('.pagelayer-ai-topbar-btn').length > 0){
6649 + jQuery('.pagelayer-ai-topbar-btn').trigger('click');
6650 + } else if(window.parent && window.parent.jQuery && window.parent.jQuery('.pagelayer-ai-topbar-btn').length > 0){
6651 + window.parent.jQuery('.pagelayer-ai-topbar-btn').trigger('click');
6652 + }
6653 + });
6654 +
6655 +
6656 +
6657 + // Background click fallback (adds column if clicked outside circles)
6658 + add_area.on('click', function(e){
6659 + if(e.target === this || jQuery(e.target).hasClass('pagelayer-add-widget-text')){
6660 + e.stopPropagation();
6661 + add_sc('pl_col');
6662 + }
6663 + });
6664 +
2464 6665 // Handle Drag over
2465 6666 add_area.on('dragover', function(e){
2466 6667 //console.log(e)
2467 6668 add_area.addClass('pagelayer-add-widget-drag');
@@ -2481,8 +6682,9 @@
2481 6682 add_area.removeClass('pagelayer-add-widget-drag');
2482 6683 jQuery('.pagelayer-is-dragging').removeClass('pagelayer-is-dragging');
2483 6684
2484 6685 var tag = e.originalEvent.dataTransfer.getData('tag');
6686 + var global_id = e.originalEvent.dataTransfer.getData('global_id');
2485 6687
2486 6688 // Is it an existing element ?
2487 6689 if(tag.length < 1){
2488 6690 return false;
@@ -2491,7 +6693,1490 @@
2491 6693 e.preventDefault();
2492 6694
2493 6695 //console.log(tag);
2494 6696
2495 - add_sc(tag);
6697 + add_sc(tag, global_id);
2496 6698 });
6699 +};
6700 +
6701 +// Is the element in view while scrolling
6702 +function pagelayer_isElementInView(elem, holder, partial) {
6703 + partial = partial || true;
6704 + var container = jQuery(holder);
6705 + var contHeight = container.height();
6706 + var contTop = container.scrollTop();
6707 + var contBottom = contTop + contHeight ;
6708 +
6709 + var elemTop = jQuery(elem).offset().top - container.offset().top;
6710 + var elemBottom = elemTop + jQuery(elem).height();
6711 +
6712 + var isTotal = (elemTop >= 0 && elemBottom <=contHeight);
6713 + var isPart = ((elemTop < 0 && elemBottom > 0 ) || (elemTop > 0 && elemTop <= container.height())) && partial;
6714 +
6715 + return isTotal || isPart ;
2497 6716 }
6717 +
6718 +// Append section modal into body
6719 +function pagelayer_add_section_area(){
6720 +
6721 + var body = pagelayer.$$('body');
6722 + var mEle = body.find('.pagelayer-add-section-modal-container');
6723 +
6724 + if(mEle.length > 0){
6725 + mEle.show();
6726 + return;
6727 + }
6728 +
6729 + var section_modal = '<div class="pagelayer-add-section-modal-container">'+
6730 + '<div class="pagelayer-add-section-modal-holder">'+
6731 + '<div class="pagelayer-add-section-modal">'+
6732 + '<div class="pagelayer-add-section-modal-header">'+
6733 + '<div>Add Sections</div>'+
6734 + '<div class="pagelayer-section-type-div">Type : '+
6735 + '<select name="type" id="pagelayer-section-type">'+
6736 + '<option value="section">Sections</option>'+
6737 + '<option value="header">Headers</option>'+
6738 + '<option value="footer">Footers</option>'+
6739 + '<option value="page">Pages</option>'+
6740 + '</select>'+
6741 + '</div>'+
6742 + '<div class="pagelayer-add-section-modal-close">&times;</div>'+
6743 + '</div>'+
6744 + '<div class="pagelayer-add-section-modal-row">'+
6745 + '<div class="pagelayer-add-section-modal-left">'+
6746 + '<div class="pagelayer-section-search-div">'+
6747 + '<i class="pli pli-search" ></i><input class="pagelayer-section-search" /><span class="pagelayer-sf-empty pli">&times;</span>'+
6748 + '</div>'+
6749 + '<div class="pagelayer-section-tags-holder"></div>'+
6750 + '</div>'+
6751 + '<div class="pagelayer-section-modal-body-holder">'+
6752 + '<div class="pagelayer-add-section-modal-body"></div>'+
6753 + '</div>'+
6754 + '</div>'+
6755 + '<div class="pagelayer-add-section-modal-overlay" style="display:none;">'+
6756 + '<div class="pagelayer-section-wait">'+
6757 + '<div class="pagelayer-loader">'+
6758 + '<div class="pagelayer-percent-parent"></div>'+
6759 + '</div><br/>'+
6760 + '<span>Please wait a moment</span>'+
6761 + '</div>'+
6762 + '</div>'+
6763 + '</div>'+
6764 + '</div>'+
6765 + '</div>';
6766 +
6767 + mEle = jQuery(section_modal);
6768 +
6769 + // Append the element in the body
6770 + body.append(mEle);
6771 +
6772 + // On click close modal
6773 + mEle.find('.pagelayer-add-section-modal-close').on('click', function(){
6774 + mEle.hide();
6775 + });
6776 +
6777 + // Search Empty
6778 + mEle.find('.pagelayer-sf-empty').on('click', function(){
6779 + mEle.find('.pagelayer-section-search').val('');
6780 + });
6781 +
6782 + // On select section type
6783 + mEle.find('#pagelayer-section-type').on('change', function(){
6784 + var val = jQuery(this).val();
6785 + pagelayer_add_sections_list_setup(val);
6786 + });
6787 +
6788 + // Append the list items into modal body
6789 + pagelayer_add_sections_list_setup();
6790 +
6791 + mEle.show();// Show the modal
6792 +
6793 +};
6794 +
6795 +// Append section list into modal body
6796 +function pagelayer_add_sections_list_setup(type){
6797 +
6798 + var mEle = pagelayer.$$('.pagelayer-add-section-modal-container');
6799 + var body = mEle.find('.pagelayer-add-section-modal-body');
6800 + var add_area = jQuery('.pagelayer-add-widget-area');
6801 + type = type || 'section';
6802 +
6803 + // Find the number of cols
6804 + var body_width = jQuery(window.parent).width();
6805 + var num_cols = 3;
6806 + if(body_width >= 1500){
6807 + num_cols = 4;
6808 + }else if(body_width >= 992){
6809 + num_cols = 3;
6810 + }else if(body_width >= 768){
6811 + num_cols = 2;
6812 + }else if(body_width >= 360){
6813 + num_cols = 1;
6814 + }
6815 + //console.log(num_cols+' - '+body_width);
6816 +
6817 + var viewer = '<div class="pagelayer-section-is-visible"></div>';
6818 + var selected_tags = {};
6819 + var result_set = {};
6820 +
6821 + // Setup the scroll
6822 + mEle.find('.pagelayer-section-tags-holder').slimScroll({
6823 + height: 'calc(100vh - 150px)',
6824 + railVisible: false,
6825 + alwaysVisible: true,
6826 + color: '#000',
6827 + size: '5px',
6828 + });
6829 +
6830 + // Create list of items
6831 + var pagelayer_section_list = function(){
6832 +
6833 + // List the tags
6834 + if(!pagelayer_empty(pagelayer_add_section_data[type]['tags'])){
6835 + var tags_html = '';
6836 + var tags = pagelayer_add_section_data[type]['tags'];
6837 + for(var k in tags){
6838 + tags_html += '<span class="pagelayer-section-tags" tag="'+k+'">'+k+' ('+tags[k].length+')</span>';
6839 + }
6840 + mEle.find('.pagelayer-section-tags-holder').html(tags_html);
6841 +
6842 + // Handle tag click
6843 + mEle.find('.pagelayer-section-tags').unbind('click');
6844 + mEle.find('.pagelayer-section-tags').on('click', function(e){
6845 +
6846 + var search = mEle.find('.pagelayer-section-search');
6847 +
6848 + // Blank the search
6849 + if(search.val().length > 0){
6850 + search.val('');
6851 + selected_tags = {};
6852 + }
6853 +
6854 + // Fill the selected_tags
6855 + tEle = jQuery(this);
6856 + var tag = tEle.attr('tag')
6857 +
6858 + if(tEle.attr('on') == '1'){
6859 + delete selected_tags[tag];
6860 + tEle.removeAttr('on');
6861 + }else{
6862 + tEle.attr('on', 1);
6863 + selected_tags[tag] = 1;
6864 + }
6865 +
6866 + // Filter
6867 + pagelayer_section_filter(false, 1);
6868 +
6869 + });
6870 + }
6871 +
6872 + // Fill in the result
6873 + result_set = { ...pagelayer_add_section_data[type]['list']};
6874 +
6875 + show_result();
6876 +
6877 + };
6878 +
6879 + // How the result and setup scroll
6880 + var show_result = function(){
6881 +
6882 + var html = '';
6883 + for(var i = 0; i < num_cols; i++){
6884 + html += '<div class="pagelayer-section-holder" pagelayer-section-type="'+type+'" num="'+i+'"></div>';
6885 + }
6886 +
6887 + // Blank the body
6888 + body.html(html+viewer);
6889 +
6890 + mEle.find('.pagelayer-section-modal-body-holder').unbind('scroll');
6891 + mEle.find('.pagelayer-section-modal-body-holder').on('scroll', pagelayer_section_body_scroll);
6892 + pagelayer_section_body_scroll();
6893 + }
6894 +
6895 + var scroll_accessed = false;
6896 +
6897 + // Section body ON scroll
6898 + var pagelayer_section_body_scroll = function(){
6899 +
6900 + // Check if there is anything to display in the first place, as we do delete pagelayer_add_section_data
6901 + if(pagelayer_empty(result_set)){
6902 + return;
6903 + }
6904 +
6905 + var tester = mEle.find('.pagelayer-section-is-visible');
6906 + var modal = mEle.find('.pagelayer-section-modal-body-holder');
6907 +
6908 + // If we have scroll
6909 + if(!pagelayer_isElementInView(tester, modal) || scroll_accessed){
6910 + return;
6911 + }
6912 +
6913 + scroll_accessed = true;
6914 +
6915 + var html = '';
6916 + var i = 0;
6917 +
6918 + // Loop result_set
6919 + for(var id in result_set){
6920 +
6921 + if(i >= (num_cols * 5)){
6922 + break;
6923 + }
6924 +
6925 + var col = i % num_cols;
6926 + //console.log(col);
6927 +
6928 + i++;
6929 +
6930 + var pro = 0;
6931 +
6932 + // Is it pro ?
6933 + if(!pagelayer_empty(result_set[id]) && pagelayer_empty(pagelayer_pro)){
6934 + pro = 1;
6935 + }
6936 +
6937 + html = '<div class="pagelayer-section-item" pagelayer-section-type="'+type+'" pagelayer-add-section-id="'+id+'">'+
6938 + '<img src="'+ pagelayer_add_section_data[type]['image_url'] + id +'/screenshot.jpg" alt="Pagelayer code screenshot" />'+
6939 + (pro ? '<div class="pagelayer-section-pro-req">Pro</div><div class="pagelayer-section-pro-txt">'+pagelayer.pro_txt+'</div>' : '')+
6940 + '</div>';
6941 +
6942 + body.find('.pagelayer-section-holder[num='+col+']').append(html);
6943 +
6944 + delete result_set[id];
6945 +
6946 + }
6947 +
6948 + //console.log(result_set);
6949 +
6950 + mEle.find('.pagelayer-section-item').unbind('click');
6951 + mEle.find('.pagelayer-section-item').on('click', function(e){
6952 + pagelayer_section_item_clickable(jQuery(this));
6953 + });
6954 +
6955 + scroll_accessed = false;
6956 +
6957 + }
6958 +
6959 + // If we have searched something / or clicked tags
6960 + var pagelayer_section_filter = function(event, not_input){
6961 +
6962 + var txt = mEle.find('.pagelayer-section-search').val();
6963 + var tags = pagelayer_add_section_data[type]['tags'];
6964 +
6965 + // Searched anything
6966 + if(!pagelayer_empty(txt) || pagelayer_empty(not_input)){
6967 +
6968 + // Blank the tags
6969 + selected_tags = {};
6970 +
6971 + mEle.find('.pagelayer-section-tags').removeAttr('on');
6972 +
6973 + for(var k in tags){
6974 + if(k.search(txt) >= 0){
6975 + selected_tags[k] = 1;
6976 + mEle.find('.pagelayer-section-tags[tag="'+k+'"]').attr('on', 1);
6977 + }
6978 + }
6979 +
6980 + }
6981 +
6982 + var new_result = {};
6983 + var new_length = 0;
6984 +
6985 + // Filter the content
6986 + for(var t in selected_tags){
6987 +
6988 + for(var i in tags[t]){
6989 + new_length++;
6990 + new_result[tags[t][i]] = tags[t][i];
6991 + }
6992 +
6993 + }
6994 +
6995 + // Copy the result
6996 + result_set = {...new_result};
6997 + //console.log(type);console.log(selected_tags);console.log(result_set);
6998 +
6999 + show_result();
7000 +
7001 + }
7002 +
7003 + // On search change
7004 + mEle.find('.pagelayer-section-search').unbind('input');
7005 + mEle.find('.pagelayer-section-search').on('input', pagelayer_section_filter);
7006 +
7007 + // On click items
7008 + var pagelayer_section_item_clickable = function(jEle){
7009 +
7010 + var section_id = jEle.attr('pagelayer-add-section-id');
7011 +
7012 + // IF section id not found
7013 + if(pagelayer_empty(section_id)){
7014 + return false;
7015 + }
7016 +
7017 + if(jEle.find('.pagelayer-section-pro-req').length > 0){
7018 + return false;
7019 + }
7020 +
7021 + // Show the overlay
7022 + mEle.find('.pagelayer-add-section-modal-overlay').show();
7023 +
7024 + // Do shortcode the content
7025 + jQuery.ajax({
7026 + url: pagelayer_ajax_url+'&action=pagelayer_get_section_shortcodes&postID='+pagelayer_postID,
7027 + type: 'POST',
7028 + data: {
7029 + 'pagelayer_nonce': pagelayer_ajax_nonce,
7030 + 'pagelayer_section_id': section_id,
7031 + 'pagelayer-live': 1
7032 + },
7033 + success: function(data) {
7034 +
7035 + try{
7036 +
7037 + var data = JSON.parse(data);
7038 +
7039 + if(!pagelayer_empty(data['error'])){
7040 + pagelayer_show_msg('Error getting the section', 'error');
7041 + mEle.find('.pagelayer-add-section-modal-overlay').hide();
7042 + mEle.hide();
7043 + return;
7044 + }
7045 +
7046 + var cEle = jQuery(data['code']);
7047 +
7048 + // Add section before add widget area
7049 + add_area.before(cEle);
7050 +
7051 + // We need to it setup
7052 + cEle.each(function(){
7053 + var pl_id = pagelayer_id(jQuery(this));
7054 +
7055 + if(!pagelayer_empty(pl_id)){
7056 + pagelayer_element_setup('[pagelayer-id="'+pl_id+'"], [pagelayer-id='+pl_id+'] .pagelayer-ele', true);
7057 + }
7058 + });
7059 +
7060 + }catch(e){
7061 + pagelayer_show_msg('Error getting the section', 'error');
7062 + mEle.find('.pagelayer-add-section-modal-overlay').hide();
7063 + mEle.hide();
7064 + return;
7065 + }
7066 +
7067 + },
7068 + complete: function(){
7069 + mEle.find('.pagelayer-add-section-modal-overlay').hide();
7070 + mEle.hide();
7071 + }
7072 + });
7073 + }
7074 +
7075 + // Load the data if not there
7076 + if(!(type in pagelayer_add_section_data)){
7077 +
7078 + // Show the loading
7079 + mEle.find('.pagelayer-add-section-modal-overlay').show();
7080 +
7081 + // Get the sections list data and append it
7082 + jQuery.ajax({
7083 + url: pagelayer_api_url+'/library.php?give='+type,
7084 + type: 'post',
7085 + success: function(response){
7086 + var tmp = JSON.parse(response);
7087 +
7088 + // Is the list there ?
7089 + if( !('list' in tmp && !pagelayer_empty(tmp['list'])) ){
7090 + return;
7091 + }
7092 +
7093 + pagelayer_add_section_data[type] = tmp;
7094 +
7095 + // Create the Type
7096 + pagelayer_section_list(type);
7097 +
7098 + // Hide the loading
7099 + mEle.find('.pagelayer-add-section-modal-overlay').hide();
7100 +
7101 + },
7102 + complete: function(){
7103 + mEle.find('.pagelayer-add-section-modal-overlay').hide();
7104 + }
7105 + });
7106 +
7107 + // We have the data, so show it
7108 + }else{
7109 + pagelayer_section_list(type);
7110 + }
7111 +}
7112 +
7113 +// Upload an image
7114 +function pagelayer_upload_image(fileName, blob, pagelayer_ajax_func){
7115 +
7116 + var formData = new FormData();
7117 + formData.append('action', 'upload-attachment');
7118 + formData.append('_ajax_nonce', pagelayer_media_ajax_nonce);
7119 + formData.append('async-upload', blob, fileName);
7120 +
7121 + jQuery.ajax({
7122 + url:pagelayer_ajax_url,
7123 + data: formData,// the formData function is available in almost all new browsers.
7124 + type:"post",
7125 + contentType:false,
7126 + processData:false,
7127 + cache:false,
7128 + beforeSend: function( xhr ) {
7129 + if(typeof pagelayer_ajax_func.beforeSend == 'function'){
7130 + pagelayer_ajax_func.beforeSend(xhr);
7131 + }
7132 + },
7133 + xhr: function() {
7134 + var xhr = new window.XMLHttpRequest();
7135 + if(typeof pagelayer_ajax_func.uploadProgress == 'function'){
7136 + xhr = pagelayer_ajax_func.uploadProgress(xhr);
7137 + }
7138 + return xhr;
7139 + },
7140 + error:function(err){
7141 + //console.error(err);
7142 + pagelayer_show_msg('Unable to upload image for some reason.', 'error');
7143 + },
7144 + success:function(response){
7145 + var obj = jQuery.parseJSON(response);
7146 + if(typeof pagelayer_ajax_func.success == 'function'){
7147 + pagelayer_ajax_func.success(obj);
7148 + }
7149 + },
7150 + complete:function(xhr){
7151 + if(typeof pagelayer_ajax_func.complete == 'function'){
7152 + pagelayer_ajax_func.complete(xhr);
7153 + }
7154 + }
7155 + });
7156 +};
7157 +
7158 +// On editable area image paste handler
7159 +function pagelayer_editable_paste_handler(pasteEvent, pagelayer_ajax_func){
7160 + var items,
7161 + is_Paste = (pasteEvent.type == 'paste' ? true : false),
7162 + mustPreventDefault = false,
7163 + reader;
7164 +
7165 + try {
7166 + if(is_Paste){
7167 + items = (pasteEvent.originalEvent || pasteEvent).clipboardData.items;
7168 + }else{
7169 + items = [pasteEvent];
7170 + }
7171 +
7172 + for (var i = items.length - 1; i >= 0; i -= 1) {
7173 +
7174 + if (items[i].type.match(/^image\//)) {
7175 +
7176 + reader = new FileReader();
7177 + /* jshint -W083 */
7178 + reader.onloadend = function(event) {
7179 +
7180 + var src = event.target.result;
7181 +
7182 + if(src.indexOf('data:image') === 0 ) {
7183 +
7184 + var block = src.split(";");
7185 + var contentType = block[0].split(":")[1];
7186 + var realData = block[1].split(",")[1];
7187 + if(is_Paste){
7188 + var fileName = "image."+contentType.split("/")[1];
7189 + }else{
7190 + var fileName = items[0]['name'];
7191 + }
7192 +
7193 + // Convert it to a blob to upload
7194 + var blob = pagelayer_b64toBlob(realData, contentType);
7195 +
7196 + pagelayer_upload_image(fileName, blob, pagelayer_ajax_func);
7197 +
7198 + }
7199 +
7200 + };
7201 + /* jshint +W083 */
7202 + if(is_Paste){
7203 + reader.readAsDataURL(items[i].getAsFile());
7204 + }else{
7205 + reader.readAsDataURL(items[i]);
7206 + }
7207 + mustPreventDefault = true;
7208 + }
7209 + }
7210 +
7211 + if(mustPreventDefault && is_Paste){
7212 + pasteEvent.stopPropagation();
7213 + pasteEvent.preventDefault();
7214 + }
7215 +
7216 + }catch(err){
7217 + console.log(err);
7218 + }
7219 +
7220 + return mustPreventDefault;
7221 +
7222 +}
7223 +
7224 +// Convert base64 to Blob
7225 +function pagelayer_b64toBlob(b64Data, contentType, sliceSize) {
7226 + contentType = contentType || '';
7227 + sliceSize = sliceSize || 512;
7228 +
7229 + var byteCharacters = atob(b64Data);
7230 + var byteArrays = [];
7231 +
7232 + for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
7233 + var slice = byteCharacters.slice(offset, offset + sliceSize);
7234 +
7235 + var byteNumbers = new Array(slice.length);
7236 + for (var i = 0; i < slice.length; i++) {
7237 + byteNumbers[i] = slice.charCodeAt(i);
7238 + }
7239 +
7240 + var byteArray = new Uint8Array(byteNumbers);
7241 +
7242 + byteArrays.push(byteArray);
7243 + }
7244 +
7245 + var blob = new Blob(byteArrays, {type: contentType});
7246 + return blob;
7247 +}
7248 +
7249 +// Function to check if the URL is external
7250 +function pagelayer_parse_theme_vars(img_url){
7251 +
7252 + for(x in pagelayer_theme_vars){
7253 + img_url = img_url.replace(x, pagelayer_theme_vars[x]);
7254 + }
7255 +
7256 + return img_url;
7257 +};
7258 +
7259 +// Tooltip Setup for Editor
7260 +function pagelayer_tooltip_setup(){
7261 + //pagelayer.$$('[data-tlite]').each(function(){pagelayer_tlite.show(jQuery(this).get(0));});return;
7262 + pagelayer.$$('[data-tlite]').hover(function(){
7263 + pagelayer_tlite.show(jQuery(this).get(0));
7264 + }, function(){
7265 + pagelayer_tlite.hide(jQuery(this).get(0));
7266 + });
7267 +
7268 +};
7269 +
7270 +// Pagelayer Messages
7271 +function pagelayer_show_msg(msg, state, time){
7272 +
7273 + time = time || 5000;
7274 + state = !pagelayer_empty(state) ? 'pagelayer-editor-msg-state-'+state : '';
7275 + var nholder = pagelayer.$$('.pagelayer-editor-notice');
7276 + var mEle = jQuery('<div class="pagelayer-editor-msg '+state+'">'+msg+' <span class="pli pli-cross pagelayer-notice-x"></span></div>');
7277 +
7278 + nholder.append(mEle);
7279 +
7280 + mEle.find('.pagelayer-notice-x').on('click', function(){
7281 + mEle.css({opacity: 0});
7282 + setTimeout(function(){
7283 + mEle.css({transition: 'none'});
7284 + mEle.slideUp(function(){
7285 + mEle.remove();
7286 + });
7287 + }, 900);
7288 + });
7289 +
7290 + setTimeout(function(){
7291 + mEle.find('.pagelayer-notice-x').click();
7292 + }, time);
7293 +
7294 +}
7295 +
7296 +// Pagelayer confirmation box
7297 +function pagelayer_confirmation_box(message, yesCallback, noCallback, yesText, noText) {
7298 +
7299 + yesText = yesText || pagelayer_l('Yes');
7300 + noText = noText || pagelayer_l('No');
7301 +
7302 + var dialog = jQuery('<div class="pagelayer-confirm-box-holder">'+
7303 + '<div class="pagelayer-confirm-box" style="border-radius:5px">'+
7304 + '<div class="pagelayer-confirmation-msg">'+ message +'</div>'+
7305 + '<center>'+
7306 + '<span class="pagelayer-btnyes button button-pagelayer">'+ yesText +'</span>&nbsp;&nbsp;&nbsp;'+
7307 + '<span class="pagelayer-btnno button button-pagelayer">'+ noText +'</span>'+
7308 + '</center>'+
7309 + '</div>'+
7310 + '</div>');
7311 +
7312 + pagelayer.$$('body').append(dialog);
7313 +
7314 + dialog.find('.pagelayer-btnyes').on('click', function() {
7315 + dialog.remove();
7316 + if(typeof yesCallback == 'function'){
7317 + yesCallback();
7318 + }
7319 + });
7320 + dialog.find('.pagelayer-btnno').on('click', function() {
7321 + dialog.remove();
7322 + if(typeof noCallback == 'function'){
7323 + noCallback();
7324 + }
7325 + });
7326 + dialog.show();
7327 +}
7328 +
7329 +function pagelayer_trim(str, charlist){
7330 + // discuss at: http://locutus.io/php/trim/
7331 +
7332 + if(typeof str != 'string'){
7333 + return str;
7334 + }
7335 +
7336 + var whitespace = [' ', '\n', '\r', '\t', '\f', '\x0b', '\xa0', '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u2005', '\u2006', '\u2007', '\u2008', '\u2009', '\u200a', '\u200b', '\u2028', '\u2029', '\u3000' ].join('');
7337 + var l = 0;
7338 + var i = 0;
7339 + str += '';
7340 +
7341 + if (charlist) {
7342 + whitespace = (charlist + '').replace(/([[\]().?/*{}+$^:])/g, '$1');
7343 + }
7344 +
7345 + l = str.length;
7346 + for (i = 0; i < l; i++) {
7347 + if (whitespace.indexOf(str.charAt(i)) === -1) {
7348 + str = str.substring(i);
7349 + break;
7350 + }
7351 + }
7352 +
7353 + l = str.length;
7354 + for (i = l - 1; i >= 0; i--) {
7355 + if (whitespace.indexOf(str.charAt(i)) === -1) {
7356 + str = str.substring(0, i + 1);
7357 + break;
7358 + }
7359 + }
7360 +
7361 + return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
7362 +};
7363 +
7364 +function pagelayer_ucwords(str) {
7365 + return (str + '').replace(/^([a-z])|\s+([a-z])/g, function ($1) {
7366 + return $1.toUpperCase();
7367 + });
7368 +}
7369 +
7370 +// Check length for string and object
7371 +function pagelayer_length(mixed_var) {
7372 +
7373 + var length = 0;
7374 + var undef, key, i, len;
7375 + var emptyValues = [undef, null, false];
7376 +
7377 + for(i = 0, len = emptyValues.length; i < len; i++) {
7378 + if (mixed_var === emptyValues[i]) {
7379 + return length;
7380 + }
7381 + }
7382 +
7383 + // Is array, object or jQuery object?
7384 + if(typeof mixed_var === 'object'){
7385 +
7386 + // If is jQuery object
7387 + if( mixed_var.hasOwnProperty('length')){
7388 + return mixed_var.length;
7389 + }
7390 +
7391 + for (key in mixed_var) {
7392 + // TODO: should we check for own properties only?
7393 + //if ( .hasOwnProperty(key)) {
7394 + length++;
7395 + //}
7396 + }
7397 +
7398 + return length;
7399 + }
7400 +
7401 + length = String(mixed_var).length;
7402 +
7403 + return length;
7404 +};
7405 +
7406 +// Create Widget list dropdown
7407 +function pagelayer_create_widget_tooltip(){
7408 +
7409 + var html = '<div class="pagelayer-widget-tooltip">'+
7410 + '<div class="pagelayer-widget-search-holder">'+
7411 + '<div class="pagelayer-widget-search">'+
7412 + '<i class="pli pli-search" ></i><input class="pagelayer-search-field" /><span class="pagelayer-sf-empty pli">&times;</span>'+
7413 + '</div>'+
7414 + '</div>';
7415 +
7416 + for(var x in pagelayer_groups){
7417 +
7418 + // Title
7419 + html += '<div class="pagelayer-widget-group pagelayer-group-name-'+x+'"><h5>'+x+'</h5>';
7420 +
7421 + // Indivdual icon
7422 + for(var y in pagelayer_groups[x]){
7423 +
7424 + var sc = pagelayer_groups[x][y];
7425 +
7426 + if(!(sc in pagelayer_shortcodes) || 'not_visible' in pagelayer_shortcodes[sc]){
7427 + continue;
7428 + }
7429 +
7430 + html += '<div class="pagelayer-shortcode-holder" pagelayer-tag="'+sc+'">'+
7431 + '<div class="pagelayer-pointer pagelayer-sc">'+
7432 + '<center class="pagelayer-shortcode-inner">';
7433 +
7434 + if('icon' in pagelayer_shortcodes[sc]){
7435 + html += '<i class="pagelayer-shortcode '+pagelayer_shortcodes[sc]['icon']+'"></i>';
7436 + }else{
7437 + html += '<i class="pagelayer-shortcode pli pagelayer-'+sc+'"></i>';
7438 + }
7439 +
7440 + html += '</center>'+
7441 + '<span class="pagelayer-pointer pagelayer-shortcode-text">'+pagelayer_shortcodes[sc]['name']+'</span>'+
7442 + '</div>'+
7443 + '</div>';
7444 +
7445 + }
7446 +
7447 + html += '</div>';
7448 +
7449 + }
7450 +
7451 + html += '</div>';
7452 +
7453 + pagelayer.$$('body').append(html);
7454 +
7455 + var wdHolder = pagelayer.$$('.pagelayer-widget-tooltip');
7456 +
7457 + // Hide the ones which are not supposed to be shown
7458 + wdHolder.find('.pagelayer-search-field').on('input', function(){
7459 +
7460 + var val = jQuery(this).val();
7461 + var re = new RegExp(val, 'i');
7462 +
7463 + // Show only the required tags
7464 + wdHolder.find('.pagelayer-widget-group').each(function(){
7465 +
7466 + var group = jQuery(this);
7467 + var res = group.find('[pagelayer-tag]');
7468 + var hidden = 0;
7469 +
7470 + res.each(function(){
7471 +
7472 + var tEle = jQuery(this);
7473 + if(tEle.find('.pagelayer-shortcode-text').html().match(re)){
7474 + tEle.show();
7475 + }else{
7476 + hidden += 1;
7477 + tEle.hide();
7478 + }
7479 +
7480 + });
7481 +
7482 + // Hide the whole group
7483 + if(hidden == res.length){
7484 + group.hide();
7485 + }else{
7486 + group.show();
7487 + }
7488 +
7489 + });
7490 +
7491 + wdHolder.find('.pagelayer-shortcode-holder:visible').first().trigger('widget_active');
7492 +
7493 + });
7494 +
7495 + // On click search empty
7496 + wdHolder.find('.pagelayer-widget-search>.pagelayer-sf-empty').click(function(){
7497 + wdHolder.find('.pagelayer-search-field').val('').trigger('input');
7498 + });
7499 +
7500 + // Register widget active event
7501 + wdHolder.find('.pagelayer-shortcode-holder').on('widget_active', function(){
7502 + var activeEle = jQuery(this);
7503 + wdHolder.find('.pagelayer-list-widget-active').removeClass('pagelayer-list-widget-active');
7504 +
7505 + if(!activeEle.hasClass('pagelayer-list-widget-active')){
7506 + activeEle.addClass('pagelayer-list-widget-active');
7507 + }
7508 +
7509 + activeEle[0].scrollIntoView({behavior: "smooth", block: "end"});
7510 + });
7511 +
7512 + pagelayer.gDocument.on('mousedown.pagelayer_wdlist', function(e){
7513 + var target = jQuery(e.target);
7514 +
7515 + if(target.closest('.pagelayer-widget-tooltip').is(wdHolder)){
7516 + return;
7517 + }
7518 +
7519 + wdHolder.find('.pagelayer-shortcode-holder:visible').first().trigger('widget_active');
7520 +
7521 + wdHolder.hide();
7522 + jQuery('.pagelayer-show-wiget-list').removeClass('pagelayer-show-wiget-list');
7523 + jQuery(window).off('scroll.pagelayer_wdlist resize.pagelayer_wdlist');
7524 + });
7525 +
7526 +}
7527 +
7528 +// Show Widget list dropdown
7529 +function pagelayer_show_widget_list(jEle, val){
7530 +
7531 + val = val || '';
7532 + jEle = jQuery(jEle);
7533 +
7534 + var wEle = pagelayer.$$('.pagelayer-widget-tooltip'),
7535 + winH = jQuery(window).height(),
7536 + iframe = pagelayer.$$('#pagelayer-iframe'),
7537 + iframeTop = iframe.offset().top,
7538 + iframeLeft = iframe.offset().left,
7539 + style = {},
7540 + wTop = 'auto',
7541 + wBottom = 'auto',
7542 + wLeft = '';
7543 + wHeight = '';
7544 +
7545 + searchField = wEle.find('.pagelayer-search-field');
7546 + searchField.val(val);
7547 + searchField.trigger('input');
7548 +
7549 + // Add widget show class
7550 + if(jEle.hasClass('pagelayer-shortcode-plus')){
7551 + jEle.parent('.pagelayer-ele-overlay').addClass('pagelayer-show-wiget-list');
7552 + }
7553 +
7554 + var bounds = jEle[0].getBoundingClientRect();
7555 +
7556 + wEle.removeClass('pagelayer-widget-list-tooltip');
7557 + wLeft = (bounds.left + iframeLeft) - wEle.width() / 2;
7558 +
7559 + // In list view?
7560 + if(jEle.closest('[pagelayer-editable]').length > 0){
7561 + wEle.addClass('pagelayer-widget-list-tooltip');
7562 + var selection = window.getSelection();
7563 + var range = selection.getRangeAt(0);
7564 + wLeft = (range.getBoundingClientRect().left + iframeLeft) - wEle.width() / 2;
7565 + }
7566 +
7567 + wEle.closest('.pagelayer-widget-tooltip').show();
7568 + wEle.find('.pagelayer-shortcode-holder:visible').first().trigger('widget_active');
7569 +
7570 + // Hide Widget list
7571 + if(jEle.closest('[pagelayer-editable]').length > 0 && wEle.find('.pagelayer-widget-group:visible').length < 1){
7572 + pagelayer.gDocument.trigger('mousedown.pagelayer_wdlist');
7573 + return;
7574 + }else{
7575 + searchField.focus().select();
7576 + }
7577 +
7578 + var docW = iframeLeft + iframe.width() - 30;
7579 +
7580 + // Prevent to hide on left or right
7581 + if(docW < wLeft + wEle.width()){
7582 + wLeft = docW - wEle.width();
7583 + }else if(iframeLeft > wLeft){
7584 + wLeft = iframeLeft;
7585 + }
7586 +
7587 + if(winH / 2 < bounds.top + 10){
7588 + wBottom = winH - bounds.top + 10;
7589 + wHeight = bounds.top - 10;
7590 + }else{
7591 + wTop = bounds.bottom + iframeTop + 10;
7592 + wHeight = winH - bounds.bottom - 10;
7593 + }
7594 +
7595 + style['left'] = wLeft;
7596 + style['top'] = wTop;
7597 + style['bottom'] = wBottom;
7598 + style['max-height'] = '';
7599 +
7600 + if(wHeight < 350){
7601 + style['max-height'] = wHeight;
7602 + }
7603 +
7604 + wEle.css(style);
7605 +
7606 + jQuery(window).off('scroll.pagelayer_wdlist resize.pagelayer_wdlist');
7607 + jQuery(window).on('scroll.pagelayer_wdlist resize.pagelayer_wdlist', function(){
7608 + var _val = wEle.find('.pagelayer-search-field').val();
7609 + pagelayer_show_widget_list(jEle, _val);
7610 + });
7611 +
7612 + wEle.find('.pagelayer-shortcode-holder').off('click');
7613 + wEle.find('.pagelayer-shortcode-holder').on('click', function(e){
7614 +
7615 + var tag = jQuery(this).attr('pagelayer-tag');
7616 + var mWrap = jEle.closest('.pagelayer-ele-wrap[pagelayer-wrap-id]');
7617 + var mTag = pagelayer_tag(mWrap);
7618 +
7619 + var ele = jQuery('<div pagelayer-tag="'+tag+'"></div>');
7620 +
7621 + // Is col?
7622 + if(mTag == 'pl_col'){
7623 + var colHolder = mWrap.find('>.pagelayer-col > .pagelayer-col-holder');
7624 + colHolder.append(ele);
7625 + pagelayer_empty_col(colHolder);
7626 + }else{
7627 + mWrap.after(ele);
7628 + }
7629 +
7630 + // Replace widget
7631 + if(jEle.closest('[pagelayer-editable]').length > 0){
7632 + pagelayer_delete_element(mWrap.find('>.pagelayer-ele'));
7633 + }
7634 +
7635 + var eleId = pagelayer_onadd(ele, false);
7636 + var eEle = pagelayer_ele_by_id(eleId);
7637 +
7638 + // Create Column
7639 + if( tag == 'pl_inner_row' ){
7640 + var in_col = jQuery('<div pagelayer-tag="pl_col"></div>');
7641 + eEle.find('>.pagelayer-row-holder').append(in_col);
7642 + var in_col_id = pagelayer_onadd(in_col, false);
7643 + }
7644 +
7645 + eEle.click();
7646 +
7647 + // Hide Widget list
7648 + pagelayer.gDocument.trigger('mousedown.pagelayer_wdlist');
7649 + });
7650 +
7651 +}
7652 +
7653 +// Set Selection By Character Offsets
7654 +function pagelayer_setCaret(containerEl, start, end){
7655 +
7656 + end = end || start;
7657 +
7658 + // Refered from http://jsfiddle.net/zQUhV/47/
7659 + if(window.getSelection && document.createRange){
7660 +
7661 + var charIndex = 0, range = document.createRange();
7662 + range.setStart(containerEl, 0);
7663 + range.collapse(true);
7664 + var nodeStack = [containerEl], node, foundStart = false, stop = false;
7665 +
7666 + while (!stop && (node = nodeStack.pop())) {
7667 + if (node.nodeType == 3) {
7668 + var nextCharIndex = charIndex + node.length;
7669 + if (!foundStart && start >= charIndex && start <= nextCharIndex) {
7670 + range.setStart(node, start - charIndex);
7671 + foundStart = true;
7672 + }
7673 + if (foundStart && end >= charIndex && end <= nextCharIndex) {
7674 + range.setEnd(node, end - charIndex);
7675 + stop = true;
7676 + }
7677 + charIndex = nextCharIndex;
7678 + } else {
7679 + var i = node.childNodes.length;
7680 + while (i--) {
7681 + nodeStack.push(node.childNodes[i]);
7682 + }
7683 + }
7684 + }
7685 +
7686 + var sel = window.getSelection();
7687 + sel.removeAllRanges();
7688 + sel.addRange(range);
7689 +
7690 + } else if (document.selection) {
7691 + var textRange = document.body.createTextRange();
7692 + textRange.moveToElementText(containerEl);
7693 + textRange.collapse(true);
7694 + textRange.moveEnd("character", end);
7695 + textRange.moveStart("character", start);
7696 + textRange.select();
7697 + }
7698 +}
7699 +
7700 +// Set Selection By Character Offsets
7701 +function pagelayer_content_line(containerEl){
7702 +
7703 + var lines = [], charIndex = 0, range = document.createRange();
7704 + range.setStart(containerEl, 0);
7705 + range.collapse(true);
7706 + var bounding = range.getBoundingClientRect();
7707 + var nodeStack = [containerEl], node, prevX = bounding.x, nextStart = 0;
7708 +
7709 + while(node = nodeStack.pop()){
7710 + if (node.nodeType == 3) {
7711 + for(var i = 1; i <= node.length; i++){
7712 + range.setStart(node, i);
7713 + range.setEnd(node, i);
7714 + bounding = range.getBoundingClientRect();
7715 + charIndex ++;
7716 +
7717 + if(prevX > bounding.x){
7718 + lines.push({start:nextStart, end:charIndex - 1});
7719 + nextStart = charIndex;
7720 + }
7721 + prevX = bounding.x;
7722 + }
7723 + } else {
7724 + var i = node.childNodes.length;
7725 + while(i--){
7726 + nodeStack.push(node.childNodes[i]);
7727 + }
7728 + }
7729 + }
7730 +
7731 + // Push last line
7732 + if(nextStart != charIndex || nextStart == 0){
7733 + lines.push({start:nextStart, end:charIndex});
7734 + }
7735 +
7736 + return lines;
7737 +}
7738 +
7739 +//http://jsfiddle.net/TjXEG/900/
7740 +function pagelayer_getCaretCharacterOffsetWithin(element){
7741 + var caretOffset = 0;
7742 + var doc = element.ownerDocument || element.document;
7743 + var win = doc.defaultView || doc.parentWindow;
7744 + var sel;
7745 + if( typeof win.getSelection != "undefined" ){
7746 + sel = win.getSelection();
7747 + if (sel.rangeCount > 0) {
7748 + var range = win.getSelection().getRangeAt(0);
7749 + var preCaretRange = range.cloneRange();
7750 + preCaretRange.selectNodeContents(element);
7751 + preCaretRange.setEnd(range.endContainer, range.endOffset);
7752 + caretOffset = preCaretRange.toString().length;
7753 + }
7754 + }else if( (sel = doc.selection) && sel.type != "Control" ){
7755 + var textRange = sel.createRange();
7756 + var preCaretTextRange = doc.body.createTextRange();
7757 + preCaretTextRange.moveToElementText(element);
7758 + preCaretTextRange.setEndPoint("EndToEnd", textRange);
7759 + caretOffset = preCaretTextRange.text.length;
7760 + }
7761 + return caretOffset;
7762 +}
7763 +
7764 +// ==========================================================================
7765 +// PAGELAYER UX IMPROVEMENTS
7766 +// ==========================================================================
7767 +
7768 +var pagelayer_is_command_palette_open = false;
7769 +
7770 +function pagelayer_ux_improvements_init() {
7771 + // Setup global shortcuts inside Parent Window and Iframe Document
7772 + var setupShortcuts = function(doc) {
7773 + jQuery(doc).on('keydown', function(e) {
7774 + // Command Palette: Ctrl+K
7775 + if (e.key === 'k' && (e.ctrlKey || e.metaKey)) {
7776 + e.preventDefault();
7777 + pagelayer_toggle_command_palette();
7778 + }
7779 + });
7780 + };
7781 +
7782 + setupShortcuts(document);
7783 + if (pagelayer.gDocument) {
7784 + setupShortcuts(pagelayer.gDocument);
7785 + }
7786 +
7787 + // Hook selection callback to refresh Navigator if it is open in the right sidebar
7788 + pagelayer_add_action('pagelayer_element_clicked', function(jEle) {
7789 + if (jEle && jEle.length > 0) {
7790 + var isNavigatorOpen = pagelayer.$$('body').hasClass('pagelayer-right-sidebar-open') && pagelayer.$$('#pagelayer-navigator').is(':visible');
7791 + if (isNavigatorOpen) {
7792 + var newId = pagelayer_id(jEle);
7793 + if (newId) {
7794 + pagelayer_active.el = pagelayer_active.el || {};
7795 + pagelayer_active.el.id = newId;
7796 + }
7797 + pagelayer_navigator_setup();
7798 + }
7799 + }
7800 + });
7801 +
7802 + // Redirect Navigator & History/Revisions tabs to a new small right sidebar
7803 + window.pagelayer_close_right_sidebar = function() {
7804 + var sidebar = pagelayer.$$('.pagelayer-right-sidebar');
7805 + if (sidebar.length > 0) {
7806 + sidebar.css('right', '-300px');
7807 + pagelayer.$$('body').removeClass('pagelayer-right-sidebar-open');
7808 + pagelayer.$$('.pagelayer-navigator-icon, .pagelayer-history-icon').closest('.pagelayer-header-icon-wrap').removeClass('active');
7809 + pagelayer.$$('#pagelayer-navigator').hide();
7810 + pagelayer.$$('#pagelayer-history').hide();
7811 + }
7812 + };
7813 +
7814 + window.pagelayer_open_right_sidebar = function(tab) {
7815 + var sidebar = pagelayer.$$('.pagelayer-right-sidebar');
7816 + if (sidebar.length === 0) {
7817 + var sidebarHtml =
7818 + '<div class="pagelayer-right-sidebar">' +
7819 + '<div class="pagelayer-right-sidebar-header">' +
7820 + '<h4 class="pagelayer-right-sidebar-title"></h4>' +
7821 + '<button class="pagelayer-right-sidebar-close"><i class="pli pli-cross"></i></button>' +
7822 + '</div>' +
7823 + '<div class="pagelayer-right-sidebar-content">' +
7824 + '</div>' +
7825 + '</div>';
7826 + pagelayer.$$('body').append(sidebarHtml);
7827 + sidebar = pagelayer.$$('.pagelayer-right-sidebar');
7828 +
7829 + sidebar.find('.pagelayer-right-sidebar-close').on('click', function() {
7830 + window.pagelayer_close_right_sidebar();
7831 + });
7832 + }
7833 +
7834 + var isDark = pagelayer.$$('body').hasClass('pagelayer-dark');
7835 + if (isDark) {
7836 + sidebar.addClass('pagelayer-dark');
7837 + } else {
7838 + sidebar.removeClass('pagelayer-dark');
7839 + }
7840 +
7841 + pagelayer.$$('.pagelayer-navigator-icon, .pagelayer-history-icon').closest('.pagelayer-header-icon-wrap').removeClass('active');
7842 +
7843 + var title = '';
7844 + var iconClass = '';
7845 + if (tab === 'pagelayer-navigator') {
7846 + title = pagelayer_l('pagelayer_navigator') || 'Navigator';
7847 + iconClass = '.pagelayer-navigator-icon';
7848 + } else {
7849 + title = pagelayer_l('pagelayer_history') || 'History & Revisions';
7850 + iconClass = '.pagelayer-history-icon';
7851 + }
7852 +
7853 + sidebar.find('.pagelayer-right-sidebar-title').text(title);
7854 +
7855 + var isVisible = pagelayer.$$('body').hasClass('pagelayer-right-sidebar-open');
7856 + var targetContainer = pagelayer.$$('#' + tab);
7857 + if (isVisible && targetContainer.length > 0 && targetContainer.is(':visible')) {
7858 + window.pagelayer_close_right_sidebar();
7859 + return;
7860 + }
7861 +
7862 + pagelayer.$$(iconClass).closest('.pagelayer-header-icon-wrap').addClass('active');
7863 + sidebar.find('.pagelayer-right-sidebar-content').children().hide();
7864 +
7865 + if (targetContainer.parent().hasClass('pagelayer-right-sidebar-content') === false) {
7866 + sidebar.find('.pagelayer-right-sidebar-content').append(targetContainer);
7867 + }
7868 +
7869 + targetContainer.show().css({'height': '100%', 'position': 'static'});
7870 + sidebar.css('right', '0px');
7871 + pagelayer.$$('body').addClass('pagelayer-right-sidebar-open');
7872 + };
7873 +
7874 + var original_pagelayer_leftbar_tab = window.pagelayer_leftbar_tab;
7875 + window.pagelayer_leftbar_tab = function(tab) {
7876 + if (tab === 'pagelayer-navigator' || tab === 'pagelayer-history') {
7877 + window.pagelayer_open_right_sidebar(tab);
7878 + } else {
7879 + // Do not hide navigator or history tab if they are in the right sidebar
7880 + pagelayer.$$('.pagelayer-leftbar-tab').not('#pagelayer-navigator, #pagelayer-history').hide();
7881 + pagelayer.$$('#'+tab).show();
7882 + }
7883 + };
7884 +
7885 + var bindIcons = function() {
7886 + var $historyIcon = pagelayer.$$('.pagelayer-history-icon');
7887 + $historyIcon.off('click');
7888 + $historyIcon.closest('.pagelayer-header-icon-wrap').off('click').on('click', function(e) {
7889 + e.stopPropagation();
7890 + window.pagelayer_open_right_sidebar('pagelayer-history');
7891 + pagelayer_history_setup();
7892 + });
7893 +
7894 + var $navigatorIcon = pagelayer.$$('.pagelayer-navigator-icon');
7895 + $navigatorIcon.off('click');
7896 + $navigatorIcon.closest('.pagelayer-header-icon-wrap').off('click').on('click', function(e) {
7897 + e.stopPropagation();
7898 + var targetContainer = pagelayer.$$('#pagelayer-navigator');
7899 + if (!targetContainer.is(':visible')) {
7900 + pagelayer_navigator_setup();
7901 + }
7902 + window.pagelayer_open_right_sidebar('pagelayer-navigator');
7903 + });
7904 + };
7905 +
7906 + bindIcons();
7907 + setInterval(bindIcons, 3000);
7908 +}
7909 +
7910 +// Toggle Command Palette Modal (Figma / Bricks style search palette)
7911 +function pagelayer_toggle_command_palette() {
7912 + var modal = pagelayer.$$('.pagelayer-command-palette-modal');
7913 + if (modal.length > 0) {
7914 + if (modal.is(':visible')) {
7915 + modal.hide();
7916 + pagelayer_is_command_palette_open = false;
7917 + } else {
7918 + modal.show().find('.pagelayer-cmd-input').focus().val('');
7919 + pagelayer_is_command_palette_open = true;
7920 + pagelayer_render_command_palette_results('');
7921 + }
7922 + return;
7923 + }
7924 +
7925 + // Create modal in parent window
7926 + var modalHtml = '<div class="pagelayer-command-palette-modal" style="position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(15, 23, 42, 0.4); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); z-index: 99999; display: flex; align-items: center; justify-content: center; font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;">' +
7927 + '<div class="pagelayer-cmd-container" style="width: 550px; background: #ffffff; border-radius: 12px; box-shadow: 0 20px 25px -5px rgba(0,0,0,0.1), 0 10px 10px -5px rgba(0,0,0,0.04); display: flex; flex-direction: column; overflow: hidden; border: 1px solid #e2e8f0; max-height: 450px;">' +
7928 + '<div class="pagelayer-cmd-search-bar" style="display: flex; align-items: center; padding: 14px 18px; border-bottom: 1px solid #f1f5f9; gap: 12px;">' +
7929 + '<i class="fas fa-search" style="color: #64748b; font-size: 16px;"></i>' +
7930 + '<input type="text" class="pagelayer-cmd-input" placeholder="Search widgets, actions, settings..." style="flex: 1; border: none; outline: none; font-size: 15px; color: #0f172a; padding: 0; background: transparent;" />' +
7931 + '<span style="font-size: 11px; background: #f1f5f9; color: #64748b; padding: 2px 6px; border-radius: 4px; border: 1px solid #cbd5e1;">ESC</span>' +
7932 + '</div>' +
7933 + '<div class="pagelayer-cmd-results" style="flex: 1; overflow-y: auto; padding: 8px 0; max-height: 380px;">' +
7934 + '</div>' +
7935 + '</div>' +
7936 + '</div>';
7937 +
7938 + pagelayer.$$('body').append(modalHtml);
7939 + modal = pagelayer.$$('.pagelayer-command-palette-modal');
7940 + pagelayer_is_command_palette_open = true;
7941 +
7942 + // Add dark mode support to command palette
7943 + if (pagelayer.$$('body').hasClass('pagelayer-dark')) {
7944 + modal.find('.pagelayer-cmd-container').css({ 'background': '#0b0f19', 'border-color': '#1e293b', 'color': '#f8fafc' });
7945 + modal.find('.pagelayer-cmd-search-bar').css({ 'border-bottom-color': '#1e293b' });
7946 + modal.find('.pagelayer-cmd-input').css({ 'color': '#f8fafc' });
7947 + modal.find('span').css({ 'background': '#1e293b', 'color': '#cbd5e1', 'border-color': '#334155' });
7948 + }
7949 +
7950 + modal.on('click', function(e) {
7951 + if (e.target === this) {
7952 + modal.hide();
7953 + pagelayer_is_command_palette_open = false;
7954 + }
7955 + });
7956 +
7957 + modal.find('.pagelayer-cmd-input').on('input', function() {
7958 + var q = jQuery(this).val();
7959 + pagelayer_render_command_palette_results(q);
7960 + });
7961 +
7962 + modal.find('.pagelayer-cmd-input').on('keydown', function(e) {
7963 + var results = modal.find('.pagelayer-cmd-item');
7964 + var active = modal.find('.pagelayer-cmd-item.active');
7965 +
7966 + if (e.key === 'ArrowDown') {
7967 + e.preventDefault();
7968 + if (active.length === 0 || active.is(':last-child')) {
7969 + results.removeClass('active').first().addClass('active').get(0).scrollIntoView({ block: 'nearest' });
7970 + } else {
7971 + active.removeClass('active').next().addClass('active').get(0).scrollIntoView({ block: 'nearest' });
7972 + }
7973 + } else if (e.key === 'ArrowUp') {
7974 + e.preventDefault();
7975 + if (active.length === 0 || active.is(':first-child')) {
7976 + results.removeClass('active').last().addClass('active').get(0).scrollIntoView({ block: 'nearest' });
7977 + } else {
7978 + active.removeClass('active').prev().addClass('active').get(0).scrollIntoView({ block: 'nearest' });
7979 + }
7980 + } else if (e.key === 'Enter') {
7981 + e.preventDefault();
7982 + if (active.length > 0) {
7983 + active.click();
7984 + }
7985 + } else if (e.key === 'Escape') {
7986 + modal.hide();
7987 + pagelayer_is_command_palette_open = false;
7988 + }
7989 + });
7990 +
7991 + modal.find('.pagelayer-cmd-input').focus();
7992 + pagelayer_render_command_palette_results('');
7993 +}
7994 +
7995 +function pagelayer_render_command_palette_results(query) {
7996 + var modal = pagelayer.$$('.pagelayer-command-palette-modal');
7997 + var resultsContainer = modal.find('.pagelayer-cmd-results');
7998 + resultsContainer.empty();
7999 +
8000 + query = query.toLowerCase().trim();
8001 + var items = [];
8002 +
8003 + // 1. Gather all shortcodes/widgets
8004 + var addedWidgets = {};
8005 +
8006 + // First, gather from pagelayer_groups to prioritize standard draggable widgets
8007 + for (var group in pagelayer_groups) {
8008 + for (var index in pagelayer_groups[group]) {
8009 + var key = pagelayer_groups[group][index];
8010 + if (addedWidgets[key]) continue;
8011 +
8012 + var sc = pagelayer_shortcodes[key];
8013 + if (!sc || !sc.name || 'not_visible' in sc) continue;
8014 +
8015 + if (query === '' || sc.name.toLowerCase().indexOf(query) > -1 || key.toLowerCase().indexOf(query) > -1) {
8016 + items.push({
8017 + type: 'widget',
8018 + title: sc.name,
8019 + subtitle: 'Add Widget',
8020 + key: key,
8021 + icon: sc.icon || '',
8022 + action: (function(k) {
8023 + return function() {
8024 + pagelayer_insert_widget(k);
8025 + };
8026 + })(key)
8027 + });
8028 + addedWidgets[key] = true;
8029 + }
8030 + }
8031 + }
8032 +
8033 + // Fallback to scan raw shortcodes to capture any miscellaneous widgets not categorized in sidebar groups
8034 + for (var key in pagelayer_shortcodes) {
8035 + if (addedWidgets[key]) continue;
8036 +
8037 + var sc = pagelayer_shortcodes[key];
8038 + if (!sc || !sc.name || 'not_visible' in sc) continue;
8039 +
8040 + if (query === '' || sc.name.toLowerCase().indexOf(query) > -1 || key.toLowerCase().indexOf(query) > -1) {
8041 + items.push({
8042 + type: 'widget',
8043 + title: sc.name,
8044 + subtitle: 'Add Widget',
8045 + key: key,
8046 + icon: sc.icon || '',
8047 + action: (function(k) {
8048 + return function() {
8049 + pagelayer_insert_widget(k);
8050 + };
8051 + })(key)
8052 + });
8053 + addedWidgets[key] = true;
8054 + }
8055 + }
8056 +
8057 + // 2. Gather editor actions
8058 + var actions = [
8059 + { title: 'Undo Last Edit', subtitle: 'History Action', icon: 'fas fa-undo', search: 'undo ctrl+z back', action: function() { pagelayer_do_history('undo'); } },
8060 + { title: 'Redo Edit', subtitle: 'History Action', icon: 'fas fa-redo', search: 'redo ctrl+y', action: function() { pagelayer_do_history('redo'); } },
8061 + { title: 'Switch to Desktop View', subtitle: 'Screen Mode', icon: 'fas fa-desktop', search: 'desktop screen responsive preview', action: function() { pagelayer_set_screen_mode('desktop'); } },
8062 + { title: 'Switch to Tablet View', subtitle: 'Screen Mode', icon: 'fas fa-tablet-alt', search: 'tablet screen responsive preview', action: function() { pagelayer_set_screen_mode('tablet'); } },
8063 + { title: 'Switch to Mobile View', subtitle: 'Screen Mode', icon: 'fas fa-mobile-alt', search: 'mobile screen responsive preview phone', action: function() { pagelayer_set_screen_mode('mobile'); } },
8064 + { title: 'Open Revisions & History', subtitle: 'Revision History', icon: 'fas fa-history', search: 'history revisions undo changes', action: function() { pagelayer.$$('.pagelayer-history-icon').click(); } },
8065 + { title: 'Save Page Changes', subtitle: 'Update Page', icon: 'fas fa-save', search: 'save update publish commit ctrl+s', action: function() { pagelayer.$$('.pagelayer-update-button').click(); } },
8066 + { title: 'Open Navigator / Elements Tree', subtitle: 'Navigator Panel', icon: 'fas fa-sitemap', search: 'navigator tree hierarchy layers structure outline', action: function() { pagelayer.$$('.pagelayer-navigator-icon').click(); } }
8067 + ];
8068 +
8069 + actions.forEach(function(act) {
8070 + if (query === '' || act.title.toLowerCase().indexOf(query) > -1 || act.search.indexOf(query) > -1) {
8071 + items.push({
8072 + type: 'action',
8073 + title: act.title,
8074 + subtitle: act.subtitle,
8075 + icon: act.icon,
8076 + action: act.action
8077 + });
8078 + }
8079 + });
8080 +
8081 + if (items.length === 0) {
8082 + resultsContainer.html('<div style="text-align: center; color: #64748b; padding: 24px 0; font-size: 14px;">No results found. Try another query.</div>');
8083 + return;
8084 + }
8085 +
8086 + var slice = items.slice(0, 100);
8087 + var isDark = pagelayer.$$('body').hasClass('pagelayer-dark');
8088 +
8089 + slice.forEach(function(item, idx) {
8090 + var iconClass = '';
8091 + if (item.type === 'widget') {
8092 + if (item.icon) {
8093 + iconClass = 'pagelayer-shortcode ' + item.icon;
8094 + } else {
8095 + iconClass = 'pagelayer-shortcode pli pagelayer-' + item.key;
8096 + }
8097 + } else {
8098 + iconClass = item.icon;
8099 + }
8100 + var itemHtml = jQuery('<div class="pagelayer-cmd-item ' + (idx === 0 ? 'active' : '') + '" style="display: flex; align-items: center; padding: 10px 18px; cursor: pointer; transition: background 0.15s, color 0.15s; gap: 14px; font-size: 14px;">' +
8101 + '<div class="pagelayer-cmd-icon" style="width: 28px; height: 28px; background: ' + (isDark ? '#1e293b' : '#f1f5f9') + '; border-radius: 6px; display: flex; align-items: center; justify-content: center; color: #2563eb; font-size: 16px;"><i class="' + iconClass + '"></i></div>' +
8102 + '<div style="flex: 1; display: flex; flex-direction: column;">' +
8103 + '<span style="font-weight: 500; color: ' + (isDark ? '#f8fafc' : '#0f172a') + ';">' + item.title + '</span>' +
8104 + '<span style="font-size: 11px; color: #64748b;">' + item.subtitle + '</span>' +
8105 + '</div>' +
8106 + '</div>');
8107 +
8108 + var hoverBg = isDark ? '#1e293b' : '#f8fafc';
8109 +
8110 + itemHtml.hover(function() {
8111 + modal.find('.pagelayer-cmd-item').removeClass('active');
8112 + jQuery(this).addClass('active');
8113 + });
8114 +
8115 + itemHtml.on('click', function() {
8116 + modal.hide();
8117 + pagelayer_is_command_palette_open = false;
8118 + item.action();
8119 + });
8120 +
8121 + resultsContainer.append(itemHtml);
8122 + });
8123 +
8124 + var styleTag = pagelayer.$$('head #pagelayer-cmd-palette-styles');
8125 + if (styleTag.length === 0) {
8126 + pagelayer.$$('head').append('<style id="pagelayer-cmd-palette-styles">' +
8127 + '.pagelayer-cmd-item.active { background: ' + (isDark ? '#1e293b !important' : '#f1f5f9 !important') + '; }' +
8128 + '</style>');
8129 + }
8130 +}
8131 +
8132 +// Programmatic widget placement
8133 +function pagelayer_insert_widget(tag) {
8134 + var active = pagelayer_active.el;
8135 + var parentCol = null;
8136 + var target = null;
8137 + var method = 'append';
8138 +
8139 + if (active && active.$) {
8140 + var tag_active = pagelayer_tag(active.$);
8141 + if (tag_active === 'pl_col') {
8142 + parentCol = active.$.find('>.pagelayer-col-holder');
8143 + method = 'append';
8144 + } else if (tag_active === 'pl_row' || tag_active === 'pl_inner_row') {
8145 + parentCol = active.$.find('.pagelayer-col-holder').first();
8146 + method = 'append';
8147 + } else {
8148 + target = active.$.closest('.pagelayer-ele-wrap');
8149 + method = 'after';
8150 + }
8151 + } else {
8152 + parentCol = jQuery(pagelayer_editable).find('.pagelayer-col-holder').first();
8153 + method = 'append';
8154 + }
8155 +
8156 + if ((!parentCol || parentCol.length === 0) && (!target || target.length === 0)) {
8157 + var row = jQuery('<div pagelayer-tag="pl_row"></div>');
8158 + jQuery(pagelayer_editable).append(row);
8159 + var rowId = pagelayer_onadd(row, false);
8160 + var rEle = pagelayer_ele_by_id(rowId);
8161 +
8162 + var col = jQuery('<div pagelayer-tag="pl_col"></div>');
8163 + rEle.find('.pagelayer-row-holder').append(col);
8164 + var colId = pagelayer_onadd(col, false);
8165 + var cEle = pagelayer_ele_by_id(colId);
8166 + parentCol = cEle.find('.pagelayer-col-holder');
8167 + method = 'append';
8168 + }
8169 +
8170 + var ele = jQuery('<div pagelayer-tag="' + tag + '"></div>');
8171 + if (method === 'append') {
8172 + parentCol.append(ele);
8173 + pagelayer_empty_col(parentCol);
8174 + } else {
8175 + target.after(ele);
8176 + pagelayer_empty_col(target.closest('.pagelayer-col-holder'));
8177 + }
8178 +
8179 + var newId = pagelayer_onadd(ele, true);
8180 + pagelayer_do_dirty(ele);
8181 +}
8182 +