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

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