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 +6619 -618 0.9.0 → 2.2.2 View file →
@@ -8,15 +8,117 @@
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 - copy_selected: ''
14 + copy_selected: '',
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
14 24 }
15 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 +
16 97 // Lets start
17 -jQuery(document).ready(function(){
98 +jQuery(document).ready(pagelayer_start);
99 +
100 +// Function to load the codes
101 +function pagelayer_start(){
18 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 +
114 + pagelayer_shortcodes['pl_inner_row'] = JSON.parse(JSON.stringify(pagelayer_shortcodes['pl_row']));
115 + pagelayer_shortcodes['pl_inner_row']['name'] = 'Inner Row';
116 + pagelayer_groups['grid'].push('pl_inner_row');
117 +
118 + // Removing post props options
119 + pagelayer_setting_post_props();
120 +
19 121 // Make the Topbar
20 122 pagelayer_bottombar();
21 123
22 124 // Make the Leftbar
@@ -21,47 +123,11 @@
21 123
22 124 // Make the Leftbar
23 125 pagelayer_leftbar();
24 126
25 - // The left bar drag
26 - pagelayer.$$('.pagelayer-leftbar-group').each(function(){
27 -
28 - var group = jQuery(this);
29 - Sortable.create(group[0], {
30 - animation: 150,
31 - sort: false,
32 - group: {
33 - name: 'pagelayer-shortcodes',
34 - pull: function(evt) {
35 - var tmp = jQuery(evt.el).parents('.pagelayer-leftbar');
36 - //console.log(tmp);
37 - if(tmp.length > 0){
38 - return false;
39 - }
40 - return 'clone';
41 - }
42 - },
43 - draggable: '.pagelayer-shortcode-drag',
44 - onEnd : function(evt) {
45 -
46 - // Only if the parent is not the leftbar itself
47 - var tmp = pagelayer.$$(evt.to).parents('.pagelayer-leftbar');
48 - //console.log(tmp);
49 - if(tmp.length > 0){
50 - return;
51 - }
52 -
53 - // The parent must be entry-content
54 - //if(!(jQuery(evt.to).hasClass('pagelayer-add-widget-area'))){
55 - // Trigger clone
56 - pagelayer_onadd(evt);
57 - //}
58 -
59 - }
60 - });
61 - });
127 + // Make widget list toolbar
128 + pagelayer_create_widget_tooltip();
62 129
63 -
64 130 // Add widget section
65 131 pagelayer_add_widget();
66 132
67 133 // Setup the ELPD
@@ -66,142 +132,1075 @@
66 132
67 133 // Setup the ELPD
68 134 pagelayer_elpd_setup();
69 135
136 + // Dump the data we have
137 + pagelayer_element_dump_data();
138 +
70 139 // Setup the properties of the elements
71 140 pagelayer_element_setup();
72 141
142 + // An image to show for drag
143 + jQuery('body').append('<img src="'+pagelayer_url+'/images/drag-ghost.png" class="pagelayer-drag-show" />');
144 +
73 145 // Setup the grid drag
74 - pagelayer_setup_grid_drag();
146 + pagelayer_setup_drag();
75 147
148 + // Set left bar draggable
149 + pagelayer_make_leftbar_movable();
150 +
76 151 // Set to desktop
77 152 pagelayer_set_screen_mode('desktop');
78 153
154 + // Create list of fonts
155 + pagelayer_fonts = pagelayer_l('pl_fonts_list');
156 +
79 157 // Set up right click
80 158 pagelayer_left_click();
81 159 pagelayer_right_click();
82 160
83 -});
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 + };
84 186
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 +}
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 +
85 431 // The jQuery Object of the ELPD
86 432 var pagelayer_elpd;
87 433
88 -// Make rows and cols draggable
89 -function pagelayer_setup_grid_drag(){
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 +}
90 470
91 - // Make all rows draggable
92 - Sortable.create(jQuery('.entry-content')[0], {
93 - animation: 150,
94 - scroll: true,
95 - scrollSensitivity: 100,
96 - scrollSpeed: 20,
97 - //swapThreshold: 0.5,
98 - //invertSwap: true,
99 - //invertedSwapThreshold: 0.3,
100 - group: {
101 - name: 'pagelayer-rows',
102 - put: function(to, from, dragEl, evt){
103 - return pagelayer_onput(to, from, dragEl, evt);
471 +function pagelayer_closest_corner(jEle){
472 + var corners = [];
473 + var w = jEle.outerWidth();
474 + var h = jEle.outerHeight();
475 + var topleft = jEle.offset();
476 +
477 + // 0 - Top Left
478 + corners.push(topleft);
479 +
480 + // 1 - Top Right
481 + corners.push({top: topleft.top, left: topleft.left+w});
482 +
483 + // 2 - Bottom Right
484 + corners.push({top: topleft.top+h, left: topleft.left+w});
485 +
486 + // 3 - Bottom Left
487 + corners.push({top: topleft.top+h, left: topleft.left});
488 +
489 + //console.log(corners);
490 +
491 + // Calculate the closest to the mouse
492 + var distances = {};
493 + for(var c in corners){
494 + var dist = Math.hypot(pagelayer.mouse.x - corners[c].left, pagelayer.mouse.y - corners[c].top);
495 + distances[c] = dist;
496 + }
497 + //console.log(distances);
498 +
499 + var corner = Object.keys(distances).sort(function(a,b){return distances[a]-distances[b]})[0];
500 + //console.log(corner);
501 +
502 + return corner;
503 +
504 +};
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;
104 540 }
105 - },
106 - handle: '.pagelayer-row-option',
107 - draggable: '.pagelayer-wrap-row',
108 - onAdd: function(evt){
109 - //pagelayer_onadd(evt);
110 - },
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 +
111 609 });
112 610
113 - // Columns draggable
114 - jQuery('.pagelayer-row-holder').each(function(){
115 - Sortable.create(jQuery(this)[0], {
116 - animation: 150,
117 - scroll: true,
118 - scrollSensitivity: 100,
119 - scrollSpeed: 20,
120 - //swapThreshold: 0.5,
121 - //invertSwap: true,
122 - //invertedSwapThreshold: 0.3,
123 - //ghostClass: 'pagelayer-drag-ghost',
124 - group : {
125 - name: 'pagelayer-cols',
126 - put: function(to, from, dragEl, evt){
127 - return pagelayer_onput(to, from, dragEl, evt);
611 +}
612 +
613 +// Make rows and cols draggable
614 +function pagelayer_setup_drag(){
615 +
616 + // The object to show as drag
617 + var shower = jQuery('.pagelayer-drag-show');
618 +
619 + // Delete any prospect
620 + var clear_prospect = function(){
621 + jQuery('.pagelayer-drag-prospect').remove();
622 +
623 + // Shows the wrap as active
624 + jQuery('.pagelayer-drag-ele-hover').removeClass('pagelayer-drag-ele-hover');
625 + }
626 +
627 + // Reset the complete drag stuff
628 + var reset_dragging = function(){
629 + pagelayer.dragging = false;
630 + pagelayer.drag_is_new = false;
631 + pagelayer.drag_mouse = {x: 0, y: 0};
632 + reset_on_drag();
633 + }
634 +
635 + // Reset the element on you were last
636 + var reset_on_drag = function(){
637 + pagelayer.drag_closest = false;
638 + pagelayer.drag_closest_corner = null;
639 + }
640 +
641 + // Scroll by
642 + var scrollPx = 7;
643 + var scrollDist = 30;
644 +
645 + // If we are too close too the window edge, then scroll
646 + var handle_scroll = function(e){
647 +
648 + var windowHeight = jQuery(window).height();
649 + var windowWidth = jQuery(window).width();
650 +
651 + // Are we to close to the top or bottom
652 + if(e.clientY < scrollDist){
653 + window.scrollBy(0, -scrollPx);
654 + }else if((windowHeight - e.clientY) < scrollDist){
655 + window.scrollBy(0, scrollPx);
656 + }
657 +
658 + // Are we to close to the top or bottom
659 + if(e.clientX < scrollDist){
660 + window.scrollBy(-scrollPx, 0);
661 + }else if((windowWidth - e.clientX) < scrollDist){
662 + window.scrollBy(scrollPx, 0);
663 + }
664 +
665 + }
666 +
667 + // SET the values
668 + reset_dragging();
669 +
670 + var ondragover = function(e) {
671 + //console.log(e);
672 +
673 + pagelayer.mouse.x = parseInt(e.pageX);
674 + pagelayer.mouse.y = parseInt(e.pageY);
675 + //console.log(pagelayer.mouse);
676 +
677 + // Are we dragging ?
678 + if(pagelayer.dragging){
679 +
680 + //console.log(e);
681 +
682 + e.preventDefault();
683 + //e.stopPropagation();
684 +
685 + // The wrap of the element being dragged
686 + var wrap = pagelayer.dragging;
687 +
688 + // New addition
689 + var is_new = pagelayer.drag_is_new;
690 + var ele;
691 + var tag = pagelayer_tag(wrap);
692 + var id = pagelayer_id(wrap);
693 +
694 + // If existing element then add we are dragging
695 + if(!is_new){
696 +
697 + // Start Dragging
698 + if(!wrap.hasClass('pagelayer-is-dragging')){
699 + wrap.addClass('pagelayer-is-dragging');
128 700 }
129 - },
130 - handle: '.pagelayer-col-option',
131 - draggable: '.pagelayer-wrap-col',
132 - onAdd: function(evt){
133 701
134 - // When adding a new column, from the left bar we need to re-order after creation
135 - if(jQuery(evt.from).hasClass('pagelayer-leftbar-group')){
702 + //shower.hide();
703 +
704 + ele = document.elementFromPoint(e.clientX, e.clientY);
705 + //console.log(ele);
706 +
707 + // Drag the show object
708 + //shower.show();
709 + //var offset = {top: (e.pageY-10)+'px', left: (e.pageX-10)+'px'}
710 + //shower.css(offset);
711 +
712 + }else{
713 + ele = document.elementFromPoint(e.clientX, e.clientY);
714 + }
715 + //console.log(e);
716 +
717 + // Have we moved more than 5px;
718 + var dist = Math.hypot(pagelayer.mouse.x - pagelayer.drag_mouse.x, pagelayer.mouse.y - pagelayer.drag_mouse.y);
719 + //console.log(dist);
720 + /*if(dist && dist < 5){
721 + return false;
722 + }*/
723 +
724 + // Handle the scroll
725 + handle_scroll(e);
726 +
727 + // Find the closest wrap
728 + var onWrap;
729 +
730 + // If we are a column, we can be over another column or row
731 + if(tag == 'pl_col'){
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 + }
745 + //console.log(pagelayer_id(onWrap));
746 +
747 + // If we are a row, we can be over another row or a column
748 + }else if(tag == 'pl_row'){
749 + onWrap = jQuery(ele).closest('.pagelayer-wrap-row');
750 + //console.log(pagelayer_id(onWrap));
751 +
752 + // For inner row we restrict to 1 level only
753 + }else if(tag == 'pl_inner_row'){
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');
761 + }else{
762 + onWrap = jQuery(ele).closest('.pagelayer-wrap-inner-row');
763 + }
764 + // For every other element, we can be over a col or ele
765 + }else{
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 + }
829 + }
830 + //console.log(onWrap);
831 +
832 + // If we find nothing
833 + if(pagelayer_empty(onWrap) || onWrap.length < 1){
834 + clear_prospect();// Clear existing prospects
835 + reset_on_drag();// Also reset the last on item
836 + return false;
837 + }
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 +
857 + // Get the ID
858 + var onId = pagelayer_id(onWrap);
859 + var onEle = pagelayer_ele_by_id(onId);
860 +
861 + // Do we have a parent ?
862 + var have_parent = function(Ele){
863 + var pOnId = pagelayer_get_parent(Ele);
864 +
865 + if(pagelayer_empty(pOnId) || tag == 'pl_col'){
136 866 return;
137 867 }
138 868
139 - // Reorder the columns
140 - pagelayer_renumber_col(evt.to);
869 + onId = pOnId;
870 + onEle = pagelayer_ele_by_id(pOnId);
871 + onWrap = pagelayer_wrap_by_id(pOnId);
872 + have_parent(onEle);
141 873
142 - },
143 - onRemove: function(evt){
144 - // Reorder the columns
145 - pagelayer_renumber_col(evt.from);
146 - },
147 - });
148 - });
874 + }
875 +
876 + // Do we have a parent ?
877 + have_parent(onEle);
878 +
879 + var changed = false;
880 +
881 + // Was it the same ID like the one we were on before
882 + if(pagelayer.drag_closest != onId){
883 + pagelayer.drag_closest = onId;
884 + changed = true;
885 + }
886 + //console.log(onId+' '+pagelayer.drag_closest)
887 +
888 + var req_corners = {0: 'top', 1: 'top', 2: 'bottom', 3: 'bottom'};
889 +
890 + // For columns we redefine the top and bottom
891 + if(tag == 'pl_col'){
892 + req_corners[1] = 'bottom';
893 + req_corners[3] = 'top';
894 + }
895 +
896 + // Determine the previous and next
897 + var next = wrap.next('.pagelayer-ele-wrap');
898 + var prev = wrap.prev('.pagelayer-ele-wrap');
899 +
900 + if(next.length == 1 && pagelayer_id(next) == onId){
901 + req_corners = {0: 'bottom', 1: 'bottom', 2: 'bottom', 3: 'bottom'};
902 + }
903 +
904 + if(prev.length == 1 && pagelayer_id(prev) == onId){
905 + req_corners = {0: 'top', 1: 'top', 2: 'top', 3: 'top'};
906 + }
907 +
908 + // Which corner are we closest to ?
909 + var corner_num = pagelayer_closest_corner(onWrap);
910 + var corner = req_corners[corner_num];
911 +
912 + //console.log(corner+' != '+pagelayer.drag_closest_corner)
913 + if(corner != pagelayer.drag_closest_corner){
914 + pagelayer.drag_closest_corner = corner;
915 + changed = true;
916 + }
917 +
918 + //console.log(changed);
919 +
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')){
922 + clear_prospect();// Clear existing prospects
923 + reset_on_drag();// Also reset the last on item
924 + return false;
925 + }
926 +
927 + // Then lets start showing
928 + if(changed){
929 +
930 + // Record the mouse points
931 + pagelayer.drag_mouse.x = parseInt(e.pageX);
932 + pagelayer.drag_mouse.y = parseInt(e.pageY);
933 +
934 + // Clear any existing prospect
935 + clear_prospect();
936 +
937 + // Add new prospect
938 + var prospect = '<div class="pagelayer-drag-prospect" pagelayer-corner="'+corner+'"></div>';
939 +
940 + if(corner == 'bottom'){
941 + onWrap.append(prospect);
942 + }else if(corner == 'top'){
943 + onWrap.prepend(prospect);
944 + }
945 +
946 + prospect = jQuery('.pagelayer-drag-prospect')
947 + var animate_props = {height: '5px'};
948 +
949 + // For column add a special class
950 + if(tag == 'pl_col'){
951 + prospect.addClass('pagelayer-drag-prospect-col');
952 + animate_props['width'] = '5px';
953 +
954 + // Adjust the left and right
955 + var css = {};
956 + css[(corner == 'bottom' ? 'right' : 'left')] = '0px';
957 + prospect.css(css);
958 + }
959 +
960 + // Animate the prospect
961 + prospect.animate(animate_props, 200);
962 +
963 + // Highlight the wrap via overlay
964 + onWrap.children('.pagelayer-ele-overlay').addClass('pagelayer-drag-ele-hover');
965 +
966 + }
967 +
968 + }
969 + }
149 970
150 - // Elements draggable
151 - jQuery('.pagelayer-col-holder').each(function(){
152 - Sortable.create(jQuery(this)[0], {
153 - animation: 150,
154 - scroll: true,
155 - scrollSensitivity: 100,
156 - scrollSpeed: 20,
157 - //swapThreshold: 0.5,
158 - //invertSwap: true,
159 - //invertedSwapThreshold: 0.3,
160 - //ghostClass: 'pagelayer-drag-ghost',
161 - group : {
162 - name: 'pagelayer-eles',
163 - put: function(to, from, dragEl, evt){
164 - return pagelayer_onput(to, from, dragEl, evt);
971 + // When mouse is pressed down
972 + var ondragstart = function(e){
973 +
974 + //console.log(e);
975 +
976 + // Target
977 + var tEle = jQuery(e.target);
978 + var wrap = tEle.closest('.pagelayer-ele-wrap');
979 + //console.log(jEle[0]);
980 +
981 + // Is it an existing element ?
982 + if(wrap.length < 1){
983 + return false;
984 + }
985 +
986 + // Do we have a parent ?
987 + var id = pagelayer_id(wrap);
988 + var jEle = pagelayer_ele_by_id(id);
989 + var pId = pagelayer_get_parent(jEle);
990 +
991 + if(pId){
992 + wrap = pagelayer_wrap_by_id(pId);
993 + }
994 +
995 + //e.preventDefault();
996 +
997 + var tag = pagelayer_tag(wrap);
998 +
999 + e.originalEvent.dataTransfer.setData('Text', 1);
1000 + var img = document.createElement('img');
1001 + img.src = shower.attr('src');
1002 + e.originalEvent.dataTransfer.setDragImage(img, 32, 32);
1003 +
1004 + pagelayer.dragging = wrap;
1005 +
1006 + }
1007 +
1008 + // When mouse is pressed down
1009 + var ondrop = function(e){
1010 +
1011 + //console.log(e);
1012 +
1013 + // Stop dragging ?
1014 + if(pagelayer.dragging){
1015 +
1016 + e.preventDefault();
1017 +
1018 + var wrap = pagelayer.dragging;
1019 + var tag = pagelayer_tag(wrap);
1020 + var gId = wrap.attr('pagelayer-global-id');
1021 + var fromEl = wrap.parent();
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 +
1029 + wrap.removeClass('pagelayer-is-dragging');
1030 +
1031 + // Find any prospect
1032 + var prospect = jQuery('.pagelayer-drag-prospect');
1033 + //console.log(prospect[0]);
1034 +
1035 + // It should be exactly 1
1036 + if(prospect.length == 1){
1037 +
1038 + var onWrap = prospect.parent();
1039 + var onId = pagelayer_id(onWrap);
1040 + var onTag = pagelayer_tag(onWrap);
1041 + var dropped;
1042 + var corner = prospect.attr('pagelayer-corner');
1043 + var method = (corner == 'top') ? 'before' : 'after';
1044 + var before_loc; // Location before the drop
1045 +
1046 + // Create the element if it needs to be created
1047 + if(pagelayer.drag_is_new){
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 + }
1054 +
1055 + // Move the object
1056 + }else{
1057 +
1058 + // Get near by element before move
1059 + before_loc = pagelayer_near_by_ele(pagelayer_id(wrap), tag);
1060 +
1061 + dropped = wrap;
1062 + dropped.detach();
165 1063 }
166 - },
167 - draggable: '.pagelayer-ele-wrap',
168 - onAdd: function(evt){
169 - pagelayer_empty_col(evt.to);
170 - pagelayer_empty_col(evt.from);
171 - },
172 - });
1064 +
1065 + // If I am a column or row, then I go only before or after my same type !
1066 + if((onTag == 'pl_col' || onTag == 'pl_row') && onTag == tag){
1067 +
1068 + // If I am a column and I am on a row
1069 + // OR I am a normal element and I am on column
1070 + }else if((tag == 'pl_col' && (onTag == 'pl_row' || onTag == 'pl_inner_row')) || onTag == 'pl_col'){
1071 + // We need to find the holder and add the prospect there
1072 + var holder = pagelayer_shortcodes[onTag]['holder'];
1073 + onWrap = onWrap.children('.pagelayer-ele').children(holder);
1074 + method = (corner == 'top') ? 'prepend' : 'append';
1075 + }
1076 +
1077 + // Attach or shift the element
1078 + onWrap[method](dropped);
1079 + //console.log(dropped);
1080 +
1081 + // Trigger the onadd
1082 + if(pagelayer.drag_is_new){
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 + }
1091 +
1092 + // Existing elements
1093 + }else{
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));
1106 + }
1107 +
1108 + // Defining the variables as needed
1109 + var jEle = pagelayer_ele_by_id(id);
1110 + wrap = pagelayer_wrap_by_id(id);
1111 + var toEl = wrap.parent();
1112 +
1113 + // Column number handle
1114 + if(tag == 'pl_col'){
1115 +
1116 + var row_holder = jEle.parent().closest('.pagelayer-row-holder');
1117 +
1118 + // Renumber the col where you are going
1119 + pagelayer_renumber_col(row_holder);
1120 +
1121 + // Renumber the old columns as well
1122 + if(!pagelayer.drag_is_new){
1123 + var from_row = fromEl.closest('.pagelayer-row-holder');
1124 + pagelayer_renumber_col(from_row);
1125 + }
1126 + }
1127 +
1128 + // Handle the empty col
1129 + if(tag != 'pl_col'){
1130 +
1131 + pagelayer_empty_col(toEl.closest('.pagelayer-col-holder'));
1132 +
1133 + if(!pagelayer.drag_is_new){
1134 + pagelayer_empty_col(fromEl.closest('.pagelayer-col-holder'));
1135 + }
1136 +
1137 + }
1138 +
1139 + }
1140 +
1141 + // Clear prospect
1142 + clear_prospect();
1143 + }
1144 +
1145 + reset_dragging();
1146 +
1147 + }
1148 +
1149 + // Add the events for inner content - as we are using the drag API
1150 + jQuery(document).on('dragstart', ondragstart);
1151 + jQuery(document).on('dragover', ondragover);
1152 + jQuery(document).on('drop', ondrop);
1153 +
1154 + // For addition of new elements
1155 + pagelayer.$$('.pagelayer-leftbar').on('dragstart', function(e){
1156 + //console.log(e);
1157 +
1158 + var tEle = jQuery(e.target);
1159 + var jEle = tEle.closest('.pagelayer-shortcode-drag');
1160 + var global_id = jEle.attr('pagelayer-global-id');
1161 +
1162 + // Is it an existing element ?
1163 + if(jEle.length < 1){
1164 + return false;
1165 + }
1166 +
1167 + e.originalEvent.dataTransfer.setData('tag', pagelayer_tag(jEle));
1168 +
1169 + if(!pagelayer_empty(global_id)){
1170 + e.originalEvent.dataTransfer.setData( 'global_id', global_id );
1171 + }
1172 +
1173 + pagelayer.dragging = jEle;
1174 + pagelayer.drag_is_new = true;
1175 +
173 1176 });
174 1177
175 - /*// Elements draggable
176 - Sortable.create(jQuery('.pagelayer-add-widget-area')[0], {
177 - animation: 150,
178 - scroll: true,
179 - scrollSensitivity: 100,
180 - scrollSpeed: 20,
181 - //swapThreshold: 0.5,
182 - //invertSwap: true,
183 - //invertedSwapThreshold: 0.3,
184 - //ghostClass: 'pagelayer-drag-ghost',
185 - group : {
186 - name: 'pagelayer-add-eles',
187 - put: function(to, from, dragEl, evt){
188 - return pagelayer_onput(to, from, dragEl, evt);
189 - }
190 - },
191 - draggable: 'null',
192 - onAdd: function(evt){
193 - var sc = jQuery(evt.item);
194 - //var sc = pagelayer_tag(item);
195 - var jEle = jQuery(evt.to);
196 -
197 - pagelayer_add_sc(jEle, sc);
198 - },
199 - });*/
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);
200 1198
201 1199 };
202 1200
203 1201 // Handle empty col
1202 +// selector should be col holder
204 1203 function pagelayer_empty_col(selector){
205 1204
206 1205 // Loop through
207 1206 jQuery(selector).each(function(){
@@ -215,23 +1214,31 @@
215 1214
216 1215 // Column is becoming blank, so show add ele
217 1216 if(jEle.children().length < 1){
218 1217 //from.addClass('pagelayer-empty-col');
219 - jEle.append('<div class="pagelayer-add-ele pagelayer-ele-wrap"><i class="fa fa-plus"><br>Empty column please add something</div>');
220 - var h = jEle.parent().parent().children('.pagelayer-ele-overlay').height();
221 - jEle.children('.pagelayer-add-ele').height(h);
222 - pagelayer_setup_grid_drag();
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);
223 1221
224 1222 // Any add ele sign with non-empty columns here ?
225 - }else if(jEle.children('.pagelayer-add-ele').length > 0){
1223 + }else if(jEle.children('.pagelayer-add-ele').length > 0 && jEle.children().length > 1){
226 1224 jEle.children('.pagelayer-add-ele').remove();
227 1225 }
228 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 +
229 1235 });
230 1236
231 1237 };
232 1238
233 1239 // Reset the column widths
1240 +// The selector should be a ROW HOLDER
234 1241 function pagelayer_renumber_col(selector){
235 1242
236 1243 var pEle = jQuery(selector);
237 1244 var children = pEle.children('.pagelayer-ele-wrap');
@@ -254,105 +1261,157 @@
254 1261 break;
255 1262 }
256 1263 }
257 1264 jEle.addClass('pagelayer-col-'+cols);
258 - Ele.addClass('pagelayer-col-'+cols);
259 -
1265 + jEle.css({'width': ''});
1266 +
260 1267 // Set the att
261 1268 pagelayer_set_atts(Ele, obj);
1269 + pagelayer_set_atts(Ele, 'col_width','');
1270 + pagelayer_sc_render(Ele)
262 1271 });
263 1272 }
264 1273
265 -// When an item is being dragged and finally being put
266 -// This is called throughout the drag when the drag engine thinks it has found a target
267 -// If this returns false, then the drag is cancelled
268 -function pagelayer_onput(to, from, dragEl, evt){
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');
269 1281
270 - var sc = pagelayer_tag(jQuery(dragEl));
271 - var parent_tag = pagelayer_tag(jQuery(to.el));
272 - //console.log(sc+' '+parent_tag);
273 - //if(!parent_tag) console.log(jQuery(to.el));
274 - // Verify the element being dragged
275 - // Item is a col
276 - if(sc == 'pl_col'){
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();
277 1292
278 - // You can be within a row only
279 - if(parent_tag != 'pl_row'){
280 - return false;
281 - }
1293 + var next_ele = wrap.next();
1294 + var rHolder_width = wrap.closest('.pagelayer-row-holder').width();
1295 + var new_width, nEle_new_width;
282 1296
283 - // Item is a row
284 - }else if(sc == 'pl_row'){
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;
285 1301
286 - // Row cannot be within row
287 - //if(parent_tag == 'pl_row' || parent_tag == 'pl_col' || jQuery(to.el).hasClass('pagelayer-add-widget-area')){
288 - if(parent_tag == 'pl_row' || parent_tag == 'pl_col'){
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){
289 1308 return false;
290 1309 }
291 1310
292 - // The parent must be entry-content
293 - if(jQuery(to.el).hasClass('entry-content')){
294 - return true;
295 - }
296 -
297 - // Regular elements
298 - }else{
1311 + jQuery('body').css({'cursor': 'ew-resize'});
1312 + rHandler.css({'display': 'block'});
299 1313
300 - // The parent must be pagelayer-add-widget-area
301 - //if(jQuery(to.el).hasClass('pagelayer-add-widget-area')){
302 - // return true;
303 - //}
1314 + var mousemoved = false;
304 1315
305 - // Row cannot be within row
306 - if(parent_tag != 'pl_col'){
307 - return false;
308 - }
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 + };
309 1333
310 - }
311 -
312 - return true;
313 -};
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 +}
314 1368
315 1369 // Handle addition of elements from the left
316 1370 // NOTE : At this point the addition is FINALIZED
317 1371 // The add element cannot be prevented !
318 -function pagelayer_onadd(evt){
1372 +function pagelayer_onadd(jEle, toClick){
319 1373
320 - var cloneEl = jQuery(evt.item);
321 - var to = jQuery(evt.to);
1374 + toClick = arguments.length == 2 ? toClick : true;
322 1375
323 - var id = pagelayer_element_added(cloneEl, to);
1376 + //console.log(jEle);
1377 + var id = pagelayer_element_added(jEle);
324 1378 var jEle = jQuery("[pagelayer-id="+id+"]");
325 - jEle.click();
326 1379
1380 + if(toClick){
1381 + //console.log('here');
1382 + jEle.click();
1383 + }
1384 +
1385 + return id;
1386 +
327 1387 };
328 1388
329 1389 // Add an element into the POST
330 -function pagelayer_element_added(jEle, to){
1390 +function pagelayer_element_added(jEle){
331 1391
332 1392 var sc = jEle.attr('pagelayer-tag');
333 - var parent_tag = to.attr('pagelayer-tag');
334 - var create_parent = '';
335 1393 var id, par_id;
1394 + var gId = jEle.attr('pagelayer-global-id');
1395 + gId = gId && !pagelayer_empty(pagelayer_global_widgets[gId]) ? gId : 0;
336 1396
337 - /*// Is the target a row ?
338 - if(parent_tag == 'pl_row' && sc != 'pl_col'){
339 - create_parent = 'pl_col';
340 - }*/
1397 + // Set Pagelayer History FALSE to prevent saving attributes in action history
1398 + pagelayer.history_action = false;
1399 + pagelayer.global_render = false;
341 1400
1401 + // Is this a global widget ?
1402 + if(!pagelayer_empty(gId)){
1403 +
1404 + html = pagelayer_element_unsetup(pagelayer_global_widgets[gId].$);
1405 +
342 1406 // Generate the HTML
343 - html = pagelayer_create_sc(sc, to);
1407 + }else{
1408 + html = pagelayer_create_sc(sc);
1409 + }
1410 +
344 1411 id = pagelayer_assign_id(html);
345 1412 par_id = id;
346 1413
347 - /*// We need to create a parent
348 - if(create_parent.length > 0){
349 - var pEle = pagelayer_create_sc(create_parent, to);
350 - par_id = pagelayer_assign_id(pEle);
351 - pEle.append(html);
352 - html = pEle;
353 - }*/
354 -
355 1414 // Insert the HTML
356 1415 jEle[0].outerHTML = html[0].outerHTML;
357 1416
358 1417 // Setup the properties of the elements
@@ -357,41 +1416,73 @@
357 1416
358 1417 // Setup the properties of the elements
359 1418 pagelayer_element_setup("[pagelayer-id="+par_id+"], [pagelayer-id="+par_id+"] .pagelayer-ele", true);
360 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 +
361 1425 // Any children to add ?
362 1426 if(!('widget' in pagelayer_shortcodes[sc])){
363 1427
364 1428 // The element props
365 - var props = pagelayer_shortcodes[sc]['params'];
1429 + var props = pagelayer_shortcodes[sc];
366 1430
367 1431 // Do we have to create children ?
368 - if(!pagelayer_empty(props['elements'])){
369 -
370 - // Add the items
371 - for(var i=0; i < props['elements']['count']; i++){
372 - var cid = pagelayer_element_add_child(jQuery("[pagelayer-id="+id+"]"), props['elements']['sc']);
373 - pagelayer_element_setup('[pagelayer-id='+cid+']', true);
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);
1442 +
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+'"]'));
374 1453 }
375 -
376 1454 }
377 1455
378 1456 }
379 1457
380 - // Setup grid drag again
381 - pagelayer_setup_grid_drag();
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 + });
382 1468
383 - if(sc == 'pl_col'){
384 - pagelayer_renumber_col(to);
385 - }
1469 + // Set pagelayer history TRUE
1470 + pagelayer.history_action = true;
1471 + pagelayer.global_render = true;
386 1472
1473 + // To update nav item list
1474 + pagelayer_do_dirty(pagelayer_ele_by_id(id));
1475 +
387 1476 return id;
388 1477
389 1478 };
390 1479
391 1480 // Add an element
392 -function pagelayer_element_add_child(pEle, sc){
393 - var child = pagelayer_create_sc(sc, pEle);
1481 +function pagelayer_element_add_child(pEle, sc, gProp){
1482 +
1483 + gProp = gProp || {};
1484 + var child = pagelayer_create_sc(sc);
394 1485 var cid = pagelayer_assign_id(child);
395 1486 pagelayer_set_parent(child, pagelayer_assign_id(pEle));
396 1487
397 1488 // Does the parent have a holder ?
@@ -406,16 +1497,120 @@
406 1497 }else{
407 1498 pEle.append(child);
408 1499 }
409 1500
1501 + pagelayer_element_setup('[pagelayer-id='+cid+']', true);
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 +
1568 + // Do we have to create children ?
1569 + if('has_group' in pagelayer_shortcodes[sc]){
1570 +
1571 + var has_group = pagelayer_shortcodes[sc]['has_group'];
1572 + var gProp = pagelayer_shortcodes[sc][has_group['section']][has_group['prop']];
1573 +
1574 + for(var i=0; i < gProp['count']; i++){
1575 + var in_cid = pagelayer_element_add_child(jQuery("[pagelayer-id="+cid+"]"), gProp['sc'], gProp);
1576 + }
1577 +
1578 + }
1579 +
410 1580 return cid;
411 1581 };
412 1582
413 -// Return an element by parent ID
1583 +// Return an element by ID
414 1584 function pagelayer_ele_by_id(id){
415 1585 return jQuery('[pagelayer-id='+id+']');
416 1586 };
417 1587
1588 +// Return the wrap by ID
1589 +function pagelayer_wrap_by_id(id){
1590 + return jQuery('[pagelayer-wrap-id='+id+']');
1591 +};
1592 +
1593 +// Give the Pagelayer ID
1594 +function pagelayer_id(jEle){
1595 +
1596 + var id = jEle.attr('pagelayer-wrap-id');
1597 + if(id){
1598 + return id;
1599 + }
1600 +
1601 + id = jEle.attr('pagelayer-id');
1602 +
1603 + return id;
1604 +
1605 +}
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 +
418 1613 // Assign the jQuery object an ID
419 1614 function pagelayer_assign_id(jEle){
420 1615
421 1616 // Do you have the pagelayer id
@@ -420,9 +1615,10 @@
420 1615
421 1616 // Do you have the pagelayer id
422 1617 var id = jEle.attr("pagelayer-id");
423 1618 if(!id || id.length < 1){
424 - id = pagelayer_randstr(16);
1619 + id = pagelayer_randstr(3)+pagelayer_randInt(9999).toString();
1620 + id = id.toLowerCase();
425 1621 jEle.attr("pagelayer-id", id);
426 1622 }
427 1623
428 1624 return id;
@@ -433,8 +1629,9 @@
433 1629 function pagelayer_element_clicked(selector, e){
434 1630
435 1631 var jEle = jQuery(selector);
436 1632 e = e || false;
1633 + //console.log(e);
437 1634
438 1635 // You must be a element atleast
439 1636 if(!jEle.hasClass('pagelayer-ele')){
440 1637 return false;
@@ -447,18 +1644,25 @@
447 1644 if(pId){
448 1645 jEle = pagelayer_ele_by_id(pId);
449 1646 }
450 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 +
451 1659 // Lets not rebuild everything to make it faster
452 1660 if(pagelayer_is_active(jEle)){
453 1661 return false;
454 1662 }
455 1663
456 - // Make the editable fields active
457 - pagelayer_clear_editable();// First clear
458 - jEle.find('[pagelayer-editable]').each(function (){
459 - pagelayer_make_editable(jQuery(this), e);
460 - });
1664 + pagelayer_trigger_action('pagelayer_element_clicked', [jEle]);
461 1665
462 1666 // Set this as the active element
463 1667 pagelayer_set_active(jEle);
464 1668
@@ -466,13 +1670,69 @@
466 1670 pagelayer_elpd_open(jEle);
467 1671
468 1672 }
469 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 +
470 1720 // The edit option
471 1721 function pagelayer_edit_element(selector){
472 1722 pagelayer_element_clicked(selector);
473 1723 }
474 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 +
475 1735 // Setup the properties on a single click
476 1736 function pagelayer_element_setup(selector, render){
477 1737
478 1738 var selector = selector || ".pagelayer-ele";
@@ -478,10 +1738,10 @@
478 1738 var selector = selector || ".pagelayer-ele";
479 1739 render = render || false;
480 1740
481 1741 // Loop through
482 - jQuery(selector).each(function(){
483 -
1742 + jQuery(pagelayer_editable+' '+selector).each(function(){
1743 +
484 1744 var jEle = jQuery(this);
485 1745
486 1746 // Assign an ID if not there
487 1747 var id = pagelayer_assign_id(jEle);
@@ -487,8 +1747,13 @@
487 1747 var id = pagelayer_assign_id(jEle);
488 1748 var pId = pagelayer_get_parent(jEle) || '';// Options to show on hover
489 1749 var selector = '[pagelayer-id='+id+']';
490 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 +
491 1756 if(render){
492 1757 pagelayer_sc_render(jEle);
493 1758 }
494 1759
@@ -493,8 +1758,9 @@
493 1758 }
494 1759
495 1760 // Get the tag
496 1761 var tag = pagelayer_tag(jEle);
1762 + var props = pagelayer_get_props(jEle);
497 1763
498 1764 // Lets check if we are the child of a parent i.e. element of a group
499 1765 if(pagelayer_empty(pId)){
500 1766
@@ -506,11 +1772,12 @@
506 1772
507 1773 var pTag = pagelayer_tag(pEle);
508 1774
509 1775 // Is the parent a group of this child ?
510 - if(!pagelayer_empty(pagelayer_shortcodes[pTag]) && 'elements' in pagelayer_shortcodes[pTag]['params']){
1776 + if(!pagelayer_empty(pagelayer_shortcodes[pTag]) && pagelayer_is_group(pTag)){
511 1777
512 - var child_type = pagelayer_shortcodes[pTag]['params']['elements']['sc'];
1778 + var has_group = pagelayer_shortcodes[pTag]['has_group'];
1779 + var child_type = pagelayer_shortcodes[pTag][has_group['section']][has_group['prop']]['sc'];
513 1780
514 1781 // If the type is the same as jEle
515 1782 if(child_type == pagelayer_tag(jEle)){
516 1783 pId = pagelayer_assign_id(pEle);
@@ -520,9 +1787,14 @@
520 1787
521 1788 }
522 1789
523 1790 }
524 -
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 +
525 1797 // Make the wraps
526 1798 jEle.wrap('<div class="pagelayer-ele-wrap" pagelayer-wrap-id="'+id+'"></div>');
527 1799 var wrap = jEle.parent();
528 1800
@@ -535,15 +1807,10 @@
535 1807 col = 'pagelayer-col-'+x;
536 1808 break;
537 1809 }
538 1810 }
1811 +
539 1812
540 - var is_custom_width = pagelayer_get_att(jEle, 'col');
541 - var col_width = pagelayer_get_att(jEle, 'col_width');
542 - if(pagelayer_empty(is_custom_width) && col_width){
543 - wrap.css('width', col_width+'%');
544 - }
545 -
546 1813 wrap.addClass('pagelayer-col '+col);
547 1814 //jEle.removeClass('pagelayer-col '+col);
548 1815 wrap.addClass('pagelayer-wrap-col');
549 1816
@@ -548,10 +1815,14 @@
548 1815 wrap.addClass('pagelayer-wrap-col');
549 1816
550 1817 }else if(tag == 'pl_row'){
551 1818 wrap.addClass('pagelayer-wrap-row');
1819 + }else if(tag == 'pl_inner_row'){
1820 + wrap.addClass('pagelayer-wrap-inner-row');
1821 + }else{
1822 + wrap.addClass('pagelayer-wrap-ele');
552 1823 }
553 -
1824 +
554 1825 // Create the overlay
555 1826 wrap.prepend('<div class="pagelayer-ele-overlay"></div>');
556 1827
557 1828 var overlay = wrap.children('.pagelayer-ele-overlay');
@@ -556,9 +1827,9 @@
556 1827
557 1828 var overlay = wrap.children('.pagelayer-ele-overlay');
558 1829 var html;
559 1830
560 - if(tag == 'pl_row'){
1831 + if(tag == 'pl_row' || tag == 'pl_inner_row'){
561 1832
562 1833 overlay.addClass('pagelayer-row-hover');
563 1834
564 1835 if(jEle.hasClass('pagelayer-row-stretch-full')){
@@ -565,11 +1836,13 @@
565 1836 pagelayer_sc_render(jEle);
566 1837 }
567 1838
568 1839 html = '<div class="pagelayer-row-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
569 - '<i class="fa fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" />'+
570 - '<i class="fa fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" />'+
571 - '<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>'+
572 1845 '</div>';
573 1846
574 1847 }else if(tag == 'pl_col'){
575 1848
@@ -575,20 +1848,25 @@
575 1848
576 1849 overlay.addClass('pagelayer-col-hover');
577 1850
578 1851 html = '<div class="pagelayer-col-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
579 - '<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>'+
580 1853 '</div>';
581 1854
582 1855 // Is it an empty col ?
583 1856 pagelayer_empty_col(jEle.children('.pagelayer-col-holder'));
1857 +
1858 + // Make col resizable
1859 + pagelayer_col_make_resizable(wrap);
584 1860
585 1861 }else{
586 1862
587 1863 html = '<div class="pagelayer-ele-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
588 - '<i class="fa fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" />'+
589 - '<i class="fa fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" />'+
590 - '<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>'+
591 1869 '</div>';
592 1870
593 1871 }
594 1872
@@ -593,15 +1871,31 @@
593 1871 }
594 1872
595 1873 // Append to the child
596 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 +
597 1881 jQuery('[pagelayer-option-id='+id+']').hide();
598 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 +
599 1890 // Setup the HOVER events ABD create WRAPS IF we dont have a parent
600 1891 if(pId.length > 0){
601 1892 return;
602 1893 }
603 1894
1895 + // Make the wrap draggable, but only of independent or parent elements
1896 + wrap.attr('draggable', 'true');
1897 +
604 1898 wrap.hover(function(){
605 1899
606 1900 // Is there an element option shower ?
607 1901 var opts = jQuery('[pagelayer-option-id='+id+']');
@@ -627,13 +1921,51 @@
627 1921
628 1922 });
629 1923 }
630 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 +
631 1961 // Left Click
632 1962 function pagelayer_left_click(){
633 1963
634 - jQuery('.entry-content').on('click', function(e){
1964 + jQuery(pagelayer_editable).on('click', function(e){
635 1965
1966 + e.preventDefault();// Added by Jivan in Actions / Revisions version
1967 +
636 1968 // Hide the context menu
637 1969 jQuery('.pagelayer-right-click-options').hide();
638 1970
639 1971 // Target
@@ -656,12 +1988,15 @@
656 1988
657 1989 var html = '<div class="pagelayer-right-click-options" style="display:none;">'+
658 1990 '<ul>'+
659 1991 '<li><a class="pagelayer-right-edit">Edit</a></li>'+
660 - '<li><a class="pagelayer-right-duplicate">Duplicate</a></li>'+
661 - '<li><a class="pagelayer-right-copy">Copy</a></li>'+
662 - '<li><a class="pagelayer-right-paste">Paste</a></li>'+
663 - '<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>'+
664 1999 '</ul>'+
665 2000 '</div>';
666 2001
667 2002 jQuery('body').append(html);
@@ -667,13 +2002,18 @@
667 2002 jQuery('body').append(html);
668 2003
669 2004 var $contextMenu = jQuery('.pagelayer-right-click-options');
670 2005
671 - jQuery('.entry-content').on('contextmenu', function(e){
2006 + jQuery(pagelayer_editable).on('contextmenu', function(e){
672 2007
673 2008 var tEle = jQuery(e.target);
674 2009 var jEle = tEle.closest('.pagelayer-ele-wrap').children('.pagelayer-ele');
675 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 +
676 2016 // Get the parent
677 2017 var pId = pagelayer_get_parent(jEle);
678 2018
679 2019 // If we found a parent
@@ -684,26 +2024,89 @@
684 2024 // The basics
685 2025 var id = pagelayer_assign_id(jEle);
686 2026 var tag = pagelayer_tag(jEle);
687 2027
688 - $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']);
689 2029 $contextMenu.find('.pagelayer-right-duplicate').attr('onclick', 'pagelayer_copy_element("[pagelayer-id='+id+']")');
690 2030 $contextMenu.find('.pagelayer-right-copy').attr('onclick', 'pagelayer_copy_select("[pagelayer-id='+id+']")');
691 - $contextMenu.find('.pagelayer-right-paste').attr('onclick', 'pagelayer_paste_element("[pagelayer-id='+id+']")');
692 2031 $contextMenu.find('.pagelayer-right-delete').attr('onclick', 'pagelayer_delete_element("[pagelayer-id='+id+']")');
693 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 +
694 2060 // Are we to hide the paste ?
695 - if(!pagelayer_empty(pagelayer.copy_selected) && pagelayer_can_copy_to(jEle)){
696 - //console.log(pagelayer_can_copy_to(jEle));
697 - $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);
698 2073 }else{
699 - $contextMenu.find('.pagelayer-right-paste').parent().hide();
2074 + showPaste();
700 2075 }
701 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 +
702 2105 $contextMenu.css({
703 2106 display: "block",
704 - left: e.pageX,
705 - top: e.pageY
2107 + left: hPosition,
2108 + top: vPosition
706 2109 });
707 2110
708 2111 return false;
709 2112
@@ -718,9 +2121,14 @@
718 2121 function pagelayer_set_parent(jEle, id){
719 2122 jEle.attr('pagelayer-parent', id);
720 2123 };
721 2124
722 -// 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
723 2131 function pagelayer_get_parent(jEle){
724 2132 return jEle.attr('pagelayer-parent');
725 2133 };
726 2134
@@ -741,10 +2149,13 @@
741 2149 // Add the class
742 2150 body.addClass('pagelayer-screen-'+mode);
743 2151
744 2152 // Add the class to the button
745 - pagelayer.$$('.pagelayer-mode-button').removeClass('fa-'+current).addClass('fa-'+mode);
2153 + pagelayer.$$('.pagelayer-mode-button').removeClass('pli-'+current).addClass('pli-'+mode);
746 2154
2155 + // Add the class to the button
2156 + pagelayer.$$('.pagelayer-prop-screen').removeClass('pli-'+current).addClass('pli-'+mode);
2157 +
747 2158 // Trigger screen change if any
748 2159 pagelayer.$$('.pagelayer-elp-screen').trigger('pagelayer-screen-changed');
749 2160
750 2161 };
@@ -760,58 +2171,511 @@
760 2171 }
761 2172 }
762 2173 }
763 2174
764 -// Makes any element draggable
765 -function pagelayer_drag(prop){
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));
766 2184
767 - var $ = jQuery;
768 - var jEle = $(prop.ele);
769 - var elmnt = jEle[0];
2185 + var tEle = jQuery(e.target);
2186 + var editable = tEle.closest('[contenteditable="true"]');
2187 + var tooltip = pagelayer.$$('.pagelayer-widget-tooltip');
770 2188
771 - var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
772 - // If present, the header is where you move the DIV from:*/
773 - if ('handle' in prop) {
774 - $(prop.handle)[0].onmousedown = dragMouseDown;
775 - // otherwise, move the DIV from anywhere inside the DIV:*/
776 - } else {
777 - elmnt.onmousedown = dragMouseDown;
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;
778 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));
779 2221
780 - function dragMouseDown(e) {
781 - e = e || window.event;
782 - e.preventDefault();
783 - // get the mouse cursor position at startup:
784 - pos3 = e.clientX;
785 - pos4 = e.clientY;
786 - document.onmouseup = closeDragElement;
787 - // call a function whenever the cursor moves:
788 - document.onmousemove = elementDrag;
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);
789 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 +});
790 2323
791 - function elementDrag(e) {
792 - e = e || window.event;
793 - e.preventDefault();
794 - // calculate the new cursor position:
795 - pos1 = pos3 - e.clientX;
796 - pos2 = pos4 - e.clientY;
797 - pos3 = e.clientX;
798 - pos4 = e.clientY;
799 - // set the element's new position:
800 - elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
801 - elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
2324 +// Handle key press events
2325 +pagelayer.gDocument.keydown(function(event){
2326 + //alert(String.fromCharCode(event.which));
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');
802 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();
803 2502
804 - function closeDragElement() {
805 - /* stop moving when mouse button is released:*/
806 - document.onmouseup = null;
807 - document.onmousemove = null;
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 +
808 2551 }
809 -};
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)){
810 2616
811 -// Handle key press events
812 -jQuery(document).keydown(function(event){
813 - //alert(String.fromCharCode(event.which));
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 + }
814 2678
815 2679 // Delete
816 2680 if(event.keyCode == 46){
817 2681 pagelayer_delete_element('[pagelayer-active]');
@@ -816,18 +2680,236 @@
816 2680 if(event.keyCode == 46){
817 2681 pagelayer_delete_element('[pagelayer-active]');
818 2682 }
819 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 +
820 2694 });
821 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 +
822 2902 // Delete an element as per the selector
823 2903 function pagelayer_delete_element(selector){
824 2904 var jEle = jQuery(selector);
2905 + var nearBy = jEle;
825 2906
826 2907 // Anything found ?
827 2908 if(jEle.length > 0){
828 2909
829 2910 var id = pagelayer_assign_id(jEle);
2911 + var sc = pagelayer_tag(jEle);
830 2912
831 2913 // Is there a wrap
832 2914 var wrap = jQuery('[pagelayer-wrap-id="'+id+'"]');
833 2915
@@ -832,25 +2914,124 @@
832 2914 var wrap = jQuery('[pagelayer-wrap-id="'+id+'"]');
833 2915
834 2916 var par = wrap.parent();
835 2917
836 - wrap.remove();
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 + }
837 2944
2945 + wrap.remove();
2946 +
838 2947 pagelayer_empty_col(par);
839 2948
840 - if(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)){
841 2951 pagelayer.$$('.pagelayer-elpd-close').click();
842 2952 }
843 2953
844 2954 }
845 - pagelayer_isDirty = true;
2955 +
2956 + // Do Pagelayer dirty
2957 + pagelayer_do_dirty(nearBy);
846 2958 };
847 2959
848 2960 // Select an element
849 -function pagelayer_copy_select(selector){
850 - 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 +
851 2999 }
852 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 +
853 3034 function pagelayer_can_copy_to(to){
854 3035 var jEle = jQuery(pagelayer.copy_selected);
855 3036 var tEle = jQuery(to);
856 3037
@@ -855,9 +3036,15 @@
855 3036 var tEle = jQuery(to);
856 3037
857 3038 var eTag = pagelayer_tag(jEle);
858 3039 var tTag = pagelayer_tag(tEle);
859 - console.log(eTag+' - '+tTag);
3040 + //console.log(eTag+' - '+tTag);
3041 +
3042 + // Invalid HTML copied
3043 + if(pagelayer_empty(eTag)){
3044 + return false;
3045 + }
3046 +
860 3047 // Final to
861 3048 var fTo;
862 3049
863 3050 // Selected element is a Row, can go only after a row
@@ -883,10 +3070,26 @@
883 3070
884 3071 }
885 3072
886 3073 // Select an element
887 -function pagelayer_paste_element(to){
3074 +function pagelayer_paste_element(to, syncClipboard = true){
888 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 +
889 3092 var fTo = pagelayer_can_copy_to(to);
890 3093
891 3094 // Is it a valid to
892 3095 if(!fTo){
@@ -892,33 +3095,63 @@
892 3095 if(!fTo){
893 3096 return false;
894 3097 }
895 3098
896 - 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;
897 3107 }
898 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 +
899 3144 // Copy an element
900 3145 // Note : insertAfter should always be an pagelayer-ele
901 3146 function pagelayer_copy_element(selector, insertAfter){
902 3147 var src = jQuery(selector);
903 - var html = src[0].outerHTML;
3148 + var tag = pagelayer_tag(src);
904 3149 insertAfter = insertAfter || src;
905 3150 insertAfter = insertAfter.parent();
906 3151
907 - var jEle = jQuery(html);
908 - jEle.removeAttr('pagelayer-id');
909 - jEle.find('[pagelayer-id]').removeAttr('pagelayer-id');
910 - jEle.find('style').remove();
911 - jEle.find('.pagelayer-ele-overlay').remove();
3152 + var jEle = pagelayer_element_unsetup(src);
912 3153
913 - // Unwrap the wraps
914 - jEle.find('.pagelayer-ele').each(function (){
915 - var ele = jQuery(this);
916 - if(ele.parent().is('.pagelayer-ele-wrap')){
917 - ele.unwrap();
918 - }
919 - });
920 -
921 3154 // Give it an ID
922 3155 var id = pagelayer_assign_id(jEle);
923 3156
924 3157 jQuery(insertAfter).after(jEle);
@@ -924,18 +3157,388 @@
924 3157 jQuery(insertAfter).after(jEle);
925 3158
926 3159 pagelayer_element_setup('[pagelayer-id='+id+'], [pagelayer-id='+id+'] .pagelayer-ele', true);
927 3160
928 - // Setup grid drag
929 - pagelayer_setup_grid_drag();
930 - pagelayer_isDirty = true;
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 +
3177 + //If column then renumber columns
3178 + if(tag == 'pl_col'){
3179 + var row = src.parent().closest('.pagelayer-row');
3180 + pagelayer_renumber_col(row);
3181 + }
3182 +
3183 + pagelayer_do_dirty(jEle);
3184 +
3185 + return id;
931 3186 };
932 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 +
933 3484 // Language key
934 3485 function pagelayer_l(k){
3486 + if(k in pagelayer_lang){
3487 + return pagelayer_lang[k];
3488 + }
935 3489 return k;
936 3490 }
937 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 +
938 3541 // Set the given jELE as active
939 3542 function pagelayer_set_active(jEle){
940 3543
941 3544 // Make all other element as inactive
@@ -958,17 +3561,17 @@
958 3561 };
959 3562
960 3563 // Create a HTML dom element of the Short code
961 3564 // Return the jEle
962 -function pagelayer_create_sc(sc, pEle){
3565 +function pagelayer_create_sc(sc){
963 3566
964 3567 var html;
965 3568 var _sc = pagelayer_sc(sc);
966 - var func = window['pagelayer_sc_'+sc];
3569 + var func = window['pagelayer_create_sc_'+sc];
967 3570
968 3571 // Generate the HTML
969 3572 if(typeof func == 'function'){
970 - html = window['pagelayer_sc_'+sc](pEle);
3573 + html = window['pagelayer_create_sc_'+sc]();
971 3574 }else{
972 3575 html = '<div '+pagelayer_sc_atts('pagelayer-'+_sc)+'></div>';
973 3576 }
974 3577
@@ -1033,16 +3636,88 @@
1033 3636
1034 3637 return jEle.attr('pagelayer-tag');
1035 3638 }
1036 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 +
1037 3704 // Gets a single attribute value
1038 3705 function pagelayer_get_att(jEle, att){
1039 - 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;
1040 3711 };
1041 3712
1042 3713 // Gets a single attribute value
1043 3714 function pagelayer_get_tmp_att(jEle, att){
1044 - 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;
1045 3720 };
1046 3721
1047 3722 // This function will just set atts and not do anything else
1048 3723 // Atts can be string or object. If its string, then val is needed
@@ -1071,8 +3746,9 @@
1071 3746 var all_props = pagelayer_shortcodes[tag];//console.log(tag);console.log(jEle);
1072 3747 var trigger_props = {};
1073 3748 var no_val = {};
1074 3749 var defaults = {};
3750 + var _props = {};
1075 3751
1076 3752 // Loop through all props
1077 3753 for(var i in pagelayer_tabs){
1078 3754
@@ -1087,15 +3763,39 @@
1087 3763 if('default' in props[x]){
1088 3764 defaults[x] = 1;
1089 3765 }
1090 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 +
1091 3776 // Dont set any val, but we set temp value
1092 3777 if('no_val' in props[x]){
1093 3778 no_val[x] = 1;
1094 3779 }
1095 3780
1096 - if('req' in props[x] || 'show' in props[x]){
3781 + if('req' in props[x] || 'show' in props[x]){
1097 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 +
1098 3798 for(var showParam in show){
1099 3799 var val = show[showParam];
1100 3800 var except = showParam.substr(0, 1) == '!' ? true : false;
1101 3801 showParam = except ? showParam.substr(1) : showParam;
@@ -1109,8 +3809,10 @@
1109 3809 }
1110 3810
1111 3811 }
1112 3812
3813 + var ref_data = pagelayer_el_data_ref(jEle);
3814 +
1113 3815 for(var x in atts){
1114 3816
1115 3817 // Are we to trigger change
1116 3818 if(x in trigger_props){
@@ -1118,44 +3820,57 @@
1118 3820 }
1119 3821
1120 3822 //console.log(x+'-'+atts[x]);
1121 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 +
1122 3829 if(x in no_val){
1123 3830 pagelayer_set_tmp_atts(jEle, x, atts[x]);
1124 3831 continue;
1125 3832 }
1126 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 +
1127 3855 // Remove the attribute if its BLANK and there is no default for it
1128 3856 // If there is a default, we set it to blank to keep record of the current val
1129 - if(atts[x].length < 1){
3857 + if(pagelayer_length(atts[x]) < 1){
1130 3858
1131 - // Dont remove the value as there is a default
3859 + // Remove values which are not defaults
1132 3860 if(!(x in defaults)){
1133 - jEle.removeAttr('pagelayer-a-'+x);
1134 - // Otherwise blank it
3861 + delete ref_data['attr'][x];
3862 + // Otherwise keep value set for avoiding resetting
1135 3863 }else{
1136 - jEle.attr('pagelayer-a-'+x, atts[x]);
3864 + ref_data['attr'][x] = atts[x];
1137 3865 }
1138 3866
1139 3867 // Remove the tmp atts anyway
1140 - var to_del = new Array();
1141 - var regexp = new RegExp('pagelayer\-tmp\-'+x, 'gi');
1142 -
1143 - jQuery.each(jEle[0].attributes, function(index, att){
1144 - if(!att) return;
1145 - if(att.name.match(regexp)){
1146 - to_del.push(att.name);
1147 - }
1148 - });
1149 -
1150 - //console.log(to_del);
1151 - for(var n in to_del){
1152 - jEle.removeAttr(to_del[n]);
1153 - }
3868 + pagelayer_clear_tmp_atts(jEle, x);
1154 3869
1155 3870 // Set the value
1156 3871 }else{
1157 - jEle.attr('pagelayer-a-'+x, atts[x]);
3872 + ref_data['attr'][x] = pagelayer_trim(atts[x]);
1158 3873 }
1159 3874
1160 3875 // Are you the active element
1161 3876 if(pagelayer_is_active(jEle)){
@@ -1165,14 +3880,17 @@
1165 3880 }
1166 3881
1167 3882 }
1168 3883
3884 + pagelayer_el_dump_data(jEle);
3885 +
1169 3886 // Trigger the change of the parameter and show the required properties
1170 3887 if(trigger_onchange){
1171 3888 pagelayer_elpd_show_rows();
1172 3889 }
1173 3890
1174 - pagelayer_isDirty = true;
3891 + pagelayer_do_dirty(jEle);
3892 +
1175 3893 };
1176 3894
1177 3895 // This function will just set atts and not do anything else
1178 3896 // Atts can be string or object. If its string, then val is needed
@@ -1187,27 +3905,71 @@
1187 3905 if(typeof atts != 'object'){
1188 3906 return false;
1189 3907 }
1190 3908
3909 + var ref_data = pagelayer_el_data_ref(jEle);
3910 +
1191 3911 for(var x in atts){
1192 - 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 +
1193 3932 }
1194 3933
3934 + pagelayer_el_dump_data(jEle);
3935 +
1195 3936 };
1196 3937
1197 -// Set the att and classes of an HTML which is not yet created
1198 -function pagelayer_sc_atts(classes, atts){
3938 +// This function removes the temporary attributes of an ele
3939 +function pagelayer_clear_tmp_atts(jEle, attr){
1199 3940
1200 - if(typeof atts != 'object'){
1201 - 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 + }
1202 3950 }
3951 +}
3952 +
3953 +// This function removes the temporary attributes of an ele
3954 +function pagelayer_img_tmp_atts(jEle, attr){
1203 3955
1204 - var r = new Array();
3956 + var found = {};
3957 + var regexp = new RegExp('^'+attr+'\-', 'gi');
3958 + var ref_data = pagelayer_el_data_ref(jEle);
1205 3959
1206 - for(var x in atts){
1207 - 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 + }
1208 3964 }
1209 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();
1210 3972 return 'class="'+classes+' pagelayer-ele" '+r.join(' ');
1211 3973 }
1212 3974
1213 3975 // Is the jEle the active element ?
@@ -1233,16 +3995,33 @@
1233 3995
1234 3996 // Seperator
1235 3997 seperator = seperator || ',';
1236 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 +
1237 4012 // Replace the val
1238 - css = css.split('{{val}}').join(val);
4013 + css = replaceCss(css, val, '{{val}}');
1239 4014
1240 4015 // If there is an array
1241 4016 if(css.match(/val\[\d/)){
1242 - val = val.split(seperator);
4017 +
4018 + if(typeof val != 'object' || val === null){
4019 + val = String(val).split(seperator);
4020 + }
4021 +
1243 4022 for(var i in val){
1244 - css = css.split('{{val['+i+']}}').join(val[i]);
4023 + css = replaceCss(css, val[i], '{{val['+i+']}}');
1245 4024 }
1246 4025 }
1247 4026
1248 4027 //console.log('Final CSS '+css);
@@ -1250,9 +4029,40 @@
1250 4029 return css;
1251 4030
1252 4031 };
1253 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 +
1254 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
1255 4065 function pagelayer_parse_vars(str, el){
1256 4066
1257 4067 for(var x in el.tmp){
1258 4068 str = str.split('{{{'+x+'}}}').join(el.tmp[x]);
@@ -1272,9 +4082,11 @@
1272 4082 if(!pagelayer_is_active(jEle)){
1273 4083 //return false;
1274 4084 }
1275 4085
1276 - // Handle the CSS part
4086 + //console.log('Rendering');
4087 +
4088 + // Handle the CSS part
1277 4089 // Get the id, tag, atts, data, etc
1278 4090 var el = pagelayer_data(jEle, true);
1279 4091 var all_props = pagelayer_shortcodes[el.tag];
1280 4092 var elCSS = {
@@ -1283,13 +4095,18 @@
1283 4095 attr: [],
1284 4096 remove_attr: [],
1285 4097 css: [],
1286 4098 edit: [],
1287 - sel: '[pagelayer-id="'+el.id+'"]'
4099 + cssSel: '.p-'+el.id,
4100 + sel: '[pagelayer-id="'+el.id+'"]',
4101 + wrap: '[pagelayer-wrap-id="'+el.id+'"]'
1288 4102 };
1289 4103
1290 4104 // Create a reference
1291 4105 el.CSS = elCSS;
4106 +
4107 + // Make sure if we have the class selector
4108 + el.$.addClass('p-'+el.id);
1292 4109
1293 4110 //console.log(el.atts);
1294 4111
1295 4112 for(var i in pagelayer_tabs){
@@ -1303,10 +4120,10 @@
1303 4120
1304 4121 // pagelayer_data will return attributes even if they are BLANK e.g. attr=""
1305 4122 // Render doesnt consider BLANK values as values, and we are unsetting them now
1306 4123 // If in any situation you need to consider blank values, please handle in the JS / PHP function of the Shortcode
1307 - if(x in el.atts && el.atts[x].length < 1){
1308 - delete el.atts[x];
4124 + if(x in el.atts && pagelayer_length(el.atts[x]) < 1){
4125 + delete el.atts[x];
1309 4126 }
1310 4127
1311 4128 // Any editor ?
1312 4129 if('edit' in props[x]){
@@ -1312,8 +4129,59 @@
1312 4129 if('edit' in props[x]){
1313 4130 elCSS.edit.push({prop: x, sel: props[x]['edit']});
1314 4131 }
1315 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 +
1316 4184 // Do we have a addClass ?
1317 4185 // We are checking before the element has a value so that we can add or remove the class
1318 4186 if('addClass' in props[x]){
1319 4187
@@ -1348,9 +4216,9 @@
1348 4216 }
1349 4217
1350 4218 }else{
1351 4219
1352 - var tmp = {'sel': tSel, 'val': addClasses[c]};
4220 + var tmp = {'sel': tSel, 'val': addClasses[c].replace('{{val}}', el.atts[x])};
1353 4221
1354 4222 // If the value is there
1355 4223 if(x in el.atts){
1356 4224 elCSS['classes'].push(tmp);
@@ -1403,8 +4271,9 @@
1403 4271 }
1404 4272
1405 4273 // Screen modes
1406 4274 var modes = {desktop: '', tablet: '_tablet', mobile: '_mobile'};
4275 + var desk_global = (props[x]['type'] == 'typography') ? pagelayer_is_global_typo(el.atts[x]) : '';
1407 4276
1408 4277 for(var m in modes){
1409 4278
1410 4279 var xm = x+modes[m];
@@ -1409,12 +4278,37 @@
1409 4278
1410 4279 var xm = x+modes[m];
1411 4280
1412 4281 // If the value is there
1413 - if(!(xm in el.atts)){
4282 + if(!(xm in el.atts) && pagelayer_empty(desk_global)){
1414 4283 continue;
1415 4284 }
1416 -
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 +
1417 4311 for(var c in css){
1418 4312
1419 4313 // The selector
1420 4314 var tSel = jQuery.isNumeric(c) ? '{{element}}' : c;
@@ -1419,20 +4313,20 @@
1419 4313 // The selector
1420 4314 var tSel = jQuery.isNumeric(c) ? '{{element}}' : c;
1421 4315 var tmp = {
1422 4316 sel: tSel,
1423 - val: pagelayer_css_render(css[c], el.atts[xm], (props[x].sep || ',')),
4317 + val: pagelayer_css_render(css[c], xm_val, (props[x].sep || ',')),
1424 4318 };
1425 4319
1426 4320 // Is this a tablet
1427 4321 if(m == 'tablet'){
1428 - 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;
1429 4323 tmp.val = tmp.val+'}';
1430 4324 }
1431 4325
1432 4326 // Is this a mobile mode ?
1433 4327 if(m == 'mobile'){
1434 - tmp.sel = '@media (max-width: 360px){'+tmp.sel;
4328 + tmp.sel = '@media (max-width: '+ pagelayer_settings['mobile_breakpoint'] +'px){'+tmp.sel;
1435 4329 tmp.val = tmp.val+'}';
1436 4330 }
1437 4331
1438 4332 // Push to store
@@ -1450,9 +4344,16 @@
1450 4344 }
1451 4345
1452 4346 // If there is an HTML, then process it
1453 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')];
1454 4351
4352 + if(typeof fn == 'function'){
4353 + fn(el);
4354 + }
4355 +
1455 4356 el.iHTML = jQuery('<div>'+pagelayer_shortcodes[el.tag]['html']+'</div>');
1456 4357
1457 4358 // Lets process the 'if-ext'
1458 4359 el.iHTML.find('[if-ext]').each(function (){
@@ -1480,16 +4381,9 @@
1480 4381 $j.remove();
1481 4382 }
1482 4383
1483 4384 });
1484 -
1485 - // Is there a function to render ?
1486 - var fn = window['pagelayer_render_'+jEle.attr('pagelayer-tag')];
1487 4385
1488 - if(typeof fn == 'function'){
1489 - fn(el);
1490 - }
1491 -
1492 4386 //console.log(el.atts);
1493 4387
1494 4388 // Parse the variables
1495 4389 var new_html = pagelayer_parse_vars(el.iHTML.html(), el);
@@ -1498,9 +4392,9 @@
1498 4392 // Do we have to wrap the innerHTML ?
1499 4393 if('holder' in pagelayer_shortcodes[el.tag]){
1500 4394
1501 4395 var hSel = pagelayer_shortcodes[el.tag]['holder'];
1502 - var holder = jEle.find(hSel);
4396 + var holder = jEle.find(hSel).first();
1503 4397
1504 4398 // Detach the holder
1505 4399 holder.detach();
1506 4400
@@ -1546,9 +4440,9 @@
1546 4440 for(var c in elCSS.edit){
1547 4441 var prop = elCSS.edit[c]['prop'];
1548 4442 var tSel = elCSS.edit[c]['sel'];
1549 4443 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
1550 - node.attr('pagelayer-editable', prop);
4444 + node.attr({'pagelayer-editable': prop, 'contenteditable' : 'true'});
1551 4445 }
1552 4446
1553 4447 }
1554 4448
@@ -1560,9 +4454,9 @@
1560 4454 if(elCSS.classes.length > 0){
1561 4455 //console.log(elCSS.classes);
1562 4456
1563 4457 for(var c in elCSS.classes){
1564 - var tSel = elCSS.classes[c]['sel'];
4458 + var tSel = elCSS.classes[c]['sel'].replace('{{element}}', '');
1565 4459 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
1566 4460 if(!node.hasClass(elCSS.classes[c]['val'])){
1567 4461 node.addClass(elCSS.classes[c]['val']);
1568 4462 }
@@ -1573,9 +4467,9 @@
1573 4467 if(elCSS.remove_classes.length > 0){
1574 4468 //console.log(elCSS.remove_classes);
1575 4469
1576 4470 for(var c in elCSS.remove_classes){
1577 - var tSel = elCSS.remove_classes[c]['sel'];
4471 + var tSel = elCSS.remove_classes[c]['sel'].replace('{{element}}', '');
1578 4472 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
1579 4473 if(node.hasClass(elCSS.remove_classes[c]['val'])){
1580 4474 node.removeClass(elCSS.remove_classes[c]['val']);
1581 4475 }
@@ -1592,14 +4486,14 @@
1592 4486
1593 4487 for(var c in elCSS.attr){
1594 4488 var tSel = elCSS.attr[c]['sel'].replace('{{element}}', '');
1595 4489 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
1596 - var att = elCSS.attr[c]['val'].split('=');
4490 + var att = elCSS.attr[c]['val'].split(/=(.*)/);
1597 4491 att[1] = pagelayer_parse_vars(att[1], el);
1598 4492 att[1] = pagelayer_trim(att[1], '"');
1599 4493
1600 4494 // Is it the same val ?
1601 - if(!node.attr(att[0]) != att[1]){
4495 + if(!node.attr(att[0]) !== att[1]){
1602 4496 node.attr(att[0], att[1]);
1603 4497 }
1604 4498 }
1605 4499 }
@@ -1637,15 +4531,28 @@
1637 4531 var rules = [];
1638 4532
1639 4533 // Loop
1640 4534 for(var c in elCSS.css){
1641 - var tSel = elCSS.css[c]['sel'].replace('{{element}}', elCSS.sel);
1642 - var rule = pagelayer_parse_vars(elCSS.css[c]['val'], el);
1643 - 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 + }
1644 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 + }
1645 4552
1646 4553 // Set the style
1647 - style.html(rules.join("\n"));
4554 + style.html(pagelayer_parse_vars(rules.join("\n"), el));
1648 4555 //console.log(style);
1649 4556 }else{
1650 4557 style.remove();
1651 4558 }
@@ -1658,18 +4565,154 @@
1658 4565 }
1659 4566
1660 4567 // If the element have any parent
1661 4568 var par = pagelayer_get_parent(jEle);
4569 + var eleId = el.id;
4570 +
1662 4571 if(par){
4572 + eleId = par;
1663 4573 pagelayer_sc_render(pagelayer_ele_by_id(par));
1664 4574 }
1665 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 +
1666 4595 };
1667 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 +
1668 4711 // Is the given tag a group
1669 4712 function pagelayer_is_group(tag){
1670 4713
1671 - if('params' in pagelayer_shortcodes[tag] && 'elements' in pagelayer_shortcodes[tag]['params']){
4714 + if('has_group' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['has_group'])){
1672 4715 return true;
1673 4716 }
1674 4717
1675 4718 return false;
@@ -1675,36 +4718,308 @@
1675 4718 return false;
1676 4719
1677 4720 }
1678 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 +
1679 4910 // Save the post
1680 4911 function pagelayer_save(){
1681 4912
1682 - var post = pagelayer_generate_sc(".entry-content");//alert(post);return;
1683 - var pagelayerajaxurl = pagelayer_ajax_url+'?action=pagelayer_save_content&postID='+pagelayer_postID;
1684 - jQuery.ajax({
1685 - type: "POST",
1686 - url: pagelayerajaxurl,
1687 - data: {
1688 - pagelayer_update_content : post,
1689 - nonce: pagelayer_ajax_nonce
1690 - },
1691 - success: function(response, status, xhr){
1692 - //alert(data);
1693 - var obj = jQuery.parseJSON(response);
1694 - //alert(obj);
1695 - if(obj['error']){
1696 - alert(obj['error']);
1697 - }else{
1698 - pagelayer_isDirty = false;
1699 - alert(obj['success']);
4913 + // hiding and showing loading animation
4914 + pagelayer.$$('.pagelayer-update-text').hide();
4915 + pagelayer.$$('.pagelayer-update-loader').show();
4916 +
4917 + pagelayer_trigger_action('pagelayer_save');
4918 +
4919 + var pagelayerajaxurl = pagelayer_ajax_url+'&action=pagelayer_save_content&postID='+pagelayer_postID;
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 + }
1700 5011 }
1701 - },
1702 - error: function(errorThrown){
1703 - console.log(errorThrown);
1704 - }
1705 - });
5012 + });
5013 + }
1706 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();
1707 5022 };
1708 5023
1709 5024 //Close the Editor
1710 5025 function pagelayer_close(){
@@ -1717,18 +5032,30 @@
1717 5032 }else{
1718 5033 window.top.location.href = pagelayer_returnURL;
1719 5034 }
1720 5035 };
5036 +
5037 +function pagelayer_htmlEntities(str) {
5038 + return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
5039 +}
1721 5040
1722 -// Generate Shortcode Post to save
1723 -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){
1724 5052
5053 + selfEle = selfEle || false;
1725 5054 var txt = '';
1726 5055
1727 - jQuery(selector).children(".pagelayer-ele-wrap").each(function(){
5056 + var generate_sc_single = function(jEle){
1728 5057
1729 - var jEle = jQuery(this).children('.pagelayer-ele');
1730 -
1731 5058 // The ID
1732 5059 var id = jEle.attr('pagelayer-id');
1733 5060
1734 5061 // If there is an Add element wrapper
@@ -1737,9 +5064,34 @@
1737 5064 }
1738 5065
1739 5066 // Find the type of tag
1740 5067 var tag = jEle.attr('pagelayer-tag');
5068 + var final_tag = tag;
5069 + var closestEle = jEle.closest('.pagelayer-col-holder');
1741 5070
5071 + // Skip to create shortcode to prevent save, allowed by tag
5072 + if('skip_save' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['skip_save'])){
5073 + return;
5074 + }
5075 +
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){
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);
5086 + }
5087 +
5088 + // Define inner column
5089 + if(tag == 'pl_col' && closestEle.length > 0 && closestEle.closest(pagelayer_editable).length > 0){
5090 + final_tag = 'pl_inner_col';
5091 + }
5092 + //console.log(tag);
5093 +
1742 5094 // Is there an innerHTML ele
1743 5095 var inner = '';
1744 5096 if('innerHTML' in pagelayer_shortcodes[tag]){
1745 5097 inner = pagelayer_shortcodes[tag]['innerHTML'];
@@ -1744,57 +5096,61 @@
1744 5096 if('innerHTML' in pagelayer_shortcodes[tag]){
1745 5097 inner = pagelayer_shortcodes[tag]['innerHTML'];
1746 5098 }
1747 5099
5100 + // Data reference
5101 + var ref_data = pagelayer_el_data_ref(jEle);
5102 +
1748 5103 // Create the tag
1749 - var data = '['+tag;
5104 + var data = JSON.parse(JSON.stringify(ref_data['attr']));
1750 5105
1751 - // Get the attributes to store
1752 - jQuery.each(jEle[0].attributes, function(i, attrib){
1753 - var res = attrib.name.match(/^pagelayer-a-(.+)/i);
1754 - if(res && res[1] != inner){
1755 - //console.log(attrib.name+' '+res[1]);
1756 - data += ' '+res[1]+'="'+pagelayer_escapeHTML(attrib.value)+'"';
1757 - }
1758 - });
5106 + data['pagelayer-id'] = id;
5107 + data = pagelayer_serializeAttributes(data);
5108 +
5109 + var content = '';
1759 5110
1760 - data = data+']';
1761 -
1762 - // Add to the text
1763 - txt = txt+data+"\n";
1764 -
1765 5111 // Any internal function to handle the save ?
1766 5112 var func = window['pagelayer_tag_'+tag];
1767 5113 if(typeof func == 'function'){
1768 5114
1769 - var content = '';
1770 5115 content = func(jEle);
1771 5116
1772 - if(content.length > 0){
1773 - txt = txt+content;
1774 - }
1775 -
1776 5117 // If its a Row or Column or Group then it will have children
1777 - }else if(jEle.hasClass('pagelayer-row') || jEle.hasClass('pagelayer-col') || pagelayer_is_group(tag)){
5118 + }else if(jEle.hasClass('pagelayer-row') || jEle.hasClass('pagelayer-col') || jEle.hasClass('pagelayer-inner_row') || pagelayer_is_group(tag)){
1778 5119
1779 - var sel = "[pagelayer-id="+id+"]";
5120 + var sel = jEle;
1780 5121
1781 5122 // Any holder which holds children ?
1782 5123 if('holder' in pagelayer_shortcodes[tag]){
1783 - sel = sel+' '+pagelayer_shortcodes[tag]['holder'];
5124 + sel = jEle.find(pagelayer_shortcodes[tag]['holder']);
1784 5125 }
1785 5126
1786 - var childrens = pagelayer_generate_sc(sel);
1787 - if(childrens.length > 0){
1788 - 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 + }
1789 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 + }
1790 5147
1791 5148 // Its a normal element so we might need to handle the content
1792 5149 }else{
1793 5150
1794 - var content = '';
1795 5151 if(inner.length > 0){
1796 - content = jEle.attr('pagelayer-a-'+inner);
5152 + content = pagelayer_get_att(jEle, inner);
1797 5153 if(!content){
1798 5154 content = '';
1799 5155 }
1800 5156 }else{
@@ -1800,108 +5156,112 @@
1800 5156 }else{
1801 5157 content = '';//jEle.html();
1802 5158 }
1803 5159
1804 - if(content.length > 0){
1805 - txt = txt+content;
1806 - }
1807 -
1808 5160 }
1809 5161
1810 - // Close the tag
1811 - txt = txt+"[/"+tag+"]\n";
5162 + // Leaving HTML and non-pagelayer supported content intact
5163 + if(final_tag == 'pl_missing'){
5164 + txt += content;
5165 + return;
5166 + }
1812 5167
1813 - });
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 + };
1814 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 +
1815 5193 return txt;
1816 5194
1817 5195 };
1818 5196
1819 -// Escape charaters in attributes
1820 -var pagelayer_escapeChars = {
1821 - '\\]' : '#93',
1822 - '\\[' : '#91',
1823 - //'=' : '#61',
1824 - '<' : 'lt',
1825 - '>' : 'gt',
1826 - '"' : 'quot',
1827 - //'&' : 'amp',
1828 - '\'' : '#39'
1829 -};
1830 -
1831 -// To unescape
1832 -var pagelayer_unescapeChars = {
1833 - '#93' : ']',
1834 - '#91' : '[',
1835 - //'#61' : '=',
1836 - 'lt' : '<',
1837 - 'gt' : '>',
1838 - 'quot' : '"',
1839 - //'amp' : '&',
1840 - '#39' : '\''
1841 -};
1842 -
1843 -var pagelayer_escaperegex_S = '[';
1844 -for(var key in pagelayer_escapeChars) {
1845 - 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();
1846 5201 }
1847 -pagelayer_escaperegex_S += ']';
1848 5202
1849 -var pagelayer_escaperegex = new RegExp( pagelayer_escaperegex_S, 'g');
1850 -
1851 -// The function which escapes everything
1852 -function pagelayer_escapeHTML(str) {
1853 - return str.replace(pagelayer_escaperegex, function(m) {
1854 - if(m == '[' || m == ']') m = '\\'+m;
1855 - return '&' + pagelayer_escapeChars[m] + ';';
1856 - });
1857 -};
1858 -
1859 -// This will unescape everything
1860 -function pagelayer_unescapeHTML(str){
1861 - return str.replace(/\&([^;]+);/g, function (entity, entityCode) {
1862 - if(entityCode in pagelayer_unescapeChars){
1863 - return pagelayer_unescapeChars[entityCode];
1864 - }else{
1865 - return entity;
1866 - }
1867 - });
1868 -};
1869 -
1870 5203 // Sets up the leftbar
1871 5204 function pagelayer_leftbar(){
1872 5205
1873 5206 // Toggle the holder
1874 5207 pagelayer.$$('.pagelayer-leftbar-toggle').on('click', function(){
1875 - pagelayer.$$('.pagelayer-leftbar-table').toggle();
5208 + pagelayer.$$('.pagelayer-leftbar-table').toggleClass('pagelayer-leftbar-hidden');
5209 + pagelayer_trigger_action('pagelayer-leftbar-toggle');
1876 5210 });
1877 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 +
1878 5222 var html = '<div class="pagelayer-leftbar">'+
1879 5223 '<div class="pagelayer-leftbar-scroll">'+
1880 - '<div class="pagelayer-shortcodes">'+
1881 - '<div class="pagelayer-leftbar-search">'+
1882 - '<input class="pagelayer-search-field" />'+
1883 - '</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>';
1884 5234
1885 5235 for(var x in pagelayer_groups){
1886 5236
1887 5237 // Title
1888 - 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';
1889 5241
5242 + html += '<div class="pagelayer-leftbar-group pagelayer-group-name-'+x+'"><h5>'+group_title+'</h5>';
5243 +
1890 5244 // Indivdual icon
1891 5245 for(var y in pagelayer_groups[x]){
1892 5246
1893 5247 var sc = pagelayer_groups[x][y];
1894 5248
1895 - if('not_visible' in pagelayer_shortcodes[sc]){
5249 + if(!(sc in pagelayer_shortcodes) || 'not_visible' in pagelayer_shortcodes[sc]){
1896 5250 continue;
1897 5251 }
1898 5252
1899 - html += '<div class="pagelayer-shortcode-drag" pagelayer-tag="'+sc+'">'+
5253 + html += '<div class="pagelayer-shortcode-drag" draggable="true" pagelayer-tag="'+sc+'">'+
1900 5254 '<div class="pagelayer-sc">'+
1901 - '<center class="pagelayer-shortcode-inner">'+
1902 - '<div class="pagelayer-shortcode pagelayer-'+sc+'"></div>'+
1903 - '</center>'+
5255 + '<center class="pagelayer-shortcode-inner">';
5256 +
5257 + if('icon' in pagelayer_shortcodes[sc]){
5258 + html += '<i class="pagelayer-shortcode '+pagelayer_shortcodes[sc]['icon']+'"></i>';
5259 + }else{
5260 + html += '<i class="pagelayer-shortcode pli pagelayer-'+sc+'"></i>';
5261 + }
5262 +
5263 + html += '</center>'+
1904 5264 '<span class="pagelayer-shortcode-text">'+pagelayer_shortcodes[sc]['name']+'</span>'+
1905 5265 '</div>'+
1906 5266 '</div>';
1907 5267
@@ -1911,16 +5271,24 @@
1911 5271
1912 5272 }
1913 5273
1914 5274 html += '</div>'+
1915 - '<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>'+
1916 5283 '</div>'+
1917 5284 '</div>';
1918 5285
1919 5286 pagelayer.$$('.pagelayer-leftbar-holder').prepend(html);
5287 + pagelayer_leftbar_tab('pagelayer-shortcodes');
1920 5288
1921 5289 pagelayer.$$('.pagelayer-leftbar-scroll').slimScroll({
1922 - height: '100%',
5290 + height: '100%',
1923 5291 railVisible: false,
1924 5292 alwaysVisible: true,
1925 5293 color: '#000',
1926 5294 size: '5px',
@@ -1960,10 +5328,725 @@
1960 5328
1961 5329 });
1962 5330 });
1963 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 + });
1964 5469 };
1965 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 +
1966 6049 // Report an error
1967 6050 function pagelayer_error(error, func){
1968 6051 var prefix = func || '';
1969 6052 alert(prefix+error);
@@ -1969,41 +6052,128 @@
1969 6052 alert(prefix+error);
1970 6053 };
1971 6054
1972 6055 function pagelayer_bottombar(){
1973 - var holder = pagelayer.$$('.pagelayer-bottombar-holder');
1974 - var html = '<div class="pagelayer-bottombar">'+
1975 - '<div class="pagelayer-bottombar-rightbuttons">'+
1976 - '<button class="pagelayer-update-button">Update</button>'+
1977 - '<button class="pagelayer-close-button">Close</button>'+
1978 - '<div class="pagelayer-mode-wrapper">'+
1979 - '<i class="pagelayer-mode-button fa fa-desktop"></i>'+
1980 - '<div class="pagelayer-mode-buttons-wrapper">'+
1981 - '<i class="screen-mode fa fa-desktop" pagelayer-mode-data="desktop"></i>'+
1982 - '<i class="screen-mode fa fa-tablet" pagelayer-mode-data="tablet"></i>'+
1983 - '<i class="screen-mode fa fa-mobile" pagelayer-mode-data="mobile"></i>'+
1984 - '</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>'+
1985 6071 '</div>'+
1986 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>'+
1987 6088 '</div>';
1988 6089
1989 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 +
1990 6096 holder.find('.pagelayer-update-button').on('click', function(){
1991 6097 pagelayer_save();
6098 + pagelayer_history_setup();// Setup history tab after update
1992 6099 });
6100 +
1993 6101 holder.find('.pagelayer-close-button').on('click', function(){
1994 6102 pagelayer_close();
1995 6103 });
6104 +
1996 6105 holder.find('.screen-mode').on('click', function(){
1997 6106 var screen_mode = jQuery(this).attr('pagelayer-mode-data');
1998 6107 pagelayer_set_screen_mode(screen_mode);
1999 - holder.find('.pagelayer-mode-buttons-wrapper').toggle();
6108 + holder.find('.screen-mode').removeClass('active');
6109 + jQuery(this).addClass('active');
2000 6110 });
2001 6111
2002 - holder.find('.pagelayer-mode-button').on('click', function(){
2003 - 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();
2004 6118 });
2005 -}
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 +};
2006 6176
2007 6177
2008 6178 ///////////////////////////////
2009 6179 // Miscellaneuos Functions
@@ -2008,89 +6178,298 @@
2008 6178 ///////////////////////////////
2009 6179 // Miscellaneuos Functions
2010 6180 ///////////////////////////////
2011 6181
2012 -// Generates a random string of "n" characters
2013 -function pagelayer_randstr(n, special){
2014 - var text = '';
2015 - var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
6182 +// Setup General options
6183 +function pagelayer_setup_general_options(){
2016 6184
2017 - special = special || 0;
2018 - if(special){
2019 - possible = possible + '&#$%@';
6185 + var holder = pagelayer.$$('.pagelayer-general-options');
6186 +
6187 + if(holder.children().length > 0){
6188 + return;
2020 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>';
2021 6225
2022 - for(var i=0; i < n; i++){
2023 - text += possible.charAt(Math.floor(Math.random() * possible.length));
2024 - }
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 + });
2025 6263
2026 - return text;
2027 -};
6264 + modal.unbind('click');
6265 + modal.on('click', function(e){
6266 +
6267 + if(e.target != this) {
6268 + return;
6269 + }
2028 6270
2029 -function pagelayer_update_site_title(val){
2030 - if(!pagelayer_empty(val)){
2031 - var site_name = jQuery('.pagelayer-wp-title').attr('pagelayer-a-site_name');
2032 - if(!pagelayer_empty(site_name)){
2033 - var site_title = jQuery.ajax({
2034 - url: pagelayer_ajax_url+'?action=pagelayer_fetch_site_title',
2035 - type: 'post',
2036 - async: false
2037 - }).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(){
2038 6289
2039 - if(site_title != site_name){
2040 - var site_title = jQuery.ajax({
2041 - url: pagelayer_ajax_url+'?action=pagelayer_update_site_title',
2042 - type: 'post',
2043 - data: {'site_title': site_name},
2044 - async: false
2045 - }).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;
2046 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+']');
2047 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();
2048 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 +
2049 6416 }
2050 6417
2051 -function pagelayer_trim(str, charlist){
2052 - // discuss at: http://locutus.io/php/trim/
6418 +// Scroll page to element view port
6419 +function pagelayer_scroll_to_viewport(jEle, timeout, parentEle){
2053 6420
2054 - if(typeof str != 'string'){
2055 - return str;
2056 - }
6421 + var scrolled = parentEle || jQuery('html, body');
6422 + timeout = timeout || 500;
6423 + parentEle = parentEle || jQuery(window);
2057 6424
2058 - var whitespace = [' ', '\n', '\r', '\t', '\f', '\x0b', '\xa0', '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u2005', '\u2006', '\u2007', '\u2008', '\u2009', '\u200a', '\u200b', '\u2028', '\u2029', '\u3000' ].join('')
2059 - var l = 0
2060 - var i = 0
2061 - 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 + }
2062 6434
2063 - if (charlist) {
2064 - whitespace = (charlist + '').replace(/([[\]().?/*{}+$^:])/g, '$1')
2065 - }
6435 + var scrolling = elementTop - parentHeight / 2;
6436 + scrolled.stop(true).animate({
6437 + scrollTop: scrolling
6438 + }, 1000);
6439 + }, timeout);
6440 +}
2066 6441
2067 - l = str.length
2068 - for (i = 0; i < l; i++) {
2069 - if (whitespace.indexOf(str.charAt(i)) === -1) {
2070 - str = str.substring(i)
2071 - break
2072 - }
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 + '&#$%@';
2073 6450 }
2074 -
2075 - l = str.length
2076 - for (i = l - 1; i >= 0; i--) {
2077 - if (whitespace.indexOf(str.charAt(i)) === -1) {
2078 - str = str.substring(0, i + 1)
2079 - break
2080 - }
6451 +
6452 + for(var i=0; i < n; i++){
6453 + text += possible.charAt(Math.floor(Math.random() * possible.length));
2081 6454 }
2082 6455
2083 - return whitespace.indexOf(str.charAt(0)) === -1 ? str : ''
6456 + return text;
2084 6457 };
2085 6458
6459 +function pagelayer_randInt(max) {
6460 + return Math.floor(Math.random() * Math.floor(max));
6461 +}
6462 +
2086 6463 // Convert the regular URL of a Video to a Embed URL
2087 -function pagelayer_video_url(src){
2088 -
6464 +function pagelayer_video_url(src, no_url){
6465 +
6466 + no_url = no_url || false;
2089 6467 var youtubeRegExp = /youtube\.com|youtu\.be/;
2090 6468 var vimeoRegExp = /vimeo\.com/;
2091 6469 var match = '';
2092 6470 var videoId = '';
6471 + var vid_params = {};
2093 6472
2094 6473 if (youtubeRegExp.exec(src)) {
2095 6474 match = 'youtube';
2096 6475 } else if (vimeoRegExp.exec(src)) {
@@ -2117,9 +6496,15 @@
2117 6496 } else if (youtube.exec(src)) {
2118 6497 videoId = src.split('.be/');
2119 6498 }
2120 6499
2121 - return 'http://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();
2122 6507
2123 6508 break;
2124 6509
2125 6510 case 'vimeo':
@@ -2132,50 +6517,1666 @@
2132 6517 } else if (vimeoRegExp.exec(src)) {
2133 6518 videoId = src.split('.com/');
2134 6519 }
2135 6520
2136 - return 'http://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 + };
2137 6526
2138 6527 break;
2139 6528 default:
2140 - return src;
6529 + vid_params = {
6530 + type : 'local',
6531 + src : src
6532 + };
6533 +
2141 6534 }
6535 +
6536 + if(!no_url){
6537 + return vid_params.src;
6538 + }
6539 +
6540 + return vid_params;
2142 6541 };
2143 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 +
2144 6554 // Add widget section
2145 6555 function pagelayer_add_widget(){
2146 6556
2147 6557 html='<div class="pagelayer-add-widget-area">'+
2148 - '<i class="pagelayer-add-row fa fa-plus-circle"></i>'+
2149 - '<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>'+
2150 6564 '</div>';
2151 6565
2152 - jQuery('.entry-content').append(html);
6566 + jQuery(pagelayer_editable).append(html);
2153 6567
2154 - jQuery('.pagelayer-add-widget-area').on('click', function(){
2155 - pagelayer_add_sc(jQuery(this));
6568 + var add_area = jQuery('.pagelayer-add-widget-area');
6569 +
6570 + // Add a code before this
6571 + var add_sc = function(tag, global_id = ''){
6572 +
6573 + var attr = '';
6574 + if(!pagelayer_empty(global_id)){
6575 + attr = ' pagelayer-global-id="'+global_id+'" ';
6576 + }
6577 +
6578 + // Create Row
6579 + var row = jQuery('<div pagelayer-tag="pl_row" '+((tag == 'pl_row') ? attr : '') +'></div>');
6580 + add_area.before(row);
6581 + var row_id = pagelayer_onadd(row, false);
6582 + var rEle = pagelayer_ele_by_id(row_id);
6583 +
6584 + if(tag == 'pl_row' && !pagelayer_empty(global_id)){
6585 + rEle.click();
6586 + return row_id;
6587 + }
6588 +
6589 + // Create Column
6590 + var col = jQuery('<div pagelayer-tag="pl_col" '+((tag == 'pl_col') ? attr : '') +'></div>');
6591 + rEle.find('.pagelayer-row-holder').append(col);
6592 + var col_id = pagelayer_onadd(col, false);
6593 + var cEle = pagelayer_ele_by_id(col_id);
6594 +
6595 +
6596 + if(tag == 'pl_row'){
6597 + rEle.click();
6598 + return row_id;
6599 + }
6600 +
6601 + if(tag == 'pl_col'){
6602 + cEle.click();
6603 + return col_id;
6604 + }
6605 +
6606 + // Create element
6607 + var ele = jQuery('<div pagelayer-tag="'+tag+'" '+attr+'></div>');
6608 + cEle.find('.pagelayer-col-holder').append(ele);
6609 + //console.log(ele);
6610 + var id = pagelayer_onadd(ele);
6611 + //console.log(id);
6612 + //console.log(col_id);
6613 + var eEle = pagelayer_ele_by_id(col_id);
6614 + //console.log(eEle);
6615 + // Ensure the column is not empty
6616 + pagelayer_empty_col(cEle.find('.pagelayer-col-holder'));
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 +
6625 + return id;
6626 +
6627 + }
6628 +
6629 + // Handle Click on Plus Button
6630 + add_area.find('.pagelayer-add-circle-plus').on('click', function(e){
6631 + e.stopPropagation();
6632 + add_sc('pl_col');
2156 6633 });
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 +
6665 + // Handle Drag over
6666 + add_area.on('dragover', function(e){
6667 + //console.log(e)
6668 + add_area.addClass('pagelayer-add-widget-drag');
6669 + });
6670 +
6671 + // Handle Drag Leave
6672 + add_area.on('dragleave', function(e){
6673 + //console.log(e)
6674 + add_area.removeClass('pagelayer-add-widget-drag');
6675 + });
6676 +
6677 + // Handle On Drop
6678 + add_area.on('drop', function(e){
6679 +
6680 + //console.log(e);
6681 + //console.log(e.originalEvent.dataTransfer.getData('tag'));
6682 + add_area.removeClass('pagelayer-add-widget-drag');
6683 + jQuery('.pagelayer-is-dragging').removeClass('pagelayer-is-dragging');
6684 +
6685 + var tag = e.originalEvent.dataTransfer.getData('tag');
6686 + var global_id = e.originalEvent.dataTransfer.getData('global_id');
6687 +
6688 + // Is it an existing element ?
6689 + if(tag.length < 1){
6690 + return false;
6691 + }
6692 +
6693 + e.preventDefault();
6694 +
6695 + //console.log(tag);
6696 +
6697 + add_sc(tag, global_id);
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 ;
2157 6716 }
2158 6717
2159 -// Add row and column
2160 -function pagelayer_add_sc(jEle, sc){
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(){
2161 6832
2162 - // Add new row
2163 - var new_row = pagelayer_create_sc('pl_row');
2164 - jEle.closest('.pagelayer-add-widget-area').before(new_row);
2165 - pagelayer_element_setup(new_row, true);
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);
2166 6841
2167 - // Add column inside row
2168 - var new_col = pagelayer_create_sc('pl_col');
2169 - jQuery(new_row.find('.pagelayer-row-holder')).html(new_col);
2170 - pagelayer_element_setup(new_col, true);
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 + };
2171 6878
2172 - if(sc){
2173 - // Add column inside row
2174 - var add_widget = pagelayer_element_added(sc, new_col);
2175 - var widget_ele = jQuery('[pagelayer-id='+add_widget+']');
2176 - jQuery(new_col.find('.pagelayer-col-holder')).html(widget_ele);
2177 - pagelayer_element_setup(widget_ele, true);
2178 - jEle.find(widget_ele).closest('.pagelayer-ele-wrap').remove();
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 +}
2179 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);
2180 7218 }
2181 -}
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 +