Page Builder: PageLayer – Drag and Drop website builder - Version 1.6.6

Version Description

(March 09, 2022) = * [Task] The editing experience within Pagelayer editor has been further improved. Now user can move from one widget to another with the help of up and down arrow keys. Weare trying to make the editor into a more user friendly document editor. * [Task] Now we will add a text widget after the active widget when enter is pressed. You can add a slash "/" to search and convert the widget.

Download this release

Release Info

Developer pagelayer
Plugin Icon 128x128 Page Builder: PageLayer – Drag and Drop website builder
Version 1.6.6
Comparing to
See all releases

Code changes from version 1.6.5 to 1.6.6

css/pagelayer-editor-frontend.css CHANGED
@@ -520,8 +520,12 @@ color: #fff;
520
  background: #0069d9;
521
  }
522
 
 
 
 
 
523
  [data-placeholder-text]::after{
524
- display:inline-block;
525
  content: attr(data-placeholder-text);
526
  position:absolute;
527
  top: 50%;
520
  background: #0069d9;
521
  }
522
 
523
+ [contenteditable]:focus{
524
+ outline: 0px;
525
+ }
526
+
527
  [data-placeholder-text]::after{
528
+ display:flex;
529
  content: attr(data-placeholder-text);
530
  position:absolute;
531
  top: 50%;
css/pagelayer-pen.css CHANGED
@@ -49,6 +49,7 @@ padding: 3px 5px;
49
  width: 28px;
50
  font-size: 14px !important;
51
  font-weight: 700 !important;
 
52
  }
53
 
54
  .pagelayer-pen-toolbar button strong{
49
  width: 28px;
50
  font-size: 14px !important;
51
  font-weight: 700 !important;
52
+ color: #444;
53
  }
54
 
55
  .pagelayer-pen-toolbar button strong{
init.php CHANGED
@@ -5,7 +5,7 @@ if (!defined('ABSPATH')) exit;
5
 
6
  define('PAGELAYER_BASE', plugin_basename(PAGELAYER_FILE));
7
  define('PAGELAYER_PRO_BASE', 'pagelayer-pro/pagelayer-pro.php');
8
- define('PAGELAYER_VERSION', '1.6.5');
9
  define('PAGELAYER_DIR', dirname(PAGELAYER_FILE));
10
  define('PAGELAYER_SLUG', 'pagelayer');
11
  define('PAGELAYER_URL', plugins_url('', PAGELAYER_FILE));
5
 
6
  define('PAGELAYER_BASE', plugin_basename(PAGELAYER_FILE));
7
  define('PAGELAYER_PRO_BASE', 'pagelayer-pro/pagelayer-pro.php');
8
+ define('PAGELAYER_VERSION', '1.6.6');
9
  define('PAGELAYER_DIR', dirname(PAGELAYER_FILE));
10
  define('PAGELAYER_SLUG', 'pagelayer');
11
  define('PAGELAYER_URL', plugins_url('', PAGELAYER_FILE));
js/pagelayer-editor.js CHANGED
@@ -197,7 +197,7 @@ function pagelayer_start(){
197
  pagelayer_setup_props_editable();
198
 
199
  // Make elements editable
200
- jQuery(pagelayer_editable + ' [pagelayer-editable]').attr('contenteditable', 'true');
201
 
202
  // Use text widget for search widget
203
  pagelayer_search_widgets();
@@ -1223,9 +1223,6 @@ function pagelayer_empty_col(selector){
1223
  event.stopPropagation();
1224
  pagelayer.$$('.pagelayer-elpd-close').click();
1225
 
1226
- // Show left bar
1227
- pagelayer.$$('.pagelayer-leftbar-table').removeClass('pagelayer-leftbar-hidden pagelayer-leftbar-minimize');
1228
-
1229
  pagelayer_show_widget_list(jQuery(this));
1230
  });
1231
 
@@ -1649,7 +1646,9 @@ function pagelayer_element_clicked(selector, e){
1649
  });
1650
 
1651
  // Show left bar
1652
- pagelayer.$$('.pagelayer-leftbar-table').removeClass('pagelayer-leftbar-hidden pagelayer-leftbar-minimize');
 
 
1653
 
1654
  // Lets not rebuild everything to make it faster
1655
  if(pagelayer_is_active(jEle)){
@@ -1669,7 +1668,7 @@ function pagelayer_element_clicked(selector, e){
1669
  // Use text widget for search widget
1670
  function pagelayer_search_widgets(hEle){
1671
 
1672
- hEle = hEle || jQuery(pagelayer_editable +' .pagelayer-heading');
1673
 
1674
  hEle.each(function(){
1675
 
@@ -2149,24 +2148,212 @@ function pagelayer_get_screen_mode(){
2149
  }
2150
  }
2151
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2152
  // Handle key press events
2153
  pagelayer.gDocument.keydown(function(event){
2154
  //alert(String.fromCharCode(event.which));
2155
 
2156
  var tEle = jQuery(event.target);
2157
  var editable = tEle.closest('[contenteditable="true"]');
2158
-
 
2159
  // Enter handle
2160
- if(event.keyCode == 13 && !event.shiftKey){
2161
-
2162
  var jEle = tEle.closest('.pagelayer-ele');
2163
  var tag = pagelayer_tag(jEle);
2164
 
2165
- if(tag != 'pl_heading' || editable.length < 1){
 
 
2166
  return;
2167
  }
2168
 
2169
- event.preventDefault();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2170
 
2171
  var selection = window.getSelection();
2172
  var range = selection.getRangeAt(0);
@@ -2175,7 +2362,9 @@ pagelayer.gDocument.keydown(function(event){
2175
  if(jQuery(range.startContainer).closest('[pagelayer-editable] li').length > 0){
2176
  return;
2177
  }
2178
-
 
 
2179
  var lastChild = editable[0].lastChild;
2180
  var startContainer = range.startContainer;
2181
 
@@ -2189,21 +2378,19 @@ pagelayer.gDocument.keydown(function(event){
2189
  var selfEle = jQuery('<div>').append(val);
2190
  var selContent = selfEle.html();
2191
  var selfFC = selfEle[0].firstChild;
 
2192
 
2193
  if(selfFC == null || pagelayer_empty(selContent)){
2194
  selContent = '<p><br></p>';
2195
- }else if(selfFC.nodeType == Node.TEXT_NODE){
 
2196
  selContent = '<p>'+selContent+'</p>';
2197
  }else if(selfEle.text() == '' && selfEle.find('br').length < 1){
2198
- range.collapse(true);
2199
- var br = document.createElement('br');
2200
- range.insertNode(br);
2201
- range.setStartBefore(br);
2202
- range.setEndAfter(lastChild);
2203
- val = range.cloneContents();
2204
- selContent = jQuery('<div>').append(val).html();
2205
  }else if(selfEle.text().trim() == ''){
2206
  selContent = selContent.replace(/\s+/, "\u00A0");
 
2207
  }
2208
 
2209
  range.deleteContents();
@@ -2221,14 +2408,20 @@ pagelayer.gDocument.keydown(function(event){
2221
 
2222
  editable.trigger('input');
2223
  editable.blur();
2224
-
2225
- var id = pagelayer_copy_element(jEle);
2226
- var ele = pagelayer_ele_by_id(id);
 
 
 
 
 
 
 
2227
  ele.click();
2228
  var editorArea = ele.find('[pagelayer-editable]');
2229
  editorArea.html(selContent);
2230
  editorArea.find('p:empty').remove();
2231
- editorArea.click();
2232
  editorArea.focus().trigger('input');
2233
  }
2234
 
@@ -2249,13 +2442,41 @@ pagelayer.gDocument.keydown(function(event){
2249
 
2250
  }
2251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2252
  // Backspace handler
2253
  if(event.keyCode == 8 && editable.length > 0){
2254
  var jEle = tEle.closest('.pagelayer-ele-wrap');
2255
  var tag = pagelayer_tag(jEle);
2256
  var prev = jEle.prev();
2257
 
2258
- if(tag != 'pl_heading' || prev.length < 1){
2259
  return;
2260
  }
2261
 
@@ -2270,33 +2491,9 @@ pagelayer.gDocument.keydown(function(event){
2270
  return;
2271
  }
2272
 
2273
- var getCaretCharacterOffsetWithin = function(element){ // http://jsfiddle.net/TjXEG/900/
2274
- var caretOffset = 0;
2275
- var doc = element.ownerDocument || element.document;
2276
- var win = doc.defaultView || doc.parentWindow;
2277
- var sel;
2278
- if( typeof win.getSelection != "undefined" ){
2279
- sel = win.getSelection();
2280
- if (sel.rangeCount > 0) {
2281
- var range = win.getSelection().getRangeAt(0);
2282
- var preCaretRange = range.cloneRange();
2283
- preCaretRange.selectNodeContents(element);
2284
- preCaretRange.setEnd(range.endContainer, range.endOffset);
2285
- caretOffset = preCaretRange.toString().length;
2286
- }
2287
- }else if( (sel = doc.selection) && sel.type != "Control" ){
2288
- var textRange = sel.createRange();
2289
- var preCaretTextRange = doc.body.createTextRange();
2290
- preCaretTextRange.moveToElementText(element);
2291
- preCaretTextRange.setEndPoint("EndToEnd", textRange);
2292
- caretOffset = preCaretTextRange.text.length;
2293
- }
2294
- return caretOffset;
2295
- }
2296
-
2297
  var prevArea = prev.find('[pagelayer-editable="text"]');
2298
 
2299
- if( getCaretCharacterOffsetWithin(editable[0]) != 0 || prevArea.length < 1){
2300
  return;
2301
  }
2302
 
@@ -2328,7 +2525,128 @@ pagelayer.gDocument.keydown(function(event){
2328
  pagelayer_delete_element(jEle.children('.pagelayer-ele'));
2329
 
2330
  }
2331
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2332
  // Is this in the editable area ?
2333
  if (tEle.is('input, textarea') || editable.length > 0) {
2334
  return;
@@ -4775,9 +5093,6 @@ function pagelayer_leftbar(){
4775
  }else{
4776
  cEle.closest('#pagelayer-shortcodes').find('.pagelayer-shortcodes-widget').removeClass('pagelayer-hidden');
4777
  cEle.closest('#pagelayer-shortcodes').find('.pagelayer-global-widget').addClass('pagelayer-hidden');
4778
-
4779
- // Set focus to search
4780
- pagelayer.$$('.pagelayer-search-field').focus().select();
4781
  }
4782
  });
4783
 
@@ -6795,6 +7110,8 @@ function pagelayer_create_widget_tooltip(){
6795
  }
6796
 
6797
  });
 
 
6798
 
6799
  });
6800
 
@@ -6803,13 +7120,27 @@ function pagelayer_create_widget_tooltip(){
6803
  wdHolder.find('.pagelayer-search-field').val('').trigger('input');
6804
  });
6805
 
 
 
 
 
 
 
 
 
 
 
 
 
6806
  pagelayer.gDocument.on('mousedown.pagelayer_wdlist', function(e){
6807
  var target = jQuery(e.target);
6808
 
6809
  if(target.closest('.pagelayer-widget-tooltip').is(wdHolder)){
6810
  return;
6811
  }
6812
-
 
 
6813
  wdHolder.hide();
6814
  jQuery('.pagelayer-show-wiget-list').removeClass('pagelayer-show-wiget-list');
6815
  jQuery(window).off('scroll.pagelayer_wdlist resize.pagelayer_wdlist');
@@ -6833,11 +7164,10 @@ function pagelayer_show_widget_list(jEle, val){
6833
  wBottom = 'auto',
6834
  wLeft = '';
6835
  wHeight = '';
6836
-
6837
- wEle.find('.pagelayer-search-field').val(val);
6838
- wEle.find('.pagelayer-search-field').trigger('input');
6839
-
6840
- wEle.closest('.pagelayer-widget-tooltip').show();
6841
 
6842
  // Add widget show class
6843
  if(jEle.hasClass('pagelayer-shortcode-plus')){
@@ -6845,24 +7175,27 @@ function pagelayer_show_widget_list(jEle, val){
6845
  }
6846
 
6847
  var bounds = jEle[0].getBoundingClientRect();
6848
-
 
 
 
6849
  // In list view?
6850
  if(jEle.closest('[pagelayer-editable]').length > 0){
6851
  wEle.addClass('pagelayer-widget-list-tooltip');
6852
-
6853
- if(wEle.find('.pagelayer-widget-group:visible').length < 1){
6854
- // Hide Widget list
6855
- pagelayer.gDocument.trigger('mousedown.pagelayer_wdlist');
6856
- return;
6857
- }
6858
-
6859
  var selection = window.getSelection();
6860
  var range = selection.getRangeAt(0);
6861
  wLeft = (range.getBoundingClientRect().left + iframeLeft) - wEle.width() / 2;
6862
-
 
 
 
 
 
 
 
 
6863
  }else{
6864
- wEle.removeClass('pagelayer-widget-list-tooltip');
6865
- wLeft = (bounds.left + iframeLeft) - wEle.width() / 2;
6866
  }
6867
 
6868
  var docW = iframeLeft + iframe.width() - 30;
@@ -6917,7 +7250,7 @@ function pagelayer_show_widget_list(jEle, val){
6917
  mWrap.after(ele);
6918
  }
6919
 
6920
- // Replace widegt
6921
  if(jEle.closest('[pagelayer-editable]').length > 0){
6922
  pagelayer_delete_element(mWrap.find('>.pagelayer-ele'));
6923
  }
@@ -6938,4 +7271,115 @@ function pagelayer_show_widget_list(jEle, val){
6938
  pagelayer.gDocument.trigger('mousedown.pagelayer_wdlist');
6939
  });
6940
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6941
  }
197
  pagelayer_setup_props_editable();
198
 
199
  // Make elements editable
200
+ jQuery(pagelayer_editable+' [pagelayer-editable]').attr('contenteditable', 'true');
201
 
202
  // Use text widget for search widget
203
  pagelayer_search_widgets();
1223
  event.stopPropagation();
1224
  pagelayer.$$('.pagelayer-elpd-close').click();
1225
 
 
 
 
1226
  pagelayer_show_widget_list(jQuery(this));
1227
  });
1228
 
1646
  });
1647
 
1648
  // Show left bar
1649
+ if(pagelayer_empty(e)){
1650
+ pagelayer.$$('.pagelayer-leftbar-table').removeClass('pagelayer-leftbar-hidden pagelayer-leftbar-minimize');
1651
+ }
1652
 
1653
  // Lets not rebuild everything to make it faster
1654
  if(pagelayer_is_active(jEle)){
1668
  // Use text widget for search widget
1669
  function pagelayer_search_widgets(hEle){
1670
 
1671
+ hEle = hEle || jQuery(pagelayer_editable +' [pagelayer-tag="pl_text"], '+pagelayer_editable +' [pagelayer-tag="pl_heading"]');
1672
 
1673
  hEle.each(function(){
1674
 
2148
  }
2149
  }
2150
 
2151
+ var pagelayer_keydown_data = {};
2152
+ pagelayer_add_action('pagelayer_do_dirty', function(){
2153
+ pagelayer_keydown_data = {};
2154
+ });
2155
+
2156
+ var pagelayer_active_ele_timmer = {};
2157
+ // Handle widget selecttion and move cursor in editable areas on key press events
2158
+ jQuery(document).keydown(function(e){
2159
+ //alert(String.fromCharCode(e.which));
2160
+
2161
+ var tEle = jQuery(e.target);
2162
+ var editable = tEle.closest('[contenteditable="true"]');
2163
+ var tooltip = pagelayer.$$('.pagelayer-widget-tooltip');
2164
+
2165
+ // If ArrowDown and ArrowUp key not pressed
2166
+ if(!(e.key == 'ArrowDown' || e.key == 'ArrowUp') || tooltip.is(':visible')){
2167
+ pagelayer_keydown_data = {};
2168
+ return;
2169
+ }
2170
+
2171
+ var findEles = jQuery(pagelayer_editable+' .pagelayer-ele,'+pagelayer_editable+' [contenteditable="true"]');
2172
+ var activeEle = findEles.first();
2173
+
2174
+ if(editable.length > 0){
2175
+ activeEle = editable;
2176
+ }else if( '$' in pagelayer_keydown_data ){
2177
+ activeEle = pagelayer_keydown_data.$;
2178
+ }else if( pagelayer_active.el && 'id' in pagelayer_active.el ){
2179
+ activeEle = pagelayer_active.el.$;
2180
+ }
2181
+
2182
+ if(pagelayer_empty(activeEle) || activeEle.length < 1){
2183
+ return;
2184
+ }
2185
+
2186
+ // Make element active
2187
+ var makeEleActive = function(index, next){
2188
+
2189
+ next = next || false;
2190
+ var cursorPos = 0, focusEle;
2191
+
2192
+ // We are editable area
2193
+ if(editable.length > 0){
2194
+
2195
+ var lines = pagelayer_content_line(editable.get(0));
2196
+ var cursorPos = pagelayer_getCaretCharacterOffsetWithin(editable.get(0));
2197
+
2198
+ if((next && lines[lines.length - 1].start > cursorPos) || (!next && lines[0].end < cursorPos)){
2199
+ return;
2200
+ }
2201
+
2202
+ e.preventDefault();
2203
+
2204
+ var lastLineStart = lines[lines.length - 1]['start'];
2205
+
2206
+ // We are on the last line
2207
+ if(next && lastLineStart <= cursorPos){
2208
+ cursorPos = cursorPos - lastLineStart;
2209
+ }
2210
+
2211
+ }
2212
+
2213
+ // Search for next/previous element
2214
+ var searchEle = function(indexEle){
2215
+
2216
+ indexEle = next ? ++indexEle : --indexEle;
2217
+ var sIndex = findEles.eq(indexEle);
2218
+
2219
+ if(sIndex.length < 1){
2220
+ return sIndex;
2221
+ }
2222
+
2223
+ var sEle = sIndex.closest('.pagelayer-ele');
2224
+ var tag = pagelayer_tag(sEle);
2225
+
2226
+ if(tag == 'pl_row' || tag == 'pl_inner_row' || tag == 'pl_col' || sEle.parent().hasClass('pagelayer-hide-active') || !pagelayer_empty(sIndex.attr('pagelayer-parent'))){
2227
+ sIndex = searchEle(indexEle);
2228
+ }
2229
+
2230
+ return sIndex;
2231
+ }
2232
+
2233
+ var ele = searchEle(index);
2234
+
2235
+ // If ArrowUp and we are come from editable area and previous element is not editable
2236
+ if(ele.length > 0 && !next && ele.attr('contenteditable') != 'true'){
2237
+ ele = searchEle(findEles.index( ele ));
2238
+ }
2239
+
2240
+ if(ele.length < 1){
2241
+ return;
2242
+ }
2243
+
2244
+ // Save in global variable
2245
+ pagelayer_keydown_data.$ = ele;
2246
+ jQuery(':focus').blur();
2247
+
2248
+ var jEle = ele.closest('.pagelayer-ele');
2249
+ var tag = pagelayer_tag(jEle);
2250
+
2251
+ if(ele.attr('contenteditable') == 'true'){
2252
+ focusEle = ele;
2253
+ }else if(tag != 'pl_row' && tag != 'pl_inner_row' && tag != 'pl_col'){
2254
+
2255
+ var focusAble = ele.find('[contenteditable="true"]');
2256
+ var isfocusAble = focusAble.closest('.pagelayer-ele').is(jEle);
2257
+
2258
+ if(isfocusAble && next){
2259
+ focusEle = focusAble.first();
2260
+ }else if(isfocusAble){
2261
+ focusEle = focusAble.last();
2262
+ }
2263
+ }
2264
+
2265
+ if(!pagelayer_empty(focusEle) && focusEle.length > 0){
2266
+ focusEle.focus();
2267
+
2268
+ var focusLine = pagelayer_content_line(focusEle.get(0));
2269
+ var fLine = next ? focusLine[0] : focusLine[focusLine.length -1];
2270
+
2271
+ cursorPos = (fLine['start'] + cursorPos > fLine['end'] ? fLine['end'] : fLine['start'] + cursorPos);
2272
+
2273
+ pagelayer_setCaret(focusEle.get(0), cursorPos);
2274
+ }
2275
+
2276
+ pagelayer_set_active(jEle);
2277
+ ele[0].scrollIntoView({behavior: "smooth", block: "nearest"});
2278
+
2279
+ clearTimeout(pagelayer_active_ele_timmer);
2280
+ pagelayer_active_ele_timmer = setTimeout(function(){
2281
+ pagelayer_keydown_data = {};
2282
+ ele.closest('.pagelayer-ele').click();
2283
+ }, 1000);
2284
+ }
2285
+
2286
+ // If cursor on first line & up arrow key
2287
+ var currentIndex = findEles.index( activeEle );
2288
+ pagelayer_keydown_data.$ = activeEle;
2289
+
2290
+ // Move active element and cursor arround editor
2291
+ if(e.key == 'ArrowDown'){
2292
+ makeEleActive(currentIndex, true);
2293
+ }
2294
+
2295
+ if(e.key == 'ArrowUp'){
2296
+ makeEleActive(currentIndex, false);
2297
+ }
2298
+ });
2299
+
2300
  // Handle key press events
2301
  pagelayer.gDocument.keydown(function(event){
2302
  //alert(String.fromCharCode(event.which));
2303
 
2304
  var tEle = jQuery(event.target);
2305
  var editable = tEle.closest('[contenteditable="true"]');
2306
+ var tooltip = pagelayer.$$('.pagelayer-widget-tooltip');
2307
+
2308
  // Enter handle
2309
+ if(event.keyCode == 13){
2310
+
2311
  var jEle = tEle.closest('.pagelayer-ele');
2312
  var tag = pagelayer_tag(jEle);
2313
 
2314
+ // Add selected widget from widget list
2315
+ if(tooltip.is(':visible')){
2316
+ tooltip.find('.pagelayer-list-widget-active:visible').click();
2317
  return;
2318
  }
2319
 
2320
+ if( pagelayer_empty(pagelayer_active.el) || !('id' in pagelayer_active.el) ){
2321
+ return;
2322
+ }
2323
+
2324
+ var active_el_par = pagelayer_active.el.$.parent();
2325
+
2326
+ // Create and add text widget
2327
+ var addTitle = function(insertAfter){
2328
+ var ele = jQuery('<div pagelayer-tag="pl_text"></div>');
2329
+ insertAfter.after(ele);
2330
+ return pagelayer_ele_by_id( pagelayer_onadd(ele) );
2331
+ }
2332
+
2333
+ // If we have an active element then add text widget
2334
+ if(!(tEle.is('input, textarea') || editable.length > 0)){
2335
+
2336
+ event.preventDefault();
2337
+
2338
+ var activeTag = pagelayer_active.el.tag;
2339
+
2340
+ // If is row or column ?
2341
+ if(activeTag == 'pl_row' || activeTag == 'pl_col'){
2342
+ return;
2343
+ }
2344
+
2345
+ var hEle = addTitle(active_el_par);
2346
+ hEle.click();
2347
+ hEle.find('[pagelayer-editable]').focus();
2348
+
2349
+ // Ensure the column is not empty
2350
+ pagelayer_empty_col(hEle.closest('.pagelayer-col-holder'));
2351
+ return;
2352
+ }
2353
+
2354
+ if( (tag != 'pl_text' && tag != 'pl_heading') || editable.length < 1 || event.shiftKey){
2355
+ return;
2356
+ }
2357
 
2358
  var selection = window.getSelection();
2359
  var range = selection.getRangeAt(0);
2362
  if(jQuery(range.startContainer).closest('[pagelayer-editable] li').length > 0){
2363
  return;
2364
  }
2365
+
2366
+ event.preventDefault();
2367
+
2368
  var lastChild = editable[0].lastChild;
2369
  var startContainer = range.startContainer;
2370
 
2378
  var selfEle = jQuery('<div>').append(val);
2379
  var selContent = selfEle.html();
2380
  var selfFC = selfEle[0].firstChild;
2381
+ var emptyContent = false;
2382
 
2383
  if(selfFC == null || pagelayer_empty(selContent)){
2384
  selContent = '<p><br></p>';
2385
+ emptyContent = true;
2386
+ }else if(selfFC.nodeType == Node.TEXT_NODE){
2387
  selContent = '<p>'+selContent+'</p>';
2388
  }else if(selfEle.text() == '' && selfEle.find('br').length < 1){
2389
+ selContent = '<p><br></p>';
2390
+ emptyContent = true;
 
 
 
 
 
2391
  }else if(selfEle.text().trim() == ''){
2392
  selContent = selContent.replace(/\s+/, "\u00A0");
2393
+ emptyContent = true;
2394
  }
2395
 
2396
  range.deleteContents();
2408
 
2409
  editable.trigger('input');
2410
  editable.blur();
2411
+
2412
+ // Create and add text widget
2413
+ var ele;
2414
+ if(emptyContent){
2415
+ ele = addTitle(jEle.parent());
2416
+ }else{
2417
+ var id = pagelayer_copy_element(jEle);
2418
+ ele = pagelayer_ele_by_id(id);
2419
+ }
2420
+
2421
  ele.click();
2422
  var editorArea = ele.find('[pagelayer-editable]');
2423
  editorArea.html(selContent);
2424
  editorArea.find('p:empty').remove();
 
2425
  editorArea.focus().trigger('input');
2426
  }
2427
 
2442
 
2443
  }
2444
 
2445
+ // Delete handler for text widget
2446
+ if(event.keyCode == 46 && editable.length > 0){
2447
+ var jEle = tEle.closest('.pagelayer-ele-wrap');
2448
+ var tag = pagelayer_tag(jEle);
2449
+ var next = jEle.next();
2450
+ var pTag = pagelayer_tag(next);
2451
+
2452
+ var selection = window.getSelection();
2453
+ var orgRange = selection.getRangeAt(0);
2454
+ var cloneRange = orgRange.cloneRange();
2455
+
2456
+ if((tag != 'pl_text' && tag != 'pl_heading') || next.length < 1 || pTag != tag || !cloneRange.collapsed ){
2457
+ return;
2458
+ }
2459
+
2460
+ var currentOffset = pagelayer_getCaretCharacterOffsetWithin(editable[0]);
2461
+ cloneRange.selectNodeContents(editable[0]);
2462
+ var caretOffset = cloneRange.toString().length;
2463
+
2464
+ if(currentOffset != caretOffset){
2465
+ return;
2466
+ }
2467
+
2468
+ var nextHtml = next.find('[pagelayer-editable="text"]').html();
2469
+ editable.append(nextHtml);
2470
+ pagelayer_delete_element(next.children('.pagelayer-ele'));
2471
+ }
2472
+
2473
  // Backspace handler
2474
  if(event.keyCode == 8 && editable.length > 0){
2475
  var jEle = tEle.closest('.pagelayer-ele-wrap');
2476
  var tag = pagelayer_tag(jEle);
2477
  var prev = jEle.prev();
2478
 
2479
+ if((tag != 'pl_text' && tag != 'pl_heading') || prev.length < 1){
2480
  return;
2481
  }
2482
 
2491
  return;
2492
  }
2493
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2494
  var prevArea = prev.find('[pagelayer-editable="text"]');
2495
 
2496
+ if( pagelayer_getCaretCharacterOffsetWithin(editable[0]) != 0 || prevArea.length < 1){
2497
  return;
2498
  }
2499
 
2525
  pagelayer_delete_element(jEle.children('.pagelayer-ele'));
2526
 
2527
  }
2528
+
2529
+ if(tooltip.is(':visible')){
2530
+
2531
+ // Select previous widget in widget tooltip
2532
+ if(event.key == 'ArrowUp' || event.key == 'ArrowLeft' || (event.key == 'Tab' && event.shiftKey)){
2533
+
2534
+ event.preventDefault();
2535
+
2536
+ var current = tooltip.find('.pagelayer-list-widget-active:visible'),
2537
+ prev = current.prevAll('.pagelayer-shortcode-holder:visible');
2538
+
2539
+ if(event.key == 'ArrowUp'){
2540
+ var _prev = prev,
2541
+ cOffset = current.offset();
2542
+ findNext = false;
2543
+
2544
+ var searchNext = function(nEle){
2545
+
2546
+ var nOffset = nEle.offset();
2547
+ var nBottom = nOffset.top + nEle.height();
2548
+
2549
+ if(nBottom > cOffset.top){
2550
+ return true;
2551
+ }
2552
+
2553
+ prev = nEle;
2554
+ findNext = true;
2555
+
2556
+ // Current element left set +20 to manager previous scale (css) element on hover
2557
+ if(cOffset.left + 20 >= nOffset.left){
2558
+ return false;
2559
+ }
2560
+
2561
+ return true;
2562
+ }
2563
+
2564
+ _prev.each(function(){
2565
+ return searchNext(jQuery(this));
2566
+ });
2567
+
2568
+ if(!findNext){
2569
+ var gNext = current.parent().prevAll('.pagelayer-widget-group:visible').first();
2570
+ _prev = gNext.children('.pagelayer-shortcode-holder:visible');
2571
+
2572
+ jQuery(_prev.get().reverse()).each(function(){
2573
+ return searchNext(jQuery(this));
2574
+ });
2575
+ }
2576
+
2577
+ }
2578
+
2579
+ if(prev.length < 1){
2580
+ prev = current.parent().prevAll('.pagelayer-widget-group:visible').first().find('.pagelayer-shortcode-holder:visible').last();
2581
+ }
2582
+
2583
+ if(prev.length < 1){
2584
+ return;
2585
+ }
2586
+
2587
+ prev.first().trigger('widget_active');
2588
+ }
2589
+
2590
+ // Select next widget in widget tooltip
2591
+ if(event.key == 'ArrowDown' || event.key == 'ArrowRight' || (event.key == 'Tab' && !event.shiftKey)){
2592
+
2593
+ event.preventDefault();
2594
+
2595
+ var current = tooltip.find('.pagelayer-list-widget-active:visible');
2596
+ next = current.nextAll('.pagelayer-shortcode-holder:visible');
2597
+
2598
+ if(event.key == 'ArrowDown'){
2599
+
2600
+ var _next = next,
2601
+ cOffset = current.offset(),
2602
+ findNext = false;
2603
+
2604
+ var searchNext = function(nEle){
2605
+ var nOffset = nEle.offset();
2606
+ var cBottom = cOffset.top + current.height();
2607
+
2608
+ if(cBottom > nOffset.top){
2609
+ return true;
2610
+ }
2611
+
2612
+ next = nEle;
2613
+ findNext = true;
2614
+
2615
+ // Current element left set -20 to manager next scale (css) element on hover
2616
+ if(cOffset.left - 20 <= nOffset.left){
2617
+ return false;
2618
+ }
2619
+
2620
+ return true;
2621
+ }
2622
+
2623
+ _next.each(function(){
2624
+ return searchNext(jQuery(this));
2625
+ });
2626
+
2627
+ if(!findNext){
2628
+ var gNext = current.parent().nextAll('.pagelayer-widget-group:visible').first();
2629
+ _next = gNext.children('.pagelayer-shortcode-holder:visible');
2630
+ _next.each(function(){
2631
+ return searchNext(jQuery(this));
2632
+ });
2633
+ }
2634
+
2635
+ }
2636
+
2637
+ if(next.length < 1){
2638
+ next = current.parent().nextAll('.pagelayer-widget-group:visible').first().find('.pagelayer-shortcode-holder:visible');
2639
+ }
2640
+
2641
+ if(next.length < 1){
2642
+ return;
2643
+ }
2644
+
2645
+ next.first().trigger('widget_active');
2646
+
2647
+ }
2648
+ }
2649
+
2650
  // Is this in the editable area ?
2651
  if (tEle.is('input, textarea') || editable.length > 0) {
2652
  return;
5093
  }else{
5094
  cEle.closest('#pagelayer-shortcodes').find('.pagelayer-shortcodes-widget').removeClass('pagelayer-hidden');
5095
  cEle.closest('#pagelayer-shortcodes').find('.pagelayer-global-widget').addClass('pagelayer-hidden');
 
 
 
5096
  }
5097
  });
5098
 
7110
  }
7111
 
7112
  });
7113
+
7114
+ wdHolder.find('.pagelayer-shortcode-holder:visible').first().trigger('widget_active');
7115
 
7116
  });
7117
 
7120
  wdHolder.find('.pagelayer-search-field').val('').trigger('input');
7121
  });
7122
 
7123
+ // Register widget active event
7124
+ wdHolder.find('.pagelayer-shortcode-holder').on('widget_active', function(){
7125
+ var activeEle = jQuery(this);
7126
+ wdHolder.find('.pagelayer-list-widget-active').removeClass('pagelayer-list-widget-active');
7127
+
7128
+ if(!activeEle.hasClass('pagelayer-list-widget-active')){
7129
+ activeEle.addClass('pagelayer-list-widget-active');
7130
+ }
7131
+
7132
+ activeEle[0].scrollIntoView({behavior: "smooth", block: "end"});
7133
+ });
7134
+
7135
  pagelayer.gDocument.on('mousedown.pagelayer_wdlist', function(e){
7136
  var target = jQuery(e.target);
7137
 
7138
  if(target.closest('.pagelayer-widget-tooltip').is(wdHolder)){
7139
  return;
7140
  }
7141
+
7142
+ wdHolder.find('.pagelayer-shortcode-holder:visible').first().trigger('widget_active');
7143
+
7144
  wdHolder.hide();
7145
  jQuery('.pagelayer-show-wiget-list').removeClass('pagelayer-show-wiget-list');
7146
  jQuery(window).off('scroll.pagelayer_wdlist resize.pagelayer_wdlist');
7164
  wBottom = 'auto',
7165
  wLeft = '';
7166
  wHeight = '';
7167
+
7168
+ searchField = wEle.find('.pagelayer-search-field');
7169
+ searchField.val(val);
7170
+ searchField.trigger('input');
 
7171
 
7172
  // Add widget show class
7173
  if(jEle.hasClass('pagelayer-shortcode-plus')){
7175
  }
7176
 
7177
  var bounds = jEle[0].getBoundingClientRect();
7178
+
7179
+ wEle.removeClass('pagelayer-widget-list-tooltip');
7180
+ wLeft = (bounds.left + iframeLeft) - wEle.width() / 2;
7181
+
7182
  // In list view?
7183
  if(jEle.closest('[pagelayer-editable]').length > 0){
7184
  wEle.addClass('pagelayer-widget-list-tooltip');
 
 
 
 
 
 
 
7185
  var selection = window.getSelection();
7186
  var range = selection.getRangeAt(0);
7187
  wLeft = (range.getBoundingClientRect().left + iframeLeft) - wEle.width() / 2;
7188
+ }
7189
+
7190
+ wEle.closest('.pagelayer-widget-tooltip').show();
7191
+ wEle.find('.pagelayer-shortcode-holder:visible').first().trigger('widget_active');
7192
+
7193
+ // Hide Widget list
7194
+ if(jEle.closest('[pagelayer-editable]').length > 0 && wEle.find('.pagelayer-widget-group:visible').length < 1){
7195
+ pagelayer.gDocument.trigger('mousedown.pagelayer_wdlist');
7196
+ return;
7197
  }else{
7198
+ searchField.focus().select();
 
7199
  }
7200
 
7201
  var docW = iframeLeft + iframe.width() - 30;
7250
  mWrap.after(ele);
7251
  }
7252
 
7253
+ // Replace widget
7254
  if(jEle.closest('[pagelayer-editable]').length > 0){
7255
  pagelayer_delete_element(mWrap.find('>.pagelayer-ele'));
7256
  }
7271
  pagelayer.gDocument.trigger('mousedown.pagelayer_wdlist');
7272
  });
7273
 
7274
+ }
7275
+
7276
+ // Set Selection By Character Offsets
7277
+ function pagelayer_setCaret(containerEl, start, end){
7278
+
7279
+ end = end || start;
7280
+
7281
+ // Refered from http://jsfiddle.net/zQUhV/47/
7282
+ if(window.getSelection && document.createRange){
7283
+
7284
+ var charIndex = 0, range = document.createRange();
7285
+ range.setStart(containerEl, 0);
7286
+ range.collapse(true);
7287
+ var nodeStack = [containerEl], node, foundStart = false, stop = false;
7288
+
7289
+ while (!stop && (node = nodeStack.pop())) {
7290
+ if (node.nodeType == 3) {
7291
+ var nextCharIndex = charIndex + node.length;
7292
+ if (!foundStart && start >= charIndex && start <= nextCharIndex) {
7293
+ range.setStart(node, start - charIndex);
7294
+ foundStart = true;
7295
+ }
7296
+ if (foundStart && end >= charIndex && end <= nextCharIndex) {
7297
+ range.setEnd(node, end - charIndex);
7298
+ stop = true;
7299
+ }
7300
+ charIndex = nextCharIndex;
7301
+ } else {
7302
+ var i = node.childNodes.length;
7303
+ while (i--) {
7304
+ nodeStack.push(node.childNodes[i]);
7305
+ }
7306
+ }
7307
+ }
7308
+
7309
+ var sel = window.getSelection();
7310
+ sel.removeAllRanges();
7311
+ sel.addRange(range);
7312
+
7313
+ } else if (document.selection) {
7314
+ var textRange = document.body.createTextRange();
7315
+ textRange.moveToElementText(containerEl);
7316
+ textRange.collapse(true);
7317
+ textRange.moveEnd("character", end);
7318
+ textRange.moveStart("character", start);
7319
+ textRange.select();
7320
+ }
7321
+ }
7322
+
7323
+ // Set Selection By Character Offsets
7324
+ function pagelayer_content_line(containerEl){
7325
+
7326
+ var lines = [], charIndex = 0, range = document.createRange();
7327
+ range.setStart(containerEl, 0);
7328
+ range.collapse(true);
7329
+ var bounding = range.getBoundingClientRect();
7330
+ var nodeStack = [containerEl], node, prevX = bounding.x, nextStart = 0;
7331
+
7332
+ while(node = nodeStack.pop()){
7333
+ if (node.nodeType == 3) {
7334
+ for(var i = 1; i <= node.length; i++){
7335
+ range.setStart(node, i);
7336
+ range.setEnd(node, i);
7337
+ bounding = range.getBoundingClientRect();
7338
+ charIndex ++;
7339
+
7340
+ if(prevX > bounding.x){
7341
+ lines.push({start:nextStart, end:charIndex - 1});
7342
+ nextStart = charIndex;
7343
+ }
7344
+ prevX = bounding.x;
7345
+ }
7346
+ } else {
7347
+ var i = node.childNodes.length;
7348
+ while(i--){
7349
+ nodeStack.push(node.childNodes[i]);
7350
+ }
7351
+ }
7352
+ }
7353
+
7354
+ // Push last line
7355
+ if(nextStart != charIndex || nextStart == 0){
7356
+ lines.push({start:nextStart, end:charIndex});
7357
+ }
7358
+
7359
+ return lines;
7360
+ }
7361
+
7362
+ //http://jsfiddle.net/TjXEG/900/
7363
+ function pagelayer_getCaretCharacterOffsetWithin(element){
7364
+ var caretOffset = 0;
7365
+ var doc = element.ownerDocument || element.document;
7366
+ var win = doc.defaultView || doc.parentWindow;
7367
+ var sel;
7368
+ if( typeof win.getSelection != "undefined" ){
7369
+ sel = win.getSelection();
7370
+ if (sel.rangeCount > 0) {
7371
+ var range = win.getSelection().getRangeAt(0);
7372
+ var preCaretRange = range.cloneRange();
7373
+ preCaretRange.selectNodeContents(element);
7374
+ preCaretRange.setEnd(range.endContainer, range.endOffset);
7375
+ caretOffset = preCaretRange.toString().length;
7376
+ }
7377
+ }else if( (sel = doc.selection) && sel.type != "Control" ){
7378
+ var textRange = sel.createRange();
7379
+ var preCaretTextRange = doc.body.createTextRange();
7380
+ preCaretTextRange.moveToElementText(element);
7381
+ preCaretTextRange.setEndPoint("EndToEnd", textRange);
7382
+ caretOffset = preCaretTextRange.text.length;
7383
+ }
7384
+ return caretOffset;
7385
  }
js/pagelayer-pen.js CHANGED
@@ -1027,7 +1027,7 @@ class PagelayerPen{
1027
  var editorTop = editorOffset.top;
1028
  var editorLeft = editorOffset.left;
1029
  var editorbottom = editorTop + editorOffset.height - tooltipHeight;
1030
- var toolBarTop = editorTop;
1031
  var bound = t.getBounds(range);
1032
 
1033
  if(bound.height == 0 && bound.top == 0 && bound.left == 0){
1027
  var editorTop = editorOffset.top;
1028
  var editorLeft = editorOffset.left;
1029
  var editorbottom = editorTop + editorOffset.height - tooltipHeight;
1030
+ var toolBarTop = editorTop - 10;
1031
  var bound = t.getBounds(range);
1032
 
1033
  if(bound.height == 0 && bound.top == 0 && bound.left == 0){
js/widgets.js CHANGED
@@ -1405,6 +1405,10 @@ function pagelayer_render_end_pl_heading(el) {
1405
  pagelayer_search_widgets(el.$);
1406
  }
1407
 
 
 
 
 
1408
  // Render the contact form
1409
  function pagelayer_render_pl_contact_item(el){
1410
  var html = '';
1405
  pagelayer_search_widgets(el.$);
1406
  }
1407
 
1408
+ function pagelayer_render_end_pl_text(el) {
1409
+ pagelayer_search_widgets(el.$);
1410
+ }
1411
+
1412
  // Render the contact form
1413
  function pagelayer_render_pl_contact_item(el){
1414
  var html = '';
main/functions.php CHANGED
@@ -2598,12 +2598,14 @@ function pagelayer_get_social_urls(){
2598
  function pagelayer_get_option($opt){
2599
  $ret = get_option($opt);
2600
 
2601
- $opts = array('pagelayer-address' => '1, My Address, My Street, New York City, NY, USA',
2602
- 'pagelayer-phone' => '+1234567890',
2603
- 'pagelayer-copyright' => '© '.date('Y').' '.get_option('blogname'),
2604
- 'pagelayer_cf_to_email' => 'contact@domain.com',
2605
- 'pagelayer_cf_success' => __pl('cf_success'),
2606
- 'pagelayer_cf_failed' => __pl('cf_failed'));
 
 
2607
 
2608
  if(empty($ret)){
2609
  return $opts[$opt];
2598
  function pagelayer_get_option($opt){
2599
  $ret = get_option($opt);
2600
 
2601
+ $opts = array(
2602
+ 'pagelayer-address' => '1, My Address, My Street, New York City, NY, USA',
2603
+ 'pagelayer-phone' => '+1234567890',
2604
+ 'pagelayer-copyright' => '© '.date('Y').' '.get_option('blogname'),
2605
+ 'pagelayer_cf_to_email' => 'contact@domain.com',
2606
+ 'pagelayer_cf_success' => __pl('cf_success'),
2607
+ 'pagelayer_cf_failed' => __pl('cf_failed'),
2608
+ );
2609
 
2610
  if(empty($ret)){
2611
  return $opts[$opt];
main/shortcodes.php CHANGED
@@ -3206,7 +3206,7 @@ pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_text', array(
3206
  'text' => array(
3207
  'type' => 'editor',
3208
  'label' => __pl('Edit Rich Text'),
3209
- 'default' => '<p>Lorem ipsum dolor sit amet</p>',
3210
  'rows' => '15',
3211
  'desc' => __pl('Edit the content by clicking on the content you want to edit on the website'),
3212
  'edit' => '.pagelayer-text-holder', // Edit the text and also mirror the same
3206
  'text' => array(
3207
  'type' => 'editor',
3208
  'label' => __pl('Edit Rich Text'),
3209
+ 'default' => '<p><br></p>',
3210
  'rows' => '15',
3211
  'desc' => __pl('Edit the content by clicking on the content you want to edit on the website'),
3212
  'edit' => '.pagelayer-text-holder', // Edit the text and also mirror the same
pagelayer.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: PageLayer
4
  Plugin URI: http://wordpress.org/plugins/pagelayer/
5
  Description: PageLayer is a WordPress page builder plugin. Its very easy to use and very light on the browser.
6
- Version: 1.6.5
7
  Author: Pagelayer Team
8
  Author URI: https://pagelayer.com/
9
  License: LGPL v2.1
3
  Plugin Name: PageLayer
4
  Plugin URI: http://wordpress.org/plugins/pagelayer/
5
  Description: PageLayer is a WordPress page builder plugin. Its very easy to use and very light on the browser.
6
+ Version: 1.6.6
7
  Author: Pagelayer Team
8
  Author URI: https://pagelayer.com/
9
  License: LGPL v2.1
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: page builder, editor, drag and drop, form builder, landing page, responsiv
4
  Requires at least: 4.7
5
  Tested up to: 5.9
6
  Requires PHP: 5.5
7
- Stable tag: 1.6.5
8
  License: LGPL v2.1
9
  License URI: http://www.gnu.org/licenses/lgpl-2.1.html
10
 
@@ -127,6 +127,10 @@ Do you have questions related to Pagelayer? Use the following links :
127
 
128
  == Changelog ==
129
 
 
 
 
 
130
  = 1.6.5 (Feb 21, 2022) =
131
  * [Task] The Pagelayer pen editor UX has been further improved.
132
  * [Bug-Fix] In some cases, the font-family and other css of icons were not applied correctly after the previous version. This is fixed.
4
  Requires at least: 4.7
5
  Tested up to: 5.9
6
  Requires PHP: 5.5
7
+ Stable tag: 1.6.6
8
  License: LGPL v2.1
9
  License URI: http://www.gnu.org/licenses/lgpl-2.1.html
10
 
127
 
128
  == Changelog ==
129
 
130
+ = 1.6.6 (March 09, 2022) =
131
+ * [Task] The editing experience within Pagelayer editor has been further improved. Now user can move from one widget to another with the help of up and down arrow keys. Weare trying to make the editor into a more user friendly document editor.
132
+ * [Task] Now we will add a text widget after the active widget when enter is pressed. You can add a slash "/" to search and convert the widget.
133
+
134
  = 1.6.5 (Feb 21, 2022) =
135
  * [Task] The Pagelayer pen editor UX has been further improved.
136
  * [Bug-Fix] In some cases, the font-family and other css of icons were not applied correctly after the previous version. This is fixed.