PluginProbe
Page Builder: Pagelayer – Drag and Drop website builder / 1.0.0
Page Builder: Pagelayer – Drag and Drop website builder v1.0.0
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 1.0.5 All 129 releases
pagelayer / js / pagelayer-editor.js

pagelayer-editor.js in Page Builder: Pagelayer – Drag and Drop website builder 1.0.0, at js/pagelayer-editor.js

3,546 lines 89.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /*
2 PAGELAYER
3 http://pagelayer.com/
4 (c) Pagelayer Team
5 */
6
7 pagelayer = {
8 $: jQuery,
9 $$ : function(select){
10 return jQuery(select, window.parent.document);
11 },
12 p : this,
13 copy_selected: '',
14 mouse: {x: -1, y: -1},
15 history_action : true,
16 }
17
18 var pagelayer_history_obj = {}, pagelayer_revision_obj = {};
19
20 // Lets start
21 jQuery(document).ready(function(){
22
23 // Set the title of the parent window
24 try{ pagelayer.$$('head').append(pagelayer.$('title')[0].outerHTML); }catch(e){};
25
26 pagelayer.blank_img = pagelayer_url+'/images/default-image.png';
27
28 pagelayer_shortcodes['pl_inner_row'] = JSON.parse(JSON.stringify(pagelayer_shortcodes['pl_row']));
29 pagelayer_shortcodes['pl_inner_row']['name'] = 'Inner Row';
30 pagelayer_groups['grid'].push('pl_inner_row');
31
32 // Make the Topbar
33 pagelayer_bottombar();
34
35 // Make the Leftbar
36 pagelayer_leftbar();
37
38 // Add widget section
39 pagelayer_add_widget();
40
41 // Setup the ELPD
42 pagelayer_elpd_setup();
43
44 // Setup the properties of the elements
45 pagelayer_element_setup();
46
47 // An image to show for drag
48 jQuery('body').append('<img src="'+pagelayer_url+'/images/drag-ghost.png" class="pagelayer-drag-show" />');
49
50 // Setup the grid drag
51 pagelayer_setup_drag();
52
53 // Set to desktop
54 pagelayer_set_screen_mode('desktop');
55
56 // Set up right click
57 pagelayer_left_click();
58 pagelayer_right_click();
59
60 // Setup pagelayer history handle
61 pagelayer_history_obj['action_data'] = [];
62 pagelayer_history_setup(true);
63
64 });
65
66 // The jQuery Object of the ELPD
67 var pagelayer_elpd;
68
69 function pagelayer_closest_corner(jEle){
70 var corners = [];
71 var w = jEle.outerWidth();
72 var h = jEle.outerHeight();
73 var topleft = jEle.offset();
74
75 // 0 - Top Left
76 corners.push(topleft);
77
78 // 1 - Top Right
79 corners.push({top: topleft.top, left: topleft.left+w});
80
81 // 2 - Bottom Right
82 corners.push({top: topleft.top+h, left: topleft.left+w});
83
84 // 3 - Bottom Left
85 corners.push({top: topleft.top+h, left: topleft.left});
86
87 //console.log(corners);
88
89 // Calculate the closest to the mouse
90 var distances = {};
91 for(var c in corners){
92 var dist = Math.hypot(pagelayer.mouse.x - corners[c].left, pagelayer.mouse.y - corners[c].top);
93 distances[c] = dist;
94 }
95 //console.log(distances);
96
97 var corner = Object.keys(distances).sort(function(a,b){return distances[a]-distances[b]})[0];
98 //console.log(corner);
99
100 return corner;
101
102 };
103
104 // Make rows and cols draggable
105 function pagelayer_setup_drag(){
106
107 // The object to show as drag
108 var shower = jQuery('.pagelayer-drag-show');
109
110 // Delete any prospect
111 var clear_prospect = function(){
112 jQuery('.pagelayer-drag-prospect').remove();
113
114 // Shows the wrap as active
115 jQuery('.pagelayer-drag-ele-hover').removeClass('pagelayer-drag-ele-hover');
116 }
117
118 // Reset the complete drag stuff
119 var reset_dragging = function(){
120 pagelayer.dragging = false;
121 pagelayer.drag_is_new = false;
122 pagelayer.drag_mouse = {x: 0, y: 0};
123 reset_on_drag();
124 }
125
126 // Reset the element on you were last
127 var reset_on_drag = function(){
128 pagelayer.drag_closest = false;
129 pagelayer.drag_closest_corner = null;
130 }
131
132 // Scroll by
133 var scrollPx = 7;
134 var scrollDist = 30;
135
136 // If we are too close too the window edge, then scroll
137 var handle_scroll = function(e){
138
139 var windowHeight = jQuery(window).height();
140 var windowWidth = jQuery(window).width();
141
142 // Are we to close to the top or bottom
143 if(e.clientY < scrollDist){
144 window.scrollBy(0, -scrollPx);
145 }else if((windowHeight - e.clientY) < scrollDist){
146 window.scrollBy(0, scrollPx);
147 }
148
149 // Are we to close to the top or bottom
150 if(e.clientX < scrollDist){
151 window.scrollBy(-scrollPx, 0);
152 }else if((windowWidth - e.clientX) < scrollDist){
153 window.scrollBy(scrollPx, 0);
154 }
155
156 }
157
158 // SET the values
159 reset_dragging();
160
161 var ondragover = function(e) {
162 //console.log(e);
163
164 pagelayer.mouse.x = parseInt(e.pageX);
165 pagelayer.mouse.y = parseInt(e.pageY);
166 //console.log(pagelayer.mouse);
167
168 // Are we dragging ?
169 if(pagelayer.dragging){
170
171 //console.log(e);
172
173 e.preventDefault();
174 //e.stopPropagation();
175
176 // The wrap of the element being dragged
177 var wrap = pagelayer.dragging;
178
179 // New addition
180 var is_new = pagelayer.drag_is_new;
181 var ele;
182 var tag = pagelayer_tag(wrap);
183 var id = pagelayer_id(wrap);
184
185 // If existing element then add we are dragging
186 if(!is_new){
187
188 // Start Dragging
189 if(!wrap.hasClass('pagelayer-is-dragging')){
190 wrap.addClass('pagelayer-is-dragging');
191 }
192
193 //shower.hide();
194
195 ele = document.elementFromPoint(e.clientX, e.clientY);
196 //console.log(ele);
197
198 // Drag the show object
199 //shower.show();
200 //var offset = {top: (e.pageY-10)+'px', left: (e.pageX-10)+'px'}
201 //shower.css(offset);
202
203 }else{
204 ele = document.elementFromPoint(e.clientX, e.clientY);
205 }
206 //console.log(e);
207
208 // Have we moved more than 5px;
209 var dist = Math.hypot(pagelayer.mouse.x - pagelayer.drag_mouse.x, pagelayer.mouse.y - pagelayer.drag_mouse.y);
210 //console.log(dist);
211 /*if(dist && dist < 5){
212 return false;
213 }*/
214
215 // Handle the scroll
216 handle_scroll(e);
217
218 // Find the closest wrap
219 var onWrap;
220
221 // If we are a column, we can be over another column or row
222 if(tag == 'pl_col'){
223 onWrap = jQuery(ele).closest('.pagelayer-wrap-col,.pagelayer-wrap-row,.pagelayer-wrap-inner-row');
224 //console.log(pagelayer_id(onWrap));
225
226 // If we are a row, we can be over another row or a column
227 }else if(tag == 'pl_row'){
228 onWrap = jQuery(ele).closest('.pagelayer-wrap-row');
229 //console.log(pagelayer_id(onWrap));
230
231 // For inner row we restrict to 1 level only
232 }else if(tag == 'pl_inner_row'){
233 var ele_wrap = jQuery(ele).parents('.pagelayer-wrap-col');
234 if(ele_wrap.length == 1 && !jQuery(ele).hasClass('pagelayer-wrap-col')){
235 onWrap = jQuery(ele).closest('.pagelayer-wrap-ele,.pagelayer-wrap-col,.pagelayer-wrap-inner-row');
236 }else{
237 onWrap = jQuery(ele).closest('.pagelayer-wrap-inner-row');
238 }
239 // For every other element, we can be over a col or ele
240 }else{
241 onWrap = jQuery(ele).closest('.pagelayer-wrap-ele,.pagelayer-wrap-col,.pagelayer-wrap-inner-row');
242 }
243 //console.log(onWrap);
244
245 // If we find nothing
246 if(pagelayer_empty(onWrap) || onWrap.length < 1){
247 clear_prospect();// Clear existing prospects
248 reset_on_drag();// Also reset the last on item
249 return false;
250 }
251
252 /*// If the columns more than 12 inside the row then return - As of now not enabled the below code
253 if(tag == 'pl_col'){
254 var _onTag = pagelayer_tag(onWrap);
255 var colEles;
256
257 // Is on col
258 if(_onTag == 'pl_col'){
259 colEles = onWrap.closest('.pagelayer-row-holder').children('.pagelayer-ele-wrap');
260 }else{
261 colEles = onWrap.find('.pagelayer-row-holder').first().children('.pagelayer-ele-wrap');
262 }
263
264 // If the columns more than 12
265 if(colEles.length >= 12){
266 return false;
267 }
268 }*/
269
270 // Get the ID
271 var onId = onWrap.attr('pagelayer-wrap-id');
272 var onEle = onWrap.children('.pagelayer-ele');
273
274 // Do we have a parent ?
275 var pOnId = pagelayer_get_parent(onEle);
276
277 if(pOnId){
278 onId = pOnId;
279 onEle = pagelayer_ele_by_id(onId);
280 onWrap = pagelayer_wrap_by_id(onId);
281 }
282
283 var changed = false;
284
285 // Was it the same ID like the one we were on before
286 if(pagelayer.drag_closest != onId){
287 pagelayer.drag_closest = onId;
288 changed = true;
289 }
290 //console.log(onId+' '+pagelayer.drag_closest)
291
292 var req_corners = {0: 'top', 1: 'top', 2: 'bottom', 3: 'bottom'};
293
294 // For columns we redefine the top and bottom
295 if(tag == 'pl_col'){
296 req_corners[1] = 'bottom';
297 req_corners[3] = 'top';
298 }
299
300 // Determine the previous and next
301 var next = wrap.next('.pagelayer-ele-wrap');
302 var prev = wrap.prev('.pagelayer-ele-wrap');
303
304 if(next.length == 1 && pagelayer_id(next) == onId){
305 req_corners = {0: 'bottom', 1: 'bottom', 2: 'bottom', 3: 'bottom'};
306 }
307
308 if(prev.length == 1 && pagelayer_id(prev) == onId){
309 req_corners = {0: 'top', 1: 'top', 2: 'top', 3: 'top'};
310 }
311
312 // Which corner are we closest to ?
313 var corner_num = pagelayer_closest_corner(onWrap);
314 var corner = req_corners[corner_num];
315
316 //console.log(corner+' != '+pagelayer.drag_closest_corner)
317 if(corner != pagelayer.drag_closest_corner){
318 pagelayer.drag_closest_corner = corner;
319 changed = true;
320 }
321
322 //console.log(changed);
323
324 // If we are on our self then clear return false
325 if(onId == id){
326 clear_prospect();// Clear existing prospects
327 reset_on_drag();// Also reset the last on item
328 return false;
329 }
330
331 // Then lets start showing
332 if(changed){
333
334 // Record the mouse points
335 pagelayer.drag_mouse.x = parseInt(e.pageX);
336 pagelayer.drag_mouse.y = parseInt(e.pageY);
337
338 // Clear any existing prospect
339 clear_prospect();
340
341 // Add new prospect
342 var prospect = '<div class="pagelayer-drag-prospect" pagelayer-corner="'+corner+'"></div>';
343
344 if(corner == 'bottom'){
345 onWrap.append(prospect);
346 }else if(corner == 'top'){
347 onWrap.prepend(prospect);
348 }
349
350 prospect = jQuery('.pagelayer-drag-prospect')
351 var animate_props = {height: '5px'};
352
353 // For column add a special class
354 if(tag == 'pl_col'){
355 prospect.addClass('pagelayer-drag-prospect-col');
356 animate_props['width'] = '5px';
357
358 // Adjust the left and right
359 var css = {};
360 css[(corner == 'bottom' ? 'right' : 'left')] = '0px';
361 prospect.css(css);
362 }
363
364 // Animate the prospect
365 prospect.animate(animate_props, 200);
366
367 // Highlight the wrap via overlay
368 onWrap.children('.pagelayer-ele-overlay').addClass('pagelayer-drag-ele-hover');
369
370 }
371
372 }
373 }
374
375 // When mouse is pressed down
376 var ondragstart = function(e){
377
378 //console.log(e);
379
380 // Target
381 var tEle = jQuery(e.target);
382 var wrap = tEle.closest('.pagelayer-ele-wrap');
383 //console.log(jEle[0]);
384
385 // Is it an existing element ?
386 if(wrap.length < 1){
387 return false;
388 }
389
390 // Do we have a parent ?
391 var id = pagelayer_id(wrap);
392 var jEle = pagelayer_ele_by_id(id);
393 var pId = pagelayer_get_parent(jEle);
394
395 if(pId){
396 wrap = pagelayer_wrap_by_id(pId);
397 }
398
399 //e.preventDefault();
400
401 var tag = pagelayer_tag(wrap);
402
403 e.originalEvent.dataTransfer.setData('Text', 1);
404 var img = document.createElement('img');
405 img.src = shower.attr('src');
406 e.originalEvent.dataTransfer.setDragImage(img, 32, 32);
407
408 pagelayer.dragging = wrap;
409
410 }
411
412 // When mouse is pressed down
413 var ondrop = function(e){
414
415 //console.log(e);
416
417 // Stop dragging ?
418 if(pagelayer.dragging){
419
420 e.preventDefault();
421
422 var wrap = pagelayer.dragging;
423 var tag = pagelayer_tag(wrap);
424 var fromEl = wrap.parent();
425 var id;
426 wrap.removeClass('pagelayer-is-dragging');
427
428 // Find any prospect
429 var prospect = jQuery('.pagelayer-drag-prospect');
430 //console.log(prospect[0]);
431
432 // It should be exactly 1
433 if(prospect.length == 1){
434
435 var onWrap = prospect.parent();
436 var onId = pagelayer_id(onWrap);
437 var onTag = pagelayer_tag(onWrap);
438 var dropped;
439 var corner = prospect.attr('pagelayer-corner');
440 var method = (corner == 'top') ? 'before' : 'after';
441
442 // Create the element if it needs to be created
443 if(pagelayer.drag_is_new){
444 dropped = jQuery('<div pagelayer-tag="'+tag+'"></div>');
445
446 // Move the object
447 }else{
448 dropped = wrap;
449 dropped.detach();
450 }
451
452 // If I am a column or row, then I go only before or after my same type !
453 if((onTag == 'pl_col' || onTag == 'pl_row') && onTag == tag){
454
455 // If I am a column and I am on a row
456 // OR I am a normal element and I am on column
457 }else if((tag == 'pl_col' && (onTag == 'pl_row' || onTag == 'pl_inner_row')) || onTag == 'pl_col'){
458 // We need to find the holder and add the prospect there
459 var holder = pagelayer_shortcodes[onTag]['holder'];
460 onWrap = onWrap.children('.pagelayer-ele').children(holder);
461 method = (corner == 'top') ? 'prepend' : 'append';
462 }
463
464 // Attach or shift the element
465 onWrap[method](dropped);
466 //console.log(dropped);
467
468 // Trigger the onadd
469 if(pagelayer.drag_is_new){
470 id = pagelayer_onadd(dropped);
471
472 // Existing elements
473 }else{
474 id = pagelayer_id(wrap);
475 }
476
477 // Defining the variables as needed
478 var jEle = pagelayer_ele_by_id(id);
479 wrap = pagelayer_wrap_by_id(id);
480 var toEl = wrap.parent();
481
482 // Column number handle
483 if(tag == 'pl_col'){
484
485 var row_holder = jEle.parent().closest('.pagelayer-row-holder');
486
487 // Renumber the col where you are going
488 pagelayer_renumber_col(row_holder);
489
490 // Renumber the old columns as well
491 if(!pagelayer.drag_is_new){
492 var from_row = fromEl.closest('.pagelayer-row-holder');
493 pagelayer_renumber_col(from_row);
494 }
495 }
496
497 // Handle the empty col
498 if(tag != 'pl_col'){
499
500 pagelayer_empty_col(toEl.closest('.pagelayer-col-holder'));
501
502 if(!pagelayer.drag_is_new){
503 pagelayer_empty_col(fromEl.closest('.pagelayer-col-holder'));
504 }
505
506 }
507
508 }
509
510 // Clear prospect
511 clear_prospect();
512 }
513
514 reset_dragging();
515
516 }
517
518 // Add the events for inner content - as we are using the drag API
519 jQuery(document).on('dragstart', ondragstart);
520 jQuery(document).on('dragover', ondragover);
521 jQuery(document).on('drop', ondrop);
522
523 // For addition of new elements
524 pagelayer.$$('[pagelayer-tag]').on('dragstart', function(e){
525 //console.log(e);
526
527 var tEle = jQuery(e.target);
528 var jEle = tEle.closest('.pagelayer-shortcode-drag');
529
530 // Is it an existing element ?
531 if(jEle.length < 1){
532 return false;
533 }
534
535 e.originalEvent.dataTransfer.setData('tag', pagelayer_tag(jEle));
536
537 pagelayer.dragging = jEle;
538 pagelayer.drag_is_new = true;
539
540 });
541
542 // Handle editable content by removing drag
543 var onmousedown = function(e){
544
545 var tEle = jQuery(e.originalEvent.explicitOriginalTarget);
546
547 if(tEle.closest('[pagelayer-editable]').length > 0){
548 //console.log('Is Editable MouseDown');
549 tEle.parents('[draggable]').attr('draggable', 'false');
550 }
551
552 }
553
554 // Handle editable content by adding drag that was removed
555 var onmouseup = function(e){
556 jQuery(document).find('[draggable=false]').attr('draggable', 'true');
557 }
558
559 // Handle editable contents by temprarily removing drag
560 jQuery(document).on('mousedown', onmousedown);
561 jQuery(document).on('mouseup', onmouseup);
562
563 };
564
565 // Handle empty col
566 // selector should be col holder
567 function pagelayer_empty_col(selector){
568
569 // Loop through
570 jQuery(selector).each(function(){
571
572 var jEle = jQuery(this);// jEle is the COL HOLDER
573
574 // Are we a col ?
575 if(!jEle.hasClass('pagelayer-col-holder')){
576 return;
577 }
578
579 // Column is becoming blank, so show add ele
580 if(jEle.children().length < 1){
581 //from.addClass('pagelayer-empty-col');
582 jEle.append('<div class="pagelayer-add-ele pagelayer-ele-wrap"><i class="fa fa-plus"><br /><span>Empty column please Drag Widgets</span></i></div>');
583 //var h = jEle.parent().parent().children('.pagelayer-ele-overlay').height();
584 //jEle.children('.pagelayer-add-ele').height(h);
585
586 // Any add ele sign with non-empty columns here ?
587 }else if(jEle.children('.pagelayer-add-ele').length > 0){
588 jEle.children('.pagelayer-add-ele').remove();
589 }
590
591 });
592
593 };
594
595 // Reset the column widths
596 // The selector should be a ROW HOLDER
597 function pagelayer_renumber_col(selector){
598
599 var pEle = jQuery(selector);
600 var children = pEle.children('.pagelayer-ele-wrap');
601 var cols = Math.floor(12 / (children.length));
602 var obj = {col: cols};
603
604 // Find out the number of cols of other cols
605 children.each(function(){
606
607 // This is the wrapper
608 var jEle = jQuery(this);
609
610 // The real element
611 var Ele = jEle.find('>.pagelayer-ele');
612
613 for(var x=1; x<=12; x++){
614 if(jEle.hasClass('pagelayer-col-'+x)){
615 jEle.removeClass('pagelayer-col-'+x);
616 Ele.removeClass('pagelayer-col-'+x);
617 break;
618 }
619 }
620 jEle.addClass('pagelayer-col-'+cols);
621 jEle.css({'width': ''});
622 Ele.addClass('pagelayer-col-'+cols);
623 Ele.css({'width': ''});
624
625 // Set the att
626 pagelayer_set_atts(Ele, obj);
627 });
628 }
629
630 // Make column resizable handler
631 function pagelayer_col_make_resizable(wrap){
632
633 // Resize handler element
634 var rHandler = jQuery('<div class="pagelayer-resize-handler"><div class="pagelayer-resize-icon"></div></div>');
635
636 if( wrap.is(":last-child") ){
637 wrap = wrap.prev();
638 }
639
640 var pResize = wrap.children('.pagelayer-ele-overlay').find('.pagelayer-resize-handler');
641
642 if(pResize.length > 0){
643 return;
644 }
645
646 // Append it
647 wrap.children('.pagelayer-ele-overlay').append(rHandler);
648
649 // Resize start
650 rHandler.on('mousedown', function(e) {
651 e.preventDefault();
652
653 var next_ele = wrap.next();
654 var rHolder_width = wrap.closest('.pagelayer-row-holder').width();
655 var new_width, nEle_new_width;
656
657 // Original width
658 var original_width = wrap.width();
659 var original_mouse_x = e.pageX;
660
661 // Add the element width and next element width
662 both_width = (original_width / rHolder_width *100) + (next_ele.width() / rHolder_width *100);
663
664 if(both_width > 100){
665 return false;
666 }
667
668 jQuery('body').css({'cursor': 'ew-resize'});
669 rHandler.show();
670
671 var r_mousemove = function(e){
672 var width = original_width + (e.pageX - original_mouse_x);
673
674 // Covert width in percentage
675 new_width = (width / rHolder_width *100).toFixed(2);
676
677 if(both_width > new_width && new_width > 0){
678 nEle_new_width = (both_width - new_width).toFixed(2);
679 wrap.css({'width': new_width+'%'});
680 next_ele.css({'width': nEle_new_width+'%'});
681
682 rHandler.attr({'pre-width': new_width+'%', 'next-width': nEle_new_width+'%'});
683 }
684
685 };
686
687 var r_mouseup = function(e){
688
689 jQuery(document).off('mousemove', r_mousemove);
690 jQuery('body').css({'cursor': ''});
691 rHandler.removeAttr('style pre-width next-width');
692
693 // find real element and next real element
694 var jEle = wrap.find('>.pagelayer-ele');
695 var nEle = next_ele.find('>.pagelayer-ele');
696
697 // Set the element attrs
698 jEle.attr({'pagelayer-a-col_width': new_width, 'pagelayer-a-col': ''});
699 nEle.attr({'pagelayer-a-col_width': nEle_new_width, 'pagelayer-a-col': ''});
700 jQuery(document).off('mouseup', r_mouseup);
701
702 };
703
704 // Resize start
705 jQuery(document).on('mousemove', r_mousemove);
706 jQuery(document).on('mouseup', r_mouseup);
707 });
708 }
709
710 // Handle addition of elements from the left
711 // NOTE : At this point the addition is FINALIZED
712 // The add element cannot be prevented !
713 function pagelayer_onadd(jEle, toClick){
714
715 toClick = arguments.length == 2 ? toClick : true;
716
717 //console.log(jEle);
718 var id = pagelayer_element_added(jEle);
719 var jEle = jQuery("[pagelayer-id="+id+"]");
720
721 if(toClick){
722 //console.log('here');
723 jEle.click();
724 }
725
726 return id;
727
728 };
729
730 // Add an element into the POST
731 function pagelayer_element_added(jEle){
732
733 var sc = jEle.attr('pagelayer-tag');
734 var id, par_id;
735
736 // Set Pagelayer History FALSE to prevent saving attributes in action history
737 pagelayer.history_action = false;
738
739 // Generate the HTML
740 html = pagelayer_create_sc(sc);
741 id = pagelayer_assign_id(html);
742 par_id = id;
743
744 // Insert the HTML
745 jEle[0].outerHTML = html[0].outerHTML;
746
747 // Setup the properties of the elements
748 pagelayer_element_setup("[pagelayer-id="+par_id+"], [pagelayer-id="+par_id+"] .pagelayer-ele", true);
749
750 // Any children to add ?
751 if(!('widget' in pagelayer_shortcodes[sc])){
752
753 // The element props
754 var props = pagelayer_shortcodes[sc];
755
756 // Do we have to create children ?
757 if('has_group' in props){
758
759 var has_group = props['has_group'];
760 var gProp = props[has_group['section']][has_group['prop']];
761
762 for(var i=0; i < gProp['count']; i++){
763 var cid = pagelayer_element_add_child(jQuery("[pagelayer-id="+id+"]"), gProp['sc']);
764 //pagelayer_element_setup('[pagelayer-id='+cid+']', true);
765 }
766
767 }
768
769 }
770
771 // Save in action history
772 var cEle = pagelayer_near_by_ele(id, sc);
773
774 pagelayer_history_action_push({
775 'title' : pagelayer_shortcodes[sc]['name'],
776 'action' : 'Added',
777 'pl_id' : id,
778 'html' : jQuery("[pagelayer-id="+id+"]"),
779 'cEle' : cEle
780 });
781
782 // Set pagelayer history TRUE
783 pagelayer.history_action = true;
784
785 return id;
786
787 };
788
789 // Add an element
790 function pagelayer_element_add_child(pEle, sc){
791 var child = pagelayer_create_sc(sc);
792 var cid = pagelayer_assign_id(child);
793 pagelayer_set_parent(child, pagelayer_assign_id(pEle));
794
795 // Does the parent have a holder ?
796 var tag = pagelayer_tag(pEle);
797
798 // There is a holder
799 if('holder' in pagelayer_shortcodes[tag]){
800
801 pEle.find(pagelayer_shortcodes[tag]['holder']).append(child);
802
803 // No holder, just append
804 }else{
805 pEle.append(child);
806 }
807
808 pagelayer_element_setup('[pagelayer-id='+cid+']', true);
809
810 // Do we have to create children ?
811 if('has_group' in pagelayer_shortcodes[sc]){
812
813 var has_group = pagelayer_shortcodes[sc]['has_group'];
814 var gProp = pagelayer_shortcodes[sc][has_group['section']][has_group['prop']];
815
816 for(var i=0; i < gProp['count']; i++){
817 var in_cid = pagelayer_element_add_child(jQuery("[pagelayer-id="+cid+"]"), gProp['sc']);
818 }
819
820 }
821
822 return cid;
823 };
824
825 // Return an element by ID
826 function pagelayer_ele_by_id(id){
827 return jQuery('[pagelayer-id='+id+']');
828 };
829
830 // Return the wrap by ID
831 function pagelayer_wrap_by_id(id){
832 return jQuery('[pagelayer-wrap-id='+id+']');
833 };
834
835 // Give the Pagelayer ID
836 function pagelayer_id(jEle){
837
838 var id = jEle.attr('pagelayer-wrap-id');
839 if(id){
840 return id;
841 }
842
843 id = jEle.attr('pagelayer-id');
844
845 return id;
846
847 }
848
849 // Assign the jQuery object an ID
850 function pagelayer_assign_id(jEle){
851
852 // Do you have the pagelayer id
853 var id = jEle.attr("pagelayer-id");
854 if(!id || id.length < 1){
855 id = pagelayer_randstr(16);
856 jEle.attr("pagelayer-id", id);
857 }
858
859 return id;
860
861 }
862
863 // Show the edit options
864 function pagelayer_element_clicked(selector, e){
865
866 var jEle = jQuery(selector);
867 e = e || false;
868 //console.log(e);
869
870 // You must be a element atleast
871 if(!jEle.hasClass('pagelayer-ele')){
872 return false;
873 }
874
875 // Get the parent
876 var pId = pagelayer_get_parent(jEle);
877
878 // If we found a parent
879 if(pId){
880 jEle = pagelayer_ele_by_id(pId);
881 }
882
883 // Make the editable fields active
884 //pagelayer_clear_editable();// First clear
885 jEle.find('[pagelayer-editable]').each(function (){
886 pagelayer_make_editable(jQuery(this), e);
887 });
888
889 // Lets not rebuild everything to make it faster
890 if(pagelayer_is_active(jEle)){
891 return false;
892 }
893
894 // Set this as the active element
895 pagelayer_set_active(jEle);
896
897 // Show the properties
898 pagelayer_elpd_open(jEle);
899
900 }
901
902 // The edit option
903 function pagelayer_edit_element(selector){
904 pagelayer_element_clicked(selector);
905 }
906
907 // Setup the properties on a single click
908 function pagelayer_element_setup(selector, render){
909
910 var selector = selector || ".pagelayer-ele";
911 render = render || false;
912
913 // Loop through
914 jQuery(pagelayer_editable+' '+selector).each(function(){
915
916 var jEle = jQuery(this);
917
918 // Assign an ID if not there
919 var id = pagelayer_assign_id(jEle);
920 var pId = pagelayer_get_parent(jEle) || '';// Options to show on hover
921 var selector = '[pagelayer-id='+id+']';
922
923 if(render){
924 pagelayer_sc_render(jEle);
925 }
926
927 // Get the tag
928 var tag = pagelayer_tag(jEle);
929
930 // Lets check if we are the child of a parent i.e. element of a group
931 if(pagelayer_empty(pId)){
932
933 // Get the parent
934 var pEle = jEle.parent().closest('.pagelayer-ele');
935
936 // If we found a parent
937 if(pEle.length > 0){
938
939 var pTag = pagelayer_tag(pEle);
940
941 // Is the parent a group of this child ?
942 if(!pagelayer_empty(pagelayer_shortcodes[pTag]) && pagelayer_is_group(pTag)){
943
944 var has_group = pagelayer_shortcodes[pTag]['has_group'];
945 var child_type = pagelayer_shortcodes[pTag][has_group['section']][has_group['prop']]['sc'];
946
947 // If the type is the same as jEle
948 if(child_type == pagelayer_tag(jEle)){
949 pId = pagelayer_assign_id(pEle);
950 pagelayer_set_parent(jEle, pId);
951 }
952 }
953
954 }
955
956 }
957
958 // Make the wraps
959 jEle.wrap('<div class="pagelayer-ele-wrap" pagelayer-wrap-id="'+id+'"></div>');
960 var wrap = jEle.parent();
961
962 // For column we have to do some kidas !
963 if(tag == 'pl_col'){
964
965 var col;
966 for(var x=1; x<=12; x++){
967 if(jEle.hasClass('pagelayer-col-'+x)){
968 col = 'pagelayer-col-'+x;
969 break;
970 }
971 }
972
973 var is_custom_width = pagelayer_get_att(jEle, 'col');
974 var col_width = pagelayer_get_att(jEle, 'col_width');
975 if(pagelayer_empty(is_custom_width) && col_width){
976 wrap.css('width', col_width+'%');
977 }
978
979 wrap.addClass('pagelayer-col '+col);
980 //jEle.removeClass('pagelayer-col '+col);
981 wrap.addClass('pagelayer-wrap-col');
982
983 }else if(tag == 'pl_row'){
984 wrap.addClass('pagelayer-wrap-row');
985 }else if(tag == 'pl_inner_row'){
986 wrap.addClass('pagelayer-wrap-inner-row');
987 }else{
988 wrap.addClass('pagelayer-wrap-ele');
989 }
990
991 // Create the overlay
992 wrap.prepend('<div class="pagelayer-ele-overlay"></div>');
993
994 var overlay = wrap.children('.pagelayer-ele-overlay');
995 var html;
996
997 if(tag == 'pl_row' || tag == 'pl_inner_row'){
998
999 overlay.addClass('pagelayer-row-hover');
1000
1001 if(jEle.hasClass('pagelayer-row-stretch-full')){
1002 pagelayer_sc_render(jEle);
1003 }
1004
1005 html = '<div class="pagelayer-row-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
1006 '<i class="fa fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" />'+
1007 '<i class="fa fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" />'+
1008 '<i class="fa fa-pencil pagelayer-eoi" onclick="pagelayer_edit_element(\''+selector+'\', event)" />'+
1009 '</div>';
1010
1011 }else if(tag == 'pl_col'){
1012
1013 overlay.addClass('pagelayer-col-hover');
1014
1015 html = '<div class="pagelayer-col-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
1016 '<i class="fa fa-columns pagelayer-eoi" onclick="pagelayer_edit_element(\''+selector+'\', event)" />'+
1017 '</div>';
1018
1019 // Is it an empty col ?
1020 pagelayer_empty_col(jEle.children('.pagelayer-col-holder'));
1021
1022 // Make col resizable
1023 pagelayer_col_make_resizable(wrap);
1024
1025 }else{
1026
1027 html = '<div class="pagelayer-ele-option" pagelayer-option-edit pagelayer-option-id="'+id+'">'+
1028 '<i class="fa fa-clone pagelayer-eoi" onclick="pagelayer_copy_element(\''+selector+'\')" />'+
1029 '<i class="fa fa-trash pagelayer-eoi" onclick="pagelayer_delete_element(\''+selector+'\')" />'+
1030 '<i class="fa fa-pencil pagelayer-eoi" onclick="pagelayer_edit_element(\''+selector+'\', event)" />'+
1031 '</div>';
1032
1033 }
1034
1035 // Append to the child
1036 overlay.append(html);
1037 jQuery('[pagelayer-option-id='+id+']').hide();
1038
1039 // Setup the HOVER events ABD create WRAPS IF we dont have a parent
1040 if(pId.length > 0){
1041 return;
1042 }
1043
1044 // Make the wrap draggable, but only of independent or parent elements
1045 wrap.attr('draggable', 'true');
1046
1047 wrap.hover(function(){
1048
1049 // Is there an element option shower ?
1050 var opts = jQuery('[pagelayer-option-id='+id+']');
1051
1052 // Give the overlay the hover class
1053 opts.parent().addClass('pagelayer-ele-hover');
1054
1055 // Show them
1056 opts.show();
1057
1058 }, function(){
1059
1060 // Is there an element option shower ?
1061 var opts = jQuery('[pagelayer-option-id='+id+']');
1062
1063 // Remove hover class
1064 opts.parent().removeClass('pagelayer-ele-hover');
1065
1066 // Hide opts
1067 opts.hide();
1068
1069 });
1070
1071 });
1072 }
1073
1074 // Left Click
1075 function pagelayer_left_click(){
1076
1077 jQuery(pagelayer_editable).on('click', function(e){
1078
1079 e.preventDefault();// Added by Jivan in Actions / Revisions version
1080
1081 // Hide the context menu
1082 jQuery('.pagelayer-right-click-options').hide();
1083
1084 // Target
1085 var tEle = jQuery(e.target);
1086
1087 // If its an edit option click
1088 if(tEle.hasClass('pagelayer-eoi')){
1089 return false;
1090 }
1091
1092 pagelayer_element_clicked(tEle.closest('.pagelayer-ele'), e);
1093
1094 return false;
1095
1096 });
1097 };
1098
1099 // Right Click Menu
1100 function pagelayer_right_click(){
1101
1102 var html = '<div class="pagelayer-right-click-options" style="display:none;">'+
1103 '<ul>'+
1104 '<li><a class="pagelayer-right-edit">Edit</a></li>'+
1105 '<li><a class="pagelayer-right-duplicate"><i class="fa fa-clone" /> Duplicate</a></li>'+
1106 '<li><a class="pagelayer-right-copy"><i class="fa fa-files-o" /> Copy</a></li>'+
1107 '<li><a class="pagelayer-right-paste"><i class="fa fa-clipboard" /> Paste</a></li>'+
1108 '<li><a class="pagelayer-right-delete"><i class="fa fa-trash-o" /> Delete</a></li>'+
1109 '</ul>'+
1110 '</div>';
1111
1112 jQuery('body').append(html);
1113
1114 var $contextMenu = jQuery('.pagelayer-right-click-options');
1115
1116 jQuery(pagelayer_editable).on('contextmenu', function(e){
1117
1118 var tEle = jQuery(e.target);
1119 var jEle = tEle.closest('.pagelayer-ele-wrap').children('.pagelayer-ele');
1120
1121 // Get the parent
1122 var pId = pagelayer_get_parent(jEle);
1123
1124 // If we found a parent
1125 if(pId){
1126 jEle = pagelayer_ele_by_id(pId);
1127 }
1128
1129 // The basics
1130 var id = pagelayer_assign_id(jEle);
1131 var tag = pagelayer_tag(jEle);
1132
1133 $contextMenu.find('.pagelayer-right-edit').attr('onclick', 'pagelayer_edit_element("[pagelayer-id='+id+']")').html('<i class="fa fa-pencil-square-o" /> Edit '+pagelayer_shortcodes[tag]['name']);
1134 $contextMenu.find('.pagelayer-right-duplicate').attr('onclick', 'pagelayer_copy_element("[pagelayer-id='+id+']")');
1135 $contextMenu.find('.pagelayer-right-copy').attr('onclick', 'pagelayer_copy_select("[pagelayer-id='+id+']")');
1136 $contextMenu.find('.pagelayer-right-paste').attr('onclick', 'pagelayer_paste_element("[pagelayer-id='+id+']")');
1137 $contextMenu.find('.pagelayer-right-delete').attr('onclick', 'pagelayer_delete_element("[pagelayer-id='+id+']")');
1138
1139 // Are we to hide the paste ?
1140 if(!pagelayer_empty(pagelayer.copy_selected) && pagelayer_can_copy_to(jEle)){
1141 //console.log(pagelayer_can_copy_to(jEle));
1142 $contextMenu.find('.pagelayer-right-paste').parent().show();
1143 }else{
1144 $contextMenu.find('.pagelayer-right-paste').parent().hide();
1145 }
1146
1147 $contextMenu.css({
1148 display: "block",
1149 left: e.pageX,
1150 top: e.pageY
1151 });
1152
1153 return false;
1154
1155 });
1156
1157 jQuery('html').on('click', function(e){
1158 $contextMenu.hide();
1159 });
1160 }
1161
1162 // Set the parent for the group
1163 function pagelayer_set_parent(jEle, id){
1164 jEle.attr('pagelayer-parent', id);
1165 };
1166
1167 // Set the parent for the group
1168 function pagelayer_get_parent(jEle){
1169 return jEle.attr('pagelayer-parent');
1170 };
1171
1172 // Sets the screen mode
1173 function pagelayer_set_screen_mode(mode){
1174 var modes = ['desktop', 'tablet', 'mobile'];
1175 var body = pagelayer.$$('.pagelayer-iframe-holder iframe');
1176 var current = '';
1177
1178 for(var x in modes){
1179
1180 if(body.hasClass('pagelayer-screen-'+modes[x]) && modes[x] != mode){
1181 current = modes[x];
1182 body.removeClass('pagelayer-screen-'+modes[x]);
1183 }
1184 }
1185
1186 // Add the class
1187 body.addClass('pagelayer-screen-'+mode);
1188
1189 // Add the class to the button
1190 pagelayer.$$('.pagelayer-mode-button').removeClass('fa-'+current).addClass('fa-'+mode);
1191
1192 // Add the class to the button
1193 pagelayer.$$('.pagelayer-prop-screen').removeClass('fa-'+current).addClass('fa-'+mode);
1194
1195 // Trigger screen change if any
1196 pagelayer.$$('.pagelayer-elp-screen').trigger('pagelayer-screen-changed');
1197
1198 };
1199
1200 // Get the current screen mode
1201 function pagelayer_get_screen_mode(){
1202 var modes = ['desktop', 'tablet', 'mobile'];
1203 var body = pagelayer.$$('.pagelayer-iframe-holder iframe');
1204
1205 for(var x in modes){
1206 if(body.hasClass('pagelayer-screen-'+modes[x])){
1207 return modes[x];
1208 }
1209 }
1210 }
1211
1212 // Handle key press events
1213 jQuery(document).keydown(function(event){
1214 //alert(String.fromCharCode(event.which));
1215
1216 // Delete
1217 if(event.keyCode == 46){
1218 pagelayer_delete_element('[pagelayer-active]');
1219 }
1220
1221 // ctrl+z handle
1222 if(event.keyCode == 90 && event.ctrlKey){
1223 pagelayer_do_history('undo');
1224 }
1225
1226 // ctrl+y handle
1227 if(event.keyCode == 89 && event.ctrlKey){
1228 pagelayer_do_history('redo');
1229 }
1230 });
1231
1232 // Handle Copy of content
1233 jQuery(document).on('copy', function(copyEvent){
1234
1235 // Check the active element
1236 if(pagelayer_active.el && pagelayer_active.el.id){
1237
1238 copyEvent.preventDefault();
1239
1240 var eHtml = jQuery("[pagelayer-id='"+pagelayer_active.el.id+"']")[0].outerHTML;
1241
1242 // We need to do Empty clipboard
1243 (copyEvent.originalEvent || copyEvent).clipboardData.setData('pagelayer_ele', eHtml);
1244
1245 // Save the active element id
1246 //pagelayer_copy_select("[pagelayer-id='"+pagelayer_active.el.id+"']");
1247
1248 }
1249
1250 });
1251
1252 // Handle Paste in the editor
1253 jQuery(document).on('paste', function(pasteEvent){
1254
1255 var pEle_target = jQuery((pasteEvent.originalEvent || pasteEvent).target);
1256 var pagelayer_ajax_func = {};
1257 var contenteditable = false;
1258
1259 if(pEle_target.closest('[contenteditable]').length > 0){
1260 pEle_target = pEle_target.closest('[contenteditable]');
1261 contenteditable = true;
1262 }
1263
1264 // This function for ajax before send call back
1265 pagelayer_ajax_func['beforeSend'] = function(xhr){
1266
1267 // If target is not content editable
1268 if( pagelayer_empty(contenteditable) ){
1269
1270 // If we dont have an active element then return false and stop ajax
1271 if( !(pagelayer_active.el && pagelayer_active.el.id) ){
1272 return false;
1273 }
1274
1275 pagelayer.copy_selected = jQuery('<div pagelayer-tag="pl_image"></div>');
1276
1277 // Is it to be pastable
1278 if(!pagelayer_can_copy_to('[pagelayer-id="'+pagelayer_active.el.id+'"]')){
1279 pagelayer.copy_selected = '';
1280 return false;
1281 }
1282 }
1283
1284 pEle_target.css({'opacity': '0.33' , 'transition' : '0.1s'});
1285 }
1286
1287 // This function for ajax success call back
1288 pagelayer_ajax_func['success'] = function(obj){
1289
1290 // Successfully Uploaded
1291 if(obj['success']){
1292
1293 // For content editable e.g. Rich Text
1294 if( !pagelayer_empty(contenteditable) ){
1295 document.execCommand('insertImage', false, obj['data']['url']);
1296
1297 // For our widgets
1298 }else{
1299 var fTo = pagelayer_can_copy_to('[pagelayer-id="'+pagelayer_active.el.id+'"]');
1300 // We need to empty pagelayer.copy_selected
1301 pagelayer.copy_selected = '';
1302
1303 // Create image html
1304 var html = jQuery( pagelayer_create_sc('pl_image') );
1305 html.attr('pagelayer-a-id', obj['data']['id']);
1306 html.attr('pagelayer-tmp-id-url', obj['data']['url']);
1307
1308 // Copy the element
1309 var id = pagelayer_copy_element(html, fTo);
1310 jQuery('[pagelayer-id="'+id+'"]').click();
1311 }
1312
1313 // Some error occured
1314 }else{
1315 alert(obj['data']['message']);
1316 }
1317 }
1318
1319 // This function for ajax complete call back
1320 pagelayer_ajax_func['complete'] = function(xhr){
1321 //console.log(xhr);
1322 pEle_target.css({'opacity': '1' , 'transition' : '0.1s'});
1323 }
1324
1325 var findImg = pagelayer_editable_paste_handler(pasteEvent, pagelayer_ajax_func);
1326
1327 if(pagelayer_empty(findImg)){
1328
1329 // Check the active element
1330 if(pagelayer_active.el && pagelayer_active.el.id){
1331
1332 var jEle = jQuery("[pagelayer-id='"+pagelayer_active.el.id+"']");
1333
1334 var copy_ele = jQuery((pasteEvent.originalEvent || pasteEvent).clipboardData.getData('pagelayer_ele'));
1335
1336 // Check if the any element is copied
1337 if(copy_ele.length > 0 && pagelayer_can_copy_to(jEle)){
1338 pagelayer.copy_selected = copy_ele;
1339 pagelayer_paste_element("[pagelayer-id='"+pagelayer_active.el.id+"']");
1340 }
1341
1342 }
1343 }
1344 });
1345
1346 // Delete an element as per the selector
1347 function pagelayer_delete_element(selector){
1348 var jEle = jQuery(selector);
1349
1350 // Anything found ?
1351 if(jEle.length > 0){
1352
1353 var id = pagelayer_assign_id(jEle);
1354 var sc = pagelayer_tag(jEle);
1355
1356 // Is there a wrap
1357 var wrap = jQuery('[pagelayer-wrap-id="'+id+'"]');
1358
1359 var par = wrap.parent();
1360
1361 // Save this element in history action
1362 if(pagelayer.history_action){
1363 var cEle = pagelayer_near_by_ele(id, sc);
1364
1365 // To save in history, we need to save only element not the wraps as we call setup if we redo or undo
1366 jEle.find('style').remove();
1367 jEle.find('.pagelayer-ele-overlay').remove();
1368
1369 // Unwrap the wraps
1370 jEle.find('.pagelayer-ele').each(function (){
1371 var ele = jQuery(this);
1372 if(ele.parent().is('.pagelayer-ele-wrap')){
1373 ele.unwrap();
1374 }
1375 });
1376
1377 pagelayer_history_action_push({
1378 'title' : pagelayer_shortcodes[sc]['name'],
1379 'action' : 'Deleted',
1380 'pl_id' : id,
1381 'html' : jEle,
1382 'cEle' : cEle
1383 });
1384 }
1385
1386 wrap.remove();
1387
1388 pagelayer_empty_col(par);
1389
1390 if(pagelayer_active.el && pagelayer_active.el.id == id){
1391 pagelayer.$$('.pagelayer-elpd-close').click();
1392 }
1393
1394 }
1395
1396 pagelayer_isDirty = true;
1397 };
1398
1399 // Select an element
1400 function pagelayer_copy_select(selector){
1401 pagelayer.copy_selected = selector;
1402 }
1403
1404 function pagelayer_can_copy_to(to){
1405 var jEle = jQuery(pagelayer.copy_selected);
1406 var tEle = jQuery(to);
1407
1408 var eTag = pagelayer_tag(jEle);
1409 var tTag = pagelayer_tag(tEle);
1410 //console.log(eTag+' - '+tTag);
1411 // Final to
1412 var fTo;
1413
1414 // Selected element is a Row, can go only after a row
1415 if(eTag == 'pl_row'){
1416 fTo = tEle.closest('.pagelayer-ele.pagelayer-row');
1417 if(fTo.length != 1) return false;
1418 return fTo;
1419 }
1420
1421 // Selected element is a Column, can go only after a col
1422 if(eTag == 'pl_col'){
1423 fTo = tEle.closest('.pagelayer-ele.pagelayer-col');
1424 if(fTo.length != 1) return false;
1425 return fTo;
1426 }
1427
1428 // Is the TARGET a row or column when the selected item is a element
1429 if(tTag == 'pl_row' || tTag == 'pl_col'){
1430 return false;
1431 }
1432
1433 return tEle;
1434
1435 }
1436
1437 // Select an element
1438 function pagelayer_paste_element(to){
1439
1440 var fTo = pagelayer_can_copy_to(to);
1441
1442 // Is it a valid to
1443 if(!fTo){
1444 return false;
1445 }
1446
1447 pagelayer_copy_element(pagelayer.copy_selected, fTo);
1448 }
1449
1450 // Copy an element
1451 // Note : insertAfter should always be an pagelayer-ele
1452 function pagelayer_copy_element(selector, insertAfter){
1453 var src = jQuery(selector);
1454 var html = src[0].outerHTML;
1455 var tag = pagelayer_tag(src);
1456 insertAfter = insertAfter || src;
1457 insertAfter = insertAfter.parent();
1458
1459 var jEle = jQuery(html);
1460 jEle.removeAttr('pagelayer-id');
1461 jEle.find('[pagelayer-id]').removeAttr('pagelayer-id');
1462 jEle.find('[pagelayer-parent]').removeAttr('pagelayer-parent');// Remove the parent attribute as it will be reset during pagelayer_element_setup
1463 jEle.find('style').remove();
1464 jEle.find('.pagelayer-ele-overlay').remove();
1465
1466 // Unwrap the wraps
1467 jEle.find('.pagelayer-ele').each(function (){
1468 var ele = jQuery(this);
1469 if(ele.parent().is('.pagelayer-ele-wrap')){
1470 ele.unwrap();
1471 }
1472 });
1473
1474 // Give it an ID
1475 var id = pagelayer_assign_id(jEle);
1476
1477 jQuery(insertAfter).after(jEle);
1478
1479 pagelayer_element_setup('[pagelayer-id='+id+'], [pagelayer-id='+id+'] .pagelayer-ele', true);
1480
1481 // Save this element in history action
1482 if(pagelayer.history_action){
1483 var cEle = pagelayer_near_by_ele(id, tag);
1484 pagelayer_history_action_push({
1485 'title' : pagelayer_shortcodes[tag]['name'],
1486 'action' : 'Copied',
1487 'pl_id' : id,
1488 'html' : jEle,
1489 'cEle' : cEle
1490 });
1491 }
1492
1493 //If column then renumber columns
1494 if(tag == 'pl_col'){
1495 var row = src.parent().closest('.pagelayer-row');
1496 pagelayer_renumber_col(row);
1497 }
1498
1499 pagelayer_isDirty = true;
1500
1501 return id;
1502 };
1503
1504 // Language key
1505 function pagelayer_l(k){
1506 return k;
1507 }
1508
1509 // Set the given jELE as active
1510 function pagelayer_set_active(jEle){
1511
1512 // Make all other element as inactive
1513 jQuery('[pagelayer-active]').each(function(){
1514 var $j = jQuery(this);
1515 $j.removeAttr('pagelayer-active');
1516 });
1517
1518 jEle.attr('pagelayer-active', 1);
1519
1520 // Add and remove the class
1521 jQuery('.pagelayer-active').removeClass('pagelayer-active');
1522
1523 jEle.parent().children('.pagelayer-ele-overlay').addClass('pagelayer-active');
1524
1525 }
1526
1527 function pagelayer_sc(sc){
1528 return sc.replace('pl_', '');
1529 };
1530
1531 // Create a HTML dom element of the Short code
1532 // Return the jEle
1533 function pagelayer_create_sc(sc){
1534
1535 var html;
1536 var _sc = pagelayer_sc(sc);
1537 var func = window['pagelayer_sc_'+sc];
1538
1539 // Generate the HTML
1540 if(typeof func == 'function'){
1541 html = window['pagelayer_sc_'+sc]();
1542 }else{
1543 html = '<div '+pagelayer_sc_atts('pagelayer-'+_sc)+'></div>';
1544 }
1545
1546 html = jQuery(html);
1547
1548 // Add the tag
1549 html.attr('pagelayer-tag', sc);
1550
1551 // Give it an ID
1552 id = pagelayer_assign_id(html);
1553
1554 // Try to set the default values over 5 loops
1555 pagelayer_set_default_atts(html, 5);
1556
1557 return html;
1558
1559 };
1560
1561 // Returns a list of default attributes to set as per the current selection
1562 function pagelayer_set_default_atts(jEle, set){
1563
1564 set = set || 0;
1565 var hasSet = false;
1566
1567 for(var i = 1; i <= set;i++){
1568
1569 //console.log('[pagelayer_set_default_atts] Loop :'+i);
1570 //console.log(jEle);
1571
1572 // Get existing data
1573 var el = pagelayer_data(jEle, true);
1574
1575 // If it is the last loop and we are greater than 1
1576 if(i > 1 && i == set){
1577 console.log('[pagelayer_default_atts] Still vars to set. Please check your shortcode params !');
1578 }
1579
1580 // We are supposed to set !
1581 if('set' in el && !pagelayer_empty(el.set)){
1582 pagelayer_set_atts(jEle, el.set);
1583 hasSet = true;
1584 }else{
1585 break;
1586 }
1587 }
1588
1589 return hasSet;
1590 }
1591
1592 // Returns the tag
1593 function pagelayer_tag(jEle){
1594
1595 // It could be the wrap
1596 if(jEle.hasClass('pagelayer-ele-wrap')){
1597 return jEle.children('.pagelayer-ele').attr('pagelayer-tag');
1598 }
1599
1600 // It could be the row or col holder
1601 if(jEle.hasClass('pagelayer-row-holder') || jEle.hasClass('pagelayer-col-holder')){
1602 return jEle.parent().attr('pagelayer-tag');
1603 }
1604
1605 return jEle.attr('pagelayer-tag');
1606 }
1607
1608 // Gets a single attribute value
1609 function pagelayer_get_att(jEle, att){
1610 return jEle.attr('pagelayer-a-'+att);
1611 };
1612
1613 // Gets a single attribute value
1614 function pagelayer_get_tmp_att(jEle, att){
1615 return jEle.attr('pagelayer-tmp-'+att);
1616 };
1617
1618 // This function will just set atts and not do anything else
1619 // Atts can be string or object. If its string, then val is needed
1620 function pagelayer_set_atts(jEle, atts, val){
1621
1622 if(typeof atts == 'string'){
1623 var tmp = {};
1624 tmp[atts] = val;
1625 atts = tmp;
1626 }
1627
1628 if(typeof atts != 'object'){
1629 return false;
1630 }
1631
1632 var tag = pagelayer_tag(jEle);
1633 var trigger_onchange = 0;
1634
1635 if(pagelayer_empty(tag)){
1636 console.log('Set atts found no tag');
1637 console.log(jEle);
1638 return;
1639 }
1640
1641 // All props
1642 var all_props = pagelayer_shortcodes[tag];//console.log(tag);console.log(jEle);
1643 var trigger_props = {};
1644 var no_val = {};
1645 var defaults = {};
1646
1647 // Loop through all props
1648 for(var i in pagelayer_tabs){
1649
1650 var tab = pagelayer_tabs[i];
1651
1652 for(var section in all_props[tab]){
1653
1654 var props = section in pagelayer_shortcodes[tag] ? pagelayer_shortcodes[tag][section] : pagelayer_styles[section];
1655
1656 for(var x in props){
1657
1658 if('default' in props[x]){
1659 defaults[x] = 1;
1660 }
1661
1662 // Dont set any val, but we set temp value
1663 if('no_val' in props[x]){
1664 no_val[x] = 1;
1665 }
1666
1667 if('req' in props[x] || 'show' in props[x]){
1668 var show = 'req' in props[x] ? props[x]['req'] : props[x]['show'];
1669 for(var showParam in show){
1670 var val = show[showParam];
1671 var except = showParam.substr(0, 1) == '!' ? true : false;
1672 showParam = except ? showParam.substr(1) : showParam;
1673 trigger_props[showParam] = 1;
1674 }
1675
1676 }
1677
1678 }
1679
1680 }
1681
1682 }
1683
1684 for(var x in atts){
1685
1686 // Are we to trigger change
1687 if(x in trigger_props){
1688 trigger_onchange = 1;
1689 }
1690
1691 //console.log(x+'-'+atts[x]);
1692
1693 if(x in no_val){
1694 pagelayer_set_tmp_atts(jEle, x, atts[x]);
1695 continue;
1696 }
1697
1698 // Record History
1699 if(pagelayer.history_action){
1700 var attr_label = '';
1701 for(var section in all_props){
1702 for(var props in all_props[section]){
1703 if(props == x){
1704 attr_label = all_props[section][props]['label'];
1705 }
1706 }
1707
1708 }
1709
1710 var old_val = pagelayer_get_att(jEle, x) || '';
1711 pagelayer_history_action_push({
1712 'title' : all_props['name'],
1713 'subTitle' : attr_label,
1714 'action' : 'Edited',
1715 'attrType' : 'a_attr',
1716 'pl_id' : pagelayer_id(jEle),
1717 'atts' : x,
1718 'oldVal' : old_val,
1719 'newVal' : atts[x]
1720 });
1721 }
1722
1723 // Remove the attribute if its BLANK and there is no default for it
1724 // If there is a default, we set it to blank to keep record of the current val
1725 if(atts[x].length < 1){
1726
1727 // Dont remove the value as there is a default
1728 if(!(x in defaults)){
1729 jEle.removeAttr('pagelayer-a-'+x);
1730 // Otherwise blank it
1731 }else{
1732 jEle.attr('pagelayer-a-'+x, atts[x]);
1733 }
1734
1735 // Remove the tmp atts anyway
1736 var to_del = new Array();
1737 var regexp = new RegExp('pagelayer\-tmp\-'+x, 'gi');
1738
1739 jQuery.each(jEle[0].attributes, function(index, att){
1740 if(!att) return;
1741 if(att.name.match(regexp)){
1742 to_del.push(att.name);
1743 }
1744 });
1745
1746 //console.log(to_del);
1747 for(var n in to_del){
1748 jEle.removeAttr(to_del[n]);
1749 }
1750
1751 // Set the value
1752 }else{
1753 jEle.attr('pagelayer-a-'+x, atts[x]);
1754 }
1755
1756 // Are you the active element
1757 if(pagelayer_is_active(jEle)){
1758
1759 // TODO : Record Undo and Redo
1760
1761 }
1762
1763 }
1764
1765 // Trigger the change of the parameter and show the required properties
1766 if(trigger_onchange){
1767 pagelayer_elpd_show_rows();
1768 }
1769
1770 pagelayer_isDirty = true;
1771 };
1772
1773 // This function will just set atts and not do anything else
1774 // Atts can be string or object. If its string, then val is needed
1775 function pagelayer_set_tmp_atts(jEle, atts, val){
1776
1777 if(typeof atts == 'string'){
1778 var tmp = {};
1779 tmp[atts] = val;
1780 atts = tmp;
1781 }
1782
1783 if(typeof atts != 'object'){
1784 return false;
1785 }
1786
1787 for(var x in atts){
1788
1789 // Record history
1790 if(pagelayer.history_action){
1791
1792 var old_val = pagelayer_get_tmp_att(jEle, x) || '';
1793 pagelayer_history_action_push({
1794 'title' : pagelayer_shortcodes[pagelayer_tag(jEle)]['name'],
1795 'subTitle' : x,
1796 'action' : 'Edited',
1797 'attrType' : 'tmp_attr',
1798 'pl_id' : pagelayer_id(jEle),
1799 'atts' : x,
1800 'oldVal' : old_val,
1801 'newVal' : atts[x]
1802 });
1803
1804 }
1805
1806 jEle.attr('pagelayer-tmp-'+x, atts[x]);
1807 }
1808
1809 };
1810
1811 // Set the att and classes of an HTML which is not yet created
1812 function pagelayer_sc_atts(classes, atts){
1813
1814 if(typeof atts != 'object'){
1815 atts = new Object();
1816 }
1817
1818 var r = new Array();
1819
1820 for(var x in atts){
1821 r.push('pagelayer-a-'+x+'="'+atts[x]+'"');
1822 }
1823
1824 return 'class="'+classes+' pagelayer-ele" '+r.join(' ');
1825 }
1826
1827 // Is the jEle the active element ?
1828 function pagelayer_is_active(jEle){
1829
1830 // Is this the active Element ?
1831 if(pagelayer_empty(pagelayer_active.el) || jEle.attr('pagelayer-id') != pagelayer_active.el.id){
1832 return false;
1833 }
1834
1835 return true;
1836
1837 };
1838
1839 // Removes {{}} from the variable name
1840 function pagelayer_var(val){
1841 return val.substring(2, (val.length - 2));
1842 }
1843
1844 // Take care of the CSS
1845 function pagelayer_css_render(css, val, seperator){
1846 //console.log('CSS '+css+' | '+val);
1847
1848 // Seperator
1849 seperator = seperator || ',';
1850
1851 // Replace the val
1852 css = css.split('{{val}}').join(val);
1853
1854 // If there is an array
1855 if(css.match(/val\[\d/)){
1856 val = val.split(seperator);
1857 for(var i in val){
1858 css = css.split('{{val['+i+']}}').join(val[i]);
1859 }
1860 }
1861
1862 //console.log('Final CSS '+css);
1863
1864 return css;
1865
1866 };
1867
1868 // Replace the variables
1869 function pagelayer_parse_vars(str, el){
1870
1871 for(var x in el.tmp){
1872 str = str.split('{{{'+x+'}}}').join(el.tmp[x]);
1873 }
1874
1875 for(var x in el.atts){
1876 str = str.split('{{'+x+'}}').join(el.atts[x]);
1877 }
1878
1879 return str;
1880 };
1881
1882 // Render the Element
1883 function pagelayer_sc_render(jEle){
1884
1885 // We render only the active element
1886 if(!pagelayer_is_active(jEle)){
1887 //return false;
1888 }
1889
1890 //console.log('Rendering');
1891
1892 // Handle the CSS part
1893 // Get the id, tag, atts, data, etc
1894 var el = pagelayer_data(jEle, true);
1895 var all_props = pagelayer_shortcodes[el.tag];
1896 var elCSS = {
1897 classes: [],
1898 remove_classes: [],
1899 attr: [],
1900 remove_attr: [],
1901 css: [],
1902 edit: [],
1903 sel: '[pagelayer-id="'+el.id+'"]'
1904 };
1905
1906 // Create a reference
1907 el.CSS = elCSS;
1908
1909 //console.log(el.atts);
1910
1911 for(var i in pagelayer_tabs){
1912 var tab = pagelayer_tabs[i];
1913 for(var section in all_props[tab]){ //console.log(tab+' '+section);
1914
1915 var props = section in pagelayer_shortcodes[el.tag] ? pagelayer_shortcodes[el.tag][section] : pagelayer_styles[section];//console.log(props);
1916
1917 // Loop the props
1918 for(var x in props){
1919
1920 // pagelayer_data will return attributes even if they are BLANK e.g. attr=""
1921 // Render doesnt consider BLANK values as values, and we are unsetting them now
1922 // If in any situation you need to consider blank values, please handle in the JS / PHP function of the Shortcode
1923 if(x in el.atts && el.atts[x].length < 1){
1924 delete el.atts[x];
1925 }
1926
1927 // Any editor ?
1928 if('edit' in props[x]){
1929 elCSS.edit.push({prop: x, sel: props[x]['edit']});
1930 }
1931
1932 // Do we have a addClass ?
1933 // We are checking before the element has a value so that we can add or remove the class
1934 if('addClass' in props[x]){
1935
1936 var addClasses;
1937
1938 // Convert the string to an array
1939 if(typeof props[x]['addClass'] === 'string'){
1940 addClasses = [props[x]['addClass']];
1941 }else{
1942 addClasses = props[x]['addClass'];
1943 }
1944
1945 for(var c in addClasses){
1946
1947 // The selector
1948 var tSel = jQuery.isNumeric(c) ? '' : c;
1949
1950 // If there is a VAL
1951 // NOTE : Only val is allowed when there is a list
1952 if(addClasses[c].match(/\{\{val\}\}/) && 'list' in props[x]){
1953
1954 for(var l in props[x]['list']){
1955
1956 var tmp = {'sel': tSel, 'val': addClasses[c].replace('{{val}}', l)};
1957
1958 if(el.atts[x] == l){
1959 elCSS['classes'].push(tmp);
1960 }else{
1961 elCSS['remove_classes'].push(tmp);
1962 }
1963
1964 }
1965
1966 }else{
1967
1968 var tmp = {'sel': tSel, 'val': addClasses[c]};
1969
1970 // If the value is there
1971 if(x in el.atts){
1972 elCSS['classes'].push(tmp);
1973 }else{
1974 elCSS['remove_classes'].push(tmp);
1975 }
1976
1977 }
1978 }
1979 }
1980
1981 // Do we have a addAttr ?
1982 // We are checking before the element has a value so that we can add or remove the attr
1983 if('addAttr' in props[x]){
1984
1985 var addAttr;
1986
1987 // Convert the string to an array
1988 if(typeof props[x]['addAttr'] === 'string'){
1989 addAttr = [props[x]['addAttr']];
1990 }else{
1991 addAttr = props[x]['addAttr'];
1992 }
1993
1994 for(var c in addAttr){
1995
1996 // The selector
1997 var tSel = jQuery.isNumeric(c) ? '' : c;
1998 var tmp = {'sel': tSel, 'val': addAttr[c]};
1999
2000 // If the value is there
2001 if(x in el.atts){
2002 elCSS['attr'].push(tmp);
2003 }else{
2004 elCSS['remove_attr'].push(tmp);
2005 }
2006 }
2007 }
2008
2009 // Do we have a CSS ?
2010 if('css' in props[x]){
2011
2012 var css;
2013
2014 // Convert the string to an array
2015 if(typeof props[x]['css'] === 'string'){
2016 css = [props[x]['css']];
2017 }else{
2018 css = props[x]['css'];
2019 }
2020
2021 // Screen modes
2022 var modes = {desktop: '', tablet: '_tablet', mobile: '_mobile'};
2023
2024 for(var m in modes){
2025
2026 var xm = x+modes[m];
2027
2028 // If the value is there
2029 if(!(xm in el.atts)){
2030 continue;
2031 }
2032
2033 for(var c in css){
2034
2035 // The selector
2036 var tSel = jQuery.isNumeric(c) ? '{{element}}' : c;
2037 var tmp = {
2038 sel: tSel,
2039 val: pagelayer_css_render(css[c], el.atts[xm], (props[x].sep || ',')),
2040 };
2041
2042 // Is this a tablet
2043 if(m == 'tablet'){
2044 tmp.sel = '@media (max-width: 768px) and (min-width: 361px){'+tmp.sel;
2045 tmp.val = tmp.val+'}';
2046 }
2047
2048 // Is this a mobile mode ?
2049 if(m == 'mobile'){
2050 tmp.sel = '@media (max-width: 360px){'+tmp.sel;
2051 tmp.val = tmp.val+'}';
2052 }
2053
2054 // Push to store
2055 elCSS.css.push(tmp);
2056 }
2057
2058 }
2059
2060 }
2061
2062 }
2063
2064 }
2065
2066 }
2067
2068 // If there is an HTML, then process it
2069 if('html' in pagelayer_shortcodes[el.tag]){
2070
2071 el.iHTML = jQuery('<div>'+pagelayer_shortcodes[el.tag]['html']+'</div>');
2072
2073 // Lets process the 'if-ext'
2074 el.iHTML.find('[if-ext]').each(function (){
2075 var $j = jQuery(this);
2076 var reqvar = pagelayer_var($j.attr('if-ext'));
2077 $j.removeAttr('if-ext');
2078
2079 // Is the element there ?
2080 if(!(reqvar in el.atts && !pagelayer_empty(el.atts[reqvar]))){
2081 //console.log('HERE');
2082 $j[0].outerHTML = $j.html();
2083 }
2084
2085 });
2086
2087 // Lets process the 'if'
2088 el.iHTML.find('[if]').each(function (){
2089 var $j = jQuery(this);
2090 var reqvar = pagelayer_var($j.attr('if'));
2091 $j.removeAttr('if');
2092
2093 // Is the element there ?
2094 if(!(reqvar in el.atts && !pagelayer_empty(el.atts[reqvar]))){
2095 //console.log('HERE');
2096 $j.remove();
2097 }
2098
2099 });
2100
2101 // Is there a function to render ?
2102 var fn = window['pagelayer_render_'+jEle.attr('pagelayer-tag')];
2103
2104 if(typeof fn == 'function'){
2105 fn(el);
2106 }
2107
2108 //console.log(el.atts);
2109
2110 // Parse the variables
2111 var new_html = pagelayer_parse_vars(el.iHTML.html(), el);
2112 el.iHTML.html(new_html);
2113
2114 // Do we have to wrap the innerHTML ?
2115 if('holder' in pagelayer_shortcodes[el.tag]){
2116
2117 var hSel = pagelayer_shortcodes[el.tag]['holder'];
2118 var holder = jEle.find(hSel).first();
2119
2120 // Detach the holder
2121 holder.detach();
2122
2123 // Add the new HTML
2124 el.$.html(el.iHTML.html());
2125
2126 // reAttach the children only
2127 el.$.find(hSel).html(holder.children());
2128
2129 // No holder
2130 }else{
2131
2132 //console.log(el.iHTML.html());
2133 el.$.html(el.iHTML.html());
2134
2135 }
2136
2137 // Rows, Cols and Groups
2138 }else{
2139
2140 // Is there a function to render ?
2141 var fn = window['pagelayer_sc_render_'+jEle.attr('pagelayer-tag')];
2142
2143 if(typeof fn == 'function'){
2144 fn(el);
2145 }
2146
2147 }
2148
2149 // Is there a function to render after HTML insertion but before CSS and attr ?
2150 var post = window['pagelayer_render_html_'+jEle.attr('pagelayer-tag')];
2151
2152 if(typeof post == 'function'){
2153 post(el);
2154 }
2155
2156 ////////////////////////////
2157 // Are there any edit fields ?
2158 ////////////////////////////
2159
2160 if(elCSS.edit.length > 0){
2161
2162 for(var c in elCSS.edit){
2163 var prop = elCSS.edit[c]['prop'];
2164 var tSel = elCSS.edit[c]['sel'];
2165 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2166 node.attr('pagelayer-editable', prop);
2167 }
2168
2169 }
2170
2171 ////////////////////////////
2172 // Are there any addClass ?
2173 ////////////////////////////
2174
2175 // If we have any classes to add
2176 if(elCSS.classes.length > 0){
2177 //console.log(elCSS.classes);
2178
2179 for(var c in elCSS.classes){
2180 var tSel = elCSS.classes[c]['sel'];
2181 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2182 if(!node.hasClass(elCSS.classes[c]['val'])){
2183 node.addClass(elCSS.classes[c]['val']);
2184 }
2185 }
2186 }
2187
2188 // If we have any classes to remove
2189 if(elCSS.remove_classes.length > 0){
2190 //console.log(elCSS.remove_classes);
2191
2192 for(var c in elCSS.remove_classes){
2193 var tSel = elCSS.remove_classes[c]['sel'];
2194 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2195 if(node.hasClass(elCSS.remove_classes[c]['val'])){
2196 node.removeClass(elCSS.remove_classes[c]['val']);
2197 }
2198 }
2199 }
2200
2201 ////////////////////////////
2202 // Are there any addAttr ?
2203 ////////////////////////////
2204
2205 // If we have any attributes to add
2206 if(elCSS.attr.length > 0){
2207 //console.log(elCSS.attr);
2208
2209 for(var c in elCSS.attr){
2210 var tSel = elCSS.attr[c]['sel'].replace('{{element}}', '');
2211 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2212 var att = elCSS.attr[c]['val'].split('=');
2213 att[1] = pagelayer_parse_vars(att[1], el);
2214 att[1] = pagelayer_trim(att[1], '"');
2215
2216 // Is it the same val ?
2217 if(!node.attr(att[0]) != att[1]){
2218 node.attr(att[0], att[1]);
2219 }
2220 }
2221 }
2222
2223 // If we have any attributes to add
2224 if(elCSS.remove_attr.length > 0){
2225 //console.log(elCSS.remove_attr);
2226
2227 for(var c in elCSS.remove_attr){
2228 var tSel = elCSS.remove_attr[c]['sel'].replace('{{element}}', '');
2229 var node = tSel.length < 1 ? jEle : jEle.find(tSel);
2230 var att = elCSS.remove_attr[c]['val'].split('=');
2231
2232 if(node.is('['+att[0]+']')){
2233 node.removeAttr(att[0]);
2234 }
2235 }
2236 }
2237
2238 // The style element
2239 var style = pagelayer.$('[pagelayer-style-id='+el.id+']');
2240
2241 // If we have any RULES CSS, then handle it
2242 if(elCSS.css.length > 0){
2243
2244 // Did we find it ?
2245 if(style.length < 1){
2246 jEle.prepend('<style pagelayer-style-id="'+el.id+'"></style>');
2247 }
2248
2249 // Get it again
2250 style = pagelayer.$('[pagelayer-style-id='+el.id+']');
2251
2252 // Make the rules
2253 var rules = [];
2254
2255 // Loop
2256 for(var c in elCSS.css){
2257 var tSel = elCSS.css[c]['sel'].replace('{{element}}', elCSS.sel);
2258 var rule = pagelayer_parse_vars(elCSS.css[c]['val'], el);
2259 rules.push(tSel+'{'+rule+'}');
2260 }
2261
2262 // Set the style
2263 style.html(rules.join("\n"));
2264 //console.log(style);
2265 }else{
2266 style.remove();
2267 }
2268
2269 // Is there a function to render at the end ?
2270 var end = window['pagelayer_render_end_'+jEle.attr('pagelayer-tag')];
2271
2272 if(typeof end == 'function'){
2273 end(el);
2274 }
2275
2276 // If the element have any parent
2277 var par = pagelayer_get_parent(jEle);
2278 if(par){
2279 pagelayer_sc_render(pagelayer_ele_by_id(par));
2280 }
2281
2282 };
2283
2284 // Is the given tag a group
2285 function pagelayer_is_group(tag){
2286
2287 if('has_group' in pagelayer_shortcodes[tag] && !pagelayer_empty(pagelayer_shortcodes[tag]['has_group'])){
2288 return true;
2289 }
2290
2291 return false;
2292
2293 }
2294
2295 // Save the post
2296 function pagelayer_save(){
2297
2298 var post = pagelayer_generate_sc(pagelayer_editable);//alert(post);return;
2299 var pagelayerajaxurl = pagelayer_ajax_url+'&action=pagelayer_save_content&postID='+pagelayer_postID;
2300 jQuery.ajax({
2301 type: "POST",
2302 url: pagelayerajaxurl,
2303 data: {
2304 pagelayer_update_content : post,
2305 pagelayer_nonce: pagelayer_ajax_nonce
2306 },
2307 success: function(response, status, xhr){
2308 //alert(data);
2309 var obj = jQuery.parseJSON(response);
2310 //alert(obj);
2311 if(obj['error']){
2312 alert(obj['error']);
2313 }else{
2314 pagelayer_isDirty = false;
2315 alert(obj['success']);
2316 pagelayer_get_revision();
2317 }
2318 },
2319 error: function(errorThrown){
2320 console.log(errorThrown);
2321 }
2322 });
2323
2324 };
2325
2326 //Close the Editor
2327 function pagelayer_close(){
2328 if(pagelayer_isDirty == true){
2329 var r = confirm('Your Data has not been Saved yet! \n Press OK to stay on the Page.'+
2330 '\n Press Cancel to Close Editor. ');
2331 if(r == false){
2332 window.top.location.href = pagelayer_returnURL;
2333 }
2334 }else{
2335 window.top.location.href = pagelayer_returnURL;
2336 }
2337 };
2338
2339 // Generate Shortcode Post to save
2340 function pagelayer_generate_sc(selector){
2341
2342 var txt = '';
2343
2344 jQuery(selector).children(".pagelayer-ele-wrap").each(function(){
2345
2346 var jEle = jQuery(this).children('.pagelayer-ele');
2347
2348 // The ID
2349 var id = jEle.attr('pagelayer-id');
2350
2351 // If there is an Add element wrapper
2352 if(pagelayer_empty(id)){
2353 return;
2354 }
2355
2356 // Find the type of tag
2357 var tag = jEle.attr('pagelayer-tag');
2358 var final_tag = tag;
2359 var closestEle = jQuery(this).closest('.pagelayer-col-holder');
2360
2361 // Define inner row | Note : Commented as we now have a new widget of type inner_row
2362 /*if(tag == 'pl_row' && closestEle.length > 0 && closestEle.closest(pagelayer_editable).length > 0){
2363 final_tag = 'pl_inner_row';
2364 }*/
2365
2366 // Define inner column
2367 if(tag == 'pl_col' && closestEle.length > 0 && closestEle.closest(pagelayer_editable).length > 0){
2368 final_tag = 'pl_inner_col';
2369 }
2370 //console.log(tag);
2371
2372 // Is there an innerHTML ele
2373 var inner = '';
2374 if('innerHTML' in pagelayer_shortcodes[tag]){
2375 inner = pagelayer_shortcodes[tag]['innerHTML'];
2376 }
2377
2378 // Create the tag
2379 var data = '['+final_tag;
2380
2381 // Get the attributes to store
2382 jQuery.each(jEle[0].attributes, function(i, attrib){
2383 var res = attrib.name.match(/^pagelayer-a-(.+)/i);
2384 if(res && res[1] != inner){
2385 //console.log(attrib.name+' '+res[1]);
2386 data += ' '+res[1]+'="'+pagelayer_escapeHTML(attrib.value)+'"';
2387 }
2388 });
2389
2390 data = data+']';
2391
2392 // Add to the text
2393 txt = txt+data+"\n";
2394
2395 // Any internal function to handle the save ?
2396 var func = window['pagelayer_tag_'+tag];
2397 if(typeof func == 'function'){
2398
2399 var content = '';
2400 content = func(jEle);
2401
2402 if(content.length > 0){
2403 txt = txt+content;
2404 }
2405
2406 // If its a Row or Column or Group then it will have children
2407 }else if(jEle.hasClass('pagelayer-row') || jEle.hasClass('pagelayer-col') || jEle.hasClass('pagelayer-inner_row') || pagelayer_is_group(tag)){
2408
2409 var sel = "[pagelayer-id="+id+"]";
2410
2411 // Any holder which holds children ?
2412 if('holder' in pagelayer_shortcodes[tag]){
2413 sel = sel+' '+pagelayer_shortcodes[tag]['holder'];
2414 }
2415
2416 // Select the top-most element
2417 sel = jQuery(sel).first();
2418
2419 // Any child selector - Majorly for owl carousel
2420 // NOTE : Child selector should be very specific with immediate child selection at all levels
2421 var child_selector = false;
2422 if('child_selector' in pagelayer_shortcodes[tag]){
2423 sel = sel.find(pagelayer_shortcodes[tag]['child_selector']);
2424 }
2425
2426 var childrens = pagelayer_generate_sc(sel);
2427 if(childrens.length > 0){
2428 txt = txt+childrens;
2429 }
2430
2431 // Its a normal element so we might need to handle the content
2432 }else{
2433
2434 var content = '';
2435 if(inner.length > 0){
2436 content = jEle.attr('pagelayer-a-'+inner);
2437 if(!content){
2438 content = '';
2439 }
2440 }else{
2441 content = '';//jEle.html();
2442 }
2443
2444 if(content.length > 0){
2445 txt = txt+content;
2446 }
2447
2448 }
2449
2450 // Close the tag
2451 txt = txt+"[/"+final_tag+"]\n";
2452
2453 });
2454
2455 return txt;
2456
2457 };
2458
2459 // Escape charaters in attributes
2460 var pagelayer_escapeChars = {
2461 '\\]' : '#93',
2462 '\\[' : '#91',
2463 //'=' : '#61',
2464 '<' : 'lt',
2465 '>' : 'gt',
2466 '"' : 'quot',
2467 //'&' : 'amp',
2468 '\'' : '#39'
2469 };
2470
2471 // To unescape
2472 var pagelayer_unescapeChars = {
2473 '#93' : ']',
2474 '#91' : '[',
2475 //'#61' : '=',
2476 'lt' : '<',
2477 'gt' : '>',
2478 'quot' : '"',
2479 //'amp' : '&',
2480 '#39' : '\''
2481 };
2482
2483 var pagelayer_escaperegex_S = '[';
2484 for(var key in pagelayer_escapeChars) {
2485 pagelayer_escaperegex_S += key;
2486 }
2487 pagelayer_escaperegex_S += ']';
2488
2489 var pagelayer_escaperegex = new RegExp( pagelayer_escaperegex_S, 'g');
2490
2491 // The function which escapes everything
2492 function pagelayer_escapeHTML(str) {
2493 return str.replace(pagelayer_escaperegex, function(m) {
2494 if(m == '[' || m == ']') m = '\\'+m;
2495 return '&' + pagelayer_escapeChars[m] + ';';
2496 });
2497 };
2498
2499 // This will unescape everything
2500 function pagelayer_unescapeHTML(str){
2501 return str.replace(/\&([^;]+);/g, function (entity, entityCode) {
2502 if(entityCode in pagelayer_unescapeChars){
2503 return pagelayer_unescapeChars[entityCode];
2504 }else{
2505 return entity;
2506 }
2507 });
2508 };
2509
2510 // Show the required leftbar tab
2511 function pagelayer_leftbar_tab(tab){
2512 pagelayer.$$('.pagelayer-leftbar-tab').hide();
2513 pagelayer.$$('#'+tab).show();
2514 }
2515
2516 // Sets up the leftbar
2517 function pagelayer_leftbar(){
2518
2519 // Toggle the holder
2520 pagelayer.$$('.pagelayer-leftbar-toggle').on('click', function(){
2521 pagelayer.$$('.pagelayer-leftbar-table').toggle();
2522 });
2523
2524 var html = '<div class="pagelayer-leftbar">'+
2525 '<div class="pagelayer-leftbar-scroll">'+
2526 '<div id="pagelayer-shortcodes" class="pagelayer-leftbar-tab pagelayer-shortcodes">'+
2527 '<div class="pagelayer-leftbar-search">'+
2528 '<i class="fa fa-search" /><input class="pagelayer-search-field" />'+
2529 '</div>';
2530
2531 for(var x in pagelayer_groups){
2532
2533 // Title
2534 html += '<div class="pagelayer-leftbar-group"><h5>'+x+'</h5>';
2535
2536 // Indivdual icon
2537 for(var y in pagelayer_groups[x]){
2538
2539 var sc = pagelayer_groups[x][y];
2540
2541 if(!(sc in pagelayer_shortcodes) || 'not_visible' in pagelayer_shortcodes[sc]){
2542 continue;
2543 }
2544
2545 html += '<div class="pagelayer-shortcode-drag" draggable="true" pagelayer-tag="'+sc+'">'+
2546 '<div class="pagelayer-sc">'+
2547 '<center class="pagelayer-shortcode-inner">';
2548
2549 if('icon' in pagelayer_shortcodes[sc]){
2550 html += '<i class="pagelayer-shortcode fa fa-'+pagelayer_shortcodes[sc]['icon']+'"></i>';
2551 }else{
2552 html += '<i class="pagelayer-shortcode pagelayer-'+sc+'"></i>';
2553 }
2554
2555 html += '</center>'+
2556 '<span class="pagelayer-shortcode-text">'+pagelayer_shortcodes[sc]['name']+'</span>'+
2557 '</div>'+
2558 '</div>';
2559
2560 }
2561
2562 html += '</div>';
2563
2564 }
2565
2566 html += '</div>'+
2567 '<div id="pagelayer-elpd" class="pagelayer-leftbar-tab pagelayer-elpd"></div>'+
2568 '<div id="pagelayer-history" class="pagelayer-leftbar-tab pagelayer-history"></div>'+
2569 '<div id="pagelayer-post-settings" class="pagelayer-leftbar-tab pagelayer-post-settings"></div>'+
2570 '</div>'+
2571 '</div>';
2572
2573 pagelayer.$$('.pagelayer-leftbar-holder').prepend(html);
2574 pagelayer_leftbar_tab('pagelayer-shortcodes');
2575
2576 pagelayer.$$('.pagelayer-leftbar-scroll').slimScroll({
2577 height: '100%',
2578 railVisible: false,
2579 alwaysVisible: true,
2580 color: '#000',
2581 size: '5px',
2582 });
2583
2584 // Hide the ones which are not supposed to be shown
2585 pagelayer.$$('.pagelayer-search-field').on('input', function(){
2586
2587 var val = jQuery(this).val();
2588 var re = new RegExp(val, 'i');
2589
2590 // Show only the required tags
2591 pagelayer.$$('.pagelayer-leftbar-group').each(function(){
2592
2593 var group = jQuery(this);
2594 var res = group.find('[pagelayer-tag]');
2595 var hidden = 0;
2596
2597 res.each(function(){
2598
2599 var tEle = jQuery(this);
2600 if(tEle.find('.pagelayer-shortcode-text').html().match(re)){
2601 tEle.show();
2602 }else{
2603 hidden += 1;
2604 tEle.hide();
2605 }
2606
2607 });
2608
2609 // Hide the whole group
2610 if(hidden == res.length){
2611 group.hide();
2612 }else{
2613 group.show();
2614 }
2615
2616 });
2617 });
2618
2619 // On click Pagelayer setting icon
2620 pagelayer.$$('.pagelayer-settings-icon').click(function(){
2621 pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text('Post Settings');
2622 pagelayer.$$('.pagelayer-logo').hide();
2623 pagelayer_leftbar_tab('pagelayer-post-settings');
2624 pagelayer_active = {};
2625 pagelayer_post_settings();
2626 });
2627
2628 };
2629
2630 // Post setting holder
2631 function pagelayer_post_settings(){
2632
2633 // Start pagelayer settings holder
2634 var setting_holder = '<div class="pagelayer-post-settings-holder">';
2635
2636 // Start pagelayer settings content body
2637 setting_holder += '<div class="pagelayer-post-settings-acc">'+
2638 '<div class="pagelayer-post-settings-lable"><span>Title</span><i class="pagelayer-toggle fa"></i></div>'+
2639 '<div class="pagelayer-post-settings-fields">'+
2640 '<label for="post_title">Post Title</label> '+
2641 '<input type="text" name="post_title" value="'+ pagelayer_postTitle +'" id="title" spellcheck="true" autocomplete="off">'+
2642 '<button class="pagelayer-post-settings-apply pagelayer-success-btn" disabled>Apply</button>'+
2643 '</div>'+
2644 '</div>';
2645
2646 /*if(pagelayer_postType == pagelayer_cpt['name']){
2647 setting_holder += '<div class="pagelayer-post-settings-acc">'+
2648 '<div class="pagelayer-post-settings-lable"><span>Custom Template type</span><i class="pagelayer-toggle fa"></i></div>'+
2649 '<div class="pagelayer-post-settings-fields">'+ pagelayer_CPT_condi +
2650 '</div>'+
2651 '</div>';
2652 }*/
2653
2654 /* if(pagelayer_support_FI){
2655 setting_holder += '<div class="pagelayer-post-settings-acc">'+
2656 '<div class="pagelayer-post-settings-lable"><span>Featured Image</span><i class="pagelayer-toggle fa"></i></div>'+
2657 '<div class="pagelayer-post-settings-fields">Featured Image'+
2658 '</div>'+
2659 '</div>';
2660 } */
2661
2662 // End pagelayer settings content body
2663
2664 // End pagelayer settings holder
2665 setting_holder += '</div>';
2666 var holder = pagelayer.$$('#pagelayer-post-settings');
2667 holder.html(setting_holder);
2668
2669 // On change input fields enable the apply button
2670 holder.find('input, select, textarea').on('change input', function(){
2671 jQuery(this).closest('.pagelayer-post-settings-fields').find('.pagelayer-post-settings-apply').removeAttr('disabled');
2672 });
2673
2674 // On click the label toggle the setting field holder
2675 holder.find('.pagelayer-post-settings-lable').on('click', function(){
2676
2677 var lEle = jQuery(this);
2678 var lEle_next = lEle.next('.pagelayer-post-settings-fields');
2679
2680 holder.find('.pagelayer-post-settings-fields').each(function(){
2681 var fEle = jQuery(this);
2682 if(!fEle.is(lEle_next)){
2683 fEle.hide().prev('.pagelayer-post-settings-lable').find('.pagelayer-toggle').removeClass('pagelayer-open');
2684 }
2685 });
2686
2687 lEle.next('.pagelayer-post-settings-fields').toggle();
2688 lEle.find('.pagelayer-toggle').toggleClass('pagelayer-open');
2689
2690 });
2691
2692 // On click apply button
2693 holder.find('.pagelayer-post-settings-apply').click(function(){
2694 var fEle = jQuery(this).closest('.pagelayer-post-settings-fields');
2695 var data = fEle.find('input, select, textarea').serialize();
2696
2697 jQuery.ajax({
2698 url: pagelayer_ajax_url+'action=pagelayer_save_settings&postID='+pagelayer_postID,
2699 type: 'post',
2700 data : 'pagelayer_nonce='+ pagelayer_ajax_nonce +'&'+ data,
2701 success: function(response, status, xhr){
2702 //alert(data);
2703 var obj = jQuery.parseJSON(response);
2704 //alert(obj);
2705 if(obj['error']){
2706 alert(obj['error']);
2707 }else{
2708 alert(obj['success']);
2709 window.location.reload();
2710 }
2711 },
2712 error: function(errorThrown){
2713 console.log(errorThrown);
2714 }
2715 });
2716
2717 });
2718
2719 return;
2720 }
2721
2722 // Get the closest element and method
2723 function pagelayer_near_by_ele(id, sc){
2724
2725 // Get the previous element of the id element
2726 var prevEle_id = jQuery('[pagelayer-wrap-id="'+id+'"]').prev().attr('pagelayer-wrap-id') || '';
2727 var method, cEle, args = {};
2728
2729 if(prevEle_id.length > 0){
2730
2731 // If have previous element of the id element
2732 // Set the method and previous element selector
2733 args = {'method' : 'after', 'cEle' : '[pagelayer-wrap-id="'+prevEle_id+'"]'};
2734
2735 }else{
2736
2737 // If don't have previous element of the id element then get parent element
2738 if(sc == "pl_row"){
2739 args = {'method' : 'prepend', 'cEle' : pagelayer_editable};
2740 }else{
2741
2742 // Get the parent element
2743 var pEle_id = pagelayer_id(jQuery('[pagelayer-wrap-id="'+id+'"]').closest('.pagelayer-ele'));
2744
2745 // Get the parent element tag
2746 var pEle_tag = pagelayer_tag(jQuery('[pagelayer-id="'+pEle_id+'"]'));
2747 var holder = pagelayer_shortcodes[pEle_tag]['holder'] || '';
2748 args = {'method' : 'prepend', 'cEle' : '[pagelayer-id="'+pEle_id+'"] '+ holder+' '};
2749
2750 }
2751
2752 }
2753
2754 return args;
2755
2756 };
2757
2758 // Push the action data in the pagelayer_history_obj object
2759 function pagelayer_history_action_push(args){
2760
2761 var history_obj_len = pagelayer_history_obj['action_data'].length;
2762
2763 // If the history_obj_len is less then 1 then set the data in array 0 position
2764 if(history_obj_len < 1){
2765 pagelayer_history_obj['action_data'][0] = {'title' : 'Start Editing', 'action' : 'Start' };
2766 pagelayer_history_obj['current_active_item_id'] = 0;
2767 }
2768
2769 // Remove the second array element if the history_obj_len greater then 100
2770 if(history_obj_len > 100){
2771 pagelayer_history_obj['action_data'].splice(1, 1);
2772 }
2773
2774 // Get current active history action id
2775 var action_id = parseInt(pagelayer_history_obj['current_active_item_id']) || 0;
2776
2777 // Remove the all array element after the active array element
2778 var del_ele = history_obj_len - action_id - 1;
2779 pagelayer_history_obj['action_data'].splice(action_id + 1, del_ele);
2780
2781 // Check if the same attr set as current active history
2782 if(args.action == "Edited" && history_obj_len > 1){
2783 var atts = pagelayer_history_obj['action_data'][action_id] || '';
2784 if(atts['atts'] == args['atts']){
2785 args['oldVal'] = atts['oldVal'];
2786 pagelayer_history_obj['action_data'][action_id] = args;
2787 pagelayer_history_setup();
2788 return true;
2789 }
2790 }
2791
2792 pagelayer_history_obj['action_data'].push(args);
2793 pagelayer_history_obj['current_active_item_id'] = pagelayer_history_obj['action_data'].length - 1;
2794 pagelayer_history_setup();
2795
2796 }
2797
2798 // Setup pagelayer history
2799 function pagelayer_history_setup(force){
2800
2801 var force = force || false;
2802
2803 // If the history tab is visible, only then setup
2804 if(!pagelayer.$$('#pagelayer-history').is(':visible') && !force){
2805 return;
2806 }
2807
2808 // The current active action id
2809 var current_id = pagelayer_history_obj['current_active_item_id'];
2810
2811 // pagelayer-HISTORY - Element Properties Dialog
2812 var pagelayer_history_html = '<div class="pagelayer-history-tabs">'+
2813 '<div class="pagelayer-history-tab" pagelayer-history-tab="actions" pagelayer-history-active-tab="1">Actions</div>'+
2814 '<div class="pagelayer-history-tab" pagelayer-history-tab="revisions">Revisions</div>'+
2815 '</div>'+
2816 '<div class="pagelayer-history-body">'+
2817 '<div class="pagelayer-history-section active" pagelayer-show-tab="actions">';
2818
2819 // Any actions
2820 if(pagelayer_history_obj['action_data'].length > 0){
2821
2822 for(var x in pagelayer_history_obj['action_data']){
2823
2824 if(pagelayer_empty(pagelayer_history_obj['action_data'][x])){continue;}
2825
2826 var title = pagelayer_history_obj['action_data'][x]['title'] || '';
2827 var subTitle = pagelayer_history_obj['action_data'][x]['subTitle'] || '';
2828 var action = pagelayer_history_obj['action_data'][x]['action'] || '';
2829 var tmp_attr = pagelayer_history_obj['action_data'][x]['attrType'] || '';
2830 var eAttr = '';
2831
2832 if(!pagelayer_empty(tmp_attr) && tmp_attr == "tmp_attr"){
2833 eAttr = "pagelayer-history-hidden";
2834 }
2835
2836 pagelayer_history_html += '<div class="pagelayer-history-holder '+((current_id == x) ? 'current_active_item' : '' )+' '+eAttr+'" history-action-id="'+x+'" >'+
2837 '<div class="pagelayer-history-detail-holder">'+
2838 '<span class="pagelayer-history-title"><b> '+title+' </b></span>'+
2839 '<span class="pagelayer-history-subtitle"> '+subTitle+' </span>'+
2840 '<span class="pagelayer-history-action"><i> '+action+' </i></span>'+
2841 '</div>'+
2842 '<div class="pagelayer-history-icon">'+
2843 '<span class="pagelayer-history-check fa fa-check" aria-hidden="true"></span>'+
2844 '</div>'+
2845 '</div>';
2846 }
2847
2848 }else{
2849 pagelayer_history_html += 'No Actions history available yet';
2850 }
2851
2852 pagelayer_history_html += '</div>'+
2853 '<div class="pagelayer-history-section" pagelayer-show-tab="revisions">';
2854
2855 // Any revisions ?
2856 if(pagelayer_revision_obj){
2857 for(var x in pagelayer_revision_obj){
2858 pagelayer_history_html += '<div class="pagelayer-revision-holder" revision-id="'+pagelayer_revision_obj[x]['ID']+'">'+
2859 '<div class="pagelayer-revision-img-holder">'+
2860 '<img src="'+pagelayer_revision_obj[x]['post_author_url']+'" />'+
2861 '</div>'+
2862 '<div class="pagelayer-revision-detail-holder">'+
2863 '<div class="pagelayer-revision-date">'+
2864 pagelayer_revision_obj[x]['post_date_ago']+
2865 '('+pagelayer_revision_obj[x]['post_date']+')'+
2866 '</div>'+
2867 '<div class="pagelayer-revision-author">'+
2868 pagelayer_revision_obj[x]['post_type'] +' by '+
2869 pagelayer_revision_obj[x]['post_author_name']+
2870 '</div>'+
2871 '</div>'+
2872 '<div class="pagelayer-revision-icon-holder">'+
2873 '<i class="pagelayer-revision-delete fa fa-times"></i>'+
2874 '</div>'+
2875 '</div>';
2876 }
2877
2878 }else{
2879 pagelayer_history_html += 'No Revisions history available';
2880 }
2881
2882 pagelayer_history_html += '</div>'+
2883 '</div>';
2884
2885 // Create the dialog box
2886 pagelayer.$$('#pagelayer-history').html(pagelayer_history_html);
2887 var holder = pagelayer.$$('#pagelayer-history');
2888
2889 // Set active history holder
2890 holder.find('.pagelayer-history-holder').on('click', function(){
2891 var hEle = jQuery(this);
2892 var prev_item_id = pagelayer_history_obj['current_active_item_id'];
2893 hEle.parent().children().removeClass('current_active_item');
2894 hEle.addClass('current_active_item');
2895 var do_item_id = parseInt(hEle.attr('history-action-id'));
2896 pagelayer_history_action_setup(do_item_id, prev_item_id);
2897 });
2898
2899 // Apply revision
2900 holder.find('.pagelayer-revision-holder').on('click', function(){
2901 var revision_id = jQuery(this).attr('revision-id');
2902
2903 jQuery.ajax({
2904 url: pagelayer_ajax_url+'&action=pagelayer_apply_revision&revisionID='+revision_id,
2905 type: 'post',
2906 data: {
2907 pagelayer_nonce: pagelayer_ajax_nonce,
2908 'pagelayer-live' : 1,
2909 },
2910 success: function(response, status, xhr){
2911
2912 var obj = jQuery.parseJSON(response);
2913 if(obj['error']){
2914 alert(obj['error']);
2915 }else{
2916 jQuery(pagelayer_editable).html(obj['content']);
2917 alert(obj['success']);
2918 pagelayer_element_setup();
2919 pagelayer_add_widget();
2920 }
2921 }
2922 });
2923 });
2924
2925 // Delete the revision
2926 holder.find('.pagelayer-revision-delete').click(function(e){
2927
2928 e.stopPropagation();
2929 var rEle = jQuery(this).closest('.pagelayer-revision-holder');
2930 var revision_id = rEle.attr('revision-id');
2931
2932 if(confirm("Are you sure you want to delete the revision ?")){
2933 jQuery.ajax({
2934 url: pagelayer_ajax_url+'&action=pagelayer_delete_revision&revisionID='+revision_id,
2935 type: 'post',
2936 data: {pagelayer_nonce: pagelayer_ajax_nonce},
2937 success: function(response, status, xhr){
2938
2939 var obj = jQuery.parseJSON(response);
2940 if(obj['error']){
2941 alert(obj['error']);
2942 }else{
2943 alert(obj['success']);
2944 rEle.hide();
2945 }
2946
2947 }
2948 });
2949 }
2950
2951 });
2952
2953 // The tabs
2954 holder.find('.pagelayer-history-tab').on('click', function(){
2955 var attr = 'pagelayer-history-active-tab';
2956 holder.find('.pagelayer-history-tab').each(function(){
2957 jQuery(this).removeAttr(attr);
2958 });
2959 jQuery(this).attr(attr, 1);
2960
2961 // Get the active tab
2962 var active_tab = holder.find('[pagelayer-history-active-tab]').attr('pagelayer-history-tab');
2963
2964 // Trigger the showing of rows
2965 holder.find('[pagelayer-show-tab]').each(function(){
2966 var sec = jQuery(this);
2967
2968 // Is it the active tab ?
2969 if(sec.attr('pagelayer-show-tab') != active_tab){
2970 sec.hide();
2971 }else{
2972 sec.show();
2973 }
2974 });
2975 });
2976 }
2977
2978 // Get evisions Handler
2979 function pagelayer_get_revision(){
2980
2981 jQuery.ajax({
2982 url: pagelayer_ajax_url+'&action=pagelayer_get_revision&postID='+pagelayer_postID,
2983 type: 'post',
2984 data: {
2985 pagelayer_nonce: pagelayer_ajax_nonce,
2986 },
2987 //async:false,
2988 success: function(response, status, xhr){
2989 var obj = jQuery.parseJSON(response);
2990
2991 if(!pagelayer_empty(obj['error'])){
2992 alert(obj['error']);
2993 }else{
2994 pagelayer_revision_obj = obj;
2995 pagelayer_history_setup(true);
2996 }
2997 }
2998 });
2999 };
3000
3001 // Do the history action - use for ctrl-z and ctrl-y
3002 function pagelayer_do_history(action){
3003
3004 var cur_id = pagelayer_history_obj['current_active_item_id'];
3005 var new_id = cur_id;
3006 var action_data_len = pagelayer_history_obj['action_data'].length;
3007
3008
3009 if(action == 'undo'){
3010
3011 // You cannot undo from the first movement
3012 if(cur_id == 0){
3013 return true;
3014 }
3015
3016 for(var i = (cur_id - 1); i => 0; i--){
3017
3018 var action = pagelayer_history_obj['action_data'][i];
3019
3020 if('attrType' in action && action['attrType'] == 'tmp_attr'){
3021 continue;
3022 }
3023
3024 new_id = i;
3025 break;
3026
3027 }
3028
3029 }else if(action == 'redo'){
3030 for(var i = cur_id + 1; i < action_data_len; i++){
3031
3032 var action = pagelayer_history_obj['action_data'][i];
3033
3034 if('attrType' in action && action['attrType'] == 'tmp_attr'){
3035 continue;
3036 }
3037
3038 new_id = i;
3039 break;
3040
3041 }
3042 }
3043
3044 // Do the action
3045 pagelayer_history_action_setup(new_id, cur_id);
3046 pagelayer_history_setup();
3047
3048 };
3049
3050 // Action setup handle on ctrl-z and ctrl-y
3051 function pagelayer_history_action_setup(current_item_id, prev_item_id){
3052
3053 // Set this as the current active
3054 pagelayer_history_obj['current_active_item_id'] = current_item_id;
3055
3056 // Delete the element
3057 var delete_ele = function(id){
3058
3059 // Set Pagelayer History FALSE to prevent saving delete action in action history
3060 pagelayer.history_action = false;
3061
3062 pagelayer_delete_element('[pagelayer-id='+id+']');
3063
3064 // Set Pagelayer History TRUE
3065 pagelayer.history_action = true;
3066
3067 };
3068
3069 // Re-setup the element
3070 var resetup_ele = function(history_array){
3071 jQuery(history_array.cEle.cEle)[history_array.cEle.method](history_array.html);
3072 pagelayer_element_setup('[pagelayer-id='+history_array.pl_id+'], [pagelayer-id='+history_array.pl_id+'] .pagelayer-ele', true);
3073 pagelayer_empty_col(jQuery('[pagelayer-id="'+history_array.pl_id+'"]').closest('.pagelayer-col-holder'));
3074 };
3075
3076 // Re-setup the element attr
3077 var reset_ele_attr = function(hEle, atts, val, attrType){
3078
3079 // Set Pagelayer History FALSE to prevent saving attributes in action history
3080 pagelayer.history_action = false;
3081 if(attrType == "tmp_attr"){
3082 pagelayer_set_tmp_atts(hEle, atts, val);
3083 }else{
3084 pagelayer_set_atts(hEle, atts, val);
3085 }
3086
3087 // The property holder
3088 var holder = pagelayer.$$('.pagelayer-elpd-body');
3089 holder.html(' ');
3090 pagelayer_sc_render(hEle);
3091 pagelayer_elpd_generate(hEle, holder);
3092 pagelayer.history_action = true;
3093
3094 };
3095
3096 if(prev_item_id > current_item_id){
3097
3098 // All Actions for undo here
3099 var i = parseInt(prev_item_id);
3100
3101 for(i; i > current_item_id; i--){
3102
3103 var history_array = pagelayer_history_obj['action_data'][i];
3104 var action = history_array.action;
3105 var id = history_array.pl_id;
3106
3107 if(action == "Edited"){
3108 hEle = jQuery('[pagelayer-id="'+id+'"]');
3109 reset_ele_attr(hEle, history_array.atts, history_array.oldVal, history_array.attrType);
3110 }else if(action == "Added"){
3111 delete_ele(id);
3112 }else if(action == "Deleted"){
3113 resetup_ele(history_array);
3114 }else if(action == "Copied"){
3115 delete_ele(id);
3116 }
3117
3118 }
3119
3120 }else{
3121
3122 // All Actions for redo here
3123 var i = parseInt(prev_item_id)+1;
3124
3125 for(i; i <= current_item_id; i++){
3126
3127 var history_array = pagelayer_history_obj['action_data'][i];
3128 var action = history_array.action;
3129 var id = history_array.pl_id;
3130
3131 if(action == "Edited"){
3132 hEle = jQuery('[pagelayer-id="'+id+'"]');
3133 reset_ele_attr(hEle, history_array.atts, history_array.newVal, history_array.attrType);
3134 }else if(action == "Added"){
3135 resetup_ele(history_array);
3136
3137 if(history_array.tag != "pl_row" && history_array.tag != "pl_col" ){
3138 // Ensure the column is not empty
3139 pagelayer_empty_col(history_array.cEle.cEle);
3140 }
3141 }else if(action == "Deleted"){
3142 delete_ele(id);
3143 }else if(action == "Copied"){
3144 resetup_ele(history_array);
3145 }
3146
3147 }
3148 }
3149
3150 };
3151
3152 // Report an error
3153 function pagelayer_error(error, func){
3154 var prefix = func || '';
3155 alert(prefix+error);
3156 };
3157
3158 function pagelayer_bottombar(){
3159 var holder = pagelayer.$$('.pagelayer-bottombar-holder');
3160 var html = '<div class="pagelayer-bottombar">'+
3161 '<div class="pagelayer-bottombar-rightbuttons">'+
3162 '<button class="pagelayer-update-button pagelayer-success-btn">Update</button>'+
3163 '<button class="pagelayer-close-button">Close</button>'+
3164 '<div class="pagelayer-mode-wrapper">'+
3165 '<i class="pagelayer-mode-button fa fa-desktop"></i>'+
3166 '<div class="pagelayer-mode-buttons-wrapper">'+
3167 '<i class="screen-mode fa fa-desktop" pagelayer-mode-data="desktop"></i>'+
3168 '<i class="screen-mode fa fa-tablet" pagelayer-mode-data="tablet"></i>'+
3169 '<i class="screen-mode fa fa-mobile" pagelayer-mode-data="mobile"></i>'+
3170 '</div>'+
3171 '</div>'+
3172 '<i class="pagelayer-history-icon fa fa-history"></i>'+
3173 '</div>'+
3174 '</div>';
3175
3176 holder.html(html);
3177 holder.find('.pagelayer-update-button').on('click', function(){
3178 pagelayer_save();
3179 pagelayer_history_setup();// Setup history tab after update
3180 });
3181
3182 holder.find('.pagelayer-close-button').on('click', function(){
3183 pagelayer_close();
3184 });
3185 holder.find('.screen-mode').on('click', function(){
3186 var screen_mode = jQuery(this).attr('pagelayer-mode-data');
3187 pagelayer_set_screen_mode(screen_mode);
3188 holder.find('.pagelayer-mode-buttons-wrapper').toggle();
3189 });
3190
3191 holder.find('.pagelayer-mode-button').on('click', function(){
3192 holder.find('.pagelayer-mode-buttons-wrapper').toggle();
3193 });
3194
3195 holder.find('.pagelayer-history-icon').click(function(){
3196 pagelayer.$$('.pagelayer-elpd-header').show().find('.pagelayer-elpd-title').text('Pagelayer History');
3197 pagelayer.$$('.pagelayer-logo').hide();
3198 pagelayer_leftbar_tab('pagelayer-history');
3199 pagelayer_active = {};
3200 pagelayer_history_setup();
3201 });
3202 };
3203
3204
3205 ///////////////////////////////
3206 // Miscellaneuos Functions
3207 ///////////////////////////////
3208
3209 // Generates a random string of "n" characters
3210 function pagelayer_randstr(n, special){
3211 var text = '';
3212 var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
3213
3214 special = special || 0;
3215 if(special){
3216 possible = possible + '&#$%@';
3217 }
3218
3219 for(var i=0; i < n; i++){
3220 text += possible.charAt(Math.floor(Math.random() * possible.length));
3221 }
3222
3223 return text;
3224 };
3225
3226 function pagelayer_update_site_title(val){
3227 if(!pagelayer_empty(val)){
3228 var site_name = jQuery('.pagelayer-wp-title').attr('pagelayer-a-site_name');
3229 if(!pagelayer_empty(site_name)){
3230 var site_title = jQuery.ajax({
3231 url: pagelayer_ajax_url+'&action=pagelayer_fetch_site_title',
3232 type: 'post',
3233 async: false
3234 }).responseText;
3235
3236 if(site_title != site_name){
3237 var site_title = jQuery.ajax({
3238 url: pagelayer_ajax_url+'&action=pagelayer_update_site_title',
3239 type: 'post',
3240 data: {'site_title': site_name},
3241 async: false
3242 }).responseText;
3243 }
3244 }
3245 }
3246 }
3247
3248 function pagelayer_trim(str, charlist){
3249 // discuss at: http://locutus.io/php/trim/
3250
3251 if(typeof str != 'string'){
3252 return str;
3253 }
3254
3255 var whitespace = [' ', '\n', '\r', '\t', '\f', '\x0b', '\xa0', '\u2000', '\u2001', '\u2002', '\u2003', '\u2004', '\u2005', '\u2006', '\u2007', '\u2008', '\u2009', '\u200a', '\u200b', '\u2028', '\u2029', '\u3000' ].join('')
3256 var l = 0
3257 var i = 0
3258 str += ''
3259
3260 if (charlist) {
3261 whitespace = (charlist + '').replace(/([[\]().?/*{}+$^:])/g, '$1')
3262 }
3263
3264 l = str.length
3265 for (i = 0; i < l; i++) {
3266 if (whitespace.indexOf(str.charAt(i)) === -1) {
3267 str = str.substring(i)
3268 break
3269 }
3270 }
3271
3272 l = str.length
3273 for (i = l - 1; i >= 0; i--) {
3274 if (whitespace.indexOf(str.charAt(i)) === -1) {
3275 str = str.substring(0, i + 1)
3276 break
3277 }
3278 }
3279
3280 return whitespace.indexOf(str.charAt(0)) === -1 ? str : ''
3281 };
3282
3283 // Convert the regular URL of a Video to a Embed URL
3284 function pagelayer_video_url(src){
3285
3286 var youtubeRegExp = /youtube\.com|youtu\.be/;
3287 var vimeoRegExp = /vimeo\.com/;
3288 var match = '';
3289 var videoId = '';
3290
3291 if (youtubeRegExp.exec(src)) {
3292 match = 'youtube';
3293 } else if (vimeoRegExp.exec(src)) {
3294 match = 'vimeo';
3295 }
3296
3297 switch(match){
3298 case 'youtube':
3299
3300 var youtubeRegExp1 = /youtube\.com/;
3301 var youtubewatch = /watch/;
3302 var youtubeembed = /embed/;
3303 var youtube = /youtu\.be/;
3304
3305 if (youtubeRegExp1.exec(src)) {
3306
3307 if (youtubewatch.exec(src)) {
3308 videoId = src.split('?v=');
3309
3310 } else if (youtubewatch.exec(src)) {
3311 videoId = src.split('embed/');
3312 }
3313
3314 } else if (youtube.exec(src)) {
3315 videoId = src.split('.be/');
3316 }
3317
3318 return '//youtube.com/embed/'+videoId[1];
3319
3320 break;
3321
3322 case 'vimeo':
3323
3324 var vimeoplayer = /player\.vimeo\.com/;
3325 var vimeovideo = /video/;
3326
3327 if (vimeoplayer.exec(src) && vimeovideo.exec(src)) {
3328 videoId = src.split('video/');
3329 } else if (vimeoRegExp.exec(src)) {
3330 videoId = src.split('.com/');
3331 }
3332
3333 return '//player.vimeo.com/video/'+videoId[1];
3334
3335 break;
3336 default:
3337 return src;
3338 }
3339 };
3340
3341 // Add widget section
3342 function pagelayer_add_widget(){
3343
3344 html='<div class="pagelayer-add-widget-area">'+
3345 '<i class="pagelayer-add-row fa fa-plus-circle"></i>'+
3346 '<p>Click here to add new row OR drag widgets</p>'+
3347 '</div>';
3348
3349 jQuery(pagelayer_editable).append(html);
3350
3351 var add_area = jQuery('.pagelayer-add-widget-area');
3352
3353 // Add a code before this
3354 var add_sc = function(tag){
3355
3356 // Create Row
3357 var row = jQuery('<div pagelayer-tag="pl_row"></div>');
3358 add_area.before(row);
3359 var row_id = pagelayer_onadd(row, false);
3360 var rEle = pagelayer_ele_by_id(row_id);
3361
3362 if(tag == 'pl_row'){
3363 rEle.click();
3364 return row_id;
3365 }
3366
3367 // Create Column
3368 var col = jQuery('<div pagelayer-tag="pl_col"></div>');
3369 rEle.find('.pagelayer-row-holder').append(col);
3370 var col_id = pagelayer_onadd(col, false);
3371 var cEle = pagelayer_ele_by_id(col_id);
3372
3373 if(tag == 'pl_col'){
3374 cEle.click();
3375 return col_id;
3376 }
3377
3378 // Create element
3379 var ele = jQuery('<div pagelayer-tag="'+tag+'"></div>');
3380 cEle.find('.pagelayer-col-holder').append(ele);
3381 var id = pagelayer_onadd(ele);
3382
3383 // Ensure the column is not empty
3384 pagelayer_empty_col(cEle.find('.pagelayer-col-holder'));
3385
3386 return id;
3387
3388 }
3389
3390 // Handle Click
3391 add_area.on('click', function(e){
3392 e.stopPropagation();
3393 add_sc('pl_col');
3394 });
3395
3396 // Handle Drag over
3397 add_area.on('dragover', function(e){
3398 //console.log(e)
3399 add_area.addClass('pagelayer-add-widget-drag');
3400 });
3401
3402 // Handle Drag Leave
3403 add_area.on('dragleave', function(e){
3404 //console.log(e)
3405 add_area.removeClass('pagelayer-add-widget-drag');
3406 });
3407
3408 // Handle On Drop
3409 add_area.on('drop', function(e){
3410
3411 //console.log(e);
3412 //console.log(e.originalEvent.dataTransfer.getData('tag'));
3413 add_area.removeClass('pagelayer-add-widget-drag');
3414 jQuery('.pagelayer-is-dragging').removeClass('pagelayer-is-dragging');
3415
3416 var tag = e.originalEvent.dataTransfer.getData('tag');
3417
3418 // Is it an existing element ?
3419 if(tag.length < 1){
3420 return false;
3421 }
3422
3423 e.preventDefault();
3424
3425 //console.log(tag);
3426
3427 add_sc(tag);
3428 });
3429 }
3430
3431 // On editable area image paste handler
3432 function pagelayer_editable_paste_handler(pasteEvent, pagelayer_ajax_func){
3433
3434 try {
3435 var items = (pasteEvent.originalEvent || pasteEvent).clipboardData.items,
3436 mustPreventDefault = false,
3437 reader;
3438
3439 for (var i = items.length - 1; i >= 0; i -= 1) {
3440
3441 if (items[i].type.match(/^image\//)) {
3442
3443 reader = new FileReader();
3444 /* jshint -W083 */
3445 reader.onloadend = function (event) {
3446
3447 var src = event.target.result;
3448
3449 if( src.indexOf('data:image') === 0 ) {
3450
3451 var block = src.split(";");
3452 var contentType = block[0].split(":")[1];
3453 var realData = block[1].split(",")[1];
3454 var fileName = "image."+contentType.split("/")[1];
3455
3456 // Convert it to a blob to upload
3457 var blob = pagelayer_b64toBlob(realData, contentType);
3458
3459 var formData = new FormData();
3460 formData.append('action', 'upload-attachment');
3461 formData.append('_ajax_nonce', pagelayer_media_ajax_nonce);
3462 formData.append('async-upload', blob, fileName);
3463
3464 $.ajax({
3465 url:pagelayer_ajax_url,
3466 data: formData,// the formData function is available in almost all new browsers.
3467 type:"post",
3468 contentType:false,
3469 processData:false,
3470 cache:false,
3471 beforeSend: function( xhr ) {
3472 if(typeof pagelayer_ajax_func.beforeSend == 'function'){
3473 pagelayer_ajax_func.beforeSend(xhr);
3474 }
3475 },
3476 error:function(err){
3477 //console.error(err);
3478 alert("Unable to upload image for some reason.");
3479 },
3480 success:function(response){
3481 var obj = jQuery.parseJSON(response);
3482 if(typeof pagelayer_ajax_func.success == 'function'){
3483 pagelayer_ajax_func.success(obj);
3484 }
3485 },
3486 complete:function(xhr){
3487 if(typeof pagelayer_ajax_func.complete == 'function'){
3488 pagelayer_ajax_func.complete(xhr);
3489 }
3490 }
3491 });
3492
3493 }
3494
3495 };
3496 /* jshint +W083 */
3497 reader.readAsDataURL(items[i].getAsFile());
3498 mustPreventDefault = true;
3499 }
3500 }
3501
3502 if(mustPreventDefault){
3503 pasteEvent.stopPropagation();
3504 pasteEvent.preventDefault();
3505 }
3506
3507 }catch(err){}
3508
3509 return mustPreventDefault;
3510
3511 }
3512
3513 // Convert base64 to Blob
3514 function pagelayer_b64toBlob(b64Data, contentType, sliceSize) {
3515 contentType = contentType || '';
3516 sliceSize = sliceSize || 512;
3517
3518 var byteCharacters = atob(b64Data);
3519 var byteArrays = [];
3520
3521 for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
3522 var slice = byteCharacters.slice(offset, offset + sliceSize);
3523
3524 var byteNumbers = new Array(slice.length);
3525 for (var i = 0; i < slice.length; i++) {
3526 byteNumbers[i] = slice.charCodeAt(i);
3527 }
3528
3529 var byteArray = new Uint8Array(byteNumbers);
3530
3531 byteArrays.push(byteArray);
3532 }
3533
3534 var blob = new Blob(byteArrays, {type: contentType});
3535 return blob;
3536 }
3537
3538 // Function to check if the URL is external
3539 function pagelayer_parse_theme_vars(img_url){
3540
3541 for(x in pagelayer_theme_vars){
3542 img_url = img_url.replace(x, pagelayer_theme_vars[x]);
3543 }
3544
3545 return img_url;
3546 };