PluginProbe
Page Builder: Pagelayer – Drag and Drop website builder / 1.0.4
Page Builder: Pagelayer – Drag and Drop website builder v1.0.4
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.4, at js/pagelayer-editor.js

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